diff --git a/amd_lib/shared/d3d11/build/AMD_LIB_2010.vcxproj b/amd_lib/shared/d3d11/build/AMD_LIB_2010.vcxproj index 46478b0..81c0d27 100644 --- a/amd_lib/shared/d3d11/build/AMD_LIB_2010.vcxproj +++ b/amd_lib/shared/d3d11/build/AMD_LIB_2010.vcxproj @@ -288,7 +288,6 @@ - diff --git a/amd_lib/shared/d3d11/build/AMD_LIB_2010.vcxproj.filters b/amd_lib/shared/d3d11/build/AMD_LIB_2010.vcxproj.filters index ed6f070..42f78d0 100644 --- a/amd_lib/shared/d3d11/build/AMD_LIB_2010.vcxproj.filters +++ b/amd_lib/shared/d3d11/build/AMD_LIB_2010.vcxproj.filters @@ -1,23 +1,11 @@ - - {61705900-4DFC-870B-B6AA-880BA255880B} + + {AEFEE3F6-9AA0-0ECD-835B-22216F9C951D} - - {CC6E590B-3883-81BC-0105-251C6DD87DED} - - - {4CE19223-B8A1-0E5A-81DC-57D7ED5B5336} - - - {553A9689-C150-941F-0AC8-1F41761D65A7} - - - {993A4365-05A5-F7DB-4EE3-A881BA8CD530} - - - {22723C73-8E32-B8A9-576D-0127C3ECFC85} + + {B7381BB1-A3F0-5CFE-0CF8-355AF8CEF7EE} {1F80880B-8B89-887C-1405-9F7C800D947C} @@ -59,11 +47,8 @@ - - ..\..\ags_lib\inc - - ..\common\inc + common\inc inc diff --git a/amd_lib/shared/d3d11/build/AMD_LIB_2012.vcxproj b/amd_lib/shared/d3d11/build/AMD_LIB_2012.vcxproj index c21f221..8bb6f31 100644 --- a/amd_lib/shared/d3d11/build/AMD_LIB_2012.vcxproj +++ b/amd_lib/shared/d3d11/build/AMD_LIB_2012.vcxproj @@ -288,7 +288,6 @@ - diff --git a/amd_lib/shared/d3d11/build/AMD_LIB_2012.vcxproj.filters b/amd_lib/shared/d3d11/build/AMD_LIB_2012.vcxproj.filters index ed6f070..42f78d0 100644 --- a/amd_lib/shared/d3d11/build/AMD_LIB_2012.vcxproj.filters +++ b/amd_lib/shared/d3d11/build/AMD_LIB_2012.vcxproj.filters @@ -1,23 +1,11 @@ - - {61705900-4DFC-870B-B6AA-880BA255880B} + + {AEFEE3F6-9AA0-0ECD-835B-22216F9C951D} - - {CC6E590B-3883-81BC-0105-251C6DD87DED} - - - {4CE19223-B8A1-0E5A-81DC-57D7ED5B5336} - - - {553A9689-C150-941F-0AC8-1F41761D65A7} - - - {993A4365-05A5-F7DB-4EE3-A881BA8CD530} - - - {22723C73-8E32-B8A9-576D-0127C3ECFC85} + + {B7381BB1-A3F0-5CFE-0CF8-355AF8CEF7EE} {1F80880B-8B89-887C-1405-9F7C800D947C} @@ -59,11 +47,8 @@ - - ..\..\ags_lib\inc - - ..\common\inc + common\inc inc diff --git a/amd_lib/shared/d3d11/build/AMD_LIB_2013.vcxproj b/amd_lib/shared/d3d11/build/AMD_LIB_2013.vcxproj index fef26f1..f7f9d39 100644 --- a/amd_lib/shared/d3d11/build/AMD_LIB_2013.vcxproj +++ b/amd_lib/shared/d3d11/build/AMD_LIB_2013.vcxproj @@ -289,7 +289,6 @@ - diff --git a/amd_lib/shared/d3d11/build/AMD_LIB_2013.vcxproj.filters b/amd_lib/shared/d3d11/build/AMD_LIB_2013.vcxproj.filters index ed6f070..42f78d0 100644 --- a/amd_lib/shared/d3d11/build/AMD_LIB_2013.vcxproj.filters +++ b/amd_lib/shared/d3d11/build/AMD_LIB_2013.vcxproj.filters @@ -1,23 +1,11 @@ - - {61705900-4DFC-870B-B6AA-880BA255880B} + + {AEFEE3F6-9AA0-0ECD-835B-22216F9C951D} - - {CC6E590B-3883-81BC-0105-251C6DD87DED} - - - {4CE19223-B8A1-0E5A-81DC-57D7ED5B5336} - - - {553A9689-C150-941F-0AC8-1F41761D65A7} - - - {993A4365-05A5-F7DB-4EE3-A881BA8CD530} - - - {22723C73-8E32-B8A9-576D-0127C3ECFC85} + + {B7381BB1-A3F0-5CFE-0CF8-355AF8CEF7EE} {1F80880B-8B89-887C-1405-9F7C800D947C} @@ -59,11 +47,8 @@ - - ..\..\ags_lib\inc - - ..\common\inc + common\inc inc diff --git a/amd_lib/shared/d3d11/build/AMD_LIB_2015.vcxproj b/amd_lib/shared/d3d11/build/AMD_LIB_2015.vcxproj index af775b4..4722368 100644 --- a/amd_lib/shared/d3d11/build/AMD_LIB_2015.vcxproj +++ b/amd_lib/shared/d3d11/build/AMD_LIB_2015.vcxproj @@ -284,7 +284,6 @@ - diff --git a/amd_lib/shared/d3d11/build/AMD_LIB_2015.vcxproj.filters b/amd_lib/shared/d3d11/build/AMD_LIB_2015.vcxproj.filters index ed6f070..42f78d0 100644 --- a/amd_lib/shared/d3d11/build/AMD_LIB_2015.vcxproj.filters +++ b/amd_lib/shared/d3d11/build/AMD_LIB_2015.vcxproj.filters @@ -1,23 +1,11 @@ - - {61705900-4DFC-870B-B6AA-880BA255880B} + + {AEFEE3F6-9AA0-0ECD-835B-22216F9C951D} - - {CC6E590B-3883-81BC-0105-251C6DD87DED} - - - {4CE19223-B8A1-0E5A-81DC-57D7ED5B5336} - - - {553A9689-C150-941F-0AC8-1F41761D65A7} - - - {993A4365-05A5-F7DB-4EE3-A881BA8CD530} - - - {22723C73-8E32-B8A9-576D-0127C3ECFC85} + + {B7381BB1-A3F0-5CFE-0CF8-355AF8CEF7EE} {1F80880B-8B89-887C-1405-9F7C800D947C} @@ -59,11 +47,8 @@ - - ..\..\ags_lib\inc - - ..\common\inc + common\inc inc diff --git a/amd_tressfx/inc/AMD_TressFX.h b/amd_tressfx/inc/AMD_TressFX.h index aa4fd4f..dd194c2 100644 --- a/amd_tressfx/inc/AMD_TressFX.h +++ b/amd_tressfx/inc/AMD_TressFX.h @@ -24,6 +24,14 @@ #define AMD_TRESSFX_H #include +#if AMD_TRESSFX_VULKAN +#include +#elif AMD_TRESSFX_DIRECT3D11 +#include +#else +#error +#endif + #include #define AMD_TRESSFX_VERSION_MAJOR 3 @@ -75,6 +83,19 @@ #define IDSRV_HAIR_FRAGMENT_COLORS 14 #define IDSRV_HAIR_ACCUM_INV_ALPHA 15 +#define IDSRV_CONSTANTS_BUFFER 16 +#define IDSRV_ATOMIC_COUNTER_BUFFER 17 +#define IDSRV_NOISE_SAMPLER 18 +#define IDSRV_SHADOW_SAMPLER 19 + +#define IDSRV_HAIR_PREVIOUS_VERTEX_POSITIONS 20 +#define IDSRV_HAIR_VERTEX_INITIAL_POSITIONS 21 +#define IDSRV_HAIR_STRAND_TYPE 22 +#define IDSRV_HAIR_GLOBAL_ROTATION 23 +#define IDSRV_HAIR_LOCAL_REF_VEC 24 +#define IDSRV_HAIR_ROOT_OFFSET 25 +#define IDSRV_HAIR_LENGTH 26 +#define IDSRV_HEAD_TRANSFORM 27 #if defined(DEBUG) || defined(_DEBUG) #define AMD_TRESSFX_DEBUG 1 @@ -167,10 +188,17 @@ struct TressFX_HairBlob struct TressFX_SceneMesh { +#if AMD_TRESSFX_VULKAN + VkBufferView pMeshVertices; // untransformed vertices + VkBufferView pTransformedVerts; // untransformed vertices +#elif AMD_TRESSFX_DIRECT3D11 ID3D11ShaderResourceView* pMeshVertices; // untransformed vertices + ID3D11ShaderResourceView* pTransformedVerts; // transformed vertices +#else +#error +#endif unsigned numMeshes; // number of meshes unsigned* meshOffsets; // offset to the start of each mesh - ID3D11ShaderResourceView* pTransformedVerts; // transformed vertices }; struct TressFX_HairTransform @@ -227,33 +255,71 @@ struct TressFX_Desc // Buffer of transformations (one transform per strand) for hair skinning // This UAV is used as a structured buffer where each element is a TressFX_HairTransform. // The number of elements in the buffer is numTotalHairStrands. +#if AMD_TRESSFX_VULKAN + VkBufferView pSkinningTransformationsUAV; + // hair shadow map + VkImageView pHairShadowMapSRV; + VkDevice pvkDevice; + VkPhysicalDeviceMemoryProperties memoryProperties; + VkImageView pvkDepthSRV; + uint32_t maxConstantBuffers; + VkFormat depthStencilFormat; + VkFormat colorFormat; +#elif AMD_TRESSFX_DIRECT3D11 ID3D11UnorderedAccessView* pSkinningTransformationsUAV; - // hair shadow map ID3D11ShaderResourceView* pHairShadowMapSRV; - ID3D11Device* pd3dDevice; ID3D11DeviceContext* pd3dDeviceContext; ID3D11ShaderResourceView* pd3dDepthSRV; ID3D11RenderTargetView* pd3dOutputRTV; +#else +#error +#endif }; extern "C" { AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_GetVersion(uint* major, uint* minor, uint* patch); - AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Initialize(TressFX_Desc & desc); AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_LoadRawAsset(TressFX_Desc & desc, const TressFX_GuideFollowParams& guideFollowParams, TressFX_HairBlob *pRawHairBlob); - AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_LoadProcessedAsset(TressFX_Desc & desc, TressFX_HairBlob *pHairBlob, TressFX_SceneMesh *sceneMesh, ID3D11ShaderResourceView *pTextureSRV); - AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_CreateProcessedAsset(TressFX_Desc & desc, TressFX_HairBlob **ppHairBlob, TressFX_SceneMesh *sceneMesh, ID3D11ShaderResourceView *pTextureSRV); - AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Begin(TressFX_Desc & desc); AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_End(TressFX_Desc & desc); AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_GenerateTransforms(TressFX_Desc & desc, TressFX_SceneMesh &sceneMesh); AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_ApplyRigidTransforms(TressFX_Desc & desc); - AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Simulate(TressFX_Desc & desc, float elapsedTime); - AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_RenderShadowMap(TressFX_Desc & desc); - AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Render(TressFX_Desc & desc); - AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Resize(TressFX_Desc & desc); AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Release(TressFX_Desc & desc); +#if AMD_TRESSFX_VULKAN + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Initialize( + TressFX_Desc &desc, VkImageView depthTexture, VkImageView colorTexture, + VkCommandBuffer commandBuffer, VkDeviceMemory scratchMemory, + VkBuffer scratchBuffer, size_t &offsetInScratchBuffer); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_LoadProcessedAsset( + TressFX_Desc &desc, TressFX_HairBlob *pHairBlob, + TressFX_SceneMesh *sceneMesh, VkImageView pTextureSRV, + VkCommandBuffer uploadCmdBuffer, + VkBuffer scratchBuffer, VkDeviceMemory scratchMemory); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_CreateProcessedAsset( + TressFX_Desc &desc, TressFX_HairBlob **ppHairBlob, + TressFX_SceneMesh *sceneMesh, VkImageView pTextureSRV, + VkCommandBuffer uploadCmdBuffer, + VkBuffer scratchBuffer, VkDeviceMemory scratchMemory); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Begin(TressFX_Desc & desc, uint32_t uniformBufferIndex); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Simulate(TressFX_Desc & desc, VkCommandBuffer commandBuffer, float elapsedTime, uint32_t uniformBufferIndex); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_RenderShadowMap(TressFX_Desc & desc, VkCommandBuffer commandBuffer, uint32_t uniformBufferIndex); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE + TressFX_Render(TressFX_Desc &desc, VkCommandBuffer commandBuffer, uint32_t uniformBufferIndex); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE + TressFX_Resize(TressFX_Desc &desc, VkPhysicalDeviceMemoryProperties memProperties); +#elif AMD_TRESSFX_DIRECT3D11 + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Initialize(TressFX_Desc &desc); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_LoadProcessedAsset(TressFX_Desc & desc, TressFX_HairBlob *pHairBlob, TressFX_SceneMesh *sceneMesh, ID3D11ShaderResourceView *pTextureSRV); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_CreateProcessedAsset(TressFX_Desc & desc, TressFX_HairBlob **ppHairBlob, TressFX_SceneMesh *sceneMesh, ID3D11ShaderResourceView *pTextureSRV); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Begin(TressFX_Desc & desc); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Render(TressFX_Desc & desc); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Resize(TressFX_Desc &desc); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_RenderShadowMap(TressFX_Desc & desc); + AMD_TRESSFX_DLL_API TRESSFX_RETURN_CODE TressFX_Simulate(TressFX_Desc & desc, float elapsedTime); +#else +#error +#endif } } // namespace AMD diff --git a/amd_tressfx_viewer/build/TressFX_Viewer_2012.sln b/amd_tressfx_viewer/build/TressFX_Viewer_2012.sln index d8add24..6dfac25 100644 --- a/amd_tressfx_viewer/build/TressFX_Viewer_2012.sln +++ b/amd_tressfx_viewer/build/TressFX_Viewer_2012.sln @@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_SDK_Minimal", "..\..\fr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_TressFX", "..\..\AMD_TressFX\build\AMD_TressFX_2012.vcxproj", "{252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_TressFX_Vulkan", "..\..\AMD_TressFX_Vulkan\build\AMD_TressFX_Vulkan_2012.vcxproj", "{9B729252-7D58-4B28-882F-DFB4EF44A485}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DXUT", "..\..\framework\d3d11\dxut\Core\DXUT_2012.vcxproj", "{85344B7F-5AA0-4E12-A065-D1333D11F6CA}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DXUTOpt", "..\..\framework\d3d11\dxut\Optional\DXUTOpt_2012.vcxproj", "{61B333C2-C4F7-4CC1-A9BF-83F6D95588EB}" @@ -35,6 +37,10 @@ Global {252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}.Debug|x64.Build.0 = DLL_Debug|x64 {252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}.Release|x64.ActiveCfg = DLL_Release|x64 {252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}.Release|x64.Build.0 = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Debug|x64.ActiveCfg = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Debug|x64.Build.0 = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Release|x64.ActiveCfg = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Release|x64.Build.0 = DLL_Release|x64 {85344B7F-5AA0-4E12-A065-D1333D11F6CA}.Debug|x64.ActiveCfg = Debug|x64 {85344B7F-5AA0-4E12-A065-D1333D11F6CA}.Debug|x64.Build.0 = Debug|x64 {85344B7F-5AA0-4E12-A065-D1333D11F6CA}.Release|x64.ActiveCfg = Release|x64 diff --git a/amd_tressfx_viewer/build/TressFX_Viewer_2013.sln b/amd_tressfx_viewer/build/TressFX_Viewer_2013.sln index 741b627..1e91dac 100644 --- a/amd_tressfx_viewer/build/TressFX_Viewer_2013.sln +++ b/amd_tressfx_viewer/build/TressFX_Viewer_2013.sln @@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_SDK_Minimal", "..\..\fr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_TressFX", "..\..\AMD_TressFX\build\AMD_TressFX_2013.vcxproj", "{252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_TressFX_Vulkan", "..\..\AMD_TressFX_Vulkan\build\AMD_TressFX_Vulkan_2013.vcxproj", "{9B729252-7D58-4B28-882F-DFB4EF44A485}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DXUT", "..\..\framework\d3d11\dxut\Core\DXUT_2013.vcxproj", "{85344B7F-5AA0-4E12-A065-D1333D11F6CA}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DXUTOpt", "..\..\framework\d3d11\dxut\Optional\DXUTOpt_2013.vcxproj", "{61B333C2-C4F7-4CC1-A9BF-83F6D95588EB}" @@ -35,6 +37,10 @@ Global {252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}.Debug|x64.Build.0 = DLL_Debug|x64 {252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}.Release|x64.ActiveCfg = DLL_Release|x64 {252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}.Release|x64.Build.0 = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Debug|x64.ActiveCfg = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Debug|x64.Build.0 = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Release|x64.ActiveCfg = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Release|x64.Build.0 = DLL_Release|x64 {85344B7F-5AA0-4E12-A065-D1333D11F6CA}.Debug|x64.ActiveCfg = Debug|x64 {85344B7F-5AA0-4E12-A065-D1333D11F6CA}.Debug|x64.Build.0 = Debug|x64 {85344B7F-5AA0-4E12-A065-D1333D11F6CA}.Release|x64.ActiveCfg = Release|x64 diff --git a/amd_tressfx_viewer/build/TressFX_Viewer_2015.sln b/amd_tressfx_viewer/build/TressFX_Viewer_2015.sln index ad6a952..7caf805 100644 --- a/amd_tressfx_viewer/build/TressFX_Viewer_2015.sln +++ b/amd_tressfx_viewer/build/TressFX_Viewer_2015.sln @@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_SDK_Minimal", "..\..\fr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_TressFX", "..\..\AMD_TressFX\build\AMD_TressFX_2015.vcxproj", "{252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_TressFX_Vulkan", "..\..\AMD_TressFX_Vulkan\build\AMD_TressFX_Vulkan_2015.vcxproj", "{9B729252-7D58-4B28-882F-DFB4EF44A485}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DXUT", "..\..\framework\d3d11\dxut\Core\DXUT_2015.vcxproj", "{85344B7F-5AA0-4E12-A065-D1333D11F6CA}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DXUTOpt", "..\..\framework\d3d11\dxut\Optional\DXUTOpt_2015.vcxproj", "{61B333C2-C4F7-4CC1-A9BF-83F6D95588EB}" @@ -35,6 +37,10 @@ Global {252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}.Debug|x64.Build.0 = DLL_Debug|x64 {252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}.Release|x64.ActiveCfg = DLL_Release|x64 {252C0AF0-91E1-82E5-1AD6-7CBC868A79E9}.Release|x64.Build.0 = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Debug|x64.ActiveCfg = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Debug|x64.Build.0 = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Release|x64.ActiveCfg = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Release|x64.Build.0 = DLL_Release|x64 {85344B7F-5AA0-4E12-A065-D1333D11F6CA}.Debug|x64.ActiveCfg = Debug|x64 {85344B7F-5AA0-4E12-A065-D1333D11F6CA}.Debug|x64.Build.0 = Debug|x64 {85344B7F-5AA0-4E12-A065-D1333D11F6CA}.Release|x64.ActiveCfg = Release|x64 diff --git a/amd_tressfx_viewer/premake/premake5.lua b/amd_tressfx_viewer/premake/premake5.lua index 3ebfad4..b0fafad 100644 --- a/amd_tressfx_viewer/premake/premake5.lua +++ b/amd_tressfx_viewer/premake/premake5.lua @@ -25,6 +25,16 @@ externalproject ("AMD_" .. _AMD_LIBRARY_NAME) ["Debug"] = "DLL_Debug", ["Release"] = "DLL_Release" } +externalproject ("AMD_" .. _AMD_LIBRARY_NAME .. "_Vulkan") + kind "SharedLib" + language "C++" + location "../../AMD_%{_AMD_LIBRARY_NAME}_Vulkan/build" + filename ("AMD_" .. _AMD_LIBRARY_NAME .. "_Vulkan" .. _AMD_VS_SUFFIX) + uuid "9B729252-7D58-4B28-882F-DFB4EF44A485" + configmap { + ["Debug"] = "DLL_Debug", + ["Release"] = "DLL_Release" } + externalproject "AMD_LIB_Minimal" kind "StaticLib" language "C++" diff --git a/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2012.sln b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2012.sln new file mode 100644 index 0000000..168ff52 --- /dev/null +++ b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2012.sln @@ -0,0 +1,66 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_TressFX_Vulkan", "AMD_TressFX_Vulkan_2012.vcxproj", "{9B729252-7D58-4B28-882F-DFB4EF44A485}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_LIB_Minimal", "..\..\amd_lib\shared\d3d11\build\AMD_LIB_Minimal_2012.vcxproj", "{0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DLL_Debug|Win32 = DLL_Debug|Win32 + DLL_Debug|x64 = DLL_Debug|x64 + DLL_Release_MT|Win32 = DLL_Release_MT|Win32 + DLL_Release_MT|x64 = DLL_Release_MT|x64 + DLL_Release|Win32 = DLL_Release|Win32 + DLL_Release|x64 = DLL_Release|x64 + Lib_Debug|Win32 = Lib_Debug|Win32 + Lib_Debug|x64 = Lib_Debug|x64 + Lib_Release|Win32 = Lib_Release|Win32 + Lib_Release|x64 = Lib_Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|Win32.ActiveCfg = DLL_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|Win32.Build.0 = DLL_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|x64.ActiveCfg = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|x64.Build.0 = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|Win32.ActiveCfg = DLL_Release_MT|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|Win32.Build.0 = DLL_Release_MT|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|x64.ActiveCfg = DLL_Release_MT|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|x64.Build.0 = DLL_Release_MT|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|Win32.ActiveCfg = DLL_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|Win32.Build.0 = DLL_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|x64.ActiveCfg = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|x64.Build.0 = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|Win32.ActiveCfg = Lib_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|Win32.Build.0 = Lib_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|x64.ActiveCfg = Lib_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|x64.Build.0 = Lib_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|Win32.ActiveCfg = Lib_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|Win32.Build.0 = Lib_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|x64.ActiveCfg = Lib_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|x64.Build.0 = Lib_Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|Win32.ActiveCfg = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|Win32.Build.0 = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|x64.ActiveCfg = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|x64.Build.0 = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|Win32.ActiveCfg = Release_MT|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|Win32.Build.0 = Release_MT|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|x64.ActiveCfg = Release_MT|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|x64.Build.0 = Release_MT|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|Win32.ActiveCfg = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|Win32.Build.0 = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|x64.ActiveCfg = Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|x64.Build.0 = Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|Win32.ActiveCfg = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|Win32.Build.0 = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|x64.ActiveCfg = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|x64.Build.0 = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|Win32.ActiveCfg = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|Win32.Build.0 = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|x64.ActiveCfg = Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2012.vcxproj b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2012.vcxproj new file mode 100644 index 0000000..a8a1c69 --- /dev/null +++ b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2012.vcxproj @@ -0,0 +1,567 @@ + + + + + DLL_Debug + Win32 + + + DLL_Debug + x64 + + + DLL_Release + Win32 + + + DLL_Release + x64 + + + Lib_Debug + Win32 + + + Lib_Debug + x64 + + + Lib_Release + Win32 + + + Lib_Release + x64 + + + DLL_Release_MT + Win32 + + + DLL_Release_MT + x64 + + + + {9B729252-7D58-4B28-882F-DFB4EF44A485} + Win32Proj + AMD_TressFX_Vulkan + AMD_TressFX_Vulkan + + + + DynamicLibrary + true + Unicode + v110 + + + DynamicLibrary + true + Unicode + v110 + + + DynamicLibrary + false + Unicode + v110 + + + DynamicLibrary + false + Unicode + v110 + + + StaticLibrary + true + Unicode + v110 + + + StaticLibrary + true + Unicode + v110 + + + StaticLibrary + false + Unicode + v110 + + + StaticLibrary + false + Unicode + v110 + + + DynamicLibrary + false + Unicode + v110 + + + DynamicLibrary + false + Unicode + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + ..\lib\VS2012\Win32\DLL_Debug\ + VS2012\Win32\DLL_Debug\ + GPUOpen_TressFX_x86d + .dll + + + true + ..\lib\VS2012\x64\DLL_Debug\ + VS2012\x64\DLL_Debug\ + GPUOpen_TressFX_x64d + .dll + + + false + ..\lib\VS2012\Win32\DLL_Release\ + VS2012\Win32\DLL_Release\ + GPUOpen_TressFX_x86 + .dll + + + false + ..\lib\VS2012\x64\DLL_Release\ + VS2012\x64\DLL_Release\ + GPUOpen_TressFX_x64 + .dll + + + ..\lib\VS2012\Win32\Lib_Debug\ + VS2012\Win32\Lib_Debug\ + GPUOpen_TressFX_x86d + .lib + + + ..\lib\VS2012\x64\Lib_Debug\ + VS2012\x64\Lib_Debug\ + GPUOpen_TressFX_x64d + .lib + + + ..\lib\VS2012\Win32\Lib_Release\ + VS2012\Win32\Lib_Release\ + GPUOpen_TressFX_x86 + .lib + + + ..\lib\VS2012\x64\Lib_Release\ + VS2012\x64\Lib_Release\ + GPUOpen_TressFX_x64 + .lib + + + false + ..\lib\VS2012\Win32\DLL_Release_MT\ + VS2012\Win32\DLL_Release_MT\ + GPUOpen_TressFX_x86 + .dll + + + false + ..\lib\VS2012\x64\DLL_Release_MT\ + VS2012\x64\DLL_Release_MT\ + GPUOpen_TressFX_x64 + .dll + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + EditAndContinue + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2012\Win32\DLL_Debug\GPUOpen_TressFX_x86d.lib + true + + + copy /b "..\lib\VS2012\Win32\DLL_Debug\$(TargetName).lib" +,, "..\lib\VS2012\Win32\DLL_Debug\" > nul +xcopy "..\lib\VS2012\Win32\DLL_Debug\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2012\Win32\DLL_Debug\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + ProgramDatabase + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2012\x64\DLL_Debug\GPUOpen_TressFX_x64d.lib + true + + + copy /b "..\lib\VS2012\x64\DLL_Debug\$(TargetName).lib" +,, "..\lib\VS2012\x64\DLL_Debug\" > nul +xcopy "..\lib\VS2012\x64\DLL_Debug\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2012\x64\DLL_Debug\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2012\Win32\DLL_Release\GPUOpen_TressFX_x86.lib + true + + + copy /b "..\lib\VS2012\Win32\DLL_Release\$(TargetName).lib" +,, "..\lib\VS2012\Win32\DLL_Release\" > nul +xcopy "..\lib\VS2012\Win32\DLL_Release\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2012\Win32\DLL_Release\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2012\x64\DLL_Release\GPUOpen_TressFX_x64.lib + true + + + copy /b "..\lib\VS2012\x64\DLL_Release\$(TargetName).lib" +,, "..\lib\VS2012\x64\DLL_Release\" > nul +xcopy "..\lib\VS2012\x64\DLL_Release\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2012\x64\DLL_Release\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + EditAndContinue + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + ProgramDatabase + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + MultiThreaded + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2012\Win32\DLL_Release_MT\GPUOpen_TressFX_x86.lib + true + + + copy /b "..\lib\VS2012\Win32\DLL_Release_MT\$(TargetName).lib" +,, "..\lib\VS2012\Win32\DLL_Release_MT\" > nul +xcopy "..\lib\VS2012\Win32\DLL_Release_MT\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2012\Win32\DLL_Release_MT\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + MultiThreaded + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2012\x64\DLL_Release_MT\GPUOpen_TressFX_x64.lib + true + + + copy /b "..\lib\VS2012\x64\DLL_Release_MT\$(TargetName).lib" +,, "..\lib\VS2012\x64\DLL_Release_MT\" > nul +xcopy "..\lib\VS2012\x64\DLL_Release_MT\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2012\x64\DLL_Release_MT\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44} + + + + + + \ No newline at end of file diff --git a/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2012.vcxproj.filters b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2012.vcxproj.filters new file mode 100644 index 0000000..9682ca1 --- /dev/null +++ b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2012.vcxproj.filters @@ -0,0 +1,167 @@ + + + + + {E5B4C84B-516A-4141-DA5E-3B1846133845} + + + {7C5D4EB9-E8E8-BB7D-F1F9-3E725D04187E} + + + {D58F8ECE-C11E-1898-6A3D-2C9356AB283E} + + + {2DAB880B-99B4-887C-2230-9F7C8E38947C} + + + {06ADC7FB-7262-40F1-FB56-3AC8670B37F5} + + + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src + + + amd_tressfx\src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + \ No newline at end of file diff --git a/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2013.sln b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2013.sln new file mode 100644 index 0000000..d0c6490 --- /dev/null +++ b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2013.sln @@ -0,0 +1,66 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_TressFX_Vulkan", "AMD_TressFX_Vulkan_2013.vcxproj", "{9B729252-7D58-4B28-882F-DFB4EF44A485}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_LIB_Minimal", "..\..\amd_lib\shared\d3d11\build\AMD_LIB_Minimal_2013.vcxproj", "{0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DLL_Debug|Win32 = DLL_Debug|Win32 + DLL_Debug|x64 = DLL_Debug|x64 + DLL_Release_MT|Win32 = DLL_Release_MT|Win32 + DLL_Release_MT|x64 = DLL_Release_MT|x64 + DLL_Release|Win32 = DLL_Release|Win32 + DLL_Release|x64 = DLL_Release|x64 + Lib_Debug|Win32 = Lib_Debug|Win32 + Lib_Debug|x64 = Lib_Debug|x64 + Lib_Release|Win32 = Lib_Release|Win32 + Lib_Release|x64 = Lib_Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|Win32.ActiveCfg = DLL_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|Win32.Build.0 = DLL_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|x64.ActiveCfg = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|x64.Build.0 = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|Win32.ActiveCfg = DLL_Release_MT|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|Win32.Build.0 = DLL_Release_MT|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|x64.ActiveCfg = DLL_Release_MT|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|x64.Build.0 = DLL_Release_MT|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|Win32.ActiveCfg = DLL_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|Win32.Build.0 = DLL_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|x64.ActiveCfg = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|x64.Build.0 = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|Win32.ActiveCfg = Lib_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|Win32.Build.0 = Lib_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|x64.ActiveCfg = Lib_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|x64.Build.0 = Lib_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|Win32.ActiveCfg = Lib_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|Win32.Build.0 = Lib_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|x64.ActiveCfg = Lib_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|x64.Build.0 = Lib_Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|Win32.ActiveCfg = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|Win32.Build.0 = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|x64.ActiveCfg = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|x64.Build.0 = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|Win32.ActiveCfg = Release_MT|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|Win32.Build.0 = Release_MT|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|x64.ActiveCfg = Release_MT|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|x64.Build.0 = Release_MT|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|Win32.ActiveCfg = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|Win32.Build.0 = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|x64.ActiveCfg = Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|x64.Build.0 = Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|Win32.ActiveCfg = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|Win32.Build.0 = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|x64.ActiveCfg = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|x64.Build.0 = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|Win32.ActiveCfg = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|Win32.Build.0 = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|x64.ActiveCfg = Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2013.vcxproj b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2013.vcxproj new file mode 100644 index 0000000..9c7fc12 --- /dev/null +++ b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2013.vcxproj @@ -0,0 +1,568 @@ + + + + + DLL_Debug + Win32 + + + DLL_Debug + x64 + + + DLL_Release + Win32 + + + DLL_Release + x64 + + + Lib_Debug + Win32 + + + Lib_Debug + x64 + + + Lib_Release + Win32 + + + Lib_Release + x64 + + + DLL_Release_MT + Win32 + + + DLL_Release_MT + x64 + + + + {9B729252-7D58-4B28-882F-DFB4EF44A485} + true + Win32Proj + AMD_TressFX_Vulkan + AMD_TressFX_Vulkan + + + + DynamicLibrary + true + Unicode + v120 + + + DynamicLibrary + true + Unicode + v120 + + + DynamicLibrary + false + Unicode + v120 + + + DynamicLibrary + false + Unicode + v120 + + + StaticLibrary + true + Unicode + v120 + + + StaticLibrary + true + Unicode + v120 + + + StaticLibrary + false + Unicode + v120 + + + StaticLibrary + false + Unicode + v120 + + + DynamicLibrary + false + Unicode + v120 + + + DynamicLibrary + false + Unicode + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + ..\lib\VS2013\Win32\DLL_Debug\ + VS2013\Win32\DLL_Debug\ + GPUOpen_TressFX_x86d + .dll + + + true + ..\lib\VS2013\x64\DLL_Debug\ + VS2013\x64\DLL_Debug\ + GPUOpen_TressFX_x64d + .dll + + + false + ..\lib\VS2013\Win32\DLL_Release\ + VS2013\Win32\DLL_Release\ + GPUOpen_TressFX_x86 + .dll + + + false + ..\lib\VS2013\x64\DLL_Release\ + VS2013\x64\DLL_Release\ + GPUOpen_TressFX_x64 + .dll + + + ..\lib\VS2013\Win32\Lib_Debug\ + VS2013\Win32\Lib_Debug\ + GPUOpen_TressFX_x86d + .lib + + + ..\lib\VS2013\x64\Lib_Debug\ + VS2013\x64\Lib_Debug\ + GPUOpen_TressFX_x64d + .lib + + + ..\lib\VS2013\Win32\Lib_Release\ + VS2013\Win32\Lib_Release\ + GPUOpen_TressFX_x86 + .lib + + + ..\lib\VS2013\x64\Lib_Release\ + VS2013\x64\Lib_Release\ + GPUOpen_TressFX_x64 + .lib + + + false + ..\lib\VS2013\Win32\DLL_Release_MT\ + VS2013\Win32\DLL_Release_MT\ + GPUOpen_TressFX_x86 + .dll + + + false + ..\lib\VS2013\x64\DLL_Release_MT\ + VS2013\x64\DLL_Release_MT\ + GPUOpen_TressFX_x64 + .dll + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + EditAndContinue + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2013\Win32\DLL_Debug\GPUOpen_TressFX_x86d.lib + true + + + copy /b "..\lib\VS2013\Win32\DLL_Debug\$(TargetName).lib" +,, "..\lib\VS2013\Win32\DLL_Debug\" > nul +xcopy "..\lib\VS2013\Win32\DLL_Debug\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2013\Win32\DLL_Debug\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + ProgramDatabase + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2013\x64\DLL_Debug\GPUOpen_TressFX_x64d.lib + true + + + copy /b "..\lib\VS2013\x64\DLL_Debug\$(TargetName).lib" +,, "..\lib\VS2013\x64\DLL_Debug\" > nul +xcopy "..\lib\VS2013\x64\DLL_Debug\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2013\x64\DLL_Debug\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2013\Win32\DLL_Release\GPUOpen_TressFX_x86.lib + true + + + copy /b "..\lib\VS2013\Win32\DLL_Release\$(TargetName).lib" +,, "..\lib\VS2013\Win32\DLL_Release\" > nul +xcopy "..\lib\VS2013\Win32\DLL_Release\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2013\Win32\DLL_Release\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2013\x64\DLL_Release\GPUOpen_TressFX_x64.lib + true + + + copy /b "..\lib\VS2013\x64\DLL_Release\$(TargetName).lib" +,, "..\lib\VS2013\x64\DLL_Release\" > nul +xcopy "..\lib\VS2013\x64\DLL_Release\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2013\x64\DLL_Release\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + EditAndContinue + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + ProgramDatabase + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + MultiThreaded + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2013\Win32\DLL_Release_MT\GPUOpen_TressFX_x86.lib + true + + + copy /b "..\lib\VS2013\Win32\DLL_Release_MT\$(TargetName).lib" +,, "..\lib\VS2013\Win32\DLL_Release_MT\" > nul +xcopy "..\lib\VS2013\Win32\DLL_Release_MT\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2013\Win32\DLL_Release_MT\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + MultiThreaded + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2013\x64\DLL_Release_MT\GPUOpen_TressFX_x64.lib + true + + + copy /b "..\lib\VS2013\x64\DLL_Release_MT\$(TargetName).lib" +,, "..\lib\VS2013\x64\DLL_Release_MT\" > nul +xcopy "..\lib\VS2013\x64\DLL_Release_MT\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2013\x64\DLL_Release_MT\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44} + + + + + + \ No newline at end of file diff --git a/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2013.vcxproj.filters b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2013.vcxproj.filters new file mode 100644 index 0000000..9682ca1 --- /dev/null +++ b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2013.vcxproj.filters @@ -0,0 +1,167 @@ + + + + + {E5B4C84B-516A-4141-DA5E-3B1846133845} + + + {7C5D4EB9-E8E8-BB7D-F1F9-3E725D04187E} + + + {D58F8ECE-C11E-1898-6A3D-2C9356AB283E} + + + {2DAB880B-99B4-887C-2230-9F7C8E38947C} + + + {06ADC7FB-7262-40F1-FB56-3AC8670B37F5} + + + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src + + + amd_tressfx\src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + \ No newline at end of file diff --git a/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2015.sln b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2015.sln new file mode 100644 index 0000000..7db7b73 --- /dev/null +++ b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2015.sln @@ -0,0 +1,66 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_TressFX_Vulkan", "AMD_TressFX_Vulkan_2015.vcxproj", "{9B729252-7D58-4B28-882F-DFB4EF44A485}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_LIB_Minimal", "..\..\amd_lib\shared\d3d11\build\AMD_LIB_Minimal_2015.vcxproj", "{0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DLL_Debug|Win32 = DLL_Debug|Win32 + DLL_Debug|x64 = DLL_Debug|x64 + DLL_Release_MT|Win32 = DLL_Release_MT|Win32 + DLL_Release_MT|x64 = DLL_Release_MT|x64 + DLL_Release|Win32 = DLL_Release|Win32 + DLL_Release|x64 = DLL_Release|x64 + Lib_Debug|Win32 = Lib_Debug|Win32 + Lib_Debug|x64 = Lib_Debug|x64 + Lib_Release|Win32 = Lib_Release|Win32 + Lib_Release|x64 = Lib_Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|Win32.ActiveCfg = DLL_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|Win32.Build.0 = DLL_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|x64.ActiveCfg = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Debug|x64.Build.0 = DLL_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|Win32.ActiveCfg = DLL_Release_MT|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|Win32.Build.0 = DLL_Release_MT|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|x64.ActiveCfg = DLL_Release_MT|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release_MT|x64.Build.0 = DLL_Release_MT|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|Win32.ActiveCfg = DLL_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|Win32.Build.0 = DLL_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|x64.ActiveCfg = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.DLL_Release|x64.Build.0 = DLL_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|Win32.ActiveCfg = Lib_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|Win32.Build.0 = Lib_Debug|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|x64.ActiveCfg = Lib_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Debug|x64.Build.0 = Lib_Debug|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|Win32.ActiveCfg = Lib_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|Win32.Build.0 = Lib_Release|Win32 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|x64.ActiveCfg = Lib_Release|x64 + {9B729252-7D58-4B28-882F-DFB4EF44A485}.Lib_Release|x64.Build.0 = Lib_Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|Win32.ActiveCfg = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|Win32.Build.0 = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|x64.ActiveCfg = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Debug|x64.Build.0 = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|Win32.ActiveCfg = Release_MT|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|Win32.Build.0 = Release_MT|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|x64.ActiveCfg = Release_MT|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release_MT|x64.Build.0 = Release_MT|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|Win32.ActiveCfg = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|Win32.Build.0 = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|x64.ActiveCfg = Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.DLL_Release|x64.Build.0 = Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|Win32.ActiveCfg = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|Win32.Build.0 = Debug|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|x64.ActiveCfg = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Debug|x64.Build.0 = Debug|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|Win32.ActiveCfg = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|Win32.Build.0 = Release|Win32 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|x64.ActiveCfg = Release|x64 + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44}.Lib_Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2015.vcxproj b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2015.vcxproj new file mode 100644 index 0000000..40fc07b --- /dev/null +++ b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2015.vcxproj @@ -0,0 +1,559 @@ + + + + + DLL_Debug + Win32 + + + DLL_Debug + x64 + + + DLL_Release + Win32 + + + DLL_Release + x64 + + + Lib_Debug + Win32 + + + Lib_Debug + x64 + + + Lib_Release + Win32 + + + Lib_Release + x64 + + + DLL_Release_MT + Win32 + + + DLL_Release_MT + x64 + + + + {9B729252-7D58-4B28-882F-DFB4EF44A485} + true + Win32Proj + AMD_TressFX_Vulkan + AMD_TressFX_Vulkan + 8.1 + + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + false + Unicode + v140 + + + DynamicLibrary + false + Unicode + v140 + + + StaticLibrary + true + Unicode + v140 + + + StaticLibrary + true + Unicode + v140 + + + StaticLibrary + false + Unicode + v140 + + + StaticLibrary + false + Unicode + v140 + + + DynamicLibrary + false + Unicode + v140 + + + DynamicLibrary + false + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + ..\lib\VS2015\Win32\DLL_Debug\ + VS2015\Win32\DLL_Debug\ + GPUOpen_TressFX_x86d + .dll + + + true + ..\lib\VS2015\x64\DLL_Debug\ + VS2015\x64\DLL_Debug\ + GPUOpen_TressFX_x64d + .dll + + + false + ..\lib\VS2015\Win32\DLL_Release\ + VS2015\Win32\DLL_Release\ + GPUOpen_TressFX_x86 + .dll + + + false + ..\lib\VS2015\x64\DLL_Release\ + VS2015\x64\DLL_Release\ + GPUOpen_TressFX_x64 + .dll + + + ..\lib\VS2015\Win32\Lib_Debug\ + VS2015\Win32\Lib_Debug\ + GPUOpen_TressFX_x86d + .lib + + + ..\lib\VS2015\x64\Lib_Debug\ + VS2015\x64\Lib_Debug\ + GPUOpen_TressFX_x64d + .lib + + + ..\lib\VS2015\Win32\Lib_Release\ + VS2015\Win32\Lib_Release\ + GPUOpen_TressFX_x86 + .lib + + + ..\lib\VS2015\x64\Lib_Release\ + VS2015\x64\Lib_Release\ + GPUOpen_TressFX_x64 + .lib + + + false + ..\lib\VS2015\Win32\DLL_Release_MT\ + VS2015\Win32\DLL_Release_MT\ + GPUOpen_TressFX_x86 + .dll + + + false + ..\lib\VS2015\x64\DLL_Release_MT\ + VS2015\x64\DLL_Release_MT\ + GPUOpen_TressFX_x64 + .dll + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + EditAndContinue + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2015\Win32\DLL_Debug\GPUOpen_TressFX_x86d.lib + true + + + copy /b "..\lib\VS2015\Win32\DLL_Debug\$(TargetName).lib" +,, "..\lib\VS2015\Win32\DLL_Debug\" > nul +xcopy "..\lib\VS2015\Win32\DLL_Debug\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2015\Win32\DLL_Debug\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + ProgramDatabase + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2015\x64\DLL_Debug\GPUOpen_TressFX_x64d.lib + true + + + copy /b "..\lib\VS2015\x64\DLL_Debug\$(TargetName).lib" +,, "..\lib\VS2015\x64\DLL_Debug\" > nul +xcopy "..\lib\VS2015\x64\DLL_Debug\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2015\x64\DLL_Debug\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2015\Win32\DLL_Release\GPUOpen_TressFX_x86.lib + true + + + copy /b "..\lib\VS2015\Win32\DLL_Release\$(TargetName).lib" +,, "..\lib\VS2015\Win32\DLL_Release\" > nul +xcopy "..\lib\VS2015\Win32\DLL_Release\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2015\Win32\DLL_Release\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2015\x64\DLL_Release\GPUOpen_TressFX_x64.lib + true + + + copy /b "..\lib\VS2015\x64\DLL_Release\$(TargetName).lib" +,, "..\lib\VS2015\x64\DLL_Release\" > nul +xcopy "..\lib\VS2015\x64\DLL_Release\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2015\x64\DLL_Release\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + EditAndContinue + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + ProgramDatabase + Disabled + false + false + /EHsc %(AdditionalOptions) + + + Windows + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_LIB;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=0;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + + + true + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + MultiThreaded + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2015\Win32\DLL_Release_MT\GPUOpen_TressFX_x86.lib + true + + + copy /b "..\lib\VS2015\Win32\DLL_Release_MT\$(TargetName).lib" +,, "..\lib\VS2015\Win32\DLL_Release_MT\" > nul +xcopy "..\lib\VS2015\Win32\DLL_Release_MT\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2015\Win32\DLL_Release_MT\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + NotUsing + Level4 + true + AMD_TRESSFX_VULKAN=1;_USRDLL;AMD_TRESSFX_COMPILE_DYNAMIC_LIB=1;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0601;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ..\inc;..\..\amd_lib\shared\common\inc;..\..\amd_tressfx\inc;..\..\amd_tressfx\src;$(VULKAN_SDK)\Include;%(AdditionalIncludeDirectories) + Full + true + true + false + true + MultiThreaded + false + false + /EHsc %(AdditionalOptions) + + + Windows + false + true + true + vulkan-1.lib;%(AdditionalDependencies) + $(VULKAN_SDK)\Bin;%(AdditionalLibraryDirectories) + ..\lib\VS2015\x64\DLL_Release_MT\GPUOpen_TressFX_x64.lib + true + + + copy /b "..\lib\VS2015\x64\DLL_Release_MT\$(TargetName).lib" +,, "..\lib\VS2015\x64\DLL_Release_MT\" > nul +xcopy "..\lib\VS2015\x64\DLL_Release_MT\$(TargetName).dll" "..\lib" /H /R /Y > nul +xcopy "..\lib\VS2015\x64\DLL_Release_MT\$(TargetName).lib" "..\lib" /H /R /Y > nul + Copying build output to lib directory... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {0D2AEA47-7909-69E3-8221-F4B9EE7FCF44} + + + + + + \ No newline at end of file diff --git a/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2015.vcxproj.filters b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2015.vcxproj.filters new file mode 100644 index 0000000..9682ca1 --- /dev/null +++ b/amd_tressfx_vulkan/build/AMD_TressFX_Vulkan_2015.vcxproj.filters @@ -0,0 +1,167 @@ + + + + + {E5B4C84B-516A-4141-DA5E-3B1846133845} + + + {7C5D4EB9-E8E8-BB7D-F1F9-3E725D04187E} + + + {D58F8ECE-C11E-1898-6A3D-2C9356AB283E} + + + {2DAB880B-99B4-887C-2230-9F7C8E38947C} + + + {06ADC7FB-7262-40F1-FB56-3AC8670B37F5} + + + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + src\Shaders + + + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src\Math + + + amd_tressfx\src + + + amd_tressfx\src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + \ No newline at end of file diff --git a/amd_tressfx_vulkan/premake/premake5.lua b/amd_tressfx_vulkan/premake/premake5.lua new file mode 100644 index 0000000..11efec6 --- /dev/null +++ b/amd_tressfx_vulkan/premake/premake5.lua @@ -0,0 +1,94 @@ +_AMD_LIBRARY_NAME = "TressFX" +_AMD_LIBRARY_NAME_ALL_CAPS = string.upper(_AMD_LIBRARY_NAME) + +-- Set _AMD_LIBRARY_NAME before including amd_premake_util.lua +dofile ("../../premake/amd_premake_util.lua") + +workspace ("AMD_" .. _AMD_LIBRARY_NAME .. "_Vulkan") + configurations { "DLL_Debug", "DLL_Release", "Lib_Debug", "Lib_Release", "DLL_Release_MT" } + platforms { "Win32", "x64" } + location "../build" + filename ("AMD_" .. _AMD_LIBRARY_NAME .. "_Vulkan" .. _AMD_VS_SUFFIX) + startproject ("AMD_" .. _AMD_LIBRARY_NAME .. "_Vulkan") + + filter "platforms:Win32" + system "Windows" + architecture "x86" + + filter "platforms:x64" + system "Windows" + architecture "x64" + +externalproject "AMD_LIB_Minimal" + kind "StaticLib" + language "C++" + location "../../amd_lib/shared/d3d11/build" + filename ("AMD_LIB_Minimal" .. _AMD_VS_SUFFIX) + uuid "0D2AEA47-7909-69E3-8221-F4B9EE7FCF44" + configmap { + ["DLL_Debug"] = "Debug", + ["DLL_Release"] = "Release", + ["Lib_Debug"] = "Debug", + ["Lib_Release"] = "Release", + ["DLL_Release_MT"] = "Release_MT" } + +project ("AMD_" .. _AMD_LIBRARY_NAME .. "_Vulkan") + language "C++" + location "../build" + filename ("AMD_" .. _AMD_LIBRARY_NAME .. "_Vulkan".. _AMD_VS_SUFFIX) + uuid "9B729252-7D58-4B28-882F-DFB4EF44A485" + targetdir "../lib/%{_AMD_LIBRARY_DIR_LAYOUT}" + objdir "../build/%{_AMD_LIBRARY_DIR_LAYOUT}" + warnings "Extra" + exceptionhandling "Off" + rtti "Off" + + -- Specify WindowsTargetPlatformVersion here for VS2015 + windowstarget (_AMD_WIN_SDK_VERSION) + defines { "AMD_TRESSFX_VULKAN=1"} + files { "../inc/**.h", "../src/**.h", "../src/**.cpp", "../src/Shaders/**.glsl", "../src/Shaders/**.comp", "../src/Shaders/**.vert", "../src/Shaders/**.frag", "../../amd_tressfx/src/TressFXAsset.cpp", "../../amd_tressfx/src/Util.cpp", "../../amd_tressfx/src/Math/**.cpp" } + includedirs { "../inc", "../../amd_lib/shared/common/inc", "../../amd_tressfx/inc", "../../amd_tressfx/src", "$(VULKAN_SDK)/Include" } + libdirs { "$(VULKAN_SDK)/Bin"} + links { "AMD_LIB_Minimal", "vulkan-1" } + + filter "configurations:DLL_*" + kind "SharedLib" + defines { "_USRDLL", "AMD_%{_AMD_LIBRARY_NAME_ALL_CAPS}_COMPILE_DYNAMIC_LIB=1" } + -- Copy DLL and import library to the lib directory + postbuildcommands { amdLibPostbuildCommands() } + postbuildmessage "Copying build output to lib directory..." + + filter "configurations:Lib_*" + kind "StaticLib" + defines { "_LIB", "AMD_%{_AMD_LIBRARY_NAME_ALL_CAPS}_COMPILE_DYNAMIC_LIB=0" } + + filter "configurations:*_Debug" + defines { "WIN32", "_DEBUG", "_WINDOWS", "_WIN32_WINNT=0x0601", "_SCL_SECURE_NO_WARNINGS" } + flags { "Symbols", "FatalWarnings", "Unicode" } + -- add "d" to the end of the library name for debug builds + targetsuffix "d" + + filter "configurations:*_Release" + defines { "WIN32", "NDEBUG", "_WINDOWS", "_WIN32_WINNT=0x0601", "_SCL_SECURE_NO_WARNINGS" } + flags { "FatalWarnings", "Unicode" } + optimize "On" + + filter "configurations:DLL_Release_MT" + defines { "WIN32", "NDEBUG", "_WINDOWS", "_WIN32_WINNT=0x0601", "_SCL_SECURE_NO_WARNINGS" } + flags { "FatalWarnings", "Unicode" } + -- link against the static runtime to avoid introducing a dependency + -- on the particular version of Visual Studio used to build the DLLs + flags { "StaticRuntime" } + optimize "On" + + filter "action:vs*" + -- specify exception handling model for Visual Studio to avoid + -- "'noexcept' used with no exception handling mode specified" + -- warning in vs2015 + buildoptions { "/EHsc" } + + filter "platforms:Win32" + targetname "%{_AMD_LIBRARY_PREFIX}%{_AMD_LIBRARY_NAME}_x86" + + filter "platforms:x64" + targetname "%{_AMD_LIBRARY_PREFIX}%{_AMD_LIBRARY_NAME}_x64" diff --git a/amd_tressfx_vulkan/shader_builder/shader_builder/shader_builder.py b/amd_tressfx_vulkan/shader_builder/shader_builder/shader_builder.py new file mode 100644 index 0000000..f0a4ec3 --- /dev/null +++ b/amd_tressfx_vulkan/shader_builder/shader_builder/shader_builder.py @@ -0,0 +1,68 @@ +import os; +import array; +import re; + +def get_file_content(filename): + src_file = open("..\..\src\Shaders\\" + filename, 'r') + return src_file.read() + +def load_array(name, filename): + src_file = open("..\..\src\Shaders\\" + filename) + if filename.endswith('.vert'): + temporary_file = open('temp.vert', 'w') + elif filename.endswith('.frag'): + temporary_file = open('temp.frag', 'w') + else: + temporary_file = open('temp.comp', 'w') + line = src_file.readline() + while line != '': + m = re.search(r'^#include "(.*)"', line) + if m: + temporary_file.write(get_file_content(m.group(1))) + else: + temporary_file.write(line) + line = src_file.readline() + temporary_file.close() + if filename.endswith('.vert'): + os.system("glslangValidator.exe -V temp.vert") + f = open("vert.spv", 'rb') + filesize = os.path.getsize("vert.spv") + elif filename.endswith('.frag'): + os.system("glslangValidator.exe -V temp.frag") + f = open("frag.spv", 'rb') + filesize = os.path.getsize("frag.spv") + else: + os.system("glslangValidator.exe -V temp.comp") + f = open("comp.spv", 'rb') + filesize = os.path.getsize("comp.spv") + a = array.array('L') + a.fromfile(f, filesize // 4) + f.close() + code = "const std::vector " + name +" = {" + for i in a: + code += str(i) + ",\n" + code += "};\n" + return code + +output = open("..\..\src\TressFXPrecompiledShadersVulkan.h", 'w') +output.write("#include \n") +output.write(load_array("hair_shadow_vertex", "HairShadowMap.vert")) +output.write(load_array("hair_shadow_fragment", "HairShadowMap.frag")) +output.write(load_array("render_hair_vertex", "RenderHair.vert")) +output.write(load_array("render_hair_aa_vertex", "RenderHairAA.vert")) +output.write(load_array("render_hair_strand_copies_vertex", "RenderHairStrandCopies.vert")) +output.write(load_array("render_hair_aa_strand_copies_vertex", "RenderHairAAStrandCopies.vert")) +output.write(load_array("pass1_fragment", "TressFXRender.frag")) +output.write(load_array("pass2_vertex", "TressFXRender_pass2.vert")) +output.write(load_array("pass2_fragment", "TressFXRender_pass2.frag")) +output.write(load_array("global_constraints", "GlobalConstraints.comp")) +output.write(load_array("local_constraints", "LocalConstraints.comp")) +output.write(load_array("compute_tangents", "ComputeTangents.comp")) +output.write(load_array("length_wind_collision", "LengthWindCollision.comp")) +output.write(load_array("prepare_follow_hair", "PrepareFollowHair.comp")) +output.write(load_array("update_follow_hair", "UpdateFollowHair.comp")) +output.write(load_array("depth_hair_data", "FS_Depth_Hair_Data.frag")) +output.write(load_array("resolve_depth", "FS_ResolveDepth_Hair_Data.frag")) +output.write(load_array("fillcolors_hair_data", "FS_FillColors_Hair_Data.frag")) +output.write(load_array("resolvecolors", "FS_ResolveColor_Hair_Data.frag")) +output.close() diff --git a/amd_tressfx_vulkan/shader_builder/shader_builder/shader_builder.pyproj b/amd_tressfx_vulkan/shader_builder/shader_builder/shader_builder.pyproj new file mode 100644 index 0000000..2888265 --- /dev/null +++ b/amd_tressfx_vulkan/shader_builder/shader_builder/shader_builder.pyproj @@ -0,0 +1,41 @@ + + + + Debug + 2.0 + 5cb29e1d-e89d-42ae-9c2d-dbc0a988c843 + . + shader_builder.py + + + . + . + shader_builder + shader_builder + + + true + false + + + true + false + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets + + + + + + + + + + \ No newline at end of file diff --git a/amd_tressfx_vulkan/src/Shaders/ComputeCoverage.glsl b/amd_tressfx_vulkan/src/Shaders/ComputeCoverage.glsl new file mode 100644 index 0000000..175fa61 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/ComputeCoverage.glsl @@ -0,0 +1,33 @@ +//-------------------------------------------------------------------------------------- +// ComputeCoverage +// +// Calculate the pixel coverage of a hair strand by computing the hair width +//-------------------------------------------------------------------------------------- +float ComputeCoverage(vec2 p0, vec2 p1, vec2 pixelLoc) +{ + // p0, p1, pixelLoc are in d3d clip space (-1 to 1)x(-1 to 1) + + // Scale positions so 1.f = half pixel width + p0 *= g_WinSize.xy; + p1 *= g_WinSize.xy; + pixelLoc.y *= -1; + pixelLoc *= g_WinSize.xy; + + float p0dist = length(p0 - pixelLoc); + float p1dist = length(p1 - pixelLoc); + float hairWidth = length(p0 - p1); + + // will be 1.f if pixel outside hair, 0.f if pixel inside hair + bool outside = any(bvec2(step(hairWidth, p0dist) > 0., step(hairWidth, p1dist) > 0.)); + + // if outside, set sign to -1, else set sign to 1 + float sign = outside ? -1.f : 1.f; + + // signed distance (positive if inside hair, negative if outside hair) + float relDist = sign * clamp(min(p0dist, p1dist), 0., 1.); + + // returns coverage based on the relative distance + // 0, if completely outside hair edge + // 1, if completely inside hair edge + return (relDist + 1.f) * 0.5f; +} \ No newline at end of file diff --git a/amd_tressfx_vulkan/src/Shaders/ComputeHairShading.glsl b/amd_tressfx_vulkan/src/Shaders/ComputeHairShading.glsl new file mode 100644 index 0000000..5ab3121 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/ComputeHairShading.glsl @@ -0,0 +1,83 @@ + +vec3 ComputeHairShading(vec3 iPos, vec3 iTangent, vec4 iTex, float amountLight, vec3 color) +{ + vec3 baseColor = g_MatBaseColor.xyz; + float rand_value = 1; + + // if(abs(iTex.x) + abs(iTex.y) >1e-5) // if texcoord is available, use texture map + // rand_value = g_txNoise.SampleLevel(g_samLinearWrap, iTex.xy, 0).x; + + // define baseColor and Ka Kd Ks coefficient for hair + float Ka = g_MatKValue.x, Kd = g_MatKValue.y, + Ks1 = g_MatKValue.z, Ex1 = g_MatKValue.w, + Ks2 = g_fHairKs2, Ex2 = g_fHairEx2; + + vec3 lightPos = g_PointLightPos.xyz; + vec3 vLightDir = normalize(lightPos - iPos.xyz); + vec3 vEyeDir = normalize(g_vEye.xyz - iPos.xyz); + vec3 tangent = normalize(iTangent); + + // in Kajiya's model: diffuse component: sin(t, l) + float cosTL = (dot(tangent, vLightDir)); + float sinTL = sqrt(1 - cosTL*cosTL); + float diffuse = sinTL; // here sinTL is apparently larger than 0 + + float alpha = (rand_value * 10) * PI / 180; // tiled angle (5-10 dgree) + + // in Kajiya's model: specular component: cos(t, rl) * cos(t, e) + sin(t, rl)sin(t, e) + float cosTRL = -cosTL; + float sinTRL = sinTL; + float cosTE = (dot(tangent, vEyeDir)); + float sinTE = sqrt(1 - cosTE*cosTE); + + // primary highlight: reflected direction shift towards root (2 * Alpha) + float cosTRL_root = cosTRL * cos(2 * alpha) - sinTRL * sin(2 * alpha); + float sinTRL_root = sqrt(1 - cosTRL_root * cosTRL_root); + float specular_root = max(0., cosTRL_root * cosTE + sinTRL_root * sinTE); + + // secondary highlight: reflected direction shifted toward tip (3*Alpha) + float cosTRL_tip = cosTRL*cos(-3 * alpha) - sinTRL*sin(-3 * alpha); + float sinTRL_tip = sqrt(1 - cosTRL_tip * cosTRL_tip); + float specular_tip = max(0., cosTRL_tip * cosTE + sinTRL_tip * sinTE); + + vec3 vColor = Ka * g_AmbientLightColor.xyz * baseColor + // ambient + amountLight * g_PointLightColor.xyz * ( + Kd * diffuse * baseColor + // diffuse + Ks1 * pow(specular_root, Ex1) + // primary hightlight r + Ks2 * pow(specular_tip, Ex2) * baseColor); // secondary highlight rtr + + return vColor * amountLight; +} + +#define SUPERSIMPLESHADING + +vec3 SimpleHairShading(vec3 iPos, vec3 iTangent, vec4 iTex, float amountLight) +{ + vec3 baseColor = g_MatBaseColor.xyz; + float Kd = g_MatKValue.y; + +#ifdef SUPERSIMPLESHADING + vec3 vColor = amountLight * Kd * baseColor; +#else + // define baseColor and Ka Kd Ks coefficient for hair + float Ka = g_MatKValue.x; + float Ks1 = g_MatKValue.z; + float Ex1 = g_MatKValue.w; + float Ks2 = g_fHairKs2; + float Ex2 = g_fHairEx2; + + vec3 lightPos = g_PointLightPos.xyz; + vec3 vLightDir = normalize(lightPos - iPos.xyz); + vec3 tangent = normalize(iTangent); + + // in Kajiya's model: diffuse component: sin(t, l) + float cosTL = (dot(tangent, vLightDir)); + float sinTL = sqrt(1 - cosTL*cosTL); + float diffuse = sinTL; // here sinTL is apparently larger than 0 + + vec3 vColor = Ka * g_AmbientLightColor.xyz * baseColor + // ambient + amountLight * g_PointLightColor.xyz * (Kd * diffuse * baseColor); // diffuse +#endif + return vColor * amountLight; +} + diff --git a/amd_tressfx_vulkan/src/Shaders/ComputeShadow.glsl b/amd_tressfx_vulkan/src/Shaders/ComputeShadow.glsl new file mode 100644 index 0000000..9597f91 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/ComputeShadow.glsl @@ -0,0 +1,93 @@ +layout(set = 0, binding = IDSRV_HAIRSM) uniform texture2D HairShadowMap; +layout(set = 0, binding = IDSRV_SHADOW_SAMPLER) uniform sampler g_samPointClamp; + +//-------------------------------------------------------------------------------------- +// ComputeShadow +// +// Computes the shadow using a simplified deep shadow map technique for the hair and +// PCF for scene objects. It uses multiple taps to filter over a (KERNEL_SIZE x KERNEL_SIZE) +// kernel for high quality results. +//-------------------------------------------------------------------------------------- +float ComputeShadow(vec3 worldPos, float alpha) +{ + vec4 projPosLight = g_mViewProjLight * vec4(worldPos, 1); + projPosLight.xy /= projPosLight.w; + vec2 texSM = .5 * projPosLight.xy + .5; + texSM.y = 1. - texSM.y; + float depth = projPosLight.z / projPosLight.w; + float epsilon = depth * SM_EPSILON; + float depth_fragment = projPosLight.w; + + // for shadow casted by scene objs, use PCF shadow + float total_weight = 0; + float amountLight_hair = 0; + + total_weight = 0; + for (int dx = (1 - KERNEL_SIZE) / 2; dx <= KERNEL_SIZE / 2; dx++) + { + for (int dy = (1 - KERNEL_SIZE) / 2; dy <= KERNEL_SIZE / 2; dy++) + { + float size = 2.4; + float sigma = (KERNEL_SIZE / 2.0) / size; // standard deviation, when kernel/2 > 3*sigma, it's close to zero, here we use 1.5 instead + float exp = -1 * (dx * dx + dy * dy) / (2 * sigma * sigma); + float weight = 1 / (2 * PI * sigma * sigma) * pow(2.7, exp); + + // shadow casted by hair: simplified deep shadow map + float depthSMHair = 2. * texture(sampler2D(HairShadowMap, g_samPointClamp), texSM + vec2(dx, dy) / 640.).x - 1.; //z/w + + float depth_smPoint = g_fNearLight / (1 - depthSMHair * (g_fFarLight - g_fNearLight) / g_fFarLight); + + float depth_range = max(0., depth_fragment - depth_smPoint); + float numFibers = depth_range / (g_FiberSpacing * g_FiberRadius); + + // if occluded by hair, there is at least one fiber + numFibers += (depth_range > .00001) ? 1. : 0.; + amountLight_hair += pow(abs(1 - alpha), numFibers) * weight; + + total_weight += weight; + } + } + amountLight_hair /= total_weight; + + float amountLight_scene = 1.;//g_txSMScene.SampleCmpLevelZero(g_samShadow, texSM, depth-epsilon); + + return (amountLight_hair * amountLight_scene); +} + + +//-------------------------------------------------------------------------------------- +// ComputeSimpleShadow +// +// Computes the shadow using a simplified deep shadow map technique for the hair and +// PCF for scene objects. This function only uses one sample, so it is faster but +// not as good quality as ComputeShadow +//-------------------------------------------------------------------------------------- +float ComputeSimpleShadow(vec3 worldPos, float alpha) +{ + vec4 projPosLight = g_mViewProjLight * vec4(worldPos, 1); + projPosLight.xy /= projPosLight.w; + + vec2 texSM = .5 * projPosLight.xy + .5; + texSM.y = 1. - texSM.y; + float depth = projPosLight.z / projPosLight.w; + float epsilon = depth * SM_EPSILON; + float depth_fragment = projPosLight.w; + + // shadow casted by scene + float amountLight_scene = 1.;//g_txSMScene.SampleCmpLevelZero(g_samShadow, texSM, depth-epsilon); // TODO + + // shadow casted by hair: simplified deep shadow map + float depthSMHair = 2. * texture(sampler2D(HairShadowMap, g_samPointClamp), texSM).x - 1.; //z/w + + float depth_smPoint = g_fNearLight / (1. - depthSMHair * (g_fFarLight - g_fNearLight) / g_fFarLight); + + float depth_range = max(0., depth_fragment - depth_smPoint); + + float numFibers = depth_range / (g_FiberSpacing * g_FiberRadius); + + // if occluded by hair, there is at least one fiber + numFibers += (depth_range > .00001) ? 1. : 0.; + float amountLight_hair = pow(abs(1 - alpha), numFibers); + + return amountLight_hair; +} diff --git a/amd_tressfx_vulkan/src/Shaders/ComputeTangents.comp b/amd_tressfx_vulkan/src/Shaders/ComputeTangents.comp new file mode 100644 index 0000000..1e6c697 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/ComputeTangents.comp @@ -0,0 +1,44 @@ +#version 450 + +#include "SimulationConfig.glsl" + +layout(local_size_x = THREAD_GROUP_SIZE, local_size_y = 1, local_size_z = 1) in; +layout(set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) uniform usamplerBuffer g_HairVertexPositions; +layout(std430, set = 1, binding = IDSRV_HAIR_TANGENTS) buffer writeablePositions +{ + vec4 g_HairVertexTangents[]; +}; + +#include "IndicesComputations.glsl" + +shared vec4 sharedPos[THREAD_GROUP_SIZE]; + +void main() +{ + uint globalStrandIndex, localStrandIndex, localVertexIndex, numVerticesInTheStrand, indexForSharedMem, strandType; + int globalVertexIndex; + CalcIndicesInVertexLevelTotal(gl_LocalInvocationID.x, gl_WorkGroupID.x, globalStrandIndex, localStrandIndex, globalVertexIndex, localVertexIndex, numVerticesInTheStrand, indexForSharedMem, strandType); + + sharedPos[indexForSharedMem] = texelFetch(g_HairVertexPositions, globalVertexIndex); + barrier(); + + uint numOfStrandsPerThreadGroup = g_NumOfStrandsPerThreadGroup; + + if (localVertexIndex == 0) // vertex 0 + { + vec3 tangent = sharedPos[indexForSharedMem + numOfStrandsPerThreadGroup].xyz - sharedPos[indexForSharedMem].xyz; + g_HairVertexTangents[globalVertexIndex].xyz = normalize(tangent); + } + else // vertex 1 through n-1 + { + vec3 vert_i_minus_1 = sharedPos[indexForSharedMem - numOfStrandsPerThreadGroup].xyz; + vec3 vert_i = sharedPos[indexForSharedMem].xyz; + g_HairVertexTangents[globalVertexIndex].xyz = normalize(vert_i - vert_i_minus_1); + } + +/* if ( localVertexIndex < numVerticesInTheStrand - 1 ) + { + vec3 tangent = sharedPos[indexForSharedMem + numOfStrandsPerThreadGroup].xyz - sharedPos[indexForSharedMem].xyz; + g_HairVertexTangents[globalVertexIndex].xyz = normalize(tangent); + }*/ +} diff --git a/amd_tressfx_vulkan/src/Shaders/FS_Depth_Hair_Data.frag b/amd_tressfx_vulkan/src/Shaders/FS_Depth_Hair_Data.frag new file mode 100644 index 0000000..918c9c0 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/FS_Depth_Hair_Data.frag @@ -0,0 +1,78 @@ +#version 450 +#extension GL_GOOGLE_include_directive : require +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" +#include "PackUnpack.glsl" +#include "ComputeCoverage.glsl" + +layout(set = 0, binding = IDSRV_HAIR_FRAGMENT_DEPTHS, r32ui) uniform uimage2DArray RWFragmentDepthsTexture; + +layout(early_fragment_tests) in; + +layout(location = 0) in float depth; +layout(location = 1) in vec4 p0p1; +layout(location = 2) in vec4 tangent; + +layout(location = 0) out float FragColor; + +//-------------------------------------------------------------------------------------- +// PS_Depth_Hair +// +//-------------------------------------------------------------------------------------- +void main() +{ + // Render AA Line, calculate pixel coverage + vec4 proj_pos = vec4(2 * gl_FragCoord.x * g_WinSize.z - 1.0, // g_WinSize.z = 1.0/g_WinSize.x + 1 - 2 * gl_FragCoord.y * g_WinSize.w, // g_WinSize.w = 1.0/g_WinSize.y + gl_FragCoord.z, + 1); + + float curve_scale = 1; + if (g_bThinTip > 0) + curve_scale = tangent.w; + + float fiber_radius = curve_scale * g_FiberRadius; + + float coverage = 1.f; + if (g_bUseCoverage != 0) + { + coverage = ComputeCoverage(p0p1.xy, p0p1.zw, proj_pos.xy); + } + + float alpha = coverage * g_FiberAlpha; + + if (alpha < g_alphaThreshold) + { + FragColor = 1.0; + return; + } + + uvec2 vScreenAddress = uvec2(gl_FragCoord.xy); + + uint uDepth = floatBitsToUint(gl_FragCoord.z); + uint uDepth0Prev, uDepth1Prev; + + // Min of depth 0 and input depth + // Original value is uDepth0Prev + uDepth0Prev = imageAtomicMin(RWFragmentDepthsTexture, ivec3(vScreenAddress, 0), uDepth); + + // Min of depth 1 and greater of the last compare + // If fragment opaque, always use input depth (don't need greater depths) + uDepth = (alpha > 0.98) ? uDepth : max(uDepth, uDepth0Prev); + + uDepth1Prev = imageAtomicMin(RWFragmentDepthsTexture, ivec3(vScreenAddress, 1), uDepth); + +#if SHORTCUT_NUM_DEPTHS == 3 + uint uDepth2Prev; + + // Min of depth 2 and greater of the last compare + // If fragment opaque, always use input depth (don't need greater depths) + uDepth = (alpha > 0.98) ? uDepth : max(uDepth, uDepth1Prev); + + uDepth2Prev = imageAtomicMin(RWFragmentDepthsTexture, ivec3(vScreenAddress, 2), uDepth); +#endif + + FragColor = 1.0 - alpha; +} diff --git a/amd_tressfx_vulkan/src/Shaders/FS_FillColors_Hair_Data.frag b/amd_tressfx_vulkan/src/Shaders/FS_FillColors_Hair_Data.frag new file mode 100644 index 0000000..a8c29df --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/FS_FillColors_Hair_Data.frag @@ -0,0 +1,134 @@ +#version 450 +#extension GL_GOOGLE_include_directive : require +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" +#include "PackUnpack.glsl" +#include "ComputeCoverage.glsl" +#include "ComputeShadow.glsl" +#include "ComputeHairShading.glsl" + +layout(set = 0, binding = IDSRV_HAIR_FRAGMENT_DEPTHS, r32ui) uniform uimage2DArray FragmentDepthsTexture; +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE +#else +layout(set = 0, binding = IDSRV_HAIR_FRAGMENT_COLORS, r32ui) uniform uimageBuffer RWFragmentColors; +#endif + +layout(early_fragment_tests) in; + +// Convert 2D address to 1D address +int GetAddress(ivec2 vAddress) +{ + int nAddress = vAddress.y * int(g_WinSize.x) + vAddress.x; + return nAddress; +} + +layout(location = 0) in float depth; +layout(location = 1) in vec4 p0p1; +layout(location = 2) in vec4 tangent; +layout(location = 3) in vec4 strandColor; + +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE +layout(location = 0) out vec4 FragColor; +#endif + +void main() +{ + // Render AA Line, calculate pixel coverage + vec4 proj_pos = vec4(2 * gl_FragCoord.x * g_WinSize.z - 1.0, // g_WinSize.z = 1.0/g_WinSize.x + 1 - 2 * gl_FragCoord.y * g_WinSize.w, // g_WinSize.w = 1.0/g_WinSize.y + gl_FragCoord.z, + 1); + + vec4 world_pos = g_mInvViewProj * proj_pos; + world_pos.xyz = world_pos.xyz / world_pos.w; + world_pos.w = 1.0; + + float curve_scale = 1; + if (g_bThinTip > 0) + curve_scale = tangent.w; + + float fiber_radius = curve_scale * g_FiberRadius; + + float coverage = 1.f; + if (g_bUseCoverage != 0) + { + coverage = ComputeCoverage(p0p1.xy, p0p1.zw, proj_pos.xy); + } + + float alpha = coverage * g_FiberAlpha; + + if (alpha < g_alphaThreshold) + { +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + FragColor = vec4(0, 0, 0, 0); +#endif + return; + } + + ivec2 vScreenAddress = ivec2(gl_FragCoord.xy); + int fragmentIndex = GetAddress(vScreenAddress); + + uint uDepth = floatBitsToUint(gl_FragCoord.z); + + uint uDepth0 = imageLoad(FragmentDepthsTexture, ivec3(vScreenAddress, 0)).x; + uint uDepth1 = imageLoad(FragmentDepthsTexture, ivec3(vScreenAddress, 1)).x; +#if SHORTCUT_NUM_DEPTHS == 3 + uint uDepth2 = imageLoad(FragmentDepthsTexture, ivec3(vScreenAddress, 2)).x; +#endif + + // Shade regardless of depth, since ResolveDepth pass writes one of the near depths + + float amountLight = ComputeShadow(world_pos.xyz, g_HairShadowAlpha); + vec3 color = ComputeHairShading(world_pos.xyz, tangent.xyz, vec4(0, 0, 0, 0), amountLight, strandColor.xyz); + uint uColor = PackFloat4IntoUint(vec4(color, alpha)); + + +#if SHORTCUT_DETERMINISTIC // deterministic result when fragments match in depth, with added cost + +#if SHORTCUT_WEIGHTED_AVERAGE + FragColor = vec4(color * alpha, alpha); + return; +#else + // For fragments of equal depth, keep colors with greatest uint value + if (uDepth == uDepth0) + { + uint uColorPrev = imageAtomicMax(RWFragmentColors, fragmentIndex, uColor); + uColor = min(uColor, uColorPrev); + } + if (uDepth == uDepth1) + { + uint uColorPrev = imageAtomicMax(RWFragmentColors, fragmentIndex + 1, uColor); + uColor = min(uColor, uColorPrev); + } +#if SHORTCUT_NUM_DEPTHS == 3 + if (uDepth == uDepth2) + { + uint uColorPrev = imageAtomicMax(RWFragmentColors, fragmentIndex + 2, uColor); + uColor = min(uColor, uColorPrev); + } +#endif +#endif + +#else // !SHORTCUT_DETERMINISTIC + + if (uDepth == uDepth0) + { + imageStore(RWFragmentColors, fragmentIndex, uvec4(uColor)); + uColor = 0; + } + if (uDepth == uDepth1) + { + imageStore(RWFragmentColors, fragmentIndex + 1, uvec4(uColor)); + uColor = 0; + } +#if SHORTCUT_NUM_DEPTHS == 3 + if (uDepth == uDepth2) + { + imageStore(RWFragmentColors, fragmentIndex + 2, uvec4(uColor)); + } +#endif + +#endif +} diff --git a/amd_tressfx_vulkan/src/Shaders/FS_ResolveColor_Hair_Data.frag b/amd_tressfx_vulkan/src/Shaders/FS_ResolveColor_Hair_Data.frag new file mode 100644 index 0000000..fe403cf --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/FS_ResolveColor_Hair_Data.frag @@ -0,0 +1,119 @@ +#version 450 +#extension GL_GOOGLE_include_directive : require +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" +#include "PackUnpack.glsl" + +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE +layout(input_attachment_index = 2, set = 0, binding = IDSRV_HAIR_FRAGMENT_COLORS) uniform subpassInput FragmentColors; +#else +layout(set = 0, binding = IDSRV_HAIR_FRAGMENT_DEPTHS, r32ui) uniform uimage2DArray FragmentDepthsTexture; +layout(set = 0, binding = IDSRV_HAIR_FRAGMENT_COLORS, r32ui) uniform uimageBuffer FragmentColors; +#endif + +layout(set = 0, binding = IDSRV_HAIRSM) uniform texture2D HairShadowMap; +layout(set = 0, binding = IDSRV_SHADOW_SAMPLER) uniform sampler g_samPointClamp; + +layout(input_attachment_index = 1, set = 0, binding = IDSRV_HAIR_ACCUM_INV_ALPHA) uniform subpassInput tAccumInvAlpha; + +layout(early_fragment_tests) in; + +layout(location = 0) out vec4 FragColor; + +// Convert 2D address to 1D address +int GetAddress(ivec2 vAddress) +{ + int nAddress = vAddress.y * int(g_WinSize.x) + vAddress.x; + return nAddress; +} + + +//-------------------------------------------------------------------------------------- +// PS_ResolveColor_Hair +// +//-------------------------------------------------------------------------------------- +void main() +{ + ivec2 vScreenAddress = ivec2(gl_FragCoord.xy); + int fragmentIndex = GetAddress(vScreenAddress); + + float fInvAlpha = subpassLoad(tAccumInvAlpha).x; + float fAlpha = 1.0 - fInvAlpha; + + if (fAlpha < SHORTCUT_MIN_ALPHA) + { + FragColor = vec4(0, 0, 0, 1); + return; + } + +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + vec4 fcolor = subpassLoad(FragmentColors); + float colorSumX = fcolor.x; + float colorSumY = fcolor.y; + float colorSumZ = fcolor.z; + float colorSumW = fcolor.w; + fcolor.x = colorSumX / colorSumW; + fcolor.y = colorSumY / colorSumW; + fcolor.z = colorSumZ / colorSumW; + fcolor.xyz *= fAlpha; +#else + uint uDepth0 = imageLoad(FragmentDepthsTexture, ivec3(vScreenAddress, 0)).x; + uint uDepth1 = imageLoad(FragmentDepthsTexture, ivec3(vScreenAddress, 1)).x; + uint uColor0 = imageLoad(FragmentColors, fragmentIndex).x; + uint uColor1 = imageLoad(FragmentColors, fragmentIndex).y; + + vec4 color0 = UnpackUintIntoFloat4(uColor0); + float alpha0 = color0.w; + float invAlpha0 = 1.0 - alpha0; + + vec4 color1 = (uDepth1 == SHORTCUT_INITIAL_DEPTH) ? vec4(0, 0, 0, 0) : UnpackUintIntoFloat4(uColor1); + float alpha1 = color1.w; + float invAlpha1 = 1.0 - alpha1; + +#if SHORTCUT_NUM_DEPTHS == 3 + uint uDepth2 = FragmentDepthsTexture[uint3(vScreenAddress, 2)]; + uint uColor2 = FragmentColors[fragmentIndex].z; + + vec4 color2 = (uDepth2 == SHORTCUT_INITIAL_DEPTH) ? vec4(0, 0, 0, 0) : UnpackUintIntoFloat4(uColor2); + float alpha2 = color2.w; +#endif + + vec4 fcolor; + +#if SHORTCUT_WEIGHTED_AVERAGE +#if SHORTCUT_NUM_DEPTHS == 3 + fcolor.xyz = fAlpha * (color0.xyz * alpha0 + color1.xyz * alpha1 + color2.xyz * alpha2) / (alpha0 + alpha1 + alpha2); +#else + fcolor.xyz = fAlpha * (color0.xyz * alpha0 + color1.xyz * alpha1) / (alpha0 + alpha1); +#endif +#else +#if SHORTCUT_NUM_DEPTHS == 3 + float invAlpha01 = invAlpha0 * invAlpha1; + + // Get cumulative alpha for all fragments after front two; apply to back fragment + float fInvAlphaBack = invAlpha01 < 0.0001 ? fInvAlpha : fInvAlpha / invAlpha01; + float fAlphaBack = 1.0 - fInvAlphaBack; + + vec3 backColor = (uColor2 == 0) ? ((uColor1 == 0) ? color0.xyz : color1.xyz) : color2.xyz; + + // Blend is: + // alpha0 * color0 + (1 - alpha0) * (alpha1 * color1 + (1 - alpha1) * (fAlphaBack * backColor + fInvAlphaBack * dstcolor)) + fcolor.xyz = color0.xyz * alpha0 + color1.xyz * (1 - alpha0) * alpha1 + backColor.xyz * (1 - alpha0) * (1 - alpha1) * fAlphaBack; +#else + // Get cumulative alpha for all fragments after front; apply to back fragment + float fInvAlphaBack = invAlpha0 < 0.0001 ? fInvAlpha : fInvAlpha / invAlpha0; + float fAlphaBack = 1.0 - fInvAlphaBack; + + vec3 backColor = (uColor1 == 0) ? color0.xyz : color1.xyz; + + // Blend is: + // alpha0 * color0 + (1 - alpha0) * (fAlphaBack * backColor + fInvAlphaBack * dstcolor)) + fcolor.xyz = color0.xyz * alpha0 + backColor * (1 - alpha0) * fAlphaBack; +#endif +#endif +#endif + fcolor.w = fInvAlpha; + FragColor = fcolor; +} diff --git a/amd_tressfx_vulkan/src/Shaders/FS_ResolveDepth_Hair_Data.frag b/amd_tressfx_vulkan/src/Shaders/FS_ResolveDepth_Hair_Data.frag new file mode 100644 index 0000000..9635c0b --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/FS_ResolveDepth_Hair_Data.frag @@ -0,0 +1,31 @@ +#version 450 +#extension GL_GOOGLE_include_directive : require +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" + +layout(set = 0, binding = IDSRV_HAIR_FRAGMENT_DEPTHS, r32ui) uniform uimage2DArray FragmentDepthsTexture; + +//-------------------------------------------------------------------------------------- +// PS_ResolveDepth_Hair +// +//-------------------------------------------------------------------------------------- +void main() +{ + ivec2 vScreenAddress = ivec2(gl_FragCoord.xy); + + uint uDepth = 0; + +// NOTE: A bug in FXC in the Win 8.x SDKs prevents +// this shader from compiling if depth is read from a +// structured buffer. A texture array is used instead. + +#if SHORTCUT_NUM_DEPTHS == 3 + uDepth = imageLoad(FragmentDepthsTexture, ivec3(vScreenAddress, 2)).x; +#else + uDepth = imageLoad(FragmentDepthsTexture, ivec3(vScreenAddress, 1)).x; +#endif + + gl_FragDepth = uintBitsToFloat(uDepth); +} \ No newline at end of file diff --git a/amd_tressfx_vulkan/src/Shaders/GlobalConstraints.comp b/amd_tressfx_vulkan/src/Shaders/GlobalConstraints.comp new file mode 100644 index 0000000..4416476 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/GlobalConstraints.comp @@ -0,0 +1,143 @@ +#version 450 + +#include "SimulationConfig.glsl" + + +layout (local_size_x = THREAD_GROUP_SIZE, local_size_y = 1, local_size_z = 1) in; + +layout(std430, set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) buffer writeablePositions +{ + vec4 g_HairVertexPositions[]; +}; +layout(std430, set = 1, binding = IDSRV_HAIR_PREVIOUS_VERTEX_POSITIONS) buffer writeablePrevPositions +{ + vec4 g_HairVertexPositionsPrev[]; +}; +layout(set = 1, binding = IDSRV_HAIR_VERTEX_INITIAL_POSITIONS) uniform samplerBuffer g_InitialHairPositions; + +#include "IndicesComputations.glsl" + +//-------------------------------------------------------------------------------------- +// +// Integrate +// +// Uses Verlet integration to calculate the new position for the current time step +// +//-------------------------------------------------------------------------------------- +vec4 Integrate(vec4 curPosition, vec4 oldPosition, vec4 initialPos, vec4 force, uint globalVertexIndex, uint localVertexIndex, uint numVerticesInTheStrand, float dampingCoeff) +{ + vec4 outputPos = curPosition; + + force.xyz += g_GravityMagnitude * vec3(0, -1.0f, 0); + outputPos.xyz = curPosition.xyz + (1.0 - dampingCoeff)*(curPosition.xyz - oldPosition.xyz) + force.xyz*g_TimeStep*g_TimeStep; + + return outputPos; +} + +//-------------------------------------------------------------------------------------- +// +// UpdateFinalVertexPositions +// +// Updates the hair vertex positions based on the physics simulation +// +//-------------------------------------------------------------------------------------- +void UpdateFinalVertexPositions(vec4 oldPosition, vec4 newPosition, uint globalVertexIndex, uint localVertexIndex, uint numVerticesInTheStrand) +{ + g_HairVertexPositionsPrev[int(globalVertexIndex)] = oldPosition; + g_HairVertexPositions[int(globalVertexIndex)] = newPosition; +} + +//-------------------------------------------------------------------------------------- +// +// IntegrationAndGlobalShapeConstraints +// +// Compute shader to simulate the gravitational force with integration and to maintain the +// global shape constraints. +// +// One thread computes one vertex. +// +//-------------------------------------------------------------------------------------- +void main() +{ + uint globalStrandIndex, localStrandIndex, localVertexIndex, numVerticesInTheStrand, indexForSharedMem, strandType; + int globalVertexIndex; + CalcIndicesInVertexLevelMaster(gl_LocalInvocationID.x, gl_WorkGroupID.x, globalStrandIndex, localStrandIndex, globalVertexIndex, localVertexIndex, numVerticesInTheStrand, indexForSharedMem, strandType); + + vec4 currentPos = vec4(0, 0, 0, 0); // position when this step starts. In other words, a position from the last step. + vec4 initialPos = vec4(0, 0, 0, 0); // rest position + + vec4 tmpPos; + + // Copy data into shared memory + initialPos = texelFetch(g_InitialHairPositions, globalVertexIndex); + initialPos.xyz = (g_ModelTransformForHead * vec4(initialPos.xyz, 1)).xyz; + if (g_bWarp != 0) + currentPos = initialPos; + else + currentPos = tmpPos = g_HairVertexPositions[globalVertexIndex]; + + // Integrate + float dampingCoeff = 0.03f; + + if ( strandType == 0 ) + dampingCoeff = g_Damping0; + else if ( strandType == 1 ) + dampingCoeff = g_Damping1; + else if ( strandType == 2 ) + dampingCoeff = g_Damping2; + else if ( strandType == 3 ) + dampingCoeff = g_Damping3; + + vec4 oldPos; + if (g_bWarp != 0) + oldPos = currentPos; + else + oldPos = g_HairVertexPositionsPrev[globalVertexIndex]; + vec4 force = vec4(0, 0, 0, 0); + + if ( IsMovable(currentPos) ) + tmpPos = Integrate(currentPos, oldPos, initialPos, force, globalVertexIndex, localVertexIndex, numVerticesInTheStrand, dampingCoeff); + else + tmpPos = initialPos; + + // Global Shape Constraints + float stiffnessForGlobalShapeMatching = 0; + float globalShapeMatchingEffectiveRange = 0; + + if ( strandType == 0 ) + { + stiffnessForGlobalShapeMatching = g_StiffnessForGlobalShapeMatching0; + globalShapeMatchingEffectiveRange = g_GlobalShapeMatchingEffectiveRange0; + } + else if ( strandType == 1 ) + { + stiffnessForGlobalShapeMatching = g_StiffnessForGlobalShapeMatching1; + globalShapeMatchingEffectiveRange = g_GlobalShapeMatchingEffectiveRange1; + } + else if ( strandType == 2 ) + { + stiffnessForGlobalShapeMatching = g_StiffnessForGlobalShapeMatching2; + globalShapeMatchingEffectiveRange = g_GlobalShapeMatchingEffectiveRange2; + } + else if ( strandType == 3 ) + { + stiffnessForGlobalShapeMatching = g_StiffnessForGlobalShapeMatching3; + globalShapeMatchingEffectiveRange = g_GlobalShapeMatchingEffectiveRange3; + } + + if ( stiffnessForGlobalShapeMatching > 0 && globalShapeMatchingEffectiveRange != 0.) + { + if (IsMovable(tmpPos)) + { + if (float(localVertexIndex) < globalShapeMatchingEffectiveRange * float(numVerticesInTheStrand)) + { + float factor = stiffnessForGlobalShapeMatching; + vec3 del = factor * (initialPos - tmpPos).xyz; + tmpPos.xyz += del; + } + } + } + + // update global position buffers + UpdateFinalVertexPositions(currentPos, tmpPos, globalVertexIndex, localVertexIndex, numVerticesInTheStrand); +} diff --git a/amd_tressfx_vulkan/src/Shaders/HairShadowMap.frag b/amd_tressfx_vulkan/src/Shaders/HairShadowMap.frag new file mode 100644 index 0000000..a9eff44 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/HairShadowMap.frag @@ -0,0 +1,7 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +void main() +{ +} \ No newline at end of file diff --git a/amd_tressfx_vulkan/src/Shaders/HairShadowMap.vert b/amd_tressfx_vulkan/src/Shaders/HairShadowMap.vert new file mode 100644 index 0000000..2966967 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/HairShadowMap.vert @@ -0,0 +1,17 @@ +#version 450 +#extension GL_GOOGLE_include_directive : require +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" + +layout(set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) uniform samplerBuffer g_HairVertexPositions; + +out gl_PerVertex{ + vec4 gl_Position; +}; + +void main() +{ + gl_Position = g_mViewProjLight * vec4(texelFetch(g_HairVertexPositions, gl_VertexIndex).xyz, 1.); +} \ No newline at end of file diff --git a/amd_tressfx_vulkan/src/Shaders/IndicesComputations.glsl b/amd_tressfx_vulkan/src/Shaders/IndicesComputations.glsl new file mode 100644 index 0000000..807e97b --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/IndicesComputations.glsl @@ -0,0 +1,45 @@ +layout(set = 1, binding = IDSRV_HAIR_STRAND_TYPE) uniform usamplerBuffer g_HairStrandType; + +void CalcIndicesInVertexLevelMaster(uint local_id, uint group_id, inout uint globalStrandIndex, inout uint localStrandIndex, inout int globalVertexIndex, inout uint localVertexIndex, inout uint numVerticesInTheStrand, inout uint indexForSharedMem, inout uint strandType) +{ + indexForSharedMem = local_id; + numVerticesInTheStrand = (THREAD_GROUP_SIZE / g_NumOfStrandsPerThreadGroup); + + localStrandIndex = local_id % g_NumOfStrandsPerThreadGroup; + globalStrandIndex = group_id * g_NumOfStrandsPerThreadGroup + localStrandIndex; + globalStrandIndex *= (g_NumFollowHairsPerGuideHair + 1); + localVertexIndex = (local_id - localStrandIndex) / g_NumOfStrandsPerThreadGroup; + + strandType = texelFetch(g_HairStrandType, int(globalStrandIndex)).x; + globalVertexIndex = int(globalStrandIndex * numVerticesInTheStrand + localVertexIndex); +} + +void CalcIndicesInVertexLevelTotal(uint local_id, uint group_id, inout uint globalStrandIndex, inout uint localStrandIndex, inout int globalVertexIndex, inout uint localVertexIndex, inout uint numVerticesInTheStrand, inout uint indexForSharedMem, inout uint strandType) +{ + indexForSharedMem = local_id; + numVerticesInTheStrand = (THREAD_GROUP_SIZE / g_NumOfStrandsPerThreadGroup); + + localStrandIndex = local_id % g_NumOfStrandsPerThreadGroup; + globalStrandIndex = group_id * g_NumOfStrandsPerThreadGroup + localStrandIndex; + localVertexIndex = (local_id - localStrandIndex) / g_NumOfStrandsPerThreadGroup; + + strandType = texelFetch(g_HairStrandType, int(globalStrandIndex)).x; + globalVertexIndex = int(globalStrandIndex * numVerticesInTheStrand + localVertexIndex); +} + +void CalcIndicesInStrandLevelTotal(uint local_id, uint group_id, inout uint globalStrandIndex, inout uint numVerticesInTheStrand, inout uint globalRootVertexIndex, inout uint strandType) +{ + globalStrandIndex = THREAD_GROUP_SIZE*group_id + local_id; + numVerticesInTheStrand = (THREAD_GROUP_SIZE / g_NumOfStrandsPerThreadGroup); + strandType = texelFetch(g_HairStrandType, int(globalStrandIndex)).x; + globalRootVertexIndex = globalStrandIndex * numVerticesInTheStrand; +} + +void CalcIndicesInStrandLevelMaster(int local_id, int group_id, inout int globalStrandIndex, inout uint numVerticesInTheStrand, inout int globalRootVertexIndex, inout uint strandType) +{ + globalStrandIndex = THREAD_GROUP_SIZE * group_id + local_id; + globalStrandIndex *= int(g_NumFollowHairsPerGuideHair + 1); + numVerticesInTheStrand = (THREAD_GROUP_SIZE / g_NumOfStrandsPerThreadGroup); + strandType = texelFetch(g_HairStrandType, globalStrandIndex).x; + globalRootVertexIndex = globalStrandIndex * int(numVerticesInTheStrand); +} diff --git a/amd_tressfx_vulkan/src/Shaders/LengthWindCollision.comp b/amd_tressfx_vulkan/src/Shaders/LengthWindCollision.comp new file mode 100644 index 0000000..19cae7b --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/LengthWindCollision.comp @@ -0,0 +1,199 @@ +#version 450 + +#include "SimulationConfig.glsl" + +layout (local_size_x = THREAD_GROUP_SIZE, local_size_y = 1, local_size_z = 1) in; + +layout(std430, set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) buffer writeablePositions +{ + vec4 g_HairVertexPositions[]; +}; +layout(set = 1, binding = IDSRV_HAIR_LENGTH) uniform samplerBuffer g_HairRestLengthSRV; + +#include "IndicesComputations.glsl" + +shared vec4 sharedPos[THREAD_GROUP_SIZE]; +shared float sharedLength[THREAD_GROUP_SIZE]; + +vec2 ConstraintMultiplier(vec4 particle0, vec4 particle1) +{ + if (IsMovable(particle0)) + { + if (IsMovable(particle1)) + return vec2(0.5, 0.5); + else + return vec2(1, 0); + } + else + { + if (IsMovable(particle1)) + return vec2(0, 1); + else + return vec2(0, 0); + } +} + +void ApplyDistanceConstraint(inout vec4 pos0, inout vec4 pos1, float targetDistance, float stiffness) +{ + vec3 delta = pos1.xyz - pos0.xyz; + float distance = max(length(delta), 1e-7); + float stretching = 1 - targetDistance / distance; + delta = stretching * delta; + vec2 multiplier = ConstraintMultiplier(pos0, pos1); + + pos0.xyz += multiplier[0] * delta * stiffness; + pos1.xyz -= multiplier[1] * delta * stiffness; +} + + +//-------------------------------------------------------------------------------------- +// +// LengthConstriantsWindAndCollision +// +// Compute shader to move the vertex position based on wind, maintain the lenght constraints +// and handles collisions. +// +// One thread computes one vertex. +// +//-------------------------------------------------------------------------------------- + +void main() +{ + uint globalStrandIndex, localStrandIndex, localVertexIndex, numVerticesInTheStrand, indexForSharedMem, strandType; + int globalVertexIndex; + CalcIndicesInVertexLevelMaster(gl_LocalInvocationID.x, gl_WorkGroupID.x, globalStrandIndex, localStrandIndex, globalVertexIndex, localVertexIndex, numVerticesInTheStrand, indexForSharedMem, strandType); + + uint numOfStrandsPerThreadGroup = g_NumOfStrandsPerThreadGroup; + + //------------------------------ + // Copy data into shared memory + //------------------------------ + sharedPos[indexForSharedMem] = g_HairVertexPositions[globalVertexIndex]; + sharedLength[indexForSharedMem] = texelFetch(g_HairRestLengthSRV, globalVertexIndex).x; + barrier(); + + + //------------ + // Wind + //------------ + if (g_Wind.x != 0 || g_Wind.y != 0 || g_Wind.z != 0) + { + vec4 force = vec4(0.); + + float frame = g_Wind.w; + + if (localVertexIndex >= 2 && localVertexIndex < numVerticesInTheStrand - 1) + { + // combining four winds. + float a = float(globalStrandIndex % 20) / 20.0; + vec3 w = a * g_Wind.xyz + (1.0 - a) * g_Wind1.xyz + a * g_Wind2.xyz + (1. - a) * g_Wind3.xyz; + + int sharedIndex = int(localVertexIndex) * int(numOfStrandsPerThreadGroup) + int(localStrandIndex); + + vec3 v = sharedPos[sharedIndex].xyz - sharedPos[sharedIndex + numOfStrandsPerThreadGroup].xyz; + vec3 force = -cross(cross(v, w), v); + sharedPos[sharedIndex].xyz += force*g_TimeStep*g_TimeStep; + } + } + + barrier(); + + //---------------------------- + // Enforce length constraints + //---------------------------- + int a = int(floor(numVerticesInTheStrand / 2.)); + int b = int(floor((numVerticesInTheStrand - 1.) / 2.)); + + for (int iterationE = 0; iterationE < g_NumLengthConstraintIterations; iterationE++) + { + int sharedIndex = 2 * int(localVertexIndex) * int(numOfStrandsPerThreadGroup) + int(localStrandIndex); + + if( localVertexIndex < a) + ApplyDistanceConstraint(sharedPos[sharedIndex], sharedPos[sharedIndex+numOfStrandsPerThreadGroup], sharedLength[sharedIndex].x, 1.); + + barrier(); + + if( localVertexIndex < b) + ApplyDistanceConstraint(sharedPos[sharedIndex + numOfStrandsPerThreadGroup], sharedPos[sharedIndex + numOfStrandsPerThreadGroup * 2], sharedLength[sharedIndex + numOfStrandsPerThreadGroup].x, 1.); + + barrier(); + } + + + //------------------------------------------------- + // Collision handling hard-code collision shapes + //------------------------------------------------- + bool bColDetected = false; + + /* + float4 oldPos = g_HairVertexPositionsPrev[globalVertexIndex]; + + if ( g_bCollision > 0 ) + { + float3 newPos; + + { + float3 centerSphere = g_cc0_center; + centerSphere = mul(float4( centerSphere.xyz, 1), g_ModelTransformForHead).xyz; + float radius = g_cc0_radius; + + CollisionCapsule cc; + cc.p1.xyz = centerSphere; + cc.p1.w = radius; + cc.p2.xyz = centerSphere + float3(0.0,1.0,0.0); + cc.p2.w = g_cc0_radius2; + + bColDetected = CapsuleCollision(sharedPos[indexForSharedMem], oldPos, newPos, cc, true); + + if ( bColDetected ) + sharedPos[indexForSharedMem].xyz = newPos; + } + + { + float3 centerSphere = g_cc1_center; + centerSphere = mul(float4( centerSphere.xyz, 1), g_ModelTransformForHead).xyz; + float radius = g_cc1_radius; + + CollisionCapsule cc; + cc.p1.xyz = centerSphere; + cc.p1.w = radius; + cc.p2.xyz = centerSphere + float3(0.0,1.0,0.0); + cc.p2.w = g_cc1_radius2; + + bColDetected = CapsuleCollision(sharedPos[indexForSharedMem], oldPos, newPos, cc, true); + + if ( bColDetected ) + sharedPos[indexForSharedMem].xyz = newPos; + } + + { + float3 centerSphere = g_cc2_center; + centerSphere = mul(float4( centerSphere.xyz, 1), g_ModelTransformForHead).xyz; + float radius = g_cc2_radius; + + CollisionCapsule cc; + cc.p1.xyz = centerSphere; + cc.p1.w = radius; + cc.p2.xyz = centerSphere + float3(0.0,1.0,0.0); + cc.p2.w = g_cc2_radius2; + + bColDetected = CapsuleCollision(sharedPos[indexForSharedMem], oldPos, newPos, cc, true); + + if ( bColDetected ) + sharedPos[indexForSharedMem].xyz = newPos; + } + } + + GroupMemoryBarrierWithGroupSync(); +*/ + + //--------------------------------------- + // update global position buffers + //--------------------------------------- + g_HairVertexPositions[globalVertexIndex] = sharedPos[indexForSharedMem]; + +// if ( bColDetected ) +// g_HairVertexPositionsPrev[globalVertexIndex] = sharedPos[indexForSharedMem]; + + return; +} diff --git a/amd_tressfx_vulkan/src/Shaders/LocalConstraints.comp b/amd_tressfx_vulkan/src/Shaders/LocalConstraints.comp new file mode 100644 index 0000000..e7c9dc0 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/LocalConstraints.comp @@ -0,0 +1,173 @@ +#version 450 + +#include "SimulationConfig.glsl" + +layout (local_size_x = THREAD_GROUP_SIZE, local_size_y = 1, local_size_z = 1) in; + +layout(std430, set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) buffer writeablePositions +{ + vec4 g_HairVertexPositions[]; +}; +layout(set = 1, binding = IDSRV_HAIR_GLOBAL_ROTATION) uniform samplerBuffer g_GlobalRotations; +layout(set = 1, binding = IDSRV_HAIR_LOCAL_REF_VEC) uniform samplerBuffer g_HairRefVecsInLocalFrame; + +#include "IndicesComputations.glsl" + +vec4 MultQuaternionAndQuaternion(vec4 qA, vec4 qB) +{ + vec4 q; + + q.w = qA.w * qB.w - qA.x * qB.x - qA.y * qB.y - qA.z * qB.z; + q.x = qA.w * qB.x + qA.x * qB.w + qA.y * qB.z - qA.z * qB.y; + q.y = qA.w * qB.y + qA.y * qB.w + qA.z * qB.x - qA.x * qB.z; + q.z = qA.w * qB.z + qA.z * qB.w + qA.x * qB.y - qA.y * qB.x; + + return q; +} + +vec3 MultQuaternionAndVector(vec4 q, vec3 v) +{ + vec3 uv, uuv; + vec3 qvec = vec3(q.x, q.y, q.z); + uv = cross(qvec, v); + uuv = cross(qvec, uv); + uv *= (2.0f * q.w); + uuv *= 2.0f; + + return v + uv + uuv; +} + +vec4 MakeQuaternion(float angle_radian, vec3 axis) +{ + // create quaternion using angle and rotation axis + vec4 quaternion; + float halfAngle = 0.5f * angle_radian; + float sinHalf = sin(halfAngle); + + quaternion.w = cos(halfAngle); + quaternion.xyz = sinHalf * axis.xyz; + + return quaternion; +} + +vec4 InverseQuaternion(vec4 q) +{ + float lengthSqr = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w; + + if ( lengthSqr < 0.001 ) + return vec4(0, 0, 0, 1.0f); + + q.x = -q.x / lengthSqr; + q.y = -q.y / lengthSqr; + q.z = -q.z / lengthSqr; + q.w = q.w / lengthSqr; + + return q; +} + + +//-------------------------------------------------------------------------------------- +// +// LocalShapeConstraintsWithIteration +// +// Compute shader to maintain the local shape constraints. This is the same as +// the LocalShapeConstraints shader, except the iterations are done on the GPU +// instead of multiple dispatch calls on the CPU, for better performance +// +//-------------------------------------------------------------------------------------- + +void main() +{ + int globalStrandIndex, globalRootVertexIndex; + uint numVerticesInTheStrand, strandType; + CalcIndicesInStrandLevelMaster(int(gl_LocalInvocationID.x), int(gl_WorkGroupID.x), globalStrandIndex, numVerticesInTheStrand, globalRootVertexIndex, strandType); + + // stiffness for local shape constraints + float stiffnessForLocalShapeMatching = 0.4; + + if ( strandType == 2) + stiffnessForLocalShapeMatching = g_StiffnessForLocalShapeMatching2; + else if ( strandType == 3 ) + stiffnessForLocalShapeMatching = g_StiffnessForLocalShapeMatching3; + else if ( strandType == 1 ) + stiffnessForLocalShapeMatching = g_StiffnessForLocalShapeMatching1; + else if ( strandType == 0 ) + stiffnessForLocalShapeMatching = g_StiffnessForLocalShapeMatching0; + + //1.0 for stiffness makes things unstable sometimes. + stiffnessForLocalShapeMatching = 0.5 * min(stiffnessForLocalShapeMatching, 0.95); + + //------------------------------ + // Copy strand data into registers, for faster iteration + //------------------------------ + int globalVertexIndex = 0; + vec4 sharedStrandPos[MAX_VERTS_PER_STRAND]; + for (int localVertexIndex = 0; localVertexIndex < numVerticesInTheStrand; localVertexIndex++) + { + globalVertexIndex = globalRootVertexIndex + localVertexIndex; + sharedStrandPos[localVertexIndex] = g_HairVertexPositions[globalVertexIndex]; + } + + //-------------------------------------------- + // Local shape constraint for bending/twisting + //-------------------------------------------- + for (int iterations = 0; iterations < g_NumLocalShapeMatchingIterations; iterations++) + { + vec4 pos = sharedStrandPos[1]; + vec4 rotGlobal = texelFetch(g_GlobalRotations, globalRootVertexIndex); + + for (int localVertexIndex = 1; localVertexIndex < numVerticesInTheStrand - 1; localVertexIndex++) + { + globalVertexIndex = globalRootVertexIndex + localVertexIndex; + vec4 pos_plus_one = sharedStrandPos[localVertexIndex+1]; + + //-------------------------------- + // Update position i and i_plus_1 + //-------------------------------- + vec4 rotGlobalWorld = MultQuaternionAndQuaternion(g_ModelRotateForHead, rotGlobal); + + vec3 orgPos_i_plus_1_InLocalFrame_i = texelFetch(g_HairRefVecsInLocalFrame, globalVertexIndex + 1).xyz; + vec3 orgPos_i_plus_1_InGlobalFrame = MultQuaternionAndVector(rotGlobalWorld, orgPos_i_plus_1_InLocalFrame_i) + pos.xyz; + + vec3 del = stiffnessForLocalShapeMatching * (orgPos_i_plus_1_InGlobalFrame - pos_plus_one.xyz).xyz; + + if (IsMovable(pos)) + pos.xyz -= del.xyz; + + if (IsMovable(pos_plus_one)) + pos_plus_one.xyz += del.xyz; + + //--------------------------- + // Update local/global frames + //--------------------------- + vec4 invRotGlobalWorld = InverseQuaternion(rotGlobalWorld); + vec3 vec = normalize(pos_plus_one.xyz - pos.xyz); + + vec3 x_i_plus_1_frame_i = normalize(MultQuaternionAndVector(invRotGlobalWorld, vec)); + vec3 e = vec3(1., 0, 0); + vec3 rotAxis = cross(e, x_i_plus_1_frame_i); + + if ( length(rotAxis) > 0.001 ) + { + float angle_radian = acos(dot(e, x_i_plus_1_frame_i)); + rotAxis = normalize(rotAxis); + + vec4 localRot = MakeQuaternion(angle_radian, rotAxis); + rotGlobal = MultQuaternionAndQuaternion(rotGlobal, localRot); + } + + sharedStrandPos[localVertexIndex].xyz = pos.xyz; + sharedStrandPos[localVertexIndex+1].xyz = pos_plus_one.xyz; + + pos = pos_plus_one; + } + } + + for (int localVertexIndex = 0; localVertexIndex < numVerticesInTheStrand; localVertexIndex++) + { + globalVertexIndex = globalRootVertexIndex + localVertexIndex; + g_HairVertexPositions[globalVertexIndex] = sharedStrandPos[localVertexIndex]; + } + + return; +} diff --git a/amd_tressfx_vulkan/src/Shaders/PackUnpack.glsl b/amd_tressfx_vulkan/src/Shaders/PackUnpack.glsl new file mode 100644 index 0000000..0b8f1a5 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/PackUnpack.glsl @@ -0,0 +1,31 @@ +//-------------------------------------------------------------------------------------- +// Helper functions for packing and unpacking the stored tangent and coverage +//-------------------------------------------------------------------------------------- +uint PackFloat4IntoUint(vec4 vValue) +{ + uint byte3 = uint(vValue.x * 255.) & 0xFF; + uint byte2 = uint(vValue.y * 255.) & 0xFF; + uint byte1 = uint(vValue.z * 255) & 0xFF; + uint byte0 = uint(vValue.w * 255) & 0xFF; + return (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0; +} + +vec4 UnpackUintIntoFloat4(uint uValue) +{ + return vec4(((uValue & 0xFF000000) >> 24) / 255.0, ((uValue & 0x00FF0000) >> 16) / 255.0, ((uValue & 0x0000FF00) >> 8) / 255.0, ((uValue & 0x000000FF)) / 255.0); +} + +uint PackTangentAndCoverage(vec3 tangent, float coverage) +{ + return PackFloat4IntoUint(vec4(tangent.xyz*0.5 + 0.5, coverage)); +} + +vec3 GetTangent(uint packedTangent) +{ + return 2.0 * UnpackUintIntoFloat4(packedTangent).xyz - 1.0; +} + +float GetCoverage(uint packedCoverage) +{ + return UnpackUintIntoFloat4(packedCoverage).w; +} diff --git a/amd_tressfx_vulkan/src/Shaders/PrepareFollowHair.comp b/amd_tressfx_vulkan/src/Shaders/PrepareFollowHair.comp new file mode 100644 index 0000000..c394fbe --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/PrepareFollowHair.comp @@ -0,0 +1,29 @@ +#version 450 + +#include "SimulationConfig.glsl" + +layout (local_size_x = THREAD_GROUP_SIZE, local_size_y = 1, local_size_z = 1) in; +layout(std430, set = 1, binding = IDSRV_HAIR_PREVIOUS_VERTEX_POSITIONS) buffer writeablePositionPrev +{ + vec4 g_HairVertexPositionsPrev[]; +}; +layout(set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) uniform samplerBuffer g_HairVertexPositions; + +#include "IndicesComputations.glsl" + +// One thread computes one vertex. +void main() +{ + uint globalStrandIndex, localStrandIndex, localVertexIndex, numVerticesInTheStrand, indexForSharedMem, strandType; + int globalVertexIndex; + CalcIndicesInVertexLevelMaster(gl_LocalInvocationID.x, gl_WorkGroupID.x, globalStrandIndex, localStrandIndex, globalVertexIndex, localVertexIndex, numVerticesInTheStrand, indexForSharedMem, strandType); + + for (int i = 0; i < g_NumFollowHairsPerGuideHair; i++) + { + int globalFollowVertexIndex = globalVertexIndex + int(numVerticesInTheStrand) * (i + 1); + vec4 hairPos = texelFetch(g_HairVertexPositions, globalFollowVertexIndex).xyzw; + g_HairVertexPositionsPrev[globalFollowVertexIndex] = hairPos; + } + + return; +} diff --git a/amd_tressfx_vulkan/src/Shaders/RenderConfig.glsl b/amd_tressfx_vulkan/src/Shaders/RenderConfig.glsl new file mode 100644 index 0000000..377bf47 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/RenderConfig.glsl @@ -0,0 +1,92 @@ +#pragma once + +// shader resource view slots +#define IDSRV_PPLL 0 +#define IDSRV_HEAD_PPLL 1 +#define IDSRV_SCENESM 2 +#define IDSRV_HAIRSM 3 +#define IDSRV_HAIR_COLOR_TEXTURE 4 +#define IDSRV_NOISEMAP 5 +#define IDSRV_HAIR_THICKNESSES 6 +#define IDSRV_HAIR_VERTEX_POSITIONS 7 +#define IDSRV_HAIR_TANGENTS 8 +#define IDSRV_HAIR_TRANSFORMS 9 +#define IDSRV_HAIR_STRAND_TEX_COORDS 10 +#define IDSRV_HAIR_VERTEX_TEX_COORDS 11 +#define IDSRV_HAIR_VERTEX_COLORS 12 + +// Shortcut resources. +#define IDSRV_HAIR_FRAGMENT_DEPTHS 13 +#define IDSRV_HAIR_FRAGMENT_COLORS 14 +#define IDSRV_HAIR_ACCUM_INV_ALPHA 15 + +#define IDSRV_CONSTANTS_BUFFER 16 +#define IDSRV_ATOMIC_COUNTER_BUFFER 17 +#define IDSRV_NOISE_SAMPLER 18 +#define IDSRV_SHADOW_SAMPLER 19 + +#define IDSRV_HAIR_PREVIOUS_VERTEX_POSITIONS 20 +#define IDSRV_HAIR_VERTEX_INITIAL_POSITIONS 21 +#define IDSRV_HAIR_STRAND_TYPE 22 +#define IDSRV_HAIR_GLOBAL_ROTATION 23 +#define IDSRV_HAIR_LOCAL_REF_VEC 24 +#define IDSRV_HAIR_ROOT_OFFSET 25 +#define IDSRV_HAIR_LENGTH 26 +#define IDSRV_HEAD_TRANSFORM 27 + +#define SM_EPSILON 0.01 +#define KERNEL_SIZE 5 +#define PI 3.14 +#define FLOAT_EPSILON 1e-7 + +#define SHORTCUT_MIN_ALPHA 0.02 + +// Number of depth layers to use. 2 or 3 supported. +#define SHORTCUT_NUM_DEPTHS 3 + +// Compute source color as weighted average of front fragments, vs blending in order. +#define SHORTCUT_WEIGHTED_AVERAGE 1 + +// Output color deterministically when fragments have the same depth. Requires additional clear of colors resource. +#define SHORTCUT_DETERMINISTIC 1 + +layout(std140, set = 0, binding = IDSRV_CONSTANTS_BUFFER) uniform Constants +{ +mat4 g_mWorld; +mat4 g_mViewProj; +mat4 g_mInvViewProj; +mat4 g_mViewProjLight; + +vec3 g_vEye; +float g_fvFov; + +vec4 g_AmbientLightColor; +vec4 g_PointLightColor; +vec4 g_PointLightPos; +vec4 g_MatBaseColor; +vec4 g_MatKValue; // Ka, Kd, Ks, Ex + +float g_FiberAlpha; +float g_HairShadowAlpha; +float g_bExpandPixels; +float g_FiberRadius; + +vec4 g_WinSize; // screen size + +float g_FiberSpacing; // average spacing between fibers +float g_bThinTip; +float g_fNearLight; +float g_fFarLight; + +int g_iTechSM; +int g_bUseCoverage; +int g_iStrandCopies; // strand copies that the transparency shader will produce +int g_iMaxFragments; + +float g_alphaThreshold; +float g_fHairKs2; // for second highlight +float g_fHairEx2; // for second highlight + +mat4 g_mInvViewProjViewport; +}; + diff --git a/amd_tressfx_vulkan/src/Shaders/RenderHair.vert b/amd_tressfx_vulkan/src/Shaders/RenderHair.vert new file mode 100644 index 0000000..1f8e21a --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/RenderHair.vert @@ -0,0 +1,59 @@ +#version 450 +#extension GL_GOOGLE_include_directive : require +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" + +layout(set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) uniform samplerBuffer g_HairVertexPositions; +layout(set = 1, binding = IDSRV_HAIR_TANGENTS) uniform samplerBuffer g_HairVertexTangents; +layout(set = 1, binding = IDSRV_HAIR_THICKNESSES) uniform samplerBuffer g_HairThicknessCoeffs; + +out gl_PerVertex{ + vec4 gl_Position; +}; + +vec2 Safe_normalize(vec2 vec) +{ + float len = length(vec); + return len >= FLOAT_EPSILON ? (vec / len) : vec2(0, 0); +} + +vec3 Safe_normalize(vec3 vec) +{ + float len = length(vec); + return len >= FLOAT_EPSILON ? (vec / len) : vec3(0, 0, 0); +} + +// Need Depth, gl_FragCoord.z returns meaningless values... +layout(location = 0) out float depth; +layout(location = 1) out vec4 p0p1; +layout(location = 2) out vec4 tangent; +layout(location = 3) out vec4 strandColor; + +//-------------------------------------------------------------------------------------- +// VS_RenderHair +// +// Vertex shader for rendering the hair strands without AA +//-------------------------------------------------------------------------------------- +void main() +{ + vec3 v = texelFetch(g_HairVertexPositions, gl_VertexIndex / 2).xyz; + vec3 Tangent = texelFetch(g_HairVertexTangents, gl_VertexIndex / 2).xyz; + float ratio = (g_bThinTip > 0) ? texelFetch(g_HairThicknessCoeffs, gl_VertexIndex / 2).x : 1.; + + // Calculate right and projected right vectors + vec3 right = Safe_normalize(cross(Tangent, normalize(v - g_vEye))); + vec2 proj_right = Safe_normalize((g_mViewProj * vec4(right, 0)).xy); + + float expandPixels = (g_bExpandPixels < 0) ? 0.0 : 0.71; + float fDirIndex = (gl_VertexIndex % 2 == 1) ? -1.0 : 1.0; + + vec3 temp = v + fDirIndex * right * ratio * g_FiberRadius; + gl_Position = g_mViewProj * vec4(temp, 1.f); + gl_Position = gl_Position + fDirIndex * vec4(proj_right * expandPixels / g_WinSize.y, 0.f, 0.f) * gl_Position.w; + depth = gl_Position.z / gl_Position.w; + tangent = vec4(Tangent, ratio); + p0p1 = vec4(v.xy, texelFetch(g_HairVertexPositions, gl_VertexIndex / 2 + 1).xy); + // TODO: Strand color +} \ No newline at end of file diff --git a/amd_tressfx_vulkan/src/Shaders/RenderHairAA.vert b/amd_tressfx_vulkan/src/Shaders/RenderHairAA.vert new file mode 100644 index 0000000..3c671f3 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/RenderHairAA.vert @@ -0,0 +1,65 @@ +#version 450 +#extension GL_GOOGLE_include_directive : require +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" + +layout(set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) uniform samplerBuffer g_HairVertexPositions; +layout(set = 1, binding = IDSRV_HAIR_TANGENTS) uniform samplerBuffer g_HairVertexTangents; +layout(set = 1, binding = IDSRV_HAIR_THICKNESSES) uniform samplerBuffer g_HairThicknessCoeffs; + +out gl_PerVertex { + vec4 gl_Position; +}; + +vec2 Safe_normalize(vec2 vec) +{ + float len = length(vec); + return len >= FLOAT_EPSILON ? (vec / len) : vec2(0,0); +} + +vec3 Safe_normalize(vec3 vec) +{ + float len = length(vec); + return len >= FLOAT_EPSILON ? (vec / len) : vec3(0,0,0); +} + +// Need Depth, gl_FragCoord.z returns meaningless values... +layout(location = 0) out float depth; +layout(location = 1) out vec4 p0p1; +layout(location = 2) out vec4 tangent; +layout(location = 3) out vec4 strandColor; + +//-------------------------------------------------------------------------------------- +// VS_RenderHair_AA +// +// Vertex shader for rendering the hair strands with randomized copies and AA +//-------------------------------------------------------------------------------------- +void main(void) { + vec3 v = texelFetch(g_HairVertexPositions, gl_VertexIndex / 2).xyz; + vec3 Tangent = texelFetch(g_HairVertexTangents, gl_VertexIndex / 2).xyz; + float ratio = (g_bThinTip > 0) ? texelFetch(g_HairThicknessCoeffs, gl_VertexIndex / 2).x : 1.; + + // Calculate right and projected right vectors + vec3 right = Safe_normalize( cross( Tangent, normalize(v - g_vEye))); + vec2 proj_right = Safe_normalize( (g_mViewProj * vec4(right, 0)).xy ); + + vec4 hairEdgePositions0, hairEdgePositions1; // 0 is negative, 1 is positive + hairEdgePositions0 = vec4(v - 1.0 * right * ratio * g_FiberRadius, 1.0); + hairEdgePositions1 = vec4(v + 1.0 * right * ratio * g_FiberRadius, 1.0); + hairEdgePositions0 = g_mViewProj * hairEdgePositions0; + hairEdgePositions1 = g_mViewProj * hairEdgePositions1; + hairEdgePositions0 = hairEdgePositions0 / hairEdgePositions0.w; + hairEdgePositions1 = hairEdgePositions1 / hairEdgePositions1.w; + + float expandPixels = (g_bExpandPixels < 0) ? 0.0 : 0.71; + + float fDirIndex = (gl_VertexIndex % 2 == 1) ? -1.0 : 1.0; + + gl_Position = (fDirIndex==-1.0 ? hairEdgePositions0 : hairEdgePositions1) + fDirIndex * vec4(proj_right * expandPixels / g_WinSize.y, 0.0, 0.0); + depth = gl_Position.z; + tangent = vec4(Tangent, ratio); + p0p1 = vec4( hairEdgePositions0.xy, hairEdgePositions1.xy ); + // TODO: Strand color +} diff --git a/amd_tressfx_vulkan/src/Shaders/RenderHairAAStrandCopies.vert b/amd_tressfx_vulkan/src/Shaders/RenderHairAAStrandCopies.vert new file mode 100644 index 0000000..4f3fe20 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/RenderHairAAStrandCopies.vert @@ -0,0 +1,85 @@ +#version 450 +#extension GL_GOOGLE_include_directive : require +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" + +layout(set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) uniform samplerBuffer g_HairVertexPositions; +layout(set = 1, binding = IDSRV_HAIR_TANGENTS) uniform samplerBuffer g_HairVertexTangents; +layout(set = 1, binding = IDSRV_HAIR_THICKNESSES) uniform samplerBuffer g_HairThicknessCoeffs; +layout(set = 0, binding = IDSRV_NOISEMAP) uniform texture2D g_txNoise; +layout(set = 0, binding = IDSRV_NOISE_SAMPLER) uniform sampler g_samLinearWrap; + +out gl_PerVertex{ + vec4 gl_Position; +}; + +vec2 Safe_normalize(vec2 vec) +{ + float len = length(vec); + return len >= FLOAT_EPSILON ? (vec / len) : vec2(0, 0); +} + +vec3 Safe_normalize(vec3 vec) +{ + float len = length(vec); + return len >= FLOAT_EPSILON ? (vec / len) : vec3(0, 0, 0); +} + +// Need Depth, gl_FragCoord.z returns meaningless values... +layout(location = 0) out float depth; +layout(location = 1) out vec4 p0p1; +layout(location = 2) out vec4 tangent; +layout(location = 3) out vec4 strandColor; + +//-------------------------------------------------------------------------------------- +// VS_RenderHair_AA_StrandCopies +// +// Vertex shader for rendering the hair strands with randomized copies and AA +//-------------------------------------------------------------------------------------- +void main() +{ + // Access the current line segment + int index = gl_VertexIndex / 2; // vertexId is actually the indexed vertex id when indexed triangles are used + + // Identifies which copy of the strand this is (0 is the original, 1 is the first copy, etc.) + int randOffsetIndex = gl_InstanceIndex; + + // Getting a random offset value + uint seedRand = ((index / 64 + 1) * (randOffsetIndex + 1)) % 512; + vec2 seedTexcorrd = vec2(float(seedRand % 512), float(seedRand / 512)) * (1.f / 512.f); + vec3 randOffset = float(randOffsetIndex) * textureLod(sampler2D(g_txNoise, g_samLinearWrap), seedTexcorrd, 0).xyz; + randOffset = 2.0f * randOffset - 1.0f; // so we have random offsets between -1 and 1 + + + // Get updated positions and tangents from simulation result + vec3 Tangent = texelFetch(g_HairVertexTangents, gl_VertexIndex / 2).xyz; + vec3 v = randOffset.xyz + texelFetch(g_HairVertexPositions, gl_VertexIndex / 2).xyz; // We apply a random offset to each vertex when multiple strands are requested + + // Get hair strand thickness + float ratio = (g_bThinTip > 0) ? texelFetch(g_HairThicknessCoeffs, gl_VertexIndex / 2).x : 1.; + + // Calculate right and projected right vectors + vec3 right = Safe_normalize(cross(Tangent, normalize(v - g_vEye))); + vec2 proj_right = Safe_normalize((g_mViewProj * vec4(right, 0)).xy); + + // g_bExpandPixels should be set to 0 at minimum from the CPU side; this would avoid the below test + float expandPixels = (g_bExpandPixels < 0) ? 0.0 : 0.71; + + // Calculate the negative and positive offset screenspace positions + vec4 hairEdgePositions0, hairEdgePositions1; // 0 is negative, 1 is positive + hairEdgePositions0 = vec4(v - 1.0 * right * ratio * g_FiberRadius, 1.0); + hairEdgePositions1 = vec4(v + 1.0 * right * ratio * g_FiberRadius, 1.0); + hairEdgePositions0 = g_mViewProj * hairEdgePositions0; + hairEdgePositions1 = g_mViewProj * hairEdgePositions1; + + // Write output data + + float fDirIndex = (gl_VertexIndex % 2 == 1) ? -1.0 : 1.0; + gl_Position = ((fDirIndex == -1.0) ? hairEdgePositions0 : hairEdgePositions1) + fDirIndex * vec4(proj_right * expandPixels / g_WinSize.y, 0.0f, 0.0f) * ((fDirIndex == -1.0) ? hairEdgePositions0.w : hairEdgePositions1.w); + depth = gl_Position.z / gl_Position.w; + tangent = vec4(Tangent, ratio); + p0p1 = vec4(hairEdgePositions0.xy / max(hairEdgePositions0.w, FLOAT_EPSILON), hairEdgePositions1.xy / max(hairEdgePositions1.w, FLOAT_EPSILON)); + // TODO: Strand color +} \ No newline at end of file diff --git a/amd_tressfx_vulkan/src/Shaders/RenderHairStrandCopies.vert b/amd_tressfx_vulkan/src/Shaders/RenderHairStrandCopies.vert new file mode 100644 index 0000000..e9efc80 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/RenderHairStrandCopies.vert @@ -0,0 +1,77 @@ +#version 450 +#extension GL_GOOGLE_include_directive : require +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" + +layout(set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) uniform samplerBuffer g_HairVertexPositions; +layout(set = 1, binding = IDSRV_HAIR_TANGENTS) uniform samplerBuffer g_HairVertexTangents; +layout(set = 1, binding = IDSRV_HAIR_THICKNESSES) uniform samplerBuffer g_HairThicknessCoeffs; +layout(set = 0, binding = IDSRV_NOISEMAP) uniform texture2D g_txNoise; +layout(set = 0, binding = IDSRV_NOISE_SAMPLER) uniform sampler g_samLinearWrap; + +out gl_PerVertex{ + vec4 gl_Position; +}; + +vec2 Safe_normalize(vec2 vec) +{ + float len = length(vec); + return len >= FLOAT_EPSILON ? (vec / len) : vec2(0, 0); +} + +vec3 Safe_normalize(vec3 vec) +{ + float len = length(vec); + return len >= FLOAT_EPSILON ? (vec / len) : vec3(0, 0, 0); +} + +// Need Depth, gl_FragCoord.z returns meaningless values... +layout(location = 0) out float depth; +layout(location = 1) out vec4 p0p1; +layout(location = 2) out vec4 tangent; +layout(location = 3) out vec4 strandColor; + +//-------------------------------------------------------------------------------------- +// VS_RenderHair_StrandCopies +// +// Vertex shader for rendering the hair strands with randomized copies and without AA +//-------------------------------------------------------------------------------------- +void main() +{ + // Access the current line segment + int index = gl_VertexIndex / 2; // vertexId is actually the indexed vertex id when indexed triangles are used + + // Identifies which copy of the strand this is (0 is the original, 1 is the first copy, etc.) + int randOffsetIndex = gl_InstanceIndex; + + // Getting a random offset value + uint seedRand = ((index / 64 + 1) * (randOffsetIndex + 1)) % 512; + vec2 seedTexcorrd = vec2(float(seedRand % 512), float(seedRand / 512)) * (1.f / 512.f); + vec3 randOffset = float(randOffsetIndex) * textureLod(sampler2D(g_txNoise, g_samLinearWrap), seedTexcorrd, 0).xyz; + randOffset = 2.0f * randOffset - 1.0f; // so we have random offsets between -1 and 1 + + // Get updated positions and tangents from simulation result + vec3 Tangent = texelFetch(g_HairVertexTangents, gl_VertexIndex / 2).xyz; + vec3 v = randOffset.xyz + texelFetch(g_HairVertexPositions, gl_VertexIndex / 2).xyz; // We apply a random offset to each vertex when multiple strands are requested + + // Get hair strand thickness + float ratio = (g_bThinTip > 0) ? texelFetch(g_HairThicknessCoeffs, gl_VertexIndex / 2).x : 1.; + + // Calculate right and projected right vectors + vec3 right = Safe_normalize(cross(Tangent, normalize(v - g_vEye))); + vec2 proj_right = Safe_normalize((g_mViewProj * vec4(right, 0)).xy); + + // g_bExpandPixels should be set to 0 at minimum from the CPU side; this would avoid the below test + float expandPixels = (g_bExpandPixels < 0) ? 0.0 : 0.71; + + float fDirIndex = (gl_VertexIndex % 2 == 1) ? -1.0 : 1.0; + vec3 temp = v + fDirIndex * right * ratio * g_FiberRadius; + gl_Position = g_mViewProj * vec4(temp, 1.f); + gl_Position = gl_Position + fDirIndex * vec4(proj_right * expandPixels / g_WinSize.y, 0.f, 0.f) * gl_Position.w; + depth = gl_Position.z / gl_Position.w; + tangent = vec4(Tangent, ratio); + p0p1 = vec4(v.xy, randOffset.xy + texelFetch(g_HairVertexPositions, gl_VertexIndex / 2 + 1).xy); + // TODO: Strand color +} \ No newline at end of file diff --git a/amd_tressfx_vulkan/src/Shaders/SimulationConfig.glsl b/amd_tressfx_vulkan/src/Shaders/SimulationConfig.glsl new file mode 100644 index 0000000..3582fde --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/SimulationConfig.glsl @@ -0,0 +1,92 @@ +// If you change the value below, you must change it in TressFXAsset.h as well. +#define THREAD_GROUP_SIZE 64 + +// shader resource view slots +#define IDSRV_PPLL 0 +#define IDSRV_HEAD_PPLL 1 +#define IDSRV_SCENESM 2 +#define IDSRV_HAIRSM 3 +#define IDSRV_HAIR_COLOR_TEXTURE 4 +#define IDSRV_NOISEMAP 5 +#define IDSRV_HAIR_THICKNESSES 6 +#define IDSRV_HAIR_VERTEX_POSITIONS 7 +#define IDSRV_HAIR_TANGENTS 8 +#define IDSRV_HAIR_TRANSFORMS 9 +#define IDSRV_HAIR_STRAND_TEX_COORDS 10 +#define IDSRV_HAIR_VERTEX_TEX_COORDS 11 +#define IDSRV_HAIR_VERTEX_COLORS 12 + +// Shortcut resources. +#define IDSRV_HAIR_FRAGMENT_DEPTHS 13 +#define IDSRV_HAIR_FRAGMENT_COLORS 14 +#define IDSRV_HAIR_ACCUM_INV_ALPHA 15 + +#define IDSRV_CONSTANTS_BUFFER 16 +#define IDSRV_ATOMIC_COUNTER_BUFFER 17 +#define IDSRV_NOISE_SAMPLER 18 +#define IDSRV_SHADOW_SAMPLER 19 + +#define IDSRV_HAIR_PREVIOUS_VERTEX_POSITIONS 20 +#define IDSRV_HAIR_VERTEX_INITIAL_POSITIONS 21 +#define IDSRV_HAIR_STRAND_TYPE 22 +#define IDSRV_HAIR_GLOBAL_ROTATION 23 +#define IDSRV_HAIR_LOCAL_REF_VEC 24 +#define IDSRV_HAIR_ROOT_OFFSET 25 +#define IDSRV_HAIR_LENGTH 26 +#define IDSRV_HEAD_TRANSFORM 27 + +#define MAX_VERTS_PER_STRAND 16 + +layout(std140, set = 0, binding = IDSRV_CONSTANTS_BUFFER) buffer Constants +{ + vec4 g_Wind; + vec4 g_Wind1; + vec4 g_Wind2; + vec4 g_Wind3; + + int g_NumLengthConstraintIterations; + int g_bCollision; + + float g_GravityMagnitude; + float g_TimeStep; + + float g_Damping0; + float g_StiffnessForLocalShapeMatching0; + float g_StiffnessForGlobalShapeMatching0; + float g_GlobalShapeMatchingEffectiveRange0; + + float g_Damping1; + float g_StiffnessForLocalShapeMatching1; + float g_StiffnessForGlobalShapeMatching1; + float g_GlobalShapeMatchingEffectiveRange1; + + float g_Damping2; + float g_StiffnessForLocalShapeMatching2; + float g_StiffnessForGlobalShapeMatching2; + float g_GlobalShapeMatchingEffectiveRange2; + + float g_Damping3; + float g_StiffnessForLocalShapeMatching3; + float g_StiffnessForGlobalShapeMatching3; + float g_GlobalShapeMatchingEffectiveRange3; + + uint g_NumOfStrandsPerThreadGroup; + uint g_NumFollowHairsPerGuideHair; + float g_TipSeparationFactor; + + int g_bWarp; + int g_NumLocalShapeMatchingIterations; +}; + +layout(std140, set = 0, binding = IDSRV_HEAD_TRANSFORM) buffer HeadTransform +{ + mat4 g_ModelTransformForHead; + vec4 g_ModelRotateForHead; // quaternion + int bSingleHeadTransform; + float padding[3]; +}; + +bool IsMovable(vec4 particle) +{ + return particle.w > 0; +} diff --git a/amd_tressfx_vulkan/src/Shaders/TressFXRender_pass2.frag b/amd_tressfx_vulkan/src/Shaders/TressFXRender_pass2.frag new file mode 100644 index 0000000..5e9c914 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/TressFXRender_pass2.frag @@ -0,0 +1,147 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" +#include "PackUnpack.glsl" +#include "ComputeShadow.glsl" +#include "ComputeHairShading.glsl" + +layout(set = 0, binding = IDSRV_HEAD_PPLL, r32ui) uniform restrict uimage2D PerPixelLinkedListHead; + +struct PerPixelListBucket +{ + float depth; + uint TangentAndCoverage; + uint next; +}; + +layout(std430, set = 0, binding = IDSRV_PPLL) buffer PerPixelLinkedList +{ + PerPixelListBucket PPLL[]; +}; + +#define K_BUFFER 8 + +struct FragmentElement { + float depth; + uint TangentAndCoverage; +}; + +layout(location = 0) out vec4 FragColor; + +//-------------------------------------------------------------------------------------- +// PS_KBuffer_Hair +// +// Second pass pixel shader which selects the nearest k fragments (k-buffer) and renders +// then in depth order for correct transparent blending of the hair. It uses the per-pixel +// linked list to access all of the layers of hair fragment so that the nearest k fragments +// are rendered at a higher quality than the remaining fragments. The lighting and shadows +// are calculated in screen space using the tangent and depth stored in the per-pixel linked +// list, similar to deferred shading. +// +//-------------------------------------------------------------------------------------- +void main() { + ivec2 iuv = ivec2(gl_FragCoord.xy); + uint ListBucketHead = imageLoad(PerPixelLinkedListHead, iuv).x; + if (ListBucketHead == -1) discard; + + FragmentElement kbuf[K_BUFFER]; + // Load first K_BUFFER element in temp array + int kbuf_size; + for (kbuf_size = 0; kbuf_size < K_BUFFER; kbuf_size++) + { + if (ListBucketHead == -1) + break; + kbuf[kbuf_size].depth = PPLL[ListBucketHead].depth; + kbuf[kbuf_size].TangentAndCoverage = PPLL[ListBucketHead].TangentAndCoverage; + ListBucketHead = PPLL[ListBucketHead].next; + } + + uint ListBucketId = ListBucketHead; + vec4 result = vec4(0., 0., 0., 1.); + + uint numfrag = 0; + while (ListBucketId != -1) { + numfrag++; + float max_depth = 0.; + uint max_idx = 0; + for (int i = 0; i < kbuf_size; i++) + { + float d = kbuf[i].depth; + max_depth = max(max_depth, d); + max_idx = (max_depth == d) ? i : max_idx; + } + + if (PPLL[ListBucketId].depth < max_depth) + { + float tmp = PPLL[ListBucketId].depth; + PPLL[ListBucketId].depth = kbuf[max_idx].depth; + kbuf[max_idx].depth = tmp; + uint tmpu = PPLL[ListBucketId].TangentAndCoverage; + PPLL[ListBucketId].TangentAndCoverage = kbuf[max_idx].TangentAndCoverage; + kbuf[max_idx].TangentAndCoverage = tmpu; + } + + float d = PPLL[ListBucketId].depth; + vec3 ndcPos = 2. * vec3(gl_FragCoord.x * g_WinSize.z, 1. - gl_FragCoord.y * g_WinSize.w, d) - 1.; + ndcPos.z = d; + vec4 Pos = g_mInvViewProj * vec4(ndcPos, 1.); + Pos /= Pos.w; + vec3 Tangent = GetTangent(PPLL[ListBucketId].TangentAndCoverage); + float FragmentAlpha = GetCoverage(PPLL[ListBucketId].TangentAndCoverage); + float amountOfLight = ComputeSimpleShadow(Pos.xyz, g_HairShadowAlpha); + vec3 FragmentColor = SimpleHairShading(Pos.xyz, Tangent, vec4(0.), amountOfLight); + result.xyz = result.xyz * (1. - FragmentAlpha) + FragmentAlpha * FragmentColor; + result.w *= (1. - FragmentAlpha); + + ListBucketId = PPLL[ListBucketId].next; + } + +//#define DEBUG +#ifdef DEBUG + result = vec4(0., 1., 0., 0.); + if (numfrag > 32) result.xyz = vec3(1., 1., 0.); + if (numfrag > 64) result.xyz = vec3(1., .5, 0.); + if (numfrag > 128) result.xyz = vec3(1., 0., 0.); + FragColor = result; + return; +#endif + + uint reverse = 0; + bool isSorted = false; + while (!isSorted) { + isSorted = true; + for (int i = 0; i < kbuf_size - 1; i++) + { + if (kbuf[i].depth < kbuf[i + 1].depth) { + isSorted = false; + float tmp = kbuf[i].depth; + kbuf[i].depth = kbuf[i + 1].depth; + kbuf[i + 1].depth = tmp; + uint ttmp = kbuf[i].TangentAndCoverage; + kbuf[i].TangentAndCoverage = kbuf[i + 1].TangentAndCoverage; + kbuf[i + 1].TangentAndCoverage = ttmp; + reverse++; + } + } + } + + for (int i = 0; i < kbuf_size; i++) + { + float d = kbuf[i].depth; + vec3 ndcPos = 2. * vec3(gl_FragCoord.x * g_WinSize.z, 1. - gl_FragCoord.y * g_WinSize.w, d) - 1.; + ndcPos.z = d; + vec4 Pos = g_mInvViewProj * vec4(ndcPos, 1.); + Pos /= Pos.w; + + vec3 Tangent = GetTangent(kbuf[i].TangentAndCoverage); + float FragmentAlpha = GetCoverage(kbuf[i].TangentAndCoverage); + float amountOfLight = ComputeShadow(Pos.xyz, g_HairShadowAlpha); + vec3 FragmentColor = ComputeHairShading(Pos.xyz, Tangent, vec4(0.), amountOfLight, g_MatBaseColor.xyz); + + result.xyz = result.xyz * (1. - FragmentAlpha) + FragmentAlpha * FragmentColor; + result.w *= (1. - FragmentAlpha); + } + FragColor = result; +} \ No newline at end of file diff --git a/amd_tressfx_vulkan/src/Shaders/TressFXRender_pass2.vert b/amd_tressfx_vulkan/src/Shaders/TressFXRender_pass2.vert new file mode 100644 index 0000000..fac5ddd --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/TressFXRender_pass2.vert @@ -0,0 +1,37 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout(location = 0) out vec2 vTex; + +out gl_PerVertex { + vec4 gl_Position; +}; + +vec4 getPosition(uint index) +{ + switch (index) + { + case 0: return vec4(-1, 1, 0, 1); + case 1: return vec4(3, 1, 0, 1); + case 2: return vec4(-1, -3, 0, 1); + default: return vec4(0.); + } +} + +vec2 getTC(uint index) +{ + switch (index) + { + case 0: return vec2(0., 0.); + case 1: return vec2(0., 2.); + case 2: return vec2(2., 0.); + default: return vec2(0.); + } +} + +void main() +{ + gl_Position = getPosition(gl_VertexIndex); + vTex = getTC(gl_VertexIndex); +} diff --git a/amd_tressfx_vulkan/src/Shaders/TressFxRender.frag b/amd_tressfx_vulkan/src/Shaders/TressFxRender.frag new file mode 100644 index 0000000..27325e0 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/TressFxRender.frag @@ -0,0 +1,67 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#include "RenderConfig.glsl" +#include "PackUnpack.glsl" +#include "ComputeCoverage.glsl" + +layout(set = 0, binding = IDSRV_ATOMIC_COUNTER_BUFFER) buffer AtomicBuffer +{ + uint PixelCount; +}; +layout(set = 0, binding = IDSRV_HEAD_PPLL, r32ui) uniform restrict uimage2D PerPixelLinkedListHead; + +struct PerPixelListBucket +{ + float depth; + uint TangentAndCoverage; + uint next; +}; + +layout(std430, set = 0, binding = IDSRV_PPLL) buffer PerPixelLinkedList +{ + PerPixelListBucket PPLL[]; +}; +layout(early_fragment_tests) in; + +void StoreFragments_Hair(vec2 FragCoordXY, vec3 Tangent, float Coverage, float depth) +{ + uint pixel_id = atomicAdd(PixelCount, 1); + int pxid = int(pixel_id); + ivec2 iuv = ivec2(FragCoordXY); + uint tmp = imageAtomicExchange(PerPixelLinkedListHead, iuv, pixel_id); + PPLL[pxid].depth = depth; + PPLL[pxid].TangentAndCoverage = PackTangentAndCoverage(Tangent.xyz, Coverage); + PPLL[pxid].next = tmp; +} + +layout(location = 0) in float depth; +layout(location = 1) in vec4 p0p1; +layout(location = 2) in vec4 tangent; + + +//-------------------------------------------------------------------------------------- +// PS_ABuffer_Hair +// +// This is the first pass pixel shader for rendering hair geometry into an A-buffer. +// It keeps all of the layers of the transparent hair in a UAV per-pixel linked list. +// +// Coverage for antialiasing is calculated and stored in the linked list along with geometry +// and attributes necessary for lighting and shadows which are calculated in a subsequent +// pass by rendering a full screen quad. +// +//-------------------------------------------------------------------------------------- +void main() { + // Render AA Line, calculate pixel coverage + vec4 proj_pos = vec4(2 * gl_FragCoord.x * g_WinSize.z - 1., + 1. - 2 * gl_FragCoord.y * g_WinSize.w, + 1., 1.); + vec4 original_pos = g_mInvViewProj * proj_pos; // Not used ?? + + float coverage = (g_bUseCoverage != 0) ? ComputeCoverage(p0p1.xy, p0p1.zw, proj_pos.xy) : 1.; + + coverage *= g_FiberAlpha; + if (coverage > g_alphaThreshold) + StoreFragments_Hair(gl_FragCoord.xy, tangent.xyz, coverage, gl_FragCoord.z); +} diff --git a/amd_tressfx_vulkan/src/Shaders/UpdateFollowHair.comp b/amd_tressfx_vulkan/src/Shaders/UpdateFollowHair.comp new file mode 100644 index 0000000..fbc95a8 --- /dev/null +++ b/amd_tressfx_vulkan/src/Shaders/UpdateFollowHair.comp @@ -0,0 +1,37 @@ +#version 450 + +#include "SimulationConfig.glsl" + +layout (local_size_x = THREAD_GROUP_SIZE, local_size_y = 1, local_size_z = 1) in; + +layout(std430, set = 1, binding = IDSRV_HAIR_VERTEX_POSITIONS) buffer writeablePositions +{ + vec4 g_HairVertexPositions[]; +}; +layout(set = 1, binding = IDSRV_HAIR_ROOT_OFFSET) uniform samplerBuffer g_FollowHairRootOffset; + +#include "IndicesComputations.glsl" + +shared vec4 sharedPos[THREAD_GROUP_SIZE]; + +// One thread computes one vertex. +void main() +{ + uint globalStrandIndex, localStrandIndex, localVertexIndex, numVerticesInTheStrand, indexForSharedMem, strandType; + int globalVertexIndex; + CalcIndicesInVertexLevelMaster(gl_LocalInvocationID.x, gl_WorkGroupID.x, globalStrandIndex, localStrandIndex, globalVertexIndex, localVertexIndex, numVerticesInTheStrand, indexForSharedMem, strandType); + + sharedPos[indexForSharedMem] = g_HairVertexPositions[globalVertexIndex]; + barrier(); + + for (int i = 0; i < g_NumFollowHairsPerGuideHair; i++) + { + int globalFollowVertexIndex = globalVertexIndex + int(numVerticesInTheStrand) * (i + 1); + int globalFollowStrandIndex = int(globalStrandIndex) + i + 1; + float factor = g_TipSeparationFactor * (float(localVertexIndex) / float(numVerticesInTheStrand)) + 1.0f; + vec3 followPos = sharedPos[indexForSharedMem].xyz + factor * texelFetch(g_FollowHairRootOffset, globalFollowStrandIndex).xyz; + g_HairVertexPositions[globalFollowVertexIndex].xyz = followPos; + } + + return; +} diff --git a/amd_tressfx_vulkan/src/TressFXMeshVulkan.cpp b/amd_tressfx_vulkan/src/TressFXMeshVulkan.cpp new file mode 100644 index 0000000..028d453 --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXMeshVulkan.cpp @@ -0,0 +1,1160 @@ +//-------------------------------------------------------------------------------------- +// File: TressFXMesh.cpp +// +// Hair mesh code +// +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// +//-------------------------------------------------------------------------------------- + +#include "TressFXMeshVulkan.h" +#include "AMD_Types.h" +#include "UtilVulkan.h" + +#include +#include + +using namespace std; +using namespace DirectX; + +namespace AMD +{ + +//-------------------------------------------------------------------------------------- +// +// Constructor +// +// Used for initializing member variables to default values. +//-------------------------------------------------------------------------------------- +TressFXMesh::TressFXMesh(void) + : m_pIndexBuffer(NULL), m_pTriangleIndexBuffer(NULL), m_pThicknessCoeffsBuffer(NULL), m_pThicknessIndexTriangleIndexMemory(NULL), + m_pThicknessCoeffsView(NULL) +{ + m_HairVertexPositionsBuffer = NULL; + m_HairVertexPositionsView = NULL; + m_HairVertexPositionsPrevBuffer = NULL; + + m_HairStrandTypeBuffer = NULL; + m_HairStrandTypeView = NULL; + + m_HairVertexPositionsView = NULL; + m_HairVertexPositionsPrevView = NULL; + + m_HairLengthBuffer = NULL; + m_HairRestLengthSRV = NULL; + + m_InitialHairPositionsBuffer = NULL; + m_InitialHairPositionsView = NULL; + + m_HairVertexTangentsBuffer = NULL; + m_HairVertexTangentsView = NULL; + + m_HairRefVectorsBuffer = NULL; + m_HairRefVecsInLocalFrameView = NULL; + + m_FollowHairRootOffsetBuffer = NULL; + m_FollowHairRootOffsetView = NULL; + + m_GlobalRotationsBuffer = NULL; + m_GlobalRotationsView = NULL; + + m_LocalRotationsBuffer = NULL; + m_LocalRotationsView = NULL; + + m_HairAsset.m_pHairStrandType = NULL; + m_HairAsset.m_pRefVectors = NULL; + m_HairAsset.m_pTriangleVertices = NULL; + m_HairAsset.m_pGlobalRotations = NULL; + m_HairAsset.m_pLocalRotations = NULL; + m_HairAsset.m_pVertices = NULL; + m_HairAsset.m_pTangents = NULL; + m_HairAsset.m_pThicknessCoeffs = NULL; + m_HairAsset.m_pRestLengths = NULL; + m_HairAsset.m_pFollowRootOffset = NULL; + + m_HairAsset.m_NumFollowHairsPerGuideHair = 4; + m_HairAsset.m_NumGuideHairStrands = 0; + m_HairAsset.m_NumOfVerticesInStrand = 2; + + m_HairSkinMappingBuffer = NULL; + m_HairTransformsBuffer = NULL; + m_HairSkinMappingView = NULL; + m_HairTransformsView = NULL; + m_pStrandTexCoordBuffer = NULL; + m_pStrandTexCoordView = NULL; +} + +//-------------------------------------------------------------------------------------- +// +// Destructor +// +//-------------------------------------------------------------------------------------- +TressFXMesh::~TressFXMesh(void) { OnDestroy(); } + +//-------------------------------------------------------------------------------------- +// +// OnCreate +// +// Called to create a hair mesh. This function creates the VK resources +// and stores the hair data into these resources. +// +//-------------------------------------------------------------------------------------- +VkResult TressFXMesh::OnCreate(VkDevice pvkDevice, + TressFX_HairBlob *pHairBlob, + TressFX_SceneMesh *sceneMesh, + VkImageView pTexture, + VkPhysicalDeviceMemoryProperties memProperties, + VkCommandBuffer upload_cmd_buffer, + VkBuffer scratchBuffer, + VkDeviceMemory scratchMemory, + VkDescriptorSetLayout GlobalConstraintsSetLayout, + VkDescriptorSetLayout LocalConstraintsSetLayout, + VkDescriptorSetLayout LenghtWindCollisionSetLayout, + VkDescriptorSetLayout PrepareFollowHairSetLayout, + VkDescriptorSetLayout UpdateFollowHaitSetLayout, + VkDescriptorSetLayout computeTangentSetLayout, + VkDescriptorSetLayout Pass1SetLayout, + VkDescriptorSetLayout ShadowSetLayout, const DebugMarkerPointer& markerCallbacks) +{ + VkResult vr; + size_t offsetInUploadBuffer = 0; + + // load the binary file + if (!Deserialize(pHairBlob)) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + + // Create Buffers + { + // thickness coeff buffer + VkBufferCreateInfo bd{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bd.usage = + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + bd.size = sizeof(float) * m_HairAsset.m_NumTotalHairVertices; + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bd, nullptr, &m_pThicknessCoeffsBuffer)); + + //----------------------------------- + // Index buffer (lines and triangles) + //----------------------------------- + + // Line index buffer + m_TotalIndexCount = (int)m_HairAsset.m_LineIndices.size(); + bd.size = (UINT)(sizeof(unsigned int) * m_TotalIndexCount); + bd.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bd, nullptr, &m_pIndexBuffer)); + + // Triangle index buffer + m_TotalTriangleIndexCount = (int)m_HairAsset.m_TriangleIndices.size(); + bd.size = (UINT)(sizeof(unsigned int) * m_TotalTriangleIndexCount); + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bd, nullptr, &m_pTriangleIndexBuffer)); + + VkMemoryRequirements thicknessBufferMemReq; + vkGetBufferMemoryRequirements(pvkDevice, m_pThicknessCoeffsBuffer, &thicknessBufferMemReq); + VkMemoryRequirements indexBufferMemReq; + vkGetBufferMemoryRequirements(pvkDevice, m_pIndexBuffer, &indexBufferMemReq); + VkMemoryRequirements triangleIndexBufferMemReq; + vkGetBufferMemoryRequirements(pvkDevice, m_pTriangleIndexBuffer, &triangleIndexBufferMemReq); + + uint32_t memoryType = getMemoryTypeIndex(indexBufferMemReq.memoryTypeBits & triangleIndexBufferMemReq.memoryTypeBits & thicknessBufferMemReq.memoryTypeBits, + memProperties, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + if (memoryType == -1) return VK_ERROR_INITIALIZATION_FAILED; + + VkDeviceSize indexBufferOffset = align(thicknessBufferMemReq.size, indexBufferMemReq.alignment); + VkDeviceSize triangleIndexBufferOffset = align(indexBufferOffset + indexBufferMemReq.size, triangleIndexBufferMemReq.alignment); + VkDeviceSize totalSize = triangleIndexBufferOffset + triangleIndexBufferMemReq.size; + + VkMemoryAllocateInfo allocateInfo{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; + allocateInfo.allocationSize = totalSize; + allocateInfo.memoryTypeIndex = memoryType; + vkAllocateMemory(pvkDevice, &allocateInfo, nullptr, &m_pThicknessIndexTriangleIndexMemory); + + vkBindBufferMemory(pvkDevice, m_pThicknessCoeffsBuffer, m_pThicknessIndexTriangleIndexMemory, 0); + vkBindBufferMemory(pvkDevice, m_pIndexBuffer, m_pThicknessIndexTriangleIndexMemory, indexBufferOffset); + vkBindBufferMemory(pvkDevice, m_pTriangleIndexBuffer, m_pThicknessIndexTriangleIndexMemory, triangleIndexBufferOffset); + + // Fill them + void *uploadBuffer; + vkMapMemory(pvkDevice, scratchMemory, 0, totalSize, 0, &uploadBuffer); + + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pThicknessCoeffs, m_pThicknessCoeffsBuffer, + offsetInUploadBuffer, sizeof(float) * m_HairAsset.m_NumTotalHairVertices); + + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + &m_HairAsset.m_LineIndices[0], m_pIndexBuffer, offsetInUploadBuffer, + sizeof(unsigned int) * m_TotalIndexCount); + + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + &m_HairAsset.m_TriangleIndices[0], m_pTriangleIndexBuffer, + offsetInUploadBuffer, sizeof(unsigned int) * m_TotalTriangleIndexCount); + vkUnmapMemory(pvkDevice, scratchMemory); + } + + // thickness coeff buffer srv + { + VkBufferViewCreateInfo SRVDesc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + SRVDesc.format = VK_FORMAT_R32_SFLOAT; + SRVDesc.range = m_HairAsset.m_NumTotalHairVertices * sizeof(float); + SRVDesc.buffer = m_pThicknessCoeffsBuffer; + + AMD_CHECKED_VULKAN_CALL( + vkCreateBufferView(pvkDevice, &SRVDesc, nullptr, &m_pThicknessCoeffsView)); + } + + m_pHairTextureSRV = pTexture; + + AMD_CHECKED_VULKAN_CALL(CreateBufferAndViews(pvkDevice, sceneMesh, + memProperties, + upload_cmd_buffer, scratchBuffer, + scratchMemory, + offsetInUploadBuffer, markerCallbacks )); + AMD_CHECKED_VULKAN_CALL(AllocateDescriptorsSets(pvkDevice, GlobalConstraintsSetLayout, + LocalConstraintsSetLayout, LenghtWindCollisionSetLayout, + PrepareFollowHairSetLayout, UpdateFollowHaitSetLayout, + computeTangentSetLayout, Pass1SetLayout, ShadowSetLayout)); + + VkBufferMemoryBarrier bufferBarrier[] = { + getBufferBarrier(m_pThicknessCoeffsBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT), + getBufferBarrier(m_pIndexBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_INDEX_READ_BIT), + getBufferBarrier(m_pTriangleIndexBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_INDEX_READ_BIT), + getBufferBarrier(m_HairStrandTypeBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT), + getBufferBarrier(m_InitialHairPositionsBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT), + getBufferBarrier(m_HairLengthBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT), + getBufferBarrier(m_HairRefVectorsBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT), + getBufferBarrier(m_FollowHairRootOffsetBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT), + getBufferBarrier(m_GlobalRotationsBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT), + getBufferBarrier(m_LocalRotationsBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT), + }; + + vkCmdPipelineBarrier(upload_cmd_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(bufferBarrier), bufferBarrier, 0, nullptr); + + DestroyAsset(); + + return vr; +} + +//-------------------------------------------------------------------------------------- +// +// CreateBufferAndViews +// +// Called by the OnCreate function to create the VK resources +// +//-------------------------------------------------------------------------------------- +VkResult TressFXMesh::CreateBufferAndViews( + VkDevice pvkDevice, + TressFX_SceneMesh *sceneMesh, + VkPhysicalDeviceMemoryProperties memProp, + VkCommandBuffer upload_cmd_buffer, + VkBuffer scratchBuffer, VkDeviceMemory scratchMemory, size_t &offsetInUploadBuffer, const DebugMarkerPointer& markerCallbacks) +{ + VkResult vr; + m_pvkDevice = pvkDevice; + size_t sizeToUpload = + // m_HairStrandTypeSRV + m_HairAsset.m_NumTotalHairStrands * sizeof(int) + + // m_InitialHairPositionsSRV + m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4) + + // m_HairVertexPositionsUAB + 2 * m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4) + + // m_HairVertexTangentsUAB + m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4) + + // m_HairRestLengthSRV + m_HairAsset.m_NumTotalHairVertices * sizeof(float) + + // m_HairRefVecsInLocalFrameSRV + m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4) + + // m_FollowHairRootOffsetSRV + m_HairAsset.m_NumTotalHairStrands * sizeof(XMFLOAT4) + + // m_GlobalRotationsUAB + m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4) + + // m_LocalRotationsUAB + m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4) + + // m_pStrandTexCoordBuffer + m_HairAsset.m_NumTotalHairStrands * sizeof(float) * 2; + + void *uploadBuffer; + vkMapMemory(pvkDevice, scratchMemory, 0, sizeToUpload, 0, &uploadBuffer); + + //-------------------------------- + // m_HairStrandTypeSRV + //-------------------------------- + { + VkBufferCreateInfo bufferDesc{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDesc.usage = + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + bufferDesc.size = m_HairAsset.m_NumTotalHairStrands * sizeof(int); + AMD_CHECKED_VULKAN_CALL( + vkCreateBuffer(pvkDevice, &bufferDesc, nullptr, &m_HairStrandTypeBuffer)); + markerCallbacks.nameObject(m_HairStrandTypeBuffer, "HairStrandTypeBuffer"); + + m_HairStrandTypeMemory = allocBufferMemory(pvkDevice, m_HairStrandTypeBuffer, + memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_HairStrandTypeMemory, "HairStrandTypeMemory"); + + VkBufferViewCreateInfo SRVDesc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + SRVDesc.format = VK_FORMAT_R32_SINT; + SRVDesc.range = m_HairAsset.m_NumTotalHairStrands * sizeof(int32_t); + SRVDesc.buffer = m_HairStrandTypeBuffer; + AMD_CHECKED_VULKAN_CALL( + vkCreateBufferView(pvkDevice, &SRVDesc, nullptr, &m_HairStrandTypeView)); + markerCallbacks.nameObject(m_HairStrandTypeView, "HairStrandTypeView"); + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pHairStrandType, m_HairStrandTypeBuffer, + offsetInUploadBuffer, bufferDesc.size); + } + + //--------------------------------- + // m_InitialHairPositionsSRV + // m_InitialHairPositionsUAV + //--------------------------------- + { + VkBufferCreateInfo bufferDesc{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDesc.size = m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4); + bufferDesc.usage = + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bufferDesc, nullptr, + &m_InitialHairPositionsBuffer)); + markerCallbacks.nameObject(m_InitialHairPositionsBuffer, "InitialHairPositionBuffer"); + m_InitialHairPositionsMemory = allocBufferMemory( + pvkDevice, m_InitialHairPositionsBuffer, memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_InitialHairPositionsMemory, "InitialHairPositionsMemory"); + + VkBufferViewCreateInfo desc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + desc.format = VK_FORMAT_R32G32B32A32_SFLOAT; + desc.range = m_HairAsset.m_NumTotalHairVertices * 4 * sizeof(float); + desc.buffer = m_InitialHairPositionsBuffer; + AMD_CHECKED_VULKAN_CALL( + vkCreateBufferView(pvkDevice, &desc, nullptr, &m_InitialHairPositionsView)); + markerCallbacks.nameObject(m_InitialHairPositionsView, "InitialHairPositionsView"); + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pVertices, m_InitialHairPositionsBuffer, + offsetInUploadBuffer, bufferDesc.size); + } + + // ------------------------ + // m_HairVertexPositionsUAB + //------------------------- + { + VkBufferCreateInfo bufferDescUA{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDescUA.size = m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4); + bufferDescUA.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT; + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bufferDescUA, nullptr, + &m_HairVertexPositionsBuffer)); + markerCallbacks.nameObject(m_HairVertexPositionsBuffer, "HairVertexPositionsBuffer"); + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bufferDescUA, nullptr, + &m_HairVertexPositionsPrevBuffer)); + markerCallbacks.nameObject(m_HairVertexPositionsPrevBuffer, "HairVertexPositionsPrevBuffer"); + + m_HairVertexPositionsMemory = allocBufferMemory( + pvkDevice, m_HairVertexPositionsBuffer, memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_HairVertexPositionsMemory, "HairVertexPositionsMemory"); + m_HairVertexPositionsPrevMemory = allocBufferMemory( + pvkDevice, m_HairVertexPositionsPrevBuffer, memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_HairVertexPositionsPrevMemory, "HairVertexPositionsPrevMemory"); + // TODO: We could write only once to uploadBuffer and share data between + // the + // 3 buffers + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pVertices, m_HairVertexPositionsBuffer, + offsetInUploadBuffer, bufferDescUA.size); + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pVertices, m_HairVertexPositionsPrevBuffer, + offsetInUploadBuffer, bufferDescUA.size); + } + + // ----------------------------- + // m_HairVertexTangentsUAB + //------------------------------ + { + VkBufferCreateInfo bufferDescUA{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDescUA.size = m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4); + bufferDescUA.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT; + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bufferDescUA, nullptr, + &m_HairVertexTangentsBuffer)); + markerCallbacks.nameObject(m_HairVertexTangentsBuffer, "HairVertexTangentsBuffer"); + m_HairVertexTangentsMemory = allocBufferMemory( + pvkDevice, m_HairVertexTangentsBuffer, memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_HairVertexTangentsMemory, "HairVertexTangentsMemory"); + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pTangents, m_HairVertexTangentsBuffer, + offsetInUploadBuffer, bufferDescUA.size); + } + + //----------------------- + // m_HairVertexPositionsView + //----------------------- + { + VkBufferViewCreateInfo sbSRVDesc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + sbSRVDesc.range = m_HairAsset.m_NumTotalHairVertices * 4 * sizeof(float); + sbSRVDesc.format = VK_FORMAT_R32G32B32A32_SFLOAT; + sbSRVDesc.buffer = m_HairVertexPositionsBuffer; + AMD_CHECKED_VULKAN_CALL(vkCreateBufferView(pvkDevice, &sbSRVDesc, nullptr, + &m_HairVertexPositionsView)); + markerCallbacks.nameObject(m_HairVertexPositionsView, "HairVertexPositionsView"); + } + + //----------------------- + // m_HairVertexTangentsView + //----------------------- + { + VkBufferViewCreateInfo sbSRVDesc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + sbSRVDesc.range = m_HairAsset.m_NumTotalHairVertices * 4 * sizeof(float); + sbSRVDesc.format = VK_FORMAT_R32G32B32A32_SFLOAT; + sbSRVDesc.buffer = m_HairVertexTangentsBuffer; + AMD_CHECKED_VULKAN_CALL(vkCreateBufferView(pvkDevice, &sbSRVDesc, nullptr, + &m_HairVertexTangentsView)); + markerCallbacks.nameObject(m_HairVertexTangentsView, "HairVertexTangentsView"); + } + + //----------------------- + // m_HairVertexPositionsView + //----------------------- + { + VkBufferViewCreateInfo sbUAVDesc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + sbUAVDesc.range = m_HairAsset.m_NumTotalHairVertices * 4 * sizeof(float); + sbUAVDesc.format = VK_FORMAT_R32G32B32A32_SFLOAT; + sbUAVDesc.buffer = m_HairVertexPositionsPrevBuffer; + AMD_CHECKED_VULKAN_CALL(vkCreateBufferView(pvkDevice, &sbUAVDesc, nullptr, + &m_HairVertexPositionsPrevView)); + markerCallbacks.nameObject(m_HairVertexPositionsPrevView, "HairVertexPositionsPrevView"); + } + + //--------------------------- + // m_HairRestLengthSRV + //--------------------------- + { + VkBufferCreateInfo bufferDesc{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDesc.size = m_HairAsset.m_NumTotalHairVertices * sizeof(float); + bufferDesc.usage = + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + // AMD_SAFE_RELEASE(m_HairLengthBuffer); + AMD_CHECKED_VULKAN_CALL( + vkCreateBuffer(pvkDevice, &bufferDesc, nullptr, &m_HairLengthBuffer)); + markerCallbacks.nameObject(m_HairLengthBuffer, "HairLengthBuffer"); + m_HairLengthMemory = + allocBufferMemory(pvkDevice, m_HairLengthBuffer, memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_HairLengthMemory, "HairLengthMemory"); + + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pRestLengths, m_HairLengthBuffer, + offsetInUploadBuffer, bufferDesc.size); + + VkBufferViewCreateInfo desc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + desc.format = VK_FORMAT_R32_SFLOAT; + desc.range = m_HairAsset.m_NumTotalHairVertices * sizeof(float); + desc.buffer = m_HairLengthBuffer; + AMD_CHECKED_VULKAN_CALL(vkCreateBufferView(pvkDevice, &desc, nullptr, &m_HairRestLengthSRV)); + markerCallbacks.nameObject(m_HairRestLengthSRV, "HairRestLengthSRV"); + } + + //----------------------------------- + // m_HairRefVecsInLocalFrameSRV + //----------------------------------- + { + + VkBufferCreateInfo bufferDesc{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDesc.size = m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4); + bufferDesc.usage = + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + AMD_CHECKED_VULKAN_CALL( + vkCreateBuffer(pvkDevice, &bufferDesc, nullptr, &m_HairRefVectorsBuffer)); + markerCallbacks.nameObject(m_HairRefVectorsBuffer, "HairRefVectorsBuffer"); + m_HairRefVectorsMemory = allocBufferMemory(pvkDevice, m_HairRefVectorsBuffer, + memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_HairRefVectorsMemory, "HairRefVectorsMemory"); + + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pRefVectors, m_HairRefVectorsBuffer, + offsetInUploadBuffer, bufferDesc.size); + + VkBufferViewCreateInfo desc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + desc.format = VK_FORMAT_R32G32B32A32_SFLOAT; + desc.range = m_HairAsset.m_NumTotalHairVertices * 4 * sizeof(float); + desc.buffer = m_HairRefVectorsBuffer; + AMD_CHECKED_VULKAN_CALL(vkCreateBufferView(pvkDevice, &desc, nullptr, + &m_HairRefVecsInLocalFrameView)); + markerCallbacks.nameObject(m_HairRefVecsInLocalFrameView, "HairRefVecsInLocalFrameView"); + } + + //----------------------------------- + // m_FollowHairRootOffsetSRV + //----------------------------------- + { + VkBufferCreateInfo bufferDesc{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDesc.size = m_HairAsset.m_NumTotalHairStrands * sizeof(XMFLOAT4); + bufferDesc.usage = + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + // AMD_SAFE_RELEASE(m_FollowHairRootOffsetBuffer); + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bufferDesc, nullptr, + &m_FollowHairRootOffsetBuffer)); + markerCallbacks.nameObject(m_FollowHairRootOffsetBuffer, "FollowHairRootOffsetBuffer"); + m_FollowHairRootOffsetMemory = allocBufferMemory( + pvkDevice, m_FollowHairRootOffsetBuffer, memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_FollowHairRootOffsetMemory, "FollowHaitRootOffsetMemory"); + + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pFollowRootOffset, m_FollowHairRootOffsetBuffer, + offsetInUploadBuffer, bufferDesc.size); + + VkBufferViewCreateInfo desc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + desc.format = VK_FORMAT_R32G32B32A32_SFLOAT; + desc.range = m_HairAsset.m_NumTotalHairStrands * 4 * sizeof(float); + desc.buffer = m_FollowHairRootOffsetBuffer; + AMD_CHECKED_VULKAN_CALL( + vkCreateBufferView(pvkDevice, &desc, nullptr, &m_FollowHairRootOffsetView)); + markerCallbacks.nameObject(m_FollowHairRootOffsetView, "FollowHairRootOffsetView"); + } + + // -------------------------------------------- + // m_GlobalRotationsUAB & m_GlobalRotationsUAV + //--------------------------------------------- + { + VkBufferCreateInfo bufferDescUA{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDescUA.size = m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4); + bufferDescUA.usage = + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + AMD_CHECKED_VULKAN_CALL( + vkCreateBuffer(pvkDevice, &bufferDescUA, nullptr, &m_GlobalRotationsBuffer)); + markerCallbacks.nameObject(m_GlobalRotationsBuffer, "GlobalRotationsBuffer"); + m_GlobalRotationsMemory = allocBufferMemory(pvkDevice, m_GlobalRotationsBuffer, + memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_GlobalRotationsMemory, "GlobalRotationsMemory"); + + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pGlobalRotations, m_GlobalRotationsBuffer, + offsetInUploadBuffer, bufferDescUA.size); + + VkBufferViewCreateInfo sbUAVDesc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + sbUAVDesc.range = m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4); + sbUAVDesc.format = VK_FORMAT_R32G32B32A32_SFLOAT; + sbUAVDesc.buffer = m_GlobalRotationsBuffer; + AMD_CHECKED_VULKAN_CALL( + vkCreateBufferView(pvkDevice, &sbUAVDesc, nullptr, &m_GlobalRotationsView)); + markerCallbacks.nameObject(m_GlobalRotationsView, "GlobalRotationsView"); + } + + // -------------------------------------------- + // m_LocalRotationsUAB & m_LocalRotationsUAV + //--------------------------------------------- + { + VkBufferCreateInfo bufferDescUA{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDescUA.size = m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4); + bufferDescUA.usage = + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + AMD_CHECKED_VULKAN_CALL( + vkCreateBuffer(pvkDevice, &bufferDescUA, nullptr, &m_LocalRotationsBuffer)); + markerCallbacks.nameObject(m_LocalRotationsBuffer, "LocalROtationsBuffer"); + m_LocalRotationsMemory = allocBufferMemory(pvkDevice, m_LocalRotationsBuffer, + memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_LocalRotationsMemory, "LocalRotationMemory"); + + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pLocalRotations, m_LocalRotationsBuffer, + offsetInUploadBuffer, bufferDescUA.size); + + VkBufferViewCreateInfo sbUAVDesc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + sbUAVDesc.range = m_HairAsset.m_NumTotalHairVertices * sizeof(XMFLOAT4); + sbUAVDesc.format = VK_FORMAT_R32G32B32A32_SFLOAT; + sbUAVDesc.buffer = m_LocalRotationsBuffer; + // AMD_SAFE_RELEASE(m_LocalRotationsUAV); + // AMD_CHECKED_VULKAN_CALL( + // vkCreateBufferView(pvkDevice, &sbUAVDesc, nullptr, + // &m_LocalRotationsView)); + } + + if (m_HairAsset.m_pMapping != NULL) + { + // ----------------------------------------------- + // m_HairSkinMappingBuffer & m_HairSkinMappingSRV + //------------------------------------------------ + { + // D3D11_SUBRESOURCE_DATA initialData; + + // "flatten" the mapping for one big vertex array + for (int i = 0; i < m_HairAsset.m_NumTotalHairStrands; i++) + { + m_HairAsset.m_pMapping[i].triangle += + sceneMesh->meshOffsets[m_HairAsset.m_pMapping[i].mesh]; + } + + // initialData.pSysMem = m_HairAsset.m_pMapping; + VkBufferCreateInfo bufferDesc{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDesc.size = + m_HairAsset.m_NumTotalHairStrands * sizeof(HairToTriangleMapping); + bufferDesc.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bufferDesc, nullptr, + &m_HairSkinMappingBuffer)); + markerCallbacks.nameObject(m_HairSkinMappingBuffer, "HairSkinMappingBuffer"); + + VkBufferViewCreateInfo desc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + desc.format = VK_FORMAT_UNDEFINED; + desc.range = + m_HairAsset.m_NumTotalHairStrands * sizeof(HairToTriangleMapping); + desc.buffer = m_HairSkinMappingBuffer; + AMD_CHECKED_VULKAN_CALL( + vkCreateBufferView(pvkDevice, &desc, nullptr, &m_HairSkinMappingView)); + markerCallbacks.nameObject(m_HairSkinMappingView, "HairSkinMappingView"); + } + + // -------------------------------------------- + // m_HairTransformsBuffer & m_HairTransformsUAV + //--------------------------------------------- + { + TressFX_HairTransform *pTransforms = + new TressFX_HairTransform[m_HairAsset.m_NumTotalHairStrands]; + for (int i = 0; i < m_HairAsset.m_NumTotalHairStrands; i++) + { + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < 4; k++) + { + if (j == k) + { + pTransforms[i].matrix[j][k] = 1.0f; + } + else + { + pTransforms[i].matrix[j][k] = 0.0f; + } + } + if (j == 3) + { + pTransforms[i].quaternion[j] = 1.0f; + } + else + { + pTransforms[i].quaternion[j] = 0.0f; + } + } + } + + VkBufferCreateInfo bufferDescUA{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDescUA.size = + m_HairAsset.m_NumTotalHairStrands * sizeof(TressFX_HairTransform); + bufferDescUA.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bufferDescUA, nullptr, + &m_HairTransformsBuffer)); + markerCallbacks.nameObject(m_HairTransformsBuffer, "HairTransformsBuffer"); + + VkBufferViewCreateInfo desc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + desc.range = + m_HairAsset.m_NumTotalHairStrands * sizeof(TressFX_HairTransform); + desc.format = VK_FORMAT_UNDEFINED; + desc.buffer = m_HairTransformsBuffer; + AMD_CHECKED_VULKAN_CALL( + vkCreateBufferView(pvkDevice, &desc, nullptr, &m_HairTransformsView)); + markerCallbacks.nameObject(m_HairTransformsView, "HairTransformView"); + + AMD_SAFE_DELETE_ARRAY(pTransforms); + } + } + + if (m_HairAsset.m_pStrandTexCoords != NULL) + { + // ----------------------------------------------- + // m_pStrandTexCoordBuffer & m_pStrandTexCoordSRV + //------------------------------------------------ + { + VkBufferCreateInfo bufferDesc{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufferDesc.size = m_HairAsset.m_NumTotalHairStrands * sizeof(float) * 2; + bufferDesc.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT; + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &bufferDesc, nullptr, + &m_pStrandTexCoordBuffer)); + markerCallbacks.nameObject(m_pStrandTexCoordBuffer, "StrandTexCoordBuffer"); + m_pStrandTexCoordMemory = allocBufferMemory( + pvkDevice, m_pStrandTexCoordBuffer, memProp, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + markerCallbacks.nameObject(m_pStrandTexCoordMemory, "StrandTexCoordMemory"); + + fillInitialData(upload_cmd_buffer, scratchBuffer, uploadBuffer, + m_HairAsset.m_pStrandTexCoords, m_pStrandTexCoordBuffer, + offsetInUploadBuffer, bufferDesc.size); + + VkBufferViewCreateInfo desc{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}; + desc.format = VK_FORMAT_R32G32_SFLOAT; + desc.range = m_HairAsset.m_NumTotalHairStrands * sizeof(float) * 2; + desc.buffer = m_pStrandTexCoordBuffer; + // AMD_SAFE_RELEASE(m_pStrandTexCoordSRV); + AMD_CHECKED_VULKAN_CALL( + vkCreateBufferView(pvkDevice, &desc, nullptr, &m_pStrandTexCoordView)); + markerCallbacks.nameObject(m_pStrandTexCoordView, "StrandTexCoordView"); + } + } + vkUnmapMemory(pvkDevice, scratchMemory); + return VK_SUCCESS; +} + +VkResult TressFXMesh::AllocateDescriptorsSets( + VkDevice pvkDevice, VkDescriptorSetLayout GlobalConstraintsSetLayout, + VkDescriptorSetLayout LocalConstraintsSetLayout, + VkDescriptorSetLayout LenghtWindTangentSetLayout, + VkDescriptorSetLayout PrepareFollowHairSetLayout, + VkDescriptorSetLayout UpdateFollowHaitSetLayout, + VkDescriptorSetLayout computeTangentSetLayout, VkDescriptorSetLayout Pass1SetLayout, + VkDescriptorSetLayout ShadowSetLayout) +{ + VkDescriptorPoolSize poolSizes[] = {{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 17}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 11}}; + VkDescriptorPoolCreateInfo info{VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO}; + info.maxSets = 8; + info.poolSizeCount = AMD_ARRAY_SIZE(poolSizes); + info.pPoolSizes = poolSizes; + VkResult vr; + AMD_CHECKED_VULKAN_CALL(vkCreateDescriptorPool(pvkDevice, &info, nullptr, &m_descriptorPool)); + + const VkDescriptorSetLayout setLayouts[] = {GlobalConstraintsSetLayout, + LocalConstraintsSetLayout, + LenghtWindTangentSetLayout, + PrepareFollowHairSetLayout, + UpdateFollowHaitSetLayout, + computeTangentSetLayout, + Pass1SetLayout, + ShadowSetLayout}; + VkDescriptorSetAllocateInfo allocateInfo{ + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO}; + allocateInfo.descriptorPool = m_descriptorPool; + allocateInfo.descriptorSetCount = AMD_ARRAY_SIZE(setLayouts); + allocateInfo.pSetLayouts = setLayouts; + + VkDescriptorSet sets[AMD_ARRAY_SIZE(setLayouts)]{}; + + AMD_CHECKED_VULKAN_CALL(vkAllocateDescriptorSets(pvkDevice, &allocateInfo, sets)); + m_GlobalConstraintsSet = sets[0]; + m_LocalConstraintsSet = sets[1]; + m_LenghtWindCollisionSet = sets[2]; + m_PrepareFollowHairSet = sets[3]; + m_UpdateFollowHairSet = sets[4]; + m_ComputeTangentSet = sets[5]; + m_pass1_set = sets[6]; + m_shadow_pass_set = sets[7]; + + VkDescriptorBufferInfo positionInfo{m_HairVertexPositionsBuffer, 0, + m_HairAsset.m_NumTotalHairVertices * 4 * + sizeof(float)}; + VkDescriptorBufferInfo prevPositionInfo{m_HairVertexPositionsPrevBuffer, 0, + m_HairAsset.m_NumTotalHairVertices * 4 * + sizeof(float)}; + VkDescriptorBufferInfo tangentInfo{m_HairVertexTangentsBuffer, 0, + m_HairAsset.m_NumTotalHairVertices * 4 * + sizeof(float)}; + + VkWriteDescriptorSet writeDescriptorSets[] = { + getWriteDescriptor(m_GlobalConstraintsSet, IDSRV_HAIR_VERTEX_POSITIONS, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &positionInfo), + getWriteDescriptor(m_GlobalConstraintsSet, IDSRV_HAIR_PREVIOUS_VERTEX_POSITIONS, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &prevPositionInfo), + getWriteDescriptor(m_GlobalConstraintsSet, IDSRV_HAIR_VERTEX_INITIAL_POSITIONS, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_InitialHairPositionsView), + getWriteDescriptor(m_GlobalConstraintsSet, IDSRV_HAIR_STRAND_TYPE, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairStrandTypeView), + + getWriteDescriptor(m_LocalConstraintsSet, IDSRV_HAIR_VERTEX_POSITIONS, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &positionInfo), + getWriteDescriptor(m_LocalConstraintsSet, IDSRV_HAIR_STRAND_TYPE, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairStrandTypeView), + getWriteDescriptor(m_LocalConstraintsSet, IDSRV_HAIR_GLOBAL_ROTATION, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_GlobalRotationsView), + getWriteDescriptor(m_LocalConstraintsSet, IDSRV_HAIR_LOCAL_REF_VEC, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairRefVecsInLocalFrameView), + + getWriteDescriptor(m_ComputeTangentSet, IDSRV_HAIR_VERTEX_POSITIONS, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairVertexPositionsView), + getWriteDescriptor(m_ComputeTangentSet, IDSRV_HAIR_STRAND_TYPE, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairStrandTypeView), + getWriteDescriptor(m_ComputeTangentSet, IDSRV_HAIR_TANGENTS, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &tangentInfo), + + getWriteDescriptor(m_LenghtWindCollisionSet, IDSRV_HAIR_VERTEX_POSITIONS, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &positionInfo), + getWriteDescriptor(m_LenghtWindCollisionSet, IDSRV_HAIR_STRAND_TYPE, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairStrandTypeView), + getWriteDescriptor(m_LenghtWindCollisionSet, IDSRV_HAIR_LENGTH, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, &m_HairRestLengthSRV), + + getWriteDescriptor(m_PrepareFollowHairSet, IDSRV_HAIR_VERTEX_POSITIONS, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairVertexPositionsView), + getWriteDescriptor(m_PrepareFollowHairSet, IDSRV_HAIR_PREVIOUS_VERTEX_POSITIONS, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &prevPositionInfo), + getWriteDescriptor(m_PrepareFollowHairSet, IDSRV_HAIR_STRAND_TYPE, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairStrandTypeView), + + getWriteDescriptor(m_UpdateFollowHairSet, IDSRV_HAIR_VERTEX_POSITIONS, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &positionInfo), + getWriteDescriptor(m_UpdateFollowHairSet, IDSRV_HAIR_STRAND_TYPE, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairStrandTypeView), + getWriteDescriptor(m_UpdateFollowHairSet, IDSRV_HAIR_ROOT_OFFSET, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_FollowHairRootOffsetView), + + getWriteDescriptor(m_pass1_set, IDSRV_HAIR_VERTEX_POSITIONS, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairVertexPositionsView), + getWriteDescriptor(m_pass1_set, IDSRV_HAIR_TANGENTS, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairVertexTangentsView), + getWriteDescriptor(m_pass1_set, IDSRV_HAIR_THICKNESSES, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_pThicknessCoeffsView), + + getWriteDescriptor(m_shadow_pass_set, IDSRV_HAIR_VERTEX_POSITIONS, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + &m_HairVertexPositionsView), + }; + + vkUpdateDescriptorSets(pvkDevice, AMD_ARRAY_SIZE(writeDescriptorSets), + writeDescriptorSets, 0, nullptr); + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// OnDestroy +// +// Called when the D3D device is being destroyed. +// +//-------------------------------------------------------------------------------------- +void TressFXMesh::OnDestroy() +{ + AMD_SAFE_RELEASE(m_pTriangleIndexBuffer, vkDestroyBuffer, m_pvkDevice); + + AMD_SAFE_RELEASE(m_pIndexBuffer, vkDestroyBuffer, m_pvkDevice); + + AMD_SAFE_RELEASE(m_pThicknessCoeffsView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_pThicknessCoeffsBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_pThicknessIndexTriangleIndexMemory, vkFreeMemory, m_pvkDevice); + + // compute shader variables + AMD_SAFE_RELEASE(m_HairVertexPositionsView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairVertexPositionsBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairVertexPositionsMemory, vkFreeMemory, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairVertexPositionsPrevView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairVertexPositionsPrevBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairVertexPositionsPrevMemory, vkFreeMemory, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairVertexTangentsView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairVertexTangentsBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairVertexTangentsMemory, vkFreeMemory, m_pvkDevice); + + AMD_SAFE_RELEASE(m_HairStrandTypeView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairStrandTypeBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairStrandTypeMemory, vkFreeMemory, m_pvkDevice); + + // vertex buffers + AMD_SAFE_RELEASE(m_HairRestLengthSRV, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairLengthBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairLengthMemory, vkFreeMemory, m_pvkDevice); + + AMD_SAFE_RELEASE(m_InitialHairPositionsView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_InitialHairPositionsBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_InitialHairPositionsMemory, vkFreeMemory, m_pvkDevice); + + AMD_SAFE_RELEASE(m_HairRefVecsInLocalFrameView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairRefVectorsBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairRefVectorsMemory, vkFreeMemory, m_pvkDevice); + + AMD_SAFE_RELEASE(m_FollowHairRootOffsetView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_FollowHairRootOffsetBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_FollowHairRootOffsetMemory, vkFreeMemory, m_pvkDevice); + + AMD_SAFE_RELEASE(m_GlobalRotationsView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_GlobalRotationsBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_GlobalRotationsMemory, vkFreeMemory, m_pvkDevice); + + AMD_SAFE_RELEASE(m_LocalRotationsView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_LocalRotationsBuffer, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_LocalRotationsMemory, vkFreeMemory, m_pvkDevice); + + AMD_SAFE_RELEASE(m_HairSkinMappingView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairSkinMappingBuffer, vkDestroyBuffer, m_pvkDevice); + // AMD_SAFE_RELEASE(m_HairSkinMappingMemory, vkFreeMemory, m_pvkDevice); + + AMD_SAFE_RELEASE(m_HairTransformsView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_HairTransformsBuffer, vkDestroyBuffer, m_pvkDevice); + // AMD_SAFE_RELEASE(m_HairTransformsMemory, vkFreeMemory, m_pvkDevice); + + AMD_SAFE_RELEASE(m_pStrandTexCoordView, vkDestroyBufferView, m_pvkDevice); + AMD_SAFE_RELEASE(m_pStrandTexCoordBuffer, vkDestroyBuffer, m_pvkDevice); + // AMD_SAFE_RELEASE(m_pStrandTexCoordMemory, vkFreeMemory, m_pvkDevice); + + // AMD_SAFE_RELEASE(m_pHairTextureSRV); + AMD_SAFE_RELEASE(m_descriptorPool, vkDestroyDescriptorPool, m_pvkDevice); + + DestroyAsset(); +} + +//-------------------------------------------------------------------------------------- +// +// Deserialize +// +// Converts the hair blob from a serialized stream to a TressFXAsset structure. +// +//-------------------------------------------------------------------------------------- +bool TressFXMesh::Deserialize(TressFX_HairBlob *pHairBlob) +{ + string str; + str.assign((char *)pHairBlob->pHair, pHairBlob->size); + stringbuf buffer; + buffer.str(str); + + buffer.sgetn((char *)&m_HairAsset.m_NumTotalHairVertices, sizeof(int)); + buffer.sgetn((char *)&m_HairAsset.m_NumTotalHairStrands, sizeof(int)); + buffer.sgetn((char *)&m_HairAsset.m_NumOfVerticesInStrand, sizeof(int)); + buffer.sgetn((char *)&m_HairAsset.m_NumGuideHairVertices, sizeof(int)); + buffer.sgetn((char *)&m_HairAsset.m_NumGuideHairStrands, sizeof(int)); + buffer.sgetn((char *)&m_HairAsset.m_NumFollowHairsPerGuideHair, sizeof(int)); + buffer.sgetn((char *)&m_HairAsset.m_TipSeparationFactor, sizeof(float)); + buffer.sgetn((char *)&m_HairAsset.m_NumPerStrandTexCoords, sizeof(int)); + buffer.sgetn((char *)&m_HairAsset.m_NumPerVertexColors, sizeof(int)); + buffer.sgetn((char *)&m_HairAsset.m_NumPerVertexTexCoords, sizeof(int)); + buffer.sgetn((char *)&m_HairAsset.m_NumHairToTriangleMappings, sizeof(int)); + + m_HairAsset.m_pHairStrandType = new int[m_HairAsset.m_NumTotalHairStrands]; + buffer.sgetn((char *)m_HairAsset.m_pHairStrandType, + m_HairAsset.m_NumTotalHairStrands * sizeof(int)); + + m_HairAsset.m_pRefVectors = new DirectX::XMFLOAT4[m_HairAsset.m_NumTotalHairVertices]; + buffer.sgetn((char *)m_HairAsset.m_pRefVectors, + m_HairAsset.m_NumTotalHairVertices * sizeof(DirectX::XMFLOAT4)); + + m_HairAsset.m_pGlobalRotations = + new DirectX::XMFLOAT4[m_HairAsset.m_NumTotalHairVertices]; + buffer.sgetn((char *)m_HairAsset.m_pGlobalRotations, + m_HairAsset.m_NumTotalHairVertices * sizeof(DirectX::XMFLOAT4)); + + m_HairAsset.m_pLocalRotations = + new DirectX::XMFLOAT4[m_HairAsset.m_NumTotalHairVertices]; + buffer.sgetn((char *)m_HairAsset.m_pLocalRotations, + m_HairAsset.m_NumTotalHairVertices * sizeof(DirectX::XMFLOAT4)); + + m_HairAsset.m_pVertices = new DirectX::XMFLOAT4[m_HairAsset.m_NumTotalHairVertices]; + buffer.sgetn((char *)m_HairAsset.m_pVertices, + m_HairAsset.m_NumTotalHairVertices * sizeof(DirectX::XMFLOAT4)); + + m_HairAsset.m_pTangents = new DirectX::XMFLOAT4[m_HairAsset.m_NumTotalHairVertices]; + buffer.sgetn((char *)m_HairAsset.m_pTangents, + m_HairAsset.m_NumTotalHairVertices * sizeof(DirectX::XMFLOAT4)); + + m_HairAsset.m_pTriangleVertices = + new StrandVertex[m_HairAsset.m_NumTotalHairVertices]; + buffer.sgetn((char *)m_HairAsset.m_pTriangleVertices, + m_HairAsset.m_NumTotalHairVertices * sizeof(StrandVertex)); + + m_HairAsset.m_pThicknessCoeffs = new float[m_HairAsset.m_NumTotalHairVertices]; + buffer.sgetn((char *)m_HairAsset.m_pThicknessCoeffs, + m_HairAsset.m_NumTotalHairVertices * sizeof(float)); + + m_HairAsset.m_pFollowRootOffset = + new DirectX::XMFLOAT4[m_HairAsset.m_NumTotalHairStrands]; + buffer.sgetn((char *)m_HairAsset.m_pFollowRootOffset, + m_HairAsset.m_NumTotalHairStrands * sizeof(XMFLOAT4)); + + m_HairAsset.m_pRestLengths = new float[m_HairAsset.m_NumTotalHairVertices]; + buffer.sgetn((char *)m_HairAsset.m_pRestLengths, + m_HairAsset.m_NumTotalHairVertices * sizeof(float)); + + buffer.sgetn((char *)&m_HairAsset.m_bSphere, sizeof(BSphere)); + + m_HairAsset.m_TriangleIndices.clear(); + + int size; + buffer.sgetn((char *)&size, sizeof(int)); + int *pIndices = new int[size]; + buffer.sgetn((char *)pIndices, size * sizeof(int)); + for (int i = 0; i < size; i++) + { + m_HairAsset.m_TriangleIndices.push_back(pIndices[i]); + } + AMD_SAFE_DELETE_ARRAY(pIndices); + + m_HairAsset.m_LineIndices.clear(); + buffer.sgetn((char *)&size, sizeof(int)); + pIndices = new int[size]; + buffer.sgetn((char *)pIndices, size * sizeof(int)); + for (int i = 0; i < size; i++) + { + m_HairAsset.m_LineIndices.push_back(pIndices[i]); + } + AMD_SAFE_DELETE_ARRAY(pIndices); + + if (m_HairAsset.m_NumPerStrandTexCoords) + { + m_HairAsset.m_pStrandTexCoords = + new DirectX::XMFLOAT2[m_HairAsset.m_NumTotalHairStrands]; + buffer.sgetn((char *)m_HairAsset.m_pStrandTexCoords, + m_HairAsset.m_NumTotalHairStrands * sizeof(DirectX::XMFLOAT2)); + } + else + { + m_HairAsset.m_pStrandTexCoords = NULL; + } + + if (m_HairAsset.m_NumPerVertexColors) + { + m_HairAsset.m_pVertexColors = + new DirectX::XMFLOAT4[m_HairAsset.m_NumTotalHairVertices]; + buffer.sgetn((char *)m_HairAsset.m_pVertexColors, + m_HairAsset.m_NumTotalHairVertices * sizeof(DirectX::XMFLOAT4)); + } + else + { + m_HairAsset.m_pVertexColors = NULL; + } + + if (m_HairAsset.m_NumPerVertexTexCoords) + { + m_HairAsset.m_pVertexTexCoords = + new DirectX::XMFLOAT2[m_HairAsset.m_NumTotalHairVertices]; + buffer.sgetn((char *)m_HairAsset.m_pVertexTexCoords, + m_HairAsset.m_NumTotalHairVertices * sizeof(DirectX::XMFLOAT2)); + } + else + { + m_HairAsset.m_pVertexTexCoords = NULL; + } + + if (m_HairAsset.m_NumHairToTriangleMappings > 0) + { + m_HairAsset.m_pMapping = + new HairToTriangleMapping[m_HairAsset.m_NumTotalHairStrands]; + buffer.sgetn((char *)m_HairAsset.m_pMapping, + m_HairAsset.m_NumTotalHairStrands * sizeof(HairToTriangleMapping)); + } + else + { + m_HairAsset.m_pMapping = NULL; + } + + return true; +} + +//-------------------------------------------------------------------------------------- +// +// Destructor +// +//-------------------------------------------------------------------------------------- +void TressFXMesh::DestroyAsset(void) +{ + m_HairAsset.m_TriangleIndices.clear(); + m_HairAsset.m_LineIndices.clear(); + + if (m_HairAsset.m_pVertices) + { + delete[] m_HairAsset.m_pVertices; + m_HairAsset.m_pVertices = NULL; + } + + if (m_HairAsset.m_pTangents) + { + delete[] m_HairAsset.m_pTangents; + m_HairAsset.m_pTangents = NULL; + } + + if (m_HairAsset.m_pStrandTexCoords) + { + delete[] m_HairAsset.m_pStrandTexCoords; + m_HairAsset.m_pStrandTexCoords = NULL; + } + + if (m_HairAsset.m_pHairStrandType) + { + delete[] m_HairAsset.m_pHairStrandType; + m_HairAsset.m_pHairStrandType = NULL; + } + + if (m_HairAsset.m_pLocalRotations) + { + delete[] m_HairAsset.m_pLocalRotations; + m_HairAsset.m_pLocalRotations = NULL; + } + + if (m_HairAsset.m_pGlobalRotations) + { + delete[] m_HairAsset.m_pGlobalRotations; + m_HairAsset.m_pGlobalRotations = NULL; + } + + if (m_HairAsset.m_pRefVectors) + { + delete[] m_HairAsset.m_pRefVectors; + m_HairAsset.m_pRefVectors = NULL; + } + + if (m_HairAsset.m_pTriangleVertices) + { + delete[] m_HairAsset.m_pTriangleVertices; + m_HairAsset.m_pTriangleVertices = NULL; + } + + if (m_HairAsset.m_pThicknessCoeffs) + { + delete[] m_HairAsset.m_pThicknessCoeffs; + m_HairAsset.m_pThicknessCoeffs = NULL; + } + + if (m_HairAsset.m_pRestLengths) + { + delete[] m_HairAsset.m_pRestLengths; + m_HairAsset.m_pRestLengths = NULL; + } + + if (m_HairAsset.m_pFollowRootOffset) + { + delete[] m_HairAsset.m_pFollowRootOffset; + m_HairAsset.m_pFollowRootOffset = NULL; + } + + if (m_HairAsset.m_pMapping) + { + delete[] m_HairAsset.m_pMapping; + m_HairAsset.m_pMapping = NULL; + } +} + +} // namespace AMD diff --git a/amd_tressfx_vulkan/src/TressFXMeshVulkan.h b/amd_tressfx_vulkan/src/TressFXMeshVulkan.h new file mode 100644 index 0000000..480a29f --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXMeshVulkan.h @@ -0,0 +1,184 @@ +//-------------------------------------------------------------------------------------- +// File: TressFXMesh.h +// +// Hair mesh code +// +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// +//-------------------------------------------------------------------------------------- + +#pragma once +#include "TressFXAsset.h" +#include "Util.h" +#include "UtilVulkan.h" + +namespace AMD +{ + +class TressFXMesh +{ + private: + VkDevice m_pvkDevice; + // private member function + VkResult CreateBufferAndViews(VkDevice pvkDevice, + TressFX_SceneMesh *sceneMesh, + VkPhysicalDeviceMemoryProperties memProperties, + VkCommandBuffer upload_cmd_buffer, + VkBuffer scratchBuffer, + VkDeviceMemory scratchMemory, + size_t &offsetInUploadBuffer, const DebugMarkerPointer& markerCallbacks); + + VkResult AllocateDescriptorsSets(VkDevice pvkDevice, + VkDescriptorSetLayout GlobalConstraintsSetLayout, + VkDescriptorSetLayout LocalConstraintsSetLayout, + VkDescriptorSetLayout LenghtWindTangentSetLayout, + VkDescriptorSetLayout PrepareFollowHairSetLayout, + VkDescriptorSetLayout UpdateFollowHaitSetLayout, + VkDescriptorSetLayout computeTangentSetLayout, + VkDescriptorSetLayout Pass1SetLayout, + VkDescriptorSetLayout ShadowSetLayout); + + VkDescriptorPool m_descriptorPool; + + public: + VkBuffer m_pIndexBuffer; + VkBuffer m_pTriangleIndexBuffer; + VkBuffer m_pThicknessCoeffsBuffer; + // Store thickness, index and triangle index buffer + VkDeviceMemory m_pThicknessIndexTriangleIndexMemory; + VkBufferView m_pThicknessCoeffsView; + int m_TotalIndexCount; + int m_TotalTriangleIndexCount; + TressFXAsset m_HairAsset; + + // Simulation Descriptor Sets + VkDescriptorSet m_GlobalConstraintsSet; + VkDescriptorSet m_LocalConstraintsSet; + VkDescriptorSet m_LenghtWindCollisionSet; + VkDescriptorSet m_ComputeTangentSet; + VkDescriptorSet m_PrepareFollowHairSet; + VkDescriptorSet m_UpdateFollowHairSet; + + // Rendering Descriptor Sets + VkDescriptorSet m_pass1_set; + VkDescriptorSet m_shadow_pass_set; + + // vertex positions + VkBuffer m_HairVertexPositionsBuffer; + VkDeviceMemory m_HairVertexPositionsMemory; + VkBufferView m_HairVertexPositionsView; + + VkBuffer m_HairVertexPositionsPrevBuffer; + VkDeviceMemory m_HairVertexPositionsPrevMemory; + VkBufferView m_HairVertexPositionsPrevView; + + VkBuffer m_InitialHairPositionsBuffer; + VkDeviceMemory m_InitialHairPositionsMemory; + VkBufferView m_InitialHairPositionsView; + + // strand type + VkBuffer m_HairStrandTypeBuffer; + VkDeviceMemory m_HairStrandTypeMemory; + VkBufferView m_HairStrandTypeView; + + // rest length + VkBuffer m_HairLengthBuffer; + VkDeviceMemory m_HairLengthMemory; + VkBufferView m_HairRestLengthSRV; + + // reference vectors + VkBuffer m_HairRefVectorsBuffer; + VkDeviceMemory m_HairRefVectorsMemory; + VkBufferView m_HairRefVecsInLocalFrameView; + + // follow hair root offset + VkBuffer m_FollowHairRootOffsetBuffer; + VkDeviceMemory m_FollowHairRootOffsetMemory; + VkBufferView m_FollowHairRootOffsetView; + + // global and local transforms for each vertex + VkBuffer m_GlobalRotationsBuffer; + VkDeviceMemory m_GlobalRotationsMemory; + VkBufferView m_GlobalRotationsView; + + VkBuffer m_LocalRotationsBuffer; + VkDeviceMemory m_LocalRotationsMemory; + VkBufferView m_LocalRotationsView; + + // vertex tangents + VkBuffer m_HairVertexTangentsBuffer; + VkDeviceMemory m_HairVertexTangentsMemory; + VkBufferView m_HairVertexTangentsView; + + // mapping from hair to skinned mesh + VkBuffer m_HairSkinMappingBuffer; + VkDeviceMemory m_HairSkinMappingMemory; + VkBufferView m_HairSkinMappingView; + + // per-strand transformations for skinning + VkBuffer m_HairTransformsBuffer; + VkDeviceMemory m_HairTransformsMemory; + VkBufferView m_HairTransformsView; + + // per-strand texture coordinates + VkBuffer m_pStrandTexCoordBuffer; + VkDeviceMemory m_pStrandTexCoordMemory; + VkBufferView m_pStrandTexCoordView; + + // hair texture + VkImageView m_pHairTextureSRV; + + // public member functions + TressFXMesh(void); + ~TressFXMesh(void); + + VkResult OnCreate(VkDevice pvkDevice, + TressFX_HairBlob *pHairBlob, + TressFX_SceneMesh *sceneMesh, + VkImageView pTexture, + VkPhysicalDeviceMemoryProperties memProperties, + VkCommandBuffer upload_cmd_buffer, + VkBuffer scratchBuffer, + VkDeviceMemory scratchMemory, + + VkDescriptorSetLayout GlobalConstraintsSetLayout, + + VkDescriptorSetLayout LocalConstraintsSetLayout, + + VkDescriptorSetLayout LenghtWindCollisiontSetLayout, + + VkDescriptorSetLayout PrepareFollowHairSetLayout, + + VkDescriptorSetLayout UpdateFollowHaitSetLayout, + + VkDescriptorSetLayout ComputeTangetSetLayout, + + VkDescriptorSetLayout Pass1SetLayout, + VkDescriptorSetLayout ShadowSetLayout, const DebugMarkerPointer& markerCallbacks); + void OnDestroy(); + + void DestroyAsset(); + + bool Deserialize(TressFX_HairBlob *pHairBlob); +}; + +} // namespace AMD diff --git a/amd_tressfx_vulkan/src/TressFXOpaqueVulkan.cpp b/amd_tressfx_vulkan/src/TressFXOpaqueVulkan.cpp new file mode 100644 index 0000000..441c1e0 --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXOpaqueVulkan.cpp @@ -0,0 +1,238 @@ +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// + +#include "TressFXOpaqueVulkan.h" + +namespace AMD +{ +void TressFX_OpaqueDesc::Initialize(TressFX_Desc &desc, + VkImageView depthTexture, + VkImageView colorTexture, + VkCommandBuffer commandBuffer, + VkDeviceMemory scratchMemory, + VkBuffer scratchBuffer, + size_t &offsetInScratchBuffer, + VkPhysicalDeviceMemoryProperties memProperties) +{ + refCount = 0; + markerCallbacks.init(desc.pvkDevice); + tressFXSimulation.OnCreateDevice(desc.pvkDevice, + &desc.collisionCapsule, + desc.maxConstantBuffers, memProperties, + markerCallbacks); + tressFXRenderer.OnCreateDevice( + desc.pvkDevice, desc.backBufferWidth, desc.backBufferHeight, desc.bShortCutOn, + desc.maxConstantBuffers, memProperties, + depthTexture, colorTexture, commandBuffer, scratchMemory, scratchBuffer, + offsetInScratchBuffer, desc.depthStencilFormat, desc.colorFormat); + refCount++; +} + +void TressFX_OpaqueDesc::Release(VkDevice pvkDevice) +{ + refCount--; + if (refCount <= 0) + { + tressFXRenderer.OnDestroy(); + tressFXSimulation.OnDestroy(pvkDevice); + refCount = 0; + } +} + +bool TressFX_OpaqueDesc::LoadAppendAsset( + TressFX_HairBlob *pRawHairBlob, const TressFX_GuideFollowParams &guideFollowParams, + int groupId) +{ + return tressFXAssetLoader.LoadAppend(pRawHairBlob, guideFollowParams, groupId); +} + +bool TressFX_OpaqueDesc::CreateProcessedAsset( + TressFX_Desc &desc, TressFX_HairBlob **ppHairBlob, TressFX_SceneMesh *sceneMesh, + VkImageView hairTexture, VkPhysicalDeviceMemoryProperties memProperties, + VkCommandBuffer uploadCmdBuffer, VkBuffer scratchBuffer, VkDeviceMemory scratchMemory) +{ + tressFXAssetLoader.GenerateFollowHairs(); + tressFXAssetLoader.ProcessVertices(); + + if (desc.tressFXHair.pHair != NULL) + { + delete desc.tressFXHair.pHair; + desc.tressFXHair.pHair = NULL; + desc.tressFXHair.size = 0; + } + + tressFXAssetLoader.Serialize(&desc.tressFXHair); + + TressFXMesh *pTressFXMesh = (TressFXMesh *)desc.pTressFXMesh; + if (pTressFXMesh != NULL) + { + delete pTressFXMesh; + } + pTressFXMesh = new TressFXMesh(); + pTressFXMesh->OnCreate(desc.pvkDevice, &desc.tressFXHair, sceneMesh, + hairTexture, + memProperties, uploadCmdBuffer, + scratchBuffer, + scratchMemory, + tressFXSimulation.m_GlobalConstraintsSetLayout, + tressFXSimulation.m_LocalConstraintsSetLayout, + tressFXSimulation.m_LenghtWindTangentSetLayout, + tressFXSimulation.m_PrepareFollowHairSetLayout, + tressFXSimulation.m_UpdateFollowHaitSetLayout, + desc.pOpaque->tressFXSimulation.m_ComputeTangentSetLayout, + tressFXRenderer.m_pass1_hair_set_layout, + tressFXRenderer.m_shadow_pass_hair_set_layout, + desc.pOpaque->markerCallbacks); + + desc.numTotalHairStrands = pTressFXMesh->m_HairAsset.m_NumTotalHairStrands; + desc.numTotalHairVertices = pTressFXMesh->m_HairAsset.m_NumTotalHairVertices; + desc.pTressFXMesh = (void *)pTressFXMesh; + + if (ppHairBlob != NULL) + { + *ppHairBlob = &desc.tressFXHair; + } + + tressFXAssetLoader.Clear(); + + return true; +} + +bool TressFX_OpaqueDesc::Simulate(TressFX_Desc &desc, VkCommandBuffer commandBuffer, + float elapsedTime, uint32_t uniformBufferIndex) +{ + tressFXSimulation.m_pTressFXMesh = (TressFXMesh *)desc.pTressFXMesh; + desc.numTotalHairStrands = + tressFXSimulation.m_pTressFXMesh->m_HairAsset.m_NumTotalHairStrands; + desc.numTotalHairVertices = + tressFXSimulation.m_pTressFXMesh->m_HairAsset.m_NumTotalHairVertices; + tressFXSimulation.SetSimulationParams(desc.simulationParams); + tressfx_vec3 windDir; + windDir.x = desc.simulationParams.windDir.x; + windDir.y = desc.simulationParams.windDir.y; + windDir.z = desc.simulationParams.windDir.z; + VkResult vr = tressFXSimulation.Simulate( + desc.pvkDevice, commandBuffer, elapsedTime, desc.hairParams.density, windDir, + desc.simulationParams.windMag, &desc.modelTransformForHead, + desc.targetFrameRate, desc.bSingleHeadTransform, false, uniformBufferIndex, + markerCallbacks); + + return vr == VK_SUCCESS; +} + +bool TressFX_OpaqueDesc::Begin(TressFX_Desc &desc, uint32_t uniformBufferIndex) +{ + tressFXRenderer.m_pTressFXMesh = (TressFXMesh *)desc.pTressFXMesh; + tressFXSimulation.m_pTressFXMesh = (TressFXMesh *)desc.pTressFXMesh; + desc.numTotalHairStrands = + tressFXSimulation.m_pTressFXMesh->m_HairAsset.m_NumTotalHairStrands; + desc.numTotalHairVertices = + tressFXSimulation.m_pTressFXMesh->m_HairAsset.m_NumTotalHairVertices; + tressFXRenderer.m_hairParams = desc.hairParams; + tressFXRenderer.BeginHairFrame( + desc.pvkDevice, desc.eyePoint, desc.lightPosition, &desc.modelTransformForHead, + &desc.mViewProj, &desc.mViewProjLightFromLibrary, (float)desc.backBufferWidth, + (float)desc.backBufferHeight, desc.bSingleHeadTransform, uniformBufferIndex); + return true; +} + +bool TressFX_OpaqueDesc::RenderShadowMap(TressFX_Desc &desc, + VkCommandBuffer commandBuffer, + uint32_t uniformBufferIndex) +{ + tressFXRenderer.GenerateShadowMap(desc.pvkDevice, + commandBuffer, + desc.hairParams.density, uniformBufferIndex, + markerCallbacks); + desc.pHairShadowMapSRV = tressFXRenderer.GetShadowMapSRV(); + return true; +} + +bool TressFX_OpaqueDesc::RenderHair(TressFX_Desc &desc, VkCommandBuffer commandBuffer, + uint32_t uniformBufferIndex) +{ + if (desc.bShortCutOn) + { + tressFXRenderer.RenderHairShortcut(desc.pvkDevice, + commandBuffer, + desc.backBufferWidth, + desc.backBufferHeight, + uniformBufferIndex, markerCallbacks); + } + else + { + tressFXRenderer.RenderHair(desc.pvkDevice, commandBuffer, + desc.backBufferWidth, + desc.backBufferHeight, uniformBufferIndex, + markerCallbacks); + } + return true; +} + +bool TressFX_OpaqueDesc::End(TressFX_Desc &desc) +{ + tressFXRenderer.EndHairFrame(desc.pvkDevice); + return true; +} + +bool TressFX_OpaqueDesc::Resize(TressFX_Desc &desc, VkPhysicalDeviceMemoryProperties memProperties) +{ + VkResult vr = tressFXRenderer.OnResizedSwapChain( + desc.pvkDevice, desc.backBufferWidth, desc.backBufferHeight, desc.bShortCutOn, + memProperties); + return (vr == VK_SUCCESS); +} + +bool TressFX_OpaqueDesc::GenerateTransforms(TressFX_Desc &desc, + TressFX_SceneMesh &sceneMesh) +{ + (void)desc; + (void)sceneMesh; + /* tressFXSimulation.m_pTressFXMesh = (TressFXMesh *)desc.pTressFXMesh; + desc.numTotalHairStrands = + tressFXSimulation.m_pTressFXMesh->m_HairAsset.m_NumTotalHairStrands; + desc.numTotalHairVertices = + tressFXSimulation.m_pTressFXMesh->m_HairAsset.m_NumTotalHairVertices; + HRESULT hr = tressFXSimulation.GenerateTransforms(desc.pd3dDeviceContext, + sceneMesh, + &desc.pSkinningTransformationsUAV, &desc.modelTransformForHead); + return (hr == S_OK);*/ + return true; +} + +bool TressFX_OpaqueDesc::ApplyRigidTransforms(TressFX_Desc &desc) +{ + (void)desc; + /* tressFXSimulation.m_pTressFXMesh = (TressFXMesh *)desc.pTressFXMesh; + desc.numTotalHairStrands = + tressFXSimulation.m_pTressFXMesh->m_HairAsset.m_NumTotalHairStrands; + desc.numTotalHairVertices = + tressFXSimulation.m_pTressFXMesh->m_HairAsset.m_NumTotalHairVertices; + HRESULT hr = + tressFXSimulation.ApplyTransformGlobally(desc.pd3dDeviceContext, + desc.pSkinningTransformationsUAV, desc.hairParams.density, + desc.bSingleHeadTransform, &desc.modelTransformForHead); + return (hr == S_OK);*/ + return true; +} + +} // namespace AMD diff --git a/amd_tressfx_vulkan/src/TressFXOpaqueVulkan.h b/amd_tressfx_vulkan/src/TressFXOpaqueVulkan.h new file mode 100644 index 0000000..aaa44cc --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXOpaqueVulkan.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// + +#ifndef AMD_TRESSFX_OPAQUE_H +#define AMD_TRESSFX_OPAQUE_H + +#include "TressFXAsset.h" +#include "TressFXMeshVulkan.h" +#include "TressFXRendererVulkan.h" +#include "TressFXSimulationVulkan.h" + +namespace AMD +{ + +struct TressFX_OpaqueDesc +{ + public: + TressFX_OpaqueDesc() : refCount(0) {} + void Initialize(TressFX_Desc &desc, + VkImageView depthTexture, + VkImageView colorTexture, + VkCommandBuffer commandBuffer, + VkDeviceMemory scratchMemory, + VkBuffer scratchBuffer, + size_t &offsetInScratchBuffer, VkPhysicalDeviceMemoryProperties memProperties); + void Release(VkDevice pvkDevice); + + bool LoadAppendAsset(TressFX_HairBlob *pRawHairBlob, + const TressFX_GuideFollowParams &guideFollowParams, int groupId); + bool CreateProcessedAsset(TressFX_Desc &desc, TressFX_HairBlob **ppHairBlob, + TressFX_SceneMesh *sceneMesh, VkImageView hairTexture, + VkPhysicalDeviceMemoryProperties memProperties, + VkCommandBuffer uploadCmdBuffer, VkBuffer scratchBuffer, + VkDeviceMemory scratchMemor); + + bool Begin(TressFX_Desc &desc, uint32_t uniformBufferIndex); + bool End(TressFX_Desc &desc); + bool RenderShadowMap(TressFX_Desc &desc, VkCommandBuffer commandBuffer, + uint32_t uniformBufferIndex); + bool RenderHair(TressFX_Desc &desc, VkCommandBuffer commandBuffer, + uint32_t uniformBufferIndex); + bool Simulate(TressFX_Desc &desc, VkCommandBuffer commandBuffer, float elapsedTime, + uint32_t uniformBufferIndex); + bool GenerateTransforms(TressFX_Desc &desc, TressFX_SceneMesh &sceneMesh); + bool ApplyRigidTransforms(TressFX_Desc &desc); + bool Resize(TressFX_Desc &desc, VkPhysicalDeviceMemoryProperties memProperties); + + TressFXSimulation tressFXSimulation; // Hair simulation class + TressFXRenderer tressFXRenderer; // Hair rendering class + DebugMarkerPointer markerCallbacks; + private: + TressFXAssetLoader tressFXAssetLoader; // Hair asset loading class + int refCount; // reference count - delete allocations when 0 + TressFX_OpaqueDesc(const TressFX_OpaqueDesc&) {} + TressFX_OpaqueDesc& operator=(const TressFX_OpaqueDesc&) {} +}; + +} // namespace AMD + +#endif diff --git a/amd_tressfx_vulkan/src/TressFXPrecompiledShadersVulkan.h b/amd_tressfx_vulkan/src/TressFXPrecompiledShadersVulkan.h new file mode 100644 index 0000000..7f680f6 --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXPrecompiledShadersVulkan.h @@ -0,0 +1,49399 @@ +#include +const std::vector hair_shadow_vertex = {119734787, +65536, +524289, +41, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +458767, +0, +4, +1852399981, +0, +10, +28, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +655364, +1197427783, +1279741775, +1885560645, +1953718128, +1600482425, +1701734764, +1919509599, +1769235301, +25974, +524292, +1197427783, +1279741775, +1852399429, +1685417059, +1768185701, +1952671090, +6649449, +262149, +4, +1852399981, +0, +393221, +8, +1348430951, +1700164197, +2019914866, +0, +393222, +8, +0, +1348430951, +1953067887, +7237481, +196613, +10, +0, +327685, +15, +1936617283, +1953390964, +115, +393222, +15, +0, +1466785639, +1684828783, +0, +393222, +15, +1, +1450008423, +1350002025, +6975346, +458758, +15, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +15, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +15, +4, +1165385575, +25977, +327686, +15, +5, +1986420583, +7761734, +524294, +15, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +15, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +15, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +15, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +15, +10, +1632460647, +1633045364, +6649196, +458758, +15, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +15, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +15, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +15, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +15, +15, +1767333735, +2053722990, +101, +458758, +15, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +15, +17, +1415733095, +1416522088, +28777, +458758, +15, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +15, +19, +1181114215, +1766617697, +7628903, +393222, +15, +20, +1416191847, +1399350117, +77, +458758, +15, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +15, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +15, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +15, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +15, +25, +1214668647, +1265789281, +12915, +393222, +15, +26, +1214668647, +1165125985, +12920, +589830, +15, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +17, +0, +524293, +25, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +393221, +28, +1449094247, +1702130277, +1684949368, +30821, +327752, +8, +0, +11, +0, +196679, +8, +2, +262216, +15, +0, +5, +327752, +15, +0, +35, +0, +327752, +15, +0, +7, +16, +262216, +15, +1, +5, +327752, +15, +1, +35, +64, +327752, +15, +1, +7, +16, +262216, +15, +2, +5, +327752, +15, +2, +35, +128, +327752, +15, +2, +7, +16, +262216, +15, +3, +5, +327752, +15, +3, +35, +192, +327752, +15, +3, +7, +16, +327752, +15, +4, +35, +256, +327752, +15, +5, +35, +268, +327752, +15, +6, +35, +272, +327752, +15, +7, +35, +288, +327752, +15, +8, +35, +304, +327752, +15, +9, +35, +320, +327752, +15, +10, +35, +336, +327752, +15, +11, +35, +352, +327752, +15, +12, +35, +356, +327752, +15, +13, +35, +360, +327752, +15, +14, +35, +364, +327752, +15, +15, +35, +368, +327752, +15, +16, +35, +384, +327752, +15, +17, +35, +388, +327752, +15, +18, +35, +392, +327752, +15, +19, +35, +396, +327752, +15, +20, +35, +400, +327752, +15, +21, +35, +404, +327752, +15, +22, +35, +408, +327752, +15, +23, +35, +412, +327752, +15, +24, +35, +416, +327752, +15, +25, +35, +420, +327752, +15, +26, +35, +424, +262216, +15, +27, +5, +327752, +15, +27, +35, +432, +327752, +15, +27, +7, +16, +196679, +15, +2, +262215, +17, +34, +0, +262215, +17, +33, +16, +262215, +25, +34, +1, +262215, +25, +33, +7, +262215, +28, +11, +42, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +196638, +8, +7, +262176, +9, +3, +8, +262203, +9, +10, +3, +262165, +11, +32, +1, +262187, +11, +12, +0, +262168, +13, +7, +4, +262167, +14, +6, +3, +1966110, +15, +13, +13, +13, +13, +14, +6, +7, +7, +7, +7, +7, +6, +6, +6, +6, +7, +6, +6, +6, +6, +11, +11, +11, +11, +6, +6, +6, +13, +262176, +16, +2, +15, +262203, +16, +17, +2, +262187, +11, +18, +3, +262176, +19, +2, +13, +589849, +22, +6, +5, +0, +0, +0, +1, +0, +196635, +23, +22, +262176, +24, +0, +23, +262203, +24, +25, +0, +262176, +27, +1, +11, +262203, +27, +28, +1, +262187, +6, +33, +1065353216, +262176, +39, +3, +7, +327734, +2, +4, +0, +3, +131320, +5, +327745, +19, +20, +17, +18, +262205, +13, +21, +20, +262205, +23, +26, +25, +262205, +11, +29, +28, +262244, +22, +30, +26, +327775, +7, +31, +30, +29, +524367, +14, +32, +31, +31, +0, +1, +2, +327761, +6, +34, +32, +0, +327761, +6, +35, +32, +1, +327761, +6, +36, +32, +2, +458832, +7, +37, +34, +35, +36, +33, +327825, +7, +38, +21, +37, +327745, +39, +40, +10, +12, +196670, +40, +38, +65789, +65592, +}; +const std::vector hair_shadow_fragment = {119734787, +65536, +524289, +6, +0, +131089, +1, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +327695, +4, +4, +1852399981, +0, +196624, +4, +7, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +262149, +4, +1852399981, +0, +131091, +2, +196641, +3, +2, +327734, +2, +4, +0, +3, +131320, +5, +65789, +65592, +}; +const std::vector render_hair_vertex = {119734787, +65536, +524289, +232, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +720911, +0, +4, +1852399981, +0, +65, +167, +202, +209, +216, +231, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +655364, +1197427783, +1279741775, +1885560645, +1953718128, +1600482425, +1701734764, +1919509599, +1769235301, +25974, +524292, +1197427783, +1279741775, +1852399429, +1685417059, +1768185701, +1952671090, +6649449, +262149, +4, +1852399981, +0, +458757, +11, +1701208403, +1919905375, +1768710509, +1982358906, +3879526, +196613, +10, +6514038, +458757, +17, +1701208403, +1919905375, +1768710509, +1982358906, +3879782, +196613, +16, +6514038, +196613, +20, +7234924, +196613, +40, +7234924, +196613, +57, +118, +524293, +61, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +393221, +65, +1449094247, +1702130277, +1684949368, +30821, +262149, +73, +1735287124, +7630437, +524293, +74, +1632132967, +1700164201, +2019914866, +1735287124, +1937010277, +0, +262149, +81, +1769234802, +111, +327685, +84, +1936617283, +1953390964, +115, +393222, +84, +0, +1466785639, +1684828783, +0, +393222, +84, +1, +1450008423, +1350002025, +6975346, +458758, +84, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +84, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +84, +4, +1165385575, +25977, +327686, +84, +5, +1986420583, +7761734, +524294, +84, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +84, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +84, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +84, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +84, +10, +1632460647, +1633045364, +6649196, +458758, +84, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +84, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +84, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +84, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +84, +15, +1767333735, +2053722990, +101, +458758, +84, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +84, +17, +1415733095, +1416522088, +28777, +458758, +84, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +84, +19, +1181114215, +1766617697, +7628903, +393222, +84, +20, +1416191847, +1399350117, +77, +458758, +84, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +84, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +84, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +84, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +84, +25, +1214668647, +1265789281, +12915, +393222, +84, +26, +1214668647, +1165125985, +12920, +589830, +84, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +86, +0, +524293, +94, +1632132967, +1750364777, +1852531561, +1131639653, +1717986671, +115, +262149, +106, +1751607666, +116, +262149, +116, +1634886000, +109, +327685, +118, +1785688688, +1734963807, +29800, +262149, +129, +1634886000, +109, +393221, +132, +1634760805, +1766876270, +1936483704, +0, +327685, +143, +1919501414, +1701080649, +120, +262149, +153, +1886217588, +0, +393221, +165, +1348430951, +1700164197, +2019914866, +0, +393222, +165, +0, +1348430951, +1953067887, +7237481, +196613, +167, +0, +262149, +202, +1953523044, +104, +262149, +209, +1735287156, +7630437, +262149, +216, +829436016, +0, +327685, +231, +1634890867, +1866687598, +7499628, +262215, +61, +34, +1, +262215, +61, +33, +7, +262215, +65, +11, +42, +262215, +74, +34, +1, +262215, +74, +33, +8, +262216, +84, +0, +5, +327752, +84, +0, +35, +0, +327752, +84, +0, +7, +16, +262216, +84, +1, +5, +327752, +84, +1, +35, +64, +327752, +84, +1, +7, +16, +262216, +84, +2, +5, +327752, +84, +2, +35, +128, +327752, +84, +2, +7, +16, +262216, +84, +3, +5, +327752, +84, +3, +35, +192, +327752, +84, +3, +7, +16, +327752, +84, +4, +35, +256, +327752, +84, +5, +35, +268, +327752, +84, +6, +35, +272, +327752, +84, +7, +35, +288, +327752, +84, +8, +35, +304, +327752, +84, +9, +35, +320, +327752, +84, +10, +35, +336, +327752, +84, +11, +35, +352, +327752, +84, +12, +35, +356, +327752, +84, +13, +35, +360, +327752, +84, +14, +35, +364, +327752, +84, +15, +35, +368, +327752, +84, +16, +35, +384, +327752, +84, +17, +35, +388, +327752, +84, +18, +35, +392, +327752, +84, +19, +35, +396, +327752, +84, +20, +35, +400, +327752, +84, +21, +35, +404, +327752, +84, +22, +35, +408, +327752, +84, +23, +35, +412, +327752, +84, +24, +35, +416, +327752, +84, +25, +35, +420, +327752, +84, +26, +35, +424, +262216, +84, +27, +5, +327752, +84, +27, +35, +432, +327752, +84, +27, +7, +16, +196679, +84, +2, +262215, +86, +34, +0, +262215, +86, +33, +16, +262215, +94, +34, +1, +262215, +94, +33, +6, +327752, +165, +0, +11, +0, +196679, +165, +2, +262215, +202, +30, +0, +262215, +209, +30, +2, +262215, +216, +30, +1, +262215, +231, +30, +3, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +2, +262176, +8, +7, +7, +262177, +9, +7, +8, +262167, +13, +6, +3, +262176, +14, +7, +13, +262177, +15, +13, +14, +262176, +19, +7, +6, +262187, +6, +25, +869711765, +131092, +26, +262187, +6, +35, +0, +327724, +7, +36, +35, +35, +393260, +13, +53, +35, +35, +35, +589849, +58, +6, +5, +0, +0, +0, +1, +0, +196635, +59, +58, +262176, +60, +0, +59, +262203, +60, +61, +0, +262165, +63, +32, +1, +262176, +64, +1, +63, +262203, +64, +65, +1, +262187, +63, +67, +2, +262167, +70, +6, +4, +262203, +60, +74, +0, +262168, +83, +70, +4, +1966110, +84, +83, +83, +83, +83, +13, +6, +70, +70, +70, +70, +70, +6, +6, +6, +6, +70, +6, +6, +6, +6, +63, +63, +63, +63, +6, +6, +6, +83, +262176, +85, +2, +84, +262203, +85, +86, +2, +262187, +63, +87, +17, +262176, +88, +2, +6, +262203, +60, +94, +0, +262165, +100, +32, +0, +262187, +100, +101, +0, +262187, +6, +104, +1065353216, +262187, +63, +109, +4, +262176, +110, +2, +13, +262187, +63, +119, +1, +262176, +120, +2, +83, +262187, +63, +134, +13, +262187, +6, +141, +1060487823, +262187, +6, +150, +3212836864, +262187, +63, +160, +14, +196638, +165, +70, +262176, +166, +3, +165, +262203, +166, +167, +3, +262187, +63, +168, +0, +262176, +177, +3, +70, +262187, +63, +185, +15, +262187, +100, +186, +1, +262187, +100, +195, +3, +262176, +196, +3, +6, +262203, +196, +202, +3, +262187, +100, +203, +2, +262203, +177, +209, +3, +262203, +177, +216, +3, +262203, +177, +231, +3, +327734, +2, +4, +0, +3, +131320, +5, +262203, +14, +57, +7, +262203, +14, +73, +7, +262203, +19, +81, +7, +262203, +19, +82, +7, +262203, +14, +106, +7, +262203, +14, +116, +7, +262203, +8, +118, +7, +262203, +8, +129, +7, +262203, +19, +132, +7, +262203, +19, +133, +7, +262203, +19, +143, +7, +262203, +19, +144, +7, +262203, +14, +153, +7, +262205, +59, +62, +61, +262205, +63, +66, +65, +327815, +63, +68, +66, +67, +262244, +58, +69, +62, +327775, +70, +71, +69, +68, +524367, +13, +72, +71, +71, +0, +1, +2, +196670, +57, +72, +262205, +59, +75, +74, +262205, +63, +76, +65, +327815, +63, +77, +76, +67, +262244, +58, +78, +75, +327775, +70, +79, +78, +77, +524367, +13, +80, +79, +79, +0, +1, +2, +196670, +73, +80, +327745, +88, +89, +86, +87, +262205, +6, +90, +89, +327866, +26, +91, +90, +35, +196855, +93, +0, +262394, +91, +92, +103, +131320, +92, +262205, +59, +95, +94, +262205, +63, +96, +65, +327815, +63, +97, +96, +67, +262244, +58, +98, +95, +327775, +70, +99, +98, +97, +327761, +6, +102, +99, +0, +196670, +82, +102, +131321, +93, +131320, +103, +196670, +82, +104, +131321, +93, +131320, +93, +262205, +6, +105, +82, +196670, +81, +105, +262205, +13, +107, +73, +262205, +13, +108, +57, +327745, +110, +111, +86, +109, +262205, +13, +112, +111, +327811, +13, +113, +108, +112, +393228, +13, +114, +1, +69, +113, +458764, +13, +115, +1, +68, +107, +114, +196670, +116, +115, +327737, +13, +117, +17, +116, +196670, +106, +117, +327745, +120, +121, +86, +119, +262205, +83, +122, +121, +262205, +13, +123, +106, +327761, +6, +124, +123, +0, +327761, +6, +125, +123, +1, +327761, +6, +126, +123, +2, +458832, +70, +127, +124, +125, +126, +35, +327825, +70, +128, +122, +127, +458831, +7, +130, +128, +128, +0, +1, +196670, +129, +130, +327737, +7, +131, +11, +129, +196670, +118, +131, +327745, +88, +135, +86, +134, +262205, +6, +136, +135, +327864, +26, +137, +136, +35, +196855, +139, +0, +262394, +137, +138, +140, +131320, +138, +196670, +133, +35, +131321, +139, +131320, +140, +196670, +133, +141, +131321, +139, +131320, +139, +262205, +6, +142, +133, +196670, +132, +142, +262205, +63, +145, +65, +327819, +63, +146, +145, +67, +327850, +26, +147, +146, +119, +196855, +149, +0, +262394, +147, +148, +151, +131320, +148, +196670, +144, +150, +131321, +149, +131320, +151, +196670, +144, +104, +131321, +149, +131320, +149, +262205, +6, +152, +144, +196670, +143, +152, +262205, +13, +154, +57, +262205, +6, +155, +143, +262205, +13, +156, +106, +327822, +13, +157, +156, +155, +262205, +6, +158, +81, +327822, +13, +159, +157, +158, +327745, +88, +161, +86, +160, +262205, +6, +162, +161, +327822, +13, +163, +159, +162, +327809, +13, +164, +154, +163, +196670, +153, +164, +327745, +120, +169, +86, +119, +262205, +83, +170, +169, +262205, +13, +171, +153, +327761, +6, +172, +171, +0, +327761, +6, +173, +171, +1, +327761, +6, +174, +171, +2, +458832, +70, +175, +172, +173, +174, +104, +327825, +70, +176, +170, +175, +327745, +177, +178, +167, +168, +196670, +178, +176, +327745, +177, +179, +167, +168, +262205, +70, +180, +179, +262205, +6, +181, +143, +262205, +7, +182, +118, +262205, +6, +183, +132, +327822, +7, +184, +182, +183, +393281, +88, +187, +86, +185, +186, +262205, +6, +188, +187, +327760, +7, +189, +188, +188, +327816, +7, +190, +184, +189, +327761, +6, +191, +190, +0, +327761, +6, +192, +190, +1, +458832, +70, +193, +191, +192, +35, +35, +327822, +70, +194, +193, +181, +393281, +196, +197, +167, +168, +195, +262205, +6, +198, +197, +327822, +70, +199, +194, +198, +327809, +70, +200, +180, +199, +327745, +177, +201, +167, +168, +196670, +201, +200, +393281, +196, +204, +167, +168, +203, +262205, +6, +205, +204, +393281, +196, +206, +167, +168, +195, +262205, +6, +207, +206, +327816, +6, +208, +205, +207, +196670, +202, +208, +262205, +13, +210, +73, +262205, +6, +211, +81, +327761, +6, +212, +210, +0, +327761, +6, +213, +210, +1, +327761, +6, +214, +210, +2, +458832, +70, +215, +212, +213, +214, +211, +196670, +209, +215, +262205, +13, +217, +57, +458831, +7, +218, +217, +217, +0, +1, +262205, +59, +219, +61, +262205, +63, +220, +65, +327815, +63, +221, +220, +67, +327808, +63, +222, +221, +119, +262244, +58, +223, +219, +327775, +70, +224, +223, +222, +458831, +7, +225, +224, +224, +0, +1, +327761, +6, +226, +218, +0, +327761, +6, +227, +218, +1, +327761, +6, +228, +225, +0, +327761, +6, +229, +225, +1, +458832, +70, +230, +226, +227, +228, +229, +196670, +216, +230, +65789, +65592, +327734, +7, +11, +0, +9, +196663, +8, +10, +131320, +12, +262203, +19, +20, +7, +262203, +8, +23, +7, +262205, +7, +21, +10, +393228, +6, +22, +1, +66, +21, +196670, +20, +22, +262205, +6, +24, +20, +327870, +26, +27, +24, +25, +196855, +29, +0, +262394, +27, +28, +34, +131320, +28, +262205, +7, +30, +10, +262205, +6, +31, +20, +327760, +7, +32, +31, +31, +327816, +7, +33, +30, +32, +196670, +23, +33, +131321, +29, +131320, +34, +196670, +23, +36, +131321, +29, +131320, +29, +262205, +7, +37, +23, +131326, +37, +65592, +327734, +13, +17, +0, +15, +196663, +14, +16, +131320, +18, +262203, +19, +40, +7, +262203, +14, +43, +7, +262205, +13, +41, +16, +393228, +6, +42, +1, +66, +41, +196670, +40, +42, +262205, +6, +44, +40, +327870, +26, +45, +44, +25, +196855, +47, +0, +262394, +45, +46, +52, +131320, +46, +262205, +13, +48, +16, +262205, +6, +49, +40, +393296, +13, +50, +49, +49, +49, +327816, +13, +51, +48, +50, +196670, +43, +51, +131321, +47, +131320, +52, +196670, +43, +53, +131321, +47, +131320, +47, +262205, +13, +54, +43, +131326, +54, +65592, +}; +const std::vector render_hair_aa_vertex = {119734787, +65536, +524289, +255, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +720911, +0, +4, +1852399981, +0, +65, +204, +233, +237, +244, +254, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +655364, +1197427783, +1279741775, +1885560645, +1953718128, +1600482425, +1701734764, +1919509599, +1769235301, +25974, +524292, +1197427783, +1279741775, +1852399429, +1685417059, +1768185701, +1952671090, +6649449, +262149, +4, +1852399981, +0, +458757, +11, +1701208403, +1919905375, +1768710509, +1982358906, +3879526, +196613, +10, +6514038, +458757, +17, +1701208403, +1919905375, +1768710509, +1982358906, +3879782, +196613, +16, +6514038, +196613, +20, +7234924, +196613, +40, +7234924, +196613, +57, +118, +524293, +61, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +393221, +65, +1449094247, +1702130277, +1684949368, +30821, +262149, +73, +1735287124, +7630437, +524293, +74, +1632132967, +1700164201, +2019914866, +1735287124, +1937010277, +0, +262149, +81, +1769234802, +111, +327685, +84, +1936617283, +1953390964, +115, +393222, +84, +0, +1466785639, +1684828783, +0, +393222, +84, +1, +1450008423, +1350002025, +6975346, +458758, +84, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +84, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +84, +4, +1165385575, +25977, +327686, +84, +5, +1986420583, +7761734, +524294, +84, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +84, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +84, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +84, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +84, +10, +1632460647, +1633045364, +6649196, +458758, +84, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +84, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +84, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +84, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +84, +15, +1767333735, +2053722990, +101, +458758, +84, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +84, +17, +1415733095, +1416522088, +28777, +458758, +84, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +84, +19, +1181114215, +1766617697, +7628903, +393222, +84, +20, +1416191847, +1399350117, +77, +458758, +84, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +84, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +84, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +84, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +84, +25, +1214668647, +1265789281, +12915, +393222, +84, +26, +1214668647, +1165125985, +12920, +589830, +84, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +86, +0, +524293, +94, +1632132967, +1750364777, +1852531561, +1131639653, +1717986671, +115, +262149, +106, +1751607666, +116, +262149, +116, +1634886000, +109, +327685, +118, +1785688688, +1734963807, +29800, +262149, +129, +1634886000, +109, +458757, +133, +1919508840, +1701274693, +1769172816, +1852795252, +12403, +458757, +148, +1919508840, +1701274693, +1769172816, +1852795252, +12659, +393221, +181, +1634760805, +1766876270, +1936483704, +0, +327685, +192, +1919501414, +1701080649, +120, +393221, +202, +1348430951, +1700164197, +2019914866, +0, +393222, +202, +0, +1348430951, +1953067887, +7237481, +196613, +204, +0, +262149, +233, +1953523044, +104, +262149, +237, +1735287156, +7630437, +262149, +244, +829436016, +0, +327685, +254, +1634890867, +1866687598, +7499628, +262215, +61, +34, +1, +262215, +61, +33, +7, +262215, +65, +11, +42, +262215, +74, +34, +1, +262215, +74, +33, +8, +262216, +84, +0, +5, +327752, +84, +0, +35, +0, +327752, +84, +0, +7, +16, +262216, +84, +1, +5, +327752, +84, +1, +35, +64, +327752, +84, +1, +7, +16, +262216, +84, +2, +5, +327752, +84, +2, +35, +128, +327752, +84, +2, +7, +16, +262216, +84, +3, +5, +327752, +84, +3, +35, +192, +327752, +84, +3, +7, +16, +327752, +84, +4, +35, +256, +327752, +84, +5, +35, +268, +327752, +84, +6, +35, +272, +327752, +84, +7, +35, +288, +327752, +84, +8, +35, +304, +327752, +84, +9, +35, +320, +327752, +84, +10, +35, +336, +327752, +84, +11, +35, +352, +327752, +84, +12, +35, +356, +327752, +84, +13, +35, +360, +327752, +84, +14, +35, +364, +327752, +84, +15, +35, +368, +327752, +84, +16, +35, +384, +327752, +84, +17, +35, +388, +327752, +84, +18, +35, +392, +327752, +84, +19, +35, +396, +327752, +84, +20, +35, +400, +327752, +84, +21, +35, +404, +327752, +84, +22, +35, +408, +327752, +84, +23, +35, +412, +327752, +84, +24, +35, +416, +327752, +84, +25, +35, +420, +327752, +84, +26, +35, +424, +262216, +84, +27, +5, +327752, +84, +27, +35, +432, +327752, +84, +27, +7, +16, +196679, +84, +2, +262215, +86, +34, +0, +262215, +86, +33, +16, +262215, +94, +34, +1, +262215, +94, +33, +6, +327752, +202, +0, +11, +0, +196679, +202, +2, +262215, +233, +30, +0, +262215, +237, +30, +2, +262215, +244, +30, +1, +262215, +254, +30, +3, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +2, +262176, +8, +7, +7, +262177, +9, +7, +8, +262167, +13, +6, +3, +262176, +14, +7, +13, +262177, +15, +13, +14, +262176, +19, +7, +6, +262187, +6, +25, +869711765, +131092, +26, +262187, +6, +35, +0, +327724, +7, +36, +35, +35, +393260, +13, +53, +35, +35, +35, +589849, +58, +6, +5, +0, +0, +0, +1, +0, +196635, +59, +58, +262176, +60, +0, +59, +262203, +60, +61, +0, +262165, +63, +32, +1, +262176, +64, +1, +63, +262203, +64, +65, +1, +262187, +63, +67, +2, +262167, +70, +6, +4, +262203, +60, +74, +0, +262168, +83, +70, +4, +1966110, +84, +83, +83, +83, +83, +13, +6, +70, +70, +70, +70, +70, +6, +6, +6, +6, +70, +6, +6, +6, +6, +63, +63, +63, +63, +6, +6, +6, +83, +262176, +85, +2, +84, +262203, +85, +86, +2, +262187, +63, +87, +17, +262176, +88, +2, +6, +262203, +60, +94, +0, +262165, +100, +32, +0, +262187, +100, +101, +0, +262187, +6, +104, +1065353216, +262187, +63, +109, +4, +262176, +110, +2, +13, +262187, +63, +119, +1, +262176, +120, +2, +83, +262176, +132, +7, +70, +262187, +63, +139, +14, +262187, +100, +171, +3, +262187, +63, +183, +13, +262187, +6, +190, +1060487823, +262187, +6, +199, +3212836864, +196638, +202, +70, +262176, +203, +3, +202, +262203, +203, +204, +3, +262187, +63, +205, +0, +262187, +63, +219, +15, +262187, +100, +220, +1, +262176, +230, +3, +70, +262176, +232, +3, +6, +262203, +232, +233, +3, +262187, +100, +234, +2, +262203, +230, +237, +3, +262203, +230, +244, +3, +262203, +230, +254, +3, +327734, +2, +4, +0, +3, +131320, +5, +262203, +14, +57, +7, +262203, +14, +73, +7, +262203, +19, +81, +7, +262203, +19, +82, +7, +262203, +14, +106, +7, +262203, +14, +116, +7, +262203, +8, +118, +7, +262203, +8, +129, +7, +262203, +132, +133, +7, +262203, +132, +148, +7, +262203, +19, +181, +7, +262203, +19, +182, +7, +262203, +19, +192, +7, +262203, +19, +193, +7, +262203, +132, +206, +7, +262205, +59, +62, +61, +262205, +63, +66, +65, +327815, +63, +68, +66, +67, +262244, +58, +69, +62, +327775, +70, +71, +69, +68, +524367, +13, +72, +71, +71, +0, +1, +2, +196670, +57, +72, +262205, +59, +75, +74, +262205, +63, +76, +65, +327815, +63, +77, +76, +67, +262244, +58, +78, +75, +327775, +70, +79, +78, +77, +524367, +13, +80, +79, +79, +0, +1, +2, +196670, +73, +80, +327745, +88, +89, +86, +87, +262205, +6, +90, +89, +327866, +26, +91, +90, +35, +196855, +93, +0, +262394, +91, +92, +103, +131320, +92, +262205, +59, +95, +94, +262205, +63, +96, +65, +327815, +63, +97, +96, +67, +262244, +58, +98, +95, +327775, +70, +99, +98, +97, +327761, +6, +102, +99, +0, +196670, +82, +102, +131321, +93, +131320, +103, +196670, +82, +104, +131321, +93, +131320, +93, +262205, +6, +105, +82, +196670, +81, +105, +262205, +13, +107, +73, +262205, +13, +108, +57, +327745, +110, +111, +86, +109, +262205, +13, +112, +111, +327811, +13, +113, +108, +112, +393228, +13, +114, +1, +69, +113, +458764, +13, +115, +1, +68, +107, +114, +196670, +116, +115, +327737, +13, +117, +17, +116, +196670, +106, +117, +327745, +120, +121, +86, +119, +262205, +83, +122, +121, +262205, +13, +123, +106, +327761, +6, +124, +123, +0, +327761, +6, +125, +123, +1, +327761, +6, +126, +123, +2, +458832, +70, +127, +124, +125, +126, +35, +327825, +70, +128, +122, +127, +458831, +7, +130, +128, +128, +0, +1, +196670, +129, +130, +327737, +7, +131, +11, +129, +196670, +118, +131, +262205, +13, +134, +57, +262205, +13, +135, +106, +327822, +13, +136, +135, +104, +262205, +6, +137, +81, +327822, +13, +138, +136, +137, +327745, +88, +140, +86, +139, +262205, +6, +141, +140, +327822, +13, +142, +138, +141, +327811, +13, +143, +134, +142, +327761, +6, +144, +143, +0, +327761, +6, +145, +143, +1, +327761, +6, +146, +143, +2, +458832, +70, +147, +144, +145, +146, +104, +196670, +133, +147, +262205, +13, +149, +57, +262205, +13, +150, +106, +327822, +13, +151, +150, +104, +262205, +6, +152, +81, +327822, +13, +153, +151, +152, +327745, +88, +154, +86, +139, +262205, +6, +155, +154, +327822, +13, +156, +153, +155, +327809, +13, +157, +149, +156, +327761, +6, +158, +157, +0, +327761, +6, +159, +157, +1, +327761, +6, +160, +157, +2, +458832, +70, +161, +158, +159, +160, +104, +196670, +148, +161, +327745, +120, +162, +86, +119, +262205, +83, +163, +162, +262205, +70, +164, +133, +327825, +70, +165, +163, +164, +196670, +133, +165, +327745, +120, +166, +86, +119, +262205, +83, +167, +166, +262205, +70, +168, +148, +327825, +70, +169, +167, +168, +196670, +148, +169, +262205, +70, +170, +133, +327745, +19, +172, +133, +171, +262205, +6, +173, +172, +458832, +70, +174, +173, +173, +173, +173, +327816, +70, +175, +170, +174, +196670, +133, +175, +262205, +70, +176, +148, +327745, +19, +177, +148, +171, +262205, +6, +178, +177, +458832, +70, +179, +178, +178, +178, +178, +327816, +70, +180, +176, +179, +196670, +148, +180, +327745, +88, +184, +86, +183, +262205, +6, +185, +184, +327864, +26, +186, +185, +35, +196855, +188, +0, +262394, +186, +187, +189, +131320, +187, +196670, +182, +35, +131321, +188, +131320, +189, +196670, +182, +190, +131321, +188, +131320, +188, +262205, +6, +191, +182, +196670, +181, +191, +262205, +63, +194, +65, +327819, +63, +195, +194, +67, +327850, +26, +196, +195, +119, +196855, +198, +0, +262394, +196, +197, +200, +131320, +197, +196670, +193, +199, +131321, +198, +131320, +200, +196670, +193, +104, +131321, +198, +131320, +198, +262205, +6, +201, +193, +196670, +192, +201, +262205, +6, +207, +192, +327860, +26, +208, +207, +199, +196855, +210, +0, +262394, +208, +209, +212, +131320, +209, +262205, +70, +211, +133, +196670, +206, +211, +131321, +210, +131320, +212, +262205, +70, +213, +148, +196670, +206, +213, +131321, +210, +131320, +210, +262205, +70, +214, +206, +262205, +6, +215, +192, +262205, +7, +216, +118, +262205, +6, +217, +181, +327822, +7, +218, +216, +217, +393281, +88, +221, +86, +219, +220, +262205, +6, +222, +221, +327760, +7, +223, +222, +222, +327816, +7, +224, +218, +223, +327761, +6, +225, +224, +0, +327761, +6, +226, +224, +1, +458832, +70, +227, +225, +226, +35, +35, +327822, +70, +228, +227, +215, +327809, +70, +229, +214, +228, +327745, +230, +231, +204, +205, +196670, +231, +229, +393281, +232, +235, +204, +205, +234, +262205, +6, +236, +235, +196670, +233, +236, +262205, +13, +238, +73, +262205, +6, +239, +81, +327761, +6, +240, +238, +0, +327761, +6, +241, +238, +1, +327761, +6, +242, +238, +2, +458832, +70, +243, +240, +241, +242, +239, +196670, +237, +243, +262205, +70, +245, +133, +458831, +7, +246, +245, +245, +0, +1, +262205, +70, +247, +148, +458831, +7, +248, +247, +247, +0, +1, +327761, +6, +249, +246, +0, +327761, +6, +250, +246, +1, +327761, +6, +251, +248, +0, +327761, +6, +252, +248, +1, +458832, +70, +253, +249, +250, +251, +252, +196670, +244, +253, +65789, +65592, +327734, +7, +11, +0, +9, +196663, +8, +10, +131320, +12, +262203, +19, +20, +7, +262203, +8, +23, +7, +262205, +7, +21, +10, +393228, +6, +22, +1, +66, +21, +196670, +20, +22, +262205, +6, +24, +20, +327870, +26, +27, +24, +25, +196855, +29, +0, +262394, +27, +28, +34, +131320, +28, +262205, +7, +30, +10, +262205, +6, +31, +20, +327760, +7, +32, +31, +31, +327816, +7, +33, +30, +32, +196670, +23, +33, +131321, +29, +131320, +34, +196670, +23, +36, +131321, +29, +131320, +29, +262205, +7, +37, +23, +131326, +37, +65592, +327734, +13, +17, +0, +15, +196663, +14, +16, +131320, +18, +262203, +19, +40, +7, +262203, +14, +43, +7, +262205, +13, +41, +16, +393228, +6, +42, +1, +66, +41, +196670, +40, +42, +262205, +6, +44, +40, +327870, +26, +45, +44, +25, +196855, +47, +0, +262394, +45, +46, +52, +131320, +46, +262205, +13, +48, +16, +262205, +6, +49, +40, +393296, +13, +50, +49, +49, +49, +327816, +13, +51, +48, +50, +196670, +43, +51, +131321, +47, +131320, +52, +196670, +43, +53, +131321, +47, +131320, +47, +262205, +13, +54, +43, +131326, +54, +65592, +}; +const std::vector render_hair_strand_copies_vertex = {119734787, +65536, +524289, +289, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +786447, +0, +4, +1852399981, +0, +61, +66, +221, +256, +263, +270, +288, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +655364, +1197427783, +1279741775, +1885560645, +1953718128, +1600482425, +1701734764, +1919509599, +1769235301, +25974, +524292, +1197427783, +1279741775, +1852399429, +1685417059, +1768185701, +1952671090, +6649449, +262149, +4, +1852399981, +0, +458757, +11, +1701208403, +1919905375, +1768710509, +1982358906, +3879526, +196613, +10, +6514038, +458757, +17, +1701208403, +1919905375, +1768710509, +1982358906, +3879782, +196613, +16, +6514038, +196613, +20, +7234924, +196613, +40, +7234924, +262149, +59, +1701080681, +120, +393221, +61, +1449094247, +1702130277, +1684949368, +30821, +393221, +65, +1684955506, +1936090703, +1850307685, +7890276, +458757, +66, +1230990439, +1635021678, +1231381358, +2019910766, +0, +327685, +70, +1684366707, +1684955474, +0, +393221, +82, +1684366707, +1668834644, +1685221999, +0, +327685, +93, +1684955506, +1936090703, +29797, +327685, +98, +2020892519, +1936289614, +101, +393221, +102, +1634951015, +1852394605, +1467113829, +7364978, +262149, +117, +1735287124, +7630437, +524293, +121, +1632132967, +1700164201, +2019914866, +1735287124, +1937010277, +0, +196613, +128, +118, +524293, +130, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +262149, +138, +1769234802, +111, +327685, +141, +1936617283, +1953390964, +115, +393222, +141, +0, +1466785639, +1684828783, +0, +393222, +141, +1, +1450008423, +1350002025, +6975346, +458758, +141, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +141, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +141, +4, +1165385575, +25977, +327686, +141, +5, +1986420583, +7761734, +524294, +141, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +141, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +141, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +141, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +141, +10, +1632460647, +1633045364, +6649196, +458758, +141, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +141, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +141, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +141, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +141, +15, +1767333735, +2053722990, +101, +458758, +141, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +141, +17, +1415733095, +1416522088, +28777, +458758, +141, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +141, +19, +1181114215, +1766617697, +7628903, +393222, +141, +20, +1416191847, +1399350117, +77, +458758, +141, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +141, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +141, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +141, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +141, +25, +1214668647, +1265789281, +12915, +393222, +141, +26, +1214668647, +1165125985, +12920, +589830, +141, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +143, +0, +524293, +151, +1632132967, +1750364777, +1852531561, +1131639653, +1717986671, +115, +262149, +161, +1751607666, +116, +262149, +171, +1634886000, +109, +327685, +173, +1785688688, +1734963807, +29800, +262149, +183, +1634886000, +109, +393221, +186, +1634760805, +1766876270, +1936483704, +0, +327685, +197, +1919501414, +1701080649, +120, +262149, +207, +1886217588, +0, +393221, +219, +1348430951, +1700164197, +2019914866, +0, +393222, +219, +0, +1348430951, +1953067887, +7237481, +196613, +221, +0, +262149, +256, +1953523044, +104, +262149, +263, +1735287156, +7630437, +262149, +270, +829436016, +0, +327685, +288, +1634890867, +1866687598, +7499628, +262215, +61, +11, +42, +262215, +66, +11, +43, +262215, +98, +34, +0, +262215, +98, +33, +5, +262215, +102, +34, +0, +262215, +102, +33, +18, +262215, +121, +34, +1, +262215, +121, +33, +8, +262215, +130, +34, +1, +262215, +130, +33, +7, +262216, +141, +0, +5, +327752, +141, +0, +35, +0, +327752, +141, +0, +7, +16, +262216, +141, +1, +5, +327752, +141, +1, +35, +64, +327752, +141, +1, +7, +16, +262216, +141, +2, +5, +327752, +141, +2, +35, +128, +327752, +141, +2, +7, +16, +262216, +141, +3, +5, +327752, +141, +3, +35, +192, +327752, +141, +3, +7, +16, +327752, +141, +4, +35, +256, +327752, +141, +5, +35, +268, +327752, +141, +6, +35, +272, +327752, +141, +7, +35, +288, +327752, +141, +8, +35, +304, +327752, +141, +9, +35, +320, +327752, +141, +10, +35, +336, +327752, +141, +11, +35, +352, +327752, +141, +12, +35, +356, +327752, +141, +13, +35, +360, +327752, +141, +14, +35, +364, +327752, +141, +15, +35, +368, +327752, +141, +16, +35, +384, +327752, +141, +17, +35, +388, +327752, +141, +18, +35, +392, +327752, +141, +19, +35, +396, +327752, +141, +20, +35, +400, +327752, +141, +21, +35, +404, +327752, +141, +22, +35, +408, +327752, +141, +23, +35, +412, +327752, +141, +24, +35, +416, +327752, +141, +25, +35, +420, +327752, +141, +26, +35, +424, +262216, +141, +27, +5, +327752, +141, +27, +35, +432, +327752, +141, +27, +7, +16, +196679, +141, +2, +262215, +143, +34, +0, +262215, +143, +33, +16, +262215, +151, +34, +1, +262215, +151, +33, +6, +327752, +219, +0, +11, +0, +196679, +219, +2, +262215, +256, +30, +0, +262215, +263, +30, +2, +262215, +270, +30, +1, +262215, +288, +30, +3, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +2, +262176, +8, +7, +7, +262177, +9, +7, +8, +262167, +13, +6, +3, +262176, +14, +7, +13, +262177, +15, +13, +14, +262176, +19, +7, +6, +262187, +6, +25, +869711765, +131092, +26, +262187, +6, +35, +0, +327724, +7, +36, +35, +35, +393260, +13, +53, +35, +35, +35, +262165, +57, +32, +1, +262176, +58, +7, +57, +262176, +60, +1, +57, +262203, +60, +61, +1, +262187, +57, +63, +2, +262203, +60, +66, +1, +262165, +68, +32, +0, +262176, +69, +7, +68, +262187, +57, +72, +64, +262187, +57, +74, +1, +262187, +57, +79, +512, +262187, +68, +84, +512, +262187, +6, +91, +989855744, +589849, +96, +6, +1, +0, +0, +0, +1, +0, +262176, +97, +0, +96, +262203, +97, +98, +0, +131098, +100, +262176, +101, +0, +100, +262203, +101, +102, +0, +196635, +104, +96, +262167, +107, +6, +4, +262187, +6, +111, +1073741824, +262187, +6, +114, +1065353216, +589849, +118, +6, +5, +0, +0, +0, +1, +0, +196635, +119, +118, +262176, +120, +0, +119, +262203, +120, +121, +0, +262203, +120, +130, +0, +262168, +140, +107, +4, +1966110, +141, +140, +140, +140, +140, +13, +6, +107, +107, +107, +107, +107, +6, +6, +6, +6, +107, +6, +6, +6, +6, +57, +57, +57, +57, +6, +6, +6, +140, +262176, +142, +2, +141, +262203, +142, +143, +2, +262187, +57, +144, +17, +262176, +145, +2, +6, +262203, +120, +151, +0, +262187, +68, +157, +0, +262187, +57, +164, +4, +262176, +165, +2, +13, +262176, +174, +2, +140, +262187, +57, +188, +13, +262187, +6, +195, +1060487823, +262187, +6, +204, +3212836864, +262187, +57, +214, +14, +196638, +219, +107, +262176, +220, +3, +219, +262203, +220, +221, +3, +262187, +57, +222, +0, +262176, +231, +3, +107, +262187, +57, +239, +15, +262187, +68, +240, +1, +262187, +68, +249, +3, +262176, +250, +3, +6, +262203, +250, +256, +3, +262187, +68, +257, +2, +262203, +231, +263, +3, +262203, +231, +270, +3, +262203, +231, +288, +3, +327734, +2, +4, +0, +3, +131320, +5, +262203, +58, +59, +7, +262203, +58, +65, +7, +262203, +69, +70, +7, +262203, +8, +82, +7, +262203, +14, +93, +7, +262203, +14, +117, +7, +262203, +14, +128, +7, +262203, +19, +138, +7, +262203, +19, +139, +7, +262203, +14, +161, +7, +262203, +14, +171, +7, +262203, +8, +173, +7, +262203, +8, +183, +7, +262203, +19, +186, +7, +262203, +19, +187, +7, +262203, +19, +197, +7, +262203, +19, +198, +7, +262203, +14, +207, +7, +262205, +57, +62, +61, +327815, +57, +64, +62, +63, +196670, +59, +64, +262205, +57, +67, +66, +196670, +65, +67, +262205, +57, +71, +59, +327815, +57, +73, +71, +72, +327808, +57, +75, +73, +74, +262205, +57, +76, +65, +327808, +57, +77, +76, +74, +327812, +57, +78, +75, +77, +327819, +57, +80, +78, +79, +262268, +68, +81, +80, +196670, +70, +81, +262205, +68, +83, +70, +327817, +68, +85, +83, +84, +262256, +6, +86, +85, +262205, +68, +87, +70, +327814, +68, +88, +87, +84, +262256, +6, +89, +88, +327760, +7, +90, +86, +89, +327822, +7, +92, +90, +91, +196670, +82, +92, +262205, +57, +94, +65, +262255, +6, +95, +94, +262205, +96, +99, +98, +262205, +100, +103, +102, +327766, +104, +105, +99, +103, +262205, +7, +106, +82, +458840, +107, +108, +105, +106, +2, +35, +524367, +13, +109, +108, +108, +0, +1, +2, +327822, +13, +110, +109, +95, +196670, +93, +110, +262205, +13, +112, +93, +327822, +13, +113, +112, +111, +393296, +13, +115, +114, +114, +114, +327811, +13, +116, +113, +115, +196670, +93, +116, +262205, +119, +122, +121, +262205, +57, +123, +61, +327815, +57, +124, +123, +63, +262244, +118, +125, +122, +327775, +107, +126, +125, +124, +524367, +13, +127, +126, +126, +0, +1, +2, +196670, +117, +127, +262205, +13, +129, +93, +262205, +119, +131, +130, +262205, +57, +132, +61, +327815, +57, +133, +132, +63, +262244, +118, +134, +131, +327775, +107, +135, +134, +133, +524367, +13, +136, +135, +135, +0, +1, +2, +327809, +13, +137, +129, +136, +196670, +128, +137, +327745, +145, +146, +143, +144, +262205, +6, +147, +146, +327866, +26, +148, +147, +35, +196855, +150, +0, +262394, +148, +149, +159, +131320, +149, +262205, +119, +152, +151, +262205, +57, +153, +61, +327815, +57, +154, +153, +63, +262244, +118, +155, +152, +327775, +107, +156, +155, +154, +327761, +6, +158, +156, +0, +196670, +139, +158, +131321, +150, +131320, +159, +196670, +139, +114, +131321, +150, +131320, +150, +262205, +6, +160, +139, +196670, +138, +160, +262205, +13, +162, +117, +262205, +13, +163, +128, +327745, +165, +166, +143, +164, +262205, +13, +167, +166, +327811, +13, +168, +163, +167, +393228, +13, +169, +1, +69, +168, +458764, +13, +170, +1, +68, +162, +169, +196670, +171, +170, +327737, +13, +172, +17, +171, +196670, +161, +172, +327745, +174, +175, +143, +74, +262205, +140, +176, +175, +262205, +13, +177, +161, +327761, +6, +178, +177, +0, +327761, +6, +179, +177, +1, +327761, +6, +180, +177, +2, +458832, +107, +181, +178, +179, +180, +35, +327825, +107, +182, +176, +181, +458831, +7, +184, +182, +182, +0, +1, +196670, +183, +184, +327737, +7, +185, +11, +183, +196670, +173, +185, +327745, +145, +189, +143, +188, +262205, +6, +190, +189, +327864, +26, +191, +190, +35, +196855, +193, +0, +262394, +191, +192, +194, +131320, +192, +196670, +187, +35, +131321, +193, +131320, +194, +196670, +187, +195, +131321, +193, +131320, +193, +262205, +6, +196, +187, +196670, +186, +196, +262205, +57, +199, +61, +327819, +57, +200, +199, +63, +327850, +26, +201, +200, +74, +196855, +203, +0, +262394, +201, +202, +205, +131320, +202, +196670, +198, +204, +131321, +203, +131320, +205, +196670, +198, +114, +131321, +203, +131320, +203, +262205, +6, +206, +198, +196670, +197, +206, +262205, +13, +208, +128, +262205, +6, +209, +197, +262205, +13, +210, +161, +327822, +13, +211, +210, +209, +262205, +6, +212, +138, +327822, +13, +213, +211, +212, +327745, +145, +215, +143, +214, +262205, +6, +216, +215, +327822, +13, +217, +213, +216, +327809, +13, +218, +208, +217, +196670, +207, +218, +327745, +174, +223, +143, +74, +262205, +140, +224, +223, +262205, +13, +225, +207, +327761, +6, +226, +225, +0, +327761, +6, +227, +225, +1, +327761, +6, +228, +225, +2, +458832, +107, +229, +226, +227, +228, +114, +327825, +107, +230, +224, +229, +327745, +231, +232, +221, +222, +196670, +232, +230, +327745, +231, +233, +221, +222, +262205, +107, +234, +233, +262205, +6, +235, +197, +262205, +7, +236, +173, +262205, +6, +237, +186, +327822, +7, +238, +236, +237, +393281, +145, +241, +143, +239, +240, +262205, +6, +242, +241, +327760, +7, +243, +242, +242, +327816, +7, +244, +238, +243, +327761, +6, +245, +244, +0, +327761, +6, +246, +244, +1, +458832, +107, +247, +245, +246, +35, +35, +327822, +107, +248, +247, +235, +393281, +250, +251, +221, +222, +249, +262205, +6, +252, +251, +327822, +107, +253, +248, +252, +327809, +107, +254, +234, +253, +327745, +231, +255, +221, +222, +196670, +255, +254, +393281, +250, +258, +221, +222, +257, +262205, +6, +259, +258, +393281, +250, +260, +221, +222, +249, +262205, +6, +261, +260, +327816, +6, +262, +259, +261, +196670, +256, +262, +262205, +13, +264, +117, +262205, +6, +265, +138, +327761, +6, +266, +264, +0, +327761, +6, +267, +264, +1, +327761, +6, +268, +264, +2, +458832, +107, +269, +266, +267, +268, +265, +196670, +263, +269, +262205, +13, +271, +128, +458831, +7, +272, +271, +271, +0, +1, +262205, +13, +273, +93, +458831, +7, +274, +273, +273, +0, +1, +262205, +119, +275, +130, +262205, +57, +276, +61, +327815, +57, +277, +276, +63, +327808, +57, +278, +277, +74, +262244, +118, +279, +275, +327775, +107, +280, +279, +278, +458831, +7, +281, +280, +280, +0, +1, +327809, +7, +282, +274, +281, +327761, +6, +283, +272, +0, +327761, +6, +284, +272, +1, +327761, +6, +285, +282, +0, +327761, +6, +286, +282, +1, +458832, +107, +287, +283, +284, +285, +286, +196670, +270, +287, +65789, +65592, +327734, +7, +11, +0, +9, +196663, +8, +10, +131320, +12, +262203, +19, +20, +7, +262203, +8, +23, +7, +262205, +7, +21, +10, +393228, +6, +22, +1, +66, +21, +196670, +20, +22, +262205, +6, +24, +20, +327870, +26, +27, +24, +25, +196855, +29, +0, +262394, +27, +28, +34, +131320, +28, +262205, +7, +30, +10, +262205, +6, +31, +20, +327760, +7, +32, +31, +31, +327816, +7, +33, +30, +32, +196670, +23, +33, +131321, +29, +131320, +34, +196670, +23, +36, +131321, +29, +131320, +29, +262205, +7, +37, +23, +131326, +37, +65592, +327734, +13, +17, +0, +15, +196663, +14, +16, +131320, +18, +262203, +19, +40, +7, +262203, +14, +43, +7, +262205, +13, +41, +16, +393228, +6, +42, +1, +66, +41, +196670, +40, +42, +262205, +6, +44, +40, +327870, +26, +45, +44, +25, +196855, +47, +0, +262394, +45, +46, +52, +131320, +46, +262205, +13, +48, +16, +262205, +6, +49, +40, +393296, +13, +50, +49, +49, +49, +327816, +13, +51, +48, +50, +196670, +43, +51, +131321, +47, +131320, +52, +196670, +43, +53, +131321, +47, +131320, +47, +262205, +13, +54, +43, +131326, +54, +65592, +}; +const std::vector render_hair_aa_strand_copies_vertex = {119734787, +65536, +524289, +324, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +786447, +0, +4, +1852399981, +0, +61, +66, +247, +289, +296, +303, +323, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +655364, +1197427783, +1279741775, +1885560645, +1953718128, +1600482425, +1701734764, +1919509599, +1769235301, +25974, +524292, +1197427783, +1279741775, +1852399429, +1685417059, +1768185701, +1952671090, +6649449, +262149, +4, +1852399981, +0, +458757, +11, +1701208403, +1919905375, +1768710509, +1982358906, +3879526, +196613, +10, +6514038, +458757, +17, +1701208403, +1919905375, +1768710509, +1982358906, +3879782, +196613, +16, +6514038, +196613, +20, +7234924, +196613, +40, +7234924, +262149, +59, +1701080681, +120, +393221, +61, +1449094247, +1702130277, +1684949368, +30821, +393221, +65, +1684955506, +1936090703, +1850307685, +7890276, +458757, +66, +1230990439, +1635021678, +1231381358, +2019910766, +0, +327685, +70, +1684366707, +1684955474, +0, +393221, +82, +1684366707, +1668834644, +1685221999, +0, +327685, +93, +1684955506, +1936090703, +29797, +327685, +98, +2020892519, +1936289614, +101, +393221, +102, +1634951015, +1852394605, +1467113829, +7364978, +262149, +117, +1735287124, +7630437, +524293, +121, +1632132967, +1700164201, +2019914866, +1735287124, +1937010277, +0, +196613, +128, +118, +524293, +130, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +262149, +138, +1769234802, +111, +327685, +141, +1936617283, +1953390964, +115, +393222, +141, +0, +1466785639, +1684828783, +0, +393222, +141, +1, +1450008423, +1350002025, +6975346, +458758, +141, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +141, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +141, +4, +1165385575, +25977, +327686, +141, +5, +1986420583, +7761734, +524294, +141, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +141, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +141, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +141, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +141, +10, +1632460647, +1633045364, +6649196, +458758, +141, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +141, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +141, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +141, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +141, +15, +1767333735, +2053722990, +101, +458758, +141, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +141, +17, +1415733095, +1416522088, +28777, +458758, +141, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +141, +19, +1181114215, +1766617697, +7628903, +393222, +141, +20, +1416191847, +1399350117, +77, +458758, +141, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +141, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +141, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +141, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +141, +25, +1214668647, +1265789281, +12915, +393222, +141, +26, +1214668647, +1165125985, +12920, +589830, +141, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +143, +0, +524293, +151, +1632132967, +1750364777, +1852531561, +1131639653, +1717986671, +115, +262149, +161, +1751607666, +116, +262149, +171, +1634886000, +109, +327685, +173, +1785688688, +1734963807, +29800, +262149, +183, +1634886000, +109, +393221, +186, +1634760805, +1766876270, +1936483704, +0, +458757, +198, +1919508840, +1701274693, +1769172816, +1852795252, +12403, +458757, +213, +1919508840, +1701274693, +1769172816, +1852795252, +12659, +327685, +235, +1919501414, +1701080649, +120, +393221, +245, +1348430951, +1700164197, +2019914866, +0, +393222, +245, +0, +1348430951, +1953067887, +7237481, +196613, +247, +0, +262149, +289, +1953523044, +104, +262149, +296, +1735287156, +7630437, +262149, +303, +829436016, +0, +327685, +323, +1634890867, +1866687598, +7499628, +262215, +61, +11, +42, +262215, +66, +11, +43, +262215, +98, +34, +0, +262215, +98, +33, +5, +262215, +102, +34, +0, +262215, +102, +33, +18, +262215, +121, +34, +1, +262215, +121, +33, +8, +262215, +130, +34, +1, +262215, +130, +33, +7, +262216, +141, +0, +5, +327752, +141, +0, +35, +0, +327752, +141, +0, +7, +16, +262216, +141, +1, +5, +327752, +141, +1, +35, +64, +327752, +141, +1, +7, +16, +262216, +141, +2, +5, +327752, +141, +2, +35, +128, +327752, +141, +2, +7, +16, +262216, +141, +3, +5, +327752, +141, +3, +35, +192, +327752, +141, +3, +7, +16, +327752, +141, +4, +35, +256, +327752, +141, +5, +35, +268, +327752, +141, +6, +35, +272, +327752, +141, +7, +35, +288, +327752, +141, +8, +35, +304, +327752, +141, +9, +35, +320, +327752, +141, +10, +35, +336, +327752, +141, +11, +35, +352, +327752, +141, +12, +35, +356, +327752, +141, +13, +35, +360, +327752, +141, +14, +35, +364, +327752, +141, +15, +35, +368, +327752, +141, +16, +35, +384, +327752, +141, +17, +35, +388, +327752, +141, +18, +35, +392, +327752, +141, +19, +35, +396, +327752, +141, +20, +35, +400, +327752, +141, +21, +35, +404, +327752, +141, +22, +35, +408, +327752, +141, +23, +35, +412, +327752, +141, +24, +35, +416, +327752, +141, +25, +35, +420, +327752, +141, +26, +35, +424, +262216, +141, +27, +5, +327752, +141, +27, +35, +432, +327752, +141, +27, +7, +16, +196679, +141, +2, +262215, +143, +34, +0, +262215, +143, +33, +16, +262215, +151, +34, +1, +262215, +151, +33, +6, +327752, +245, +0, +11, +0, +196679, +245, +2, +262215, +289, +30, +0, +262215, +296, +30, +2, +262215, +303, +30, +1, +262215, +323, +30, +3, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +2, +262176, +8, +7, +7, +262177, +9, +7, +8, +262167, +13, +6, +3, +262176, +14, +7, +13, +262177, +15, +13, +14, +262176, +19, +7, +6, +262187, +6, +25, +869711765, +131092, +26, +262187, +6, +35, +0, +327724, +7, +36, +35, +35, +393260, +13, +53, +35, +35, +35, +262165, +57, +32, +1, +262176, +58, +7, +57, +262176, +60, +1, +57, +262203, +60, +61, +1, +262187, +57, +63, +2, +262203, +60, +66, +1, +262165, +68, +32, +0, +262176, +69, +7, +68, +262187, +57, +72, +64, +262187, +57, +74, +1, +262187, +57, +79, +512, +262187, +68, +84, +512, +262187, +6, +91, +989855744, +589849, +96, +6, +1, +0, +0, +0, +1, +0, +262176, +97, +0, +96, +262203, +97, +98, +0, +131098, +100, +262176, +101, +0, +100, +262203, +101, +102, +0, +196635, +104, +96, +262167, +107, +6, +4, +262187, +6, +111, +1073741824, +262187, +6, +114, +1065353216, +589849, +118, +6, +5, +0, +0, +0, +1, +0, +196635, +119, +118, +262176, +120, +0, +119, +262203, +120, +121, +0, +262203, +120, +130, +0, +262168, +140, +107, +4, +1966110, +141, +140, +140, +140, +140, +13, +6, +107, +107, +107, +107, +107, +6, +6, +6, +6, +107, +6, +6, +6, +6, +57, +57, +57, +57, +6, +6, +6, +140, +262176, +142, +2, +141, +262203, +142, +143, +2, +262187, +57, +144, +17, +262176, +145, +2, +6, +262203, +120, +151, +0, +262187, +68, +157, +0, +262187, +57, +164, +4, +262176, +165, +2, +13, +262176, +174, +2, +140, +262187, +57, +188, +13, +262187, +6, +195, +1060487823, +262176, +197, +7, +107, +262187, +57, +204, +14, +262187, +6, +242, +3212836864, +196638, +245, +107, +262176, +246, +3, +245, +262203, +246, +247, +3, +262187, +57, +248, +0, +262187, +57, +262, +15, +262187, +68, +263, +1, +262187, +68, +277, +3, +262176, +286, +3, +107, +262176, +288, +3, +6, +262203, +288, +289, +3, +262187, +68, +290, +2, +262203, +286, +296, +3, +262203, +286, +303, +3, +262203, +286, +323, +3, +327734, +2, +4, +0, +3, +131320, +5, +262203, +58, +59, +7, +262203, +58, +65, +7, +262203, +69, +70, +7, +262203, +8, +82, +7, +262203, +14, +93, +7, +262203, +14, +117, +7, +262203, +14, +128, +7, +262203, +19, +138, +7, +262203, +19, +139, +7, +262203, +14, +161, +7, +262203, +14, +171, +7, +262203, +8, +173, +7, +262203, +8, +183, +7, +262203, +19, +186, +7, +262203, +19, +187, +7, +262203, +197, +198, +7, +262203, +197, +213, +7, +262203, +19, +235, +7, +262203, +19, +236, +7, +262203, +197, +249, +7, +262203, +19, +272, +7, +262205, +57, +62, +61, +327815, +57, +64, +62, +63, +196670, +59, +64, +262205, +57, +67, +66, +196670, +65, +67, +262205, +57, +71, +59, +327815, +57, +73, +71, +72, +327808, +57, +75, +73, +74, +262205, +57, +76, +65, +327808, +57, +77, +76, +74, +327812, +57, +78, +75, +77, +327819, +57, +80, +78, +79, +262268, +68, +81, +80, +196670, +70, +81, +262205, +68, +83, +70, +327817, +68, +85, +83, +84, +262256, +6, +86, +85, +262205, +68, +87, +70, +327814, +68, +88, +87, +84, +262256, +6, +89, +88, +327760, +7, +90, +86, +89, +327822, +7, +92, +90, +91, +196670, +82, +92, +262205, +57, +94, +65, +262255, +6, +95, +94, +262205, +96, +99, +98, +262205, +100, +103, +102, +327766, +104, +105, +99, +103, +262205, +7, +106, +82, +458840, +107, +108, +105, +106, +2, +35, +524367, +13, +109, +108, +108, +0, +1, +2, +327822, +13, +110, +109, +95, +196670, +93, +110, +262205, +13, +112, +93, +327822, +13, +113, +112, +111, +393296, +13, +115, +114, +114, +114, +327811, +13, +116, +113, +115, +196670, +93, +116, +262205, +119, +122, +121, +262205, +57, +123, +61, +327815, +57, +124, +123, +63, +262244, +118, +125, +122, +327775, +107, +126, +125, +124, +524367, +13, +127, +126, +126, +0, +1, +2, +196670, +117, +127, +262205, +13, +129, +93, +262205, +119, +131, +130, +262205, +57, +132, +61, +327815, +57, +133, +132, +63, +262244, +118, +134, +131, +327775, +107, +135, +134, +133, +524367, +13, +136, +135, +135, +0, +1, +2, +327809, +13, +137, +129, +136, +196670, +128, +137, +327745, +145, +146, +143, +144, +262205, +6, +147, +146, +327866, +26, +148, +147, +35, +196855, +150, +0, +262394, +148, +149, +159, +131320, +149, +262205, +119, +152, +151, +262205, +57, +153, +61, +327815, +57, +154, +153, +63, +262244, +118, +155, +152, +327775, +107, +156, +155, +154, +327761, +6, +158, +156, +0, +196670, +139, +158, +131321, +150, +131320, +159, +196670, +139, +114, +131321, +150, +131320, +150, +262205, +6, +160, +139, +196670, +138, +160, +262205, +13, +162, +117, +262205, +13, +163, +128, +327745, +165, +166, +143, +164, +262205, +13, +167, +166, +327811, +13, +168, +163, +167, +393228, +13, +169, +1, +69, +168, +458764, +13, +170, +1, +68, +162, +169, +196670, +171, +170, +327737, +13, +172, +17, +171, +196670, +161, +172, +327745, +174, +175, +143, +74, +262205, +140, +176, +175, +262205, +13, +177, +161, +327761, +6, +178, +177, +0, +327761, +6, +179, +177, +1, +327761, +6, +180, +177, +2, +458832, +107, +181, +178, +179, +180, +35, +327825, +107, +182, +176, +181, +458831, +7, +184, +182, +182, +0, +1, +196670, +183, +184, +327737, +7, +185, +11, +183, +196670, +173, +185, +327745, +145, +189, +143, +188, +262205, +6, +190, +189, +327864, +26, +191, +190, +35, +196855, +193, +0, +262394, +191, +192, +194, +131320, +192, +196670, +187, +35, +131321, +193, +131320, +194, +196670, +187, +195, +131321, +193, +131320, +193, +262205, +6, +196, +187, +196670, +186, +196, +262205, +13, +199, +128, +262205, +13, +200, +161, +327822, +13, +201, +200, +114, +262205, +6, +202, +138, +327822, +13, +203, +201, +202, +327745, +145, +205, +143, +204, +262205, +6, +206, +205, +327822, +13, +207, +203, +206, +327811, +13, +208, +199, +207, +327761, +6, +209, +208, +0, +327761, +6, +210, +208, +1, +327761, +6, +211, +208, +2, +458832, +107, +212, +209, +210, +211, +114, +196670, +198, +212, +262205, +13, +214, +128, +262205, +13, +215, +161, +327822, +13, +216, +215, +114, +262205, +6, +217, +138, +327822, +13, +218, +216, +217, +327745, +145, +219, +143, +204, +262205, +6, +220, +219, +327822, +13, +221, +218, +220, +327809, +13, +222, +214, +221, +327761, +6, +223, +222, +0, +327761, +6, +224, +222, +1, +327761, +6, +225, +222, +2, +458832, +107, +226, +223, +224, +225, +114, +196670, +213, +226, +327745, +174, +227, +143, +74, +262205, +140, +228, +227, +262205, +107, +229, +198, +327825, +107, +230, +228, +229, +196670, +198, +230, +327745, +174, +231, +143, +74, +262205, +140, +232, +231, +262205, +107, +233, +213, +327825, +107, +234, +232, +233, +196670, +213, +234, +262205, +57, +237, +61, +327819, +57, +238, +237, +63, +327850, +26, +239, +238, +74, +196855, +241, +0, +262394, +239, +240, +243, +131320, +240, +196670, +236, +242, +131321, +241, +131320, +243, +196670, +236, +114, +131321, +241, +131320, +241, +262205, +6, +244, +236, +196670, +235, +244, +262205, +6, +250, +235, +327860, +26, +251, +250, +242, +196855, +253, +0, +262394, +251, +252, +255, +131320, +252, +262205, +107, +254, +198, +196670, +249, +254, +131321, +253, +131320, +255, +262205, +107, +256, +213, +196670, +249, +256, +131321, +253, +131320, +253, +262205, +107, +257, +249, +262205, +6, +258, +235, +262205, +7, +259, +173, +262205, +6, +260, +186, +327822, +7, +261, +259, +260, +393281, +145, +264, +143, +262, +263, +262205, +6, +265, +264, +327760, +7, +266, +265, +265, +327816, +7, +267, +261, +266, +327761, +6, +268, +267, +0, +327761, +6, +269, +267, +1, +458832, +107, +270, +268, +269, +35, +35, +327822, +107, +271, +270, +258, +262205, +6, +273, +235, +327860, +26, +274, +273, +242, +196855, +276, +0, +262394, +274, +275, +280, +131320, +275, +327745, +19, +278, +198, +277, +262205, +6, +279, +278, +196670, +272, +279, +131321, +276, +131320, +280, +327745, +19, +281, +213, +277, +262205, +6, +282, +281, +196670, +272, +282, +131321, +276, +131320, +276, +262205, +6, +283, +272, +327822, +107, +284, +271, +283, +327809, +107, +285, +257, +284, +327745, +286, +287, +247, +248, +196670, +287, +285, +393281, +288, +291, +247, +248, +290, +262205, +6, +292, +291, +393281, +288, +293, +247, +248, +277, +262205, +6, +294, +293, +327816, +6, +295, +292, +294, +196670, +289, +295, +262205, +13, +297, +117, +262205, +6, +298, +138, +327761, +6, +299, +297, +0, +327761, +6, +300, +297, +1, +327761, +6, +301, +297, +2, +458832, +107, +302, +299, +300, +301, +298, +196670, +296, +302, +262205, +107, +304, +198, +458831, +7, +305, +304, +304, +0, +1, +327745, +19, +306, +198, +277, +262205, +6, +307, +306, +458764, +6, +308, +1, +40, +307, +25, +327760, +7, +309, +308, +308, +327816, +7, +310, +305, +309, +262205, +107, +311, +213, +458831, +7, +312, +311, +311, +0, +1, +327745, +19, +313, +213, +277, +262205, +6, +314, +313, +458764, +6, +315, +1, +40, +314, +25, +327760, +7, +316, +315, +315, +327816, +7, +317, +312, +316, +327761, +6, +318, +310, +0, +327761, +6, +319, +310, +1, +327761, +6, +320, +317, +0, +327761, +6, +321, +317, +1, +458832, +107, +322, +318, +319, +320, +321, +196670, +303, +322, +65789, +65592, +327734, +7, +11, +0, +9, +196663, +8, +10, +131320, +12, +262203, +19, +20, +7, +262203, +8, +23, +7, +262205, +7, +21, +10, +393228, +6, +22, +1, +66, +21, +196670, +20, +22, +262205, +6, +24, +20, +327870, +26, +27, +24, +25, +196855, +29, +0, +262394, +27, +28, +34, +131320, +28, +262205, +7, +30, +10, +262205, +6, +31, +20, +327760, +7, +32, +31, +31, +327816, +7, +33, +30, +32, +196670, +23, +33, +131321, +29, +131320, +34, +196670, +23, +36, +131321, +29, +131320, +29, +262205, +7, +37, +23, +131326, +37, +65592, +327734, +13, +17, +0, +15, +196663, +14, +16, +131320, +18, +262203, +19, +40, +7, +262203, +14, +43, +7, +262205, +13, +41, +16, +393228, +6, +42, +1, +66, +41, +196670, +40, +42, +262205, +6, +44, +40, +327870, +26, +45, +44, +25, +196855, +47, +0, +262394, +45, +46, +52, +131320, +46, +262205, +13, +48, +16, +262205, +6, +49, +40, +393296, +13, +50, +49, +49, +49, +327816, +13, +51, +48, +50, +196670, +43, +51, +131321, +47, +131320, +52, +196670, +43, +53, +131321, +47, +131320, +47, +262205, +13, +54, +43, +131326, +54, +65592, +}; +const std::vector pass1_fragment = {119734787, +65536, +524289, +346, +0, +131089, +1, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +589839, +4, +4, +1852399981, +0, +276, +308, +332, +345, +196624, +4, +7, +196624, +4, +9, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +262149, +4, +1852399981, +0, +524293, +12, +1801675088, +1634692166, +1850291316, +1767206772, +1982362734, +3880038, +262149, +11, +1818318454, +25973, +589829, +17, +1634758229, +1767205731, +1850307694, +1816555380, +880042351, +993097000, +0, +262149, +16, +1818318453, +25973, +655365, +25, +1801675088, +1735287124, +1098149477, +1866687598, +1634887030, +1982358887, +1715155814, +15153, +262149, +23, +1735287156, +7630437, +327685, +24, +1702260579, +1701273970, +0, +393221, +29, +1416914247, +1701277281, +1965585518, +15153, +393221, +28, +1801675120, +1632920677, +1852139374, +116, +393221, +33, +1131701575, +1919252079, +677734241, +3879285, +393221, +32, +1801675120, +1866687589, +1634887030, +25959, +655365, +41, +1886220099, +1130722421, +1919252079, +677734241, +993158774, +993158774, +993158774, +0, +196613, +38, +12400, +196613, +39, +12656, +327685, +40, +1702390128, +1668238444, +0, +720901, +48, +1919906899, +1634879077, +1852140903, +1214215028, +678586721, +993158774, +993224310, +1715155302, +15153, +327685, +44, +1734439494, +1919905603, +5855332, +262149, +45, +1735287124, +7630437, +327685, +46, +1702260547, +1701273970, +0, +262149, +47, +1953523044, +104, +262149, +50, +1702132066, +51, +262149, +59, +1702132066, +50, +262149, +66, +1702132066, +49, +262149, +73, +1702132066, +48, +262149, +131, +1634886000, +109, +262149, +136, +1634886000, +109, +262149, +146, +1634886000, +109, +327685, +153, +1936617283, +1953390964, +115, +393222, +153, +0, +1466785639, +1684828783, +0, +393222, +153, +1, +1450008423, +1350002025, +6975346, +458758, +153, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +153, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +153, +4, +1165385575, +25977, +327686, +153, +5, +1986420583, +7761734, +524294, +153, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +153, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +153, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +153, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +153, +10, +1632460647, +1633045364, +6649196, +458758, +153, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +153, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +153, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +153, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +153, +15, +1767333735, +2053722990, +101, +458758, +153, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +153, +17, +1415733095, +1416522088, +28777, +458758, +153, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +153, +19, +1181114215, +1766617697, +7628903, +393222, +153, +20, +1416191847, +1399350117, +77, +458758, +153, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +153, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +153, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +153, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +153, +25, +1214668647, +1265789281, +12915, +393222, +153, +26, +1214668647, +1165125985, +12920, +589830, +153, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +155, +0, +262149, +178, +1768173680, +29811, +262149, +183, +1768173936, +29811, +327685, +188, +1919508840, +1952737623, +104, +262149, +195, +1937012079, +6644841, +262149, +208, +1852270963, +0, +262149, +215, +1147954546, +7631721, +327685, +227, +1702390128, +1684627308, +0, +393221, +228, +1836020801, +1967285097, +1919247974, +0, +393222, +228, +0, +1702390096, +1970226028, +29806, +196613, +230, +0, +262149, +236, +1684633712, +0, +196613, +241, +7763305, +196613, +244, +7368052, +524293, +247, +1349674320, +1818589289, +1802398028, +1766614117, +1699247219, +25697, +458757, +253, +1349674320, +1818589289, +1953720652, +1801680194, +29797, +327686, +253, +0, +1953523044, +104, +524294, +253, +1, +1735287124, +1098149477, +1866687598, +1634887030, +25959, +327686, +253, +2, +1954047342, +0, +458757, +255, +1349674320, +1818589289, +1802398028, +1766614117, +29811, +327686, +255, +0, +1280069712, +0, +196613, +257, +0, +262149, +264, +1634886000, +109, +262149, +266, +1634886000, +109, +327685, +274, +1785688688, +1936683103, +0, +393221, +276, +1180658791, +1130848626, +1685221231, +0, +393221, +293, +1734963823, +1818324585, +1936683103, +0, +327685, +299, +1702260579, +1701273970, +0, +262149, +308, +829436016, +0, +262149, +309, +1634886000, +109, +262149, +312, +1634886000, +109, +262149, +315, +1634886000, +109, +262149, +332, +1735287156, +7630437, +262149, +333, +1634886000, +109, +262149, +336, +1634886000, +109, +262149, +339, +1634886000, +109, +262149, +341, +1634886000, +109, +262149, +345, +1953523044, +104, +262216, +153, +0, +5, +327752, +153, +0, +35, +0, +327752, +153, +0, +7, +16, +262216, +153, +1, +5, +327752, +153, +1, +35, +64, +327752, +153, +1, +7, +16, +262216, +153, +2, +5, +327752, +153, +2, +35, +128, +327752, +153, +2, +7, +16, +262216, +153, +3, +5, +327752, +153, +3, +35, +192, +327752, +153, +3, +7, +16, +327752, +153, +4, +35, +256, +327752, +153, +5, +35, +268, +327752, +153, +6, +35, +272, +327752, +153, +7, +35, +288, +327752, +153, +8, +35, +304, +327752, +153, +9, +35, +320, +327752, +153, +10, +35, +336, +327752, +153, +11, +35, +352, +327752, +153, +12, +35, +356, +327752, +153, +13, +35, +360, +327752, +153, +14, +35, +364, +327752, +153, +15, +35, +368, +327752, +153, +16, +35, +384, +327752, +153, +17, +35, +388, +327752, +153, +18, +35, +392, +327752, +153, +19, +35, +396, +327752, +153, +20, +35, +400, +327752, +153, +21, +35, +404, +327752, +153, +22, +35, +408, +327752, +153, +23, +35, +412, +327752, +153, +24, +35, +416, +327752, +153, +25, +35, +420, +327752, +153, +26, +35, +424, +262216, +153, +27, +5, +327752, +153, +27, +35, +432, +327752, +153, +27, +7, +16, +196679, +153, +2, +262215, +155, +34, +0, +262215, +155, +33, +16, +327752, +228, +0, +35, +0, +196679, +228, +3, +262215, +230, +34, +0, +262215, +230, +33, +17, +262215, +247, +34, +0, +262215, +247, +33, +1, +196679, +247, +19, +327752, +253, +0, +35, +0, +327752, +253, +1, +35, +4, +327752, +253, +2, +35, +8, +262215, +254, +6, +12, +327752, +255, +0, +35, +0, +196679, +255, +3, +262215, +257, +34, +0, +262215, +257, +33, +0, +262215, +276, +11, +15, +262215, +308, +30, +1, +262215, +332, +30, +2, +262215, +345, +30, +0, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +262165, +9, +32, +0, +262177, +10, +9, +8, +262176, +14, +7, +9, +262177, +15, +7, +14, +262167, +19, +6, +3, +262176, +20, +7, +19, +262176, +21, +7, +6, +327713, +22, +9, +20, +21, +262177, +27, +19, +14, +262177, +31, +6, +14, +262167, +35, +6, +2, +262176, +36, +7, +35, +393249, +37, +6, +36, +36, +36, +458785, +43, +2, +36, +20, +21, +21, +262187, +9, +51, +0, +262187, +6, +54, +1132396544, +262187, +9, +57, +255, +262187, +9, +60, +1, +262187, +9, +67, +2, +262187, +9, +74, +3, +262165, +81, +32, +1, +262187, +81, +82, +24, +262187, +81, +85, +16, +262187, +81, +89, +8, +262187, +9, +97, +4278190080, +262187, +9, +103, +16711680, +262187, +9, +109, +65280, +262187, +6, +122, +1056964608, +262187, +6, +135, +1073741824, +262187, +6, +141, +1065353216, +262168, +152, +7, +4, +1966110, +153, +152, +152, +152, +152, +19, +6, +7, +7, +7, +7, +7, +6, +6, +6, +6, +7, +6, +6, +6, +6, +81, +81, +81, +81, +6, +6, +6, +152, +262176, +154, +2, +153, +262203, +154, +155, +2, +262187, +81, +156, +15, +262176, +157, +2, +7, +262187, +6, +168, +3212836864, +131092, +193, +262176, +194, +7, +193, +262187, +6, +199, +0, +262167, +205, +193, +2, +196638, +228, +9, +262176, +229, +2, +228, +262203, +229, +230, +2, +262187, +81, +231, +0, +262176, +232, +2, +9, +262176, +235, +7, +81, +262167, +239, +81, +2, +262176, +240, +7, +239, +589849, +245, +9, +1, +0, +0, +0, +2, +33, +262176, +246, +0, +245, +262203, +246, +247, +0, +262176, +250, +11, +9, +327710, +253, +6, +9, +9, +196637, +254, +253, +196638, +255, +254, +262176, +256, +2, +255, +262203, +256, +257, +2, +262176, +260, +2, +6, +262187, +81, +263, +1, +262187, +81, +271, +2, +262176, +275, +1, +7, +262203, +275, +276, +1, +262176, +277, +1, +6, +262176, +294, +2, +152, +262187, +81, +301, +21, +262176, +302, +2, +81, +262203, +275, +308, +1, +262187, +81, +321, +11, +262203, +275, +332, +1, +262203, +277, +345, +1, +327734, +2, +4, +0, +3, +131320, +5, +262203, +8, +274, +7, +262203, +8, +293, +7, +262203, +21, +299, +7, +262203, +21, +300, +7, +262203, +36, +309, +7, +262203, +36, +312, +7, +262203, +36, +315, +7, +262203, +36, +333, +7, +262203, +20, +336, +7, +262203, +21, +339, +7, +262203, +21, +341, +7, +327745, +277, +278, +276, +51, +262205, +6, +279, +278, +327813, +6, +280, +135, +279, +393281, +260, +281, +155, +156, +67, +262205, +6, +282, +281, +327813, +6, +283, +280, +282, +327811, +6, +284, +283, +141, +327745, +277, +285, +276, +60, +262205, +6, +286, +285, +327813, +6, +287, +135, +286, +393281, +260, +288, +155, +156, +74, +262205, +6, +289, +288, +327813, +6, +290, +287, +289, +327811, +6, +291, +141, +290, +458832, +7, +292, +284, +291, +141, +141, +196670, +274, +292, +327745, +294, +295, +155, +271, +262205, +152, +296, +295, +262205, +7, +297, +274, +327825, +7, +298, +296, +297, +196670, +293, +298, +327745, +302, +303, +155, +301, +262205, +81, +304, +303, +327851, +193, +305, +304, +231, +196855, +307, +0, +262394, +305, +306, +319, +131320, +306, +262205, +7, +310, +308, +458831, +35, +311, +310, +310, +0, +1, +196670, +309, +311, +262205, +7, +313, +308, +458831, +35, +314, +313, +313, +2, +3, +196670, +312, +314, +262205, +7, +316, +274, +458831, +35, +317, +316, +316, +0, +1, +196670, +315, +317, +458809, +6, +318, +41, +309, +312, +315, +196670, +300, +318, +131321, +307, +131320, +319, +196670, +300, +141, +131321, +307, +131320, +307, +262205, +6, +320, +300, +196670, +299, +320, +327745, +260, +322, +155, +321, +262205, +6, +323, +322, +262205, +6, +324, +299, +327813, +6, +325, +324, +323, +196670, +299, +325, +262205, +6, +326, +299, +327745, +260, +327, +155, +82, +262205, +6, +328, +327, +327866, +193, +329, +326, +328, +196855, +331, +0, +262394, +329, +330, +331, +131320, +330, +262205, +7, +334, +276, +458831, +35, +335, +334, +334, +0, +1, +196670, +333, +335, +262205, +7, +337, +332, +524367, +19, +338, +337, +337, +0, +1, +2, +196670, +336, +338, +262205, +6, +340, +299, +196670, +339, +340, +327745, +277, +342, +276, +67, +262205, +6, +343, +342, +196670, +341, +343, +524345, +2, +344, +48, +333, +336, +339, +341, +131321, +331, +131320, +331, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +262203, +14, +50, +7, +262203, +14, +59, +7, +262203, +14, +66, +7, +262203, +14, +73, +7, +327745, +21, +52, +11, +51, +262205, +6, +53, +52, +327813, +6, +55, +53, +54, +262253, +9, +56, +55, +327879, +9, +58, +56, +57, +196670, +50, +58, +327745, +21, +61, +11, +60, +262205, +6, +62, +61, +327813, +6, +63, +62, +54, +262253, +9, +64, +63, +327879, +9, +65, +64, +57, +196670, +59, +65, +327745, +21, +68, +11, +67, +262205, +6, +69, +68, +327813, +6, +70, +69, +54, +262253, +9, +71, +70, +327879, +9, +72, +71, +57, +196670, +66, +72, +327745, +21, +75, +11, +74, +262205, +6, +76, +75, +327813, +6, +77, +76, +54, +262253, +9, +78, +77, +327879, +9, +79, +78, +57, +196670, +73, +79, +262205, +9, +80, +50, +327876, +9, +83, +80, +82, +262205, +9, +84, +59, +327876, +9, +86, +84, +85, +327877, +9, +87, +83, +86, +262205, +9, +88, +66, +327876, +9, +90, +88, +89, +327877, +9, +91, +87, +90, +262205, +9, +92, +73, +327877, +9, +93, +91, +92, +131326, +93, +65592, +327734, +7, +17, +0, +15, +196663, +14, +16, +131320, +18, +262205, +9, +96, +16, +327879, +9, +98, +96, +97, +327874, +9, +99, +98, +82, +262256, +6, +100, +99, +327816, +6, +101, +100, +54, +262205, +9, +102, +16, +327879, +9, +104, +102, +103, +327874, +9, +105, +104, +85, +262256, +6, +106, +105, +327816, +6, +107, +106, +54, +262205, +9, +108, +16, +327879, +9, +110, +108, +109, +327874, +9, +111, +110, +89, +262256, +6, +112, +111, +327816, +6, +113, +112, +54, +262205, +9, +114, +16, +327879, +9, +115, +114, +57, +262256, +6, +116, +115, +327816, +6, +117, +116, +54, +458832, +7, +118, +101, +107, +113, +117, +131326, +118, +65592, +327734, +9, +25, +0, +22, +196663, +20, +23, +196663, +21, +24, +131320, +26, +262203, +8, +131, +7, +262205, +19, +121, +23, +327822, +19, +123, +121, +122, +393296, +19, +124, +122, +122, +122, +327809, +19, +125, +123, +124, +262205, +6, +126, +24, +327761, +6, +127, +125, +0, +327761, +6, +128, +125, +1, +327761, +6, +129, +125, +2, +458832, +7, +130, +127, +128, +129, +126, +196670, +131, +130, +327737, +9, +132, +12, +131, +131326, +132, +65592, +327734, +19, +29, +0, +27, +196663, +14, +28, +131320, +30, +262203, +14, +136, +7, +262205, +9, +137, +28, +196670, +136, +137, +327737, +7, +138, +17, +136, +524367, +19, +139, +138, +138, +0, +1, +2, +327822, +19, +140, +139, +135, +393296, +19, +142, +141, +141, +141, +327811, +19, +143, +140, +142, +131326, +143, +65592, +327734, +6, +33, +0, +31, +196663, +14, +32, +131320, +34, +262203, +14, +146, +7, +262205, +9, +147, +32, +196670, +146, +147, +327737, +7, +148, +17, +146, +327761, +6, +149, +148, +3, +131326, +149, +65592, +327734, +6, +41, +0, +37, +196663, +36, +38, +196663, +36, +39, +196663, +36, +40, +131320, +42, +262203, +21, +178, +7, +262203, +21, +183, +7, +262203, +21, +188, +7, +262203, +194, +195, +7, +262203, +21, +208, +7, +262203, +21, +209, +7, +262203, +21, +215, +7, +327745, +157, +158, +155, +156, +262205, +7, +159, +158, +458831, +35, +160, +159, +159, +0, +1, +262205, +35, +161, +38, +327813, +35, +162, +161, +160, +196670, +38, +162, +327745, +157, +163, +155, +156, +262205, +7, +164, +163, +458831, +35, +165, +164, +164, +0, +1, +262205, +35, +166, +39, +327813, +35, +167, +166, +165, +196670, +39, +167, +327745, +21, +169, +40, +60, +262205, +6, +170, +169, +327813, +6, +171, +170, +168, +327745, +21, +172, +40, +60, +196670, +172, +171, +327745, +157, +173, +155, +156, +262205, +7, +174, +173, +458831, +35, +175, +174, +174, +0, +1, +262205, +35, +176, +40, +327813, +35, +177, +176, +175, +196670, +40, +177, +262205, +35, +179, +38, +262205, +35, +180, +40, +327811, +35, +181, +179, +180, +393228, +6, +182, +1, +66, +181, +196670, +178, +182, +262205, +35, +184, +39, +262205, +35, +185, +40, +327811, +35, +186, +184, +185, +393228, +6, +187, +1, +66, +186, +196670, +183, +187, +262205, +35, +189, +38, +262205, +35, +190, +39, +327811, +35, +191, +189, +190, +393228, +6, +192, +1, +66, +191, +196670, +188, +192, +262205, +6, +196, +188, +262205, +6, +197, +178, +458764, +6, +198, +1, +48, +196, +197, +327866, +193, +200, +198, +199, +262205, +6, +201, +188, +262205, +6, +202, +183, +458764, +6, +203, +1, +48, +201, +202, +327866, +193, +204, +203, +199, +327760, +205, +206, +200, +204, +262298, +193, +207, +206, +196670, +195, +207, +262205, +193, +210, +195, +196855, +212, +0, +262394, +210, +211, +213, +131320, +211, +196670, +209, +168, +131321, +212, +131320, +213, +196670, +209, +141, +131321, +212, +131320, +212, +262205, +6, +214, +209, +196670, +208, +214, +262205, +6, +216, +208, +262205, +6, +217, +178, +262205, +6, +218, +183, +458764, +6, +219, +1, +37, +217, +218, +524300, +6, +220, +1, +43, +219, +199, +141, +327813, +6, +221, +216, +220, +196670, +215, +221, +262205, +6, +222, +215, +327809, +6, +223, +222, +141, +327813, +6, +224, +223, +122, +131326, +224, +65592, +327734, +2, +48, +0, +43, +196663, +36, +44, +196663, +20, +45, +196663, +21, +46, +196663, +21, +47, +131320, +49, +262203, +14, +227, +7, +262203, +235, +236, +7, +262203, +240, +241, +7, +262203, +14, +244, +7, +262203, +20, +264, +7, +262203, +21, +266, +7, +327745, +232, +233, +230, +231, +458986, +9, +234, +233, +60, +51, +60, +196670, +227, +234, +262205, +9, +237, +227, +262268, +81, +238, +237, +196670, +236, +238, +262205, +35, +242, +44, +262254, +239, +243, +242, +196670, +241, +243, +262205, +239, +248, +241, +262205, +9, +249, +227, +393276, +250, +251, +247, +248, +51, +458981, +9, +252, +251, +60, +51, +249, +196670, +244, +252, +262205, +81, +258, +236, +262205, +6, +259, +47, +458817, +260, +261, +257, +231, +258, +231, +196670, +261, +259, +262205, +81, +262, +236, +262205, +19, +265, +45, +196670, +264, +265, +262205, +6, +267, +46, +196670, +266, +267, +393273, +9, +268, +25, +264, +266, +458817, +232, +269, +257, +231, +262, +263, +196670, +269, +268, +262205, +81, +270, +236, +262205, +9, +272, +244, +458817, +232, +273, +257, +231, +270, +271, +196670, +273, +272, +65789, +65592, +}; +const std::vector pass2_vertex = {119734787, +65536, +524289, +75, +0, +131089, +1, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +524303, +0, +4, +1852399981, +0, +58, +62, +70, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +262149, +4, +1852399981, +0, +393221, +12, +1349805415, +1953067887, +678326121, +3879285, +262149, +11, +1701080681, +120, +327685, +17, +1416914279, +829761603, +59, +262149, +16, +1701080681, +120, +393221, +56, +1348430951, +1700164197, +2019914866, +0, +393222, +56, +0, +1348430951, +1953067887, +7237481, +196613, +58, +0, +393221, +62, +1449094247, +1702130277, +1684949368, +30821, +262149, +65, +1634886000, +109, +262149, +70, +2019906678, +0, +262149, +73, +1634886000, +109, +327752, +56, +0, +11, +0, +196679, +56, +2, +262215, +62, +11, +42, +262215, +70, +30, +0, +131091, +2, +196641, +3, +2, +262165, +6, +32, +0, +262176, +7, +7, +6, +196630, +8, +32, +262167, +9, +8, +4, +262177, +10, +9, +7, +262167, +14, +8, +2, +262177, +15, +14, +7, +262187, +8, +25, +3212836864, +262187, +8, +26, +1065353216, +262187, +8, +27, +0, +458796, +9, +28, +25, +26, +27, +26, +262187, +8, +30, +1077936128, +458796, +9, +31, +30, +26, +27, +26, +262187, +8, +33, +3225419776, +458796, +9, +34, +25, +33, +27, +26, +458796, +9, +36, +27, +27, +27, +27, +327724, +14, +46, +27, +27, +262187, +8, +48, +1073741824, +327724, +14, +49, +27, +48, +327724, +14, +51, +48, +27, +196638, +56, +9, +262176, +57, +3, +56, +262203, +57, +58, +3, +262165, +59, +32, +1, +262187, +59, +60, +0, +262176, +61, +1, +59, +262203, +61, +62, +1, +262176, +67, +3, +9, +262176, +69, +3, +14, +262203, +69, +70, +3, +327734, +2, +4, +0, +3, +131320, +5, +262203, +7, +65, +7, +262203, +7, +73, +7, +262205, +59, +63, +62, +262268, +6, +64, +63, +196670, +65, +64, +327737, +9, +66, +12, +65, +327745, +67, +68, +58, +60, +196670, +68, +66, +262205, +59, +71, +62, +262268, +6, +72, +71, +196670, +73, +72, +327737, +14, +74, +17, +73, +196670, +70, +74, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +7, +11, +131320, +13, +262205, +6, +19, +11, +196855, +24, +0, +590075, +19, +23, +0, +20, +1, +21, +2, +22, +131320, +23, +131326, +36, +131320, +20, +131326, +28, +131320, +21, +131326, +31, +131320, +22, +131326, +34, +131320, +24, +196609, +9, +39, +131326, +39, +65592, +327734, +14, +17, +0, +15, +196663, +7, +16, +131320, +18, +262205, +6, +40, +16, +196855, +45, +0, +590075, +40, +44, +0, +41, +1, +42, +2, +43, +131320, +44, +131326, +46, +131320, +41, +131326, +46, +131320, +42, +131326, +49, +131320, +43, +131326, +51, +131320, +45, +196609, +14, +55, +131326, +55, +65592, +}; +const std::vector pass2_fragment = {119734787, +65536, +524289, +1047, +0, +131089, +1, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +458767, +4, +4, +1852399981, +0, +655, +1045, +196624, +4, +7, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +262149, +4, +1852399981, +0, +524293, +12, +1801675088, +1634692166, +1850291316, +1767206772, +1982362734, +3880038, +262149, +11, +1818318454, +25973, +589829, +17, +1634758229, +1767205731, +1850307694, +1816555380, +880042351, +993097000, +0, +262149, +16, +1818318453, +25973, +655365, +25, +1801675088, +1735287124, +1098149477, +1866687598, +1634887030, +1982358887, +1715155814, +15153, +262149, +23, +1735287156, +7630437, +327685, +24, +1702260579, +1701273970, +0, +393221, +29, +1416914247, +1701277281, +1965585518, +15153, +393221, +28, +1801675120, +1632920677, +1852139374, +116, +393221, +33, +1131701575, +1919252079, +677734241, +3879285, +393221, +32, +1801675120, +1866687589, +1634887030, +25959, +524293, +38, +1886220099, +1399157877, +1868849512, +1719019639, +828783411, +59, +327685, +36, +1819438967, +1936674916, +0, +262149, +37, +1752198241, +97, +589829, +42, +1886220099, +1399157877, +1819307369, +1634227045, +678915940, +993224310, +3879270, +327685, +40, +1819438967, +1936674916, +0, +262149, +41, +1752198241, +97, +786437, +50, +1886220099, +1214608501, +1400007009, +1768186216, +1982359406, +1983591270, +1983591270, +1715156070, +1719024433, +15155, +262149, +45, +1936674921, +0, +327685, +46, +1851872361, +1953391975, +0, +262149, +47, +2019906665, +0, +327685, +48, +1970236769, +1766618222, +7628903, +262149, +49, +1869377379, +114, +720901, +57, +1886218579, +1632134508, +1750299241, +1852400737, +1719019623, +1719024435, +1719024435, +828783412, +59, +262149, +53, +1936674921, +0, +327685, +54, +1851872361, +1953391975, +0, +262149, +55, +2019906665, +0, +327685, +56, +1970236769, +1766618222, +7628903, +262149, +59, +1702132066, +51, +262149, +68, +1702132066, +50, +262149, +75, +1702132066, +49, +262149, +82, +1702132066, +48, +262149, +140, +1634886000, +109, +262149, +145, +1634886000, +109, +262149, +155, +1634886000, +109, +393221, +161, +1785688688, +1282633552, +1952999273, +0, +327685, +163, +1936617283, +1953390964, +115, +393222, +163, +0, +1466785639, +1684828783, +0, +393222, +163, +1, +1450008423, +1350002025, +6975346, +458758, +163, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +163, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +163, +4, +1165385575, +25977, +327686, +163, +5, +1986420583, +7761734, +524294, +163, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +163, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +163, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +163, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +163, +10, +1632460647, +1633045364, +6649196, +458758, +163, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +163, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +163, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +163, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +163, +15, +1767333735, +2053722990, +101, +458758, +163, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +163, +17, +1415733095, +1416522088, +28777, +458758, +163, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +163, +19, +1181114215, +1766617697, +7628903, +393222, +163, +20, +1416191847, +1399350117, +77, +458758, +163, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +163, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +163, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +163, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +163, +25, +1214668647, +1265789281, +12915, +393222, +163, +26, +1214668647, +1165125985, +12920, +589830, +163, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +165, +0, +262149, +186, +1400399220, +77, +262149, +196, +1953523044, +104, +262149, +202, +1769173093, +7237484, +393221, +206, +1953523044, +1919311720, +1701668705, +29806, +393221, +209, +1635020660, +1702322028, +1952999273, +0, +458757, +211, +1970236769, +1766618222, +1601464423, +1919508840, +0, +196613, +213, +30820, +196613, +224, +31076, +262149, +232, +1702521203, +0, +262149, +234, +1835493747, +97, +196613, +238, +7370853, +262149, +254, +1734960503, +29800, +327685, +265, +1953523044, +1213027176, +7498081, +393221, +268, +1919508808, +1684105299, +1632466799, +112, +393221, +272, +1634951015, +1768902765, +1816360046, +7368033, +393221, +290, +1953523044, +1836277608, +1852403536, +116, +327685, +308, +1953523044, +1634885480, +6645614, +327685, +313, +1181578606, +1919246953, +115, +458757, +352, +1970236769, +1766618222, +1601464423, +1852138355, +101, +393221, +358, +1785688688, +1282633552, +1952999273, +0, +262149, +375, +1400399220, +77, +262149, +385, +1953523044, +104, +262149, +391, +1769173093, +7237484, +393221, +394, +1953523044, +1919311720, +1701668705, +29806, +458757, +397, +1970236769, +1766618222, +1601464423, +1852138355, +101, +327685, +398, +1953523044, +1213027176, +7498081, +393221, +407, +1953523044, +1836277608, +1852403536, +116, +327685, +422, +1953523044, +1634885480, +6645614, +327685, +427, +1181578606, +1919246953, +115, +458757, +444, +1970236769, +1766618222, +1601464423, +1919508840, +0, +327685, +453, +1702060386, +1869377347, +114, +327685, +459, +1684955506, +1818326623, +25973, +196613, +460, +24907, +196613, +464, +25675, +196613, +467, +3240779, +196613, +470, +3242053, +196613, +473, +3306315, +196613, +477, +3307589, +327685, +481, +1751607660, +1936674932, +0, +327685, +485, +1734954102, +1766093928, +114, +262149, +490, +1702446454, +7498052, +262149, +498, +1735287156, +7630437, +262149, +501, +1416851299, +76, +262149, +505, +1416522099, +76, +262149, +511, +1717987684, +6648693, +262149, +513, +1752198241, +97, +262149, +521, +1416851299, +19538, +262149, +524, +1416522099, +19538, +262149, +526, +1416851299, +69, +262149, +530, +1416522099, +69, +327685, +536, +1416851299, +1918848082, +7630703, +327685, +548, +1416522099, +1918848082, +7630703, +393221, +554, +1667592307, +1918987381, +1869574751, +116, +327685, +563, +1416851299, +1952402514, +28777, +327685, +576, +1416522099, +1952402514, +28777, +393221, +582, +1667592307, +1918987381, +1885959263, +0, +262149, +591, +1819231094, +29295, +327685, +633, +1702060386, +1869377347, +114, +196613, +637, +25675, +262149, +640, +1819231094, +29295, +196613, +653, +7763305, +393221, +655, +1180658791, +1130848626, +1685221231, +0, +393221, +659, +1953720652, +1801680194, +1699247205, +25697, +524293, +662, +1349674320, +1818589289, +1802398028, +1766614117, +1699247219, +25697, +327685, +674, +1718968939, +2053731167, +101, +393221, +688, +1734439494, +1953391981, +1835363397, +7630437, +327686, +688, +0, +1953523044, +104, +524294, +688, +1, +1735287124, +1098149477, +1866687598, +1634887030, +25959, +262149, +692, +1718968939, +0, +458757, +694, +1349674320, +1818589289, +1953720652, +1801680194, +29797, +327686, +694, +0, +1953523044, +104, +524294, +694, +1, +1735287124, +1098149477, +1866687598, +1634887030, +25959, +327686, +694, +2, +1954047342, +0, +458757, +696, +1349674320, +1818589289, +1802398028, +1766614117, +29811, +327686, +696, +0, +1280069712, +0, +196613, +698, +0, +393221, +714, +1953720652, +1801680194, +1682535525, +0, +262149, +716, +1970496882, +29804, +262149, +718, +1718449518, +6775154, +327685, +728, +1601724781, +1953523044, +104, +262149, +729, +1601724781, +7890025, +196613, +730, +105, +196613, +739, +100, +196613, +766, +7368052, +262149, +778, +1970302324, +0, +196613, +790, +100, +262149, +794, +1348691054, +29551, +196613, +815, +7565136, +262149, +829, +1735287124, +7630437, +262149, +831, +1634886000, +109, +393221, +835, +1734439494, +1953391981, +1752198209, +97, +262149, +837, +1634886000, +109, +393221, +841, +1970236769, +1716483182, +1751607628, +116, +262149, +843, +1634886000, +109, +262149, +846, +1634886000, +109, +393221, +850, +1734439494, +1953391981, +1869377347, +114, +262149, +852, +1634886000, +109, +262149, +855, +1634886000, +109, +262149, +857, +1634886000, +109, +262149, +858, +1634886000, +109, +262149, +881, +1702258034, +6648690, +327685, +883, +1867740009, +1684370546, +0, +196613, +893, +105, +196613, +913, +7368052, +262149, +927, +1886221428, +0, +196613, +945, +105, +196613, +954, +100, +262149, +958, +1348691054, +29551, +196613, +977, +7565136, +262149, +991, +1735287124, +7630437, +262149, +993, +1634886000, +109, +393221, +997, +1734439494, +1953391981, +1752198209, +97, +262149, +999, +1634886000, +109, +393221, +1003, +1970236769, +1716483182, +1751607628, +116, +262149, +1004, +1634886000, +109, +262149, +1007, +1634886000, +109, +393221, +1011, +1734439494, +1953391981, +1869377347, +114, +262149, +1012, +1634886000, +109, +262149, +1015, +1634886000, +109, +262149, +1017, +1634886000, +109, +262149, +1018, +1634886000, +109, +262149, +1020, +1634886000, +109, +327685, +1045, +1734439494, +1869377347, +114, +262216, +163, +0, +5, +327752, +163, +0, +35, +0, +327752, +163, +0, +7, +16, +262216, +163, +1, +5, +327752, +163, +1, +35, +64, +327752, +163, +1, +7, +16, +262216, +163, +2, +5, +327752, +163, +2, +35, +128, +327752, +163, +2, +7, +16, +262216, +163, +3, +5, +327752, +163, +3, +35, +192, +327752, +163, +3, +7, +16, +327752, +163, +4, +35, +256, +327752, +163, +5, +35, +268, +327752, +163, +6, +35, +272, +327752, +163, +7, +35, +288, +327752, +163, +8, +35, +304, +327752, +163, +9, +35, +320, +327752, +163, +10, +35, +336, +327752, +163, +11, +35, +352, +327752, +163, +12, +35, +356, +327752, +163, +13, +35, +360, +327752, +163, +14, +35, +364, +327752, +163, +15, +35, +368, +327752, +163, +16, +35, +384, +327752, +163, +17, +35, +388, +327752, +163, +18, +35, +392, +327752, +163, +19, +35, +396, +327752, +163, +20, +35, +400, +327752, +163, +21, +35, +404, +327752, +163, +22, +35, +408, +327752, +163, +23, +35, +412, +327752, +163, +24, +35, +416, +327752, +163, +25, +35, +420, +327752, +163, +26, +35, +424, +262216, +163, +27, +5, +327752, +163, +27, +35, +432, +327752, +163, +27, +7, +16, +196679, +163, +2, +262215, +165, +34, +0, +262215, +165, +33, +16, +262215, +268, +34, +0, +262215, +268, +33, +3, +262215, +272, +34, +0, +262215, +272, +33, +19, +262215, +655, +11, +15, +262215, +662, +34, +0, +262215, +662, +33, +1, +196679, +662, +19, +327752, +694, +0, +35, +0, +327752, +694, +1, +35, +4, +327752, +694, +2, +35, +8, +262215, +695, +6, +12, +327752, +696, +0, +35, +0, +196679, +696, +3, +262215, +698, +34, +0, +262215, +698, +33, +0, +262215, +1045, +30, +0, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +262165, +9, +32, +0, +262177, +10, +9, +8, +262176, +14, +7, +9, +262177, +15, +7, +14, +262167, +19, +6, +3, +262176, +20, +7, +19, +262176, +21, +7, +6, +327713, +22, +9, +20, +21, +262177, +27, +19, +14, +262177, +31, +6, +14, +327713, +35, +6, +20, +21, +524321, +44, +19, +20, +20, +8, +21, +20, +458785, +52, +19, +20, +20, +8, +21, +262187, +9, +60, +0, +262187, +6, +63, +1132396544, +262187, +9, +66, +255, +262187, +9, +69, +1, +262187, +9, +76, +2, +262187, +9, +83, +3, +262165, +90, +32, +1, +262187, +90, +91, +24, +262187, +90, +94, +16, +262187, +90, +98, +8, +262187, +9, +106, +4278190080, +262187, +9, +112, +16711680, +262187, +9, +118, +65280, +262187, +6, +131, +1056964608, +262187, +6, +144, +1073741824, +262187, +6, +150, +1065353216, +262168, +162, +7, +4, +1966110, +163, +162, +162, +162, +162, +19, +6, +7, +7, +7, +7, +7, +6, +6, +6, +6, +7, +6, +6, +6, +6, +90, +90, +90, +90, +6, +6, +6, +162, +262176, +164, +2, +163, +262203, +164, +165, +2, +262187, +90, +166, +3, +262176, +167, +2, +162, +262167, +178, +6, +2, +262176, +185, +7, +178, +262187, +6, +204, +1008981770, +262187, +6, +210, +0, +262176, +212, +7, +90, +262187, +90, +214, +4294967294, +262187, +90, +221, +2, +131092, +222, +262187, +6, +233, +1075419546, +262187, +6, +235, +1075838976, +262187, +90, +239, +4294967295, +262187, +6, +255, +1086911939, +262187, +6, +261, +1076677837, +589849, +266, +6, +1, +0, +0, +0, +1, +0, +262176, +267, +0, +266, +262203, +267, +268, +0, +131098, +270, +262176, +271, +0, +270, +262203, +271, +272, +0, +196635, +274, +266, +262187, +6, +282, +1142947840, +262187, +90, +291, +18, +262176, +292, +2, +6, +262187, +90, +296, +19, +262187, +90, +317, +14, +262187, +6, +324, +925353388, +262187, +90, +345, +1, +262187, +90, +454, +9, +262176, +455, +2, +7, +262187, +90, +461, +10, +262187, +90, +474, +25, +262187, +90, +478, +26, +262187, +90, +491, +4, +262176, +492, +2, +19, +262187, +6, +515, +1092616192, +262187, +6, +517, +1078523331, +262187, +6, +519, +1127481344, +262187, +6, +565, +3225419776, +262187, +90, +593, +6, +262187, +90, +601, +7, +262167, +651, +90, +2, +262176, +652, +7, +651, +262176, +654, +1, +7, +262203, +654, +655, +1, +589849, +660, +9, +1, +0, +0, +0, +2, +33, +262176, +661, +0, +660, +262203, +661, +662, +0, +262167, +665, +9, +4, +262187, +9, +669, +4294967295, +262187, +90, +675, +0, +262174, +688, +6, +9, +262187, +9, +689, +8, +262172, +690, +688, +689, +262176, +691, +7, +690, +327710, +694, +6, +9, +9, +196637, +695, +694, +196638, +696, +695, +262176, +697, +2, +696, +262203, +697, +698, +2, +262176, +705, +2, +9, +458796, +7, +717, +210, +210, +210, +150, +262176, +795, +1, +6, +262187, +90, +798, +15, +262187, +90, +842, +12, +458796, +7, +851, +210, +210, +210, +210, +262176, +882, +7, +222, +196650, +222, +884, +196649, +222, +892, +262176, +1044, +3, +7, +262203, +1044, +1045, +3, +327734, +2, +4, +0, +3, +131320, +5, +262203, +652, +653, +7, +262203, +14, +659, +7, +262203, +212, +674, +7, +262203, +691, +692, +7, +262203, +14, +714, +7, +262203, +8, +716, +7, +262203, +14, +718, +7, +262203, +21, +728, +7, +262203, +14, +729, +7, +262203, +212, +730, +7, +262203, +21, +739, +7, +262203, +14, +746, +7, +262203, +21, +766, +7, +262203, +14, +778, +7, +262203, +21, +790, +7, +262203, +20, +794, +7, +262203, +8, +815, +7, +262203, +20, +829, +7, +262203, +14, +831, +7, +262203, +21, +835, +7, +262203, +14, +837, +7, +262203, +21, +841, +7, +262203, +20, +843, +7, +262203, +21, +846, +7, +262203, +20, +850, +7, +262203, +20, +852, +7, +262203, +20, +855, +7, +262203, +8, +857, +7, +262203, +21, +858, +7, +262203, +14, +881, +7, +262203, +882, +883, +7, +262203, +212, +893, +7, +262203, +21, +913, +7, +262203, +14, +927, +7, +262203, +212, +945, +7, +262203, +21, +954, +7, +262203, +20, +958, +7, +262203, +8, +977, +7, +262203, +20, +991, +7, +262203, +14, +993, +7, +262203, +21, +997, +7, +262203, +14, +999, +7, +262203, +21, +1003, +7, +262203, +20, +1004, +7, +262203, +21, +1007, +7, +262203, +20, +1011, +7, +262203, +20, +1012, +7, +262203, +20, +1015, +7, +262203, +8, +1017, +7, +262203, +21, +1018, +7, +262203, +20, +1020, +7, +262205, +7, +656, +655, +458831, +178, +657, +656, +656, +0, +1, +262254, +651, +658, +657, +196670, +653, +658, +262205, +660, +663, +662, +262205, +651, +664, +653, +327778, +665, +666, +663, +664, +327761, +9, +667, +666, +0, +196670, +659, +667, +262205, +9, +668, +659, +327850, +222, +670, +668, +669, +196855, +672, +0, +262394, +670, +671, +672, +131320, +671, +65788, +131320, +672, +196670, +674, +675, +131321, +676, +131320, +676, +262390, +678, +679, +0, +131321, +680, +131320, +680, +262205, +90, +681, +674, +327857, +222, +682, +681, +98, +262394, +682, +677, +678, +131320, +677, +262205, +9, +683, +659, +327850, +222, +684, +683, +669, +196855, +686, +0, +262394, +684, +685, +686, +131320, +685, +131321, +678, +131320, +686, +262205, +90, +693, +674, +262205, +9, +699, +659, +458817, +292, +700, +698, +675, +699, +675, +262205, +6, +701, +700, +393281, +21, +702, +692, +693, +675, +196670, +702, +701, +262205, +90, +703, +674, +262205, +9, +704, +659, +458817, +705, +706, +698, +675, +704, +345, +262205, +9, +707, +706, +393281, +14, +708, +692, +703, +345, +196670, +708, +707, +262205, +9, +709, +659, +458817, +705, +710, +698, +675, +709, +221, +262205, +9, +711, +710, +196670, +659, +711, +131321, +679, +131320, +679, +262205, +90, +712, +674, +327808, +90, +713, +712, +345, +196670, +674, +713, +131321, +676, +131320, +678, +262205, +9, +715, +659, +196670, +714, +715, +196670, +716, +717, +196670, +718, +60, +131321, +719, +131320, +719, +262390, +721, +722, +0, +131321, +723, +131320, +723, +262205, +9, +724, +714, +327851, +222, +725, +724, +669, +262394, +725, +720, +721, +131320, +720, +262205, +9, +726, +718, +327808, +9, +727, +726, +345, +196670, +718, +727, +196670, +728, +210, +196670, +729, +60, +196670, +730, +675, +131321, +731, +131320, +731, +262390, +733, +734, +0, +131321, +735, +131320, +735, +262205, +90, +736, +730, +262205, +90, +737, +674, +327857, +222, +738, +736, +737, +262394, +738, +732, +733, +131320, +732, +262205, +90, +740, +730, +393281, +21, +741, +692, +740, +675, +262205, +6, +742, +741, +196670, +739, +742, +262205, +6, +743, +728, +262205, +6, +744, +739, +458764, +6, +745, +1, +40, +743, +744, +196670, +728, +745, +262205, +6, +747, +728, +262205, +6, +748, +739, +327860, +222, +749, +747, +748, +196855, +751, +0, +262394, +749, +750, +754, +131320, +750, +262205, +90, +752, +730, +262268, +9, +753, +752, +196670, +746, +753, +131321, +751, +131320, +754, +262205, +9, +755, +729, +196670, +746, +755, +131321, +751, +131320, +751, +262205, +9, +756, +746, +196670, +729, +756, +131321, +734, +131320, +734, +262205, +90, +757, +730, +327808, +90, +758, +757, +345, +196670, +730, +758, +131321, +731, +131320, +733, +262205, +9, +759, +714, +458817, +292, +760, +698, +675, +759, +675, +262205, +6, +761, +760, +262205, +6, +762, +728, +327864, +222, +763, +761, +762, +196855, +765, +0, +262394, +763, +764, +765, +131320, +764, +262205, +9, +767, +714, +458817, +292, +768, +698, +675, +767, +675, +262205, +6, +769, +768, +196670, +766, +769, +262205, +9, +770, +714, +262205, +9, +771, +729, +393281, +21, +772, +692, +771, +675, +262205, +6, +773, +772, +458817, +292, +774, +698, +675, +770, +675, +196670, +774, +773, +262205, +9, +775, +729, +262205, +6, +776, +766, +393281, +21, +777, +692, +775, +675, +196670, +777, +776, +262205, +9, +779, +714, +458817, +705, +780, +698, +675, +779, +345, +262205, +9, +781, +780, +196670, +778, +781, +262205, +9, +782, +714, +262205, +9, +783, +729, +393281, +14, +784, +692, +783, +345, +262205, +9, +785, +784, +458817, +705, +786, +698, +675, +782, +345, +196670, +786, +785, +262205, +9, +787, +729, +262205, +9, +788, +778, +393281, +14, +789, +692, +787, +345, +196670, +789, +788, +131321, +765, +131320, +765, +262205, +9, +791, +714, +458817, +292, +792, +698, +675, +791, +675, +262205, +6, +793, +792, +196670, +790, +793, +327745, +795, +796, +655, +60, +262205, +6, +797, +796, +393281, +292, +799, +165, +798, +76, +262205, +6, +800, +799, +327813, +6, +801, +797, +800, +327745, +795, +802, +655, +69, +262205, +6, +803, +802, +393281, +292, +804, +165, +798, +83, +262205, +6, +805, +804, +327813, +6, +806, +803, +805, +327811, +6, +807, +150, +806, +262205, +6, +808, +790, +393296, +19, +809, +801, +807, +808, +327822, +19, +810, +809, +144, +393296, +19, +811, +150, +150, +150, +327811, +19, +812, +810, +811, +196670, +794, +812, +262205, +6, +813, +790, +327745, +21, +814, +794, +76, +196670, +814, +813, +327745, +167, +816, +165, +221, +262205, +162, +817, +816, +262205, +19, +818, +794, +327761, +6, +819, +818, +0, +327761, +6, +820, +818, +1, +327761, +6, +821, +818, +2, +458832, +7, +822, +819, +820, +821, +150, +327825, +7, +823, +817, +822, +196670, +815, +823, +327745, +21, +824, +815, +83, +262205, +6, +825, +824, +262205, +7, +826, +815, +458832, +7, +827, +825, +825, +825, +825, +327816, +7, +828, +826, +827, +196670, +815, +828, +262205, +9, +830, +714, +458817, +705, +832, +698, +675, +830, +345, +262205, +9, +833, +832, +196670, +831, +833, +327737, +19, +834, +29, +831, +196670, +829, +834, +262205, +9, +836, +714, +458817, +705, +838, +698, +675, +836, +345, +262205, +9, +839, +838, +196670, +837, +839, +327737, +6, +840, +33, +837, +196670, +835, +840, +262205, +7, +844, +815, +524367, +19, +845, +844, +844, +0, +1, +2, +196670, +843, +845, +327745, +292, +847, +165, +842, +262205, +6, +848, +847, +196670, +846, +848, +393273, +6, +849, +42, +843, +846, +196670, +841, +849, +262205, +7, +853, +815, +524367, +19, +854, +853, +853, +0, +1, +2, +196670, +852, +854, +262205, +19, +856, +829, +196670, +855, +856, +196670, +857, +851, +262205, +6, +859, +841, +196670, +858, +859, +524345, +19, +860, +57, +852, +855, +857, +858, +196670, +850, +860, +262205, +7, +861, +716, +524367, +19, +862, +861, +861, +0, +1, +2, +262205, +6, +863, +835, +327811, +6, +864, +150, +863, +327822, +19, +865, +862, +864, +262205, +6, +866, +835, +262205, +19, +867, +850, +327822, +19, +868, +867, +866, +327809, +19, +869, +865, +868, +262205, +7, +870, +716, +589903, +7, +871, +870, +869, +4, +5, +6, +3, +196670, +716, +871, +262205, +6, +872, +835, +327811, +6, +873, +150, +872, +327745, +21, +874, +716, +83, +262205, +6, +875, +874, +327813, +6, +876, +875, +873, +327745, +21, +877, +716, +83, +196670, +877, +876, +262205, +9, +878, +714, +458817, +705, +879, +698, +675, +878, +221, +262205, +9, +880, +879, +196670, +714, +880, +131321, +722, +131320, +722, +131321, +719, +131320, +721, +196670, +881, +60, +196670, +883, +884, +131321, +885, +131320, +885, +262390, +887, +888, +0, +131321, +889, +131320, +889, +262205, +222, +890, +883, +262312, +222, +891, +890, +262394, +891, +886, +887, +131320, +886, +196670, +883, +892, +196670, +893, +675, +131321, +894, +131320, +894, +262390, +896, +897, +0, +131321, +898, +131320, +898, +262205, +90, +899, +893, +262205, +90, +900, +674, +327810, +90, +901, +900, +345, +327857, +222, +902, +899, +901, +262394, +902, +895, +896, +131320, +895, +262205, +90, +903, +893, +393281, +21, +904, +692, +903, +675, +262205, +6, +905, +904, +262205, +90, +906, +893, +327808, +90, +907, +906, +345, +393281, +21, +908, +692, +907, +675, +262205, +6, +909, +908, +327864, +222, +910, +905, +909, +196855, +912, +0, +262394, +910, +911, +912, +131320, +911, +196670, +883, +884, +262205, +90, +914, +893, +393281, +21, +915, +692, +914, +675, +262205, +6, +916, +915, +196670, +913, +916, +262205, +90, +917, +893, +262205, +90, +918, +893, +327808, +90, +919, +918, +345, +393281, +21, +920, +692, +919, +675, +262205, +6, +921, +920, +393281, +21, +922, +692, +917, +675, +196670, +922, +921, +262205, +90, +923, +893, +327808, +90, +924, +923, +345, +262205, +6, +925, +913, +393281, +21, +926, +692, +924, +675, +196670, +926, +925, +262205, +90, +928, +893, +393281, +14, +929, +692, +928, +345, +262205, +9, +930, +929, +196670, +927, +930, +262205, +90, +931, +893, +262205, +90, +932, +893, +327808, +90, +933, +932, +345, +393281, +14, +934, +692, +933, +345, +262205, +9, +935, +934, +393281, +14, +936, +692, +931, +345, +196670, +936, +935, +262205, +90, +937, +893, +327808, +90, +938, +937, +345, +262205, +9, +939, +927, +393281, +14, +940, +692, +938, +345, +196670, +940, +939, +262205, +9, +941, +881, +327808, +9, +942, +941, +345, +196670, +881, +942, +131321, +912, +131320, +912, +131321, +897, +131320, +897, +262205, +90, +943, +893, +327808, +90, +944, +943, +345, +196670, +893, +944, +131321, +894, +131320, +896, +131321, +888, +131320, +888, +131321, +885, +131320, +887, +196670, +945, +675, +131321, +946, +131320, +946, +262390, +948, +949, +0, +131321, +950, +131320, +950, +262205, +90, +951, +945, +262205, +90, +952, +674, +327857, +222, +953, +951, +952, +262394, +953, +947, +948, +131320, +947, +262205, +90, +955, +945, +393281, +21, +956, +692, +955, +675, +262205, +6, +957, +956, +196670, +954, +957, +327745, +795, +959, +655, +60, +262205, +6, +960, +959, +393281, +292, +961, +165, +798, +76, +262205, +6, +962, +961, +327813, +6, +963, +960, +962, +327745, +795, +964, +655, +69, +262205, +6, +965, +964, +393281, +292, +966, +165, +798, +83, +262205, +6, +967, +966, +327813, +6, +968, +965, +967, +327811, +6, +969, +150, +968, +262205, +6, +970, +954, +393296, +19, +971, +963, +969, +970, +327822, +19, +972, +971, +144, +393296, +19, +973, +150, +150, +150, +327811, +19, +974, +972, +973, +196670, +958, +974, +262205, +6, +975, +954, +327745, +21, +976, +958, +76, +196670, +976, +975, +327745, +167, +978, +165, +221, +262205, +162, +979, +978, +262205, +19, +980, +958, +327761, +6, +981, +980, +0, +327761, +6, +982, +980, +1, +327761, +6, +983, +980, +2, +458832, +7, +984, +981, +982, +983, +150, +327825, +7, +985, +979, +984, +196670, +977, +985, +327745, +21, +986, +977, +83, +262205, +6, +987, +986, +262205, +7, +988, +977, +458832, +7, +989, +987, +987, +987, +987, +327816, +7, +990, +988, +989, +196670, +977, +990, +262205, +90, +992, +945, +393281, +14, +994, +692, +992, +345, +262205, +9, +995, +994, +196670, +993, +995, +327737, +19, +996, +29, +993, +196670, +991, +996, +262205, +90, +998, +945, +393281, +14, +1000, +692, +998, +345, +262205, +9, +1001, +1000, +196670, +999, +1001, +327737, +6, +1002, +33, +999, +196670, +997, +1002, +262205, +7, +1005, +977, +524367, +19, +1006, +1005, +1005, +0, +1, +2, +196670, +1004, +1006, +327745, +292, +1008, +165, +842, +262205, +6, +1009, +1008, +196670, +1007, +1009, +393273, +6, +1010, +38, +1004, +1007, +196670, +1003, +1010, +262205, +7, +1013, +977, +524367, +19, +1014, +1013, +1013, +0, +1, +2, +196670, +1012, +1014, +262205, +19, +1016, +991, +196670, +1015, +1016, +196670, +1017, +851, +262205, +6, +1019, +1003, +196670, +1018, +1019, +327745, +455, +1021, +165, +454, +262205, +7, +1022, +1021, +524367, +19, +1023, +1022, +1022, +0, +1, +2, +196670, +1020, +1023, +589881, +19, +1024, +50, +1012, +1015, +1017, +1018, +1020, +196670, +1011, +1024, +262205, +7, +1025, +716, +524367, +19, +1026, +1025, +1025, +0, +1, +2, +262205, +6, +1027, +997, +327811, +6, +1028, +150, +1027, +327822, +19, +1029, +1026, +1028, +262205, +6, +1030, +997, +262205, +19, +1031, +1011, +327822, +19, +1032, +1031, +1030, +327809, +19, +1033, +1029, +1032, +262205, +7, +1034, +716, +589903, +7, +1035, +1034, +1033, +4, +5, +6, +3, +196670, +716, +1035, +262205, +6, +1036, +997, +327811, +6, +1037, +150, +1036, +327745, +21, +1038, +716, +83, +262205, +6, +1039, +1038, +327813, +6, +1040, +1039, +1037, +327745, +21, +1041, +716, +83, +196670, +1041, +1040, +131321, +949, +131320, +949, +262205, +90, +1042, +945, +327808, +90, +1043, +1042, +345, +196670, +945, +1043, +131321, +946, +131320, +948, +262205, +7, +1046, +716, +196670, +1045, +1046, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +262203, +14, +59, +7, +262203, +14, +68, +7, +262203, +14, +75, +7, +262203, +14, +82, +7, +327745, +21, +61, +11, +60, +262205, +6, +62, +61, +327813, +6, +64, +62, +63, +262253, +9, +65, +64, +327879, +9, +67, +65, +66, +196670, +59, +67, +327745, +21, +70, +11, +69, +262205, +6, +71, +70, +327813, +6, +72, +71, +63, +262253, +9, +73, +72, +327879, +9, +74, +73, +66, +196670, +68, +74, +327745, +21, +77, +11, +76, +262205, +6, +78, +77, +327813, +6, +79, +78, +63, +262253, +9, +80, +79, +327879, +9, +81, +80, +66, +196670, +75, +81, +327745, +21, +84, +11, +83, +262205, +6, +85, +84, +327813, +6, +86, +85, +63, +262253, +9, +87, +86, +327879, +9, +88, +87, +66, +196670, +82, +88, +262205, +9, +89, +59, +327876, +9, +92, +89, +91, +262205, +9, +93, +68, +327876, +9, +95, +93, +94, +327877, +9, +96, +92, +95, +262205, +9, +97, +75, +327876, +9, +99, +97, +98, +327877, +9, +100, +96, +99, +262205, +9, +101, +82, +327877, +9, +102, +100, +101, +131326, +102, +65592, +327734, +7, +17, +0, +15, +196663, +14, +16, +131320, +18, +262205, +9, +105, +16, +327879, +9, +107, +105, +106, +327874, +9, +108, +107, +91, +262256, +6, +109, +108, +327816, +6, +110, +109, +63, +262205, +9, +111, +16, +327879, +9, +113, +111, +112, +327874, +9, +114, +113, +94, +262256, +6, +115, +114, +327816, +6, +116, +115, +63, +262205, +9, +117, +16, +327879, +9, +119, +117, +118, +327874, +9, +120, +119, +98, +262256, +6, +121, +120, +327816, +6, +122, +121, +63, +262205, +9, +123, +16, +327879, +9, +124, +123, +66, +262256, +6, +125, +124, +327816, +6, +126, +125, +63, +458832, +7, +127, +110, +116, +122, +126, +131326, +127, +65592, +327734, +9, +25, +0, +22, +196663, +20, +23, +196663, +21, +24, +131320, +26, +262203, +8, +140, +7, +262205, +19, +130, +23, +327822, +19, +132, +130, +131, +393296, +19, +133, +131, +131, +131, +327809, +19, +134, +132, +133, +262205, +6, +135, +24, +327761, +6, +136, +134, +0, +327761, +6, +137, +134, +1, +327761, +6, +138, +134, +2, +458832, +7, +139, +136, +137, +138, +135, +196670, +140, +139, +327737, +9, +141, +12, +140, +131326, +141, +65592, +327734, +19, +29, +0, +27, +196663, +14, +28, +131320, +30, +262203, +14, +145, +7, +262205, +9, +146, +28, +196670, +145, +146, +327737, +7, +147, +17, +145, +524367, +19, +148, +147, +147, +0, +1, +2, +327822, +19, +149, +148, +144, +393296, +19, +151, +150, +150, +150, +327811, +19, +152, +149, +151, +131326, +152, +65592, +327734, +6, +33, +0, +31, +196663, +14, +32, +131320, +34, +262203, +14, +155, +7, +262205, +9, +156, +32, +196670, +155, +156, +327737, +7, +157, +17, +155, +327761, +6, +158, +157, +3, +131326, +158, +65592, +327734, +6, +38, +0, +35, +196663, +20, +36, +196663, +21, +37, +131320, +39, +262203, +8, +161, +7, +262203, +185, +186, +7, +262203, +21, +196, +7, +262203, +21, +202, +7, +262203, +21, +206, +7, +262203, +21, +209, +7, +262203, +21, +211, +7, +262203, +212, +213, +7, +262203, +212, +224, +7, +262203, +21, +232, +7, +262203, +21, +234, +7, +262203, +21, +238, +7, +262203, +21, +254, +7, +262203, +21, +265, +7, +262203, +21, +290, +7, +262203, +21, +308, +7, +262203, +21, +313, +7, +262203, +21, +322, +7, +262203, +21, +352, +7, +327745, +167, +168, +165, +166, +262205, +162, +169, +168, +262205, +19, +170, +36, +327761, +6, +171, +170, +0, +327761, +6, +172, +170, +1, +327761, +6, +173, +170, +2, +458832, +7, +174, +171, +172, +173, +150, +327825, +7, +175, +169, +174, +196670, +161, +175, +327745, +21, +176, +161, +83, +262205, +6, +177, +176, +262205, +7, +179, +161, +458831, +178, +180, +179, +179, +0, +1, +327760, +178, +181, +177, +177, +327816, +178, +182, +180, +181, +262205, +7, +183, +161, +589903, +7, +184, +183, +182, +4, +5, +2, +3, +196670, +161, +184, +262205, +7, +187, +161, +458831, +178, +188, +187, +187, +0, +1, +327822, +178, +189, +188, +131, +327760, +178, +190, +131, +131, +327809, +178, +191, +189, +190, +196670, +186, +191, +327745, +21, +192, +186, +69, +262205, +6, +193, +192, +327811, +6, +194, +150, +193, +327745, +21, +195, +186, +69, +196670, +195, +194, +327745, +21, +197, +161, +76, +262205, +6, +198, +197, +327745, +21, +199, +161, +83, +262205, +6, +200, +199, +327816, +6, +201, +198, +200, +196670, +196, +201, +262205, +6, +203, +196, +327813, +6, +205, +203, +204, +196670, +202, +205, +327745, +21, +207, +161, +83, +262205, +6, +208, +207, +196670, +206, +208, +196670, +209, +210, +196670, +211, +210, +196670, +209, +210, +196670, +213, +214, +131321, +215, +131320, +215, +262390, +217, +218, +0, +131321, +219, +131320, +219, +262205, +90, +220, +213, +327859, +222, +223, +220, +221, +262394, +223, +216, +217, +131320, +216, +196670, +224, +214, +131321, +225, +131320, +225, +262390, +227, +228, +0, +131321, +229, +131320, +229, +262205, +90, +230, +224, +327859, +222, +231, +230, +221, +262394, +231, +226, +227, +131320, +226, +196670, +232, +233, +262205, +6, +236, +232, +327816, +6, +237, +235, +236, +196670, +234, +237, +262205, +90, +240, +213, +262205, +90, +241, +213, +327812, +90, +242, +240, +241, +262205, +90, +243, +224, +262205, +90, +244, +224, +327812, +90, +245, +243, +244, +327808, +90, +246, +242, +245, +327812, +90, +247, +239, +246, +262255, +6, +248, +247, +262205, +6, +249, +234, +327813, +6, +250, +144, +249, +262205, +6, +251, +234, +327813, +6, +252, +250, +251, +327816, +6, +253, +248, +252, +196670, +238, +253, +262205, +6, +256, +234, +327813, +6, +257, +255, +256, +262205, +6, +258, +234, +327813, +6, +259, +257, +258, +327816, +6, +260, +150, +259, +262205, +6, +262, +238, +458764, +6, +263, +1, +26, +261, +262, +327813, +6, +264, +260, +263, +196670, +254, +264, +262205, +266, +269, +268, +262205, +270, +273, +272, +327766, +274, +275, +269, +273, +262205, +178, +276, +186, +262205, +90, +277, +213, +262255, +6, +278, +277, +262205, +90, +279, +224, +262255, +6, +280, +279, +327760, +178, +281, +278, +280, +327760, +178, +283, +282, +282, +327816, +178, +284, +281, +283, +327809, +178, +285, +276, +284, +327767, +7, +286, +275, +285, +327761, +6, +287, +286, +0, +327813, +6, +288, +144, +287, +327811, +6, +289, +288, +150, +196670, +265, +289, +327745, +292, +293, +165, +291, +262205, +6, +294, +293, +262205, +6, +295, +265, +327745, +292, +297, +165, +296, +262205, +6, +298, +297, +327745, +292, +299, +165, +291, +262205, +6, +300, +299, +327811, +6, +301, +298, +300, +327813, +6, +302, +295, +301, +327745, +292, +303, +165, +296, +262205, +6, +304, +303, +327816, +6, +305, +302, +304, +327811, +6, +306, +150, +305, +327816, +6, +307, +294, +306, +196670, +290, +307, +262205, +6, +309, +206, +262205, +6, +310, +290, +327811, +6, +311, +309, +310, +458764, +6, +312, +1, +40, +210, +311, +196670, +308, +312, +262205, +6, +314, +308, +327745, +292, +315, +165, +94, +262205, +6, +316, +315, +327745, +292, +318, +165, +317, +262205, +6, +319, +318, +327813, +6, +320, +316, +319, +327816, +6, +321, +314, +320, +196670, +313, +321, +262205, +6, +323, +308, +327866, +222, +325, +323, +324, +196855, +327, +0, +262394, +325, +326, +328, +131320, +326, +196670, +322, +150, +131321, +327, +131320, +328, +196670, +322, +210, +131321, +327, +131320, +327, +262205, +6, +329, +322, +262205, +6, +330, +313, +327809, +6, +331, +330, +329, +196670, +313, +331, +262205, +6, +332, +37, +327811, +6, +333, +150, +332, +393228, +6, +334, +1, +4, +333, +262205, +6, +335, +313, +458764, +6, +336, +1, +26, +334, +335, +262205, +6, +337, +254, +327813, +6, +338, +336, +337, +262205, +6, +339, +211, +327809, +6, +340, +339, +338, +196670, +211, +340, +262205, +6, +341, +254, +262205, +6, +342, +209, +327809, +6, +343, +342, +341, +196670, +209, +343, +131321, +228, +131320, +228, +262205, +90, +344, +224, +327808, +90, +346, +344, +345, +196670, +224, +346, +131321, +225, +131320, +227, +131321, +218, +131320, +218, +262205, +90, +347, +213, +327808, +90, +348, +347, +345, +196670, +213, +348, +131321, +215, +131320, +217, +262205, +6, +349, +209, +262205, +6, +350, +211, +327816, +6, +351, +350, +349, +196670, +211, +351, +196670, +352, +150, +262205, +6, +353, +211, +262205, +6, +354, +352, +327813, +6, +355, +353, +354, +131326, +355, +65592, +327734, +6, +42, +0, +35, +196663, +20, +40, +196663, +21, +41, +131320, +43, +262203, +8, +358, +7, +262203, +185, +375, +7, +262203, +21, +385, +7, +262203, +21, +391, +7, +262203, +21, +394, +7, +262203, +21, +397, +7, +262203, +21, +398, +7, +262203, +21, +407, +7, +262203, +21, +422, +7, +262203, +21, +427, +7, +262203, +21, +435, +7, +262203, +21, +444, +7, +327745, +167, +359, +165, +166, +262205, +162, +360, +359, +262205, +19, +361, +40, +327761, +6, +362, +361, +0, +327761, +6, +363, +361, +1, +327761, +6, +364, +361, +2, +458832, +7, +365, +362, +363, +364, +150, +327825, +7, +366, +360, +365, +196670, +358, +366, +327745, +21, +367, +358, +83, +262205, +6, +368, +367, +262205, +7, +369, +358, +458831, +178, +370, +369, +369, +0, +1, +327760, +178, +371, +368, +368, +327816, +178, +372, +370, +371, +262205, +7, +373, +358, +589903, +7, +374, +373, +372, +4, +5, +2, +3, +196670, +358, +374, +262205, +7, +376, +358, +458831, +178, +377, +376, +376, +0, +1, +327822, +178, +378, +377, +131, +327760, +178, +379, +131, +131, +327809, +178, +380, +378, +379, +196670, +375, +380, +327745, +21, +381, +375, +69, +262205, +6, +382, +381, +327811, +6, +383, +150, +382, +327745, +21, +384, +375, +69, +196670, +384, +383, +327745, +21, +386, +358, +76, +262205, +6, +387, +386, +327745, +21, +388, +358, +83, +262205, +6, +389, +388, +327816, +6, +390, +387, +389, +196670, +385, +390, +262205, +6, +392, +385, +327813, +6, +393, +392, +204, +196670, +391, +393, +327745, +21, +395, +358, +83, +262205, +6, +396, +395, +196670, +394, +396, +196670, +397, +150, +262205, +266, +399, +268, +262205, +270, +400, +272, +327766, +274, +401, +399, +400, +262205, +178, +402, +375, +327767, +7, +403, +401, +402, +327761, +6, +404, +403, +0, +327813, +6, +405, +144, +404, +327811, +6, +406, +405, +150, +196670, +398, +406, +327745, +292, +408, +165, +291, +262205, +6, +409, +408, +262205, +6, +410, +398, +327745, +292, +411, +165, +296, +262205, +6, +412, +411, +327745, +292, +413, +165, +291, +262205, +6, +414, +413, +327811, +6, +415, +412, +414, +327813, +6, +416, +410, +415, +327745, +292, +417, +165, +296, +262205, +6, +418, +417, +327816, +6, +419, +416, +418, +327811, +6, +420, +150, +419, +327816, +6, +421, +409, +420, +196670, +407, +421, +262205, +6, +423, +394, +262205, +6, +424, +407, +327811, +6, +425, +423, +424, +458764, +6, +426, +1, +40, +210, +425, +196670, +422, +426, +262205, +6, +428, +422, +327745, +292, +429, +165, +94, +262205, +6, +430, +429, +327745, +292, +431, +165, +317, +262205, +6, +432, +431, +327813, +6, +433, +430, +432, +327816, +6, +434, +428, +433, +196670, +427, +434, +262205, +6, +436, +422, +327866, +222, +437, +436, +324, +196855, +439, +0, +262394, +437, +438, +440, +131320, +438, +196670, +435, +150, +131321, +439, +131320, +440, +196670, +435, +210, +131321, +439, +131320, +439, +262205, +6, +441, +435, +262205, +6, +442, +427, +327809, +6, +443, +442, +441, +196670, +427, +443, +262205, +6, +445, +41, +327811, +6, +446, +150, +445, +393228, +6, +447, +1, +4, +446, +262205, +6, +448, +427, +458764, +6, +449, +1, +26, +447, +448, +196670, +444, +449, +262205, +6, +450, +444, +131326, +450, +65592, +327734, +19, +50, +0, +44, +196663, +20, +45, +196663, +20, +46, +196663, +8, +47, +196663, +21, +48, +196663, +20, +49, +131320, +51, +262203, +20, +453, +7, +262203, +21, +459, +7, +262203, +21, +460, +7, +262203, +21, +464, +7, +262203, +21, +467, +7, +262203, +21, +470, +7, +262203, +21, +473, +7, +262203, +21, +477, +7, +262203, +20, +481, +7, +262203, +20, +485, +7, +262203, +20, +490, +7, +262203, +20, +498, +7, +262203, +21, +501, +7, +262203, +21, +505, +7, +262203, +21, +511, +7, +262203, +21, +513, +7, +262203, +21, +521, +7, +262203, +21, +524, +7, +262203, +21, +526, +7, +262203, +21, +530, +7, +262203, +21, +536, +7, +262203, +21, +548, +7, +262203, +21, +554, +7, +262203, +21, +563, +7, +262203, +21, +576, +7, +262203, +21, +582, +7, +262203, +20, +591, +7, +327745, +455, +456, +165, +454, +262205, +7, +457, +456, +524367, +19, +458, +457, +457, +0, +1, +2, +196670, +453, +458, +196670, +459, +150, +393281, +292, +462, +165, +461, +60, +262205, +6, +463, +462, +196670, +460, +463, +393281, +292, +465, +165, +461, +69, +262205, +6, +466, +465, +196670, +464, +466, +393281, +292, +468, +165, +461, +76, +262205, +6, +469, +468, +196670, +467, +469, +393281, +292, +471, +165, +461, +83, +262205, +6, +472, +471, +196670, +470, +472, +327745, +292, +475, +165, +474, +262205, +6, +476, +475, +196670, +473, +476, +327745, +292, +479, +165, +478, +262205, +6, +480, +479, +196670, +477, +480, +327745, +455, +482, +165, +98, +262205, +7, +483, +482, +524367, +19, +484, +483, +483, +0, +1, +2, +196670, +481, +484, +262205, +19, +486, +481, +262205, +19, +487, +45, +327811, +19, +488, +486, +487, +393228, +19, +489, +1, +69, +488, +196670, +485, +489, +327745, +492, +493, +165, +491, +262205, +19, +494, +493, +262205, +19, +495, +45, +327811, +19, +496, +494, +495, +393228, +19, +497, +1, +69, +496, +196670, +490, +497, +262205, +19, +499, +46, +393228, +19, +500, +1, +69, +499, +196670, +498, +500, +262205, +19, +502, +498, +262205, +19, +503, +485, +327828, +6, +504, +502, +503, +196670, +501, +504, +262205, +6, +506, +501, +262205, +6, +507, +501, +327813, +6, +508, +506, +507, +327811, +6, +509, +150, +508, +393228, +6, +510, +1, +31, +509, +196670, +505, +510, +262205, +6, +512, +505, +196670, +511, +512, +262205, +6, +514, +459, +327813, +6, +516, +514, +515, +327813, +6, +518, +516, +517, +327816, +6, +520, +518, +519, +196670, +513, +520, +262205, +6, +522, +501, +262271, +6, +523, +522, +196670, +521, +523, +262205, +6, +525, +505, +196670, +524, +525, +262205, +19, +527, +498, +262205, +19, +528, +490, +327828, +6, +529, +527, +528, +196670, +526, +529, +262205, +6, +531, +526, +262205, +6, +532, +526, +327813, +6, +533, +531, +532, +327811, +6, +534, +150, +533, +393228, +6, +535, +1, +31, +534, +196670, +530, +535, +262205, +6, +537, +521, +262205, +6, +538, +513, +327813, +6, +539, +144, +538, +393228, +6, +540, +1, +14, +539, +327813, +6, +541, +537, +540, +262205, +6, +542, +524, +262205, +6, +543, +513, +327813, +6, +544, +144, +543, +393228, +6, +545, +1, +13, +544, +327813, +6, +546, +542, +545, +327811, +6, +547, +541, +546, +196670, +536, +547, +262205, +6, +549, +536, +262205, +6, +550, +536, +327813, +6, +551, +549, +550, +327811, +6, +552, +150, +551, +393228, +6, +553, +1, +31, +552, +196670, +548, +553, +262205, +6, +555, +536, +262205, +6, +556, +526, +327813, +6, +557, +555, +556, +262205, +6, +558, +548, +262205, +6, +559, +530, +327813, +6, +560, +558, +559, +327809, +6, +561, +557, +560, +458764, +6, +562, +1, +40, +210, +561, +196670, +554, +562, +262205, +6, +564, +521, +262205, +6, +566, +513, +327813, +6, +567, +565, +566, +393228, +6, +568, +1, +14, +567, +327813, +6, +569, +564, +568, +262205, +6, +570, +524, +262205, +6, +571, +513, +327813, +6, +572, +565, +571, +393228, +6, +573, +1, +13, +572, +327813, +6, +574, +570, +573, +327811, +6, +575, +569, +574, +196670, +563, +575, +262205, +6, +577, +563, +262205, +6, +578, +563, +327813, +6, +579, +577, +578, +327811, +6, +580, +150, +579, +393228, +6, +581, +1, +31, +580, +196670, +576, +581, +262205, +6, +583, +563, +262205, +6, +584, +526, +327813, +6, +585, +583, +584, +262205, +6, +586, +576, +262205, +6, +587, +530, +327813, +6, +588, +586, +587, +327809, +6, +589, +585, +588, +458764, +6, +590, +1, +40, +210, +589, +196670, +582, +590, +262205, +6, +592, +460, +327745, +455, +594, +165, +593, +262205, +7, +595, +594, +524367, +19, +596, +595, +595, +0, +1, +2, +327822, +19, +597, +596, +592, +262205, +19, +598, +453, +327813, +19, +599, +597, +598, +262205, +6, +600, +48, +327745, +455, +602, +165, +601, +262205, +7, +603, +602, +524367, +19, +604, +603, +603, +0, +1, +2, +327822, +19, +605, +604, +600, +262205, +6, +606, +464, +262205, +6, +607, +511, +327813, +6, +608, +606, +607, +262205, +19, +609, +453, +327822, +19, +610, +609, +608, +262205, +6, +611, +467, +262205, +6, +612, +554, +262205, +6, +613, +470, +458764, +6, +614, +1, +26, +612, +613, +327813, +6, +615, +611, +614, +393296, +19, +616, +615, +615, +615, +327809, +19, +617, +610, +616, +262205, +6, +618, +473, +262205, +6, +619, +582, +262205, +6, +620, +477, +458764, +6, +621, +1, +26, +619, +620, +327813, +6, +622, +618, +621, +262205, +19, +623, +453, +327822, +19, +624, +623, +622, +327809, +19, +625, +617, +624, +327813, +19, +626, +605, +625, +327809, +19, +627, +599, +626, +196670, +591, +627, +262205, +19, +628, +591, +262205, +6, +629, +48, +327822, +19, +630, +628, +629, +131326, +630, +65592, +327734, +19, +57, +0, +52, +196663, +20, +53, +196663, +20, +54, +196663, +8, +55, +196663, +21, +56, +131320, +58, +262203, +20, +633, +7, +262203, +21, +637, +7, +262203, +20, +640, +7, +327745, +455, +634, +165, +454, +262205, +7, +635, +634, +524367, +19, +636, +635, +635, +0, +1, +2, +196670, +633, +636, +393281, +292, +638, +165, +461, +69, +262205, +6, +639, +638, +196670, +637, +639, +262205, +6, +641, +56, +262205, +6, +642, +637, +327813, +6, +643, +641, +642, +262205, +19, +644, +633, +327822, +19, +645, +644, +643, +196670, +640, +645, +262205, +19, +646, +640, +262205, +6, +647, +56, +327822, +19, +648, +646, +647, +131326, +648, +65592, +}; +const std::vector global_constraints = {119734787, +65536, +524289, +516, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +458767, +5, +4, +1852399981, +0, +270, +271, +393232, +4, +17, +64, +1, +1, +196611, +2, +450, +262149, +4, +1852399981, +0, +393221, +12, +1867346761, +1818386806, +1719019621, +15156, +327685, +11, +1953653104, +1701602153, +0, +1114117, +28, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1953718605, +1965584997, +829766449, +993097019, +1765486965, +829766449, +993097019, +1966813557, +15153, +327685, +19, +1633906540, +1684627308, +0, +327685, +20, +1970238055, +1684627312, +0, +458757, +21, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +22, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +23, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +24, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +25, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +26, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +27, +1634890867, +2035573870, +25968, +1114117, +39, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +828980017, +993097019, +1966813557, +829766449, +59, +327685, +30, +1633906540, +1684627308, +0, +327685, +31, +1970238055, +1684627312, +0, +458757, +32, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +33, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +34, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +35, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +36, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +37, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +38, +1634890867, +2035573870, +25968, +983045, +48, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +829766449, +993097019, +0, +327685, +42, +1633906540, +1684627308, +0, +327685, +43, +1970238055, +1684627312, +0, +458757, +44, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +45, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +46, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +47, +1634890867, +2035573870, +25968, +983045, +57, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1953718605, +1764258405, +828980017, +993093947, +1765486965, +829766449, +59, +327685, +51, +1633906540, +1684627308, +0, +327685, +52, +1970238055, +1684627312, +0, +458757, +53, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +54, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +55, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +56, +1634890867, +2035573870, +25968, +786437, +69, +1702129225, +1952543335, +1719019621, +1719024436, +1719024436, +1719024436, +829766452, +993097019, +1715155317, +15153, +327685, +61, +1349678435, +1953067887, +7237481, +327685, +62, +1348758639, +1953067887, +7237481, +327685, +63, +1953066601, +1349280105, +29551, +262149, +64, +1668444006, +101, +458757, +65, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +66, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +67, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +393221, +68, +1886216548, +1130851945, +1717986671, +0, +917509, +77, +1633972309, +1766221172, +1449943406, +1702130277, +1936674936, +1869182057, +1982362478, +1983591526, +1966814310, +829766449, +993097019, +0, +327685, +72, +1348758639, +1953067887, +7237481, +327685, +73, +1350002030, +1953067887, +7237481, +458757, +74, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +75, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +76, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +327685, +88, +1936617283, +1953390964, +115, +327686, +88, +0, +1767333735, +25710, +327686, +88, +1, +1767333735, +3236974, +327686, +88, +2, +1767333735, +3302510, +327686, +88, +3, +1767333735, +3368046, +720902, +88, +4, +1968070503, +1852132461, +1130919015, +1953721967, +1852399986, +1702119796, +1769234802, +7564911, +458758, +88, +5, +1130520423, +1768713327, +1852795251, +0, +524294, +88, +6, +1917280103, +1953068641, +1734430073, +1970563438, +25956, +393222, +88, +7, +1767137127, +1951622509, +28773, +393222, +88, +8, +1631870823, +1852403821, +12391, +786438, +88, +9, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +48, +786438, +88, +10, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12391, +851974, +88, +11, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +811951982, +0, +393222, +88, +12, +1631870823, +1852403821, +12647, +786438, +88, +13, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +49, +786438, +88, +14, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12647, +851974, +88, +15, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +828729198, +0, +393222, +88, +16, +1631870823, +1852403821, +12903, +786438, +88, +17, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +50, +786438, +88, +18, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12903, +851974, +88, +19, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +845506414, +0, +393222, +88, +20, +1631870823, +1852403821, +13159, +786438, +88, +21, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +51, +786438, +88, +22, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +13159, +851974, +88, +23, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +862283630, +0, +720902, +88, +24, +1968070503, +1399213933, +1851880052, +1699771236, +1919439986, +1197760869, +1886744434, +0, +720902, +88, +25, +1968070503, +1819231853, +1215786860, +1936877921, +1198679376, +1701079413, +1919508808, +0, +589830, +88, +26, +1767137127, +1885688688, +1952543329, +1181642601, +1869898593, +114, +327686, +88, +27, +1466064743, +7369313, +786438, +88, +28, +1968070503, +1668238445, +1750297697, +1298493537, +1751348321, +1231515241, +1634887028, +1852795252, +115, +196613, +90, +0, +458757, +122, +1632132967, +1951625833, +1684955506, +1701869908, +0, +327685, +208, +1886680431, +1867543669, +115, +524293, +251, +1953067639, +1818386789, +1701990501, +1936674934, +1869182057, +29550, +655366, +251, +0, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +1701990515, +118, +196613, +253, +0, +458757, +261, +1953067639, +1818386789, +1936674917, +1869182057, +29550, +589830, +261, +0, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +196613, +263, +0, +524293, +270, +1281322087, +1818321775, +1870032457, +1769234787, +1145663087, +0, +393221, +271, +1465871463, +1198223983, +1886744434, +17481, +458757, +272, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +273, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +274, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +275, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +276, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +277, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +278, +1634890867, +2035573870, +25968, +262149, +279, +1634886000, +109, +262149, +283, +1634886000, +109, +262149, +286, +1634886000, +109, +262149, +288, +1634886000, +109, +262149, +290, +1634886000, +109, +262149, +292, +1634886000, +109, +262149, +294, +1634886000, +109, +262149, +296, +1634886000, +109, +262149, +298, +1634886000, +109, +327685, +308, +1920103779, +1349807717, +29551, +327685, +310, +1953066601, +1349280105, +29551, +524293, +314, +1850302311, +1634301033, +1767983212, +1936674930, +1869182057, +29550, +393221, +321, +1684104520, +1851880020, +1919903347, +109, +589830, +321, +0, +1867341671, +1416389988, +1936613746, +1836216166, +1215459142, +6578533, +589830, +321, +1, +1867341671, +1382835556, +1952543855, +1919895141, +1684104520, +0, +589830, +321, +2, +1852396386, +1214606439, +1415864677, +1936613746, +1836216166, +0, +327686, +321, +3, +1684300144, +6778473, +196613, +323, +0, +262149, +346, +1349545332, +29551, +393221, +350, +1886216548, +1130851945, +1717986671, +0, +262149, +389, +1348758639, +29551, +262149, +395, +1668444006, +101, +262149, +396, +1634886000, +109, +262149, +403, +1634886000, +109, +262149, +405, +1634886000, +109, +262149, +407, +1634886000, +109, +262149, +409, +1634886000, +109, +262149, +411, +1634886000, +109, +262149, +412, +1634886000, +109, +262149, +414, +1634886000, +109, +262149, +416, +1634886000, +109, +655365, +421, +1718187123, +1936027238, +1919895155, +1651469383, +1750297697, +1298493537, +1751348321, +6778473, +720901, +422, +1651469415, +1750297697, +1298493537, +1751348321, +1164406377, +1667589734, +1702259060, +1735287122, +101, +262149, +473, +1634886000, +109, +262149, +487, +1952670054, +29295, +196613, +490, +7103844, +262149, +505, +1634886000, +109, +262149, +507, +1634886000, +109, +262149, +509, +1634886000, +109, +262149, +510, +1634886000, +109, +262149, +512, +1634886000, +109, +327752, +88, +0, +35, +0, +327752, +88, +1, +35, +16, +327752, +88, +2, +35, +32, +327752, +88, +3, +35, +48, +327752, +88, +4, +35, +64, +327752, +88, +5, +35, +68, +327752, +88, +6, +35, +72, +327752, +88, +7, +35, +76, +327752, +88, +8, +35, +80, +327752, +88, +9, +35, +84, +327752, +88, +10, +35, +88, +327752, +88, +11, +35, +92, +327752, +88, +12, +35, +96, +327752, +88, +13, +35, +100, +327752, +88, +14, +35, +104, +327752, +88, +15, +35, +108, +327752, +88, +16, +35, +112, +327752, +88, +17, +35, +116, +327752, +88, +18, +35, +120, +327752, +88, +19, +35, +124, +327752, +88, +20, +35, +128, +327752, +88, +21, +35, +132, +327752, +88, +22, +35, +136, +327752, +88, +23, +35, +140, +327752, +88, +24, +35, +144, +327752, +88, +25, +35, +148, +327752, +88, +26, +35, +152, +327752, +88, +27, +35, +156, +327752, +88, +28, +35, +160, +196679, +88, +3, +262215, +90, +34, +0, +262215, +90, +33, +16, +262215, +122, +34, +1, +262215, +122, +33, +22, +262215, +250, +6, +16, +327752, +251, +0, +35, +0, +196679, +251, +3, +262215, +253, +34, +1, +262215, +253, +33, +20, +262215, +260, +6, +16, +327752, +261, +0, +35, +0, +196679, +261, +3, +262215, +263, +34, +1, +262215, +263, +33, +7, +262215, +270, +11, +27, +262215, +271, +11, +26, +262215, +314, +34, +1, +262215, +314, +33, +21, +262215, +320, +6, +16, +262216, +321, +0, +5, +327752, +321, +0, +35, +0, +327752, +321, +0, +7, +16, +327752, +321, +1, +35, +64, +327752, +321, +2, +35, +80, +327752, +321, +3, +35, +96, +196679, +321, +3, +262215, +323, +34, +0, +262215, +323, +33, +27, +262215, +515, +11, +25, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +131092, +9, +262177, +10, +9, +8, +262165, +14, +32, +0, +262176, +15, +7, +14, +262165, +16, +32, +1, +262176, +17, +7, +16, +786465, +18, +2, +15, +15, +15, +15, +17, +15, +15, +15, +15, +589857, +41, +2, +15, +15, +15, +15, +15, +15, +589857, +50, +2, +17, +17, +17, +15, +17, +15, +262176, +59, +7, +6, +720929, +60, +7, +8, +8, +8, +8, +15, +15, +15, +59, +524321, +71, +2, +8, +8, +15, +15, +15, +262187, +14, +79, +3, +262187, +6, +82, +0, +262187, +14, +87, +64, +2031646, +88, +7, +7, +7, +7, +16, +16, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +14, +14, +6, +16, +16, +262176, +89, +2, +88, +262203, +89, +90, +2, +262187, +16, +91, +24, +262176, +92, +2, +14, +262187, +16, +106, +25, +262187, +14, +109, +1, +589849, +119, +14, +5, +0, +0, +0, +1, +0, +196635, +120, +119, +262176, +121, +0, +120, +262203, +121, +122, +0, +262167, +127, +14, +4, +262187, +14, +129, +0, +262187, +16, +185, +64, +262187, +16, +210, +6, +262176, +211, +2, +6, +262167, +214, +6, +3, +262187, +6, +215, +3212836864, +393260, +214, +216, +82, +215, +82, +262187, +6, +225, +1065353216, +262187, +16, +237, +7, +196637, +250, +7, +196638, +251, +250, +262176, +252, +2, +251, +262203, +252, +253, +2, +262187, +16, +254, +0, +262176, +258, +2, +7, +196637, +260, +7, +196638, +261, +260, +262176, +262, +2, +261, +262203, +262, +263, +2, +262167, +268, +14, +3, +262176, +269, +1, +268, +262203, +269, +270, +1, +262203, +269, +271, +1, +262176, +280, +1, +14, +458796, +7, +309, +82, +82, +82, +82, +589849, +311, +6, +5, +0, +0, +0, +1, +0, +196635, +312, +311, +262176, +313, +0, +312, +262203, +313, +314, +0, +262168, +319, +7, +4, +262172, +320, +6, +79, +393246, +321, +319, +7, +16, +320, +262176, +322, +2, +321, +262203, +322, +323, +2, +262176, +324, +2, +319, +262187, +16, +337, +27, +262176, +338, +2, +16, +262187, +6, +351, +1022739087, +262187, +16, +356, +8, +262187, +16, +364, +12, +262187, +14, +369, +2, +262187, +16, +373, +16, +262187, +16, +381, +20, +262187, +16, +427, +10, +262187, +16, +430, +11, +262187, +16, +438, +14, +262187, +16, +441, +15, +262187, +16, +449, +18, +262187, +16, +452, +19, +262187, +16, +460, +22, +262187, +16, +463, +23, +262176, +489, +7, +214, +393260, +268, +515, +87, +109, +109, +327734, +2, +4, +0, +3, +131320, +5, +262203, +15, +272, +7, +262203, +15, +273, +7, +262203, +17, +274, +7, +262203, +15, +275, +7, +262203, +15, +276, +7, +262203, +15, +277, +7, +262203, +15, +278, +7, +262203, +15, +279, +7, +262203, +15, +283, +7, +262203, +15, +286, +7, +262203, +15, +288, +7, +262203, +17, +290, +7, +262203, +15, +292, +7, +262203, +15, +294, +7, +262203, +15, +296, +7, +262203, +15, +298, +7, +262203, +8, +308, +7, +262203, +8, +310, +7, +262203, +8, +346, +7, +262203, +59, +350, +7, +262203, +8, +389, +7, +262203, +8, +395, +7, +262203, +8, +396, +7, +262203, +8, +403, +7, +262203, +8, +405, +7, +262203, +8, +407, +7, +262203, +8, +409, +7, +262203, +15, +411, +7, +262203, +15, +412, +7, +262203, +15, +414, +7, +262203, +59, +416, +7, +262203, +59, +421, +7, +262203, +59, +422, +7, +262203, +8, +473, +7, +262203, +59, +487, +7, +262203, +489, +490, +7, +262203, +8, +505, +7, +262203, +8, +507, +7, +262203, +15, +509, +7, +262203, +15, +510, +7, +262203, +15, +512, +7, +327745, +280, +281, +270, +129, +262205, +14, +282, +281, +196670, +279, +282, +327745, +280, +284, +271, +129, +262205, +14, +285, +284, +196670, +283, +285, +262205, +14, +287, +272, +196670, +286, +287, +262205, +14, +289, +273, +196670, +288, +289, +262205, +16, +291, +274, +196670, +290, +291, +262205, +14, +293, +275, +196670, +292, +293, +262205, +14, +295, +276, +196670, +294, +295, +262205, +14, +297, +277, +196670, +296, +297, +262205, +14, +299, +278, +196670, +298, +299, +852025, +2, +300, +28, +279, +283, +286, +288, +290, +292, +294, +296, +298, +262205, +14, +301, +286, +196670, +272, +301, +262205, +14, +302, +288, +196670, +273, +302, +262205, +16, +303, +290, +196670, +274, +303, +262205, +14, +304, +292, +196670, +275, +304, +262205, +14, +305, +294, +196670, +276, +305, +262205, +14, +306, +296, +196670, +277, +306, +262205, +14, +307, +298, +196670, +278, +307, +196670, +308, +309, +196670, +310, +309, +262205, +312, +315, +314, +262205, +16, +316, +274, +262244, +311, +317, +315, +327775, +7, +318, +317, +316, +196670, +310, +318, +327745, +324, +325, +323, +254, +262205, +319, +326, +325, +262205, +7, +327, +310, +524367, +214, +328, +327, +327, +0, +1, +2, +327761, +6, +329, +328, +0, +327761, +6, +330, +328, +1, +327761, +6, +331, +328, +2, +458832, +7, +332, +329, +330, +331, +225, +327825, +7, +333, +326, +332, +524367, +214, +334, +333, +333, +0, +1, +2, +262205, +7, +335, +310, +589903, +7, +336, +335, +334, +4, +5, +6, +3, +196670, +310, +336, +327745, +338, +339, +90, +337, +262205, +16, +340, +339, +327851, +9, +341, +340, +254, +196855, +343, +0, +262394, +341, +342, +345, +131320, +342, +262205, +7, +344, +310, +196670, +308, +344, +131321, +343, +131320, +345, +262205, +16, +347, +274, +393281, +258, +348, +263, +254, +347, +262205, +7, +349, +348, +196670, +346, +349, +196670, +308, +349, +131321, +343, +131320, +343, +196670, +350, +351, +262205, +14, +352, +278, +327850, +9, +353, +352, +129, +196855, +355, +0, +262394, +353, +354, +359, +131320, +354, +327745, +211, +357, +90, +356, +262205, +6, +358, +357, +196670, +350, +358, +131321, +355, +131320, +359, +262205, +14, +360, +278, +327850, +9, +361, +360, +109, +196855, +363, +0, +262394, +361, +362, +367, +131320, +362, +327745, +211, +365, +90, +364, +262205, +6, +366, +365, +196670, +350, +366, +131321, +363, +131320, +367, +262205, +14, +368, +278, +327850, +9, +370, +368, +369, +196855, +372, +0, +262394, +370, +371, +376, +131320, +371, +327745, +211, +374, +90, +373, +262205, +6, +375, +374, +196670, +350, +375, +131321, +372, +131320, +376, +262205, +14, +377, +278, +327850, +9, +378, +377, +79, +196855, +380, +0, +262394, +378, +379, +380, +131320, +379, +327745, +211, +382, +90, +381, +262205, +6, +383, +382, +196670, +350, +383, +131321, +380, +131320, +380, +131321, +372, +131320, +372, +131321, +363, +131320, +363, +131321, +355, +131320, +355, +327745, +338, +384, +90, +337, +262205, +16, +385, +384, +327851, +9, +386, +385, +254, +196855, +388, +0, +262394, +386, +387, +391, +131320, +387, +262205, +7, +390, +308, +196670, +389, +390, +131321, +388, +131320, +391, +262205, +16, +392, +274, +393281, +258, +393, +253, +254, +392, +262205, +7, +394, +393, +196670, +389, +394, +131321, +388, +131320, +388, +196670, +395, +309, +262205, +7, +397, +308, +196670, +396, +397, +327737, +9, +398, +12, +396, +196855, +400, +0, +262394, +398, +399, +419, +131320, +399, +262205, +16, +401, +274, +262268, +14, +402, +401, +262205, +7, +404, +308, +196670, +403, +404, +262205, +7, +406, +389, +196670, +405, +406, +262205, +7, +408, +310, +196670, +407, +408, +262205, +7, +410, +395, +196670, +409, +410, +196670, +411, +402, +262205, +14, +413, +275, +196670, +412, +413, +262205, +14, +415, +276, +196670, +414, +415, +262205, +6, +417, +350, +196670, +416, +417, +786489, +7, +418, +69, +403, +405, +407, +409, +411, +412, +414, +416, +196670, +346, +418, +131321, +400, +131320, +419, +262205, +7, +420, +310, +196670, +346, +420, +131321, +400, +131320, +400, +196670, +421, +82, +196670, +422, +82, +262205, +14, +423, +278, +327850, +9, +424, +423, +129, +196855, +426, +0, +262394, +424, +425, +433, +131320, +425, +327745, +211, +428, +90, +427, +262205, +6, +429, +428, +196670, +421, +429, +327745, +211, +431, +90, +430, +262205, +6, +432, +431, +196670, +422, +432, +131321, +426, +131320, +433, +262205, +14, +434, +278, +327850, +9, +435, +434, +109, +196855, +437, +0, +262394, +435, +436, +444, +131320, +436, +327745, +211, +439, +90, +438, +262205, +6, +440, +439, +196670, +421, +440, +327745, +211, +442, +90, +441, +262205, +6, +443, +442, +196670, +422, +443, +131321, +437, +131320, +444, +262205, +14, +445, +278, +327850, +9, +446, +445, +369, +196855, +448, +0, +262394, +446, +447, +455, +131320, +447, +327745, +211, +450, +90, +449, +262205, +6, +451, +450, +196670, +421, +451, +327745, +211, +453, +90, +452, +262205, +6, +454, +453, +196670, +422, +454, +131321, +448, +131320, +455, +262205, +14, +456, +278, +327850, +9, +457, +456, +79, +196855, +459, +0, +262394, +457, +458, +459, +131320, +458, +327745, +211, +461, +90, +460, +262205, +6, +462, +461, +196670, +421, +462, +327745, +211, +464, +90, +463, +262205, +6, +465, +464, +196670, +422, +465, +131321, +459, +131320, +459, +131321, +448, +131320, +448, +131321, +437, +131320, +437, +131321, +426, +131320, +426, +262205, +6, +466, +421, +327866, +9, +467, +466, +82, +262205, +6, +468, +422, +327862, +9, +469, +468, +82, +327847, +9, +470, +467, +469, +196855, +472, +0, +262394, +470, +471, +472, +131320, +471, +262205, +7, +474, +346, +196670, +473, +474, +327737, +9, +475, +12, +473, +196855, +477, +0, +262394, +475, +476, +477, +131320, +476, +262205, +14, +478, +275, +262256, +6, +479, +478, +262205, +6, +480, +422, +262205, +14, +481, +276, +262256, +6, +482, +481, +327813, +6, +483, +480, +482, +327864, +9, +484, +479, +483, +196855, +486, +0, +262394, +484, +485, +486, +131320, +485, +262205, +6, +488, +421, +196670, +487, +488, +262205, +6, +491, +487, +262205, +7, +492, +310, +262205, +7, +493, +346, +327811, +7, +494, +492, +493, +524367, +214, +495, +494, +494, +0, +1, +2, +327822, +214, +496, +495, +491, +196670, +490, +496, +262205, +214, +497, +490, +262205, +7, +498, +346, +524367, +214, +499, +498, +498, +0, +1, +2, +327809, +214, +500, +499, +497, +262205, +7, +501, +346, +589903, +7, +502, +501, +500, +4, +5, +6, +3, +196670, +346, +502, +131321, +486, +131320, +486, +131321, +477, +131320, +477, +131321, +472, +131320, +472, +262205, +16, +503, +274, +262268, +14, +504, +503, +262205, +7, +506, +308, +196670, +505, +506, +262205, +7, +508, +346, +196670, +507, +508, +196670, +509, +504, +262205, +14, +511, +275, +196670, +510, +511, +262205, +14, +513, +276, +196670, +512, +513, +589881, +2, +514, +77, +505, +507, +509, +510, +512, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +327745, +59, +80, +11, +79, +262205, +6, +81, +80, +327866, +9, +83, +81, +82, +131326, +83, +65592, +327734, +2, +28, +0, +18, +196663, +15, +19, +196663, +15, +20, +196663, +15, +21, +196663, +15, +22, +196663, +17, +23, +196663, +15, +24, +196663, +15, +25, +196663, +15, +26, +196663, +15, +27, +131320, +29, +262205, +14, +86, +19, +196670, +26, +86, +327745, +92, +93, +90, +91, +262205, +14, +94, +93, +327814, +14, +95, +87, +94, +196670, +25, +95, +262205, +14, +96, +19, +327745, +92, +97, +90, +91, +262205, +14, +98, +97, +327817, +14, +99, +96, +98, +196670, +22, +99, +262205, +14, +100, +20, +327745, +92, +101, +90, +91, +262205, +14, +102, +101, +327812, +14, +103, +100, +102, +262205, +14, +104, +22, +327808, +14, +105, +103, +104, +196670, +21, +105, +327745, +92, +107, +90, +106, +262205, +14, +108, +107, +327808, +14, +110, +108, +109, +262205, +14, +111, +21, +327812, +14, +112, +111, +110, +196670, +21, +112, +262205, +14, +113, +19, +262205, +14, +114, +22, +327810, +14, +115, +113, +114, +327745, +92, +116, +90, +91, +262205, +14, +117, +116, +327814, +14, +118, +115, +117, +196670, +24, +118, +262205, +120, +123, +122, +262205, +14, +124, +21, +262268, +16, +125, +124, +262244, +119, +126, +123, +327775, +127, +128, +126, +125, +327761, +14, +130, +128, +0, +196670, +27, +130, +262205, +14, +131, +21, +262205, +14, +132, +25, +327812, +14, +133, +131, +132, +262205, +14, +134, +24, +327808, +14, +135, +133, +134, +262268, +16, +136, +135, +196670, +23, +136, +65789, +65592, +327734, +2, +39, +0, +18, +196663, +15, +30, +196663, +15, +31, +196663, +15, +32, +196663, +15, +33, +196663, +17, +34, +196663, +15, +35, +196663, +15, +36, +196663, +15, +37, +196663, +15, +38, +131320, +40, +262205, +14, +137, +30, +196670, +37, +137, +327745, +92, +138, +90, +91, +262205, +14, +139, +138, +327814, +14, +140, +87, +139, +196670, +36, +140, +262205, +14, +141, +30, +327745, +92, +142, +90, +91, +262205, +14, +143, +142, +327817, +14, +144, +141, +143, +196670, +33, +144, +262205, +14, +145, +31, +327745, +92, +146, +90, +91, +262205, +14, +147, +146, +327812, +14, +148, +145, +147, +262205, +14, +149, +33, +327808, +14, +150, +148, +149, +196670, +32, +150, +262205, +14, +151, +30, +262205, +14, +152, +33, +327810, +14, +153, +151, +152, +327745, +92, +154, +90, +91, +262205, +14, +155, +154, +327814, +14, +156, +153, +155, +196670, +35, +156, +262205, +120, +157, +122, +262205, +14, +158, +32, +262268, +16, +159, +158, +262244, +119, +160, +157, +327775, +127, +161, +160, +159, +327761, +14, +162, +161, +0, +196670, +38, +162, +262205, +14, +163, +32, +262205, +14, +164, +36, +327812, +14, +165, +163, +164, +262205, +14, +166, +35, +327808, +14, +167, +165, +166, +262268, +16, +168, +167, +196670, +34, +168, +65789, +65592, +327734, +2, +48, +0, +41, +196663, +15, +42, +196663, +15, +43, +196663, +15, +44, +196663, +15, +45, +196663, +15, +46, +196663, +15, +47, +131320, +49, +262205, +14, +169, +43, +327812, +14, +170, +87, +169, +262205, +14, +171, +42, +327808, +14, +172, +170, +171, +196670, +44, +172, +327745, +92, +173, +90, +91, +262205, +14, +174, +173, +327814, +14, +175, +87, +174, +196670, +45, +175, +262205, +120, +176, +122, +262205, +14, +177, +44, +262268, +16, +178, +177, +262244, +119, +179, +176, +327775, +127, +180, +179, +178, +327761, +14, +181, +180, +0, +196670, +47, +181, +262205, +14, +182, +44, +262205, +14, +183, +45, +327812, +14, +184, +182, +183, +196670, +46, +184, +65789, +65592, +327734, +2, +57, +0, +50, +196663, +17, +51, +196663, +17, +52, +196663, +17, +53, +196663, +15, +54, +196663, +17, +55, +196663, +15, +56, +131320, +58, +262205, +16, +186, +52, +327812, +16, +187, +185, +186, +262205, +16, +188, +51, +327808, +16, +189, +187, +188, +196670, +53, +189, +327745, +92, +190, +90, +106, +262205, +14, +191, +190, +327808, +14, +192, +191, +109, +262268, +16, +193, +192, +262205, +16, +194, +53, +327812, +16, +195, +194, +193, +196670, +53, +195, +327745, +92, +196, +90, +91, +262205, +14, +197, +196, +327814, +14, +198, +87, +197, +196670, +54, +198, +262205, +120, +199, +122, +262205, +16, +200, +53, +262244, +119, +201, +199, +327775, +127, +202, +201, +200, +327761, +14, +203, +202, +0, +196670, +56, +203, +262205, +16, +204, +53, +262205, +14, +205, +54, +262268, +16, +206, +205, +327812, +16, +207, +204, +206, +196670, +55, +207, +65789, +65592, +327734, +7, +69, +0, +60, +196663, +8, +61, +196663, +8, +62, +196663, +8, +63, +196663, +8, +64, +196663, +15, +65, +196663, +15, +66, +196663, +15, +67, +196663, +59, +68, +131320, +70, +262203, +8, +208, +7, +262205, +7, +209, +61, +196670, +208, +209, +327745, +211, +212, +90, +210, +262205, +6, +213, +212, +327822, +214, +217, +216, +213, +262205, +7, +218, +64, +524367, +214, +219, +218, +218, +0, +1, +2, +327809, +214, +220, +219, +217, +262205, +7, +221, +64, +589903, +7, +222, +221, +220, +4, +5, +6, +3, +196670, +64, +222, +262205, +7, +223, +61, +524367, +214, +224, +223, +223, +0, +1, +2, +262205, +6, +226, +68, +327811, +6, +227, +225, +226, +262205, +7, +228, +61, +524367, +214, +229, +228, +228, +0, +1, +2, +262205, +7, +230, +62, +524367, +214, +231, +230, +230, +0, +1, +2, +327811, +214, +232, +229, +231, +327822, +214, +233, +232, +227, +327809, +214, +234, +224, +233, +262205, +7, +235, +64, +524367, +214, +236, +235, +235, +0, +1, +2, +327745, +211, +238, +90, +237, +262205, +6, +239, +238, +327822, +214, +240, +236, +239, +327745, +211, +241, +90, +237, +262205, +6, +242, +241, +327822, +214, +243, +240, +242, +327809, +214, +244, +234, +243, +262205, +7, +245, +208, +589903, +7, +246, +245, +244, +4, +5, +6, +3, +196670, +208, +246, +262205, +7, +247, +208, +131326, +247, +65592, +327734, +2, +77, +0, +71, +196663, +8, +72, +196663, +8, +73, +196663, +15, +74, +196663, +15, +75, +196663, +15, +76, +131320, +78, +262205, +14, +255, +74, +262268, +16, +256, +255, +262205, +7, +257, +72, +393281, +258, +259, +253, +254, +256, +196670, +259, +257, +262205, +14, +264, +74, +262268, +16, +265, +264, +262205, +7, +266, +73, +393281, +258, +267, +263, +254, +265, +196670, +267, +266, +65789, +65592, +}; +const std::vector local_constraints = {119734787, +65536, +524289, +707, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +458767, +5, +4, +1852399981, +0, +421, +426, +393232, +4, +17, +64, +1, +1, +196611, +2, +450, +262149, +4, +1852399981, +0, +393221, +12, +1867346761, +1818386806, +1719019621, +15156, +327685, +11, +1953653104, +1701602153, +0, +1114117, +28, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1953718605, +1965584997, +829766449, +993097019, +1765486965, +829766449, +993097019, +1966813557, +15153, +327685, +19, +1633906540, +1684627308, +0, +327685, +20, +1970238055, +1684627312, +0, +458757, +21, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +22, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +23, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +24, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +25, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +26, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +27, +1634890867, +2035573870, +25968, +1114117, +39, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +828980017, +993097019, +1966813557, +829766449, +59, +327685, +30, +1633906540, +1684627308, +0, +327685, +31, +1970238055, +1684627312, +0, +458757, +32, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +33, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +34, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +35, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +36, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +37, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +38, +1634890867, +2035573870, +25968, +983045, +48, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +829766449, +993097019, +0, +327685, +42, +1633906540, +1684627308, +0, +327685, +43, +1970238055, +1684627312, +0, +458757, +44, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +45, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +46, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +47, +1634890867, +2035573870, +25968, +983045, +57, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1953718605, +1764258405, +828980017, +993093947, +1765486965, +829766449, +59, +327685, +51, +1633906540, +1684627308, +0, +327685, +52, +1970238055, +1684627312, +0, +458757, +53, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +54, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +55, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +56, +1634890867, +2035573870, +25968, +786437, +62, +1953264973, +1952544081, +1768845925, +1849781871, +1635078500, +1852990836, +678326121, +993289846, +993289846, +0, +196613, +60, +16753, +196613, +61, +17009, +720901, +69, +1953264973, +1952544081, +1768845925, +1849781871, +1667585636, +678588276, +993289846, +993224310, +0, +196613, +67, +113, +196613, +68, +118, +524293, +75, +1701536077, +1952544081, +1768845925, +1713925743, +1719024433, +15155, +393221, +73, +1818717793, +1634885477, +1851877732, +0, +262149, +74, +1936291937, +0, +524293, +79, +1702260297, +1365603186, +1702125941, +1869180530, +1719019630, +15156, +196613, +78, +113, +327685, +90, +1936617283, +1953390964, +115, +327686, +90, +0, +1767333735, +25710, +327686, +90, +1, +1767333735, +3236974, +327686, +90, +2, +1767333735, +3302510, +327686, +90, +3, +1767333735, +3368046, +720902, +90, +4, +1968070503, +1852132461, +1130919015, +1953721967, +1852399986, +1702119796, +1769234802, +7564911, +458758, +90, +5, +1130520423, +1768713327, +1852795251, +0, +524294, +90, +6, +1917280103, +1953068641, +1734430073, +1970563438, +25956, +393222, +90, +7, +1767137127, +1951622509, +28773, +393222, +90, +8, +1631870823, +1852403821, +12391, +786438, +90, +9, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +48, +786438, +90, +10, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12391, +851974, +90, +11, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +811951982, +0, +393222, +90, +12, +1631870823, +1852403821, +12647, +786438, +90, +13, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +49, +786438, +90, +14, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12647, +851974, +90, +15, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +828729198, +0, +393222, +90, +16, +1631870823, +1852403821, +12903, +786438, +90, +17, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +50, +786438, +90, +18, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12903, +851974, +90, +19, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +845506414, +0, +393222, +90, +20, +1631870823, +1852403821, +13159, +786438, +90, +21, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +51, +786438, +90, +22, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +13159, +851974, +90, +23, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +862283630, +0, +720902, +90, +24, +1968070503, +1399213933, +1851880052, +1699771236, +1919439986, +1197760869, +1886744434, +0, +720902, +90, +25, +1968070503, +1819231853, +1215786860, +1936877921, +1198679376, +1701079413, +1919508808, +0, +589830, +90, +26, +1767137127, +1885688688, +1952543329, +1181642601, +1869898593, +114, +327686, +90, +27, +1466064743, +7369313, +786438, +90, +28, +1968070503, +1668238445, +1750297697, +1298493537, +1751348321, +1231515241, +1634887028, +1852795252, +115, +196613, +92, +0, +458757, +124, +1632132967, +1951625833, +1684955506, +1701869908, +0, +196613, +210, +113, +262149, +311, +1667593841, +0, +196613, +319, +30325, +196613, +323, +7763317, +327685, +342, +1718378856, +1818717761, +101, +262149, +346, +1215195507, +6712417, +327685, +349, +1952544113, +1768845925, +28271, +327685, +361, +1735288172, +1901291636, +114, +524293, +421, +1281322087, +1818321775, +1870032457, +1769234787, +1145663087, +0, +393221, +426, +1465871463, +1198223983, +1886744434, +17481, +458757, +430, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +431, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +432, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +433, +1634890867, +2035573870, +25968, +262149, +434, +1634886000, +109, +262149, +435, +1634886000, +109, +262149, +436, +1634886000, +109, +262149, +438, +1634886000, +109, +262149, +440, +1634886000, +109, +262149, +442, +1634886000, +109, +655365, +449, +1718187123, +1936027238, +1919895155, +1633906508, +1634227052, +1632462192, +1768448884, +26478, +458757, +487, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +489, +1633906540, +1919243884, +1232627060, +2019910766, +0, +393221, +505, +1918986355, +1951622245, +1684955506, +7565136, +458757, +508, +1953067639, +1818386789, +1936674917, +1869182057, +29550, +589830, +508, +0, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +196613, +510, +0, +327685, +519, +1919251561, +1869182049, +29550, +196613, +531, +7565168, +327685, +534, +1198813042, +1633841004, +108, +458757, +538, +1816616807, +1818321519, +1635020626, +1852795252, +115, +458757, +543, +1633906540, +1919243884, +1232627060, +2019910766, +0, +393221, +557, +1601400688, +1937075312, +1701736287, +0, +393221, +562, +1198813042, +1633841004, +1919899500, +25708, +393221, +565, +1684104520, +1851880020, +1919903347, +109, +589830, +565, +0, +1867341671, +1416389988, +1936613746, +1836216166, +1215459142, +6578533, +589830, +565, +1, +1867341671, +1382835556, +1952543855, +1919895141, +1684104520, +0, +589830, +565, +2, +1852396386, +1214606439, +1415864677, +1936613746, +1836216166, +0, +327686, +565, +3, +1684300144, +6778473, +196613, +567, +0, +262149, +568, +1634886000, +109, +262149, +571, +1634886000, +109, +655365, +574, +1348956783, +1767863151, +1970040927, +1597071219, +1867279945, +1181507939, +1701667186, +26975, +589829, +575, +1632132967, +1699902057, +1667585638, +1282296179, +1818321775, +1835102790, +101, +655365, +582, +1348956783, +1767863151, +1970040927, +1597071219, +1816620617, +1818321519, +1835102790, +101, +262149, +583, +1634886000, +109, +262149, +585, +1634886000, +109, +196613, +591, +7103844, +262149, +598, +1634886000, +109, +262149, +609, +1634886000, +109, +458757, +620, +1383493225, +1816622191, +1818321519, +1819438935, +100, +262149, +621, +1634886000, +109, +196613, +624, +6514038, +458757, +631, +1600741240, +1937075312, +1717514591, +1701667186, +26975, +262149, +632, +1634886000, +109, +262149, +634, +1634886000, +109, +196613, +638, +101, +262149, +640, +1098149746, +7563640, +393221, +649, +1818717793, +1634885477, +1851877732, +0, +327685, +656, +1633906540, +1953452652, +0, +262149, +657, +1634886000, +109, +262149, +659, +1634886000, +109, +262149, +662, +1634886000, +109, +262149, +664, +1634886000, +109, +458757, +685, +1633906540, +1919243884, +1232627060, +2019910766, +0, +327752, +90, +0, +35, +0, +327752, +90, +1, +35, +16, +327752, +90, +2, +35, +32, +327752, +90, +3, +35, +48, +327752, +90, +4, +35, +64, +327752, +90, +5, +35, +68, +327752, +90, +6, +35, +72, +327752, +90, +7, +35, +76, +327752, +90, +8, +35, +80, +327752, +90, +9, +35, +84, +327752, +90, +10, +35, +88, +327752, +90, +11, +35, +92, +327752, +90, +12, +35, +96, +327752, +90, +13, +35, +100, +327752, +90, +14, +35, +104, +327752, +90, +15, +35, +108, +327752, +90, +16, +35, +112, +327752, +90, +17, +35, +116, +327752, +90, +18, +35, +120, +327752, +90, +19, +35, +124, +327752, +90, +20, +35, +128, +327752, +90, +21, +35, +132, +327752, +90, +22, +35, +136, +327752, +90, +23, +35, +140, +327752, +90, +24, +35, +144, +327752, +90, +25, +35, +148, +327752, +90, +26, +35, +152, +327752, +90, +27, +35, +156, +327752, +90, +28, +35, +160, +196679, +90, +3, +262215, +92, +34, +0, +262215, +92, +33, +16, +262215, +124, +34, +1, +262215, +124, +33, +22, +262215, +421, +11, +27, +262215, +426, +11, +26, +262215, +507, +6, +16, +327752, +508, +0, +35, +0, +196679, +508, +3, +262215, +510, +34, +1, +262215, +510, +33, +7, +262215, +538, +34, +1, +262215, +538, +33, +23, +262215, +564, +6, +16, +262216, +565, +0, +5, +327752, +565, +0, +35, +0, +327752, +565, +0, +7, +16, +327752, +565, +1, +35, +64, +327752, +565, +2, +35, +80, +327752, +565, +3, +35, +96, +196679, +565, +3, +262215, +567, +34, +0, +262215, +567, +33, +27, +262215, +575, +34, +1, +262215, +575, +33, +24, +262215, +706, +11, +25, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +131092, +9, +262177, +10, +9, +8, +262165, +14, +32, +0, +262176, +15, +7, +14, +262165, +16, +32, +1, +262176, +17, +7, +16, +786465, +18, +2, +15, +15, +15, +15, +17, +15, +15, +15, +15, +589857, +41, +2, +15, +15, +15, +15, +15, +15, +589857, +50, +2, +17, +17, +17, +15, +17, +15, +327713, +59, +7, +8, +8, +262167, +64, +6, +3, +262176, +65, +7, +64, +327713, +66, +64, +8, +65, +262176, +71, +7, +6, +327713, +72, +7, +71, +65, +262177, +77, +7, +8, +262187, +14, +81, +3, +262187, +6, +84, +0, +262187, +14, +89, +64, +2031646, +90, +7, +7, +7, +7, +16, +16, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +14, +14, +6, +16, +16, +262176, +91, +2, +90, +262203, +91, +92, +2, +262187, +16, +93, +24, +262176, +94, +2, +14, +262187, +16, +108, +25, +262187, +14, +111, +1, +589849, +121, +14, +5, +0, +0, +0, +1, +0, +196635, +122, +121, +262176, +123, +0, +122, +262203, +123, +124, +0, +262167, +129, +14, +4, +262187, +14, +131, +0, +262187, +16, +187, +64, +262187, +14, +228, +2, +262187, +6, +327, +1073741824, +262187, +6, +343, +1056964608, +262187, +6, +386, +981668463, +262187, +6, +390, +1065353216, +458796, +7, +391, +84, +84, +84, +390, +262167, +419, +14, +3, +262176, +420, +1, +419, +262203, +420, +421, +1, +262176, +422, +1, +14, +262203, +420, +426, +1, +262187, +6, +450, +1053609165, +262187, +16, +455, +17, +262176, +456, +2, +6, +262187, +16, +464, +21, +262187, +16, +472, +13, +262187, +16, +480, +9, +262187, +6, +484, +1064514355, +262187, +16, +488, +0, +262187, +14, +502, +16, +262172, +503, +7, +502, +262176, +504, +7, +503, +196637, +507, +7, +196638, +508, +507, +262176, +509, +2, +508, +262203, +509, +510, +2, +262176, +512, +2, +7, +262187, +16, +517, +1, +262187, +16, +526, +28, +262176, +527, +2, +16, +589849, +535, +6, +5, +0, +0, +0, +1, +0, +196635, +536, +535, +262176, +537, +0, +536, +262203, +537, +538, +0, +262168, +563, +7, +4, +262172, +564, +6, +81, +393246, +565, +563, +7, +16, +564, +262176, +566, +2, +565, +262203, +566, +567, +2, +262203, +537, +575, +0, +393260, +64, +639, +390, +84, +84, +393260, +419, +706, +89, +111, +111, +327734, +2, +4, +0, +3, +131320, +5, +262203, +17, +430, +7, +262203, +15, +431, +7, +262203, +17, +432, +7, +262203, +15, +433, +7, +262203, +17, +434, +7, +262203, +17, +435, +7, +262203, +17, +436, +7, +262203, +15, +438, +7, +262203, +17, +440, +7, +262203, +15, +442, +7, +262203, +71, +449, +7, +262203, +17, +487, +7, +262203, +17, +489, +7, +262203, +504, +505, +7, +262203, +17, +519, +7, +262203, +8, +531, +7, +262203, +8, +534, +7, +262203, +17, +543, +7, +262203, +8, +557, +7, +262203, +8, +562, +7, +262203, +8, +568, +7, +262203, +8, +571, +7, +262203, +65, +574, +7, +262203, +65, +582, +7, +262203, +8, +583, +7, +262203, +65, +585, +7, +262203, +65, +591, +7, +262203, +8, +598, +7, +262203, +8, +609, +7, +262203, +8, +620, +7, +262203, +8, +621, +7, +262203, +65, +624, +7, +262203, +65, +631, +7, +262203, +8, +632, +7, +262203, +65, +634, +7, +262203, +65, +638, +7, +262203, +65, +640, +7, +262203, +71, +649, +7, +262203, +8, +656, +7, +262203, +71, +657, +7, +262203, +65, +659, +7, +262203, +8, +662, +7, +262203, +8, +664, +7, +262203, +17, +685, +7, +327745, +422, +423, +421, +131, +262205, +14, +424, +423, +262268, +16, +425, +424, +327745, +422, +427, +426, +131, +262205, +14, +428, +427, +262268, +16, +429, +428, +196670, +434, +425, +196670, +435, +429, +262205, +16, +437, +430, +196670, +436, +437, +262205, +14, +439, +431, +196670, +438, +439, +262205, +16, +441, +432, +196670, +440, +441, +262205, +14, +443, +433, +196670, +442, +443, +655417, +2, +444, +57, +434, +435, +436, +438, +440, +442, +262205, +16, +445, +436, +196670, +430, +445, +262205, +14, +446, +438, +196670, +431, +446, +262205, +16, +447, +440, +196670, +432, +447, +262205, +14, +448, +442, +196670, +433, +448, +196670, +449, +450, +262205, +14, +451, +433, +327850, +9, +452, +451, +228, +196855, +454, +0, +262394, +452, +453, +459, +131320, +453, +327745, +456, +457, +92, +455, +262205, +6, +458, +457, +196670, +449, +458, +131321, +454, +131320, +459, +262205, +14, +460, +433, +327850, +9, +461, +460, +81, +196855, +463, +0, +262394, +461, +462, +467, +131320, +462, +327745, +456, +465, +92, +464, +262205, +6, +466, +465, +196670, +449, +466, +131321, +463, +131320, +467, +262205, +14, +468, +433, +327850, +9, +469, +468, +111, +196855, +471, +0, +262394, +469, +470, +475, +131320, +470, +327745, +456, +473, +92, +472, +262205, +6, +474, +473, +196670, +449, +474, +131321, +471, +131320, +475, +262205, +14, +476, +433, +327850, +9, +477, +476, +131, +196855, +479, +0, +262394, +477, +478, +479, +131320, +478, +327745, +456, +481, +92, +480, +262205, +6, +482, +481, +196670, +449, +482, +131321, +479, +131320, +479, +131321, +471, +131320, +471, +131321, +463, +131320, +463, +131321, +454, +131320, +454, +262205, +6, +483, +449, +458764, +6, +485, +1, +37, +483, +484, +327813, +6, +486, +343, +485, +196670, +449, +486, +196670, +487, +488, +196670, +489, +488, +131321, +490, +131320, +490, +262390, +492, +493, +0, +131321, +494, +131320, +494, +262205, +16, +495, +489, +262268, +14, +496, +495, +262205, +14, +497, +431, +327856, +9, +498, +496, +497, +262394, +498, +491, +492, +131320, +491, +262205, +16, +499, +432, +262205, +16, +500, +489, +327808, +16, +501, +499, +500, +196670, +487, +501, +262205, +16, +506, +489, +262205, +16, +511, +487, +393281, +512, +513, +510, +488, +511, +262205, +7, +514, +513, +327745, +8, +515, +505, +506, +196670, +515, +514, +131321, +493, +131320, +493, +262205, +16, +516, +489, +327808, +16, +518, +516, +517, +196670, +489, +518, +131321, +490, +131320, +492, +196670, +519, +488, +131321, +520, +131320, +520, +262390, +522, +523, +0, +131321, +524, +131320, +524, +262205, +16, +525, +519, +327745, +527, +528, +92, +526, +262205, +16, +529, +528, +327857, +9, +530, +525, +529, +262394, +530, +521, +522, +131320, +521, +327745, +8, +532, +505, +517, +262205, +7, +533, +532, +196670, +531, +533, +262205, +536, +539, +538, +262205, +16, +540, +432, +262244, +535, +541, +539, +327775, +7, +542, +541, +540, +196670, +534, +542, +196670, +543, +517, +131321, +544, +131320, +544, +262390, +546, +547, +0, +131321, +548, +131320, +548, +262205, +16, +549, +543, +262268, +14, +550, +549, +262205, +14, +551, +431, +327810, +14, +552, +551, +111, +327856, +9, +553, +550, +552, +262394, +553, +545, +546, +131320, +545, +262205, +16, +554, +432, +262205, +16, +555, +543, +327808, +16, +556, +554, +555, +196670, +487, +556, +262205, +16, +558, +543, +327808, +16, +559, +558, +517, +327745, +8, +560, +505, +559, +262205, +7, +561, +560, +196670, +557, +561, +327745, +512, +569, +567, +517, +262205, +7, +570, +569, +196670, +568, +570, +262205, +7, +572, +534, +196670, +571, +572, +393273, +7, +573, +62, +568, +571, +196670, +562, +573, +262205, +536, +576, +575, +262205, +16, +577, +487, +327808, +16, +578, +577, +517, +262244, +535, +579, +576, +327775, +7, +580, +579, +578, +524367, +64, +581, +580, +580, +0, +1, +2, +196670, +574, +581, +262205, +7, +584, +562, +196670, +583, +584, +262205, +64, +586, +574, +196670, +585, +586, +393273, +64, +587, +69, +583, +585, +262205, +7, +588, +531, +524367, +64, +589, +588, +588, +0, +1, +2, +327809, +64, +590, +587, +589, +196670, +582, +590, +262205, +6, +592, +449, +262205, +64, +593, +582, +262205, +7, +594, +557, +524367, +64, +595, +594, +594, +0, +1, +2, +327811, +64, +596, +593, +595, +327822, +64, +597, +596, +592, +196670, +591, +597, +262205, +7, +599, +531, +196670, +598, +599, +327737, +9, +600, +12, +598, +196855, +602, +0, +262394, +600, +601, +602, +131320, +601, +262205, +64, +603, +591, +262205, +7, +604, +531, +524367, +64, +605, +604, +604, +0, +1, +2, +327811, +64, +606, +605, +603, +262205, +7, +607, +531, +589903, +7, +608, +607, +606, +4, +5, +6, +3, +196670, +531, +608, +131321, +602, +131320, +602, +262205, +7, +610, +557, +196670, +609, +610, +327737, +9, +611, +12, +609, +196855, +613, +0, +262394, +611, +612, +613, +131320, +612, +262205, +64, +614, +591, +262205, +7, +615, +557, +524367, +64, +616, +615, +615, +0, +1, +2, +327809, +64, +617, +616, +614, +262205, +7, +618, +557, +589903, +7, +619, +618, +617, +4, +5, +6, +3, +196670, +557, +619, +131321, +613, +131320, +613, +262205, +7, +622, +562, +196670, +621, +622, +327737, +7, +623, +79, +621, +196670, +620, +623, +262205, +7, +625, +557, +524367, +64, +626, +625, +625, +0, +1, +2, +262205, +7, +627, +531, +524367, +64, +628, +627, +627, +0, +1, +2, +327811, +64, +629, +626, +628, +393228, +64, +630, +1, +69, +629, +196670, +624, +630, +262205, +7, +633, +620, +196670, +632, +633, +262205, +64, +635, +624, +196670, +634, +635, +393273, +64, +636, +69, +632, +634, +393228, +64, +637, +1, +69, +636, +196670, +631, +637, +196670, +638, +639, +262205, +64, +641, +638, +262205, +64, +642, +631, +458764, +64, +643, +1, +68, +641, +642, +196670, +640, +643, +262205, +64, +644, +640, +393228, +6, +645, +1, +66, +644, +327866, +9, +646, +645, +386, +196855, +648, +0, +262394, +646, +647, +648, +131320, +647, +262205, +64, +650, +638, +262205, +64, +651, +631, +327828, +6, +652, +650, +651, +393228, +6, +653, +1, +17, +652, +196670, +649, +653, +262205, +64, +654, +640, +393228, +64, +655, +1, +69, +654, +196670, +640, +655, +262205, +6, +658, +649, +196670, +657, +658, +262205, +64, +660, +640, +196670, +659, +660, +393273, +7, +661, +75, +657, +659, +196670, +656, +661, +262205, +7, +663, +534, +196670, +662, +663, +262205, +7, +665, +656, +196670, +664, +665, +393273, +7, +666, +62, +662, +664, +196670, +534, +666, +131321, +648, +131320, +648, +262205, +16, +667, +543, +262205, +7, +668, +531, +524367, +64, +669, +668, +668, +0, +1, +2, +327745, +8, +670, +505, +667, +262205, +7, +671, +670, +589903, +7, +672, +671, +669, +4, +5, +6, +3, +196670, +670, +672, +262205, +16, +673, +543, +327808, +16, +674, +673, +517, +262205, +7, +675, +557, +524367, +64, +676, +675, +675, +0, +1, +2, +327745, +8, +677, +505, +674, +262205, +7, +678, +677, +589903, +7, +679, +678, +676, +4, +5, +6, +3, +196670, +677, +679, +262205, +7, +680, +557, +196670, +531, +680, +131321, +547, +131320, +547, +262205, +16, +681, +543, +327808, +16, +682, +681, +517, +196670, +543, +682, +131321, +544, +131320, +546, +131321, +523, +131320, +523, +262205, +16, +683, +519, +327808, +16, +684, +683, +517, +196670, +519, +684, +131321, +520, +131320, +522, +196670, +685, +488, +131321, +686, +131320, +686, +262390, +688, +689, +0, +131321, +690, +131320, +690, +262205, +16, +691, +685, +262268, +14, +692, +691, +262205, +14, +693, +431, +327856, +9, +694, +692, +693, +262394, +694, +687, +688, +131320, +687, +262205, +16, +695, +432, +262205, +16, +696, +685, +327808, +16, +697, +695, +696, +196670, +487, +697, +262205, +16, +698, +487, +262205, +16, +699, +685, +327745, +8, +700, +505, +699, +262205, +7, +701, +700, +393281, +512, +702, +510, +488, +698, +196670, +702, +701, +131321, +689, +131320, +689, +262205, +16, +703, +685, +327808, +16, +704, +703, +517, +196670, +685, +704, +131321, +686, +131320, +688, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +327745, +71, +82, +11, +81, +262205, +6, +83, +82, +327866, +9, +85, +83, +84, +131326, +85, +65592, +327734, +2, +28, +0, +18, +196663, +15, +19, +196663, +15, +20, +196663, +15, +21, +196663, +15, +22, +196663, +17, +23, +196663, +15, +24, +196663, +15, +25, +196663, +15, +26, +196663, +15, +27, +131320, +29, +262205, +14, +88, +19, +196670, +26, +88, +327745, +94, +95, +92, +93, +262205, +14, +96, +95, +327814, +14, +97, +89, +96, +196670, +25, +97, +262205, +14, +98, +19, +327745, +94, +99, +92, +93, +262205, +14, +100, +99, +327817, +14, +101, +98, +100, +196670, +22, +101, +262205, +14, +102, +20, +327745, +94, +103, +92, +93, +262205, +14, +104, +103, +327812, +14, +105, +102, +104, +262205, +14, +106, +22, +327808, +14, +107, +105, +106, +196670, +21, +107, +327745, +94, +109, +92, +108, +262205, +14, +110, +109, +327808, +14, +112, +110, +111, +262205, +14, +113, +21, +327812, +14, +114, +113, +112, +196670, +21, +114, +262205, +14, +115, +19, +262205, +14, +116, +22, +327810, +14, +117, +115, +116, +327745, +94, +118, +92, +93, +262205, +14, +119, +118, +327814, +14, +120, +117, +119, +196670, +24, +120, +262205, +122, +125, +124, +262205, +14, +126, +21, +262268, +16, +127, +126, +262244, +121, +128, +125, +327775, +129, +130, +128, +127, +327761, +14, +132, +130, +0, +196670, +27, +132, +262205, +14, +133, +21, +262205, +14, +134, +25, +327812, +14, +135, +133, +134, +262205, +14, +136, +24, +327808, +14, +137, +135, +136, +262268, +16, +138, +137, +196670, +23, +138, +65789, +65592, +327734, +2, +39, +0, +18, +196663, +15, +30, +196663, +15, +31, +196663, +15, +32, +196663, +15, +33, +196663, +17, +34, +196663, +15, +35, +196663, +15, +36, +196663, +15, +37, +196663, +15, +38, +131320, +40, +262205, +14, +139, +30, +196670, +37, +139, +327745, +94, +140, +92, +93, +262205, +14, +141, +140, +327814, +14, +142, +89, +141, +196670, +36, +142, +262205, +14, +143, +30, +327745, +94, +144, +92, +93, +262205, +14, +145, +144, +327817, +14, +146, +143, +145, +196670, +33, +146, +262205, +14, +147, +31, +327745, +94, +148, +92, +93, +262205, +14, +149, +148, +327812, +14, +150, +147, +149, +262205, +14, +151, +33, +327808, +14, +152, +150, +151, +196670, +32, +152, +262205, +14, +153, +30, +262205, +14, +154, +33, +327810, +14, +155, +153, +154, +327745, +94, +156, +92, +93, +262205, +14, +157, +156, +327814, +14, +158, +155, +157, +196670, +35, +158, +262205, +122, +159, +124, +262205, +14, +160, +32, +262268, +16, +161, +160, +262244, +121, +162, +159, +327775, +129, +163, +162, +161, +327761, +14, +164, +163, +0, +196670, +38, +164, +262205, +14, +165, +32, +262205, +14, +166, +36, +327812, +14, +167, +165, +166, +262205, +14, +168, +35, +327808, +14, +169, +167, +168, +262268, +16, +170, +169, +196670, +34, +170, +65789, +65592, +327734, +2, +48, +0, +41, +196663, +15, +42, +196663, +15, +43, +196663, +15, +44, +196663, +15, +45, +196663, +15, +46, +196663, +15, +47, +131320, +49, +262205, +14, +171, +43, +327812, +14, +172, +89, +171, +262205, +14, +173, +42, +327808, +14, +174, +172, +173, +196670, +44, +174, +327745, +94, +175, +92, +93, +262205, +14, +176, +175, +327814, +14, +177, +89, +176, +196670, +45, +177, +262205, +122, +178, +124, +262205, +14, +179, +44, +262268, +16, +180, +179, +262244, +121, +181, +178, +327775, +129, +182, +181, +180, +327761, +14, +183, +182, +0, +196670, +47, +183, +262205, +14, +184, +44, +262205, +14, +185, +45, +327812, +14, +186, +184, +185, +196670, +46, +186, +65789, +65592, +327734, +2, +57, +0, +50, +196663, +17, +51, +196663, +17, +52, +196663, +17, +53, +196663, +15, +54, +196663, +17, +55, +196663, +15, +56, +131320, +58, +262205, +16, +188, +52, +327812, +16, +189, +187, +188, +262205, +16, +190, +51, +327808, +16, +191, +189, +190, +196670, +53, +191, +327745, +94, +192, +92, +108, +262205, +14, +193, +192, +327808, +14, +194, +193, +111, +262268, +16, +195, +194, +262205, +16, +196, +53, +327812, +16, +197, +196, +195, +196670, +53, +197, +327745, +94, +198, +92, +93, +262205, +14, +199, +198, +327814, +14, +200, +89, +199, +196670, +54, +200, +262205, +122, +201, +124, +262205, +16, +202, +53, +262244, +121, +203, +201, +327775, +129, +204, +203, +202, +327761, +14, +205, +204, +0, +196670, +56, +205, +262205, +16, +206, +53, +262205, +14, +207, +54, +262268, +16, +208, +207, +327812, +16, +209, +206, +208, +196670, +55, +209, +65789, +65592, +327734, +7, +62, +0, +59, +196663, +8, +60, +196663, +8, +61, +131320, +63, +262203, +8, +210, +7, +327745, +71, +211, +60, +81, +262205, +6, +212, +211, +327745, +71, +213, +61, +81, +262205, +6, +214, +213, +327813, +6, +215, +212, +214, +327745, +71, +216, +60, +131, +262205, +6, +217, +216, +327745, +71, +218, +61, +131, +262205, +6, +219, +218, +327813, +6, +220, +217, +219, +327811, +6, +221, +215, +220, +327745, +71, +222, +60, +111, +262205, +6, +223, +222, +327745, +71, +224, +61, +111, +262205, +6, +225, +224, +327813, +6, +226, +223, +225, +327811, +6, +227, +221, +226, +327745, +71, +229, +60, +228, +262205, +6, +230, +229, +327745, +71, +231, +61, +228, +262205, +6, +232, +231, +327813, +6, +233, +230, +232, +327811, +6, +234, +227, +233, +327745, +71, +235, +210, +81, +196670, +235, +234, +327745, +71, +236, +60, +81, +262205, +6, +237, +236, +327745, +71, +238, +61, +131, +262205, +6, +239, +238, +327813, +6, +240, +237, +239, +327745, +71, +241, +60, +131, +262205, +6, +242, +241, +327745, +71, +243, +61, +81, +262205, +6, +244, +243, +327813, +6, +245, +242, +244, +327809, +6, +246, +240, +245, +327745, +71, +247, +60, +111, +262205, +6, +248, +247, +327745, +71, +249, +61, +228, +262205, +6, +250, +249, +327813, +6, +251, +248, +250, +327809, +6, +252, +246, +251, +327745, +71, +253, +60, +228, +262205, +6, +254, +253, +327745, +71, +255, +61, +111, +262205, +6, +256, +255, +327813, +6, +257, +254, +256, +327811, +6, +258, +252, +257, +327745, +71, +259, +210, +131, +196670, +259, +258, +327745, +71, +260, +60, +81, +262205, +6, +261, +260, +327745, +71, +262, +61, +111, +262205, +6, +263, +262, +327813, +6, +264, +261, +263, +327745, +71, +265, +60, +111, +262205, +6, +266, +265, +327745, +71, +267, +61, +81, +262205, +6, +268, +267, +327813, +6, +269, +266, +268, +327809, +6, +270, +264, +269, +327745, +71, +271, +60, +228, +262205, +6, +272, +271, +327745, +71, +273, +61, +131, +262205, +6, +274, +273, +327813, +6, +275, +272, +274, +327809, +6, +276, +270, +275, +327745, +71, +277, +60, +131, +262205, +6, +278, +277, +327745, +71, +279, +61, +228, +262205, +6, +280, +279, +327813, +6, +281, +278, +280, +327811, +6, +282, +276, +281, +327745, +71, +283, +210, +111, +196670, +283, +282, +327745, +71, +284, +60, +81, +262205, +6, +285, +284, +327745, +71, +286, +61, +228, +262205, +6, +287, +286, +327813, +6, +288, +285, +287, +327745, +71, +289, +60, +228, +262205, +6, +290, +289, +327745, +71, +291, +61, +81, +262205, +6, +292, +291, +327813, +6, +293, +290, +292, +327809, +6, +294, +288, +293, +327745, +71, +295, +60, +131, +262205, +6, +296, +295, +327745, +71, +297, +61, +111, +262205, +6, +298, +297, +327813, +6, +299, +296, +298, +327809, +6, +300, +294, +299, +327745, +71, +301, +60, +111, +262205, +6, +302, +301, +327745, +71, +303, +61, +131, +262205, +6, +304, +303, +327813, +6, +305, +302, +304, +327811, +6, +306, +300, +305, +327745, +71, +307, +210, +228, +196670, +307, +306, +262205, +7, +308, +210, +131326, +308, +65592, +327734, +64, +69, +0, +66, +196663, +8, +67, +196663, +65, +68, +131320, +70, +262203, +65, +311, +7, +262203, +65, +319, +7, +262203, +65, +323, +7, +327745, +71, +312, +67, +131, +262205, +6, +313, +312, +327745, +71, +314, +67, +111, +262205, +6, +315, +314, +327745, +71, +316, +67, +228, +262205, +6, +317, +316, +393296, +64, +318, +313, +315, +317, +196670, +311, +318, +262205, +64, +320, +311, +262205, +64, +321, +68, +458764, +64, +322, +1, +68, +320, +321, +196670, +319, +322, +262205, +64, +324, +311, +262205, +64, +325, +319, +458764, +64, +326, +1, +68, +324, +325, +196670, +323, +326, +327745, +71, +328, +67, +81, +262205, +6, +329, +328, +327813, +6, +330, +327, +329, +262205, +64, +331, +319, +327822, +64, +332, +331, +330, +196670, +319, +332, +262205, +64, +333, +323, +327822, +64, +334, +333, +327, +196670, +323, +334, +262205, +64, +335, +68, +262205, +64, +336, +319, +327809, +64, +337, +335, +336, +262205, +64, +338, +323, +327809, +64, +339, +337, +338, +131326, +339, +65592, +327734, +7, +75, +0, +72, +196663, +71, +73, +196663, +65, +74, +131320, +76, +262203, +71, +342, +7, +262203, +71, +346, +7, +262203, +8, +349, +7, +262205, +6, +344, +73, +327813, +6, +345, +343, +344, +196670, +342, +345, +262205, +6, +347, +342, +393228, +6, +348, +1, +13, +347, +196670, +346, +348, +262205, +6, +350, +342, +393228, +6, +351, +1, +14, +350, +327745, +71, +352, +349, +81, +196670, +352, +351, +262205, +6, +353, +346, +262205, +64, +354, +74, +327822, +64, +355, +354, +353, +262205, +7, +356, +349, +589903, +7, +357, +356, +355, +4, +5, +6, +3, +196670, +349, +357, +262205, +7, +358, +349, +131326, +358, +65592, +327734, +7, +79, +0, +77, +196663, +8, +78, +131320, +80, +262203, +71, +361, +7, +327745, +71, +362, +78, +131, +262205, +6, +363, +362, +327745, +71, +364, +78, +131, +262205, +6, +365, +364, +327813, +6, +366, +363, +365, +327745, +71, +367, +78, +111, +262205, +6, +368, +367, +327745, +71, +369, +78, +111, +262205, +6, +370, +369, +327813, +6, +371, +368, +370, +327809, +6, +372, +366, +371, +327745, +71, +373, +78, +228, +262205, +6, +374, +373, +327745, +71, +375, +78, +228, +262205, +6, +376, +375, +327813, +6, +377, +374, +376, +327809, +6, +378, +372, +377, +327745, +71, +379, +78, +81, +262205, +6, +380, +379, +327745, +71, +381, +78, +81, +262205, +6, +382, +381, +327813, +6, +383, +380, +382, +327809, +6, +384, +378, +383, +196670, +361, +384, +262205, +6, +385, +361, +327864, +9, +387, +385, +386, +196855, +389, +0, +262394, +387, +388, +389, +131320, +388, +131326, +391, +131320, +389, +327745, +71, +393, +78, +131, +262205, +6, +394, +393, +262271, +6, +395, +394, +262205, +6, +396, +361, +327816, +6, +397, +395, +396, +327745, +71, +398, +78, +131, +196670, +398, +397, +327745, +71, +399, +78, +111, +262205, +6, +400, +399, +262271, +6, +401, +400, +262205, +6, +402, +361, +327816, +6, +403, +401, +402, +327745, +71, +404, +78, +111, +196670, +404, +403, +327745, +71, +405, +78, +228, +262205, +6, +406, +405, +262271, +6, +407, +406, +262205, +6, +408, +361, +327816, +6, +409, +407, +408, +327745, +71, +410, +78, +228, +196670, +410, +409, +327745, +71, +411, +78, +81, +262205, +6, +412, +411, +262205, +6, +413, +361, +327816, +6, +414, +412, +413, +327745, +71, +415, +78, +81, +196670, +415, +414, +262205, +7, +416, +78, +131326, +416, +65592, +}; +const std::vector compute_tangents = {119734787, +65536, +524289, +302, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +458767, +5, +4, +1852399981, +0, +191, +192, +393232, +4, +17, +64, +1, +1, +196611, +2, +450, +262149, +4, +1852399981, +0, +393221, +12, +1867346761, +1818386806, +1719019621, +15156, +327685, +11, +1953653104, +1701602153, +0, +1114117, +28, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1953718605, +1965584997, +829766449, +993097019, +1765486965, +829766449, +993097019, +1966813557, +15153, +327685, +19, +1633906540, +1684627308, +0, +327685, +20, +1970238055, +1684627312, +0, +458757, +21, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +22, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +23, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +24, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +25, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +26, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +27, +1634890867, +2035573870, +25968, +1114117, +39, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +828980017, +993097019, +1966813557, +829766449, +59, +327685, +30, +1633906540, +1684627308, +0, +327685, +31, +1970238055, +1684627312, +0, +458757, +32, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +33, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +34, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +35, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +36, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +37, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +38, +1634890867, +2035573870, +25968, +983045, +48, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +829766449, +993097019, +0, +327685, +42, +1633906540, +1684627308, +0, +327685, +43, +1970238055, +1684627312, +0, +458757, +44, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +45, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +46, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +47, +1634890867, +2035573870, +25968, +983045, +57, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1953718605, +1764258405, +828980017, +993093947, +1765486965, +829766449, +59, +327685, +51, +1633906540, +1684627308, +0, +327685, +52, +1970238055, +1684627312, +0, +458757, +53, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +54, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +55, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +56, +1634890867, +2035573870, +25968, +327685, +69, +1936617283, +1953390964, +115, +327686, +69, +0, +1767333735, +25710, +327686, +69, +1, +1767333735, +3236974, +327686, +69, +2, +1767333735, +3302510, +327686, +69, +3, +1767333735, +3368046, +720902, +69, +4, +1968070503, +1852132461, +1130919015, +1953721967, +1852399986, +1702119796, +1769234802, +7564911, +458758, +69, +5, +1130520423, +1768713327, +1852795251, +0, +524294, +69, +6, +1917280103, +1953068641, +1734430073, +1970563438, +25956, +393222, +69, +7, +1767137127, +1951622509, +28773, +393222, +69, +8, +1631870823, +1852403821, +12391, +786438, +69, +9, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +48, +786438, +69, +10, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12391, +851974, +69, +11, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +811951982, +0, +393222, +69, +12, +1631870823, +1852403821, +12647, +786438, +69, +13, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +49, +786438, +69, +14, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12647, +851974, +69, +15, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +828729198, +0, +393222, +69, +16, +1631870823, +1852403821, +12903, +786438, +69, +17, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +50, +786438, +69, +18, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12903, +851974, +69, +19, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +845506414, +0, +393222, +69, +20, +1631870823, +1852403821, +13159, +786438, +69, +21, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +51, +786438, +69, +22, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +13159, +851974, +69, +23, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +862283630, +0, +720902, +69, +24, +1968070503, +1399213933, +1851880052, +1699771236, +1919439986, +1197760869, +1886744434, +0, +720902, +69, +25, +1968070503, +1819231853, +1215786860, +1936877921, +1198679376, +1701079413, +1919508808, +0, +589830, +69, +26, +1767137127, +1885688688, +1952543329, +1181642601, +1869898593, +114, +327686, +69, +27, +1466064743, +7369313, +786438, +69, +28, +1968070503, +1668238445, +1750297697, +1298493537, +1751348321, +1231515241, +1634887028, +1852795252, +115, +196613, +71, +0, +458757, +103, +1632132967, +1951625833, +1684955506, +1701869908, +0, +524293, +191, +1281322087, +1818321775, +1870032457, +1769234787, +1145663087, +0, +393221, +192, +1465871463, +1198223983, +1886744434, +17481, +458757, +193, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +194, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +195, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +196, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +197, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +198, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +199, +1634890867, +2035573870, +25968, +262149, +200, +1634886000, +109, +262149, +204, +1634886000, +109, +262149, +207, +1634886000, +109, +262149, +209, +1634886000, +109, +262149, +211, +1634886000, +109, +262149, +213, +1634886000, +109, +262149, +215, +1634886000, +109, +262149, +217, +1634886000, +109, +262149, +219, +1634886000, +109, +327685, +231, +1918986355, +1867539557, +115, +524293, +233, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +589829, +242, +1332573550, +1920226150, +1935961697, +1416783184, +1634038376, +1869760356, +28789, +262149, +251, +1735287156, +7630437, +458757, +264, +1953067639, +1818386789, +1936674917, +1869182057, +29550, +589830, +264, +0, +1632132967, +1700164201, +2019914866, +1735287124, +1937010277, +0, +196613, +266, +0, +393221, +276, +1953654134, +1834969439, +1937075817, +12639, +262149, +283, +1953654134, +26975, +393221, +298, +1684104520, +1851880020, +1919903347, +109, +589830, +298, +0, +1867341671, +1416389988, +1936613746, +1836216166, +1215459142, +6578533, +589830, +298, +1, +1867341671, +1382835556, +1952543855, +1919895141, +1684104520, +0, +589830, +298, +2, +1852396386, +1214606439, +1415864677, +1936613746, +1836216166, +0, +327686, +298, +3, +1684300144, +6778473, +196613, +300, +0, +327752, +69, +0, +35, +0, +327752, +69, +1, +35, +16, +327752, +69, +2, +35, +32, +327752, +69, +3, +35, +48, +327752, +69, +4, +35, +64, +327752, +69, +5, +35, +68, +327752, +69, +6, +35, +72, +327752, +69, +7, +35, +76, +327752, +69, +8, +35, +80, +327752, +69, +9, +35, +84, +327752, +69, +10, +35, +88, +327752, +69, +11, +35, +92, +327752, +69, +12, +35, +96, +327752, +69, +13, +35, +100, +327752, +69, +14, +35, +104, +327752, +69, +15, +35, +108, +327752, +69, +16, +35, +112, +327752, +69, +17, +35, +116, +327752, +69, +18, +35, +120, +327752, +69, +19, +35, +124, +327752, +69, +20, +35, +128, +327752, +69, +21, +35, +132, +327752, +69, +22, +35, +136, +327752, +69, +23, +35, +140, +327752, +69, +24, +35, +144, +327752, +69, +25, +35, +148, +327752, +69, +26, +35, +152, +327752, +69, +27, +35, +156, +327752, +69, +28, +35, +160, +196679, +69, +3, +262215, +71, +34, +0, +262215, +71, +33, +16, +262215, +103, +34, +1, +262215, +103, +33, +22, +262215, +191, +11, +27, +262215, +192, +11, +26, +262215, +233, +34, +1, +262215, +233, +33, +7, +262215, +263, +6, +16, +327752, +264, +0, +35, +0, +196679, +264, +3, +262215, +266, +34, +1, +262215, +266, +33, +8, +262215, +297, +6, +16, +262216, +298, +0, +5, +327752, +298, +0, +35, +0, +327752, +298, +0, +7, +16, +327752, +298, +1, +35, +64, +327752, +298, +2, +35, +80, +327752, +298, +3, +35, +96, +196679, +298, +3, +262215, +300, +34, +0, +262215, +300, +33, +27, +262215, +301, +11, +25, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +131092, +9, +262177, +10, +9, +8, +262165, +14, +32, +0, +262176, +15, +7, +14, +262165, +16, +32, +1, +262176, +17, +7, +16, +786465, +18, +2, +15, +15, +15, +15, +17, +15, +15, +15, +15, +589857, +41, +2, +15, +15, +15, +15, +15, +15, +589857, +50, +2, +17, +17, +17, +15, +17, +15, +262187, +14, +59, +3, +262176, +60, +7, +6, +262187, +6, +63, +0, +262187, +14, +68, +64, +2031646, +69, +7, +7, +7, +7, +16, +16, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +14, +14, +6, +16, +16, +262176, +70, +2, +69, +262203, +70, +71, +2, +262187, +16, +72, +24, +262176, +73, +2, +14, +262187, +16, +87, +25, +262187, +14, +90, +1, +589849, +100, +14, +5, +0, +0, +0, +1, +0, +196635, +101, +100, +262176, +102, +0, +101, +262203, +102, +103, +0, +262167, +108, +14, +4, +262187, +14, +110, +0, +262187, +16, +166, +64, +262167, +189, +14, +3, +262176, +190, +1, +189, +262203, +190, +191, +1, +262203, +190, +192, +1, +262176, +201, +1, +14, +262172, +229, +7, +68, +262176, +230, +4, +229, +262203, +230, +231, +4, +262203, +102, +233, +0, +262176, +239, +4, +7, +262187, +14, +241, +2, +262167, +249, +6, +3, +262176, +250, +7, +249, +196637, +263, +7, +196638, +264, +263, +262176, +265, +2, +264, +262203, +265, +266, +2, +262187, +16, +267, +0, +262176, +271, +2, +7, +262168, +296, +7, +4, +262172, +297, +6, +59, +393246, +298, +296, +7, +16, +297, +262176, +299, +2, +298, +262203, +299, +300, +2, +393260, +189, +301, +68, +90, +90, +327734, +2, +4, +0, +3, +131320, +5, +262203, +15, +193, +7, +262203, +15, +194, +7, +262203, +17, +195, +7, +262203, +15, +196, +7, +262203, +15, +197, +7, +262203, +15, +198, +7, +262203, +15, +199, +7, +262203, +15, +200, +7, +262203, +15, +204, +7, +262203, +15, +207, +7, +262203, +15, +209, +7, +262203, +17, +211, +7, +262203, +15, +213, +7, +262203, +15, +215, +7, +262203, +15, +217, +7, +262203, +15, +219, +7, +262203, +15, +242, +7, +262203, +250, +251, +7, +262203, +250, +276, +7, +262203, +250, +283, +7, +327745, +201, +202, +191, +110, +262205, +14, +203, +202, +196670, +200, +203, +327745, +201, +205, +192, +110, +262205, +14, +206, +205, +196670, +204, +206, +262205, +14, +208, +193, +196670, +207, +208, +262205, +14, +210, +194, +196670, +209, +210, +262205, +16, +212, +195, +196670, +211, +212, +262205, +14, +214, +196, +196670, +213, +214, +262205, +14, +216, +197, +196670, +215, +216, +262205, +14, +218, +198, +196670, +217, +218, +262205, +14, +220, +199, +196670, +219, +220, +852025, +2, +221, +39, +200, +204, +207, +209, +211, +213, +215, +217, +219, +262205, +14, +222, +207, +196670, +193, +222, +262205, +14, +223, +209, +196670, +194, +223, +262205, +16, +224, +211, +196670, +195, +224, +262205, +14, +225, +213, +196670, +196, +225, +262205, +14, +226, +215, +196670, +197, +226, +262205, +14, +227, +217, +196670, +198, +227, +262205, +14, +228, +219, +196670, +199, +228, +262205, +14, +232, +198, +262205, +101, +234, +233, +262205, +16, +235, +195, +262244, +100, +236, +234, +327775, +108, +237, +236, +235, +262256, +7, +238, +237, +327745, +239, +240, +231, +232, +196670, +240, +238, +262368, +241, +90, +110, +327745, +73, +243, +71, +72, +262205, +14, +244, +243, +196670, +242, +244, +262205, +14, +245, +196, +327850, +9, +246, +245, +110, +196855, +248, +0, +262394, +246, +247, +275, +131320, +247, +262205, +14, +252, +198, +262205, +14, +253, +242, +327808, +14, +254, +252, +253, +327745, +239, +255, +231, +254, +262205, +7, +256, +255, +524367, +249, +257, +256, +256, +0, +1, +2, +262205, +14, +258, +198, +327745, +239, +259, +231, +258, +262205, +7, +260, +259, +524367, +249, +261, +260, +260, +0, +1, +2, +327811, +249, +262, +257, +261, +196670, +251, +262, +262205, +16, +268, +195, +262205, +249, +269, +251, +393228, +249, +270, +1, +69, +269, +393281, +271, +272, +266, +267, +268, +262205, +7, +273, +272, +589903, +7, +274, +273, +270, +4, +5, +6, +3, +196670, +272, +274, +131321, +248, +131320, +275, +262205, +14, +277, +198, +262205, +14, +278, +242, +327810, +14, +279, +277, +278, +327745, +239, +280, +231, +279, +262205, +7, +281, +280, +524367, +249, +282, +281, +281, +0, +1, +2, +196670, +276, +282, +262205, +14, +284, +198, +327745, +239, +285, +231, +284, +262205, +7, +286, +285, +524367, +249, +287, +286, +286, +0, +1, +2, +196670, +283, +287, +262205, +16, +288, +195, +262205, +249, +289, +283, +262205, +249, +290, +276, +327811, +249, +291, +289, +290, +393228, +249, +292, +1, +69, +291, +393281, +271, +293, +266, +267, +288, +262205, +7, +294, +293, +589903, +7, +295, +294, +292, +4, +5, +6, +3, +196670, +293, +295, +131321, +248, +131320, +248, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +327745, +60, +61, +11, +59, +262205, +6, +62, +61, +327866, +9, +64, +62, +63, +131326, +64, +65592, +327734, +2, +28, +0, +18, +196663, +15, +19, +196663, +15, +20, +196663, +15, +21, +196663, +15, +22, +196663, +17, +23, +196663, +15, +24, +196663, +15, +25, +196663, +15, +26, +196663, +15, +27, +131320, +29, +262205, +14, +67, +19, +196670, +26, +67, +327745, +73, +74, +71, +72, +262205, +14, +75, +74, +327814, +14, +76, +68, +75, +196670, +25, +76, +262205, +14, +77, +19, +327745, +73, +78, +71, +72, +262205, +14, +79, +78, +327817, +14, +80, +77, +79, +196670, +22, +80, +262205, +14, +81, +20, +327745, +73, +82, +71, +72, +262205, +14, +83, +82, +327812, +14, +84, +81, +83, +262205, +14, +85, +22, +327808, +14, +86, +84, +85, +196670, +21, +86, +327745, +73, +88, +71, +87, +262205, +14, +89, +88, +327808, +14, +91, +89, +90, +262205, +14, +92, +21, +327812, +14, +93, +92, +91, +196670, +21, +93, +262205, +14, +94, +19, +262205, +14, +95, +22, +327810, +14, +96, +94, +95, +327745, +73, +97, +71, +72, +262205, +14, +98, +97, +327814, +14, +99, +96, +98, +196670, +24, +99, +262205, +101, +104, +103, +262205, +14, +105, +21, +262268, +16, +106, +105, +262244, +100, +107, +104, +327775, +108, +109, +107, +106, +327761, +14, +111, +109, +0, +196670, +27, +111, +262205, +14, +112, +21, +262205, +14, +113, +25, +327812, +14, +114, +112, +113, +262205, +14, +115, +24, +327808, +14, +116, +114, +115, +262268, +16, +117, +116, +196670, +23, +117, +65789, +65592, +327734, +2, +39, +0, +18, +196663, +15, +30, +196663, +15, +31, +196663, +15, +32, +196663, +15, +33, +196663, +17, +34, +196663, +15, +35, +196663, +15, +36, +196663, +15, +37, +196663, +15, +38, +131320, +40, +262205, +14, +118, +30, +196670, +37, +118, +327745, +73, +119, +71, +72, +262205, +14, +120, +119, +327814, +14, +121, +68, +120, +196670, +36, +121, +262205, +14, +122, +30, +327745, +73, +123, +71, +72, +262205, +14, +124, +123, +327817, +14, +125, +122, +124, +196670, +33, +125, +262205, +14, +126, +31, +327745, +73, +127, +71, +72, +262205, +14, +128, +127, +327812, +14, +129, +126, +128, +262205, +14, +130, +33, +327808, +14, +131, +129, +130, +196670, +32, +131, +262205, +14, +132, +30, +262205, +14, +133, +33, +327810, +14, +134, +132, +133, +327745, +73, +135, +71, +72, +262205, +14, +136, +135, +327814, +14, +137, +134, +136, +196670, +35, +137, +262205, +101, +138, +103, +262205, +14, +139, +32, +262268, +16, +140, +139, +262244, +100, +141, +138, +327775, +108, +142, +141, +140, +327761, +14, +143, +142, +0, +196670, +38, +143, +262205, +14, +144, +32, +262205, +14, +145, +36, +327812, +14, +146, +144, +145, +262205, +14, +147, +35, +327808, +14, +148, +146, +147, +262268, +16, +149, +148, +196670, +34, +149, +65789, +65592, +327734, +2, +48, +0, +41, +196663, +15, +42, +196663, +15, +43, +196663, +15, +44, +196663, +15, +45, +196663, +15, +46, +196663, +15, +47, +131320, +49, +262205, +14, +150, +43, +327812, +14, +151, +68, +150, +262205, +14, +152, +42, +327808, +14, +153, +151, +152, +196670, +44, +153, +327745, +73, +154, +71, +72, +262205, +14, +155, +154, +327814, +14, +156, +68, +155, +196670, +45, +156, +262205, +101, +157, +103, +262205, +14, +158, +44, +262268, +16, +159, +158, +262244, +100, +160, +157, +327775, +108, +161, +160, +159, +327761, +14, +162, +161, +0, +196670, +47, +162, +262205, +14, +163, +44, +262205, +14, +164, +45, +327812, +14, +165, +163, +164, +196670, +46, +165, +65789, +65592, +327734, +2, +57, +0, +50, +196663, +17, +51, +196663, +17, +52, +196663, +17, +53, +196663, +15, +54, +196663, +17, +55, +196663, +15, +56, +131320, +58, +262205, +16, +167, +52, +327812, +16, +168, +166, +167, +262205, +16, +169, +51, +327808, +16, +170, +168, +169, +196670, +53, +170, +327745, +73, +171, +71, +87, +262205, +14, +172, +171, +327808, +14, +173, +172, +90, +262268, +16, +174, +173, +262205, +16, +175, +53, +327812, +16, +176, +175, +174, +196670, +53, +176, +327745, +73, +177, +71, +72, +262205, +14, +178, +177, +327814, +14, +179, +68, +178, +196670, +54, +179, +262205, +101, +180, +103, +262205, +16, +181, +53, +262244, +100, +182, +180, +327775, +108, +183, +182, +181, +327761, +14, +184, +183, +0, +196670, +56, +184, +262205, +16, +185, +53, +262205, +14, +186, +54, +262268, +16, +187, +186, +327812, +16, +188, +185, +187, +196670, +55, +188, +65789, +65592, +}; +const std::vector length_wind_collision = {119734787, +65536, +524289, +586, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +458767, +5, +4, +1852399981, +0, +283, +284, +393232, +4, +17, +64, +1, +1, +196611, +2, +450, +262149, +4, +1852399981, +0, +393221, +12, +1867346761, +1818386806, +1719019621, +15156, +327685, +11, +1953653104, +1701602153, +0, +1114117, +28, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1953718605, +1965584997, +829766449, +993097019, +1765486965, +829766449, +993097019, +1966813557, +15153, +327685, +19, +1633906540, +1684627308, +0, +327685, +20, +1970238055, +1684627312, +0, +458757, +21, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +22, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +23, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +24, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +25, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +26, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +27, +1634890867, +2035573870, +25968, +1114117, +39, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +828980017, +993097019, +1966813557, +829766449, +59, +327685, +30, +1633906540, +1684627308, +0, +327685, +31, +1970238055, +1684627312, +0, +458757, +32, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +33, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +34, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +35, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +36, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +37, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +38, +1634890867, +2035573870, +25968, +983045, +48, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +829766449, +993097019, +0, +327685, +42, +1633906540, +1684627308, +0, +327685, +43, +1970238055, +1684627312, +0, +458757, +44, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +45, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +46, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +47, +1634890867, +2035573870, +25968, +983045, +57, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1953718605, +1764258405, +828980017, +993093947, +1765486965, +829766449, +59, +327685, +51, +1633906540, +1684627308, +0, +327685, +52, +1970238055, +1684627312, +0, +458757, +53, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +54, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +55, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +56, +1634890867, +2035573870, +25968, +655365, +63, +1936617283, +1767993972, +1968010350, +1885959276, +1919248748, +879130152, +879130171, +59, +327685, +61, +1953653104, +1701602153, +48, +327685, +62, +1953653104, +1701602153, +49, +786437, +71, +1819308097, +1936278649, +1668178292, +1852785509, +1634890867, +678719081, +993289846, +993289846, +1715155302, +15153, +262149, +67, +812871536, +0, +262149, +68, +829648752, +0, +393221, +69, +1735549300, +1766093925, +1851880563, +25955, +327685, +70, +1718187123, +1936027238, +115, +327685, +82, +1936617283, +1953390964, +115, +327686, +82, +0, +1767333735, +25710, +327686, +82, +1, +1767333735, +3236974, +327686, +82, +2, +1767333735, +3302510, +327686, +82, +3, +1767333735, +3368046, +720902, +82, +4, +1968070503, +1852132461, +1130919015, +1953721967, +1852399986, +1702119796, +1769234802, +7564911, +458758, +82, +5, +1130520423, +1768713327, +1852795251, +0, +524294, +82, +6, +1917280103, +1953068641, +1734430073, +1970563438, +25956, +393222, +82, +7, +1767137127, +1951622509, +28773, +393222, +82, +8, +1631870823, +1852403821, +12391, +786438, +82, +9, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +48, +786438, +82, +10, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12391, +851974, +82, +11, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +811951982, +0, +393222, +82, +12, +1631870823, +1852403821, +12647, +786438, +82, +13, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +49, +786438, +82, +14, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12647, +851974, +82, +15, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +828729198, +0, +393222, +82, +16, +1631870823, +1852403821, +12903, +786438, +82, +17, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +50, +786438, +82, +18, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12903, +851974, +82, +19, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +845506414, +0, +393222, +82, +20, +1631870823, +1852403821, +13159, +786438, +82, +21, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +51, +786438, +82, +22, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +13159, +851974, +82, +23, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +862283630, +0, +720902, +82, +24, +1968070503, +1399213933, +1851880052, +1699771236, +1919439986, +1197760869, +1886744434, +0, +720902, +82, +25, +1968070503, +1819231853, +1215786860, +1936877921, +1198679376, +1701079413, +1919508808, +0, +589830, +82, +26, +1767137127, +1885688688, +1952543329, +1181642601, +1869898593, +114, +327686, +82, +27, +1466064743, +7369313, +786438, +82, +28, +1968070503, +1668238445, +1750297697, +1298493537, +1751348321, +1231515241, +1634887028, +1852795252, +115, +196613, +84, +0, +458757, +116, +1632132967, +1951625833, +1684955506, +1701869908, +0, +262149, +202, +1634886000, +109, +262149, +207, +1634886000, +109, +262149, +220, +1634886000, +109, +262149, +233, +1953260900, +97, +327685, +239, +1953720676, +1701015137, +0, +327685, +244, +1701999731, +1768448884, +26478, +327685, +253, +1953265005, +1768714345, +29285, +262149, +254, +1634886000, +109, +262149, +256, +1634886000, +109, +524293, +283, +1281322087, +1818321775, +1870032457, +1769234787, +1145663087, +0, +393221, +284, +1465871463, +1198223983, +1886744434, +17481, +458757, +285, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +286, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +287, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +288, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +289, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +290, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +291, +1634890867, +2035573870, +25968, +262149, +292, +1634886000, +109, +262149, +296, +1634886000, +109, +262149, +299, +1634886000, +109, +262149, +301, +1634886000, +109, +262149, +303, +1634886000, +109, +262149, +305, +1634886000, +109, +262149, +307, +1634886000, +109, +262149, +309, +1634886000, +109, +262149, +311, +1634886000, +109, +589829, +321, +1332573550, +1920226150, +1935961697, +1416783184, +1634038376, +1869760356, +28789, +327685, +326, +1918986355, +1867539557, +115, +458757, +329, +1953067639, +1818386789, +1936674917, +1869182057, +29550, +589830, +329, +0, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +196613, +331, +0, +393221, +341, +1918986355, +1699505253, +1752459118, +0, +458757, +346, +1632132967, +1699902057, +1699509363, +1752459118, +5657171, +262149, +375, +1668444006, +101, +262149, +377, +1835102822, +101, +196613, +391, +97, +196613, +398, +119, +327685, +427, +1918986355, +1850303589, +7890276, +196613, +436, +118, +262149, +449, +1668444006, +101, +196613, +472, +97, +196613, +479, +98, +327685, +486, +1919251561, +1869182049, +17774, +327685, +498, +1918986355, +1850303589, +7890276, +262149, +520, +1634886000, +109, +262149, +523, +1634886000, +109, +262149, +526, +1634886000, +109, +262149, +529, +1634886000, +109, +262149, +554, +1634886000, +109, +262149, +557, +1634886000, +109, +262149, +560, +1634886000, +109, +262149, +563, +1634886000, +109, +393221, +572, +1819231074, +1702126916, +1684370531, +0, +393221, +582, +1684104520, +1851880020, +1919903347, +109, +589830, +582, +0, +1867341671, +1416389988, +1936613746, +1836216166, +1215459142, +6578533, +589830, +582, +1, +1867341671, +1382835556, +1952543855, +1919895141, +1684104520, +0, +589830, +582, +2, +1852396386, +1214606439, +1415864677, +1936613746, +1836216166, +0, +327686, +582, +3, +1684300144, +6778473, +196613, +584, +0, +327752, +82, +0, +35, +0, +327752, +82, +1, +35, +16, +327752, +82, +2, +35, +32, +327752, +82, +3, +35, +48, +327752, +82, +4, +35, +64, +327752, +82, +5, +35, +68, +327752, +82, +6, +35, +72, +327752, +82, +7, +35, +76, +327752, +82, +8, +35, +80, +327752, +82, +9, +35, +84, +327752, +82, +10, +35, +88, +327752, +82, +11, +35, +92, +327752, +82, +12, +35, +96, +327752, +82, +13, +35, +100, +327752, +82, +14, +35, +104, +327752, +82, +15, +35, +108, +327752, +82, +16, +35, +112, +327752, +82, +17, +35, +116, +327752, +82, +18, +35, +120, +327752, +82, +19, +35, +124, +327752, +82, +20, +35, +128, +327752, +82, +21, +35, +132, +327752, +82, +22, +35, +136, +327752, +82, +23, +35, +140, +327752, +82, +24, +35, +144, +327752, +82, +25, +35, +148, +327752, +82, +26, +35, +152, +327752, +82, +27, +35, +156, +327752, +82, +28, +35, +160, +196679, +82, +3, +262215, +84, +34, +0, +262215, +84, +33, +16, +262215, +116, +34, +1, +262215, +116, +33, +22, +262215, +283, +11, +27, +262215, +284, +11, +26, +262215, +328, +6, +16, +327752, +329, +0, +35, +0, +196679, +329, +3, +262215, +331, +34, +1, +262215, +331, +33, +7, +262215, +346, +34, +1, +262215, +346, +33, +26, +262215, +581, +6, +16, +262216, +582, +0, +5, +327752, +582, +0, +35, +0, +327752, +582, +0, +7, +16, +327752, +582, +1, +35, +64, +327752, +582, +2, +35, +80, +327752, +582, +3, +35, +96, +196679, +582, +3, +262215, +584, +34, +0, +262215, +584, +33, +27, +262215, +585, +11, +25, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +131092, +9, +262177, +10, +9, +8, +262165, +14, +32, +0, +262176, +15, +7, +14, +262165, +16, +32, +1, +262176, +17, +7, +16, +786465, +18, +2, +15, +15, +15, +15, +17, +15, +15, +15, +15, +589857, +41, +2, +15, +15, +15, +15, +15, +15, +589857, +50, +2, +17, +17, +17, +15, +17, +15, +262167, +59, +6, +2, +327713, +60, +59, +8, +8, +262176, +65, +7, +6, +458785, +66, +2, +8, +8, +65, +65, +262187, +14, +73, +3, +262187, +6, +76, +0, +262187, +14, +81, +64, +2031646, +82, +7, +7, +7, +7, +16, +16, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +14, +14, +6, +16, +16, +262176, +83, +2, +82, +262203, +83, +84, +2, +262187, +16, +85, +24, +262176, +86, +2, +14, +262187, +16, +100, +25, +262187, +14, +103, +1, +589849, +113, +14, +5, +0, +0, +0, +1, +0, +196635, +114, +113, +262176, +115, +0, +114, +262203, +115, +116, +0, +262167, +121, +14, +4, +262187, +14, +123, +0, +262187, +16, +179, +64, +262187, +6, +212, +1056964608, +327724, +59, +213, +212, +212, +262187, +6, +216, +1065353216, +327724, +59, +217, +216, +76, +327724, +59, +225, +76, +216, +327724, +59, +228, +76, +76, +262167, +231, +6, +3, +262176, +232, +7, +231, +262187, +6, +242, +869711765, +262176, +252, +7, +59, +262167, +281, +14, +3, +262176, +282, +1, +281, +262203, +282, +283, +1, +262203, +282, +284, +1, +262176, +293, +1, +14, +262172, +324, +7, +81, +262176, +325, +4, +324, +262203, +325, +326, +4, +196637, +328, +7, +196638, +329, +328, +262176, +330, +2, +329, +262203, +330, +331, +2, +262187, +16, +332, +0, +262176, +334, +2, +7, +262176, +337, +4, +7, +262172, +339, +6, +81, +262176, +340, +4, +339, +262203, +340, +341, +4, +589849, +343, +6, +5, +0, +0, +0, +1, +0, +196635, +344, +343, +262176, +345, +0, +344, +262203, +345, +346, +0, +262176, +352, +4, +6, +262187, +14, +354, +2, +262176, +355, +2, +6, +458796, +7, +376, +76, +76, +76, +76, +262187, +14, +393, +20, +262187, +6, +396, +1101004800, +262187, +16, +406, +1, +262187, +16, +413, +2, +262187, +16, +421, +3, +262187, +16, +458, +7, +262187, +6, +475, +1073741824, +262187, +16, +493, +4, +262176, +494, +2, +16, +262176, +571, +7, +9, +196650, +9, +573, +262168, +580, +7, +4, +262172, +581, +6, +73, +393246, +582, +580, +7, +16, +581, +262176, +583, +2, +582, +262203, +583, +584, +2, +393260, +281, +585, +81, +103, +103, +327734, +2, +4, +0, +3, +131320, +5, +262203, +15, +285, +7, +262203, +15, +286, +7, +262203, +17, +287, +7, +262203, +15, +288, +7, +262203, +15, +289, +7, +262203, +15, +290, +7, +262203, +15, +291, +7, +262203, +15, +292, +7, +262203, +15, +296, +7, +262203, +15, +299, +7, +262203, +15, +301, +7, +262203, +17, +303, +7, +262203, +15, +305, +7, +262203, +15, +307, +7, +262203, +15, +309, +7, +262203, +15, +311, +7, +262203, +15, +321, +7, +262203, +8, +375, +7, +262203, +65, +377, +7, +262203, +65, +391, +7, +262203, +232, +398, +7, +262203, +17, +427, +7, +262203, +232, +436, +7, +262203, +232, +449, +7, +262203, +17, +472, +7, +262203, +17, +479, +7, +262203, +17, +486, +7, +262203, +17, +498, +7, +262203, +8, +520, +7, +262203, +8, +523, +7, +262203, +65, +526, +7, +262203, +65, +529, +7, +262203, +8, +554, +7, +262203, +8, +557, +7, +262203, +65, +560, +7, +262203, +65, +563, +7, +262203, +571, +572, +7, +327745, +293, +294, +283, +123, +262205, +14, +295, +294, +196670, +292, +295, +327745, +293, +297, +284, +123, +262205, +14, +298, +297, +196670, +296, +298, +262205, +14, +300, +285, +196670, +299, +300, +262205, +14, +302, +286, +196670, +301, +302, +262205, +16, +304, +287, +196670, +303, +304, +262205, +14, +306, +288, +196670, +305, +306, +262205, +14, +308, +289, +196670, +307, +308, +262205, +14, +310, +290, +196670, +309, +310, +262205, +14, +312, +291, +196670, +311, +312, +852025, +2, +313, +28, +292, +296, +299, +301, +303, +305, +307, +309, +311, +262205, +14, +314, +299, +196670, +285, +314, +262205, +14, +315, +301, +196670, +286, +315, +262205, +16, +316, +303, +196670, +287, +316, +262205, +14, +317, +305, +196670, +288, +317, +262205, +14, +318, +307, +196670, +289, +318, +262205, +14, +319, +309, +196670, +290, +319, +262205, +14, +320, +311, +196670, +291, +320, +327745, +86, +322, +84, +85, +262205, +14, +323, +322, +196670, +321, +323, +262205, +14, +327, +290, +262205, +16, +333, +287, +393281, +334, +335, +331, +332, +333, +262205, +7, +336, +335, +327745, +337, +338, +326, +327, +196670, +338, +336, +262205, +14, +342, +290, +262205, +344, +347, +346, +262205, +16, +348, +287, +262244, +343, +349, +347, +327775, +7, +350, +349, +348, +327761, +6, +351, +350, +0, +327745, +352, +353, +341, +342, +196670, +353, +351, +262368, +354, +103, +123, +393281, +355, +356, +84, +332, +123, +262205, +6, +357, +356, +327862, +9, +358, +357, +76, +262312, +9, +359, +358, +196855, +361, +0, +262394, +359, +360, +361, +131320, +360, +393281, +355, +362, +84, +332, +103, +262205, +6, +363, +362, +327862, +9, +364, +363, +76, +131321, +361, +131320, +361, +458997, +9, +365, +358, +5, +364, +360, +262312, +9, +366, +365, +196855, +368, +0, +262394, +366, +367, +368, +131320, +367, +393281, +355, +369, +84, +332, +354, +262205, +6, +370, +369, +327862, +9, +371, +370, +76, +131321, +368, +131320, +368, +458997, +9, +372, +365, +361, +371, +367, +196855, +374, +0, +262394, +372, +373, +374, +131320, +373, +196670, +375, +376, +393281, +355, +378, +84, +332, +73, +262205, +6, +379, +378, +196670, +377, +379, +262205, +14, +380, +288, +327854, +9, +381, +380, +354, +196855, +383, +0, +262394, +381, +382, +383, +131320, +382, +262205, +14, +384, +288, +262205, +14, +385, +289, +327810, +14, +386, +385, +103, +327856, +9, +387, +384, +386, +131321, +383, +131320, +383, +458997, +9, +388, +381, +373, +387, +382, +196855, +390, +0, +262394, +388, +389, +390, +131320, +389, +262205, +14, +392, +285, +327817, +14, +394, +392, +393, +262256, +6, +395, +394, +327816, +6, +397, +395, +396, +196670, +391, +397, +262205, +6, +399, +391, +327745, +334, +400, +84, +332, +262205, +7, +401, +400, +524367, +231, +402, +401, +401, +0, +1, +2, +327822, +231, +403, +402, +399, +262205, +6, +404, +391, +327811, +6, +405, +216, +404, +327745, +334, +407, +84, +406, +262205, +7, +408, +407, +524367, +231, +409, +408, +408, +0, +1, +2, +327822, +231, +410, +409, +405, +327809, +231, +411, +403, +410, +262205, +6, +412, +391, +327745, +334, +414, +84, +413, +262205, +7, +415, +414, +524367, +231, +416, +415, +415, +0, +1, +2, +327822, +231, +417, +416, +412, +327809, +231, +418, +411, +417, +262205, +6, +419, +391, +327811, +6, +420, +216, +419, +327745, +334, +422, +84, +421, +262205, +7, +423, +422, +524367, +231, +424, +423, +423, +0, +1, +2, +327822, +231, +425, +424, +420, +327809, +231, +426, +418, +425, +196670, +398, +426, +262205, +14, +428, +288, +262268, +16, +429, +428, +262205, +14, +430, +321, +262268, +16, +431, +430, +327812, +16, +432, +429, +431, +262205, +14, +433, +286, +262268, +16, +434, +433, +327808, +16, +435, +432, +434, +196670, +427, +435, +262205, +16, +437, +427, +327745, +337, +438, +326, +437, +262205, +7, +439, +438, +524367, +231, +440, +439, +439, +0, +1, +2, +262205, +16, +441, +427, +262268, +14, +442, +441, +262205, +14, +443, +321, +327808, +14, +444, +442, +443, +327745, +337, +445, +326, +444, +262205, +7, +446, +445, +524367, +231, +447, +446, +446, +0, +1, +2, +327811, +231, +448, +440, +447, +196670, +436, +448, +262205, +231, +450, +436, +262205, +231, +451, +398, +458764, +231, +452, +1, +68, +450, +451, +262205, +231, +453, +436, +458764, +231, +454, +1, +68, +452, +453, +262271, +231, +455, +454, +196670, +449, +455, +262205, +16, +456, +427, +262205, +231, +457, +449, +327745, +355, +459, +84, +458, +262205, +6, +460, +459, +327822, +231, +461, +457, +460, +327745, +355, +462, +84, +458, +262205, +6, +463, +462, +327822, +231, +464, +461, +463, +327745, +337, +465, +326, +456, +262205, +7, +466, +465, +524367, +231, +467, +466, +466, +0, +1, +2, +327809, +231, +468, +467, +464, +327745, +337, +469, +326, +456, +262205, +7, +470, +469, +589903, +7, +471, +470, +468, +4, +5, +6, +3, +196670, +469, +471, +131321, +390, +131320, +390, +131321, +374, +131320, +374, +262368, +354, +103, +123, +262205, +14, +473, +289, +262256, +6, +474, +473, +327816, +6, +476, +474, +475, +393228, +6, +477, +1, +8, +476, +262254, +16, +478, +477, +196670, +472, +478, +262205, +14, +480, +289, +262256, +6, +481, +480, +327811, +6, +482, +481, +216, +327816, +6, +483, +482, +475, +393228, +6, +484, +1, +8, +483, +262254, +16, +485, +484, +196670, +479, +485, +196670, +486, +332, +131321, +487, +131320, +487, +262390, +489, +490, +0, +131321, +491, +131320, +491, +262205, +16, +492, +486, +327745, +494, +495, +84, +493, +262205, +16, +496, +495, +327857, +9, +497, +492, +496, +262394, +497, +488, +489, +131320, +488, +262205, +14, +499, +288, +262268, +16, +500, +499, +327812, +16, +501, +413, +500, +262205, +14, +502, +321, +262268, +16, +503, +502, +327812, +16, +504, +501, +503, +262205, +14, +505, +286, +262268, +16, +506, +505, +327808, +16, +507, +504, +506, +196670, +498, +507, +262205, +14, +508, +288, +262205, +16, +509, +472, +262268, +14, +510, +509, +327856, +9, +511, +508, +510, +196855, +513, +0, +262394, +511, +512, +513, +131320, +512, +262205, +16, +514, +498, +262205, +16, +515, +498, +262268, +14, +516, +515, +262205, +14, +517, +321, +327808, +14, +518, +516, +517, +262205, +16, +519, +498, +327745, +337, +521, +326, +514, +262205, +7, +522, +521, +196670, +520, +522, +327745, +337, +524, +326, +518, +262205, +7, +525, +524, +196670, +523, +525, +327745, +352, +527, +341, +519, +262205, +6, +528, +527, +196670, +526, +528, +196670, +529, +216, +524345, +2, +530, +71, +520, +523, +526, +529, +262205, +7, +531, +520, +327745, +337, +532, +326, +514, +196670, +532, +531, +262205, +7, +533, +523, +327745, +337, +534, +326, +518, +196670, +534, +533, +131321, +513, +131320, +513, +262368, +354, +103, +123, +262205, +14, +535, +288, +262205, +16, +536, +479, +262268, +14, +537, +536, +327856, +9, +538, +535, +537, +196855, +540, +0, +262394, +538, +539, +540, +131320, +539, +262205, +16, +541, +498, +262268, +14, +542, +541, +262205, +14, +543, +321, +327808, +14, +544, +542, +543, +262205, +16, +545, +498, +262268, +14, +546, +545, +262205, +14, +547, +321, +327812, +14, +548, +547, +354, +327808, +14, +549, +546, +548, +262205, +16, +550, +498, +262268, +14, +551, +550, +262205, +14, +552, +321, +327808, +14, +553, +551, +552, +327745, +337, +555, +326, +544, +262205, +7, +556, +555, +196670, +554, +556, +327745, +337, +558, +326, +549, +262205, +7, +559, +558, +196670, +557, +559, +327745, +352, +561, +341, +553, +262205, +6, +562, +561, +196670, +560, +562, +196670, +563, +216, +524345, +2, +564, +71, +554, +557, +560, +563, +262205, +7, +565, +554, +327745, +337, +566, +326, +544, +196670, +566, +565, +262205, +7, +567, +557, +327745, +337, +568, +326, +549, +196670, +568, +567, +131321, +540, +131320, +540, +262368, +354, +103, +123, +131321, +490, +131320, +490, +262205, +16, +569, +486, +327808, +16, +570, +569, +406, +196670, +486, +570, +131321, +487, +131320, +489, +196670, +572, +573, +262205, +16, +574, +287, +262205, +14, +575, +290, +327745, +337, +576, +326, +575, +262205, +7, +577, +576, +393281, +334, +578, +331, +332, +574, +196670, +578, +577, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +327745, +65, +74, +11, +73, +262205, +6, +75, +74, +327866, +9, +77, +75, +76, +131326, +77, +65592, +327734, +2, +28, +0, +18, +196663, +15, +19, +196663, +15, +20, +196663, +15, +21, +196663, +15, +22, +196663, +17, +23, +196663, +15, +24, +196663, +15, +25, +196663, +15, +26, +196663, +15, +27, +131320, +29, +262205, +14, +80, +19, +196670, +26, +80, +327745, +86, +87, +84, +85, +262205, +14, +88, +87, +327814, +14, +89, +81, +88, +196670, +25, +89, +262205, +14, +90, +19, +327745, +86, +91, +84, +85, +262205, +14, +92, +91, +327817, +14, +93, +90, +92, +196670, +22, +93, +262205, +14, +94, +20, +327745, +86, +95, +84, +85, +262205, +14, +96, +95, +327812, +14, +97, +94, +96, +262205, +14, +98, +22, +327808, +14, +99, +97, +98, +196670, +21, +99, +327745, +86, +101, +84, +100, +262205, +14, +102, +101, +327808, +14, +104, +102, +103, +262205, +14, +105, +21, +327812, +14, +106, +105, +104, +196670, +21, +106, +262205, +14, +107, +19, +262205, +14, +108, +22, +327810, +14, +109, +107, +108, +327745, +86, +110, +84, +85, +262205, +14, +111, +110, +327814, +14, +112, +109, +111, +196670, +24, +112, +262205, +114, +117, +116, +262205, +14, +118, +21, +262268, +16, +119, +118, +262244, +113, +120, +117, +327775, +121, +122, +120, +119, +327761, +14, +124, +122, +0, +196670, +27, +124, +262205, +14, +125, +21, +262205, +14, +126, +25, +327812, +14, +127, +125, +126, +262205, +14, +128, +24, +327808, +14, +129, +127, +128, +262268, +16, +130, +129, +196670, +23, +130, +65789, +65592, +327734, +2, +39, +0, +18, +196663, +15, +30, +196663, +15, +31, +196663, +15, +32, +196663, +15, +33, +196663, +17, +34, +196663, +15, +35, +196663, +15, +36, +196663, +15, +37, +196663, +15, +38, +131320, +40, +262205, +14, +131, +30, +196670, +37, +131, +327745, +86, +132, +84, +85, +262205, +14, +133, +132, +327814, +14, +134, +81, +133, +196670, +36, +134, +262205, +14, +135, +30, +327745, +86, +136, +84, +85, +262205, +14, +137, +136, +327817, +14, +138, +135, +137, +196670, +33, +138, +262205, +14, +139, +31, +327745, +86, +140, +84, +85, +262205, +14, +141, +140, +327812, +14, +142, +139, +141, +262205, +14, +143, +33, +327808, +14, +144, +142, +143, +196670, +32, +144, +262205, +14, +145, +30, +262205, +14, +146, +33, +327810, +14, +147, +145, +146, +327745, +86, +148, +84, +85, +262205, +14, +149, +148, +327814, +14, +150, +147, +149, +196670, +35, +150, +262205, +114, +151, +116, +262205, +14, +152, +32, +262268, +16, +153, +152, +262244, +113, +154, +151, +327775, +121, +155, +154, +153, +327761, +14, +156, +155, +0, +196670, +38, +156, +262205, +14, +157, +32, +262205, +14, +158, +36, +327812, +14, +159, +157, +158, +262205, +14, +160, +35, +327808, +14, +161, +159, +160, +262268, +16, +162, +161, +196670, +34, +162, +65789, +65592, +327734, +2, +48, +0, +41, +196663, +15, +42, +196663, +15, +43, +196663, +15, +44, +196663, +15, +45, +196663, +15, +46, +196663, +15, +47, +131320, +49, +262205, +14, +163, +43, +327812, +14, +164, +81, +163, +262205, +14, +165, +42, +327808, +14, +166, +164, +165, +196670, +44, +166, +327745, +86, +167, +84, +85, +262205, +14, +168, +167, +327814, +14, +169, +81, +168, +196670, +45, +169, +262205, +114, +170, +116, +262205, +14, +171, +44, +262268, +16, +172, +171, +262244, +113, +173, +170, +327775, +121, +174, +173, +172, +327761, +14, +175, +174, +0, +196670, +47, +175, +262205, +14, +176, +44, +262205, +14, +177, +45, +327812, +14, +178, +176, +177, +196670, +46, +178, +65789, +65592, +327734, +2, +57, +0, +50, +196663, +17, +51, +196663, +17, +52, +196663, +17, +53, +196663, +15, +54, +196663, +17, +55, +196663, +15, +56, +131320, +58, +262205, +16, +180, +52, +327812, +16, +181, +179, +180, +262205, +16, +182, +51, +327808, +16, +183, +181, +182, +196670, +53, +183, +327745, +86, +184, +84, +100, +262205, +14, +185, +184, +327808, +14, +186, +185, +103, +262268, +16, +187, +186, +262205, +16, +188, +53, +327812, +16, +189, +188, +187, +196670, +53, +189, +327745, +86, +190, +84, +85, +262205, +14, +191, +190, +327814, +14, +192, +81, +191, +196670, +54, +192, +262205, +114, +193, +116, +262205, +16, +194, +53, +262244, +113, +195, +193, +327775, +121, +196, +195, +194, +327761, +14, +197, +196, +0, +196670, +56, +197, +262205, +16, +198, +53, +262205, +14, +199, +54, +262268, +16, +200, +199, +327812, +16, +201, +198, +200, +196670, +55, +201, +65789, +65592, +327734, +59, +63, +0, +60, +196663, +8, +61, +196663, +8, +62, +131320, +64, +262203, +8, +202, +7, +262203, +8, +207, +7, +262203, +8, +220, +7, +262205, +7, +203, +61, +196670, +202, +203, +327737, +9, +204, +12, +202, +196855, +206, +0, +262394, +204, +205, +219, +131320, +205, +262205, +7, +208, +62, +196670, +207, +208, +327737, +9, +209, +12, +207, +196855, +211, +0, +262394, +209, +210, +215, +131320, +210, +131326, +213, +131320, +215, +131326, +217, +131320, +211, +131321, +206, +131320, +219, +262205, +7, +221, +62, +196670, +220, +221, +327737, +9, +222, +12, +220, +196855, +224, +0, +262394, +222, +223, +227, +131320, +223, +131326, +225, +131320, +227, +131326, +228, +131320, +224, +131321, +206, +131320, +206, +196609, +59, +230, +131326, +230, +65592, +327734, +2, +71, +0, +66, +196663, +8, +67, +196663, +8, +68, +196663, +65, +69, +196663, +65, +70, +131320, +72, +262203, +232, +233, +7, +262203, +65, +239, +7, +262203, +65, +244, +7, +262203, +252, +253, +7, +262203, +8, +254, +7, +262203, +8, +256, +7, +262205, +7, +234, +68, +524367, +231, +235, +234, +234, +0, +1, +2, +262205, +7, +236, +67, +524367, +231, +237, +236, +236, +0, +1, +2, +327811, +231, +238, +235, +237, +196670, +233, +238, +262205, +231, +240, +233, +393228, +6, +241, +1, +66, +240, +458764, +6, +243, +1, +40, +241, +242, +196670, +239, +243, +262205, +6, +245, +69, +262205, +6, +246, +239, +327816, +6, +247, +245, +246, +327811, +6, +248, +216, +247, +196670, +244, +248, +262205, +6, +249, +244, +262205, +231, +250, +233, +327822, +231, +251, +250, +249, +196670, +233, +251, +262205, +7, +255, +67, +196670, +254, +255, +262205, +7, +257, +68, +196670, +256, +257, +393273, +59, +258, +63, +254, +256, +196670, +253, +258, +327745, +65, +259, +253, +123, +262205, +6, +260, +259, +262205, +231, +261, +233, +327822, +231, +262, +261, +260, +262205, +6, +263, +70, +327822, +231, +264, +262, +263, +262205, +7, +265, +67, +524367, +231, +266, +265, +265, +0, +1, +2, +327809, +231, +267, +266, +264, +262205, +7, +268, +67, +589903, +7, +269, +268, +267, +4, +5, +6, +3, +196670, +67, +269, +327745, +65, +270, +253, +103, +262205, +6, +271, +270, +262205, +231, +272, +233, +327822, +231, +273, +272, +271, +262205, +6, +274, +70, +327822, +231, +275, +273, +274, +262205, +7, +276, +68, +524367, +231, +277, +276, +276, +0, +1, +2, +327811, +231, +278, +277, +275, +262205, +7, +279, +68, +589903, +7, +280, +279, +278, +4, +5, +6, +3, +196670, +68, +280, +65789, +65592, +}; +const std::vector prepare_follow_hair = {119734787, +65536, +524289, +276, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +458767, +5, +4, +1852399981, +0, +191, +192, +393232, +4, +17, +64, +1, +1, +196611, +2, +450, +262149, +4, +1852399981, +0, +393221, +12, +1867346761, +1818386806, +1719019621, +15156, +327685, +11, +1953653104, +1701602153, +0, +1114117, +28, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1953718605, +1965584997, +829766449, +993097019, +1765486965, +829766449, +993097019, +1966813557, +15153, +327685, +19, +1633906540, +1684627308, +0, +327685, +20, +1970238055, +1684627312, +0, +458757, +21, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +22, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +23, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +24, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +25, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +26, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +27, +1634890867, +2035573870, +25968, +1114117, +39, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +828980017, +993097019, +1966813557, +829766449, +59, +327685, +30, +1633906540, +1684627308, +0, +327685, +31, +1970238055, +1684627312, +0, +458757, +32, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +33, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +34, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +35, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +36, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +37, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +38, +1634890867, +2035573870, +25968, +983045, +48, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +829766449, +993097019, +0, +327685, +42, +1633906540, +1684627308, +0, +327685, +43, +1970238055, +1684627312, +0, +458757, +44, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +45, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +46, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +47, +1634890867, +2035573870, +25968, +983045, +57, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1953718605, +1764258405, +828980017, +993093947, +1765486965, +829766449, +59, +327685, +51, +1633906540, +1684627308, +0, +327685, +52, +1970238055, +1684627312, +0, +458757, +53, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +54, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +55, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +56, +1634890867, +2035573870, +25968, +327685, +69, +1936617283, +1953390964, +115, +327686, +69, +0, +1767333735, +25710, +327686, +69, +1, +1767333735, +3236974, +327686, +69, +2, +1767333735, +3302510, +327686, +69, +3, +1767333735, +3368046, +720902, +69, +4, +1968070503, +1852132461, +1130919015, +1953721967, +1852399986, +1702119796, +1769234802, +7564911, +458758, +69, +5, +1130520423, +1768713327, +1852795251, +0, +524294, +69, +6, +1917280103, +1953068641, +1734430073, +1970563438, +25956, +393222, +69, +7, +1767137127, +1951622509, +28773, +393222, +69, +8, +1631870823, +1852403821, +12391, +786438, +69, +9, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +48, +786438, +69, +10, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12391, +851974, +69, +11, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +811951982, +0, +393222, +69, +12, +1631870823, +1852403821, +12647, +786438, +69, +13, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +49, +786438, +69, +14, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12647, +851974, +69, +15, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +828729198, +0, +393222, +69, +16, +1631870823, +1852403821, +12903, +786438, +69, +17, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +50, +786438, +69, +18, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12903, +851974, +69, +19, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +845506414, +0, +393222, +69, +20, +1631870823, +1852403821, +13159, +786438, +69, +21, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +51, +786438, +69, +22, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +13159, +851974, +69, +23, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +862283630, +0, +720902, +69, +24, +1968070503, +1399213933, +1851880052, +1699771236, +1919439986, +1197760869, +1886744434, +0, +720902, +69, +25, +1968070503, +1819231853, +1215786860, +1936877921, +1198679376, +1701079413, +1919508808, +0, +589830, +69, +26, +1767137127, +1885688688, +1952543329, +1181642601, +1869898593, +114, +327686, +69, +27, +1466064743, +7369313, +786438, +69, +28, +1968070503, +1668238445, +1750297697, +1298493537, +1751348321, +1231515241, +1634887028, +1852795252, +115, +196613, +71, +0, +458757, +103, +1632132967, +1951625833, +1684955506, +1701869908, +0, +524293, +191, +1281322087, +1818321775, +1870032457, +1769234787, +1145663087, +0, +393221, +192, +1465871463, +1198223983, +1886744434, +17481, +458757, +193, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +194, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +195, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +196, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +197, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +198, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +199, +1634890867, +2035573870, +25968, +262149, +200, +1634886000, +109, +262149, +204, +1634886000, +109, +262149, +207, +1634886000, +109, +262149, +209, +1634886000, +109, +262149, +211, +1634886000, +109, +262149, +213, +1634886000, +109, +262149, +215, +1634886000, +109, +262149, +217, +1634886000, +109, +262149, +219, +1634886000, +109, +196613, +229, +105, +524293, +241, +1651469415, +1866886241, +2003790956, +1953654102, +1850308709, +7890276, +262149, +250, +1919508840, +7565136, +524293, +254, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +524293, +260, +1953067639, +1818386789, +1936674917, +1869182057, +1701990510, +118, +655366, +260, +0, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +1701990515, +118, +196613, +262, +0, +393221, +272, +1684104520, +1851880020, +1919903347, +109, +589830, +272, +0, +1867341671, +1416389988, +1936613746, +1836216166, +1215459142, +6578533, +589830, +272, +1, +1867341671, +1382835556, +1952543855, +1919895141, +1684104520, +0, +589830, +272, +2, +1852396386, +1214606439, +1415864677, +1936613746, +1836216166, +0, +327686, +272, +3, +1684300144, +6778473, +196613, +274, +0, +327752, +69, +0, +35, +0, +327752, +69, +1, +35, +16, +327752, +69, +2, +35, +32, +327752, +69, +3, +35, +48, +327752, +69, +4, +35, +64, +327752, +69, +5, +35, +68, +327752, +69, +6, +35, +72, +327752, +69, +7, +35, +76, +327752, +69, +8, +35, +80, +327752, +69, +9, +35, +84, +327752, +69, +10, +35, +88, +327752, +69, +11, +35, +92, +327752, +69, +12, +35, +96, +327752, +69, +13, +35, +100, +327752, +69, +14, +35, +104, +327752, +69, +15, +35, +108, +327752, +69, +16, +35, +112, +327752, +69, +17, +35, +116, +327752, +69, +18, +35, +120, +327752, +69, +19, +35, +124, +327752, +69, +20, +35, +128, +327752, +69, +21, +35, +132, +327752, +69, +22, +35, +136, +327752, +69, +23, +35, +140, +327752, +69, +24, +35, +144, +327752, +69, +25, +35, +148, +327752, +69, +26, +35, +152, +327752, +69, +27, +35, +156, +327752, +69, +28, +35, +160, +196679, +69, +3, +262215, +71, +34, +0, +262215, +71, +33, +16, +262215, +103, +34, +1, +262215, +103, +33, +22, +262215, +191, +11, +27, +262215, +192, +11, +26, +262215, +254, +34, +1, +262215, +254, +33, +7, +262215, +259, +6, +16, +327752, +260, +0, +35, +0, +196679, +260, +3, +262215, +262, +34, +1, +262215, +262, +33, +20, +262215, +271, +6, +16, +262216, +272, +0, +5, +327752, +272, +0, +35, +0, +327752, +272, +0, +7, +16, +327752, +272, +1, +35, +64, +327752, +272, +2, +35, +80, +327752, +272, +3, +35, +96, +196679, +272, +3, +262215, +274, +34, +0, +262215, +274, +33, +27, +262215, +275, +11, +25, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +131092, +9, +262177, +10, +9, +8, +262165, +14, +32, +0, +262176, +15, +7, +14, +262165, +16, +32, +1, +262176, +17, +7, +16, +786465, +18, +2, +15, +15, +15, +15, +17, +15, +15, +15, +15, +589857, +41, +2, +15, +15, +15, +15, +15, +15, +589857, +50, +2, +17, +17, +17, +15, +17, +15, +262187, +14, +59, +3, +262176, +60, +7, +6, +262187, +6, +63, +0, +262187, +14, +68, +64, +2031646, +69, +7, +7, +7, +7, +16, +16, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +14, +14, +6, +16, +16, +262176, +70, +2, +69, +262203, +70, +71, +2, +262187, +16, +72, +24, +262176, +73, +2, +14, +262187, +16, +87, +25, +262187, +14, +90, +1, +589849, +100, +14, +5, +0, +0, +0, +1, +0, +196635, +101, +100, +262176, +102, +0, +101, +262203, +102, +103, +0, +262167, +108, +14, +4, +262187, +14, +110, +0, +262187, +16, +166, +64, +262167, +189, +14, +3, +262176, +190, +1, +189, +262203, +190, +191, +1, +262203, +190, +192, +1, +262176, +201, +1, +14, +262187, +16, +230, +0, +262187, +16, +246, +1, +589849, +251, +6, +5, +0, +0, +0, +1, +0, +196635, +252, +251, +262176, +253, +0, +252, +262203, +253, +254, +0, +196637, +259, +7, +196638, +260, +259, +262176, +261, +2, +260, +262203, +261, +262, +2, +262176, +265, +2, +7, +262168, +270, +7, +4, +262172, +271, +6, +59, +393246, +272, +270, +7, +16, +271, +262176, +273, +2, +272, +262203, +273, +274, +2, +393260, +189, +275, +68, +90, +90, +327734, +2, +4, +0, +3, +131320, +5, +262203, +15, +193, +7, +262203, +15, +194, +7, +262203, +17, +195, +7, +262203, +15, +196, +7, +262203, +15, +197, +7, +262203, +15, +198, +7, +262203, +15, +199, +7, +262203, +15, +200, +7, +262203, +15, +204, +7, +262203, +15, +207, +7, +262203, +15, +209, +7, +262203, +17, +211, +7, +262203, +15, +213, +7, +262203, +15, +215, +7, +262203, +15, +217, +7, +262203, +15, +219, +7, +262203, +17, +229, +7, +262203, +17, +241, +7, +262203, +8, +250, +7, +327745, +201, +202, +191, +110, +262205, +14, +203, +202, +196670, +200, +203, +327745, +201, +205, +192, +110, +262205, +14, +206, +205, +196670, +204, +206, +262205, +14, +208, +193, +196670, +207, +208, +262205, +14, +210, +194, +196670, +209, +210, +262205, +16, +212, +195, +196670, +211, +212, +262205, +14, +214, +196, +196670, +213, +214, +262205, +14, +216, +197, +196670, +215, +216, +262205, +14, +218, +198, +196670, +217, +218, +262205, +14, +220, +199, +196670, +219, +220, +852025, +2, +221, +28, +200, +204, +207, +209, +211, +213, +215, +217, +219, +262205, +14, +222, +207, +196670, +193, +222, +262205, +14, +223, +209, +196670, +194, +223, +262205, +16, +224, +211, +196670, +195, +224, +262205, +14, +225, +213, +196670, +196, +225, +262205, +14, +226, +215, +196670, +197, +226, +262205, +14, +227, +217, +196670, +198, +227, +262205, +14, +228, +219, +196670, +199, +228, +196670, +229, +230, +131321, +231, +131320, +231, +262390, +233, +234, +0, +131321, +235, +131320, +235, +262205, +16, +236, +229, +262268, +14, +237, +236, +327745, +73, +238, +71, +87, +262205, +14, +239, +238, +327856, +9, +240, +237, +239, +262394, +240, +232, +233, +131320, +232, +262205, +16, +242, +195, +262205, +14, +243, +197, +262268, +16, +244, +243, +262205, +16, +245, +229, +327808, +16, +247, +245, +246, +327812, +16, +248, +244, +247, +327808, +16, +249, +242, +248, +196670, +241, +249, +262205, +252, +255, +254, +262205, +16, +256, +241, +262244, +251, +257, +255, +327775, +7, +258, +257, +256, +196670, +250, +258, +262205, +16, +263, +241, +262205, +7, +264, +250, +393281, +265, +266, +262, +230, +263, +196670, +266, +264, +131321, +234, +131320, +234, +262205, +16, +267, +229, +327808, +16, +268, +267, +246, +196670, +229, +268, +131321, +231, +131320, +233, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +327745, +60, +61, +11, +59, +262205, +6, +62, +61, +327866, +9, +64, +62, +63, +131326, +64, +65592, +327734, +2, +28, +0, +18, +196663, +15, +19, +196663, +15, +20, +196663, +15, +21, +196663, +15, +22, +196663, +17, +23, +196663, +15, +24, +196663, +15, +25, +196663, +15, +26, +196663, +15, +27, +131320, +29, +262205, +14, +67, +19, +196670, +26, +67, +327745, +73, +74, +71, +72, +262205, +14, +75, +74, +327814, +14, +76, +68, +75, +196670, +25, +76, +262205, +14, +77, +19, +327745, +73, +78, +71, +72, +262205, +14, +79, +78, +327817, +14, +80, +77, +79, +196670, +22, +80, +262205, +14, +81, +20, +327745, +73, +82, +71, +72, +262205, +14, +83, +82, +327812, +14, +84, +81, +83, +262205, +14, +85, +22, +327808, +14, +86, +84, +85, +196670, +21, +86, +327745, +73, +88, +71, +87, +262205, +14, +89, +88, +327808, +14, +91, +89, +90, +262205, +14, +92, +21, +327812, +14, +93, +92, +91, +196670, +21, +93, +262205, +14, +94, +19, +262205, +14, +95, +22, +327810, +14, +96, +94, +95, +327745, +73, +97, +71, +72, +262205, +14, +98, +97, +327814, +14, +99, +96, +98, +196670, +24, +99, +262205, +101, +104, +103, +262205, +14, +105, +21, +262268, +16, +106, +105, +262244, +100, +107, +104, +327775, +108, +109, +107, +106, +327761, +14, +111, +109, +0, +196670, +27, +111, +262205, +14, +112, +21, +262205, +14, +113, +25, +327812, +14, +114, +112, +113, +262205, +14, +115, +24, +327808, +14, +116, +114, +115, +262268, +16, +117, +116, +196670, +23, +117, +65789, +65592, +327734, +2, +39, +0, +18, +196663, +15, +30, +196663, +15, +31, +196663, +15, +32, +196663, +15, +33, +196663, +17, +34, +196663, +15, +35, +196663, +15, +36, +196663, +15, +37, +196663, +15, +38, +131320, +40, +262205, +14, +118, +30, +196670, +37, +118, +327745, +73, +119, +71, +72, +262205, +14, +120, +119, +327814, +14, +121, +68, +120, +196670, +36, +121, +262205, +14, +122, +30, +327745, +73, +123, +71, +72, +262205, +14, +124, +123, +327817, +14, +125, +122, +124, +196670, +33, +125, +262205, +14, +126, +31, +327745, +73, +127, +71, +72, +262205, +14, +128, +127, +327812, +14, +129, +126, +128, +262205, +14, +130, +33, +327808, +14, +131, +129, +130, +196670, +32, +131, +262205, +14, +132, +30, +262205, +14, +133, +33, +327810, +14, +134, +132, +133, +327745, +73, +135, +71, +72, +262205, +14, +136, +135, +327814, +14, +137, +134, +136, +196670, +35, +137, +262205, +101, +138, +103, +262205, +14, +139, +32, +262268, +16, +140, +139, +262244, +100, +141, +138, +327775, +108, +142, +141, +140, +327761, +14, +143, +142, +0, +196670, +38, +143, +262205, +14, +144, +32, +262205, +14, +145, +36, +327812, +14, +146, +144, +145, +262205, +14, +147, +35, +327808, +14, +148, +146, +147, +262268, +16, +149, +148, +196670, +34, +149, +65789, +65592, +327734, +2, +48, +0, +41, +196663, +15, +42, +196663, +15, +43, +196663, +15, +44, +196663, +15, +45, +196663, +15, +46, +196663, +15, +47, +131320, +49, +262205, +14, +150, +43, +327812, +14, +151, +68, +150, +262205, +14, +152, +42, +327808, +14, +153, +151, +152, +196670, +44, +153, +327745, +73, +154, +71, +72, +262205, +14, +155, +154, +327814, +14, +156, +68, +155, +196670, +45, +156, +262205, +101, +157, +103, +262205, +14, +158, +44, +262268, +16, +159, +158, +262244, +100, +160, +157, +327775, +108, +161, +160, +159, +327761, +14, +162, +161, +0, +196670, +47, +162, +262205, +14, +163, +44, +262205, +14, +164, +45, +327812, +14, +165, +163, +164, +196670, +46, +165, +65789, +65592, +327734, +2, +57, +0, +50, +196663, +17, +51, +196663, +17, +52, +196663, +17, +53, +196663, +15, +54, +196663, +17, +55, +196663, +15, +56, +131320, +58, +262205, +16, +167, +52, +327812, +16, +168, +166, +167, +262205, +16, +169, +51, +327808, +16, +170, +168, +169, +196670, +53, +170, +327745, +73, +171, +71, +87, +262205, +14, +172, +171, +327808, +14, +173, +172, +90, +262268, +16, +174, +173, +262205, +16, +175, +53, +327812, +16, +176, +175, +174, +196670, +53, +176, +327745, +73, +177, +71, +72, +262205, +14, +178, +177, +327814, +14, +179, +68, +178, +196670, +54, +179, +262205, +101, +180, +103, +262205, +16, +181, +53, +262244, +100, +182, +180, +327775, +108, +183, +182, +181, +327761, +14, +184, +183, +0, +196670, +56, +184, +262205, +16, +185, +53, +262205, +14, +186, +54, +262268, +16, +187, +186, +327812, +16, +188, +185, +187, +196670, +55, +188, +65789, +65592, +}; +const std::vector update_follow_hair = {119734787, +65536, +524289, +317, +0, +131089, +1, +131089, +46, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +458767, +5, +4, +1852399981, +0, +191, +192, +393232, +4, +17, +64, +1, +1, +196611, +2, +450, +262149, +4, +1852399981, +0, +393221, +12, +1867346761, +1818386806, +1719019621, +15156, +327685, +11, +1953653104, +1701602153, +0, +1114117, +28, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1953718605, +1965584997, +829766449, +993097019, +1765486965, +829766449, +993097019, +1966813557, +15153, +327685, +19, +1633906540, +1684627308, +0, +327685, +20, +1970238055, +1684627312, +0, +458757, +21, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +22, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +23, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +24, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +25, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +26, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +27, +1634890867, +2035573870, +25968, +1114117, +39, +1668047171, +1768189513, +1232299363, +1919243886, +1282958708, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +828980017, +993097019, +1966813557, +829766449, +59, +327685, +30, +1633906540, +1684627308, +0, +327685, +31, +1970238055, +1684627312, +0, +458757, +32, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +33, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +34, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +35, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +36, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +37, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +38, +1634890867, +2035573870, +25968, +983045, +48, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1635020628, +829761644, +993097019, +1966813557, +829766449, +993097019, +0, +327685, +42, +1633906540, +1684627308, +0, +327685, +43, +1970238055, +1684627312, +0, +458757, +44, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +45, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +46, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +47, +1634890867, +2035573870, +25968, +983045, +57, +1668047171, +1768189513, +1232299363, +1920226158, +1281650273, +1818588773, +1953718605, +1764258405, +828980017, +993093947, +1765486965, +829766449, +59, +327685, +51, +1633906540, +1684627308, +0, +327685, +52, +1970238055, +1684627312, +0, +458757, +53, +1651469415, +1951624289, +1684955506, +1701080649, +120, +524293, +54, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +524293, +55, +1651469415, +1867672673, +1700164719, +2019914866, +1701080649, +120, +327685, +56, +1634890867, +2035573870, +25968, +327685, +69, +1936617283, +1953390964, +115, +327686, +69, +0, +1767333735, +25710, +327686, +69, +1, +1767333735, +3236974, +327686, +69, +2, +1767333735, +3302510, +327686, +69, +3, +1767333735, +3368046, +720902, +69, +4, +1968070503, +1852132461, +1130919015, +1953721967, +1852399986, +1702119796, +1769234802, +7564911, +458758, +69, +5, +1130520423, +1768713327, +1852795251, +0, +524294, +69, +6, +1917280103, +1953068641, +1734430073, +1970563438, +25956, +393222, +69, +7, +1767137127, +1951622509, +28773, +393222, +69, +8, +1631870823, +1852403821, +12391, +786438, +69, +9, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +48, +786438, +69, +10, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12391, +851974, +69, +11, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +811951982, +0, +393222, +69, +12, +1631870823, +1852403821, +12647, +786438, +69, +13, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +49, +786438, +69, +14, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12647, +851974, +69, +15, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +828729198, +0, +393222, +69, +16, +1631870823, +1852403821, +12903, +786438, +69, +17, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +50, +786438, +69, +18, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +12903, +851974, +69, +19, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +845506414, +0, +393222, +69, +20, +1631870823, +1852403821, +13159, +786438, +69, +21, +1951620967, +1852204649, +1181971301, +1867281007, +1399611747, +1701863784, +1668571469, +1735289192, +51, +786438, +69, +22, +1951620967, +1852204649, +1181971301, +1816621679, +1818321519, +1885431891, +1952533861, +1852401763, +13159, +851974, +69, +23, +1816616807, +1818321519, +1885431891, +1952533861, +1852401763, +1717978471, +1769235301, +1632789878, +862283630, +0, +720902, +69, +24, +1968070503, +1399213933, +1851880052, +1699771236, +1919439986, +1197760869, +1886744434, +0, +720902, +69, +25, +1968070503, +1819231853, +1215786860, +1936877921, +1198679376, +1701079413, +1919508808, +0, +589830, +69, +26, +1767137127, +1885688688, +1952543329, +1181642601, +1869898593, +114, +327686, +69, +27, +1466064743, +7369313, +786438, +69, +28, +1968070503, +1668238445, +1750297697, +1298493537, +1751348321, +1231515241, +1634887028, +1852795252, +115, +196613, +71, +0, +458757, +103, +1632132967, +1951625833, +1684955506, +1701869908, +0, +524293, +191, +1281322087, +1818321775, +1870032457, +1769234787, +1145663087, +0, +393221, +192, +1465871463, +1198223983, +1886744434, +17481, +458757, +193, +1651469415, +1951624289, +1684955506, +1701080649, +120, +458757, +194, +1633906540, +1920226156, +1231318625, +2019910766, +0, +458757, +195, +1651469415, +1700162657, +2019914866, +1701080649, +120, +458757, +196, +1633906540, +1919243884, +1232627060, +2019910766, +0, +524293, +197, +1450014062, +1769239141, +1232299363, +1701336174, +1634890835, +25710, +458757, +198, +1701080681, +1919895160, +1918986323, +1699570789, +109, +327685, +199, +1634890867, +2035573870, +25968, +262149, +200, +1634886000, +109, +262149, +204, +1634886000, +109, +262149, +207, +1634886000, +109, +262149, +209, +1634886000, +109, +262149, +211, +1634886000, +109, +262149, +213, +1634886000, +109, +262149, +215, +1634886000, +109, +262149, +217, +1634886000, +109, +262149, +219, +1634886000, +109, +327685, +231, +1918986355, +1867539557, +115, +458757, +234, +1953067639, +1818386789, +1936674917, +1869182057, +29550, +589830, +234, +0, +1632132967, +1700164201, +2019914866, +1769172816, +1852795252, +115, +196613, +236, +0, +196613, +245, +105, +524293, +256, +1651469415, +1866886241, +2003790956, +1953654102, +1850308709, +7890276, +524293, +265, +1651469415, +1866886241, +2003790956, +1634890835, +1850303598, +7890276, +262149, +271, +1952670054, +29295, +327685, +286, +1819045734, +1867544431, +115, +524293, +295, +1866882919, +2003790956, +1919508808, +1953460050, +1936090703, +29797, +393221, +313, +1684104520, +1851880020, +1919903347, +109, +589830, +313, +0, +1867341671, +1416389988, +1936613746, +1836216166, +1215459142, +6578533, +589830, +313, +1, +1867341671, +1382835556, +1952543855, +1919895141, +1684104520, +0, +589830, +313, +2, +1852396386, +1214606439, +1415864677, +1936613746, +1836216166, +0, +327686, +313, +3, +1684300144, +6778473, +196613, +315, +0, +327752, +69, +0, +35, +0, +327752, +69, +1, +35, +16, +327752, +69, +2, +35, +32, +327752, +69, +3, +35, +48, +327752, +69, +4, +35, +64, +327752, +69, +5, +35, +68, +327752, +69, +6, +35, +72, +327752, +69, +7, +35, +76, +327752, +69, +8, +35, +80, +327752, +69, +9, +35, +84, +327752, +69, +10, +35, +88, +327752, +69, +11, +35, +92, +327752, +69, +12, +35, +96, +327752, +69, +13, +35, +100, +327752, +69, +14, +35, +104, +327752, +69, +15, +35, +108, +327752, +69, +16, +35, +112, +327752, +69, +17, +35, +116, +327752, +69, +18, +35, +120, +327752, +69, +19, +35, +124, +327752, +69, +20, +35, +128, +327752, +69, +21, +35, +132, +327752, +69, +22, +35, +136, +327752, +69, +23, +35, +140, +327752, +69, +24, +35, +144, +327752, +69, +25, +35, +148, +327752, +69, +26, +35, +152, +327752, +69, +27, +35, +156, +327752, +69, +28, +35, +160, +196679, +69, +3, +262215, +71, +34, +0, +262215, +71, +33, +16, +262215, +103, +34, +1, +262215, +103, +33, +22, +262215, +191, +11, +27, +262215, +192, +11, +26, +262215, +233, +6, +16, +327752, +234, +0, +35, +0, +196679, +234, +3, +262215, +236, +34, +1, +262215, +236, +33, +7, +262215, +295, +34, +1, +262215, +295, +33, +25, +262215, +312, +6, +16, +262216, +313, +0, +5, +327752, +313, +0, +35, +0, +327752, +313, +0, +7, +16, +327752, +313, +1, +35, +64, +327752, +313, +2, +35, +80, +327752, +313, +3, +35, +96, +196679, +313, +3, +262215, +315, +34, +0, +262215, +315, +33, +27, +262215, +316, +11, +25, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +131092, +9, +262177, +10, +9, +8, +262165, +14, +32, +0, +262176, +15, +7, +14, +262165, +16, +32, +1, +262176, +17, +7, +16, +786465, +18, +2, +15, +15, +15, +15, +17, +15, +15, +15, +15, +589857, +41, +2, +15, +15, +15, +15, +15, +15, +589857, +50, +2, +17, +17, +17, +15, +17, +15, +262187, +14, +59, +3, +262176, +60, +7, +6, +262187, +6, +63, +0, +262187, +14, +68, +64, +2031646, +69, +7, +7, +7, +7, +16, +16, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +14, +14, +6, +16, +16, +262176, +70, +2, +69, +262203, +70, +71, +2, +262187, +16, +72, +24, +262176, +73, +2, +14, +262187, +16, +87, +25, +262187, +14, +90, +1, +589849, +100, +14, +5, +0, +0, +0, +1, +0, +196635, +101, +100, +262176, +102, +0, +101, +262203, +102, +103, +0, +262167, +108, +14, +4, +262187, +14, +110, +0, +262187, +16, +166, +64, +262167, +189, +14, +3, +262176, +190, +1, +189, +262203, +190, +191, +1, +262203, +190, +192, +1, +262176, +201, +1, +14, +262172, +229, +7, +68, +262176, +230, +4, +229, +262203, +230, +231, +4, +196637, +233, +7, +196638, +234, +233, +262176, +235, +2, +234, +262203, +235, +236, +2, +262187, +16, +237, +0, +262176, +239, +2, +7, +262176, +242, +4, +7, +262187, +14, +244, +2, +262187, +16, +261, +1, +262187, +16, +272, +26, +262176, +273, +2, +6, +262187, +6, +282, +1065353216, +262167, +284, +6, +3, +262176, +285, +7, +284, +589849, +292, +6, +5, +0, +0, +0, +1, +0, +196635, +293, +292, +262176, +294, +0, +293, +262203, +294, +295, +0, +262168, +311, +7, +4, +262172, +312, +6, +59, +393246, +313, +311, +7, +16, +312, +262176, +314, +2, +313, +262203, +314, +315, +2, +393260, +189, +316, +68, +90, +90, +327734, +2, +4, +0, +3, +131320, +5, +262203, +15, +193, +7, +262203, +15, +194, +7, +262203, +17, +195, +7, +262203, +15, +196, +7, +262203, +15, +197, +7, +262203, +15, +198, +7, +262203, +15, +199, +7, +262203, +15, +200, +7, +262203, +15, +204, +7, +262203, +15, +207, +7, +262203, +15, +209, +7, +262203, +17, +211, +7, +262203, +15, +213, +7, +262203, +15, +215, +7, +262203, +15, +217, +7, +262203, +15, +219, +7, +262203, +17, +245, +7, +262203, +17, +256, +7, +262203, +17, +265, +7, +262203, +60, +271, +7, +262203, +285, +286, +7, +327745, +201, +202, +191, +110, +262205, +14, +203, +202, +196670, +200, +203, +327745, +201, +205, +192, +110, +262205, +14, +206, +205, +196670, +204, +206, +262205, +14, +208, +193, +196670, +207, +208, +262205, +14, +210, +194, +196670, +209, +210, +262205, +16, +212, +195, +196670, +211, +212, +262205, +14, +214, +196, +196670, +213, +214, +262205, +14, +216, +197, +196670, +215, +216, +262205, +14, +218, +198, +196670, +217, +218, +262205, +14, +220, +199, +196670, +219, +220, +852025, +2, +221, +28, +200, +204, +207, +209, +211, +213, +215, +217, +219, +262205, +14, +222, +207, +196670, +193, +222, +262205, +14, +223, +209, +196670, +194, +223, +262205, +16, +224, +211, +196670, +195, +224, +262205, +14, +225, +213, +196670, +196, +225, +262205, +14, +226, +215, +196670, +197, +226, +262205, +14, +227, +217, +196670, +198, +227, +262205, +14, +228, +219, +196670, +199, +228, +262205, +14, +232, +198, +262205, +16, +238, +195, +393281, +239, +240, +236, +237, +238, +262205, +7, +241, +240, +327745, +242, +243, +231, +232, +196670, +243, +241, +262368, +244, +90, +110, +196670, +245, +237, +131321, +246, +131320, +246, +262390, +248, +249, +0, +131321, +250, +131320, +250, +262205, +16, +251, +245, +262268, +14, +252, +251, +327745, +73, +253, +71, +87, +262205, +14, +254, +253, +327856, +9, +255, +252, +254, +262394, +255, +247, +248, +131320, +247, +262205, +16, +257, +195, +262205, +14, +258, +197, +262268, +16, +259, +258, +262205, +16, +260, +245, +327808, +16, +262, +260, +261, +327812, +16, +263, +259, +262, +327808, +16, +264, +257, +263, +196670, +256, +264, +262205, +14, +266, +193, +262268, +16, +267, +266, +262205, +16, +268, +245, +327808, +16, +269, +267, +268, +327808, +16, +270, +269, +261, +196670, +265, +270, +327745, +273, +274, +71, +272, +262205, +6, +275, +274, +262205, +14, +276, +196, +262256, +6, +277, +276, +262205, +14, +278, +197, +262256, +6, +279, +278, +327816, +6, +280, +277, +279, +327813, +6, +281, +275, +280, +327809, +6, +283, +281, +282, +196670, +271, +283, +262205, +14, +287, +198, +327745, +242, +288, +231, +287, +262205, +7, +289, +288, +524367, +284, +290, +289, +289, +0, +1, +2, +262205, +6, +291, +271, +262205, +293, +296, +295, +262205, +16, +297, +265, +262244, +292, +298, +296, +327775, +7, +299, +298, +297, +524367, +284, +300, +299, +299, +0, +1, +2, +327822, +284, +301, +300, +291, +327809, +284, +302, +290, +301, +196670, +286, +302, +262205, +16, +303, +256, +262205, +284, +304, +286, +393281, +239, +305, +236, +237, +303, +262205, +7, +306, +305, +589903, +7, +307, +306, +304, +4, +5, +6, +3, +196670, +305, +307, +131321, +249, +131320, +249, +262205, +16, +308, +245, +327808, +16, +309, +308, +261, +196670, +245, +309, +131321, +246, +131320, +248, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +327745, +60, +61, +11, +59, +262205, +6, +62, +61, +327866, +9, +64, +62, +63, +131326, +64, +65592, +327734, +2, +28, +0, +18, +196663, +15, +19, +196663, +15, +20, +196663, +15, +21, +196663, +15, +22, +196663, +17, +23, +196663, +15, +24, +196663, +15, +25, +196663, +15, +26, +196663, +15, +27, +131320, +29, +262205, +14, +67, +19, +196670, +26, +67, +327745, +73, +74, +71, +72, +262205, +14, +75, +74, +327814, +14, +76, +68, +75, +196670, +25, +76, +262205, +14, +77, +19, +327745, +73, +78, +71, +72, +262205, +14, +79, +78, +327817, +14, +80, +77, +79, +196670, +22, +80, +262205, +14, +81, +20, +327745, +73, +82, +71, +72, +262205, +14, +83, +82, +327812, +14, +84, +81, +83, +262205, +14, +85, +22, +327808, +14, +86, +84, +85, +196670, +21, +86, +327745, +73, +88, +71, +87, +262205, +14, +89, +88, +327808, +14, +91, +89, +90, +262205, +14, +92, +21, +327812, +14, +93, +92, +91, +196670, +21, +93, +262205, +14, +94, +19, +262205, +14, +95, +22, +327810, +14, +96, +94, +95, +327745, +73, +97, +71, +72, +262205, +14, +98, +97, +327814, +14, +99, +96, +98, +196670, +24, +99, +262205, +101, +104, +103, +262205, +14, +105, +21, +262268, +16, +106, +105, +262244, +100, +107, +104, +327775, +108, +109, +107, +106, +327761, +14, +111, +109, +0, +196670, +27, +111, +262205, +14, +112, +21, +262205, +14, +113, +25, +327812, +14, +114, +112, +113, +262205, +14, +115, +24, +327808, +14, +116, +114, +115, +262268, +16, +117, +116, +196670, +23, +117, +65789, +65592, +327734, +2, +39, +0, +18, +196663, +15, +30, +196663, +15, +31, +196663, +15, +32, +196663, +15, +33, +196663, +17, +34, +196663, +15, +35, +196663, +15, +36, +196663, +15, +37, +196663, +15, +38, +131320, +40, +262205, +14, +118, +30, +196670, +37, +118, +327745, +73, +119, +71, +72, +262205, +14, +120, +119, +327814, +14, +121, +68, +120, +196670, +36, +121, +262205, +14, +122, +30, +327745, +73, +123, +71, +72, +262205, +14, +124, +123, +327817, +14, +125, +122, +124, +196670, +33, +125, +262205, +14, +126, +31, +327745, +73, +127, +71, +72, +262205, +14, +128, +127, +327812, +14, +129, +126, +128, +262205, +14, +130, +33, +327808, +14, +131, +129, +130, +196670, +32, +131, +262205, +14, +132, +30, +262205, +14, +133, +33, +327810, +14, +134, +132, +133, +327745, +73, +135, +71, +72, +262205, +14, +136, +135, +327814, +14, +137, +134, +136, +196670, +35, +137, +262205, +101, +138, +103, +262205, +14, +139, +32, +262268, +16, +140, +139, +262244, +100, +141, +138, +327775, +108, +142, +141, +140, +327761, +14, +143, +142, +0, +196670, +38, +143, +262205, +14, +144, +32, +262205, +14, +145, +36, +327812, +14, +146, +144, +145, +262205, +14, +147, +35, +327808, +14, +148, +146, +147, +262268, +16, +149, +148, +196670, +34, +149, +65789, +65592, +327734, +2, +48, +0, +41, +196663, +15, +42, +196663, +15, +43, +196663, +15, +44, +196663, +15, +45, +196663, +15, +46, +196663, +15, +47, +131320, +49, +262205, +14, +150, +43, +327812, +14, +151, +68, +150, +262205, +14, +152, +42, +327808, +14, +153, +151, +152, +196670, +44, +153, +327745, +73, +154, +71, +72, +262205, +14, +155, +154, +327814, +14, +156, +68, +155, +196670, +45, +156, +262205, +101, +157, +103, +262205, +14, +158, +44, +262268, +16, +159, +158, +262244, +100, +160, +157, +327775, +108, +161, +160, +159, +327761, +14, +162, +161, +0, +196670, +47, +162, +262205, +14, +163, +44, +262205, +14, +164, +45, +327812, +14, +165, +163, +164, +196670, +46, +165, +65789, +65592, +327734, +2, +57, +0, +50, +196663, +17, +51, +196663, +17, +52, +196663, +17, +53, +196663, +15, +54, +196663, +17, +55, +196663, +15, +56, +131320, +58, +262205, +16, +167, +52, +327812, +16, +168, +166, +167, +262205, +16, +169, +51, +327808, +16, +170, +168, +169, +196670, +53, +170, +327745, +73, +171, +71, +87, +262205, +14, +172, +171, +327808, +14, +173, +172, +90, +262268, +16, +174, +173, +262205, +16, +175, +53, +327812, +16, +176, +175, +174, +196670, +53, +176, +327745, +73, +177, +71, +72, +262205, +14, +178, +177, +327814, +14, +179, +68, +178, +196670, +54, +179, +262205, +101, +180, +103, +262205, +16, +181, +53, +262244, +100, +182, +180, +327775, +108, +183, +182, +181, +327761, +14, +184, +183, +0, +196670, +56, +184, +262205, +16, +185, +53, +262205, +14, +186, +54, +262268, +16, +187, +186, +327812, +16, +188, +185, +187, +196670, +55, +188, +65789, +65592, +}; +const std::vector depth_hair_data = {119734787, +65536, +524289, +364, +0, +131089, +1, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +655375, +4, +4, +1852399981, +0, +222, +249, +267, +291, +363, +196624, +4, +7, +196624, +4, +9, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +655364, +1197427783, +1279741775, +1885560645, +1953718128, +1600482425, +1701734764, +1919509599, +1769235301, +25974, +524292, +1197427783, +1279741775, +1852399429, +1685417059, +1768185701, +1952671090, +6649449, +262149, +4, +1852399981, +0, +524293, +12, +1801675088, +1634692166, +1850291316, +1767206772, +1982362734, +3880038, +262149, +11, +1818318454, +25973, +589829, +17, +1634758229, +1767205731, +1850307694, +1816555380, +880042351, +993097000, +0, +262149, +16, +1818318453, +25973, +655365, +25, +1801675088, +1735287124, +1098149477, +1866687598, +1634887030, +1982358887, +1715155814, +15153, +262149, +23, +1735287156, +7630437, +327685, +24, +1702260579, +1701273970, +0, +393221, +29, +1416914247, +1701277281, +1965585518, +15153, +393221, +28, +1801675120, +1632920677, +1852139374, +116, +393221, +33, +1131701575, +1919252079, +677734241, +3879285, +393221, +32, +1801675120, +1866687589, +1634887030, +25959, +655365, +41, +1886220099, +1130722421, +1919252079, +677734241, +993158774, +993158774, +993158774, +0, +196613, +38, +12400, +196613, +39, +12656, +327685, +40, +1702390128, +1668238444, +0, +262149, +43, +1702132066, +51, +262149, +52, +1702132066, +50, +262149, +59, +1702132066, +49, +262149, +66, +1702132066, +48, +262149, +124, +1634886000, +109, +262149, +129, +1634886000, +109, +262149, +139, +1634886000, +109, +327685, +146, +1936617283, +1953390964, +115, +393222, +146, +0, +1466785639, +1684828783, +0, +393222, +146, +1, +1450008423, +1350002025, +6975346, +458758, +146, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +146, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +146, +4, +1165385575, +25977, +327686, +146, +5, +1986420583, +7761734, +524294, +146, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +146, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +146, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +146, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +146, +10, +1632460647, +1633045364, +6649196, +458758, +146, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +146, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +146, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +146, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +146, +15, +1767333735, +2053722990, +101, +458758, +146, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +146, +17, +1415733095, +1416522088, +28777, +458758, +146, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +146, +19, +1181114215, +1766617697, +7628903, +393222, +146, +20, +1416191847, +1399350117, +77, +458758, +146, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +146, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +146, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +146, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +146, +25, +1214668647, +1265789281, +12915, +393222, +146, +26, +1214668647, +1165125985, +12920, +589830, +146, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +148, +0, +262149, +171, +1768173680, +29811, +262149, +176, +1768173936, +29811, +327685, +181, +1919508840, +1952737623, +104, +262149, +188, +1937012079, +6644841, +262149, +201, +1852270963, +0, +262149, +208, +1147954546, +7631721, +327685, +220, +1785688688, +1936683103, +0, +393221, +222, +1180658791, +1130848626, +1685221231, +0, +327685, +242, +1987212643, +1668505445, +6646881, +262149, +249, +1735287156, +7630437, +393221, +252, +1700948326, +1634885490, +1937074532, +0, +327685, +258, +1702260579, +1701273970, +0, +262149, +267, +829436016, +0, +262149, +268, +1634886000, +109, +262149, +271, +1634886000, +109, +262149, +274, +1634886000, +109, +262149, +278, +1752198241, +97, +327685, +291, +1734439494, +1869377347, +114, +393221, +295, +1919112054, +1097753957, +1701995620, +29555, +262149, +299, +1885684853, +26740, +327685, +303, +1885684853, +1345349748, +7759218, +524293, +306, +1917212498, +1701668705, +1698985070, +1936225392, +1954047316, +6648437, +327685, +330, +1885684853, +1345415284, +7759218, +327685, +351, +1885684853, +1345480820, +7759218, +262149, +363, +1953523044, +104, +262216, +146, +0, +5, +327752, +146, +0, +35, +0, +327752, +146, +0, +7, +16, +262216, +146, +1, +5, +327752, +146, +1, +35, +64, +327752, +146, +1, +7, +16, +262216, +146, +2, +5, +327752, +146, +2, +35, +128, +327752, +146, +2, +7, +16, +262216, +146, +3, +5, +327752, +146, +3, +35, +192, +327752, +146, +3, +7, +16, +327752, +146, +4, +35, +256, +327752, +146, +5, +35, +268, +327752, +146, +6, +35, +272, +327752, +146, +7, +35, +288, +327752, +146, +8, +35, +304, +327752, +146, +9, +35, +320, +327752, +146, +10, +35, +336, +327752, +146, +11, +35, +352, +327752, +146, +12, +35, +356, +327752, +146, +13, +35, +360, +327752, +146, +14, +35, +364, +327752, +146, +15, +35, +368, +327752, +146, +16, +35, +384, +327752, +146, +17, +35, +388, +327752, +146, +18, +35, +392, +327752, +146, +19, +35, +396, +327752, +146, +20, +35, +400, +327752, +146, +21, +35, +404, +327752, +146, +22, +35, +408, +327752, +146, +23, +35, +412, +327752, +146, +24, +35, +416, +327752, +146, +25, +35, +420, +327752, +146, +26, +35, +424, +262216, +146, +27, +5, +327752, +146, +27, +35, +432, +327752, +146, +27, +7, +16, +196679, +146, +2, +262215, +148, +34, +0, +262215, +148, +33, +16, +262215, +222, +11, +15, +262215, +249, +30, +2, +262215, +267, +30, +1, +262215, +291, +30, +0, +262215, +306, +34, +0, +262215, +306, +33, +13, +262215, +363, +30, +0, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +262165, +9, +32, +0, +262177, +10, +9, +8, +262176, +14, +7, +9, +262177, +15, +7, +14, +262167, +19, +6, +3, +262176, +20, +7, +19, +262176, +21, +7, +6, +327713, +22, +9, +20, +21, +262177, +27, +19, +14, +262177, +31, +6, +14, +262167, +35, +6, +2, +262176, +36, +7, +35, +393249, +37, +6, +36, +36, +36, +262187, +9, +44, +0, +262187, +6, +47, +1132396544, +262187, +9, +50, +255, +262187, +9, +53, +1, +262187, +9, +60, +2, +262187, +9, +67, +3, +262165, +74, +32, +1, +262187, +74, +75, +24, +262187, +74, +78, +16, +262187, +74, +82, +8, +262187, +9, +90, +4278190080, +262187, +9, +96, +16711680, +262187, +9, +102, +65280, +262187, +6, +115, +1056964608, +262187, +6, +128, +1073741824, +262187, +6, +134, +1065353216, +262168, +145, +7, +4, +1966110, +146, +145, +145, +145, +145, +19, +6, +7, +7, +7, +7, +7, +6, +6, +6, +6, +7, +6, +6, +6, +6, +74, +74, +74, +74, +6, +6, +6, +145, +262176, +147, +2, +146, +262203, +147, +148, +2, +262187, +74, +149, +15, +262176, +150, +2, +7, +262187, +6, +161, +3212836864, +131092, +186, +262176, +187, +7, +186, +262187, +6, +192, +0, +262167, +198, +186, +2, +262176, +221, +1, +7, +262203, +221, +222, +1, +262176, +223, +1, +6, +262176, +227, +2, +6, +262187, +74, +243, +17, +262203, +221, +249, +1, +262187, +74, +254, +14, +262187, +74, +259, +21, +262176, +260, +2, +74, +262187, +74, +263, +0, +262203, +221, +267, +1, +262187, +74, +280, +11, +262176, +290, +3, +6, +262203, +290, +291, +3, +262167, +293, +9, +2, +262176, +294, +7, +293, +589849, +304, +9, +1, +0, +1, +0, +2, +33, +262176, +305, +0, +304, +262203, +305, +306, +0, +262167, +308, +74, +2, +262167, +310, +74, +3, +262176, +315, +11, +9, +262187, +6, +320, +1065017672, +262187, +74, +333, +1, +262187, +74, +354, +2, +262203, +223, +363, +1, +327734, +2, +4, +0, +3, +131320, +5, +262203, +8, +220, +7, +262203, +21, +242, +7, +262203, +21, +252, +7, +262203, +21, +258, +7, +262203, +36, +268, +7, +262203, +36, +271, +7, +262203, +36, +274, +7, +262203, +21, +278, +7, +262203, +294, +295, +7, +262203, +14, +299, +7, +262203, +14, +303, +7, +262203, +14, +318, +7, +262203, +14, +330, +7, +262203, +14, +340, +7, +262203, +14, +351, +7, +327745, +223, +224, +222, +44, +262205, +6, +225, +224, +327813, +6, +226, +128, +225, +393281, +227, +228, +148, +149, +60, +262205, +6, +229, +228, +327813, +6, +230, +226, +229, +327811, +6, +231, +230, +134, +327745, +223, +232, +222, +53, +262205, +6, +233, +232, +327813, +6, +234, +128, +233, +393281, +227, +235, +148, +149, +67, +262205, +6, +236, +235, +327813, +6, +237, +234, +236, +327811, +6, +238, +134, +237, +327745, +223, +239, +222, +60, +262205, +6, +240, +239, +458832, +7, +241, +231, +238, +240, +134, +196670, +220, +241, +196670, +242, +134, +327745, +227, +244, +148, +243, +262205, +6, +245, +244, +327866, +186, +246, +245, +192, +196855, +248, +0, +262394, +246, +247, +248, +131320, +247, +327745, +223, +250, +249, +67, +262205, +6, +251, +250, +196670, +242, +251, +131321, +248, +131320, +248, +262205, +6, +253, +242, +327745, +227, +255, +148, +254, +262205, +6, +256, +255, +327813, +6, +257, +253, +256, +196670, +252, +257, +196670, +258, +134, +327745, +260, +261, +148, +259, +262205, +74, +262, +261, +327851, +186, +264, +262, +263, +196855, +266, +0, +262394, +264, +265, +266, +131320, +265, +262205, +7, +269, +267, +458831, +35, +270, +269, +269, +0, +1, +196670, +268, +270, +262205, +7, +272, +267, +458831, +35, +273, +272, +272, +2, +3, +196670, +271, +273, +262205, +7, +275, +220, +458831, +35, +276, +275, +275, +0, +1, +196670, +274, +276, +458809, +6, +277, +41, +268, +271, +274, +196670, +258, +277, +131321, +266, +131320, +266, +262205, +6, +279, +258, +327745, +227, +281, +148, +280, +262205, +6, +282, +281, +327813, +6, +283, +279, +282, +196670, +278, +283, +262205, +6, +284, +278, +327745, +227, +285, +148, +75, +262205, +6, +286, +285, +327864, +186, +287, +284, +286, +196855, +289, +0, +262394, +287, +288, +289, +131320, +288, +196670, +291, +134, +65789, +131320, +289, +262205, +7, +296, +222, +458831, +35, +297, +296, +296, +0, +1, +262253, +293, +298, +297, +196670, +295, +298, +327745, +223, +300, +222, +60, +262205, +6, +301, +300, +262268, +9, +302, +301, +196670, +299, +302, +262205, +293, +307, +295, +262268, +308, +309, +307, +327761, +74, +311, +309, +0, +327761, +74, +312, +309, +1, +393296, +310, +313, +311, +312, +263, +262205, +9, +314, +299, +393276, +315, +316, +306, +313, +44, +458989, +9, +317, +316, +53, +44, +314, +196670, +303, +317, +262205, +6, +319, +278, +327866, +186, +321, +319, +320, +196855, +323, +0, +262394, +321, +322, +325, +131320, +322, +262205, +9, +324, +299, +196670, +318, +324, +131321, +323, +131320, +325, +262205, +9, +326, +299, +262205, +9, +327, +303, +458764, +9, +328, +1, +41, +326, +327, +196670, +318, +328, +131321, +323, +131320, +323, +262205, +9, +329, +318, +196670, +299, +329, +262205, +293, +331, +295, +262268, +308, +332, +331, +327761, +74, +334, +332, +0, +327761, +74, +335, +332, +1, +393296, +310, +336, +334, +335, +333, +262205, +9, +337, +299, +393276, +315, +338, +306, +336, +44, +458989, +9, +339, +338, +53, +44, +337, +196670, +330, +339, +262205, +6, +341, +278, +327866, +186, +342, +341, +320, +196855, +344, +0, +262394, +342, +343, +346, +131320, +343, +262205, +9, +345, +299, +196670, +340, +345, +131321, +344, +131320, +346, +262205, +9, +347, +299, +262205, +9, +348, +330, +458764, +9, +349, +1, +41, +347, +348, +196670, +340, +349, +131321, +344, +131320, +344, +262205, +9, +350, +340, +196670, +299, +350, +262205, +293, +352, +295, +262268, +308, +353, +352, +327761, +74, +355, +353, +0, +327761, +74, +356, +353, +1, +393296, +310, +357, +355, +356, +354, +262205, +9, +358, +299, +393276, +315, +359, +306, +357, +44, +458989, +9, +360, +359, +53, +44, +358, +196670, +351, +360, +262205, +6, +361, +278, +327811, +6, +362, +134, +361, +196670, +291, +362, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +262203, +14, +43, +7, +262203, +14, +52, +7, +262203, +14, +59, +7, +262203, +14, +66, +7, +327745, +21, +45, +11, +44, +262205, +6, +46, +45, +327813, +6, +48, +46, +47, +262253, +9, +49, +48, +327879, +9, +51, +49, +50, +196670, +43, +51, +327745, +21, +54, +11, +53, +262205, +6, +55, +54, +327813, +6, +56, +55, +47, +262253, +9, +57, +56, +327879, +9, +58, +57, +50, +196670, +52, +58, +327745, +21, +61, +11, +60, +262205, +6, +62, +61, +327813, +6, +63, +62, +47, +262253, +9, +64, +63, +327879, +9, +65, +64, +50, +196670, +59, +65, +327745, +21, +68, +11, +67, +262205, +6, +69, +68, +327813, +6, +70, +69, +47, +262253, +9, +71, +70, +327879, +9, +72, +71, +50, +196670, +66, +72, +262205, +9, +73, +43, +327876, +9, +76, +73, +75, +262205, +9, +77, +52, +327876, +9, +79, +77, +78, +327877, +9, +80, +76, +79, +262205, +9, +81, +59, +327876, +9, +83, +81, +82, +327877, +9, +84, +80, +83, +262205, +9, +85, +66, +327877, +9, +86, +84, +85, +131326, +86, +65592, +327734, +7, +17, +0, +15, +196663, +14, +16, +131320, +18, +262205, +9, +89, +16, +327879, +9, +91, +89, +90, +327874, +9, +92, +91, +75, +262256, +6, +93, +92, +327816, +6, +94, +93, +47, +262205, +9, +95, +16, +327879, +9, +97, +95, +96, +327874, +9, +98, +97, +78, +262256, +6, +99, +98, +327816, +6, +100, +99, +47, +262205, +9, +101, +16, +327879, +9, +103, +101, +102, +327874, +9, +104, +103, +82, +262256, +6, +105, +104, +327816, +6, +106, +105, +47, +262205, +9, +107, +16, +327879, +9, +108, +107, +50, +262256, +6, +109, +108, +327816, +6, +110, +109, +47, +458832, +7, +111, +94, +100, +106, +110, +131326, +111, +65592, +327734, +9, +25, +0, +22, +196663, +20, +23, +196663, +21, +24, +131320, +26, +262203, +8, +124, +7, +262205, +19, +114, +23, +327822, +19, +116, +114, +115, +393296, +19, +117, +115, +115, +115, +327809, +19, +118, +116, +117, +262205, +6, +119, +24, +327761, +6, +120, +118, +0, +327761, +6, +121, +118, +1, +327761, +6, +122, +118, +2, +458832, +7, +123, +120, +121, +122, +119, +196670, +124, +123, +327737, +9, +125, +12, +124, +131326, +125, +65592, +327734, +19, +29, +0, +27, +196663, +14, +28, +131320, +30, +262203, +14, +129, +7, +262205, +9, +130, +28, +196670, +129, +130, +327737, +7, +131, +17, +129, +524367, +19, +132, +131, +131, +0, +1, +2, +327822, +19, +133, +132, +128, +393296, +19, +135, +134, +134, +134, +327811, +19, +136, +133, +135, +131326, +136, +65592, +327734, +6, +33, +0, +31, +196663, +14, +32, +131320, +34, +262203, +14, +139, +7, +262205, +9, +140, +32, +196670, +139, +140, +327737, +7, +141, +17, +139, +327761, +6, +142, +141, +3, +131326, +142, +65592, +327734, +6, +41, +0, +37, +196663, +36, +38, +196663, +36, +39, +196663, +36, +40, +131320, +42, +262203, +21, +171, +7, +262203, +21, +176, +7, +262203, +21, +181, +7, +262203, +187, +188, +7, +262203, +21, +201, +7, +262203, +21, +202, +7, +262203, +21, +208, +7, +327745, +150, +151, +148, +149, +262205, +7, +152, +151, +458831, +35, +153, +152, +152, +0, +1, +262205, +35, +154, +38, +327813, +35, +155, +154, +153, +196670, +38, +155, +327745, +150, +156, +148, +149, +262205, +7, +157, +156, +458831, +35, +158, +157, +157, +0, +1, +262205, +35, +159, +39, +327813, +35, +160, +159, +158, +196670, +39, +160, +327745, +21, +162, +40, +53, +262205, +6, +163, +162, +327813, +6, +164, +163, +161, +327745, +21, +165, +40, +53, +196670, +165, +164, +327745, +150, +166, +148, +149, +262205, +7, +167, +166, +458831, +35, +168, +167, +167, +0, +1, +262205, +35, +169, +40, +327813, +35, +170, +169, +168, +196670, +40, +170, +262205, +35, +172, +38, +262205, +35, +173, +40, +327811, +35, +174, +172, +173, +393228, +6, +175, +1, +66, +174, +196670, +171, +175, +262205, +35, +177, +39, +262205, +35, +178, +40, +327811, +35, +179, +177, +178, +393228, +6, +180, +1, +66, +179, +196670, +176, +180, +262205, +35, +182, +38, +262205, +35, +183, +39, +327811, +35, +184, +182, +183, +393228, +6, +185, +1, +66, +184, +196670, +181, +185, +262205, +6, +189, +181, +262205, +6, +190, +171, +458764, +6, +191, +1, +48, +189, +190, +327866, +186, +193, +191, +192, +262205, +6, +194, +181, +262205, +6, +195, +176, +458764, +6, +196, +1, +48, +194, +195, +327866, +186, +197, +196, +192, +327760, +198, +199, +193, +197, +262298, +186, +200, +199, +196670, +188, +200, +262205, +186, +203, +188, +196855, +205, +0, +262394, +203, +204, +206, +131320, +204, +196670, +202, +161, +131321, +205, +131320, +206, +196670, +202, +134, +131321, +205, +131320, +205, +262205, +6, +207, +202, +196670, +201, +207, +262205, +6, +209, +201, +262205, +6, +210, +171, +262205, +6, +211, +176, +458764, +6, +212, +1, +37, +210, +211, +524300, +6, +213, +1, +43, +212, +192, +134, +327813, +6, +214, +209, +213, +196670, +208, +214, +262205, +6, +215, +208, +327809, +6, +216, +215, +134, +327813, +6, +217, +216, +115, +131326, +217, +65592, +}; +const std::vector resolve_depth = {119734787, +65536, +524289, +44, +0, +131089, +1, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +458767, +4, +4, +1852399981, +0, +13, +36, +196624, +4, +7, +196624, +4, +12, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +655364, +1197427783, +1279741775, +1885560645, +1953718128, +1600482425, +1701734764, +1919509599, +1769235301, +25974, +524292, +1197427783, +1279741775, +1852399429, +1685417059, +1768185701, +1952671090, +6649449, +262149, +4, +1852399981, +0, +393221, +9, +1919112054, +1097753957, +1701995620, +29555, +393221, +13, +1180658791, +1130848626, +1685221231, +0, +262149, +20, +1885684853, +26740, +524293, +24, +1734439494, +1953391981, +1953523012, +1700033384, +1920300152, +101, +393221, +36, +1180658791, +1147625842, +1752461413, +0, +327685, +41, +1936617283, +1953390964, +115, +393222, +41, +0, +1466785639, +1684828783, +0, +393222, +41, +1, +1450008423, +1350002025, +6975346, +458758, +41, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +41, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +41, +4, +1165385575, +25977, +327686, +41, +5, +1986420583, +7761734, +524294, +41, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +41, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +41, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +41, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +41, +10, +1632460647, +1633045364, +6649196, +458758, +41, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +41, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +41, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +41, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +41, +15, +1767333735, +2053722990, +101, +458758, +41, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +41, +17, +1415733095, +1416522088, +28777, +458758, +41, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +41, +19, +1181114215, +1766617697, +7628903, +393222, +41, +20, +1416191847, +1399350117, +77, +458758, +41, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +41, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +41, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +41, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +41, +25, +1214668647, +1265789281, +12915, +393222, +41, +26, +1214668647, +1165125985, +12920, +589830, +41, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +43, +0, +262215, +13, +11, +15, +262215, +24, +34, +0, +262215, +24, +33, +13, +262215, +36, +11, +22, +262216, +41, +0, +5, +327752, +41, +0, +35, +0, +327752, +41, +0, +7, +16, +262216, +41, +1, +5, +327752, +41, +1, +35, +64, +327752, +41, +1, +7, +16, +262216, +41, +2, +5, +327752, +41, +2, +35, +128, +327752, +41, +2, +7, +16, +262216, +41, +3, +5, +327752, +41, +3, +35, +192, +327752, +41, +3, +7, +16, +327752, +41, +4, +35, +256, +327752, +41, +5, +35, +268, +327752, +41, +6, +35, +272, +327752, +41, +7, +35, +288, +327752, +41, +8, +35, +304, +327752, +41, +9, +35, +320, +327752, +41, +10, +35, +336, +327752, +41, +11, +35, +352, +327752, +41, +12, +35, +356, +327752, +41, +13, +35, +360, +327752, +41, +14, +35, +364, +327752, +41, +15, +35, +368, +327752, +41, +16, +35, +384, +327752, +41, +17, +35, +388, +327752, +41, +18, +35, +392, +327752, +41, +19, +35, +396, +327752, +41, +20, +35, +400, +327752, +41, +21, +35, +404, +327752, +41, +22, +35, +408, +327752, +41, +23, +35, +412, +327752, +41, +24, +35, +416, +327752, +41, +25, +35, +420, +327752, +41, +26, +35, +424, +262216, +41, +27, +5, +327752, +41, +27, +35, +432, +327752, +41, +27, +7, +16, +196679, +41, +2, +262215, +43, +34, +0, +262215, +43, +33, +16, +131091, +2, +196641, +3, +2, +262165, +6, +32, +1, +262167, +7, +6, +2, +262176, +8, +7, +7, +196630, +10, +32, +262167, +11, +10, +4, +262176, +12, +1, +11, +262203, +12, +13, +1, +262167, +14, +10, +2, +262165, +18, +32, +0, +262176, +19, +7, +18, +262187, +18, +21, +0, +589849, +22, +18, +1, +0, +1, +0, +2, +33, +262176, +23, +0, +22, +262203, +23, +24, +0, +262187, +6, +27, +2, +262167, +28, +6, +3, +262167, +32, +18, +4, +262176, +35, +3, +10, +262203, +35, +36, +3, +262168, +39, +11, +4, +262167, +40, +10, +3, +1966110, +41, +39, +39, +39, +39, +40, +10, +11, +11, +11, +11, +11, +10, +10, +10, +10, +11, +10, +10, +10, +10, +6, +6, +6, +6, +10, +10, +10, +39, +262176, +42, +2, +41, +262203, +42, +43, +2, +327734, +2, +4, +0, +3, +131320, +5, +262203, +8, +9, +7, +262203, +19, +20, +7, +262205, +11, +15, +13, +458831, +14, +16, +15, +15, +0, +1, +262254, +7, +17, +16, +196670, +9, +17, +196670, +20, +21, +262205, +22, +25, +24, +262205, +7, +26, +9, +327761, +6, +29, +26, +0, +327761, +6, +30, +26, +1, +393296, +28, +31, +29, +30, +27, +327778, +32, +33, +25, +31, +327761, +18, +34, +33, +0, +196670, +20, +34, +262205, +18, +37, +20, +262268, +10, +38, +37, +196670, +36, +38, +65789, +65592, +}; +const std::vector fillcolors_hair_data = {119734787, +65536, +524289, +914, +0, +131089, +1, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +720911, +4, +4, +1852399981, +0, +746, +786, +803, +827, +881, +913, +196624, +4, +7, +196624, +4, +9, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +655364, +1197427783, +1279741775, +1885560645, +1953718128, +1600482425, +1701734764, +1919509599, +1769235301, +25974, +524292, +1197427783, +1279741775, +1852399429, +1685417059, +1768185701, +1952671090, +6649449, +262149, +4, +1852399981, +0, +524293, +12, +1801675088, +1634692166, +1850291316, +1767206772, +1982362734, +3880038, +262149, +11, +1818318454, +25973, +589829, +17, +1634758229, +1767205731, +1850307694, +1816555380, +880042351, +993097000, +0, +262149, +16, +1818318453, +25973, +655365, +25, +1801675088, +1735287124, +1098149477, +1866687598, +1634887030, +1982358887, +1715155814, +15153, +262149, +23, +1735287156, +7630437, +327685, +24, +1702260579, +1701273970, +0, +393221, +29, +1416914247, +1701277281, +1965585518, +15153, +393221, +28, +1801675120, +1632920677, +1852139374, +116, +393221, +33, +1131701575, +1919252079, +677734241, +3879285, +393221, +32, +1801675120, +1866687589, +1634887030, +25959, +655365, +41, +1886220099, +1130722421, +1919252079, +677734241, +993158774, +993158774, +993158774, +0, +196613, +38, +12400, +196613, +39, +12656, +327685, +40, +1702390128, +1668238444, +0, +524293, +46, +1886220099, +1399157877, +1868849512, +1719019639, +828783411, +59, +327685, +44, +1819438967, +1936674916, +0, +262149, +45, +1752198241, +97, +589829, +50, +1886220099, +1399157877, +1819307369, +1634227045, +678915940, +993224310, +3879270, +327685, +48, +1819438967, +1936674916, +0, +262149, +49, +1752198241, +97, +786437, +58, +1886220099, +1214608501, +1400007009, +1768186216, +1982359406, +1983591270, +1983591270, +1715156070, +1719024433, +15155, +262149, +53, +1936674921, +0, +327685, +54, +1851872361, +1953391975, +0, +262149, +55, +2019906665, +0, +327685, +56, +1970236769, +1766618222, +7628903, +262149, +57, +1869377379, +114, +720901, +65, +1886218579, +1632134508, +1750299241, +1852400737, +1719019623, +1719024435, +1719024435, +828783412, +59, +262149, +61, +1936674921, +0, +327685, +62, +1851872361, +1953391975, +0, +262149, +63, +2019906665, +0, +327685, +64, +1970236769, +1766618222, +7628903, +393221, +72, +1098147143, +1701995620, +1982362483, +3879529, +327685, +71, +1684291958, +1936942450, +0, +262149, +74, +1702132066, +51, +262149, +83, +1702132066, +50, +262149, +90, +1702132066, +49, +262149, +97, +1702132066, +48, +262149, +154, +1634886000, +109, +262149, +159, +1634886000, +109, +262149, +169, +1634886000, +109, +327685, +176, +1936617283, +1953390964, +115, +393222, +176, +0, +1466785639, +1684828783, +0, +393222, +176, +1, +1450008423, +1350002025, +6975346, +458758, +176, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +176, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +176, +4, +1165385575, +25977, +327686, +176, +5, +1986420583, +7761734, +524294, +176, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +176, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +176, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +176, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +176, +10, +1632460647, +1633045364, +6649196, +458758, +176, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +176, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +176, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +176, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +176, +15, +1767333735, +2053722990, +101, +458758, +176, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +176, +17, +1415733095, +1416522088, +28777, +458758, +176, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +176, +19, +1181114215, +1766617697, +7628903, +393222, +176, +20, +1416191847, +1399350117, +77, +458758, +176, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +176, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +176, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +176, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +176, +25, +1214668647, +1265789281, +12915, +393222, +176, +26, +1214668647, +1165125985, +12920, +589830, +176, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +178, +0, +262149, +201, +1768173680, +29811, +262149, +206, +1768173936, +29811, +327685, +211, +1919508840, +1952737623, +104, +262149, +218, +1937012079, +6644841, +262149, +231, +1852270963, +0, +262149, +238, +1147954546, +7631721, +393221, +250, +1785688688, +1282633552, +1952999273, +0, +262149, +269, +1400399220, +77, +262149, +279, +1953523044, +104, +262149, +285, +1769173093, +7237484, +393221, +289, +1953523044, +1919311720, +1701668705, +29806, +393221, +292, +1635020660, +1702322028, +1952999273, +0, +458757, +293, +1970236769, +1766618222, +1601464423, +1919508840, +0, +196613, +295, +30820, +196613, +305, +31076, +262149, +313, +1702521203, +0, +262149, +315, +1835493747, +97, +196613, +319, +7370853, +262149, +335, +1734960503, +29800, +327685, +346, +1953523044, +1213027176, +7498081, +393221, +349, +1919508808, +1684105299, +1632466799, +112, +393221, +353, +1634951015, +1768902765, +1816360046, +7368033, +393221, +371, +1953523044, +1836277608, +1852403536, +116, +327685, +389, +1953523044, +1634885480, +6645614, +327685, +394, +1181578606, +1919246953, +115, +458757, +433, +1970236769, +1766618222, +1601464423, +1852138355, +101, +393221, +439, +1785688688, +1282633552, +1952999273, +0, +262149, +456, +1400399220, +77, +262149, +466, +1953523044, +104, +262149, +472, +1769173093, +7237484, +393221, +475, +1953523044, +1919311720, +1701668705, +29806, +458757, +478, +1970236769, +1766618222, +1601464423, +1852138355, +101, +327685, +479, +1953523044, +1213027176, +7498081, +393221, +488, +1953523044, +1836277608, +1852403536, +116, +327685, +503, +1953523044, +1634885480, +6645614, +327685, +508, +1181578606, +1919246953, +115, +458757, +525, +1970236769, +1766618222, +1601464423, +1919508840, +0, +327685, +534, +1702060386, +1869377347, +114, +327685, +539, +1684955506, +1818326623, +25973, +196613, +540, +24907, +196613, +544, +25675, +196613, +547, +3240779, +196613, +550, +3242053, +196613, +553, +3306315, +196613, +557, +3307589, +327685, +561, +1751607660, +1936674932, +0, +327685, +565, +1734954102, +1766093928, +114, +262149, +570, +1702446454, +7498052, +262149, +578, +1735287156, +7630437, +262149, +581, +1416851299, +76, +262149, +585, +1416522099, +76, +262149, +591, +1717987684, +6648693, +262149, +593, +1752198241, +97, +262149, +601, +1416851299, +19538, +262149, +604, +1416522099, +19538, +262149, +606, +1416851299, +69, +262149, +610, +1416522099, +69, +327685, +616, +1416851299, +1918848082, +7630703, +327685, +628, +1416522099, +1918848082, +7630703, +393221, +634, +1667592307, +1918987381, +1869574751, +116, +327685, +643, +1416851299, +1952402514, +28777, +327685, +656, +1416522099, +1952402514, +28777, +393221, +662, +1667592307, +1918987381, +1885959263, +0, +262149, +671, +1819231094, +29295, +327685, +713, +1702060386, +1869377347, +114, +196613, +717, +25675, +262149, +720, +1819231094, +29295, +327685, +731, +1684291950, +1936942450, +0, +327685, +744, +1785688688, +1936683103, +0, +393221, +746, +1180658791, +1130848626, +1685221231, +0, +327685, +765, +1819438967, +1869635428, +115, +327685, +779, +1987212643, +1668505445, +6646881, +262149, +786, +1735287156, +7630437, +393221, +789, +1700948326, +1634885490, +1937074532, +0, +327685, +794, +1702260579, +1701273970, +0, +262149, +803, +829436016, +0, +262149, +804, +1634886000, +109, +262149, +807, +1634886000, +109, +262149, +810, +1634886000, +109, +262149, +814, +1752198241, +97, +327685, +827, +1734439494, +1869377347, +114, +393221, +830, +1919112054, +1097753957, +1701995620, +29555, +393221, +834, +1734439526, +1953391981, +1701080649, +120, +262149, +835, +1634886000, +109, +262149, +838, +1885684853, +26740, +262149, +842, +1885684853, +3172468, +524293, +845, +1734439494, +1953391981, +1953523012, +1700033384, +1920300152, +101, +262149, +855, +1885684853, +3238004, +262149, +863, +1885684853, +3303540, +327685, +871, +1970236769, +1766618222, +7628903, +262149, +873, +1634886000, +109, +262149, +876, +1634886000, +109, +262149, +880, +1869377379, +114, +327685, +881, +1634890867, +1866687598, +7499628, +262149, +882, +1634886000, +109, +262149, +885, +1634886000, +109, +262149, +888, +1634886000, +109, +262149, +889, +1634886000, +109, +262149, +891, +1634886000, +109, +262149, +895, +1819231093, +29295, +262149, +902, +1634886000, +109, +262149, +913, +1953523044, +104, +262216, +176, +0, +5, +327752, +176, +0, +35, +0, +327752, +176, +0, +7, +16, +262216, +176, +1, +5, +327752, +176, +1, +35, +64, +327752, +176, +1, +7, +16, +262216, +176, +2, +5, +327752, +176, +2, +35, +128, +327752, +176, +2, +7, +16, +262216, +176, +3, +5, +327752, +176, +3, +35, +192, +327752, +176, +3, +7, +16, +327752, +176, +4, +35, +256, +327752, +176, +5, +35, +268, +327752, +176, +6, +35, +272, +327752, +176, +7, +35, +288, +327752, +176, +8, +35, +304, +327752, +176, +9, +35, +320, +327752, +176, +10, +35, +336, +327752, +176, +11, +35, +352, +327752, +176, +12, +35, +356, +327752, +176, +13, +35, +360, +327752, +176, +14, +35, +364, +327752, +176, +15, +35, +368, +327752, +176, +16, +35, +384, +327752, +176, +17, +35, +388, +327752, +176, +18, +35, +392, +327752, +176, +19, +35, +396, +327752, +176, +20, +35, +400, +327752, +176, +21, +35, +404, +327752, +176, +22, +35, +408, +327752, +176, +23, +35, +412, +327752, +176, +24, +35, +416, +327752, +176, +25, +35, +420, +327752, +176, +26, +35, +424, +262216, +176, +27, +5, +327752, +176, +27, +35, +432, +327752, +176, +27, +7, +16, +196679, +176, +2, +262215, +178, +34, +0, +262215, +178, +33, +16, +262215, +349, +34, +0, +262215, +349, +33, +3, +262215, +353, +34, +0, +262215, +353, +33, +19, +262215, +746, +11, +15, +262215, +786, +30, +2, +262215, +803, +30, +1, +262215, +827, +30, +0, +262215, +845, +34, +0, +262215, +845, +33, +13, +262215, +881, +30, +3, +262215, +913, +30, +0, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +262165, +9, +32, +0, +262177, +10, +9, +8, +262176, +14, +7, +9, +262177, +15, +7, +14, +262167, +19, +6, +3, +262176, +20, +7, +19, +262176, +21, +7, +6, +327713, +22, +9, +20, +21, +262177, +27, +19, +14, +262177, +31, +6, +14, +262167, +35, +6, +2, +262176, +36, +7, +35, +393249, +37, +6, +36, +36, +36, +327713, +43, +6, +20, +21, +524321, +52, +19, +20, +20, +8, +21, +20, +458785, +60, +19, +20, +20, +8, +21, +262165, +67, +32, +1, +262167, +68, +67, +2, +262176, +69, +7, +68, +262177, +70, +67, +69, +262187, +9, +75, +0, +262187, +6, +78, +1132396544, +262187, +9, +81, +255, +262187, +9, +84, +1, +262187, +9, +91, +2, +262187, +9, +98, +3, +262187, +67, +105, +24, +262187, +67, +108, +16, +262187, +67, +112, +8, +262187, +9, +120, +4278190080, +262187, +9, +126, +16711680, +262187, +9, +132, +65280, +262187, +6, +145, +1056964608, +262187, +6, +158, +1073741824, +262187, +6, +164, +1065353216, +262168, +175, +7, +4, +1966110, +176, +175, +175, +175, +175, +19, +6, +7, +7, +7, +7, +7, +6, +6, +6, +6, +7, +6, +6, +6, +6, +67, +67, +67, +67, +6, +6, +6, +175, +262176, +177, +2, +176, +262203, +177, +178, +2, +262187, +67, +179, +15, +262176, +180, +2, +7, +262187, +6, +191, +3212836864, +131092, +216, +262176, +217, +7, +216, +262187, +6, +222, +0, +262167, +228, +216, +2, +262187, +67, +251, +3, +262176, +252, +2, +175, +262187, +6, +287, +1008981770, +262176, +294, +7, +67, +262187, +67, +296, +4294967294, +262187, +67, +303, +2, +262187, +6, +314, +1075419546, +262187, +6, +316, +1075838976, +262187, +67, +320, +4294967295, +262187, +6, +336, +1086911939, +262187, +6, +342, +1076677837, +589849, +347, +6, +1, +0, +0, +0, +1, +0, +262176, +348, +0, +347, +262203, +348, +349, +0, +131098, +351, +262176, +352, +0, +351, +262203, +352, +353, +0, +196635, +355, +347, +262187, +6, +363, +1142947840, +262187, +67, +372, +18, +262176, +373, +2, +6, +262187, +67, +377, +19, +262187, +67, +398, +14, +262187, +6, +405, +925353388, +262187, +67, +426, +1, +262187, +67, +535, +9, +262187, +67, +541, +10, +262187, +67, +554, +25, +262187, +67, +558, +26, +262187, +67, +571, +4, +262176, +572, +2, +19, +262187, +6, +595, +1092616192, +262187, +6, +597, +1078523331, +262187, +6, +599, +1127481344, +262187, +6, +645, +3225419776, +262187, +67, +673, +6, +262187, +67, +681, +7, +262176, +745, +1, +7, +262203, +745, +746, +1, +262176, +747, +1, +6, +262187, +67, +780, +17, +262203, +745, +786, +1, +262187, +67, +795, +21, +262176, +796, +2, +67, +262187, +67, +799, +0, +262203, +745, +803, +1, +262187, +67, +816, +11, +262176, +826, +3, +7, +262203, +826, +827, +3, +458796, +7, +828, +222, +222, +222, +222, +589849, +843, +9, +1, +0, +1, +0, +2, +33, +262176, +844, +0, +843, +262203, +844, +845, +0, +262167, +848, +67, +3, +262167, +852, +9, +4, +262187, +67, +872, +12, +262203, +745, +881, +1, +262203, +747, +913, +1, +327734, +2, +4, +0, +3, +131320, +5, +262203, +8, +744, +7, +262203, +8, +765, +7, +262203, +21, +779, +7, +262203, +21, +789, +7, +262203, +21, +794, +7, +262203, +36, +804, +7, +262203, +36, +807, +7, +262203, +36, +810, +7, +262203, +21, +814, +7, +262203, +69, +830, +7, +262203, +294, +834, +7, +262203, +69, +835, +7, +262203, +14, +838, +7, +262203, +14, +842, +7, +262203, +14, +855, +7, +262203, +14, +863, +7, +262203, +21, +871, +7, +262203, +20, +873, +7, +262203, +21, +876, +7, +262203, +20, +880, +7, +262203, +20, +882, +7, +262203, +20, +885, +7, +262203, +8, +888, +7, +262203, +21, +889, +7, +262203, +20, +891, +7, +262203, +14, +895, +7, +262203, +8, +902, +7, +327745, +747, +748, +746, +75, +262205, +6, +749, +748, +327813, +6, +750, +158, +749, +393281, +373, +751, +178, +179, +91, +262205, +6, +752, +751, +327813, +6, +753, +750, +752, +327811, +6, +754, +753, +164, +327745, +747, +755, +746, +84, +262205, +6, +756, +755, +327813, +6, +757, +158, +756, +393281, +373, +758, +178, +179, +98, +262205, +6, +759, +758, +327813, +6, +760, +757, +759, +327811, +6, +761, +164, +760, +327745, +747, +762, +746, +91, +262205, +6, +763, +762, +458832, +7, +764, +754, +761, +763, +164, +196670, +744, +764, +327745, +252, +766, +178, +303, +262205, +175, +767, +766, +262205, +7, +768, +744, +327825, +7, +769, +767, +768, +196670, +765, +769, +262205, +7, +770, +765, +524367, +19, +771, +770, +770, +0, +1, +2, +327745, +21, +772, +765, +98, +262205, +6, +773, +772, +393296, +19, +774, +773, +773, +773, +327816, +19, +775, +771, +774, +262205, +7, +776, +765, +589903, +7, +777, +776, +775, +4, +5, +6, +3, +196670, +765, +777, +327745, +21, +778, +765, +98, +196670, +778, +164, +196670, +779, +164, +327745, +373, +781, +178, +780, +262205, +6, +782, +781, +327866, +216, +783, +782, +222, +196855, +785, +0, +262394, +783, +784, +785, +131320, +784, +327745, +747, +787, +786, +98, +262205, +6, +788, +787, +196670, +779, +788, +131321, +785, +131320, +785, +262205, +6, +790, +779, +327745, +373, +791, +178, +398, +262205, +6, +792, +791, +327813, +6, +793, +790, +792, +196670, +789, +793, +196670, +794, +164, +327745, +796, +797, +178, +795, +262205, +67, +798, +797, +327851, +216, +800, +798, +799, +196855, +802, +0, +262394, +800, +801, +802, +131320, +801, +262205, +7, +805, +803, +458831, +35, +806, +805, +805, +0, +1, +196670, +804, +806, +262205, +7, +808, +803, +458831, +35, +809, +808, +808, +2, +3, +196670, +807, +809, +262205, +7, +811, +744, +458831, +35, +812, +811, +811, +0, +1, +196670, +810, +812, +458809, +6, +813, +41, +804, +807, +810, +196670, +794, +813, +131321, +802, +131320, +802, +262205, +6, +815, +794, +327745, +373, +817, +178, +816, +262205, +6, +818, +817, +327813, +6, +819, +815, +818, +196670, +814, +819, +262205, +6, +820, +814, +327745, +373, +821, +178, +105, +262205, +6, +822, +821, +327864, +216, +823, +820, +822, +196855, +825, +0, +262394, +823, +824, +825, +131320, +824, +196670, +827, +828, +65789, +131320, +825, +262205, +7, +831, +746, +458831, +35, +832, +831, +831, +0, +1, +262254, +68, +833, +832, +196670, +830, +833, +262205, +68, +836, +830, +196670, +835, +836, +327737, +67, +837, +72, +835, +196670, +834, +837, +327745, +747, +839, +746, +91, +262205, +6, +840, +839, +262268, +9, +841, +840, +196670, +838, +841, +262205, +843, +846, +845, +262205, +68, +847, +830, +327761, +67, +849, +847, +0, +327761, +67, +850, +847, +1, +393296, +848, +851, +849, +850, +799, +327778, +852, +853, +846, +851, +327761, +9, +854, +853, +0, +196670, +842, +854, +262205, +843, +856, +845, +262205, +68, +857, +830, +327761, +67, +858, +857, +0, +327761, +67, +859, +857, +1, +393296, +848, +860, +858, +859, +426, +327778, +852, +861, +856, +860, +327761, +9, +862, +861, +0, +196670, +855, +862, +262205, +843, +864, +845, +262205, +68, +865, +830, +327761, +67, +866, +865, +0, +327761, +67, +867, +865, +1, +393296, +848, +868, +866, +867, +303, +327778, +852, +869, +864, +868, +327761, +9, +870, +869, +0, +196670, +863, +870, +262205, +7, +874, +765, +524367, +19, +875, +874, +874, +0, +1, +2, +196670, +873, +875, +327745, +373, +877, +178, +872, +262205, +6, +878, +877, +196670, +876, +878, +393273, +6, +879, +46, +873, +876, +196670, +871, +879, +262205, +7, +883, +765, +524367, +19, +884, +883, +883, +0, +1, +2, +196670, +882, +884, +262205, +7, +886, +786, +524367, +19, +887, +886, +886, +0, +1, +2, +196670, +885, +887, +196670, +888, +828, +262205, +6, +890, +871, +196670, +889, +890, +262205, +7, +892, +881, +524367, +19, +893, +892, +892, +0, +1, +2, +196670, +891, +893, +589881, +19, +894, +58, +882, +885, +888, +889, +891, +196670, +880, +894, +262205, +19, +896, +880, +262205, +6, +897, +814, +327761, +6, +898, +896, +0, +327761, +6, +899, +896, +1, +327761, +6, +900, +896, +2, +458832, +7, +901, +898, +899, +900, +897, +196670, +902, +901, +327737, +9, +903, +12, +902, +196670, +895, +903, +262205, +19, +904, +880, +262205, +6, +905, +814, +327822, +19, +906, +904, +905, +262205, +6, +907, +814, +327761, +6, +908, +906, +0, +327761, +6, +909, +906, +1, +327761, +6, +910, +906, +2, +458832, +7, +911, +908, +909, +910, +907, +196670, +827, +911, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +262203, +14, +74, +7, +262203, +14, +83, +7, +262203, +14, +90, +7, +262203, +14, +97, +7, +327745, +21, +76, +11, +75, +262205, +6, +77, +76, +327813, +6, +79, +77, +78, +262253, +9, +80, +79, +327879, +9, +82, +80, +81, +196670, +74, +82, +327745, +21, +85, +11, +84, +262205, +6, +86, +85, +327813, +6, +87, +86, +78, +262253, +9, +88, +87, +327879, +9, +89, +88, +81, +196670, +83, +89, +327745, +21, +92, +11, +91, +262205, +6, +93, +92, +327813, +6, +94, +93, +78, +262253, +9, +95, +94, +327879, +9, +96, +95, +81, +196670, +90, +96, +327745, +21, +99, +11, +98, +262205, +6, +100, +99, +327813, +6, +101, +100, +78, +262253, +9, +102, +101, +327879, +9, +103, +102, +81, +196670, +97, +103, +262205, +9, +104, +74, +327876, +9, +106, +104, +105, +262205, +9, +107, +83, +327876, +9, +109, +107, +108, +327877, +9, +110, +106, +109, +262205, +9, +111, +90, +327876, +9, +113, +111, +112, +327877, +9, +114, +110, +113, +262205, +9, +115, +97, +327877, +9, +116, +114, +115, +131326, +116, +65592, +327734, +7, +17, +0, +15, +196663, +14, +16, +131320, +18, +262205, +9, +119, +16, +327879, +9, +121, +119, +120, +327874, +9, +122, +121, +105, +262256, +6, +123, +122, +327816, +6, +124, +123, +78, +262205, +9, +125, +16, +327879, +9, +127, +125, +126, +327874, +9, +128, +127, +108, +262256, +6, +129, +128, +327816, +6, +130, +129, +78, +262205, +9, +131, +16, +327879, +9, +133, +131, +132, +327874, +9, +134, +133, +112, +262256, +6, +135, +134, +327816, +6, +136, +135, +78, +262205, +9, +137, +16, +327879, +9, +138, +137, +81, +262256, +6, +139, +138, +327816, +6, +140, +139, +78, +458832, +7, +141, +124, +130, +136, +140, +131326, +141, +65592, +327734, +9, +25, +0, +22, +196663, +20, +23, +196663, +21, +24, +131320, +26, +262203, +8, +154, +7, +262205, +19, +144, +23, +327822, +19, +146, +144, +145, +393296, +19, +147, +145, +145, +145, +327809, +19, +148, +146, +147, +262205, +6, +149, +24, +327761, +6, +150, +148, +0, +327761, +6, +151, +148, +1, +327761, +6, +152, +148, +2, +458832, +7, +153, +150, +151, +152, +149, +196670, +154, +153, +327737, +9, +155, +12, +154, +131326, +155, +65592, +327734, +19, +29, +0, +27, +196663, +14, +28, +131320, +30, +262203, +14, +159, +7, +262205, +9, +160, +28, +196670, +159, +160, +327737, +7, +161, +17, +159, +524367, +19, +162, +161, +161, +0, +1, +2, +327822, +19, +163, +162, +158, +393296, +19, +165, +164, +164, +164, +327811, +19, +166, +163, +165, +131326, +166, +65592, +327734, +6, +33, +0, +31, +196663, +14, +32, +131320, +34, +262203, +14, +169, +7, +262205, +9, +170, +32, +196670, +169, +170, +327737, +7, +171, +17, +169, +327761, +6, +172, +171, +3, +131326, +172, +65592, +327734, +6, +41, +0, +37, +196663, +36, +38, +196663, +36, +39, +196663, +36, +40, +131320, +42, +262203, +21, +201, +7, +262203, +21, +206, +7, +262203, +21, +211, +7, +262203, +217, +218, +7, +262203, +21, +231, +7, +262203, +21, +232, +7, +262203, +21, +238, +7, +327745, +180, +181, +178, +179, +262205, +7, +182, +181, +458831, +35, +183, +182, +182, +0, +1, +262205, +35, +184, +38, +327813, +35, +185, +184, +183, +196670, +38, +185, +327745, +180, +186, +178, +179, +262205, +7, +187, +186, +458831, +35, +188, +187, +187, +0, +1, +262205, +35, +189, +39, +327813, +35, +190, +189, +188, +196670, +39, +190, +327745, +21, +192, +40, +84, +262205, +6, +193, +192, +327813, +6, +194, +193, +191, +327745, +21, +195, +40, +84, +196670, +195, +194, +327745, +180, +196, +178, +179, +262205, +7, +197, +196, +458831, +35, +198, +197, +197, +0, +1, +262205, +35, +199, +40, +327813, +35, +200, +199, +198, +196670, +40, +200, +262205, +35, +202, +38, +262205, +35, +203, +40, +327811, +35, +204, +202, +203, +393228, +6, +205, +1, +66, +204, +196670, +201, +205, +262205, +35, +207, +39, +262205, +35, +208, +40, +327811, +35, +209, +207, +208, +393228, +6, +210, +1, +66, +209, +196670, +206, +210, +262205, +35, +212, +38, +262205, +35, +213, +39, +327811, +35, +214, +212, +213, +393228, +6, +215, +1, +66, +214, +196670, +211, +215, +262205, +6, +219, +211, +262205, +6, +220, +201, +458764, +6, +221, +1, +48, +219, +220, +327866, +216, +223, +221, +222, +262205, +6, +224, +211, +262205, +6, +225, +206, +458764, +6, +226, +1, +48, +224, +225, +327866, +216, +227, +226, +222, +327760, +228, +229, +223, +227, +262298, +216, +230, +229, +196670, +218, +230, +262205, +216, +233, +218, +196855, +235, +0, +262394, +233, +234, +236, +131320, +234, +196670, +232, +191, +131321, +235, +131320, +236, +196670, +232, +164, +131321, +235, +131320, +235, +262205, +6, +237, +232, +196670, +231, +237, +262205, +6, +239, +231, +262205, +6, +240, +201, +262205, +6, +241, +206, +458764, +6, +242, +1, +37, +240, +241, +524300, +6, +243, +1, +43, +242, +222, +164, +327813, +6, +244, +239, +243, +196670, +238, +244, +262205, +6, +245, +238, +327809, +6, +246, +245, +164, +327813, +6, +247, +246, +145, +131326, +247, +65592, +327734, +6, +46, +0, +43, +196663, +20, +44, +196663, +21, +45, +131320, +47, +262203, +8, +250, +7, +262203, +36, +269, +7, +262203, +21, +279, +7, +262203, +21, +285, +7, +262203, +21, +289, +7, +262203, +21, +292, +7, +262203, +21, +293, +7, +262203, +294, +295, +7, +262203, +294, +305, +7, +262203, +21, +313, +7, +262203, +21, +315, +7, +262203, +21, +319, +7, +262203, +21, +335, +7, +262203, +21, +346, +7, +262203, +21, +371, +7, +262203, +21, +389, +7, +262203, +21, +394, +7, +262203, +21, +403, +7, +262203, +21, +433, +7, +327745, +252, +253, +178, +251, +262205, +175, +254, +253, +262205, +19, +255, +44, +327761, +6, +256, +255, +0, +327761, +6, +257, +255, +1, +327761, +6, +258, +255, +2, +458832, +7, +259, +256, +257, +258, +164, +327825, +7, +260, +254, +259, +196670, +250, +260, +327745, +21, +261, +250, +98, +262205, +6, +262, +261, +262205, +7, +263, +250, +458831, +35, +264, +263, +263, +0, +1, +327760, +35, +265, +262, +262, +327816, +35, +266, +264, +265, +262205, +7, +267, +250, +589903, +7, +268, +267, +266, +4, +5, +2, +3, +196670, +250, +268, +262205, +7, +270, +250, +458831, +35, +271, +270, +270, +0, +1, +327822, +35, +272, +271, +145, +327760, +35, +273, +145, +145, +327809, +35, +274, +272, +273, +196670, +269, +274, +327745, +21, +275, +269, +84, +262205, +6, +276, +275, +327811, +6, +277, +164, +276, +327745, +21, +278, +269, +84, +196670, +278, +277, +327745, +21, +280, +250, +91, +262205, +6, +281, +280, +327745, +21, +282, +250, +98, +262205, +6, +283, +282, +327816, +6, +284, +281, +283, +196670, +279, +284, +262205, +6, +286, +279, +327813, +6, +288, +286, +287, +196670, +285, +288, +327745, +21, +290, +250, +98, +262205, +6, +291, +290, +196670, +289, +291, +196670, +292, +222, +196670, +293, +222, +196670, +292, +222, +196670, +295, +296, +131321, +297, +131320, +297, +262390, +299, +300, +0, +131321, +301, +131320, +301, +262205, +67, +302, +295, +327859, +216, +304, +302, +303, +262394, +304, +298, +299, +131320, +298, +196670, +305, +296, +131321, +306, +131320, +306, +262390, +308, +309, +0, +131321, +310, +131320, +310, +262205, +67, +311, +305, +327859, +216, +312, +311, +303, +262394, +312, +307, +308, +131320, +307, +196670, +313, +314, +262205, +6, +317, +313, +327816, +6, +318, +316, +317, +196670, +315, +318, +262205, +67, +321, +295, +262205, +67, +322, +295, +327812, +67, +323, +321, +322, +262205, +67, +324, +305, +262205, +67, +325, +305, +327812, +67, +326, +324, +325, +327808, +67, +327, +323, +326, +327812, +67, +328, +320, +327, +262255, +6, +329, +328, +262205, +6, +330, +315, +327813, +6, +331, +158, +330, +262205, +6, +332, +315, +327813, +6, +333, +331, +332, +327816, +6, +334, +329, +333, +196670, +319, +334, +262205, +6, +337, +315, +327813, +6, +338, +336, +337, +262205, +6, +339, +315, +327813, +6, +340, +338, +339, +327816, +6, +341, +164, +340, +262205, +6, +343, +319, +458764, +6, +344, +1, +26, +342, +343, +327813, +6, +345, +341, +344, +196670, +335, +345, +262205, +347, +350, +349, +262205, +351, +354, +353, +327766, +355, +356, +350, +354, +262205, +35, +357, +269, +262205, +67, +358, +295, +262255, +6, +359, +358, +262205, +67, +360, +305, +262255, +6, +361, +360, +327760, +35, +362, +359, +361, +327760, +35, +364, +363, +363, +327816, +35, +365, +362, +364, +327809, +35, +366, +357, +365, +327767, +7, +367, +356, +366, +327761, +6, +368, +367, +0, +327813, +6, +369, +158, +368, +327811, +6, +370, +369, +164, +196670, +346, +370, +327745, +373, +374, +178, +372, +262205, +6, +375, +374, +262205, +6, +376, +346, +327745, +373, +378, +178, +377, +262205, +6, +379, +378, +327745, +373, +380, +178, +372, +262205, +6, +381, +380, +327811, +6, +382, +379, +381, +327813, +6, +383, +376, +382, +327745, +373, +384, +178, +377, +262205, +6, +385, +384, +327816, +6, +386, +383, +385, +327811, +6, +387, +164, +386, +327816, +6, +388, +375, +387, +196670, +371, +388, +262205, +6, +390, +289, +262205, +6, +391, +371, +327811, +6, +392, +390, +391, +458764, +6, +393, +1, +40, +222, +392, +196670, +389, +393, +262205, +6, +395, +389, +327745, +373, +396, +178, +108, +262205, +6, +397, +396, +327745, +373, +399, +178, +398, +262205, +6, +400, +399, +327813, +6, +401, +397, +400, +327816, +6, +402, +395, +401, +196670, +394, +402, +262205, +6, +404, +389, +327866, +216, +406, +404, +405, +196855, +408, +0, +262394, +406, +407, +409, +131320, +407, +196670, +403, +164, +131321, +408, +131320, +409, +196670, +403, +222, +131321, +408, +131320, +408, +262205, +6, +410, +403, +262205, +6, +411, +394, +327809, +6, +412, +411, +410, +196670, +394, +412, +262205, +6, +413, +45, +327811, +6, +414, +164, +413, +393228, +6, +415, +1, +4, +414, +262205, +6, +416, +394, +458764, +6, +417, +1, +26, +415, +416, +262205, +6, +418, +335, +327813, +6, +419, +417, +418, +262205, +6, +420, +293, +327809, +6, +421, +420, +419, +196670, +293, +421, +262205, +6, +422, +335, +262205, +6, +423, +292, +327809, +6, +424, +423, +422, +196670, +292, +424, +131321, +309, +131320, +309, +262205, +67, +425, +305, +327808, +67, +427, +425, +426, +196670, +305, +427, +131321, +306, +131320, +308, +131321, +300, +131320, +300, +262205, +67, +428, +295, +327808, +67, +429, +428, +426, +196670, +295, +429, +131321, +297, +131320, +299, +262205, +6, +430, +292, +262205, +6, +431, +293, +327816, +6, +432, +431, +430, +196670, +293, +432, +196670, +433, +164, +262205, +6, +434, +293, +262205, +6, +435, +433, +327813, +6, +436, +434, +435, +131326, +436, +65592, +327734, +6, +50, +0, +43, +196663, +20, +48, +196663, +21, +49, +131320, +51, +262203, +8, +439, +7, +262203, +36, +456, +7, +262203, +21, +466, +7, +262203, +21, +472, +7, +262203, +21, +475, +7, +262203, +21, +478, +7, +262203, +21, +479, +7, +262203, +21, +488, +7, +262203, +21, +503, +7, +262203, +21, +508, +7, +262203, +21, +516, +7, +262203, +21, +525, +7, +327745, +252, +440, +178, +251, +262205, +175, +441, +440, +262205, +19, +442, +48, +327761, +6, +443, +442, +0, +327761, +6, +444, +442, +1, +327761, +6, +445, +442, +2, +458832, +7, +446, +443, +444, +445, +164, +327825, +7, +447, +441, +446, +196670, +439, +447, +327745, +21, +448, +439, +98, +262205, +6, +449, +448, +262205, +7, +450, +439, +458831, +35, +451, +450, +450, +0, +1, +327760, +35, +452, +449, +449, +327816, +35, +453, +451, +452, +262205, +7, +454, +439, +589903, +7, +455, +454, +453, +4, +5, +2, +3, +196670, +439, +455, +262205, +7, +457, +439, +458831, +35, +458, +457, +457, +0, +1, +327822, +35, +459, +458, +145, +327760, +35, +460, +145, +145, +327809, +35, +461, +459, +460, +196670, +456, +461, +327745, +21, +462, +456, +84, +262205, +6, +463, +462, +327811, +6, +464, +164, +463, +327745, +21, +465, +456, +84, +196670, +465, +464, +327745, +21, +467, +439, +91, +262205, +6, +468, +467, +327745, +21, +469, +439, +98, +262205, +6, +470, +469, +327816, +6, +471, +468, +470, +196670, +466, +471, +262205, +6, +473, +466, +327813, +6, +474, +473, +287, +196670, +472, +474, +327745, +21, +476, +439, +98, +262205, +6, +477, +476, +196670, +475, +477, +196670, +478, +164, +262205, +347, +480, +349, +262205, +351, +481, +353, +327766, +355, +482, +480, +481, +262205, +35, +483, +456, +327767, +7, +484, +482, +483, +327761, +6, +485, +484, +0, +327813, +6, +486, +158, +485, +327811, +6, +487, +486, +164, +196670, +479, +487, +327745, +373, +489, +178, +372, +262205, +6, +490, +489, +262205, +6, +491, +479, +327745, +373, +492, +178, +377, +262205, +6, +493, +492, +327745, +373, +494, +178, +372, +262205, +6, +495, +494, +327811, +6, +496, +493, +495, +327813, +6, +497, +491, +496, +327745, +373, +498, +178, +377, +262205, +6, +499, +498, +327816, +6, +500, +497, +499, +327811, +6, +501, +164, +500, +327816, +6, +502, +490, +501, +196670, +488, +502, +262205, +6, +504, +475, +262205, +6, +505, +488, +327811, +6, +506, +504, +505, +458764, +6, +507, +1, +40, +222, +506, +196670, +503, +507, +262205, +6, +509, +503, +327745, +373, +510, +178, +108, +262205, +6, +511, +510, +327745, +373, +512, +178, +398, +262205, +6, +513, +512, +327813, +6, +514, +511, +513, +327816, +6, +515, +509, +514, +196670, +508, +515, +262205, +6, +517, +503, +327866, +216, +518, +517, +405, +196855, +520, +0, +262394, +518, +519, +521, +131320, +519, +196670, +516, +164, +131321, +520, +131320, +521, +196670, +516, +222, +131321, +520, +131320, +520, +262205, +6, +522, +516, +262205, +6, +523, +508, +327809, +6, +524, +523, +522, +196670, +508, +524, +262205, +6, +526, +49, +327811, +6, +527, +164, +526, +393228, +6, +528, +1, +4, +527, +262205, +6, +529, +508, +458764, +6, +530, +1, +26, +528, +529, +196670, +525, +530, +262205, +6, +531, +525, +131326, +531, +65592, +327734, +19, +58, +0, +52, +196663, +20, +53, +196663, +20, +54, +196663, +8, +55, +196663, +21, +56, +196663, +20, +57, +131320, +59, +262203, +20, +534, +7, +262203, +21, +539, +7, +262203, +21, +540, +7, +262203, +21, +544, +7, +262203, +21, +547, +7, +262203, +21, +550, +7, +262203, +21, +553, +7, +262203, +21, +557, +7, +262203, +20, +561, +7, +262203, +20, +565, +7, +262203, +20, +570, +7, +262203, +20, +578, +7, +262203, +21, +581, +7, +262203, +21, +585, +7, +262203, +21, +591, +7, +262203, +21, +593, +7, +262203, +21, +601, +7, +262203, +21, +604, +7, +262203, +21, +606, +7, +262203, +21, +610, +7, +262203, +21, +616, +7, +262203, +21, +628, +7, +262203, +21, +634, +7, +262203, +21, +643, +7, +262203, +21, +656, +7, +262203, +21, +662, +7, +262203, +20, +671, +7, +327745, +180, +536, +178, +535, +262205, +7, +537, +536, +524367, +19, +538, +537, +537, +0, +1, +2, +196670, +534, +538, +196670, +539, +164, +393281, +373, +542, +178, +541, +75, +262205, +6, +543, +542, +196670, +540, +543, +393281, +373, +545, +178, +541, +84, +262205, +6, +546, +545, +196670, +544, +546, +393281, +373, +548, +178, +541, +91, +262205, +6, +549, +548, +196670, +547, +549, +393281, +373, +551, +178, +541, +98, +262205, +6, +552, +551, +196670, +550, +552, +327745, +373, +555, +178, +554, +262205, +6, +556, +555, +196670, +553, +556, +327745, +373, +559, +178, +558, +262205, +6, +560, +559, +196670, +557, +560, +327745, +180, +562, +178, +112, +262205, +7, +563, +562, +524367, +19, +564, +563, +563, +0, +1, +2, +196670, +561, +564, +262205, +19, +566, +561, +262205, +19, +567, +53, +327811, +19, +568, +566, +567, +393228, +19, +569, +1, +69, +568, +196670, +565, +569, +327745, +572, +573, +178, +571, +262205, +19, +574, +573, +262205, +19, +575, +53, +327811, +19, +576, +574, +575, +393228, +19, +577, +1, +69, +576, +196670, +570, +577, +262205, +19, +579, +54, +393228, +19, +580, +1, +69, +579, +196670, +578, +580, +262205, +19, +582, +578, +262205, +19, +583, +565, +327828, +6, +584, +582, +583, +196670, +581, +584, +262205, +6, +586, +581, +262205, +6, +587, +581, +327813, +6, +588, +586, +587, +327811, +6, +589, +164, +588, +393228, +6, +590, +1, +31, +589, +196670, +585, +590, +262205, +6, +592, +585, +196670, +591, +592, +262205, +6, +594, +539, +327813, +6, +596, +594, +595, +327813, +6, +598, +596, +597, +327816, +6, +600, +598, +599, +196670, +593, +600, +262205, +6, +602, +581, +262271, +6, +603, +602, +196670, +601, +603, +262205, +6, +605, +585, +196670, +604, +605, +262205, +19, +607, +578, +262205, +19, +608, +570, +327828, +6, +609, +607, +608, +196670, +606, +609, +262205, +6, +611, +606, +262205, +6, +612, +606, +327813, +6, +613, +611, +612, +327811, +6, +614, +164, +613, +393228, +6, +615, +1, +31, +614, +196670, +610, +615, +262205, +6, +617, +601, +262205, +6, +618, +593, +327813, +6, +619, +158, +618, +393228, +6, +620, +1, +14, +619, +327813, +6, +621, +617, +620, +262205, +6, +622, +604, +262205, +6, +623, +593, +327813, +6, +624, +158, +623, +393228, +6, +625, +1, +13, +624, +327813, +6, +626, +622, +625, +327811, +6, +627, +621, +626, +196670, +616, +627, +262205, +6, +629, +616, +262205, +6, +630, +616, +327813, +6, +631, +629, +630, +327811, +6, +632, +164, +631, +393228, +6, +633, +1, +31, +632, +196670, +628, +633, +262205, +6, +635, +616, +262205, +6, +636, +606, +327813, +6, +637, +635, +636, +262205, +6, +638, +628, +262205, +6, +639, +610, +327813, +6, +640, +638, +639, +327809, +6, +641, +637, +640, +458764, +6, +642, +1, +40, +222, +641, +196670, +634, +642, +262205, +6, +644, +601, +262205, +6, +646, +593, +327813, +6, +647, +645, +646, +393228, +6, +648, +1, +14, +647, +327813, +6, +649, +644, +648, +262205, +6, +650, +604, +262205, +6, +651, +593, +327813, +6, +652, +645, +651, +393228, +6, +653, +1, +13, +652, +327813, +6, +654, +650, +653, +327811, +6, +655, +649, +654, +196670, +643, +655, +262205, +6, +657, +643, +262205, +6, +658, +643, +327813, +6, +659, +657, +658, +327811, +6, +660, +164, +659, +393228, +6, +661, +1, +31, +660, +196670, +656, +661, +262205, +6, +663, +643, +262205, +6, +664, +606, +327813, +6, +665, +663, +664, +262205, +6, +666, +656, +262205, +6, +667, +610, +327813, +6, +668, +666, +667, +327809, +6, +669, +665, +668, +458764, +6, +670, +1, +40, +222, +669, +196670, +662, +670, +262205, +6, +672, +540, +327745, +180, +674, +178, +673, +262205, +7, +675, +674, +524367, +19, +676, +675, +675, +0, +1, +2, +327822, +19, +677, +676, +672, +262205, +19, +678, +534, +327813, +19, +679, +677, +678, +262205, +6, +680, +56, +327745, +180, +682, +178, +681, +262205, +7, +683, +682, +524367, +19, +684, +683, +683, +0, +1, +2, +327822, +19, +685, +684, +680, +262205, +6, +686, +544, +262205, +6, +687, +591, +327813, +6, +688, +686, +687, +262205, +19, +689, +534, +327822, +19, +690, +689, +688, +262205, +6, +691, +547, +262205, +6, +692, +634, +262205, +6, +693, +550, +458764, +6, +694, +1, +26, +692, +693, +327813, +6, +695, +691, +694, +393296, +19, +696, +695, +695, +695, +327809, +19, +697, +690, +696, +262205, +6, +698, +553, +262205, +6, +699, +662, +262205, +6, +700, +557, +458764, +6, +701, +1, +26, +699, +700, +327813, +6, +702, +698, +701, +262205, +19, +703, +534, +327822, +19, +704, +703, +702, +327809, +19, +705, +697, +704, +327813, +19, +706, +685, +705, +327809, +19, +707, +679, +706, +196670, +671, +707, +262205, +19, +708, +671, +262205, +6, +709, +56, +327822, +19, +710, +708, +709, +131326, +710, +65592, +327734, +19, +65, +0, +60, +196663, +20, +61, +196663, +20, +62, +196663, +8, +63, +196663, +21, +64, +131320, +66, +262203, +20, +713, +7, +262203, +21, +717, +7, +262203, +20, +720, +7, +327745, +180, +714, +178, +535, +262205, +7, +715, +714, +524367, +19, +716, +715, +715, +0, +1, +2, +196670, +713, +716, +393281, +373, +718, +178, +541, +84, +262205, +6, +719, +718, +196670, +717, +719, +262205, +6, +721, +64, +262205, +6, +722, +717, +327813, +6, +723, +721, +722, +262205, +19, +724, +713, +327822, +19, +725, +724, +723, +196670, +720, +725, +262205, +19, +726, +720, +262205, +6, +727, +64, +327822, +19, +728, +726, +727, +131326, +728, +65592, +327734, +67, +72, +0, +70, +196663, +69, +71, +131320, +73, +262203, +294, +731, +7, +327745, +294, +732, +71, +84, +262205, +67, +733, +732, +393281, +373, +734, +178, +179, +75, +262205, +6, +735, +734, +262254, +67, +736, +735, +327812, +67, +737, +733, +736, +327745, +294, +738, +71, +75, +262205, +67, +739, +738, +327808, +67, +740, +737, +739, +196670, +731, +740, +262205, +67, +741, +731, +131326, +741, +65592, +}; +const std::vector resolvecolors = {119734787, +65536, +524289, +240, +0, +131089, +1, +131089, +40, +393227, +1, +1280527431, +1685353262, +808793134, +0, +196622, +0, +1, +458767, +4, +4, +1852399981, +0, +165, +193, +196624, +4, +7, +196624, +4, +9, +196611, +2, +450, +589828, +1096764487, +1935622738, +1918988389, +1600484449, +1684105331, +1868526181, +1667590754, +29556, +589828, +1096764487, +1935622738, +1768186216, +1818191726, +1969712737, +1600481121, +1882206772, +7037793, +655364, +1197427783, +1279741775, +1885560645, +1953718128, +1600482425, +1701734764, +1919509599, +1769235301, +25974, +524292, +1197427783, +1279741775, +1852399429, +1685417059, +1768185701, +1952671090, +6649449, +262149, +4, +1852399981, +0, +524293, +12, +1801675088, +1634692166, +1850291316, +1767206772, +1982362734, +3880038, +262149, +11, +1818318454, +25973, +589829, +17, +1634758229, +1767205731, +1850307694, +1816555380, +880042351, +993097000, +0, +262149, +16, +1818318453, +25973, +655365, +25, +1801675088, +1735287124, +1098149477, +1866687598, +1634887030, +1982358887, +1715155814, +15153, +262149, +23, +1735287156, +7630437, +327685, +24, +1702260579, +1701273970, +0, +393221, +29, +1416914247, +1701277281, +1965585518, +15153, +393221, +28, +1801675120, +1632920677, +1852139374, +116, +393221, +33, +1131701575, +1919252079, +677734241, +3879285, +393221, +32, +1801675120, +1866687589, +1634887030, +25959, +393221, +40, +1098147143, +1701995620, +1982362483, +3879529, +327685, +39, +1684291958, +1936942450, +0, +262149, +42, +1702132066, +51, +262149, +51, +1702132066, +50, +262149, +58, +1702132066, +49, +262149, +65, +1702132066, +48, +262149, +122, +1634886000, +109, +262149, +127, +1634886000, +109, +262149, +137, +1634886000, +109, +327685, +144, +1684291950, +1936942450, +0, +327685, +148, +1936617283, +1953390964, +115, +393222, +148, +0, +1466785639, +1684828783, +0, +393222, +148, +1, +1450008423, +1350002025, +6975346, +458758, +148, +2, +1231904615, +1767274094, +1917876069, +27247, +524294, +148, +3, +1450008423, +1350002025, +1282043762, +1952999273, +0, +327686, +148, +4, +1165385575, +25977, +327686, +148, +5, +1986420583, +7761734, +524294, +148, +6, +1833000807, +1852139874, +1734954100, +1866691688, +7499628, +524294, +148, +7, +1867538279, +1282698857, +1952999273, +1869377347, +114, +458758, +148, +8, +1867538279, +1282698857, +1952999273, +7565136, +458758, +148, +9, +1632460647, +1935753844, +1819231077, +29295, +393222, +148, +10, +1632460647, +1633045364, +6649196, +458758, +148, +11, +1766219623, +1098016098, +1634234476, +0, +524294, +148, +12, +1632132967, +1750299241, +2003788897, +1752198209, +97, +458758, +148, +13, +1164074855, +1851879544, +2020167780, +7564389, +458758, +148, +14, +1766219623, +1383228770, +1969841249, +115, +393222, +148, +15, +1767333735, +2053722990, +101, +458758, +148, +16, +1766219623, +1400005986, +1768120688, +26478, +393222, +148, +17, +1415733095, +1416522088, +28777, +458758, +148, +18, +1315331943, +1282564453, +1952999273, +0, +393222, +148, +19, +1181114215, +1766617697, +7628903, +393222, +148, +20, +1416191847, +1399350117, +77, +458758, +148, +21, +1432510311, +1866687859, +1634887030, +25959, +458758, +148, +22, +1399414631, +1851880052, +1886339940, +7562601, +458758, +148, +23, +1298751335, +1917220961, +1701668705, +7566446, +524294, +148, +24, +1818320743, +1415669872, +1936028264, +1684828008, +0, +393222, +148, +25, +1214668647, +1265789281, +12915, +393222, +148, +26, +1214668647, +1165125985, +12920, +589830, +148, +27, +1231904615, +1767274094, +1917876069, +1767271023, +1869641573, +29810, +196613, +150, +0, +393221, +163, +1919112054, +1097753957, +1701995620, +29555, +393221, +165, +1180658791, +1130848626, +1685221231, +0, +393221, +170, +1734439526, +1953391981, +1701080649, +120, +262149, +171, +1634886000, +109, +327685, +174, +1986939238, +1752198209, +97, +393221, +177, +1667449204, +1850305909, +1886142838, +24936, +262149, +183, +1886142822, +24936, +327685, +193, +1734439494, +1869377347, +114, +262149, +197, +1819239270, +29295, +393221, +198, +1734439494, +1953391981, +1869377347, +29554, +327685, +201, +1869377379, +1836405618, +88, +327685, +204, +1869377379, +1836405618, +89, +327685, +207, +1869377379, +1836405618, +90, +327685, +210, +1869377379, +1836405618, +87, +393221, +236, +1919508808, +1684105299, +1632466799, +112, +393221, +239, +1634951015, +1768902765, +1816360046, +7368033, +262216, +148, +0, +5, +327752, +148, +0, +35, +0, +327752, +148, +0, +7, +16, +262216, +148, +1, +5, +327752, +148, +1, +35, +64, +327752, +148, +1, +7, +16, +262216, +148, +2, +5, +327752, +148, +2, +35, +128, +327752, +148, +2, +7, +16, +262216, +148, +3, +5, +327752, +148, +3, +35, +192, +327752, +148, +3, +7, +16, +327752, +148, +4, +35, +256, +327752, +148, +5, +35, +268, +327752, +148, +6, +35, +272, +327752, +148, +7, +35, +288, +327752, +148, +8, +35, +304, +327752, +148, +9, +35, +320, +327752, +148, +10, +35, +336, +327752, +148, +11, +35, +352, +327752, +148, +12, +35, +356, +327752, +148, +13, +35, +360, +327752, +148, +14, +35, +364, +327752, +148, +15, +35, +368, +327752, +148, +16, +35, +384, +327752, +148, +17, +35, +388, +327752, +148, +18, +35, +392, +327752, +148, +19, +35, +396, +327752, +148, +20, +35, +400, +327752, +148, +21, +35, +404, +327752, +148, +22, +35, +408, +327752, +148, +23, +35, +412, +327752, +148, +24, +35, +416, +327752, +148, +25, +35, +420, +327752, +148, +26, +35, +424, +262216, +148, +27, +5, +327752, +148, +27, +35, +432, +327752, +148, +27, +7, +16, +196679, +148, +2, +262215, +150, +34, +0, +262215, +150, +33, +16, +262215, +165, +11, +15, +262215, +177, +34, +0, +262215, +177, +33, +15, +262215, +177, +43, +1, +262215, +193, +30, +0, +262215, +198, +34, +0, +262215, +198, +33, +14, +262215, +198, +43, +2, +262215, +236, +34, +0, +262215, +236, +33, +3, +262215, +239, +34, +0, +262215, +239, +33, +19, +131091, +2, +196641, +3, +2, +196630, +6, +32, +262167, +7, +6, +4, +262176, +8, +7, +7, +262165, +9, +32, +0, +262177, +10, +9, +8, +262176, +14, +7, +9, +262177, +15, +7, +14, +262167, +19, +6, +3, +262176, +20, +7, +19, +262176, +21, +7, +6, +327713, +22, +9, +20, +21, +262177, +27, +19, +14, +262177, +31, +6, +14, +262165, +35, +32, +1, +262167, +36, +35, +2, +262176, +37, +7, +36, +262177, +38, +35, +37, +262187, +9, +43, +0, +262187, +6, +46, +1132396544, +262187, +9, +49, +255, +262187, +9, +52, +1, +262187, +9, +59, +2, +262187, +9, +66, +3, +262187, +35, +73, +24, +262187, +35, +76, +16, +262187, +35, +80, +8, +262187, +9, +88, +4278190080, +262187, +9, +94, +16711680, +262187, +9, +100, +65280, +262187, +6, +113, +1056964608, +262187, +6, +126, +1073741824, +262187, +6, +132, +1065353216, +262176, +143, +7, +35, +262168, +147, +7, +4, +1966110, +148, +147, +147, +147, +147, +19, +6, +7, +7, +7, +7, +7, +6, +6, +6, +6, +7, +6, +6, +6, +6, +35, +35, +35, +35, +6, +6, +6, +147, +262176, +149, +2, +148, +262203, +149, +150, +2, +262187, +35, +151, +15, +262176, +152, +2, +6, +262176, +164, +1, +7, +262203, +164, +165, +1, +262167, +166, +6, +2, +589849, +175, +6, +6, +0, +0, +0, +2, +0, +262176, +176, +0, +175, +262203, +176, +177, +0, +262187, +35, +179, +0, +327724, +36, +180, +179, +179, +262187, +6, +187, +1017370378, +131092, +188, +262176, +192, +3, +7, +262203, +192, +193, +3, +262187, +6, +194, +0, +458796, +7, +195, +194, +194, +194, +132, +262203, +176, +198, +0, +589849, +234, +6, +1, +0, +0, +0, +1, +0, +262176, +235, +0, +234, +262203, +235, +236, +0, +131098, +237, +262176, +238, +0, +237, +262203, +238, +239, +0, +327734, +2, +4, +0, +3, +131320, +5, +262203, +37, +163, +7, +262203, +143, +170, +7, +262203, +37, +171, +7, +262203, +21, +174, +7, +262203, +21, +183, +7, +262203, +8, +197, +7, +262203, +21, +201, +7, +262203, +21, +204, +7, +262203, +21, +207, +7, +262203, +21, +210, +7, +262205, +7, +167, +165, +458831, +166, +168, +167, +167, +0, +1, +262254, +36, +169, +168, +196670, +163, +169, +262205, +36, +172, +163, +196670, +171, +172, +327737, +35, +173, +40, +171, +196670, +170, +173, +262205, +175, +178, +177, +327778, +7, +181, +178, +180, +327761, +6, +182, +181, +0, +196670, +174, +182, +262205, +6, +184, +174, +327811, +6, +185, +132, +184, +196670, +183, +185, +262205, +6, +186, +183, +327864, +188, +189, +186, +187, +196855, +191, +0, +262394, +189, +190, +191, +131320, +190, +196670, +193, +195, +65789, +131320, +191, +262205, +175, +199, +198, +327778, +7, +200, +199, +180, +196670, +197, +200, +327745, +21, +202, +197, +43, +262205, +6, +203, +202, +196670, +201, +203, +327745, +21, +205, +197, +52, +262205, +6, +206, +205, +196670, +204, +206, +327745, +21, +208, +197, +59, +262205, +6, +209, +208, +196670, +207, +209, +327745, +21, +211, +197, +66, +262205, +6, +212, +211, +196670, +210, +212, +262205, +6, +213, +201, +262205, +6, +214, +210, +327816, +6, +215, +213, +214, +327745, +21, +216, +197, +43, +196670, +216, +215, +262205, +6, +217, +204, +262205, +6, +218, +210, +327816, +6, +219, +217, +218, +327745, +21, +220, +197, +52, +196670, +220, +219, +262205, +6, +221, +207, +262205, +6, +222, +210, +327816, +6, +223, +221, +222, +327745, +21, +224, +197, +59, +196670, +224, +223, +262205, +6, +225, +183, +262205, +7, +226, +197, +524367, +19, +227, +226, +226, +0, +1, +2, +327822, +19, +228, +227, +225, +262205, +7, +229, +197, +589903, +7, +230, +229, +228, +4, +5, +6, +3, +196670, +197, +230, +262205, +6, +231, +174, +327745, +21, +232, +197, +66, +196670, +232, +231, +262205, +7, +233, +197, +196670, +193, +233, +65789, +65592, +327734, +9, +12, +0, +10, +196663, +8, +11, +131320, +13, +262203, +14, +42, +7, +262203, +14, +51, +7, +262203, +14, +58, +7, +262203, +14, +65, +7, +327745, +21, +44, +11, +43, +262205, +6, +45, +44, +327813, +6, +47, +45, +46, +262253, +9, +48, +47, +327879, +9, +50, +48, +49, +196670, +42, +50, +327745, +21, +53, +11, +52, +262205, +6, +54, +53, +327813, +6, +55, +54, +46, +262253, +9, +56, +55, +327879, +9, +57, +56, +49, +196670, +51, +57, +327745, +21, +60, +11, +59, +262205, +6, +61, +60, +327813, +6, +62, +61, +46, +262253, +9, +63, +62, +327879, +9, +64, +63, +49, +196670, +58, +64, +327745, +21, +67, +11, +66, +262205, +6, +68, +67, +327813, +6, +69, +68, +46, +262253, +9, +70, +69, +327879, +9, +71, +70, +49, +196670, +65, +71, +262205, +9, +72, +42, +327876, +9, +74, +72, +73, +262205, +9, +75, +51, +327876, +9, +77, +75, +76, +327877, +9, +78, +74, +77, +262205, +9, +79, +58, +327876, +9, +81, +79, +80, +327877, +9, +82, +78, +81, +262205, +9, +83, +65, +327877, +9, +84, +82, +83, +131326, +84, +65592, +327734, +7, +17, +0, +15, +196663, +14, +16, +131320, +18, +262205, +9, +87, +16, +327879, +9, +89, +87, +88, +327874, +9, +90, +89, +73, +262256, +6, +91, +90, +327816, +6, +92, +91, +46, +262205, +9, +93, +16, +327879, +9, +95, +93, +94, +327874, +9, +96, +95, +76, +262256, +6, +97, +96, +327816, +6, +98, +97, +46, +262205, +9, +99, +16, +327879, +9, +101, +99, +100, +327874, +9, +102, +101, +80, +262256, +6, +103, +102, +327816, +6, +104, +103, +46, +262205, +9, +105, +16, +327879, +9, +106, +105, +49, +262256, +6, +107, +106, +327816, +6, +108, +107, +46, +458832, +7, +109, +92, +98, +104, +108, +131326, +109, +65592, +327734, +9, +25, +0, +22, +196663, +20, +23, +196663, +21, +24, +131320, +26, +262203, +8, +122, +7, +262205, +19, +112, +23, +327822, +19, +114, +112, +113, +393296, +19, +115, +113, +113, +113, +327809, +19, +116, +114, +115, +262205, +6, +117, +24, +327761, +6, +118, +116, +0, +327761, +6, +119, +116, +1, +327761, +6, +120, +116, +2, +458832, +7, +121, +118, +119, +120, +117, +196670, +122, +121, +327737, +9, +123, +12, +122, +131326, +123, +65592, +327734, +19, +29, +0, +27, +196663, +14, +28, +131320, +30, +262203, +14, +127, +7, +262205, +9, +128, +28, +196670, +127, +128, +327737, +7, +129, +17, +127, +524367, +19, +130, +129, +129, +0, +1, +2, +327822, +19, +131, +130, +126, +393296, +19, +133, +132, +132, +132, +327811, +19, +134, +131, +133, +131326, +134, +65592, +327734, +6, +33, +0, +31, +196663, +14, +32, +131320, +34, +262203, +14, +137, +7, +262205, +9, +138, +32, +196670, +137, +138, +327737, +7, +139, +17, +137, +327761, +6, +140, +139, +3, +131326, +140, +65592, +327734, +35, +40, +0, +38, +196663, +37, +39, +131320, +41, +262203, +143, +144, +7, +327745, +143, +145, +39, +52, +262205, +35, +146, +145, +393281, +152, +153, +150, +151, +43, +262205, +6, +154, +153, +262254, +35, +155, +154, +327812, +35, +156, +146, +155, +327745, +143, +157, +39, +43, +262205, +35, +158, +157, +327808, +35, +159, +156, +158, +196670, +144, +159, +262205, +35, +160, +144, +131326, +160, +65592, +}; diff --git a/amd_tressfx_vulkan/src/TressFXRendererVulkan.cpp b/amd_tressfx_vulkan/src/TressFXRendererVulkan.cpp new file mode 100644 index 0000000..6b5076b --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXRendererVulkan.cpp @@ -0,0 +1,1509 @@ +//-------------------------------------------------------------------------------------- +// File: TressFXRenderer.cpp +// +// Main hair rendering code +// +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// +//-------------------------------------------------------------------------------------- + +#include "TressFXRendererVulkan.h" +#include "AMD_Types.h" +#include "TressFXOpaqueVulkan.h" +#include "TressFXPrecompiledShadersVulkan.h" +#include "UtilVulkan.h" + +// Number of depth layers to use. 2 or 3 supported. +#define SHORTCUT_NUM_DEPTHS 3 + +// unreferenced formal parameter +#pragma warning(disable : 4100) + +using namespace DirectX; + +extern int g_TressFXNumVerticesPerStrand; + +struct CB_PER_FRAME +{ + XMMATRIX m_mWorld; + XMMATRIX m_mViewProj; + XMMATRIX m_mInvViewProj; + XMMATRIX m_mViewProjLight; + + XMFLOAT3 m_vEye; + float m_fvFOV; + + XMFLOAT4 m_AmbientLightColor; + XMFLOAT4 m_PointLightColor; + XMFLOAT4 m_PointLightPos; + XMFLOAT4 m_MatBaseColor; + XMFLOAT4 m_MatKValue; + + float m_FiberAlpha; + float m_HairSMAlpha; + float m_bExpandPixels; + float m_FiberRadius; + + XMFLOAT4 m_WinSize; + + float m_FiberSpacing; + float m_bThinTip; + float m_fNearLight; + float m_fFarLight; + + int m_iTechSM; + int m_bUseCoverage; + int m_iStrandCopies; + int m_iMaxFragments; + + float m_alphaThreshold; + float m_fHairKs2; + float m_fHairEx2; + unsigned m_optionalSRVs; + + XMMATRIX m_mInvViewProjViewport; + + int m_mNumVerticesPerStrand; + int m_mNumFollowHairsPerGuideHair; + int m_bSingleHeadTransform; + int padding0; +}; + +// Optional SRVs +#define PER_STRAND_TEX_COORDS 0x0001 +#define PER_VERTEX_TEX_COORDS 0x0002 +#define PER_VERTEX_COLORS 0x0004 + +struct PER_PIXEL_LINKED_LIST_STRUCT +{ + DWORD TangentAndCoverage; + DWORD depth; + DWORD strandColor; + DWORD dwNext; +}; + +struct PPLL_BUFFERS +{ + // Buffers for the head of the per-pixel linked lists (PPLL) + VkImage pHeadPPLL_Buffer; + VkDeviceMemory pHeadPPLL_Memory; + VkImageView pHeadPPLL_View; + + // Buffers for the per-pixel linked list (PPLL) data + VkBuffer pPPLL_Buffer; + VkDeviceMemory pPPLL_Memory; + + // Buffer for the atomic counter + VkBuffer pAtomicCounterPLL_Buffer; + VkDeviceMemory pAtomicCounterPLL_Memory; + + // If possible PLLL head, PPLL and atomic counter use same memory block + VkDeviceMemory pSharedMemory; + + int width; + int height; + int refCount; // reference count - delete buffers when 0 +}; + +PPLL_BUFFERS g_PPLBuffers = {VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, 0, 0, 0}; + +const static UINT g_HairTotalLayers = 32; + +namespace +{ +//---------------------------------------------------------------------------------- +// +// CreateRenderPass +// +// Create the render pass used for the non shortcut algorithm +// +//---------------------------------------------------------------------------------- +VkRenderPass CreateRenderPass(VkDevice dev, VkFormat depthStencilFormat, VkFormat colorFormat) +{ + const VkAttachmentDescription attachments[] = { + // Depth Buffer + {0, depthStencilFormat, VK_SAMPLE_COUNT_1_BIT, + VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, + VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}, + // color texture + {0, colorFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, + VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, + VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}}; + + const VkAttachmentReference depthStencilReference = { + 0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; + const VkAttachmentReference colorReference = { + 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; + + const VkSubpassDescription subpasses[] = { + {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, + &depthStencilReference, 0, nullptr}, + {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &colorReference, nullptr, + &depthStencilReference, 0, nullptr}}; + + const VkSubpassDependency dependencies[] = { + {0, 1, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 0}}; + + VkRenderPassCreateInfo renderPassInfo{VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + nullptr, + 0, + AMD_ARRAY_SIZE(attachments), + attachments, + AMD_ARRAY_SIZE(subpasses), + subpasses, + AMD_ARRAY_SIZE(dependencies), + dependencies}; + VkRenderPass result; + vkCreateRenderPass(dev, &renderPassInfo, nullptr, &result); + return result; +} + +VkRenderPass CreateShadowRenderPass(VkDevice dev) +{ + const VkAttachmentDescription attachments[] = { + // Depth Buffer + {0, VK_FORMAT_D32_SFLOAT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, + VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}, + }; + + const VkAttachmentReference depthReference = { + 0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; + + const VkSubpassDescription subpasses[] = {{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, + nullptr, 0, nullptr, nullptr, + &depthReference, 0, nullptr}}; + + VkRenderPassCreateInfo renderPassInfo{VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + nullptr, + 0, + AMD_ARRAY_SIZE(attachments), + attachments, + AMD_ARRAY_SIZE(subpasses), + subpasses, + 0, + nullptr}; + VkRenderPass result; + vkCreateRenderPass(dev, &renderPassInfo, nullptr, &result); + return result; +} + +} // End anonymous namespace + +namespace AMD +{ +//-------------------------------------------------------------------------------------- +// +// CreateTextureAndViews +// +// Creates the textures and corresponding views for hair rendering +// +//-------------------------------------------------------------------------------------- +VkResult TressFXRenderer::CreateTextureAndViews( + VkDevice pvkDevice, VkPhysicalDeviceMemoryProperties memProperties, VkCommandBuffer commandBuffer, + VkDeviceMemory scratchMemory, VkBuffer scratchBuffer, size_t &offsetInScratchBuffer) +{ + VkResult vr; + + // Create SM DSVs for hair + { + VkImageCreateInfo hairShadowMapInfo = getImageCreateInfo( + VK_FORMAT_D32_SFLOAT, SM_HAIR_WIDTH, SM_HAIR_HEIGHT, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + AMD_CHECKED_VULKAN_CALL( + vkCreateImage(pvkDevice, &hairShadowMapInfo, nullptr, &m_pSMHairTexture)); + + m_pSMHairMemory = allocImageMemory(pvkDevice, m_pSMHairTexture, memProperties); + + VkImageViewCreateInfo dsvDesc{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; + dsvDesc.format = VK_FORMAT_D32_SFLOAT; + dsvDesc.viewType = VK_IMAGE_VIEW_TYPE_2D; + dsvDesc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + dsvDesc.subresourceRange.layerCount = 1; + dsvDesc.subresourceRange.levelCount = 1; + dsvDesc.image = m_pSMHairTexture; + AMD_CHECKED_VULKAN_CALL(vkCreateImageView(pvkDevice, &dsvDesc, nullptr, &m_pSMHairView)); + + VkImageMemoryBarrier defineHairSMLayoutBarrier[] = {getImageMemoryBarrier( + m_pSMHairTexture, 0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1, VK_IMAGE_ASPECT_DEPTH_BIT)}; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, + nullptr, AMD_ARRAY_SIZE(defineHairSMLayoutBarrier), + defineHairSMLayoutBarrier); + } + + // Noise texture + { + VkImageCreateInfo noiseTextureInfo = getImageCreateInfo( + VK_FORMAT_R32G32B32A32_SFLOAT, 512, 512, + VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + AMD_CHECKED_VULKAN_CALL( + vkCreateImage(pvkDevice, &noiseTextureInfo, nullptr, &m_pNoiseTexture)); + m_pNoiseMemory = allocImageMemory(pvkDevice, m_pNoiseTexture, memProperties); + + XMFLOAT4 *noiseArray = new XMFLOAT4[512 * 512]; + for (UINT i = 0; i < 512 * 512; i++) + { + noiseArray[i].x = rand() / (float)RAND_MAX; + noiseArray[i].y = rand() / (float)RAND_MAX; + noiseArray[i].z = rand() / (float)RAND_MAX; + noiseArray[i].w = rand() / (float)RAND_MAX; + } + + void *memoryPointer; + vkMapMemory(pvkDevice, scratchMemory, offsetInScratchBuffer, + 512 * 512 * sizeof(XMFLOAT4), 0, &memoryPointer); + memcpy(memoryPointer, noiseArray, 512 * 512 * sizeof(XMFLOAT4)); + vkUnmapMemory(pvkDevice, scratchMemory); + + VkImageMemoryBarrier makeNoiseTextureTransferableBarrier[] = { + getImageMemoryBarrier(m_pNoiseTexture, 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, VK_IMAGE_ASPECT_COLOR_BIT)}; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, + nullptr, AMD_ARRAY_SIZE(makeNoiseTextureTransferableBarrier), + makeNoiseTextureTransferableBarrier); + + VkBufferImageCopy copyInfo{offsetInScratchBuffer, 512, 512}; + copyInfo.imageExtent.width = 512; + copyInfo.imageExtent.height = 512; + copyInfo.imageExtent.depth = 1; + copyInfo.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyInfo.imageSubresource.layerCount = 1; + vkCmdCopyBufferToImage(commandBuffer, scratchBuffer, m_pNoiseTexture, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Info); + offsetInScratchBuffer += 512 * 512 * sizeof(XMFLOAT4); + + VkImageMemoryBarrier makeNoiseTextureSampleableBarrier[] = {getImageMemoryBarrier( + m_pNoiseTexture, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1, VK_IMAGE_ASPECT_COLOR_BIT)}; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, + nullptr, AMD_ARRAY_SIZE(makeNoiseTextureSampleableBarrier), + makeNoiseTextureSampleableBarrier); + + delete[] noiseArray; + + VkImageViewCreateInfo srDesc{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; + srDesc.format = VK_FORMAT_R32G32B32A32_SFLOAT; + srDesc.viewType = VK_IMAGE_VIEW_TYPE_2D; + srDesc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + srDesc.subresourceRange.layerCount = 1; + srDesc.subresourceRange.levelCount = 1; + srDesc.image = m_pNoiseTexture; + + AMD_CHECKED_VULKAN_CALL(vkCreateImageView(pvkDevice, &srDesc, nullptr, &m_pNoiseView)); + } + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// CreateConstantBuffers +// +// Creates the constant buffers for hair rendering +// +//-------------------------------------------------------------------------------------- +VkResult TressFXRenderer::CreateConstantBuffer(VkDevice pvkDevice, + uint32_t maxUniformBuffer, + VkPhysicalDeviceMemoryProperties memProperties) +{ + VkResult vr; + VkBufferCreateInfo cbDesc{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + cbDesc.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + cbDesc.size = maxUniformBuffer * sizeof(CB_PER_FRAME); + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &cbDesc, nullptr, &m_pcbPerFrame)); + m_pcbPerFrameMemory = allocBufferMemory(pvkDevice, m_pcbPerFrame, memProperties, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + return VK_SUCCESS; +} + +VkResult TressFXRenderer::CreateFrameBuffer(VkDevice pvkDevice, + VkImageView depthTextureView, + VkImageView colorTexture, uint32_t width, + uint32_t height) +{ + m_depthBuffer = depthTextureView; + m_colorTexture = colorTexture; + VkResult vr; + + { + VkImageView attachements[] = {m_depthBuffer, m_colorTexture}; + VkFramebufferCreateInfo info{VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO}; + info.renderPass = m_pRPHairRendering; + info.attachmentCount = AMD_ARRAY_SIZE(attachements); + info.pAttachments = attachements; + info.width = width; + info.height = height; + info.layers = 1; + AMD_CHECKED_VULKAN_CALL( + vkCreateFramebuffer(pvkDevice, &info, nullptr, &m_renderHairFramebuffer)); + } + + VkImageView attachements[1] = {m_pSMHairView}; + VkFramebufferCreateInfo info{VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO}; + info.renderPass = m_RPHairShadow; + info.attachmentCount = AMD_ARRAY_SIZE(attachements); + info.pAttachments = attachements; + info.width = SM_HAIR_WIDTH; + info.height = SM_HAIR_HEIGHT; + info.layers = 1; + AMD_CHECKED_VULKAN_CALL(vkCreateFramebuffer(pvkDevice, &info, nullptr, &m_shadowFrameBuffer)); + return VK_SUCCESS; +} + +VkResult TressFXRenderer::CreateSamplers(VkDevice pvkDevice) +{ + VkResult vr; + + // Create sampler state objects + VkSamplerCreateInfo samDesc{VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; + samDesc.minFilter = VK_FILTER_LINEAR; + samDesc.magFilter = VK_FILTER_LINEAR; + samDesc.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samDesc.addressModeU = samDesc.addressModeV = samDesc.addressModeW = + VK_SAMPLER_ADDRESS_MODE_REPEAT; + samDesc.maxAnisotropy = 16.f; + samDesc.compareOp = VK_COMPARE_OP_NEVER; + samDesc.minLod = 0.f; + samDesc.maxLod = 1000.f; + AMD_CHECKED_VULKAN_CALL( + vkCreateSampler(pvkDevice, &samDesc, nullptr, &m_pSamplerStateLinearWrap)); + + samDesc.minFilter = VK_FILTER_NEAREST; + samDesc.magFilter = VK_FILTER_NEAREST; + samDesc.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + AMD_CHECKED_VULKAN_CALL( + vkCreateSampler(pvkDevice, &samDesc, nullptr, &m_pSamplerStatePointClamp)); + + samDesc.minFilter = VK_FILTER_LINEAR; + samDesc.magFilter = VK_FILTER_LINEAR; + samDesc.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samDesc.compareEnable = true, samDesc.compareOp = VK_COMPARE_OP_LESS; + samDesc.borderColor = VK_BORDER_COLOR_INT_OPAQUE_WHITE; + samDesc.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samDesc.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + samDesc.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + AMD_CHECKED_VULKAN_CALL(vkCreateSampler(pvkDevice, &samDesc, nullptr, &m_pSamplerStateCmpLess)); + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// CreateRenderStateObjects +// +// Creates the render state objects for hair rendering +// +//-------------------------------------------------------------------------------------- +VkResult TressFXRenderer::CreateRenderStateObjects(VkDevice pvkDevice, VkFormat depthStencilFormat, VkFormat colorFormat) +{ + VkResult vr; + + m_pRPHairRendering = CreateRenderPass(pvkDevice, depthStencilFormat, colorFormat); + ShaderModule fragmentShadersModule(pvkDevice, pass1_fragment); + + ShaderModule vertexShadersModule(pvkDevice, render_hair_aa_strand_copies_vertex); + VkPipelineShaderStageCreateInfo renderHairAAStrandCopiesStage[2] = { + getShaderStageCreateInfo(vertexShadersModule.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(fragmentShadersModule.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + VkGraphicsPipelineCreateInfo renderHairAAStrandCopiesDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::ColorWritesOff, + &CommonPipelineState::inputAssemblyTriangle, renderHairAAStrandCopiesStage, + m_pass1_layout, m_pRPHairRendering, 0); + + ShaderModule RenderHairAAVertexShader(pvkDevice, render_hair_aa_vertex); + VkPipelineShaderStageCreateInfo renderHairAAStage[2] = { + getShaderStageCreateInfo(RenderHairAAVertexShader.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(fragmentShadersModule.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + VkGraphicsPipelineCreateInfo renderHairAADesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::ColorWritesOff, + &CommonPipelineState::inputAssemblyTriangle, renderHairAAStage, + m_pass1_layout, m_pRPHairRendering, 0); + + ShaderModule renderHairStrandCopiesVertexModule(pvkDevice, + render_hair_strand_copies_vertex); + VkPipelineShaderStageCreateInfo renderHairStrandCopiesStage[2] = { + getShaderStageCreateInfo(renderHairStrandCopiesVertexModule.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(fragmentShadersModule.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + VkGraphicsPipelineCreateInfo renderHairStrandCopiesDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::ColorWritesOff, + &CommonPipelineState::inputAssemblyTriangle, renderHairStrandCopiesStage, + m_pass1_layout, m_pRPHairRendering, 0); + + ShaderModule renderHairVertexModule(pvkDevice, render_hair_vertex); + VkPipelineShaderStageCreateInfo renderHairStage[2] = { + getShaderStageCreateInfo(renderHairVertexModule.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(fragmentShadersModule.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + VkGraphicsPipelineCreateInfo renderHairDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::ColorWritesOff, + &CommonPipelineState::inputAssemblyTriangle, renderHairStage, m_pass1_layout, + m_pRPHairRendering, 0); + + ShaderModule pass2VSModule(pvkDevice, pass2_vertex); + ShaderModule pass2FSModule(pvkDevice, pass2_fragment); + VkPipelineShaderStageCreateInfo renderKBufferStage[2] = { + getShaderStageCreateInfo(pass2VSModule.m_shaderModule, VK_SHADER_STAGE_VERTEX_BIT, + "main"), + getShaderStageCreateInfo(pass2FSModule.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + VkGraphicsPipelineCreateInfo renderKBufferDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutQuad, + &CommonPipelineState::DepthTestDisabledStencilTestLessDSS, + &CommonPipelineState::BlendStateBlendToBg, + &CommonPipelineState::inputAssemblyTriangle, renderKBufferStage, + m_pass2_layout, m_pRPHairRendering, 1); + + m_RPHairShadow = CreateShadowRenderPass(pvkDevice); + + ShaderModule shadowVSModule(pvkDevice, hair_shadow_vertex); + ShaderModule shadowFSModule(pvkDevice, hair_shadow_fragment); + VkPipelineShaderStageCreateInfo renderHairShadow[2] = { + getShaderStageCreateInfo(shadowVSModule.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(shadowFSModule.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + VkGraphicsPipelineCreateInfo renderHairShadowDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, + &CommonPipelineState::DepthTestEnabledDesc, + &CommonPipelineState::ColorWritesOff, &CommonPipelineState::inputAssemblyLine, + renderHairShadow, m_shadow_pass_layout, m_RPHairShadow, 0); + + VkGraphicsPipelineCreateInfo pipelineInfoArray[] = {renderHairAAStrandCopiesDesc, + renderHairAADesc, + renderHairStrandCopiesDesc, + renderHairDesc, + renderKBufferDesc, + renderHairShadowDesc}; + + VkPipeline pipelineArray[6] = {}; + + AMD_CHECKED_VULKAN_CALL(vkCreateGraphicsPipelines(pvkDevice, VK_NULL_HANDLE, + AMD_ARRAY_SIZE(pipelineInfoArray), + pipelineInfoArray, nullptr, pipelineArray)); + + m_pPLRenderHairAAStrandCopies = pipelineArray[0]; + m_pPLRenderHairAA = pipelineArray[1]; + m_pPLRenderHairStrandCopies = pipelineArray[2]; + m_pPLRenderHair = pipelineArray[3]; + m_pPLResolveKBuffer = pipelineArray[4]; + m_pPLGenerateHairSM = pipelineArray[5]; + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// OnCreateDevice +// +// Called when the device is created to create resources for hair rendering +// +//-------------------------------------------------------------------------------------- +VkResult TressFXRenderer::OnCreateDevice( + VkDevice pvkDevice, int winWidth, int winHeight, bool bShortCutOn, + uint32_t maxUniformBuffer, VkPhysicalDeviceMemoryProperties memProperties, + VkImageView depthTexture, VkImageView colorTexture, VkCommandBuffer commandBuffer, + VkDeviceMemory scratchMemory, VkBuffer scratchBuffer, size_t &offsetInScratchBuffer, + VkFormat depthStencilFormat, VkFormat colorFormat) +{ + m_pvkDevice = pvkDevice; + VkResult vr; + + AMD_CHECKED_VULKAN_CALL(CreateTextureAndViews(pvkDevice, memProperties, commandBuffer, + scratchMemory, scratchBuffer, + offsetInScratchBuffer)); + AMD_CHECKED_VULKAN_CALL(CreateConstantBuffer(pvkDevice, maxUniformBuffer, memProperties)); + AMD_CHECKED_VULKAN_CALL(CreateSamplers(pvkDevice)); + AMD_CHECKED_VULKAN_CALL(CreateLayouts(pvkDevice)); + if (!bShortCutOn) + { + AMD_CHECKED_VULKAN_CALL( + CreatePPLL(pvkDevice, winWidth, winHeight, false, memProperties)); + VkImageMemoryBarrier defineHeadPPLLBarrier[] = {getImageMemoryBarrier( + m_pHeadPPLLTexture, 0, VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 1, VK_IMAGE_ASPECT_COLOR_BIT)}; + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, + nullptr, AMD_ARRAY_SIZE(defineHeadPPLLBarrier), + defineHeadPPLLBarrier); + } + else + { + m_ShortCut.OnCreateDevice(pvkDevice, winWidth, winHeight, m_pass1_hair_set_layout, + m_pSamplerStateLinearWrap, m_pSamplerStatePointClamp, + depthTexture, colorTexture, m_pcbPerFrame, + sizeof(CB_PER_FRAME), m_pNoiseView, m_pSMHairView, + memProperties, winWidth, winHeight, depthStencilFormat, colorFormat); + + VkImageMemoryBarrier barriers[] = { + getImageMemoryBarrier(m_ShortCut.m_pAccumInvAlphaTexture, 0, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1, VK_IMAGE_ASPECT_COLOR_BIT), + getImageMemoryBarrier(m_ShortCut.m_pFragmentDepthsTexture, 0, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, + SHORTCUT_NUM_DEPTHS, VK_IMAGE_ASPECT_COLOR_BIT), + getImageMemoryBarrier(m_ShortCut.m_pFragmentColorsTexture, 0, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1, VK_IMAGE_ASPECT_COLOR_BIT)}; + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, + nullptr, AMD_ARRAY_SIZE(barriers), barriers); + } + + AMD_CHECKED_VULKAN_CALL(CreateRenderStateObjects(pvkDevice, depthStencilFormat, colorFormat)); + AMD_CHECKED_VULKAN_CALL(AllocateAndPopulateSets(pvkDevice, bShortCutOn)); + AMD_CHECKED_VULKAN_CALL( + CreateFrameBuffer(pvkDevice, depthTexture, colorTexture, winWidth, winHeight)); + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// CreateRenderStateObjects +// +// Creates the pipelines for hair rendering +// +//-------------------------------------------------------------------------------------- +VkResult TressFXRenderer::CreateLayouts(VkDevice pvkDevice) +{ + VkResult vr; + + // First pass model dependent set layout + { + const VkDescriptorSetLayoutBinding pass1_hair_bindings[] = { + // Hair Pos + {IDSRV_HAIR_VERTEX_POSITIONS, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_VERTEX_BIT}, + // Hair Tangent + {IDSRV_HAIR_TANGENTS, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_VERTEX_BIT}, + // Hair Thickness + {IDSRV_HAIR_THICKNESSES, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_VERTEX_BIT}, + }; + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, pass1_hair_bindings, + AMD_ARRAY_SIZE(pass1_hair_bindings), + m_pass1_hair_set_layout)); + } + + // First pass non model dependent set layout + { + VkDescriptorSetLayoutBinding pass1_config_bindings[] = { + // TressFX parameters + {IDSRV_CONSTANTS_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, + VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT}, + // Atomic counter + {IDSRV_ATOMIC_COUNTER_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, + // PPLL Head + {IDSRV_HEAD_PPLL, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, + // PPLL List + {IDSRV_PPLL, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, + // Sampler for noise texture in VS + {IDSRV_NOISE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER, 1, + VK_SHADER_STAGE_VERTEX_BIT, &m_pSamplerStateLinearWrap}, + // Noise texture + {IDSRV_NOISEMAP, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, + VK_SHADER_STAGE_VERTEX_BIT}, + }; + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, pass1_config_bindings, + AMD_ARRAY_SIZE(pass1_config_bindings), + m_pass1_config_set_layout)); + } + + VkDescriptorSetLayout pass1_descriptor_set_layouts[] = {m_pass1_config_set_layout, + m_pass1_hair_set_layout}; + VkPipelineLayoutCreateInfo pipelineLayoutInfo{ + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0, + AMD_ARRAY_SIZE(pass1_descriptor_set_layouts), pass1_descriptor_set_layouts}; + AMD_CHECKED_VULKAN_CALL( + vkCreatePipelineLayout(pvkDevice, &pipelineLayoutInfo, nullptr, &m_pass1_layout)); + + // Pass 2 set layout + { + VkDescriptorSetLayoutBinding pass2_bindings[] = { + // TressFX parameters + {IDSRV_CONSTANTS_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, + VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT}, + // PPLL Head + {IDSRV_HEAD_PPLL, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, + // PPLL List + {IDSRV_PPLL, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, + // Shadow texture + {IDSRV_HAIRSM, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, + // Sampler for hair shadow texture + {IDSRV_SHADOW_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER, 1, + VK_SHADER_STAGE_FRAGMENT_BIT, &m_pSamplerStatePointClamp}, + }; + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, pass2_bindings, + AMD_ARRAY_SIZE(pass2_bindings), + m_pass2_set_layout)); + } + + VkPipelineLayoutCreateInfo pass2PipelineLayoutInfo{ + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0, 1, + &m_pass2_set_layout}; + AMD_CHECKED_VULKAN_CALL(vkCreatePipelineLayout(pvkDevice, &pass2PipelineLayoutInfo, nullptr, + &m_pass2_layout)); + + // Shadow pass model dependent set layout + { + VkDescriptorSetLayoutBinding shadow_pass_hair_bindings[] = { + // TressFX parameters + {IDSRV_HAIR_VERTEX_POSITIONS, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_VERTEX_BIT}, + }; + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, shadow_pass_hair_bindings, + AMD_ARRAY_SIZE(shadow_pass_hair_bindings), + m_shadow_pass_hair_set_layout)); + } + + // Shadow pass non model dependent set layout + { + VkDescriptorSetLayoutBinding shadow_pass_config_bindings[] = { + // TressFX parameters + {IDSRV_CONSTANTS_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, + VK_SHADER_STAGE_VERTEX_BIT}}; + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, shadow_pass_config_bindings, + AMD_ARRAY_SIZE(shadow_pass_config_bindings), + m_shadow_pass_config_set_layout)); + } + + VkDescriptorSetLayout shadow_pass_descriptor_set_layouts[] = { + m_shadow_pass_config_set_layout, m_shadow_pass_hair_set_layout}; + VkPipelineLayoutCreateInfo shadowPassPipelineLayoutInfo{ + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0, + AMD_ARRAY_SIZE(shadow_pass_descriptor_set_layouts), + shadow_pass_descriptor_set_layouts}; + AMD_CHECKED_VULKAN_CALL(vkCreatePipelineLayout(pvkDevice, &shadowPassPipelineLayoutInfo, nullptr, + &m_shadow_pass_layout)); + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// AllocateAndPopulateSets +// +// Allocate descriptor set and fills them +// +//-------------------------------------------------------------------------------------- +VkResult TressFXRenderer::AllocateAndPopulateSets(VkDevice pvkDevice, bool isShortcut) +{ + VkResult vr; + const VkDescriptorPoolSize descriptorPoolSize[] = { + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 3}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 3}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2}, + {VK_DESCRIPTOR_TYPE_SAMPLER, 3}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 2}}; + + VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{ + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO}; + descriptorPoolCreateInfo.maxSets = 3; + descriptorPoolCreateInfo.poolSizeCount = AMD_ARRAY_SIZE(descriptorPoolSize); + descriptorPoolCreateInfo.pPoolSizes = descriptorPoolSize; + AMD_CHECKED_VULKAN_CALL(vkCreateDescriptorPool(pvkDevice, &descriptorPoolCreateInfo, nullptr, + &m_descriptorStorage)); + + VkDescriptorBufferInfo bufferDescriptor{m_pcbPerFrame, 0, sizeof(CB_PER_FRAME)}; + VkDescriptorSetAllocateInfo allocateInfo{ + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO}; + allocateInfo.descriptorPool = m_descriptorStorage; + allocateInfo.descriptorSetCount = 1; + allocateInfo.pSetLayouts = &m_shadow_pass_config_set_layout; + AMD_CHECKED_VULKAN_CALL( + vkAllocateDescriptorSets(pvkDevice, &allocateInfo, &m_shadow_pass_set)); + if (!isShortcut) + { + allocateInfo.descriptorSetCount = 1; + allocateInfo.pSetLayouts = &m_pass1_config_set_layout; + AMD_CHECKED_VULKAN_CALL( + vkAllocateDescriptorSets(pvkDevice, &allocateInfo, &m_pass1_config_set)); + + allocateInfo.descriptorSetCount = 1; + allocateInfo.pSetLayouts = &m_pass2_set_layout; + AMD_CHECKED_VULKAN_CALL(vkAllocateDescriptorSets(pvkDevice, &allocateInfo, &m_pass2_set)); + + VkDescriptorBufferInfo atomicCounterDescriptor{m_pAtomicCounterPPLLBuffer, 0, + sizeof(unsigned int)}; + VkDescriptorBufferInfo PPLL_Buffer_Descriptor{ + m_pPPLLBuffer, 0, + g_HairTotalLayers * 1024 * 1024 * sizeof(PER_PIXEL_LINKED_LIST_STRUCT)}; + VkDescriptorImageInfo headPLLDescriptor{VK_NULL_HANDLE, m_pHeadPPLLView, + VK_IMAGE_LAYOUT_GENERAL}; + VkDescriptorImageInfo noiseDescriptor{VK_NULL_HANDLE, m_pNoiseView, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; + VkDescriptorImageInfo shadowDescriptor{VK_NULL_HANDLE, m_pSMHairView, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; + + VkWriteDescriptorSet writeDescriptorSets[] = { + getWriteDescriptor(m_pass1_config_set, IDSRV_CONSTANTS_BUFFER, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + &bufferDescriptor), + getWriteDescriptor(m_pass1_config_set, IDSRV_ATOMIC_COUNTER_BUFFER, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + &atomicCounterDescriptor), + getWriteDescriptor(m_pass1_config_set, IDSRV_HEAD_PPLL, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &headPLLDescriptor), + getWriteDescriptor(m_pass1_config_set, IDSRV_PPLL, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + &PPLL_Buffer_Descriptor), + getWriteDescriptor(m_pass1_config_set, IDSRV_NOISEMAP, + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &noiseDescriptor), + getWriteDescriptor(m_pass2_set, IDSRV_CONSTANTS_BUFFER, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + &bufferDescriptor), + getWriteDescriptor(m_pass2_set, IDSRV_HEAD_PPLL, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &headPLLDescriptor), + getWriteDescriptor(m_pass2_set, IDSRV_PPLL, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + &PPLL_Buffer_Descriptor), + getWriteDescriptor(m_pass2_set, IDSRV_HAIRSM, + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &shadowDescriptor), + getWriteDescriptor(m_shadow_pass_set, IDSRV_CONSTANTS_BUFFER, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + &bufferDescriptor), + }; + + vkUpdateDescriptorSets(pvkDevice, AMD_ARRAY_SIZE(writeDescriptorSets), + writeDescriptorSets, 0, nullptr); + } + else + { + VkWriteDescriptorSet writeDescriptorSets[] = { + getWriteDescriptor(m_shadow_pass_set, IDSRV_CONSTANTS_BUFFER, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + &bufferDescriptor), + }; + + vkUpdateDescriptorSets(pvkDevice, AMD_ARRAY_SIZE(writeDescriptorSets), + writeDescriptorSets, 0, nullptr); + } + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// CreatePPLL +// +// Creates the per pixel linked list buffers and views. To save space, the PPLL is +// shared between multiple TressFXRenderer objects. The ref count gets incremented +// when the PPLL is shared with a new TressFXRenderer object. +// +//-------------------------------------------------------------------------------------- +VkResult TressFXRenderer::CreatePPLL(VkDevice pvkDevice, int winWidth, int winHeight, + bool resize, VkPhysicalDeviceMemoryProperties memProperties) +{ + VkResult vr; + + // see if the buffer needs to be resized or if refCount is 0 + if ((winWidth != g_PPLBuffers.width) || (winHeight != g_PPLBuffers.height) || + (g_PPLBuffers.refCount == 0)) + { + // linked list head texture + VkImageCreateInfo headPPLLInfo = + getImageCreateInfo(VK_FORMAT_R32_UINT, winWidth, winHeight, + VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + AMD_CHECKED_VULKAN_CALL(vkCreateImage(pvkDevice, &headPPLLInfo, nullptr, + &g_PPLBuffers.pHeadPPLL_Buffer)); + + // Per-pixel Linked List (PPLL) buffer + VkBufferCreateInfo BufferDesc{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + BufferDesc.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + BufferDesc.size = (DWORD)(g_HairTotalLayers * winWidth * winHeight * + sizeof(PER_PIXEL_LINKED_LIST_STRUCT)); + AMD_CHECKED_VULKAN_CALL( + vkCreateBuffer(pvkDevice, &BufferDesc, nullptr, &g_PPLBuffers.pPPLL_Buffer)); + + // Atomic counter buffer + BufferDesc.usage = + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + BufferDesc.size = sizeof(unsigned int); + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &BufferDesc, nullptr, + &g_PPLBuffers.pAtomicCounterPLL_Buffer)); + + VkMemoryRequirements headPPLLMemReq; + vkGetImageMemoryRequirements(pvkDevice, g_PPLBuffers.pHeadPPLL_Buffer, &headPPLLMemReq); + VkMemoryRequirements PPLBufferMemReq; + vkGetBufferMemoryRequirements(pvkDevice, g_PPLBuffers.pPPLL_Buffer, &PPLBufferMemReq); + VkMemoryRequirements atomicBufferMemReq; + vkGetBufferMemoryRequirements(pvkDevice, g_PPLBuffers.pAtomicCounterPLL_Buffer, &atomicBufferMemReq); + + uint32_t typeBits = headPPLLMemReq.memoryTypeBits & PPLBufferMemReq.memoryTypeBits & atomicBufferMemReq.memoryTypeBits; + uint32_t memoryType = getMemoryTypeIndex(typeBits, memProperties, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + if (memoryType == -1) + { + // Split in 3 + g_PPLBuffers.pHeadPPLL_Memory = allocImageMemory( + pvkDevice, g_PPLBuffers.pHeadPPLL_Buffer, memProperties); + + g_PPLBuffers.pPPLL_Memory = + allocBufferMemory(pvkDevice, g_PPLBuffers.pPPLL_Buffer, memProperties, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + g_PPLBuffers.pAtomicCounterPLL_Memory = allocBufferMemory( + pvkDevice, g_PPLBuffers.pAtomicCounterPLL_Buffer, memProperties, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + else + { + VkDeviceSize PPLBufferOffset = align(headPPLLMemReq.size, PPLBufferMemReq.alignment); + VkDeviceSize atomicBufferOffset = align(PPLBufferOffset + PPLBufferMemReq.size, atomicBufferMemReq.alignment); + VkDeviceSize totalSize = atomicBufferOffset + atomicBufferMemReq.size; + + VkMemoryAllocateInfo allocate{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + allocate.allocationSize = totalSize; + allocate.memoryTypeIndex = memoryType; + AMD_CHECKED_VULKAN_CALL(vkAllocateMemory(pvkDevice, &allocate, NULL, &g_PPLBuffers.pSharedMemory)); + + AMD_CHECKED_VULKAN_CALL(vkBindImageMemory(pvkDevice, g_PPLBuffers.pHeadPPLL_Buffer, g_PPLBuffers.pSharedMemory, 0)); + AMD_CHECKED_VULKAN_CALL(vkBindBufferMemory(pvkDevice, g_PPLBuffers.pPPLL_Buffer, g_PPLBuffers.pSharedMemory, PPLBufferOffset)); + AMD_CHECKED_VULKAN_CALL(vkBindBufferMemory(pvkDevice, g_PPLBuffers.pAtomicCounterPLL_Buffer, g_PPLBuffers.pSharedMemory, atomicBufferOffset)); + } + + + // View for linked list head + VkImageViewCreateInfo srDesc{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; + srDesc.format = VK_FORMAT_R32_UINT; + srDesc.viewType = VK_IMAGE_VIEW_TYPE_2D; + srDesc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + srDesc.subresourceRange.layerCount = 1; + srDesc.subresourceRange.levelCount = 1; + srDesc.image = g_PPLBuffers.pHeadPPLL_Buffer; + AMD_CHECKED_VULKAN_CALL( + vkCreateImageView(pvkDevice, &srDesc, nullptr, &g_PPLBuffers.pHeadPPLL_View)); + + + + // update the width and height + g_PPLBuffers.width = winWidth; + g_PPLBuffers.height = winHeight; + + // if the refCount is non-zero, then we're just resizing the buffers + if (g_PPLBuffers.refCount == 0) + { + g_PPLBuffers.refCount++; + } + } + else + { + if (!resize) + { + g_PPLBuffers.refCount++; + } + } + + m_pHeadPPLLTexture = g_PPLBuffers.pHeadPPLL_Buffer; + m_pHeadPPLLView = g_PPLBuffers.pHeadPPLL_View; + m_pPPLLBuffer = g_PPLBuffers.pPPLL_Buffer; + m_pAtomicCounterPPLLBuffer = g_PPLBuffers.pAtomicCounterPLL_Buffer; + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// DeletePPLL +// +// Deletes the PPLL buffers when the refCount goes to 0 +// +//-------------------------------------------------------------------------------------- +void TressFXRenderer::DeletePPLL(VkDevice pvkDevice) +{ + if (g_PPLBuffers.refCount == 0) + { + return; + } + + g_PPLBuffers.refCount--; + + m_pHeadPPLLTexture = NULL; + m_pHeadPPLLView = NULL; + m_pPPLLBuffer = NULL; + + if (g_PPLBuffers.refCount == 0) + { + AMD_SAFE_RELEASE(g_PPLBuffers.pHeadPPLL_View, vkDestroyImageView, pvkDevice); + AMD_SAFE_RELEASE(g_PPLBuffers.pHeadPPLL_Buffer, vkDestroyImage, pvkDevice); + AMD_SAFE_RELEASE(g_PPLBuffers.pHeadPPLL_Memory, vkFreeMemory, pvkDevice); + AMD_SAFE_RELEASE(g_PPLBuffers.pPPLL_Buffer, vkDestroyBuffer, pvkDevice); + AMD_SAFE_RELEASE(g_PPLBuffers.pPPLL_Memory, vkFreeMemory, pvkDevice); + AMD_SAFE_RELEASE(g_PPLBuffers.pAtomicCounterPLL_Buffer, vkDestroyBuffer, + pvkDevice); + AMD_SAFE_RELEASE(g_PPLBuffers.pAtomicCounterPLL_Memory, vkFreeMemory, pvkDevice); + AMD_SAFE_RELEASE(g_PPLBuffers.pSharedMemory, vkFreeMemory, pvkDevice); + + g_PPLBuffers.width = 0; + g_PPLBuffers.height = 0; + } +} + +//-------------------------------------------------------------------------------------- +// +// OnResizedSwapChain +// +// Called when the swap chain is being resized. Allocate resources that need to be +// created at this time because they are dependent on the size of the frame buffer. +// +//-------------------------------------------------------------------------------------- +VkResult TressFXRenderer::OnResizedSwapChain(VkDevice pvkDevice, int width, int height, + bool bShortCutOn, + VkPhysicalDeviceMemoryProperties memProperties) +{ + VkResult vr; + if (bShortCutOn) + { + // AMD_CHECKED_VULKAN_CALL(m_ShortCut.OnResizedSwapChain(pd3dDevice, width, height)); + } + else + { + AMD_CHECKED_VULKAN_CALL(CreatePPLL(pvkDevice, width, height, true, memProperties)); + } + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// BeginHairFrame +// +// Start of hair rendering. +// +//-------------------------------------------------------------------------------------- +void TressFXRenderer::BeginHairFrame( + VkDevice pvkDevice, DirectX::XMVECTOR eyePoint, DirectX::XMVECTOR lightPosition, + DirectX::XMMATRIX *pModelTransformForHead, DirectX::XMMATRIX *pViewProj, + DirectX::XMMATRIX *pViewProjLightOut, float screenWidth, float screenHeight, + bool singleHeadTransform, uint32_t uniformBufferIndex) +{ + // Set up camera parameters for when the camera is at the position of the light for + // rendering the shadow map + XMMATRIX mViewLight, mProjLight; + XMVECTOR modelCenter = XMVector3TransformCoord( + XMLoadFloat3(&m_pTressFXMesh->m_HairAsset.m_bSphere.center), + *pModelTransformForHead); + XMVECTOR vLightAt = modelCenter; + XMVECTOR vUp = XMVectorSet(0, 1, 0, 0); + mViewLight = XMMatrixLookAtLH(lightPosition, vLightAt, vUp); + + XMVECTOR vLightToObject = XMVectorSubtract(lightPosition, modelCenter); + float dis = XMVectorGetX(XMVector3Length(vLightToObject)); + + float min_dis = max(0.001f, dis - m_pTressFXMesh->m_HairAsset.m_bSphere.radius); + float max_dis = dis + m_pTressFXMesh->m_HairAsset.m_bSphere.radius; + + float halfAngle = 1.5f * asin(m_pTressFXMesh->m_HairAsset.m_bSphere.radius / dis); + float FOV = 2 * halfAngle; + + float ratio = 1; + + mProjLight = XMMatrixPerspectiveFovLH(FOV, ratio, min_dis, max_dis); + *pViewProjLightOut = mViewLight * mProjLight; + + // Map the per-frame constant buffer + CB_PER_FRAME *pcbPerFrame; + vkMapMemory(pvkDevice, m_pcbPerFrameMemory, uniformBufferIndex * sizeof(CB_PER_FRAME), + sizeof(CB_PER_FRAME), 0, reinterpret_cast(&pcbPerFrame)); + + // camera parameters + XMMATRIX mViewProj = *pViewProj; + XMMATRIX mInvViewProj = XMMatrixInverse(0, mViewProj); + + float fRenderWidth = screenWidth; + float fRenderHeight = screenHeight; + + // Inverse of viewprojection matrix with viewport mapping + XMMATRIX mViewport(2.0f / fRenderWidth, 0.0f, 0.0f, 0.0f, 0.0f, -2.0f / fRenderHeight, + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f); + + XMMATRIX mInvViewProjViewport = mInvViewProj; + + pcbPerFrame->m_mViewProj = XMMatrixTranspose(mViewProj); + pcbPerFrame->m_mInvViewProj = XMMatrixTranspose(mInvViewProj); + + pcbPerFrame->m_mInvViewProjViewport = XMMatrixTranspose(mInvViewProjViewport); + + pcbPerFrame->m_mWorld = XMMatrixTranspose(*pModelTransformForHead); + + XMStoreFloat3(&pcbPerFrame->m_vEye, eyePoint); + + pcbPerFrame->m_fvFOV = XM_PI / 4; + + // Light camera parameters + pcbPerFrame->m_mViewProjLight = *pViewProjLightOut; + pcbPerFrame->m_fNearLight = min_dis; + pcbPerFrame->m_fFarLight = max_dis; + + XMStoreFloat4(&pcbPerFrame->m_PointLightPos, lightPosition); + pcbPerFrame->m_PointLightPos.w = 1; + + // scene light color + pcbPerFrame->m_AmbientLightColor = m_hairParams.ambientLightColor; + pcbPerFrame->m_PointLightColor = m_hairParams.pointLightColor; + + // hair material + pcbPerFrame->m_MatBaseColor = + XMFLOAT4(m_hairParams.color.x, m_hairParams.color.y, m_hairParams.color.z, 1); + pcbPerFrame->m_MatKValue = + XMFLOAT4(m_hairParams.Ka, m_hairParams.Kd, m_hairParams.Ks1, m_hairParams.Ex1); + pcbPerFrame->m_fHairKs2 = m_hairParams.Ks2; + pcbPerFrame->m_fHairEx2 = m_hairParams.Ex2; + + pcbPerFrame->m_FiberAlpha = m_hairParams.alpha; + pcbPerFrame->m_HairSMAlpha = m_hairParams.shadowMapAlpha; + + pcbPerFrame->m_FiberRadius = m_hairParams.thickness; + + pcbPerFrame->m_FiberSpacing = m_hairParams.duplicateStrandSpacing; + + pcbPerFrame->m_bThinTip = (m_hairParams.bThinTip ? 1.f : -1.f); + pcbPerFrame->m_bExpandPixels = 1; + + pcbPerFrame->m_WinSize = + XMFLOAT4((float)screenWidth, (float)screenHeight, 1.0f / (float)screenWidth, + 1.0f / (float)screenHeight); + + pcbPerFrame->m_iMaxFragments = m_hairParams.maxFragments; + + pcbPerFrame->m_alphaThreshold = m_hairParams.alphaThreshold; + + pcbPerFrame->m_iTechSM = m_hairParams.shadowTechnique; + pcbPerFrame->m_bUseCoverage = m_hairParams.bAntialias ? 1 : 0; + pcbPerFrame->m_iStrandCopies = m_hairParams.strandCopies; + + pcbPerFrame->m_mNumVerticesPerStrand = g_TressFXNumVerticesPerStrand; + pcbPerFrame->m_mNumFollowHairsPerGuideHair = + m_pTressFXMesh->m_HairAsset.m_NumFollowHairsPerGuideHair; + pcbPerFrame->m_bSingleHeadTransform = singleHeadTransform; + + unsigned optionalSRVs = 0; + if ((m_pTressFXMesh->m_pStrandTexCoordView) && (m_pTressFXMesh->m_pHairTextureSRV)) + { + optionalSRVs |= PER_STRAND_TEX_COORDS; + // ignore the material base color when getting hair color from the texture + pcbPerFrame->m_MatBaseColor = XMFLOAT4(1, 1, 1, 1); + } + pcbPerFrame->m_optionalSRVs = optionalSRVs; + + vkUnmapMemory(pvkDevice, m_pcbPerFrameMemory); +} + +//-------------------------------------------------------------------------------------- +// +// RenderScreenQuad +// +// Renders a triangle big enough to cover whole screen +// +////-------------------------------------------------------------------------------------- +void TressFXRenderer::RenderScreenQuad(VkCommandBuffer cmdbuffer, VkPipeline pPipeline) +{ + // set shader + vkCmdBindPipeline(cmdbuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pPipeline); + + // Draw full screen triangle + vkCmdDraw(cmdbuffer, 3, 1, 0, 0); +} + +//-------------------------------------------------------------------------------------- +// +// GenerateShadowMap +// +// Renders the hair from the point of view of the light into a shadow map +// +//-------------------------------------------------------------------------------------- +void TressFXRenderer::GenerateShadowMap(VkDevice pvkDevice, + VkCommandBuffer commandBuffer, + float density, uint32_t uniformBufferIndex, + const DebugMarkerPointer& markerCallbacks) +{ + VkViewport viewport{0.f, 0.f, SM_HAIR_WIDTH, SM_HAIR_HEIGHT, 0.f, 1.f}; + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + VkRect2D scissor{0, 0, SM_HAIR_WIDTH, SM_HAIR_HEIGHT}; + vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + // clear depth for early z + VkRenderPassBeginInfo info{VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO}; + info.renderPass = m_RPHairShadow; + info.framebuffer = m_shadowFrameBuffer; + info.clearValueCount = 1; + VkClearValue depthClear{}; + depthClear.depthStencil.depth = 1.f; + info.pClearValues = &depthClear; + info.renderArea.extent = {SM_HAIR_WIDTH, SM_HAIR_HEIGHT}; + markerCallbacks.markBeginRegion(commandBuffer, "Shadowmap"); + vkCmdBeginRenderPass(commandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_pPLGenerateHairSM); + VkDescriptorSet sets[] = {m_shadow_pass_set, m_pTressFXMesh->m_shadow_pass_set}; + uint32_t descriptorOffsets[] = {uniformBufferIndex * sizeof(CB_PER_FRAME)}; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_shadow_pass_layout, 0, AMD_ARRAY_SIZE(sets), sets, + AMD_ARRAY_SIZE(descriptorOffsets), descriptorOffsets); + vkCmdBindIndexBuffer(commandBuffer, m_pTressFXMesh->m_pIndexBuffer, 0, + VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(commandBuffer, UINT(density * m_pTressFXMesh->m_TotalIndexCount), 1, + 0, 0, 0); + vkCmdEndRenderPass(commandBuffer); + markerCallbacks.markEndRegion(commandBuffer); +} + +//-------------------------------------------------------------------------------------- +// +// RenderHair +// +// Renders the hair in two passes. The first pass fills an A-buffer by rendering the +// hair geometry into a per-pixel linked list which keeps all of the overlapping +// fragments. +// The second pass renders a full screen quad (using a stencil mask set in the first pass +// to avoid unnecessary pixels) which reads fragments from the per-pixel linked list +// and blends the nearest k fragments (K-buffer) in back to front order. +// +////-------------------------------------------------------------------------------------- +void TressFXRenderer::RenderHair(VkDevice pvkDevice, + VkCommandBuffer commandBuffer, + uint32_t width, + uint32_t height, + uint32_t uniformBufferIndex, const DebugMarkerPointer& markerCallbacks) +{ + // Caller must rebind original render target and depth stencil view after call + + // render hair + markerCallbacks.markBeginRegion(commandBuffer, "RenderHair"); + + // Clear HeadPPLL buffer as it's not an attachment + VkClearColorValue dwClearDataMinusOne{}; + dwClearDataMinusOne.uint32[0] = 0xFFFFFFFF; + VkImageSubresourceRange range{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + vkCmdClearColorImage(commandBuffer, m_pHeadPPLLTexture, VK_IMAGE_LAYOUT_GENERAL, + &dwClearDataMinusOne, 1, &range); + vkCmdFillBuffer(commandBuffer, m_pAtomicCounterPPLLBuffer, 0, sizeof(unsigned int), + 0); + + VkBufferMemoryBarrier flushAtomicCounterBarrier[] = { + getBufferBarrier(m_pAtomicCounterPPLLBuffer, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT)}; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(flushAtomicCounterBarrier), + flushAtomicCounterBarrier, 0, nullptr); + + uint32_t descriptorOffsets[] = {uniformBufferIndex * sizeof(CB_PER_FRAME)}; + + { + VkClearValue clearStencil{}; + clearStencil.depthStencil.stencil = 0; + VkRenderPassBeginInfo renderPassBeginInfo{ + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO}; + renderPassBeginInfo.renderPass = m_pRPHairRendering; + renderPassBeginInfo.framebuffer = m_renderHairFramebuffer; + renderPassBeginInfo.renderArea.extent.width = width; + renderPassBeginInfo.renderArea.extent.height = height; + renderPassBeginInfo.clearValueCount = 1; + renderPassBeginInfo.pClearValues = &clearStencil; + vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, + VK_SUBPASS_CONTENTS_INLINE); + } + + // Pass 1: A-Buffer pass + if (m_hairParams.bAntialias) + { + if (m_hairParams.strandCopies > 1) + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_pPLRenderHairAAStrandCopies); + } + else + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_pPLRenderHairAA); + } + } + else + { + if (m_hairParams.strandCopies > 1) + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_pPLRenderHairStrandCopies); + } + else + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_pPLRenderHair); + } + } + VkDescriptorSet descriptorSets[] = {m_pass1_config_set, m_pTressFXMesh->m_pass1_set}; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_pass1_layout, 0, AMD_ARRAY_SIZE(descriptorSets), + descriptorSets, AMD_ARRAY_SIZE(descriptorOffsets), + descriptorOffsets); + + vkCmdBindIndexBuffer(commandBuffer, m_pTressFXMesh->m_pTriangleIndexBuffer, 0, + VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(commandBuffer, UINT(m_hairParams.density * + m_pTressFXMesh->m_TotalTriangleIndexCount), + m_hairParams.strandCopies, 0, 0, 0); + + vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); + + // Pass 2: K-Buffer pass + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_pass2_layout, 0, 1, &m_pass2_set, + AMD_ARRAY_SIZE(descriptorOffsets), descriptorOffsets); + RenderScreenQuad(commandBuffer, m_pPLResolveKBuffer); + vkCmdEndRenderPass(commandBuffer); + markerCallbacks.markEndRegion(commandBuffer); +} + +void TressFXRenderer::RenderHairShortcut(VkDevice pvkDevice, + + VkCommandBuffer commandBuffer, + uint32_t width, + uint32_t height, uint32_t uniformBufferIndex, const DebugMarkerPointer& markerCallbacks) +{ + m_ShortCut.SetupDepthPass(pvkDevice, commandBuffer, width, height); + + uint32_t descriptorOffsets[] = {uniformBufferIndex * sizeof(CB_PER_FRAME)}; + + // DEPTH FILL + if (m_hairParams.bAntialias) + { + if (m_hairParams.strandCopies > 1) + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_ShortCut.m_pPLRenderHairAAStrandCopiesDepthsAlpha); + } + else + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_ShortCut.m_pPLRenderHairAADepthsAlpha); + } + } + else + { + if (m_hairParams.strandCopies > 1) + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_ShortCut.m_pPLRenderHairStrandCopiesDepthsAlpha); + } + else + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_ShortCut.m_pPLRenderHairDepthsAlpha); + } + } + + { + VkDescriptorSet descriptorSets[] = {m_ShortCut.m_depthPassSet, + m_pTressFXMesh->m_pass1_set}; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_ShortCut.m_depthPassPipelineLayout, 0, + AMD_ARRAY_SIZE(descriptorSets), descriptorSets, + AMD_ARRAY_SIZE(descriptorOffsets), descriptorOffsets); + } + + vkCmdBindIndexBuffer(commandBuffer, m_pTressFXMesh->m_pTriangleIndexBuffer, 0, + VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(commandBuffer, UINT(m_hairParams.density * + m_pTressFXMesh->m_TotalTriangleIndexCount), + m_hairParams.strandCopies, 0, 0, 0); + + // DEPTH RESOLVE + m_ShortCut.SetupResolveDepth(pvkDevice, commandBuffer, width, height); + RenderScreenQuad(commandBuffer, m_ShortCut.m_pPLDepthResolve); + + // COLOR FILL + m_ShortCut.SetupShadePass(pvkDevice, commandBuffer, width, height); + + if (m_hairParams.bAntialias) + { + if (m_hairParams.strandCopies > 1) + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_ShortCut.m_pPLRenderHairAAStrandCopiesFillColors); + } + else + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_ShortCut.m_pPLRenderHairAAFillColors); + } + } + else + { + if (m_hairParams.strandCopies > 1) + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_ShortCut.m_pPLRenderHairStrandCopiesFillColors); + } + else + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_ShortCut.m_pPLRenderHairFillColors); + } + } + + { + VkDescriptorSet descriptorSets[] = {m_ShortCut.m_colorPassSet, + m_pTressFXMesh->m_pass1_set}; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + m_ShortCut.m_colorPassPipelineLayout, 0, + AMD_ARRAY_SIZE(descriptorSets), descriptorSets, + AMD_ARRAY_SIZE(descriptorOffsets), descriptorOffsets); + } + + vkCmdBindIndexBuffer(commandBuffer, m_pTressFXMesh->m_pTriangleIndexBuffer, 0, + VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(commandBuffer, UINT(m_hairParams.density * + m_pTressFXMesh->m_TotalTriangleIndexCount), + m_hairParams.strandCopies, 0, 0, 0); + + // COLOR RESOLVE + m_ShortCut.SetupResolveColor(pvkDevice, commandBuffer, width, height); + RenderScreenQuad(commandBuffer, m_ShortCut.m_pPLColorResolve); + vkCmdEndRenderPass(commandBuffer); +} + +//-------------------------------------------------------------------------------------- +// +// EndHairFrame +// +// Start of hair rendering. +// +//-------------------------------------------------------------------------------------- +void TressFXRenderer::EndHairFrame(VkDevice pvkDevice) {} + +//-------------------------------------------------------------------------------------- +// +// OnDestroy +// +// Called when device is destroyed. +// +//-------------------------------------------------------------------------------------- +void TressFXRenderer::OnDestroy() +{ + m_ShortCut.OnDestroy(true); + + { + AMD_SAFE_RELEASE(m_pPLRenderHairAAStrandCopies, vkDestroyPipeline, m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLRenderHairAA, vkDestroyPipeline, m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLRenderHairStrandCopies, vkDestroyPipeline, m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLRenderHair, vkDestroyPipeline, m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLResolveKBuffer, vkDestroyPipeline, m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLGenerateHairSM, vkDestroyPipeline, m_pvkDevice); + + AMD_SAFE_RELEASE(m_renderHairFramebuffer, vkDestroyFramebuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_shadowFrameBuffer, vkDestroyFramebuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_pRPHairRendering, vkDestroyRenderPass, m_pvkDevice); + AMD_SAFE_RELEASE(m_RPHairShadow, vkDestroyRenderPass, m_pvkDevice); + AMD_SAFE_RELEASE(m_pass1_layout, vkDestroyPipelineLayout, m_pvkDevice); + AMD_SAFE_RELEASE(m_pass2_layout, vkDestroyPipelineLayout, m_pvkDevice); + AMD_SAFE_RELEASE(m_shadow_pass_layout, vkDestroyPipelineLayout, m_pvkDevice); + AMD_SAFE_RELEASE(m_pass1_config_set_layout, vkDestroyDescriptorSetLayout, + m_pvkDevice); + AMD_SAFE_RELEASE(m_pass1_hair_set_layout, vkDestroyDescriptorSetLayout, + m_pvkDevice); + AMD_SAFE_RELEASE(m_pass2_set_layout, vkDestroyDescriptorSetLayout, m_pvkDevice); + AMD_SAFE_RELEASE(m_shadow_pass_config_set_layout, vkDestroyDescriptorSetLayout, + m_pvkDevice); + AMD_SAFE_RELEASE(m_shadow_pass_hair_set_layout, vkDestroyDescriptorSetLayout, + m_pvkDevice); + } + + AMD_SAFE_RELEASE(m_pSamplerStateLinearWrap, vkDestroySampler, m_pvkDevice); + AMD_SAFE_RELEASE(m_pSamplerStatePointClamp, vkDestroySampler, m_pvkDevice); + AMD_SAFE_RELEASE(m_pSamplerStateCmpLess, vkDestroySampler, m_pvkDevice); + + AMD_SAFE_RELEASE(m_descriptorStorage, vkDestroyDescriptorPool, m_pvkDevice); + + // constant buffer + AMD_SAFE_RELEASE(m_pcbPerFrame, vkDestroyBuffer, m_pvkDevice); + AMD_SAFE_RELEASE(m_pcbPerFrameMemory, vkFreeMemory, m_pvkDevice); + + // PPLL buffers + DeletePPLL(m_pvkDevice); + + // textures and views + AMD_SAFE_RELEASE(m_pNoiseView, vkDestroyImageView, m_pvkDevice); + AMD_SAFE_RELEASE(m_pNoiseTexture, vkDestroyImage, m_pvkDevice); + AMD_SAFE_RELEASE(m_pNoiseMemory, vkFreeMemory, m_pvkDevice); + + // Hair shadow map depth stencil buffer + AMD_SAFE_RELEASE(m_pSMHairView, vkDestroyImageView, m_pvkDevice); + AMD_SAFE_RELEASE(m_pSMHairTexture, vkDestroyImage, m_pvkDevice); + AMD_SAFE_RELEASE(m_pSMHairMemory, vkFreeMemory, m_pvkDevice); +} + +} // namespace AMD diff --git a/amd_tressfx_vulkan/src/TressFXRendererVulkan.h b/amd_tressfx_vulkan/src/TressFXRendererVulkan.h new file mode 100644 index 0000000..1bff44f --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXRendererVulkan.h @@ -0,0 +1,173 @@ +//-------------------------------------------------------------------------------------- +// File: TressFXRenderer.h +// +// Header file for the main hair rendering code +// +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// +//-------------------------------------------------------------------------------------- + +#pragma once +#include "AMD_TressFX.h" +#include "Math\Vector3D.h" +#include "TressFXMeshVulkan.h" +#include "TressFXShortCutVulkan.h" + +#define SM_HAIR_WIDTH 640 +#define SM_HAIR_HEIGHT 640 + +namespace AMD +{ + +class TressFXRenderer +{ + private: + VkDevice m_pvkDevice; + // We need 2 pass because buffer need to be flushed inbetween + VkRenderPass m_pRPHairRendering; + VkRenderPass m_RPHairShadow; + + // Layout + VkDescriptorSetLayout m_pass1_config_set_layout; + VkPipelineLayout m_pass1_layout; + VkDescriptorSetLayout m_pass2_set_layout; + VkPipelineLayout m_pass2_layout; + VkDescriptorSetLayout m_shadow_pass_config_set_layout; + VkPipelineLayout m_shadow_pass_layout; + VkDescriptorPool m_descriptorStorage; + VkDescriptorSet m_pass1_config_set; + VkDescriptorSet m_pass2_set; + VkDescriptorSet m_shadow_pass_set; + + // Pass 1 pipeline + VkPipeline m_pPLRenderHair; + VkPipeline m_pPLRenderHairStrandCopies; + VkPipeline m_pPLRenderHairAA; + VkPipeline m_pPLRenderHairAAStrandCopies; + // final rendering using a k-buffer for sorting the k nearest fragments + VkPipeline m_pPLResolveKBuffer; + // pipeline for generating the hair shadow map + VkPipeline m_pPLGenerateHairSM; + + // samplers + VkSampler m_pSamplerStateLinearWrap; + VkSampler m_pSamplerStatePointClamp; + VkSampler m_pSamplerStateCmpLess; + + // constant buffer + VkBuffer m_pcbPerFrame; + VkDeviceMemory m_pcbPerFrameMemory; + + // Buffers for the head of the per-pixel linked lists (PPLL) + VkImage m_pHeadPPLLTexture; + VkImageView m_pHeadPPLLView; + + // Buffers for the per-pixel linked list (PPLL) data + VkBuffer m_pPPLLBuffer; + + // Buffer for the atomic counter + VkBuffer m_pAtomicCounterPPLLBuffer; + + // textures and views + VkImage m_pNoiseTexture; + VkDeviceMemory m_pNoiseMemory; + VkImageView m_pNoiseView; + + // Hair shadow map depth stencil buffer + VkImage m_pSMHairTexture; + VkDeviceMemory m_pSMHairMemory; + VkImageView m_pSMHairView; + + TressFXShortCut m_ShortCut; + + VkImageView m_depthBuffer; + VkImageView m_colorTexture; + VkFramebuffer m_renderHairFramebuffer; + VkFramebuffer m_shadowFrameBuffer; + + public: + VkDescriptorSetLayout m_pass1_hair_set_layout; + VkDescriptorSetLayout m_shadow_pass_hair_set_layout; + + // hair rendering params + TressFX_HairParams m_hairParams; + + // hair geometry + TressFXMesh *m_pTressFXMesh; + + private: + VkResult CreateFrameBuffer(VkDevice pvkDevice, VkImageView depthTextureView, + VkImageView colorTextureView, uint32_t width, + uint32_t height); + VkResult CreateTextureAndViews(VkDevice pvkDevice, VkPhysicalDeviceMemoryProperties memProperties, + VkCommandBuffer commandBuffer, + VkDeviceMemory scratchMemory, VkBuffer scratchBuffer, + size_t &offsetInScratchBuffer); + VkResult CreateConstantBuffer(VkDevice pvkDevice, uint32_t maxUniformBuffer, + VkPhysicalDeviceMemoryProperties memProperties); + VkResult CreateSamplers(VkDevice pvkDevice); + VkResult CreateRenderStateObjects(VkDevice pvkDevice, VkFormat depthStencilFormat, VkFormat colorFormat); + VkResult CreatePPLL(VkDevice pvkDevice, int winWidth, int winHeight, bool resize, + VkPhysicalDeviceMemoryProperties memProperties); + VkResult CreateLayouts(VkDevice pvkDevice); + VkResult AllocateAndPopulateSets(VkDevice pvkDevice, bool isShortcut); + void DeletePPLL(VkDevice pvkDevice); + void RenderScreenQuad(VkCommandBuffer pcmdbuffer, VkPipeline pPipeline); + + public: + TressFXRenderer(void){}; + ~TressFXRenderer(void){}; + + VkImageView GetShadowMapSRV() { return m_pSMHairView; }; + VkResult OnCreateDevice(VkDevice pvkDevice, int winWidth, int winHeight, + bool bShortCutOn, uint32_t maxUniformBuffer, + VkPhysicalDeviceMemoryProperties memProperties, + VkImageView depthTexture, VkImageView colorTexture, + VkCommandBuffer commandBuffer, VkDeviceMemory scratchMemory, + VkBuffer scratchBuffer, size_t &offsetInScratchBuffer, + VkFormat depthStencilFormat, VkFormat colorFormat); + VkResult OnResizedSwapChain(VkDevice pvkDevice, int winWidth, int WinHeight, + bool bShortCutOn, VkPhysicalDeviceMemoryProperties memProperties); + void BeginHairFrame(VkDevice pvkDevice, DirectX::XMVECTOR eyePoint, + DirectX::XMVECTOR lightPosition, + DirectX::XMMATRIX *pModelTrasnsformForHead, + DirectX::XMMATRIX *pViewProj, + DirectX::XMMATRIX *pViewProjLightOut, float screenWidth, + float screenHeight, bool singleHeadTransform, + uint32_t uniformBufferIndex); + void GenerateShadowMap(VkDevice pvkDevice, + VkCommandBuffer commandBuffer, + float density, uint32_t uniformBufferIndex, + const DebugMarkerPointer& markerCallbacks); + void RenderHair(VkDevice pvkDevice, VkCommandBuffer commandBuffer, + uint32_t width, + uint32_t height, uint32_t uniformBufferIndex, + const DebugMarkerPointer& markerCallbacks); + void RenderHairShortcut(VkDevice pvkDevice, + VkCommandBuffer commandBuffer, + uint32_t width, uint32_t height, uint32_t uniformBufferIndex, + const DebugMarkerPointer& markerCallbacks); + void EndHairFrame(VkDevice pvkDevice); + void OnDestroy(); +}; + +} // namespace AMD diff --git a/amd_tressfx_vulkan/src/TressFXShortCutVulkan.cpp b/amd_tressfx_vulkan/src/TressFXShortCutVulkan.cpp new file mode 100644 index 0000000..2a91d61 --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXShortCutVulkan.cpp @@ -0,0 +1,854 @@ +//-------------------------------------------------------------------------------------- +// File: TressFXShortCut.cpp +// +// TressFX ShortCut method. +// +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// +//-------------------------------------------------------------------------------------- + +#include "TressFXShortCutVulkan.h" +#include "AMD_Types.h" +#include "TressFXPrecompiledShadersVulkan.h" +#include "UtilVulkan.h" +#include + +// unreferenced formal parameter +#pragma warning(disable : 4100) + +// Constants must match in TressFXRender.hlsl + +// Clear value for depths resource +#define SHORTCUT_INITIAL_DEPTH 0x3f800000 + +// Number of depth layers to use. 2 or 3 supported. +#define SHORTCUT_NUM_DEPTHS 3 + +// Compute source color as weighted average of front fragments, vs blending in order. +#define SHORTCUT_WEIGHTED_AVERAGE 1 + +// Output color deterministically when fragments have the same depth. Requires additional +// clear of colors resource. +#define SHORTCUT_DETERMINISTIC 1 + +namespace AMD +{ + +VkResult GPUOnlyStructuredBuffer::Create(VkDevice pvkDevice, uint32_t structSize, + uint32_t structCount) +{ + VkResult vr; + + // Per-pixel Linked List (PPLL) buffer + VkBufferCreateInfo BufferDesc{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + BufferDesc.size = structCount * structSize; + BufferDesc.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &BufferDesc, NULL, &m_pBuffer)); + m_pvkDevice = pvkDevice; + + return VK_SUCCESS; +} + +void GPUOnlyStructuredBuffer::Destroy() +{ + if (m_pBuffer) + vkDestroyBuffer(m_pvkDevice, m_pBuffer, nullptr); +} + +VkResult TressFXShortCut::CreateScreenSizedItems(VkDevice pvkDevice, int winWidth, + int winHeight, + VkPhysicalDeviceMemoryProperties memProperties) +{ + m_pvkDevice = pvkDevice; + VkResult vr; + { + VkImageCreateInfo accumInvAlphaInfo = getImageCreateInfo( + VK_FORMAT_R16_SFLOAT, winWidth, winHeight, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT); + AMD_CHECKED_VULKAN_CALL(vkCreateImage(pvkDevice, &accumInvAlphaInfo, nullptr, + &m_pAccumInvAlphaTexture)); + m_pAccumInvAlphaMemory = + allocImageMemory(pvkDevice, m_pAccumInvAlphaTexture, memProperties); + + VkImageViewCreateInfo srDesc{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; + srDesc.format = VK_FORMAT_R16_SFLOAT; + srDesc.viewType = VK_IMAGE_VIEW_TYPE_2D; + srDesc.subresourceRange.levelCount = 1; + srDesc.subresourceRange.layerCount = 1; + srDesc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + srDesc.image = m_pAccumInvAlphaTexture; + AMD_CHECKED_VULKAN_CALL( + vkCreateImageView(pvkDevice, &srDesc, nullptr, &m_pAccumInvAlphaView)); + } + + { + VkImageCreateInfo fragmentDepthInfo = + getImageCreateInfo(VK_FORMAT_R32_UINT, winWidth, winHeight, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT, + SHORTCUT_NUM_DEPTHS); + AMD_CHECKED_VULKAN_CALL(vkCreateImage(pvkDevice, &fragmentDepthInfo, nullptr, + &m_pFragmentDepthsTexture)); + + m_pFragmentDepthsMemory = + allocImageMemory(pvkDevice, m_pFragmentDepthsTexture, memProperties); + + VkImageViewCreateInfo srDesc{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; + srDesc.format = VK_FORMAT_R32_UINT; + srDesc.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + srDesc.subresourceRange.levelCount = 1; + srDesc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + srDesc.subresourceRange.layerCount = SHORTCUT_NUM_DEPTHS; + srDesc.image = m_pFragmentDepthsTexture; + AMD_CHECKED_VULKAN_CALL( + vkCreateImageView(pvkDevice, &srDesc, nullptr, &m_pFragmentDepthsView)); + } + +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + { + VkImageCreateInfo fragmentColorInfo = getImageCreateInfo( + VK_FORMAT_R16G16B16A16_SFLOAT, winWidth, winHeight, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT); + AMD_CHECKED_VULKAN_CALL(vkCreateImage(pvkDevice, &fragmentColorInfo, nullptr, + &m_pFragmentColorsTexture)); + + m_pFragmentColorsMemory = + allocImageMemory(pvkDevice, m_pFragmentColorsTexture, memProperties); + + VkImageViewCreateInfo srDesc{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; + srDesc.format = VK_FORMAT_R16G16B16A16_SFLOAT; + srDesc.viewType = VK_IMAGE_VIEW_TYPE_2D; + srDesc.subresourceRange.levelCount = 1; + srDesc.subresourceRange.layerCount = 1; + srDesc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + srDesc.image = m_pFragmentColorsTexture; + AMD_CHECKED_VULKAN_CALL( + vkCreateImageView(pvkDevice, &srDesc, nullptr, &m_pFragmentColorsView)); + } +#else + m_FragmentColors.Create(pd3dDevice, 4 * SHORTCUT_NUM_DEPTHS, winWidth * winHeight); +#endif + + return VK_SUCCESS; +} + +void TressFXShortCut::DestroyScreenSizedItems() +{ + AMD_SAFE_RELEASE(m_pFBRenderHair, vkDestroyFramebuffer, m_pvkDevice); + + AMD_SAFE_RELEASE(m_pFragmentColorsView, vkDestroyImageView, m_pvkDevice); + AMD_SAFE_RELEASE(m_pFragmentDepthsView, vkDestroyImageView, m_pvkDevice); + AMD_SAFE_RELEASE(m_pAccumInvAlphaView, vkDestroyImageView, m_pvkDevice); + + AMD_SAFE_RELEASE(m_pFragmentColorsMemory, vkFreeMemory, m_pvkDevice); + AMD_SAFE_RELEASE(m_pFragmentDepthsMemory, vkFreeMemory, m_pvkDevice); + AMD_SAFE_RELEASE(m_pAccumInvAlphaMemory, vkFreeMemory, m_pvkDevice); + + AMD_SAFE_RELEASE(m_pFragmentColorsTexture, vkDestroyImage, m_pvkDevice); + AMD_SAFE_RELEASE(m_pFragmentDepthsTexture, vkDestroyImage, m_pvkDevice); + AMD_SAFE_RELEASE(m_pAccumInvAlphaTexture, vkDestroyImage, m_pvkDevice); + m_FragmentColors.Destroy(); +} + +namespace +{ +VkAttachmentDescription getAttachmentDescription( + VkFormat format, VkAttachmentLoadOp loadOp, VkAttachmentStoreOp storeOp, + VkImageLayout inoutLayout, + VkAttachmentLoadOp stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + VkAttachmentStoreOp stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE) +{ + return {0, format, VK_SAMPLE_COUNT_1_BIT, loadOp, + storeOp, stencilLoadOp, stencilStoreOp, inoutLayout, + inoutLayout}; +} + +VkRenderPass createRenderPass(VkDevice pvkDevice, VkFormat depthStencilFormat, VkFormat colorFormat) +{ + VkRenderPassCreateInfo info{VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO}; + + const VkAttachmentDescription attachments[] = { + // DS + getAttachmentDescription(depthStencilFormat, VK_ATTACHMENT_LOAD_OP_LOAD, + VK_ATTACHMENT_STORE_OP_STORE, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_STORE_OP_DONT_CARE), + // accumInvAlpha + getAttachmentDescription(VK_FORMAT_R16_SFLOAT, VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_STORE_OP_DONT_CARE, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL), +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + // FragmentColor + getAttachmentDescription( + VK_FORMAT_R16G16B16A16_SFLOAT, VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL), +#else +// TODO +#endif + // Result + getAttachmentDescription(colorFormat, VK_ATTACHMENT_LOAD_OP_LOAD, + VK_ATTACHMENT_STORE_OP_STORE, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL), + + }; + + VkAttachmentReference depthStencil{0, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; + VkAttachmentReference accumInvAlpha{1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + VkAttachmentReference FragmentColor{2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; +#else +// TODO +#endif + VkAttachmentReference colorAttachment{3, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; + + VkAttachmentReference colorResolveInputAttachments[] = {{1, VK_IMAGE_LAYOUT_GENERAL}, + {2, VK_IMAGE_LAYOUT_GENERAL}}; + + uint32_t untouchedAttachmentDepthResolve[] = {1}; + uint32_t untouchedAttachmentColorFill[] = {1}; + + const VkSubpassDescription subpasses[] = { + // Depth alpha + {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &accumInvAlpha, nullptr, + &depthStencil, 0, nullptr}, + // Depth resolve + {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, + &depthStencil, AMD_ARRAY_SIZE(untouchedAttachmentDepthResolve), + untouchedAttachmentDepthResolve}, + // Color fill + {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &FragmentColor, nullptr, + &depthStencil, AMD_ARRAY_SIZE(untouchedAttachmentColorFill), + untouchedAttachmentColorFill}, + // Color resolve + {0, VK_PIPELINE_BIND_POINT_GRAPHICS, AMD_ARRAY_SIZE(colorResolveInputAttachments), + colorResolveInputAttachments, 1, &colorAttachment, nullptr, &depthStencil, 0, + nullptr}, + }; + + const VkSubpassDependency dependencies[] = { + // Depth alpha modifies fragment depth image while depth resolve reads it + {0, 1, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_SHADER_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}, + {0, 2, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, VK_DEPENDENCY_BY_REGION_BIT}, + {0, 3, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}, + // Depth resolve update depth attachement while color fill reads it + {1, 2, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}, + {1, 3, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, VK_DEPENDENCY_BY_REGION_BIT}, + // color resolve consumes output from color fill + {2, 3, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}, + }; + + info.attachmentCount = AMD_ARRAY_SIZE(attachments); + info.pAttachments = attachments; + info.subpassCount = AMD_ARRAY_SIZE(subpasses); + info.pSubpasses = subpasses; + info.dependencyCount = AMD_ARRAY_SIZE(dependencies); + info.pDependencies = dependencies; + + VkRenderPass result; + vkCreateRenderPass(pvkDevice, &info, nullptr, &result); + return result; +} +} + +//-------------------------------------------------------------------------------------- +// +// CreateRenderStateObjects +// +// Creates the pipelines for hair rendering +// +//-------------------------------------------------------------------------------------- +VkResult TressFXShortCut::CreateRenderStateObjects(VkDevice pvkDevice, VkFormat depthStencilFormat, VkFormat colorFormat) +{ + m_pRPRenderHair = createRenderPass(pvkDevice, depthStencilFormat, colorFormat); + + ShaderModule m_pPSDepthsAlpha(pvkDevice, depth_hair_data); + ShaderModule m_pPSFillColors(pvkDevice, fillcolors_hair_data); + + ShaderModule render_hair_aa_strand_copiesModule(pvkDevice, + render_hair_aa_strand_copies_vertex); + const VkPipelineShaderStageCreateInfo renderHairAAStrandCopiesDepthsAlphaStage[2] = { + getShaderStageCreateInfo(render_hair_aa_strand_copiesModule.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(m_pPSDepthsAlpha.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + const VkGraphicsPipelineCreateInfo renderHairAAStrandCopiesDepthsAlphaDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::m_pDepthWritesToColor_BS, + &CommonPipelineState::inputAssemblyTriangle, + renderHairAAStrandCopiesDepthsAlphaStage, m_depthPassPipelineLayout, + m_pRPRenderHair, 0); + + const VkPipelineShaderStageCreateInfo renderHairAAStrandCopiesFillColorsStage[2] = { + getShaderStageCreateInfo(render_hair_aa_strand_copiesModule.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(m_pPSFillColors.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + const VkGraphicsPipelineCreateInfo renderHairAAStrandCopiesFillColorsDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::m_pSum_BS, +#else + &m_pDepthTestEnabledNoDepthWritesStencilWriteIncrement_DSS, &m_pNoWrites_BS, +#endif + &CommonPipelineState::inputAssemblyTriangle, + renderHairAAStrandCopiesFillColorsStage, m_colorPassPipelineLayout, + m_pRPRenderHair, 2); + + ShaderModule RenderHairAAVertexShader(pvkDevice, render_hair_aa_vertex); + const VkPipelineShaderStageCreateInfo renderHairAADepthsAlphaStage[2] = { + getShaderStageCreateInfo(RenderHairAAVertexShader.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(m_pPSDepthsAlpha.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + const VkGraphicsPipelineCreateInfo renderHairAADepthsAlphaDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::m_pDepthWritesToColor_BS, + &CommonPipelineState::inputAssemblyTriangle, renderHairAADepthsAlphaStage, + m_depthPassPipelineLayout, m_pRPRenderHair, 0); + + const VkPipelineShaderStageCreateInfo renderHairAAFillColorsStage[2] = { + getShaderStageCreateInfo(RenderHairAAVertexShader.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(m_pPSFillColors.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + const VkGraphicsPipelineCreateInfo renderHairAAFillColorsDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::m_pSum_BS, +#else + &m_pDepthTestEnabledNoDepthWritesStencilWriteIncrement_DSS, &m_pNoWrites_BS, +#endif + &CommonPipelineState::inputAssemblyTriangle, renderHairAAFillColorsStage, + m_colorPassPipelineLayout, m_pRPRenderHair, 2); + + ShaderModule renderHairStrandCopiesVertexModule(pvkDevice, + render_hair_strand_copies_vertex); + const VkPipelineShaderStageCreateInfo renderHairStrandCopiesDepthsAlphaStage[2] = { + getShaderStageCreateInfo(renderHairStrandCopiesVertexModule.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(m_pPSDepthsAlpha.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + const VkGraphicsPipelineCreateInfo renderHairStrandCopiesDepthsAlphaDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::m_pDepthWritesToColor_BS, + &CommonPipelineState::inputAssemblyTriangle, + renderHairStrandCopiesDepthsAlphaStage, m_depthPassPipelineLayout, + m_pRPRenderHair, 0); + + const VkPipelineShaderStageCreateInfo renderHairStrandCopiesFillColorsStage[2] = { + getShaderStageCreateInfo(renderHairStrandCopiesVertexModule.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(m_pPSFillColors.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + const VkGraphicsPipelineCreateInfo renderHairStrandCopiesFillColorsDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::m_pSum_BS, +#else + &m_pDepthTestEnabledNoDepthWritesStencilWriteIncrement_DSS, &m_pNoWrites_BS, +#endif + &CommonPipelineState::inputAssemblyTriangle, + renderHairStrandCopiesFillColorsStage, m_colorPassPipelineLayout, + m_pRPRenderHair, 2); + + ShaderModule renderHairVertexModule(pvkDevice, render_hair_vertex); + const VkPipelineShaderStageCreateInfo renderHairDepthsAlphaStage[2] = { + getShaderStageCreateInfo(renderHairVertexModule.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(m_pPSDepthsAlpha.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + const VkGraphicsPipelineCreateInfo renderHairDepthsAlphaDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::m_pDepthWritesToColor_BS, + &CommonPipelineState::inputAssemblyTriangle, renderHairDepthsAlphaStage, + m_depthPassPipelineLayout, m_pRPRenderHair, 0); + + const VkPipelineShaderStageCreateInfo renderHairFillColorsStage[2] = { + getShaderStageCreateInfo(renderHairVertexModule.m_shaderModule, + VK_SHADER_STAGE_VERTEX_BIT, "main"), + getShaderStageCreateInfo(m_pPSFillColors.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + const VkGraphicsPipelineCreateInfo renderHairFillColorsDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutHair, +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + &CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc, + &CommonPipelineState::m_pSum_BS, +#else + &m_pDepthTestEnabledNoDepthWritesStencilWriteIncrement_DSS, &m_pNoWrites_BS, +#endif + &CommonPipelineState::inputAssemblyTriangle, renderHairFillColorsStage, + m_colorPassPipelineLayout, m_pRPRenderHair, 2); + + // Resolve depth + ShaderModule renderQuadVS(pvkDevice, pass2_vertex); + ShaderModule depth_resolve(pvkDevice, resolve_depth); + const VkPipelineShaderStageCreateInfo depthResolveStage[2] = { + getShaderStageCreateInfo(renderQuadVS.m_shaderModule, VK_SHADER_STAGE_VERTEX_BIT, + "main"), + getShaderStageCreateInfo(depth_resolve.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + const VkGraphicsPipelineCreateInfo depthResolveDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutQuad, + &CommonPipelineState::m_pDepthWriteEnabledStencilTestLess_DSS, + &CommonPipelineState::ColorWritesOff, + &CommonPipelineState::inputAssemblyTriangle, depthResolveStage, + m_depthPassPipelineLayout, m_pRPRenderHair, 1); + + // Resolve Color + ShaderModule color_resolve(pvkDevice, resolvecolors); + const VkPipelineShaderStageCreateInfo colorResolveStage[2] = { + getShaderStageCreateInfo(renderQuadVS.m_shaderModule, VK_SHADER_STAGE_VERTEX_BIT, + "main"), + getShaderStageCreateInfo(color_resolve.m_shaderModule, + VK_SHADER_STAGE_FRAGMENT_BIT, "main"), + }; + + const VkGraphicsPipelineCreateInfo colorResolveDesc = + CommonPipelineState::getBasePipelineCreateInfo( + &CommonPipelineState::m_pLayoutQuad, + &CommonPipelineState::DepthTestDisabledStencilTestLessDSS, + &CommonPipelineState::m_pResolveColor_BS, + &CommonPipelineState::inputAssemblyTriangle, colorResolveStage, + m_colorPassPipelineLayout, m_pRPRenderHair, 3); + + VkGraphicsPipelineCreateInfo pipelinesDesc[] = { + renderHairAAStrandCopiesDepthsAlphaDesc, + renderHairAAStrandCopiesFillColorsDesc, + renderHairAADepthsAlphaDesc, + renderHairAAFillColorsDesc, + renderHairStrandCopiesDepthsAlphaDesc, + renderHairStrandCopiesFillColorsDesc, + renderHairDepthsAlphaDesc, + renderHairFillColorsDesc, + depthResolveDesc, + colorResolveDesc}; + + VkPipeline pipelines[AMD_ARRAY_SIZE(pipelinesDesc)]; + + VkResult vr; + AMD_CHECKED_VULKAN_CALL(vkCreateGraphicsPipelines(pvkDevice, VK_NULL_HANDLE, + AMD_ARRAY_SIZE(pipelinesDesc), pipelinesDesc, + nullptr, pipelines)); + + m_pPLRenderHairAAStrandCopiesDepthsAlpha = pipelines[0]; + m_pPLRenderHairAAStrandCopiesFillColors = pipelines[1]; + m_pPLRenderHairAADepthsAlpha = pipelines[2]; + m_pPLRenderHairAAFillColors = pipelines[3]; + m_pPLRenderHairStrandCopiesDepthsAlpha = pipelines[4]; + m_pPLRenderHairStrandCopiesFillColors = pipelines[5]; + m_pPLRenderHairDepthsAlpha = pipelines[6]; + m_pPLRenderHairFillColors = pipelines[7]; + m_pPLDepthResolve = pipelines[8]; + m_pPLColorResolve = pipelines[9]; + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// CreateLayouts +// +// Creates the descriptors set and pipeline layouts. +// +//-------------------------------------------------------------------------------------- +VkResult TressFXShortCut::CreateLayouts(VkDevice pvkDevice, + VkDescriptorSetLayout mesh_layout, + VkSampler noiseSamplerRef, + VkSampler shadowSamplerRef) +{ + VkResult vr; + + { + VkDescriptorSetLayoutCreateInfo info{ + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO}; + VkDescriptorSetLayoutBinding bindings[] = { + // TressFX parameters + {IDSRV_CONSTANTS_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, + VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT}, + // Fragment depth + {IDSRV_HAIR_FRAGMENT_DEPTHS, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, + // Sampler for noise texture in VS + {IDSRV_NOISE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER, 1, + VK_SHADER_STAGE_VERTEX_BIT, &noiseSamplerRef}, + // Noise texture + {IDSRV_NOISEMAP, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, + VK_SHADER_STAGE_VERTEX_BIT}, + }; + info.bindingCount = AMD_ARRAY_SIZE(bindings); + info.pBindings = bindings; + AMD_CHECKED_VULKAN_CALL( + vkCreateDescriptorSetLayout(pvkDevice, &info, nullptr, &m_pSLDepthAlpha)); + } + + { + VkDescriptorSetLayoutCreateInfo info{ + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO}; + VkDescriptorSetLayoutBinding bindings[] = { + // TressFX parameters + {IDSRV_CONSTANTS_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, + VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT}, + // Fragment depth + {IDSRV_HAIR_FRAGMENT_DEPTHS, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, + // Sampler for noise texture in VS + {IDSRV_NOISE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER, 1, + VK_SHADER_STAGE_VERTEX_BIT, &noiseSamplerRef}, + // Noise texture + {IDSRV_NOISEMAP, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, + VK_SHADER_STAGE_VERTEX_BIT}, + // Hair shadow + {IDSRV_HAIRSM, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, + // Hair shadow sampler + {IDSRV_SHADOW_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER, 1, + VK_SHADER_STAGE_FRAGMENT_BIT, &shadowSamplerRef}, +// Fragment color +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + {IDSRV_HAIR_FRAGMENT_COLORS, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, +#else +// TODO +#endif + // inv alpha accum + {IDSRV_HAIR_ACCUM_INV_ALPHA, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, + VK_SHADER_STAGE_FRAGMENT_BIT}, + }; + info.bindingCount = AMD_ARRAY_SIZE(bindings); + info.pBindings = bindings; + AMD_CHECKED_VULKAN_CALL( + vkCreateDescriptorSetLayout(pvkDevice, &info, nullptr, &m_pSLColors)); + } + + { + VkPipelineLayoutCreateInfo info{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; + VkDescriptorSetLayout set_layout[] = {m_pSLDepthAlpha, mesh_layout}; + + info.setLayoutCount = AMD_ARRAY_SIZE(set_layout); + info.pSetLayouts = set_layout; + AMD_CHECKED_VULKAN_CALL(vkCreatePipelineLayout(pvkDevice, &info, nullptr, + &m_depthPassPipelineLayout)); + } + + { + VkPipelineLayoutCreateInfo info{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; + VkDescriptorSetLayout set_layout[] = {m_pSLColors, mesh_layout}; + + info.setLayoutCount = AMD_ARRAY_SIZE(set_layout); + info.pSetLayouts = set_layout; + AMD_CHECKED_VULKAN_CALL(vkCreatePipelineLayout(pvkDevice, &info, nullptr, + &m_colorPassPipelineLayout)); + } + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// CreateFramebuffer +// +// Creates the framebuffer for every pass of the shortcut algorithm +// +//-------------------------------------------------------------------------------------- +VkResult TressFXShortCut::CreateFramebuffer(VkDevice pvkDevice, + VkImageView depthStencilView, + VkImageView colorView, uint32_t width, + uint32_t height) +{ + VkResult vr; + { + VkFramebufferCreateInfo info{VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO}; + info.renderPass = m_pRPRenderHair; + info.height = height; + info.width = width; + info.layers = 1; +#if SHORTCUT_DETERMINISTIC && SHORTCUT_WEIGHTED_AVERAGE + VkImageView attachments[] = {depthStencilView, m_pAccumInvAlphaView, + m_pFragmentColorsView, colorView}; + info.attachmentCount = AMD_ARRAY_SIZE(attachments); + info.pAttachments = attachments; +#else +// TODO +#endif + AMD_CHECKED_VULKAN_CALL(vkCreateFramebuffer(pvkDevice, &info, nullptr, &m_pFBRenderHair)); + } + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// AllocateAndPopulateSets +// +// Allocate descriptor set and fills them +// +//-------------------------------------------------------------------------------------- +VkResult TressFXShortCut::AllocateAndPopulateSets(VkDevice pvkDevice, + VkBuffer configBuffer, + uint64_t configBufferSize, + VkImageView noiseMap, + VkImageView hairShadowMap) +{ + VkResult vr; + { + VkDescriptorPoolCreateInfo info{VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO}; + VkDescriptorPoolSize sizes[] = {{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 2}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 5}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 5}, + {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2}, + {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1}, + {VK_DESCRIPTOR_TYPE_SAMPLER, 5}}; + info.maxSets = 2; + info.poolSizeCount = AMD_ARRAY_SIZE(sizes); + info.pPoolSizes = sizes; + AMD_CHECKED_VULKAN_CALL( + vkCreateDescriptorPool(pvkDevice, &info, nullptr, &m_pDPShortcutPool)); + } + + { + VkDescriptorSetLayout setLayout[] = {m_pSLDepthAlpha, m_pSLColors}; + VkDescriptorSetAllocateInfo info{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO}; + info.descriptorPool = m_pDPShortcutPool; + info.descriptorSetCount = AMD_ARRAY_SIZE(setLayout); + info.pSetLayouts = setLayout; + VkDescriptorSet sets[AMD_ARRAY_SIZE(setLayout)]; + AMD_CHECKED_VULKAN_CALL(vkAllocateDescriptorSets(pvkDevice, &info, sets)); + m_depthPassSet = sets[0]; + m_colorPassSet = sets[1]; + } + + VkDescriptorBufferInfo bufferdesc{configBuffer, 0, configBufferSize}; + VkDescriptorImageInfo noise_descriptor{VK_NULL_HANDLE, noiseMap, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; + VkDescriptorImageInfo hairSM_descriptor{VK_NULL_HANDLE, hairShadowMap, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; + VkDescriptorImageInfo hairFragmentDepthsDescriptor{ + VK_NULL_HANDLE, m_pFragmentDepthsView, VK_IMAGE_LAYOUT_GENERAL}; + VkDescriptorImageInfo hairFragmentColorDescriptor{ + VK_NULL_HANDLE, m_pFragmentColorsView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; + VkDescriptorImageInfo hairAccumInvAlphaDescriptor{ + VK_NULL_HANDLE, m_pAccumInvAlphaView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; + + VkWriteDescriptorSet writes[] = { + getWriteDescriptor(m_depthPassSet, IDSRV_CONSTANTS_BUFFER, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, &bufferdesc), + getWriteDescriptor(m_depthPassSet, IDSRV_HAIR_FRAGMENT_DEPTHS, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + &hairFragmentDepthsDescriptor), + getWriteDescriptor(m_depthPassSet, IDSRV_NOISEMAP, + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &noise_descriptor), + + getWriteDescriptor(m_colorPassSet, IDSRV_CONSTANTS_BUFFER, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, &bufferdesc), + getWriteDescriptor(m_colorPassSet, IDSRV_HAIR_FRAGMENT_DEPTHS, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + &hairFragmentDepthsDescriptor), + getWriteDescriptor(m_colorPassSet, IDSRV_NOISEMAP, + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &noise_descriptor), + getWriteDescriptor(m_colorPassSet, IDSRV_HAIRSM, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + &hairSM_descriptor), + getWriteDescriptor(m_colorPassSet, IDSRV_HAIR_FRAGMENT_COLORS, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + &hairFragmentColorDescriptor), + getWriteDescriptor(m_colorPassSet, IDSRV_HAIR_ACCUM_INV_ALPHA, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + &hairAccumInvAlphaDescriptor), + }; + + vkUpdateDescriptorSets(pvkDevice, AMD_ARRAY_SIZE(writes), writes, 0, nullptr); + + return VK_SUCCESS; +} + +VkResult TressFXShortCut::OnCreateDevice( + VkDevice pd3dDevice, int winWidth, int winHeight, VkDescriptorSetLayout mesh_layout, + VkSampler noiseSamplerRef, VkSampler shadowSamplerRef, VkImageView depthStencilView, + VkImageView colorView, VkBuffer configBuffer, uint64_t configBufferSize, + VkImageView noiseMap, VkImageView hairShadowMap, VkPhysicalDeviceMemoryProperties memProperties, + uint32_t width, uint32_t height, VkFormat depthStencilFormat, VkFormat colorFormat) +{ + VkResult vr; + + AMD_CHECKED_VULKAN_CALL( + CreateScreenSizedItems(pd3dDevice, winWidth, winHeight, memProperties)); + AMD_CHECKED_VULKAN_CALL( + CreateLayouts(pd3dDevice, mesh_layout, noiseSamplerRef, shadowSamplerRef)); + AMD_CHECKED_VULKAN_CALL(CreateRenderStateObjects(pd3dDevice, depthStencilFormat, colorFormat)); + AMD_CHECKED_VULKAN_CALL( + CreateFramebuffer(pd3dDevice, depthStencilView, colorView, width, height)); + AMD_CHECKED_VULKAN_CALL(AllocateAndPopulateSets(pd3dDevice, configBuffer, configBufferSize, + noiseMap, hairShadowMap)) + + return VK_SUCCESS; +} + +VkResult TressFXShortCut::OnResizedSwapChain(VkDevice pd3dDevice, int winWidth, + int winHeight, + VkPhysicalDeviceMemoryProperties memProperties) +{ + DestroyScreenSizedItems(); + + VkResult vr; + AMD_CHECKED_VULKAN_CALL( + CreateScreenSizedItems(pd3dDevice, winWidth, winHeight, memProperties)); + return VK_SUCCESS; +} + +void TressFXShortCut::OnDestroy(bool destroyShaders) +{ + DestroyScreenSizedItems(); + + if (destroyShaders) + { + AMD_SAFE_RELEASE(m_pPLRenderHairAAStrandCopiesDepthsAlpha, vkDestroyPipeline, + m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLRenderHairAAStrandCopiesFillColors, vkDestroyPipeline, + m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLRenderHairAADepthsAlpha, vkDestroyPipeline, m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLRenderHairAAFillColors, vkDestroyPipeline, m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLRenderHairStrandCopiesDepthsAlpha, vkDestroyPipeline, + m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLRenderHairStrandCopiesFillColors, vkDestroyPipeline, + m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLRenderHairDepthsAlpha, vkDestroyPipeline, m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLRenderHairFillColors, vkDestroyPipeline, m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLDepthResolve, vkDestroyPipeline, m_pvkDevice); + AMD_SAFE_RELEASE(m_pPLColorResolve, vkDestroyPipeline, m_pvkDevice); + + AMD_SAFE_RELEASE(m_pRPRenderHair, vkDestroyRenderPass, m_pvkDevice); + + AMD_SAFE_RELEASE(m_depthPassPipelineLayout, vkDestroyPipelineLayout, m_pvkDevice); + AMD_SAFE_RELEASE(m_colorPassPipelineLayout, vkDestroyPipelineLayout, m_pvkDevice); + AMD_SAFE_RELEASE(m_pSLDepthAlpha, vkDestroyDescriptorSetLayout, m_pvkDevice); + AMD_SAFE_RELEASE(m_pSLColors, vkDestroyDescriptorSetLayout, m_pvkDevice); + } + AMD_SAFE_RELEASE(m_pDPShortcutPool, vkDestroyDescriptorPool, m_pvkDevice); +} + +void TressFXShortCut::SetupDepthPass(VkDevice pvkDevice, VkCommandBuffer commandBuffer, + uint32_t width, uint32_t height) +{ + VkClearColorValue dwDepthClearMax{}; + dwDepthClearMax.uint32[0] = SHORTCUT_INITIAL_DEPTH; + dwDepthClearMax.uint32[1] = SHORTCUT_INITIAL_DEPTH; + dwDepthClearMax.uint32[2] = SHORTCUT_INITIAL_DEPTH; + dwDepthClearMax.uint32[3] = SHORTCUT_INITIAL_DEPTH; + VkImageSubresourceRange range{}; + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + range.layerCount = SHORTCUT_NUM_DEPTHS; + range.levelCount = 1; + vkCmdClearColorImage(commandBuffer, m_pFragmentDepthsTexture, VK_IMAGE_LAYOUT_GENERAL, + &dwDepthClearMax, 1, &range); + + { + VkRenderPassBeginInfo info{VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO}; + info.framebuffer = m_pFBRenderHair; + info.renderPass = m_pRPRenderHair; + info.renderArea.extent.height = height; + info.renderArea.extent.width = width; + VkClearValue clearValue[3]; + clearValue[0].depthStencil.stencil = 0; + // alpha + clearValue[1].color.float32[0] = 1; + clearValue[1].color.float32[1] = 1; + clearValue[1].color.float32[2] = 1; + clearValue[1].color.float32[3] = 1; + // color + clearValue[2].color.float32[0] = 0.; + clearValue[2].color.float32[1] = 0.; + clearValue[2].color.float32[2] = 0.; + clearValue[2].color.float32[3] = 0.; + info.clearValueCount = 3; + info.pClearValues = clearValue; + vkCmdBeginRenderPass(commandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE); + } +} + +void TressFXShortCut::SetupResolveDepth(VkDevice pvkDevice, VkCommandBuffer commandBuffer, + uint32_t width, uint32_t height) +{ + vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); +} + +void TressFXShortCut::SetupShadePass(VkDevice pvkDevice, VkCommandBuffer commandBuffer, + uint32_t width, uint32_t height) +{ + vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); +} + +void TressFXShortCut::SetupResolveColor(VkDevice pvkDevice, VkCommandBuffer commandBuffer, + uint32_t width, uint32_t height) +{ + vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); +} +} diff --git a/amd_tressfx_vulkan/src/TressFXShortCutVulkan.h b/amd_tressfx_vulkan/src/TressFXShortCutVulkan.h new file mode 100644 index 0000000..354a989 --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXShortCutVulkan.h @@ -0,0 +1,142 @@ +//-------------------------------------------------------------------------------------- +// File: TressFXShortCut.h +// +// Header file for TressFX ShortCut method. +// +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// +//-------------------------------------------------------------------------------------- + +#pragma once +#include "AMD_TressFX.h" +#include "Math\Vector3D.h" + +namespace AMD +{ +struct GPUOnlyStructuredBuffer +{ + GPUOnlyStructuredBuffer() : m_pBuffer(VK_NULL_HANDLE), m_pvkDevice(nullptr) {} + VkResult Create(VkDevice pd3dDevice, uint32_t structCount, uint32_t structSize); + void Destroy(); + + VkBuffer m_pBuffer; + + private: + VkDevice m_pvkDevice; +}; + +class TressFXShortCut +{ + private: + VkDevice m_pvkDevice; + VkDescriptorPool m_pDPShortcutPool; + + VkDescriptorSetLayout m_pSLDepthAlpha; + VkDescriptorSetLayout m_pSLColors; + + VkRenderPass m_pRPRenderHair; + VkFramebuffer m_pFBRenderHair; + + public: + VkPipelineLayout m_depthPassPipelineLayout; + VkPipelineLayout m_colorPassPipelineLayout; + VkDescriptorSet m_depthPassSet; + VkDescriptorSet m_colorPassSet; + // Pipelines for depth alpha + VkPipeline m_pPLRenderHairDepthsAlpha; + VkPipeline m_pPLRenderHairStrandCopiesDepthsAlpha; + VkPipeline m_pPLRenderHairAADepthsAlpha; + VkPipeline m_pPLRenderHairAAStrandCopiesDepthsAlpha; + // Pipeline for depth resolve + VkPipeline m_pPLDepthResolve; + // Pipelines for color filling + VkPipeline m_pPLRenderHairFillColors; + VkPipeline m_pPLRenderHairAAStrandCopiesFillColors; + VkPipeline m_pPLRenderHairAAFillColors; + VkPipeline m_pPLRenderHairStrandCopiesFillColors; + // Pipeline for color resolve + VkPipeline m_pPLColorResolve; + + VkImage m_pFragmentColorsTexture; + VkDeviceMemory m_pFragmentColorsMemory; + VkImageView m_pFragmentColorsView; + + VkImage m_pFragmentDepthsTexture; + VkDeviceMemory m_pFragmentDepthsMemory; + VkImageView m_pFragmentDepthsView; + + VkImage m_pAccumInvAlphaTexture; + VkDeviceMemory m_pAccumInvAlphaMemory; + VkImageView m_pAccumInvAlphaView; + + private: + GPUOnlyStructuredBuffer m_FragmentColors; + + VkResult CreateScreenSizedItems(VkDevice pvkDevice, int winWidth, int winHeight, + VkPhysicalDeviceMemoryProperties memProperties); + void DestroyScreenSizedItems(); + VkResult CreateRenderStateObjects(VkDevice pvkDevice, VkFormat depthStencilFormat, VkFormat colorFormat); + VkResult CreateLayouts(VkDevice pvkDevice, VkDescriptorSetLayout SLMesh, + VkSampler noiseSamplerRef, VkSampler shadowSamplerRef); + VkResult CreateFramebuffer(VkDevice pvkDevice, VkImageView depthStencilView, + VkImageView colorView, uint32_t width, uint32_t height); + VkResult AllocateAndPopulateSets(VkDevice pvkDevice, VkBuffer configBuffer, + uint64_t configBufferSize, VkImageView noiseMap, + VkImageView hairShadowMap); + + public: + TressFXShortCut(void) + : m_pFragmentColorsTexture(VK_NULL_HANDLE), m_pFragmentColorsMemory(VK_NULL_HANDLE), + m_pFragmentColorsView(VK_NULL_HANDLE), m_pFragmentDepthsTexture(VK_NULL_HANDLE), + m_pFragmentDepthsMemory(VK_NULL_HANDLE), m_pFragmentDepthsView(VK_NULL_HANDLE), + m_pAccumInvAlphaTexture(VK_NULL_HANDLE), m_pAccumInvAlphaMemory(VK_NULL_HANDLE), + m_pAccumInvAlphaView(VK_NULL_HANDLE) + { + } + ~TressFXShortCut(void){}; + + VkResult OnCreateDevice(VkDevice pvkDevice, int winWidth, int winHeight, + VkDescriptorSetLayout mesh_layout, VkSampler noiseSamplerRef, + VkSampler shadowSamplerRef, VkImageView depthStencilView, + VkImageView colorView, VkBuffer configBuffer, + uint64_t configBufferSize, VkImageView noiseMap, + VkImageView hairShadowMap, VkPhysicalDeviceMemoryProperties memProperties, + uint32_t width, uint32_t height, VkFormat depthStencilFormat, VkFormat colorFormat); + VkResult OnResizedSwapChain(VkDevice pvkDevice, int winWidth, int WinHeight, + VkPhysicalDeviceMemoryProperties memProperties); + + // Individual render pass setups. + // Each basically sets up render state, UAVs, SRVs, and returns pixel + // shader to use. + void SetupDepthPass(VkDevice pvkDevice, VkCommandBuffer commandBuffer, uint32_t width, + uint32_t height); + void SetupShadePass(VkDevice pvkDevice, VkCommandBuffer commandBuffer, uint32_t width, + uint32_t height); + void SetupResolveDepth(VkDevice pvkDevice, VkCommandBuffer commandBuffer, + uint32_t width, uint32_t height); + void SetupResolveColor(VkDevice pvkDevice, VkCommandBuffer commandBuffer, + uint32_t width, uint32_t height); + + void OnDestroy(bool destroyShaders); +}; + +} // namespace AMD diff --git a/amd_tressfx_vulkan/src/TressFXSimulationVulkan.cpp b/amd_tressfx_vulkan/src/TressFXSimulationVulkan.cpp new file mode 100644 index 0000000..d83c388 --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXSimulationVulkan.cpp @@ -0,0 +1,1194 @@ +//-------------------------------------------------------------------------------------- +// File: TressFXSimulation.cpp +// +// Hair physics simulation using DirectCompute +// +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// +//-------------------------------------------------------------------------------------- + +#include "TressFXSimulationVulkan.h" +#include "AMD_Types.h" +#include "Math\\Transform.h" +#include "TressFXMeshVulkan.h" +#include "TressFXPrecompiledShadersVulkan.h" +#include "UtilVulkan.h" + +#include + +using namespace DirectX; + +extern int g_TressFXNumVerticesPerStrand; + +struct TransformConstantBuffer +{ + DirectX::XMMATRIX ModelTransformForHead; +}; + +struct ConstBufferCS_Per_Frame +{ + float4 Wind; + float4 Wind1; + float4 Wind2; + float4 Wind3; + + int NumLengthConstraintIterations; + int bCollision; + + float GravityMagnitude; + float timeStep; + + float Damping0; + float StiffnessForLocalShapeMatching0; + float StiffnessForGlobalShapeMatching0; + float GlobalShapeMatchingEffectiveRange0; + + float Damping1; + float StiffnessForLocalShapeMatching1; + float StiffnessForGlobalShapeMatching1; + float GlobalShapeMatchingEffectiveRange1; + + float Damping2; + float StiffnessForLocalShapeMatching2; + float StiffnessForGlobalShapeMatching2; + float GlobalShapeMatchingEffectiveRange2; + + float Damping3; + float StiffnessForLocalShapeMatching3; + float StiffnessForGlobalShapeMatching3; + float GlobalShapeMatchingEffectiveRange3; + + unsigned int NumOfStrandsPerThreadGroup; + unsigned int NumFollowHairsPerGuideHair; + float TipSeparationFactor; + + int bWarp; + int NumLocalShapeMatchingIterations; + + int NumVerticesPerStrand; // should be 2^n (n is integer and greater and 3) and less + // than or equal to THREAD_GROUP_SIZE. i.e. 8, 16, 32 or 64 + float pad[2]; +}; + +struct ConstBufferCS_HeadTransform +{ + DirectX::XMMATRIX ModelTransformForHead; + XMVECTOR ModelRotateForHead; // quaternion + int bSingleHeadTransform; + float padding[3]; +}; + +namespace AMD +{ +//-------------------------------------------------------------------------------------- +// +// Constructor +// +//-------------------------------------------------------------------------------------- +TressFXSimulation::TressFXSimulation(void) +{ + m_CSIntegrationAndGlobalShapeConstraints = NULL; + m_CSApplyHairTransformGlobally = NULL; + m_CSComputeTangents = NULL; + m_CSLocalShapeConstraints = NULL; + m_CSLengthConstriantsWindAndCollision = NULL; + m_CSUpdateFollowHairVertices = NULL; + m_CSPrepareFollowHairBeforeTurningIntoGuide = NULL; + m_pCBCSPerFrame = NULL; + m_pCBCSCollisionCapsule = NULL; + m_pCBHeadTransforms = NULL; + + m_simParams.numLengthConstraintIterations = 2; + m_simParams.numLocalShapeMatchingIterations = 1; + m_simParams.gravityMagnitude = 9.82f; + + m_simParams.bCollision = true; + m_simParams.bGuideFollowSimulation = true; + m_bGuideFollowHairPrev = m_simParams.bGuideFollowSimulation; + + m_elapsedTimeSinceLastSim = 0; +} + +//-------------------------------------------------------------------------------------- +// +// Destructor +// +//-------------------------------------------------------------------------------------- +TressFXSimulation::~TressFXSimulation(void) {} + +namespace +{ +VkComputePipelineCreateInfo getComputePipelineInfo(VkPipelineLayout layout, + VkShaderModule computeShader) +{ + VkComputePipelineCreateInfo result{ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; + result.layout = layout; + result.stage.module = computeShader; + result.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + result.stage.pName = "main"; + result.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; + return result; +} +} + +namespace +{ +VkResult getPipelineLayout(VkDevice pvkDevice, VkDescriptorSetLayout configSetLayout, + VkDescriptorSetLayout secondSetLayout, + VkPipelineLayout &result) +{ + VkPipelineLayoutCreateInfo pipelineInfo{ + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; + VkDescriptorSetLayout setLayouts[] = { configSetLayout, secondSetLayout }; + pipelineInfo.setLayoutCount = AMD_ARRAY_SIZE(setLayouts); + pipelineInfo.pSetLayouts = setLayouts; + VkResult vr; + AMD_CHECKED_VULKAN_CALL(vkCreatePipelineLayout(pvkDevice, &pipelineInfo, nullptr, &result)); + return VK_SUCCESS; +} +} + +VkResult TressFXSimulation::CreateDescriptorSet(VkDevice pvkDevice) +{ + VkResult vr; + + const VkDescriptorSetLayoutBinding global_constraints_bindings[] = { + {IDSRV_HAIR_VERTEX_POSITIONS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_PREVIOUS_VERTEX_POSITIONS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_VERTEX_INITIAL_POSITIONS, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_STRAND_TYPE, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + }; + + const VkDescriptorSetLayoutBinding local_constraints_bindings[] = { + {IDSRV_HAIR_VERTEX_POSITIONS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_STRAND_TYPE, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_GLOBAL_ROTATION, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_LOCAL_REF_VEC, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + }; + + const VkDescriptorSetLayoutBinding length_wind_collision_bindings[] = { + {IDSRV_HAIR_VERTEX_POSITIONS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_STRAND_TYPE, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_LENGTH, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + }; + + const VkDescriptorSetLayoutBinding prepare_follow_hair_bindings[] = { + {IDSRV_HAIR_VERTEX_POSITIONS, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_PREVIOUS_VERTEX_POSITIONS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_STRAND_TYPE, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + }; + + const VkDescriptorSetLayoutBinding update_follow_hair_bindings[] = { + {IDSRV_HAIR_VERTEX_POSITIONS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_STRAND_TYPE, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_ROOT_OFFSET, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + }; + + const VkDescriptorSetLayoutBinding compute_tangent_bindings[] = { + {IDSRV_HAIR_VERTEX_POSITIONS, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_STRAND_TYPE, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HAIR_TANGENTS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + }; + + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, global_constraints_bindings, + AMD_ARRAY_SIZE(global_constraints_bindings), + m_GlobalConstraintsSetLayout)); + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, local_constraints_bindings, + AMD_ARRAY_SIZE(local_constraints_bindings), + m_LocalConstraintsSetLayout)); + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, length_wind_collision_bindings, + AMD_ARRAY_SIZE(length_wind_collision_bindings), + m_LenghtWindTangentSetLayout)); + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, prepare_follow_hair_bindings, + AMD_ARRAY_SIZE(prepare_follow_hair_bindings), + m_PrepareFollowHairSetLayout)); + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, update_follow_hair_bindings, + AMD_ARRAY_SIZE(update_follow_hair_bindings), + m_UpdateFollowHaitSetLayout)); + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, compute_tangent_bindings, + AMD_ARRAY_SIZE(compute_tangent_bindings), + m_ComputeTangentSetLayout)); + + const VkDescriptorSetLayoutBinding configBindings[] = { + {IDSRV_CONSTANTS_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1, + VK_SHADER_STAGE_COMPUTE_BIT}, + {IDSRV_HEAD_TRANSFORM, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, + VK_SHADER_STAGE_COMPUTE_BIT} }; + AMD_CHECKED_VULKAN_CALL(getDescriptorLayout(pvkDevice, configBindings, + AMD_ARRAY_SIZE(configBindings), m_configSetLayout)); + + AMD_CHECKED_VULKAN_CALL(getPipelineLayout(pvkDevice, m_configSetLayout, + m_GlobalConstraintsSetLayout, + m_CSIntegrationAndGlobalShapeConstraintsLayout)); + AMD_CHECKED_VULKAN_CALL(getPipelineLayout(pvkDevice, m_configSetLayout, + m_LocalConstraintsSetLayout, + m_CSLocalShapeConstraintsLayout)); + AMD_CHECKED_VULKAN_CALL(getPipelineLayout(pvkDevice, m_configSetLayout, + m_LocalConstraintsSetLayout, + m_CSLocalShapeConstraintsSingleDispatchLayout)); + AMD_CHECKED_VULKAN_CALL(getPipelineLayout(pvkDevice, m_configSetLayout, + m_LenghtWindTangentSetLayout, + m_CSLengthConstriantsWindAndCollisionLayout)); + AMD_CHECKED_VULKAN_CALL(getPipelineLayout(pvkDevice, m_configSetLayout, + m_PrepareFollowHairSetLayout, + m_CSPrepareFollowHairBeforeTurningIntoGuideLayout)); + AMD_CHECKED_VULKAN_CALL(getPipelineLayout(pvkDevice, m_configSetLayout, + m_UpdateFollowHaitSetLayout, + m_CSUpdateFollowHairVerticesLayout)); + AMD_CHECKED_VULKAN_CALL(getPipelineLayout(pvkDevice, m_configSetLayout, + m_ComputeTangentSetLayout, m_CSComputeTangentsLayout)); + + VkDescriptorPoolSize poolSizes[] = { {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1} }; + VkDescriptorPoolCreateInfo descriptorPoolInfo{ + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + descriptorPoolInfo.maxSets = 1; + descriptorPoolInfo.poolSizeCount = AMD_ARRAY_SIZE(poolSizes); + descriptorPoolInfo.pPoolSizes = poolSizes; + AMD_CHECKED_VULKAN_CALL(vkCreateDescriptorPool(pvkDevice, &descriptorPoolInfo, nullptr, + &m_descriptorPool)); + + VkDescriptorSetAllocateInfo allocInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; + allocInfo.descriptorSetCount = 1; + allocInfo.pSetLayouts = &m_configSetLayout; + allocInfo.descriptorPool = m_descriptorPool; + + AMD_CHECKED_VULKAN_CALL(vkAllocateDescriptorSets(pvkDevice, &allocInfo, &m_configSet)); + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// OnCreateDevice +// +// Called when the D3D device is being created. Creates the compute shaders and the D3D +// resources used for the hair simulation. +// +//-------------------------------------------------------------------------------------- +VkResult TressFXSimulation::OnCreateDevice(VkDevice pvkDevice, + TressFX_CollisionCapsule *pCollision, + uint32_t maxUniformCount, + VkPhysicalDeviceMemoryProperties memProperties, const DebugMarkerPointer& markerCallbacks) +{ + VkResult vr; + AMD_CHECKED_VULKAN_CALL(CreateDescriptorSet(pvkDevice)); + // reset m_elapsedTimeSinceLastSim to zero + m_elapsedTimeSinceLastSim = 0; + + ShaderModule IntegrationAndGlobalShapeConstraints_Module(pvkDevice, + global_constraints); + + ShaderModule ApplyHairTransformGlobally_Module(pvkDevice, global_constraints); + ShaderModule ComputeTangents_Module(pvkDevice, compute_tangents); + ShaderModule LocalShapeConstraints_Module(pvkDevice, local_constraints); + ShaderModule LocalShapeConstraintsWithIteration_Module(pvkDevice, local_constraints); + ShaderModule LengthConstraintsWindAndCollision_Module(pvkDevice, + length_wind_collision); + ShaderModule UpdateFollowHairVertices_Module(pvkDevice, update_follow_hair); + ShaderModule PrepareFollowHairBeforeTurningIntoGuide_Data(pvkDevice, + prepare_follow_hair); + + ShaderModule GenerateTransforms_Module(pvkDevice, global_constraints); + + VkComputePipelineCreateInfo computePipelineInfo[] = { + getComputePipelineInfo( + m_CSIntegrationAndGlobalShapeConstraintsLayout, + IntegrationAndGlobalShapeConstraints_Module.m_shaderModule), + getComputePipelineInfo(m_CSIntegrationAndGlobalShapeConstraintsLayout, + ApplyHairTransformGlobally_Module.m_shaderModule), + getComputePipelineInfo(m_CSComputeTangentsLayout, + ComputeTangents_Module.m_shaderModule), + getComputePipelineInfo(m_CSLocalShapeConstraintsSingleDispatchLayout, + LocalShapeConstraints_Module.m_shaderModule), + getComputePipelineInfo(m_CSLocalShapeConstraintsLayout, + LocalShapeConstraintsWithIteration_Module.m_shaderModule), + getComputePipelineInfo(m_CSLengthConstriantsWindAndCollisionLayout, + LengthConstraintsWindAndCollision_Module.m_shaderModule), + getComputePipelineInfo(m_CSUpdateFollowHairVerticesLayout, + UpdateFollowHairVertices_Module.m_shaderModule), + getComputePipelineInfo( + m_CSPrepareFollowHairBeforeTurningIntoGuideLayout, + PrepareFollowHairBeforeTurningIntoGuide_Data.m_shaderModule), + getComputePipelineInfo(m_CSIntegrationAndGlobalShapeConstraintsLayout, + GenerateTransforms_Module.m_shaderModule), + }; + + VkPipeline pipelines[9]{}; + AMD_CHECKED_VULKAN_CALL(vkCreateComputePipelines(pvkDevice, VK_NULL_HANDLE, + AMD_ARRAY_SIZE(computePipelineInfo), + computePipelineInfo, nullptr, pipelines)); + + m_CSIntegrationAndGlobalShapeConstraints = pipelines[0]; + markerCallbacks.nameObject(m_CSIntegrationAndGlobalShapeConstraints, "CSIntegrationAndGlobalShapeConstraints"); + m_CSApplyHairTransformGlobally = pipelines[1]; + markerCallbacks.nameObject(m_CSApplyHairTransformGlobally, "CSApplyHairTransformGlobally"); + m_CSComputeTangents = pipelines[2]; + markerCallbacks.nameObject(m_CSComputeTangents, "CSComputeTangents"); + m_CSLocalShapeConstraints = pipelines[3]; + markerCallbacks.nameObject(m_CSLocalShapeConstraints, "CSLocalShapeConstraints"); + m_CSLocalShapeConstraintsSingleDispatch = pipelines[4]; + markerCallbacks.nameObject(m_CSLocalShapeConstraintsSingleDispatch, "CSLocalShapeConstraintsSingleDispatch"); + m_CSLengthConstriantsWindAndCollision = pipelines[5]; + markerCallbacks.nameObject(m_CSLengthConstriantsWindAndCollision, "CSLengthConstriantsWindAndCollision"); + m_CSUpdateFollowHairVertices = pipelines[6]; + markerCallbacks.nameObject(m_CSUpdateFollowHairVertices, "CSUpdateFollowHairVertices"); + m_CSPrepareFollowHairBeforeTurningIntoGuide = pipelines[7]; + markerCallbacks.nameObject(m_CSPrepareFollowHairBeforeTurningIntoGuide, "CSPrepareFollowHairBeforeTurningIntoGuide"); + m_CSGenerateTransforms = pipelines[8]; + markerCallbacks.nameObject(m_CSGenerateTransforms, "CSGenerateTransforms"); + + //------------------------- + // Create constant buffers + //------------------------- + AMD_CHECKED_VULKAN_CALL(CreateComputeShaderConstantBuffers( + pvkDevice, pCollision, maxUniformCount, memProperties)); + + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// GenerateTransforms +// +// Create an array of transformation matrices, one for each hair strand, and an associated +// quaternion for the rotation. The transformations generated are based on the position +// of the skinned (deformed) model that the hair strands are on. These transformations +// can be used for simulating the positions and orientations of fur strands on an +// animated mesh. +// +//-------------------------------------------------------------------------------------- +// VkResult TressFXSimulation::GenerateTransforms(ID3D11DeviceContext* pd3dContext, +// TressFX_SceneMesh sceneMesh, +// ID3D11UnorderedAccessView** +// ppSkinningTransformationsUAV, +// XMMATRIX *pModelTransformForHead) +//{ +// VkResult vr = VK_SUCCESS; +// +// // update the constant buffers +// D3D11_MAPPED_SUBRESOURCE MappedResource; +// +// pd3dContext->Map(m_pCBCSPerFrame, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource); +// { +// ConstBufferCS_Per_Frame* pCSPerFrame = +// (ConstBufferCS_Per_Frame*)MappedResource.pData; +// +// int numOfStrandsPerThreadGroup = THREAD_GROUP_SIZE / +// m_pTressFXMesh->m_HairAsset.m_NumOfVerticesInStrand; +// pCSPerFrame->NumOfStrandsPerThreadGroup = numOfStrandsPerThreadGroup; +// pCSPerFrame->NumFollowHairsPerGuideHair = (m_bGuideFollowHairPrev ? +// m_pTressFXMesh->m_HairAsset.m_NumFollowHairsPerGuideHair : 0); +// } +// pd3dContext->Unmap(m_pCBCSPerFrame, 0); +// pd3dContext->CSSetConstantBuffers(0, 1, &m_pCBCSPerFrame); +// +// pd3dContext->Map(m_pCBGenerateTransforms, 0, D3D11_MAP_WRITE_DISCARD, 0, +// &MappedResource); +// { +// TransformConstantBuffer* pCSTransformCB = +// (TransformConstantBuffer*)MappedResource.pData; +// pCSTransformCB->ModelTransformForHead = *pModelTransformForHead; +// } +// pd3dContext->Unmap(m_pCBGenerateTransforms, 0); +// pd3dContext->CSSetConstantBuffers(4, 1, &m_pCBGenerateTransforms); +// +// //Set the shader resources +// ID3D11ShaderResourceView* ppSRV[3] = {sceneMesh.pMeshVertices, +// sceneMesh.pTransformedVerts, m_pTressFXMesh->m_HairSkinMappingSRV}; +// +// pd3dContext->CSSetShaderResources( 4, 3, ppSRV); +// +// //Bind unordered access views +// ID3D11UnorderedAccessView* ppUAV[4] = {m_pTressFXMesh->m_InitialHairPositionsUAV, 0, +// 0, m_pTressFXMesh->m_HairTransformsUAV}; +// pd3dContext->CSSetUnorderedAccessViews( 3, 4, ppUAV, NULL ); +// +// // execute the shader +// int numOfGroupsForCS_StrandLevel = (m_bGuideFollowHairPrev ? +// m_pTressFXMesh->m_HairAsset.m_NumGuideHairStrands : +// m_pTressFXMesh->m_HairAsset.m_NumTotalHairStrands); +// +// pd3dContext->CSSetShader(m_CSGenerateTransforms, NULL, 0 ); +// pd3dContext->Dispatch(numOfGroupsForCS_StrandLevel, 1, 1); +// +// *ppSkinningTransformationsUAV = m_pTressFXMesh->m_HairTransformsUAV; +// +// // unbind the resources +// ppSRV [0] = NULL; +// ppSRV [1] = NULL; +// ppSRV [2] = NULL; +// pd3dContext->CSSetShaderResources( 4, 3, ppSRV); +// +// ID3D11UnorderedAccessView* ppUAVNULL[4] = {NULL, NULL, NULL, NULL}; +// pd3dContext->CSSetUnorderedAccessViews( 3, 4, ppUAVNULL, NULL ); +// +// return vr; +//} + +//// Applies skin transforms to all hair so that hair would do rigid transform +// HRESULT TressFXSimulation::ApplyTransformGlobally(ID3D11DeviceContext* pd3dContext, +// ID3D11UnorderedAccessView* pSkinningTransforms, float density, bool +// singleHeadTransform, XMMATRIX *pModelTransformForHead) +//{ +// int numOfStrandsPerThreadGroup = THREAD_GROUP_SIZE / +// m_pTressFXMesh->m_HairAsset.m_NumOfVerticesInStrand; +// +// // ConstBufferCS_Per_Frame +// D3D11_MAPPED_SUBRESOURCE MappedResource; +// +// pd3dContext->Map(m_pCBCSPerFrame, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource); +// { +// ConstBufferCS_Per_Frame* pCSPerFrame = +// (ConstBufferCS_Per_Frame*)MappedResource.pData; +// pCSPerFrame->NumOfStrandsPerThreadGroup = numOfStrandsPerThreadGroup; +// pCSPerFrame->NumFollowHairsPerGuideHair = (m_bGuideFollowHairPrev ? +// m_pTressFXMesh->m_HairAsset.m_NumFollowHairsPerGuideHair : 0); +// pCSPerFrame->TipSeparationFactor = +// m_pTressFXMesh->m_HairAsset.m_TipSeparationFactor; +// pCSPerFrame->NumVerticesPerStrand = g_TressFXNumVerticesPerStrand; +// } +// pd3dContext->Unmap(m_pCBCSPerFrame, 0); +// +// // ConstBufferCS_HeadTransform +// pd3dContext->Map(m_pCBHeadTransforms, 0, D3D11_MAP_WRITE_DISCARD, 0, +// &MappedResource); +// { +// ConstBufferCS_HeadTransform* pCSHeadTransform = +// (ConstBufferCS_HeadTransform*)MappedResource.pData; +// pCSHeadTransform->bSingleHeadTransform = singleHeadTransform; +// pCSHeadTransform->ModelRotateForHead = +// XMQuaternionRotationMatrix(*pModelTransformForHead); +// pCSHeadTransform->ModelTransformForHead = *pModelTransformForHead; +// } +// pd3dContext->Unmap(m_pCBHeadTransforms, 0); +// +// // set const buffers +// pd3dContext->CSSetConstantBuffers(0, 1, &m_pCBCSPerFrame); +// pd3dContext->CSSetConstantBuffers(5, 1, &m_pCBHeadTransforms); +// +// //Set the shader resources +// ID3D11ShaderResourceView* ppSRV[4] = { NULL, NULL, NULL, +// m_pTressFXMesh->m_FollowHairRootOffsetSRV }; +// pd3dContext->CSSetShaderResources(0, 4, ppSRV); +// +// //Bind unordered access views +// ID3D11UnorderedAccessView* ppUAV[8] = +// { +// m_pTressFXMesh->m_HairVertexPositionsUAV, +// m_pTressFXMesh->m_HairVertexPositionsPrevUAV, +// m_pTressFXMesh->m_HairVertexTangentsUAV, +// m_pTressFXMesh->m_InitialHairPositionsUAV, +// m_pTressFXMesh->m_GlobalRotationsUAV, +// m_pTressFXMesh->m_LocalRotationsUAV, +// pSkinningTransforms +// }; +// +// UINT initCounts = 0; +// pd3dContext->CSSetUnorderedAccessViews(0, 8, ppUAV, &initCounts); +// +// //======= Run the compute shader ======= +// int numOfGroupsForCS_VertexLevel = (int)(((float)(m_bGuideFollowHairPrev ? +// m_pTressFXMesh->m_HairAsset.m_NumGuideHairVertices : +// m_pTressFXMesh->m_HairAsset.m_NumTotalHairVertices) / +//(float)THREAD_GROUP_SIZE)*density); +// +// // One thread computes one vertex +// pd3dContext->CSSetShader(m_CSApplyHairTransformGlobally, NULL, 0); +// pd3dContext->Dispatch(numOfGroupsForCS_VertexLevel, 1, 1); +// +// // Update follow hair vertices +// // One thread computes one vertex +// if (m_bGuideFollowHairPrev) +// { +// pd3dContext->CSSetShader(m_CSUpdateFollowHairVertices, NULL, 0); +// pd3dContext->Dispatch(numOfGroupsForCS_VertexLevel, 1, 1); +// } +// +// // Compute tangents for every vertex (guide + follow) +// int numOfGroupsForCS_TotalVertexLevel = +//(int)(((float)(m_pTressFXMesh->m_HairAsset.m_NumTotalHairVertices) / +//(float)THREAD_GROUP_SIZE)*density); +// pd3dContext->CSSetShader(m_CSComputeTangents, NULL, 0); +// pd3dContext->Dispatch(numOfGroupsForCS_TotalVertexLevel, 1, 1); +// +// // Unbind resources for CS +// ID3D11UnorderedAccessView* ppUAViewNULL[8] = { NULL, NULL, NULL, NULL, NULL, NULL, +// NULL, NULL }; +// pd3dContext->CSSetUnorderedAccessViews(0, 8, ppUAViewNULL, &initCounts); +// +// ID3D11ShaderResourceView* ppSRVNULL[4] = { NULL, NULL, NULL, NULL }; +// pd3dContext->CSSetShaderResources(0, 4, ppSRVNULL); +// +// return S_OK; +//} + +const float MATH_PI2 = 3.14159265359f; +#define DEG_TO_RAD2(d) (d * MATH_PI2 / 180) + +//-------------------------------------------------------------------------------------- +// +// ComputeWindPyramid +// +// Wind noise is generated using blends of four vectors. The four vectors are +// generated from some angle around winDir. This code generates the four vectors. +// Shader code generates the per-strand noise from these vectors. +// +// This function currently has some hard coded constants, including a hard-coded +// sin function for magnitude based on frame count. This will be changed in the next +// major update, but we maintain it in 3.1 for compatibility. +// +//-------------------------------------------------------------------------------------- +void ComputeWindPyramid(float4 &wind, float4 &wind1, float4 &wind2, float4 &wind3, + const float windMag, const tressfx_vec3 &windDir) +{ + static int frame = 0; + + float wM = windMag * (pow(sin(frame * 0.05f), 2.0f) + 0.5f); + + tressfx_vec3 windDirN(windDir); + windDirN.Normalize(); + + tressfx_vec3 XAxis(1.0f, 0, 0); + tressfx_vec3 xCrossW = XAxis.Cross(windDirN); + + tressfx_quat rotFromXAxisToWindDir; + rotFromXAxisToWindDir.SetIdentity(); + + float angle = asin(xCrossW.Length()); + + if (angle > 0.001) + { + rotFromXAxisToWindDir.SetRotation(xCrossW.Normalize(), angle); + } + + float angleToWideWindCone = DEG_TO_RAD2(40.f); + + { + tressfx_vec3 rotAxis(0, 1.0f, 0); + + tressfx_quat rot(rotAxis, angleToWideWindCone); + tressfx_vec3 windVec = rotFromXAxisToWindDir * rot * XAxis * wM; + wind = float4(windVec.x, windVec.y, windVec.z, (float)frame); + } + + { + tressfx_vec3 rotAxis(0, -1.0f, 0); + tressfx_quat rot(rotAxis, angleToWideWindCone); + tressfx_vec3 windVec = rotFromXAxisToWindDir * rot * XAxis * wM; + wind1 = float4(windVec.x, windVec.y, windVec.z, (float)frame); + } + + { + tressfx_vec3 rotAxis(0, 0, 1.0f); + tressfx_quat rot(rotAxis, angleToWideWindCone); + tressfx_vec3 windVec = rotFromXAxisToWindDir * rot * XAxis * wM; + wind2 = float4(windVec.x, windVec.y, windVec.z, (float)frame); + } + + { + tressfx_vec3 rotAxis(0, 0, -1.0f); + tressfx_quat rot(rotAxis, angleToWideWindCone); + tressfx_vec3 windVec = rotFromXAxisToWindDir * rot * XAxis * wM; + wind3 = float4(windVec.x, windVec.y, windVec.z, (float)frame); + } + + frame++; +} + +// scale the stiffness value based on current and target frames rates and minimum +// stiffness value. +float getScaledStiffness(float s0, float s_min_scale, float h, float h0) +{ + float s_min = s0 * s_min_scale; + float s = ((s0 - s_min) / h0) * h + s_min; + return s; +} + +//-------------------------------------------------------------------------------------- +// +// Simulate +// +// Runs the hair simulation which will animate the hair vertices. This function calls +// Dispatch to execute compute shaders that implement the simulation. +// +////-------------------------------------------------------------------------------------- +VkResult TressFXSimulation::Simulate(VkDevice pvkDevice, VkCommandBuffer commandBuffer, + float fElapsedTime, float density, + tressfx_vec3 &windDir, float windMag, + XMMATRIX *pModelTransformForHead, + float targetFrameRate, bool singleHeadTransform, + bool warp, uint32_t uniformBufferIndex, + const DebugMarkerPointer& markerCallbacks) +{ + m_elapsedTimeSinceLastSim += fElapsedTime; + bool bFullSimulate = true; + + // Simulation is sensitive to frame rate. So, we set the target frame rate (defaulted + // to 1/60) + // and if the current elapsed time since the last simulation is too early, + // we run the simulation with lower iterations and stiffness values. + if ((m_elapsedTimeSinceLastSim < targetFrameRate) && !warp) + { + bFullSimulate = false; + } + else + { + m_elapsedTimeSinceLastSim = 0; + } + + VkResult vr = VK_SUCCESS; + + int numOfStrandsPerThreadGroup = + THREAD_GROUP_SIZE / m_pTressFXMesh->m_HairAsset.m_NumOfVerticesInStrand; + + ConstBufferCS_Per_Frame *pCSPerFrame; + vkMapMemory(pvkDevice, m_pCBCSPerFrameMemory, + uniformBufferIndex * sizeof(ConstBufferCS_Per_Frame), + sizeof(ConstBufferCS_Per_Frame), 0, + reinterpret_cast(&pCSPerFrame)); + + fillConstantBuffer(pCSPerFrame, warp, bFullSimulate, targetFrameRate, numOfStrandsPerThreadGroup, windMag, windDir, fElapsedTime); + vkUnmapMemory(pvkDevice, m_pCBCSPerFrameMemory); + + // ConstBufferCS_HeadTransform + ConstBufferCS_HeadTransform *pCSHeadTransform; + AMD_CHECKED_VULKAN_CALL(vkMapMemory(pvkDevice, m_pCBHeadTransformsMemory, 0, + sizeof(ConstBufferCS_HeadTransform), 0, + reinterpret_cast(&pCSHeadTransform))); + fillHeadConstantBuffer(pCSHeadTransform, singleHeadTransform, pModelTransformForHead); + vkUnmapMemory(pvkDevice, m_pCBHeadTransformsMemory); + + markerCallbacks.markBeginRegion(commandBuffer, "Simulation"); + fillSimulationCommands(commandBuffer, density, uniformBufferIndex); + markerCallbacks.markEndRegion(commandBuffer); + + return vr; +} + +void TressFXSimulation::fillSimulationCommands(const VkCommandBuffer &commandBuffer, float &density, const uint32_t &uniformBufferIndex) +{ + VkBufferMemoryBarrier bufferBarrier[] = { + getBufferBarrier(m_pCBCSPerFrame, VK_ACCESS_HOST_WRITE_BIT, + VK_ACCESS_UNIFORM_READ_BIT), + getBufferBarrier(m_pCBHeadTransforms, VK_ACCESS_HOST_WRITE_BIT, + VK_ACCESS_UNIFORM_READ_BIT), + }; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_HOST_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(bufferBarrier), bufferBarrier, 0, nullptr); + + //======= Run the compute shader ======= + + // Increase density a little bit (0.05) to hide popping. This allows simulation to + // take more hair than rendering and gives a chance + // to simulate hairs before they get rendered so that there will be enough time for + // popping to disappear. + density += 0.05f; + + if (density > 1.0f) + { + density = 1.0f; + } + + int numOfGroupsForCS_VertexLevel = + (int)(((float)(m_bGuideFollowHairPrev + ? m_pTressFXMesh->m_HairAsset.m_NumGuideHairVertices + : m_pTressFXMesh->m_HairAsset.m_NumTotalHairVertices) / + (float)THREAD_GROUP_SIZE) * + density); + + uint32_t descriptorOffset[] = { uniformBufferIndex * sizeof(ConstBufferCS_Per_Frame) }; + + // Prepare follow hair vertices before they are turning into guide ones. + // One thread computes one vertex + if (m_bGuideFollowHairPrev && !m_simParams.bGuideFollowSimulation) + { + VkDescriptorSet prepareFollowHairSets[] = { + m_configSet, m_pTressFXMesh->m_PrepareFollowHairSet }; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSPrepareFollowHairBeforeTurningIntoGuideLayout, 0, + AMD_ARRAY_SIZE(prepareFollowHairSets), + prepareFollowHairSets, AMD_ARRAY_SIZE(descriptorOffset), + descriptorOffset); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSPrepareFollowHairBeforeTurningIntoGuide); + vkCmdDispatch(commandBuffer, numOfGroupsForCS_VertexLevel, 1, 1); + + VkBufferMemoryBarrier flushPrevPositionBarrier[] = { getBufferBarrier( + m_pTressFXMesh->m_HairVertexPositionsPrevBuffer, VK_ACCESS_MEMORY_WRITE_BIT, + VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT) }; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(flushPrevPositionBarrier), + flushPrevPositionBarrier, 0, nullptr); + } + + // Integrate and global shape constraints + // One thread computes one vertex + VkDescriptorSet globalConstraintSets[] = { m_configSet, + m_pTressFXMesh->m_GlobalConstraintsSet }; + + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSIntegrationAndGlobalShapeConstraintsLayout, 0, + AMD_ARRAY_SIZE(globalConstraintSets), globalConstraintSets, + AMD_ARRAY_SIZE(descriptorOffset), descriptorOffset); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSIntegrationAndGlobalShapeConstraints); + vkCmdDispatch(commandBuffer, numOfGroupsForCS_VertexLevel, 1, 1); + + VkBufferMemoryBarrier globalConstraintsBarriers[] = { + getBufferBarrier(m_pTressFXMesh->m_HairVertexPositionsBuffer, + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT), + getBufferBarrier(m_pTressFXMesh->m_HairVertexPositionsPrevBuffer, + VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_SHADER_READ_BIT) }; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(globalConstraintsBarriers), + globalConstraintsBarriers, 0, nullptr); + + // Local shape constraints. If the hair is very curly, increase the iteration so that + // hair style can be preserved well. + // One thread computes one strand + + // If more than 16 vertices per strand, iterate on the CPU + if (g_TressFXNumVerticesPerStrand >= 16) + { + for (int iteration = 0; iteration < m_simParams.numLocalShapeMatchingIterations; + iteration++) + { + int numOfGroupsForCS_StrandLevel = + (int)(((float)(m_bGuideFollowHairPrev + ? m_pTressFXMesh->m_HairAsset.m_NumGuideHairStrands + : m_pTressFXMesh->m_HairAsset.m_NumTotalHairStrands) / + (float)THREAD_GROUP_SIZE) * + density); + VkDescriptorSet localConstraintSets[] = { + m_configSet, m_pTressFXMesh->m_LocalConstraintsSet }; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSLocalShapeConstraintsSingleDispatchLayout, 0, + AMD_ARRAY_SIZE(localConstraintSets), + localConstraintSets, AMD_ARRAY_SIZE(descriptorOffset), + descriptorOffset); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSLocalShapeConstraints); + vkCmdDispatch(commandBuffer, numOfGroupsForCS_StrandLevel, 1, 1); + + VkBufferMemoryBarrier localBarrier[] = { + getBufferBarrier(m_pTressFXMesh->m_HairVertexPositionsBuffer, + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT) }; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(localBarrier), localBarrier, 0, nullptr); + } + } + else + { + int numOfGroupsForCS_StrandLevel = + (int)(((float)(m_bGuideFollowHairPrev + ? m_pTressFXMesh->m_HairAsset.m_NumGuideHairStrands + : m_pTressFXMesh->m_HairAsset.m_NumTotalHairStrands) / + (float)THREAD_GROUP_SIZE) * + density); + VkDescriptorSet localConstraintSets[] = { m_configSet, + m_pTressFXMesh->m_LocalConstraintsSet }; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSLocalShapeConstraintsSingleDispatchLayout, 0, + AMD_ARRAY_SIZE(localConstraintSets), localConstraintSets, + AMD_ARRAY_SIZE(descriptorOffset), descriptorOffset); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSLocalShapeConstraintsSingleDispatch); + vkCmdDispatch(commandBuffer, numOfGroupsForCS_StrandLevel, 1, 1); + + VkBufferMemoryBarrier localBarrier[] = { + getBufferBarrier(m_pTressFXMesh->m_HairVertexPositionsBuffer, + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT) }; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(localBarrier), localBarrier, 0, nullptr); + } + + // Edge length constraints, wind and collisions + // One thread computes one vertex + VkDescriptorSet lengthWindCollisionSets[] = { + m_configSet, m_pTressFXMesh->m_LenghtWindCollisionSet }; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSLengthConstriantsWindAndCollisionLayout, 0, + AMD_ARRAY_SIZE(lengthWindCollisionSets), + lengthWindCollisionSets, AMD_ARRAY_SIZE(descriptorOffset), + descriptorOffset); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSLengthConstriantsWindAndCollision); + vkCmdDispatch(commandBuffer, numOfGroupsForCS_VertexLevel, 1, 1); + + VkBufferMemoryBarrier lengthWindCollisionBarriers[] = { + getBufferBarrier(m_pTressFXMesh->m_HairVertexPositionsBuffer, + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT) }; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(lengthWindCollisionBarriers), + lengthWindCollisionBarriers, 0, nullptr); + + // Update follow hair vertices + // One thread computes one vertex + if (m_bGuideFollowHairPrev) + { + VkDescriptorSet updateFollowHairSets[] = { m_configSet, + m_pTressFXMesh->m_UpdateFollowHairSet }; + vkCmdBindDescriptorSets( + commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSUpdateFollowHairVerticesLayout, 0, AMD_ARRAY_SIZE(updateFollowHairSets), + updateFollowHairSets, AMD_ARRAY_SIZE(descriptorOffset), descriptorOffset); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSUpdateFollowHairVertices); + vkCmdDispatch(commandBuffer, numOfGroupsForCS_VertexLevel, 1, 1); + + VkBufferMemoryBarrier updateFollowHairBarriers[] = { + getBufferBarrier(m_pTressFXMesh->m_HairVertexPositionsBuffer, + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_SHADER_READ_BIT), + getBufferBarrier( + m_pTressFXMesh->m_HairVertexTangentsBuffer, VK_ACCESS_MEMORY_READ_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT) + }; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(updateFollowHairBarriers), + updateFollowHairBarriers, 0, nullptr); + } + else + { + VkBufferMemoryBarrier makeTangentBarrier[] = { getBufferBarrier( + m_pTressFXMesh->m_HairVertexTangentsBuffer, VK_ACCESS_MEMORY_READ_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT) }; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(makeTangentBarrier), makeTangentBarrier, 0, + nullptr); + } + + // Compute tangents for every vertex (guide + follow) + { + int numOfGroupsForCS_TotalVertexLevel = + (int)(((float)(m_pTressFXMesh->m_HairAsset.m_NumTotalHairVertices) / + (float)THREAD_GROUP_SIZE) * + density); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSComputeTangents); + VkDescriptorSet computeTangentSet[] = { m_configSet, + m_pTressFXMesh->m_ComputeTangentSet }; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, + m_CSComputeTangentsLayout, 0, + AMD_ARRAY_SIZE(computeTangentSet), computeTangentSet, + AMD_ARRAY_SIZE(descriptorOffset), descriptorOffset); + vkCmdDispatch(commandBuffer, numOfGroupsForCS_TotalVertexLevel, 1, 1); + + VkBufferMemoryBarrier computeTangentBarrier[] = { + getBufferBarrier(m_pTressFXMesh->m_HairVertexTangentsBuffer, + VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT) }; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, + AMD_ARRAY_SIZE(computeTangentBarrier), computeTangentBarrier, + 0, nullptr); + } +} + +void TressFXSimulation::fillHeadConstantBuffer(ConstBufferCS_HeadTransform * pCSHeadTransform, bool singleHeadTransform, DirectX::XMMATRIX * pModelTransformForHead) +{ + pCSHeadTransform->bSingleHeadTransform = singleHeadTransform; + pCSHeadTransform->ModelRotateForHead = + XMQuaternionRotationMatrix(*pModelTransformForHead); + pCSHeadTransform->ModelTransformForHead = *pModelTransformForHead; +} + +void TressFXSimulation::fillConstantBuffer(ConstBufferCS_Per_Frame * pCSPerFrame, bool warp, bool bFullSimulate, float targetFrameRate, int numOfStrandsPerThreadGroup, float windMag, AMD::tressfx_vec3 & windDir, float fElapsedTime) +{ + pCSPerFrame->bWarp = warp; + + if (bFullSimulate) + { + pCSPerFrame->NumLengthConstraintIterations = + m_simParams.numLengthConstraintIterations; + } + else + { + pCSPerFrame->NumLengthConstraintIterations = 1; + } + + pCSPerFrame->bCollision = (m_simParams.bCollision == true) ? 1 : 0; + + pCSPerFrame->GravityMagnitude = m_simParams.gravityMagnitude; + + pCSPerFrame->timeStep = targetFrameRate; + + pCSPerFrame->NumOfStrandsPerThreadGroup = numOfStrandsPerThreadGroup; + pCSPerFrame->NumFollowHairsPerGuideHair = + (m_bGuideFollowHairPrev + ? m_pTressFXMesh->m_HairAsset.m_NumFollowHairsPerGuideHair + : 0); + pCSPerFrame->TipSeparationFactor = + m_pTressFXMesh->m_HairAsset.m_TipSeparationFactor; + + ComputeWindPyramid(pCSPerFrame->Wind, pCSPerFrame->Wind1, pCSPerFrame->Wind2, + pCSPerFrame->Wind3, windMag, windDir); + + int numSections = m_simParams.numHairSections; + + switch (numSections) + { + // hair section 3 + case 4: + pCSPerFrame->Damping3 = m_simParams.perSectionShapeParams[3].damping; + pCSPerFrame->StiffnessForLocalShapeMatching3 = + m_simParams.perSectionShapeParams[3].stiffnessForLocalShapeMatching; + pCSPerFrame->StiffnessForGlobalShapeMatching3 = + m_simParams.perSectionShapeParams[3].stiffnessForGlobalShapeMatching; + pCSPerFrame->GlobalShapeMatchingEffectiveRange3 = + m_simParams.perSectionShapeParams[3].globalShapeMatchingEffectiveRange; + // hair section 2 + case 3: + pCSPerFrame->Damping2 = m_simParams.perSectionShapeParams[2].damping; + pCSPerFrame->StiffnessForLocalShapeMatching2 = + m_simParams.perSectionShapeParams[2].stiffnessForLocalShapeMatching; + pCSPerFrame->StiffnessForGlobalShapeMatching2 = + m_simParams.perSectionShapeParams[2].stiffnessForGlobalShapeMatching; + pCSPerFrame->GlobalShapeMatchingEffectiveRange2 = + m_simParams.perSectionShapeParams[2].globalShapeMatchingEffectiveRange; + // hair section 1 + case 2: + pCSPerFrame->Damping1 = m_simParams.perSectionShapeParams[1].damping; + pCSPerFrame->StiffnessForLocalShapeMatching1 = + m_simParams.perSectionShapeParams[1].stiffnessForLocalShapeMatching; + pCSPerFrame->StiffnessForGlobalShapeMatching1 = + m_simParams.perSectionShapeParams[1].stiffnessForGlobalShapeMatching; + pCSPerFrame->GlobalShapeMatchingEffectiveRange1 = + m_simParams.perSectionShapeParams[1].globalShapeMatchingEffectiveRange; + // hair section 0 + case 1: + pCSPerFrame->Damping0 = m_simParams.perSectionShapeParams[0].damping; + pCSPerFrame->StiffnessForLocalShapeMatching0 = + m_simParams.perSectionShapeParams[0].stiffnessForLocalShapeMatching; + pCSPerFrame->StiffnessForGlobalShapeMatching0 = + m_simParams.perSectionShapeParams[0].stiffnessForGlobalShapeMatching; + pCSPerFrame->GlobalShapeMatchingEffectiveRange0 = + m_simParams.perSectionShapeParams[0].globalShapeMatchingEffectiveRange; + } + + if (!bFullSimulate) + { + float h = fElapsedTime; + float h0 = targetFrameRate; + float s_min_scale = + 0.3f; // minimum stiffness = s_min_scale * current stiffness + + pCSPerFrame->StiffnessForLocalShapeMatching0 = getScaledStiffness( + m_simParams.perSectionShapeParams[0].stiffnessForLocalShapeMatching, + s_min_scale, h, h0); + pCSPerFrame->StiffnessForLocalShapeMatching1 = getScaledStiffness( + m_simParams.perSectionShapeParams[1].stiffnessForLocalShapeMatching, + s_min_scale, h, h0); + pCSPerFrame->StiffnessForLocalShapeMatching2 = getScaledStiffness( + m_simParams.perSectionShapeParams[2].stiffnessForLocalShapeMatching, + s_min_scale, h, h0); + pCSPerFrame->StiffnessForLocalShapeMatching3 = getScaledStiffness( + m_simParams.perSectionShapeParams[3].stiffnessForLocalShapeMatching, + s_min_scale, h, h0); + } + + if (bFullSimulate) + { + pCSPerFrame->NumLocalShapeMatchingIterations = + m_simParams.numLocalShapeMatchingIterations; + } + else + { + pCSPerFrame->NumLocalShapeMatchingIterations = 1; + } + + pCSPerFrame->NumVerticesPerStrand = g_TressFXNumVerticesPerStrand; +} + +//-------------------------------------------------------------------------------------- +// +// CreateComputeShaderConstantBuffers +// +// Called by OnCreateDevice to allocate a constant buffer used by the compute shader code +// +//-------------------------------------------------------------------------------------- +VkResult TressFXSimulation::CreateComputeShaderConstantBuffers( + VkDevice pvkDevice, TressFX_CollisionCapsule *pCollision, + uint32_t maxUniformBufferCount, VkPhysicalDeviceMemoryProperties memProperties) +{ + (void)pCollision; + VkResult vr = VK_SUCCESS; + // const buffer for per frame data + VkBufferCreateInfo Desc{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + // FIXME: Uniform buffer + compute shader crash nvidia driver + Desc.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + Desc.size = maxUniformBufferCount * sizeof(ConstBufferCS_Per_Frame); + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &Desc, nullptr, &m_pCBCSPerFrame)); + m_pCBCSPerFrameMemory = + allocBufferMemory(pvkDevice, m_pCBCSPerFrame, memProperties, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + // const buffer for capsule collision + Desc.size = sizeof(TressFX_CollisionCapsule); + // data.pSysMem = (void *)pCollision; + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &Desc, nullptr, &m_pCBCSCollisionCapsule)); + m_pCBCSCollisionCapsuleMemory = + allocBufferMemory(pvkDevice, m_pCBCSCollisionCapsule, memProperties, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + /* void* scratch_buffer_mapped_memory; + vkMapMemory(pvkDevice, ..., 0, sizeof(TressFX_CollisionCapsule), 0, + &scratch_buffer_mapped_memory); + memcpy(scratch_buffer_mapped_memory, pCollision, + sizeof(TressFX_CollisionCapsule)); + vkUnmapMemory(pvkDevice, ...); + vkCmdCopyBuffer(..., ..., m_pCBCSCollisionCapsule, 1, );*/ + + // const buffer for hair root transformation + Desc.size = sizeof(TransformConstantBuffer); + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &Desc, nullptr, &m_pCBGenerateTransforms)); + m_pCBGenerateTransformsMemory = + allocBufferMemory(pvkDevice, m_pCBGenerateTransforms, memProperties, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + // const buffer for head transformation + Desc.size = sizeof(ConstBufferCS_HeadTransform); + AMD_CHECKED_VULKAN_CALL(vkCreateBuffer(pvkDevice, &Desc, nullptr, &m_pCBHeadTransforms)); + m_pCBHeadTransformsMemory = + allocBufferMemory(pvkDevice, m_pCBHeadTransforms, memProperties, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + VkDescriptorBufferInfo perFrameCBCS{ m_pCBCSPerFrame, 0, + sizeof(ConstBufferCS_Per_Frame) }; + VkDescriptorBufferInfo headTransform{ m_pCBHeadTransforms, 0, + sizeof(ConstBufferCS_HeadTransform) }; + VkWriteDescriptorSet writeSet[] = { + getWriteDescriptor(m_configSet, IDSRV_CONSTANTS_BUFFER, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, &perFrameCBCS), + getWriteDescriptor(m_configSet, IDSRV_HEAD_TRANSFORM, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &headTransform), + }; + vkUpdateDescriptorSets(pvkDevice, AMD_ARRAY_SIZE(writeSet), writeSet, 0, nullptr); + return VK_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// OnDestroy +// +// Called when the D3D device is being destroyed +// +//-------------------------------------------------------------------------------------- +void TressFXSimulation::OnDestroy(VkDevice pvkDevice) +{ + { + AMD_SAFE_RELEASE(m_CSIntegrationAndGlobalShapeConstraints, vkDestroyPipeline, + pvkDevice); + AMD_SAFE_RELEASE(m_CSApplyHairTransformGlobally, vkDestroyPipeline, pvkDevice); + AMD_SAFE_RELEASE(m_CSComputeTangents, vkDestroyPipeline, pvkDevice); + AMD_SAFE_RELEASE(m_CSLocalShapeConstraints, vkDestroyPipeline, pvkDevice); + AMD_SAFE_RELEASE(m_CSLocalShapeConstraintsSingleDispatch, vkDestroyPipeline, + pvkDevice); + AMD_SAFE_RELEASE(m_CSLengthConstriantsWindAndCollision, vkDestroyPipeline, + pvkDevice); + AMD_SAFE_RELEASE(m_CSUpdateFollowHairVertices, vkDestroyPipeline, pvkDevice); + AMD_SAFE_RELEASE(m_CSPrepareFollowHairBeforeTurningIntoGuide, vkDestroyPipeline, + pvkDevice); + AMD_SAFE_RELEASE(m_CSGenerateTransforms, vkDestroyPipeline, pvkDevice); + + AMD_SAFE_RELEASE(m_CSIntegrationAndGlobalShapeConstraintsLayout, + vkDestroyPipelineLayout, pvkDevice); + // AMD_SAFE_RELEASE(m_CSApplyHairTransformGloballyLayout, vkDestroyPipelineLayout, + // pvkDevice); + AMD_SAFE_RELEASE(m_CSComputeTangentsLayout, vkDestroyPipelineLayout, pvkDevice); + AMD_SAFE_RELEASE(m_CSLocalShapeConstraintsLayout, vkDestroyPipelineLayout, + pvkDevice); + AMD_SAFE_RELEASE(m_CSLocalShapeConstraintsSingleDispatchLayout, + vkDestroyPipelineLayout, pvkDevice); + AMD_SAFE_RELEASE(m_CSLengthConstriantsWindAndCollisionLayout, + vkDestroyPipelineLayout, pvkDevice); + AMD_SAFE_RELEASE(m_CSUpdateFollowHairVerticesLayout, vkDestroyPipelineLayout, + pvkDevice); + AMD_SAFE_RELEASE(m_CSPrepareFollowHairBeforeTurningIntoGuideLayout, + vkDestroyPipelineLayout, pvkDevice); + // AMD_SAFE_RELEASE(m_CSGenerateTransformsLayout, vkDestroyPipelineLayout, + // pvkDevice); + + AMD_SAFE_RELEASE(m_GlobalConstraintsSetLayout, vkDestroyDescriptorSetLayout, + pvkDevice); + AMD_SAFE_RELEASE(m_LocalConstraintsSetLayout, vkDestroyDescriptorSetLayout, + pvkDevice); + AMD_SAFE_RELEASE(m_LenghtWindTangentSetLayout, vkDestroyDescriptorSetLayout, + pvkDevice); + AMD_SAFE_RELEASE(m_PrepareFollowHairSetLayout, vkDestroyDescriptorSetLayout, + pvkDevice); + AMD_SAFE_RELEASE(m_UpdateFollowHaitSetLayout, vkDestroyDescriptorSetLayout, + pvkDevice); + AMD_SAFE_RELEASE(m_ComputeTangentSetLayout, vkDestroyDescriptorSetLayout, + pvkDevice); + AMD_SAFE_RELEASE(m_configSetLayout, vkDestroyDescriptorSetLayout, pvkDevice); + } + AMD_SAFE_RELEASE(m_descriptorPool, vkDestroyDescriptorPool, pvkDevice); + AMD_SAFE_RELEASE(m_pCBCSPerFrame, vkDestroyBuffer, pvkDevice); + AMD_SAFE_RELEASE(m_pCBCSPerFrameMemory, vkFreeMemory, pvkDevice); + AMD_SAFE_RELEASE(m_pCBCSCollisionCapsule, vkDestroyBuffer, pvkDevice); + AMD_SAFE_RELEASE(m_pCBCSCollisionCapsuleMemory, vkFreeMemory, pvkDevice); + AMD_SAFE_RELEASE(m_pCBGenerateTransforms, vkDestroyBuffer, pvkDevice); + AMD_SAFE_RELEASE(m_pCBGenerateTransformsMemory, vkFreeMemory, pvkDevice); + AMD_SAFE_RELEASE(m_pCBHeadTransforms, vkDestroyBuffer, pvkDevice); + AMD_SAFE_RELEASE(m_pCBHeadTransformsMemory, vkFreeMemory, pvkDevice); +} +} // namespace AMD diff --git a/amd_tressfx_vulkan/src/TressFXSimulationVulkan.h b/amd_tressfx_vulkan/src/TressFXSimulationVulkan.h new file mode 100644 index 0000000..39f1dc8 --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXSimulationVulkan.h @@ -0,0 +1,128 @@ +//-------------------------------------------------------------------------------------- +// File: TressFXSimulation.h +// +// Hair physics simulation header +// +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// +//-------------------------------------------------------------------------------------- + +#pragma once + +#include "AMD_TressFX.h" +#include "Math\vector3D.h" +#include "TressFXMeshVulkan.h" +#include "Util.h" +#include +#include + +typedef DirectX::XMFLOAT4 float4; +typedef DirectX::XMFLOAT3 float3; + +struct ConstBufferCS_Per_Frame; +struct ConstBufferCS_HeadTransform; + +namespace AMD +{ +class TressFXSimulation +{ +public: + TressFXSimulation(void); + ~TressFXSimulation(void); + + VkResult OnCreateDevice(VkDevice pvkDevice, + TressFX_CollisionCapsule *pCollision, + uint32_t maxUniformCount, VkPhysicalDeviceMemoryProperties memProperties, const DebugMarkerPointer& markerCallbacks); + VkResult Simulate(VkDevice pvkContext, VkCommandBuffer commandBuffer, + float fElapsedTime, float density, tressfx_vec3 &windDir, + float windMag, DirectX::XMMATRIX *pModelTransformForHead, + float targetFrameRate, bool singleHeadTransform, bool warp, + uint32_t uniformBufferIndex, const DebugMarkerPointer& markerCallbacks); + void OnDestroy(VkDevice pvkDevice); + TressFXMesh *m_pTressFXMesh; + float m_elapsedTimeSinceLastSim; + + // Descriptors set layout + VkDescriptorSetLayout m_GlobalConstraintsSetLayout; + VkDescriptorSetLayout m_LocalConstraintsSetLayout; + VkDescriptorSetLayout m_LenghtWindTangentSetLayout; + VkDescriptorSetLayout m_PrepareFollowHairSetLayout; + VkDescriptorSetLayout m_UpdateFollowHaitSetLayout; + VkDescriptorSetLayout m_ComputeTangentSetLayout; + +private: + bool m_bGuideFollowHairPrev; + + // hair simulation params + TressFX_SimulationParams m_simParams; + + VkDescriptorPool m_descriptorPool; + VkDescriptorSetLayout m_configSetLayout; + VkDescriptorSet m_configSet; + + // Compute Shader + // data for compute shaders + VkPipelineLayout m_CSIntegrationAndGlobalShapeConstraintsLayout; + VkPipeline m_CSIntegrationAndGlobalShapeConstraints; + VkPipelineLayout m_CSApplyHairTransformGloballyLayout; + VkPipeline m_CSApplyHairTransformGlobally; + VkPipelineLayout m_CSComputeTangentsLayout; + VkPipeline m_CSComputeTangents; + VkPipelineLayout m_CSLocalShapeConstraintsLayout; + VkPipeline m_CSLocalShapeConstraints; + VkPipelineLayout m_CSLocalShapeConstraintsSingleDispatchLayout; + VkPipeline m_CSLocalShapeConstraintsSingleDispatch; + VkPipelineLayout m_CSLengthConstriantsWindAndCollisionLayout; + VkPipeline m_CSLengthConstriantsWindAndCollision; + VkPipelineLayout m_CSUpdateFollowHairVerticesLayout; + VkPipeline m_CSUpdateFollowHairVertices; + VkPipelineLayout m_CSPrepareFollowHairBeforeTurningIntoGuideLayout; + VkPipeline m_CSPrepareFollowHairBeforeTurningIntoGuide; + VkPipelineLayout m_CSGenerateTransformsLayout; + VkPipeline m_CSGenerateTransforms; + + // const buffers for CS + VkBuffer m_pCBCSPerFrame; + VkDeviceMemory m_pCBCSPerFrameMemory; + VkBuffer m_pCBCSCollisionCapsule; + VkDeviceMemory m_pCBCSCollisionCapsuleMemory; + VkBuffer m_pCBGenerateTransforms; + VkDeviceMemory m_pCBGenerateTransformsMemory; + VkBuffer m_pCBHeadTransforms; + VkDeviceMemory m_pCBHeadTransformsMemory; + + VkResult CreateComputeShaderConstantBuffers(VkDevice pvkDevice, + TressFX_CollisionCapsule *pCollision, + uint32_t maxUniformBufferCount, + VkPhysicalDeviceMemoryProperties memProps); + VkResult CreateDescriptorSet(VkDevice pvkDevice); + + void fillConstantBuffer(ConstBufferCS_Per_Frame * pCSPerFrame, bool warp, bool bFullSimulate, float targetFrameRate, int numOfStrandsPerThreadGroup, float windMag, AMD::tressfx_vec3 & windDir, float fElapsedTime); + void fillHeadConstantBuffer(ConstBufferCS_HeadTransform * pCSHeadTransform, bool singleHeadTransform, DirectX::XMMATRIX * pModelTransformForHead); + void fillSimulationCommands(const VkCommandBuffer &commandBuffer, float &density, const uint32_t &uniformBufferIndex); +public: + void SetSimulationParams(const TressFX_SimulationParams &simParams) + { + m_simParams = simParams; + } +}; +} // namespace AMD diff --git a/amd_tressfx_vulkan/src/TressFXVulkan.cpp b/amd_tressfx_vulkan/src/TressFXVulkan.cpp new file mode 100644 index 0000000..a1048cb --- /dev/null +++ b/amd_tressfx_vulkan/src/TressFXVulkan.cpp @@ -0,0 +1,326 @@ +//-------------------------------------------------------------------------------------- +// File: TresssFX.cpp +// +// Hair asset structure +// +// +// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. +// +// 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. +// +//-------------------------------------------------------------------------------------- + +#if AMD_TRESSFX_COMPILE_DYNAMIC_LIB +#define AMD_DLL_EXPORTS +#endif +#include "TressFXOpaqueVulkan.h" + +static AMD::TressFX_OpaqueDesc gTressFXOpaqueDesc; + +int g_TressFXNumVerticesPerStrand = 16; // must be 2^n (n is integer and greater and 3) + // and less than or equal to THREAD_GROUP_SIZE. + // i.e. 8, 16, 32 or 64 + +namespace AMD +{ +//-------------------------------------------------------------------------------------- +// +// TressFX_GetVersion +// +// Gets the TressFX library version number. +// This can be called before TressFX_Initialize. +// +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_GetVersion(uint *major, uint *minor, + uint *patch) +{ + if (major == NULL || minor == NULL || patch == NULL) + { + return TRESSFX_RETURN_CODE_INVALID_POINTER; + } + + *major = AMD_TRESSFX_VERSION_MAJOR; + *minor = AMD_TRESSFX_VERSION_MINOR; + *patch = AMD_TRESSFX_VERSION_PATCH; + + return TRESSFX_RETURN_CODE_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_Initialize +// +// Initializes TressFX rendering and simulation. Allocates the needed resources. +// The opaque initialization happens only once for the lifetime of the program, and +// descriptors share the same opaque pointer. +// +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API +TressFX_Initialize(TressFX_Desc &desc, VkImageView depthTexture, VkImageView colorTexture, + VkCommandBuffer commandBuffer, VkDeviceMemory scratchMemory, + VkBuffer scratchBuffer, size_t &offsetInScratchBuffer) +{ + desc.pOpaque = &gTressFXOpaqueDesc; + desc.pOpaque->Initialize(desc, depthTexture, + colorTexture, + commandBuffer, + scratchMemory, + scratchBuffer, + offsetInScratchBuffer, + desc.memoryProperties); + + desc.pTressFXMesh = NULL; + desc.groupID = 0; + desc.tressFXHair.pHair = NULL; + desc.tressFXHair.size = 0; + + return TRESSFX_RETURN_CODE_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_LoadRawAsset +// +// Reads the contents of a binary .tfx file. The data in pRawHairBlob is what was +// read from the .tfx file without any processing. Data from multiple .tfx files +// can be loaded by calling TressFXLoadRawAsset multiple times. +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_LoadRawAsset( + TressFX_Desc &desc, const TressFX_GuideFollowParams &guideFollowParams, + TressFX_HairBlob *pRawHairBlob) +{ + bool success = + desc.pOpaque->LoadAppendAsset(pRawHairBlob, guideFollowParams, desc.groupID); + if (success) + { + desc.groupID++; + } + return (success ? TRESSFX_RETURN_CODE_SUCCESS : TRESSFX_RETURN_CODE_FAIL); +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_LoadProcessedAsset +// +// Loads a processed hair asset. The data in pHairBlob was created by calling +// TressFX_CreateProcessedAsset(). Since it's a preprocessed asset it loads faster +// than a raw asset. +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_LoadProcessedAsset( + TressFX_Desc &desc, TressFX_HairBlob *pHairBlob, TressFX_SceneMesh *sceneMesh, + VkImageView pTressFXTexture, VkCommandBuffer uploadCmdBuffer, VkBuffer scratchBuffer, + VkDeviceMemory scratchMemory) +{ + TressFXMesh *pTressFXMesh = (TressFXMesh *)desc.pTressFXMesh; + if (pTressFXMesh != NULL) + { + delete pTressFXMesh; + } + pTressFXMesh = new TressFXMesh(); + memcpy(desc.tressFXHair.pHair, pHairBlob->pHair, pHairBlob->size); + desc.tressFXHair.size = pHairBlob->size; + pTressFXMesh->OnCreate(desc.pvkDevice, &desc.tressFXHair, sceneMesh, + pTressFXTexture, + desc.memoryProperties, uploadCmdBuffer, + scratchBuffer, + scratchMemory, + desc.pOpaque->tressFXSimulation.m_GlobalConstraintsSetLayout, + desc.pOpaque->tressFXSimulation.m_LocalConstraintsSetLayout, + desc.pOpaque->tressFXSimulation.m_LenghtWindTangentSetLayout, + desc.pOpaque->tressFXSimulation.m_PrepareFollowHairSetLayout, + desc.pOpaque->tressFXSimulation.m_UpdateFollowHaitSetLayout, + desc.pOpaque->tressFXSimulation.m_ComputeTangentSetLayout, + desc.pOpaque->tressFXRenderer.m_pass1_hair_set_layout, + desc.pOpaque->tressFXRenderer.m_shadow_pass_hair_set_layout, + desc.pOpaque->markerCallbacks); + desc.numTotalHairStrands = pTressFXMesh->m_HairAsset.m_NumTotalHairStrands; + desc.numTotalHairVertices = pTressFXMesh->m_HairAsset.m_NumTotalHairVertices; + desc.pTressFXMesh = (void *)pTressFXMesh; + + return TRESSFX_RETURN_CODE_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_CreateProcessedAsset +// +// Creates a processed hair asset from previous loads of raw hair asset data. +// A pointer to the processed hair asset is returned in pHairBlob. The caller of this +// function should copy the contents of pHairBlob instead of using it directly, since +// the memory for it will be released when a new file is loaded. +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_CreateProcessedAsset( + TressFX_Desc &desc, TressFX_HairBlob **ppHairBlob, TressFX_SceneMesh *sceneMesh, + VkImageView hairTexture, VkCommandBuffer uploadCmdBuffer, VkBuffer scratchBuffer, + VkDeviceMemory scratchMemory) +{ + bool success = desc.pOpaque->CreateProcessedAsset( + desc, ppHairBlob, sceneMesh, hairTexture, desc.memoryProperties, + uploadCmdBuffer, scratchBuffer, scratchMemory); + desc.groupID = 0; + return (success ? TRESSFX_RETURN_CODE_SUCCESS : TRESSFX_RETURN_CODE_FAIL); +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_Simulate +// +// Runs the hair simulation +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_Simulate(TressFX_Desc &desc, + VkCommandBuffer commandBuffer, + float elapsedTime, + uint32_t uniformBufferIndex) +{ + bool success = + desc.pOpaque->Simulate(desc, commandBuffer, elapsedTime, uniformBufferIndex); + return (success ? TRESSFX_RETURN_CODE_SUCCESS : TRESSFX_RETURN_CODE_FAIL); +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_Begin +// +// Indicates that hair simulation and rendering will begin +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_Begin(TressFX_Desc &desc, + uint32_t uniformBufferIndex) +{ + bool success = desc.pOpaque->Begin(desc, uniformBufferIndex); + return (success ? TRESSFX_RETURN_CODE_SUCCESS : TRESSFX_RETURN_CODE_FAIL); +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_RenderShadowMap +// +// Render the hair into a shadow map. Returns the shadow map in the descriptor +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_RenderShadowMap( + TressFX_Desc &desc, VkCommandBuffer commandBuffer, uint32_t uniformBufferIndex) +{ + bool success = desc.pOpaque->RenderShadowMap(desc, commandBuffer, uniformBufferIndex); + return (success ? TRESSFX_RETURN_CODE_SUCCESS : TRESSFX_RETURN_CODE_FAIL); +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_Render +// +// Render the hair model. Multiple render calls can be made for different hair models +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_Render(TressFX_Desc &desc, + VkCommandBuffer commandBuffer, + uint32_t uniformBufferIndex) +{ + bool success = desc.pOpaque->RenderHair(desc, commandBuffer, uniformBufferIndex); + return (success ? TRESSFX_RETURN_CODE_SUCCESS : TRESSFX_RETURN_CODE_FAIL); +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_End +// +// Indicates that hair rendering is finished. Final post-process rendering can be +// done at this point +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_End(TressFX_Desc &desc) +{ + bool success = desc.pOpaque->End(desc); + return (success ? TRESSFX_RETURN_CODE_SUCCESS : TRESSFX_RETURN_CODE_FAIL); +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_Resize +// +// Called when the back buffer is resized so internal buffers can also be resized +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_Resize(TressFX_Desc &desc, + VkPhysicalDeviceMemoryProperties memProperties) +{ + bool success = desc.pOpaque->Resize(desc, memProperties); + return (success ? TRESSFX_RETURN_CODE_SUCCESS : TRESSFX_RETURN_CODE_FAIL); +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_Release +// +// Releases any memory allocated by the library +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_Release(TressFX_Desc &desc) +{ + if (!desc.pOpaque) + { + return TRESSFX_RETURN_CODE_SUCCESS; + } + + desc.pOpaque->Release(desc.pvkDevice); + TressFXMesh *pTressFXMesh = (TressFXMesh *)desc.pTressFXMesh; + delete pTressFXMesh; + delete desc.tressFXHair.pHair; + desc.tressFXHair.pHair = NULL; + desc.tressFXHair.size = 0; + return TRESSFX_RETURN_CODE_SUCCESS; +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_GenerateTransforms +// +// Calculates the transformations for each strand. +// Used for fur skinning. +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API +TressFX_GenerateTransforms(TressFX_Desc &desc, TressFX_SceneMesh &sceneMesh) +{ + bool success = desc.pOpaque->GenerateTransforms(desc, sceneMesh); + return (success ? TRESSFX_RETURN_CODE_SUCCESS : TRESSFX_RETURN_CODE_FAIL); +} + +//-------------------------------------------------------------------------------------- +// +// TressFX_ApplyRigidTransforms +// +// Apply skin transforms to all hair vertices so that hair would be transformed in a rigid +// motion. +// Used for fur skinning. +// +//-------------------------------------------------------------------------------------- +TRESSFX_RETURN_CODE AMD_TRESSFX_DLL_API TressFX_ApplyRigidTransforms(TressFX_Desc &desc) +{ + bool success = desc.pOpaque->ApplyRigidTransforms(desc); + return (success ? TRESSFX_RETURN_CODE_SUCCESS : TRESSFX_RETURN_CODE_FAIL); +} + +} // namespace AMD diff --git a/amd_tressfx_vulkan/src/UtilVulkan.cpp b/amd_tressfx_vulkan/src/UtilVulkan.cpp new file mode 100644 index 0000000..3e43d8c --- /dev/null +++ b/amd_tressfx_vulkan/src/UtilVulkan.cpp @@ -0,0 +1,390 @@ +#include "UtilVulkan.h" + +namespace AMD +{ +ShaderModule::ShaderModule(VkDevice dev, const std::vector &code) + : m_pvkDevice(dev) +{ + VkShaderModuleCreateInfo moduleInfo{VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + nullptr, 0, code.size() * sizeof(uint32_t), + code.data()}; + + vkCreateShaderModule(m_pvkDevice, &moduleInfo, nullptr, &m_shaderModule); +} + +ShaderModule::~ShaderModule() +{ + vkDestroyShaderModule(m_pvkDevice, m_shaderModule, nullptr); +} + + +uint32_t getMemoryTypeIndex(uint32_t typeBits, const VkPhysicalDeviceMemoryProperties &memprops, VkMemoryPropertyFlags properties) +{ + // Iterate over all memory types available for the device used in this example + for (uint32_t i = 0; i < memprops.memoryTypeCount; i++) + { + if ((typeBits & 1) == 1) + { + if ((memprops.memoryTypes[i].propertyFlags & properties) == properties) + { + return i; + } + } + typeBits >>= 1; + } + return static_cast(-1); +} + +VkDeviceSize align(VkDeviceSize offset, VkDeviceSize alignment) +{ + return ((offset + alignment - 1) / alignment) * alignment; +} + + +VkDeviceMemory allocBufferMemory(VkDevice dev, VkBuffer buffer, + const VkPhysicalDeviceMemoryProperties &memprops, VkMemoryPropertyFlags properties) +{ + VkMemoryRequirements memReqs; + vkGetBufferMemoryRequirements(dev, buffer, &memReqs); + + VkMemoryAllocateInfo allocateInfo{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; + allocateInfo.allocationSize = memReqs.size; + allocateInfo.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, memprops, properties); + VkDeviceMemory result; + vkAllocateMemory(dev, &allocateInfo, nullptr, &result); + vkBindBufferMemory(dev, buffer, result, 0); + return result; +} + +VkDeviceMemory allocImageMemory(VkDevice dev, VkImage image, + const VkPhysicalDeviceMemoryProperties &memprops) +{ + VkMemoryRequirements memReqs; + vkGetImageMemoryRequirements(dev, image, &memReqs); + + VkMemoryAllocateInfo allocateInfo{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; + allocateInfo.allocationSize = memReqs.size; + allocateInfo.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, memprops, VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VkDeviceMemory result; + vkAllocateMemory(dev, &allocateInfo, nullptr, &result); + vkBindImageMemory(dev, image, result, 0); + return result; +} + +VkWriteDescriptorSet getWriteDescriptor(VkDescriptorSet dstSet, uint32_t dstBinding, + VkDescriptorType descriptorType, + const VkBufferView *texelBufferView) +{ + VkWriteDescriptorSet result{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET}; + result.descriptorCount = 1; + result.dstSet = dstSet; + result.dstBinding = dstBinding; + result.descriptorType = descriptorType; + result.pTexelBufferView = texelBufferView; + return result; +} + +VkWriteDescriptorSet getWriteDescriptor(VkDescriptorSet dstSet, uint32_t dstBinding, + VkDescriptorType descriptorType, + const VkDescriptorBufferInfo *Bufferdescriptor) +{ + VkWriteDescriptorSet result{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET}; + result.descriptorCount = 1; + result.dstSet = dstSet; + result.dstBinding = dstBinding; + result.descriptorType = descriptorType; + result.pBufferInfo = Bufferdescriptor; + return result; +} + +VkWriteDescriptorSet getWriteDescriptor(VkDescriptorSet dstSet, uint32_t dstBinding, + VkDescriptorType descriptorType, + const VkDescriptorImageInfo *descriptor) +{ + VkWriteDescriptorSet result{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET}; + result.descriptorCount = 1; + result.dstSet = dstSet; + result.dstBinding = dstBinding; + result.descriptorType = descriptorType; + result.pImageInfo = descriptor; + return result; +} + +void fillInitialData(VkCommandBuffer commandBuffer, VkBuffer scratchBuffer, + void *pScratchBuffer, void *pDataToUpload, VkBuffer destBuffer, + size_t &offsetInScratchBuffer, VkDeviceSize size) +{ + memcpy(reinterpret_cast(pScratchBuffer) + offsetInScratchBuffer, + pDataToUpload, static_cast(size)); + VkBufferCopy copyInfo{offsetInScratchBuffer, 0, static_cast(size)}; + vkCmdCopyBuffer(commandBuffer, scratchBuffer, destBuffer, 1, ©Info); + offsetInScratchBuffer += static_cast(size); +} + +VkResult getDescriptorLayout(VkDevice pvkDevice, const VkDescriptorSetLayoutBinding *ptr, + size_t count, VkDescriptorSetLayout &result) +{ + VkDescriptorSetLayoutCreateInfo info{ + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO}; + info.bindingCount = static_cast(count); + info.pBindings = ptr; + + VkResult vr; + AMD_CHECKED_VULKAN_CALL(vkCreateDescriptorSetLayout(pvkDevice, &info, nullptr, &result)); + return VK_SUCCESS; +} + +VkBufferMemoryBarrier getBufferBarrier(VkBuffer buffer, VkAccessFlags srcAccess, + VkAccessFlags dstAccess, size_t offset, + uint64_t size) +{ + VkBufferMemoryBarrier result{VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER}; + result.buffer = buffer; + result.srcAccessMask = srcAccess; + result.dstAccessMask = dstAccess; + result.offset = offset; + result.size = size; + return result; +} + +VkPipelineShaderStageCreateInfo getShaderStageCreateInfo(VkShaderModule module, + VkShaderStageFlagBits stage, + const char *shaderName) +{ + VkPipelineShaderStageCreateInfo shaderStageInfo{ + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO}; + shaderStageInfo.module = module; + shaderStageInfo.pName = shaderName; + shaderStageInfo.stage = stage; + return shaderStageInfo; +} + +// No tesselation +const VkPipelineTessellationStateCreateInfo CommonPipelineState::tessellationState{ + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO}; +const VkDynamicState CommonPipelineState::dynamicStates[] = {VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR}; +const VkPipelineDynamicStateCreateInfo CommonPipelineState::dynamicState{ + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, nullptr, 0, 2, dynamicStates}; +// One sample +const VkPipelineMultisampleStateCreateInfo CommonPipelineState::multisampleState{ + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, nullptr, 0, + VK_SAMPLE_COUNT_1_BIT}; +// One viewport and scissor +const VkPipelineViewportStateCreateInfo CommonPipelineState::viewportState{ + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + nullptr, + 0, + 1, + nullptr, + 1, + nullptr}; +const VkPipelineRasterizationStateCreateInfo + CommonPipelineState::rasterizationCreateInfo = { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + nullptr, + 0, + VK_FALSE, + VK_FALSE, + VK_POLYGON_MODE_FILL, + VK_CULL_MODE_NONE, + VK_FRONT_FACE_CLOCKWISE, + VK_FALSE, + 0., + 0., + 0., + 1.}; + +const VkPipelineInputAssemblyStateCreateInfo CommonPipelineState::inputAssemblyTriangle = + {VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false}; + +const VkPipelineInputAssemblyStateCreateInfo CommonPipelineState::inputAssemblyLine = { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST, false}; + +const VkPipelineVertexInputStateCreateInfo CommonPipelineState::m_pLayoutHair{ + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO}; + +VkGraphicsPipelineCreateInfo CommonPipelineState::getBasePipelineCreateInfo( + const VkPipelineVertexInputStateCreateInfo *vertex_input_state, + const VkPipelineDepthStencilStateCreateInfo *depth_stencil_state, + const VkPipelineColorBlendStateCreateInfo *color_blend_state, + const VkPipelineInputAssemblyStateCreateInfo *input_assembly, + const VkPipelineShaderStageCreateInfo *stages, VkPipelineLayout layout, + VkRenderPass render_pass, uint32_t subpass) +{ + VkGraphicsPipelineCreateInfo pipelineCreateInfo{ + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO}; + pipelineCreateInfo.pTessellationState = &tessellationState; + pipelineCreateInfo.pMultisampleState = &multisampleState; + pipelineCreateInfo.pVertexInputState = vertex_input_state; + pipelineCreateInfo.pViewportState = &viewportState; + pipelineCreateInfo.pDynamicState = &dynamicState; + pipelineCreateInfo.pDepthStencilState = depth_stencil_state; + pipelineCreateInfo.pColorBlendState = color_blend_state; + pipelineCreateInfo.stageCount = 2; + pipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE; + pipelineCreateInfo.basePipelineIndex = -1; + pipelineCreateInfo.pRasterizationState = &rasterizationCreateInfo; + pipelineCreateInfo.pInputAssemblyState = input_assembly; + pipelineCreateInfo.pStages = stages; + pipelineCreateInfo.layout = layout; + pipelineCreateInfo.renderPass = render_pass; + pipelineCreateInfo.subpass = subpass; + return pipelineCreateInfo; +} + +namespace +{ +VkPipelineDepthStencilStateCreateInfo +getSpecializedDepthStencilState(bool depth_test_enable, bool depth_write_enable, + bool stencil_test_enable, VkCompareOp stencil_op, VkStencilOp pass_op, + uint32_t write_mask) +{ + VkPipelineDepthStencilStateCreateInfo DSS{ + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO}; + DSS.depthTestEnable = depth_test_enable; + DSS.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + DSS.depthWriteEnable = depth_write_enable; + DSS.stencilTestEnable = stencil_test_enable; + DSS.front.compareMask = 0xff; + DSS.front.writeMask = write_mask; + DSS.front.failOp = VK_STENCIL_OP_KEEP; + DSS.front.depthFailOp = VK_STENCIL_OP_KEEP; + DSS.front.passOp = pass_op; + DSS.front.compareOp = stencil_op; + DSS.back.compareMask = 0xff; + DSS.back.writeMask = write_mask; + DSS.back.failOp = VK_STENCIL_OP_KEEP; + DSS.back.depthFailOp = VK_STENCIL_OP_KEEP; + DSS.back.passOp = pass_op; + DSS.back.compareOp = stencil_op; + return DSS; +} + +const VkPipelineColorBlendAttachmentState BlendStateBlendToBg_render_target_0{ + true, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_OP_ADD, + VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_A_BIT | VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_G_BIT}; + +const VkPipelineColorBlendAttachmentState m_pDepthWritesToColor_BS_render_target_0{ + true, + VK_BLEND_FACTOR_ZERO, + VK_BLEND_FACTOR_SRC_COLOR, + VK_BLEND_OP_ADD, + VK_BLEND_FACTOR_ZERO, + VK_BLEND_FACTOR_SRC_ALPHA, + VK_BLEND_OP_ADD, + VK_COLOR_COMPONENT_R_BIT}; + +const VkPipelineColorBlendAttachmentState m_pResolveColor_BS_BS_render_target_0{ + true, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_OP_ADD, + VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT}; + +const VkPipelineColorBlendAttachmentState m_pSum_BS_render_target_0{ + true, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ONE, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ONE, + VK_BLEND_FACTOR_ONE, VK_BLEND_OP_ADD, + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT}; +} + +const VkPipelineDepthStencilStateCreateInfo CommonPipelineState::DepthTestEnabledDesc = + getSpecializedDepthStencilState(true, true, false, VK_COMPARE_OP_NEVER, VK_STENCIL_OP_KEEP, 0xff); +const VkPipelineDepthStencilStateCreateInfo + CommonPipelineState::DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc = + getSpecializedDepthStencilState(true, false, true, VK_COMPARE_OP_ALWAYS, + VK_STENCIL_OP_INCREMENT_AND_WRAP, 0xff); +const VkPipelineDepthStencilStateCreateInfo + CommonPipelineState::DepthTestDisabledStencilTestLessDSS = getSpecializedDepthStencilState( + false, false, true, VK_COMPARE_OP_LESS, VK_STENCIL_OP_KEEP, 0x00); +const VkPipelineDepthStencilStateCreateInfo + CommonPipelineState::m_pDepthWriteEnabledStencilTestLess_DSS = + getSpecializedDepthStencilState(true, true, true, VK_COMPARE_OP_LESS, VK_STENCIL_OP_KEEP, 0x0); + +// disable color write if there is no need for fragments counting +const VkPipelineColorBlendStateCreateInfo CommonPipelineState::ColorWritesOff{ + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO}; + +const VkPipelineColorBlendStateCreateInfo CommonPipelineState::BlendStateBlendToBg{ + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + nullptr, + 0, + VK_FALSE, + VK_LOGIC_OP_NO_OP, + 1, + &BlendStateBlendToBg_render_target_0}; + +const VkPipelineColorBlendStateCreateInfo CommonPipelineState::m_pDepthWritesToColor_BS{ + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + nullptr, + 0, + VK_FALSE, + VK_LOGIC_OP_NO_OP, + 1, + &m_pDepthWritesToColor_BS_render_target_0}; + +const VkPipelineColorBlendStateCreateInfo CommonPipelineState::m_pResolveColor_BS{ + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + nullptr, + 0, + VK_FALSE, + VK_LOGIC_OP_NO_OP, + 1, + &m_pResolveColor_BS_BS_render_target_0}; + +const VkPipelineColorBlendStateCreateInfo CommonPipelineState::m_pSum_BS{ + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + nullptr, + 0, + VK_FALSE, + VK_LOGIC_OP_NO_OP, + 1, + &m_pSum_BS_render_target_0}; + +const VkPipelineVertexInputStateCreateInfo CommonPipelineState::m_pLayoutQuad{ + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + nullptr, + 0, + 0, + nullptr, + 0, + nullptr}; + +VkImageMemoryBarrier getImageMemoryBarrier(VkImage image, VkAccessFlags srcMask, + VkAccessFlags dstMask, VkImageLayout oldLayout, + VkImageLayout newLayout, uint32_t layoutCount, + VkImageAspectFlags aspect) +{ + VkImageMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER}; + memoryBarrier.srcAccessMask = srcMask; + memoryBarrier.dstAccessMask = dstMask; + memoryBarrier.oldLayout = oldLayout; + memoryBarrier.newLayout = newLayout; + memoryBarrier.image = image; + memoryBarrier.subresourceRange.aspectMask = aspect; + memoryBarrier.subresourceRange.levelCount = 1; + memoryBarrier.subresourceRange.layerCount = layoutCount; + return memoryBarrier; +} + +VkImageCreateInfo getImageCreateInfo(VkFormat format, uint32_t width, uint32_t height, + VkImageUsageFlags usage, uint32_t layers) +{ + VkImageCreateInfo tex2D_desc{VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO}; + tex2D_desc.extent.width = width; + tex2D_desc.extent.height = height; + tex2D_desc.extent.depth = 1; + tex2D_desc.arrayLayers = layers; + tex2D_desc.mipLevels = 1; + tex2D_desc.format = format; + tex2D_desc.usage = usage; + tex2D_desc.samples = VK_SAMPLE_COUNT_1_BIT; + tex2D_desc.imageType = VK_IMAGE_TYPE_2D; + tex2D_desc.tiling = VK_IMAGE_TILING_OPTIMAL; + return tex2D_desc; +} +} diff --git a/amd_tressfx_vulkan/src/UtilVulkan.h b/amd_tressfx_vulkan/src/UtilVulkan.h new file mode 100644 index 0000000..b5c396b --- /dev/null +++ b/amd_tressfx_vulkan/src/UtilVulkan.h @@ -0,0 +1,196 @@ +#pragma once + +#include +#include + +#define AMD_CHECKED_VULKAN_CALL(x) \ + { \ + vr = (x); \ + if (vr != VK_SUCCESS) \ + { \ + return vr; \ + } \ + } + +#undef AMD_SAFE_RELEASE +#define AMD_SAFE_RELEASE(object, releaseFunction, device) if (object != VK_NULL_HANDLE) releaseFunction(device, object, nullptr); + +namespace AMD +{ + struct DebugMarkerPointer + { + DebugMarkerPointer() {} + + void init(VkDevice device) + { + dev = device; + pfnDebugMarkerSetObjectTag = (PFN_vkDebugMarkerSetObjectTagEXT)vkGetDeviceProcAddr(device, "vkDebugMarkerSetObjectTagEXT"); + pfnDebugMarkerSetObjectName = (PFN_vkDebugMarkerSetObjectNameEXT)vkGetDeviceProcAddr(device, "vkDebugMarkerSetObjectNameEXT"); + pfnCmdDebugMarkerBegin = (PFN_vkCmdDebugMarkerBeginEXT)vkGetDeviceProcAddr(device, "vkCmdDebugMarkerBeginEXT"); + pfnCmdDebugMarkerEnd = (PFN_vkCmdDebugMarkerEndEXT)vkGetDeviceProcAddr(device, "vkCmdDebugMarkerEndEXT"); + pfnCmdDebugMarkerInsert = (PFN_vkCmdDebugMarkerInsertEXT)vkGetDeviceProcAddr(device, "vkCmdDebugMarkerInsertEXT"); + } + + void nameObject(VkBuffer object, const char* name) const + { + nameObject_impl(VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, reinterpret_cast(object), name); + } + + void nameObject(VkBufferView object, const char* name) const + { + nameObject_impl(VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT, reinterpret_cast(object), name); + } + + void nameObject(VkDeviceMemory object, const char* name) const + { + nameObject_impl(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, reinterpret_cast(object), name); + } + + void nameObject(VkPipeline object, const char* name) const + { + + nameObject_impl(VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, reinterpret_cast(object), name); + } + + void markBeginRegion(VkCommandBuffer cmdBuffer, const char* name) const + { + if (!pfnCmdDebugMarkerBegin) + return; + VkDebugMarkerMarkerInfoEXT info{ VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT }; + info.pMarkerName = name; + info.color[0] = 1.f; + pfnCmdDebugMarkerBegin(cmdBuffer, &info); + } + + void markEndRegion(VkCommandBuffer cmdBuffer) const + { + if (!pfnCmdDebugMarkerEnd) + return; + pfnCmdDebugMarkerEnd(cmdBuffer); + } + + private: + PFN_vkDebugMarkerSetObjectTagEXT pfnDebugMarkerSetObjectTag = NULL; + PFN_vkDebugMarkerSetObjectNameEXT pfnDebugMarkerSetObjectName = NULL; + PFN_vkCmdDebugMarkerBeginEXT pfnCmdDebugMarkerBegin = NULL; + PFN_vkCmdDebugMarkerEndEXT pfnCmdDebugMarkerEnd = NULL; + PFN_vkCmdDebugMarkerInsertEXT pfnCmdDebugMarkerInsert = NULL; + + VkDevice dev; + + void nameObject_impl(VkDebugReportObjectTypeEXT type, uint64_t object, const char* name) const + { + if (!pfnDebugMarkerSetObjectName) + return; + VkDebugMarkerObjectNameInfoEXT info{ VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT }; + info.objectType = type; + info.object = object; + info.pObjectName = name; + pfnDebugMarkerSetObjectName(dev, &info); + } + }; + + + struct ShaderModule + { + VkShaderModule m_shaderModule; + + ShaderModule(VkDevice dev, const std::vector &code); + ~ShaderModule(); + private: + VkDevice m_pvkDevice; + + ShaderModule(const ShaderModule&) {}; + ShaderModule& operator=(const ShaderModule&) {}; + }; + + uint32_t getMemoryTypeIndex(uint32_t typeBits, const VkPhysicalDeviceMemoryProperties &memprops, VkMemoryPropertyFlags properties); + VkDeviceSize align(VkDeviceSize offset, VkDeviceSize alignment); + VkDeviceMemory allocBufferMemory(VkDevice dev, VkBuffer buffer, + const VkPhysicalDeviceMemoryProperties &memprops, VkMemoryPropertyFlags properties); + VkDeviceMemory allocImageMemory(VkDevice dev, VkImage image, + const VkPhysicalDeviceMemoryProperties &memprops); + + VkWriteDescriptorSet getWriteDescriptor(VkDescriptorSet dstSet, uint32_t dstBinding, + VkDescriptorType descriptorType, + const VkBufferView *texelBufferView); + + VkWriteDescriptorSet getWriteDescriptor(VkDescriptorSet dstSet, uint32_t dstBinding, + VkDescriptorType descriptorType, + const VkDescriptorBufferInfo *Bufferdescriptor); + + VkWriteDescriptorSet getWriteDescriptor(VkDescriptorSet dstSet, uint32_t dstBinding, + VkDescriptorType descriptorType, + const VkDescriptorImageInfo *descriptor); + + void fillInitialData(VkCommandBuffer commandBuffer, VkBuffer scratchBuffer, + void *pScratchBuffer, void *pDataToUpload, VkBuffer destBuffer, + size_t &offsetInScratchBuffer, VkDeviceSize size); + + VkResult getDescriptorLayout(VkDevice pvkDevice, const VkDescriptorSetLayoutBinding *ptr, + size_t count, VkDescriptorSetLayout &result); + VkBufferMemoryBarrier getBufferBarrier(VkBuffer buffer, VkAccessFlags srcAccess, + VkAccessFlags dstAccess, size_t offset = 0u, + uint64_t size = VK_WHOLE_SIZE); + + VkPipelineShaderStageCreateInfo getShaderStageCreateInfo(VkShaderModule module, + VkShaderStageFlagBits stage, + const char *shaderName); + + VkImageCreateInfo getImageCreateInfo(VkFormat format, uint32_t width, uint32_t height, + VkImageUsageFlags usage, uint32_t layers = 1); + + struct CommonPipelineState + { + // No tesselation + static const VkPipelineTessellationStateCreateInfo tessellationState; + // One viewport and scissor + static const VkDynamicState dynamicStates[2]; + static const VkPipelineDynamicStateCreateInfo dynamicState; + // One sample + static const VkPipelineMultisampleStateCreateInfo multisampleState; + // One viewport + static const VkPipelineViewportStateCreateInfo viewportState; + static const VkPipelineRasterizationStateCreateInfo rasterizationCreateInfo; + + static const VkPipelineVertexInputStateCreateInfo m_pLayoutHair; + // Full screen quad layout structure + static const VkPipelineVertexInputStateCreateInfo m_pLayoutQuad; + + // Triangles list + static const VkPipelineInputAssemblyStateCreateInfo inputAssemblyTriangle; + // Lines list + static const VkPipelineInputAssemblyStateCreateInfo inputAssemblyLine; + + static VkGraphicsPipelineCreateInfo getBasePipelineCreateInfo( + const VkPipelineVertexInputStateCreateInfo *vertex_input_state, + const VkPipelineDepthStencilStateCreateInfo *depth_stencil_state, + const VkPipelineColorBlendStateCreateInfo *color_blend_state, + const VkPipelineInputAssemblyStateCreateInfo *input_assembly, + const VkPipelineShaderStageCreateInfo *stages, VkPipelineLayout layout, + VkRenderPass render_pass, uint32_t subpass); + + static const VkPipelineDepthStencilStateCreateInfo DepthTestEnabledDesc; + // Enable depth test to use early z, disable depth write to make sure required layers + // won't be clipped out in early z + static const VkPipelineDepthStencilStateCreateInfo + DepthTestEnabledNoDepthWritesStencilWriteIncrementDesc; + static const VkPipelineDepthStencilStateCreateInfo + DepthTestDisabledStencilTestLessDSS; + static const VkPipelineDepthStencilStateCreateInfo + m_pDepthWriteEnabledStencilTestLess_DSS; + + // disable color write if there is no need for fragments counting + static const VkPipelineColorBlendStateCreateInfo ColorWritesOff; + static const VkPipelineColorBlendStateCreateInfo BlendStateBlendToBg; + static const VkPipelineColorBlendStateCreateInfo m_pDepthWritesToColor_BS; + static const VkPipelineColorBlendStateCreateInfo m_pResolveColor_BS; + static const VkPipelineColorBlendStateCreateInfo m_pSum_BS; + }; + + VkImageMemoryBarrier + getImageMemoryBarrier(VkImage image, VkAccessFlags srcMask, VkAccessFlags dstMask, + VkImageLayout oldLayout, VkImageLayout newLayout, + uint32_t layerCount, + VkImageAspectFlags aspect); +} \ No newline at end of file