From a0632abf1350bb64c098573d84c42f053f053a6e Mon Sep 17 00:00:00 2001 From: Mark Simpson Date: Tue, 12 Dec 2023 14:21:32 +0000 Subject: [PATCH 1/2] FidelityFX FSR3 3.0.3 --- .gitlab-ci.yml | 2 + BuildAllCauldronEffectsSolution.bat | 4 +- BuildAllCauldronEffectsSolutionDll.bat | 2 + BuildAllNativeEffectsSolution.bat | 6 +- BuildAllNativeEffectsSolutionDll.bat | 2 + BuildBlurSolution.bat | 4 +- BuildCACAOSolution.bat | 4 +- BuildCASSolution.bat | 4 +- BuildCauldronSolution.bat | 4 +- BuildDOFSolution.bat | 4 +- BuildFSRSolution.bat | 4 +- BuildFSRSolutionNative.bat | 39 + BuildFSRSolutionNativeDll.bat | 40 + BuildHybridReflectionsSolution.bat | 2 +- BuildHybridShadowsSolution.bat | 2 +- BuildLPMSolution.bat | 2 +- BuildLensSolution.bat | 2 +- BuildParallelSortSolution.bat | 4 +- BuildSPDSolution.bat | 4 +- BuildSSSRSolution.bat | 2 +- BuildVRSSolution.bat | 4 +- CMakeLists.txt | 110 +- Third_party_notices.txt | 345 + docs/getting-started/building-samples.md | 12 +- docs/getting-started/index.md | 4 +- docs/index.md | 65 +- docs/samples/index.md | 2 +- docs/samples/super-resolution.md | 9 +- docs/techniques/blur.md | 2 +- .../frame-interpolation-swap-chain.md | 146 + docs/techniques/frame-interpolation.md | 204 + docs/techniques/frame-pacing.md | 87 + docs/techniques/index.md | 12 +- .../frame-interpolation-swap-chain.svg | 1137 + .../algorithm-structure.svg | 1899 + .../frame-interpolation-debug-overlay.svg | 873 + .../media/frame-pacing/fixed-high.svg | 45 + .../media/frame-pacing/fixed-low.svg | 43 + .../media/frame-pacing/pacing-overview.svg | 42 + .../media/frame-pacing/variable-inside.svg | 43 + .../media/optical-flow/optical_flow_block.svg | 130 + .../optical_flow_main_iteration.svg | 279 + .../optical_flow_main_searching.svg | 32087 ++++++++++++++++ .../optical_flow_main_upscale_area.svg | 13501 +++++++ .../optical_flow_preparation_luma.svg | 229 + .../optical_flow_preparation_scenechange.svg | 805 + .../01_FSR3_DataFlow.svg | 507 + .../02_FSR3_Flow.svg | 932 + .../03_FSR3_FlowAsyncQueue.svg | 1093 + .../04_FSR3_UiCallback.svg | 889 + .../05_FSR3_NoFG_UiCallback.svg | 798 + .../06_FSR3_UiTex.svg | 1014 + .../07_FSR3_NoFG_UiTex.svg | 938 + .../08_FSR3_HUDLess.svg | 1079 + .../super-resolution-temporal/fsr3-sample.jpg | Bin 0 -> 630054 bytes .../fsr3-sample_resized.jpg | Bin 0 -> 388092 bytes .../super-resolution-temporal/overview.svg | 2 +- docs/techniques/optical-flow.md | 155 + docs/techniques/parallel-sort.md | 2 +- .../super-resolution-interpolation.md | 387 + docs/techniques/super-resolution-spatial.md | 2 +- docs/techniques/super-resolution-temporal.md | 4 +- docs/techniques/super-resolution-upscaler.md | 758 + docs/whats-new/index.md | 37 +- .../framework/config/cauldronconfig.json | 18 +- .../inc/core/components/cameracomponent.h | 12 +- .../cauldron/framework/inc/core/framework.h | 10 + .../cauldron/framework/inc/core/uimanager.h | 2 + .../framework/inc/render/commandlist.h | 2 +- .../cauldron/framework/inc/render/swapchain.h | 8 + .../cauldron/framework/inc/render/texture.h | 4 + .../framework/inc/shaders/copytexture.hlsl | 22 - .../inc/shaders/fpslimiter/fpslimiter.hlsl | 22 + .../framework/inc/shaders/shadercommon.h | 5 - .../inc/shaders/tonemapping/tonemapping.hlsl | 6 + .../framework/inc/shaders/transferFunction.h | 2 +- .../cauldron/framework/inc/shaders/ui.hlsl | 6 + .../cauldron/framework/src/CMakeLists.txt | 5 +- .../src/core/components/cameracomponent.cpp | 18 + .../cauldron/framework/src/core/framework.cpp | 58 +- .../framework/src/core/win/uibackend_win.cpp | 40 +- .../src/render/dx12/commandlist_dx12.cpp | 11 +- .../src/render/dx12/commandlist_dx12.h | 1 + .../framework/src/render/dx12/device_dx12.cpp | 5 +- .../src/render/dx12/gpuresource_dx12.h | 1 + .../src/render/dx12/resourceview_dx12.cpp | 3 + .../src/render/dx12/swapchain_dx12.cpp | 158 +- .../src/render/dx12/swapchain_dx12.h | 26 + .../fpslimiter/fpslimiterrendermodule.cpp | 88 +- .../fpslimiter/fpslimiterrendermodule.h | 12 +- .../swapchain/swapchainrendermodule.cpp | 24 +- .../swapchain/swapchainrendermodule.h | 2 - .../tonemapping/tonemappingrendermodule.cpp | 27 +- .../tonemapping/tonemappingrendermodule.h | 2 +- .../rendermodules/ui/uirendermodule.cpp | 460 +- .../render/rendermodules/ui/uirendermodule.h | 77 +- framework/rendermodules/CMakeLists.txt | 13 + .../animatedtexturesrendermodule.cpp | 237 + .../animatedtexturesrendermodule.h | 68 + .../shaders/AnimatedTexture.hlsl | 131 + .../gbuffer/config/gbufferrendermodule.json | 8 +- .../gbuffer/shaders/gbufferps.hlsl | 4 +- .../rendermodules/rendermoduleregistry.cpp | 2 + .../rendermodules/taa/taarendermodule.cpp | 18 +- readme.md | 38 +- samples/blur/CMakeLists.txt | 17 +- samples/blur/blurrendermodule.cpp | 20 +- samples/blur/blurrendermodule.h | 18 +- .../shaders/blur_baseline_filters_cs.hlsl | 21 + .../blur/shaders/blur_compare_filters_cs.hlsl | 21 + .../blur/shaders/blur_gaussian_blur_kernels.h | 21 + samples/cacao/CMakeLists.txt | 15 +- samples/cacao/cacaorendermodule.cpp | 20 +- samples/cacao/cacaorendermodule.h | 18 +- samples/cacao/cacaosample.cpp | 16 +- samples/cacao/cacaosample.h | 16 +- samples/cacao/shaders/display_ssao.hlsl | 21 + samples/cas/CMakeLists.txt | 15 +- samples/cas/casrendermodule.cpp | 18 +- samples/cas/casrendermodule.h | 16 +- samples/dof/CMakeLists.txt | 15 +- samples/dof/dofrendermodule.cpp | 18 +- samples/dof/dofrendermodule.h | 16 +- samples/ffx_cauldron/CMakeLists.txt | 232 +- samples/ffx_cauldron/CMakeShadersBlur.txt | 15 +- samples/ffx_cauldron/CMakeShadersCACAO.txt | 15 +- samples/ffx_cauldron/CMakeShadersCAS.txt | 15 +- .../ffx_cauldron/CMakeShadersClassifier.txt | 6 +- samples/ffx_cauldron/CMakeShadersDOF.txt | 15 +- samples/ffx_cauldron/CMakeShadersDenoiser.txt | 15 +- samples/ffx_cauldron/CMakeShadersFSR1.txt | 15 +- samples/ffx_cauldron/CMakeShadersFSR2.txt | 15 +- samples/ffx_cauldron/CMakeShadersLENS.txt | 15 +- samples/ffx_cauldron/CMakeShadersLPM.txt | 15 +- .../ffx_cauldron/CMakeShadersParallelSort.txt | 15 +- samples/ffx_cauldron/CMakeShadersSPD.txt | 15 +- samples/ffx_cauldron/CMakeShadersSSSR.txt | 15 +- samples/ffx_cauldron/CMakeShadersVRS.txt | 15 +- samples/ffx_cauldron/GPUTimestamps.cpp | 132 + samples/ffx_cauldron/GPUTimestamps.h | 72 + samples/ffx_cauldron/cpu_time_event_rate.cpp | 88 + samples/ffx_cauldron/cpu_time_event_rate.h | 41 + samples/ffx_cauldron/ffx_cauldron.cpp | 67 +- samples/ffx_cauldron/ffx_cauldron.h | 24 +- .../shaders/blur/ffx_blur_pass.hlsl | 16 +- .../ffx_cacao_apply_non_smart_half_pass.hlsl | 16 +- .../cacao/ffx_cacao_apply_non_smart_pass.hlsl | 16 +- .../shaders/cacao/ffx_cacao_apply_pass.hlsl | 16 +- .../ffx_cacao_clear_load_counter_pass.hlsl | 16 +- .../ffx_cacao_edge_sensitive_blur_1_pass.hlsl | 16 +- .../ffx_cacao_edge_sensitive_blur_2_pass.hlsl | 16 +- .../ffx_cacao_edge_sensitive_blur_3_pass.hlsl | 16 +- .../ffx_cacao_edge_sensitive_blur_4_pass.hlsl | 16 +- .../ffx_cacao_edge_sensitive_blur_5_pass.hlsl | 16 +- .../ffx_cacao_edge_sensitive_blur_6_pass.hlsl | 16 +- .../ffx_cacao_edge_sensitive_blur_7_pass.hlsl | 16 +- .../ffx_cacao_edge_sensitive_blur_8_pass.hlsl | 16 +- ..._cacao_generate_importance_map_a_pass.hlsl | 16 +- ..._cacao_generate_importance_map_b_pass.hlsl | 16 +- ...fx_cacao_generate_importance_map_pass.hlsl | 16 +- .../cacao/ffx_cacao_generate_q0_pass.hlsl | 16 +- .../cacao/ffx_cacao_generate_q1_pass.hlsl | 16 +- .../cacao/ffx_cacao_generate_q2_pass.hlsl | 16 +- .../ffx_cacao_generate_q3_base_pass.hlsl | 16 +- .../cacao/ffx_cacao_generate_q3_pass.hlsl | 16 +- ...pare_downsampled_depths_and_mips_pass.hlsl | 16 +- ..._prepare_downsampled_depths_half_pass.hlsl | 16 +- ...cacao_prepare_downsampled_depths_pass.hlsl | 16 +- ...mpled_normals_from_input_normals_pass.hlsl | 16 +- ...acao_prepare_downsampled_normals_pass.hlsl | 16 +- ...o_prepare_native_depths_and_mips_pass.hlsl | 16 +- ...cacao_prepare_native_depths_half_pass.hlsl | 16 +- .../ffx_cacao_prepare_native_depths_pass.hlsl | 16 +- ...ative_normals_from_input_normals_pass.hlsl | 16 +- ...ffx_cacao_prepare_native_normals_pass.hlsl | 16 +- .../ffx_cacao_upscale_bilateral_5x5_pass.hlsl | 16 +- .../shaders/cas/ffx_cas_sharpen_pass.hlsl | 16 +- .../ffx_classifier_reflections_pass.hlsl | 7 +- .../ffx_classifier_shadows_pass.hlsl | 7 +- ...x_denoiser_filter_soft_shadows_0_pass.hlsl | 20 +- ...x_denoiser_filter_soft_shadows_1_pass.hlsl | 20 +- ...x_denoiser_filter_soft_shadows_2_pass.hlsl | 20 +- ...x_denoiser_prefilter_reflections_pass.hlsl | 16 +- ...ffx_denoiser_prepare_shadow_mask_pass.hlsl | 20 +- ...x_denoiser_reproject_reflections_pass.hlsl | 16 +- ...ser_resolve_temporal_reflections_pass.hlsl | 16 +- ...iser_shadows_tile_classification_pass.hlsl | 20 +- .../shaders/dof/ffx_dof_blur_pass.hlsl | 16 +- .../shaders/dof/ffx_dof_composite_pass.hlsl | 16 +- .../shaders/dof/ffx_dof_dilate_pass.hlsl | 16 +- .../dof/ffx_dof_downsample_color_pass.hlsl | 16 +- .../dof/ffx_dof_downsample_depth_pass.hlsl | 16 +- ...rameinterpolation_CopyUiResource_pass.glsl | 19 + ...rameinterpolation_CopyUiResource_pass.hlsl | 45 + ...olation_ReplacementFrameResource_pass.glsl | 19 + ...olation_ReplacementFrameResource_pass.hlsl | 36 + ...ameinterpolation_UiCompositionPS_pass.glsl | 7 + ...ameinterpolation_UiCompositionPS_pass.hlsl | 62 + ...ameinterpolation_UiCompositionVS_pass.glsl | 12 + ...ameinterpolation_UiCompositionVS_pass.hlsl | 55 + ...tion_UpscalerDispatchComposition_pass.glsl | 19 + ...tion_UpscalerDispatchComposition_pass.hlsl | 74 + ..._vector_field_inpainting_pyramid_pass.glsl | 19 + ..._vector_field_inpainting_pyramid_pass.hlsl | 182 + ...ation_compute_inpainting_pyramid_pass.glsl | 19 + ...ation_compute_inpainting_pyramid_pass.hlsl | 175 + ..._frameinterpolation_disocclusion_mask.glsl | 19 + ..._frameinterpolation_disocclusion_mask.hlsl | 228 + ...nterpolation_game_motion_vector_field.glsl | 19 + ...nterpolation_game_motion_vector_field.hlsl | 115 + ...fx_frameinterpolation_inpainting_pass.glsl | 19 + ...fx_frameinterpolation_inpainting_pass.hlsl | 107 + ...terpolation_optical_flow_vector_field.glsl | 19 + ...terpolation_optical_flow_vector_field.hlsl | 193 + .../ffx_frameinterpolation_pass.glsl | 19 + .../ffx_frameinterpolation_pass.hlsl | 262 + ...erpolation_reconstruct_previous_depth.glsl | 19 + ...erpolation_reconstruct_previous_depth.hlsl | 143 + .../ffx_frameinterpolation_setup.glsl | 19 + .../ffx_frameinterpolation_setup.hlsl | 117 + .../shaders/fsr1/ffx_fsr1_easu_pass.hlsl | 16 +- .../shaders/fsr1/ffx_fsr1_rcas_pass.hlsl | 16 +- .../fsr2/ffx_fsr2_accumulate_pass.glsl | 4 +- .../fsr2/ffx_fsr2_accumulate_pass.hlsl | 16 +- .../fsr2/ffx_fsr2_autogen_reactive_pass.glsl | 4 +- .../fsr2/ffx_fsr2_autogen_reactive_pass.hlsl | 16 +- ...x_fsr2_compute_luminance_pyramid_pass.glsl | 4 +- ...x_fsr2_compute_luminance_pyramid_pass.hlsl | 16 +- .../fsr2/ffx_fsr2_depth_clip_pass.glsl | 4 +- .../fsr2/ffx_fsr2_depth_clip_pass.hlsl | 16 +- .../shaders/fsr2/ffx_fsr2_lock_pass.glsl | 4 +- .../shaders/fsr2/ffx_fsr2_lock_pass.hlsl | 16 +- .../shaders/fsr2/ffx_fsr2_rcas_pass.glsl | 4 +- .../shaders/fsr2/ffx_fsr2_rcas_pass.hlsl | 16 +- ..._fsr2_reconstruct_previous_depth_pass.glsl | 4 +- ..._fsr2_reconstruct_previous_depth_pass.hlsl | 16 +- .../fsr2/ffx_fsr2_tcr_autogen_pass.glsl | 14 +- .../fsr2/ffx_fsr2_tcr_autogen_pass.hlsl | 16 +- .../ffx_fsr3upscaler_accumulate_pass.glsl | 87 + .../ffx_fsr3upscaler_accumulate_pass.hlsl | 79 + ...fx_fsr3upscaler_autogen_reactive_pass.glsl | 80 + ...fx_fsr3upscaler_autogen_reactive_pass.hlsl | 77 + ...scaler_compute_luminance_pyramid_pass.glsl | 58 + ...scaler_compute_luminance_pyramid_pass.hlsl | 55 + .../ffx_fsr3upscaler_depth_clip_pass.glsl | 67 + .../ffx_fsr3upscaler_depth_clip_pass.hlsl | 67 + .../ffx_fsr3upscaler_lock_pass.glsl | 58 + .../ffx_fsr3upscaler_lock_pass.hlsl | 56 + .../ffx_fsr3upscaler_rcas_pass.glsl | 58 + .../ffx_fsr3upscaler_rcas_pass.hlsl | 53 + ...caler_reconstruct_previous_depth_pass.glsl | 65 + ...caler_reconstruct_previous_depth_pass.hlsl | 64 + .../shaders/lens/ffx_lens_pass.hlsl | 16 +- .../shaders/lpm/ffx_lpm_filter_pass.hlsl | 16 +- .../ffx_opticalflow_blit_to_output_pass.hlsl | 22 + ...alflow_compute_luminance_pyramid_pass.glsl | 19 + ...alflow_compute_luminance_pyramid_pass.hlsl | 115 + ...compute_optical_flow_advanced_pass_v5.glsl | 19 + ...compute_optical_flow_advanced_pass_v5.hlsl | 62 + ...ticalflow_compute_scd_divergence_pass.glsl | 19 + ...ticalflow_compute_scd_divergence_pass.hlsl | 57 + ...ticalflow_filter_optical_flow_pass_v5.glsl | 19 + ...ticalflow_filter_optical_flow_pass_v5.hlsl | 56 + ...ticalflow_generate_scd_histogram_pass.glsl | 19 + ...ticalflow_generate_scd_histogram_pass.hlsl | 54 + .../ffx_opticalflow_prepare_luma_pass.glsl | 19 + .../ffx_opticalflow_prepare_luma_pass.hlsl | 51 + ...w_scale_optical_flow_advanced_pass_v5.glsl | 19 + ...w_scale_optical_flow_advanced_pass_v5.hlsl | 59 + .../ffx_parallelsort_reduce_pass.hlsl | 16 +- .../ffx_parallelsort_scan_add_pass.hlsl | 16 +- .../ffx_parallelsort_scan_pass.hlsl | 16 +- .../ffx_parallelsort_scatter_pass.hlsl | 16 +- ...parallelsort_setup_indirect_args_pass.hlsl | 16 +- .../ffx_parallelsort_sum_pass.hlsl | 16 +- .../shaders/spd/ffx_spd_downsample_pass.hlsl | 16 +- .../sssr/ffx_sssr_classify_tiles_pass.hlsl | 16 +- .../sssr/ffx_sssr_depth_downsample_pass.hlsl | 16 +- .../shaders/sssr/ffx_sssr_intersect_pass.hlsl | 16 +- ..._sssr_prepare_blue_noise_texture_pass.hlsl | 16 +- .../ffx_sssr_prepare_indirect_args_pass.hlsl | 16 +- .../shaders/vrs/ffx_vrs_imagegen_pass.hlsl | 16 +- samples/fsr/CMakeLists.txt | 55 +- .../fsr/HLSLCompile/HLSLShaderCompiler.cpp | 1408 + samples/fsr/HLSLCompile/HLSLShaderCompiler.h | 99 + samples/fsr/HLSLCompile/shadercompiler.cpp | 238 + samples/fsr/HLSLCompile/shadercompiler.h | 120 + samples/fsr/config/fsrconfig.json | 38 +- samples/fsr/fsr1rendermodule.cpp | 33 +- samples/fsr/fsr1rendermodule.h | 16 +- samples/fsr/fsr2rendermodule.cpp | 48 +- samples/fsr/fsr2rendermodule.h | 18 +- samples/fsr/fsr3rendermodule.cpp | 972 + samples/fsr/fsr3rendermodule.h | 174 + samples/fsr/fsr3upscalerendermodule.cpp | 489 + samples/fsr/fsr3upscalerendermodule.h | 170 + samples/fsr/fsrsample.cpp | 76 +- samples/fsr/fsrsample.h | 30 +- samples/fsr/media/checkerboard.dds | Bin 0 -> 87508 bytes samples/fsr/media/composition_text.dds | Bin 0 -> 1398144 bytes samples/fsr/media/lion.jpg | Bin 0 -> 357550 bytes samples/fsr/shaders/HudLessBlit.hlsl | 29 + samples/fsr/shaders/upscalecommon.h | 17 +- samples/fsr/shaders/upscalecs.hlsl | 17 +- samples/fsr/upscalerendermodule.cpp | 16 +- samples/fsr/upscalerendermodule.h | 16 +- samples/hybridreflections/CMakeLists.txt | 21 + .../hybridreflectionsrendermodule.cpp | 18 +- .../hybridreflectionsrendermodule.h | 16 +- samples/hybridreflections/shaders/Common.hlsl | 16 +- .../hybridreflections/shaders/Declarations.h | 16 +- .../hybridreflections/shaders/Intersect.hlsl | 16 +- .../shaders/apply_reflections.hlsl | 16 +- .../hybridreflections/shaders/common_types.h | 16 +- .../shaders/copy_depth_and_reset_buffers.hlsl | 16 +- .../shaders/copy_depth_and_reset_debug.hlsl | 46 + .../shaders/ffx_sssr_intersect.h | 16 +- .../shaders/prepare_blue_noise.hlsl | 16 +- .../shaders/prepare_indirect_args_hw.hlsl | 16 +- .../shaders/prepare_indirect_args_hybrid.hlsl | 16 +- .../shaders/primary_ray_tracing.hlsl | 16 +- .../shaders/sample_ggx_vndf.h | 10 +- samples/hybridshadows/CMakeLists.txt | 21 + .../hybridshadowsrendermodule.cpp | 19 +- .../hybridshadows/hybridshadowsrendermodule.h | 17 +- .../shaders/copydebugraytracing.hlsl | 17 +- samples/hybridshadows/shaders/copydepth.hlsl | 17 +- samples/hybridshadows/shaders/debugtiles.hlsl | 17 +- .../shaders/resolveraytracing.hlsl | 17 +- .../hybridshadows/shaders/traceshadows.hlsl | 17 +- samples/lens/CMakeLists.txt | 15 +- samples/lens/lensrendermodule.cpp | 18 +- samples/lens/lensrendermodule.h | 16 +- samples/lpm/CMakeLists.txt | 15 +- samples/lpm/lpmrendermodule.cpp | 32 +- samples/lpm/lpmrendermodule.h | 16 +- samples/parallelsort/CMakeLists.txt | 15 +- .../parallelsort/parallelsortrendermodule.cpp | 33 +- .../parallelsort/parallelsortrendermodule.h | 16 +- .../shaders/parallelsort_common.h | 7 +- .../parallelsort/shaders/parallelsort_cs.hlsl | 7 +- .../shaders/parallelsort_verify.hlsl | 7 +- samples/spd/CMakeLists.txt | 15 +- samples/spd/shaders/spd_common.h | 6 +- samples/spd/shaders/spd_cs_downsampler.hlsl | 6 +- samples/spd/shaders/spd_ps_downsampler.hlsl | 6 +- samples/spd/shaders/spd_verify_results.hlsl | 6 +- samples/spd/spdrendermodule.cpp | 18 +- samples/spd/spdrendermodule.h | 16 +- samples/sssr/CMakeLists.txt | 15 +- .../sssr/shaders/sssr_apply_reflections.hlsl | 21 + .../shaders/sssr_apply_reflections_common.h | 21 + samples/sssr/sssrrendermodule.cpp | 18 +- samples/sssr/sssrrendermodule.h | 16 +- samples/validation_remap.h | 48 +- samples/vrs/CMakeLists.txt | 15 +- samples/vrs/shaders/VrsOverlay.hlsl | 7 +- samples/vrs/shaders/motionvectorsps.hlsl | 21 + samples/vrs/vrsrendermodule.cpp | 18 +- samples/vrs/vrsrendermodule.h | 16 +- sdk/BuildFidelityFXSDK.bat | 6 +- sdk/BuildFidelityFXSDKSolution.bat | 4 +- sdk/CMakeLists.txt | 13 +- sdk/include/FidelityFX/gpu/blur/ffx_blur.h | 30 +- .../FidelityFX/gpu/blur/ffx_blur_blur.h | 30 +- .../gpu/blur/ffx_blur_callbacks_glsl.h | 30 +- .../gpu/blur/ffx_blur_callbacks_hlsl.h | 30 +- .../FidelityFX/gpu/blur/ffx_blur_resources.h | 30 +- .../FidelityFX/gpu/cacao/ffx_cacao_apply.h | 30 +- .../gpu/cacao/ffx_cacao_callbacks_glsl.h | 30 +- .../gpu/cacao/ffx_cacao_callbacks_hlsl.h | 30 +- .../FidelityFX/gpu/cacao/ffx_cacao_defines.h | 30 +- .../gpu/cacao/ffx_cacao_edge_sensitive_blur.h | 30 +- .../gpu/cacao/ffx_cacao_importance_map.h | 30 +- .../FidelityFX/gpu/cacao/ffx_cacao_prepare.h | 30 +- .../gpu/cacao/ffx_cacao_resources.h | 30 +- .../gpu/cacao/ffx_cacao_ssao_generation.h | 30 +- .../FidelityFX/gpu/cacao/ffx_cacao_upscale.h | 30 +- .../FidelityFX/gpu/cacao/ffx_cacao_utils.h | 30 +- sdk/include/FidelityFX/gpu/cas/ffx_cas.h | 78 +- .../gpu/cas/ffx_cas_callbacks_glsl.h | 30 +- .../gpu/cas/ffx_cas_callbacks_hlsl.h | 30 +- .../FidelityFX/gpu/cas/ffx_cas_resources.h | 30 +- .../FidelityFX/gpu/cas/ffx_cas_sharpen.h | 30 +- .../gpu/classifier/ffx_classifier_common.h | 7 +- .../classifier/ffx_classifier_reflections.h | 7 +- ...fx_classifier_reflections_callbacks_glsl.h | 7 +- ...fx_classifier_reflections_callbacks_hlsl.h | 7 +- .../ffx_classifier_reflections_common.h | 7 +- .../gpu/classifier/ffx_classifier_resources.h | 7 +- .../gpu/classifier/ffx_classifier_shadows.h | 7 +- .../ffx_classifier_shadows_callbacks_glsl.h | 7 +- .../ffx_classifier_shadows_callbacks_hlsl.h | 7 +- .../ffx_denoiser_reflections_callbacks_glsl.h | 30 +- .../ffx_denoiser_reflections_callbacks_hlsl.h | 30 +- .../ffx_denoiser_reflections_common.h | 30 +- .../ffx_denoiser_reflections_config.h | 30 +- .../ffx_denoiser_reflections_prefilter.h | 30 +- .../ffx_denoiser_reflections_reproject.h | 30 +- ...fx_denoiser_reflections_resolve_temporal.h | 30 +- .../gpu/denoiser/ffx_denoiser_resources.h | 30 +- .../ffx_denoiser_shadows_callbacks_glsl.h | 7 +- .../ffx_denoiser_shadows_callbacks_hlsl.h | 20 +- .../denoiser/ffx_denoiser_shadows_filter.h | 24 +- .../denoiser/ffx_denoiser_shadows_prepare.h | 30 +- .../ffx_denoiser_shadows_tileclassification.h | 24 +- .../gpu/denoiser/ffx_denoiser_shadows_util.h | 24 +- sdk/include/FidelityFX/gpu/dof/ffx_dof_blur.h | 30 +- .../gpu/dof/ffx_dof_callbacks_glsl.h | 30 +- .../gpu/dof/ffx_dof_callbacks_hlsl.h | 30 +- .../FidelityFX/gpu/dof/ffx_dof_common.h | 30 +- .../FidelityFX/gpu/dof/ffx_dof_composite.h | 34 +- .../FidelityFX/gpu/dof/ffx_dof_dilate_depth.h | 30 +- .../gpu/dof/ffx_dof_downsample_color.h | 36 +- .../gpu/dof/ffx_dof_downsample_depth.h | 30 +- .../FidelityFX/gpu/dof/ffx_dof_resources.h | 30 +- sdk/include/FidelityFX/gpu/ffx_common_types.h | 50 +- sdk/include/FidelityFX/gpu/ffx_core.h | 40 +- sdk/include/FidelityFX/gpu/ffx_core_cpu.h | 30 +- sdk/include/FidelityFX/gpu/ffx_core_glsl.h | 24 +- .../FidelityFX/gpu/ffx_core_gpu_common.h | 33 +- .../FidelityFX/gpu/ffx_core_gpu_common_half.h | 74 +- sdk/include/FidelityFX/gpu/ffx_core_hlsl.h | 39 +- .../FidelityFX/gpu/ffx_core_portability.h | 30 +- .../ffx_frameinterpolation.h | 170 + .../ffx_frameinterpolation_callbacks_hlsl.h | 689 + .../ffx_frameinterpolation_common.h | 405 + ...ute_game_vector_field_inpainting_pyramid.h | 121 + ...interpolation_compute_inpainting_pyramid.h | 113 + .../ffx_frameinterpolation_debug_view.h | 163 + ...ffx_frameinterpolation_disocclusion_mask.h | 141 + ...meinterpolation_game_motion_vector_field.h | 114 + .../ffx_frameinterpolation_inpainting.h | 141 + ...einterpolation_optical_flow_vector_field.h | 124 + ...interpolation_reconstruct_previous_depth.h | 59 + .../ffx_frameinterpolation_resources.h | 90 + .../ffx_frameinterpolation_setup.h | 49 + sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1.h | 52 +- .../gpu/fsr1/ffx_fsr1_callbacks_glsl.h | 30 +- .../gpu/fsr1/ffx_fsr1_callbacks_hlsl.h | 30 +- .../FidelityFX/gpu/fsr1/ffx_fsr1_easu.h | 30 +- .../FidelityFX/gpu/fsr1/ffx_fsr1_rcas.h | 30 +- .../FidelityFX/gpu/fsr1/ffx_fsr1_resources.h | 30 +- .../FidelityFX/gpu/fsr2/ffx_fsr2_accumulate.h | 30 +- .../gpu/fsr2/ffx_fsr2_callbacks_glsl.h | 30 +- .../gpu/fsr2/ffx_fsr2_callbacks_hlsl.h | 30 +- .../FidelityFX/gpu/fsr2/ffx_fsr2_common.h | 30 +- .../fsr2/ffx_fsr2_compute_luminance_pyramid.h | 30 +- .../FidelityFX/gpu/fsr2/ffx_fsr2_depth_clip.h | 30 +- .../FidelityFX/gpu/fsr2/ffx_fsr2_lock.h | 30 +- .../fsr2/ffx_fsr2_postprocess_lock_status.h | 30 +- .../FidelityFX/gpu/fsr2/ffx_fsr2_rcas.h | 30 +- ...ruct_dilated_velocity_and_previous_depth.h | 30 +- .../FidelityFX/gpu/fsr2/ffx_fsr2_reproject.h | 30 +- .../FidelityFX/gpu/fsr2/ffx_fsr2_resources.h | 30 +- .../FidelityFX/gpu/fsr2/ffx_fsr2_sample.h | 30 +- .../gpu/fsr2/ffx_fsr2_tcr_autogen.h | 30 +- .../FidelityFX/gpu/fsr2/ffx_fsr2_upsample.h | 30 +- .../gpu/fsr3/ffx_fsr3_callbacks_hlsl.h | 25 + .../FidelityFX/gpu/fsr3/ffx_fsr3_common.h | 25 + .../FidelityFX/gpu/fsr3/ffx_fsr3_resources.h | 51 + .../ffx_fsr3upscaler_accumulate.h | 288 + .../ffx_fsr3upscaler_callbacks_glsl.h | 856 + .../ffx_fsr3upscaler_callbacks_hlsl.h | 912 + .../fsr3upscaler/ffx_fsr3upscaler_common.h | 566 + ...x_fsr3upscaler_compute_luminance_pyramid.h | 176 + .../ffx_fsr3upscaler_depth_clip.h | 259 + .../gpu/fsr3upscaler/ffx_fsr3upscaler_lock.h | 116 + ...ffx_fsr3upscaler_postprocess_lock_status.h | 107 + .../gpu/fsr3upscaler/ffx_fsr3upscaler_rcas.h | 67 + ...ruct_dilated_velocity_and_previous_depth.h | 146 + .../fsr3upscaler/ffx_fsr3upscaler_reproject.h | 137 + .../fsr3upscaler/ffx_fsr3upscaler_resources.h | 104 + .../fsr3upscaler/ffx_fsr3upscaler_sample.h | 606 + .../fsr3upscaler/ffx_fsr3upscaler_upsample.h | 195 + sdk/include/FidelityFX/gpu/lens/ffx_lens.h | 30 +- .../gpu/lens/ffx_lens_callbacks_glsl.h | 30 +- .../gpu/lens/ffx_lens_callbacks_hlsl.h | 30 +- .../FidelityFX/gpu/lens/ffx_lens_resources.h | 30 +- sdk/include/FidelityFX/gpu/lpm/ffx_lpm.h | 82 +- .../gpu/lpm/ffx_lpm_callbacks_glsl.h | 30 +- .../gpu/lpm/ffx_lpm_callbacks_hlsl.h | 30 +- .../FidelityFX/gpu/lpm/ffx_lpm_filter.h | 30 +- .../FidelityFX/gpu/lpm/ffx_lpm_resources.h | 30 +- .../ffx_opticalflow_callbacks_hlsl.h | 568 + .../gpu/opticalflow/ffx_opticalflow_common.h | 103 + ...fx_opticalflow_compute_luminance_pyramid.h | 99 + .../ffx_opticalflow_compute_optical_flow_v5.h | 279 + .../ffx_opticalflow_compute_scd_divergence.h | 159 + .../ffx_opticalflow_filter_optical_flow_v5.h | 58 + .../ffx_opticalflow_generate_scd_histogram.h | 85 + .../ffx_opticalflow_prepare_luma.h | 105 + .../opticalflow/ffx_opticalflow_resources.h | 73 + ...ticalflow_scale_optical_flow_advanced_v5.h | 99 + .../gpu/parallelsort/ffx_parallelsort.h | 30 +- .../ffx_parallelsort_callbacks_glsl.h | 30 +- .../ffx_parallelsort_callbacks_hlsl.h | 30 +- .../parallelsort/ffx_parallelsort_common.h | 30 +- .../parallelsort/ffx_parallelsort_reduce.h | 30 +- .../parallelsort/ffx_parallelsort_resources.h | 30 +- .../gpu/parallelsort/ffx_parallelsort_scan.h | 30 +- .../parallelsort/ffx_parallelsort_scan_add.h | 30 +- .../parallelsort/ffx_parallelsort_scatter.h | 30 +- .../ffx_parallelsort_setup_indirect_args.h | 30 +- .../gpu/parallelsort/ffx_parallelsort_sum.h | 30 +- .../ffx_denoiser_reflections_common.h | 30 +- .../ffx_denoiser_reflections_config.h | 30 +- sdk/include/FidelityFX/gpu/spd/ffx_spd.h | 30 +- .../gpu/spd/ffx_spd_callbacks_glsl.h | 30 +- .../gpu/spd/ffx_spd_callbacks_hlsl.h | 30 +- .../FidelityFX/gpu/spd/ffx_spd_downsample.h | 30 +- .../FidelityFX/gpu/spd/ffx_spd_resources.h | 30 +- .../gpu/sssr/ffx_sssr_callbacks_glsl.h | 30 +- .../gpu/sssr/ffx_sssr_callbacks_hlsl.h | 30 +- .../gpu/sssr/ffx_sssr_classify_tiles.h | 30 +- .../FidelityFX/gpu/sssr/ffx_sssr_common.h | 30 +- .../gpu/sssr/ffx_sssr_depth_downsample.h | 30 +- .../FidelityFX/gpu/sssr/ffx_sssr_intersect.h | 30 +- .../ffx_sssr_prepare_blue_noise_texture.h | 30 +- .../gpu/sssr/ffx_sssr_prepare_indirect_args.h | 30 +- .../FidelityFX/gpu/sssr/ffx_sssr_resources.h | 30 +- .../FidelityFX/gpu/vrs/ffx_variable_shading.h | 30 +- .../gpu/vrs/ffx_vrs_callbacks_glsl.h | 30 +- .../gpu/vrs/ffx_vrs_callbacks_hlsl.h | 30 +- .../FidelityFX/gpu/vrs/ffx_vrs_resources.h | 30 +- .../FidelityFX/host/backends/dx12/d3dx12.h | 21 + .../FidelityFX/host/backends/dx12/ffx_dx12.h | 73 +- .../FidelityFX/host/backends/dx12/license.txt | 21 + .../FidelityFX/host/backends/vk/ffx_vk.h | 30 +- sdk/include/FidelityFX/host/ffx_assert.h | 30 +- sdk/include/FidelityFX/host/ffx_blur.h | 30 +- sdk/include/FidelityFX/host/ffx_cacao.h | 30 +- sdk/include/FidelityFX/host/ffx_cas.h | 30 +- sdk/include/FidelityFX/host/ffx_classifier.h | 7 +- sdk/include/FidelityFX/host/ffx_denoiser.h | 22 +- sdk/include/FidelityFX/host/ffx_dof.h | 30 +- sdk/include/FidelityFX/host/ffx_error.h | 30 +- .../FidelityFX/host/ffx_frameinterpolation.h | 242 + sdk/include/FidelityFX/host/ffx_fsr1.h | 30 +- sdk/include/FidelityFX/host/ffx_fsr2.h | 32 +- sdk/include/FidelityFX/host/ffx_fsr3.h | 503 + .../FidelityFX/host/ffx_fsr3upscaler.h | 527 + sdk/include/FidelityFX/host/ffx_fx.h | 54 +- sdk/include/FidelityFX/host/ffx_interface.h | 80 +- sdk/include/FidelityFX/host/ffx_lens.h | 30 +- sdk/include/FidelityFX/host/ffx_lpm.h | 30 +- sdk/include/FidelityFX/host/ffx_opticalflow.h | 202 + .../FidelityFX/host/ffx_parallelsort.h | 30 +- sdk/include/FidelityFX/host/ffx_spd.h | 30 +- sdk/include/FidelityFX/host/ffx_sssr.h | 32 +- sdk/include/FidelityFX/host/ffx_types.h | 184 +- sdk/include/FidelityFX/host/ffx_util.h | 30 +- sdk/include/FidelityFX/host/ffx_vrs.h | 26 +- sdk/src/backends/dx12/CMakeLists.txt | 79 +- sdk/src/backends/dx12/CMakeShadersBlur.txt | 31 +- sdk/src/backends/dx12/CMakeShadersCACAO.txt | 21 +- sdk/src/backends/dx12/CMakeShadersCAS.txt | 31 +- .../backends/dx12/CMakeShadersClassifier.txt | 21 +- sdk/src/backends/dx12/CMakeShadersDOF.txt | 21 +- .../backends/dx12/CMakeShadersDenoiser.txt | 21 +- sdk/src/backends/dx12/CMakeShadersFSR1.txt | 21 +- sdk/src/backends/dx12/CMakeShadersFSR2.txt | 31 +- .../dx12/CMakeShadersFSR3Upscaler.txt | 57 + .../dx12/CMakeShadersFrameinterpolation.txt | 49 + sdk/src/backends/dx12/CMakeShadersLENS.txt | 31 +- sdk/src/backends/dx12/CMakeShadersLPM.txt | 21 +- .../backends/dx12/CMakeShadersOpticalflow.txt | 50 + .../dx12/CMakeShadersParallelSort.txt | 31 +- sdk/src/backends/dx12/CMakeShadersSPD.txt | 31 +- sdk/src/backends/dx12/CMakeShadersSSSR.txt | 31 +- sdk/src/backends/dx12/CMakeShadersVRS.txt | 31 +- .../FrameInterpolationSwapchainDX12.cpp | 1569 + .../FrameInterpolationSwapchainDX12.h | 263 + ...rameInterpolationSwapchainDX12_Helpers.cpp | 199 + .../FrameInterpolationSwapchainDX12_Helpers.h | 283 + ...terpolationSwapchainDX12_UiComposition.cpp | 357 + ...InterpolationSwapchainDX12_UiComposition.h | 30 + ...meInterpolationSwapchainUiComposition.hlsl | 37 + ...ameInterpolationSwapchainUiCompositionPS.h | 474 + ...ameInterpolationSwapchainUiCompositionVS.h | 368 + .../recompileUiCompositionHLSL.bat | 4 + sdk/src/backends/dx12/GPUTimestamps.cpp | 134 + sdk/src/backends/dx12/GPUTimestamps.h | 72 + sdk/src/backends/dx12/ffx_dx12.cpp | 1328 +- .../dx12/shaders/blur/ffx_blur_pass.hlsl | 30 +- .../ffx_cacao_apply_non_smart_half_pass.hlsl | 30 +- .../cacao/ffx_cacao_apply_non_smart_pass.hlsl | 30 +- .../shaders/cacao/ffx_cacao_apply_pass.hlsl | 30 +- .../ffx_cacao_clear_load_counter_pass.hlsl | 30 +- .../ffx_cacao_edge_sensitive_blur_1_pass.hlsl | 30 +- .../ffx_cacao_edge_sensitive_blur_2_pass.hlsl | 30 +- .../ffx_cacao_edge_sensitive_blur_3_pass.hlsl | 30 +- .../ffx_cacao_edge_sensitive_blur_4_pass.hlsl | 30 +- .../ffx_cacao_edge_sensitive_blur_5_pass.hlsl | 30 +- .../ffx_cacao_edge_sensitive_blur_6_pass.hlsl | 30 +- .../ffx_cacao_edge_sensitive_blur_7_pass.hlsl | 30 +- .../ffx_cacao_edge_sensitive_blur_8_pass.hlsl | 30 +- ..._cacao_generate_importance_map_a_pass.hlsl | 30 +- ..._cacao_generate_importance_map_b_pass.hlsl | 30 +- ...fx_cacao_generate_importance_map_pass.hlsl | 30 +- .../cacao/ffx_cacao_generate_q0_pass.hlsl | 30 +- .../cacao/ffx_cacao_generate_q1_pass.hlsl | 30 +- .../cacao/ffx_cacao_generate_q2_pass.hlsl | 30 +- .../ffx_cacao_generate_q3_base_pass.hlsl | 30 +- .../cacao/ffx_cacao_generate_q3_pass.hlsl | 30 +- ...pare_downsampled_depths_and_mips_pass.hlsl | 30 +- ..._prepare_downsampled_depths_half_pass.hlsl | 30 +- ...cacao_prepare_downsampled_depths_pass.hlsl | 30 +- ...mpled_normals_from_input_normals_pass.hlsl | 30 +- ...acao_prepare_downsampled_normals_pass.hlsl | 30 +- ...o_prepare_native_depths_and_mips_pass.hlsl | 30 +- ...cacao_prepare_native_depths_half_pass.hlsl | 30 +- .../ffx_cacao_prepare_native_depths_pass.hlsl | 30 +- ...ative_normals_from_input_normals_pass.hlsl | 30 +- ...ffx_cacao_prepare_native_normals_pass.hlsl | 30 +- .../ffx_cacao_upscale_bilateral_5x5_pass.hlsl | 30 +- .../shaders/cas/ffx_cas_sharpen_pass.hlsl | 30 +- .../ffx_classifier_reflections_pass.hlsl | 7 +- .../ffx_classifier_shadows_pass.hlsl | 7 +- ...x_denoiser_filter_soft_shadows_0_pass.hlsl | 20 +- ...x_denoiser_filter_soft_shadows_1_pass.hlsl | 20 +- ...x_denoiser_filter_soft_shadows_2_pass.hlsl | 20 +- ...x_denoiser_prefilter_reflections_pass.hlsl | 16 +- ...ffx_denoiser_prepare_shadow_mask_pass.hlsl | 20 +- ...x_denoiser_reproject_reflections_pass.hlsl | 16 +- ...ser_resolve_temporal_reflections_pass.hlsl | 16 +- ...iser_shadows_tile_classification_pass.hlsl | 20 +- .../dx12/shaders/dof/ffx_dof_blur_pass.hlsl | 30 +- .../shaders/dof/ffx_dof_composite_pass.hlsl | 30 +- .../dx12/shaders/dof/ffx_dof_dilate_pass.hlsl | 30 +- .../dof/ffx_dof_downsample_color_pass.hlsl | 30 +- .../dof/ffx_dof_downsample_depth_pass.hlsl | 30 +- ..._vector_field_inpainting_pyramid_pass.hlsl | 92 + ...ation_compute_inpainting_pyramid_pass.hlsl | 90 + ...fx_frameinterpolation_debug_view_pass.hlsl | 58 + ...einterpolation_disocclusion_mask_pass.hlsl | 55 + ...olation_game_motion_vector_field_pass.hlsl | 54 + ...fx_frameinterpolation_inpainting_pass.hlsl | 54 + ...lation_optical_flow_vector_field_pass.hlsl | 55 + .../ffx_frameinterpolation_pass.hlsl | 58 + ...ation_reconstruct_previous_depth_pass.hlsl | 53 + .../ffx_frameinterpolation_setup_pass.hlsl | 55 + .../dx12/shaders/fsr1/ffx_fsr1_easu_pass.hlsl | 30 +- .../dx12/shaders/fsr1/ffx_fsr1_rcas_pass.hlsl | 30 +- .../fsr2/ffx_fsr2_accumulate_pass.hlsl | 30 +- .../fsr2/ffx_fsr2_autogen_reactive_pass.hlsl | 30 +- ...x_fsr2_compute_luminance_pyramid_pass.hlsl | 30 +- .../shaders/fsr2/ffx_fsr2_debug_blit.hlsl | 49 + .../fsr2/ffx_fsr2_depth_clip_pass.hlsl | 30 +- .../dx12/shaders/fsr2/ffx_fsr2_lock_pass.hlsl | 30 +- .../dx12/shaders/fsr2/ffx_fsr2_rcas_pass.hlsl | 30 +- ..._fsr2_reconstruct_previous_depth_pass.hlsl | 30 +- .../fsr2/ffx_fsr2_tcr_autogen_pass.hlsl | 30 +- .../ffx_fsr3upscaler_accumulate_pass.hlsl | 79 + ...fx_fsr3upscaler_autogen_reactive_pass.hlsl | 77 + ...scaler_compute_luminance_pyramid_pass.hlsl | 55 + .../ffx_fsr3upscaler_depth_clip_pass.hlsl | 67 + .../ffx_fsr3upscaler_lock_pass.hlsl | 56 + .../ffx_fsr3upscaler_rcas_pass.hlsl | 53 + ...caler_reconstruct_previous_depth_pass.hlsl | 64 + .../dx12/shaders/lens/ffx_lens_pass.hlsl | 30 +- .../dx12/shaders/lpm/ffx_lpm_filter_pass.hlsl | 30 +- ...alflow_compute_luminance_pyramid_pass.hlsl | 107 + ...compute_optical_flow_advanced_pass_v5.hlsl | 61 + ...ticalflow_compute_scd_divergence_pass.hlsl | 56 + ...ticalflow_filter_optical_flow_pass_v5.hlsl | 56 + ...ticalflow_generate_scd_histogram_pass.hlsl | 54 + .../ffx_opticalflow_prepare_luma_pass.hlsl | 50 + ...w_scale_optical_flow_advanced_pass_v5.hlsl | 62 + .../ffx_parallelsort_reduce_pass.hlsl | 30 +- .../ffx_parallelsort_scan_add_pass.hlsl | 30 +- .../ffx_parallelsort_scan_pass.hlsl | 30 +- .../ffx_parallelsort_scatter_pass.hlsl | 30 +- ...parallelsort_setup_indirect_args_pass.hlsl | 30 +- .../ffx_parallelsort_sum_pass.hlsl | 30 +- .../shaders/spd/ffx_spd_downsample_pass.hlsl | 30 +- .../sssr/ffx_sssr_classify_tiles_pass.hlsl | 16 +- .../sssr/ffx_sssr_depth_downsample_pass.hlsl | 16 +- .../shaders/sssr/ffx_sssr_intersect_pass.hlsl | 16 +- ..._sssr_prepare_blue_noise_texture_pass.hlsl | 16 +- .../ffx_sssr_prepare_indirect_args_pass.hlsl | 16 +- .../shaders/vrs/ffx_vrs_imagegen_pass.hlsl | 30 +- .../blob_accessors/ffx_blur_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_blur_shaderblobs.h | 18 +- .../blob_accessors/ffx_cacao_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_cacao_shaderblobs.h | 18 +- .../blob_accessors/ffx_cas_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_cas_shaderblobs.h | 18 +- .../ffx_classifier_shaderblobs.cpp | 7 +- .../ffx_classifier_shaderblobs.h | 7 +- .../ffx_denoiser_shaderblobs.cpp | 22 +- .../blob_accessors/ffx_denoiser_shaderblobs.h | 18 +- .../blob_accessors/ffx_dof_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_dof_shaderblobs.h | 18 +- .../ffx_frameinterpolation_shaderblobs.cpp | 349 + .../ffx_frameinterpolation_shaderblobs.h | 42 + .../blob_accessors/ffx_fsr1_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_fsr1_shaderblobs.h | 18 +- .../blob_accessors/ffx_fsr2_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_fsr2_shaderblobs.h | 18 +- .../ffx_fsr3upscaler_shaderblobs.cpp | 344 + .../ffx_fsr3upscaler_shaderblobs.h | 41 + .../blob_accessors/ffx_lens_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_lens_shaderblobs.h | 18 +- .../blob_accessors/ffx_lpm_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_lpm_shaderblobs.h | 18 +- .../ffx_opticalflow_shaderblobs.cpp | 265 + .../ffx_opticalflow_shaderblobs.h | 41 + .../ffx_parallelsort_shaderblobs.cpp | 20 +- .../ffx_parallelsort_shaderblobs.h | 18 +- .../blob_accessors/ffx_spd_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_spd_shaderblobs.h | 18 +- .../blob_accessors/ffx_sssr_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_sssr_shaderblobs.h | 18 +- .../blob_accessors/ffx_vrs_shaderblobs.cpp | 20 +- .../blob_accessors/ffx_vrs_shaderblobs.h | 18 +- sdk/src/backends/shared/ffx_shader_blobs.cpp | 37 +- sdk/src/backends/shared/ffx_shader_blobs.h | 19 +- sdk/src/backends/vk/CMakeLists.txt | 31 +- sdk/src/backends/vk/CMakeShadersBLUR.txt | 17 +- sdk/src/backends/vk/CMakeShadersCACAO.txt | 17 +- sdk/src/backends/vk/CMakeShadersCAS.txt | 17 +- .../backends/vk/CMakeShadersClassifier.txt | 19 +- sdk/src/backends/vk/CMakeShadersDOF.txt | 17 +- sdk/src/backends/vk/CMakeShadersDenoiser.txt | 21 +- sdk/src/backends/vk/CMakeShadersFSR1.txt | 17 +- sdk/src/backends/vk/CMakeShadersFSR2.txt | 17 +- sdk/src/backends/vk/CMakeShadersLENS.txt | 17 +- sdk/src/backends/vk/CMakeShadersLPM.txt | 17 +- .../backends/vk/CMakeShadersParallelSort.txt | 17 +- sdk/src/backends/vk/CMakeShadersSPD.txt | 17 +- sdk/src/backends/vk/CMakeShadersSSSR.txt | 17 +- sdk/src/backends/vk/CMakeShadersVRS.txt | 17 +- sdk/src/backends/vk/ffx_vk.cpp | 34 +- .../fsr2/ffx_fsr2_accumulate_pass.glsl | 4 +- .../fsr2/ffx_fsr2_autogen_reactive_pass.glsl | 4 +- ...x_fsr2_compute_luminance_pyramid_pass.glsl | 4 +- .../fsr2/ffx_fsr2_depth_clip_pass.glsl | 4 +- .../vk/shaders/fsr2/ffx_fsr2_lock_pass.glsl | 4 +- .../vk/shaders/fsr2/ffx_fsr2_rcas_pass.glsl | 4 +- ..._fsr2_reconstruct_previous_depth_pass.glsl | 4 +- .../fsr2/ffx_fsr2_tcr_autogen_pass.glsl | 4 +- sdk/src/components/blur/CMakeLists.txt | 18 +- sdk/src/components/blur/ffx_blur.cpp | 16 +- sdk/src/components/blur/ffx_blur_private.h | 16 +- sdk/src/components/cacao/CMakeLists.txt | 18 +- sdk/src/components/cacao/ffx_cacao.cpp | 18 +- sdk/src/components/cacao/ffx_cacao_private.h | 16 +- sdk/src/components/cas/CMakeLists.txt | 18 +- sdk/src/components/cas/ffx_cas.cpp | 16 +- sdk/src/components/cas/ffx_cas_private.h | 16 +- sdk/src/components/classifier/CMakeLists.txt | 7 +- .../components/classifier/ffx_classifier.cpp | 7 +- .../classifier/ffx_classifier_private.h | 7 +- sdk/src/components/denoiser/CMakeLists.txt | 18 +- sdk/src/components/denoiser/ffx_denoiser.cpp | 22 +- .../denoiser/ffx_denoiser_private.h | 20 +- sdk/src/components/dof/CMakeLists.txt | 18 +- sdk/src/components/dof/ffx_dof.cpp | 30 +- sdk/src/components/dof/ffx_dof_private.h | 16 +- .../frameinterpolation/CMakeLists.txt | 56 + .../ffx_frameinterpolation.cpp | 848 + .../ffx_frameinterpolation_private.h | 135 + sdk/src/components/fsr1/CMakeLists.txt | 18 +- sdk/src/components/fsr1/ffx_fsr1.cpp | 18 +- sdk/src/components/fsr1/ffx_fsr1_private.h | 16 +- sdk/src/components/fsr2/CMakeLists.txt | 18 +- sdk/src/components/fsr2/ffx_fsr2.cpp | 28 +- .../components/fsr2/ffx_fsr2_maximum_bias.h | 16 +- sdk/src/components/fsr2/ffx_fsr2_private.h | 16 +- sdk/src/components/fsr3/CMakeLists.txt | 59 + sdk/src/components/fsr3/ffx_fsr3.cpp | 447 + .../components/fsr3/ffx_fsr3_maximum_bias.h | 47 + sdk/src/components/fsr3/ffx_fsr3_private.h | 62 + .../components/fsr3upscaler/CMakeLists.txt | 55 + .../fsr3upscaler/ffx_fsr3upscaler.cpp | 1301 + .../ffx_fsr3upscaler_maximum_bias.h | 47 + .../fsr3upscaler/ffx_fsr3upscaler_private.h | 106 + sdk/src/components/lens/CMakeLists.txt | 18 +- sdk/src/components/lens/ffx_lens.cpp | 20 +- sdk/src/components/lens/ffx_lens_private.h | 16 +- sdk/src/components/lpm/CMakeLists.txt | 18 +- sdk/src/components/lpm/ffx_lpm.cpp | 16 +- sdk/src/components/lpm/ffx_lpm_private.h | 16 +- sdk/src/components/opticalflow/CMakeLists.txt | 56 + .../opticalflow/ffx_opticalflow.cpp | 889 + .../opticalflow/ffx_opticalflow_private.h | 106 + .../components/parallelsort/CMakeLists.txt | 18 +- .../parallelsort/ffx_parallelsort.cpp | 18 +- .../parallelsort/ffx_parallelsort_private.h | 16 +- sdk/src/components/spd/CMakeLists.txt | 18 +- sdk/src/components/spd/ffx_spd.cpp | 20 +- sdk/src/components/spd/ffx_spd_private.h | 16 +- sdk/src/components/sssr/CMakeLists.txt | 21 +- sdk/src/components/sssr/ffx_sssr.cpp | 28 +- sdk/src/components/sssr/ffx_sssr_private.h | 18 +- ...n_128x128_OptimizedFor_2d2d2d2d_128spp.cpp | 21 + ...on_128x128_OptimizedFor_2d2d2d2d_16spp.cpp | 21 + ...ion_128x128_OptimizedFor_2d2d2d2d_1spp.cpp | 21 + ...n_128x128_OptimizedFor_2d2d2d2d_256spp.cpp | 21 + ...ion_128x128_OptimizedFor_2d2d2d2d_2spp.cpp | 21 + ...on_128x128_OptimizedFor_2d2d2d2d_32spp.cpp | 21 + ...ion_128x128_OptimizedFor_2d2d2d2d_4spp.cpp | 21 + ...on_128x128_OptimizedFor_2d2d2d2d_64spp.cpp | 21 + ...ion_128x128_OptimizedFor_2d2d2d2d_8spp.cpp | 21 + sdk/src/components/vrs/CMakeLists.txt | 18 +- sdk/src/components/vrs/ffx_vrs.cpp | 18 +- sdk/src/components/vrs/ffx_vrs_private.h | 18 +- sdk/src/shared/ffx_assert.cpp | 16 +- sdk/src/shared/ffx_object_management.cpp | 24 +- sdk/src/shared/ffx_object_management.h | 24 +- 811 files changed, 98258 insertions(+), 6395 deletions(-) create mode 100644 BuildAllCauldronEffectsSolutionDll.bat create mode 100644 BuildAllNativeEffectsSolutionDll.bat create mode 100644 BuildFSRSolutionNative.bat create mode 100644 BuildFSRSolutionNativeDll.bat create mode 100644 Third_party_notices.txt create mode 100644 docs/techniques/frame-interpolation-swap-chain.md create mode 100644 docs/techniques/frame-interpolation.md create mode 100644 docs/techniques/frame-pacing.md create mode 100644 docs/techniques/media/frame-interpolation-swapchain/frame-interpolation-swap-chain.svg create mode 100644 docs/techniques/media/frame-interpolation/algorithm-structure.svg create mode 100644 docs/techniques/media/frame-interpolation/frame-interpolation-debug-overlay.svg create mode 100644 docs/techniques/media/frame-pacing/fixed-high.svg create mode 100644 docs/techniques/media/frame-pacing/fixed-low.svg create mode 100644 docs/techniques/media/frame-pacing/pacing-overview.svg create mode 100644 docs/techniques/media/frame-pacing/variable-inside.svg create mode 100644 docs/techniques/media/optical-flow/optical_flow_block.svg create mode 100644 docs/techniques/media/optical-flow/optical_flow_main_iteration.svg create mode 100644 docs/techniques/media/optical-flow/optical_flow_main_searching.svg create mode 100644 docs/techniques/media/optical-flow/optical_flow_main_upscale_area.svg create mode 100644 docs/techniques/media/optical-flow/optical_flow_preparation_luma.svg create mode 100644 docs/techniques/media/optical-flow/optical_flow_preparation_scenechange.svg create mode 100644 docs/techniques/media/super-resolution-interpolation/01_FSR3_DataFlow.svg create mode 100644 docs/techniques/media/super-resolution-interpolation/02_FSR3_Flow.svg create mode 100644 docs/techniques/media/super-resolution-interpolation/03_FSR3_FlowAsyncQueue.svg create mode 100644 docs/techniques/media/super-resolution-interpolation/04_FSR3_UiCallback.svg create mode 100644 docs/techniques/media/super-resolution-interpolation/05_FSR3_NoFG_UiCallback.svg create mode 100644 docs/techniques/media/super-resolution-interpolation/06_FSR3_UiTex.svg create mode 100644 docs/techniques/media/super-resolution-interpolation/07_FSR3_NoFG_UiTex.svg create mode 100644 docs/techniques/media/super-resolution-interpolation/08_FSR3_HUDLess.svg create mode 100644 docs/techniques/media/super-resolution-temporal/fsr3-sample.jpg create mode 100644 docs/techniques/media/super-resolution-temporal/fsr3-sample_resized.jpg create mode 100644 docs/techniques/optical-flow.md create mode 100644 docs/techniques/super-resolution-interpolation.md create mode 100644 docs/techniques/super-resolution-upscaler.md create mode 100644 framework/rendermodules/animatedtextures/animatedtexturesrendermodule.cpp create mode 100644 framework/rendermodules/animatedtextures/animatedtexturesrendermodule.h create mode 100644 framework/rendermodules/animatedtextures/shaders/AnimatedTexture.hlsl create mode 100644 samples/ffx_cauldron/GPUTimestamps.cpp create mode 100644 samples/ffx_cauldron/GPUTimestamps.h create mode 100644 samples/ffx_cauldron/cpu_time_event_rate.cpp create mode 100644 samples/ffx_cauldron/cpu_time_event_rate.h create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_CopyUiResource_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_CopyUiResource_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_ReplacementFrameResource_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_ReplacementFrameResource_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionPS_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionPS_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionVS_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionVS_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UpscalerDispatchComposition_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UpscalerDispatchComposition_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.hlsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_setup.glsl create mode 100644 samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_setup.hlsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_blit_to_output_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.glsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.hlsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.glsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.hlsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.glsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.hlsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.glsl create mode 100644 samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.hlsl create mode 100644 samples/fsr/HLSLCompile/HLSLShaderCompiler.cpp create mode 100644 samples/fsr/HLSLCompile/HLSLShaderCompiler.h create mode 100644 samples/fsr/HLSLCompile/shadercompiler.cpp create mode 100644 samples/fsr/HLSLCompile/shadercompiler.h create mode 100644 samples/fsr/fsr3rendermodule.cpp create mode 100644 samples/fsr/fsr3rendermodule.h create mode 100644 samples/fsr/fsr3upscalerendermodule.cpp create mode 100644 samples/fsr/fsr3upscalerendermodule.h create mode 100644 samples/fsr/media/checkerboard.dds create mode 100644 samples/fsr/media/composition_text.dds create mode 100644 samples/fsr/media/lion.jpg create mode 100644 samples/fsr/shaders/HudLessBlit.hlsl create mode 100644 samples/hybridreflections/shaders/copy_depth_and_reset_debug.hlsl create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_common.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_debug_view.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_inpainting.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_resources.h create mode 100644 sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_setup.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_callbacks_hlsl.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_common.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_resources.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_accumulate.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_common.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_depth_clip.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_lock.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_postprocess_lock_status.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_rcas.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_reconstruct_dilated_velocity_and_previous_depth.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_reproject.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_resources.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_sample.h create mode 100644 sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_upsample.h create mode 100644 sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_callbacks_hlsl.h create mode 100644 sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_common.h create mode 100644 sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_luminance_pyramid.h create mode 100644 sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_optical_flow_v5.h create mode 100644 sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_scd_divergence.h create mode 100644 sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_filter_optical_flow_v5.h create mode 100644 sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_generate_scd_histogram.h create mode 100644 sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_prepare_luma.h create mode 100644 sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_resources.h create mode 100644 sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_v5.h create mode 100644 sdk/include/FidelityFX/host/ffx_frameinterpolation.h create mode 100644 sdk/include/FidelityFX/host/ffx_fsr3.h create mode 100644 sdk/include/FidelityFX/host/ffx_fsr3upscaler.h create mode 100644 sdk/include/FidelityFX/host/ffx_opticalflow.h create mode 100644 sdk/src/backends/dx12/CMakeShadersFSR3Upscaler.txt create mode 100644 sdk/src/backends/dx12/CMakeShadersFrameinterpolation.txt create mode 100644 sdk/src/backends/dx12/CMakeShadersOpticalflow.txt create mode 100644 sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12.cpp create mode 100644 sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12.h create mode 100644 sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_Helpers.cpp create mode 100644 sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_Helpers.h create mode 100644 sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_UiComposition.cpp create mode 100644 sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_UiComposition.h create mode 100644 sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiComposition.hlsl create mode 100644 sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiCompositionPS.h create mode 100644 sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiCompositionVS.h create mode 100644 sdk/src/backends/dx12/FrameInterpolationSwapchain/recompileUiCompositionHLSL.bat create mode 100644 sdk/src/backends/dx12/GPUTimestamps.cpp create mode 100644 sdk/src/backends/dx12/GPUTimestamps.h create mode 100644 sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_debug_view_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_setup_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_debug_blit.hlsl create mode 100644 sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.hlsl create mode 100644 sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.hlsl create mode 100644 sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.hlsl create mode 100644 sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.hlsl create mode 100644 sdk/src/backends/shared/blob_accessors/ffx_frameinterpolation_shaderblobs.cpp create mode 100644 sdk/src/backends/shared/blob_accessors/ffx_frameinterpolation_shaderblobs.h create mode 100644 sdk/src/backends/shared/blob_accessors/ffx_fsr3upscaler_shaderblobs.cpp create mode 100644 sdk/src/backends/shared/blob_accessors/ffx_fsr3upscaler_shaderblobs.h create mode 100644 sdk/src/backends/shared/blob_accessors/ffx_opticalflow_shaderblobs.cpp create mode 100644 sdk/src/backends/shared/blob_accessors/ffx_opticalflow_shaderblobs.h create mode 100644 sdk/src/components/frameinterpolation/CMakeLists.txt create mode 100644 sdk/src/components/frameinterpolation/ffx_frameinterpolation.cpp create mode 100644 sdk/src/components/frameinterpolation/ffx_frameinterpolation_private.h create mode 100644 sdk/src/components/fsr3/CMakeLists.txt create mode 100644 sdk/src/components/fsr3/ffx_fsr3.cpp create mode 100644 sdk/src/components/fsr3/ffx_fsr3_maximum_bias.h create mode 100644 sdk/src/components/fsr3/ffx_fsr3_private.h create mode 100644 sdk/src/components/fsr3upscaler/CMakeLists.txt create mode 100644 sdk/src/components/fsr3upscaler/ffx_fsr3upscaler.cpp create mode 100644 sdk/src/components/fsr3upscaler/ffx_fsr3upscaler_maximum_bias.h create mode 100644 sdk/src/components/fsr3upscaler/ffx_fsr3upscaler_private.h create mode 100644 sdk/src/components/opticalflow/CMakeLists.txt create mode 100644 sdk/src/components/opticalflow/ffx_opticalflow.cpp create mode 100644 sdk/src/components/opticalflow/ffx_opticalflow_private.h diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f7a1a864..c22f10fc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -156,6 +156,7 @@ package_release_samples: - ./LICENSE.txt - ./readme.md - ./sample.cmake + - ./Third_party_notices.txt package_debug_samples: stage: package @@ -179,3 +180,4 @@ package_debug_samples: - ./LICENSE.txt - ./readme.md - ./sample.cmake + - ./Third_party_notices.txt diff --git a/BuildAllCauldronEffectsSolution.bat b/BuildAllCauldronEffectsSolution.bat index 0eadece5..05abda52 100644 --- a/BuildAllCauldronEffectsSolution.bat +++ b/BuildAllCauldronEffectsSolution.bat @@ -26,8 +26,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=ALL_SAMPLES -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=ALL_SAMPLES -DFFX_API=CAULDRON %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/BuildAllCauldronEffectsSolutionDll.bat b/BuildAllCauldronEffectsSolutionDll.bat new file mode 100644 index 00000000..851b7f90 --- /dev/null +++ b/BuildAllCauldronEffectsSolutionDll.bat @@ -0,0 +1,2 @@ +@echo off +call BuildAllCauldronEffectsSolution.bat -DFFX_BUILD_AS_DLL=1 diff --git a/BuildAllNativeEffectsSolution.bat b/BuildAllNativeEffectsSolution.bat index 248d0e2c..26a67739 100644 --- a/BuildAllNativeEffectsSolution.bat +++ b/BuildAllNativeEffectsSolution.bat @@ -3,7 +3,7 @@ :: Start by building the backend SDK echo Building native backend cd sdk -call BuildFidelityFXSDK.bat +call BuildFidelityFXSDK.bat %* cd .. echo. @@ -16,8 +16,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=ALL_SAMPLES -DFFX_API=NATIVE +cmake -A x64 .. -DBUILD_TYPE=ALL_SAMPLES -DFFX_API=NATIVE %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/BuildAllNativeEffectsSolutionDll.bat b/BuildAllNativeEffectsSolutionDll.bat new file mode 100644 index 00000000..b4efb5bf --- /dev/null +++ b/BuildAllNativeEffectsSolutionDll.bat @@ -0,0 +1,2 @@ +@echo off +call BuildAllNativeEffectsSolution.bat -DFFX_BUILD_AS_DLL=1 diff --git a/BuildBlurSolution.bat b/BuildBlurSolution.bat index d674f25e..8552445e 100644 --- a/BuildBlurSolution.bat +++ b/BuildBlurSolution.bat @@ -26,8 +26,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_BLUR -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_BLUR -DFFX_API=CAULDRON %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/BuildCACAOSolution.bat b/BuildCACAOSolution.bat index 02fb97a7..99072e18 100644 --- a/BuildCACAOSolution.bat +++ b/BuildCACAOSolution.bat @@ -26,8 +26,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_CACAO -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_CACAO -DFFX_API=CAULDRON %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/BuildCASSolution.bat b/BuildCASSolution.bat index eec0bf50..1a7ea787 100644 --- a/BuildCASSolution.bat +++ b/BuildCASSolution.bat @@ -26,8 +26,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_CAS -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_CAS -DFFX_API=CAULDRON %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/BuildCauldronSolution.bat b/BuildCauldronSolution.bat index 25436dcf..3db83ad8 100644 --- a/BuildCauldronSolution.bat +++ b/BuildCauldronSolution.bat @@ -26,8 +26,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -D BUILD_TYPE=CAULDRON +cmake -A x64 .. -D BUILD_TYPE=CAULDRON %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/BuildDOFSolution.bat b/BuildDOFSolution.bat index 069a519e..2d245841 100644 --- a/BuildDOFSolution.bat +++ b/BuildDOFSolution.bat @@ -26,8 +26,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_DOF -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_DOF -DFFX_API=CAULDRON %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/BuildFSRSolution.bat b/BuildFSRSolution.bat index 2d9b10a1..4341b172 100644 --- a/BuildFSRSolution.bat +++ b/BuildFSRSolution.bat @@ -26,8 +26,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_FSR -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_FSR -DFFX_API=CAULDRON %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/BuildFSRSolutionNative.bat b/BuildFSRSolutionNative.bat new file mode 100644 index 00000000..63d24ad6 --- /dev/null +++ b/BuildFSRSolutionNative.bat @@ -0,0 +1,39 @@ +@echo off + +echo =============================================================== +echo. +echo FidelityFX Build System +echo. +echo =============================================================== +echo Checking pre-requisites... + +:: Check if cmake is installed +cmake --version > nul 2>&1 +if %errorlevel% NEQ 0 ( + echo Cannot find path to CMake. Is CMake installed? Exiting... + exit /b -1 +) else ( + echo CMake Ready. +) + +:: Start by building the backend SDK +echo Building native backend +cd sdk +call BuildFidelityFXSDK.bat +cd .. + +echo. +echo Building FSR sample solution +echo. + +:: Check directories exist and create if not +if not exist build\ ( + mkdir build +) + +cd build +cmake -A x64 .. -DBUILD_TYPE=FFX_FSR -DFFX_API=NATIVE %* + +:: Come back to root level +cd .. +pause diff --git a/BuildFSRSolutionNativeDll.bat b/BuildFSRSolutionNativeDll.bat new file mode 100644 index 00000000..c8caa46a --- /dev/null +++ b/BuildFSRSolutionNativeDll.bat @@ -0,0 +1,40 @@ +@echo off + +echo =============================================================== +echo. +echo FidelityFX Build System +echo. +echo =============================================================== +echo Checking pre-requisites... + +:: Check if cmake is installed +cmake --version > nul 2>&1 +if %errorlevel% NEQ 0 ( + echo Cannot find path to CMake. Is CMake installed? Exiting... + exit /b -1 +) else ( + echo CMake Ready. +) + +:: Start by building the backend SDK +:: CUSTOM_CHANGES_TO_FSR3 build FSR3 DLL with RelWithDebInfo configuration +echo Building native backend +cd sdk +call BuildFidelityFXSDK.bat -DFFX_BUILD_AS_DLL=1 +cd .. + +echo. +echo Building FSR sample solution +echo. + +:: Check directories exist and create if not +if not exist build\ ( + mkdir build +) + +cd build +cmake -A x64 .. -DBUILD_TYPE=FFX_FSR -DFFX_API=NATIVE -DFFX_BUILD_AS_DLL=1 + +:: Come back to root level +cd .. +pause \ No newline at end of file diff --git a/BuildHybridReflectionsSolution.bat b/BuildHybridReflectionsSolution.bat index 832381ef..38633eb5 100644 --- a/BuildHybridReflectionsSolution.bat +++ b/BuildHybridReflectionsSolution.bat @@ -26,7 +26,7 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_HYBRIDREFLECTIONS -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_HYBRIDREFLECTIONS -DFFX_API=CAULDRON %* :: Come back to root level cd .. diff --git a/BuildHybridShadowsSolution.bat b/BuildHybridShadowsSolution.bat index 06cb1fab..cad1a320 100644 --- a/BuildHybridShadowsSolution.bat +++ b/BuildHybridShadowsSolution.bat @@ -26,7 +26,7 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_HYBRIDSHADOWS -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_HYBRIDSHADOWS -DFFX_API=CAULDRON %* :: Come back to root level cd .. diff --git a/BuildLPMSolution.bat b/BuildLPMSolution.bat index edba9c10..68bcae9d 100644 --- a/BuildLPMSolution.bat +++ b/BuildLPMSolution.bat @@ -26,7 +26,7 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_LPM -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_LPM -DFFX_API=CAULDRON %* :: Come back to root level cd .. diff --git a/BuildLensSolution.bat b/BuildLensSolution.bat index 9daa70c3..56bd8e76 100644 --- a/BuildLensSolution.bat +++ b/BuildLensSolution.bat @@ -26,7 +26,7 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_LENS -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_LENS -DFFX_API=CAULDRON %* :: Come back to root level cd .. diff --git a/BuildParallelSortSolution.bat b/BuildParallelSortSolution.bat index af29e0f9..37c92dd7 100644 --- a/BuildParallelSortSolution.bat +++ b/BuildParallelSortSolution.bat @@ -26,8 +26,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_PARALLEL_SORT -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_PARALLEL_SORT -DFFX_API=CAULDRON %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/BuildSPDSolution.bat b/BuildSPDSolution.bat index 80520b7b..ce96ab1c 100644 --- a/BuildSPDSolution.bat +++ b/BuildSPDSolution.bat @@ -26,8 +26,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_SPD -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_SPD -DFFX_API=CAULDRON %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/BuildSSSRSolution.bat b/BuildSSSRSolution.bat index 9a819f3d..5e6bcd2e 100644 --- a/BuildSSSRSolution.bat +++ b/BuildSSSRSolution.bat @@ -26,7 +26,7 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_SSSR -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_SSSR -DFFX_API=CAULDRON %* :: Come back to root level cd .. diff --git a/BuildVRSSolution.bat b/BuildVRSSolution.bat index c591f415..c7c76419 100644 --- a/BuildVRSSolution.bat +++ b/BuildVRSSolution.bat @@ -26,8 +26,8 @@ if not exist build\ ( ) cd build -cmake -A x64 .. -DBUILD_TYPE=FFX_VRS -DFFX_API=CAULDRON +cmake -A x64 .. -DBUILD_TYPE=FFX_VRS -DFFX_API=CAULDRON %* :: Come back to root level cd .. -pause \ No newline at end of file +pause diff --git a/CMakeLists.txt b/CMakeLists.txt index 289b4cd4..1793de96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ # Copyright (C) 2023 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files(the “Software”), to deal +# 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 @@ -12,7 +12,7 @@ # 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 +# 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 @@ -48,8 +48,9 @@ if (CMAKE_GENERATOR_PLATFORM STREQUAL x64) createConfig(DX12 DebugDX12 DEBUG) createConfig(VK DebugVK DEBUG) createConfig(DX12 ReleaseDX12 RELEASE) + createConfig(DX12 RelWithDebInfoDX12 RELWITHDEBINFO) createConfig(VK ReleaseVK RELEASE) - set(CMAKE_CONFIGURATION_TYPES "DebugDX12;DebugVK;ReleaseDX12;ReleaseVK") + set(CMAKE_CONFIGURATION_TYPES "DebugDX12;DebugVK;ReleaseDX12;ReleaseVK;RelWithDebInfoDX12") message(STATUS "Generated with config types: ${CMAKE_CONFIGURATION_TYPES}") # Set compile definitions as well @@ -57,6 +58,7 @@ if (CMAKE_GENERATOR_PLATFORM STREQUAL x64) $<$:_DX12 _WIN> $<$:_VK _WIN> $<$:_DX12 _WIN _RELEASE> + $<$:_DX12 _WIN _RELEASE> $<$:_VK _WIN _RELEASE> NOMINMAX ) @@ -76,6 +78,7 @@ unset(FFX_ALL CACHE) unset(FFX_FSR CACHE) unset(FFX_FSR1 CACHE) unset(FFX_FSR2 CACHE) +unset(FFX_FSR3 CACHE) unset(FFX_SPD CACHE) unset(FFX_CACAO CACHE) unset(FFX_LPM CACHE) @@ -96,13 +99,14 @@ if (BUILD_TYPE STREQUAL ALL_SAMPLES) message(STATUS "Enabling build of all Effects") option(FFX_ALL "Build All FidelityFX Samples and APIs" ON) else() - #Only enable the FFX API for the effect requested - option(FFX_ALL "Build All FidelityFX Samples and APIs" OFF) - if (BUILD_TYPE STREQUAL FFX_FSR) - option(FFX_FSR "Build FSR Sample" ON) - option(FFX_FSR1 "Build FFX FSR1 API" ON) - option(FFX_FSR2 "Build FFX FSR2 API" ON) - endif() + #Only enable the FFX API for the effect requested + option(FFX_ALL "Build All FidelityFX Samples and APIs" OFF) + if (BUILD_TYPE STREQUAL FFX_FSR) + option(FFX_FSR "Build FSR Sample" ON) + option(FFX_FSR1 "Build FFX FSR1 API" ON) + option(FFX_FSR2 "Build FFX FSR2 API" ON) + option(FFX_FSR3 "Build FFX FSR3 API" ON) + endif() if (BUILD_TYPE STREQUAL FFX_CACAO) option(FFX_CACAO "Build CACAO Sample" ON) @@ -147,15 +151,15 @@ else() endif() if (BUILD_TYPE STREQUAL FFX_SSSR) - option(FFX_SSSR "Build SSSR Sample" ON) - option(FFX_DENOISER "Build Denoiser Sample" ON) + option(FFX_SSSR "Build SSSR Sample" ON) + option(FFX_DENOISER "Build Denoiser Sample" ON) endif() - + if (BUILD_TYPE STREQUAL FFX_HYBRIDREFLECTIONS) - option(FFX_HYBRIDREFLECTIONS "Build Hybrid Reflections Sample" ON) - option(FFX_CLASSIFIER "Build Classifier Sample" ON) - option(FFX_DENOISER "Build Denoiser Sample" ON) - option(FFX_SPD "Build SPD Sample" ON) + option(FFX_HYBRIDREFLECTIONS "Build Hybrid Reflections Sample" ON) + option(FFX_CLASSIFIER "Build Classifier Sample" ON) + option(FFX_DENOISER "Build Denoiser Sample" ON) + option(FFX_SPD "Build SPD Sample" ON) endif() endif() @@ -185,19 +189,65 @@ if (FFX_API STREQUAL CAULDRON) # Build cauldron backend add_subdirectory(${FFX_API_CAULDRON_ROOT}) else() - # Set compile definitions for used API - set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS - $<$,$>:FFX_API_DX12> - $<$,$>:FFX_API_VK>) - - # Import libs - add_library(ffx_backend_native STATIC IMPORTED) - set_target_properties(ffx_backend_native PROPERTIES - IMPORTED_CONFIGURATIONS "DebugDX12;DebugVK;ReleaseDX12;ReleaseVK" - IMPORTED_LOCATION_DEBUGDX12 "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_dx12_x64d.lib" - IMPORTED_LOCATION_RELEASEDX12 "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_dx12_x64.lib" - IMPORTED_LOCATION_DEBUGVK "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_vk_x64d.lib" - IMPORTED_LOCATION_RELEASEVK "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_vk_x64.lib") + # Set compile definitions for used API + set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS + $<$,$,$>:FFX_API_DX12> + $<$,$>:FFX_API_VK>) + + # Import libs + if (FFX_BUILD_AS_DLL) + add_library(ffx_backend_native SHARED IMPORTED) + set_target_properties(ffx_backend_native PROPERTIES + IMPORTED_CONFIGURATIONS "DebugDX12;DebugVK;ReleaseDX12;ReleaseVK;RelWithDebInfoDX12" + IMPORTED_IMPLIB_DEBUGDX12 "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_dx12_x64d.lib" + IMPORTED_LOCATION_DEBUGDX12 "${SDK_ROOT}/build/src/backends/dx12/debug/ffx_backend_dx12_x64d.dll" + IMPORTED_IMPLIB_RELEASEDX12 "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_dx12_x64.lib" + IMPORTED_LOCATION_RELEASEDX12 "${SDK_ROOT}/build/src/backends/dx12/release/ffx_backend_dx12_x64.dll" + IMPORTED_IMPLIB_RELWITHDEBINFODX12 "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_dx12_x64.lib" + IMPORTED_LOCATION_RELWITHDEBINFODX12 "${SDK_ROOT}/build/src/backends/dx12/RelWithDebInfo/ffx_backend_dx12_x64.dll" + IMPORTED_IMPLIB_DEBUGVK "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_vk_x64d.lib" + IMPORTED_LOCATION_DEBUGVK "${SDK_ROOT}/build/src/backends/vk/debug/ffx_backend_vk_x64d.dll" + IMPORTED_IMPLIB_RELEASEVK "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_vk_x64.lib" + IMPORTED_LOCATION_RELEASEVK "${SDK_ROOT}/build/src/backends/vk/release/ffx_backend_vk_x64.dll") + + ADD_CUSTOM_TARGET(CopyDLL ALL + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $<$:"${SDK_ROOT}/build/src/backends/dx12/debug/ffx_backend_dx12_x64d.dll"> + $<$:"${SDK_ROOT}/build/src/backends/dx12/debug/ffx_backend_dx12_x64d.pdb"> + $<$:"${SDK_ROOT}/build/src/backends/dx12/release/ffx_backend_dx12_x64.dll"> + $<$:"${SDK_ROOT}/build/src/backends/dx12/RelWithDebInfo/ffx_backend_dx12_x64.dll"> + $<$:"${SDK_ROOT}/build/src/backends/dx12/RelWithDebInfo/ffx_backend_dx12_x64.pdb"> + $<$:"${SDK_ROOT}/build/src/backends/vk/debug/ffx_backend_vk_x64d.dll"> + $<$:"${SDK_ROOT}/build/src/backends/vk/release/ffx_backend_vk_x64.dll"> + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + else() + add_library(ffx_backend_native STATIC IMPORTED) + set_target_properties(ffx_backend_native PROPERTIES + IMPORTED_CONFIGURATIONS "DebugDX12;DebugVK;ReleaseDX12;ReleaseVK" + IMPORTED_LOCATION_DEBUGDX12 "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_dx12_x64d.lib" + IMPORTED_LOCATION_RELEASEDX12 "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_dx12_x64.lib" + IMPORTED_LOCATION_RELWITHDEBINFODX12 "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_dx12_x64.lib" + IMPORTED_LOCATION_DEBUGVK "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_vk_x64d.lib" + IMPORTED_LOCATION_RELEASEVK "${SDK_ROOT}/bin/ffx_sdk/ffx_backend_vk_x64.lib") + endif() + + + ADD_CUSTOM_TARGET(symlink-shaders-FSR3 ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${SDK_ROOT}/src/backends/dx12/shaders/fsr3upscaler ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ffx_sdk/fsr3upscaler) + ADD_CUSTOM_TARGET(symlink-shaders-FSR2 ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${SDK_ROOT}/src/backends/dx12/shaders/fsr2 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ffx_sdk/fsr2) + ADD_CUSTOM_TARGET(symlink-shaders-OF ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${SDK_ROOT}/src/backends/dx12/shaders/opticalflow ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ffx_sdk/opticalflow) + ADD_CUSTOM_TARGET(symlink-shaders-FI ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${SDK_ROOT}/src/backends/dx12/shaders/frameinterpolation ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ffx_sdk/frameinterpolation) + ADD_CUSTOM_TARGET(symlink-shader-includes ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${SDK_ROOT}/include/FidelityFX/gpu ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ffx_sdk/fidelityfx-sdk-gpu) + + add_dependencies(symlink-shaders-FSR3 Framework) + add_dependencies(symlink-shaders-FSR2 Framework) + add_dependencies(symlink-shaders-OF Framework) + add_dependencies(symlink-shaders-FI Framework) + add_dependencies(symlink-shader-includes Framework) endif() # Build all other effect samples diff --git a/Third_party_notices.txt b/Third_party_notices.txt new file mode 100644 index 00000000..9fb81188 --- /dev/null +++ b/Third_party_notices.txt @@ -0,0 +1,345 @@ +AMD Copyrighted code (MIT) + +Copyright Statements + +Copyright (c) 2020-2023 Advanced Micro Devices, Inc. All rights reserved. + +License Text http://spdx.org/licenses/MIT + +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 NON-INFRINGEMENT. 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. + + +baldurk-renderdoc v-u (MIT) + + +Copyright Statements + +Copyright (c) 2015-2022 Baldur Karlsson +Copyright (c) 2014 Crytek +Copyright (c) 1998-2018 Third party code and tools + +License Text https://spdx.org/licenses/MIT.html + +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 NON-INFRINGEMENT. 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. + + +DirectX12 Agility SDK v1.608.2 (Other) + + +Copyright Statements + +Copyright Microsoft Corporation. All Rights Reserved. + +License Text https://www.nuget.org/packages/Microsoft.Direct3D.D3D12/1.608.2/License + +MICROSOFT DIRECTX + +These license terms are an agreement between you and Microsoft +Corporation (or one of its affiliates). They apply to the software named +above and any Microsoft services or software updates (except to the +extent such services or updates are accompanied by new or additional +terms, in which case those different terms apply prospectively and do +not alter your or Microsoft's rights relating to pre-updated software or +services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS +BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. + +INSTALLATION AND USE RIGHTS. + +General. Subject to the terms of this agreement, you may install and use any number of copies of the software, and solely for use on Windows. + +Included Microsoft Applications. The software may include other Microsoft applications. These license terms apply to those included applications, if any, unless other license terms are provided with the other Microsoft applications. + +Microsoft Platforms. The software may include components from Microsoft Windows. These components are governed by separate agreements and their own product support policies, as described in the license terms found in the installation directory for that component or in the “Licenses” folder accompanying the software. + +Third Party Components. The software may include third party components with separate legal notices or governed by other agreements, as may be described in the ThirdPartyNotices file(s) accompanying the software. + +DATA. + +Data Collection. The software may collect information about you and your use of the software, and send that to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may opt-out of many of these scenarios, but not all, as described in the product documentation.There are also some features in the software that may enable you to collect data from users of your applications. If you use these features to enable data collection in your applications, you must comply with applicable law, including providing appropriate notices to users of your applications. You can learn more about data collection and use in the help documentation and the privacy statement at https://aka.ms/privacy. Your use of the software operates as your consent to these practices. + +Processing of Personal Data. To the extent Microsoft is a processor or subprocessor of personal data in connection with the software, Microsoft makes the commitments in the European Union General Data Protection Regulation Terms of the Online Services Terms to all customers effective May 25, 2018, at https://docs.microsoft.com/en-us/legal/gdpr. + +DISTRIBUTABLE CODE. The software may contain code you are permitted to distribute (i.e. make available for third parties) in applications you develop, as described in this Section. + +Distribution Rights. The code and test files described below are distributable if included with the software. + +Distributables. You may copy and distribute the object code form of the software listed in the distributables file list in the software; and + +Third Party Distribution. You may permit distributors of your applications to copy and distribute any of this distributable code you elect to distribute with your applications. + +Distribution Requirements. For any code you distribute, you must: + +add significant primary functionality to it in your applications; + +i.require distributors and external end users to agree to terms that protect it and Microsoft at least as much as this agreement; and + +ii. indemnify, defend, and hold harmless Microsoft from any claims, including attorneys' fees, related to the distribution or use of your applications, except to the extent that any claim is based solely on the unmodified distributable code. + +Distribution Restrictions. You may not: + +use Microsoft's trademarks or trade dress in your application in any way that suggests your application comes from or is endorsed by Microsoft; or modify or distribute the source code of any distributable code so that any part of it becomes subject to any license that requires that the distributable code, any other part of the software, or any of Microsoft's other intellectual property be disclosed or distributed in source code form, or that others have the right to modify it. + +SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to): + +work around any technical limitations in the software that only allow you to use it in certain ways; + +reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the software, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the software; + +remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software; + +use the software in any way that is against the law or to create or propagate malware; or + +share, publish, distribute, or lease the software (except for any distributable code, subject to the terms above), provide the software as a stand-alone offering for others to use, or transfer the software or this agreement to any third party. + +EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit https://aka.ms/exporting. + +SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is “as is”, “with all faults”, and without warranty of any kind. + +UPDATES. The software may periodically check for updates, and download and install them for you. You may obtain updates only from Microsoft or authorized sources. Microsoft may need to update your system to provide you with updates. You agree to receive these automatic updates without any additional notice. Updates may not include or support all existing software features, services, or peripheral devices. + +ENTIRE AGREEMENT. This agreement, and any other terms Microsoft may provide for supplements, updates, or third-party applications, is the entire agreement for the software. + +APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles. If you acquired the software in any other country, its laws apply. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court. If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court. + +CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you: + +a.Australia. You have statutory guarantees under the Australian +Consumer Law and nothing in this agreement is intended to affect +those rights. + +b.Canada. If you acquired this software in Canada, you may stop +receiving updates by turning off the automatic update feature, +disconnecting your device from the Internet (if and when you +re-connect to the Internet, however, the software will resume +checking for and installing updates), or uninstalling the software. +The product documentation, if any, may also specify how to turn off +updates for your specific device or software. + +c.Germany and Austria. + +i. Warranty. The properly licensed software will perform substantially +as described in any Microsoft materials that accompany the software. +However, Microsoft gives no contractual guarantee in relation to the +licensed software. + +ii. Limitation of Liability. In case of intentional conduct, gross +negligence, claims based on the Product Liability Act, as well as, in +case of death or personal or physical injury, Microsoft is liable +according to the statutory law. + +Subject to the foregoing clause ii., Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence. + +DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + +LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT, OR INCIDENTAL DAMAGES. + +This limitation applies to (a) anything related to the software, +services, content (including code) on third party Internet sites, or +third party applications; and (b) claims for breach of contract, +warranty, guarantee, or condition; strict liability, negligence, or +other tort; or any other claim; in each case to the extent permitted by +applicable law. + +It also applies even if Microsoft knew or should have known about the +possibility of the damages. The above limitation or exclusion may not +apply to you because your state, province, or country may not allow the +exclusion or limitation of incidental, consequential, or other damages. + +Please note: As this software is distributed in Canada, some of the +clauses in this agreement are provided below in French. + +Remarque: Ce logiciel étant distribué au Canada, certaines des clauses +dans ce contrat sont fournies ci-dessous en français. + +EXONéRATION DE GARANTIE. Le logiciel visé par une licence est offert " +tel quel ". Toute utilisation de ce logiciel est à votre seule risque et +péril. Microsoft n'accorde aucune autre garantie expresse. Vous pouvez +bénéficier de droits additionnels en vertu du droit local sur la +protection des consommateurs, que ce contrat ne peut modifier. La ou +elles sont permises par le droit locale, les garanties implicites de +qualité marchande, d'adéquation à un usage particulier et d'absence de +contrefaçon sont exclues. + +LIMITATION DES DOMMAGES-INTéRêTS ET EXCLUSION DE RESPONSABILITé POUR LES +DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une +indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ +US. Vous ne pouvez prétendre à aucune indemnisation pour les autres +dommages, y compris les dommages spéciaux, indirects ou accessoires et +pertes de bénéfices. + +Cette limitation concerne: + +• tout ce qui est relié au logiciel, aux services ou au contenu (y +compris le code) figurant sur des sites Internet tiers ou dans des +programmes tiers; et + +• les réclamations au titre de violation de contrat ou de garantie, ou +au titre de responsabilité stricte, de négligence ou d'une autre faute +dans la limite autorisée par la loi en vigueur. + +Elle s'applique également, même si Microsoft connaissait ou devrait +connaître l'éventualité d'un tel dommage. Si votre pays n'autorise pas +l'exclusion ou la limitation de responsabilité pour les dommages +indirects, accessoires ou de quelque nature que ce soit, il se peut que +la limitation ou l'exclusion ci-dessus ne s'appliquera pas à votre +égard. + +EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. +Vous pourriez avoir d'autres droits prévus par les lois de votre pays. +Le présent contrat ne modifie pas les droits que vous confèrent les lois +de votre pays si celles-ci ne le permettent pas. + +glampert-vectormath v-u (BSD-3-Clause) + + +Copyright Statements + +Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. +All rights reserved. + +License Text http://spdx.org/licenses/BSD-3-Clause + +Redistribution and use in source and binary forms,with or without modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of the Sony Computer Entertainment Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +MD5 v-u (MIT) + + +Copyright Statements + +Copyright 2020 Gray Watson +Copyright (c) 2015 Michael + +License Text https://spdx.org/licenses/MIT.html + +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 NON-INFRINGEMENT. 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. +. + +microsoft-directx-headers v-u (MIT) + + +Copyright Statements + +Copyright (c) Microsoft Corporation. + +License Text https://spdx.org/licenses/MIT.html + +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. + +microsoft-directxshadercompiler v101.5 (NCSA) + + +Copyright Statements + +Copyright Microsoft Corporation + +License Text http://spdx.org/licenses/NCSA + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with 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: +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. +Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. +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 CONTRIBUTORS 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 INWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THESOFTWARE. + + +nlohmann-json v3.11.2 (MIT) + + +Copyright Statements + +Copyright (c) 2013-2017 Niels Lohmann + +License Text http://spdx.org/licenses/MIT + +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 NON-INFRINGEMENT. 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. + +ocornut-imgui v1.87 (MIT) + + +Copyright Statements + +Copyright (c) 2014-2022 Omar Cornut + +License Text http://spdx.org/licenses/MIT + +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 NON-INFRINGEMENT. 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. + + +SPIRV-Reflect v-u (Apache-2.0) + + +Copyright Statements + +Copyright 2017-2022 Google Inc. + +License Text http://spdx.org/licenses/Apache-2.0 + +http://www.apache.org/licenses/ +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +1. Definitions. +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: +You must give any other recipients of the Work or Derivative Works a copy of this License; and +You must cause any modified files to carry prominent notices stating that You changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. +END OF TERMS AND CONDITIONS +APPENDIX: How to apply the Apache License to your work +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. +Copyright [yyyy] [name of copyright owner] +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and limitations under the License. + + +https://spdx.org/licenses/Apache-2.0.html + + +tiny-process-library v-u (MIT) + + +Copyright Statements + +Copyright (c) 2015-2020 Ole Christian Eidheim + +License Text http://spdx.org/licenses/MIT + +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 NON-INFRINGEMENT. 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. + + + diff --git a/docs/getting-started/building-samples.md b/docs/getting-started/building-samples.md index 7e2ed20e..812d6ec9 100644 --- a/docs/getting-started/building-samples.md +++ b/docs/getting-started/building-samples.md @@ -13,21 +13,21 @@ To build the samples in the AMD FidelityFX SDK you should follow these instructi - [Windows 10 SDK 10.0.18362.0](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk) - [Vulkan SDK 1.3.239](https://vulkan.lunarg.com/) -2) Generate Visual Studio solutions: +2) Generate Visual Studio FSR sample solutions: -**Cauldron custom-backend version** +**Native-backend linked version** ```bash - > \BuildAllCauldronEffectsSolution.bat + > \BuildFSRSolutionNative.bat ``` -**Native-backend linked versions** +**Native-backend DLL version** ```bash - > \BuildAllNativeEffectsSolution.bat + > \BuildFSRSolutionNativeDll.bat ``` - This will generate a `build\` directory where you will find the solution for either the Cauldron-backed SDK samples (`FidelityFX SDK.sln`) or the native-backend-backed SDK samples (`FidelityFX SDK Native.sln`). + This will generate a `build\` directory where you will find the solution for either the native-backend-backed SDK samples (`FidelityFX SDK Native.sln`).

Building & running in Visual Studio

diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 7da9439b..d11f3ac5 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -2,7 +2,7 @@

Introduction to the AMD FidelityFX SDK

-The FidelityFX SDK is a collection of heavily optimized, open source effects (shader and runtime code) that can be used by developers to improve their DirectX®12 or Vulkan® applications. The FidelityFX SDK includes a number of effects: +The FidelityFX SDK is a collection of heavily optimized, open source technologies (shader and runtime code) that can be used by developers to improve their DirectX®12 or Vulkan® applications. The FidelityFX SDK includes a number of effects: - [Combined Adaptive Compute Ambient Occlusion 1.3](../techniques/combined-adaptive-compute-ambient-occlusion.md) - [Contrast Adaptive Sharpening 1.1](../techniques/contrast-adaptive-sharpening.md) @@ -14,6 +14,8 @@ The FidelityFX SDK is a collection of heavily optimized, open source effects (sh - [Stochastic Screen-Space Reflections 1.4](../techniques/stochastic-screen-space-reflections.md) - [Super Resolution 1.1](../techniques/super-resolution-spatial.md) - [Super Resolution 2.2](../techniques/super-resolution-temporal.md) +- [Super Resolution 3.0](../techniques/super-resolution-interpolation.md) +- [Super Resolution 3.0 Upscaler](../techniques/super-resolution-upscaler.md) - [Variable Shading 1.1](../techniques/variable-shading.md) - [Blur 1.0](../techniques/blur.md) - [Depth of Field 1.0](../techniques/depth-of-field.md) diff --git a/docs/index.md b/docs/index.md index e889f92e..fbcf6433 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,45 +1,50 @@

Welcome to the AMD FidelityFX SDK

-![alt text](/docs/media/fidelityfxsdk-logo-rescaled.png) +![alt text](media/fidelityfxsdk-logo-rescaled.png) The FidelityFX SDK is a collection of heavily optimized, open source technologies (shader and runtime code) that can be used by developers to improve their DirectX®12 or Vulkan® applications. The FidelityFX SDK includes: -| [FidelityFX SDK](https://gpuopen.com/amd-fidelityfx-sdk/) Technique | [Samples](/docs/samples/index.md) | [GPUOpen](https://gpuopen.com/) page | Description | +| [FidelityFX SDK](https://gpuopen.com/amd-fidelityfx-sdk/) Technique | [Samples](samples/index.md) | [GPUOpen](https://gpuopen.com/) page | Description | | --- | --- | --- | --- | -| [Combined Adaptive Compute Ambient Occlusion (CACAO)](/docs/techniques/combined-adaptive-compute-ambient-occlusion.md) 1.3 | [CACAO sample](/docs/samples/combined-adaptive-compute-ambient-occlusion.md) | [FidelityFX Ambient Occlusion](https://gpuopen.com/fidelityfx-cacao/) | Uses intelligent and adaptive sampling techniques to produce excellent quality ambient occlusion at high performance. | -| [Contrast Adaptive Sharpening (CAS)](/docs/techniques/contrast-adaptive-sharpening.md) 1.1 | [CAS sample](/docs/samples/contrast-adaptive-sharpening.md) | [FidelityFX Contrast Adaptive Sharpening](https://gpuopen.com/fidelityfx-cas/) | Implements a sharpening kernel that reclaims that high-frequency detail lost during rendering. | -| [Denoiser](/docs/techniques/denoiser.md) 1.2 | n/a | [FidelityFX Denoiser](https://gpuopen.com/fidelityfx-denoiser/) | Provides a set of denoising compute shaders which remove artifacts from reflection and shadow rendering. Useful for both raytraced or rasterized content. | -| [Classifier](/docs/techniques/classifier.md) 1.0 | n/a | n/a | Provides a set of tile classification compute shaders which prepare tile metadata to drive indirect workload generation. It's useful for guided and load-balanced ray tracing applications, letting you leverage ray tracing in an efficient manner. | -| [Luminance Preserving Mapper](/docs/techniques/luminance-preserving-mapper.md) 1.3 | [LPM sample](/docs/samples/luminance-preserving-mapper.md) | [FidelityFX HDR Mapper](https://gpuopen.com/fidelityfx-lpm/) | Offers a tone mapping and gamut mapping solution for HDR and wide gamut content. | -| [Parallel Sort](/docs/techniques/parallel-sort.md) 1.2 | [Parallel Sort sample](/docs/samples/parallel-sort.md) | [FidelityFX Parallel Sort](https://gpuopen.com/fidelityfx-parallel-sort/) | Implements GPU-accelerated parallel sorting techniques. The sorts are stable useful for sorting particles or other GPU-side data sets. | -| [Single Pass Downsampler](/docs/techniques/single-pass-downsampler.md) 2.1 | [SPD sample](/docs/samples/single-pass-downsampler.md) | [FidelityFX Downsampler](https://gpuopen.com/fidelityfx-spd/) | Allows you to downsample surfaces - and optionally generate a MIPmap chain - in a single compute dispatch. | -| [Stochastic Screen-Space Reflections](/docs/techniques/stochastic-screen-space-reflections.md) 1.4 | [SSSR sample](/docs/samples/stochastic-screen-space-reflections.md) | [FidelityFX Screen Space Reflections](https://gpuopen.com/fidelityfx-sssr/) | Provides high-fidelity screen-spaced reflections in your scene, without a hefty performance price tag. | -| [Super Resolution (Spatial)](/docs/techniques/super-resolution-spatial.md) 1.1 | [Super Resolution sample](/docs/samples/super-resolution.md) | [FidelityFX Super Resolution](https://gpuopen.com/fidelityfx-superresolution/) | Offers a spatial single-frame solution for producing higher resolution frames from lower resolution inputs. | -| [Super Resolution (Temporal)](/docs/techniques/super-resolution-temporal.md) 2.2.1 | [Super Resolution sample](/docs/samples/super-resolution.md) | [FidelityFX Super Resolution 2](https://gpuopen.com/fidelityfx-superresolution-2/) | Offers both spatial single-frame and temporal multi-frame solutions for producing high resolution frames from lower resolution inputs. | -| [Variable Shading](/docs/techniques/variable-shading.md) 1.1 | [Variable Shading sample](/docs/samples/variable-shading.md) | [FidelityFX Variable Shading](https://gpuopen.com/fidelityfx-variable-shading/) | Helps you to drive Variable Rate Shading hardware introduced in RDNA2-based and contemporary GPUs, by analyzing the luminance of pixels in a tile to determine where the shading rate can be lowered to increase performance. | -| New: [Blur](/docs/samples/blur.md) 1.0 | [Blur sample](/docs/samples/blur.md) | [FidelityFX Blur](https://gpuopen.com/fidelityfx-blur/) | A library of highly optimized functions which perform common blurring operations such as Gaussian blur, radial blurs, and others. | -| New: [Depth-of-Field](/docs/techniques/depth-of-field.md) 1.0 | [DoF sample](/docs/samples/depth-of-field.md) | [FidelityFX Depth of Field](https://gpuopen.com/fidelityfx-dof/) | Implements a high-quality DOF filter complete with bokeh. | -| New: [Lens](/docs/samples/lens.md) 1.0 | [Lens sample](/docs/samples/lens.md) | [FidelityFX Lens](https://gpuopen.com/fidelityfx-lens/) | Implements a library of optimized lens effects including chromatic aberration, film grain, and vignetting. | -| [Classifier (Shadows)](/docs/techniques/classifier.md) 1.1 [Denoiser (Shadows)](/docs/techniques/denoiser.md) 1.2 | [Hybrid Shadows sample](/docs/samples/hybrid-shadows.md) 1.1 | [FidelityFX Hybrid Shadows](https://gpuopen.com/fidelityfx-hybrid-shadows/) | An implementation of an example shadowing technique which shows you how you could combine rasterized shadow maps and hardware ray tracing to deliver high quality soft shadows at a reasonable performance cost. | -| [Classifier (Reflections)](/docs/techniques/classifier.md) 1.1 [Denoiser (Reflections)](/docs/techniques/denoiser.md) 1.2 | [Hybrid Reflections sample](/docs/samples/hybrid-reflections.md) 1.1 | [FidelityFX Hybrid Reflections](https://gpuopen.com/fidelityfx-hybrid-reflections/) | An implementation of an an example reflections technique which shows you how you could mix FidelityFX SSSR with ray traced reflections, delivering higher quality reflections than SSSR alone at reasonable performance cost. | +| [Combined Adaptive Compute Ambient Occlusion (CACAO)](techniques/combined-adaptive-compute-ambient-occlusion.md) 1.3 | [CACAO sample](samples/combined-adaptive-compute-ambient-occlusion.md) | [FidelityFX Ambient Occlusion](https://gpuopen.com/fidelityfx-cacao/) | Uses intelligent and adaptive sampling techniques to produce excellent quality ambient occlusion at high performance. | +| [Contrast Adaptive Sharpening (CAS)](techniques/contrast-adaptive-sharpening.md) 1.1 | [CAS sample](samples/contrast-adaptive-sharpening.md) | [FidelityFX Contrast Adaptive Sharpening](https://gpuopen.com/fidelityfx-cas/) | Implements a sharpening kernel that reclaims that high-frequency detail lost during rendering. | +| [Denoiser](techniques/denoiser.md) 1.2 | n/a | [FidelityFX Denoiser](https://gpuopen.com/fidelityfx-denoiser/) | Provides a set of denoising compute shaders which remove artifacts from reflection and shadow rendering. Useful for both raytraced or rasterized content. | +| [Classifier](techniques/classifier.md) 1.0 | n/a | n/a | Provides a set of tile classification compute shaders which prepare tile metadata to drive indirect workload generation. It's useful for guided and load-balanced ray tracing applications, letting you leverage ray tracing in an efficient manner. | +| [Luminance Preserving Mapper](techniques/luminance-preserving-mapper.md) 1.3 | [LPM sample](samples/luminance-preserving-mapper.md) | [FidelityFX HDR Mapper](https://gpuopen.com/fidelityfx-lpm/) | Offers a tone mapping and gamut mapping solution for HDR and wide gamut content. | +| [Parallel Sort](techniques/parallel-sort.md) 1.2 | [Parallel Sort sample](samples/parallel-sort.md) | [FidelityFX Parallel Sort](https://gpuopen.com/fidelityfx-parallel-sort/) | Implements GPU-accelerated parallel sorting techniques. The sorts are stable useful for sorting particles or other GPU-side data sets. | +| [Single Pass Downsampler](techniques/single-pass-downsampler.md) 2.1 | [SPD sample](samples/single-pass-downsampler.md) | [FidelityFX Downsampler](https://gpuopen.com/fidelityfx-spd/) | Allows you to downsample surfaces - and optionally generate a MIPmap chain - in a single compute dispatch. | +| [Stochastic Screen-Space Reflections](techniques/stochastic-screen-space-reflections.md) 1.4 | [SSSR sample](samples/stochastic-screen-space-reflections.md) | [FidelityFX Screen Space Reflections](https://gpuopen.com/fidelityfx-sssr/) | Provides high-fidelity screen-spaced reflections in your scene, without a hefty performance price tag. | +| [Super Resolution (Spatial)](techniques/super-resolution-spatial.md) 1.1 | [Super Resolution sample](samples/super-resolution.md) | [FidelityFX Super Resolution](https://gpuopen.com/fidelityfx-superresolution/) | Offers a spatial single-frame solution for producing higher resolution frames from lower resolution inputs. | +| [Super Resolution (Temporal)](techniques/super-resolution-temporal.md) 2.2.2 | [Super Resolution sample](samples/super-resolution.md) | [FidelityFX Super Resolution 2](https://gpuopen.com/fidelityfx-superresolution-2/) | Offers both spatial single-frame and temporal multi-frame solutions for producing high resolution frames from lower resolution inputs. | +| New: [Super Resolution 3](techniques/super-resolution-interpolation.md) 3.0.3 | [Super Resolution sample](samples/super-resolution.md) | [FidelityFX Super Resolution 3](https://gpuopen.com/fidelityfx-superresolution-3/) | Offers generation of interpolated frames in combination with our temporal multi-frame solution for producing high resolution frames from lower resolution inputs. | +| New: [Super Resolution (Upscaler)](techniques/super-resolution-upscaler.md) 3.0.3 | [Super Resolution sample](samples/super-resolution.md) | [FidelityFX Super Resolution 3](https://gpuopen.com/fidelityfx-superresolution-3/) | Offers temporal multi-frame solutions for producing high resolution frames from lower resolution inputs. | +| New: [Frame Interpolation](techniques/frame-interpolation.md) 1.0 | [Super Resolution sample](samples/super-resolution.md) | [FidelityFX Super Resolution 3](https://gpuopen.com/fidelityfx-superresolution-3/) | Offers generation of interpolated frames from multiple real input frames, and multile sources of motion vector data. | +| New: [Frame Interpolation SwapChain](techniques/frame-interpolation-swap-chain.md) 1.0 | [Super Resolution sample](samples/super-resolution.md) | [FidelityFX Super Resolution 3](https://gpuopen.com/fidelityfx-superresolution-3/) | A replacement DXGI Swapchain implementation for DX12 which allows for additional frames to be presented along with real game frames, with relevant frame pacing. | +| New: [Optical Flow](techniques/optical-flow.md) 1.0 | [Super Resolution sample](samples/super-resolution.md) | [FidelityFX Super Resolution 3](https://gpuopen.com/fidelityfx-superresolution-3/) | Offers a motion-estimation algorithm which is useful for generating block-based motion vectors from temporal image inputs. | +| [Variable Shading](techniques/variable-shading.md) 1.1 | [Variable Shading sample](samples/variable-shading.md) | [FidelityFX Variable Shading](https://gpuopen.com/fidelityfx-variable-shading/) | Helps you to drive Variable Rate Shading hardware introduced in RDNA2-based and contemporary GPUs, by analyzing the luminance of pixels in a tile to determine where the shading rate can be lowered to increase performance. | +| [Blur](samples/blur.md) 1.0 | [Blur sample](samples/blur.md) | [FidelityFX Blur](https://gpuopen.com/fidelityfx-blur/) | A library of highly optimized functions which perform common blurring operations such as Gaussian blur, radial blurs, and others. | +| [Depth-of-Field](techniques/depth-of-field.md) 1.0 | [DoF sample](samples/depth-of-field.md) | [FidelityFX Depth of Field](https://gpuopen.com/fidelityfx-dof/) | Implements a high-quality DOF filter complete with bokeh. | +| [Lens](samples/lens.md) 1.0 | [Lens sample](samples/lens.md) | [FidelityFX Lens](https://gpuopen.com/fidelityfx-lens/) | Implements a library of optimized lens effects including chromatic aberration, film grain, and vignetting. | +| [Classifier (Shadows)](techniques/classifier.md) 1.1 [Denoiser (Shadows)](techniques/denoiser.md) 1.2 | [Hybrid Shadows sample](samples/hybrid-shadows.md) 1.1 | [FidelityFX Hybrid Shadows](https://gpuopen.com/fidelityfx-hybrid-shadows/) | An implementation of an example shadowing technique which shows you how you could combine rasterized shadow maps and hardware ray tracing to deliver high quality soft shadows at a reasonable performance cost. | +| [Classifier (Reflections)](techniques/classifier.md) 1.1 [Denoiser (Reflections)](techniques/denoiser.md) 1.2 | [Hybrid Reflections sample](samples/hybrid-reflections.md) 1.1 | [FidelityFX Hybrid Reflections](https://gpuopen.com/fidelityfx-hybrid-reflections/) | An implementation of an an example reflections technique which shows you how you could mix FidelityFX SSSR with ray traced reflections, delivering higher quality reflections than SSSR alone at reasonable performance cost. |

Further information

-- [What's new in FidelityFX SDK](/docs/whats-new/index.md) - - [FidelityFX SDK 1.0](/docs/whats-new/index.md) +- [What's new in FidelityFX SDK](whats-new/index.md) + - [FidelityFX SDK 1.0](whats-new/index.md) -- [Getting started](/docs/getting-started/index.md) - - [Overview](/docs/getting-started/index.md) - - [SDK structure](/docs/getting-started/sdk-structure.md) - - [Building the samples](/docs/getting-started/building-samples.md) - - [Running the samples](/docs/getting-started/running-samples.md) - - [Naming guidelines](/docs/getting-started/naming-guidelines.md) +- [Getting started](getting-started/index.md) + - [Overview](getting-started/index.md) + - [SDK structure](getting-started/sdk-structure.md) + - [Building the samples](getting-started/building-samples.md) + - [Running the samples](getting-started/running-samples.md) + - [Naming guidelines](getting-started/naming-guidelines.md) -- [Tools](/docs/tools/index.md) - - [Shader Precompiler](/docs/tools/ffx-sc.md) - - [FidelityFX SDK Media Delivery System](/docs/media-delivery.md) +- [Tools](tools/index.md) + - [Shader Precompiler](tools/ffx-sc.md) + - [FidelityFX SDK Media Delivery System](media-delivery.md)

Known issues

@@ -54,7 +59,7 @@ The FidelityFX SDK includes: AMD FidelityFX SDK is open source, and available under the MIT license. -For more information on the license terms please refer to [license](/docs/license.md). +For more information on the license terms please refer to [license](license.md).

Disclaimer

diff --git a/docs/samples/index.md b/docs/samples/index.md index 62c65953..1736ab3e 100644 --- a/docs/samples/index.md +++ b/docs/samples/index.md @@ -8,7 +8,7 @@ - [FidelityFX Parallel Sort 1.2](parallel-sort.md) - [FidelityFX Single Pass Downsampler 2.1](single-pass-downsampler.md) - [FidelityFX Stochastic Screen-Space Reflections 1.4](stochastic-screen-space-reflections.md) -- [FidelityFX Super Resolution 1.1 & 2.2](super-resolution.md) +- [FidelityFX Super Resolution 1.1, 2.2 & 3.0.3](super-resolution.md) - [FidelityFX Variable Shading 1.1](variable-shading.md) - [FidelityFX Blur 1.0](blur.md) - [FidelityFX Depth of Field 1.0](depth-of-field.md) diff --git a/docs/samples/super-resolution.md b/docs/samples/super-resolution.md index bd39bc77..bfe2b6d8 100644 --- a/docs/samples/super-resolution.md +++ b/docs/samples/super-resolution.md @@ -4,9 +4,9 @@ ![alt text](media/super-resolution/fsr-sample_resized.jpg "A screenshot of the FSR sample.") -This sample demonstrates the use of FidelityFX Super Resolution (FSR1) and FidelityFX Super Resolution 2 (FSR2) for upscaling. +This sample demonstrates the use of FidelityFX Super Resolution (FSR1), FidelityFX Super Resolution 2 (FSR2) and FidelityFX Super Resolution 3 (FSR3) for upscaling. -For details on the underlying algorithms you can refer to the per-technique documentation for [FSR1](../techniques/super-resolution-spatial.md) and [FSR2](../techniques/super-resolution-temporal.md). +For details on the underlying algorithms you can refer to the per-technique documentation for [FSR1](../techniques/super-resolution-spatial.md), [FSR2](../techniques/super-resolution-temporal.md) and [FSR3](../techniques/super-resolution-interpolation.md).

Requirements

@@ -36,6 +36,10 @@ The sample contains a [dedicated Render Module for FSR1](../../samples/fsr/fsr2r Similarly to FSR1, FSR2 also contains [its own Render Module that manages the context](../../samples/fsr/fsr2rendermodule.h). Additional resources are created interally for the Reactive Mask, Composition Mask. A separate resource at rendering resolution is also created for copying the color render target just before transparency is rendered, which is used for auto-generation of the Reactive mask. During the FSR2 compute dispatch, the input resource itself is used to store the upscaled result. +

Setting up FidelityFX Super Resolution 3

+ +FSR3 also contains [its own Render Module that manages the context](../../samples/fsr/fsr3rendermodule.h). In addition to FSR2, this sample replaces the swapchain with a proxy swapchain that handles pacing and presentation of both the interpolated and real frames. It also demonstrates the different ways of handling rendering of the user interface in conjunction with frame interpolation. +

Sample Controls and Configurations

For sample controls, configuration and Cauldron UI element details, please see [Running the samples](../getting-started/running-samples.md) @@ -44,4 +48,5 @@ For sample controls, configuration and Cauldron UI element details, please see [ - [FidelityFX Super Resolution 1](../techniques/super-resolution-spatial.md) - [FidelityFX Super Resolution 2](../techniques/super-resolution-temporal.md) +- [FidelityFX Super Resolution 3](../techniques/super-resolution-interpolation.md) - [FidelityFX Naming guidelines](../getting-started/naming-guidelines.md) \ No newline at end of file diff --git a/docs/techniques/blur.md b/docs/techniques/blur.md index 3451ea09..bed3c8e8 100644 --- a/docs/techniques/blur.md +++ b/docs/techniques/blur.md @@ -27,7 +27,7 @@ Example C++: ```cpp // Initialize the FFX backend and blur context (do this once) size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_BLUR_CONTEXT_COUNT); -void* scratchBuffer = malloc(scratchBufferSize); +void* scratchBuffer = calloc(scratchBufferSize, 1); FfxInterface backendInterface; ffxGetInterface(&backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_BLUR_CONTEXT_COUNT); diff --git a/docs/techniques/frame-interpolation-swap-chain.md b/docs/techniques/frame-interpolation-swap-chain.md new file mode 100644 index 00000000..490907bf --- /dev/null +++ b/docs/techniques/frame-interpolation-swap-chain.md @@ -0,0 +1,146 @@ + + +

FidelityFX Frame Interpolation Swapchain 1.0

+ +

Table of contents

+ +- [Introduction](#introduction) +- [Description](#description) +- [Integration](#integration) + - [Recording and dispatching the frame interpolation workload](#recording-and-dispatching-the-frame-interpolation-workload) + - [UI composition](#ui-composition) + - [Frame pacing and presentation](#frame-pacing-and-presentation) +- [Additional Information](#additional-information) + +

Introduction

+ +The `FrameInterpolationSwapChain` implements the `IDXGISwapChain4` interface to provide an easy way to handle dispatching the workloads required for frame interpolation and pacing presentation. + +Though this implementation may not work for all engines or applications, it was designed to provide an easy way to integrate FSR3 frame generation in a way that it is (almost) transparent to the underlying application. + +

Description

+ +`FrameInterpolationSwapChain` can be used as a replacement of the DXGI swapchain and from the application point of view behavior should be similar. + +When frame generation is disabled, the main difference will be that present is slightly more expensive (one extra surface copy) compared to using the DXGI swapchain directly. + +In this case, the frame interpolation swapchain still supports handling the UI composition, so applications don't have to handle their UI differently when disabling frame interpolation. + +Internally the `FrameInterpolationSwapChain` will create 2 additional CPU threads: + +- The first thread is used to not stall the application while waiting for interpolation to finish on the GPU. After that the thread will get the current CPU time and compute pacing information. +- The second thread dispatches the GPU workloads for UI composition (calling the callback function if needed) and pacing the non-interpolated frames' present. + +![alt text](media/frame-interpolation-swapchain/frame-interpolation-swap-chain.svg "A diagram showing the CPU workflow of the FrameInterpolationSwapChain.") + +

Integration

+ +`FrameInterpolationSwapChain` implements the `IDXGISwapChain4` interface, so once created it behaves just like a normal swapchain. + +Creation can be done by either calling `ffxReplaceSwapchainForFrameinterpolationDX12`, which will replace an existing swapchain, or by calling `ffxCreateFrameinterpolationSwapchainDX12` or `ffxCreateFrameinterpolationSwapchainForHwndDX12` similar to calling `CreateSwapChain` or `CreateSwapChainForHwnd`. + +

Recording and dispatching the frame interpolation workload

+ +The `FrameInterpolationSwapchain` has been designed to be independent of `FfxOpticalFlow` or `FfxFrameInterpolation` interfaces. To achieve this, it does not interact directly with those interfaces. The frame interpolation workload can be provided to the `FrameInterpolationSwapchain` in 2 ways: + +1. Provide a callback function (`frameGenerationCallback`) in the `FfxFrameGenerationConfig`. + This function will get called from the `FrameInterpolationSwapChain` during the call to `::Present` on the game thread, if frame interpolation is enabled to record the command list containing the frame interpolation workload. +2. Call `ffxGetFrameinterpolationCommandlistDX12(FfxSwapchain, FfxCommandList&)` to obtain a command list from the `FrameInterpolationSwapChain` and record the frame interpolation workload into it. + In this case the command list will be executed when present is called. + +The command list can either be executed on the same command queue present is being called on, or on an asynchronous compute queue: +- Synchronous execution is more resilient to issues if an application calls upscale but then decides not to call present on a frame. +- Asynchronous execution may result in higher performance depending on the hardware and what workloads are running alongside the frame interpolation workload. + +Either way, UI composition and present will be executed an a second graphics queue in order to not restrict UI composition to compute and allow the driver to schedule the present calls during preparation of the next frame. + +Note: to ensure presents can execute at the time intended by FSR3's frame pacing logic, avoid micro stuttering and assure good VRR response by the display, it is recommended to ensure the frame consists of multiple command lists. + +

UI Composition

+ +When using frame interpolation, it is highly advisable to treat the UI with special care, since distortion due to game motion vectors that would hardly be noticeable in 3D scenes will significantly impact readability of any UI text and result in very noticeable artifacts, especially on any straight, hard edges of the UI. + +To combat any artifacts and keep the UI nice and readable, FSR3 offers 3 ways to handle UI composition in the `FrameInterpolationSwapChain`: + +1. Register a call back function, which will render the UI on top of the back buffer. + This function will get called for every back buffer presented (interpolated and real) so it allows the application to render UI animations at display rate or apply effects like film grain differently for each frame sent to the monitor. + However this approach obviously has some impact on performance as the UI will have to be rendered twice, so care should be taken to only record small workloads in the UI callback. +2. Render the UI to a separate surface, so it can be alpha-blended to the final back buffer. + This way the UI can be applied to the interpolated and real back buffers without any distortion. +3. Provide a surface containing the HUD-less scene to the `FrameInterpolationSwapChain` in addition to the final back buffer. + In this case the frame interpolation shader will detect UI areas in the frame and suppress distortion in those areas. + + +

Frame pacing and presentation

+ +The `FrameInterpolationSwapchain` handles frame pacing automatically. Since Windows is not a real-time operating system and variable refresh rate displays are sensitive to timing imprecisions, FSR3 has been designed to use a busy wait loop in order to achieve the best possible timing behavior. + +With frame generation enabled, frames can take wildly different amounts of time to render. The workload for interpolated frames can be much smaller than for application rendered frames ("real" frames). It is therefore important to properly pace presentation of frames to ensure a smooth experience. The goal is to display each frame for an equal amount of time. + +Presentation and pacing are done using two additional CPU threads separate from the main render loop. A high-priority pacing thread keeps track of average frame time, including UI composition time, and calculates the target presentation time. It also waits for GPU work to finish to avoid long GPU-side waits after the CPU-side presentation call. + +To prevent any frame time spikes from impacting pacing too much, the moving average of several frames is used to estimate the frame time. + +A present thread dispatches frame composition work for the interpolated frame and first presents the interpolated frame. After this it will dispatch the frame composition work for the real frame, followed by a wait until the target presentation time and finally presents the real frame. + +The application should ensure that the rendered frame rate is slightly below half the desired output frame rate. When VSync is enabled, the render performance will be implicitly limited to half the monitors maximum refresh rate. + +It is recommended to use normal priority for any GPU queues created by the application to allow interpolation work to be scheduled with higher priority. In addition, developers should take care that command lists running concurrently with interpolation and composition are short (in terms of execution time) to allow presentation to be scheduled at a precise time. + +![](media/frame-pacing/pacing-overview.svg) + +

Expected behavior

+ +To further illustrate the pacing method and rationale behind it, the following sections will lay out expected behavior in different scenarios. We differentiate based on the post-interpolation frame rate as well as whether the display uses a fixed or variable refresh rate. + +
Fixed refresh rate
+ +
VSync enabled
+ +Here, tearing is disabled and every frame is displayed for at least one sync interval. Presentation is synchronized to the display's vertical blanking period ("vsync"). This may result in uneven display timings and may increase input latency (by up to one refresh period). + +![](media/frame-pacing/fixed-low.svg) + +In the diagram, the first real frame is presented slightly after the vertical blanking interval, leading to the prior interpolated frame being shown for two refresh intervals and increased latency compared to immediate display. + +
VSync disabled
+ +In this case, tearing is likely to occur. Presentation is not synchronized with the display. The benefit of this is reduced input latency compared to lower frame rates. + +![](media/frame-pacing/fixed-high.svg) + +
Variable refresh rate
+ +This section applies to display and GPU combinations with support for variable refresh rate (VRR) technologies, such as AMD FreeSync, NVIDIA G-SYNC® and VESA AdaptiveSync. + +The timing between display refreshes is dictated by the variable refresh rate window. The delta time between two refreshes can be any time inside the window. As an example, if the VRR window is 64-120Hz, then the delta time must be between 8.33 and 15.625 milliseconds. If the delta is outside this window, tearing will likely occur. + +If no new present happens inside the window, the prior frame is displayed again. + +
Interpolated frame rate inside VRR window
+ +The variable refresh window usually does not extend above the reported native refresh rate of the display, so tearing will be disabled in this case. + +![](media/frame-pacing/variable-inside.svg) + +
Interpolated frame rate outside VRR window
+ +If the frame rate is below the lower bound of the VRR window, the expected behavior is the same as if the frame rate is below the refresh rate of a fixed refresh rate display (see above). + +If the frame rate is above the upper bound of the VRR window, the expected behavior is the same as if the frame rate is above the refresh rate of a fixed refresh rate display (see above). + +

Additional Information

+ +List of resources created by the `FrameInterpolationSwapChain`: + +- Two CPU worker threads. One of those will be partially spinning between present of the interpolated frame and the real frame to precisely time the presents +- One asynchronous compute queue (only used `FFX_FSR3_ENABLE_ASYNC_WORKLOAD_SUPPORT` is set on FSR3 context creation and `allowAsyncWorkloads` is true in the `FfxFrameGenerationConfig`) +- One asynchronous present queue. This queue will be used to execute UI composition workloads and present +- A set of command lists, allocators and fences for the interpolation and UI composition workloads +- The GPU resources required to blit the back buffer to the swapchain and compose the UI (if no callback is used) +- The swapchain attached to the actual game window + +The `FrameInterpolationSwapchain` has been designed to minimize dynamic allocations during runtime: + +- System memory usage of the class is constant during the lifetime of the swapchain, no STL is being used +- DirectX resources are created on first use and kept alive for reuse diff --git a/docs/techniques/frame-interpolation.md b/docs/techniques/frame-interpolation.md new file mode 100644 index 00000000..87569b86 --- /dev/null +++ b/docs/techniques/frame-interpolation.md @@ -0,0 +1,204 @@ + + +

FidelityFX Frame Interpolation 1.0

+ +

Table of contents

+ +- [Introduction](#introduction) + - [Shading language requirements](#shading-language-requirements) +- [Integration](#integration) + - [Creation](#creation) + - [Dispatch](#dispatch) + - [Destruction](#destruction) +- [The technique](#the-technique) + - [Algorithm structure](#algorithm-structure) + - [Setup pass](#setup-pass) + - [Estimate interpolated frame depth](#estimate-interpolated-frame-depth) + - [Compute game motion vector field](#compute-game-motion-vector-field) + - [Compute game motion vector field inpainting pyramid](#compute-game-motion-vector-field-inpainting-pyramid) + - [Compute optical flow vector field](#compute-game-motion-vector-field) + - [Compute disocclusion mask](#compute-disocclusion-mask) + - [Compute interpolation](#compute-interpolation) + - [Compute inpainting pyramid](#compute-inpainting-pyramid) + - [Inpainting](#inpainting) +- [Debug output](#debug-output) + +

Introduction

+ +The FidelityFX Frame Interpolation technique takes 2 back buffers, and several resources shared with `FSR3Upscaler` and `FfxOpticalFlow` to compute an interpolated image between the 2 back buffers. + +This technique has been designed to work together with the `FfxOpticalFlow` (by taking textures generated by this technique) and `FfxFsr3Upscaler` (by using internal surfaces of that technique). Although `FfxFrameInterpolation` does not use the interface of those techniques directly, it will requires references to some surfaces on dispatch, so `FfxOpticalFlow` and `FfxFsr3Upscaler` must be used together with `FfxFrameInterpolation` to compute those surfaces. + +For ease of integration it is recommended to use the `FfxFsr3` interface. + +The `FfxFrameInterpolation` effect only computes the interpolated image. Once this is accomplished, the interpolated and real back buffers still need to be used, i.e. usually sent to the swapchain. On the topic of how to handle presentation and pacing of the back buffers, please refer to the [frame interpolation swapchain](frame-interpolation-swap-chain.md) documentaion. + +

Shading language requirements

+ +- `HLSL` + - `CS_6_2` + - `CS_6_6†` + +† `CS_6_6` is used on some hardware which supports 64-wide wavefronts. + +

Integration

+ +The FidelityFX Frame Interpolation technique is part of [FidelityFX Super Resolution 3](super-resolution-interpolation.md) and requires internal surfaces from the latest version of the [FidelityFX Temporal Upscaler](super-resolution-temporal.md) and is designed to work together with [FidelityFX Optical Flow](optical-flow.md). The FSR3 API has been designed to handle the interaction of the different effects, so it is recommended to refer to the [FSR3 documentation](super-resolution-interpolation.md) for integration guidelines. + +This section covers how to use the FidelityFX Frame Interpolation API directly and should help understand the inner workings of the `ffx_fsr3` component. + +

Creation

+ +The effect can be created by calling the `ffxFrameInterpolationContextCreate` function, with a pointer to a `FfxFrameInterpolationContext` container for the context, and a pointer to a `FfxFrameInterpolationContextDescription` structure which is filled with data relevant for the frame interpolation context. + +The `FfxFrameInterpolationContextDescription` structure contains configuration data: + * A FidelityFX backend interface to use + * A set of initialization flags + * The maximum resolution the rendering will be performed at + * The resolution of the resources that will get interpolated + * The format of the resources that will get interpolated + +The initialization flags are provided though the `FfxFrameInterpolationInitializationFlagBits` enumeration: + +| Flag | Note | +|-------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------| +| `FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED` | A bit indicating that the input depth buffer data provided is inverted [1..0].A bit indicating the depth buffer is inverted. | +| `FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INFINITE ` | A bit indicating that the input depth buffer data provided is using an infinite far plane. | +| `FFX_FRAMEINTERPOLATION_ENABLE_TEXTURE1D_USAGE` | A bit indicating that the backend should use 1D textures. | +| `FFX_FRAMEINTERPOLATION_ENABLE_HDR_COLOR_INPUT` | A bit indicating if the input color data provided is using a high-dynamic range. | + +

Dispatch

+ +To dispatch the effect and gain relevant results, call the `ffxFrameInterpolationContextDispatch` function with a `FfxFrameInterpolationDispatchDescription` structure filled as follows: + +| `FfxFrameInterpolationDispatchDescription` member | Note | +|---------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------| +| `flags` | A combination of `FfxFrameInterpolationDispatchFlags`. | +| `commandList` | The `FfxCommandList` to record frame interpolation commands into. | +| `displaySize` | The destination output dimensions. | +| `renderSize` | The dimensions used to render game content. `dilatedDepth` and `dilatedMotionVectors` are expected to be of this size. | +| `currentBackBuffer` | The current presentation color buffer. If `currentBackBuffer_HUDLess` is not used, this will be used as interpolation source data. | +| `currentBackBuffer_HUDLess` | The current presentation color buffer without HUD content. When use it will be used as interpolation source data. | +| `output` | The output resource to store the interpolated result. | +| `dilatedDepth` | The dilated depth buffer data. | +| `dilatedMotionVectors` | The dilated motion vector data. | +| `reconstructPrevNearDepth` | The estimated previous frame's depth buffer. | +| `interpolationRect` | The area of the backbuffer that should be used for interpolation in case only a part of the screen is used e.g. due to movie bars. | +| `opticalFlowVector` | The optical flow motion vectors. | +| `opticalFlowSceneChangeDetection` | The optical flow scene change detection data. | +| `opticalFlowBufferSize` | The optical flow motion vector resource dimensions. | +| `opticalFlowScale` | The optical flow motion vector scale factor, used to scale resoure values into [0.0,1.0] range. | +| `opticalFlowBlockSize` | The optical flow block dimension size. | +| `cameraNear` | The distance to the near plane of the camera. | +| `cameraFar` | The distance to the far plane of the camera. This is used only used in case of non infinite depth. | +| `cameraFovAngleVertical` | The camera angle field of view in the vertical direction (expressed in radians). | +| `viewSpaceToMetersFactor` | The unit to scale view space coordinates to meters. | +| `frameTimeDelta` | The time elapsed since the last frame (expressed in milliseconds). | +| `reset` | A boolean value which when set to true, indicates the camera has moved discontinuously. | +| `backBufferTransferFunction` | The transfer function use to convert interpolation source color data to linear RGB. | +| `minMaxLuminance[2]` | Min and max luminance values, used when converting HDR colors to linear RGB. | + +The `flags` attribute of `FfxFrameInterpolationDispatchDescription` can be a combination of the following: + +| `FfxFrameInterpolationDispatchFlags` | Note | +|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------| +| `FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_TEAR_LINES` | A flag indicating [Debug output](#debug-output) visualization of tear lines should be enabled. | +| `FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_VIEW` | A flag indicating [Debug output](#debug-output) visualization of internal surfaces should be enabled. | + +

Destruction

+ +A context can be destroyed using the `ffxFrameInterpolationContextDestroy` function, passing in the pointer to the relevant context container. + +

The technique

+ +

Algorithm structure

+ +The `FfxFrameInterpolation` algorithm is implemented in a series of stages, which are as follows: + +1. [Setup pass](#setup-pass) +2. [Estimate interpolated frame depth](#estimate-interpolated-frame-depth) +3. [Compute game motion vector field](#compute-game-motion-vector-field) +4. [Compute game motion vector field inpainting pyramid](#compute-game-motion-vector-field-inpainting-pyramid) +5. [Compute optical flow vector field](#compute-optical-flow-vector-field) +6. [Compute disocclusion mask](#compute-disocclusion-mask) +7. [Compute interpolation](#compute-interpolation) +8. [Compute inpainting pyramid](#compute-inpainting-pyramid) +9. [Inpainting](#inpainting) + +![Frame interpolation flowchart](media/frame-interpolation/algorithm-structure.svg "A diagram showing all passes in the FfxFrameInterpolation algorithm.") + +

Setup pass

+ +The setup pass clears the internal `Counter`, `GameMotionVectorFieldXY`, `OpticalFlowVectorFieldXY` and `DisocclusionMask` surfaces, as those will be used through atomic operations. + +

Estimate interpolated frame depth

+ +This pass (using the `ReconstructPreviousDepthPass` pipeline) computes the estimated dilated depth buffer of the interpolated frame. It is based on the logic of the reconstruct depth reconstruction of the [`ReconstructAndDilate` pass](super-resolution-temporal.md##reconstruct-and-dilate) used in the temporal upscaler. + +To compute the depth buffer of the interpolated frame, this pass consumes the dilated depth and motion vectors surfaces from the `Fsr3Upscaler` and reprojects and dilates them by half the motion vector length. + +

Compute game motion vector field

+ +The `GameMotionVectorField` pass constructs the frame of reference of the interpolated frame location. This means, when sampling previous and current frame data using the game motion vectors, an interpolated frame is generated. + +To do this, the pass packs the `DilatedMotionVectors` into the low 16 bits of a pair of 32-bit UINT values. The high 16 bits contain a priority, consisting of the highest 1-bit to indicate if the vector is primary or secondary, 10-bits to indicate high priority based on the distance from the camera, and the low 5 bits of priority are based on color similarity of the previous and current back buffers. + +The values get written using atomic operations and it is not guaranteed that all locations get written in this pass, so there may be some holes in the field. + +

Compute game motion vector field inpainting pyramid

+ +Locations not written by the previous pass will get filled in by adjacent vector information. To accomplish this, this pass generates a full mip chain of the game motion vector field using [SPD](single-pass-downsampler.md). + +In this mip chain the game motion vectors will be stored in `.xy` channels, the high, depth-based, priority factor will be stored in the `.z` channel and low, color similarity-based, priority factor will be stored in the `.w` channel. + +For computing the mip-chain the closest vector in 2D and the farthest in depth will be selected. + +

Compute optical flow vector field

+ +This pass is similar to the [`GameMotionVectorField` pass](#compute-game-motion-vector-field) but uses the motion vectors generated by [`FfxOpticalFlow`](optical-flow.md) vectors as input. + +The high priority value is computed based on vector magnitude and the low priority value is based on color similarity of reprojected colors using the optical flow motion vectors. + +

Compute disocclusion mask

+ +This pass is based on the [temporal upscaler disocclusion logic](super-resolution-temporal.md#depth-clip) but will produce two disocclusion masks: + +- One mask represents the disocclusion area between the interpolated frame and the previous frame +- One mask represents the disocclusion area between the interpolated frame and the current frame + +Using this mask the [compute interpolation pass](#compute-interpolation) will determine if any reprojection direction is to be discarded. + +

Compute interpolation

+ +This pass computes the interpolated image using the disocclusion mask and the motion vector fields. + +To do so, it first reads the counters and checks if this is the first image after a reset, in which case it will simply copy the latest back buffer. + +After this the algorithm operates in 2 stages: + + - First, it computes an interpolated color for each pixel by blending the two color values based on the disocclusion mask value + - Next, it computes an interpolated color based on the optical flow motion vectors and blends it with the game motion vector based result + - The blend factor for this operation is based on the color similarity between previous and current color for each case, so in a nutshell, if optical flow motion vectors result in a better match the algorithm prefers them to the game motion vectors. + +The resulting image may contain some holes, which will get filled by [inpainting pass](#inpainting) in the final step of the algorithm. + +

Compute inpainting pyramid

+ +This pass uses [SPD](single-pass-downsampler.md) to generate a full mip chain of the interpolated color. Holes in the interpolated color will be ignored, so sampling from the mip chain will result in a color averaged from the closest color values in 2D space. + +

Inpainting

+ +This pass fills in any holes left in [compute interpolation pass](#compute-interpolation) by using the inpainting pyramid to find the closest available color. + +After this, the pass cleans up the UI in case the HUD-less UI mode is being used, and then optionally adds debug information to the interpolated image. + +

Debug output

+ +The frame interpolation API supports 2 types of debug view: + +When `FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_TEAR_LINES` is set in the flags attribute of `FfxFrameGenerationConfig`, the inpainting pass will add bars of changing color on the left and right border of the interpolated image. This will assist visualizing if interpolated frames are getting presented and if the frames are presented with tearing enabled. + +When `FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_VIEW` is set in the flags attribute of `FfxFrameGenerationConfig`, the [FrameInterpolationSwapChain](frame-interpolation-swap-chain.md) will only present interpolated frames and execute an additional pass to render debug data from internal surfaces onto the interpolated frame, to allow you to debug. + +![Frame interpolation debug overlay](media/frame-interpolation/frame-interpolation-debug-overlay.svg "A diagram showing the debug overlay") + diff --git a/docs/techniques/frame-pacing.md b/docs/techniques/frame-pacing.md new file mode 100644 index 00000000..5b823ea0 --- /dev/null +++ b/docs/techniques/frame-pacing.md @@ -0,0 +1,87 @@ +# Frame Pacing in FSR3 + +With frame generation enabled, frames can take wildly different amounts of time to render. +The workload for interpolated frames can be much smaller than for application rendered frames ("real" frames). +It is therefore important to properly pace presentation of frames to ensure a smooth experience. +The goal here is to display each frame for an equal amount of time. + +Presentation and pacing are done on two new threads separate from the main render loop. + +A high-priority pacing thread keeps track of average frame time and calculates the target presentation time. +It also waits for gpu work to finish to avoid long GPU-side waits after the CPU-side presentation call. + +To prevent frame time spikes from impacting pacing too much, the moving average of the past seven frames is used +to calculate a stable frame time. + +A present thread dispatches frame composition work and first presents the interpolated frame, then waits +until the target presentation time and presents the real frame. + +The present interval is always set to 0 (queueing disabled) to avoid waits in the presentation backend. +If supported, the allow-tearing-flag is set if and only if the interpolated frame rate exceeds the monitor's +refresh rate. + +If the application presents to the proxy swapchain using a non-zero present interval, tearing is always disabled. +In these cases, the call to the presentation backend may block on some drivers, which prevents the frame rate from +exceeding the monitor's refresh rate. On AMD Radeon graphics cards, users should enable Enhanced Sync in AMD Software +to avoid this behavior. + +The application should ensure that the rendered frame rate is as close as possible to, but ideally slightly below +half the desired output frame rate. + + +It is recommended to use normal priority for any GPU queues created by the application to allow interpolation +work to be scheduled with higher priority. In addition, developers should take care that command lists running +concurrently with interpolation and composition are short (in terms of execution time) to allow presentation +to be scheduled at a precise time. + +![](media/frame-pacing/pacing-overview.svg) + +## Expected behavior + +To further illustrate the pacing method and rationale behind it, the following sections will lay out expected +behavior in different scenarios. We differentiate based on the post-interpolation frame rate as well as whether +the display uses a fixed or variable refresh rate. + +### Fixed refresh rate + +#### Interpolated frame rate below display refresh rate + +Here, tearing is disabled. Presentation is synchronized to the monitor's vertical blanking period ("VSync"). +This may result in uneven display timings and may increase input latency (by up to one refresh period). + +![](media/frame-pacing/fixed-low.svg) + +In the diagram, the first real frame is presented slighly after the vertical blanking interval, +leading to the prior interpolated frame being shown for two refresh intervals and increased latency compared to immediate display. + +#### Interpolated frame rate above display refresh rate + +In this case, tearing is enabled and likely to occur. Presentation is not synchronized with the monitor. +The benefit of this is reduced input latency compared to lower frame rates. + +![](media/frame-pacing/fixed-high.svg) + +### Variable refresh rate + +This section applies to displays with support for variable refresh rate (VRR) technology, such as AMD FreeSync. + +The timing between display refreshes is dictated by the variable refresh rate window. The delta time between two +refreshes can be any time inside the window. As an example, if the VRR window is 64-120Hz, then the delta time +must be between 8.33 and 15.625 milliseconds. If the delta is outside this window, tearing will likely occur. + +If no present happens inside the window, the previous frame is scanned out again. + +#### Interpolated frame rate inside VRR window + +The variable refresh window usually does not extend above the reported native refresh rate, +so tearing will be disabled in this case. + +![](media/frame-pacing/variable-inside.svg) + +#### Interpolated frame rate outside VRR window + +If the frame rate is below the lower bound of the VRR window, the expected behavior is the same as if +the frame rate is below the refresh rate of a fixed refresh rate display (see above). + +If the frame rate is above the upper bound of the VRR window, the expected behavior is the same as +if the frame rate is above the refresh rate of a fixed refresh rate display (see above). diff --git a/docs/techniques/index.md b/docs/techniques/index.md index 6d2c8137..b6397c05 100644 --- a/docs/techniques/index.md +++ b/docs/techniques/index.md @@ -12,12 +12,17 @@ - [FidelityFX Stochastic Screen-Space Reflections 1.4](stochastic-screen-space-reflections.md) - [FidelityFX Super Resolution 1.1](super-resolution-spatial.md) - [FidelityFX Super Resolution 2.2](super-resolution-temporal.md) +- [FidelityFX Super Resolution 3.0 - Interpolation](super-resolution-interpolation.md) +- [FidelityFX Super Resolution 3.0 - Upscaler](super-resolution-upscaler.md) +- [FidelityFX Frame Interpolation 1.0](frame-interpolation.md) +- [FidelityFX Frame Interpolation Swapchain 1.0](frame-interpolation-swap-chain.md) +- [FidelityFX Optical Flow 1.0](optical-flow.md) - [FidelityFX Variable Shading 1.1](variable-shading.md) - [FidelityFX Blur 1.0](blur.md) - [FidelityFX Depth of Field 1.0](depth-of-field.md) - [FidelityFX Lens 1.0](lens.md) - + @@ -27,6 +32,11 @@ + + + + + diff --git a/docs/techniques/media/frame-interpolation-swapchain/frame-interpolation-swap-chain.svg b/docs/techniques/media/frame-interpolation-swapchain/frame-interpolation-swap-chain.svg new file mode 100644 index 00000000..8c6829fe --- /dev/null +++ b/docs/techniques/media/frame-interpolation-swapchain/frame-interpolation-swap-chain.svg @@ -0,0 +1,1137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Present Thread + + + + + + + Present Interpolated + + + + Present Rendered + + + + Busy Wait to Pace Present + + + + Compose UI onto Interpolated + + + + Compose UI onto Rendered + + + + Wait for Signal + + + + + + + + + + + Interpolation Thread + + + + Signal Pacing Thread + + + + Collect CPUtiming dataUpdate Pacing + + + + Wait for Interpolation + + + + Wait for Signal + + + + + + + + + + + + + No + Yes + Yes + + + + + No + + + + Copy backbuffer andpresent to swapchain + + + + UI callback orUITexture set? + + + + Runinterpolation? + + + + Dispatch Interpolationand Signal Interpolation Thread + + + + Blit backbuffer withUI copmposition andpresent to swapchain + + + + Call to ::present + + Main Thread + + + + + + + diff --git a/docs/techniques/media/frame-interpolation/algorithm-structure.svg b/docs/techniques/media/frame-interpolation/algorithm-structure.svg new file mode 100644 index 00000000..b0067855 --- /dev/null +++ b/docs/techniques/media/frame-interpolation/algorithm-structure.svg @@ -0,0 +1,1899 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Optical FlowVector Field + + + + + Game MotionVector Field + + + + Disocclusion Mask + + + + Interpolated Frame + + + + Inpainting Pyramid(aliased use for MV and color) + + + + Motion Vector Inpainting Pyramid + + + + + Interpolated ColorInpainting Pyramid + + + + + Compute Game Motion Vector Field + + + + Compute GMV Field Inpainting Pyramid(SPD) + + + + Compute Optical Flow Vector Field + + + + Compute Disocclusion Mask + + + + Compute Interpolated Frame + + + + Compute Inpainting Pyramid(SPD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FfxOpticalFlow + + + Optical FlowMotion Vectors + Scene Change Detection + + + + FfxFrameInterpolation + + Previous Interpolation Source + + + + Inpainting + + + + Reconstructed DepthInterpolated Frame + + + + Estimate Interpolated Frame Depth + + + + Application + + Interpolation Source(HUD less if that codepath is used,Present Source otherwise) + + Present Source(identical to Interpolation Source ifHUD less codepath is NOT used) + + + + FfxUpscaler + + + + Dilated Velocity + Dilated Depth + Reconstructed DepthPrevious Frame + + + + + + + + + + + + + + + + + + + + diff --git a/docs/techniques/media/frame-interpolation/frame-interpolation-debug-overlay.svg b/docs/techniques/media/frame-interpolation/frame-interpolation-debug-overlay.svg new file mode 100644 index 00000000..a15896fd --- /dev/null +++ b/docs/techniques/media/frame-interpolation/frame-interpolation-debug-overlay.svg @@ -0,0 +1,873 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GameMotionVectorFieldVectors + GameMotionVectorFieldDepthPriority + OpticalFlowMotionVectorField + Interpolated + frame only + Disocclusion mask + Interpolation + source (without UI) + + Latest real backbuffer + ( + HUDless + mode only) + + + + + + + + + + diff --git a/docs/techniques/media/frame-pacing/fixed-high.svg b/docs/techniques/media/frame-pacing/fixed-high.svg new file mode 100644 index 00000000..5e6be162 --- /dev/null +++ b/docs/techniques/media/frame-pacing/fixed-high.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + Game + FSR3 (simplified) + GPU + + + + + Present() + + Present int. + Present real + + + + + Display + + Display + + + + + VSync + + + + + + + + + + \ No newline at end of file diff --git a/docs/techniques/media/frame-pacing/fixed-low.svg b/docs/techniques/media/frame-pacing/fixed-low.svg new file mode 100644 index 00000000..6186c737 --- /dev/null +++ b/docs/techniques/media/frame-pacing/fixed-low.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + Game + FSR3 (simplified) + GPU + + + + + Present() + + Present int. + Present real + + + + + + + + + VSync + Display + + + + + + + + + + \ No newline at end of file diff --git a/docs/techniques/media/frame-pacing/pacing-overview.svg b/docs/techniques/media/frame-pacing/pacing-overview.svg new file mode 100644 index 00000000..5a57850f --- /dev/null +++ b/docs/techniques/media/frame-pacing/pacing-overview.svg @@ -0,0 +1,42 @@ + + + + + + + + Game + FSR3 + Pacing thread + Present thread + GPU + + + + + + Present() + + + + PresentEvent + + Wait for GPU + + PacerEvent + + UI comp + + + Present int. + Pacing wait + + UI comp. + + + Present real + + + + \ No newline at end of file diff --git a/docs/techniques/media/frame-pacing/variable-inside.svg b/docs/techniques/media/frame-pacing/variable-inside.svg new file mode 100644 index 00000000..4467a3cd --- /dev/null +++ b/docs/techniques/media/frame-pacing/variable-inside.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + Game + FSR3 (simplified) + GPU + + + + + Present() + + Present int. + Present real + + + + + + + + + Scan out + Display + + Present real + + + + + + + + \ No newline at end of file diff --git a/docs/techniques/media/optical-flow/optical_flow_block.svg b/docs/techniques/media/optical-flow/optical_flow_block.svg new file mode 100644 index 00000000..3086350c --- /dev/null +++ b/docs/techniques/media/optical-flow/optical_flow_block.svg @@ -0,0 +1,130 @@ + + + + + + + + + + Optical Flow + + Color + + Motion Vector + Estimate + + Scene Change + Detection + + + + + + diff --git a/docs/techniques/media/optical-flow/optical_flow_main_iteration.svg b/docs/techniques/media/optical-flow/optical_flow_main_iteration.svg new file mode 100644 index 00000000..6cacd5ca --- /dev/null +++ b/docs/techniques/media/optical-flow/optical_flow_main_iteration.svg @@ -0,0 +1,279 @@ + + + + + + + + + + Searching + + Current Frame + Luminance + + Upscaled Motion + Vector Estimate + + Raw Motion Vector + Estimate + + + + + Filtering + + Filtered Motion + Vector Estimate + + Upscaling + + + + + Scene Change + Detection Result + + Previous Frame + Luminance + + Upscaled Motion + Vector Estimate + + + + + + + + diff --git a/docs/techniques/media/optical-flow/optical_flow_main_searching.svg b/docs/techniques/media/optical-flow/optical_flow_main_searching.svg new file mode 100644 index 00000000..c9e45cff --- /dev/null +++ b/docs/techniques/media/optical-flow/optical_flow_main_searching.svg @@ -0,0 +1,32087 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + previous frame + + current frame + motion vector input estimate (7, 5) + + + + + diff --git a/docs/techniques/media/optical-flow/optical_flow_main_upscale_area.svg b/docs/techniques/media/optical-flow/optical_flow_main_upscale_area.svg new file mode 100644 index 00000000..35064862 --- /dev/null +++ b/docs/techniques/media/optical-flow/optical_flow_main_upscale_area.svg @@ -0,0 +1,13501 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + upscale + + + diff --git a/docs/techniques/media/optical-flow/optical_flow_preparation_luma.svg b/docs/techniques/media/optical-flow/optical_flow_preparation_luma.svg new file mode 100644 index 00000000..c236b32e --- /dev/null +++ b/docs/techniques/media/optical-flow/optical_flow_preparation_luma.svg @@ -0,0 +1,229 @@ + + + + + + + + + + Luminance + Computing + + Luminance Level0 + + + + Single Pass + Downsampler + + Color + + + + + + + Luminance + Level1 + + Luminance + Level2 + + Level3 + + 6 + + + + diff --git a/docs/techniques/media/optical-flow/optical_flow_preparation_scenechange.svg b/docs/techniques/media/optical-flow/optical_flow_preparation_scenechange.svg new file mode 100644 index 00000000..78f68afe --- /dev/null +++ b/docs/techniques/media/optical-flow/optical_flow_preparation_scenechange.svg @@ -0,0 +1,805 @@ + + + + diff --git a/docs/techniques/media/super-resolution-interpolation/01_FSR3_DataFlow.svg b/docs/techniques/media/super-resolution-interpolation/01_FSR3_DataFlow.svg new file mode 100644 index 00000000..1928bfcc --- /dev/null +++ b/docs/techniques/media/super-resolution-interpolation/01_FSR3_DataFlow.svg @@ -0,0 +1,507 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FSR3 + Optical Flow + + FSR3 + Frame + Generation + + FSR3 + Upscale + + Game Engine Render + + Upscaling + + Scene + + Post Process + + User Interface + + Presentation + + FSR3 + Swapchain & + Frame + Pacing + + + + + + + UI Composition + + Present + Generated Frame + + Present + Real Frame + + + + FSR 3 Interfaces with Upscaling, User Interface + and Presentation systems of a game engine. + + + FSR3 Internal Resource Sharing Path + + + diff --git a/docs/techniques/media/super-resolution-interpolation/02_FSR3_Flow.svg b/docs/techniques/media/super-resolution-interpolation/02_FSR3_Flow.svg new file mode 100644 index 00000000..84be24c4 --- /dev/null +++ b/docs/techniques/media/super-resolution-interpolation/02_FSR3_Flow.svg @@ -0,0 +1,932 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Game Render Loop + + + Main Render Workload + + UI + + Main Render Workload + + + PostFx + + + Main Render Workload + + UI + + + PostFx + + + UI + + PostFx + + + + Optical + Flow + + Frame + Generation + + Pacing Waits + + Pacing Waits + + Present + Generated + + Present + Generated + + + + Present + Real + + FSR3 Async + + Present + Real + + Present + Real + + Present + Generated + + + + + + + Generated Frame Datapath/Presents + Real Frame Datapath/Presents + + Upscale + + Optical + Flow + + Frame + Generation + + + + + + + Optical + Flow + + Optical + Flow + + Frame + Generation + + Pacing Waits + Pacing Waits + Pacing Waits + + + diff --git a/docs/techniques/media/super-resolution-interpolation/03_FSR3_FlowAsyncQueue.svg b/docs/techniques/media/super-resolution-interpolation/03_FSR3_FlowAsyncQueue.svg new file mode 100644 index 00000000..3d952448 --- /dev/null +++ b/docs/techniques/media/super-resolution-interpolation/03_FSR3_FlowAsyncQueue.svg @@ -0,0 +1,1093 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Game Render Queue + + + Main Render Workload + + UI + + Main Render Workload + + + PostFx + + + Main Render Workload + + UI + + + PostFx + + + + + UI + + PostFx + + + + Main Render + Workload + + + Optical + Flow + + Frame + Generation + + Pacing Waits + + Pacing Waits + + Present + Generated + + + Frame + Generation + + Present + Generated + + + + + + Present + Real + + FSR3 Async + + Present + Real + + Present + Real + + Present + Generated + + Optical + Flow + + Frame + Generation + + Optical + Flow + + + + + + + + + + + Generated Frame Datapath/Presents + Real Frame Datapath/Presents + + Upscale + + + + diff --git a/docs/techniques/media/super-resolution-interpolation/04_FSR3_UiCallback.svg b/docs/techniques/media/super-resolution-interpolation/04_FSR3_UiCallback.svg new file mode 100644 index 00000000..8c81ff7b --- /dev/null +++ b/docs/techniques/media/super-resolution-interpolation/04_FSR3_UiCallback.svg @@ -0,0 +1,889 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pre + - + upscale + post + - + processing + + + + + + + + + Upscale + + + UI + Composition + Callback + + Real + Present + + Post + - + upscale + post + - + processing + + + + Render + + + + + UI + Composition + Callback + + Interpolated + Present + + + + + + + + Frame generation + & Composition pass + + FSR 3 Async frame pacing thread + + + + + + + + Interpolation + Swapchain + + New UI render is deferred to + FSR 3 Composition Callback. + UI can run at full display FPS. + + + + + + + Composition pass + Application thread calling swap chain present() + + + + diff --git a/docs/techniques/media/super-resolution-interpolation/05_FSR3_NoFG_UiCallback.svg b/docs/techniques/media/super-resolution-interpolation/05_FSR3_NoFG_UiCallback.svg new file mode 100644 index 00000000..34751c1f --- /dev/null +++ b/docs/techniques/media/super-resolution-interpolation/05_FSR3_NoFG_UiCallback.svg @@ -0,0 +1,798 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pre + - + upscale + post + - + processing + + + + + + + + + Upscale + + + UI + Composition + Callback + + Real + Present + + Post + - + upscale + post + - + processing + + + + Render + + + + + + + + + Interpolation + Swapchain + + New UI render is deferred to + FSR 3 Composition Callback. + + + + + + + Composition pass + Application thread calling swap chain present() + + + diff --git a/docs/techniques/media/super-resolution-interpolation/06_FSR3_UiTex.svg b/docs/techniques/media/super-resolution-interpolation/06_FSR3_UiTex.svg new file mode 100644 index 00000000..06a49e22 --- /dev/null +++ b/docs/techniques/media/super-resolution-interpolation/06_FSR3_UiTex.svg @@ -0,0 +1,1014 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pre + - + upscale + post + - + processing + + + + + + + + + Upscale + + UI in + separate + resource + + Post + - + upscale + post + - + processing + + + Render + + + Real + Present + + + Interpolated + Present + + + + + + + + Frame generation + FSR 3 Async frame pacing thread + + + + + + + Composition pass + + + + + + + Composition pass + + + + + + + + + Interpolation + Swapchain + + Same UI is composited onto + real and generated frames. + UI runs at render rate. + + + Application thread calling swap chain present() + + + diff --git a/docs/techniques/media/super-resolution-interpolation/07_FSR3_NoFG_UiTex.svg b/docs/techniques/media/super-resolution-interpolation/07_FSR3_NoFG_UiTex.svg new file mode 100644 index 00000000..16ec8b18 --- /dev/null +++ b/docs/techniques/media/super-resolution-interpolation/07_FSR3_NoFG_UiTex.svg @@ -0,0 +1,938 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pre + - + upscale + post + - + processing + + + + + + + + + Upscale + + UI in + separate + resource + + Post + - + upscale + post + - + processing + + + Render + + Real + Present + + + + + + + + Composition pass + + + + + + + + Interpolation + Swapchain + UI is composited onto real frames. + + Application thread calling swap chain present() + + + diff --git a/docs/techniques/media/super-resolution-interpolation/08_FSR3_HUDLess.svg b/docs/techniques/media/super-resolution-interpolation/08_FSR3_HUDLess.svg new file mode 100644 index 00000000..a83f246c --- /dev/null +++ b/docs/techniques/media/super-resolution-interpolation/08_FSR3_HUDLess.svg @@ -0,0 +1,1079 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + Pre + - + upscale + post + - + processing + + + + + + + + + Upscale + + Scene + without + UI/HUD + + Post + - + upscale + post + - + processing + + Render + + + Real + Present + + Interpolated + Present + + + + + + + Frame generation + FSR 3 Asyncframe pacing thread + + + + + + + + + Interpolation + Swapchain + + + + UI + + + + Application thread calling swap chain present() + + + diff --git a/docs/techniques/media/super-resolution-temporal/fsr3-sample.jpg b/docs/techniques/media/super-resolution-temporal/fsr3-sample.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6f9737238f06a57d766e1d3da0e228ae6b2cac33 GIT binary patch literal 630054 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 NI{@V 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[yyRvBdlU0@V>>dO4dQxLumJC#eN1y7~ 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 z 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

jCKV3)@*V+ufNps!*hp)E^iX-m3 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

$uK&fEcf>r1SBwqvRE0a$b!Mh>3-OyY~%NN^8 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ⅇ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

^$Kr~zGl~SB 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

P!^8E)GyCY-))LP$@A~FIisdGi-T|#C=1p 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

Tw+Y8p^~JG z{pDFK258OPU{9sHyOgZkEnIOvT~=(2?lC8U{4v*VtB5E~d;M!wI2*$Z7Qh7@rD3|L zS^k!udHBjK6#wItWI-Bgr~oWv_(m)!l19iJsmaX$MA86Vht7=vEe+)A40)(SKT(mw zWMx4)f2ra76P(Q(BJhNC{4gTJ+b5wf4#wTcSN8;h#V4%)05W9QyXV6XfxQ&d8B0&c z^;06KLCGAm_-mUR6yzp)qEm=>tLA<#^%mOF+dXy1jG}68ipBw>fn8ogRbRa=t1}jB+hkqB;QZa0sqef% zd3`Q70F$PMoE=M#zBGA^zV0!O?T?8v2lC#VH@L4xr7T!O8p6b%k5GU`X)f>WrcH8^ z>9(pnO3hIw0W7v_VS|y=)f|c6fRNY2W-KT*f65douPeUZ!@Ut3Uj-#0tfIc+cO~t~ z@|VAxz2BvM*Fcm&7mKMQhc!t>!%Q`ym`3Vo=dnOe3d@xfUb^fB(zF z#K{Z;nB45={B#Hm;%*@3~PHkUU%?BimW2}={ z-yl%lY425JFCz~9bYoZNce&ucl!G|qWBNOlW+89bz_ za34PuikC&>gcYSr-)U`BGtgw@C4ES}Kv&EYBm&`w*sN3w_sVdhe@( zUTEJHFt#^zCwjFr9Cu<&eey+>n{8~veCW-d7*&;XGkqF6Y?U8(H@b|>gd{f=Yw@zk z_=r0nGWMnC;3AL9DD2$g)w`X6&=wZ~i&g9r)5^~O#n)Q~wb`~&yTKibTaXgmin~*s z;tr*_dvGXj4GzWKo#Jk#KyY`5AVrH?X}j~h-#7c;-hYyrWRkfjlbQQE&$ZUE>d{L_ zvJBrk=4|9WX�MQs4IzFY3*{ucH+s--6bO(`hPE7Ur2ARKz>IlB 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°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

  • lQN+8%DM@y>8?dsMxdokrAKN6}t8 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

    rL59sjqF}u%(6b>UCR^BM+5Y#S67oQyhC@l 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 SFdPz8WD1124URdfDF4~HIoquO literal 0 HcmV?d00001 diff --git a/docs/techniques/media/super-resolution-temporal/overview.svg b/docs/techniques/media/super-resolution-temporal/overview.svg index bfbe39ca..300eddc6 100644 --- a/docs/techniques/media/super-resolution-temporal/overview.svg +++ b/docs/techniques/media/super-resolution-temporal/overview.svg @@ -109,7 +109,7 @@ font-weight="400" font-size="16px" transform="translate(701.797,243)" - id="text959">2 + id="text959">3 + +

    FidelityFX Optical Flow 1.0

    + +

    Introduction

    + +The FidelityFX Optical Flow technique estimates the motion between the current and the previous scene inputs. + +Based on AMD Fluid Motion Frames technology, and highly optimized for game inputs, the algorithm works on 8x8 blocks and calculates motion for each of these blocks. It is used in FSR3 and combined with upscaled game motion vectors. + +There is a single scene input and two outputs that correspond to the estimated motion vectors at block granularity, and a scene change detection flag. The scene change detection result is also required internally by the Optical Flow algorithm. + +The algorithm consists of two phases: preparation, and main. The preparation phase builds a luminance pyramid and detects any significant scene change. The main phase iterates through the luminance pyramid trying to detect estimated motion. At each iteration step, except iteration 0, refinements are made to previous estimate data. + +The final iteration result is what is output to the consumer of the technique. + +![alt text](media/optical-flow/optical_flow_block.svg "High level block diagram of Optical Flow component inputs and outputs") + +

    Integration

    + +

    Technical Requirements

    + +SM 6.2 is required. The effect uses wave operations, and also uses the [HLSL `msad4`](https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-msad4) intrinsic extensively. In architectures where `msad4` is not natively executed by the GPU, this may result in reduced performance. + +

    Create the effect

    + +The effect can be created by calling the `ffxOpticalflowContextCreate` function, with a pointer to an `FfxOpticalflowContext` container for the context, and a pointer to a `FfxOpticalflowContextDescription` structure which is filled with data relevant for the optical flow context. + +The `FfxOpticalflowContextDescription` structure contains configuration data: + + * A FidelityFX backend interface to use + * A set of initialization flags + * The resolution that optical flow is to run at + +The initialization flags are provided though the `FfxOpticalflowInitializationFlagBits` enumeration: + +| flag | Note | +|------------------------------------------|------------------------------------------------------------| +| `FFX_OPTICALFLOW_ENABLE_TEXTURE1D_USAGE` | A bit indicating that the TEXTURE1D resources can be used. | + +The optical flow effect can register shared resources via the `ffxOpticalflowGetSharedResourceDescriptions` function. + +Resource handles should be provided through this function using the members of `FfxOpticalflowSharedResourceDescriptions` as such: + +| Shared Resource name | Note | +|----------------------------------|--------------------------------------------------------------------------------------------| +| `opticalFlowVector` | A resource of `R16G16_SINT` format containing the block-based motion estimation output from Optical Flow. It's size is dictated by the `GetOpticalFlowTextureSize` function, which is `(displaySize.W/H + opticalFlowBlockSize - 1) / opticalFlowBlockSize`. `opticalFlowBlockSize` is always 8 in this release. | +| `opticalFlowSCD` | A 3x1 resource of `R32_UINT` indicating scene shading change output | + + +

    Dispatch the effect

    + +To dispatch the effect and gain relevant results, call the `ffxOpticalflowContextDispatch` function with a `FfxOpticalflowDispatchDescription` structure filled as follows. + + +| `FfxOpticalflowDispatchDescription` member | Note | +|----------------------------------|--------------------------------------------------------------------------------------------| +| `commandList` | The command list to use for dispatch of the workload. | +| `color`| The input color buffer to operate on. | +| `opticalFlowVector`| The output optical flow vector resource. | +| `opticalFlowSCD` | The output scene change detection resource. | +| `reset` | A boolean value which when set to true, indicates the camera has moved discontinuously. | +| `backbufferTransferFunction` | A value indicating the color space transforms required. | +| `minMaxLuminance` | Luminance values for the current HDR pipeline. | + + +

    Destroy the effect

    + +A context can be destroyed using the `ffxOpticalflowContextDestroy` function, passing in the pointer to the relevant context container. + +

    Stage Description

    + +

    Preparation

    + +To build the luma pyramid, first a luminance resource is prepared and then a pyramid of 6 additional downscaled resources is prepared. There are two pyramids of those 7 resources, which are ping-ponged so there is always a history pyramid available except for the first frame after any reset event. + +The conversion from the input color resource to the luminance is separated from computing the rest of the pyramid with the lower resolution luminance resources. Single Pass Downsampler (SPD) is used for downsampling. + +![alt text](media/optical-flow/optical_flow_preparation_luma.svg "Block diagram of luma preparation process") + +To detect a significant change in the sequence of input images, first a histogram is computed for 9 sections of full resolution luminance input. There are 2 histogram resources that ping-pong to provide history. The histograms of each section are compared between the current frame and the previous frame. If the change is greater than a threshold then a flag is set indicating the scene change detection result. + +![alt text](media/optical-flow/optical_flow_preparation_scenechange.svg "Block diagram of scene change detection process") + +

    Main

    + +The algorithm of computing the motion vector estimates repeats 7 times in a sequence of 3 passes: searching, filtering and upscaling. + +1. The searching pass is finding the best match between a current frame block and the previous frame blocks located within a search window. The search window location is determined by the previous iteration result. The best match is computed as a minimum of sum of absolute differences of luminance pixels in a block. +2. The filtering pass removes outliers by using a 3x3 median filter. +3. The upscaling pass prepares 2x larger resolution resources with the motion vector estimates that will be the input for the next iteration. Each estimate is replaced by four estimates chosen from four candidates. + +![alt text](media/optical-flow/optical_flow_main_iteration.svg "Block diagram of iteration steps within main algorithm") + +After 7 iterations of the above steps, the result is available. + +

    Searching Pass

    + +Input Resources: +* Scene change detection result +* Previous luminance of current pyramid level +* Current luminance of current pyramid level +* Upscaled motion vector estimate + +Output Resources: +* Raw motion vector estimate + +The scene change detection result is checked first and if true the zero motion estimate is returned to avoid providing random false positive estimates. The input motion vector estimate is used for computing the location of the search area in the previous frame luminance. Search area size is 24x24 pixels (an 8px radius around an 8x8 pixel block). + +Each 8x8 pixel block of the current luminance resource is processed. The blocks do not overlap. Only one motion vector estimate is provided for all 64 pixels in an 8x8 block. Every possible offset in the search window is checked. This results in 16x16 (256) cases. A sum of absolute differences (SAD) of all pixels in a block is computed. The offset for which a minimum SAD value is computed becomes a correction to the input motion vector estimate. The sum of the input estimate and the correction is written to the output motion vector estimate resource. + +![alt text](media/optical-flow/optical_flow_main_searching.svg "Diagram of searching space") + +

    Filtering Pass

    + +Input Resources: +* Raw motion vector estimate + +Output Resources: +* Filtered motion vector estimate + +A group of 3x3 input raw motion vector estimates is loaded. A "middle" vector is found in the group, which is a vector which has a minimum sum difference to the other vectors. The result vector is written to the filtered motion vector estimate resource. + +

    Upscaling Pass

    + +Input Resources: +* Previous luminance of current pyramid level +* Current luminance of current pyramid level +* Filtered motion vector estimate + +Output Resources: +* Upscaled motion vector estimate for the next pyramid level + +A 2x upscaling is performed by multiplying the motion vector estimate value by 2. An additional step considers 4 candidates: the current upscaled value, and 3 adjacent input motion vector estimates. + +To find the best candidate, a block SAD is computed between input luminance resources: the current luminance pixels covered by the upscaled block, and the previous luminance block pointed by the candidate motion vector and covered by the upscaled block. Both blocks are 4x4 pixels of the current pyramid level resolution. The best candidate has the minimum value of sum of absolute differences (SAD) of luminance pixels in the blocks. + +This pass is not executed on the last iteration. The filtered motion vector estimate becomes the result of the whole algorithm. + +![alt text](media/optical-flow/optical_flow_main_upscale_area.svg "Diagram of upscale space") + +

    Memory Information

    + +| GPU | 4K input/output memory use* | +|--------------------|-----------------------------| +| Radeon RX 7900 XTX | 28MB | +| Radeon RX 6600 | 28MB | +| GeForce RTX 4080 | 26MB | +| GeForce RTX 3060 | 26MB | + +*Figures are rounded up. + +

    Limitations

    + +The maximum tracking movement is 512 pixels. \ No newline at end of file diff --git a/docs/techniques/parallel-sort.md b/docs/techniques/parallel-sort.md index 992f3850..721b1db8 100644 --- a/docs/techniques/parallel-sort.md +++ b/docs/techniques/parallel-sort.md @@ -21,7 +21,7 @@ In order to fully sort a buffer of 32-bit keys, the algorithm is invoked over 8 - ScanPrefix + Add: Thread counts are summed and summed with thread group offsets to provide the final offset location. - Scatter: Copies the source value to its new location (sorted up to n-bits processed thus far) -![FidelityFX Parallel Sort Technique](./media/parallel-sort/parallel-sort-algorightm.jpg) +

    Example C++

    diff --git a/docs/techniques/super-resolution-interpolation.md b/docs/techniques/super-resolution-interpolation.md new file mode 100644 index 00000000..f3f29ad7 --- /dev/null +++ b/docs/techniques/super-resolution-interpolation.md @@ -0,0 +1,387 @@ + + +

    FidelityFX Super Resolution 3.0.3 (FSR3) - Interpolation

    + +![Screenshot](media/super-resolution-temporal/fsr3-sample_resized.jpg "A screenshot showcasing the final output of the effect") + +

    Table of contents

    + +- [FidelityFX Super Resolution 3.0.3 (FSR3)](#fidelityfx-super-resolution-303-fsr3) + - [Table of contents](#table-of-contents) + - [Introduction](#introduction) + - [Integration guidelines](#integration-guidelines) + - [Shading language and API requirements](#shading-language-and-api-requirements) + - [DirectX 12 + HLSL](#directx-12--hlsl) + - [Vulkan + GLSL](#vulkan--glsl) + - [Quick start checklist](#quick-start-checklist) + - [Expected input](#expected-input) + - [Walkthrough](#walkthrough) + - [Add upscaling through FSR3 interface](#add-upscaling-through-fsr3-interface) + - [Enable FSR3's proxy frame interpolation swapchain](#enable-fsr3-s-proxy-frame-interpolation-swapchain) + - [Dispatch Upscaling](#dispatch-upscaling) + - [Configure frame interpolation](#configure-frame-interpolation) + - [UI composition](#ui-composition) + - [Shutdown](#shutdown) + - [The Technique](#the-technique) + - [Memory Usage](#memory-usage) + - [See also](#see-also) + +

    Introduction

    + +AMD FidelityFX Super Resolution 3 (FSR3) improves upon FSR2 by extending its upscaling with a frame interpolation technique which can double framerate and improve the smoothness of animations and frame pacing. + +It uses temporal upscaling based on FSR 2.2.2, along with a new optical flow implementation to reproject samples from 2 rendered frames to generate an additional frame in between. FSR3 also implements a proxy swapchain class that implements the `IDXGISwapChain` interface, which is used to schedule interpolation workloads and handle frame pacing. + +![FSR3 flowchart](media/super-resolution-interpolation/01_FSR3_DataFlow.svg "A diagram showing the components of FSR3 and how they interact. ") + +

    Integration guidelines

    + +

    Shading language and API requirements

    + +

    DirectX 12 + HLSL

    + +- `HLSL` + - `CS_6_2` + - `CS_6_6†` + +† `CS_6_6` is used on some hardware which supports 64-wide wavefronts. + +

    Vulkan + GLSL

    + +Note that FSR3 does not currently support Vulkan. + +

    Quick start checklist

    + +* It is recommended to first implement FSR2 + * Please reference the [FSR2 documentation](/docs/techniques/super-resolution-temporal.md) on how to do this +* Switch from the FSR2 API to FSR3 +* Create additional backends: + * One for sharing data between upscaling and frame interpolation modules + * One for optical flow & frame interpolation +* Add a call to update the frame interpolation parameters +* Replace your application's `IDXGISwapchain` by our `FrameInterpolationSwapChainDX12` +* Frame interpolation can run synchronously or asynchronously + * An asynchronous implementation may run faster on some applications and hardware, but may require some additional effort +* Modify UI rendering - choose one of the following 3 options to handle the UI: + * Render the UI inside a callback function + * This function will get called once for every presented frame and needs to be able to render asynchronously while the next frame is being rendered + * Rendering the UI twice will have a performance cost, but the benefit is that the UI (including effects like film grain) can be updated at display frequency and with little latency + * Render the UI to a separate texture which will then be composed on top of the final frames + * This should still be pretty straight forward to integrate in most applications + * Compared to the 3rd option, this will result in the UI appearing to be rendered at lower frequency than the main scene + * Provide a HUD-less texture to frame interpolation for automatic detection and composition of the UI onto the interpolated frame + * This is probably the easiest method to implement for most applications, but may result in minor artifacts in semi-transparent parts of the UI + +

    Expected input

    + +* Frame generation requires upscaling to run, since some internal data is shared between upscaling and interpolation +* The recommendations for all input data to upscaling is identical to FSR2 + +

    Walkthrough

    + +

    Add upscaling through FSR3 interface

    + +Note: This section assumes an [FSR2](/docs/techniques/super-resolution-temporal.md) implementation to be already present and working correctly. + +Include the [`ffx_fsr3.h`](../../sdk/include/FidelityFX/host/ffx_fsr3.h) header: + +```C++ + #include +``` + +Query the amount of scratch memory required for the FFX Backend using `ffxGetScratchMemorySize` and +allocate the scratch memory for the backend and retrieve the interface using `ffxGetInterface`. Since upscaling and frame interpolation/present may be executed on different CPU threads simultaneously, additional backend interfaces are required: + +```C++ + for (auto i = 0; i < FSR3_BACKEND_COUNT; i++) + { + const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_FSR3_CONTEXT_COUNT); + void* scratchBuffer = malloc(scratchBufferSize); + memset(scratchBuffer, 0, scratchBufferSize); + ffxGetInterface(&ffxFsr3Backends_[i], GetDevice(), scratchBuffer, scratchBufferSize, FFX_FSR3_CONTEXT_COUNT); + } + + m_InitializationParameters.backendInterfaceSharedResources = ffxFsr3Backends_[FSR3_BACKEND_SHARED_RESOURCES]; + m_InitializationParameters.backendInterfaceUpscaling = ffxFsr3Backends_[FSR3_BACKEND_UPSCALING]; + m_InitializationParameters.backendInterfaceFrameInterpolation = ffxFsr3Backends_[FSR3_BACKEND_FRAME_INTERPOLATION]; +``` + +Create the `FfxFsr3Context` by filling out the `FfxFsr3ContextDescription` structure with the required arguments. + +Note: This code snippet only shows the additional initialization parameters required for FSR3, compared to FSR2: + +```C++ + // FSR upscaler output resolution, as this may be different than display resolution in some titles + m_InitializationParameters.upscaleOutputSize.width = resInfo.DisplayWidth; + m_InitializationParameters.upscaleOutputSize.height = resInfo.DisplayHeight; + + // set this flag if interpolation should run on an async queue + m_InitializationParameters.flags |= FFX_FSR3_ENABLE_ASYNC_WORKLOAD_SUPPORT; + + // fill in the format of the backbuffer that will be used for interpolation + m_InitializationParameters.backBufferFormat = GetFfxSurfaceFormat(GetSwapChainFormat()); + + FfxErrorCode errorCode = ffxFsr3ContextCreate(&m_FSR3Context, &m_InitializationParameters); +``` + +

    Enable FSR3's proxy frame interpolation swapchain

    + +For ease of integration, FSR3 provides a frame interpolation swapchain, which implements the `IDXGISwapchain` interface. This class can replace the "normal" swapchain and handles dispatching the frame interpolation and UI composition workloads, as well as modulating frame pacing to ensure frames are displayed at roughly even pacing. + +Using the frame interpolation swapchain has been optimized to ensure low latency, minimize tearing, and work well with variable refresh rate displays. + +Since replacing the swapchain is not allowed while in full-screen mode, the frame interpolation swapchain supports a passthrough mode with minimal overhead so that frame interpolation can be easily disabled without the need to recreate the swapchain. + +```C++ + FfxSwapchain ffxSwapChain = ffxGetSwapchainDX12(pSwapchain->GetImpl()->DX12SwapChain()); + ID3D12CommandQueue* pCmdQueue = GetDevice()->GetImpl()->DX12CmdQueue(CommandQueue::Graphics); + FfxCommandQueue ffxGameQueue = ffxGetCommandQueueDX12(pCmdQueue); + + // unset the swapchain in the engine + GetFramework()->GetSwapChain()->GetImpl()->SetDXGISwapChain(nullptr); + + // this function takes a FfxCommandQueue and a FfxSwapchain and + // will replace the swapchain inside the ffxSwapchain with the frame interpolation swapchain + ffxReplaceSwapchainForFrameinterpolation(ffxGameQueue, ffxSwapChain); + + // alternatively we provide functions to create a swap chain similar to the Windows API + // ffxCreateFrameinterpolationSwapchainDX12(const DXGI_SWAP_CHAIN_DESC* desc, + // ID3D12CommandQueue* queue, + // IDXGIFactory* dxgiFactory, + // FfxSwapchain& outGameSwapChain); + // + // ffxCreateFrameinterpolationSwapchainForHwndDX12(HWND hWnd, + // const DXGI_SWAP_CHAIN_DESC1* desc1, + // const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* fullscreenDesc, + // ID3D12CommandQueue* queue, + // IDXGIFactory* dxgiFactory, + // FfxSwapchain& outGameSwapChain); + + // Set frameinterpolation swapchain to engine + IDXGISwapChain4* frameinterpolationSwapchain = ffxGetDX12SwapchainPtr(ffxSwapChain); + GetFramework()->GetSwapChain()->GetImpl()->SetDXGISwapChain(frameinterpolationSwapchain); + + // In case the app is handling Alt-Enter manually we need to update the window association after creating a different swapchain + IDXGIFactory7* factory = nullptr; + if (SUCCEEDED(frameinterpolationSwapchain->GetParent(IID_PPV_ARGS(&factory)))) + { + factory->MakeWindowAssociation(GetFramework()->GetInternal()->GetHWND(), DXGI_MWA_NO_WINDOW_CHANGES); + factory->Release(); + } + + // call SetHDRMetaData and SetColorSpace1 if needed + GetFramework()->GetSwapChain()->SetHDRMetadataAndColorspace(); +``` + +

    Dispatch Upscaling

    + +FSR3 Frame Interpolation requires FSR3 Upscaling to run, since it will access some internal resources generated during the upscale passes. + +When the time comes for upscaling, fill out the `FfxFsr3DispatchUpscaleDescription` structure and call `ffxFsr3ContextDispatchUpscale` using it. + +If FSR2 support is already implemented, just replace `FfxFsr2DispatchDescription` with `FfxFsr3DispatchUpscaleDescription` and replace `ffxFsr2ContextDispatch` with `ffxFsr3ContextDispatchUpscale`: + +```C++ + FfxFsr3DispatchUpscaleDescription dispatchParameters = {}; + + // fill out dispatchParameters identical to FSR2 + + FfxErrorCode errorCode = ffxFsr3ContextDispatchUpscale(&m_FSR2Context, &dispatchParameters); + FFX_ASSERT(errorCode == FFX_OK); +``` + +

    Configure frame interpolation

    + +Configure frame interpolation by filling out the `FfxFrameGenerationConfig` structure with the required arguments and calling `ffxFsr3ConfigureFrameGeneration`. + +This may be called on a per frame basis, ideally at the start of the frame, as this must not be called between upscale and present. + +```C++ + FfxSwapchain ffxSwapChain = ffxGetSwapchainDX12(pSwapchain->DX12SwapChain()); + FfxResourceDescription hudLessDesc = GetFfxResourceDescription(m_pHudLessTexture[m_curUiTextureIndex]->DX12Resource(), (FfxResourceUsage)0); + FfxResource hudLessResource = ffxGetResourceDX12(m_pHudLessTexture[m_curUiTextureIndex]->DX12Resource(), hudLessDesc, L"FSR3_HudLessBackbuffer", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + + m_FrameGenerationConfig.swapChain = ffxSwapChain; // FfxSwapchain containing the proxy swapchain + m_FrameGenerationConfig.frameGenerationEnabled = m_FrameInterpolation; // enable or disable generation of interpolated frames + m_FrameGenerationConfig.allowAsyncWorkloads = m_AllowAsyncCompute && m_EnableAsyncCompute; // should async compute be used this frame? + m_FrameGenerationConfig.frameGenerationCallback = ffxFsr3DispatchFrameGeneration; // optional: function to record frame generation commandlist. This may be a nullptr. + + // max one of the following 2 options should be used at a time: + m_FrameGenerationConfig.presentCallback = UiCompositionCallback; // optional: UI composition callback. This may be a nullptr. + m_FrameGenerationConfig.HUDLessColor = hudLessResource; // optional: may be FfxResource({}) + + // set optional flags for development purposes: + m_FrameGenerationConfig.flags = 0; + m_FrameGenerationConfig.flags |= FFX_FSR3_FRAME_GENERATION_FLAG_DRAW_DEBUG_TEAR_LINES; // draw debug lines to better show if tearing is enabled + m_FrameGenerationConfig.flags |= FFX_FSR3_FRAME_GENERATION_FLAG_DRAW_DEBUG_VIEW; // display internal surfaces for debugging visual artifacts + + ffxFsr3ConfigureFrameGeneration(&m_FSR3Context, &m_FrameGenerationConfig); +``` +When `allowAsyncWorkloads` is set to `false` the main graphics queue will be used to execute the Optical Flow and Frame Generation workloads. It is strongly advised to profile, if significant performance benefits can be gained from asynchronous compute usage. Not using asynchronous compute will result in a lower memory overhead. + +Note that UI composition and presents will always get executed on an async queue, so they can be paced and injected into the middle of the workloads generating the next frame. + +![FSR3 non async workflow](media/super-resolution-interpolation/02_FSR3_Flow.svg "A diagram showing the FSR3 workflow when not using async compute") + +When `allowAsyncWorkloads` is set to `true`, the Optical Flow and Frame Generation workloads will run on an asynchronous compute queue and overlap with workloads of the next frame on the main game graphics queue. This can improve performance depending on the GPU and workloads. + +![FSR3 non async workflow](media/super-resolution-interpolation/03_FSR3_FlowAsyncQueue.svg "A diagram showing the FSR3 workflow when using async compute") + +

    UI Composition

    + +For frame interpolation the user interface will require some special treatment, otherwise very noticeable artifacts will be generated which can impact readability of the interface. + +To prohibit those artifacts FSR3 supports various options to handle the UI: + +The preferred method is to use the `presentCallback`. The function provided in this parameter will get called once for every frame presented and allows the application to schedule the GPU workload required to render the UI. By using this function the application can reduce UI input latency and render effects that do not work well with frame generation (e.g. film grain). + +The UI composition callback function will be called for every frame (real or generated) to allow rendering the UI separately for each presented frame, so the UI can get rendered at presentation rate to achieve smooth UI animations. + +```C++ +FfxErrorCode FSR3RenderModule::UiCompositionCallback(const FfxPresentCallbackDescription* params) +{ + ID3D12GraphicsCommandList2* pDxCmdList = reinterpret_cast(params->commandList); + CommandListInternal cmdList = {L"UI_CommandList", pDxCmdList, nullptr, CommandQueue::Graphics}; + + ID3D12Resource* pRtResource = reinterpret_cast(params->outputSwapChainBuffer.resource); + pRtResource->AddRef(); + GPUResourceInternal rtResource(pRtResource, L"UI_RenderTarget", CauldronGetStateFfx(params->outputSwapChainBuffer.state), false); + + ID3D12Resource* pBbResource = reinterpret_cast(params->currentBackBuffer.resource); + pBbResource->AddRef(); + GPUResourceInternal bbResource(pBbResource, L"BackBuffer", CauldronGetStateFfx(params->currentBackBuffer.state), false); + + // Use pDxCmdList to copy pBbResource and render UI into the outputSwapChainBuffer. + // The backbuffer is provided as SRV so postprocessing (e.g. adding a blur effect behind the UI) can easily be applied +} +``` + +![FSR3 non async workflow](media/super-resolution-interpolation/04_FSR3_UiCallback.svg "A diagram showing the FSR3 workflow when using async compute") + +If frame generation is disabled `presentCallback` will still get called on present. +![FSR3 non async workflow](media/super-resolution-interpolation/05_FSR3_NoFG_UiCallback.svg "A diagram showing the FSR3 workflow when using async compute") + +The second option to handle the UI is to render the UI into a dedicated surface that will be blended onto the interpolated and real backbuffer before present. Composition of this surface can be done automatically composed by the proxy swapchain or manually in the `presentCallback`. This method allows to present an UI unaffected by frame interpolation, however the UI will only be rendered at render rate. For applications with a largely static UI this might be a good solution without the additional overhead of rendering the UI at presentation rate. + +![FSR3 non async workflow](media/super-resolution-interpolation/06_FSR3_UiTex.svg "A diagram showing the FSR3 workflow when using async compute") + +If frame generation is disabled and the UI Texture is provided, UI composition will still get executed by the frame interpolation swapchain. +![FSR3 non async workflow](media/super-resolution-interpolation/07_FSR3_NoFG_UiTex.svg "A diagram showing the FSR3 workflow when using async compute") + +In that case the surface needs to be registered to the swap chain by calling `ffxRegisterFrameinterpolationUiResourceDX12`: + +```C++ + FfxResource uiColor = ffxGetResource(m_pUiTexture[m_curUiTextureIndex]->GetResource(), L"FSR3_UiTexture", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + ffxRegisterFrameinterpolationUiResourceDX12(ffxSwapChain, uiColor); +``` +The final method to handle the UI is to provide a `HUDLessColor` surface in the `FfxFrameGenerationConfig`. This surface will get used during frame interpolation to detect the UI and avoid distortion on UI elements. This method has been added for compatibility with engines that can not apply either of the other two options for UI rendering. + +![FSR3 non async workflow](media/super-resolution-interpolation/08_FSR3_HUDLess.svg "A diagram showing the FSR3 workflow when using async compute") + +

    Shutdown

    + +During shutdown, disable UI handling and frame generation in the proxy swapchain and destroy the FSR3 context: + +```C++ + // ensure all async workloads related to presents have finished and all surfaces can be released + cauldron::SwapChain* pSwapchain = GetFramework()->GetSwapChain(); + FfxSwapchain ffxSwapChain = ffxGetSwapchainDX12(pSwapchain->GetImpl()->DX12SwapChain()); + ffxWaitForPresents(ffxSwapChain); + + m_FrameGenerationConfig.frameGenerationEnabled = false; + m_FrameGenerationConfig.swapChain = ffxSwapChain; + m_FrameGenerationConfig.presentCallback = nullptr; + m_FrameGenerationConfig.HUDLessColor = FfxResource({}); + ffxFsr3ConfigureFrameGeneration(&m_FSR3Context, &m_FrameGenerationConfig); + + ffxRegisterFrameinterpolationUiResource(ffxSwapChain, FfxResource({})); + + ffxFsr3ContextDestroy(&m_FSR3Context); + + // free memory of the backendInterfaces + free(m_InitializationParameters.backendInterfaceSharedResources.scratchBuffer); + free(m_InitializationParameters.backendInterfaceUpscaling.scratchBuffer); + free(m_InitializationParameters.backendInterfaceFrameInterpolation.scratchBuffer); +``` + +Finally, destroy the proxy swap chain by releasing the handle and re-create the normal DX12 swap chain. + +

    The Technique

    + +FSR3 is a container effect consisting of four components. For details on each component, please refer to the dedicated documentation page: + +1. FfxFsr3Upscaler - please refer to the [FSR2 temporal upscaler documentation](super-resolution-temporal.md) for details +2. [FfxOpticalFlow](optical-flow.md) +3. [FfxFrameinterpolation](frame-interpolation.md) +4. [Frame interpolation swapchain](frame-interpolation-swap-chain.md) + +

    Memory Usage

    + +Figures are given to the nearest MB, taken on Radeon RX 7900 XTX, and are subject to change. Does not include frame interpolation swapchain overheads. + +| Scenario | Quality | Pre-Upscale Resolution | Display Resolution | Memory Usage | +|---|---|---|---|---| +| FSR3 Upscale+FG, Async Compute OF+FI, UICallback | NativeAA | 3840x2160 | 3840x2160 |984 MB| +| | Quality | 2560x1440 | 3840x2160 |648 MB| +| | Balanced | 2258x1270 | 3840x2160 |576 MB| +| | Performance | 1920x1080 | 3840x2160 |521 MB| +| | Ultra Performance | 1280x720 | 3840x2160 |428 MB| +| | | | | | +| FSR3 Upscale+FG, Async Compute OF+FI, UICallback | NativeAA | 2560x1440 | 2560x1440 |460 MB| +| | Quality | 1706x960 | 2560x1440 |303 MB| +| | Balanced | 1505x847 | 2560x1440 |270 MB| +| | Performance | 1280x720 | 2560x1440 |241 MB| +| | Ultra Performance | 853x480 | 2560x1440 |201 MB| +| | | | | | +| FSR3 Upscale+FG, Async Compute OF+FI, UICallback | NativeAA | 1920x1080 | 1920x1080 |267 MB| +| | Quality | 1280x720 | 1920x1080 |174 MB| +| | Balanced | 1129x635 | 1920x1080 |158 MB| +| | Performance | 960x540 | 1920x1080 |149 MB| +| | Ultra Performance | 640x360 | 1920x1080 |119 MB| + +| Scenario | Quality | Pre-Upscale Resolution | Display Resolution | Memory Usage | +|---|---|---|---|---| +| FSR3 Upscale+FG, Present Queue OF+FI, UICallback | NativeAA | 3840x2160 | 3840x2160 |887 MB| +| | Quality | 2560x1440 | 3840x2160 |602 MB| +| | Balanced | 2258x1270 | 3840x2160 |541 MB| +| | Performance | 1920x1080 | 3840x2160 |495 MB| +| | Ultra Performance | 1280x720 | 3840x2160 |416 MB| +| | | | | | +| FSR3 Upscale+FG, Present Queue OF+FI, UICallback | NativeAA | 2560x1440 | 2560x1440 |415 MB| +| | Quality | 1706x960 | 2560x1440 |282 MB| +| | Balanced | 1505x847 | 2560x1440 |254 MB| +| | Performance | 1280x720 | 2560x1440 |229 MB| +| | Ultra Performance | 853x480 | 2560x1440 |195 MB| +| | | | | | +| FSR3 Upscale+FG, Present Queue OF+FI, UICallback | NativeAA | 1920x1080 | 1920x1080 |241 MB| +| | Quality | 1280x720 | 1920x1080 |163 MB| +| | Balanced | 1129x635 | 1920x1080 |149 MB| +| | Performance | 960x540 | 1920x1080 |141 MB| +| | Ultra Performance | 640x360 | 1920x1080 |116 MB| + + +| Scenario | Quality | Pre-Upscale Resolution | Display Resolution | Memory Usage | +|---|---|---|---|---| +| FSR3 Upscale Only | NativeAA | 3840x2160 | 3840x2160 |628 MB| +| | Quality | 2560x1440 | 3840x2160 |437 MB| +| | Balanced | 2258x1270 | 3840x2160 |396 MB| +| | Performance | 1920x1080 | 3840x2160 |365 MB| +| | Ultra Performance | 1280x720 | 3840x2160 |312 MB| +| | | | | | +| FSR3 Upscale Only | NativeAA | 2560x1440 | 2560x1440 |293 MB| +| | Quality | 1706x960 | 2560x1440 |204 MB| +| | Balanced | 1505x847 | 2560x1440 |186 MB| +| | Performance | 1280x720 | 2560x1440 |169 MB| +| | Ultra Performance | 853x480 | 2560x1440 |147 MB| +| | | | | | +| FSR3 Upscale Only | NativeAA | 1920x1080 | 1920x1080 |169 MB| +| | Quality | 1280x720 | 1920x1080 |116 MB| +| | Balanced | 1129x635 | 1920x1080 |107 MB| +| | Performance | 960x540 | 1920x1080 |102 MB| +| | Ultra Performance | 640x360 | 1920x1080 |85 MB| + +

    See also

    + +- [Frame Pacing](frame-pacing.md) +- [FidelityFX Super Resolution Sample](../samples/super-resolution.md) +- [FidelityFX Naming guidelines](../getting-started/naming-guidelines.md) diff --git a/docs/techniques/super-resolution-spatial.md b/docs/techniques/super-resolution-spatial.md index bacc1931..38604daf 100644 --- a/docs/techniques/super-resolution-spatial.md +++ b/docs/techniques/super-resolution-spatial.md @@ -69,7 +69,7 @@ const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_FSR1_CONTEXT_COUNT) Allocate the scratch memory for the backend and retrieve the interface using `ffxGetInterface`: ```C++ -void* scratchBuffer = malloc(scratchBufferSize); +void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&backendInterface, DevicePtr(), scratchBuffer, scratchBufferSize, FFX_FSR1_CONTEXT_COUNT); FFX_ASSERT(errorCode == FFX_OK); ``` diff --git a/docs/techniques/super-resolution-temporal.md b/docs/techniques/super-resolution-temporal.md index 4fcb9089..fac8e9a7 100644 --- a/docs/techniques/super-resolution-temporal.md +++ b/docs/techniques/super-resolution-temporal.md @@ -2,6 +2,8 @@

    FidelityFX Super Resolution 2.2.2 (FSR2)

    +**Consider using [AMD FidelityFX Super Resolution 3 (FSR3)](super-resolution-interpolation.md) instead.** + ![Screenshot](media/super-resolution-temporal/fsr2-sample_resized.jpg "A screenshot showcasing the final output of the effect") AMD FidelityFX Super Resolution 2 (FSR2) is an open source, high-quality solution for producing high resolution frames from lower resolution inputs. @@ -337,7 +339,7 @@ To do this, you can either provide a full custom backend to FSR2 via the [`FfxFs ``` CPP // Setup DX12 interface. const size_t scratchBufferSize = ffxGetScratchMemorySizeDX12(); -void* scratchBuffer = malloc(scratchBufferSize); +void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterfaceDX12(&contextDescription.callbacks, m_pDevice->GetDevice(), scratchBuffer, scratchBufferSize); FFX_ASSERT(errorCode == FFX_OK); diff --git a/docs/techniques/super-resolution-upscaler.md b/docs/techniques/super-resolution-upscaler.md new file mode 100644 index 00000000..21a8266a --- /dev/null +++ b/docs/techniques/super-resolution-upscaler.md @@ -0,0 +1,758 @@ + + +

    FidelityFX Super Resolution 3.0.3 (FSR3) - Upscaler

    + +![Screenshot](media/super-resolution-temporal/fsr3-sample_resized.jpg "A screenshot showcasing the final output of the effect") + +AMD FidelityFX Super Resolution Upscaler is an open source, high-quality solution for producing high resolution frames from lower resolution inputs. + +

    Table of contents

    + +- [Introduction](#introduction) + - [Shading language requirements](#shading-language-requirements) +- [Quick start checklist](#quick-start-checklist) +- [Integration guidelines](#integration-guidelines) + - [Scaling modes](#scaling-modes) + - [Performance](#performance) + - [Memory requirements](#memory-requirements) + - [Input resources](#input-resources) + - [Depth buffer configurations](#depth-buffer-configurations) + - [Providing motion vectors](#providing-motion-vectors) + - [Reactive mask](#reactive-mask) + - [Automatically generating reactivity](#automatically-generating-reactivity) + - [Transparency and composition mask](#transparency-and-composition-mask) + - [Placement in the frame](#placement-in-the-frame) + - [Temporal antialiasing](#temporal-antialiasing) + - [Camera jitter](#camera-jitter) + - [Camera jump cuts](#camera-jump-cuts) + - [Mipmap biasing](#mipmap-biasing) + - [Frame Time Delta Input](#frame-time-delta-input) + - [HDR support](#hdr-support) + - [Falling back to 32-bit floating point](#falling-back-to-32-bit-floating-point) + - [64-wide wavefronts](#64-wide-wavefronts) + - [API Debug Checker](#debug-checker) +- [The technique](#the-technique) + - [Algorithm structure](#algorithm-structure) + - [Compute luminance pyramid](#compute-luminance-pyramid) + - [Reconstruct & dilate](#reconstruct-and-dilate) + - [Depth clip](#depth-clip) + - [Create locks](#create-locks) + - [Reproject & accumulate](#reproject-accumulate) + - [Robust Contrast Adaptive Sharpening (RCAS)](#robust-contrast-adaptive-sharpening-rcas) +- [Building the sample](#building-the-sample) +- [Limitations](#limitations) +- [Version history](#version-history) +- [References](#references) +- [See also](#see-also) + +

    Introduction

    + +**FidelityFX Super Resolution Upscaler** (or **FSR** for short) is a cutting-edge upscaling technique developed from the ground up to produce high resolution frames from lower resolution inputs. + +![alt text](media/super-resolution-temporal/overview.svg "A diagram showing the input resources to the temporal super resolution algorithm.") + +FSR uses temporal feedback to reconstruct high-resolution images while maintaining and even improving image quality compared to native rendering. + +FSR can enable "practical performance" for costly render operations, such as hardware ray tracing. + +

    Shading language requirements

    + +- `HLSL` + - `CS_6_2` + - `CS_6_6†` + +† `CS_6_6` is used on some hardware which supports 64-wide wavefronts. + +

    Quick start checklist

    + +To use FSR you should follow the steps below: + +1. Double click [`BuildAllNativeEffectsSolution.bat`](../../BuildAllNativeEffectsSolution.bat) in the [`samples`](samples) directory. + +2. Open the solution and build it. + +3. Copy the API library `ffx_FSR_x64.lib` from `bin/ffx_sdk` into the folder containing a folder in your project which contains third-party libraries. + +4. Copy the library matching the FFX backend you want to use, e.g.: `bin/ffx_sdk/ffx_backend_dx12_x64.lib` for DirectX 12. + +5. Copy the following core API header files from `src/ffx-FSR-api` into your project: `ffx_fsr3upscaler.h`, `ffx_types.h`, `ffx_error.h`, `ffx_interface.h`, `ffx_util.h`, `shaders/ffx_FSR_common.h`, and `shaders/ffx_FSR_resources.h`. Care should be taken to maintain the relative directory structure at the destination of the file copying. + +6. Copy the header files for the API backend of your choice, e.g. for DirectX 12 you would copy `dx12/ffx_FSR_dx12.h` and `dx12/shaders/ffx_FSR_shaders_dx12.h`. Care should be taken to maintain the relative directory structure at the destination of the file copying. + +7. Include the `ffx_fsr3upscaler.h` header file in your codebase where you wish to interact with FSR. + +8. Create a backend for your target API. E.g. for DirectX 12 you should call [`ffxGetInterfaceDX12`](../../sdk/include/FidelityFX/host/backends/dx12/ffx_dx12.h#L72). A scratch buffer should be allocated of the size returned by calling [`ffxGetScratchMemorySizeDX12`](../../sdk/include/FidelityFX/host/backends/dx12/ffx_dx12.h#L45) and the pointer to that buffer passed to [`ffxGetInterfaceDX12`](../../sdk/include/FidelityFX/host/backends/dx12/ffx_dx12.h#L72). + +9. Create a FSR context by calling [`ffxFsr3UpscalerContextCreate`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L288). The parameters structure should be filled out matching the configuration of your application. See the API reference documentation for more details. + +10. Each frame you should call [`ffxFsr3UpscalerContextDispatch`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L342) to launch FSR workloads. The parameters structure should be filled out matching the configuration of your application. See the API reference documentation for more details, and ensure the [`frameTimeDelta` field is provided in milliseconds](#frame-time-delta-input). + +11. When your application is terminating (or you wish to destroy the context for another reason) you should call [`ffxFsr3UpscalerContextDestroy`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L365). The GPU should be idle before calling this function. + +12. Sub-pixel jittering should be applied to your application's projection matrix. This should be done when performing the main rendering of your application. You should use the [`ffxFsr3UpscalerGetJitterOffset`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L510) function to compute the precise jitter offsets. See [Camera jitter](#camera-jitter) section for more details. + +13. For the best upscaling quality it is strongly advised that you populate the [Reactive mask](#reactive-mask) and [Transparency & composition mask](#transparency-and-composition-mask) according to our guidelines. You can also use [`ffxFsr3UpscalerContextGenerateReactiveMask`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L353) as a starting point. + +14. Applications should expose [scaling modes](#scaling-modes), in their user interface in the following order: Quality, Balanced, Performance, and (optionally) Ultra Performance. + +15. Applications should also expose a sharpening slider to allow end users to achieve additional quality. + +

    Integration guidelines

    + +

    Scaling modes

    +For the convenience of end users, the FSR API provides a number of preset scaling ratios which are named. + +| Quality | Per-dimension scaling factor | +|-------------------|------------------------------| +| NativeAA | 1.0x | +| Quality | 1.5x | +| Balanced | 1.7x | +| Performance | 2.0x | +| Ultra performance | 3.0x | + +We strongly recommend that applications adopt consistent naming and scaling ratios in their user interface. This is to ensure that user experience is consistent for your application's users which may have experience of other applications using FSR. + +

    Performance

    +Depending on your target hardware and operating configuration FSR will operate at different performance levels. + +The table below summarizes the measured performance of FSR on a variety of hardware in DX12. + +| Target resolution | Quality | RX 7900 XTX| RX 6950 XT | RX 6900 XT | RX 6800 XT | RX 6800 | RX 6700 XT | RX 6650 XT | RX 5700 XT | RX Vega 56 | RX 590 | +|-------------------|------------------|------------|------------|------------|------------|---------|------------|------------|------------|------------|--------| +| 3840x2160 | Quality (1.5x) | 0.7ms | 1.1ms | 1.2ms | 1.2ms | 1.4ms | 2.0ms | 2.8ms | 2.4ms | 4.9ms | 5.4ms | +| | Balanced (1.7x) | 0.6ms | 1.0ms | 1.0ms | 1.1ms | 1.4ms | 1.8ms | 2.6ms | 2.2ms | 4.1ms | 4.9ms | +| | Performance (2x) | 0.6ms | 0.9ms | 1.0ms | 1.0ms | 1.3ms | 1.7ms | 2.3ms | 2.0ms | 3.6ms | 4.4ms | +| | Ultra perf. (3x) | 0.5ms | 0.8ms | 0.8ms | 0.9ms | 1.1ms | 1.5ms | 1.8ms | 1.7ms | 2.9ms | 3.7ms | +| 2560x1440 | Quality (1.5x) | 0.3ms | 0.5ms | 0.5ms | 0.5ms | 0.7ms | 0.9ms | 1.2ms | 1.1ms | 1.9ms | 2.3ms | +| | Balanced (1.7x) | 0.3ms | 0.5ms | 0.5ms | 0.5ms | 0.6ms | 0.8ms | 1.1ms | 1.0ms | 1.7ms | 2.1ms | +| | Performance (2x) | 0.3ms | 0.4ms | 0.4ms | 0.4ms | 0.6ms | 0.8ms | 0.9ms | 0.9ms | 1.5ms | 1.9ms | +| | Ultra perf. (3x) | 0.2ms | 0.4ms | 0.4ms | 0.4ms | 0.5ms | 0.7ms | 0.8ms | 0.8ms | 1.2ms | 1.7ms | +| 1920x1080 | Quality (1.5x) | 0.2ms | 0.3ms | 0.3ms | 0.3ms | 0.4ms | 0.5ms | 0.6ms | 0.6ms | 1.0ms | 1.3ms | +| | Balanced (1.7x) | 0.2ms | 0.3ms | 0.3ms | 0.3ms | 0.4ms | 0.5ms | 0.6ms | 0.6ms | 0.9ms | 1.2ms | +| | Performance (2x) | 0.2ms | 0.2ms | 0.2ms | 0.3ms | 0.3ms | 0.5ms | 0.5ms | 0.5ms | 0.8ms | 1.1ms | +| | Ultra perf. (3x) | 0.1ms | 0.2ms | 0.2ms | 0.2ms | 0.3ms | 0.4ms | 0.4ms | 0.4ms | 0.7ms | 0.9ms | + +Figures are rounded to the nearest 0.1ms and are without additional [`sharpness`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L190) and are subject to change. + +

    Memory requirements

    +Using FSR requires some additional GPU local memory to be allocated for consumption by the GPU. When using the FSR API, this memory is allocated when the FSR context is created, and is done so via the series of callbacks which comprise the backend interface. This memory is used to store intermediate surfaces which are computed by the FSR algorithm as well as surfaces which are persistent across many frames of the application. The table below includes the amount of memory used by FSR under various operating conditions. The "Working set" column indicates the total amount of memory used by FSR as the algorithm is executing on the GPU; this is the amount of memory FSR will require to run. The "Persistent memory" column indicates how much of the "Working set" column is required to be left intact for subsequent frames of the application; this memory stores the temporal data consumed by FSR. The "Aliasable memory" column indicates how much of the "Working set" column may be aliased by surfaces or other resources used by the application outside of the operating boundaries of FSR. + +You can take control of resource creation in FSR by overriding the resource creation and destruction parts of the FSR backend interface, and forwarding the aliasing flags. This means that for a perfect integration of FSR, additional memory which is equal to the "Persistent memory" column of the table below is required depending on your operating conditions. + +| Resolution | Quality | Working set (MB) | Persistent memory (MB) | Aliasable memory (MB) | +| -----------|------------------------|------------------|------------------------|-------------------------| +| 3840x2160 | Quality (1.5x) | 448MB | 354MB | 93MB | +| | Balanced (1.7x) | 407MB | 330MB | 77MB | +| | Performance (2x) | 376MB | 312MB | 63MB | +| | Ultra performance (3x) | 323MB | 281MB | 42MB | +| 2560x1440 | Quality (1.5x) | 207MB | 164MB | 43MB | +| | Balanced (1.7x) | 189MB | 153MB | 36MB | +| | Performance (2x) | 172MB | 143MB | 29MB | +| | Ultra performance (3x) | 149MB | 130MB | 19MB | +| 1920x1080 | Quality (1.5x) | 115MB | 90MB | 24MB | +| | Balanced (1.7x) | 105MB | 85MB | 20MB | +| | Performance (2x) | 101MB | 83MB | 18MB | +| | Ultra performance (3x) | 84MB | 72MB | 11MB | + +Figures are approximations, rounded up to nearest MB using an RX 6700XT GPU in DX12, and are subject to change. + +For details on how to manage FSR's memory requirements please refer to the section of this document dealing with [Memory management](#memory-management). + +

    Input resources

    +FSR is a temporal algorithm, and therefore requires access to data from both the current and previous frame. The following table enumerates all external inputs required by FSR. + +The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. All resources are from the current rendered frame, for DirectX(R)12 and Vulkan(R) applications all input resources should be transitioned to [`D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE`](https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_states) and [`VK_ACCESS_SHADER_READ_BIT`](https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkAccessFlagBits.html) respectively before calling [`ffxFsr3UpscalerContextDispatch`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L342). + +| Name | Resolution | Format | Type | Notes | +| ----------------|------------------------------|------------------------------------|-----------|------------------------------------------------| +| Color buffer | Render | `APPLICATION SPECIFIED` | Texture | The render resolution color buffer for the current frame provided by the application. If the contents of the color buffer are in high dynamic range (HDR), then the [`FFX_FSR3UPSCALER_ENABLE_HIGH_DYNAMIC_RANGE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L132) flag should be set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure. | +| Depth buffer | Render | `APPLICATION SPECIFIED (1x FLOAT)` | Texture | The render resolution depth buffer for the current frame provided by the application. The data should be provided as a single floating point value, the precision of which is under the application's control. The configuration of the depth should be communicated to FSR via the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure when creating the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238). You should set the [`FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L135) flag if your depth buffer is inverted (that is [1..0] range), and you should set the [`FFX_FSR3UPSCALER_ENABLE_DEPTH_INFINITE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L136) flag if your depth buffer has an infinite far plane. If the application provides the depth buffer in `D32S8` format, then FSR will ignore the stencil component of the buffer, and create an `R32_FLOAT` resource to address the depth buffer. On GCN and RDNA hardware, depth buffers are stored separately from stencil buffers. | +| Motion vectors | Render or presentation | `APPLICATION SPECIFIED (2x FLOAT)` | Texture | The 2D motion vectors for the current frame provided by the application in **[<-width, -height> ... ]** range. If your application renders motion vectors with a different range, you may use the [`motionVectorScale`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L187) field of the [`FfxFsr3UpscalerDispatchDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L173) structure to adjust them to match the expected range for FSR. Internally, FSR uses 16-bit quantities to represent motion vectors in many cases, which means that while motion vectors with greater precision can be provided, FSR will not benefit from the increased precision. The resolution of the motion vector buffer should be equal to the render resolution, unless the [`FFX_FSR3UPSCALER_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L133) flag is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure when creating the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238), in which case it should be equal to the presentation resolution. | +| Reactive mask | Render | `R8_UNORM` | Texture | As some areas of a rendered image do not leave a footprint in the depth buffer or include motion vectors, FSR provides support for a reactive mask texture which can be used to indicate to FSR where such areas are. Good examples of these are particles, or alpha-blended objects which do not write depth or motion vectors. If this resource is not set, then FSR's shading change detection logic will handle these cases as best it can, but for optimal results, this resource should be set. For more information on the reactive mask please refer to the [Reactive mask](#reactive-mask) section. | +| Exposure | 1x1 | `R32_FLOAT` | Texture | A 1x1 texture containing the exposure value computed for the current frame. This resource is optional, and may be omitted if the [`FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L137) flag is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure when creating the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238). | + +All inputs that are provided at Render Resolution, except for motion vectors, should be rendered with jitter. Motion vectors should not have jitter applied, unless the `FFX_FSR_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION` flag is present. + +

    Depth buffer configurations

    + +It is strongly recommended that an inverted, infinite depth buffer is used with FSR. However, alternative depth buffer configurations are supported. An application should inform the FSR API of its depth buffer configuration by setting the appropriate flags during the creation of the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238). The table below contains the appropriate flags. + +| FSR flag | Note | +|----------------------------------|--------------------------------------------------------------------------------------------| +| [`FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L135) | A bit indicating that the input depth buffer data provided is inverted [max..0]. | +| [`FFX_FSR3UPSCALER_ENABLE_DEPTH_INFINITE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L136) | A bit indicating that the input depth buffer data provided is using an infinite far plane. | + + +

    Providing motion vectors

    + +

    Space

    + +A key part of a temporal algorithm (be it antialiasing or upscaling) is the provision of motion vectors. FSR accepts motion vectors in 2D which encode the motion from a pixel in the current frame to the position of that same pixel in the previous frame. FSR expects that motion vectors are provided by the application in [**<-width, -height>**..****] range; this matches screenspace. For example, a motion vector for a pixel in the upper-left corner of the screen with a value of **** would represent a motion that traversed the full width and height of the input surfaces, originating from the bottom-right corner. + +![alt text](media/super-resolution-temporal/motion-vectors.svg "A diagram showing a 2D motion vector.") + +If your application computes motion vectors in another space - for example normalized device coordinate space - then you may use the [`motionVectorScale`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L187) field of the [`FfxFsr3UpscalerDispatchDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L173) structure to instruct FSR to adjust them to match the expected range for FSR. The code examples below illustrate how motion vectors may be scaled to screen space. The example HLSL and C++ code below illustrates how NDC-space motion vectors can be scaled using the FSR host API. + +```HLSL +// GPU: Example of application NDC motion vector computation +float2 motionVector = (previousPosition.xy / previousPosition.w) - (currentPosition.xy / currentPosition.w); + +// CPU: Matching FSR 2.0 motionVectorScale configuration +dispatchParameters.motionVectorScale.x = (float)renderWidth; +dispatchParameters.motionVectorScale.y = (float)renderHeight; +``` + +

    Precision & resolution

    + +Internally, FSR uses 16-bit quantities to represent motion vectors in many cases, which means that while motion vectors with greater precision can be provided, FSR will not currently benefit from the increased precision. The resolution of the motion vector buffer should be equal to the render resolution, unless the [`FFX_FSR3UPSCALER_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L133) flag is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure when creating the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238), in which case it should be equal to the presentation resolution. + +

    Coverage

    + +FSR will perform better quality upscaling when more objects provide their motion vectors. It is therefore advised that all opaque, alpha-tested and alpha-blended objects should write their motion vectors for all covered pixels. If vertex shader effects are applied - such as scrolling UVs - these calculations should also be factored into the calculation of motion for the best results. For alpha-blended objects it is also strongly advised that the alpha value of each covered pixel is stored to the corresponding pixel in the [reactive mask](#reactive-mask). This will allow FSR to perform better handling of alpha-blended objects during upscaling. The reactive mask is especially important for alpha-blended objects where writing motion vectors might be prohibitive, such as particles. + +

    Reactive mask

    + +In the context of FSR, the term "reactivity" means how much influence the samples rendered for the current frame have over the production of the final upscaled image. Typically, samples rendered for the current frame contribute a relatively modest amount to the result computed by FSR; however, there are exceptions. To produce the best results for fast moving, alpha-blended objects, FSR requires the [Reproject & accumulate](#reproject-accumulate) stage to become more reactive for such pixels. As there is no good way to determine from either color, depth or motion vectors which pixels have been rendered using alpha blending, FSR performs best when applications explicitly mark such areas. + +Therefore, it is strongly encouraged that applications provide a reactive mask to FSR. The reactive mask guides FSR on where it should reduce its reliance on historical information when compositing the current pixel, and instead allow the current frame's samples to contribute more to the final result. The reactive mask allows the application to provide a value from [0.0..1.0] where 0.0 indicates that the pixel is not at all reactive (and should use the default FSR composition strategy), and a value of 1.0 indicates the pixel should be fully reactive. This is a floating point range and can be tailored to different situations. + +While there are other applications for the reactive mask, the primary application for the reactive mask is producing better results of upscaling images which include alpha-blended objects. A good proxy for reactiveness is actually the alpha value used when compositing an alpha-blended object into the scene, therefore, applications should write `alpha` to the reactive mask. It should be noted that it is unlikely that a reactive value of close to 1 will ever produce good results. Therefore, we recommend clamping the maximum reactive value to around 0.9. + +If a [Reactive mask](#reactive-mask) is not provided to FSR (by setting the [`reactive`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L180) field of [`FfxFsr3UpscalerDispatchDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L173) to `NULL`) then an internally generated 1x1 texture with a cleared reactive value will be used. + +

    Automatically generating reactivity

    + +To help applications generate the [Reactive mask](#reactive-mask) and the [Transparency & composition mask](#transparency-and-composition-mask), FSR provides an optional helper API. Under the hood, the API launches a compute shader which computes these values for each pixel using a luminance-based heuristic. + +Applications wishing to do this can call the [`FfxFsr3UpscalerContextGenerateReactiveMask`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L353) function and should pass two versions of the color buffer, one containing opaque only geometry, and the other containing both opaque and alpha-blended objects. + +

    Transparency and composition mask

    + +In addition to the [Reactive mask](#reactive-mask), FSR provides for the application to denote areas of other specialist rendering which should be accounted for during the upscaling process. Examples of such special rendering include areas of raytraced reflections or animated textures. + +While the [Reactive mask](#reactive-mask) adjusts the accumulation balance, the [Transparency & composition mask](#transparency-and-composition-mask) adjusts the pixel history protection mechanisms. The mask also removes the effect of the luminance instability factor. A pixel with a value of 0 in the [Transparency & composition mask](#transparency-and-composition-mask) does not perform any additional modification to the lock for that pixel. Conversely, a value of 1 denotes that the lock for that pixel should be completely removed. + +If a [Transparency & composition mask](#transparency-and-composition-mask) is not provided to FSR (by setting the [`transparencyAndComposition`](#sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L181) field of [`FfxFsr3UpscalerDispatchDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L173) to `NULL`) then an internally generated 1x1 texture with a cleared transparency and composition value will be used. + +

    Exposure

    + +FSR provides two values which control the exposure used when performing upscaling. They are as follows: + +1. **Pre-exposure** a value by which we divide the input signal to get back to the original signal produced by the game before any packing into lower precision render targets. +2. **Exposure** a value which is multiplied against the result of the pre-exposed color value. + +The exposure value should match that which the application uses during any subsequent tonemapping passes performed by the application. This means FSR will operate consistently with what is likely to be visible in the final tonemapped image. + +> In various stages of the FSR algorithm described in this document, FSR will compute its own exposure value for internal use. It is worth noting that all outputs from FSR will have this internal tonemapping reversed before the final output is written. Meaning that FSR returns results in the same domain as the original input signal. + +Poorly selected exposure values can have a drastic impact on the final quality of FSR's upscaling. Therefore, it is recommended that [`FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L137) is used by the application, unless there is a particular reason not to. When [`FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L137) is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure, the exposure calculation shown in the HLSL code below is used to compute the exposure value, which matches the exposure response of ISO 100 film stock. + +```HLSL +float ComputeAutoExposureFromAverageLog(float averageLogLuminance) +{ + const float averageLuminance = exp(averageLogLuminance); + const float S = 100.0f; // ISO arithmetic speed + const float K = 12.5f; + const float exposureIso100 = log2((averageLuminance * S) / K); + const float q = 0.65f; + const float luminanceMax = (78.0f / (q * S)) * pow(2.0f, exposureIso100); + return 1 / luminanceMax; +} +``` + +

    Placement in the frame

    + +The primary goal of FSR is to improve application rendering performance by using a temporal upscaling algorithm relying on a number of inputs. Therefore, its placement in the pipeline is key to ensuring the right balance between the highest quality visual quality and great performance. + +![alt text](media/super-resolution-temporal/pipeline-placement.svg "A diagram showing the placement of temporal FidelityFX Super Resolution in the wider rendering pipeline.") + +With any image upscaling approach is it important to understand how to place other image-space algorithms with respect to the upscaling algorithm. Placing these other image-space effects before the upscaling has the advantage that they run at a lower resolution, which of course confers a performance advantage onto the application. However, it may not be appropriate for some classes of image-space techniques. For example, many applications may introduce noise or grain into the final image, perhaps to simulate a physical camera. Doing so before an upscaler might cause the upscaler to amplify the noise, causing undesirable artifacts in the resulting upscaled image. The following table divides common real-time image-space techniques into two columns. 'Post processing A' contains all the techniques which typically would run before FSR's upscaling, meaning they would all run at render resolution. Conversely, the 'Post processing B' column contains all the techniques which are recommend to run after FSR, meaning they would run at the larger, presentation resolution. + +| Post processing A | Post processing B | +|--------------------------------|----------------------| +| Screenspace reflections | Film grain | +| Screenspace ambient occlusion | Chromatic aberration | +| Denoisers (shadow, reflections)| Vignette | +| Exposure (optional) | Tonemapping | +| | Bloom | +| | Depth of field | +| | Motion blur | + +Please note that the recommendations here are for guidance purposes only and depend on the precise characteristics of your application's implementation. + +

    Temporal Antialiasing

    + +Temporal antialiasing (TAA) is a technique which uses the output of previous frames to construct a higher quality output from the current frame. As FSR has a similar goal - albeit with the additional goal of also increasing the resolution of the rendered image - there is no longer any need to include a separate TAA pass in your application. + +

    Camera jitter

    + +FSR relies on the application to apply sub-pixel jittering while rendering - this is typically included in the projection matrix of the camera. To make the application of camera jitter simple, the FSR API provides a small set of utility function which computes the sub-pixel jitter offset for a particular frame within a sequence of separate jitter offsets. + +``` CPP +int32_t ffxFsr3UpscalerGetJitterPhaseCount(int32_t renderWidth, int32_t displayWidth); +FfxErrorCode ffxFsr3UpscalerGetJitterOffset(float* outX, float* outY, int32_t jitterPhase, int32_t sequenceLength); +``` + +Internally, these function implement a Halton[2,3] sequence [[Halton](#references)]. The goal of the Halton sequence is to provide spatially separated points, which cover the available space. + +![alt text](media/super-resolution-temporal/jitter-space.svg "A diagram showing how to map sub-pixel jitter offsets to projection offsets.") + +It is important to understand that the values returned from the [`ffxFsr3UpscalerGetJitterOffset`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L510) are in unit pixel space, and in order to composite this correctly into a projection matrix we must convert them into projection offsets. The diagram above shows a single pixel in unit pixel space, and in projection space. The code listing below shows how to correctly composite the sub-pixel jitter offset value into a projection matrix. + +``` CPP +const int32_t jitterPhaseCount = ffxFsr3UpscalerGetJitterPhaseCount(renderWidth, displayWidth); + +float jitterX = 0; +float jitterY = 0; +ffxFsr3UpscalerGetJitterOffset(&jitterX, &jitterY, index, jitterPhaseCount); + +// Calculate the jittered projection matrix. +const float jitterX = 2.0f * jitterX / (float)renderWidth; +const float jitterY = -2.0f * jitterY / (float)renderHeight; +const Matrix4 jitterTranslationMatrix = translateMatrix(Matrix3::identity, Vector3(jitterX, jitterY, 0)); +const Matrix4 jitteredProjectionMatrix = jitterTranslationMatrix * projectionMatrix; +``` + +Jitter should be applied to *all* rendering. This includes opaque, alpha transparent, and raytraced objects. For rasterized objects, the sub-pixel jittering values calculated by the [`ffxFsr3UpscalerGetJitterOffset`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L510) function can be applied to the camera projection matrix which is ultimately used to perform transformations during vertex shading. For raytraced rendering, the sub-pixel jitter should be applied to the ray's origin - often the camera's position. + +Whether you elect to use the recommended [`ffxFsr3UpscalerGetJitterOffset`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L510) function or your own sequence generator, you must set the [`jitterOffset`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L186) field of the [`FfxFSRDispatchDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L173) structure to inform FSR of the jitter offset that has been applied in order to render each frame. Moreover, if not using the recommended [`ffxFsr3UpscalerGetJitterOffset`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L510) function, care should be taken that your jitter sequence never generates a null vector; that is value of 0 in both the X and Y dimensions. + +The table below shows the jitter sequence length for each of the default quality modes. + + | Quality mode | Scaling factor | Sequence length | + |-------------------|-------------------------|-----------------| + | Quality | 1.5x (per dimension) | 18 | + | Balanced | 1.7x (per dimension) | 23 | + | Performance | 2.0x (per dimension) | 32 | + | Ultra performance | 3.0x (per dimension) | 72 | + | Custom | [1..n]x (per dimension) | `ceil(8 * n^2)` | + +

    Camera jump cuts

    + +Most applications with real-time rendering have a large degree of temporal consistency between any two consecutive frames. However, there are cases where a change to a camera's transformation might cause an abrupt change in what is rendered. In such cases, FSR is unlikely to be able to reuse any data it has accumulated from previous frames, and should clear this data such to exclude it from consideration in the compositing process. In order to indicate to FSR that a jump cut has occurred with the camera you should set the [`reset`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L193) field of the [`FfxFsr3UpscalerDispatchDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L173) structure to `true` for the first frame of the discontinuous camera transformation. + +Rendering performance may be slightly less than typical frame-to-frame operation when using the reset flag, as FSR will clear some additional internal resources. + +

    Mipmap biasing

    + +Applying a negative mipmap biasing will typically generate an upscaled image with better texture detail. We recommend applying the following formula to your Mipmap bias: + +``` CPP +mipBias = log2(renderResolution/displayResolution) - 1.0; +``` + +It is suggested that applications adjust the MIP bias for specific high-frequency texture content which is susceptible to showing temporal aliasing issues. + +The following table illustrates the mipmap biasing factor which results from evaluating the above pseudocode for the scaling ratios matching the suggested quality modes that applications should expose to end users. + + | Quality mode | Scaling factor | Mipmap bias | + |-------------------|-----------------------|-------------| + | Quality | 1.5X (per dimension) | -1.58 | + | Balanced | 1.7X (per dimension) | -1.76 | + | Performance | 2.0X (per dimension) | -2.0 | + | Ultra performance | 3.0X (per dimension) | -2.58 | + +

    Frame Time Delta Input

    + +The FSR API requires [`frameTimeDelta`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L191) be provided by the application through the [`FfxFsr3UpscalerDispatchDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L173) structure. This value is in __milliseconds__: if running at 60fps, the value passed should be around __16.6f__. + +The value is used within the temporal component of the FSR 2 auto-exposure feature. This allows for tuning of the history accumulation for quality purposes. + +

    HDR support

    + +High dynamic range images are supported in FSR. To enable this, you should set the [`FFX_FSR3UPSCALER_ENABLE_HIGH_DYNAMIC_RANGE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L132) bit in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure. Images should be provided to FSR in linear color space. + +> Support for additional color spaces might be provided in a future revision of FSR. + +

    Falling back to 32-bit floating point

    + +FSR was designed to take advantage of half precision (FP16) hardware acceleration to achieve the highest possible performance. However, to provide the maximum level of compatibility and flexibility for applications, FSR also includes the ability to compile the shaders using full precision (FP32) operations. + +It is recommended to use the FP16 version of FSR on all hardware which supports it. You can query your graphics card's level of support for FP16 by querying the [`D3D12_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT`](https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shader_min_precision_support) capability in DirectX(R)12 - you should check that the `D3D[11/12]_SHADER_MIN_PRECISION_16_BIT` is set, and if it is not, fallback to the FP32 version of FSR. For Vulkan, if [`VkPhysicalDeviceFloat16Int8FeaturesKHR::shaderFloat16`](https://khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceShaderFloat16Int8FeaturesKHR.html) is not set, then you should fallback to the FP32 version of FSR. Similarly, if [`VkPhysicalDevice16BitStorageFeatures::storageBuffer16BitAccess`](https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkPhysicalDevice16BitStorageFeatures.html) is not set, you should also fallback to the FP32 version of FSR. + +To enable the FP32 path in the FSR shader source code, you should define `FFX_HALF` to be `1`. In order to share the majority of the algorithm's source code between both FP16 and FP32 (ensuring a high level of code sharing to support ongoing maintenance), you will notice that the FSR shader source code uses a set of type macros which facilitate easy switching between 16-bit and 32-bit base types in the shader source. + +| FidelityFX type | FP32 | FP16 | +|-----------------|-------------|-----------------| +| `FFX_MIN16_F` | `float` | `min16float` | +| `FFX_MIN16_F2` | `float2` | `min16float2` | +| `FFX_MIN16_F3` | `float3` | `min16float3` | +| `FFX_MIN16_F4` | `float4` | `min16float4` | + +The table above enumerates the mappings between the abstract FidelityFX SDK types, and the underlaying intrinsic type which will be substituted depending on the configuration of the shader source during compilation. + +

    64-wide wavefronts

    + +Modern GPUs execute collections of threads - called wavefronts - together in a SIMT fashion. The precise number of threads which constitute a single wavefront is a hardware-specific quantity. Some hardware, such as AMD's GCN and RDNA-based GPUs support collecting 64 threads together into a single wavefront. Depending on the precise characteristics of an algorithm's execution, it may be more or less advantageous to prefer a specific wavefront width. With the introduction of Shader Model 6.6, Microsoft added the ability to specific the width of a wavefront via HLSL. For hardware, such as RDNA which supports both 32 and 64 wide wavefront widths, this is a very useful tool for optimization purposes, as it provides a clean and portable way to ask the driver software stack to execute a wavefront with a specific width. + +For DirectX(R)12 based applications which are running on RDNA and RDNA2-based GPUs and using the Microsoft Agility SDK, the FSR host API will select a 64-wide wavefront width. + +

    Debug Checker

    + +The context description structure can be provided with a callback function for passing textual warnings from the FSR 2 runtime to the underlying application. The `fpMessage` member of the description is of type `FfxFsr3UpscalerMessage` which is a function pointer for passing string messages of various types. Assigning this variable to a suitable function, and passing the [`FFX_FSR3UPSCALER_ENABLE_DEBUG_CHECKING`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L140) flag within the flags member of [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) will enable the feature. It is recommended this is enabled only in debug development builds. + +An example of the kind of output that can occur when the checker observes possible issues is below: + +``` +FSR_API_DEBUG_WARNING: FFX_FSR_ENABLE_DEPTH_INFINITE and FFX_FSR_ENABLE_DEPTH_INVERTED present, cameraFar value is very low which may result in depth separation artefacting +FSR_API_DEBUG_WARNING: frameTimeDelta is less than 1.0f - this value should be milliseconds (~16.6f for 60fps) +``` + +

    The technique

    + +

    Algorithm structure

    +The FSR algorithm is implemented in a series of stages, which are as follows: + +1. Compute luminance pyramid +2. Reconstruct & dilate +3. Depth clip +4. Create locks +5. Reproject & accumulate +6. Robust Contrast Adaptive Sharpening (RCAS) + +Each pass stage of the algorithm is laid out in the sections following this one, but the data flow for the complete FSR algorithm is shown in the diagram below. + +![alt text](media/super-resolution-temporal/algorithm-structure.svg "A diagram showing all passes in the FSR algorithm.") + +

    Compute luminance pyramid

    + +The compute luminance pyramid stage has two responsibilities: + +1. To produce a lower resolution version of the input color's luminance. This is used by shading change detection in the accumulation pass. +2. To produce a 1x1 exposure texture which is optionally used to apply tonemapping, and the [Reproject & Accumulate](#project-and-accumulate) stage for reversing local tonemapping ahead of producing an output from FSR. + + +

    Resource inputs

    + +The following table contains all resources consumed by the [Compute luminance pyramid](#compute-luminance-pyramid) stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ----------------|-----------------|--------------|-------------------------|-----------|----------------------------------------------| +| Color buffer | Current frame | Render | `APPLICATION SPECIFIED` | Texture | The render resolution color buffer for the current frame provided by the application. If the contents of the color buffer are in high dynamic range (HDR), then the [`FFX_FSR3UPSCALER_ENABLE_HIGH_DYNAMIC_RANGE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L132) flag should be set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure. | + +

    Resource outputs

    + +The following table contains all resources produced or modified by the [Compute luminance pyramid](#compute-luminance-pyramid) stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ----------------------------|-----------------|------------------|-------------------------|-----------|----------------------------------------------| +| Exposure | Current frame | 1x1 | `R32_FLOAT` | Texture | A 1x1 texture containing the exposure value computed for the current frame. This resource is optional, and may be omitted if the [`FFX_FSR_ENABLE_AUTO_EXPOSURE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L137) flag is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure when creating the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238). | +| Current luminance | Current frame | `Render * 0.5` + MipChain | `R16_FLOAT` | Texture | A texture at 50% of render resolution texture which contains the luminance of the current frame. A full mip chain is allocated. | + +

    Description

    + +The [Compute luminance pyramid](#compute-luminance-pyramid) stage is implemented using FidelityFX [Single Pass Downsampler](https://github.com/GPUOpen-Effects/FidelityFX-SPD), an optimized technique for producing mipmap chains using a single compute shader dispatch. Instead of the conventional (full) pyramidal approach, SPD provides a mechanism to produce a specific set of mipmap levels for an arbitrary input texture, as well as performing arbitrary calculations on that data as we store it to the target location in memory. In FSR, we are interested in producing in upto two intermediate resources depending on the configuration of the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238). The first resource is a low-resolution representation of the current luminance, this is used later in FSR to attempt to detect shading changes. The second is the exposure value, and while it is always computed, it is only used by subsequent stages if the [`FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L137) flag is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure upon context creation. The exposure value - either from the application, or the [Compute luminance pyramid](#compute-luminance-pyramid) stage - is used in the [Adjust input color](#adjust-input-color) stage of FSR, as well as by the [Reproject & Accumulate](#project-and-accumulate) stage. + +![alt text](media/super-resolution-temporal/auto-exposure.svg "A diagram showing the mipmap levels written by auto-exposure.") + +As used by FSR, SPD is configured to write only to the 2nd (half resolution) and last (1x1) mipmap level. Moreover, different calculations are applied at each of these levels to calculate the quantities required by subsequent stages of the FSR algorithm. This means the rest of the mipmap chain is not required to be backed by GPU local memory (or indeed any type of memory). + +The 2nd mipmap level contains current luminance, the value of which is computed during the downsampling of the color buffer using the following HLSL: + +``` HLSL +float3 rgb = LoadInputColor(tex); +float3 rgb2y = float3(0.2126, 0.7152, 0.0722); +float logLuma = log(max(FSR_EPSILON, dot(rgb2y, rgb))); +``` + +The last mipmap level is computed using the following HLSL: + +``` HLSL +float ComputeAutoExposureFromAverageLog(float averageLogLuminance) +{ + const float averageLuminance = exp(averageLogLuminance); + const float S = 100.0f; // ISO arithmetic speed + const float K = 12.5f; + const float exposureIso100 = log2((averageLuminance * S) / K); + const float q = 0.65f; + const float luminanceMax = (78.0f / (q * S)) * pow(2.0f, exposureIso100); + return 1 / luminanceMax; +} +``` + +

    Reconstruct and dilate

    + +The reconstruct & dilate stage consumes the applications depth buffer and motion vectors, and produces a reconstructed and dilated depth buffer for the previous frame, together with a dilated set of motion vectors in UV space. The stage runs at render resolution. + +![alt text](media/super-resolution-temporal/vector-dilation.svg "A diagram showing how a motion vector is dilated based on the depth value.") + +

    Resource inputs

    + +The following table contains all of the resources which are required by the reconstruct & dilate stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ----------------------------|-----------------|------------|------------------------------------|-----------|------------------------------------------------| +| Color buffer | Current frame | Render | `APPLICATION SPECIFIED` | Texture | The render resolution color buffer for the current frame provided by the application. If the contents of the color buffer are in high dynamic range (HDR), then the [`FFX_FSR3UPSCALER_ENABLE_HIGH_DYNAMIC_RANGE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L132) flag should be set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure. | +| Exposure | Current frame | 1x1 | ``R32_FLOAT`` | Texture | A 1x1 texture containing the exposure value computed for the current frame. This resource can be supplied by the application, or computed by the [Compute luminance pyramid](#compute-luminance-pyramid) stage of FSR if the [`FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L137) flag is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure. | +| Depth buffer | Current frame | Render | `APPLICATION SPECIFIED (1x FLOAT)` | Texture | The render resolution depth buffer for the current frame provided by the application. The data should be provided as a single floating point value, the precision of which is under the application's control. The configuration of the depth should be communicated to FSR via the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure when creating the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238). You should set the [`FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L135) flag if your depth buffer is inverted (that is [1..0] range), and you should set the flag if your depth buffer has as infinite far plane. If the application provides the depth buffer in `D32S8` format, then FSR will ignore the stencil component of the buffer, and create an `R32_FLOAT` resource to address the depth buffer. On GCN and RDNA hardware, depth buffers are stored separately from stencil buffers. | +| Motion vectors | Current fraame | Render or presentation | `APPLICATION SPECIFIED (2x FLOAT)` | Texture | The 2D motion vectors for the current frame provided by the application in [*<-width, -height>*..**] range. If your application renders motion vectors with a different range, you may use the [`motionVectorScale`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L187) field of the [`FfxFsr3UpscalerDispatchDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L173) structure to adjust them to match the expected range for FSR. Internally, FSR uses 16bit quantities to represent motion vectors in many cases, which means that while motion vectors with greater precision can be provided, FSR will not benefit from the increased precision. The resolution of the motion vector buffer should be equal to the render resolution, unless the [`FFX_FSR3UPSCALER_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L133) flag is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure when creating the [`FfxFSRContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238), in which case it should be equal to the presentation resolution. | + +

    Resource outputs

    + +The following table contains all of the resources which are produced by the reconstruct & dilate stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ------------------------------------|-----------------|------------|------------------------|-----------|------------------------------------------------| +| Est.Previous depth buffer | Current frame | Render | `R32_UNORM` | Texture | A texture containing the reconstructed previous frame depth values. This surface should first be cleared, see the [Adjust input color](#adjust-input-color) stage for details. Please note: When viewing this texture in a capture tool (such as [RenderDoc](https://renderdoc.org)) it may not display correctly. This is because the format of this texture is ``R32_UNORM`` and contains IEEE754 floating point values, which have been written after performing a bitcast using the ``asuint`` intrinsic function. See the note in [Reproject & accumulate](#reproject-accumulate) for more details on the specifics of how this works. | +| Dilated depth | Current frame | Render | `R16_UINT` | Texture | A texture containing dilated depth values computed from the application's depth buffer. | +| Dilated motion vectors | Current frame | Render | `R16G16_FLOAT` | Texture | A texture containing dilated 2D motion vectors computed from the application's 2D motion vector buffer. The red and green channel contains the two-dimensional motion vectors in NDC space. | +| Previous depth buffer | Current frame | Render | `R32_UNORM` | Texture | A texture containing a reconstructed and dilated depth values. This surface is cleared by the [Adjust input color](#adjust-input-color) stage. Please note: When viewing this texture in a capture tool (such as [RenderDoc](https://renderdoc.org)) it may not display correctly. This is because the format of this texture is ``R32_UNORM`` and contains IEEE754 floating point values, which have been written after performing a bitcast using the [`asuint`](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-asuint) intrinsic function. See the note in [Adjust input color](#adjust-input-color) for more details on the specifics of how this works. | +| Lock input luma | Current frame | Render | `R16_FLOAT` | Texture | A texture containing luma data to be consumed by the lock stage. | + +

    Description

    + +The first step of the [Reconstruct & dilate](#reconstruct-and-dilate) stage is to compute the dilated depth values and motion vectors from the application's depth values and motion vectors for the current frame. Dilated depth values and motion vectors emphasise the edges of geometry which has been rendered into the depth buffer. This is because the edges of geometry will often introduce discontinuities into a contiguous series of depth values, meaning that as depth values and motion vectors are dilated, they will naturally follow the contours of the geometric edges present in the depth buffer. In order to compute the dilated depth values and motion vectors, FSR looks at the depth values for a 3x3 neighbourhood for each pixel and then selects the depth values and motion vectors in that neighbourhood where the depth value is nearest to the camera. In the diagram below, you can see how the central pixel of the 3x3 kernel is updated with the depth value and motion vectors from the pixel with the largest depth value - the pixel on the central, right hand side. + +As this stage is the first time that motion vectors are consumed by FSR, this is where motion vector scaling is applied if using the FSR host API. Motion vector scaling factors provided via the [`motionVectorScale`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L187) field of the [`FfxFsr3UpscalerDispatchDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L173) structure and allows you to transform non-screenspace motion vectors into screenspace motion vectors which FSR expects. + +``` CPP +// An example of how to manipulate motion vector scaling factors using the FSR host API. +FfxFSRDispatchParameters dispatchParams = { 0 }; +dispatchParams.motionVectorScale.x = renderWidth; +dispatchParams.motionVectorScale.y = renderHeight; +``` + +With the dilated motion vectors, we can now move to the second part of the [Reconstruct & dilate](#reconstruct-and-dilate) stage, which is to estimate the position of each pixel in the current frame's depth buffer in the previous frame. This is done by applying the dilated motion vector computed for a pixel, to its depth buffer value. As it is possible for many pixels to reproject into the same pixel in the previous depth buffer, atomic operations are used in order to resolve the value of the nearest depth value for each pixel. This is done using the [`InterlockedMax`](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/interlockedmax) or [`InterlockedMin`](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/interlockedmin) operation (the choice depending on if the application's depth buffer is inverted or not). The use of cumulative operations to resolve the contents of the previous depth buffer implies that the reconstructed depth buffer resource must always be cleared to a known value, which is performed in the [Reproject & accumulate](#reproject-accumulate) stage. This is performed on frame N for frame N + 1. + +![alt text](media/super-resolution-temporal/reconstruct-previous-depth.svg "A diagram showing a dilated motion vector being applied to a depth value.") + +When using the FSR API, the application's depth buffer and the application's velocity buffer must be specified as separate resources as per the [Resource inputs](#resource-inputs) table above. However, if you are undertaking a bespoke integration into your application, this constraint may be relaxed. Take care that the performance characteristics of this pass do not change if moving to a format for the motion vector texture which is more sparse, e.g.: as part of a packed g-buffer in a deferred renderer. + +

    Depth clip

    + +The goal of the [Depth clip](#depth-clip) stage is to produce a mask which indicates disoccluded areas of the current frame. + +This stage runs at render resolution. + +

    Resource inputs

    + +The following table contains all the resources which are consumed by the [Depth clip](#depth-clip) stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ------------------------------------|-----------------|------------|------------------------|-----------|------------------------------------------------| +| Est.Previous depth buffer | Current frame | Render | `R32_UNORM` | Texture | A texture containing the reconstructed previous frame depth values. This surface should first be cleared, see the [Reproject & accumulate](#reproject-accumulate) stage for details. Please note: When viewing this texture in a capture tool (such as [RenderDoc](https://renderdoc.org)) it may not display correctly. This is because the format of this texture is ``R32_UINT`` and contains IEEE754 floating point values, which have been written after performing a bitcast using the ``asuint`` intrinsic function. See the note in [Reproject & accumulate](#reproject-accumulate) for more details on the specifics of how this works. | +| Dilated depth | Current frame | Render | `R32_FLOAT` | Texture | A texture containing dilated depth values computed from the application's depth buffer. | +| Dilated motion vectors | Current & Previous frame | Render | `R16G16_FLOAT` | Texture | A texture containing dilated 2D motion vectors computed from the application's 2D motion vector buffer. The red and green channel contains the two-dimensional motion vectors in NDC space, and the alpha channel contains the depth value used by the [Depth clip](#depth-clip) stage. | +| Reactive masks | Current frame | Render | `R8_UNORM` | Texture | As some areas of a rendered image do not leave a footprint in the depth buffer or include motion vectors, FSR provides support for a reactive mask texture which can be used to indicate to FSR where such areas are. Good examples of these are particles, or alpha-blended objects which do not write depth or motion vectors. If this resource is not set, then FSR's shading change detection logic will handle these cases as best it can, but for optimal results, this resource should be set. For more information on the reactive mask please refer to the [Reactive mask](#reactive-mask) section. | +| Color buffer | Current frame | Render | `APPLICATION SPECIFIED` | Texture | The render resolution color buffer for the current frame provided by the application. If the contents of the color buffer are in high dynamic range (HDR), then the [`FFX_FSR3UPSCALER_ENABLE_HIGH_DYNAMIC_RANGE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L132) flag should be set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure. | +| Exposure | Current frame | 1x1 | ``R32_FLOAT`` | Texture | A 1x1 texture containing the exposure value computed for the current frame. This resource can be supplied by the application, or computed by the [Compute luminance pyramid](#compute-luminance-pyramid) stage of FSR if the [`FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L137) flag is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure. | +| Depth buffer | Current frame | Render | `APPLICATION SPECIFIED (1x FLOAT)` | Texture | The render resolution depth buffer for the current frame provided by the application. The data should be provided as a single floating point value, the precision of which is under the application's control. The configuration of the depth should be communicated to FSR via the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure when creating the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238). You should set the [`FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L135) flag if your depth buffer is inverted (that is [1..0] range), and you should set the flag if your depth buffer has as infinite far plane. If the application provides the depth buffer in `D32S8` format, then FSR will ignore the stencil component of the buffer, and create an `R32_FLOAT` resource to address the depth buffer. On GCN and RDNA hardware, depth buffers are stored separately from stencil buffers. | +| Motion vectors | Current fraame | Render or presentation | `APPLICATION SPECIFIED (2x FLOAT)` | Texture | The 2D motion vectors for the current frame provided by the application in [*<-width, -height>*..**] range. If your application renders motion vectors with a different range, you may use the [`motionVectorScale`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L187) field of the [`FfxFsr3UpscalerDispatchDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L173) structure to adjust them to match the expected range for FSR. Internally, FSR uses 16-bit quantities to represent motion vectors in many cases, which means that while motion vectors with greater precision can be provided, FSR will not benefit from the increased precision. The resolution of the motion vector buffer should be equal to the render resolution, unless the [`FFX_FSR3UPSCALER_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L133) flag is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L161) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure when creating the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238), in which case it should be equal to the presentation resolution. | + +

    Resource outputs

    + +The following table contains all the resources which are produced by the [Depth clip](#depth-clip) stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ------------------------------------|-----------------|------------|------------------------|-----------|----------------------------------------| +| Adjusted color buffer | Current frame | Render | `R16G16B16A16_FLOAT` | Texture | A texture containing the adjusted version of the application's color buffer. The tonemapping operator may not be the same as any tonemapping operator included in the application, and is instead a local, reversible operator used throughout FSR. This buffer is stored in YCoCg format. Alpha channel contains disocclusion mask.| +| Dilated reactive mask | Current frame | Render | `R8G8_UNORM` | Texture | Dilated reactive masks. | + +

    Description

    + +To generate the disocclusion mask, the depth value must be computed for each pixel from the previous camera's position and the new camera's position. In the diagram below, you can see a camera moving from an initial position (labelled P0) to a new position (labelled P1). As it does so, the shaded area behind the sphere becomes disoccluded - that is it becomes visible from the camera at P1 and was previously occluded from the point of view of P0. + +![alt text](media/super-resolution-temporal/disocclusion.svg "A diagram showing a disoccluded area as a camera moves from position 0 to position 1.") + +With both values depth values, we can compare the delta between them against the Akeley separation value [[Akeley-06](#references)]. Intuitively, the Akeley separation constant provides a minimum distance between two objects represented in a floating point depth buffer which allow you to say - with a high degree of certainty - that the objects were originally distinct from one another. In the diagram below you can see that the mid-grey and dark-grey objects have a delta which is larger than the `kSep` value which has been computed for the application's depth buffer configuration. However, the distance from the light-gray object to the mid-grey object does not exceed the computed `kSep` value, and therefore we are unable to conclude if this object is distinct. + +![alt text](media/super-resolution-temporal/k-sep.svg "A diagram showing the concept behind the constant of separation.") + +The value stored in the disocclusion mask is in the range [0..1], where 1 maps to a value greater than or equal to the Akeley separation value. + +

    Create locks

    + +This stage is responsible for creating new locks on pixels which are consumed in the [Reproject & Accumulate](#reproject-accumulate) stage. This stage runs at render resolution. + +

    Resource inputs

    + +The following table contains all resources consumed by the [Create locks](#create-locks) stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ----------------------------|-----------------|--------------|-------------------------|-----------|----------------------------------------------| +| Lock input luma | Current frame | Render | `R16_FLOAT` | Texture | A texture containing luminance data to be consumed by the lock stage. | + +

    Resource outputs

    + +The following table contains all resources produced or modified by the [Create locks](#create-locks) stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ----------------------------|-----------------|--------------|-------------------------|-----------|----------------------------------------------| +| New lock mask | Current frame | Presentation | `R8_UNORM` | Texture | A mask which indicates whether or not to perform color rectification on a pixel, can be thought of as a lock on the pixel to stop rectification from removing the detail. Please note: This texture is part of an array of two textures along with the Lock status texture which is used as an input to this stage. The selection of which texture in the array is used for input and output is swapped each frame. The red channel contains the time remaining on the pixel lock, and the Y channel contains the luminance of the pixel at the time when the lock was created. The [Create locks](#create-locks) stage updates only a subset of this resource. | +| Est.Previous depth buffer | Next frame | Render | `R32_UNORM` | Texture | This is only written here to clear it. | + +

    Description

    + +Intuitively, a pixel lock is a mechanism to stop color rectification from being applied to a pixel. The net effect of this locking is that more of the previous frame's color data is used when computing the final, super resolution pixel color in the [Reproject & accumulate](#reproject-accumulate) stage. The lock status texture contains two values which together compose a pixel lock. The red channel of the lock status texture contains the remaining lifetime of a pixel lock. This value is decremented by the initial lock length divided by the total length of the jitter sequence. When a lock reaches zero, it is considered to be expired. The green channel of the lock status texture contains the luminance of the pixel at the time the lock was created, but it is only populated during the reprojection stage of [Reproject & accumulate](#reproject-accumulate) stage. The luminance value is ultimately used in the [Reproject & Accumulate](#reproject-accumulate) stage as part of the shading change detection, this allows FSR to unlock a pixel if there is discontinuous change to the pixel's appearance (e.g.: an abrupt change to the shading of the pixel). + +When creating locks, the 3x3 neighbourhood of luminance values is compared against a threshold. The result of this comparison determines if a new lock should be created. The use of the neighbourhood allows us to detect thin features in the input image which should be locked in order to preserve details in the final super resolution image; such as wires, or chain linked fences. + +Additionally, this stage also has the responsibility for clearing the reprojected depth buffer to a known value, ready for the [Reconstruct & dilate](#reconstruct-and-dilate) stage on the next frame of the application. The buffer must be cleared, as [Reconstruct & dilate](#reconstruct-and-dilate) will populate it using atomic operations. Depending on the configuration of the depth buffer, an appropriate clearing value is selected. + +The format of the previous depth buffer is `R32_UINT` which allows the use of [`InterlockedMax`](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/interlockedmax) and [`InterlockedMin`](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/interlockedmin) operations to be performed from the [Reconstruct & dilate](#reconstruct-and-dilate) stage of FSR. This is done with the resulting integer values returned by converting depth values using the [`asint`](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-asint) functions. This works because depth values are always greater than 0, meaning that the monotonicity of IEEE754 floating point values when interpreted as integers is guaranteed. + + +

    Reproject & accumulate

    + +This stage undertakes the following steps: + +1. The current frame's color buffer is upsampled using Lanczos filtering. +2. The previous frame's output color and lock status buffers are reprojected, as if they were viewed from the current camera's perspective. +3. Various cleanup steps to the historical color data. +4. Luma instability is computed. +5. The historical color data, and the upscaled color data from the current frame are accumulated. + +This stage runs at presentation resolution. + +

    Resource inputs

    + +The following table contain all resources required by the [Reproject & accumulate](#reproject-accumulate) stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. If display resolution motion vectors are provided, the reprojection step will use the full precision of the vectors, as we read the resource directly. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ------------------------------------|-----------------|--------------|------------------------|-----------|----------------------------------------| +| Exposure | Current frame | 1x1 | `R32_FLOAT` | Texture | A 1x1 texture containing the exposure value computed for the current frame. This resource is optional, and may be omitted if the [`FFX_FSR_ENABLE_AUTO_EXPOSURE`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L137) flag is set in the [`flags`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L162) field of the [`FfxFsr3UpscalerContextDescription`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L160) structure when creating the [`FfxFsr3UpscalerContext`](../../sdk/include/FidelityFX/host/ffx_fsr3upscaler.h#L238). | +| Dilated motion vectors | Current frame | Render | `R16G16_FLOAT` | Texture | A texture containing dilated motion vectors computed from the application's velocity buffer. The red and green channel contains the two-dimensional motion vectors in UV space. | +| Dilated reactive mask | Current frame | Render | `R8G8_UNORM` | Texture | Dilated reactive masks. | +| Upscaled buffer | Previous frame | Presentation | ``R16G16B16A16_FLOAT`` | Texture | The output buffer produced by the FSR algorithm running in the previous frame. Please note: This buffer is used internally by FSR, and is distinct from the presentation buffer which is derived from the output buffer, and has [RCAS](#robust-contrast-adpative-sharpening-rcas) applied. Please note: This texture is part of an array of two textures along with the Output buffer texture which is produced by the [Reproject & accumulate](#reproject-accumulate) stage. The selection of which texture in the array is used for input and output is swapped each frame. | +| Current luminance | Current frame | `Render * 0.5` | `R16_FLOAT` | Texture | A texture at 50% of render resolution texture which contains the luminance of the current frame. | +| Luminance history | Many frames | Render | `R8G8B8A8_UNORM` | Texture | A texture containing three frames of luminance history, as well as a stability factor encoded in the alpha channel. | +| Adjusted color buffer | Current frame | Render | `R16G16B16A16_FLOAT` | Texture | A texture containing the adjusted version of the application's color buffer. The tonemapping operator may not be the same as any tonemapping operator included in the application, and is instead a local, reversible operator used throughout FSR. This buffer is stored in YCoCg format. Alpha channel contains disocclusion mask.| +| Lock status | Previous frame | Presentation | `R16G16_FLOAT` | Texture | A mask which indicates not to perform color clipping on a pixel, can be thought of as a lock on the pixel to stop clipping removing the detail. For a more detailed description of the pixel locking mechanism please refer to the [Create locks](#create-locks) stage. Please note: This texture is part of an array of two textures along with the Lock status texture which is used as an output from this stage. The selection of which texture in the array is used for input and output is swapped each frame. | +| New lock mask | Current frame | Presentation | `R8_UNORM` | Texture | A mask which indicates whether or not to perform color rectification on a pixel, can be thought of as a lock on the pixel to stop rectification from removing the detail. Please note: This texture is part of an array of two textures along with the Lock status texture which is used as an input to this stage. The selection of which texture in the array is used for input and output is swapped each frame. The red channel contains the time remaining on the pixel lock, and the Y channel contains the luminance of the pixel at the time when the lock was created. The [Create locks](#create-locks) stage updates only a subset of this resource. | + + +

    Resource outputs

    + +This table contains the resources produced by the [Reproject & accumulate](#reproject-accumulate) stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ----------------------------|-----------------|--------------|-------------------------|-----------|----------------------------------------------| +| Upscaled buffer | Current frame | Presentation | `R16G16B16A16_FLOAT` | Texture | The output buffer produced by the [Reproject & accumulate](#reproject-accumulate) stage for the current frame. Please note: This buffer is used internally by FSR, and is distinct from the presentation buffer which is produced as an output from this stage after applying RCAS. Please note: This texture is part of an array of two textures along with the Output buffer texture which is consumed by the [Reproject & accumulate](#reproject-accumulate) stage. The selection of which texture in the array is used for input and output is swapped each frame. | +| Reprojected locks | Current frame | Render | `R16G16_FLOAT` | Texture | The reprojected lock status texture. | +| Luminance history | Many frames | Render | `R8G8B8A8_UNORM` | Texture | A texture containing three frames of luminance history, as well as a stability factor encoded in the alpha channel. | +| New lock mask | Next frame | Presentation | `R8_UNORM` | Texture | This is cleared for next frame. | + +

    Description

    + +The reproject & accumulate stage of FSR is the most complicated and expensive stage in the algorithm. It brings together the results from many of the previous algorithmic steps and accumulates the reprojected color data from the previous frame together with the upsampled color data from the current frame. Please note the description in this documentation is designed to give you an intuition for the steps involved in this stage and does not necessarily match the implementation precisely. + +The first step of the [Reproject & accumulate](#reproject-accumulate) stage is to assess each pixel for changes in its shading. If we are in a locked area, the luminance at the time the lock was created is compared to FSR's shading change threshold. In a non-locked area, both the current frame and historical luminance values are used to make this determination. Shading change determination is a key part of FSR's [Reproject & accumulate](#reproject-accumulate) stage, and feeds into many of the other parts of this stage. + +![alt text](media/super-resolution-temporal/upsample-with-lanczos.svg "A diagram showing upsampling of the current frame's input using Lanczos.") + +Next we must upsample the adjusted color. To perform upsampling, the adjusted color's pixel position serves as the center of a 5x5 Lanczos resampling kernel [[Lanczos]](#references). In the diagram above, you can see that the Lanczos functions are centered around the display resolution sample `S`. The point in each pixel - labelled `P` - denotes the render resolution jittered sample position for which we calculate the Lanczos weights. Looking above and to the right of the 5x5 pixel neighbourhood, you can see the `Lanczos(x, 2)` resampling kernel being applied to the render resolution samples in the 5x5 grid of pixels surrounding the pixel position. It is worth noting that while conceptually the neighbourhood is 5x5, in the implementation only a 4x4 is actually sampled, due to the zero weighted contributions of those pixels on the periphery of the neighbourhood. The implementation of the Lanczos kernel may vary by GPU product. On RDNA2-based products, we use a look-up-table (LUT) to encode the `sinc(x)` function. This helps to produce a more harmonious balance between ALU and memory in the [Reproject & accumulate](#reproject-accumulate) stage. As the upsample step has access to the 5x5 neighbourhood of pixels, it makes sense from an efficiency point of view to also calculate the YCoCg bounding box - which is used during color rectification - at this point. The diagram below shows a 2D YCo bounding box being constructed from a 3x3 neighbourhood around the current pixel, in reality the bounding box also has a third dimension for Cg. + +![alt text](media/super-resolution-temporal/calculate-bounding-box.svg "A diagram showing how a YCoCg bounding box is computed from the current frame's adjust color samples.") + +Reprojection is another key part of the [Reproject & accumulate](#reproject-accumulate) stage. To perform reprojection, the dilated motion vectors produced by the [Reconstruct & dilate](#reconstruct-and-dilate) stage are sampled and then applied to the output buffer from the previous frame's execution of FSR. The left of the diagram below shows two-dimensional motion vector **M** being applied to the current pixel position. On the right, you can see the `Lanczos(x, 2)` resampling kernel being applied to the 5x5 grid of pixels surrounding the translated pixel position. As with the upsampling step, the implementation of the Lanczos kernel may vary by GPU product. The result of the reprojection is a presentation resolution image which contains all the data from the previous frame that could be mapped into the current frame. However, it is not just the previous frame's output color that is reprojected. As FSR relies on a mechanism whereby each pixel may be locked to enhance its temporal stability, the locks must also be reprojected from the previous frame into the current frame. This is done in much the same way as the reprojection of the color data, but also combines the results of the shading change detection step we performed on the various luminance values, both current and historical. + +![alt text](media/super-resolution-temporal/reproject-mvs.svg "A diagram showing the 5x5 Lanczos sampling kernel applied to a pixel position determined by translating the current pixel position by the motion vectors.") + +It is now time to update our locks. The first task for update locks is to look for locks which were created during this frame's [Create locks](#create-locks) stage that are not reprojected, and instead have the luminance value of the current frame written to the green channel of the reprojected locks texture. All that remains then is to discern which locks are trustworthy for the current frame and pass those on to the color rectification step. The truthworthiness determination is done by comparing the luminance values within a neighbourhood of pixels in the current luminance texture. If the luminance separation between these values is large, then we should not trust the lock. + +With our lock updates applied and their trustworthiness determined, we can move on to color rectification which is the next crucial step of FSR's [Reproject & accumulate](#reproject-accumulate) stage. During this stage, a final color is determined from the pixel's historical data which will then be blended with the current frame's upsampled color in order to form the final accumulated super-resolution color. The determination of the final historical color and its contribution is chiefly controlled by two things: + +1. Reducing the influence of the historical samples for areas which are disoccluded. This is undertaken by modulating the color value by the disocclusion mask. +2. Reducing the influence of the historical samples (marked Sh in the diagram below) are far from the current frame color's bounding box (computed during the upsampling phase of the [Reproject & accumulate](#reproject-accumulate) stage). + +![alt text](media/super-resolution-temporal/clamp-to-box.svg "A diagram showing a historical color sample being clamped to the YCoCg bounding box for the current frame.") + +The final step of the [Reproject & accumulate](#reproject-accumulate) stage is to accumulate the current frame's upsampled color with the rectified historical color data. By default, FSR will typically blend the current frame with a relatively low linear interpolation factor - that is relatively little of the current frame will be included in the final output. However, this can be altered based on the contents of the application provided reactivity mask. See the [reactive mask](#reactive-mask) section for further details. + +

    Robust Contrast Adaptive Sharpening (RCAS)

    + +Robust Contrast Adaptive Sharpening (RCAS) was originally introduced in FidelityFX Super Resolution 1.0 as an additional sharpening pass to help generate additional clarity and sharpeness in the final upscaled image. RCAS is a derivative of the popular Contrast Adaptive Sharpening (CAS) algorithm, but with some key differences which make it more suitable for upscaling. Whereas CAS uses a simplified mechanism to convert local contrast into a variable amount of sharpness, conversely RCAS uses a more exact mechanism, solving for the maximum local sharpness possible before clipping. Additionally, RCAS also has a built-in process to limit the sharpening of what it detects as possible noise. Support for some scaling (which was included in CAS) is not included in RCAS, therefore it should run at presentation resolution. + +

    Resource inputs

    + +This table contains the resources consumed by the [Robust Contrast Adaptive Sharpening (RCAS)](#robust-contrast-adaptive-sharpening-rcas) stage. + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| ----------------------------|-----------------|--------------|-------------------------|-----------|----------------------------------------------| +| Upscaled buffer | Current frame | Presentation | `R16G16B16A16_FLOAT` | Texture | The output buffer produced by the [Reproject & Accumulate](#reproject-accumulate) stage for the current frame. Please note: This buffer is used internally by FSR, and is distinct from the presentation buffer which is produced as an output from this stage after applying RCAS. Please note: This texture is part of an array of two textures along with the Output buffer texture which is consumed by the [Reproject & Accumulate](#reproject-accumulate) stage. The selection of which texture in the array is used for input and output is swapped each frame. | + +

    Resource outputs

    + +> The temporal layer indicates which frame the data should be sourced from. 'Current frame' means that the data should be sourced from resources created for the frame that is to be presented next. 'Previous frame' indicates that the data should be sourced from resources which were created for the frame that has just presented. The resolution column indicates if the data should be at 'rendered' resolution or 'presentation' resolution. 'Rendered' resolution indicates that the resource should match the resolution at which the application is performing its rendering. Conversely, 'presentation' indicates that the resolution of the target should match that which is to be presented to the user. + +| Name | Temporal layer | Resolution | Format | Type | Notes | +| -----------------------------|-----------------|--------------|-------------------------|-----------|----------------------------------------------| +| Presentation buffer | Current frame | Presentation | Application specific | Texture | The presentation buffer produced by the completed FSR algorithm for the current frame. | + + +

    Description

    + +RCAS operates on data sampled using a 5-tap filter configured in a cross pattern. See the diagram below. + +![alt text](media/super-resolution-temporal/rcas-weights.svg "A diagram showing the weights RCAS applies to neighbourhood pixels.") + +With the samples retreived, RCAS then chooses the 'w' which results in no clipping, limits 'w', and multiplies by the 'sharp' amount. The solution above has issues with MSAA input as the steps along the gradient cause edge detection issues. To help stabilize the results of RCAS, it uses 4x the maximum and 4x the minimum (depending on equation) in place of the individual taps, as well as switching from 'm' to either the minimum or maximum (depending on side), to help in energy conservation. + +

    Building the sample

    + +To build the FSR sample, please follow the following instructions: + +1. Install the following tools: + - [CMake 3.16](https://cmake.org/download/) + - Install the "Desktop Development with C++" workload + - [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) + - [Windows 10 SDK 10.0.18362.0](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk) + - [Git 2.32.0](https://git-scm.com/downloads) +2. Generate the solutions: + ``` + > cd samples + > BuildAllNativeEffectsSolution.bat + ``` +3. Open the solution, compile and run. + +

    Limitations

    + +FSR requires a GPU with typed UAV load and R16G16B16A16_UNORM support. + +

    Version history

    + +| Version | Date | +| ---------------|-------------------| +| **3.0.1** | 2023-11-28 | + +Refer to changelog for more detail on versions. + + +

    References

    + +[**Akeley-06**] Kurt Akeley and Jonathan Su, "Minimum Triangle Separation for Correct Z-Buffer Occlusion", +[http://www.cs.cmu.edu/afs/cs/academic/class/15869-f11/www/readings/akeley06_triseparation.pdf](https://www.cs.cmu.edu/afs/cs/academic/class/15869-f11/www/readings/akeley06_triseparation.pdf) + +[**Lanczos**] Lanczos resampling, "Lanczos resampling", [https://en.wikipedia.org/wiki/Lanczos_resampling](https://en.wikipedia.org/wiki/Lanczos_resampling) + +[**Halton**] Halton sequence, "Halton sequence", [https://en.wikipedia.org/wiki/Halton_sequence](https://en.wikipedia.org/wiki/Halton_sequence) + +[**YCoCg**] YCoCg Color Space, [https://en.wikipedia.org/wiki/YCoCg](https://en.wikipedia.org/wiki/YCoCg) + +

    See also

    + +- [FidelityFX Super Resolution](../samples/super-resolution.md) +- [FidelityFX Single Pass Downsampler](../samples/single-pass-downsampler.md) +- [FidelityFX Naming guidelines](../getting-started/naming-guidelines.md) \ No newline at end of file diff --git a/docs/whats-new/index.md b/docs/whats-new/index.md index 0bc05f57..a1c89dfd 100644 --- a/docs/whats-new/index.md +++ b/docs/whats-new/index.md @@ -1,38 +1,7 @@ -

    What's new in the FidelityFX SDK 1.0?

    +

    What's new in this release of the FidelityFX SDK?

    -Welcome to the FidelityFX SDK. This inaugural version of the SDK features updated versions of all previously released FidelityFX samples ported to our new easy to use SDK format. Alongside those updated samples, we are pleased to announce the release of 3 new effects in the FidelityFX family. - -

    New effects

    - -

    FidelityFX Depth-of-Field

    - -The first release of a highly optimized, high-quality depth-of-field (DoF) effect which offers a familiar, artist-friendly, camera-based interface. This effect is capable of producing popular cinematic lens effects, such as bokeh. - -

    FidelityFX Blur

    - -While not an effect in its own right, this release of FFX SDK includes a library of common bluring operations which can either be used in isolation, or integrated into other shaders. Includes a specialized Gauassian blur at multiple kernel sizes. - -

    FidelityFX Lens

    - -Lens is another library of common operations, combining some of the most widely used lens effects such as chromatic aberration, film grain, and vignette into a single pass highly optimized effect. - -

    Updated effects

    - - All other effects in this release have had their code updated with our latest optimizations and fixes, and have been ported to our new backing graphics framework. - -

    Updated documentation

    - - With the introduction of the new FidelityFX SDK, all documentation for the constituent effects and samples has been refreshed and is available as easy to read Markdown. - - This change allows for a higher quality experience when exploring and reading the documentation, but also for suggested changes to be more easily submitted to our GitHub repository. - -

    Deprecated effects

    - -None. - -

    Deprecated components

    - -Cauldron 1.x is now deprecated and has been replaced with a re-architected Cauldron 2, which now lives directly in the SDK under the [`framework`](../../framework) folder. +Welcome to the FidelityFX SDK. This special branch of the FidelityFX SDK contains the initial open source release of FidelityFX Super Resolution 3.0, our next generation upscaling technology. It combines generation of interpolated frames with our temporal multi-frame upscaler, to produce high resolution frames from lower resolution inputs. +This branch is only for the initial open source release of FSR3, and so our other FidelityFX technologies are less well tested. Please use the 1.0 release on `main` if you'd like to do a production integration of our other technologies until the next full release of the SDK when we'll bring everything together. \ No newline at end of file diff --git a/framework/cauldron/framework/config/cauldronconfig.json b/framework/cauldron/framework/config/cauldronconfig.json index 0cc3d1df..3a9d4a7d 100644 --- a/framework/cauldron/framework/config/cauldronconfig.json +++ b/framework/cauldron/framework/config/cauldronconfig.json @@ -17,18 +17,30 @@ "Presentation": { "BackBufferCount": 3, - "Vsync": false, + "Vsync": true, "Fullscreen": false, "Width": 2560, "Height": 1440, - "Mode": "DISPLAYMODE_LDR" + "Mode": "DISPLAYMODE_HDR10_2084" }, "RenderResources": { + "LDR8Color": { + "Format": "RGBA8_UNORM", + "AllowUAV": true + }, "HDR11Color": { "Format": "RG11B10_FLOAT", "AllowUAV": true }, + "HDR10Color": { + "Format": "RGB10A2_UNORM", + "AllowUAV": true + }, + "HDR16Color": { + "Format": "RGBA16_FLOAT", + "AllowUAV": true + }, "DepthTarget": { "Format": "D32_FLOAT" } @@ -46,7 +58,7 @@ "UploadHeapSize": 419430400, "DynamicBufferPoolSize": 78643200, "GPUSamplerViewCount": 300, - "GPUResourceViewCount": 50000, + "GPUResourceViewCount": 60000, "CPUResourceViewCount": 50000, "CPURenderViewCount": 100, "CPUDepthViewCount": 100 diff --git a/framework/cauldron/framework/inc/core/components/cameracomponent.h b/framework/cauldron/framework/inc/core/components/cameracomponent.h index 64342798..114b5dbf 100644 --- a/framework/cauldron/framework/inc/core/components/cameracomponent.h +++ b/framework/cauldron/framework/inc/core/components/cameracomponent.h @@ -20,6 +20,7 @@ #include "core/component.h" #include "misc/math.h" +#include namespace cauldron { @@ -115,6 +116,8 @@ namespace cauldron std::wstring Name = L""; }; + typedef std::function CameraJitterCallback; + /** * @class CameraComponent * @@ -238,13 +241,9 @@ namespace cauldron const float GetFovY() const { return m_pData->Perspective.Yfov; } /** - * @brief Sets the camera's jitter values for the frame, and marks the camera dirty. + * @brief Sets the camera's jitter update callback to use. */ - void SetJitterValues(const Vec2& values) - { - m_jitterValues = values; - SetDirty(); - } + static void SetJitterCallbackFunc(CameraJitterCallback callbackFunc) { s_pSetJitterCallback = callbackFunc; } private: CameraComponent() = delete; @@ -292,6 +291,7 @@ namespace cauldron Vec2 m_jitterValues = Vec2(0, 0); Mat4 m_ProjJittered = Mat4::identity(); Mat4 m_PrevProjJittered = Mat4::identity(); + static CameraJitterCallback s_pSetJitterCallback; }; } // namespace cauldron diff --git a/framework/cauldron/framework/inc/core/framework.h b/framework/cauldron/framework/inc/core/framework.h index 1cdd966f..43e041a3 100644 --- a/framework/cauldron/framework/inc/core/framework.h +++ b/framework/cauldron/framework/inc/core/framework.h @@ -550,6 +550,10 @@ namespace cauldron */ bool UpscalerEnabled() const { return m_UpscalerEnabled; } + void EnableFrameInterpolation(bool enabled); + + bool FrameInterpolationEnabled() const { return m_FrameInterpolationEnabled; } + /** * @brief Overrides the default tonemapper. */ @@ -670,6 +674,8 @@ namespace cauldron void BeginFrame(); void EndFrame(); + void DeleteCommandListAsync(void* pInFlightGPUInfo); + // Members CauldronConfig m_Config = {}; std::wstring m_Name; @@ -681,6 +687,7 @@ namespace cauldron UpscalerState m_UpscalingState = UpscalerState::None; ResolutionUpdateFunc m_ResolutionUpdaterFn = nullptr; bool m_UpscalerEnabled = false; + bool m_FrameInterpolationEnabled = false; std::atomic_bool m_Running = false; FrameCaptureState m_RenderDocCaptureState = FrameCaptureState::None; FrameCaptureState m_PixCaptureState = FrameCaptureState::None; @@ -701,6 +708,9 @@ namespace cauldron uint64_t m_FrameID = -1; // Start at -1 so that the first frame is 0 (as we increment on begin frame) CommandList* m_pCmdListForFrame = nullptr; // Valid between Begin/EndFrame only + CommandList* m_pDeviceCmdListForFrame = nullptr; // Valid between Begin/EndFrame only + std::vector m_vecCmdListsForFrame; // Valid between Begin/EndFrame only + // Profiling/Perf data Profiler* m_pProfiler = nullptr; struct PerfStats diff --git a/framework/cauldron/framework/inc/core/uimanager.h b/framework/cauldron/framework/inc/core/uimanager.h index f056153a..4d97014d 100644 --- a/framework/cauldron/framework/inc/core/uimanager.h +++ b/framework/cauldron/framework/inc/core/uimanager.h @@ -126,6 +126,7 @@ namespace cauldron { std::string SectionName = ""; ///< Section name UISectionType SectionType = UISectionType::Framework; ///< UISectionType + bool defaultOpen = true; void AddText(const char* pText, bool* pEnabler = nullptr, bool sameLine = false) { @@ -279,6 +280,7 @@ namespace cauldron * @brief Gets all UISection elements that make up the general layout tab. */ const std::vector& GetGeneralLayout() const { return m_UIGeneralLayout; } + std::vector& GetGeneralLayout() { return m_UIGeneralLayout; } private: diff --git a/framework/cauldron/framework/inc/render/commandlist.h b/framework/cauldron/framework/inc/render/commandlist.h index a07d3f3a..7d040f3a 100644 --- a/framework/cauldron/framework/inc/render/commandlist.h +++ b/framework/cauldron/framework/inc/render/commandlist.h @@ -129,7 +129,7 @@ namespace cauldron /** * @brief Destruction. */ - ~UploadContext(); + virtual ~UploadContext(); /** * @brief Executes batched GPU resource copies. diff --git a/framework/cauldron/framework/inc/render/swapchain.h b/framework/cauldron/framework/inc/render/swapchain.h index 69ae6b6d..6b91baaa 100644 --- a/framework/cauldron/framework/inc/render/swapchain.h +++ b/framework/cauldron/framework/inc/render/swapchain.h @@ -115,6 +115,14 @@ namespace cauldron * @brief Executes device presentation of the swapchain. */ virtual void Present() = 0; + virtual void GetLastPresentCount(UINT* pLastPresentCount) + { + *pLastPresentCount = 0; + } + virtual void GetRefreshRate(double* outRefreshRate) + { + *outRefreshRate = 0.0; + } /** * @brief Creates a screenshot of the current swap chain. diff --git a/framework/cauldron/framework/inc/render/texture.h b/framework/cauldron/framework/inc/render/texture.h index 95e0724b..07662148 100644 --- a/framework/cauldron/framework/inc/render/texture.h +++ b/framework/cauldron/framework/inc/render/texture.h @@ -200,7 +200,11 @@ namespace cauldron protected: Texture(const TextureDesc* pDesc, ResourceState initialState, ResizeFunction fn); + + public: Texture(const TextureDesc* pDesc, GPUResource* pResource); + + protected: Texture() = delete; void Recreate(); diff --git a/framework/cauldron/framework/inc/shaders/copytexture.hlsl b/framework/cauldron/framework/inc/shaders/copytexture.hlsl index 06b599f8..edbe9dd2 100644 --- a/framework/cauldron/framework/inc/shaders/copytexture.hlsl +++ b/framework/cauldron/framework/inc/shaders/copytexture.hlsl @@ -20,35 +20,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "shadercommon.h" -#include "transferFunction.h" #include "fullscreen.hlsl" -cbuffer CBSwapchain : register(b0) -{ - SwapchainCBData swapchainCBData; -} - Texture2D TextureImg : register(t0); float4 CopyTextureToSwapChainPS(VertexOut VertexIn) : SV_Target { float4 color = TextureImg[VertexIn.PosOut.xy]; - - switch (swapchainCBData.displayMode) - { - case DisplayMode::DISPLAYMODE_LDR: - case DisplayMode::DISPLAYMODE_HDR10_SCRGB: - case DisplayMode::DISPLAYMODE_FSHDR_SCRGB: - break; - - case DisplayMode::DISPLAYMODE_HDR10_2084: - case DisplayMode::DISPLAYMODE_FSHDR_2084: - // Apply ST2084 curve - color.xyz = ApplyPQ(color.xyz); - break; - } - return color; } diff --git a/framework/cauldron/framework/inc/shaders/fpslimiter/fpslimiter.hlsl b/framework/cauldron/framework/inc/shaders/fpslimiter/fpslimiter.hlsl index 4e2f034c..4822c843 100644 --- a/framework/cauldron/framework/inc/shaders/fpslimiter/fpslimiter.hlsl +++ b/framework/cauldron/framework/inc/shaders/fpslimiter/fpslimiter.hlsl @@ -1,3 +1,25 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright © 2023 Advanced Micro Devices, Inc. +// +// 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. + RWStructuredBuffer DataBuffer : register(u0); cbuffer cb : register(b0) diff --git a/framework/cauldron/framework/inc/shaders/shadercommon.h b/framework/cauldron/framework/inc/shaders/shadercommon.h index c1206bf3..4a29bdae 100644 --- a/framework/cauldron/framework/inc/shaders/shadercommon.h +++ b/framework/cauldron/framework/inc/shaders/shadercommon.h @@ -127,11 +127,6 @@ enum class DisplayMode DISPLAYMODE_FSHDR_SCRGB }; -struct SwapchainCBData -{ - DisplayMode displayMode; -}; - #if !__cplusplus struct MaterialInfo diff --git a/framework/cauldron/framework/inc/shaders/tonemapping/tonemapping.hlsl b/framework/cauldron/framework/inc/shaders/tonemapping/tonemapping.hlsl index cabf7e49..9c850f38 100644 --- a/framework/cauldron/framework/inc/shaders/tonemapping/tonemapping.hlsl +++ b/framework/cauldron/framework/inc/shaders/tonemapping/tonemapping.hlsl @@ -19,6 +19,7 @@ #include "tonemappers.hlsl" #include "tonemappercommon.h" +#include "transferFunction.h" //-------------------------------------------------------------------------------------- // Texture definitions @@ -43,8 +44,12 @@ void MainCS(uint3 dtID : SV_DispatchThreadID) switch (MonitorDisplayMode) { case DisplayMode::DISPLAYMODE_LDR: + color.xyz = ApplyGamma(color.xyz); + break; + case DisplayMode::DISPLAYMODE_HDR10_SCRGB: case DisplayMode::DISPLAYMODE_FSHDR_SCRGB: + color.xyz = ApplyscRGBScale(color.xyz, 0.0f, DisplayMaxLuminance / 80.0f); break; case DisplayMode::DISPLAYMODE_HDR10_2084: @@ -61,6 +66,7 @@ void MainCS(uint3 dtID : SV_DispatchThreadID) // 1 * ((1000 / 80) * (80 / 10000)) = 1 / 10 = 0.1 // For simplcity we are getting rid of conversion to per 80 nit division factor and directly dividing max luminance set by 10000 nits color.xyz *= (DisplayMaxLuminance / 10000.0f); + color.xyz = ApplyPQ(color.xyz); break; } diff --git a/framework/cauldron/framework/inc/shaders/transferFunction.h b/framework/cauldron/framework/inc/shaders/transferFunction.h index e39e5f84..d755f388 100644 --- a/framework/cauldron/framework/inc/shaders/transferFunction.h +++ b/framework/cauldron/framework/inc/shaders/transferFunction.h @@ -22,7 +22,7 @@ float3 ApplyGamma(float3 color) { - color.xyz = pow(color.xyz, 1.0f / 2.2f); + color = pow(color, 1.0f / 2.2f); return color; } diff --git a/framework/cauldron/framework/inc/shaders/ui.hlsl b/framework/cauldron/framework/inc/shaders/ui.hlsl index a90fa953..c4c7993a 100644 --- a/framework/cauldron/framework/inc/shaders/ui.hlsl +++ b/framework/cauldron/framework/inc/shaders/ui.hlsl @@ -23,6 +23,7 @@ #include "uicommon.h" #include "fullscreen.hlsl" #include "upscaler.h" +#include "transferFunction.h" //-------------------------------------------------------------------------------------- // Input structures @@ -206,8 +207,12 @@ float4 uiPS(PS_INPUT input) : SV_Target switch (HDRCB.MonitorDisplayMode) { case DisplayMode::DISPLAYMODE_LDR: + out_col.xyz = ApplyGamma(out_col.xyz); + break; + case DisplayMode::DISPLAYMODE_HDR10_SCRGB: case DisplayMode::DISPLAYMODE_FSHDR_SCRGB: + out_col.xyz = ApplyscRGBScale(out_col.xyz, 0.0f, HDRCB.DisplayMaxLuminance / 80.0f); break; case DisplayMode::DISPLAYMODE_HDR10_2084: @@ -224,6 +229,7 @@ float4 uiPS(PS_INPUT input) : SV_Target // 1 * ((1000 / 80) * (80 / 10000)) = 1 / 10 = 0.1 // For simplcity we are getting rid of conversion to per 80 nit division factor and directly dividing max luminance set by 10000 nits col *= (HDRCB.DisplayMaxLuminance / 10000.0f); + col = ApplyPQ(col); out_col = float4(col, out_col.a); break; } diff --git a/framework/cauldron/framework/src/CMakeLists.txt b/framework/cauldron/framework/src/CMakeLists.txt index 6a6cabc0..47c7e05e 100644 --- a/framework/cauldron/framework/src/CMakeLists.txt +++ b/framework/cauldron/framework/src/CMakeLists.txt @@ -113,16 +113,17 @@ copyCommand("${shaderfiles}" ${SHADER_OUTPUT}) set(cauldronconfigfiles ${CMAKE_CURRENT_SOURCE_DIR}/../config/cauldronconfig.json) copyCommand("${cauldronconfigfiles}" ${CONFIG_OUTPUT}) +# CUSTOM_CHANGES_TO_FSR3 Build FSR3 DLL with RelWithDebInfo configuration add_library(Framework STATIC ${imguifiles} ${miscfiles} ${corefiles} ${cauldronconfigfiles} ${corefiles_components} ${corefiles_loaders} ${corefiles_windows} ${renderfiles} ${renderfiles_win} ${rendermodules_swapchain} ${rendermodules_ui} ${rendermodules_tonemapping} ${rendermodules_fpslimiter} ${shaderfiles} $<$,$>: ${miscfiles_vk} ${renderfiles_vk}> - $<$,$>: ${miscfiles_dx12} ${renderfiles_dx12} ${memoryallocator_dx12}>) + $<$,$,$>: ${miscfiles_dx12} ${renderfiles_dx12} ${memoryallocator_dx12}>) target_compile_definitions(Framework PRIVATE RenderModuleRoot="${RENDERMODULE_ROOT}") target_link_libraries (Framework stb imgui $<$,$>: amd_acs dxc "Vulkan::Vulkan" Xinput Shcore> - $<$,$>: amd_acs dxc DXGI amd_ags memoryallocator + $<$,$,$>: amd_acs dxc DXGI amd_ags memoryallocator D3D12 pixlib agilitysdk dxheaders Xinput Shcore>) source_group("Config" FILES ${cauldronconfigfiles}) diff --git a/framework/cauldron/framework/src/core/components/cameracomponent.cpp b/framework/cauldron/framework/src/core/components/cameracomponent.cpp index 54eb529d..ce222d81 100644 --- a/framework/cauldron/framework/src/core/components/cameracomponent.cpp +++ b/framework/cauldron/framework/src/core/components/cameracomponent.cpp @@ -69,6 +69,8 @@ namespace cauldron s_pComponentManager = nullptr; } + CameraJitterCallback CameraComponent::s_pSetJitterCallback = nullptr; + CameraComponent::CameraComponent(Entity* pOwner, ComponentData* pData, CameraComponentMgr* pManager) : Component(pOwner, pData, pManager), m_pData(reinterpret_cast(pData)), @@ -317,6 +319,22 @@ namespace cauldron } } + // Update camera jitter if we need it + if (CameraComponent::s_pSetJitterCallback) + { + s_pSetJitterCallback(m_jitterValues); + m_Dirty = true; + } + else + { + // Reset jitter if disabled + if (m_jitterValues.getX() != 0.f || m_jitterValues.getY() != 0.f) + { + m_jitterValues = Vec2(0.f, 0.f); + m_Dirty = true; + } + } + LookAt(eyePos, lookAt); UpdateMatrices(); } diff --git a/framework/cauldron/framework/src/core/framework.cpp b/framework/cauldron/framework/src/core/framework.cpp index 2ff42c0a..bcf306d0 100644 --- a/framework/cauldron/framework/src/core/framework.cpp +++ b/framework/cauldron/framework/src/core/framework.cpp @@ -1026,6 +1026,11 @@ namespace cauldron ResizeEvent(); } + void Framework::EnableFrameInterpolation(bool enabled) + { + m_FrameInterpolationEnabled = true; + } + void Framework::ResizeEvent() { // Flush everything before resizing resources (can't have anything in the pipes) @@ -1493,15 +1498,27 @@ namespace cauldron // Call all registered render modules { + CloseCmdList(m_pCmdListForFrame); + m_vecCmdListsForFrame.push_back(m_pCmdListForFrame); + CPUScopedProfileCapture marker(L"RM Executes"); for (auto& callback : m_ExecutionCallbacks) { if (callback.second.first->ModuleEnabled() && callback.second.first->ModuleReady()) + { + m_pCmdListForFrame = m_pDevice->CreateCommandList(L"RenderModuleGraphicsCmdList", CommandQueue::Graphics); + SetAllResourceViewHeaps(m_pCmdListForFrame); + callback.second.second(m_DeltaTime, m_pCmdListForFrame); + CloseCmdList(m_pCmdListForFrame); + m_vecCmdListsForFrame.push_back(m_pCmdListForFrame); + } } } } + m_pCmdListForFrame = m_pDeviceCmdListForFrame; + // EndFrame will close and submit all active command lists and // kick off the work for execution before performing a Present() EndFrame(); @@ -1610,7 +1627,11 @@ namespace cauldron m_pSwapChain->WaitForSwapChain(); // Refresh the command list pool - m_pCmdListForFrame = m_pDevice->BeginFrame(); + m_pDeviceCmdListForFrame = m_pDevice->BeginFrame(); + + // create a commandlist to use + m_pCmdListForFrame = m_pDevice->CreateCommandList(L"EndFrameGraphicsCmdList", CommandQueue::Graphics); + SetAllResourceViewHeaps(m_pCmdListForFrame); // Start GPU counters now that we have a cmd list m_pProfiler->BeginGPUFrame(m_pCmdListForFrame); @@ -1651,6 +1672,32 @@ namespace cauldron } } + struct GPUExecutionPacket + { + std::vector CmdLists = {}; + uint64_t CompletionID = 0; + + GPUExecutionPacket(std::vector& cmdLists, uint64_t completionID) + : CmdLists(std::move(cmdLists)) + , CompletionID(completionID) + { + } + GPUExecutionPacket() = delete; + }; + void Framework::DeleteCommandListAsync(void* pInFlightGPUInfo) + { + GPUExecutionPacket* pInflightPacket = static_cast(pInFlightGPUInfo); + + // Wait until the command lists are processed + m_pDevice->WaitOnQueue(pInflightPacket->CompletionID, CommandQueue::Graphics); + + // Delete them to release the allocators + for (auto cmdListIter = pInflightPacket->CmdLists.begin(); cmdListIter != pInflightPacket->CmdLists.end(); ++cmdListIter) + delete *cmdListIter; + pInflightPacket->CmdLists.clear(); + delete pInflightPacket; + } + // Handles all end of frame logic (like present) void Framework::EndFrame() { @@ -1660,11 +1707,20 @@ namespace cauldron Barrier presentBarrier = Barrier::Transition(m_pSwapChain->GetBackBufferRT()->GetCurrentResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::Present); ResourceBarrier(m_pCmdListForFrame, 1, &presentBarrier); + { + // Asynchronously delete the active command list in the background once it's cleared the graphics queue + uint64_t signalValue = m_pDevice->ExecuteCommandLists(m_vecCmdListsForFrame, CommandQueue::Graphics, false); + cauldron::GPUExecutionPacket* pInflightPacket = new GPUExecutionPacket(m_vecCmdListsForFrame, signalValue); + GetTaskManager()->AddTask(Task(std::bind(&Framework::DeleteCommandListAsync, this, std::placeholders::_1), reinterpret_cast(pInflightPacket))); + } + // End the frame of the profiler m_pProfiler->EndFrame(m_pCmdListForFrame); // Can't be referenced until next time BeginFrame is called + m_pDeviceCmdListForFrame = nullptr; m_pCmdListForFrame = nullptr; + m_vecCmdListsForFrame.clear(); // Closes all command lists m_pDevice->EndFrame(); diff --git a/framework/cauldron/framework/src/core/win/uibackend_win.cpp b/framework/cauldron/framework/src/core/win/uibackend_win.cpp index efb87a64..3b566091 100644 --- a/framework/cauldron/framework/src/core/win/uibackend_win.cpp +++ b/framework/cauldron/framework/src/core/win/uibackend_win.cpp @@ -30,6 +30,7 @@ #include "render/dynamicresourcepool.h" #include "render/rendermodules/ui/uirendermodule.h" #include "render/profiler.h" +#include "render/swapchain.h" // For windows DPI scaling fetching #include @@ -309,7 +310,42 @@ namespace cauldron ImGui::Text("GPU : %S", pDevice->GetDeviceName()); ImGui::Text("Driver : %S", pDevice->GetDriverVersion()); ImGui::Text("CPU : %S", pFwrk->GetCPUName()); - ImGui::Text("FPS : %d (%.2f ms)", fps, frameTimeMilliSeconds); + + if (GetFramework()->FrameInterpolationEnabled()) + { + static std::chrono::nanoseconds cpuTimestamp = cpuTimings[0].EndTime; + static uint64_t renderFrames = GetFramework()->GetFrameID(); + static uint64_t displayFrames = 0; // GetFramework()->GetSwapChain()->GetLastPresentCount(); + static uint64_t renderFPS = 0; + static uint64_t displayFPS = 0; + if ((cpuTimings[0].EndTime - cpuTimestamp).count() > 1000000000) + { + // minus one to exclude the current frame from measurement, + // as we're on the next frame AFTER the 1 second we wanted to measure + renderFPS = GetFramework()->GetFrameID() - renderFrames - 1; + renderFrames = GetFramework()->GetFrameID(); + + UINT lastPresentCount = 0; + GetFramework()->GetSwapChain()->GetLastPresentCount(&lastPresentCount); + displayFPS = lastPresentCount - displayFrames - 1; + displayFrames = lastPresentCount; + + cpuTimestamp = cpuTimings[0].EndTime; + } + + double monitorRefreshRate = 0.0; + GetFramework()->GetSwapChain()->GetRefreshRate(&monitorRefreshRate); + + ImGui::Text("Render FPS : %d", renderFPS); + ImGui::Text("Display FPS : %d", displayFPS); + ImGui::Text("RefreshRate : %.1f", monitorRefreshRate); + ImGui::Text("CPU time : %.2f ms", frameTimeNanoSecondsCPU / 1000000.f); + ImGui::Text("GPU time : %.2f ms", frameTimeNanoSecondsGPU / 1000000.f); + } + else + { + ImGui::Text("FPS : %d (%.2f ms)", fps, frameTimeMilliSeconds); + } if (ImGui::CollapsingHeader("Timing Information", ImGuiTreeNodeFlags_DefaultOpen)) { @@ -506,7 +542,7 @@ namespace cauldron const std::vector& sections = GetUIManager()->GetGeneralLayout(); for (auto& sectionIter = sections.begin(); sectionIter != sections.end(); ++sectionIter) { - if (ImGui::CollapsingHeader(sectionIter->SectionName.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) + if (ImGui::CollapsingHeader(sectionIter->SectionName.c_str(), sectionIter->defaultOpen ? ImGuiTreeNodeFlags_DefaultOpen : ImGuiTreeNodeFlags_None)) { // Iterate through all elements for (auto& elementIter = sectionIter->SectionElements.begin(); elementIter != sectionIter->SectionElements.end(); ++elementIter) diff --git a/framework/cauldron/framework/src/render/dx12/commandlist_dx12.cpp b/framework/cauldron/framework/src/render/dx12/commandlist_dx12.cpp index 902ed5d4..ec6ed95b 100644 --- a/framework/cauldron/framework/src/render/dx12/commandlist_dx12.cpp +++ b/framework/cauldron/framework/src/render/dx12/commandlist_dx12.cpp @@ -56,7 +56,8 @@ namespace cauldron CommandListInternal::~CommandListInternal() { // Release command allocator on delete - GetDevice()->GetImpl()->ReleaseCommandAllocator(this); + if (m_pCmdAllocator) + GetDevice()->GetImpl()->ReleaseCommandAllocator(this); } ////////////////////////////////////////////////////////////////////////// @@ -186,7 +187,13 @@ namespace cauldron void ClearUAVFloat(CommandList* pCmdList, const GPUResource* pResource, const ResourceViewInfo* pGPUView, const ResourceViewInfo* pCPUView, float clearColor[4]) { - pCmdList->GetImpl()->DX12CmdList()->ClearUnorderedAccessViewFloat(pGPUView->GetImpl()->hGPUHandle, pCPUView->GetImpl()->hCPUHandle, const_cast(pResource)->GetImpl()->DX12Resource(), clearColor, 0, nullptr); + uint32_t clearColorAsUint[4]; + clearColorAsUint[0] = reinterpret_cast (clearColor[0]); + clearColorAsUint[1] = reinterpret_cast (clearColor[1]); + clearColorAsUint[2] = reinterpret_cast (clearColor[2]); + clearColorAsUint[3] = reinterpret_cast (clearColor[3]); + + pCmdList->GetImpl()->DX12CmdList()->ClearUnorderedAccessViewUint(pGPUView->GetImpl()->hGPUHandle, pCPUView->GetImpl()->hCPUHandle, const_cast(pResource)->GetImpl()->DX12Resource(), clearColorAsUint, 0, nullptr); } void SetPipelineState(CommandList* pCmdList, PipelineObject* pPipeline) diff --git a/framework/cauldron/framework/src/render/dx12/commandlist_dx12.h b/framework/cauldron/framework/src/render/dx12/commandlist_dx12.h index 233d677b..f6fef954 100644 --- a/framework/cauldron/framework/src/render/dx12/commandlist_dx12.h +++ b/framework/cauldron/framework/src/render/dx12/commandlist_dx12.h @@ -48,6 +48,7 @@ namespace cauldron private: friend class CommandList; + friend class FSR3RenderModule; CommandListInternal(const wchar_t* Name, Microsoft::WRL::ComPtr pCmdList, Microsoft::WRL::ComPtr pCmdAllocator, CommandQueue queueType); CommandListInternal() = delete; diff --git a/framework/cauldron/framework/src/render/dx12/device_dx12.cpp b/framework/cauldron/framework/src/render/dx12/device_dx12.cpp index fa7d9383..6782b972 100644 --- a/framework/cauldron/framework/src/render/dx12/device_dx12.cpp +++ b/framework/cauldron/framework/src/render/dx12/device_dx12.cpp @@ -263,7 +263,7 @@ namespace cauldron void DeviceInternal::InitQueueSyncPrim(CommandQueue queueType, QueueSyncPrimitive& queueSyncPrim, const wchar_t* queueName) { D3D12_COMMAND_LIST_TYPE commandListType = QueueTypeToCommandListType(queueType); - D3D12_COMMAND_QUEUE_DESC queueDesc = {commandListType, D3D12_COMMAND_QUEUE_PRIORITY_HIGH, D3D12_COMMAND_QUEUE_FLAG_NONE, 0}; + D3D12_COMMAND_QUEUE_DESC queueDesc = {commandListType, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, D3D12_COMMAND_QUEUE_FLAG_NONE, 0}; // Create the queue int32_t queueIndex = static_cast(queueType); @@ -300,9 +300,8 @@ namespace cauldron { if (pSwapChain->GetImpl()->m_VSyncEnabled) CauldronThrowOnFail(pSwapChain->GetImpl()->m_pSwapChain->Present(1, 0)); - else - CauldronThrowOnFail(pSwapChain->GetImpl()->m_pSwapChain->Present(0, pSwapChain->GetImpl()->m_TearingSupported ? DXGI_PRESENT_ALLOW_TEARING : 0)); + CauldronThrowOnFail(pSwapChain->GetImpl()->m_pSwapChain->Present(0, DXGI_PRESENT_ALLOW_TEARING)); uint32_t queueID = static_cast(pSwapChain->GetImpl()->m_CreationQueue); uint64_t signalValue; diff --git a/framework/cauldron/framework/src/render/dx12/gpuresource_dx12.h b/framework/cauldron/framework/src/render/dx12/gpuresource_dx12.h index ecec1667..207ea41c 100644 --- a/framework/cauldron/framework/src/render/dx12/gpuresource_dx12.h +++ b/framework/cauldron/framework/src/render/dx12/gpuresource_dx12.h @@ -61,6 +61,7 @@ namespace cauldron private: friend class GPUResource; + friend class FSR3RenderModule; GPUResourceInternal() = delete; GPUResourceInternal(ID3D12Resource* pResource, const wchar_t* resourceName, ResourceState initialState, bool resizable = false); GPUResourceInternal(D3D12_RESOURCE_DESC& resourceDesc, D3D12_HEAP_TYPE heapType, ResourceState initialState, const wchar_t* resourceName, void* pOwner, bool resizable = false); diff --git a/framework/cauldron/framework/src/render/dx12/resourceview_dx12.cpp b/framework/cauldron/framework/src/render/dx12/resourceview_dx12.cpp index 67e47644..9a63e451 100644 --- a/framework/cauldron/framework/src/render/dx12/resourceview_dx12.cpp +++ b/framework/cauldron/framework/src/render/dx12/resourceview_dx12.cpp @@ -198,6 +198,9 @@ namespace cauldron { D3D12_RESOURCE_DESC resourceDesc = pResource->GetImpl()->DX12Desc(); + // use the format from the TextureDesc to allow overriding it, e.g. for reading SRGB surfaces + resourceDesc.Format = GetDXGIFormat(textureDesc.Format); + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; // Override TYPELESS resources to prevent device removal diff --git a/framework/cauldron/framework/src/render/dx12/swapchain_dx12.cpp b/framework/cauldron/framework/src/render/dx12/swapchain_dx12.cpp index 6fb26a16..b7d36d01 100644 --- a/framework/cauldron/framework/src/render/dx12/swapchain_dx12.cpp +++ b/framework/cauldron/framework/src/render/dx12/swapchain_dx12.cpp @@ -21,6 +21,7 @@ // _DX12 define implies windows #include "core/win/framework_win.h" +#include "core/uimanager.h" #include "misc/assert.h" #include "render/dx12/commandlist_dx12.h" @@ -105,6 +106,20 @@ namespace cauldron // Create render targets backed by the swap chain buffers CreateSwapChainRenderTargets(); + + // Register UI or defer until after init is done. + std::function addUiTaskFunc = [this](void*) { + UISection section{"SwapChain"}; + section.AddCheckBox("Vsync", &m_VSyncEnabled); + GetUIManager()->RegisterUIElements(section); + }; + if (GetUIManager()) + addUiTaskFunc(nullptr); + else + { + Task addUiTask(addUiTaskFunc); + GetFramework()->AddContentCreationTask(addUiTask); + } } SwapChainInternal::~SwapChainInternal() @@ -350,7 +365,7 @@ namespace cauldron resourceArray.push_back(GPUResource::CreateGPUResource(name.c_str(), nullptr, ResourceState::Present, &initParams, true)); } - TextureDesc rtDesc = TextureDesc::Tex2D(SwapChain::s_SwapChainRTName, ToGamma(m_SwapChainFormat), m_SwapChainDesc.Width, m_SwapChainDesc.Height, 1, 0, ResourceFlags::AllowRenderTarget); + TextureDesc rtDesc = TextureDesc::Tex2D(SwapChain::s_SwapChainRTName, m_SwapChainFormat, m_SwapChainDesc.Width, m_SwapChainDesc.Height, 1, 0, ResourceFlags::AllowRenderTarget); if (m_pRenderTarget == nullptr) m_pRenderTarget = new SwapChainRenderTarget(&rtDesc, resourceArray); else @@ -444,6 +459,147 @@ namespace cauldron } } + #include + #pragma comment(lib, "Dwmapi.lib") + + RECT clientRectToScreenSpace(HWND const hWnd) + { + RECT rc{0}; + if (GetClientRect(hWnd, &rc) == TRUE) + { + if (MapWindowPoints(hWnd, nullptr, reinterpret_cast(&rc), 2) == 0) + { + } + } + + return rc; + } + + bool isDirectFlip(IDXGISwapChain* swapChain, RECT monitorExtents) + { + bool bResult = false; + + IDXGIOutput* dxgiOutput = nullptr; + if (SUCCEEDED(swapChain->GetContainingOutput(&dxgiOutput))) + { + IDXGIOutput6* dxgiOutput6 = nullptr; + if (SUCCEEDED(dxgiOutput->QueryInterface(IID_PPV_ARGS(&dxgiOutput6)))) + { + UINT hwSupportFlags = 0; + if (SUCCEEDED(dxgiOutput6->CheckHardwareCompositionSupport(&hwSupportFlags))) + { + // check support in fullscreen mode + if (hwSupportFlags & DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_FULLSCREEN) + { + DXGI_SWAP_CHAIN_DESC desc{}; + if (SUCCEEDED(swapChain->GetDesc(&desc))) + { + RECT windowExtents = clientRectToScreenSpace(desc.OutputWindow); + bResult |= memcmp(&windowExtents, &monitorExtents, sizeof(windowExtents)) == 0; + } + } + + // check support in windowed mode + if (hwSupportFlags & DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_WINDOWED) + { + bResult |= true; + } + } + + dxgiOutput6->Release(); + } + + dxgiOutput->Release(); + } + return bResult; + } + void SwapChainInternal::GetRefreshRate(double* outRefreshRate) + { + double dwsRate = 1000.0; + *outRefreshRate = 1000.0; + + bool bIsPotentialDirectFlip = false; + IDXGIOutput* dxgiOutput = nullptr; + BOOL isFullscreen = false; + m_pSwapChain->GetFullscreenState(&isFullscreen, &dxgiOutput); + + if (!isFullscreen) + { + DWM_TIMING_INFO compositionTimingInfo{}; + compositionTimingInfo.cbSize = sizeof(DWM_TIMING_INFO); + double monitorRefreshRate = 0.0f; + HRESULT hr = DwmGetCompositionTimingInfo(nullptr, &compositionTimingInfo); + if (SUCCEEDED(hr)) + { + dwsRate = double(compositionTimingInfo.rateRefresh.uiNumerator) / compositionTimingInfo.rateRefresh.uiDenominator; + } + m_pSwapChain->GetContainingOutput(&dxgiOutput); + } + + // if FS this should be the monitor used for FS, in windowed the window containing the main portion of the output + if (dxgiOutput) + { + IDXGIOutput1* dxgiOutput1 = nullptr; + if (SUCCEEDED(dxgiOutput->QueryInterface(IID_PPV_ARGS(&dxgiOutput1)))) + { + DXGI_OUTPUT_DESC outputDes{}; + if (SUCCEEDED(dxgiOutput->GetDesc(&outputDes))) + { + MONITORINFOEXW info{}; + info.cbSize = sizeof(info); + if (GetMonitorInfoW(outputDes.Monitor, &info) != 0) + { + bIsPotentialDirectFlip = isDirectFlip(m_pSwapChain.Get(), info.rcMonitor); + + UINT32 numPathArrayElements, numModeInfoArrayElements; + if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements, &numModeInfoArrayElements) == ERROR_SUCCESS) + { + std::vector pathArray(numPathArrayElements); + std::vector modeInfoArray(numModeInfoArrayElements); + if (QueryDisplayConfig( + QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements, pathArray.data(), &numModeInfoArrayElements, modeInfoArray.data(), nullptr) == + ERROR_SUCCESS) + { + bool rateFound = false; + // iterate through all the paths until find the exact source to match + for (size_t i = 0; i < pathArray.size() && !rateFound; i++) + { + const DISPLAYCONFIG_PATH_INFO& path = pathArray[i]; + DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName; + sourceName.header = { + DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME, sizeof(sourceName), path.sourceInfo.adapterId, path.sourceInfo.id}; + + if (DisplayConfigGetDeviceInfo(&sourceName.header) == ERROR_SUCCESS) + { + if (wcscmp(info.szDevice, sourceName.viewGdiDeviceName) == 0) + { + const DISPLAYCONFIG_RATIONAL& rate = path.targetInfo.refreshRate; + if (rate.Denominator > 0) + { + double refrate = (double)rate.Numerator / (double)rate.Denominator; + *outRefreshRate = refrate; + + // we found a valid rate? + rateFound = (refrate > 0.0); + } + } + } + } + } + } + } + } + dxgiOutput1->Release(); + } + dxgiOutput->Release(); + + if (!bIsPotentialDirectFlip) + { + *outRefreshRate = std::min(*outRefreshRate, dwsRate); + } + } + } + } // namespace cauldron #endif // #if defined(_DX12) diff --git a/framework/cauldron/framework/src/render/dx12/swapchain_dx12.h b/framework/cauldron/framework/src/render/dx12/swapchain_dx12.h index 7a1baffc..e5c9fcbd 100644 --- a/framework/cauldron/framework/src/render/dx12/swapchain_dx12.h +++ b/framework/cauldron/framework/src/render/dx12/swapchain_dx12.h @@ -33,6 +33,32 @@ namespace cauldron const IDXGISwapChain4* DX12SwapChain() const { return m_pSwapChain.Get(); } IDXGISwapChain4* DX12SwapChain() { return m_pSwapChain.Get(); } + void SetDXGISwapChain(IDXGISwapChain4* pDxgiSwapChain) + { + if (pDxgiSwapChain) + { + m_pSwapChain = pDxgiSwapChain; + + CreateSwapChainRenderTargets(); + } + else + { + DestroySwapChainRenderTargets(); + + // delete m_pRenderTarget; + + // delete m_pSwapChainRTV; + + m_pSwapChain = pDxgiSwapChain; + } + } + + virtual void GetLastPresentCount(UINT* pLastPresentCount) + { + m_pSwapChain->GetLastPresentCount(pLastPresentCount); + } + virtual void GetRefreshRate(double* outRefreshRate); + void OnResize(uint32_t width, uint32_t height) override; void WaitForSwapChain() override; void Present() override; diff --git a/framework/cauldron/framework/src/render/rendermodules/fpslimiter/fpslimiterrendermodule.cpp b/framework/cauldron/framework/src/render/rendermodules/fpslimiter/fpslimiterrendermodule.cpp index d8b341cf..128a9f59 100644 --- a/framework/cauldron/framework/src/render/rendermodules/fpslimiter/fpslimiterrendermodule.cpp +++ b/framework/cauldron/framework/src/render/rendermodules/fpslimiter/fpslimiterrendermodule.cpp @@ -27,9 +27,10 @@ #include "render/rootsignature.h" #include -#include +#include using namespace cauldron; +#define USE_BUSY_WAIT 1 // Used in a few places static uint32_t sSeed; @@ -52,14 +53,15 @@ void FPSLimiterRenderModule::Init(const json& initData) { // Init from config const CauldronConfig* pConfig = GetConfig(); - m_LimitFPS = pConfig->LimitFPS; - m_LimitGPU = pConfig->GPULimitFPS; - m_TargetFPS = pConfig->LimitedFrameRate; + m_LimitFPS = pConfig->LimitFPS; + m_LimitGPU = pConfig->GPULimitFPS; + m_TargetFPS = pConfig->LimitedFrameRate; // Create FPS limiter buffer and transition it right away BufferDesc bufDesc = BufferDesc::Data(L"FPSLimiter_Buffer", BufferLength, 4, 0, ResourceFlags::AllowUnorderedAccess); m_pBuffer = Buffer::CreateBufferResource(&bufDesc, ResourceState::CommonResource); - GetDevice()->ExecuteResourceTransitionImmediate(1, &Barrier::Transition(m_pBuffer->GetResource(), ResourceState::CommonResource, ResourceState::UnorderedAccess)); + GetDevice()->ExecuteResourceTransitionImmediate( + 1, &Barrier::Transition(m_pBuffer->GetResource(), ResourceState::CommonResource, ResourceState::UnorderedAccess)); // Root signature RootSignatureDesc signatureDesc; @@ -93,31 +95,67 @@ void FPSLimiterRenderModule::Init(const json& initData) SetModuleReady(true); } +static void TimerSleepQPC(int64_t targetQPC) +{ + LARGE_INTEGER currentQPC; + do + { + QueryPerformanceCounter(¤tQPC); + } while (currentQPC.QuadPart < targetQPC); +} + +static void TimerSleep(std::chrono::steady_clock::duration duration) +{ + using ticks = std::chrono::duration>; + static HANDLE timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); + LARGE_INTEGER dueTime{}; + dueTime.QuadPart = -std::chrono::duration_cast(duration).count(); + SetWaitableTimerEx(timer, &dueTime, 0, NULL, NULL, NULL, 0); + WaitForSingleObject(timer, -1); +} + void FPSLimiterRenderModule::Execute(double deltaTime, cauldron::CommandList* pCmdList) { if (!m_LimitFPS) return; // If we aren't doing GPU-based limiting, sleep the CPU - if (!m_LimitGPU) + if (!m_LimitGPU) { CPUScopedProfileCapture marker(L"FPSLimiter"); // CPU limiter - uint64_t targetFrameTimeUs = 1000000 / m_TargetFPS; - std::chrono::steady_clock::duration targetFrameTime = std::chrono::duration_cast(std::chrono::microseconds{targetFrameTimeUs}); - static std::chrono::steady_clock::time_point lastFrameTime = std::chrono::steady_clock::now(); - std::chrono::steady_clock::time_point timeNow = std::chrono::steady_clock::now(); - std::chrono::steady_clock::duration delta = timeNow - lastFrameTime; - - if (delta < targetFrameTime) - { - std::this_thread::sleep_for(targetFrameTime - delta); - timeNow += targetFrameTime - delta; - } - - lastFrameTime = timeNow; - + #if USE_BUSY_WAIT + LARGE_INTEGER qpf; + QueryPerformanceFrequency(&qpf); + int64_t targetFrameTicks = qpf.QuadPart / m_TargetFPS; + + static LARGE_INTEGER lastFrame = {}; + LARGE_INTEGER timeNow; + QueryPerformanceCounter(&timeNow); + int64_t delta = timeNow.QuadPart - lastFrame.QuadPart; + if (delta < targetFrameTicks) + { + TimerSleepQPC(lastFrame.QuadPart + targetFrameTicks); + } + QueryPerformanceCounter(&lastFrame); + #else + // CPU limiter + uint64_t targetFrameTimeUs = 1000000 / m_TargetFPS; + std::chrono::steady_clock::duration targetFrameTime = + std::chrono::duration_cast(std::chrono::microseconds{targetFrameTimeUs}); + static std::chrono::steady_clock::time_point lastFrameTime = std::chrono::steady_clock::now(); + std::chrono::steady_clock::time_point timeNow = std::chrono::steady_clock::now(); + std::chrono::steady_clock::duration delta = timeNow - lastFrameTime; + + if (delta < targetFrameTime) + { + TimerSleep(targetFrameTime - delta); + timeNow += targetFrameTime - delta; + } + + lastFrameTime = timeNow; + #endif return; } else @@ -125,14 +163,16 @@ void FPSLimiterRenderModule::Execute(double deltaTime, cauldron::CommandList* pC GPUScopedProfileCapture marker(pCmdList, L"FPSLimiter"); uint64_t lastFrameTimeUs = 0; - auto& timings = GetProfiler()->GetGPUTimings(); + auto& timings = GetProfiler()->GetGPUTimings(); if (!timings.empty()) { - lastFrameTimeUs = std::chrono::duration_cast>(timings[0].GetDuration()).count(); + std::chrono::nanoseconds currentFrameEnd = timings[0].EndTime; + lastFrameTimeUs = std::chrono::duration_cast>(currentFrameEnd - m_LastFrameEnd).count(); + m_LastFrameEnd = currentFrameEnd; } // calculate number of loops - const double DampenFactor = 0.05; + const double DampenFactor = 0.05; const double MaxTargetFrameTimeUs = 200000.0; // 200ms 5fps to match CPU limiter UI. const double MinTargetFrameTimeUs = 50.0; @@ -150,7 +190,7 @@ void FPSLimiterRenderModule::Execute(double deltaTime, cauldron::CommandList* pC double recentFrameTimeMean = double(m_FrameTimeHistorySum) / double(std::min(m_FrameTimeHistoryCount, _countof(m_FrameTimeHistory))); double clampedTargetFrameTimeMs = std::max(std::min(double(targetFrameTimeUs), MaxTargetFrameTimeUs), MinTargetFrameTimeUs); - double deltaRatio = (recentFrameTimeMean - clampedTargetFrameTimeMs) / clampedTargetFrameTimeMs; + double deltaRatio = (recentFrameTimeMean - clampedTargetFrameTimeMs) / clampedTargetFrameTimeMs; m_Overhead -= m_Overhead * deltaRatio * DampenFactor; m_Overhead = std::min(std::max(1.0, m_Overhead), 1000000.0); diff --git a/framework/cauldron/framework/src/render/rendermodules/fpslimiter/fpslimiterrendermodule.h b/framework/cauldron/framework/src/render/rendermodules/fpslimiter/fpslimiterrendermodule.h index 36362532..a5a0fd86 100644 --- a/framework/cauldron/framework/src/render/rendermodules/fpslimiter/fpslimiterrendermodule.h +++ b/framework/cauldron/framework/src/render/rendermodules/fpslimiter/fpslimiterrendermodule.h @@ -22,6 +22,7 @@ #include "render/renderdefines.h" #include "core/uimanager.h" #include "misc/math.h" +#include namespace cauldron { @@ -49,11 +50,12 @@ class FPSLimiterRenderModule : public RenderModule cauldron::PipelineObject* m_pPipelineObj = nullptr; cauldron::Buffer* m_pBuffer = nullptr; - double m_Overhead = 1.0; - static const uint32_t s_FRAME_TIME_HISTORY_SAMPLES = 4; - uint64_t m_FrameTimeHistory[s_FRAME_TIME_HISTORY_SAMPLES]; - uint64_t m_FrameTimeHistorySum = 0; - uint64_t m_FrameTimeHistoryCount = 0; + double m_Overhead = 1.0; + static const uint32_t s_FRAME_TIME_HISTORY_SAMPLES = 4; + uint64_t m_FrameTimeHistory[s_FRAME_TIME_HISTORY_SAMPLES]; + uint64_t m_FrameTimeHistorySum = 0; + uint64_t m_FrameTimeHistoryCount = 0; + std::chrono::nanoseconds m_LastFrameEnd{0}; // UI cauldron::UISection m_UISection; diff --git a/framework/cauldron/framework/src/render/rendermodules/swapchain/swapchainrendermodule.cpp b/framework/cauldron/framework/src/render/rendermodules/swapchain/swapchainrendermodule.cpp index 674e1262..727b3097 100644 --- a/framework/cauldron/framework/src/render/rendermodules/swapchain/swapchainrendermodule.cpp +++ b/framework/cauldron/framework/src/render/rendermodules/swapchain/swapchainrendermodule.cpp @@ -32,7 +32,20 @@ namespace cauldron void SwapChainRenderModule::Init(const json& initData) { // Setup the texture to be the swapchain render target input - m_pTexture = GetFramework()->GetColorTargetForCallback(GetName()); // Pass in the highest value as this is always the last module to execute + switch (GetFramework()->GetSwapChain()->GetSwapChainDisplayMode()) + { + case DisplayMode::DISPLAYMODE_LDR: + m_pTexture = GetFramework()->GetRenderTexture(L"LDR8Color"); + break; + case DisplayMode::DISPLAYMODE_HDR10_2084: + case DisplayMode::DISPLAYMODE_FSHDR_2084: + m_pTexture = GetFramework()->GetRenderTexture(L"HDR10Color"); + break; + case DisplayMode::DISPLAYMODE_HDR10_SCRGB: + case DisplayMode::DISPLAYMODE_FSHDR_SCRGB: + m_pTexture = GetFramework()->GetRenderTexture(L"HDR16Color"); + break; + } // root signature RootSignatureDesc signatureDesc; @@ -64,7 +77,6 @@ namespace cauldron m_pPipelineObj = PipelineObject::CreatePipelineObject(L"SwapChainCopyPass_PipelineObj", psoDesc); m_pParameters = ParameterSet::CreateParameterSet(m_pRootSignature); - m_pParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(SwapchainCBData), 0); // Set our texture to the right parameter slot m_pParameters->SetTextureSRV(m_pTexture, ViewDimension::Texture2D, 0); @@ -84,8 +96,6 @@ namespace cauldron { GPUScopedProfileCapture SwapchainMarker(pCmdList, L"SwapChain"); - m_ConstantData.displayMode = GetFramework()->GetSwapChain()->GetSwapChainDisplayMode(); - // Cauldron resources need to be transitioned app-side to avoid confusion in states internally // Render modules expect resources coming in/going out to be in a shader read state Barrier barrier = Barrier::Transition(m_pRenderTarget->GetCurrentResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::RenderTargetResource); @@ -93,12 +103,6 @@ namespace cauldron BeginRaster(pCmdList, 1, &m_pRasterView); - // Allocate a dynamic constant buffers and set - BufferAddressInfo bufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(SwapchainCBData), &m_ConstantData); - - // Update constant buffers - m_pParameters->UpdateRootConstantBuffer(&bufferInfo, 0); - // Bind all the parameters m_pParameters->Bind(pCmdList, m_pPipelineObj); diff --git a/framework/cauldron/framework/src/render/rendermodules/swapchain/swapchainrendermodule.h b/framework/cauldron/framework/src/render/rendermodules/swapchain/swapchainrendermodule.h index c53a1008..fe5f798b 100644 --- a/framework/cauldron/framework/src/render/rendermodules/swapchain/swapchainrendermodule.h +++ b/framework/cauldron/framework/src/render/rendermodules/swapchain/swapchainrendermodule.h @@ -46,8 +46,6 @@ namespace cauldron private: - SwapchainCBData m_ConstantData; - RootSignature* m_pRootSignature = nullptr; const RasterView* m_pRasterView = nullptr; PipelineObject* m_pPipelineObj = nullptr; diff --git a/framework/cauldron/framework/src/render/rendermodules/tonemapping/tonemappingrendermodule.cpp b/framework/cauldron/framework/src/render/rendermodules/tonemapping/tonemappingrendermodule.cpp index 9c0fc565..603e1cad 100644 --- a/framework/cauldron/framework/src/render/rendermodules/tonemapping/tonemappingrendermodule.cpp +++ b/framework/cauldron/framework/src/render/rendermodules/tonemapping/tonemappingrendermodule.cpp @@ -57,11 +57,24 @@ void ToneMappingRenderModule::Init(const json& InitData) m_pRootSignature = RootSignature::CreateRootSignature(L"ToneMappingRenderPass_RootSignature", signatureDesc); // Get the proper post tone map color target - m_pRenderTarget = GetFramework()->GetRenderTexture(L"HDR11Color"); + switch (GetFramework()->GetSwapChain()->GetSwapChainDisplayMode()) + { + case DisplayMode::DISPLAYMODE_LDR: + m_pRenderTarget = GetFramework()->GetRenderTexture(L"LDR8Color"); + break; + case DisplayMode::DISPLAYMODE_HDR10_2084: + case DisplayMode::DISPLAYMODE_FSHDR_2084: + m_pRenderTarget = GetFramework()->GetRenderTexture(L"HDR10Color"); + break; + case DisplayMode::DISPLAYMODE_HDR10_SCRGB: + case DisplayMode::DISPLAYMODE_FSHDR_SCRGB: + m_pRenderTarget = GetFramework()->GetRenderTexture(L"HDR16Color"); + break; + } CauldronAssert(ASSERT_CRITICAL, m_pRenderTarget != nullptr, L"Couldn't find the render target for the tone mapper"); - // Get the input texture (these are the same now) - m_pTexture = m_pRenderTarget; + // Get the input texture + m_pTexture = GetFramework()->GetRenderTexture(L"HDR11Color"); // Setup the pipeline object PipelineDesc psoDesc; @@ -111,14 +124,6 @@ ToneMappingRenderModule::~ToneMappingRenderModule() void ToneMappingRenderModule::Execute(double deltaTime, CommandList* pCmdList) { - // If display mode is set to FSHDR_SCRGB or HDR10_SCRGB, the tonemapper will not run - // the color target for the duration of the frame will be RGBA16_FLOAT (HDR16Color) - if (GetFramework()->GetSwapChain()->GetSwapChainDisplayMode() == DisplayMode::DISPLAYMODE_FSHDR_SCRGB || - GetFramework()->GetSwapChain()->GetSwapChainDisplayMode() == DisplayMode::DISPLAYMODE_HDR10_SCRGB) - { - return; - } - GPUScopedProfileCapture tonemappingMarker(pCmdList, L"ToneMapping"); // Render modules expect resources coming in/going out to be in a shader read state diff --git a/framework/cauldron/framework/src/render/rendermodules/tonemapping/tonemappingrendermodule.h b/framework/cauldron/framework/src/render/rendermodules/tonemapping/tonemappingrendermodule.h index 413fc546..c1886a7c 100644 --- a/framework/cauldron/framework/src/render/rendermodules/tonemapping/tonemappingrendermodule.h +++ b/framework/cauldron/framework/src/render/rendermodules/tonemapping/tonemappingrendermodule.h @@ -57,6 +57,6 @@ class ToneMappingRenderModule : public cauldron::RenderModule cauldron::PipelineObject* m_pPipelineObj = nullptr; cauldron::ParameterSet* m_pParameters = nullptr; - const cauldron::Texture* m_pTexture = nullptr; + const cauldron::Texture* m_pTexture = nullptr; const cauldron::Texture* m_pRenderTarget = nullptr; }; diff --git a/framework/cauldron/framework/src/render/rendermodules/ui/uirendermodule.cpp b/framework/cauldron/framework/src/render/rendermodules/ui/uirendermodule.cpp index 17ea8fc3..df6768b0 100644 --- a/framework/cauldron/framework/src/render/rendermodules/ui/uirendermodule.cpp +++ b/framework/cauldron/framework/src/render/rendermodules/ui/uirendermodule.cpp @@ -33,8 +33,6 @@ #include "render/texture.h" #include "shaders/shadercommon.h" -#include "imgui/imgui.h" - namespace cauldron { constexpr uint32_t g_NumThreadX = 8; @@ -42,6 +40,8 @@ namespace cauldron void UIRenderModule::Init(const json& initData) { + // TODO: UI render module should not have its own buffer pool. This is only created for the FSR3 interpolation thread to not race with the main thread, which should ideally be handled by Cauldron itself. + m_pDynamicBufferPool = DynamicBufferPool::CreateDynamicBufferPool(); ////////////////////////////////////////////////////////////////////////// // Register UI elements for magnifier static constexpr float s_MAGNIFICATION_AMOUNT_MIN = 1.0f; @@ -59,11 +59,67 @@ namespace cauldron ////////////////////////////////////////////////////////////////////////// // Render Target - - m_pRenderTarget = GetFramework()->GetColorTargetForCallback(GetName()); - CauldronAssert(ASSERT_CRITICAL, m_pRenderTarget, L"Couldn't get the swapchain render target when initializing UIRenderModule."); + // Get the proper UI color target + switch (GetFramework()->GetSwapChain()->GetSwapChainDisplayMode()) + { + case DisplayMode::DISPLAYMODE_LDR: + m_pRenderTarget = GetFramework()->GetRenderTexture(L"LDR8Color"); + m_pUiOnlyRenderTarget[0] = GetFramework()->GetRenderTexture(L"UiTarget0_LDR8"); + m_pUiOnlyRenderTarget[1] = GetFramework()->GetRenderTexture(L"UiTarget1_LDR8"); + break; + case DisplayMode::DISPLAYMODE_HDR10_2084: + case DisplayMode::DISPLAYMODE_FSHDR_2084: + m_pRenderTarget = GetFramework()->GetRenderTexture(L"HDR10Color"); + m_pUiOnlyRenderTarget[0] = GetFramework()->GetRenderTexture(L"UiTarget0_HDR10"); + m_pUiOnlyRenderTarget[1] = GetFramework()->GetRenderTexture(L"UiTarget1_HDR10"); + break; + case DisplayMode::DISPLAYMODE_HDR10_SCRGB: + case DisplayMode::DISPLAYMODE_FSHDR_SCRGB: + m_pRenderTarget = GetFramework()->GetRenderTexture(L"HDR16Color"); + m_pUiOnlyRenderTarget[0] = GetFramework()->GetRenderTexture(L"UiTarget0_HDR16"); + m_pUiOnlyRenderTarget[1] = GetFramework()->GetRenderTexture(L"UiTarget1_HDR16"); + break; + } + CauldronAssert(ASSERT_CRITICAL, m_pRenderTarget, L"Couldn't find the render target for UIRenderModule."); m_pUIRasterView = GetRasterViewAllocator()->RequestRasterView(m_pRenderTarget, ViewDimension::Texture2D); + if (GetFramework()->GetRenderTexture(L"FSR3_HudLessTexture0")) + { + m_pHudLessRenderTarget[0] = GetFramework()->GetRenderTexture(L"FSR3_HudLessTexture0"); + m_pHudLessRenderTarget[1] = GetFramework()->GetRenderTexture(L"FSR3_HudLessTexture1"); + + m_pHudLessRasterView[0] = GetRasterViewAllocator()->RequestRasterView(m_pHudLessRenderTarget[0], ViewDimension::Texture2D); + m_pHudLessRasterView[1] = GetRasterViewAllocator()->RequestRasterView(m_pHudLessRenderTarget[1], ViewDimension::Texture2D); + + RootSignatureDesc signatureDesc; + signatureDesc.AddConstantBufferView(0, ShaderBindStage::Pixel, 1); + signatureDesc.AddTextureSRVSet(0, ShaderBindStage::Pixel, 1); + + m_pHudLessRootSignature = RootSignature::CreateRootSignature(L"HudLessBlit_RootSignature", signatureDesc); + + m_pHudLessParameters = ParameterSet::CreateParameterSet(m_pHudLessRootSignature); + m_pHudLessParameters->SetTextureSRV(m_pHudLessRenderTarget[0], ViewDimension::Texture2D, 0); + + // Setup the pipeline object + PipelineDesc psoDesc; + psoDesc.SetRootSignature(m_pHudLessRootSignature); + + // Setup the shaders to build on the pipeline object + psoDesc.AddShaderDesc(ShaderBuildDesc::Vertex(L"fullscreen.hlsl", L"FullscreenVS", ShaderModel::SM6_0, nullptr)); + psoDesc.AddShaderDesc(ShaderBuildDesc::Pixel(L"HudLessBlit.hlsl", L"BlitPS", ShaderModel::SM6_0, nullptr)); + + // Setup remaining information and build + psoDesc.AddPrimitiveTopology(PrimitiveTopologyType::Triangle); + psoDesc.AddRasterFormats(m_pHudLessRenderTarget[0]->GetFormat()); + + m_pHudLessPipelineObj = PipelineObject::CreatePipelineObject(L"HudLessBlit_PipelineObj", psoDesc); + } + + if (m_pUiOnlyRenderTarget[0]) + m_pUiOnlyRasterView[0] = GetRasterViewAllocator()->RequestRasterView(m_pUiOnlyRenderTarget[0], ViewDimension::Texture2D); + if (m_pUiOnlyRenderTarget[1]) + m_pUiOnlyRasterView[1] = GetRasterViewAllocator()->RequestRasterView(m_pUiOnlyRenderTarget[1], ViewDimension::Texture2D); + // Temp intermediate RT for magnifier render pass TextureDesc desc = m_pRenderTarget->GetDesc(); const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); @@ -119,33 +175,85 @@ namespace cauldron DefineList defineList; defineList.insert(std::make_pair(L"NUM_THREAD_X", std::to_wstring(g_NumThreadX))); defineList.insert(std::make_pair(L"NUM_THREAD_Y", std::to_wstring(g_NumThreadY))); - uiPsoDesc.AddShaderDesc(ShaderBuildDesc::Vertex(L"ui.hlsl", L"uiVS", ShaderModel::SM6_0, &defineList)); - uiPsoDesc.AddShaderDesc(ShaderBuildDesc::Pixel(L"ui.hlsl", L"uiPS", ShaderModel::SM6_0, &defineList)); - - // Setup vertex elements - std::vector vertexAttributes; - vertexAttributes.push_back(InputLayoutDesc(VertexAttributeType::Position, ResourceFormat::RG32_FLOAT, 0, 0)); - vertexAttributes.push_back(InputLayoutDesc(VertexAttributeType::Texcoord0, ResourceFormat::RG32_FLOAT, 0, 8)); - vertexAttributes.push_back(InputLayoutDesc(VertexAttributeType::Color0, ResourceFormat::RGBA8_UNORM, 0, 16)); - uiPsoDesc.AddInputLayout(vertexAttributes); - - // Setup blend and depth states - BlendDesc blendDesc = { true, Blend::SrcAlpha, Blend::InvSrcAlpha, BlendOp::Add, Blend::One, Blend::InvSrcAlpha, BlendOp::Add, static_cast(ColorWriteMask::All) }; - std::vector blends; - blends.push_back(blendDesc); - uiPsoDesc.AddBlendStates(blends, false, false); - DepthDesc depthDesc; - uiPsoDesc.AddDepthState(&depthDesc); // Use defaults - - RasterDesc rasterDesc; - rasterDesc.CullingMode = CullMode::None; - uiPsoDesc.AddRasterStateDescription(&rasterDesc); - - // Setup remaining information and build - uiPsoDesc.AddPrimitiveTopology(PrimitiveTopologyType::Triangle); - - uiPsoDesc.AddRasterFormats(m_pRenderTarget->GetFormat()); - m_pUIPipelineObj = PipelineObject::CreatePipelineObject(L"UI_PipelineObj", uiPsoDesc); + { + PipelineDesc uiPsoDesc; + uiPsoDesc.SetRootSignature(m_pUIRootSignature); + + uiPsoDesc.AddShaderDesc(ShaderBuildDesc::Vertex(L"ui.hlsl", L"uiVS", ShaderModel::SM6_0, &defineList)); + uiPsoDesc.AddShaderDesc(ShaderBuildDesc::Pixel(L"ui.hlsl", L"uiPS", ShaderModel::SM6_0, &defineList)); + + // Setup vertex elements + std::vector vertexAttributes; + vertexAttributes.push_back(InputLayoutDesc(VertexAttributeType::Position, ResourceFormat::RG32_FLOAT, 0, 0)); + vertexAttributes.push_back(InputLayoutDesc(VertexAttributeType::Texcoord0, ResourceFormat::RG32_FLOAT, 0, 8)); + vertexAttributes.push_back(InputLayoutDesc(VertexAttributeType::Color0, ResourceFormat::RGBA8_UNORM, 0, 16)); + uiPsoDesc.AddInputLayout(vertexAttributes); + + // Setup blend and depth states + BlendDesc blendDesc = {true, + Blend::SrcAlpha, + Blend::InvSrcAlpha, + BlendOp::Add, + Blend::One, + Blend::InvSrcAlpha, + BlendOp::Add, + static_cast(ColorWriteMask::All)}; + std::vector blends; + blends.push_back(blendDesc); + uiPsoDesc.AddBlendStates(blends, false, false); + DepthDesc depthDesc; + uiPsoDesc.AddDepthState(&depthDesc); // Use defaults + + RasterDesc rasterDesc; + rasterDesc.CullingMode = CullMode::None; + uiPsoDesc.AddRasterStateDescription(&rasterDesc); + + // Setup remaining information and build + uiPsoDesc.AddPrimitiveTopology(PrimitiveTopologyType::Triangle); + + uiPsoDesc.AddRasterFormats(m_pRenderTarget->GetFormat()); + m_pUIPipelineObj = PipelineObject::CreatePipelineObject(L"UI_PipelineObj", uiPsoDesc); + } + + { + PipelineDesc uiPsoDesc; + uiPsoDesc.SetRootSignature(m_pUIRootSignature); + + uiPsoDesc.AddShaderDesc(ShaderBuildDesc::Vertex(L"ui.hlsl", L"uiVS", ShaderModel::SM6_0, &defineList)); + uiPsoDesc.AddShaderDesc(ShaderBuildDesc::Pixel(L"ui.hlsl", L"uiPS", ShaderModel::SM6_0, &defineList)); + + // Setup vertex elements + std::vector vertexAttributes; + vertexAttributes.push_back(InputLayoutDesc(VertexAttributeType::Position, ResourceFormat::RG32_FLOAT, 0, 0)); + vertexAttributes.push_back(InputLayoutDesc(VertexAttributeType::Texcoord0, ResourceFormat::RG32_FLOAT, 0, 8)); + vertexAttributes.push_back(InputLayoutDesc(VertexAttributeType::Color0, ResourceFormat::RGBA8_UNORM, 0, 16)); + uiPsoDesc.AddInputLayout(vertexAttributes); + + // Setup blend and depth states + BlendDesc blendDesc = {true, + Blend::SrcAlpha, + Blend::InvSrcAlpha, + BlendOp::Add, + Blend::One, + Blend::InvSrcAlpha, + BlendOp::Add, + static_cast(ColorWriteMask::All)}; + std::vector blends; + blends.push_back(blendDesc); + uiPsoDesc.AddBlendStates(blends, false, false); + DepthDesc depthDesc; + uiPsoDesc.AddDepthState(&depthDesc); // Use defaults + + RasterDesc rasterDesc; + rasterDesc.CullingMode = CullMode::None; + uiPsoDesc.AddRasterStateDescription(&rasterDesc); + + // Setup remaining information and build + uiPsoDesc.AddPrimitiveTopology(PrimitiveTopologyType::Triangle); + + uiPsoDesc.AddRasterFormats(m_pRenderTarget->GetFormat()); + m_pAsyncPipelineObj = PipelineObject::CreatePipelineObject(L"UI_AsyncPipelineObj", uiPsoDesc); + } //---------------------------------------------------- // Magnifier @@ -162,8 +270,8 @@ namespace cauldron // UI m_pUIParameters = ParameterSet::CreateParameterSet(m_pUIRootSignature); - m_pUIParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(UIVertexBufferConstants), 0); - m_pUIParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(HDRCBData), 1); + m_pUIParameters->SetRootConstantBufferResource(m_pDynamicBufferPool->GetResource(), sizeof(UIVertexBufferConstants), 0); + m_pUIParameters->SetRootConstantBufferResource(m_pDynamicBufferPool->GetResource(), sizeof(HDRCBData), 1); // Magnifier m_pMagnifierParameters = ParameterSet::CreateParameterSet(m_pMagnifierRootSignature); @@ -175,14 +283,20 @@ namespace cauldron UIRenderModule::~UIRenderModule() { + delete m_pHudLessRootSignature; + delete m_pHudLessPipelineObj; + delete m_pHudLessParameters; + delete m_pUIRootSignature; delete m_pMagnifierRootSignature; delete m_pUIPipelineObj; + delete m_pAsyncPipelineObj; delete m_pMagnifierPipelineObj; delete m_pUIParameters; delete m_pMagnifierParameters; + delete m_pDynamicBufferPool; } void UIRenderModule::Execute(double deltaTime, CommandList* pCmdList) @@ -195,12 +309,14 @@ namespace cauldron L"Upscale state is still PreUpscale when reaching UIRendermodule. This should not be the case."); // Do input updates for magnifier - const InputState& inputState = GetInputManager()->GetInputState(); - if (inputState.GetKeyUpState(Key_M) || inputState.GetMouseButtonUpState(Mouse_MButton)) - m_MagnifierEnabled = !m_MagnifierEnabled; + { + const InputState& inputState = GetInputManager()->GetInputState(); + if (inputState.GetKeyUpState(Key_M) || inputState.GetMouseButtonUpState(Mouse_MButton)) + m_MagnifierEnabled = !m_MagnifierEnabled; - if (inputState.GetKeyUpState(Key_L)) - m_LockMagnifierPosition = !m_LockMagnifierPosition; + if (inputState.GetKeyUpState(Key_L)) + m_LockMagnifierPosition = !m_LockMagnifierPosition; + } // And fetch all the data ImGUI pushed this frame for UI rendering ImDrawData* pUIDrawData = ImGui::GetDrawData(); @@ -261,7 +377,7 @@ namespace cauldron } // If we aren't drawing UI data, then end raster and transition the render target back to read - if (!pUIDrawData) + if (!pUIDrawData || m_AsyncRender) { { Barrier barrier; @@ -275,39 +391,14 @@ namespace cauldron if (pUIDrawData) { - // UI RM always done at display resolution - const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); - SetViewportScissorRect(pCmdList, 0, 0, resInfo.DisplayWidth, resInfo.DisplayHeight, 0.f, 1.f); - SetPrimitiveTopology(pCmdList, PrimitiveTopology::TriangleList); - - // Pick the right pipeline / raster set / render target - PipelineObject* pPipelineObj = m_pUIPipelineObj; - const RasterView* pRasterView = m_pUIRasterView; - const Texture* pRenderTarget = m_pRenderTarget; - - // If we didn't render magnifier, transition the resources from a different state - { - // Render modules expect resources coming in/going out to be in a shader read state - Barrier rtBarrier = Barrier::Transition(pRenderTarget->GetResource(), - m_MagnifierEnabled ? ResourceState::CopyDest : ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, - ResourceState::RenderTargetResource); - ResourceBarrier(pCmdList, 1, &rtBarrier); - } - - // Set the render targets - BeginRaster(pCmdList, 1, &pRasterView); - - // Get buffers for vertices and indices - char* pVertices = nullptr; - BufferAddressInfo vertBufferInfo = GetDynamicBufferPool()->AllocVertexBuffer(pUIDrawData->TotalVtxCount, sizeof(ImDrawVert), reinterpret_cast(&pVertices)); - - char* pIndices = nullptr; - BufferAddressInfo idxBufferInfo = GetDynamicBufferPool()->AllocIndexBuffer(pUIDrawData->TotalIdxCount, sizeof(ImDrawIdx), reinterpret_cast(&pIndices)); + RenderParams renderParams{}; + renderParams.vtxBuffer.resize(pUIDrawData->TotalVtxCount); + renderParams.idxBuffer.resize(pUIDrawData->TotalIdxCount); // Copy data in - ImDrawVert* pVtx = (ImDrawVert*)pVertices; - ImDrawIdx* pIdx = (ImDrawIdx*)pIndices; - for (int32_t n = 0; n < pUIDrawData->CmdListsCount; n++) + ImDrawVert* pVtx = (ImDrawVert*)renderParams.vtxBuffer.data(); + ImDrawIdx* pIdx = (ImDrawIdx*)renderParams.idxBuffer.data(); + for (int n = 0; n < pUIDrawData->CmdListsCount; n++) { const ImDrawList* pIMCmdList = pUIDrawData->CmdLists[n]; memcpy(pVtx, pIMCmdList->VtxBuffer.Data, pIMCmdList->VtxBuffer.Size * sizeof(ImDrawVert)); @@ -317,16 +408,16 @@ namespace cauldron } // Setup constant buffer data - float left = 0.0f; - float right = ImGui::GetIO().DisplaySize.x; + float left = 0.0f; + float right = ImGui::GetIO().DisplaySize.x; float bottom = ImGui::GetIO().DisplaySize.y; - float top = 0.0f; - Mat4 mvp(Vec4(2.f / (right - left), 0.f, 0.f, 0.f), + float top = 0.0f; + Mat4 mvp(Vec4(2.f / (right - left), 0.f, 0.f, 0.f), Vec4(0.f, 2.f / (top - bottom), 0.f, 0.f), Vec4(0.f, 0.f, 0.5f, 0.f), Vec4((right + left) / (left - right), (top + bottom) / (bottom - top), 0.5f, 1.f)); - BufferAddressInfo bufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(Mat4), &mvp); + renderParams.matrix = mvp; m_HDRCBData.MonitorDisplayMode = GetFramework()->GetSwapChain()->GetSwapChainDisplayMode(); m_HDRCBData.DisplayMaxLuminance = GetFramework()->GetSwapChain()->GetHDRMetaData().MaxLuminance; @@ -340,64 +431,144 @@ namespace cauldron ColorSpace outputColorSpace = ColorSpace_REC2020; SetupGamutMapperMatrices(inputColorSpace, outputColorSpace, &m_HDRCBData.ContentToMonitorRecMatrix); - BufferAddressInfo hdrbufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(HDRCBData), &m_HDRCBData); - - // Update constant buffer - m_pUIParameters->UpdateRootConstantBuffer(&bufferInfo, 0); - m_pUIParameters->UpdateRootConstantBuffer(&hdrbufferInfo, 1); - - // Bind all parameters - m_pUIParameters->Bind(pCmdList, pPipelineObj); - - // Set pipeline and draw - SetPipelineState(pCmdList, pPipelineObj); + renderParams.hdr = m_HDRCBData; // Render command lists uint32_t vtxOffset = 0; uint32_t idxOffset = 0; for (int32_t n = 0; n < pUIDrawData->CmdListsCount; n++) { - // Set vertex info - SetVertexBuffers(pCmdList, 0, 1, &vertBufferInfo); - const ImDrawList* pIMCmdList = pUIDrawData->CmdLists[n]; for (int32_t cmdIndex = 0; cmdIndex < pIMCmdList->CmdBuffer.Size; cmdIndex++) { - // Set index info - SetIndexBuffer(pCmdList, &idxBufferInfo); - const ImDrawCmd* pDrawCmd = &pIMCmdList->CmdBuffer[cmdIndex]; - if (pDrawCmd->UserCallback) - pDrawCmd->UserCallback(pIMCmdList, pDrawCmd); - - else - { - // Project scissor/clipping rectangles into framebuffer space - ImVec2 clipOffset = pUIDrawData->DisplayPos; - ImVec2 clipMin(pDrawCmd->ClipRect.x - clipOffset.x, pDrawCmd->ClipRect.y - clipOffset.y); - ImVec2 clipMax(pDrawCmd->ClipRect.z - clipOffset.x, pDrawCmd->ClipRect.w - clipOffset.y); - if (clipMax.x <= clipMin.x || clipMax.y <= clipMin.y) - continue; - Rect scissorRect = {static_cast(clipMin.x), - static_cast(clipMin.y), - static_cast(clipMax.x), - static_cast(clipMax.y)}; - SetScissorRects(pCmdList, 1, &scissorRect); - DrawIndexedInstanced(pCmdList, pDrawCmd->ElemCount, 1, idxOffset, vtxOffset); - } + CauldronAssert(ASSERT_ERROR, !pDrawCmd->UserCallback, L"ImGui User Callback is not supported!"); + // Project scissor/clipping rectangles into framebuffer space + ImVec2 clipOffset = pUIDrawData->DisplayPos; + ImVec2 clipMin(pDrawCmd->ClipRect.x - clipOffset.x, pDrawCmd->ClipRect.y - clipOffset.y); + ImVec2 clipMax(pDrawCmd->ClipRect.z - clipOffset.x, pDrawCmd->ClipRect.w - clipOffset.y); + if (clipMax.x <= clipMin.x || clipMax.y <= clipMin.y) + continue; + Rect scissorRect = { + static_cast(clipMin.x), static_cast(clipMin.y), static_cast(clipMax.x), static_cast(clipMax.y)}; + + RenderCommand cmd{}; + cmd.scissor = scissorRect; + cmd.indexCount = pDrawCmd->ElemCount; + cmd.startIndex = idxOffset; + cmd.baseVertex = vtxOffset; + renderParams.commands.push_back(cmd); idxOffset += pDrawCmd->ElemCount; } vtxOffset += pIMCmdList->VtxBuffer.Size; } - // Done rendering to render target - EndRaster(pCmdList); + if (m_AsyncRender) + { + // Store value for later/different thread. + RenderParams* pParams = new RenderParams{renderParams}; + pParams = m_AsyncChannel.exchange(pParams); + // No one else has this pointer, therefore we should delete it. + delete pParams; + } + else + { + const cauldron::GPUResource* rt = m_bRenderToTexture ? m_pUiOnlyRenderTarget[m_curUiTextureIndex]->GetResource() : m_pRenderTarget->GetResource(); + ResourceState prevState = rt->GetCurrentResourceState(); + Barrier rtBarrier = Barrier::Transition(rt, prevState, ResourceState::RenderTargetResource); + ResourceBarrier(pCmdList, 1, &rtBarrier); + + if (m_bCopyHudLessTexture) + { + BlitBackbufferToHudLess(pCmdList); + } - // Render modules expect resources coming in/going out to be in a shader read state - Barrier rtBarrier = Barrier::Transition(pRenderTarget->GetResource(), ResourceState::RenderTargetResource, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource); - ResourceBarrier(pCmdList, 1, &rtBarrier); + // Set the render targets + BeginRaster(pCmdList, 1, m_bRenderToTexture ? &m_pUiOnlyRasterView[m_curUiTextureIndex] : &m_pUIRasterView); + Render(pCmdList, &renderParams); + EndRaster(pCmdList); + + // Render modules expect resources coming in/going out to be in a shader read state + rtBarrier.SourceState = rtBarrier.DestState; + rtBarrier.DestState = ResourceState::ShaderResource; + ResourceBarrier(pCmdList, 1, &rtBarrier); + + if (m_MagnifierEnabled && m_bRenderToTexture) + { + Barrier rtBarrier = Barrier::Transition(m_pRenderTarget->GetResource(), ResourceState::CopyDest, ResourceState::ShaderResource); + ResourceBarrier(pCmdList, 1, &rtBarrier); + } + } + } + } + + void UIRenderModule::Render(CommandList* pCmdList, RenderParams* pParams) + { + if (m_bRenderToTexture) + { + float clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + ClearRenderTarget(pCmdList, &m_pUiOnlyRasterView[m_curUiTextureIndex]->GetResourceView(), clearColor); + } + + m_pDynamicBufferPool->BeginFrame(); + // UI RM always done at display resolution + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + Viewport vp = {0.f, 0.f, resInfo.fDisplayWidth(), resInfo.fDisplayHeight(), 0.f, 1.f}; + SetViewport(pCmdList, &vp); + SetPrimitiveTopology(pCmdList, PrimitiveTopology::TriangleList); + + // Pick the right pipeline / raster set / render target + PipelineObject* pPipelineObj = m_AsyncRender || m_bRenderToTexture ? m_pAsyncPipelineObj : m_pUIPipelineObj; + + // Get buffers for vertices and indices + char* pVertices = nullptr; + BufferAddressInfo vertBufferInfo = + m_pDynamicBufferPool->AllocVertexBuffer((uint32_t)pParams->vtxBuffer.size(), sizeof(ImDrawVert), reinterpret_cast(&pVertices)); + memcpy(pVertices, pParams->vtxBuffer.data(), pParams->vtxBuffer.size() * sizeof(ImDrawVert)); + char* pIndices = nullptr; + BufferAddressInfo idxBufferInfo = + m_pDynamicBufferPool->AllocIndexBuffer((uint32_t)pParams->idxBuffer.size(), sizeof(ImDrawIdx), reinterpret_cast(&pIndices)); + memcpy(pIndices, pParams->idxBuffer.data(), pParams->idxBuffer.size() * sizeof(ImDrawIdx)); + + BufferAddressInfo bufferInfo = m_pDynamicBufferPool->AllocConstantBuffer(sizeof(Mat4), &pParams->matrix); + BufferAddressInfo hdrbufferInfo = m_pDynamicBufferPool->AllocConstantBuffer(sizeof(HDRCBData), &pParams->hdr); + + // Update constant buffer + m_pUIParameters->UpdateRootConstantBuffer(&bufferInfo, 0); + m_pUIParameters->UpdateRootConstantBuffer(&hdrbufferInfo, 1); + + // Bind all parameters + m_pUIParameters->Bind(pCmdList, pPipelineObj); + + // Set pipeline and draw + SetPipelineState(pCmdList, pPipelineObj); + SetVertexBuffers(pCmdList, 0, 1, &vertBufferInfo); + SetIndexBuffer(pCmdList, &idxBufferInfo); + + for (auto& cmd : pParams->commands) + { + SetScissorRects(pCmdList, 1, &cmd.scissor); + DrawIndexedInstanced(pCmdList, cmd.indexCount, 1, cmd.startIndex, cmd.baseVertex, 0); + } + } + + void UIRenderModule::ExecuteAsync(CommandList* pCmdList) + { + // Get parameters from async channel + RenderParams* pParams = m_AsyncChannel.exchange(nullptr); + // Params are buffered here so that they can be re-used for interpolated frames + if (pParams) + { + delete m_BufferedRenderParams; + m_BufferedRenderParams = pParams; + } + else + { + pParams = m_BufferedRenderParams; } + if (pParams) + Render(pCmdList, pParams); } void UIRenderModule::SetFontResourceTexture(const Texture* pFontTexture) @@ -409,6 +580,26 @@ namespace cauldron SetModuleReady(true); } + void UIRenderModule::SetAsyncRender(bool async) + { + m_AsyncRender = async; + } + + void UIRenderModule::SetRenderToTexture(bool renderToTexture) + { + m_bRenderToTexture = renderToTexture; + } + + void UIRenderModule::SetCopyHudLessTexture(bool copyHudLessTexture) + { + m_bCopyHudLessTexture = copyHudLessTexture; + } + + void UIRenderModule::SetUiSurfaceIndex(uint32_t uiTextureIndex) + { + m_curUiTextureIndex = uiTextureIndex; + } + void UIRenderModule::UpdateMagnifierParams() { // If we are locked, use locked position for mouse pos @@ -475,4 +666,41 @@ namespace cauldron } } + void UIRenderModule::BlitBackbufferToHudLess(CommandList* pCmdList) + { + GPUScopedProfileCapture SwapchainMarker(pCmdList, L"Copy Hudless"); + + // Cauldron resources need to be transitioned app-side to avoid confusion in states internally + // Render modules expect resources coming in/going out to be in a shader read state + ResourceState state0 = m_pRenderTarget->GetResource()->GetCurrentResourceState(); + ResourceState state1 = m_pHudLessRenderTarget[m_curUiTextureIndex]->GetResource()->GetCurrentResourceState(); + Barrier barriers[] = {Barrier::Transition(m_pRenderTarget->GetResource(), state0, ResourceState::PixelShaderResource), + Barrier::Transition(m_pHudLessRenderTarget[m_curUiTextureIndex]->GetResource(), state1, ResourceState::RenderTargetResource)}; + ResourceBarrier(pCmdList, _countof(barriers), barriers); + + BeginRaster(pCmdList, 1, &m_pHudLessRasterView[m_curUiTextureIndex]); + + m_pHudLessParameters->SetTextureSRV(m_pRenderTarget, ViewDimension::Texture2D, 0); + + // Bind all the parameters + m_pHudLessParameters->Bind(pCmdList, m_pHudLessPipelineObj); + + // Swap chain RM always done at display res + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + SetViewportScissorRect(pCmdList, 0, 0, resInfo.DisplayWidth, resInfo.DisplayHeight, 0.f, 1.f); + + // Set pipeline and draw + SetPrimitiveTopology(pCmdList, PrimitiveTopology::TriangleList); + SetPipelineState(pCmdList, m_pHudLessPipelineObj); + + DrawInstanced(pCmdList, 3); + + EndRaster(pCmdList); + + // Revert resource states + for (int i = 0; i < _countof(barriers); ++i) + std::swap(barriers[i].SourceState, barriers[i].DestState); + ResourceBarrier(pCmdList, _countof(barriers), barriers); + } + } // namespace cauldron diff --git a/framework/cauldron/framework/src/render/rendermodules/ui/uirendermodule.h b/framework/cauldron/framework/src/render/rendermodules/ui/uirendermodule.h index ba315f89..72c611ce 100644 --- a/framework/cauldron/framework/src/render/rendermodules/ui/uirendermodule.h +++ b/framework/cauldron/framework/src/render/rendermodules/ui/uirendermodule.h @@ -22,6 +22,8 @@ #include "shaders/shadercommon.h" #include "shaders/uicommon.h" +#include "imgui/imgui.h" + namespace cauldron { class RootSignature; @@ -30,6 +32,7 @@ namespace cauldron class PipelineObject; class ParameterSet; class Texture; + class DynamicBufferPool; class UIRenderModule : public RenderModule { @@ -42,12 +45,35 @@ namespace cauldron void SetFontResourceTexture(const Texture* pFontTexture); + void SetAsyncRender(bool async); + void SetRenderToTexture(bool renderToTexture); + void SetCopyHudLessTexture(bool copyHudLessTexture); + void SetUiSurfaceIndex(uint32_t uiTextureIndex); + + // Called on separate thread to render asynchronously. + void ExecuteAsync(CommandList* pCmdList); + void BlitBackbufferToHudLess(CommandList* pCmdList); private: // No copy, No move NO_COPY(UIRenderModule) NO_MOVE(UIRenderModule) - void UpdateMagnifierParams(); + struct RenderCommand + { + Rect scissor; + uint32_t indexCount, startIndex, baseVertex; + }; + struct RenderParams + { + std::vector vtxBuffer{}; + std::vector idxBuffer{}; + Mat4 matrix; + HDRCBData hdr; + std::vector commands; + }; + + void UpdateMagnifierParams(); + void Render(CommandList* pCmdList, RenderParams* params); private: @@ -56,25 +82,44 @@ namespace cauldron Mat4 ProjectionMatrix; }; - HDRCBData m_HDRCBData = {}; - MagnifierCBData m_MagnifierCBData = {}; - bool m_MagnifierEnabled = false; - bool m_LockMagnifierPosition = false; - int32_t m_LockedMagnifierPositionX = 0; - int32_t m_LockedMagnifierPositionY = 0; + HDRCBData m_HDRCBData = {}; + MagnifierCBData m_MagnifierCBData = {}; + bool m_MagnifierEnabled = false; + bool m_LockMagnifierPosition = false; + int32_t m_LockedMagnifierPositionX = 0; + int32_t m_LockedMagnifierPositionY = 0; + + RootSignature* m_pUIRootSignature = nullptr; + RootSignature* m_pMagnifierRootSignature = nullptr; + + const Texture* m_pRenderTarget = nullptr; + const Texture* m_pRenderTargetTemp = nullptr; + const RasterView* m_pUIRasterView = nullptr; + + uint32_t m_curUiTextureIndex = 0; + const cauldron::Texture* m_pHudLessRenderTarget[2] = {}; + const cauldron::Texture* m_pUiOnlyRenderTarget[2] = {}; + const RasterView* m_pUiOnlyRasterView[2] = {}; + RootSignature* m_pHudLessRootSignature = nullptr; + const RasterView* m_pHudLessRasterView[2] = {}; + ParameterSet* m_pHudLessParameters = nullptr; + PipelineObject* m_pHudLessPipelineObj = nullptr; + - RootSignature* m_pUIRootSignature = nullptr; - RootSignature* m_pMagnifierRootSignature = nullptr; + PipelineObject* m_pUIPipelineObj = nullptr; + PipelineObject* m_pAsyncPipelineObj = nullptr; + PipelineObject* m_pMagnifierPipelineObj = nullptr; - const Texture* m_pRenderTarget = nullptr; - const Texture* m_pRenderTargetTemp = nullptr; - const RasterView* m_pUIRasterView = nullptr; + ParameterSet* m_pUIParameters = nullptr; + ParameterSet* m_pMagnifierParameters = nullptr; - PipelineObject* m_pUIPipelineObj = nullptr; - PipelineObject* m_pMagnifierPipelineObj = nullptr; + bool m_AsyncRender = false; + std::atomic m_AsyncChannel = nullptr; + RenderParams* m_BufferedRenderParams = nullptr; + DynamicBufferPool* m_pDynamicBufferPool = nullptr; - ParameterSet* m_pUIParameters = nullptr; - ParameterSet* m_pMagnifierParameters = nullptr; + bool m_bCopyHudLessTexture = false; + bool m_bRenderToTexture = false; }; } // namespace cauldron diff --git a/framework/rendermodules/CMakeLists.txt b/framework/rendermodules/CMakeLists.txt index 95f105c3..a447e5a5 100644 --- a/framework/rendermodules/CMakeLists.txt +++ b/framework/rendermodules/CMakeLists.txt @@ -39,6 +39,16 @@ file(GLOB gbuffer_shaders set_source_files_properties(${gbuffer_shaders} PROPERTIES VS_TOOL_OVERRIDE "Text") copyCommand("${gbuffer_shaders}" ${SHADER_OUTPUT}) +# Animated textures +file(GLOB animatedtextures_src + ${CMAKE_CURRENT_SOURCE_DIR}/animatedtextures/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/animatedtextures/*.cpp) +file(GLOB animatedtextures_shaders + ${CMAKE_CURRENT_SOURCE_DIR}/animatedtextures/shaders/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/animatedtextures/shaders/*.hlsl) +set_source_files_properties(${animatedtextures_shaders} PROPERTIES VS_TOOL_OVERRIDE "Text") +copyCommand("${animatedtextures_shaders}" ${SHADER_OUTPUT}) + # Translucency file(GLOB translucency_src ${CMAKE_CURRENT_SOURCE_DIR}/translucency/*.h @@ -139,6 +149,7 @@ add_library (RenderModules STATIC ${registry_src} # Cauldron rendermodules ${gbuffer_src} ${gbuffer_config} ${gbuffer_shaders} + ${animatedtextures_src} ${animatedtextures_config} ${animatedtextures_shaders} ${translucency_src} ${translucency_config} ${translucency_shaders} ${lighting_src} ${lighting_shaders} ${limiter_src} ${limiter_shaders} @@ -164,6 +175,8 @@ source_group("GPUParticle\\Shaders\\ParallelSort" FILES ${parallelsort_shaders} source_group("Translucency" FILES ${translucency_src}) source_group("Translucency\\Config" FILES ${translucency_config}) source_group("Translucency\\Shaders" FILES ${translucency_shaders}) +source_group("Animated Textures" FILES ${animatedtextures_src}) +source_group("Animated Textures\\Shaders" FILES ${animatedtextures_shaders}) source_group("Lighting" FILES ${lighting_src}) source_group("Lighting\\Shaders" FILES ${lighting_shaders}) source_group("FPSLimiter" FILES ${limiter_src}) diff --git a/framework/rendermodules/animatedtextures/animatedtexturesrendermodule.cpp b/framework/rendermodules/animatedtextures/animatedtexturesrendermodule.cpp new file mode 100644 index 00000000..3245c275 --- /dev/null +++ b/framework/rendermodules/animatedtextures/animatedtexturesrendermodule.cpp @@ -0,0 +1,237 @@ +// AMD Cauldron code +// +// Copyright(c) 2020 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, sub-license, 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 "animatedtexturesrendermodule.h" +#include "core/framework.h" +#include "core/contentmanager.h" +#include "core/scene.h" +#include "core/loaders/textureloader.h" +#include "render/pipelineobject.h" +#include "render/rasterview.h" +#include "render/parameterset.h" +#include "render/profiler.h" + +using namespace cauldron; + +struct ConstantBufferData +{ + Mat4 CurrentViewProjection; + Mat4 PreviousViewProjection; + Vec2 CameraJitterCompensation; + float ScrollFactor; + float RotationFactor; + int Mode; + float pad[3]; +}; + +void AnimatedTexturesRenderModule::Init(const json& initData) +{ + // Root signature + RootSignatureDesc signatureDesc; + signatureDesc.AddConstantBufferView(0, ShaderBindStage::VertexAndPixel, 1); + signatureDesc.AddTextureSRVSet(0, ShaderBindStage::Pixel, 1); + SamplerDesc samplerDesc = {FilterFunc::Anisotropic, AddressMode::Wrap, AddressMode::Wrap, AddressMode::Wrap}; + signatureDesc.AddStaticSamplers(0, ShaderBindStage::Pixel, 1, &samplerDesc); + + m_pRootSignature = RootSignature::CreateRootSignature(L"AnimatedTextures_RootSignature", signatureDesc); + + // Fetch needed resources + m_pRenderTarget = GetFramework()->GetColorTargetForCallback(GetName()); + m_pMotionVectors = GetFramework()->GetRenderTexture(L"GBufferMotionVectorRT"); + m_pReactiveMask = GetFramework()->GetRenderTexture(L"ReactiveMask"); + m_pCompositionMask = GetFramework()->GetRenderTexture(L"TransCompMask"); + m_pDepthTarget = GetFramework()->GetRenderTexture(L"DepthTarget"); + CauldronAssert(ASSERT_CRITICAL, + m_pRenderTarget && m_pMotionVectors && m_pReactiveMask && m_pCompositionMask && m_pDepthTarget, + L"Could not get one of the needed resources for AnimatedTexturesRenderModule."); + + m_pRasterViews[0] = GetRasterViewAllocator()->RequestRasterView(m_pRenderTarget, ViewDimension::Texture2D); + m_pRasterViews[1] = GetRasterViewAllocator()->RequestRasterView(m_pMotionVectors, ViewDimension::Texture2D); + m_pRasterViews[2] = GetRasterViewAllocator()->RequestRasterView(m_pReactiveMask, ViewDimension::Texture2D); + m_pRasterViews[3] = GetRasterViewAllocator()->RequestRasterView(m_pCompositionMask, ViewDimension::Texture2D); + m_pRasterViews[4] = GetRasterViewAllocator()->RequestRasterView(m_pDepthTarget, ViewDimension::Texture2D); + + // Setup the pipeline object + PipelineDesc psoDesc; + psoDesc.SetRootSignature(m_pRootSignature); + + // Setup the shaders to build on the pipeline object + psoDesc.AddShaderDesc(ShaderBuildDesc::Vertex(L"AnimatedTexture.hlsl", L"VSMain", ShaderModel::SM6_0, nullptr)); + psoDesc.AddShaderDesc(ShaderBuildDesc::Pixel(L"AnimatedTexture.hlsl", L"PSMain", ShaderModel::SM6_0, nullptr)); + + BlendDesc blendDesc; + std::vector blends; + blends.push_back(blendDesc); + blendDesc.RenderTargetWriteMask = (uint32_t)ColorWriteMask::Red + (uint32_t)ColorWriteMask::Green; + blends.push_back(blendDesc); + blendDesc.RenderTargetWriteMask = 0; + blends.push_back(blendDesc); + blendDesc.RenderTargetWriteMask = (uint32_t)ColorWriteMask::Red; + blends.push_back(blendDesc); + psoDesc.AddBlendStates(blends, false, true); + + // Setup remaining information and build + DepthDesc depthDesc{}; + depthDesc.DepthEnable = true; + depthDesc.DepthFunc = ComparisonFunc::LessEqual; + psoDesc.AddDepthState(&depthDesc); // Use defaults + + RasterDesc rasterDesc{}; + rasterDesc.CullingMode = CullMode::None; + psoDesc.AddRasterStateDescription(&rasterDesc); + psoDesc.AddPrimitiveTopology(PrimitiveTopologyType::Triangle); + psoDesc.AddRasterFormats({m_pRenderTarget->GetFormat(), m_pMotionVectors->GetFormat(), m_pReactiveMask->GetFormat(), m_pCompositionMask->GetFormat()}, + ResourceFormat::D32_FLOAT); + + m_pPipelineObj = PipelineObject::CreatePipelineObject(L"AnimatedTextures_PipelineObj", psoDesc); + + // Create parameter set to bind constant buffer and texture + m_pParameters = ParameterSet::CreateParameterSet(m_pRootSignature); + m_pParameters->SetRootConstantBufferResource(GetDynamicBufferPool()->GetResource(), sizeof(ConstantBufferData), 0); + + // Load the texture data from which to create the texture + std::function&, void*)> CompletionCallback = + [this](const std::vector& textures, void* additionalParams) { this->TextureLoadComplete(textures, additionalParams); }; + std::experimental::filesystem::path texturePath = "media/textures"; + GetContentManager()->LoadTextures( + {TextureLoadInfo(texturePath / "lion.jpg"), TextureLoadInfo(texturePath / "checkerboard.dds"), TextureLoadInfo(texturePath / "composition_text.dds")}, + CompletionCallback); + + // UI + // Register UI for Tone mapping as part of post processing + m_UISection.SectionName = "Animated Textures"; + m_UISection.AddFloatSlider("Animation Speed", &m_Speed, 0.0f, 3.0f); + + GetUIManager()->RegisterUIElements(m_UISection); +} + +AnimatedTexturesRenderModule::~AnimatedTexturesRenderModule() +{ + delete m_pRootSignature; + delete m_pPipelineObj; + delete m_pParameters; +} + +void AnimatedTexturesRenderModule::TextureLoadComplete(const std::vector& textureList, void*) +{ + // Only the one texture + m_Textures = textureList; + + // We are now ready for use + SetModuleReady(true); +} + +void AnimatedTexturesRenderModule::Execute(double deltaTime, CommandList* pCmdList) +{ + GPUScopedProfileCapture sampleMarker(pCmdList, L"AnimatedTextures RM"); + + m_scrollFactor += (float)deltaTime * 1.0f * m_Speed; + m_rotationFactor += (float)deltaTime * 2.0f * m_Speed; + m_flipTimer += (float)deltaTime * 1.0f; + + if (m_scrollFactor > 10.0f) + m_scrollFactor -= 10.0f; + + const float twoPI = 6.283185307179586476925286766559f; + + if (m_rotationFactor > twoPI) + m_rotationFactor -= twoPI; + + size_t textureIndex = std::min((size_t)floorf(m_flipTimer * 0.33333f), m_Textures.size() - 1); + if (m_flipTimer > 9.0f) + m_flipTimer = 0.0f; + + const auto& camInfo = GetScene()->GetSceneInfo().CameraInfo; + auto cam = GetScene()->GetCurrentCamera(); + ConstantBufferData cbData; + cbData.CurrentViewProjection = camInfo.ViewProjectionMatrix; + cbData.PreviousViewProjection = camInfo.PrevViewProjectionMatrix; + Vec4 jitterComp = cam->GetPrevProjectionJittered().getCol2() - cam->GetProjectionJittered().getCol2(); + cbData.CameraJitterCompensation = Vec2(jitterComp.getX(), jitterComp.getY()); + cbData.ScrollFactor = m_scrollFactor; + cbData.RotationFactor = m_rotationFactor; + cbData.Mode = (int)textureIndex; + + // Set our texture to the right parameter slot + m_pParameters->SetTextureSRV(m_Textures[textureIndex], ViewDimension::Texture2D, 0); + + BufferAddressInfo bufferInfo = GetDynamicBufferPool()->AllocConstantBuffer(sizeof(cbData), &cbData); + m_pParameters->UpdateRootConstantBuffer(&bufferInfo, 0); + + // Render modules expect resources coming in/going out to be in a shader read state + std::vector barriers{}; + barriers.push_back(Barrier::Transition( + m_pRenderTarget->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::RenderTargetResource)); + barriers.push_back(Barrier::Transition( + m_pMotionVectors->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::RenderTargetResource)); + barriers.push_back(Barrier::Transition( + m_pReactiveMask->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::RenderTargetResource)); + barriers.push_back(Barrier::Transition( + m_pCompositionMask->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::RenderTargetResource)); + barriers.push_back(Barrier::Transition( + m_pDepthTarget->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::DepthRead)); + ResourceBarrier(pCmdList, (uint32_t)barriers.size(), barriers.data()); + barriers.clear(); + + BeginRaster(pCmdList, 4, m_pRasterViews.data(), m_pRasterViews[4]); + + UpscalerState upscaleState = GetFramework()->GetUpscalingState(); + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + + uint32_t width, height; + if (upscaleState == UpscalerState::None || upscaleState == UpscalerState::PostUpscale) + { + width = resInfo.DisplayWidth; + height = resInfo.DisplayHeight; + } + else + { + width = resInfo.RenderWidth; + height = resInfo.RenderHeight; + } + + Viewport vp = {0.f, 0.f, (float)width, (float)height, 0.f, 1.f}; + SetViewport(pCmdList, &vp); + Rect scissorRect = {0, 0, width, height}; + SetScissorRects(pCmdList, 1, &scissorRect); + + // Bind all parameters + m_pParameters->Bind(pCmdList, m_pPipelineObj); + + // Set pipeline and draw + SetPrimitiveTopology(pCmdList, PrimitiveTopology::TriangleStrip); + SetPipelineState(pCmdList, m_pPipelineObj); + + DrawInstanced(pCmdList, 4, 2, 0, 0); + + EndRaster(pCmdList); + + // Render modules expect resources coming in/going out to be in a shader read state + barriers.push_back(Barrier::Transition( + m_pRenderTarget->GetResource(), ResourceState::RenderTargetResource, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + barriers.push_back(Barrier::Transition( + m_pMotionVectors->GetResource(), ResourceState::RenderTargetResource, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + barriers.push_back(Barrier::Transition( + m_pReactiveMask->GetResource(), ResourceState::RenderTargetResource, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + barriers.push_back(Barrier::Transition( + m_pCompositionMask->GetResource(), ResourceState::RenderTargetResource, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + barriers.push_back(Barrier::Transition( + m_pDepthTarget->GetResource(), ResourceState::DepthRead, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + ResourceBarrier(pCmdList, (uint32_t)barriers.size(), barriers.data()); +} diff --git a/framework/rendermodules/animatedtextures/animatedtexturesrendermodule.h b/framework/rendermodules/animatedtextures/animatedtexturesrendermodule.h new file mode 100644 index 00000000..6f6d428c --- /dev/null +++ b/framework/rendermodules/animatedtextures/animatedtexturesrendermodule.h @@ -0,0 +1,68 @@ +// AMD Cauldron code +// +// Copyright(c) 2020 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, sub-license, 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 "render/rendermodule.h" +#include "core/uimanager.h" + +#include + +namespace cauldron +{ + class RootSignature; + class RasterView; + class ParameterSet; + class PipelineObject; + class RenderTarget; + class Texture; + class ResourceView; +} // namespace cauldron + +class AnimatedTexturesRenderModule : public cauldron::RenderModule +{ +public: + AnimatedTexturesRenderModule() : RenderModule(L"AnimatedTexturesRenderModule") {} + virtual ~AnimatedTexturesRenderModule(); + + virtual void Init(const json& initData) override; + virtual void Execute(double deltaTime, cauldron::CommandList* pCmdList) override; + +private: + // Callback for texture loading so we can mark ourselves "ready" + void TextureLoadComplete(const std::vector& textureList, void*); + + cauldron::RootSignature* m_pRootSignature = nullptr; + std::array m_pRasterViews = {}; + cauldron::PipelineObject* m_pPipelineObj = nullptr; + const cauldron::Texture* m_pRenderTarget = nullptr; + const cauldron::Texture* m_pMotionVectors = nullptr; + const cauldron::Texture* m_pReactiveMask = nullptr; + const cauldron::Texture* m_pCompositionMask = nullptr; + const cauldron::Texture* m_pDepthTarget = nullptr; + std::vector m_Textures = {}; + cauldron::ParameterSet* m_pParameters = nullptr; + + float m_scrollFactor = 0.0f; + float m_rotationFactor = 0.0f; + float m_flipTimer = 0.0f; + float m_Speed = 1.0f; + + // UI + cauldron::UISection m_UISection; +}; diff --git a/framework/rendermodules/animatedtextures/shaders/AnimatedTexture.hlsl b/framework/rendermodules/animatedtextures/shaders/AnimatedTexture.hlsl new file mode 100644 index 00000000..80340cbb --- /dev/null +++ b/framework/rendermodules/animatedtextures/shaders/AnimatedTexture.hlsl @@ -0,0 +1,131 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright © 2023 Advanced Micro Devices, Inc. +// +// 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. + +cbuffer cb : register(b0) +{ + matrix g_CurrentViewProjection; + matrix g_PreviousViewProjection; + float2 g_CameraJitterCompensation; + float g_ScrollFactor; + float g_RotationFactor; + int g_Mode; + int pad0; + int pad1; + int pad2; +} + + +Texture2D g_Texture : register(t0); +SamplerState g_Sampler : register(s0); + +struct VERTEX_OUT +{ + float4 CurrentPosition : TEXCOORD0; + float4 PreviousPosition : TEXCOORD1; + float3 TexCoord : TEXCOORD2; + float4 Position : SV_POSITION; +}; + + +VERTEX_OUT VSMain( uint vertexId : SV_VertexID, uint instanceId : SV_InstanceID ) +{ + VERTEX_OUT output = (VERTEX_OUT)0; + + const float2 offsets[ 4 ] = + { + float2( -1, 1 ), + float2( 1, 1 ), + float2( -1, -1 ), + float2( 1, -1 ), + }; + + float2 offset = offsets[ vertexId ]; + float2 uv = (offset+1)*float2( instanceId == 0 ? -0.5 : 0.5, -0.5 ); + + float4 worldPos = float4( offsets[ vertexId ], 0.0, 1.0 ); + + worldPos.xyz += instanceId == 0 ? float3( -13, 1.5, 2 ) : float3( -13, 1.5, -2 ); + + output.CurrentPosition = mul( g_CurrentViewProjection, worldPos ); + output.PreviousPosition = mul( g_PreviousViewProjection, worldPos ); + + output.Position = output.CurrentPosition; + + output.TexCoord.xy = uv; + output.TexCoord.z = instanceId; + + return output; +} + +struct Output +{ + float4 finalColor : SV_TARGET0; + float2 motionVectors : SV_TARGET1; + float upscaleReactive : SV_TARGET2; + float upscaleTransparencyAndComposition : SV_TARGET3; +}; + + +float4 TextureLookup( int billboardIndex, float2 uv0 ) +{ + float4 color = 1; + + if ( billboardIndex == 0 || g_Mode == 2 ) + { + // Scrolling + float2 uv = uv0; + if ( g_Mode == 2 ) + uv += float2( -g_ScrollFactor, 0.0 ); + else + uv += float2( -g_ScrollFactor, 0.5*g_ScrollFactor ); + + color.rgb = g_Texture.SampleLevel( g_Sampler, uv, 0 ).rgb; + } + else if ( billboardIndex == 1 ) + { + // Rotated UVs + float s, c; + sincos( g_RotationFactor, s, c ); + float2x2 rotation = { float2( c, s ), float2( -s, c ) }; + + float2 rotatedUV = mul( rotation, uv0-float2( 0.5, -0.5) ); + color.rgb = g_Texture.SampleLevel( g_Sampler, rotatedUV, 0 ).rgb; + } + + return color; +} + + +Output PSMain( VERTEX_OUT input ) +{ + Output output = (Output)0; + + output.finalColor = TextureLookup( (int)input.TexCoord.z, input.TexCoord.xy ); + + output.motionVectors = (input.PreviousPosition.xy / input.PreviousPosition.w) - (input.CurrentPosition.xy / input.CurrentPosition.w) + g_CameraJitterCompensation; + output.motionVectors *= float2(0.5f, -0.5f); + + output.upscaleReactive = 0; // Nothing to write to the reactice mask. Color writes are off on this target anyway. + output.upscaleTransparencyAndComposition = 1; // Write a value into here to indicate the depth and motion vectors are as expected for a static object, but the surface contents are changing. + + return output; +} \ No newline at end of file diff --git a/framework/rendermodules/gbuffer/config/gbufferrendermodule.json b/framework/rendermodules/gbuffer/config/gbufferrendermodule.json index 68d99953..0aeb529f 100644 --- a/framework/rendermodules/gbuffer/config/gbufferrendermodule.json +++ b/framework/rendermodules/gbuffer/config/gbufferrendermodule.json @@ -4,19 +4,19 @@ "RenderResources": { "MotionVectorTarget": { "Format": "RG16_FLOAT", - "RenderResolution": true + "RenderResolution": false }, "GBufferAlbedoTarget": { "Format": "RGBA8_UNORM", - "RenderResolution": true + "RenderResolution": false }, "GBufferNormalTarget": { "Format": "RGBA16_FLOAT", - "RenderResolution": true + "RenderResolution": false }, "GBufferAoRoughnessMetallicTarget": { "Format": "RGBA8_UNORM", - "RenderResolution": true, + "RenderResolution": false, "AllowUAV": true }, diff --git a/framework/rendermodules/gbuffer/shaders/gbufferps.hlsl b/framework/rendermodules/gbuffer/shaders/gbufferps.hlsl index 182b5042..f7456be5 100644 --- a/framework/rendermodules/gbuffer/shaders/gbufferps.hlsl +++ b/framework/rendermodules/gbuffer/shaders/gbufferps.hlsl @@ -66,7 +66,7 @@ struct GBufferOutput { float4 BaseColorAlpha : SV_Target0; float4 Normals : SV_Target1; - float3 AoRoughnessMetallic : SV_Target2; + float4 AoRoughnessMetallic : SV_Target2; #ifdef HAS_MOTION_VECTORS_RT float2 MotionVectors : TARGET(HAS_MOTION_VECTORS_RT); #endif // HAS_MOTION_VECTORS_RT @@ -106,7 +106,7 @@ GBufferOutput MainPS(VS_SURFACE_OUTPUT SurfaceInput #endif // HAS_MOTION_VECTORS_RT GBuffer.BaseColorAlpha = BaseColorAlpha; - GBuffer.AoRoughnessMetallic = AoRoughnessMetallic; + GBuffer.AoRoughnessMetallic = float4(AoRoughnessMetallic, 0.f); GBuffer.AoRoughnessMetallic.r = 1.0f; // Temp for SSAO float3 normals = GetPixelNormal(SurfaceInput, Textures, SceneInfo, AllTextures, AllSamplers, SceneInfo.MipLODBias, isFrontFace); diff --git a/framework/rendermodules/rendermoduleregistry.cpp b/framework/rendermodules/rendermoduleregistry.cpp index c8afbdf4..43cdc273 100644 --- a/framework/rendermodules/rendermoduleregistry.cpp +++ b/framework/rendermodules/rendermoduleregistry.cpp @@ -33,6 +33,7 @@ #include "skydome/skydomerendermodule.h" #include "taa/taarendermodule.h" #include "translucency/translucencyrendermodule.h" +#include "animatedtextures/animatedtexturesrendermodule.h" using namespace cauldron; namespace rendermodule @@ -48,6 +49,7 @@ namespace rendermodule RenderModuleFactory::RegisterModule("RasterShadowRenderModule"); RenderModuleFactory::RegisterModule("TAARenderModule"); RenderModuleFactory::RegisterModule("TranslucencyRenderModule"); + RenderModuleFactory::RegisterModule("AnimatedTexturesRenderModule"); } } // namespace rendermodule diff --git a/framework/rendermodules/taa/taarendermodule.cpp b/framework/rendermodules/taa/taarendermodule.cpp index 5786e919..40f8f1da 100644 --- a/framework/rendermodules/taa/taarendermodule.cpp +++ b/framework/rendermodules/taa/taarendermodule.cpp @@ -76,16 +76,16 @@ void TAARenderModule::Execute(double deltaTime, cauldron::CommandList* pCmdList) if (!m_bEnableTaa) { // Disable Jitter - GetScene()->GetCurrentCamera()->SetJitterValues({0, 0}); + //GetScene()->GetCurrentCamera()->SetJitterValues({0, 0}); m_bFirst = true; return; } - else + /*else { Vec2 jitterValues = CalculateJitterOffsets(m_pTAAOutputBuffer->GetDesc().Width, m_pTAAOutputBuffer->GetDesc().Height, s_Seed); GetScene()->GetCurrentCamera()->SetJitterValues(jitterValues); - } + }*/ GPUScopedProfileCapture tonemappingMarker(pCmdList, L"TAA"); @@ -168,8 +168,14 @@ void TAARenderModule::EnableModule(bool enabled) if (enabled) { - Vec2 jitterValues = CalculateJitterOffsets(m_pTAAOutputBuffer->GetDesc().Width, m_pTAAOutputBuffer->GetDesc().Height, s_Seed); - GetScene()->GetCurrentCamera()->SetJitterValues(jitterValues); + // Set the jitter callback to use + CameraJitterCallback jitterCallback = [this](Vec2& values) { + values = CalculateJitterOffsets(m_pTAAOutputBuffer->GetDesc().Width, m_pTAAOutputBuffer->GetDesc().Height, s_Seed); + }; + CameraComponent::SetJitterCallbackFunc(jitterCallback); + + /*Vec2 jitterValues = CalculateJitterOffsets(m_pTAAOutputBuffer->GetDesc().Width, m_pTAAOutputBuffer->GetDesc().Height, s_Seed); + GetScene()->GetCurrentCamera()->SetJitterValues(jitterValues);*/ m_bFirst = true; // Re-enable UI @@ -177,6 +183,8 @@ void TAARenderModule::EnableModule(bool enabled) } else { + CameraComponent::SetJitterCallbackFunc(nullptr); + // Disable the UI GetUIManager()->UnRegisterUIElements(m_UISection); } diff --git a/readme.md b/readme.md index e889f92e..e3f45d2b 100644 --- a/readme.md +++ b/readme.md @@ -1,35 +1,20 @@ -

    Welcome to the AMD FidelityFX SDK

    +

    Welcome to the FidelityFX Super Resolution 3 SDK

    ![alt text](/docs/media/fidelityfxsdk-logo-rescaled.png) The FidelityFX SDK is a collection of heavily optimized, open source technologies (shader and runtime code) that can be used by developers to improve their DirectX®12 or Vulkan® applications. -The FidelityFX SDK includes: +This release of the FidelityFX SDK includes: | [FidelityFX SDK](https://gpuopen.com/amd-fidelityfx-sdk/) Technique | [Samples](/docs/samples/index.md) | [GPUOpen](https://gpuopen.com/) page | Description | | --- | --- | --- | --- | -| [Combined Adaptive Compute Ambient Occlusion (CACAO)](/docs/techniques/combined-adaptive-compute-ambient-occlusion.md) 1.3 | [CACAO sample](/docs/samples/combined-adaptive-compute-ambient-occlusion.md) | [FidelityFX Ambient Occlusion](https://gpuopen.com/fidelityfx-cacao/) | Uses intelligent and adaptive sampling techniques to produce excellent quality ambient occlusion at high performance. | -| [Contrast Adaptive Sharpening (CAS)](/docs/techniques/contrast-adaptive-sharpening.md) 1.1 | [CAS sample](/docs/samples/contrast-adaptive-sharpening.md) | [FidelityFX Contrast Adaptive Sharpening](https://gpuopen.com/fidelityfx-cas/) | Implements a sharpening kernel that reclaims that high-frequency detail lost during rendering. | -| [Denoiser](/docs/techniques/denoiser.md) 1.2 | n/a | [FidelityFX Denoiser](https://gpuopen.com/fidelityfx-denoiser/) | Provides a set of denoising compute shaders which remove artifacts from reflection and shadow rendering. Useful for both raytraced or rasterized content. | -| [Classifier](/docs/techniques/classifier.md) 1.0 | n/a | n/a | Provides a set of tile classification compute shaders which prepare tile metadata to drive indirect workload generation. It's useful for guided and load-balanced ray tracing applications, letting you leverage ray tracing in an efficient manner. | -| [Luminance Preserving Mapper](/docs/techniques/luminance-preserving-mapper.md) 1.3 | [LPM sample](/docs/samples/luminance-preserving-mapper.md) | [FidelityFX HDR Mapper](https://gpuopen.com/fidelityfx-lpm/) | Offers a tone mapping and gamut mapping solution for HDR and wide gamut content. | -| [Parallel Sort](/docs/techniques/parallel-sort.md) 1.2 | [Parallel Sort sample](/docs/samples/parallel-sort.md) | [FidelityFX Parallel Sort](https://gpuopen.com/fidelityfx-parallel-sort/) | Implements GPU-accelerated parallel sorting techniques. The sorts are stable useful for sorting particles or other GPU-side data sets. | -| [Single Pass Downsampler](/docs/techniques/single-pass-downsampler.md) 2.1 | [SPD sample](/docs/samples/single-pass-downsampler.md) | [FidelityFX Downsampler](https://gpuopen.com/fidelityfx-spd/) | Allows you to downsample surfaces - and optionally generate a MIPmap chain - in a single compute dispatch. | -| [Stochastic Screen-Space Reflections](/docs/techniques/stochastic-screen-space-reflections.md) 1.4 | [SSSR sample](/docs/samples/stochastic-screen-space-reflections.md) | [FidelityFX Screen Space Reflections](https://gpuopen.com/fidelityfx-sssr/) | Provides high-fidelity screen-spaced reflections in your scene, without a hefty performance price tag. | -| [Super Resolution (Spatial)](/docs/techniques/super-resolution-spatial.md) 1.1 | [Super Resolution sample](/docs/samples/super-resolution.md) | [FidelityFX Super Resolution](https://gpuopen.com/fidelityfx-superresolution/) | Offers a spatial single-frame solution for producing higher resolution frames from lower resolution inputs. | -| [Super Resolution (Temporal)](/docs/techniques/super-resolution-temporal.md) 2.2.1 | [Super Resolution sample](/docs/samples/super-resolution.md) | [FidelityFX Super Resolution 2](https://gpuopen.com/fidelityfx-superresolution-2/) | Offers both spatial single-frame and temporal multi-frame solutions for producing high resolution frames from lower resolution inputs. | -| [Variable Shading](/docs/techniques/variable-shading.md) 1.1 | [Variable Shading sample](/docs/samples/variable-shading.md) | [FidelityFX Variable Shading](https://gpuopen.com/fidelityfx-variable-shading/) | Helps you to drive Variable Rate Shading hardware introduced in RDNA2-based and contemporary GPUs, by analyzing the luminance of pixels in a tile to determine where the shading rate can be lowered to increase performance. | -| New: [Blur](/docs/samples/blur.md) 1.0 | [Blur sample](/docs/samples/blur.md) | [FidelityFX Blur](https://gpuopen.com/fidelityfx-blur/) | A library of highly optimized functions which perform common blurring operations such as Gaussian blur, radial blurs, and others. | -| New: [Depth-of-Field](/docs/techniques/depth-of-field.md) 1.0 | [DoF sample](/docs/samples/depth-of-field.md) | [FidelityFX Depth of Field](https://gpuopen.com/fidelityfx-dof/) | Implements a high-quality DOF filter complete with bokeh. | -| New: [Lens](/docs/samples/lens.md) 1.0 | [Lens sample](/docs/samples/lens.md) | [FidelityFX Lens](https://gpuopen.com/fidelityfx-lens/) | Implements a library of optimized lens effects including chromatic aberration, film grain, and vignetting. | -| [Classifier (Shadows)](/docs/techniques/classifier.md) 1.1 [Denoiser (Shadows)](/docs/techniques/denoiser.md) 1.2 | [Hybrid Shadows sample](/docs/samples/hybrid-shadows.md) 1.1 | [FidelityFX Hybrid Shadows](https://gpuopen.com/fidelityfx-hybrid-shadows/) | An implementation of an example shadowing technique which shows you how you could combine rasterized shadow maps and hardware ray tracing to deliver high quality soft shadows at a reasonable performance cost. | -| [Classifier (Reflections)](/docs/techniques/classifier.md) 1.1 [Denoiser (Reflections)](/docs/techniques/denoiser.md) 1.2 | [Hybrid Reflections sample](/docs/samples/hybrid-reflections.md) 1.1 | [FidelityFX Hybrid Reflections](https://gpuopen.com/fidelityfx-hybrid-reflections/) | An implementation of an an example reflections technique which shows you how you could mix FidelityFX SSSR with ray traced reflections, delivering higher quality reflections than SSSR alone at reasonable performance cost. | +| [Super Resolution (Interpolation enabled)](/docs/techniques/super-resolution-interpolation.md) 3.0.3 | [Super Resolution sample](/docs/samples/super-resolution.md) | [FidelityFX Super Resolution 3](https://gpuopen.com/fidelityfx-superresolution-3/) | Offers a solution for producing high resolution frames from lower resolution inputs and generating interpolated frames. | +| [Optical Flow](/docs/techniques/optical-flow.md) 1.0 | [Super Resolution sample](/docs/samples/super-resolution.md) | [FidelityFX Super Resolution 3](https://gpuopen.com/fidelityfx-superresolution-3/) | Estimates the motion between the current and the previous scene inputs. | +| [Frame Interpolation](/docs/techniques/frame-interpolation.md) 1.0 | [Super Resolution sample](/docs/samples/super-resolution.md) | [FidelityFX Super Resolution 3](https://gpuopen.com/fidelityfx-superresolution-3/) | Generates an image half way between the previous and the current frame. | +| [Frame Interpolation Swap Chain](/docs/techniques/frame-interpolation-swap-chain.md) 1.0 | [Super Resolution sample](/docs/samples/super-resolution.md) | [FidelityFX Super Resolution 3](https://gpuopen.com/fidelityfx-superresolution-3/) | Proxy swap chain to replace the DXGI swap chain and handle frame pacing, UI composition and presentation. |

    Further information

    -- [What's new in FidelityFX SDK](/docs/whats-new/index.md) - - [FidelityFX SDK 1.0](/docs/whats-new/index.md) - - [Getting started](/docs/getting-started/index.md) - [Overview](/docs/getting-started/index.md) - [SDK structure](/docs/getting-started/sdk-structure.md) @@ -41,14 +26,17 @@ The FidelityFX SDK includes: - [Shader Precompiler](/docs/tools/ffx-sc.md) - [FidelityFX SDK Media Delivery System](/docs/media-delivery.md) +- Additional notes + - At this time, FSR3 only supports use of the native DirectX®12 backend. Please use [BuildFSRSolutionNative.bat](#BuildFSRSolutionNative.bat) or [BuildFSRSolutionNativeDll.bat](#BuildFSRSolutionNativeDll.bat) to build the backend and generate a solution for the sample. + - Some combinations of high-refresh rate monitors and graphics cards may not support VRR behaviour at the top range of the monitor's refresh rate. You may therefore have to set your monitor's max refresh rate to a value where VRR is supported. + - The GPU limiter in the sample can result in poor frame pacing at low frame rates. It is recommended to use the CPU limiter in all scenarios when examining FSR3 in the sample. +

    Known issues

    | FidelityFX SDK Sample | API / Configuration | Problem Description | | --- | --- | --- | -| FidelityFX LPM | Vulkan / All configurations | When rapidly pressing alt-enter to go to full screen mode and back, the HDR display handle can occasionally become lost leading to a dim screen until another full screen toggle is applied again. | -| FidelityFX Hybrid Shadows / FidelityFX FSR | Vulkan / All configurations | Due to resource view handling in the native Vulkan backend, the ability to change the number of cascades on a directional light in Vulkan samples has been disabled to prevent sample instability. | -| FidelityFX DOF | All APIs / All Configs | Some artifacts may occur on some Intel Arc GPUs. | -| All FidelityFX SDK Samples | All APIs / All Configs | There is a resource leak in the UploadContext used to load glTF content. | +| FidelityFX FSR | Vulkan® | Vulkan support is in development and will be released in a future version. | +| FidelityFX FSR | Cauldron | The Cauldron backend is not supported by FSR3. |

    Open source

    diff --git a/samples/blur/CMakeLists.txt b/samples/blur/CMakeLists.txt index 7ca8cd50..27013cd4 100644 --- a/samples/blur/CMakeLists.txt +++ b/samples/blur/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/samples/blur/blurrendermodule.cpp b/samples/blur/blurrendermodule.cpp index acf69625..6cfa9b6a 100644 --- a/samples/blur/blurrendermodule.cpp +++ b/samples/blur/blurrendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "blurrendermodule.h" #include "validation_remap.h" @@ -272,7 +272,7 @@ void BlurRenderModule::InitPipelines() { // Initialize the FFX backend size_t scratchBufferSize = ffxGetScratchMemorySize(2 * FFX_BLUR_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_BackendInterface, GetDevice(), scratchBuffer, scratchBufferSize, 2 * FFX_BLUR_CONTEXT_COUNT); FFX_ASSERT(errorCode == FFX_OK); diff --git a/samples/blur/blurrendermodule.h b/samples/blur/blurrendermodule.h index c0db5cbf..34116214 100644 --- a/samples/blur/blurrendermodule.h +++ b/samples/blur/blurrendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "render/rendermodule.h" diff --git a/samples/blur/shaders/blur_baseline_filters_cs.hlsl b/samples/blur/shaders/blur_baseline_filters_cs.hlsl index 1bd5dec4..6e71a06a 100644 --- a/samples/blur/shaders/blur_baseline_filters_cs.hlsl +++ b/samples/blur/shaders/blur_baseline_filters_cs.hlsl @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // Generic blur CS dispatch dimensions - FFX-Blur uses its own #define THREADGROUP_DIMENSION_X 8 #define THREADGROUP_DIMENSION_Y 8 diff --git a/samples/blur/shaders/blur_compare_filters_cs.hlsl b/samples/blur/shaders/blur_compare_filters_cs.hlsl index 42ca898d..86ed1dc8 100644 --- a/samples/blur/shaders/blur_compare_filters_cs.hlsl +++ b/samples/blur/shaders/blur_compare_filters_cs.hlsl @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + //-------------------------------------------------------------------------------------- // PLATFORM / PORTABILITY SETUP //-------------------------------------------------------------------------------------- diff --git a/samples/blur/shaders/blur_gaussian_blur_kernels.h b/samples/blur/shaders/blur_gaussian_blur_kernels.h index 2deb7e71..144c09bb 100644 --- a/samples/blur/shaders/blur_gaussian_blur_kernels.h +++ b/samples/blur/shaders/blur_gaussian_blur_kernels.h @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // KERNEL_RANGE is center + half width of the kernel // // consider a blur kernel 5x5 - '*' indicates the center of the kernel diff --git a/samples/cacao/CMakeLists.txt b/samples/cacao/CMakeLists.txt index ef49d9a2..5ff2fed3 100644 --- a/samples/cacao/CMakeLists.txt +++ b/samples/cacao/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/cacao/cacaorendermodule.cpp b/samples/cacao/cacaorendermodule.cpp index cf98accd..f21aa62f 100644 --- a/samples/cacao/cacaorendermodule.cpp +++ b/samples/cacao/cacaorendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "cacaorendermodule.h" #include "validation_remap.h" @@ -203,7 +203,7 @@ void CACAORenderModule::Execute(double deltaTime, CommandList* pCmdList) void CACAORenderModule::InitContext() { const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_CACAO_CONTEXT_COUNT * 2); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_FfxInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_CACAO_CONTEXT_COUNT * 2); CauldronAssert(ASSERT_CRITICAL, errorCode == FFX_OK, L"Could not initialize FidelityFX SDK backend context."); diff --git a/samples/cacao/cacaorendermodule.h b/samples/cacao/cacaorendermodule.h index b6fff074..4704ffdc 100644 --- a/samples/cacao/cacaorendermodule.h +++ b/samples/cacao/cacaorendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "render/rendermodule.h" diff --git a/samples/cacao/cacaosample.cpp b/samples/cacao/cacaosample.cpp index 793a7d63..c6e69a0c 100644 --- a/samples/cacao/cacaosample.cpp +++ b/samples/cacao/cacaosample.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "cacaosample.h" #include "misc/fileio.h" #include "rendermoduleregistry.h" diff --git a/samples/cacao/cacaosample.h b/samples/cacao/cacaosample.h index bcb26bea..a428cf90 100644 --- a/samples/cacao/cacaosample.h +++ b/samples/cacao/cacaosample.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "core/framework.h" diff --git a/samples/cacao/shaders/display_ssao.hlsl b/samples/cacao/shaders/display_ssao.hlsl index 914c8607..72ceffc9 100644 --- a/samples/cacao/shaders/display_ssao.hlsl +++ b/samples/cacao/shaders/display_ssao.hlsl @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + /********************************************************************** Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. diff --git a/samples/cas/CMakeLists.txt b/samples/cas/CMakeLists.txt index e39184c6..97fddf41 100644 --- a/samples/cas/CMakeLists.txt +++ b/samples/cas/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/cas/casrendermodule.cpp b/samples/cas/casrendermodule.cpp index 125bca43..6f2274f4 100644 --- a/samples/cas/casrendermodule.cpp +++ b/samples/cas/casrendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "casrendermodule.h" #include "validation_remap.h" @@ -57,7 +57,7 @@ void CASRenderModule::Init(const json& initData) // Setup Cauldron FidelityFX interface. const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_CAS_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_CAS_CONTEXT_COUNT); FFX_ASSERT(errorCode == FFX_OK); diff --git a/samples/cas/casrendermodule.h b/samples/cas/casrendermodule.h index 6e43c105..718b4c9f 100644 --- a/samples/cas/casrendermodule.h +++ b/samples/cas/casrendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "render/rendermodule.h" diff --git a/samples/dof/CMakeLists.txt b/samples/dof/CMakeLists.txt index 24ee6ef3..1d01fcc3 100644 --- a/samples/dof/CMakeLists.txt +++ b/samples/dof/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/dof/dofrendermodule.cpp b/samples/dof/dofrendermodule.cpp index 55ef1f5c..3f079d00 100644 --- a/samples/dof/dofrendermodule.cpp +++ b/samples/dof/dofrendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "dofrendermodule.h" #include "validation_remap.h" @@ -61,7 +61,7 @@ void DoFRenderModule::Init(const json&) // Init effect // Setup FidelityFX interface. const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_DOF_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_DOF_CONTEXT_COUNT); FFX_ASSERT(errorCode == FFX_OK); diff --git a/samples/dof/dofrendermodule.h b/samples/dof/dofrendermodule.h index 460cce0e..efd5a5ed 100644 --- a/samples/dof/dofrendermodule.h +++ b/samples/dof/dofrendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "render/rendermodule.h" diff --git a/samples/ffx_cauldron/CMakeLists.txt b/samples/ffx_cauldron/CMakeLists.txt index ac89a36e..b7c31a1c 100644 --- a/samples/ffx_cauldron/CMakeLists.txt +++ b/samples/ffx_cauldron/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# +# 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 +# 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 @@ -48,7 +47,7 @@ function(compile_shaders EXECUTABLE GLSL_SWITCH ADDITIONAL_BASE_ARGS PERMUTATION endforeach(INC) set(CAULDRON_BASE_ARGS - -compiler=glslang -e CS --target-env vulkan1.1 -S comp -Os -DFFX_GLSL=1) + -compiler=glslang --target-env vulkan1.1 -Os -DFFX_GLSL=1) # These don't really have an equivalent in GLSL set(CAULDRON_WAVE64_ARGS "") set(CAULDRON_WAVE32_ARGS "") @@ -62,12 +61,18 @@ function(compile_shaders EXECUTABLE GLSL_SWITCH ADDITIONAL_BASE_ARGS PERMUTATION list(APPEND COMPILE_INCLUDE_ARGS "-I ${INC}") endforeach(INC) + # HLSL requires -I -I etc. + set(COMPILE_INCLUDE_ARGS ) + foreach(INC ${INCLUDES_ARGS}) + list(APPEND COMPILE_INCLUDE_ARGS "-I ${INC}") + endforeach(INC) + set(CAULDRON_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(CAULDRON_WAVE64_ARGS - "-DFFX_PREFER_WAVE64=\"[WaveSize(64)]\"" -T cs_6_6) + "-DFFX_PREFER_WAVE64=\"[WaveSize(64)]\"" -T cs_6_6 -DFFX_HLSL_SM=66) set(CAULDRON_WAVE32_ARGS - -T cs_6_2) + -T cs_6_2 -DFFX_HLSL_SM=62) set(CAULDRON_FLOAT16_ARGS -enable-16bit-types) endif() @@ -89,90 +94,98 @@ function(compile_shaders EXECUTABLE GLSL_SWITCH ADDITIONAL_BASE_ARGS PERMUTATION set(WAVE32_16BIT_PERMUTATION_HEADER ${FFX_PASS_SHADER_OUTPUT_PATH}/${PASS_SHADER_TARGET}_16bit_permutations.h) set(WAVE64_16BIT_PERMUTATION_HEADER ${FFX_PASS_SHADER_OUTPUT_PATH}/${PASS_SHADER_TARGET}_wave64_16bit_permutations.h) - # combine base and permutation args - set(SC_ARGS ${BASE_ARGS} ${CAULDRON_BASE_ARGS} ${PERMUTATION_ARGS}) - - if (USE_DEPFILE) - # Wave32 - add_custom_command( - OUTPUT ${WAVE32_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME} -DFFX_HALF=0 ${CAULDRON_WAVE32_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS ${PASS_SHADER} - DEPFILE ${WAVE32_PERMUTATION_HEADER}.d - ) - list(APPEND PERMUTATION_OUTPUTS ${WAVE32_PERMUTATION_HEADER}) - - # Wave64 - add_custom_command( - OUTPUT ${WAVE64_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64 -DFFX_HALF=0 ${CAULDRON_WAVE64_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS ${PASS_SHADER} - DEPFILE ${WAVE64_PERMUTATION_HEADER}.d - ) - list(APPEND PERMUTATION_OUTPUTS ${WAVE64_PERMUTATION_HEADER}) - - # Wave32 16-bit - message(STATUS COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE32_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER}) - add_custom_command( - OUTPUT ${WAVE32_16BIT_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE32_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS ${PASS_SHADER} - DEPFILE ${WAVE32_16BIT_PERMUTATION_HEADER}.d - ) - list(APPEND PERMUTATION_OUTPUTS ${WAVE32_16BIT_PERMUTATION_HEADER}) - - # Wave64 16-bit - message(STATUS COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE64_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER}) - add_custom_command( - OUTPUT ${WAVE64_16BIT_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE64_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS ${PASS_SHADER} - DEPFILE ${WAVE64_16BIT_PERMUTATION_HEADER}.d - ) - list(APPEND PERMUTATION_OUTPUTS ${WAVE64_16BIT_PERMUTATION_HEADER}) - - else() - # Wave32 - add_custom_command( - OUTPUT ${WAVE32_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME} -DFFX_HALF=0 ${CAULDRON_WAVE32_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS ${PASS_SHADER} - ) - list(APPEND PERMUTATION_OUTPUTS ${WAVE32_PERMUTATION_HEADER}) - - # Wave64 - add_custom_command( - OUTPUT ${WAVE64_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64 -DFFX_HALF=0 ${CAULDRON_WAVE64_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS ${PASS_SHADER} - ) - list(APPEND PERMUTATION_OUTPUTS ${WAVE64_PERMUTATION_HEADER}) - - # Wave32 16-bit - message(STATUS COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE32_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER}) - add_custom_command( - OUTPUT ${WAVE32_16BIT_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE32_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS ${PASS_SHADER} - ) - list(APPEND PERMUTATION_OUTPUTS ${WAVE32_16BIT_PERMUTATION_HEADER}) - - # Wave64 16-bit - message(STATUS COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE64_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER}) - add_custom_command( - OUTPUT ${WAVE64_16BIT_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE64_ARGS} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS ${PASS_SHADER} - ) - list(APPEND PERMUTATION_OUTPUTS ${WAVE64_16BIT_PERMUTATION_HEADER}) + if (GLSL_SWITCH) + set(SC_SHADER_TYPE_WAVE32 -e CS -S comp) + set(SC_SHADER_TYPE_WAVE64 -e CS -S comp) + else() + set(SC_SHADER_TYPE_WAVE32 -E CS -T cs_6_2) + set(SC_SHADER_TYPE_WAVE64 -E CS -T cs_6_6) + endif() + + # combine base and permutation args + set(SC_ARGS ${BASE_ARGS} ${CAULDRON_BASE_ARGS} ${PERMUTATION_ARGS}) + + if (USE_DEPFILE) + # Wave32 + add_custom_command( + OUTPUT ${WAVE32_PERMUTATION_HEADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME} -DFFX_HALF=0 ${CAULDRON_WAVE32_ARGS} ${SC_SHADER_TYPE_WAVE32} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${PASS_SHADER} + DEPFILE ${WAVE32_PERMUTATION_HEADER}.d + ) + list(APPEND PERMUTATION_OUTPUTS ${WAVE32_PERMUTATION_HEADER}) + + # Wave64 + add_custom_command( + OUTPUT ${WAVE64_PERMUTATION_HEADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64 -DFFX_HALF=0 ${CAULDRON_WAVE64_ARGS} ${SC_SHADER_TYPE_WAVE64} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${PASS_SHADER} + DEPFILE ${WAVE64_PERMUTATION_HEADER}.d + ) + list(APPEND PERMUTATION_OUTPUTS ${WAVE64_PERMUTATION_HEADER}) + + # Wave32 16-bit + message(STATUS COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE32_ARGS} ${SC_SHADER_TYPE_WAVE32} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER}) + add_custom_command( + OUTPUT ${WAVE32_16BIT_PERMUTATION_HEADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE32_ARGS} ${SC_SHADER_TYPE_WAVE32} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${PASS_SHADER} + DEPFILE ${WAVE32_16BIT_PERMUTATION_HEADER}.d + ) + list(APPEND PERMUTATION_OUTPUTS ${WAVE32_16BIT_PERMUTATION_HEADER}) + + # Wave64 16-bit + message(STATUS COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE64_ARGS} ${SC_SHADER_TYPE_WAVE64} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER}) + add_custom_command( + OUTPUT ${WAVE64_16BIT_PERMUTATION_HEADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE64_ARGS} ${SC_SHADER_TYPE_WAVE64} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${PASS_SHADER} + DEPFILE ${WAVE64_16BIT_PERMUTATION_HEADER}.d + ) + list(APPEND PERMUTATION_OUTPUTS ${WAVE64_16BIT_PERMUTATION_HEADER}) + + else() + # Wave32 + add_custom_command( + OUTPUT ${WAVE32_PERMUTATION_HEADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME} -DFFX_HALF=0 ${CAULDRON_WAVE32_ARGS} ${SC_SHADER_TYPE_WAVE32} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${PASS_SHADER} + ) + list(APPEND PERMUTATION_OUTPUTS ${WAVE32_PERMUTATION_HEADER}) + + # Wave64 + add_custom_command( + OUTPUT ${WAVE64_PERMUTATION_HEADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64 -DFFX_HALF=0 ${CAULDRON_WAVE64_ARGS} ${SC_SHADER_TYPE_WAVE64} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${PASS_SHADER} + ) + list(APPEND PERMUTATION_OUTPUTS ${WAVE64_PERMUTATION_HEADER}) + + # Wave32 16-bit + message(STATUS COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE32_ARGS} ${SC_SHADER_TYPE_WAVE32} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER}) + add_custom_command( + OUTPUT ${WAVE32_16BIT_PERMUTATION_HEADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE32_ARGS} ${SC_SHADER_TYPE_WAVE32} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${PASS_SHADER} + ) + list(APPEND PERMUTATION_OUTPUTS ${WAVE32_16BIT_PERMUTATION_HEADER}) + + # Wave64 16-bit + message(STATUS COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE64_ARGS} ${SC_SHADER_TYPE_WAVE64} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER}) + add_custom_command( + OUTPUT ${WAVE64_16BIT_PERMUTATION_HEADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit -DFFX_HALF=1 ${CAULDRON_FLOAT16_ARGS} ${CAULDRON_WAVE64_ARGS} ${SC_SHADER_TYPE_WAVE64} ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${PASS_SHADER} + ) + list(APPEND PERMUTATION_OUTPUTS ${WAVE64_16BIT_PERMUTATION_HEADER}) endif() endforeach(PASS_SHADER) @@ -192,11 +205,11 @@ endmacro() #TODO: only grab files for features being built (i.e. if (FFX_FSR1 OR FFX_ALL) ... if (FFX_SPD or FFX_ALL) file(GLOB PUBLIC_SHADERS - FFX_PUBLIC_SHADER_SOURCES + FFX_PUBLIC_SHADER_SOURCES "${FFX_GPU_PATH}/fsr2/*.h" "${FFX_GPU_PATH}/fsr2/*.hlsl" "${FFX_GPU_PATH}/fsr2/*.glsl" - "${FFX_GPU_PATH}/fsr1/*.h" + "${FFX_GPU_PATH}/fsr1/*.h" "${FFX_GPU_PATH}/fsr1/*.hlsl" "${FFX_GPU_PATH}/fsr1/*.glsl" "${FFX_GPU_PATH}/spd/*.h" @@ -250,12 +263,12 @@ file(GLOB PRIVATE_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") if (FFX_FSR OR FFX_ALL) - set(FFX_FSR_PRIVATE_SOURCE - "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr1_shaderblobs.h" - "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr1_shaderblobs.cpp" - "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr2_shaderblobs.h" - "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr2_shaderblobs.cpp") - list(APPEND PRIVATE_SOURCE ${FFX_FSR_PRIVATE_SOURCE}) + set(FFX_FSR_PRIVATE_SOURCE + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr1_shaderblobs.h" + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr1_shaderblobs.cpp" + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr2_shaderblobs.h" + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr2_shaderblobs.cpp") + list(APPEND PRIVATE_SOURCE ${FFX_FSR_PRIVATE_SOURCE}) endif() if (FFX_SPD OR FFX_ALL) @@ -378,7 +391,8 @@ get_filename_component(FFX_PASS_SHADER_OUTPUT_PATH_DXIL ${CMAKE_CURRENT_BINARY_D get_filename_component(FFX_PASS_SHADER_OUTPUT_PATH_SPIRV ${CMAKE_CURRENT_BINARY_DIR}/../shaders/cauldron/vk ABSOLUTE) target_include_directories(ffx_backend_cauldron_${FFX_PLATFORM_NAME} PUBLIC ${FFX_INCLUDE_PATH}) -target_include_directories(ffx_backend_cauldron_${FFX_PLATFORM_NAME} PUBLIC $<$,$>:${FFX_PASS_SHADER_OUTPUT_PATH_DXIL}>$<$,$>:${FFX_PASS_SHADER_OUTPUT_PATH_SPIRV}>) +# CUSTOM_CHANGES_TO_FSR3 Build FSR3 DLL with RelWithDebInfo configuration +target_include_directories(ffx_backend_cauldron_${FFX_PLATFORM_NAME} PUBLIC $<$,$,$>:${FFX_PASS_SHADER_OUTPUT_PATH_DXIL}>$<$,$>:${FFX_PASS_SHADER_OUTPUT_PATH_SPIRV}>) target_include_directories(ffx_backend_cauldron_${FFX_PLATFORM_NAME} PRIVATE ${FFX_COMPONENTS_PATH}) target_include_directories(ffx_backend_cauldron_${FFX_PLATFORM_NAME} PRIVATE ${FFX_SHARED_PATH}) target_include_directories(ffx_backend_cauldron_${FFX_PLATFORM_NAME} PRIVATE "${FFX_SRC_BACKENDS_PATH}/shared") @@ -403,9 +417,9 @@ endif() # add pass shaders for all the components if (FFX_FSR OR FFX_ALL) - target_compile_definitions(ffx_backend_cauldron_${FFX_PLATFORM_NAME} PRIVATE FFX_FSR) - include (CMakeShadersFSR2.txt) - include (CMakeShadersFSR1.txt) + target_compile_definitions(ffx_backend_cauldron_${FFX_PLATFORM_NAME} PRIVATE FFX_FSR) + include (CMakeShadersFSR2.txt) + include (CMakeShadersFSR1.txt) endif() if (FFX_SPD OR FFX_ALL) target_compile_definitions(ffx_backend_cauldron_${FFX_PLATFORM_NAME} PRIVATE FFX_SPD) diff --git a/samples/ffx_cauldron/CMakeShadersBlur.txt b/samples/ffx_cauldron/CMakeShadersBlur.txt index d81457ba..164ef616 100644 --- a/samples/ffx_cauldron/CMakeShadersBlur.txt +++ b/samples/ffx_cauldron/CMakeShadersBlur.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersCACAO.txt b/samples/ffx_cauldron/CMakeShadersCACAO.txt index 2369b2fc..bd5fb865 100644 --- a/samples/ffx_cauldron/CMakeShadersCACAO.txt +++ b/samples/ffx_cauldron/CMakeShadersCACAO.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersCAS.txt b/samples/ffx_cauldron/CMakeShadersCAS.txt index fdc9bb98..9580e59f 100644 --- a/samples/ffx_cauldron/CMakeShadersCAS.txt +++ b/samples/ffx_cauldron/CMakeShadersCAS.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersClassifier.txt b/samples/ffx_cauldron/CMakeShadersClassifier.txt index 4d1581f9..f884d598 100644 --- a/samples/ffx_cauldron/CMakeShadersClassifier.txt +++ b/samples/ffx_cauldron/CMakeShadersClassifier.txt @@ -1,7 +1,7 @@ # This file is part of the FidelityFX SDK. -# +# # Copyright (c) 2023 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 @@ -10,7 +10,7 @@ # 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 diff --git a/samples/ffx_cauldron/CMakeShadersDOF.txt b/samples/ffx_cauldron/CMakeShadersDOF.txt index 51aab51b..c243eb55 100644 --- a/samples/ffx_cauldron/CMakeShadersDOF.txt +++ b/samples/ffx_cauldron/CMakeShadersDOF.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersDenoiser.txt b/samples/ffx_cauldron/CMakeShadersDenoiser.txt index 5863f8e1..ddfdd557 100644 --- a/samples/ffx_cauldron/CMakeShadersDenoiser.txt +++ b/samples/ffx_cauldron/CMakeShadersDenoiser.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersFSR1.txt b/samples/ffx_cauldron/CMakeShadersFSR1.txt index e3617da3..f753c461 100644 --- a/samples/ffx_cauldron/CMakeShadersFSR1.txt +++ b/samples/ffx_cauldron/CMakeShadersFSR1.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersFSR2.txt b/samples/ffx_cauldron/CMakeShadersFSR2.txt index ca63ab22..fdeda7d2 100644 --- a/samples/ffx_cauldron/CMakeShadersFSR2.txt +++ b/samples/ffx_cauldron/CMakeShadersFSR2.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersLENS.txt b/samples/ffx_cauldron/CMakeShadersLENS.txt index e2425c6e..27a3d538 100644 --- a/samples/ffx_cauldron/CMakeShadersLENS.txt +++ b/samples/ffx_cauldron/CMakeShadersLENS.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersLPM.txt b/samples/ffx_cauldron/CMakeShadersLPM.txt index 15f82c96..2b245d09 100644 --- a/samples/ffx_cauldron/CMakeShadersLPM.txt +++ b/samples/ffx_cauldron/CMakeShadersLPM.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersParallelSort.txt b/samples/ffx_cauldron/CMakeShadersParallelSort.txt index f033a202..5e85c650 100644 --- a/samples/ffx_cauldron/CMakeShadersParallelSort.txt +++ b/samples/ffx_cauldron/CMakeShadersParallelSort.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersSPD.txt b/samples/ffx_cauldron/CMakeShadersSPD.txt index c7fcfc58..67199dd7 100644 --- a/samples/ffx_cauldron/CMakeShadersSPD.txt +++ b/samples/ffx_cauldron/CMakeShadersSPD.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersSSSR.txt b/samples/ffx_cauldron/CMakeShadersSSSR.txt index 62c64bc8..fd9eec0d 100644 --- a/samples/ffx_cauldron/CMakeShadersSSSR.txt +++ b/samples/ffx_cauldron/CMakeShadersSSSR.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/CMakeShadersVRS.txt b/samples/ffx_cauldron/CMakeShadersVRS.txt index f40cc9fe..c0ef6534 100644 --- a/samples/ffx_cauldron/CMakeShadersVRS.txt +++ b/samples/ffx_cauldron/CMakeShadersVRS.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/ffx_cauldron/GPUTimestamps.cpp b/samples/ffx_cauldron/GPUTimestamps.cpp new file mode 100644 index 00000000..14c5030d --- /dev/null +++ b/samples/ffx_cauldron/GPUTimestamps.cpp @@ -0,0 +1,132 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include "GPUTimestamps.h" + +namespace CAULDRON_DX12 +{ + void GPUTimestamps::Verify(ID3D12Device* pDevice, uint32_t numberOfBackBuffers) + { + if (!m_pBuffer) { + m_NumberOfBackBuffers = numberOfBackBuffers; + + D3D12_QUERY_HEAP_DESC queryHeapDesc = {}; + queryHeapDesc.Count = MaxValuesPerFrame * numberOfBackBuffers; + queryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP; + queryHeapDesc.NodeMask = 0; + pDevice->CreateQueryHeap(&queryHeapDesc, IID_PPV_ARGS(&m_pQueryHeap)); + + D3D12_HEAP_PROPERTIES heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK); + D3D12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(uint64_t) * numberOfBackBuffers * MaxValuesPerFrame); + pDevice->CreateCommittedResource( + &heapProperties, + D3D12_HEAP_FLAG_NONE, + &resourceDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&m_pBuffer)); + } + //SetName(m_pBuffer, "GPUTimestamps::m_pBuffer"); + } + + void GPUTimestamps::OnDestroy() + { + m_pBuffer->Release(); + + m_pQueryHeap->Release(); + } + + void GPUTimestamps::GetTimeStamp(ID3D12GraphicsCommandList *pCommandList, const char *label) + { + uint32_t numMeasurements = (uint32_t)m_labels[m_frame].size(); + pCommandList->EndQuery(m_pQueryHeap, D3D12_QUERY_TYPE_TIMESTAMP, m_frame*MaxValuesPerFrame + numMeasurements); + m_labels[m_frame].push_back(label); + } + + void GPUTimestamps::GetTimeStampUser(const TimeStamp& ts) + { + m_cpuTimeStamps[m_frame].push_back(ts); + } + + void GPUTimestamps::CollectTimings(ID3D12GraphicsCommandList *pCommandList) + { + uint32_t numMeasurements = (uint32_t)m_labels[m_frame].size(); + + pCommandList->ResolveQueryData(m_pQueryHeap, D3D12_QUERY_TYPE_TIMESTAMP, m_frame*MaxValuesPerFrame, numMeasurements, m_pBuffer, m_frame * MaxValuesPerFrame* sizeof(UINT64)); + } + + void GPUTimestamps::OnBeginFrame(UINT64 gpuTicksPerSecond, std::vector *pTimestamps) + { + std::vector &cpuTimeStamps = m_cpuTimeStamps[m_frame]; + std::vector &gpuLabels = m_labels[m_frame]; + + pTimestamps->clear(); + pTimestamps->reserve(cpuTimeStamps.size() + gpuLabels.size()); + + // copy CPU timestamps + // + for (uint32_t i = 0; i < cpuTimeStamps.size(); i++) + { + pTimestamps->push_back(cpuTimeStamps[i]); + } + + // copy GPU timestamps + // + uint32_t numMeasurements = (uint32_t)gpuLabels.size(); + if (numMeasurements > 0) + { + double microsecondsPerTick = 1000000.0 / (double)gpuTicksPerSecond; + + uint32_t ini = MaxValuesPerFrame * m_frame; + uint32_t fin = MaxValuesPerFrame * (m_frame + 1); + + CD3DX12_RANGE readRange(ini * sizeof(UINT64), fin * sizeof(UINT64)); + UINT64 *pTimingsBuffer = NULL; + m_pBuffer->Map(0, &readRange, reinterpret_cast(&pTimingsBuffer)); + + UINT64 *pTimingsInTicks = &pTimingsBuffer[ini]; + + for (uint32_t i = 1; i < numMeasurements; i++) + { + TimeStamp ts = { gpuLabels[i], float(microsecondsPerTick * (double)(pTimingsInTicks[i] - pTimingsInTicks[i-1])) }; + pTimestamps->push_back(ts); + } + + // compute total + TimeStamp ts = { "Total GPU Time", float(microsecondsPerTick * (double)(pTimingsInTicks[numMeasurements - 1] - pTimingsInTicks[0])) }; + pTimestamps->push_back(ts); + + CD3DX12_RANGE writtenRange(0, 0); + m_pBuffer->Unmap(0, &writtenRange); + } + + // we always need to clear these ones + cpuTimeStamps.clear(); + gpuLabels.clear(); + } + + void GPUTimestamps::OnEndFrame() + { + m_frame = (m_frame + 1) % m_NumberOfBackBuffers; + } +} diff --git a/samples/ffx_cauldron/GPUTimestamps.h b/samples/ffx_cauldron/GPUTimestamps.h new file mode 100644 index 00000000..b53356bb --- /dev/null +++ b/samples/ffx_cauldron/GPUTimestamps.h @@ -0,0 +1,72 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include +#include + +struct TimeStamp +{ + std::string m_label; + float m_microseconds = 0.0f; +}; + +namespace CAULDRON_DX12 +{ + // In DX12 timestamps are written by the GPU into a system memory resource. + // Its similar to a 'dynamic' buffer but this time it is the GPU who is writing + // and CPU is who is reading. Hence we need a sort of ring buffer to make sure + // we are reading from a chunk of the buffer that is not written to by the GPU + // + + // This class helps insert queries in the command buffer and readback the results. + // The tricky part in fact is reading back the results without stalling the GPU. + // For that it splits the readback heap in pieces and it reads + // from the last used chuck. + + class GPUTimestamps + { + public: + void Verify(ID3D12Device *pDevice, uint32_t numberOfBackBuffers); + void OnDestroy(); + + void GetTimeStamp(ID3D12GraphicsCommandList *pCommandList, const char *label); + void GetTimeStampUser(const TimeStamp &ts); + void CollectTimings(ID3D12GraphicsCommandList *pCommandList); + + void OnBeginFrame(UINT64 gpuTicksPerSecond, std::vector *pTimestamps); + void OnEndFrame(); + + private: + const uint32_t MaxValuesPerFrame = 128; + + ID3D12Resource *m_pBuffer = NULL; + ID3D12QueryHeap *m_pQueryHeap = NULL; + + uint32_t m_frame = 0; + uint32_t m_NumberOfBackBuffers = 0; + + std::vector m_labels[5]; + std::vector m_cpuTimeStamps[5]; + }; +} diff --git a/samples/ffx_cauldron/cpu_time_event_rate.cpp b/samples/ffx_cauldron/cpu_time_event_rate.cpp new file mode 100644 index 00000000..996bc7ef --- /dev/null +++ b/samples/ffx_cauldron/cpu_time_event_rate.cpp @@ -0,0 +1,88 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "cpu_time_event_rate.h" +#include +#include + +CpuTimeEventRate::CpuTimeEventRate() +{ + constexpr uint32_t measurementCount = 32; + data.resize(measurementCount); +} + +double CpuTimeEventRate::MillisecondsNow() +{ + static LARGE_INTEGER s_frequency; + static BOOL s_use_qpc; + s_use_qpc = QueryPerformanceFrequency(&s_frequency); + double milliseconds = 0; + + if (s_use_qpc) + { + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + milliseconds = double(1000.0 * now.QuadPart) / s_frequency.QuadPart; + } + else + { + milliseconds = double(GetTickCount()); + } + + return milliseconds; +} + +void CpuTimeEventRate::Update() +{ + double timeNow = MillisecondsNow(); + double deltaTime = timeNow - lastEventTime; + lastEventTime = timeNow; + + data[currentIndex] = (float)deltaTime; + currentIndex = (currentIndex + 1) % data.size(); + + // get avg value + { + float sum = std::accumulate(data.begin(), data.end(), 0.0f); + uint32_t zeroCount = (uint32_t)std::count(data.begin(), data.end(), 0.0f); + float deltaTimeAvg = sum / std::max(uint32_t(data.size() - zeroCount), uint32_t(1)); + avgFps = (uint32_t)(1e3f / std::max(deltaTimeAvg, float(1e-32))); + } + // get last value + fps = (uint32_t)(1e3f / std::max(deltaTime, double(1e-32))); +} + +uint32_t CpuTimeEventRate::getRate() +{ + return fps; +} + +uint32_t CpuTimeEventRate::getStableRate() +{ + double timeNow = MillisecondsNow(); + if (timeNow - lastGetTime > 1e3) + { + stableFps = avgFps; + lastGetTime = timeNow; + } + return stableFps; +} + diff --git a/samples/ffx_cauldron/cpu_time_event_rate.h b/samples/ffx_cauldron/cpu_time_event_rate.h new file mode 100644 index 00000000..b3732505 --- /dev/null +++ b/samples/ffx_cauldron/cpu_time_event_rate.h @@ -0,0 +1,41 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 + +struct CpuTimeEventRate +{ + std::vector data; + double lastEventTime = 0; + uint32_t currentIndex = 0; + uint32_t fps = 0; + uint32_t avgFps = 0; + uint32_t stableFps = 0; + double lastGetTime = 0.0; + CpuTimeEventRate(); + ~CpuTimeEventRate() = default; + double MillisecondsNow(); + void Update(); + uint32_t getRate(); + uint32_t getStableRate(); +}; diff --git a/samples/ffx_cauldron/ffx_cauldron.cpp b/samples/ffx_cauldron/ffx_cauldron.cpp index 7b017bcf..1051837f 100644 --- a/samples/ffx_cauldron/ffx_cauldron.cpp +++ b/samples/ffx_cauldron/ffx_cauldron.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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 #include #include @@ -59,13 +59,17 @@ BINDING_SHIFT(UNORDERED_ACCESS_VIEW, 0); BINDING_SHIFT(CONSTANT_BUFFER, 0); #endif // _VK +#if _DX12 +#include "render/dx12/device_dx12.h" +#endif // _DX12 + // Cauldron prototypes for functions in the backend interface FfxUInt32 GetSDKVersionCauldron(FfxInterface* backendInterface); FfxErrorCode CreateBackendContextCauldron(FfxInterface* backendInterface, FfxUInt32* effectContextId); FfxErrorCode GetDeviceCapabilitiesCauldron(FfxInterface* backendInterface, FfxDeviceCapabilities* deviceCapabilities); FfxErrorCode DestroyBackendContextCauldron(FfxInterface* backendInterface, FfxUInt32 effectContextId); FfxErrorCode CreateResourceCauldron(FfxInterface* backendInterface, const FfxCreateResourceDescription* desc, FfxUInt32 effectContextId, FfxResourceInternal* outTexture); -FfxErrorCode DestroyResourceCauldron(FfxInterface* backendInterface, FfxResourceInternal resource); +FfxErrorCode DestroyResourceCauldron(FfxInterface* backendInterface, FfxResourceInternal resource, FfxUInt32 effectContextId); FfxErrorCode RegisterResourceCauldron(FfxInterface* backendInterface, const FfxResource* inResource, FfxUInt32 effectContextId, FfxResourceInternal* outResourceInternal); FfxResource GetResourceCauldron(FfxInterface* backendInterface, FfxResourceInternal resource); FfxErrorCode UnregisterResourcesCauldron(FfxInterface* backendInterface, FfxCommandList commandList, FfxUInt32 effectContextId); @@ -181,6 +185,17 @@ FfxDevice ffxGetDeviceCauldron(Device* cauldronDevice) return reinterpret_cast(cauldronDevice); } +FfxCommandQueue ffxGetCommandQueueCauldron(cauldron::CommandQueue cmdQueue) +{ +#if _DX12 + ID3D12CommandQueue* pGameQueue = GetDevice()->GetImpl()->DX12CmdQueue(CommandQueue::Graphics); + return reinterpret_cast(pGameQueue); +#else + FFX_ASSERT(false && "Not implemented!"); + return NULL; +#endif +} + // Populate interface with Cauldron pointers. FfxErrorCode ffxGetInterfaceCauldron(FfxInterface* backendInterface, FfxDevice device, @@ -228,6 +243,12 @@ FfxCommandList ffxGetCommandListCauldron(CommandList* cauldronCmdList) return reinterpret_cast(cauldronCmdList); } +FfxSwapchain ffxGetSwapchainCauldron(SwapChain* pSwapchain) +{ + FFX_ASSERT(nullptr != pSwapchain); + return reinterpret_cast(pSwapchain); +} + FfxResource ffxGetResourceCauldron(const cauldron::GPUResource* cauldronResource, FfxResourceDescription ffxResDescription, wchar_t* ffxResName, @@ -639,7 +660,7 @@ FfxErrorCode DestroyBackendContextCauldron(FfxInterface* backendInterface, FfxUI CauldronWarning(L"FFXInterface: Cauldron: SDK Resource %ls was not destroyed prior to destroying the backend context. There may be a resource leak.", backendContext->pResources[currentStaticResourceIndex].resourcePtr->GetName()); FfxResourceInternal internalResource = { (int32_t)currentStaticResourceIndex }; - DestroyResourceCauldron(backendInterface, internalResource); + DestroyResourceCauldron(backendInterface, internalResource, effectContextId); } } // Free up for use by another context @@ -844,21 +865,27 @@ FfxErrorCode CreateResourceCauldron(FfxInterface* backendInterface, const FfxCre return FFX_OK; } -FfxErrorCode DestroyResourceCauldron(FfxInterface* backendInterface, FfxResourceInternal resource) +FfxErrorCode DestroyResourceCauldron(FfxInterface* backendInterface, FfxResourceInternal resource, FfxUInt32 effectContextId) { // Since SDK needs to be able to destroy resources when resizing, need to explicitly allow resource destruction (which is normally handled automatically by cauldron) FFX_ASSERT(nullptr != backendInterface); BackendContext_Cauldron* backendContext = (BackendContext_Cauldron*)backendInterface->scratchBuffer; + BackendContext_Cauldron::EffectContext& effectContext = backendContext->pEffectContexts[effectContextId]; - BackendContext_Cauldron::Resource* backendResource = &backendContext->pResources[resource.internalIndex]; - if (backendResource->resourcePtr) + for (uint32_t currentStaticResourceIndex = effectContextId * FFX_MAX_RESOURCE_COUNT; + currentStaticResourceIndex < (uint32_t)effectContext.nextStaticResource; + ++currentStaticResourceIndex) { - if (backendResource->resourcePtr->IsCopyBuffer()) - delete backendResource->resourcePtr; - else - GetDynamicResourcePool()->DestroyResource(backendResource->resourcePtr); + BackendContext_Cauldron::Resource* backendResource = &backendContext->pResources[resource.internalIndex]; + if (backendResource->resourcePtr) + { + if (backendResource->resourcePtr->IsCopyBuffer()) + delete backendResource->resourcePtr; + else + GetDynamicResourcePool()->DestroyResource(backendResource->resourcePtr); - backendResource->resourcePtr = nullptr; + backendResource->resourcePtr = nullptr; + } } return FFX_OK; @@ -1077,7 +1104,7 @@ FfxErrorCode CreatePipelineCauldron(FfxInterface* backendInterfa BackendContext_Cauldron* backendContext = (BackendContext_Cauldron*)backendInterface->scratchBuffer; FfxShaderBlob shaderBlob = { 0 }; - FfxErrorCode errorCode = ffxGetPermutationBlobByIndex(effect, passId, permutationOptions, &shaderBlob); + FfxErrorCode errorCode = ffxGetPermutationBlobByIndex(effect, passId, desc->stage, permutationOptions, &shaderBlob); FFX_ASSERT(errorCode == FFX_OK); FFX_ASSERT(shaderBlob.data && shaderBlob.size); diff --git a/samples/ffx_cauldron/ffx_cauldron.h b/samples/ffx_cauldron/ffx_cauldron.h index bb394d1e..6659ff85 100644 --- a/samples/ffx_cauldron/ffx_cauldron.h +++ b/samples/ffx_cauldron/ffx_cauldron.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + /// @defgroup CauldronBackend Cauldron Backend /// Custom FidelityFX SDK Backend Implementation for Cauldron /// @@ -36,7 +36,9 @@ extern "C" { namespace cauldron { class Device; + enum class CommandQueue; class CommandList; + class SwapChain; class GPUResource; } // namespace cauldron @@ -61,7 +63,9 @@ FFX_API size_t ffxGetScratchMemorySizeCauldron(size_t maxContexts); /// @ingroup CauldronBackend FFX_API FfxDevice ffxGetDeviceCauldron(cauldron::Device* cauldronDevice); -/// Populate an interface with pointers for the Cauldron backend. +FFX_API FfxCommandQueue ffxGetCommandQueueCauldron(cauldron::CommandQueue cmdQueue); + + /// Populate an interface with pointers for the Cauldron backend. /// /// @param [out] fsr2Interface A pointer to a FfxInterface structure to populate with pointers. /// @param [in] device A pointer to the Cauldron device. @@ -88,6 +92,8 @@ FFX_API FfxErrorCode ffxGetInterfaceCauldron(FfxInterface* backendInterface, Ffx /// @ingroup CauldronBackend FFX_API FfxCommandList ffxGetCommandListCauldron(cauldron::CommandList* cauldronCmdList); +FFX_API FfxSwapchain ffxGetSwapchainCauldron(cauldron::SwapChain* pSwapchain); + /// Fetch a FfxResource from a GPUResource. /// /// @param [in] cauldronResource A pointer to the Cauldron resource. diff --git a/samples/ffx_cauldron/shaders/blur/ffx_blur_pass.hlsl b/samples/ffx_cauldron/shaders/blur/ffx_blur_pass.hlsl index 1f3cce25..64fd6f76 100644 --- a/samples/ffx_cauldron/shaders/blur/ffx_blur_pass.hlsl +++ b/samples/ffx_cauldron/shaders/blur/ffx_blur_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // BLUR pass // SRV 0 : BLUR_InputSrc : r_input_src // UAV 0 : BLUR_Output : rw_output diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_non_smart_half_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_non_smart_half_pass.hlsl index 086d8cf5..d397a530 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_non_smart_half_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_non_smart_half_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_OUTPUT 8 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_non_smart_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_non_smart_pass.hlsl index d845ce73..566dec28 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_non_smart_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_non_smart_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_OUTPUT 8 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_pass.hlsl index 2d6ddb09..d7661ea3 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_apply_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_OUTPUT 8 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_clear_load_counter_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_clear_load_counter_pass.hlsl index a2014706..d8bd25f4 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_clear_load_counter_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_clear_load_counter_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_UAV_LOAD_COUNTER 4 #define CACAO_BIND_CB_CACAO 0 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_1_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_1_pass.hlsl index 8db2a5b1..e358d366 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_1_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_1_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_2_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_2_pass.hlsl index 8ee53872..13c65133 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_2_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_2_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_3_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_3_pass.hlsl index 66b313c6..d75d6e1a 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_3_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_3_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_4_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_4_pass.hlsl index 1daaf238..decface1 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_4_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_4_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_5_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_5_pass.hlsl index 3fabae21..2ff01129 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_5_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_5_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_6_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_6_pass.hlsl index 1e05e538..0156c8b3 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_6_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_6_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_7_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_7_pass.hlsl index efd483ca..3fbc4e9a 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_7_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_7_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_8_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_8_pass.hlsl index 9169d1fc..8cafad5e 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_8_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_edge_sensitive_blur_8_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_a_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_a_pass.hlsl index a1437ce5..ac1a2262 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_a_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_a_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PONG 3 #define CACAO_BIND_SRV_IMPORTANCE_MAP 4 #define CACAO_BIND_SRV_IMPORTANCE_MAP_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_b_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_b_pass.hlsl index f2313445..6e12fb89 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_b_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_b_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PONG 3 #define CACAO_BIND_SRV_IMPORTANCE_MAP 4 #define CACAO_BIND_SRV_IMPORTANCE_MAP_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_pass.hlsl index 5a1a0010..527b55c0 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_importance_map_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PONG 3 #define CACAO_BIND_SRV_IMPORTANCE_MAP 4 #define CACAO_BIND_SRV_IMPORTANCE_MAP_PONG 7 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q0_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q0_pass.hlsl index 515d6666..6985dbda 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q0_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q0_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_LOAD_COUNTER 0 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_DEINTERLEAVED_NORMALS 2 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q1_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q1_pass.hlsl index bed3733c..a9cdbc10 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q1_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q1_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_LOAD_COUNTER 0 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_DEINTERLEAVED_NORMALS 2 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q2_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q2_pass.hlsl index 84687511..b7b770b7 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q2_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q2_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_LOAD_COUNTER 0 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_DEINTERLEAVED_NORMALS 2 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q3_base_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q3_base_pass.hlsl index 32c2bc25..018b6e9b 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q3_base_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q3_base_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_LOAD_COUNTER 0 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_DEINTERLEAVED_NORMALS 2 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q3_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q3_pass.hlsl index e2818164..e60a5b49 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q3_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_generate_q3_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_LOAD_COUNTER 0 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_DEINTERLEAVED_NORMALS 2 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_and_mips_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_and_mips_pass.hlsl index a617822f..1c1acaa5 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_and_mips_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_and_mips_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_half_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_half_pass.hlsl index 5d137794..9dde3252 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_half_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_half_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_pass.hlsl index c327f202..387af5ae 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_depths_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_normals_from_input_normals_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_normals_from_input_normals_pass.hlsl index 23a8b53c..b93ed006 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_normals_from_input_normals_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_normals_from_input_normals_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_normals_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_normals_pass.hlsl index ea022e76..6d0e8ce9 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_normals_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_downsampled_normals_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_and_mips_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_and_mips_pass.hlsl index 07808031..b94a5306 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_and_mips_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_and_mips_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_half_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_half_pass.hlsl index 6f526d2f..0aeb24be 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_half_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_half_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_pass.hlsl index 3a01fba7..e5dfbc44 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_depths_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_normals_from_input_normals_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_normals_from_input_normals_pass.hlsl index 006d8682..7cc13919 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_normals_from_input_normals_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_normals_from_input_normals_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_normals_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_normals_pass.hlsl index 80798d41..ab0dba66 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_normals_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_prepare_native_normals_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_upscale_bilateral_5x5_pass.hlsl b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_upscale_bilateral_5x5_pass.hlsl index 2a407de5..dd84db1e 100644 --- a/samples/ffx_cauldron/shaders/cacao/ffx_cacao_upscale_bilateral_5x5_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cacao/ffx_cacao_upscale_bilateral_5x5_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 diff --git a/samples/ffx_cauldron/shaders/cas/ffx_cas_sharpen_pass.hlsl b/samples/ffx_cauldron/shaders/cas/ffx_cas_sharpen_pass.hlsl index 08482d57..b344dd1a 100644 --- a/samples/ffx_cauldron/shaders/cas/ffx_cas_sharpen_pass.hlsl +++ b/samples/ffx_cauldron/shaders/cas/ffx_cas_sharpen_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // CAS pass // SRV 0 : CAS_InputColor : r_input_color // UAV 0 : CAS_OutputColor : rw__output_color diff --git a/samples/ffx_cauldron/shaders/classifier/ffx_classifier_reflections_pass.hlsl b/samples/ffx_cauldron/shaders/classifier/ffx_classifier_reflections_pass.hlsl index f09f2ac3..26b18e7b 100644 --- a/samples/ffx_cauldron/shaders/classifier/ffx_classifier_reflections_pass.hlsl +++ b/samples/ffx_cauldron/shaders/classifier/ffx_classifier_reflections_pass.hlsl @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #define FFX_WAVE 1 #define CLASSIFIER_BIND_SRV_INPUT_NORMAL 0 diff --git a/samples/ffx_cauldron/shaders/classifier/ffx_classifier_shadows_pass.hlsl b/samples/ffx_cauldron/shaders/classifier/ffx_classifier_shadows_pass.hlsl index 2b12fb29..7e2bd0d7 100644 --- a/samples/ffx_cauldron/shaders/classifier/ffx_classifier_shadows_pass.hlsl +++ b/samples/ffx_cauldron/shaders/classifier/ffx_classifier_shadows_pass.hlsl @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + // Classifier pass // CB 0 : cbClassifier // SRV 0 : CLASSIFIER_Depth : r_input_depth diff --git a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_0_pass.hlsl b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_0_pass.hlsl index 1eec1683..d385d77f 100644 --- a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_0_pass.hlsl +++ b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_0_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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. + #define DENOISER_SHADOWS_BIND_SRV_DEPTH 0 #define DENOISER_SHADOWS_BIND_SRV_NORMAL 1 #define DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT 2 diff --git a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_1_pass.hlsl b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_1_pass.hlsl index a2cd9f81..e1fe9243 100644 --- a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_1_pass.hlsl +++ b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_1_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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. + #define DENOISER_SHADOWS_BIND_SRV_DEPTH 0 #define DENOISER_SHADOWS_BIND_SRV_NORMAL 1 #define DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT 2 diff --git a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_2_pass.hlsl b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_2_pass.hlsl index 66e47dce..d0f3192b 100644 --- a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_2_pass.hlsl +++ b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_filter_soft_shadows_2_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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. + #define DENOISER_SHADOWS_BIND_SRV_DEPTH 0 #define DENOISER_SHADOWS_BIND_SRV_NORMAL 1 #define DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT 2 diff --git a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_prefilter_reflections_pass.hlsl b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_prefilter_reflections_pass.hlsl index 3776cb4c..92910d81 100644 --- a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_prefilter_reflections_pass.hlsl +++ b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_prefilter_reflections_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define DENOISER_BIND_SRV_INPUT_DEPTH_HIERARCHY 2 #define DENOISER_BIND_SRV_INPUT_NORMAL 4 #define DENOISER_BIND_SRV_RADIANCE 7 diff --git a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_prepare_shadow_mask_pass.hlsl b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_prepare_shadow_mask_pass.hlsl index ce548afd..da073c27 100644 --- a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_prepare_shadow_mask_pass.hlsl +++ b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_prepare_shadow_mask_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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. + #define FFX_WAVE 1 #define DENOISER_SHADOWS_BIND_SRV_INPUT_HIT_MASK_RESULTS 0 diff --git a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_reproject_reflections_pass.hlsl b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_reproject_reflections_pass.hlsl index 9fb572e1..d8605a5a 100644 --- a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_reproject_reflections_pass.hlsl +++ b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_reproject_reflections_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define DENOISER_BIND_SRV_INPUT_DEPTH_HIERARCHY 2 #define DENOISER_BIND_SRV_INPUT_MOTION_VECTORS 3 #define DENOISER_BIND_SRV_INPUT_NORMAL 4 diff --git a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_resolve_temporal_reflections_pass.hlsl b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_resolve_temporal_reflections_pass.hlsl index 7f292af3..4328bf9e 100644 --- a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_resolve_temporal_reflections_pass.hlsl +++ b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_resolve_temporal_reflections_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define DENOISER_BIND_SRV_RADIANCE 7 #define DENOISER_BIND_SRV_RADIANCE_HISTORY 8 #define DENOISER_BIND_SRV_VARIANCE 9 diff --git a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_shadows_tile_classification_pass.hlsl b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_shadows_tile_classification_pass.hlsl index 46a39aee..f4af2a80 100644 --- a/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_shadows_tile_classification_pass.hlsl +++ b/samples/ffx_cauldron/shaders/denoiser/ffx_denoiser_shadows_tile_classification_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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. + #define FFX_WAVE 1 #define DENOISER_SHADOWS_BIND_SRV_DEPTH 0 diff --git a/samples/ffx_cauldron/shaders/dof/ffx_dof_blur_pass.hlsl b/samples/ffx_cauldron/shaders/dof/ffx_dof_blur_pass.hlsl index e6df2a2b..d3300ce9 100644 --- a/samples/ffx_cauldron/shaders/dof/ffx_dof_blur_pass.hlsl +++ b/samples/ffx_cauldron/shaders/dof/ffx_dof_blur_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FFX_DOF_BIND_CB_DOF 0 #define FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR 0 #define FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS 1 diff --git a/samples/ffx_cauldron/shaders/dof/ffx_dof_composite_pass.hlsl b/samples/ffx_cauldron/shaders/dof/ffx_dof_composite_pass.hlsl index eb41d238..65ad29c1 100644 --- a/samples/ffx_cauldron/shaders/dof/ffx_dof_composite_pass.hlsl +++ b/samples/ffx_cauldron/shaders/dof/ffx_dof_composite_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FFX_DOF_BIND_CB_DOF 0 #if !FFX_DOF_OPTION_COMBINE_IN_PLACE diff --git a/samples/ffx_cauldron/shaders/dof/ffx_dof_dilate_pass.hlsl b/samples/ffx_cauldron/shaders/dof/ffx_dof_dilate_pass.hlsl index 1bfc952f..81ac2f40 100644 --- a/samples/ffx_cauldron/shaders/dof/ffx_dof_dilate_pass.hlsl +++ b/samples/ffx_cauldron/shaders/dof/ffx_dof_dilate_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FFX_DOF_BIND_CB_DOF 0 #define FFX_DOF_BIND_UAV_INTERNAL_RADIUS 0 #define FFX_DOF_BIND_UAV_INTERNAL_DILATED_RADIUS 1 diff --git a/samples/ffx_cauldron/shaders/dof/ffx_dof_downsample_color_pass.hlsl b/samples/ffx_cauldron/shaders/dof/ffx_dof_downsample_color_pass.hlsl index 163d52d1..50917dd7 100644 --- a/samples/ffx_cauldron/shaders/dof/ffx_dof_downsample_color_pass.hlsl +++ b/samples/ffx_cauldron/shaders/dof/ffx_dof_downsample_color_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FFX_DOF_BIND_CB_DOF 0 #define FFX_DOF_BIND_SRV_INPUT_COLOR 0 #define FFX_DOF_BIND_SRV_INPUT_DEPTH 1 diff --git a/samples/ffx_cauldron/shaders/dof/ffx_dof_downsample_depth_pass.hlsl b/samples/ffx_cauldron/shaders/dof/ffx_dof_downsample_depth_pass.hlsl index ef0354c8..d565fa88 100644 --- a/samples/ffx_cauldron/shaders/dof/ffx_dof_downsample_depth_pass.hlsl +++ b/samples/ffx_cauldron/shaders/dof/ffx_dof_downsample_depth_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FFX_DOF_BIND_CB_DOF 0 #define FFX_DOF_BIND_SRV_INPUT_DEPTH 0 #define FFX_DOF_BIND_UAV_INTERNAL_RADIUS 0 diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_CopyUiResource_pass.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_CopyUiResource_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_CopyUiResource_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_CopyUiResource_pass.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_CopyUiResource_pass.hlsl new file mode 100644 index 00000000..a8221ac0 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_CopyUiResource_pass.hlsl @@ -0,0 +1,45 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 12 + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +Texture2D r_uiTexture : register(t0); +RWTexture2D rw_uiTexture : register(u0); + +[numthreads(8, 8, 1)] +void CS(uint2 dtID : SV_DispatchThreadID) +{ + rw_uiTexture[dtID] = r_uiTexture[dtID]; +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_ReplacementFrameResource_pass.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_ReplacementFrameResource_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_ReplacementFrameResource_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_ReplacementFrameResource_pass.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_ReplacementFrameResource_pass.hlsl new file mode 100644 index 00000000..1f5dd3c7 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_ReplacementFrameResource_pass.hlsl @@ -0,0 +1,36 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +Texture2D r_dilated_depth : register(t0); +Texture2D r_dilated_motion_vectors : register(t1); +Texture2D r_reconstructed_prev_nearest_depth : register(t2); + +RWTexture2D rw_fiDilatedDepth : register(u0); +RWTexture2D rw_fiDilated_motion_vectors : register(u1); +RWTexture2D rw_fiReconstructedPrevNearestDepth : register(u2); + +[numthreads(8, 8, 1)] +void CS(uint2 dtID : SV_DispatchThreadID) +{ + rw_fiDilatedDepth[dtID] = r_dilated_depth[dtID]; + rw_fiDilated_motion_vectors[dtID] = r_dilated_motion_vectors[dtID]; + rw_fiReconstructedPrevNearestDepth[dtID] = r_reconstructed_prev_nearest_depth[dtID]; +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionPS_pass.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionPS_pass.glsl new file mode 100644 index 00000000..8daa2b0a --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionPS_pass.glsl @@ -0,0 +1,7 @@ +#version 450 core + +layout(location = 0) out vec4 color; + +void main() { + color = vec4(0.0, 0.0, 0.0, 1.0); +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionPS_pass.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionPS_pass.hlsl new file mode 100644 index 00000000..81b82145 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionPS_pass.hlsl @@ -0,0 +1,62 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FfxFloat32x3 float3 +#define ffxMax max + +FfxFloat32x3 Tonemap(FfxFloat32x3 fRgb) +{ + return fRgb / (ffxMax(ffxMax(0.f, fRgb.r), ffxMax(fRgb.g, fRgb.b)) + 1.f).xxx; +} + +#define FAR_DEPTH 0.5f + +Texture2D r_currBB : register(t0); +Texture2D r_uiTexture : register(t1); + +static const float4 FullScreenVertsPos[3] = { float4(-1, 1, FAR_DEPTH, 1), float4(3, 1, FAR_DEPTH, 1), float4(-1, -3, FAR_DEPTH, 1) }; +// static const float2 FullScreenVertsUVs[3] = { float2(0, 0), float2(2, 0), float2(0, 2) }; + +//Texture2D r_currBB : register(t0); + +struct VERTEX_OUT +{ +// float2 vTexture : TEXCOORD; + float4 vPosition : SV_POSITION; +}; + +cbuffer cbComposition : register(b0) +{ + int uiPresent; +}; + +float4 mainPS(VERTEX_OUT Input) : SV_Target +{ + float3 color = r_currBB[Input.vPosition.xy].rgb; + float4 guiColor = r_uiTexture[Input.vPosition.xy]; + + //guiColor.rgb = Tonemap(guiColor.rgb); + if (uiPresent == 1) { + color = lerp(color, guiColor.rgb, pow(1.0f - guiColor.a, 3.0f)); + } + + return float4(color, 1); +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionVS_pass.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionVS_pass.glsl new file mode 100644 index 00000000..67f0c9d2 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionVS_pass.glsl @@ -0,0 +1,12 @@ +#version 450 + +#ifndef FAR_DEPTH +#define FAR_DEPTH 0 +#endif + +vec4 fullScreenVertsPos[3] = { vec4(-1, 1, FAR_DEPTH, 1), vec4(3, 1, FAR_DEPTH, 1), vec4(-1, -3, FAR_DEPTH, 1) }; + +void main() +{ + gl_Position = fullScreenVertsPos[gl_VertexIndex]; +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionVS_pass.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionVS_pass.hlsl new file mode 100644 index 00000000..456c15c7 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UiCompositionVS_pass.hlsl @@ -0,0 +1,55 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 12 + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +#define FAR_DEPTH 0.5f + +static const float4 FullScreenVertsPos[3] = { float4(-1, 1, FAR_DEPTH, 1), float4(3, 1, FAR_DEPTH, 1), float4(-1, -3, FAR_DEPTH, 1) }; +// static const float2 FullScreenVertsUVs[3] = { float2(0, 0), float2(2, 0), float2(0, 2) }; + +struct VERTEX_OUT +{ +// float2 vTexture : TEXCOORD; + float4 vPosition : SV_POSITION; +}; + +VERTEX_OUT mainVS(uint vertexId : SV_VertexID) +{ + VERTEX_OUT Output; + Output.vPosition = FullScreenVertsPos[vertexId]; +// Output.vTexture = FullScreenVertsUVs[vertexId]; + return Output; +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UpscalerDispatchComposition_pass.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UpscalerDispatchComposition_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UpscalerDispatchComposition_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UpscalerDispatchComposition_pass.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UpscalerDispatchComposition_pass.hlsl new file mode 100644 index 00000000..0b0ab486 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_UpscalerDispatchComposition_pass.hlsl @@ -0,0 +1,74 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +Texture2D rInputs[] : register(t0); +RWTexture2D rwOutput : register(u0); + +cbuffer cbFI : register(b0) +{ + int2 renderSize; + int2 displaySize; + + float2 displaySizeRcp; + float cameraNear; + float cameraFar; + + int2 upscalerTargetSize; + int Mode; + int Reset; + + float4 fDeviceToViewDepth; + + float deltaTime; + float2 motionVectorScale; + float HUDLessAttachedFactor; + + float2 opticalFlowScale; + int opticalFlowBlockSize; + int reserved_0; + + int opticalFlowHalfResMode; + int2 maxRenderSize; + int NumInstances; + + int2 interpolationRectBase; + int2 interpolationRectSize; +} + +[numthreads(8,8,1)] +void CS(uint2 dtID : SV_DispatchThreadID) +{ + int instanceIndex = -1; + + int instanceWidth = displaySize.x / NumInstances; + if (abs((dtID.x / instanceWidth) * instanceWidth - dtID.x) > 1) + { + instanceIndex = dtID.x / instanceWidth; + } + + float3 color = 0; + + if (instanceIndex >= 0) { + color = rInputs[instanceIndex][dtID].rgb; + } + + rwOutput[dtID] = float4(color, 1); +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.hlsl new file mode 100644 index 00000000..b9f6638c --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.hlsl @@ -0,0 +1,182 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PREV_BB 12 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURR_BB 13 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OUTPUT 14 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 15 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_0 1 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_1 2 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_2 3 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_3 4 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_4 5 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_5 6 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_6 7 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_7 8 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_8 9 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_9 10 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_10 11 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_11 12 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_12 13 + +#ifdef FFX_HALF + #undef FFX_HALF + #define FFX_HALF 0 +#endif + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +#define FI_BIND_CB_INPAINTING_PYRAMID 1 +cbuffer cbInpaintingPyramid : FFX_FI_DECLARE_CB(FI_BIND_CB_INPAINTING_PYRAMID) +{ + uint mips; + uint numWorkGroups; + uint2 workGroupOffset; +} + +//-------------------------------------------------------------------------------------- +// Buffer definitions - global atomic counter +//-------------------------------------------------------------------------------------- + +groupshared uint spdCounter; +groupshared float spdIntermediateR[16][16]; +groupshared float spdIntermediateG[16][16]; +groupshared float spdIntermediateB[16][16]; +groupshared float spdIntermediateA[16][16]; + +float4 SpdLoadSourceImage(float2 tex, uint slice) +{ + VectorFieldEntry gameMv; + LoadGameFieldMv(tex, gameMv); + + //rw_debug_out[tex] = float4(abs(gameMv.fMotionVector) * RenderSize(), 0, 1); + //rw_debug_out[tex] = float4(gameMv.fMotionVector * RenderSize(), gameMv.uDepthPriorityFactor, gameMv.uColorPriorityFactor); + + return float4(gameMv.fMotionVector, gameMv.uDepthPriorityFactor, gameMv.uColorPriorityFactor) * (DisplaySize().x > 0);; +} + +float4 SpdLoad(float2 tex, uint slice) +{ + return imgDst5[tex]; +} + +void SpdStore(int2 pix, float4 outValue, uint index, uint slice) +{ +#define STORE(idx) \ + if (index == idx) \ + { \ + imgDst##idx[pix] = outValue; \ + } + + STORE(0); + STORE(1); + STORE(2); + STORE(3); + STORE(4); + STORE(5); + STORE(6); + STORE(7); + STORE(8); + STORE(9); + STORE(10); + STORE(11); + STORE(12); +} + +void SpdIncreaseAtomicCounter(uint slice) +{ + InterlockedAdd(rw_counters[int2(COUNTER_SPD,0)], 1, spdCounter); +} + +uint SpdGetAtomicCounter() +{ + return spdCounter; +} +void SpdResetAtomicCounter(uint slice) +{ + rw_counters[int2(COUNTER_SPD,0)] = 0; +} + +float4 SpdLoadIntermediate(uint x, uint y) +{ + return float4( + spdIntermediateR[x][y], + spdIntermediateG[x][y], + spdIntermediateB[x][y], + spdIntermediateA[x][y]); +} + +void SpdStoreIntermediate(uint x, uint y, float4 value) +{ + spdIntermediateR[x][y] = value.x; + spdIntermediateG[x][y] = value.y; + spdIntermediateB[x][y] = value.z; + spdIntermediateA[x][y] = value.w; +} + +float4 SpdReduce4(float4 v0, float4 v1, float4 v2, float4 v3) +{ + float4 vec = float4(0,0,0,0); + + float fWeightSum = 0.0f; +#define ADD(SAMPLE) { \ + float fWeight = (SAMPLE.z > 0.0f) * pow(1.0f - SAMPLE.z, 3.0f) /* higher weights on far-away samples */; \ + vec += SAMPLE * fWeight; \ + fWeightSum += fWeight; \ + } + + ADD(v0); + ADD(v1); + ADD(v2); + ADD(v3); + + vec /= (fWeightSum > FSR2_EPSILON) ? fWeightSum : 1.0f; + + return vec; +} + +#include "spd/ffx_spd.h" + +[numthreads(256, 1, 1)] +void CS(uint3 WorkGroupId : SV_GroupID, uint LocalThreadIndex : SV_GroupIndex) +{ + SpdDownsample( + uint2(WorkGroupId.xy), + uint1(LocalThreadIndex), + uint1(mips), + uint1(numWorkGroups), + uint1(WorkGroupId.z), + uint2(workGroupOffset)); +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.hlsl new file mode 100644 index 00000000..30e829ce --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.hlsl @@ -0,0 +1,175 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#ifdef FFX_HALF + #undef FFX_HALF + #define FFX_HALF 0 +#endif + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PREV_BB 12 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURR_BB 13 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OUTPUT 14 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 15 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_STATIC_CONTENT_MASK 16 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_0 1 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_1 2 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_2 3 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_3 4 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_4 5 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_5 6 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_6 7 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_7 8 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_8 9 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_9 10 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_10 11 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_11 12 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_12 13 + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +#define FI_BIND_CB_INPAINTING_PYRAMID 1 +cbuffer cbInpaintingPyramid : FFX_FI_DECLARE_CB(FI_BIND_CB_INPAINTING_PYRAMID) +{ + uint mips; + uint numWorkGroups; + uint2 workGroupOffset; +} + +//-------------------------------------------------------------------------------------- +// Buffer definitions - global atomic counter +//-------------------------------------------------------------------------------------- + +groupshared uint spdCounter; +groupshared float spdIntermediateR[16][16]; +groupshared float spdIntermediateG[16][16]; +groupshared float spdIntermediateB[16][16]; +groupshared float spdIntermediateA[16][16]; + +float4 SpdLoadSourceImage(float2 tex, uint slice) +{ + float4 fColor = r_FiOutput[tex] * (DisplaySize().x > 0); + + // Don't allow static areas to contribute to in-painted result + fColor.w *= (r_static_content_mask[tex][STATIC_CONTENT_MASK_CURRENT] == 0.0f); + + return fColor; +} + +float4 SpdLoad(float2 tex, uint slice) +{ + return imgDst5[tex]; +} + +void SpdStore(int2 pix, float4 outValue, uint index, uint slice) +{ +#define STORE(idx) \ + if (index == idx) \ + { \ + imgDst##idx[pix] = outValue; \ + } + + STORE(0); + STORE(1); + STORE(2); + STORE(3); + STORE(4); + STORE(5); + STORE(6); + STORE(7); + STORE(8); + STORE(9); + STORE(10); + STORE(11); + STORE(12); +} + +void SpdIncreaseAtomicCounter(uint slice) +{ + InterlockedAdd(rw_counters[int2(COUNTER_SPD,0)], 1, spdCounter); +} + +uint SpdGetAtomicCounter() +{ + return spdCounter; +} +void SpdResetAtomicCounter(uint slice) +{ + rw_counters[int2(COUNTER_SPD,0)] = 0; +} + +float4 SpdLoadIntermediate(uint x, uint y) +{ + return float4( + spdIntermediateR[x][y], + spdIntermediateG[x][y], + spdIntermediateB[x][y], + spdIntermediateA[x][y]); +} + +void SpdStoreIntermediate(uint x, uint y, float4 value) +{ + spdIntermediateR[x][y] = value.x; + spdIntermediateG[x][y] = value.y; + spdIntermediateB[x][y] = value.z; + spdIntermediateA[x][y] = value.w; +} + +float4 SpdReduce4(float4 v0, float4 v1, float4 v2, float4 v3) +{ + float4 w = float4(v0.w, v1.w, v2.w, v3.w); + + //w = 1; + float sum = (w[0] + w[1] + w[2] + w[3]); + + if (sum == 0.0f) { + return 0; + } + + return (v0 * w[0] + v1 * w[1] + v2 * w[2] + v3 * w[3]) / sum; +} + +#include "spd/ffx_spd.h" + +[numthreads(256, 1, 1)] +void CS(uint3 WorkGroupId : SV_GroupID, uint LocalThreadIndex : SV_GroupIndex) +{ + SpdDownsample( + uint2(WorkGroupId.xy), + uint1(LocalThreadIndex), + uint1(mips), + uint1(numWorkGroups), + uint1(WorkGroupId.z), + uint2(workGroupOffset)); +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.hlsl new file mode 100644 index 00000000..13644ea8 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.hlsl @@ -0,0 +1,228 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 12 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_DISOCCLUSION_MASK 0 + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +// #define FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH 1 + +static const float DepthClipBaseScale = 1.0f; + +float TanHalfFoV() +{ + return 1.777777; +} + +float ComputeSampleDepthClip(int2 iPxSamplePos, float fPreviousDepth, float fPreviousDepthBilinearWeight, float fCurrentDepthViewSpace) +{ + float fPrevNearestDepthViewSpace = ConvertFromDeviceDepthToViewSpace(fPreviousDepth); + + // Depth separation logic ref: See "Minimum Triangle Separation for Correct Z-Buffer Occlusion" + // Intention: worst case of formula in Figure4 combined with Ksep factor in Section 4 + // TODO: check intention and improve, some banding visible + const float fHalfViewportWidth = renderSize.x * 0.5f; + float fDepthThreshold = max(fCurrentDepthViewSpace, fPrevNearestDepthViewSpace); + + // WARNING: Ksep only works with reversed-z with infinite projection. + const float Ksep = 1.37e-05f; + float fRequiredDepthSeparation = Ksep * fDepthThreshold * TanHalfFoV() * fHalfViewportWidth; + float fDepthDiff = fCurrentDepthViewSpace - fPrevNearestDepthViewSpace; + + float fDepthClipFactor = (fDepthDiff > 0) ? saturate(fRequiredDepthSeparation / fDepthDiff) : 1.0f; + +#ifdef _DEBUG + //rw_debug_out[iPxSamplePos] = float4(fCurrentDepthViewSpace, fPrevNearestDepthViewSpace, fDepthDiff, fDepthClipFactor); +#endif + + return fPreviousDepthBilinearWeight * fDepthClipFactor * lerp(1.0f, DepthClipBaseScale, saturate(fDepthDiff * fDepthDiff)); +} + +float LoadEstimatedDepth(uint estimatedIndex, int2 iSamplePos) +{ + if (estimatedIndex == 0) + { + return asfloat(r_reconstructed_depth_previous_frame[iSamplePos]); + } + else if (estimatedIndex == 1) + { + return r_dilated_depth[iSamplePos]; + } + + return 0; +} + +float ComputeDepthClip(uint estimatedIndex, float2 fUvSample, float fCurrentDepthViewSpace) +{ + float2 fPxSample = fUvSample * RenderSize() - 0.5f; + int2 iPxSample = int2(floor(fPxSample)); + float2 fPxFrac = frac(fPxSample); + + const float fBilinearWeights[2][2] = {{(1 - fPxFrac.x) * (1 - fPxFrac.y), (fPxFrac.x) * (1 - fPxFrac.y)}, + {(1 - fPxFrac.x) * (fPxFrac.y), (fPxFrac.x) * (fPxFrac.y)}}; + + float fDepth = 0.0f; + float fWeightSum = 0.0f; + for (int y = 0; y <= 1; ++y) + { + for (int x = 0; x <= 1; ++x) + { + int2 iSamplePos = iPxSample + int2(x, y); + if (IsOnScreen(iSamplePos, RenderSize())) + { + float fBilinearWeight = fBilinearWeights[y][x]; + + if (fBilinearWeight > fReconstructedDepthBilinearWeightThreshold) + { + float estimatedDepth = LoadEstimatedDepth(estimatedIndex, iSamplePos); + + //if (fCurrentDepthViewSpace < 1000) //ConvertFromDeviceDepthToViewSpace(0)) + { + fDepth += ComputeSampleDepthClip(iSamplePos, estimatedDepth, fBilinearWeight, fCurrentDepthViewSpace); + fWeightSum += fBilinearWeight; + } + } + } + } + } + + return (fWeightSum > 0) ? fDepth / fWeightSum : DepthClipBaseScale; +} + +FfxFloat32 ComputeDepthClip2(uint estimatedIndex, FfxFloat32x2 fUvSample, FfxFloat32 fCurrentDepthSample) +{ + FfxFloat32 fCurrentDepthViewSpace = GetViewSpaceDepth(fCurrentDepthSample); + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUvSample, RenderSize()); + + FfxFloat32 fDilatedSum = 0.0f; + FfxFloat32 fDepth = 0.0f; + FfxFloat32 fWeightSum = 0.0f; + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) { + + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, RenderSize())) { + const FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex]; + if (fWeight > fReconstructedDepthBilinearWeightThreshold) { + + //const FfxFloat32 fPrevDepthSample = LoadReconstructedPrevDepth(iSamplePos); + const FfxFloat32 fPrevDepthSample = LoadEstimatedDepth(estimatedIndex, iSamplePos); + const FfxFloat32 fPrevNearestDepthViewSpace = GetViewSpaceDepth(fPrevDepthSample); + + const FfxFloat32 fDepthDiff = fCurrentDepthViewSpace - fPrevNearestDepthViewSpace; + + if (fDepthDiff >= 0.0f) { + +#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH + const FfxFloat32 fPlaneDepth = ffxMin(fPrevDepthSample, fCurrentDepthSample); +#else + const FfxFloat32 fPlaneDepth = ffxMax(fPrevDepthSample, fCurrentDepthSample); +#endif + + const FfxFloat32x3 fCenter = GetViewSpacePosition(FfxInt32x2(RenderSize() * 0.5f), RenderSize(), fPlaneDepth); + const FfxFloat32x3 fCorner = GetViewSpacePosition(FfxInt32x2(0, 0), RenderSize(), fPlaneDepth); + + const FfxFloat32 fHalfViewportWidth = length(FfxFloat32x2(RenderSize())); + const FfxFloat32 fDepthThreshold = ffxMax(fCurrentDepthViewSpace, fPrevNearestDepthViewSpace); + + const FfxFloat32 Ksep = 1.37e-05f; + const FfxFloat32 Kfov = length(fCorner) / length(fCenter); + const FfxFloat32 fRequiredDepthSeparation = Ksep * Kfov * fHalfViewportWidth * fDepthThreshold; + + const FfxFloat32 fResolutionFactor = ffxSaturate(length(FfxFloat32x2(RenderSize())) / length(FfxFloat32x2(1920.0f, 1080.0f))); + const FfxFloat32 fPower = ffxLerp(1.0f, 3.0f, fResolutionFactor); + //fDepth += ffxPow(ffxSaturate(FfxFloat32(fRequiredDepthSeparation / fDepthDiff)) == 1.0f, fPower) * fWeight; + + fDepth += FfxFloat32((fRequiredDepthSeparation / fDepthDiff) >= 1.0f) * fWeight; + fWeightSum += fWeight; + } + } + } + } + + return (fWeightSum > 0.0f) ? ffxSaturate(1.0f - fDepth / fWeightSum) : 0.0f; +} + +[numthreads(8, 8, 1)] +void CS(uint2 iPxPos + : SV_DispatchThreadID) { + float fDilatedDepth = LoadEstimatedInterpolationFrameDepth(iPxPos); + + float2 fDepthUv = (iPxPos + 0.5f) / RenderSize(); + float fCurrentDepthViewSpace = ConvertFromDeviceDepthToViewSpace(fDilatedDepth); + + VectorFieldEntry gameMv; + LoadGameFieldMv2(fDepthUv, gameMv); + + float fDepthClip = 1.0f; + float fDepthClip2 = 1.0f; + + fDepthClip = 1 - ComputeDepthClip2(0, fDepthUv + gameMv.fMotionVector, fDilatedDepth); + fDepthClip2 = 1 - ComputeDepthClip2(1, fDepthUv - gameMv.fMotionVector, fDilatedDepth); + + /* + if (fDepthClip > fDepthClip2) { + fDepthClip = 1.0f; + } + + if (fDepthClip2 > fDepthClip) { + fDepthClip2 = 1.0f; + } + */ + + float t = 1; // max(fDepthClip, fDepthClip2); + + //fDepthClip = fDepthClip > 0.1f; + //fDepthClip2 = fDepthClip2 > 0.1f; + //fDepthClip2 = fDepthClip; + + //fDepthClip = lerp(fDepthClip, 1.0f, 1.0f - fDepthClip2); + //fDepthClip2 = lerp(fDepthClip2, 1.0f, 1.0f - fDepthClip); + + float2 fDisocclusionMask = float2(fDepthClip, fDepthClip2); + + if(fDisocclusionMask.x < 1.0f && fDisocclusionMask.y < 1.0f) { + //fDisocclusionMask = 1; + } + + //fDisocclusionMask = 1; + rw_disocclusion_mask[iPxPos] = fDisocclusionMask; + + //rw_debug_out[iPxPos] = ConvertFromDeviceDepthToViewSpace(LoadEstimatedDepth(1, iPxPos)); //float4(fDepthClip2, fDepthClip2, 0, 1); + //rw_debug_out[iPxPos] = ConvertFromDeviceDepthToViewSpace(LoadEstimatedInterpolationFrameDepth(iPxPos)); //float4(fDepthClip2, fDepthClip2, 0, 1); + + //rw_debug_out[iPxPos] = float4(float2(fDepthClip / t, (fDepthClip2 / t)), 0, 1); +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.hlsl new file mode 100644 index 00000000..b526a637 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.hlsl @@ -0,0 +1,115 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 12 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PREV_BB 13 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURR_BB 14 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +void computeGameFieldMvs(uint2 dtID, float2 fGameMotionVector) +{ + float2 fUv = float2(float2(dtID)+0.5f) / RenderSize(); + + //fGameMotionVector.x = -100.0f / RenderSize(); + + float2 fMotionVectorHalf = fGameMotionVector * 0.5f; + + float2 fPxPrevPos = ((fUv + fMotionVectorHalf) * RenderSize()) - float2(0.5, 0.5); + int2 iPxPrevPos = int2(floor(fPxPrevPos)); + float2 fPxFrac = frac(fPxPrevPos); + + float fDepthSample = LoadEstimatedInterpolationFrameDepth(dtID); + fDepthSample = r_dilated_depth[dtID]; + + float fViewSpaceDepth = ConvertFromDeviceDepthToViewSpace(fDepthSample); // / 1000.0f; + + uint uDepthPriorityFactor = getPriorityFactorFromViewSpaceDepth(fViewSpaceDepth); + + //rw_debug_out[dtID] = uPriorityFactor / float(maxVal); + + float prevLuma = 0.01f + RGBToLuma(ffxSrgbToLinear(r_prevBB.SampleLevel(s_LinearClamp, fUv, 0).xyz)); + float currLuma = 0.01f + RGBToLuma(ffxSrgbToLinear(r_currBB.SampleLevel(s_LinearClamp, fUv + fGameMotionVector, 0).xyz)); + + //uint uColorPriorityFactor = MinDividedByMax(prevLuma, currLuma) * PRIORITY_COLOR_MAX; + uint uColorPriorityFactor = round(pow(MinDividedByMax(prevLuma, currLuma), 1.0f / 1.0f) * PRIORITY_COLOR_MAX) + * IsUvInside(fUv + fGameMotionVector); + + uint2 packedVector = PackVectorFieldEntries(uDepthPriorityFactor, uColorPriorityFactor, fMotionVectorHalf); + + //rw_debug_out[dtID] = float4(0, uColorPriorityFactor, 0, 1); + + const float bilinearWeights[2][2] = { + { + (1 - fPxFrac.x) * (1 - fPxFrac.y), + (fPxFrac.x) * (1 - fPxFrac.y) + }, + { + (1 - fPxFrac.x) * (fPxFrac.y), + (fPxFrac.x) * (fPxFrac.y) + } + }; + + // Project current depth into previous frame locations. + // Push to all pixels having some contribution if reprojection is using bilinear logic. + for (int y = 0; y <= 1; ++y) { + for (int x = 0; x <= 1; ++x) { + + int2 offset = int2(x, y); + float w = bilinearWeights[y][x]; + + if (w > 0.0f) { + + int2 storePos = iPxPrevPos + offset; + if (IsOnScreen(storePos, RenderSize())) + { + InterlockedMax(rw_game_motion_vector_field_x[storePos], packedVector.x); + InterlockedMax(rw_game_motion_vector_field_y[storePos], packedVector.y); + } + } + } + } +} + +[numthreads(8, 8, 1)] +void CS(uint2 dtID : SV_DispatchThreadID) +{ + float2 fGameMotionVector = r_dilated_motion_vectors[dtID]; + + computeGameFieldMvs(dtID, fGameMotionVector); +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.hlsl new file mode 100644 index 00000000..56b17a1c --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.hlsl @@ -0,0 +1,107 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 12 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT 0 + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +FfxFloat32x4 ComputeInpaintingLevel(float2 fUv, const FfxInt32 iMipLevel, const FfxInt32x2 iTexSize) +{ + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv, iTexSize); + + FfxFloat32x4 fColor = 0.0f; + + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) { + + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, iTexSize)) { + + FfxFloat32x4 fSample = r_InpaintingPyramid.mips[iMipLevel][iSamplePos]; + + const FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex] * (fSample.w > 0.0f); + + fColor += float4(fSample.rgb * fWeight, fWeight); + } + } + + return fColor; +} + +FfxFloat32x3 ComputeInpainting(uint2 iPxPos) +{ + float2 fUv = (iPxPos + 0.5f) / (DisplaySize()); + + FfxFloat32x4 fColor = 0; + FfxInt32x2 iTexSize = DisplaySize(); + + for (FfxInt32 iMipLevel = 0; iMipLevel < 10 && (fColor.w < 0.01f); iMipLevel++) { + + iTexSize *= 0.5f; + + fColor = ComputeInpaintingLevel(fUv, iMipLevel, iTexSize); + } + + return fColor.rgb / fColor.w; +} + +[numthreads(8, 8, 1)] +void CS(uint2 dtID : SV_DispatchThreadID) +{ + + float4 fColor = rw_FiOutput[dtID]; + + + if (fColor.w == 0.0f) { + fColor.rgb = ComputeInpainting(dtID) * (DisplaySize().x > 0); + + rw_FiOutput[dtID] = float4(fColor.rgb, 1.0f); + } + + /* + if (fColor.w == 0.0f) { + // wip, do manual bilinear sampling to stay at as high level as possible + for (float i = 1; i < 6 && fColor.w < 1.0f; i += 1.0f) { + fColor = r_InpaintingPyramid.SampleLevel(s_LinearClamp, fUv, i); + } + } + */ + + //float2 fUv = (dtID + 0.5f) / (DisplaySize()); + //fColor = r_InpaintingPyramid.SampleLevel(s_LinearClamp, fUv, 0); + + //fColor.rgb = r_currHUDLess[dtID]; +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.hlsl new file mode 100644 index 00000000..8d5e4080 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.hlsl @@ -0,0 +1,193 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 12 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PREV_BB 13 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURR_BB 14 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +void computeOpticalFlowFieldMvs(uint2 dtID, FfxFloat32x2 fOpticalFlowVector) +{ + float2 fUv = float2(float2(dtID)+0.5f) / GetOpticalFlowSize2(); + + const float scaleFactor = 1.0f; + float2 fMotionVectorHalf = fOpticalFlowVector * 0.5f; + + float2 fPxPrevPos = ((fUv + fMotionVectorHalf) * GetOpticalFlowSize2() * scaleFactor) - float2(0.5, 0.5); + int2 iPxPrevPos = int2(floor(fPxPrevPos)); + float2 fPxFrac = frac(fPxPrevPos); + + float fDilatedDepth = ConvertFromDeviceDepthToViewSpace(r_dilated_depth[dtID]); + + float prevLuma = 0.001f + RGBToLuma(ffxSrgbToLinear(r_prevBB.SampleLevel(s_LinearClamp, fUv, 0).xyz)); + float currLuma = 0.001f + RGBToLuma(ffxSrgbToLinear(r_currBB.SampleLevel(s_LinearClamp, fUv + fOpticalFlowVector, 0).xyz)); + + float fVelocity = length(fOpticalFlowVector * DisplaySize()); + uint uDepthPriorityFactor = (fVelocity > 1.0f) * saturate(fVelocity / length(DisplaySize() * 0.05f)) * PRIORITY_DEPTH_MAX; + + if(uDepthPriorityFactor > 0) { + uint uColorPriorityFactor = round(pow(MinDividedByMax(prevLuma, currLuma), 1.0f / 1.0f) * PRIORITY_COLOR_MAX) + * IsUvInside(fUv + fOpticalFlowVector); + + const float bilinearWeights[2][2] = { + { + (1 - fPxFrac.x) * (1 - fPxFrac.y), + (fPxFrac.x) * (1 - fPxFrac.y) + }, + { + (1 - fPxFrac.x) * (fPxFrac.y), + (fPxFrac.x) * (fPxFrac.y) + } + }; + + // Project current depth into previous frame locations. + // Push to all pixels having some contribution if reprojection is using bilinear logic. + for (int y = 0; y <= 1; ++y) { + for (int x = 0; x <= 1; ++x) { + + int2 offset = int2(x, y); + float w = bilinearWeights[y][x]; + + if (w > 0.0f) { + + int2 storePos = iPxPrevPos + offset; + if (IsOnScreen(storePos, GetOpticalFlowSize2() * scaleFactor)) + { + //uColorPriorityFactor = (dtID.x * dtID.y) % PRIORITY_COLOR_MAX; + uint2 packedVector = PackVectorFieldEntries(uDepthPriorityFactor, uColorPriorityFactor, fMotionVectorHalf); + + InterlockedMax(rw_optical_flow_motion_vector_field_x[storePos], packedVector.x); + InterlockedMax(rw_optical_flow_motion_vector_field_y[storePos], packedVector.y); + } + } + } + } + } +} + +FfxFloat32 ComputeMotionDivergence(FfxInt32x2 iPxPos) +{ + FfxFloat32 minconvergence = 1.0f; + + FfxFloat32x2 fMotionVectorNucleus = LoadOpticalFlow(iPxPos); + FfxFloat32 fNucleusVelocityLr = length(fMotionVectorNucleus * GetOpticalFlowSize2()); + FfxFloat32 fMaxVelocityUv = length(fMotionVectorNucleus); + + const FfxFloat32 MotionVectorVelocityEpsilon = 1e-02f; + + if (fNucleusVelocityLr > MotionVectorVelocityEpsilon) { + for (FfxInt32 y = -1; y <= 1; ++y) { + for (FfxInt32 x = -1; x <= 1; ++x) { + + FfxInt32x2 sp = iPxPos + FfxInt32x2(x, y); //ClampLoad(iPxPos, FfxInt32x2(x, y), GetOpticalFlowSize2()); + + FfxFloat32x2 fMotionVector = LoadOpticalFlow(sp); + FfxFloat32 fVelocityUv = length(fMotionVector); + + if(length(fMotionVector * DisplaySize()) > 1.0f) { + fMaxVelocityUv = ffxMax(fVelocityUv, fMaxVelocityUv); + fVelocityUv = ffxMax(fVelocityUv, fMaxVelocityUv); + minconvergence = ffxMin(minconvergence, dot(fMotionVector / fVelocityUv, fMotionVectorNucleus / fVelocityUv)); + } + } + } + } + + return ffxSaturate(1.0f - minconvergence) * ffxSaturate(fMaxVelocityUv / 0.01f); +} + +[numthreads(8, 8, 1)] +void CS(uint2 dtID : SV_DispatchThreadID) +{ + + //FfxFloat32 fMotionDivergence = ComputeMotionDivergence(dtID); + + FfxFloat32x2 fOpticalFlowVector = 0; + FfxFloat32x2 fOpticalFlowVector3x3Avg = 0; + int size = 1; + float sw = 0.0f; + + for(int y = -size; y <= size; y++) { + for(int x = -size; x <= size; x++) { + + int2 samplePos = dtID + int2(x,y); + + float2 vs = LoadOpticalFlow(samplePos); + float fConfidenceFactor = max(FSR2_EPSILON, LoadOpticalFlowConfidence(samplePos)); + + + float len = length(vs * DisplaySize()); + float len_factor = max(0.0f, 512.0f - len) * (len > 1.0f); + float w = len_factor; + + fOpticalFlowVector3x3Avg += vs * w; + + sw += w; + } + } + + fOpticalFlowVector3x3Avg /= sw; + + + sw = 0.0f; + for(int y = -size; y <= size; y++) { + for(int x = -size; x <= size; x++) { + + int2 samplePos = dtID + int2(x,y); + + float2 vs = LoadOpticalFlow(samplePos); + + float fConfidenceFactor = max(FSR2_EPSILON, LoadOpticalFlowConfidence(samplePos)); + float len = length(vs * DisplaySize()); + float len_factor = max(0.0f, 512.0f - len) * (len > 1.0f); + + + float w = max(0.0f, pow(dot(fOpticalFlowVector3x3Avg, vs), 1.25f)) * len_factor; + + fOpticalFlowVector += vs * w; + sw += w; + } + } + + if(sw > FSR2_EPSILON) { + fOpticalFlowVector /= sw; + } + + computeOpticalFlowFieldMvs(dtID, fOpticalFlowVector); +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_pass.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_pass.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_pass.hlsl new file mode 100644 index 00000000..3f69733f --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_pass.hlsl @@ -0,0 +1,262 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PREV_BB 12 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURR_BB 13 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DISOCCLUSION_MASK 14 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_STATIC_CONTENT_MASK 15 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_HUD_LESS 16 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 17 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_COUNTERS 18 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT 0 + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +float4 SampleTextureBilinear(uint2 iPxPos, Texture2D tex, float2 fUv, float2 fMotionVector, int2 texSize, int staticMaskChannel) +{ + float2 fReprojectedUv = fUv + fMotionVector; + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fReprojectedUv, texSize); + + float3 fColor = 0.0f; + float fWeightSum = 0.0f; + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) { + + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, texSize)) { + + FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex]; + + fWeight *= ffxSaturate(1.0f - r_static_content_mask[iSamplePos][staticMaskChannel]); + + fColor += tex[iSamplePos].rgb * fWeight; + fWeightSum += fWeight; + } + } + + //normalize colors + fColor = (fWeightSum != 0.0f) ? fColor / fWeightSum : tex[iPxPos].rgb; + return float4(fColor, fWeightSum); +} + +void drawDebug(uint2 iPxPos, inout float3 fColor, inout bool bColorInPainting) { + + if (iPxPos.y < 64 && iPxPos.x < 64 && HasSceneChanged()) + fColor.r = 1.f; + + if (iPxPos.x < 16) { + fColor.g = 1.f; + } + if (iPxPos.x > DisplaySize().x - 16) { + fColor += debugBarColor; + } + +#if 0 + if (length(iPxPos - DisplaySize() * 0.5f) < 25.0f) { + //if (iPxPos.x % 4 < 2) { + bColorInPainting = true; + fColor = 0; + } +#endif + + // OF verification for FFX_INTERNAL disabled + if (0) + { + float2 of = r_optical_flow[iPxPos / opticalFlowBlockSize]; + float2 fof = -of; + float2 n = normalize(of.x == 0 && of.y == 0 ? float2(1.0, 0.0) : fof); + float len = length(fof); + float phi = n.y < 0.0 ? acos(n.x) : -acos(n.x) + 2 * FFX_PI; + float h = phi / (2 * FFX_PI); + float s = len * 0.04; + float v = 0.5; + float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + float3 p = abs(frac(h.xxx + K.xyz) * 6.0 - K.www); + float3 hsv2rgbr = v * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), s); + fColor.rgb = hsv2rgbr; + } +} + +float staticComparison(uint2 iPxPos) +{ + float fPrev = RGBToLuma(ffxSrgbToLinear(r_prevBB[iPxPos].rgb)); + float fCurr = RGBToLuma(ffxSrgbToLinear(r_currBB[iPxPos].rgb)); + + return MinDividedByMax(fPrev, fCurr); +} + +void computeInterpolatedColor(uint2 iPxPos, out float3 fInterpolatedColor, out bool bColorInPainting) +{ + float2 fUv = (float2(iPxPos) + 0.5f) / DisplaySize(); + + fInterpolatedColor = 0; + bColorInPainting = false; + + float2 fLrUv = fUv * (float2(renderSize) / maxRenderSize); + uint2 uLrPos = round(fUv * renderSize); + + + VectorFieldEntry gameMv; + LoadGameFieldMv2(fUv, gameMv); + + VectorFieldEntry ofMv; + SampleOpticalFlowMotionVectorField2(fUv, ofMv); + + bool bUseGameMvs = true; + + float2 fDisocclusionFactor = saturate(r_disocclusion_mask.SampleLevel(s_LinearClamp, fLrUv, 0).xy); + + if (!gameMv.bValid && !gameMv.bNegOutside && !gameMv.bPosOutside) { + gameMv.fMotionVector *= fDisocclusionFactor.x; + } + + //gameMv.fMotionVector *= bUseGameMvs; + + float4 fPrevColorGame = SampleTextureBilinear(iPxPos, r_prevBB, fUv, +gameMv.fMotionVector, DisplaySize(), STATIC_CONTENT_MASK_PREVIOUS); + float4 fCurrColorGame = SampleTextureBilinear(iPxPos, r_currBB, fUv, -gameMv.fMotionVector, DisplaySize(), STATIC_CONTENT_MASK_CURRENT); + + float4 fPrevColorOF = SampleTextureBilinear(iPxPos, r_prevBB, fUv, +ofMv.fMotionVector, DisplaySize(), STATIC_CONTENT_MASK_PREVIOUS); + float4 fCurrColorOF = SampleTextureBilinear(iPxPos, r_currBB, fUv, -ofMv.fMotionVector, DisplaySize(), STATIC_CONTENT_MASK_CURRENT); + + float fBilinearWeightSum = 0.0f; + + if (bUseGameMvs) + { + fDisocclusionFactor.x *= !gameMv.bNegOutside; + fDisocclusionFactor.y *= !gameMv.bPosOutside; + + float t = 0.5f; + t += 0.5f * (1 - (fDisocclusionFactor.x)); + t -= 0.5f * (1 - (fDisocclusionFactor.y)); + + // bias towards current frame depending on color similarity + if(abs(t - 0.5f) < FSR2_EPSILON) { + float fSim = NormalizedDot3(fPrevColorGame.rgb, fCurrColorGame.rgb); + fSim = pow(fSim, 6.0f); + t = lerp(1.0f, t, fSim); + } + + fInterpolatedColor = lerp(fPrevColorGame.xyz, fCurrColorGame.xyz, ffxSaturate(t)); + fBilinearWeightSum = lerp(fPrevColorGame.w, fCurrColorGame.w, ffxSaturate(t)); + + if (gameMv.bNegOutside && gameMv.bPosOutside) { + bColorInPainting = true; + fInterpolatedColor = 1; + } + else if (fPrevColorGame.w == 0.0f) { + fInterpolatedColor = fCurrColorGame.xyz; + fBilinearWeightSum = fCurrColorGame.w; + } + else if (fCurrColorGame.w == 0.0f) { + fInterpolatedColor = fPrevColorGame.xyz; + fBilinearWeightSum = fPrevColorGame.w; + } + } + + + //fInterpolatedColor = lerp(fInterpolatedColor.rgb, r_currBB[iPxPos].rgb, fBilinearWeightSum <= 0.01f); + /* + if (r_static_content_mask[iPxPos] > FSR2_EPSILON) + { + fInterpolatedColor = r_currBB[iPxPos].rgb; + } else + */ + + #if 1 + { + + float ofT = 0.5f; + + if(fPrevColorOF.w > 0 && fCurrColorOF.w > 0) { + ofT = 0.5f; + } else if(fPrevColorOF.w > 0) { + ofT = 0; + } else { + ofT = 1; + } + + float fOF_Sim = NormalizedDot3(fPrevColorOF.rgb, fCurrColorOF.rgb); + fOF_Sim = pow(fOF_Sim, 6.0f); + + // bias towards current frame depending on color similarity + if(abs(ofT - 0.5f) < FSR2_EPSILON) { + ofT = lerp(1.0f, ofT, fOF_Sim); + } + + float3 ofColor = lerp(fPrevColorOF.rgb, fCurrColorOF.rgb, ofT); + + float fMvCmp = NormalizedDot2(gameMv.fMotionVector, ofMv.fMotionVector); + float t = pow(max(0, fMvCmp), 1.0f / 6.0f); + t = lerp(1.0f - t, 0.0f, saturate(length(gameMv.fMotionVector * DisplaySize()) / 256.0f)); + if(gameMv.bInPainted) { + t = 0; + } + + t = lerp(t, 0.0f, pow(MinDividedByMax(0.01f + gameMv.fVelocity, 0.01f + ofMv.fVelocity), 6.0f)); + + float fStatic = pow(staticComparison(iPxPos), 6.0f); + + fStatic *= fOF_Sim; + t = lerp(t, 0.0f, fStatic); //use gameMvs based on static comparison + + const float fFrameIndexFactor = ffxSaturate(FrameIndexSinceLastReset() > 5.0f); + t *= fFrameIndexFactor; + + fInterpolatedColor = lerp(fInterpolatedColor, ofColor, ffxSaturate(t)); + } +#endif + + //fInterpolatedColor = lerp(fPrevColorGame.xyz, fCurrColorGame.xyz, 0.5f); + + // Do InPainting in non-static areas where no valid samples where interpolated + bColorInPainting |= (max(fPrevColorGame.w, fCurrColorGame.w) == 0.0f) && (r_static_content_mask[iPxPos][STATIC_CONTENT_MASK_CURRENT] < 0.1f); +} + +[numthreads(8,8,1)] +void CS(uint2 iPxPos : SV_DispatchThreadID) +{ + float3 fColor = float3(0,0,0); + bool bColorInPainting = false; + + if(FrameIndexSinceLastReset() > 0) { + computeInterpolatedColor(iPxPos, fColor, bColorInPainting); + } else { + fColor = r_currBB[iPxPos].rgb; + } + + drawDebug(iPxPos, fColor, bColorInPainting); + + rw_FiOutput[iPxPos] = float4(fColor, !bColorInPainting); +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.hlsl new file mode 100644 index 00000000..06a3ba20 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.hlsl @@ -0,0 +1,143 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PREV_BB 12 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURR_BB 13 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PREV_BB_DOWN 14 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURR_BB_DOWN 15 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_HUD_LESS 16 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 17 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_STATIC_CONTENT_MASK 1 + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +void StoreReconstructedDepthInterpolatedFrame(int2 iPxSample, float fDepth) +{ + uint uDepth = asuint(fDepth); + +#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH + InterlockedMax(rw_reconstructed_depth_interpolated_frame[iPxSample], uDepth); +#else + InterlockedMin(rw_reconstructed_depth_interpolated_frame[iPxSample], uDepth); // min for standard, max for inverted depth +#endif +} + +/* +void StoreReconstructedDepthPreviousFrame(int2 iPxSample, float fDepth) +{ + uint uDepth = asuint(fDepth); + +#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH + InterlockedMax(rw_reconstructed_depth_previous_frame[iPxSample], uDepth); +#else + InterlockedMin(rw_reconstructed_depth_previous_frame[iPxSample], uDepth); // min for standard, max for inverted depth +#endif +} +*/ + +void ReconstructPrevDepth(int2 iPxPos, uint depthTarget, float fDepth, float2 fMotionVector, int2 iPxDepthSize) +{ + float2 fDepthUv = (iPxPos + float(0.5)) / iPxDepthSize; + float2 fPxPrevPos = (fDepthUv + fMotionVector) * iPxDepthSize - float2(0.5, 0.5); + int2 iPxPrevPos = int2(floor(fPxPrevPos)); + float2 fPxFrac = frac(fPxPrevPos); + + const float bilinearWeights[2][2] = {{(1 - fPxFrac.x) * (1 - fPxFrac.y), (fPxFrac.x) * (1 - fPxFrac.y)}, + {(1 - fPxFrac.x) * (fPxFrac.y), (fPxFrac.x) * (fPxFrac.y)}}; + + // Project current depth into previous frame locations. + // Push to all pixels having some contribution if reprojection is using bilinear logic. + for (int y = 0; y <= 1; ++y) + { + for (int x = 0; x <= 1; ++x) + { + int2 offset = int2(x, y); + float w = bilinearWeights[y][x]; + + if (w > fReconstructedDepthBilinearWeightThreshold) + { + int2 storePos = iPxPrevPos + offset; + if (IsOnScreen(storePos, RenderSize())) + { + if (depthTarget == 0) { + //StoreReconstructedDepthPreviousFrame(storePos, fDepth); + } + else { + StoreReconstructedDepthInterpolatedFrame(storePos, fDepth); + } + } + } + } + } +} + +float CalcSpatialDiff(uint2 dtID) +{ + float3 c0 = Tonemap(r_prevBB_downsampled[dtID].rgb); + float m0 = RGBToPerceivedLuma(c0); + float3 c1 = Tonemap(r_currBB_downsampled[dtID].rgb); + float m1 = RGBToPerceivedLuma(c1); + float delta = abs(m0 - m1); + + return all(abs(c0 - c1) > 0.025f); + + return saturate(delta) < 0.025f; +} + +[numthreads(8, 8, 1)] void CS(uint2 dtID : SV_DispatchThreadID) { + float2 fMotionVector = r_dilated_motion_vectors[dtID]; + float fDilatedDepth = r_dilated_depth[dtID]; + + if (all(dtID < RenderSize())) { + //ReconstructPrevDepth(dtID, 0, fDilatedDepth, fMotionVector, DisplaySize()); + ReconstructPrevDepth(dtID, 1, fDilatedDepth, fMotionVector * 0.5f, RenderSize()); + } + + //StoreReconstructedDepth(dtID, fDilatedDepth); + + float m0 = RGBToPerceivedLuma(r_currBB[dtID].rgb); + float m1 = RGBToPerceivedLuma(r_currHUDLess[dtID].rgb); + + float ml = max(length(r_currBB[dtID].rgb), length(r_currHUDLess[dtID].rgb)); + + float2 maskVal = rw_static_content_mask[dtID]; + + // TODO: Have current and previous R8 resource to temporally manage static content mask! + maskVal[STATIC_CONTENT_MASK_PREVIOUS] = maskVal[STATIC_CONTENT_MASK_CURRENT]; + maskVal[STATIC_CONTENT_MASK_CURRENT] = ffxSaturate((1.0f - NormalizedDot3(r_currBB[dtID].rgb, r_currHUDLess[dtID].rgb)) / 0.1f); + + //rw_debug_out[dtID] = maskVal * HUDLessAttachedFactor; + rw_static_content_mask[dtID] = maskVal * HUDLessAttachedFactor; +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_setup.glsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_setup.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_setup.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_setup.hlsl b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_setup.hlsl new file mode 100644 index 00000000..b89b9258 --- /dev/null +++ b/samples/ffx_cauldron/shaders/frameinterpolation/ffx_frameinterpolation_setup.hlsl @@ -0,0 +1,117 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 8 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 9 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 11 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURR_BB 12 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURR_BB_DOWN 13 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 14 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_DISOCCLUSION_MASK 4 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_CURR_BB_DOWN 5 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS 6 + +#include "frameinterpolation/ffx_frameinterpolation_defines.h" + +[numthreads(8, 8, 1)] +void CS(uint2 dtID : SV_DispatchThreadID) { + + if(all(dtID == 0)) { + if(Reset() || HasSceneChanged()) { + rw_counters[int2(COUNTER_FRAME_INDEX_SINCE_LAST_RESET,0)] = 0; + } else { + rw_counters[int2(COUNTER_FRAME_INDEX_SINCE_LAST_RESET,0)]++; + } + } + + float2 fDilatedMotionVector = r_dilated_motion_vectors[dtID]; + float fDilatedDepth = r_dilated_depth[dtID]; + +#if 1 + FfxFloat32x2 fOfVector = SampleOpticalFlowMotionVector(dtID); +#else + FfxInt32x2 fOpticalFlowSize = (1.0f / opticalFlowScale) / FfxFloat32x2(opticalFlowBlockSize.xx); + float2 s = DisplaySize() / RenderSize(); + FfxFloat32x2 fOfVector = r_optical_flow[(dtID * s) / opticalFlowBlockSize] * opticalFlowScale; +#endif + + //fOfVector = 0; + +#if 0 + + float2 fMotionVector = fDilatedMotionVector; + float2 fMotionVectorHalf = fMotionVector * 0.5f; + + + float2 fUv = (dtID + float(0.5)) / RenderSize(); + bool bNegOutside = any((fUv - fMotionVector) < 0.0) || any((fUv - fMotionVector) > 1.0f); + bool bPosOutside = any((fUv + fMotionVector) < 0.0) || any((fUv + fMotionVector) > 1.0f); + + bool isBorder = (bNegOutside || bPosOutside); + + rw_currBB_downsampled[dtID] = r_currBB.SampleLevel(s_LinearClamp, fUv, 0); + + //fMotionVectorHalf *= isBorder; + + //rw_debug_out[dtID] = float4(0, fMotionVectorHalf * RenderSize(), 1); + + //rw_debug_out[dtID] = float4(0, isBorder, 0, 1); + + //rw_debug_out[dtID] = float4(fDilatedMotionVector * RenderSize(), 0, 1); + //return; + + uint maxVal = 0xFFFF; + uint offset = 0; + uint uPriorityFactor = 0; + + uint2 packedVector = PackVectorFieldEntries(uPriorityFactor, fMotionVectorHalf); + + rw_game_motion_vector_field_x[dtID] = packedVector.x; + rw_game_motion_vector_field_y[dtID] = packedVector.y; +#else + rw_game_motion_vector_field_x[dtID] = 0; + rw_game_motion_vector_field_y[dtID] = 0; +#endif + + // TEMP, what to fill these with? + rw_optical_flow_motion_vector_field_x[dtID] = 0; + rw_optical_flow_motion_vector_field_y[dtID] = 0; + + rw_disocclusion_mask[dtID] = 0; + + //rw_debug_out[dtID] = float4(fOfVector * RenderSize(), 0, 1); + + //rw_debug_out[dtID] = float4(rw_dilated_motion_vectors[dtID] * DisplaySize(), 0, 1); +} diff --git a/samples/ffx_cauldron/shaders/fsr1/ffx_fsr1_easu_pass.hlsl b/samples/ffx_cauldron/shaders/fsr1/ffx_fsr1_easu_pass.hlsl index 4a5763c3..65b8340a 100644 --- a/samples/ffx_cauldron/shaders/fsr1/ffx_fsr1_easu_pass.hlsl +++ b/samples/ffx_cauldron/shaders/fsr1/ffx_fsr1_easu_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // FSR1 pass 1 // SRV 0 : FSR1_InputColor : r_input_color // UAV 0 : FSR1_InternalUpscaled : rw_internal_upscaled_color (if doing RCAS) diff --git a/samples/ffx_cauldron/shaders/fsr1/ffx_fsr1_rcas_pass.hlsl b/samples/ffx_cauldron/shaders/fsr1/ffx_fsr1_rcas_pass.hlsl index 9b835e14..0b1f3736 100644 --- a/samples/ffx_cauldron/shaders/fsr1/ffx_fsr1_rcas_pass.hlsl +++ b/samples/ffx_cauldron/shaders/fsr1/ffx_fsr1_rcas_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // FSR1 pass 2 (optional RCAS) // SRV 0 : FSR1_InternalUpscaled : r_internal_upscaled_color // UAV 0 : FSR1_UpscaledOutput : rw_upscaled_output diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_accumulate_pass.glsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_accumulate_pass.glsl index 0b32e84b..e93b6a95 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_accumulate_pass.glsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_accumulate_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the “Software”), to deal +// 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 @@ -12,7 +12,7 @@ // 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 +// 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 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_accumulate_pass.hlsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_accumulate_pass.hlsl index 86d2cb7d..233e63d5 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_accumulate_pass.hlsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_accumulate_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FSR2_BIND_SRV_INPUT_EXPOSURE 0 #define FSR2_BIND_SRV_DILATED_REACTIVE_MASKS 1 #if FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.glsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.glsl index c06769c4..e07f03c3 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.glsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the “Software”), to deal +// 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 @@ -12,7 +12,7 @@ // 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 +// 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 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.hlsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.hlsl index d454388f..31621431 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.hlsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FSR2_BIND_SRV_INPUT_OPAQUE_ONLY 0 #define FSR2_BIND_SRV_INPUT_COLOR 1 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.glsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.glsl index 337b1dca..7bba2c90 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.glsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the “Software”), to deal +// 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 @@ -12,7 +12,7 @@ // 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 +// 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 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.hlsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.hlsl index 67d575e3..ea6d7ac3 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.hlsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FSR2_BIND_SRV_INPUT_COLOR 0 #define FSR2_BIND_UAV_SPD_GLOBAL_ATOMIC 0 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_depth_clip_pass.glsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_depth_clip_pass.glsl index 86f5c489..e74cc921 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_depth_clip_pass.glsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_depth_clip_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the “Software”), to deal +// 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 @@ -12,7 +12,7 @@ // 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 +// 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 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_depth_clip_pass.hlsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_depth_clip_pass.hlsl index e59114a5..aa871e2b 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_depth_clip_pass.hlsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_depth_clip_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FSR2_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH 0 #define FSR2_BIND_SRV_DILATED_MOTION_VECTORS 1 #define FSR2_BIND_SRV_DILATED_DEPTH 2 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_lock_pass.glsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_lock_pass.glsl index e02c11c1..94356cd2 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_lock_pass.glsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_lock_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the “Software”), to deal +// 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 @@ -12,7 +12,7 @@ // 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 +// 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 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_lock_pass.hlsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_lock_pass.hlsl index 9dd435d5..61d74c83 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_lock_pass.hlsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_lock_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FSR2_BIND_SRV_LOCK_INPUT_LUMA 0 #define FSR2_BIND_UAV_NEW_LOCKS 0 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_rcas_pass.glsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_rcas_pass.glsl index 8cf588f4..797846ad 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_rcas_pass.glsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_rcas_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the “Software”), to deal +// 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 @@ -12,7 +12,7 @@ // 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 +// 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 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_rcas_pass.hlsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_rcas_pass.hlsl index 6223cd5a..5dc70a80 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_rcas_pass.hlsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_rcas_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FSR2_BIND_SRV_INPUT_EXPOSURE 0 #define FSR2_BIND_SRV_RCAS_INPUT 1 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.glsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.glsl index 929fd2da..b8f85451 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.glsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the “Software”), to deal +// 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 @@ -12,7 +12,7 @@ // 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 +// 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 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.hlsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.hlsl index 1d1894a3..179f34e2 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.hlsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FSR2_BIND_SRV_INPUT_MOTION_VECTORS 0 #define FSR2_BIND_SRV_INPUT_DEPTH 1 #define FSR2_BIND_SRV_INPUT_COLOR 2 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.glsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.glsl index 8af17319..65b9c901 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.glsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.glsl @@ -1,20 +1,20 @@ // This file is part of the FidelityFX SDK. // -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// Copyright � 2023 Advanced Micro Devices, Inc. +// // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files(the “Software”), to deal +// 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 +// 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 +// +// 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 +// 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 diff --git a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.hlsl b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.hlsl index 980df5f7..88889d80 100644 --- a/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.hlsl +++ b/samples/ffx_cauldron/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FSR2_BIND_SRV_INPUT_OPAQUE_ONLY 0 #define FSR2_BIND_SRV_INPUT_COLOR 1 #define FSR2_BIND_SRV_INPUT_MOTION_VECTORS 2 diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.glsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.glsl new file mode 100644 index 00000000..c0beef97 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.glsl @@ -0,0 +1,87 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2022-2023 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. + +#version 450 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_samplerless_texture_functions : require +// Needed for rw_upscaled_output declaration +#extension GL_EXT_shader_image_load_formatted : require + +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 0 +#define FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS 1 +#if FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS +#define FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS 2 +#else +#define FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS 2 +#endif +#define FSR3UPSCALER_BIND_SRV_INTERNAL_UPSCALED 3 +#define FSR3UPSCALER_BIND_SRV_LOCK_STATUS 4 +#define FSR3UPSCALER_BIND_SRV_INPUT_DEPTH_CLIP 5 +#define FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR 6 +#define FSR3UPSCALER_BIND_SRV_LUMA_INSTABILITY 7 +#define FSR3UPSCALER_BIND_SRV_LANCZOS_LUT 8 +#define FSR3UPSCALER_BIND_SRV_UPSCALE_MAXIMUM_BIAS_LUT 9 +#define FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS 10 +#define FSR3UPSCALER_BIND_SRV_AUTO_EXPOSURE 11 +#define FSR3UPSCALER_BIND_SRV_LUMA_HISTORY 12 + +#define FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED 2013 +#define FSR3UPSCALER_BIND_UAV_LOCK_STATUS 2014 +#define FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT 2015 +#define FSR3UPSCALER_BIND_UAV_NEW_LOCKS 2016 +#define FSR3UPSCALER_BIND_UAV_LUMA_HISTORY 2017 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 3000 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_upsample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_postprocess_lock_status.h" +#include "fsr3upscaler/ffx_fsr3upscaler_reproject.h" +#include "fsr3upscaler/ffx_fsr3upscaler_accumulate.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS layout (local_size_x = FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, local_size_y = FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, local_size_z = FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH) in; + +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +void main() +{ + uvec2 uGroupId = gl_WorkGroupID.xy; + const uint GroupRows = (uint(DisplaySize().y) + FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT - 1) / FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT; + uGroupId.y = GroupRows - uGroupId.y - 1; + + uvec2 uDispatchThreadId = uGroupId * uvec2(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT) + gl_LocalInvocationID.xy; + + Accumulate(ivec2(uDispatchThreadId)); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.hlsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.hlsl new file mode 100644 index 00000000..d2f1b322 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.hlsl @@ -0,0 +1,79 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 0 +#define FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS 1 +#if FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS +#define FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS 2 +#else +#define FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS 2 +#endif +#define FSR3UPSCALER_BIND_SRV_INTERNAL_UPSCALED 3 +#define FSR3UPSCALER_BIND_SRV_LOCK_STATUS 4 +#define FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR 5 +#define FSR3UPSCALER_BIND_SRV_LANCZOS_LUT 6 +#define FSR3UPSCALER_BIND_SRV_UPSCALE_MAXIMUM_BIAS_LUT 7 +#define FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS 8 +#define FSR3UPSCALER_BIND_SRV_AUTO_EXPOSURE 9 +#define FSR3UPSCALER_BIND_SRV_LUMA_HISTORY 10 + +#define FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED 0 +#define FSR3UPSCALER_BIND_UAV_LOCK_STATUS 1 +#define FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT 2 +#define FSR3UPSCALER_BIND_UAV_NEW_LOCKS 3 +#define FSR3UPSCALER_BIND_UAV_LUMA_HISTORY 4 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_upsample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_postprocess_lock_status.h" +#include "fsr3upscaler/ffx_fsr3upscaler_reproject.h" +#include "fsr3upscaler/ffx_fsr3upscaler_accumulate.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_PREFER_WAVE64 +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +void CS(uint2 uGroupId : SV_GroupID, uint2 uGroupThreadId : SV_GroupThreadID) +{ + const uint GroupRows = (uint(DisplaySize().y) + FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT - 1) / FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT; + uGroupId.y = GroupRows - uGroupId.y - 1; + + uint2 uDispatchThreadId = uGroupId * uint2(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT) + uGroupThreadId; + + Accumulate(uDispatchThreadId); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.glsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.glsl new file mode 100644 index 00000000..04641faf --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.glsl @@ -0,0 +1,80 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2022-2023 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. + +#version 450 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_samplerless_texture_functions : require + +#define FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY 0 +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 1 + +#define FSR3UPSCALER_BIND_UAV_AUTOREACTIVE 2002 + +#define FSR3UPSCALER_BIND_CB_REACTIVE 3000 +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 3001 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS layout (local_size_x = FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, local_size_y = FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, local_size_z = FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +void main() +{ + FfxUInt32x2 uDispatchThreadId = gl_GlobalInvocationID.xy; + + FfxFloat32x3 ColorPreAlpha = LoadOpaqueOnly(FFX_MIN16_I2(uDispatchThreadId)).rgb; + FfxFloat32x3 ColorPostAlpha = LoadInputColor(FFX_MIN16_I2(uDispatchThreadId)).rgb; + + if ((GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_TONEMAP) != 0) + { + ColorPreAlpha = Tonemap(ColorPreAlpha); + ColorPostAlpha = Tonemap(ColorPostAlpha); + } + + if ((GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_INVERSETONEMAP) != 0) + { + ColorPreAlpha = InverseTonemap(ColorPreAlpha); + ColorPostAlpha = InverseTonemap(ColorPostAlpha); + } + + FfxFloat32 out_reactive_value = 0.f; + FfxFloat32x3 delta = abs(ColorPostAlpha - ColorPreAlpha); + + out_reactive_value = ((GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_USE_COMPONENTS_MAX)!=0) ? max(delta.x, max(delta.y, delta.z)) : length(delta); + out_reactive_value *= GenReactiveScale(); + + out_reactive_value = ((GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_THRESHOLD)!=0) ? ((out_reactive_value < GenReactiveThreshold()) ? 0 : GenReactiveBinaryValue()) : out_reactive_value; + + imageStore(rw_output_autoreactive, FfxInt32x2(uDispatchThreadId), vec4(out_reactive_value)); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.hlsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.hlsl new file mode 100644 index 00000000..0d6e2ebb --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.hlsl @@ -0,0 +1,77 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY 0 +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 1 + +#define FSR3UPSCALER_BIND_UAV_AUTOREACTIVE 0 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 +#define FSR3UPSCALER_BIND_CB_REACTIVE 1 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +void CS(uint2 uGroupId : SV_GroupID, uint2 uGroupThreadId : SV_GroupThreadID) +{ + uint2 uDispatchThreadId = uGroupId * uint2(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT) + uGroupThreadId; + + float3 ColorPreAlpha = LoadOpaqueOnly( FFX_MIN16_I2(uDispatchThreadId) ).rgb; + float3 ColorPostAlpha = LoadInputColor(uDispatchThreadId).rgb; + + if (GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_TONEMAP) + { + ColorPreAlpha = Tonemap(ColorPreAlpha); + ColorPostAlpha = Tonemap(ColorPostAlpha); + } + + if (GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_INVERSETONEMAP) + { + ColorPreAlpha = InverseTonemap(ColorPreAlpha); + ColorPostAlpha = InverseTonemap(ColorPostAlpha); + } + + float out_reactive_value = 0.f; + float3 delta = abs(ColorPostAlpha - ColorPreAlpha); + + out_reactive_value = (GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_USE_COMPONENTS_MAX) ? max(delta.x, max(delta.y, delta.z)) : length(delta); + out_reactive_value *= GenReactiveScale(); + + out_reactive_value = (GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_THRESHOLD) ? (out_reactive_value < GenReactiveThreshold() ? 0 : GenReactiveBinaryValue()) : out_reactive_value; + + rw_output_autoreactive[uDispatchThreadId] = out_reactive_value; +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.glsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.glsl new file mode 100644 index 00000000..4954cdf5 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.glsl @@ -0,0 +1,58 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2022-2023 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. + +#version 450 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_samplerless_texture_functions : require + +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 0 + +#define FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC 2001 +#define FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE 2002 +#define FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 2003 +#define FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE 2004 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 3000 +#define FSR3UPSCALER_BIND_CB_SPD 3001 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS layout (local_size_x = FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, local_size_y = FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, local_size_z = FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +void main() +{ + ComputeAutoExposure(gl_WorkGroupID.xyz, gl_LocalInvocationIndex); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.hlsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.hlsl new file mode 100644 index 00000000..93b73326 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.hlsl @@ -0,0 +1,55 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 0 + +#define FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC 0 +#define FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE 1 +#define FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 2 +#define FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE 3 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 +#define FSR3UPSCALER_BIND_CB_SPD 1 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_CB2_ROOTSIG_CONTENT +void CS(uint3 WorkGroupId : SV_GroupID, uint LocalThreadIndex : SV_GroupIndex) +{ + ComputeAutoExposure(WorkGroupId, LocalThreadIndex); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.glsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.glsl new file mode 100644 index 00000000..28332461 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.glsl @@ -0,0 +1,67 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2022-2023 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. + +#version 450 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_samplerless_texture_functions : require + +#define FSR3UPSCALER_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH 0 +#define FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS 1 +#define FSR3UPSCALER_BIND_SRV_DILATED_DEPTH 2 +#define FSR3UPSCALER_BIND_SRV_REACTIVE_MASK 3 +#define FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK 4 +#define FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR 5 +#define FSR3UPSCALER_BIND_SRV_PREVIOUS_DILATED_MOTION_VECTORS 6 +#define FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS 7 +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 8 +#define FSR3UPSCALER_BIND_SRV_INPUT_DEPTH 9 +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 10 + +#define FSR3UPSCALER_BIND_UAV_DEPTH_CLIP 2011 +#define FSR3UPSCALER_BIND_UAV_DILATED_REACTIVE_MASKS 2012 +#define FSR3UPSCALER_BIND_UAV_PREPARED_INPUT_COLOR 2013 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 3000 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_depth_clip.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS layout (local_size_x = FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, local_size_y = FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, local_size_z = FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +void main() +{ + DepthClip(ivec2(gl_GlobalInvocationID.xy)); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.hlsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.hlsl new file mode 100644 index 00000000..70cc7ba0 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.hlsl @@ -0,0 +1,67 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH 0 +#define FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS 1 +#define FSR3UPSCALER_BIND_SRV_DILATED_DEPTH 2 +#define FSR3UPSCALER_BIND_SRV_REACTIVE_MASK 3 +#define FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK 4 +#define FSR3UPSCALER_BIND_SRV_PREVIOUS_DILATED_MOTION_VECTORS 5 +#define FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS 6 +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 7 +#define FSR3UPSCALER_BIND_SRV_INPUT_DEPTH 8 +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 9 + +#define FSR3UPSCALER_BIND_UAV_DILATED_REACTIVE_MASKS 0 +#define FSR3UPSCALER_BIND_UAV_PREPARED_INPUT_COLOR 1 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_depth_clip.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_PREFER_WAVE64 +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +void CS( + int2 iGroupId : SV_GroupID, + int2 iDispatchThreadId : SV_DispatchThreadID, + int2 iGroupThreadId : SV_GroupThreadID, + int iGroupIndex : SV_GroupIndex) +{ + DepthClip(iDispatchThreadId); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.glsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.glsl new file mode 100644 index 00000000..e1ad1660 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.glsl @@ -0,0 +1,58 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2022-2023 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. + +#version 450 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_samplerless_texture_functions : require + +#define FSR3UPSCALER_BIND_SRV_LOCK_INPUT_LUMA 0 + +#define FSR3UPSCALER_BIND_UAV_NEW_LOCKS 2001 +#define FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH 2002 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 3000 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_lock.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS layout (local_size_x = FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, local_size_y = FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, local_size_z = FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +void main() +{ + uvec2 uDispatchThreadId = gl_WorkGroupID.xy * uvec2(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT) + gl_LocalInvocationID.xy; + + ComputeLock(ivec2(uDispatchThreadId)); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.hlsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.hlsl new file mode 100644 index 00000000..26b28f01 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.hlsl @@ -0,0 +1,56 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_LOCK_INPUT_LUMA 0 + +#define FSR3UPSCALER_BIND_UAV_NEW_LOCKS 0 +#define FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH 1 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_lock.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_PREFER_WAVE64 +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +void CS(uint2 uGroupId : SV_GroupID, uint2 uGroupThreadId : SV_GroupThreadID) +{ + uint2 uDispatchThreadId = uGroupId * uint2(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT) + uGroupThreadId; + + ComputeLock(uDispatchThreadId); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.glsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.glsl new file mode 100644 index 00000000..427c9f7d --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.glsl @@ -0,0 +1,58 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2022-2023 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. + +#version 450 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_samplerless_texture_functions : require +// Needed for rw_upscaled_output declaration +#extension GL_EXT_shader_image_load_formatted : require + +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 0 +#define FSR3UPSCALER_BIND_SRV_RCAS_INPUT 1 + +#define FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT 2002 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 3000 +#define FSR3UPSCALER_BIND_CB_RCAS 3001 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_rcas.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 64 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS layout (local_size_x = FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, local_size_y = FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, local_size_z = FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +void main() +{ + RCAS(gl_LocalInvocationID.xyz, gl_WorkGroupID.xyz, gl_GlobalInvocationID.xyz); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.hlsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.hlsl new file mode 100644 index 00000000..bebdeb38 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.hlsl @@ -0,0 +1,53 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 0 +#define FSR3UPSCALER_BIND_SRV_RCAS_INPUT 1 + +#define FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT 0 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 +#define FSR3UPSCALER_BIND_CB_RCAS 1 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_rcas.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 64 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_CB2_ROOTSIG_CONTENT +void CS(uint3 LocalThreadId : SV_GroupThreadID, uint3 WorkGroupId : SV_GroupID, uint3 Dtid : SV_DispatchThreadID) +{ + RCAS(LocalThreadId, WorkGroupId, Dtid); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.glsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.glsl new file mode 100644 index 00000000..69f18355 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.glsl @@ -0,0 +1,65 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2022-2023 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. + +#version 450 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_samplerless_texture_functions : require + +#define FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS 0 +#define FSR3UPSCALER_BIND_SRV_INPUT_DEPTH 1 +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 2 +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 3 +#define FSR3UPSCALER_BIND_SRV_LUMA_HISTORY 4 + +#define FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH 2005 +#define FSR3UPSCALER_BIND_UAV_DILATED_MOTION_VECTORS 2006 +#define FSR3UPSCALER_BIND_UAV_DILATED_DEPTH 2007 +#define FSR3UPSCALER_BIND_UAV_PREPARED_INPUT_COLOR 2008 +#define FSR3UPSCALER_BIND_UAV_LUMA_HISTORY 2009 +#define FSR3UPSCALER_BIND_UAV_LUMA_INSTABILITY 2010 +#define FSR3UPSCALER_BIND_UAV_LOCK_INPUT_LUMA 2011 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 3000 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_reconstruct_dilated_velocity_and_previous_depth.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS layout (local_size_x = FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, local_size_y = FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, local_size_z = FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +void main() +{ + ReconstructAndDilate(FFX_MIN16_I2(gl_GlobalInvocationID.xy)); +} diff --git a/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.hlsl b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.hlsl new file mode 100644 index 00000000..f277fd16 --- /dev/null +++ b/samples/ffx_cauldron/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.hlsl @@ -0,0 +1,64 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS 0 +#define FSR3UPSCALER_BIND_SRV_INPUT_DEPTH 1 +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 2 +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 3 + +#define FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH 0 +#define FSR3UPSCALER_BIND_UAV_DILATED_MOTION_VECTORS 1 +#define FSR3UPSCALER_BIND_UAV_DILATED_DEPTH 2 +#define FSR3UPSCALER_BIND_UAV_LOCK_INPUT_LUMA 3 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_reconstruct_dilated_velocity_and_previous_depth.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_PREFER_WAVE64 +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +void CS( + int2 iGroupId : SV_GroupID, + int2 iDispatchThreadId : SV_DispatchThreadID, + int2 iGroupThreadId : SV_GroupThreadID, + int iGroupIndex : SV_GroupIndex +) +{ + ReconstructAndDilate(iDispatchThreadId); +} diff --git a/samples/ffx_cauldron/shaders/lens/ffx_lens_pass.hlsl b/samples/ffx_cauldron/shaders/lens/ffx_lens_pass.hlsl index c62dc00e..d00b428c 100644 --- a/samples/ffx_cauldron/shaders/lens/ffx_lens_pass.hlsl +++ b/samples/ffx_cauldron/shaders/lens/ffx_lens_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // Lens pass // SRV 0 : LENS_InputTexture : r_input_texture // UAV 0 : LENS_OutputTexture : rw_output_texture diff --git a/samples/ffx_cauldron/shaders/lpm/ffx_lpm_filter_pass.hlsl b/samples/ffx_cauldron/shaders/lpm/ffx_lpm_filter_pass.hlsl index 68e92d6f..ae2787c0 100644 --- a/samples/ffx_cauldron/shaders/lpm/ffx_lpm_filter_pass.hlsl +++ b/samples/ffx_cauldron/shaders/lpm/ffx_lpm_filter_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // LPM pass // SRV 0 : LPM_InputColor : r_input_color // UAV 0 : LPM_OutputColor : rw_output_color diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_blit_to_output_pass.hlsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_blit_to_output_pass.hlsl new file mode 100644 index 00000000..e85757c8 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_blit_to_output_pass.hlsl @@ -0,0 +1,22 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.glsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.hlsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.hlsl new file mode 100644 index 00000000..c74d7d72 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.hlsl @@ -0,0 +1,115 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_1 1 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_2 2 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_3 3 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_4 4 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_5 5 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_6 6 +//#define FFX_OPTICALFLOW_BIND_UAV_SPD_GLOBAL_ATOMIC 7 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 +#define FFX_OPTICALFLOW_BIND_CB_SPD 1 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" + +cbuffer cbSPD : FFX_OPTICALFLOW_DECLARE_CB(FFX_OPTICALFLOW_BIND_CB_SPD) { + + uint mips; + uint numWorkGroups; + uint2 workGroupOffset; + uint numWorkGroupOpticalFlowInputPyramid; + uint pad0_; + uint pad1_; + uint pad2_; +}; + +uint NumWorkGroups() +{ + return numWorkGroupOpticalFlowInputPyramid; +} + +void SPD_SetMipmap(int2 iPxPos, int index, float value) +{ + switch (index) + { + case 0: + rw_optical_flow_input_level_1[iPxPos] = value; + break; + case 1: + rw_optical_flow_input_level_2[iPxPos] = value; + break; + case 2: + rw_optical_flow_input_level_3[iPxPos] = value; + break; + case 3: + rw_optical_flow_input_level_4[iPxPos] = value; + break; + case 4: + rw_optical_flow_input_level_5[iPxPos] = value; + break; + case 5: + rw_optical_flow_input_level_6[iPxPos] = value; + break; + } +} + +void SPD_IncreaseAtomicCounter(inout uint spdCounter) +{ + // only required when L7, L8, ... need to be computed + // but for now only 7 levels pyramid are used + //InterlockedAdd(rw_spd_global_atomic[min16int2(0,0)], 1, spdCounter); +} + +void SPD_ResetAtomicCounter() +{ + // only required when L7, L8, ... need to be computed + // but for now only 7 levels pyramid are used + //rw_spd_global_atomic[min16int2(0,0)] = 0; +} + +#include "opticalflow/ffx_opticalflow_compute_luminance_pyramid.h" + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_OPTICALFLOW_NUM_THREADS + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_CB2_ROOTSIG_CONTENT +void CS(int2 iGlobalId : SV_DispatchThreadID, + int2 iGroupId : SV_GroupID, + int iLocalIndex : SV_GroupIndex) +{ + ComputeOpticalFlowInputPyramid(iGroupId, iLocalIndex); + +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.glsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.hlsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.hlsl new file mode 100644 index 00000000..2a2ffe11 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.hlsl @@ -0,0 +1,62 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_INPUT 0 +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS_INPUT 1 + +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT 1 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" + +#ifndef FFX_OPTICALFLOW_BLOCK_SIZE +#define FFX_OPTICALFLOW_BLOCK_SIZE 8 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 64 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH + +#include "opticalflow/ffx_opticalflow_compute_optical_flow_v5.h" + +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_OPTICALFLOW_NUM_THREADS + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_OPTICALFLOW_PREFER_WAVE64 +void CS(int2 iGlobalId : SV_DispatchThreadID, + int2 iLocalId : SV_GroupThreadID, + int2 iGroupId : SV_GroupID, + int iLocalIndex : SV_GroupIndex) +{ + int2 iGroupSize = int2(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT); + ComputeOpticalFlowAdvanced(iGlobalId, iLocalId, iGroupId, iLocalIndex, iGroupSize); +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.glsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.hlsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.hlsl new file mode 100644 index 00000000..bdc8d333 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.hlsl @@ -0,0 +1,57 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_HISTOGRAM 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM 1 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_TEMP 2 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT 3 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" +#include "opticalflow/ffx_opticalflow_compute_scd_divergence.h" + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_OPTICALFLOW_NUM_THREADS + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_OPTICALFLOW_PREFER_WAVE64 +void CS(int3 iGlobalId : SV_DispatchThreadID, + int2 iLocalId : SV_GroupThreadID, + int2 iGroupId : SV_GroupID, + int iLocalIndex : SV_GroupIndex) +{ + int2 iGroupSize = int2(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT); + ComputeSCDHistogramsDivergence(iGlobalId, iLocalId, iLocalIndex, iGroupId, iGroupSize); + +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.glsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.hlsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.hlsl new file mode 100644 index 00000000..3e490fde --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.hlsl @@ -0,0 +1,56 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS 0 + +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW 0 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 16 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 4 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH + +#include "opticalflow/ffx_opticalflow_filter_optical_flow_v5.h" + +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_OPTICALFLOW_NUM_THREADS + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_OPTICALFLOW_PREFER_WAVE64 +void CS(int2 iGlobalId : SV_DispatchThreadID, + int2 iLocalId : SV_GroupThreadID, + int2 iGroupId : SV_GroupID, + int iLocalIndex : SV_GroupIndex) +{ + FilterOpticalFlow(iGlobalId, iLocalId, iGroupId, iLocalIndex); +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.glsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.hlsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.hlsl new file mode 100644 index 00000000..03559356 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.hlsl @@ -0,0 +1,54 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_INPUT 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_HISTOGRAM 0 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" +#include "opticalflow/ffx_opticalflow_generate_scd_histogram.h" + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 32 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 8 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_OPTICALFLOW_PREFER_WAVE64 +void CS(int3 iGlobalId : SV_DispatchThreadID, + int2 iLocalId : SV_GroupThreadID, + int2 iGroupId : SV_GroupID, + int iLocalIndex : SV_GroupIndex) +{ + int2 iGroupSize = int2(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT); + GenerateSceneChangeDetectionHistogram(iGlobalId, iLocalId, iLocalIndex, iGroupId, iGroupSize); +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.glsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.hlsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.hlsl new file mode 100644 index 00000000..30be1a26 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.hlsl @@ -0,0 +1,51 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_SRV_INPUT_COLOR 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT 0 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 16 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 16 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif + +#include "opticalflow/ffx_opticalflow_prepare_luma.h" + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_OPTICALFLOW_PREFER_WAVE64 +void CS(int2 iGlobalId : SV_DispatchThreadID, int iLocalIndex : SV_GroupIndex) +{ + PrepareLuma(iGlobalId, iLocalIndex); +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.glsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.glsl new file mode 100644 index 00000000..d3154ae6 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.glsl @@ -0,0 +1,19 @@ +#version 450 + +#ifndef FFX_THREAD_GROUP_WIDTH +#define FFX_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_THREAD_GROUP_WIDTH +#ifndef FFX_THREAD_GROUP_HEIGHT +#define FFX_THREAD_GROUP_HEIGHT 1 +#endif // FFX_THREAD_GROUP_HEIGHT +#ifndef FFX_THREAD_GROUP_DEPTH +#define FFX_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_THREAD_GROUP_DEPTH +#ifndef FFX_NUM_THREADS +#define FFX_NUM_THREADS layout (local_size_x = FFX_THREAD_GROUP_WIDTH, local_size_y = FFX_THREAD_GROUP_HEIGHT, local_size_z = FFX_THREAD_GROUP_DEPTH) in; +#endif // #ifndef FFX_NUM_THREADS + +FFX_NUM_THREADS +void main() +{ +} diff --git a/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.hlsl b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.hlsl new file mode 100644 index 00000000..c49ef3e7 --- /dev/null +++ b/samples/ffx_cauldron/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.hlsl @@ -0,0 +1,59 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_INPUT 0 +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS_INPUT 1 +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW 2 + +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_NEXT_LEVEL 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT 1 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" + +#ifndef FFX_OPTICALFLOW_BLOCK_SIZE +#define FFX_OPTICALFLOW_BLOCK_SIZE 8 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH (FFX_OPTICALFLOW_BLOCK_SIZE / 2) +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT (FFX_OPTICALFLOW_BLOCK_SIZE / 2) +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 4 +#endif + +#include "opticalflow/ffx_opticalflow_scale_optical_flow_advanced_v5.h" + +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_OPTICALFLOW_PREFER_WAVE64 +void CS(int3 iGlobalId : SV_DispatchThreadID, int3 iLocalId : SV_GroupThreadID) +{ + ScaleOpticalFlowAdvanced(iGlobalId, iLocalId); +} diff --git a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_reduce_pass.hlsl b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_reduce_pass.hlsl index 250545be..317953c5 100644 --- a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_reduce_pass.hlsl +++ b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_reduce_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // Parallel Sort Reduce Pass // UAV 0 : ParallelSort_Sum_Table : rw_sum_table // UAV 1 : ParallelSort_Reduce_Table : rw_reduce_table diff --git a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scan_add_pass.hlsl b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scan_add_pass.hlsl index d521d5bb..110c6f7a 100644 --- a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scan_add_pass.hlsl +++ b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scan_add_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // Parallel Sort Scan Add Pass // UAV 0 : ParallelSort_Scan_Source : rw_scan_source // UAV 1 : ParallelSort_Scan_Dest : rw_scan_dest diff --git a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scan_pass.hlsl b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scan_pass.hlsl index bfd39802..5ffc72ce 100644 --- a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scan_pass.hlsl +++ b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scan_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // Parallel Sort Scan Pass // UAV 0 : ParallelSort_Scan_Source : rw_scan_source // UAV 1 : ParallelSort_Scan_Dest : rw_scan_dest diff --git a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scatter_pass.hlsl b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scatter_pass.hlsl index 945be014..f492390c 100644 --- a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scatter_pass.hlsl +++ b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_scatter_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // Parallel Sort Scatter Pass // UAV 0 : ParallelSort_Source_Keys : rw_source_keys // UAV 1 : ParallelSort_Dest_Keys : rw_dest_keys diff --git a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_setup_indirect_args_pass.hlsl b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_setup_indirect_args_pass.hlsl index 76b10db8..36f09d5f 100644 --- a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_setup_indirect_args_pass.hlsl +++ b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_setup_indirect_args_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // Setup Indirect Args Pass // UAV 0 : ParallelSort_Indirect_Count_Scatter_Args : rw_count_scatter_args // UAV 1 : ParallelSort_Indirect_Reduce_Scan_Args : rw_reduce_scan_args diff --git a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_sum_pass.hlsl b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_sum_pass.hlsl index 07150dcd..446e1e12 100644 --- a/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_sum_pass.hlsl +++ b/samples/ffx_cauldron/shaders/parallelsort/ffx_parallelsort_sum_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // Parallel Sort Sum Pass // UAV 0 : ParallelSort_Source_Keys : rw_source_keys // UAV 1 : ParallelSort_Sum_Table : rw_sum_table diff --git a/samples/ffx_cauldron/shaders/spd/ffx_spd_downsample_pass.hlsl b/samples/ffx_cauldron/shaders/spd/ffx_spd_downsample_pass.hlsl index 639b80e4..db99eee3 100644 --- a/samples/ffx_cauldron/shaders/spd/ffx_spd_downsample_pass.hlsl +++ b/samples/ffx_cauldron/shaders/spd/ffx_spd_downsample_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // SPD pass // SRV 0 : SPD_InputDownsampleSrc : r_input_downsample_src // UAV 0 : SPD_InternalGlobalAtomic : rw_internal_global_atomic diff --git a/samples/ffx_cauldron/shaders/sssr/ffx_sssr_classify_tiles_pass.hlsl b/samples/ffx_cauldron/shaders/sssr/ffx_sssr_classify_tiles_pass.hlsl index b871caea..d943f080 100644 --- a/samples/ffx_cauldron/shaders/sssr/ffx_sssr_classify_tiles_pass.hlsl +++ b/samples/ffx_cauldron/shaders/sssr/ffx_sssr_classify_tiles_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FFX_WAVE 1 #define SSSR_BIND_SRV_INPUT_NORMAL 0 diff --git a/samples/ffx_cauldron/shaders/sssr/ffx_sssr_depth_downsample_pass.hlsl b/samples/ffx_cauldron/shaders/sssr/ffx_sssr_depth_downsample_pass.hlsl index 5798d968..8a170e27 100644 --- a/samples/ffx_cauldron/shaders/sssr/ffx_sssr_depth_downsample_pass.hlsl +++ b/samples/ffx_cauldron/shaders/sssr/ffx_sssr_depth_downsample_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define SSSR_BIND_SRV_INPUT_DEPTH 0 #define SSSR_BIND_UAV_SPD_GLOBAL_ATOMIC 1 diff --git a/samples/ffx_cauldron/shaders/sssr/ffx_sssr_intersect_pass.hlsl b/samples/ffx_cauldron/shaders/sssr/ffx_sssr_intersect_pass.hlsl index fd6da33c..919d5aaa 100644 --- a/samples/ffx_cauldron/shaders/sssr/ffx_sssr_intersect_pass.hlsl +++ b/samples/ffx_cauldron/shaders/sssr/ffx_sssr_intersect_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FFX_WAVE 1 #define SSSR_BIND_SRV_INPUT_COLOR 0 diff --git a/samples/ffx_cauldron/shaders/sssr/ffx_sssr_prepare_blue_noise_texture_pass.hlsl b/samples/ffx_cauldron/shaders/sssr/ffx_sssr_prepare_blue_noise_texture_pass.hlsl index 86313ee1..f1ce2b17 100644 --- a/samples/ffx_cauldron/shaders/sssr/ffx_sssr_prepare_blue_noise_texture_pass.hlsl +++ b/samples/ffx_cauldron/shaders/sssr/ffx_sssr_prepare_blue_noise_texture_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define SSSR_BIND_SRV_SOBOL_BUFFER 0 #define SSSR_BIND_SRV_SCRAMBLING_TILE_BUFFER 1 diff --git a/samples/ffx_cauldron/shaders/sssr/ffx_sssr_prepare_indirect_args_pass.hlsl b/samples/ffx_cauldron/shaders/sssr/ffx_sssr_prepare_indirect_args_pass.hlsl index eede5f25..72812c8e 100644 --- a/samples/ffx_cauldron/shaders/sssr/ffx_sssr_prepare_indirect_args_pass.hlsl +++ b/samples/ffx_cauldron/shaders/sssr/ffx_sssr_prepare_indirect_args_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define SSSR_BIND_UAV_RAY_COUNTER 0 #define SSSR_BIND_UAV_INTERSECTION_PASS_INDIRECT_ARGS 1 diff --git a/samples/ffx_cauldron/shaders/vrs/ffx_vrs_imagegen_pass.hlsl b/samples/ffx_cauldron/shaders/vrs/ffx_vrs_imagegen_pass.hlsl index 0de55504..98acefaf 100644 --- a/samples/ffx_cauldron/shaders/vrs/ffx_vrs_imagegen_pass.hlsl +++ b/samples/ffx_cauldron/shaders/vrs/ffx_vrs_imagegen_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // Texture definitions // RWTexture2D rw_vrsimage_output : register(u0); // Texture2D r_input_color : register(t0); diff --git a/samples/fsr/CMakeLists.txt b/samples/fsr/CMakeLists.txt index 485e38c1..5ba093e9 100644 --- a/samples/fsr/CMakeLists.txt +++ b/samples/fsr/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 @@ -36,6 +35,11 @@ set(fsr_sample_files ${CMAKE_CURRENT_SOURCE_DIR}/fsrsample.h ${CMAKE_CURRENT_SOURCE_DIR}/fsrsample.cpp) +# FSR render module files +file(GLOB hlslCompile_src + ${CMAKE_CURRENT_SOURCE_DIR}/HLSLCompile/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/HLSLCompile/*.cpp) + # FSR render module files file(GLOB fsr_src ${CMAKE_CURRENT_SOURCE_DIR}/*rendermodule.h @@ -44,21 +48,29 @@ file(GLOB fsr_src file(GLOB fsr_shaders ${CMAKE_CURRENT_SOURCE_DIR}/shaders/*.h ${CMAKE_CURRENT_SOURCE_DIR}/shaders/*.hlsl) -set_source_files_properties(${spd_shaders} PROPERTIES VS_TOOL_OVERRIDE "Text") +set_source_files_properties(${fsr_shaders} PROPERTIES VS_TOOL_OVERRIDE "Text") copyCommand("${fsr_shaders}" ${SHADER_OUTPUT}) # Add config file set(config_file ${CMAKE_CURRENT_SOURCE_DIR}/config/fsrconfig.json) copyCommand("${config_file}" ${CONFIG_OUTPUT}) +# Copy media file +set(animated_media_src ${CMAKE_CURRENT_SOURCE_DIR}/media/checkerboard.dds ${CMAKE_CURRENT_SOURCE_DIR}/media/composition_text.dds ${CMAKE_CURRENT_SOURCE_DIR}/media/lion.jpg) +copyCommand("${animated_media_src}" ${BIN_OUTPUT}/media/textures) + # Add the sample to the solution -add_executable(${PROJECT_NAME} WIN32 ${default_icon_src} ${default_entry_point} ${fsr_sample_files} ${config_file} ${fsr_src} ${fsr_shaders} ${ffx_remap}) +add_executable(${PROJECT_NAME} WIN32 ${default_icon_src} ${default_entry_point} ${fsr_sample_files} ${config_file} ${fsr_src} ${hlslCompile_src} ${fsr_shaders} ${ffx_remap} ${animated_media_src}) # Setup the correct exe based on backend name set(EXE_OUT_NAME ${PROJECT_NAME}_) # Link everything -target_link_libraries(${PROJECT_NAME} LINK_PUBLIC Framework RenderModules d3dcompiler ffx_fsr2_${FFX_PLATFORM_NAME} ffx_fsr1_${FFX_PLATFORM_NAME}) +if (FFX_API STREQUAL CAULDRON) +target_link_libraries(${PROJECT_NAME} LINK_PUBLIC Framework RenderModules d3dcompiler ffx_backend_cauldron_${FFX_PLATFORM_NAME} ffx_fsr3_${FFX_PLATFORM_NAME} ffx_fsr3upscaler_${FFX_PLATFORM_NAME} ffx_frameinterpolation_${FFX_PLATFORM_NAME} ffx_opticalflow_${FFX_PLATFORM_NAME} ffx_fsr2_${FFX_PLATFORM_NAME} ffx_fsr1_${FFX_PLATFORM_NAME}) +else() +target_link_libraries(${PROJECT_NAME} LINK_PUBLIC Framework RenderModules d3dcompiler ffx_backend_native ffx_fsr3_${FFX_PLATFORM_NAME} ffx_fsr3upscaler_${FFX_PLATFORM_NAME} ffx_frameinterpolation_${FFX_PLATFORM_NAME} ffx_opticalflow_${FFX_PLATFORM_NAME} ffx_fsr2_${FFX_PLATFORM_NAME} ffx_fsr1_${FFX_PLATFORM_NAME}) +endif() set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME_DEBUGDX12 "${EXE_OUT_NAME}DX12D" OUTPUT_NAME_DEBUGVK "${EXE_OUT_NAME}VKD" @@ -69,6 +81,10 @@ set_target_properties(${PROJECT_NAME} PROPERTIES # Add dependency information add_dependencies(${PROJECT_NAME} Framework) add_dependencies(${PROJECT_NAME} RenderModules) +add_dependencies(${PROJECT_NAME} ffx_fsr3_${FFX_PLATFORM_NAME}) +add_dependencies(${PROJECT_NAME} ffx_fsr3upscaler_${FFX_PLATFORM_NAME}) +add_dependencies(${PROJECT_NAME} ffx_frameinterpolation_${FFX_PLATFORM_NAME}) +add_dependencies(${PROJECT_NAME} ffx_opticalflow_${FFX_PLATFORM_NAME}) add_dependencies(${PROJECT_NAME} ffx_fsr2_${FFX_PLATFORM_NAME}) add_dependencies(${PROJECT_NAME} ffx_fsr1_${FFX_PLATFORM_NAME}) @@ -86,14 +102,17 @@ if (FFX_API STREQUAL CAULDRON) target_include_directories(${PROJECT_NAME} PUBLIC ${FFX_API_CAULDRON_ROOT}) else() target_link_libraries(${PROJECT_NAME} LINK_PUBLIC ffx_backend_native) + add_dependencies(${PROJECT_NAME} ffx_backend_native) target_include_directories(${PROJECT_NAME} PUBLIC ${FFX_HOST_BACKENDS_PATH}) endif() # And solution layout definitions -source_group("" FILES ${default_entry_point}) -source_group("" FILES ${ffx_remap}) -source_group("Sample" FILES ${fsr_sample_files}) -source_group("Icon" FILES ${default_icon_src}) -source_group("Config" FILES ${config_file}) -source_group("RenderModule" FILES ${fsr_src}) -source_group("RenderModule\\Shaders" FILES ${fsr_shaders}) +source_group("" FILES ${default_entry_point}) +source_group("" FILES ${ffx_remap}) +source_group("Sample" FILES ${fsr_sample_files}) +source_group("Icon" FILES ${default_icon_src}) +source_group("Config" FILES ${config_file}) +source_group("RenderModule" FILES ${fsr_src}) +source_group("RenderModule\\HLSLCompile" FILES ${hlslCompile_src}) +source_group("RenderModule\\Shaders" FILES ${fsr_shaders}) +source_group("Media" FILES ${particle_media_src} ${animated_media_src}) diff --git a/samples/fsr/HLSLCompile/HLSLShaderCompiler.cpp b/samples/fsr/HLSLCompile/HLSLShaderCompiler.cpp new file mode 100644 index 00000000..8fa69d4e --- /dev/null +++ b/samples/fsr/HLSLCompile/HLSLShaderCompiler.cpp @@ -0,0 +1,1408 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include +#include + +#include +#include +#include +#include +#include + +#include "ShaderCompiler.h" +#include "HlslShaderCompiler.h" + +namespace HlslShaderCompiler +{ + #define FFX_MAX_RESOURCE_IDENTIFIER_COUNT (128) + + std::vector additionalIncludeDirs = {L"ffx_sdk\\fidelityfx-sdk-gpu\\"}; + + const std::vector getShaderPathFromEffectPassID(FfxEffect effectId, FfxPass passId) + { + if (effectId == FFX_EFFECT_FSR3UPSCALER) + { + const std::vector shaderFilenames[FFX_FSR3UPSCALER_PASS_COUNT] = { + { L"ffx_sdk\\fsr3upscaler\\ffx_fsr3upscaler_depth_clip_pass.hlsl"}, + { L"ffx_sdk\\fsr3upscaler\\ffx_fsr3upscaler_reconstruct_previous_depth_pass.hlsl"}, + { L"ffx_sdk\\fsr3upscaler\\ffx_fsr3upscaler_lock_pass.hlsl"}, + { L"ffx_sdk\\fsr3upscaler\\ffx_fsr3upscaler_accumulate_pass.hlsl"}, + { L"ffx_sdk\\fsr3upscaler\\ffx_fsr3upscaler_accumulate_pass.hlsl"}, + { L"ffx_sdk\\fsr3upscaler\\ffx_fsr3upscaler_rcas_pass.hlsl"}, + { L"ffx_sdk\\fsr3upscaler\\ffx_fsr3upscaler_compute_luminance_pyramid_pass.hlsl"}, + { L"ffx_sdk\\fsr3upscaler\\ffx_fsr3upscaler_autogen_reactive_pass.hlsl"}, + { L"ffx_sdk\\fsr3upscaler\\ffx_fsr3upscaler_tcr_autogen_pass.hlsl"}, + }; + + return shaderFilenames[passId]; + } + else if (effectId == FFX_EFFECT_OPTICALFLOW) + { + const std::vector shaderFilenames[FFX_OPTICALFLOW_PASS_COUNT] = { + { L"ffx_sdk\\opticalflow\\ffx_opticalflow_prepare_luma_pass.hlsl"}, + { L"ffx_sdk\\opticalflow\\ffx_opticalflow_compute_luminance_pyramid_pass.hlsl"}, + { L"ffx_sdk\\opticalflow\\ffx_opticalflow_generate_scd_histogram_pass.hlsl"}, + { L"ffx_sdk\\opticalflow\\ffx_opticalflow_compute_scd_divergence_pass.hlsl"}, + { L"ffx_sdk\\opticalflow\\ffx_opticalflow_compute_optical_flow_advanced_pass_v5.hlsl"}, + { L"ffx_sdk\\opticalflow\\ffx_opticalflow_filter_optical_flow_pass_v5.hlsl"}, + { L"ffx_sdk\\opticalflow\\ffx_opticalflow_scale_optical_flow_advanced_pass_v5.hlsl"}, + }; + + return shaderFilenames[passId]; + } + else if (effectId == FFX_EFFECT_FRAMEINTERPOLATION) + { + const std::vector shaderFilenames[FFX_FRAMEINTERPOLATION_PASS_COUNT] = { + { L"ffx_sdk\\frameinterpolation\\ffx_frameinterpolation_setup.hlsl"}, + { L"ffx_sdk\\frameinterpolation\\ffx_frameinterpolation_reconstruct_previous_depth.hlsl"}, + { L"ffx_sdk\\frameinterpolation\\ffx_frameinterpolation_game_motion_vector_field.hlsl"}, + { L"ffx_sdk\\frameinterpolation\\ffx_frameinterpolation_optical_flow_vector_field.hlsl"}, + { L"ffx_sdk\\frameinterpolation\\ffx_frameinterpolation_disocclusion_mask.hlsl"}, + { L"ffx_sdk\\frameinterpolation\\ffx_frameinterpolation_pass.hlsl"}, + { L"ffx_sdk\\frameinterpolation\\ffx_frameinterpolation_compute_inpainting_pyramid_pass.hlsl"}, + { L"ffx_sdk\\frameinterpolation\\ffx_frameinterpolation_inpainting_pass.hlsl"}, + { L"ffx_sdk\\frameinterpolation\\ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.hlsl"}, + }; + + return shaderFilenames[passId]; + } + return {}; + } + + + static std::map s_shaderDefines; + + struct ShaderCompilationResult + { + IDxcBlob* shaderBlob = nullptr; + std::vector boundSamplers; + std::vector boundSamplersNames; + + std::vector boundRegistersUAVs; + std::vector boundRegistersUAVNames; + std::vector boundRegistersUAVsCount; + std::vector boundRegistersSRVs; + std::vector boundRegistersSRVNames; + std::vector boundRegistersCBs; + std::vector boundRegistersCBNames; + + std::vector boundRegistersUAVBuffers; + std::vector boundRegistersUAVBuffersNames; + std::vector boundRegistersSRVBuffers; + std::vector boundRegistersSRVBuffersNames; + std::vector boundRegistersRTASs; + std::vector boundRegistersRTASsNames; + }; + + struct D3D12DeviceProperties + { + D3D_SHADER_MODEL HighestShaderModel; + uint32_t WaveLaneCountMin; + uint32_t WaveLaneCountMax; + bool HLSLWaveSizeSupported; + bool FP16Supported; + }; + + static FidelityFx::ShaderCompiler s_dxilCompiler = {}; + static wchar_t s_fullshaderCompilerPath[] = L"./dxcompiler.dll"; + static wchar_t s_fullshaderDXILPath[] = L"./dxil.dll"; + static wchar_t s_fullShaderOutputPath[] = L"./ShaderLibDX/FSR2.0/"; + static D3D12DeviceProperties s_deviceProperties; + static bool s_sharpenEnabled; + static bool s_bUseHLSLShaders = true; + static ID3D12Device* s_dx12Device = nullptr; + +// Dev options +// !NOT FOR SHIPPING! +#define DECL_DEV_OPTION(VarName, ShaderDef, DefaultVal) \ + static bool s_##VarName = DefaultVal; \ + static const wchar_t* s_##szShaderDef_##VarName = L#ShaderDef; + +#define DECL_DEV_OPTION_TYPED(Type, VarName, ShaderDef, DefaultVal) \ + static Type s_##VarName = DefaultVal; \ + static const wchar_t* s_##szShaderDef_##VarName = L#ShaderDef; + + DECL_DEV_OPTION(bOptionUpsampleSamplersUseDataHalf, FFX_FSR3UPSCALER_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF, false) + DECL_DEV_OPTION(bOptionAccumulateSamplersUseDataHalf, FFX_FSR3UPSCALER_OPTION_ACCUMULATE_SAMPLERS_USE_DATA_HALF, false) + DECL_DEV_OPTION(bOptionReprojectSamplersUseDataHalf, FFX_FSR3UPSCALER_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF, true) + DECL_DEV_OPTION(bOptionPostprocessLockstatusSamplersUseDataHalf, FFX_FSR3UPSCALER_OPTION_POSTPROCESSLOCKSTATUS_SAMPLERS_USE_DATA_HALF, false) + + enum LanczosType + { + LANCZOS_TYPE_REFERENCE, + LANCZOS_TYPE_LUT, + LANCZOS_TYPE_APPROXIMATE, + }; + DECL_DEV_OPTION_TYPED(LanczosType, bOptionUpsampleUseLanczosType, FFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE, LANCZOS_TYPE_APPROXIMATE); + DECL_DEV_OPTION_TYPED(LanczosType, bOptionReprojectUseLanczosType, FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE, LANCZOS_TYPE_LUT); + + static void queryDeviceProperties(ID3D12Device* device) + { + // setup what we need for HLSL compilation + memset(&s_deviceProperties, 0, sizeof(D3D12DeviceProperties)); + s_deviceProperties.HighestShaderModel = D3D_SHADER_MODEL_6_2; + D3D12_FEATURE_DATA_SHADER_MODEL shaderModel = {D3D_SHADER_MODEL_6_6}; + if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shaderModel, sizeof(D3D12_FEATURE_DATA_SHADER_MODEL)))) + { + s_deviceProperties.HighestShaderModel = shaderModel.HighestShaderModel; + } + + D3D12_FEATURE_DATA_D3D12_OPTIONS1 d3d12Options1 = {}; + if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS1, &d3d12Options1, sizeof(d3d12Options1)))) + { + s_deviceProperties.HLSLWaveSizeSupported = (s_deviceProperties.HighestShaderModel >= D3D_SHADER_MODEL_6_6) && d3d12Options1.WaveOps; + + s_deviceProperties.WaveLaneCountMin = d3d12Options1.WaveLaneCountMin; + s_deviceProperties.WaveLaneCountMax = d3d12Options1.WaveLaneCountMax; + } + + D3D12_FEATURE_DATA_D3D12_OPTIONS d3d12Options = {}; + if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &d3d12Options, sizeof(d3d12Options)))) + { + s_deviceProperties.FP16Supported = !!(d3d12Options.MinPrecisionSupport & D3D12_SHADER_MIN_PRECISION_SUPPORT_16_BIT); + } + } + + static void setupShaderCompiler(ID3D12Device* device) + { + s_dxilCompiler.init(s_fullshaderCompilerPath, s_fullshaderDXILPath); + } + + typedef enum Fs3UpscalerShaderPermutationOptions + { + FSR3UPSCALER_SHADER_PERMUTATION_USE_LANCZOS_TYPE = (1 << 0), ///< Off means reference, On means LUT + FSR3UPSCALER_SHADER_PERMUTATION_HDR_COLOR_INPUT = (1 << 1), ///< Enables the HDR code path + FSR3UPSCALER_SHADER_PERMUTATION_LOW_RES_MOTION_VECTORS = (1 << 2), ///< Indicates low resolution motion vectors provided + FSR3UPSCALER_SHADER_PERMUTATION_JITTER_MOTION_VECTORS = (1 << 3), ///< Indicates motion vectors were generated with jitter + FSR3UPSCALER_SHADER_PERMUTATION_DEPTH_INVERTED = (1 << 4), ///< Indicates input resources were generated with inverted depth + FSR3UPSCALER_SHADER_PERMUTATION_ENABLE_SHARPENING = (1 << 5), ///< Enables a supplementary sharpening pass + FSR3UPSCALER_SHADER_PERMUTATION_FORCE_WAVE64 = (1 << 6), ///< doesn't map to a define, selects different table + FSR3UPSCALER_SHADER_PERMUTATION_ALLOW_FP16 = (1 << 7), ///< Enables fast math computations where possible + } Fs3UpscalerShaderPermutationOptions; + + typedef enum FrameinterpolationShaderPermutationOptions + { + FRAMEINTERPOLATION_SHADER_PERMUTATION_USE_LANCZOS_TYPE = (1 << 0), ///< Off means reference, On means LUT + FRAMEINTERPOLATION_SHADER_PERMUTATION_HDR_COLOR_INPUT = (1 << 1), ///< Enables the HDR code path + FRAMEINTERPOLATION_SHADER_PERMUTATION_LOW_RES_MOTION_VECTORS = (1 << 2), ///< Indicates low resolution motion vectors provided + FRAMEINTERPOLATION_SHADER_PERMUTATION_JITTER_MOTION_VECTORS = (1 << 3), ///< Indicates motion vectors were generated with jitter + FRAMEINTERPOLATION_SHADER_PERMUTATION_DEPTH_INVERTED = (1 << 4), ///< Indicates input resources were generated with inverted depth + FRAMEINTERPOLATION_SHADER_PERMUTATION_ENABLE_SHARPENING = (1 << 5), ///< Enables a supplementary sharpening pass + FRAMEINTERPOLATION_SHADER_PERMUTATION_FORCE_WAVE64 = (1 << 6), ///< doesn't map to a define, selects different table + FRAMEINTERPOLATION_SHADER_PERMUTATION_ALLOW_FP16 = (1 << 7), ///< Enables fast math computations where possible + } FrameinterpolationShaderPermutationOptions; + + typedef enum OpticalflowShaderPermutationOptions + { + OPTICALFLOW_SHADER_PERMUTATION_FORCE_WAVE64 = (1 << 0), ///< doesn't map to a define, selects different table + OPTICALFLOW_SHADER_PERMUTATION_ALLOW_FP16 = (1 << 1), ///< Enables fast math computations where possible + OPTICALFLOW_HDR_COLOR_INPUT = (1 << 2), + } OpticalflowShaderPermutationOptions; + + static void getShaderDefinesFromEffectPassID(FfxEffect effect, FfxPass pass, uint32_t permutationOptions) + { + s_deviceProperties.FP16Supported = true; + + // clear the list of defines. + s_shaderDefines.clear(); + + s_shaderDefines[L"FFX_GPU"] = L"1"; + s_shaderDefines[L"FFX_HLSL"] = L"1"; + s_shaderDefines[L"FFX_HLSL_6_2"] = L"1"; + +#define REG_OPT(x) x ? L"1" : L"0"; + + if (effect == FFX_EFFECT_FSR3UPSCALER) + { + bool enable_fp16 = s_deviceProperties.FP16Supported && (permutationOptions & FSR3UPSCALER_SHADER_PERMUTATION_ALLOW_FP16); + switch (pass) + { + case FFX_FSR3UPSCALER_PASS_COMPUTE_LUMINANCE_PYRAMID: + case FFX_FSR3UPSCALER_PASS_RCAS: + enable_fp16 = false; + break; + } + + s_shaderDefines[L"FFX_HALF"] = REG_OPT(enable_fp16); + s_shaderDefines[L"FFX_PREFER_WAVE64"] = (permutationOptions & FSR3UPSCALER_SHADER_PERMUTATION_FORCE_WAVE64) ? L"[WaveSize(64)]" : L""; + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF"] = L"0"; + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_ACCUMULATE_SAMPLERS_USE_DATA_HALF"] = L"0"; + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF"] = L"1"; + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_POSTPROCESSLOCKSTATUS_SAMPLERS_USE_DATA_HALF"] = L"0"; + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE"] = L"2"; + + // Creation params + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE"] = REG_OPT(permutationOptions & FSR3UPSCALER_SHADER_PERMUTATION_USE_LANCZOS_TYPE); + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT"] = REG_OPT(permutationOptions & FSR3UPSCALER_SHADER_PERMUTATION_HDR_COLOR_INPUT); + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS"] = REG_OPT(permutationOptions & FSR3UPSCALER_SHADER_PERMUTATION_LOW_RES_MOTION_VECTORS); + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS"] = REG_OPT(permutationOptions & FSR3UPSCALER_SHADER_PERMUTATION_JITTER_MOTION_VECTORS); + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH"] = REG_OPT(permutationOptions & FSR3UPSCALER_SHADER_PERMUTATION_DEPTH_INVERTED); + s_shaderDefines[L"FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING"] = (pass == FFX_FSR3UPSCALER_PASS_ACCUMULATE_SHARPEN) ? L"1" : L"0"; + } + else if (effect == FFX_EFFECT_FRAMEINTERPOLATION) + { + bool enable_fp16 = s_deviceProperties.FP16Supported && (permutationOptions & FRAMEINTERPOLATION_SHADER_PERMUTATION_ALLOW_FP16); + s_shaderDefines[L"FFX_HALF"] = REG_OPT(enable_fp16); + + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF"] = L"0"; + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_ACCUMULATE_SAMPLERS_USE_DATA_HALF"] = L"0"; + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF"] = L"1"; + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_POSTPROCESSLOCKSTATUS_SAMPLERS_USE_DATA_HALF"] = L"0"; + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_UPSAMPLE_USE_LANCZOS_TYPE"] = REG_OPT(permutationOptions & FRAMEINTERPOLATION_SHADER_PERMUTATION_USE_LANCZOS_TYPE); + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_REPROJECT_USE_LANCZOS_TYPE"] = REG_OPT(permutationOptions & FRAMEINTERPOLATION_SHADER_PERMUTATION_USE_LANCZOS_TYPE); + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_HDR_COLOR_INPUT"] = REG_OPT(permutationOptions & FRAMEINTERPOLATION_SHADER_PERMUTATION_HDR_COLOR_INPUT); + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_LOW_RESOLUTION_MOTION_VECTORS"] = REG_OPT(permutationOptions & FRAMEINTERPOLATION_SHADER_PERMUTATION_LOW_RES_MOTION_VECTORS); + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_JITTERED_MOTION_VECTORS"] = REG_OPT(permutationOptions & FRAMEINTERPOLATION_SHADER_PERMUTATION_JITTER_MOTION_VECTORS); + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH"] = REG_OPT(permutationOptions & FRAMEINTERPOLATION_SHADER_PERMUTATION_DEPTH_INVERTED); + s_shaderDefines[L"FFX_FRAMEINTERPOLATION_OPTION_APPLY_SHARPENING"] = REG_OPT(permutationOptions & FRAMEINTERPOLATION_SHADER_PERMUTATION_ENABLE_SHARPENING); + } + else if (effect == FFX_EFFECT_OPTICALFLOW) + { + bool enable_fp16 = s_deviceProperties.FP16Supported && (permutationOptions & OPTICALFLOW_SHADER_PERMUTATION_ALLOW_FP16); + bool s_forceWave64 = (permutationOptions & OPTICALFLOW_SHADER_PERMUTATION_FORCE_WAVE64); + if (s_forceWave64) + { + s_shaderDefines[L"FFX_PREFER_WAVE64"] = L"[WaveSize(64)]"; + s_shaderDefines[L"FFX_OPTICALFLOW_PREFER_WAVE64"] = L"[WaveSize(64)]"; + } + + s_shaderDefines[L"FFX_HALF"] = REG_OPT(enable_fp16); + } + } + + static ShaderCompilationResult compileShader(std::wstring const& path, + std::wstring const& entryPoint, + const std::map& defines, + const std::vector& additionalIncludeDirs, + std::wstring const& profile = L"") + { + ShaderCompilationResult compilationResult; + FidelityFx::ShaderCompilationDesc shaderDesc; + + std::wstring fullshaderCompilerPath = L"dxcompiler.dll"; + std::wstring fullshaderDXILPath = L"dxil.dll"; + s_dxilCompiler.init(fullshaderCompilerPath.c_str(), fullshaderDXILPath.c_str()); + + // https://simoncoenen.com/blog/programming/graphics/DxcCompiling.html + //shaderDesc.CompileArguments.push_back(L"-Gis"); // Force IEEE strictness + shaderDesc.CompileArguments.push_back(L"-Wno-for-redefinition"); // Disable "for redefinition" warning + shaderDesc.CompileArguments.push_back(L"-Wno-ambig-lit-shift"); + // shaderDesc.CompileArguments.push_back(L"-Wconversion"); + + // Workaround: We want to keep an eye on warn_hlsl_implicit_vector_truncation, but it share the same toggle as the warn_hlsl_sema_minprecision_promotion and others. + // For debug build, enabling -Wconversion but disabling "-enable-16bit-types" as it causes flooding minprecision_promotion warnings. + //#ifndef _DEBUG + shaderDesc.CompileArguments.push_back(L"-enable-16bit-types"); // Enable 16bit types and disable min precision types. Available in HLSL 2018 and shader model 6.2 + //#endif + + // need to hold ref to the strings + std::vector additionalIncludeDirsStrings; + for (const auto& includeDir : additionalIncludeDirs) + { + additionalIncludeDirsStrings.push_back(std::wstring(L"-I") + includeDir); + } + + for (const auto& includeDir : additionalIncludeDirsStrings) + { + shaderDesc.CompileArguments.push_back(includeDir.c_str()); + } + +#if defined(_DEBUG) || defined(FFX_DEBUG_SHADERS) + shaderDesc.CompileArguments.push_back(L"-Qembed_debug"); // Embed PDB in shader container (must be used with /Zi) + shaderDesc.CompileArguments.push_back(L"-Zi"); // Enable debug information +#endif + + shaderDesc.EntryPoint = entryPoint.c_str(); + shaderDesc.TargetProfile = profile.empty() ? L"cs_6_2" : profile.c_str(); // Shader model 6.2 + std::vector definesv; + for (const auto& def : defines) + { + definesv.push_back({def.first.c_str(), def.second.c_str()}); + } + shaderDesc.Defines = definesv; + + IDxcBlob* pCS = nullptr; + IDxcBlob* pSignedCS = nullptr; + //OutputDebugString(path.c_str()); + if (SUCCEEDED(s_dxilCompiler.compileFromFile(path.c_str(), &shaderDesc, &pCS))) + { + IDxcOperationResult* result = nullptr; + if (SUCCEEDED(s_dxilCompiler.validate(pCS, &result, DxcValidatorFlags_Default))) + { + HRESULT validateStatus; + result->GetStatus(&validateStatus); + if (SUCCEEDED(validateStatus) && SUCCEEDED(result->GetResult(&pSignedCS))) + { + compilationResult.shaderBlob = pSignedCS; + + auto dgbReflection = s_dxilCompiler.dgbReflection(); + dgbReflection->Load(pSignedCS); + + UINT shaderIdx; + dgbReflection->FindFirstPartKind(FidelityFx::DFCC_DXIL, &shaderIdx); + + ID3D12ShaderReflection* pReflection = nullptr; + dgbReflection->GetPartReflection(shaderIdx, IID_PPV_ARGS(&pReflection)); + + D3D12_SHADER_DESC desc; + if (SUCCEEDED(pReflection->GetDesc(&desc))) + { + for (UINT i = 0; i < desc.BoundResources; i++) + { + D3D12_SHADER_INPUT_BIND_DESC bindDesc; + if (SUCCEEDED(pReflection->GetResourceBindingDesc(i, &bindDesc))) + { + bindDesc = bindDesc; + if (bindDesc.Type == D3D_SHADER_INPUT_TYPE::D3D_SIT_SAMPLER) + { + compilationResult.boundSamplers.push_back(bindDesc.BindPoint); + compilationResult.boundSamplersNames.push_back(bindDesc.Name); + } + else if (bindDesc.Type == D3D_SHADER_INPUT_TYPE::D3D_SIT_TEXTURE) + { + compilationResult.boundRegistersSRVs.push_back(bindDesc.BindPoint); + compilationResult.boundRegistersSRVNames.push_back(bindDesc.Name); + } + else if (bindDesc.Type == D3D_SHADER_INPUT_TYPE::D3D_SIT_UAV_RWTYPED) + { + compilationResult.boundRegistersUAVs.push_back(bindDesc.BindPoint); + compilationResult.boundRegistersUAVNames.push_back(bindDesc.Name); + compilationResult.boundRegistersUAVsCount.push_back(bindDesc.BindCount); + } + else if (bindDesc.Type == D3D_SHADER_INPUT_TYPE::D3D_SIT_CBUFFER) + { + compilationResult.boundRegistersCBs.push_back(bindDesc.BindPoint); + compilationResult.boundRegistersCBNames.push_back(bindDesc.Name); + } + else if (bindDesc.Type == D3D_SIT_STRUCTURED) + { + compilationResult.boundRegistersSRVBuffers.push_back(bindDesc.BindPoint); + compilationResult.boundRegistersSRVBuffersNames.push_back(bindDesc.Name); + } + else if (bindDesc.Type == D3D_SIT_UAV_RWSTRUCTURED) + { + compilationResult.boundRegistersUAVBuffers.push_back(bindDesc.BindPoint); + compilationResult.boundRegistersUAVBuffersNames.push_back(bindDesc.Name); + } + else if (bindDesc.Type == D3D_SIT_RTACCELERATIONSTRUCTURE) + { + compilationResult.boundRegistersRTASs.push_back(bindDesc.BindPoint); + compilationResult.boundRegistersRTASsNames.push_back(bindDesc.Name); + } + } + } + } + } + + FidelityFx::SafeRelease(result); + } + + FidelityFx::SafeRelease(pCS); + } + + return compilationResult; + } + + D3D12_TEXTURE_ADDRESS_MODE FfxGetAddressModeDX12(const FfxAddressMode& addressMode) + { + switch (addressMode) + { + case FFX_ADDRESS_MODE_WRAP: + return D3D12_TEXTURE_ADDRESS_MODE_WRAP; + case FFX_ADDRESS_MODE_MIRROR: + return D3D12_TEXTURE_ADDRESS_MODE_MIRROR; + case FFX_ADDRESS_MODE_CLAMP: + return D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + case FFX_ADDRESS_MODE_BORDER: + return D3D12_TEXTURE_ADDRESS_MODE_BORDER; + case FFX_ADDRESS_MODE_MIRROR_ONCE: + return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; + default: + FFX_ASSERT_MESSAGE(false, "Unsupported addressing mode requested. Please implement"); + return D3D12_TEXTURE_ADDRESS_MODE_WRAP; + break; + } + } + + // !!!!!!! + // BAD HACK: needs to match BackendContext_DX12 in ffx_dx12.cpp + typedef struct BackendContext_DX12 + { + // store for resources and resourceViews + typedef struct Resource + { +#ifdef _DEBUG + wchar_t resourceName[64] = {}; +#endif + ID3D12Resource* resourcePtr; + FfxResourceDescription resourceDescription; + FfxResourceStates initialState; + FfxResourceStates currentState; + uint32_t srvDescIndex; + uint32_t uavDescIndex; + uint32_t uavDescCount; + } Resource; + + ID3D12Device* device = nullptr; + + FfxGpuJobDescription* pGpuJobs; + uint32_t gpuJobCount; + + uint32_t nextRtvDescriptor; + ID3D12DescriptorHeap* descHeapRtvCpu; + + ID3D12DescriptorHeap* descHeapSrvCpu; + ID3D12DescriptorHeap* descHeapUavCpu; + ID3D12DescriptorHeap* descHeapUavGpu; + + uint32_t descRingBufferSize; + uint32_t descRingBufferBase; + ID3D12DescriptorHeap* descRingBuffer; + + void* constantBufferMem; + ID3D12Resource* constantBufferResource; + uint32_t constantBufferSize; + uint32_t constantBufferOffset; + std::mutex constantBufferMutex; + + D3D12_RESOURCE_BARRIER barriers[FFX_MAX_BARRIERS]; + uint32_t barrierCount; + + typedef struct alignas(32) EffectContext + { + // Resource allocation + uint32_t nextStaticResource; + uint32_t nextDynamicResource; + + // UAV offsets + uint32_t nextStaticUavDescriptor; + uint32_t nextDynamicUavDescriptor; + + // Usage + bool active; + + } EffectContext; + + // Resource holder + Resource* pResources; + EffectContext* pEffectContexts; + + } BackendContext_DX12; + // !!!!!!! + // End: BAD HACK: needs to match BackendContext_DX12 in ffx_dx12.cpp + + // + DXGI_FORMAT ffxGetDX12FormatFromSurfaceFormat(FfxSurfaceFormat surfaceFormat) + { + switch (surfaceFormat) + { + case (FFX_SURFACE_FORMAT_R32G32B32A32_TYPELESS): + return DXGI_FORMAT_R32G32B32A32_TYPELESS; + case (FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT): + return DXGI_FORMAT_R32G32B32A32_FLOAT; + case (FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT): + return DXGI_FORMAT_R16G16B16A16_FLOAT; + case (FFX_SURFACE_FORMAT_R32G32_FLOAT): + return DXGI_FORMAT_R32G32_FLOAT; + case (FFX_SURFACE_FORMAT_R32_UINT): + return DXGI_FORMAT_R32_UINT; + case (FFX_SURFACE_FORMAT_R8G8B8A8_TYPELESS): + return DXGI_FORMAT_R8G8B8A8_TYPELESS; + case (FFX_SURFACE_FORMAT_R8G8B8A8_UNORM): + return DXGI_FORMAT_R8G8B8A8_UNORM; + case (FFX_SURFACE_FORMAT_R8G8B8A8_SNORM): + return DXGI_FORMAT_R8G8B8A8_SNORM; + case (FFX_SURFACE_FORMAT_R11G11B10_FLOAT): + return DXGI_FORMAT_R11G11B10_FLOAT; + case (FFX_SURFACE_FORMAT_R16G16_FLOAT): + return DXGI_FORMAT_R16G16_FLOAT; + case (FFX_SURFACE_FORMAT_R16G16_UINT): + return DXGI_FORMAT_R16G16_UINT; + case (FFX_SURFACE_FORMAT_R16G16_SINT): + return DXGI_FORMAT_R16G16_SINT; + case (FFX_SURFACE_FORMAT_R16_FLOAT): + return DXGI_FORMAT_R16_FLOAT; + case (FFX_SURFACE_FORMAT_R16_UINT): + return DXGI_FORMAT_R16_UINT; + case (FFX_SURFACE_FORMAT_R16_UNORM): + return DXGI_FORMAT_R16_UNORM; + case (FFX_SURFACE_FORMAT_R16_SNORM): + return DXGI_FORMAT_R16_SNORM; + case (FFX_SURFACE_FORMAT_R8_UNORM): + return DXGI_FORMAT_R8_UNORM; + case (FFX_SURFACE_FORMAT_R8_UINT): + return DXGI_FORMAT_R8_UINT; + case (FFX_SURFACE_FORMAT_R8G8_UNORM): + return DXGI_FORMAT_R8G8_UNORM; + case (FFX_SURFACE_FORMAT_R32_FLOAT): + return DXGI_FORMAT_R32_FLOAT; + case (FFX_SURFACE_FORMAT_UNKNOWN): + return DXGI_FORMAT_UNKNOWN; + + default: + FFX_ASSERT_MESSAGE(false, "Format not yet supported"); + return DXGI_FORMAT_UNKNOWN; + } + } + + FfxErrorCode ffxGetPermutationBlobByIndexFromSource(FfxEffect effectId, FfxPass passId, FfxBindStage stageId, uint32_t permutationOptions, FfxShaderBlob* outBlob) + { + // CompileShader FromSource + std::vector shaderPath = getShaderPathFromEffectPassID(effectId, passId); + getShaderDefinesFromEffectPassID(effectId, passId, permutationOptions); + + ShaderCompilationResult compileResult; + if (stageId == FFX_BIND_COMPUTE_SHADER_STAGE) + { + compileResult = compileShader(shaderPath.back(), L"CS", s_shaderDefines, additionalIncludeDirs, L"cs_6_6"); + } + else if (stageId == FFX_BIND_VERTEX_SHADER_STAGE) + { + compileResult = compileShader(shaderPath[0], L"mainVS", s_shaderDefines, additionalIncludeDirs, L"vs_6_6"); + } + else if (stageId == FFX_BIND_PIXEL_SHADER_STAGE) + { + compileResult = compileShader(shaderPath[1], L"mainPS", s_shaderDefines, additionalIncludeDirs, L"ps_6_6"); + } + + // Copy Reflection Data to blob + char** CBNames = nullptr; + uint32_t* CBBindings = nullptr; + uint32_t* CBCounts = nullptr; + { + // TODO: deallocate this memory after use + CBNames = new char*[compileResult.boundRegistersCBs.size()]; + CBBindings = new uint32_t[compileResult.boundRegistersCBs.size()]; + CBCounts = new uint32_t[compileResult.boundRegistersCBs.size()]; + + for (int i = 0; i < compileResult.boundRegistersCBs.size(); ++i) + { + // TODO: probably replace this with strdup(), below as well + size_t strlen = compileResult.boundRegistersCBNames[i].length() + 1; + CBNames[i] = new char[strlen]; + strncpy_s(CBNames[i], strlen, compileResult.boundRegistersCBNames[i].c_str(), strlen); + + CBBindings[i] = compileResult.boundRegistersCBs[i]; + CBCounts[i] = 1; + } + } + + char** SrvTexNames = nullptr; + uint32_t* SrvTexBindings = nullptr; + uint32_t* SrvTexCounts = nullptr; + { + SrvTexNames = new char*[compileResult.boundRegistersSRVs.size()]; + SrvTexBindings = new uint32_t[compileResult.boundRegistersSRVs.size()]; + SrvTexCounts = new uint32_t[compileResult.boundRegistersSRVs.size()]; + + for (int i = 0; i < compileResult.boundRegistersSRVs.size(); ++i) + { + size_t strlen = compileResult.boundRegistersSRVNames[i].length() + 1; + SrvTexNames[i] = new char[strlen]; + strncpy_s(SrvTexNames[i], strlen, compileResult.boundRegistersSRVNames[i].c_str(), strlen); + + SrvTexBindings[i] = compileResult.boundRegistersSRVs[i]; + SrvTexCounts[i] = 1; + } + } + + char** UavTexNames = nullptr; + uint32_t* UavTexBindings = nullptr; + uint32_t* UavTexCounts = nullptr; + { + UavTexNames = new char*[compileResult.boundRegistersUAVs.size()]; + UavTexBindings = new uint32_t[compileResult.boundRegistersUAVs.size()]; + UavTexCounts = new uint32_t[compileResult.boundRegistersUAVs.size()]; + + for (int i = 0; i < compileResult.boundRegistersUAVs.size(); ++i) + { + size_t strlen = compileResult.boundRegistersUAVNames[i].length() + 1; + UavTexNames[i] = new char[strlen]; + strncpy_s(UavTexNames[i], strlen, compileResult.boundRegistersUAVNames[i].c_str(), strlen); + + UavTexBindings[i] = compileResult.boundRegistersUAVs[i]; + UavTexCounts[i] = compileResult.boundRegistersUAVsCount[i] ; + } + } + + char** SrvBufferNames = nullptr; + uint32_t* SrvBufferBindings = nullptr; + uint32_t* SrvBufferCounts = nullptr; + { + SrvBufferNames = new char*[compileResult.boundRegistersSRVBuffers.size()]; + SrvBufferBindings = new uint32_t[compileResult.boundRegistersSRVBuffers.size()]; + SrvBufferCounts = new uint32_t[compileResult.boundRegistersSRVBuffers.size()]; + + for (int i = 0; i < compileResult.boundRegistersSRVBuffers.size(); ++i) + { + size_t strlen = compileResult.boundRegistersSRVBuffersNames[i].length() + 1; + SrvBufferNames[i] = new char[strlen]; + strncpy_s(SrvBufferNames[i], strlen, compileResult.boundRegistersSRVBuffersNames[i].c_str(), strlen); + + SrvBufferBindings[i] = compileResult.boundRegistersSRVBuffers[i]; + SrvBufferCounts[i] = 1; + } + } + + char** UavBufferNames = nullptr; + uint32_t* UavBufferBindings = nullptr; + uint32_t* UavBufferCounts = nullptr; + { + UavBufferNames = new char*[compileResult.boundRegistersUAVBuffers.size()]; + UavBufferBindings = new uint32_t[compileResult.boundRegistersUAVBuffers.size()]; + UavBufferCounts = new uint32_t[compileResult.boundRegistersUAVBuffers.size()]; + + for (int i = 0; i < compileResult.boundRegistersUAVBuffers.size(); ++i) + { + size_t strlen = compileResult.boundRegistersUAVBuffersNames[i].length() + 1; + UavBufferNames[i] = new char[strlen]; + strncpy_s(UavBufferNames[i], strlen, compileResult.boundRegistersUAVBuffersNames[i].c_str(), strlen); + + UavBufferBindings[i] = compileResult.boundRegistersUAVBuffers[i]; + UavBufferCounts[i] = 1; + } + } + + char** SamplerNames = nullptr; + uint32_t* SamplerBindings = nullptr; + uint32_t* SamplerCounts = nullptr; + { + SamplerNames = new char*[compileResult.boundSamplers.size()]; + SamplerBindings = new uint32_t[compileResult.boundSamplers.size()]; + SamplerCounts = new uint32_t[compileResult.boundSamplers.size()]; + + for (int i = 0; i < compileResult.boundSamplers.size(); ++i) + { + size_t strlen = compileResult.boundSamplersNames[i].length() + 1; + SamplerNames[i] = new char[strlen]; + strncpy_s(SamplerNames[i], strlen, compileResult.boundSamplersNames[i].c_str(), strlen); + + SamplerBindings[i] = compileResult.boundSamplers[i]; + SamplerCounts[i] = 1; + } + } + + char** RTASNames = nullptr; + uint32_t* RTASBindings = nullptr; + uint32_t* RTASCounts = nullptr; + { + RTASNames = new char*[compileResult.boundRegistersRTASs.size()]; + RTASBindings = new uint32_t[compileResult.boundRegistersRTASs.size()]; + RTASCounts = new uint32_t[compileResult.boundRegistersRTASs.size()]; + + for (int i = 0; i < compileResult.boundRegistersRTASs.size(); ++i) + { + size_t strlen = compileResult.boundRegistersRTASsNames[i].length() + 1; + RTASNames[i] = new char[strlen]; + strncpy_s(RTASNames[i], strlen, compileResult.boundRegistersRTASsNames[i].c_str(), strlen); + + RTASBindings[i] = compileResult.boundRegistersRTASs[i]; + RTASCounts[i] = 1; + } + } + + FfxShaderBlob blob = { + compileResult.shaderBlob != nullptr ? (uint8_t*) compileResult.shaderBlob->GetBufferPointer() : nullptr, + compileResult.shaderBlob != nullptr ? (uint32_t) compileResult.shaderBlob->GetBufferSize() : 0, + + (uint32_t)compileResult.boundRegistersCBs.size(), + (uint32_t)compileResult.boundRegistersSRVs.size(), + (uint32_t)compileResult.boundRegistersUAVs.size(), + (uint32_t)compileResult.boundRegistersSRVBuffers.size(), + (uint32_t)compileResult.boundRegistersUAVBuffers.size(), + (uint32_t)compileResult.boundSamplers.size(), + (uint32_t)compileResult.boundRegistersRTASs.size(), + + const_cast(CBNames), CBBindings, CBCounts, + const_cast(SrvTexNames), SrvTexBindings, SrvTexCounts, + const_cast(UavTexNames), UavTexBindings, UavTexCounts, + const_cast(SrvBufferNames), SrvBufferBindings, SrvBufferCounts, + const_cast(UavBufferNames), UavBufferBindings, UavBufferCounts, + const_cast(SamplerNames), SamplerBindings, SamplerCounts, + const_cast(RTASNames), RTASBindings, RTASCounts + }; + + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + + return compileResult.shaderBlob == nullptr ? FFX_ERROR_BACKEND_API_ERROR : FFX_OK; + } + + FfxErrorCode CreatePipelineFromSourceInternal( FfxInterface* backendInterface, + FfxEffect effect, + FfxPass pass, + uint32_t permutationOptions, + const FfxPipelineDescription* pipelineDescription, + FfxUInt32 effectContextId, + FfxPipelineState* outPipeline) + { + FFX_ASSERT(NULL != backendInterface); + FFX_ASSERT(NULL != pipelineDescription); + + BackendContext_DX12* backendContext = (BackendContext_DX12*)backendInterface->scratchBuffer; + ID3D12Device* dx12Device = backendContext->device; + + if (pipelineDescription->stage == FfxBindStage(FFX_BIND_VERTEX_SHADER_STAGE | FFX_BIND_PIXEL_SHADER_STAGE)) + { + // create rasterPipeline + // ToDo: use compileShaderFromFile instead + FfxShaderBlob shaderBlobVS = {}; + ffxGetPermutationBlobByIndexFromSource(effect, pass, FFX_BIND_VERTEX_SHADER_STAGE, permutationOptions, &shaderBlobVS); + FFX_ASSERT(shaderBlobVS.data && shaderBlobVS.size); + + FfxShaderBlob shaderBlobPS = {}; + ffxGetPermutationBlobByIndexFromSource(effect, pass, FFX_BIND_PIXEL_SHADER_STAGE, permutationOptions, &shaderBlobPS); + FFX_ASSERT(shaderBlobPS.data && shaderBlobPS.size); + + { + // set up root signature + // easiest implementation: simply create one root signature per pipeline + // should add some management later on to avoid unnecessarily re-binding the root signature + { + FFX_ASSERT(pipelineDescription->samplerCount <= FFX_MAX_SAMPLERS); + const size_t samplerCount = pipelineDescription->samplerCount; + D3D12_STATIC_SAMPLER_DESC dx12SamplerDescriptions[FFX_MAX_SAMPLERS]; + for (uint32_t currentSamplerIndex = 0; currentSamplerIndex < samplerCount; ++currentSamplerIndex) + { + D3D12_STATIC_SAMPLER_DESC dx12SamplerDesc = {}; + + dx12SamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + dx12SamplerDesc.MinLOD = 0.f; + dx12SamplerDesc.MaxLOD = D3D12_FLOAT32_MAX; + dx12SamplerDesc.MipLODBias = 0.f; + dx12SamplerDesc.MaxAnisotropy = 16; + dx12SamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + dx12SamplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + dx12SamplerDesc.AddressU = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeU); + dx12SamplerDesc.AddressV = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeV); + dx12SamplerDesc.AddressW = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeW); + + switch (pipelineDescription->samplers[currentSamplerIndex].filter) + { + case FFX_FILTER_TYPE_MINMAGMIP_POINT: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + break; + case FFX_FILTER_TYPE_MINMAGMIP_LINEAR: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + break; + case FFX_FILTER_TYPE_MINMAGLINEARMIP_POINT: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; + break; + + default: + FFX_ASSERT_MESSAGE(false, "Unsupported filter type requested. Please implement"); + break; + } + + dx12SamplerDescriptions[currentSamplerIndex] = dx12SamplerDesc; + dx12SamplerDescriptions[currentSamplerIndex].ShaderRegister = (UINT)currentSamplerIndex; + } + + // storage for maximum number of descriptor ranges. + const int32_t maximumDescriptorRangeSize = 2; + D3D12_DESCRIPTOR_RANGE dx12Ranges[maximumDescriptorRangeSize] = {}; + int32_t currentDescriptorRangeIndex = 0; + + // storage for maximum number of root parameters. + const int32_t maximumRootParameters = 10; + D3D12_ROOT_PARAMETER dx12RootParameters[maximumRootParameters] = {}; + int32_t currentRootParameterIndex = 0; + + // Allocate a max of binding slots + int32_t uavCount = + shaderBlobVS.uavBufferCount || shaderBlobVS.uavTextureCount || shaderBlobVS.uavBufferCount || shaderBlobVS.uavTextureCount + ? FFX_MAX_RESOURCE_IDENTIFIER_COUNT + : 0; + int32_t srvCount = + shaderBlobVS.srvBufferCount || shaderBlobVS.srvTextureCount || shaderBlobPS.srvBufferCount || shaderBlobPS.srvTextureCount + ? FFX_MAX_RESOURCE_IDENTIFIER_COUNT + : 0; + if (uavCount > 0) + { + FFX_ASSERT(currentDescriptorRangeIndex < maximumDescriptorRangeSize); + D3D12_DESCRIPTOR_RANGE* dx12DescriptorRange = &dx12Ranges[currentDescriptorRangeIndex]; + memset(dx12DescriptorRange, 0, sizeof(D3D12_DESCRIPTOR_RANGE)); + dx12DescriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + dx12DescriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + dx12DescriptorRange->BaseShaderRegister = 0; + dx12DescriptorRange->NumDescriptors = uavCount; + currentDescriptorRangeIndex++; + + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* dx12RootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(dx12RootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + dx12RootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + dx12RootParameterSlot->DescriptorTable.NumDescriptorRanges = 1; + currentRootParameterIndex++; + } + + if (srvCount > 0) + { + FFX_ASSERT(currentDescriptorRangeIndex < maximumDescriptorRangeSize); + D3D12_DESCRIPTOR_RANGE* dx12DescriptorRange = &dx12Ranges[currentDescriptorRangeIndex]; + memset(dx12DescriptorRange, 0, sizeof(D3D12_DESCRIPTOR_RANGE)); + dx12DescriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + dx12DescriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + dx12DescriptorRange->BaseShaderRegister = 0; + dx12DescriptorRange->NumDescriptors = srvCount; + currentDescriptorRangeIndex++; + + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* dx12RootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(dx12RootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + dx12RootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + dx12RootParameterSlot->DescriptorTable.NumDescriptorRanges = 1; + currentRootParameterIndex++; + } + + // Setup the descriptor table bindings for the above + for (int32_t currentRangeIndex = 0; currentRangeIndex < currentDescriptorRangeIndex; currentRangeIndex++) + { + dx12RootParameters[currentRangeIndex].DescriptorTable.pDescriptorRanges = &dx12Ranges[currentRangeIndex]; + } + + // Setup root constants as push constants for dx12 + FFX_ASSERT(pipelineDescription->rootConstantBufferCount <= FFX_MAX_NUM_CONST_BUFFERS); + size_t rootConstantsSize = pipelineDescription->rootConstantBufferCount; + uint32_t rootConstants[FFX_MAX_NUM_CONST_BUFFERS]; + + for (uint32_t currentRootConstantIndex = 0; currentRootConstantIndex < pipelineDescription->rootConstantBufferCount; + ++currentRootConstantIndex) + { + rootConstants[currentRootConstantIndex] = pipelineDescription->rootConstants[currentRootConstantIndex].size; + } + + for (int32_t currentRootConstantIndex = 0; currentRootConstantIndex < (int32_t)pipelineDescription->rootConstantBufferCount; + currentRootConstantIndex++) + { + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* rootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(rootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + rootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParameterSlot->Constants.ShaderRegister = currentRootConstantIndex; + currentRootParameterIndex++; + } + + D3D12_ROOT_SIGNATURE_DESC dx12RootSignatureDescription = {}; + dx12RootSignatureDescription.NumParameters = currentRootParameterIndex; + dx12RootSignatureDescription.pParameters = dx12RootParameters; + dx12RootSignatureDescription.NumStaticSamplers = (UINT)samplerCount; + dx12RootSignatureDescription.pStaticSamplers = dx12SamplerDescriptions; + + ID3DBlob* outBlob = nullptr; + ID3DBlob* errorBlob = nullptr; + + //Query D3D12SerializeRootSignature from d3d12.dll handle + typedef HRESULT(__stdcall * D3D12SerializeRootSignatureType)( + const D3D12_ROOT_SIGNATURE_DESC*, D3D_ROOT_SIGNATURE_VERSION, ID3DBlob**, ID3DBlob**); + + //Do not pass hD3D12 handle to the FreeLibrary function, as GetModuleHandle will not increment refcount + HMODULE d3d12ModuleHandle = GetModuleHandleW(L"D3D12.dll"); + + if (NULL != d3d12ModuleHandle) + { + D3D12SerializeRootSignatureType dx12SerializeRootSignatureType = + (D3D12SerializeRootSignatureType)GetProcAddress(d3d12ModuleHandle, "D3D12SerializeRootSignature"); + + if (nullptr != dx12SerializeRootSignatureType) + { + HRESULT result = dx12SerializeRootSignatureType(&dx12RootSignatureDescription, D3D_ROOT_SIGNATURE_VERSION_1, &outBlob, &errorBlob); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + + size_t blobSize = outBlob->GetBufferSize(); + int64_t* blobData = (int64_t*)outBlob->GetBufferPointer(); + + result = dx12Device->CreateRootSignature(0, + outBlob->GetBufferPointer(), + outBlob->GetBufferSize(), + IID_PPV_ARGS(reinterpret_cast(&outPipeline->rootSignature))); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + + ID3D12RootSignature* dx12RootSignature = reinterpret_cast(outPipeline->rootSignature); + + // Only set the command signature if this is setup as an indirect workload + if (pipelineDescription->indirectWorkload) + { + D3D12_INDIRECT_ARGUMENT_DESC argumentDescs = {D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH}; + D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc = {}; + commandSignatureDesc.pArgumentDescs = &argumentDescs; + commandSignatureDesc.NumArgumentDescs = 1; + commandSignatureDesc.ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS); + + HRESULT result = dx12Device->CreateCommandSignature( + &commandSignatureDesc, nullptr, IID_PPV_ARGS(reinterpret_cast(&outPipeline->cmdSignature))); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + outPipeline->cmdSignature = nullptr; + } + + FFX_ASSERT(shaderBlobVS.srvTextureCount + shaderBlobVS.srvBufferCount + shaderBlobPS.srvTextureCount + shaderBlobPS.srvBufferCount <= + FFX_MAX_NUM_SRVS); + FFX_ASSERT(shaderBlobVS.uavTextureCount + shaderBlobVS.uavBufferCount + shaderBlobPS.uavTextureCount + shaderBlobPS.uavBufferCount <= + FFX_MAX_NUM_UAVS); + FFX_ASSERT(shaderBlobVS.cbvCount + shaderBlobPS.cbvCount <= FFX_MAX_NUM_CONST_BUFFERS); + + // populate the pass. + outPipeline->srvTextureCount = shaderBlobVS.srvTextureCount + shaderBlobPS.srvTextureCount; + outPipeline->uavTextureCount = shaderBlobVS.uavTextureCount + shaderBlobPS.uavTextureCount; + outPipeline->srvBufferCount = shaderBlobVS.srvBufferCount + shaderBlobPS.srvBufferCount; + outPipeline->uavBufferCount = shaderBlobVS.uavBufferCount + shaderBlobPS.uavBufferCount; + outPipeline->constCount = shaderBlobVS.cbvCount + shaderBlobPS.cbvCount; + + // Todo when needed + //outPipeline->samplerCount = shaderBlob.samplerCount; + //outPipeline->rtAccelStructCount= shaderBlob.rtAccelStructCount; + + std::wstring_convert> converter; + uint32_t srvIndex = 0; + for (uint32_t vsSrvIndex = 0; vsSrvIndex < shaderBlobVS.srvTextureCount; ++vsSrvIndex) + { + outPipeline->srvTextureBindings[srvIndex].slotIndex = shaderBlobVS.boundSRVTextures[vsSrvIndex]; + outPipeline->srvTextureBindings[srvIndex].bindCount = shaderBlobVS.boundSRVTextureCounts[vsSrvIndex]; + wcscpy_s(outPipeline->srvTextureBindings[srvIndex].name, converter.from_bytes(shaderBlobVS.boundSRVTextureNames[vsSrvIndex]).c_str()); + ++srvIndex; + } + for (uint32_t psSrvIndex = 0; psSrvIndex < shaderBlobPS.srvTextureCount; ++psSrvIndex) + { + outPipeline->srvTextureBindings[srvIndex].slotIndex = shaderBlobPS.boundSRVTextures[psSrvIndex]; + outPipeline->srvTextureBindings[srvIndex].bindCount = shaderBlobPS.boundSRVTextureCounts[psSrvIndex]; + wcscpy_s(outPipeline->srvTextureBindings[srvIndex].name, converter.from_bytes(shaderBlobPS.boundSRVTextureNames[psSrvIndex]).c_str()); + ++srvIndex; + } + + uint32_t uavIndex = 0; + for (uint32_t vsUavIndex = 0; vsUavIndex < shaderBlobVS.uavTextureCount; ++vsUavIndex) + { + outPipeline->uavTextureBindings[uavIndex].slotIndex = shaderBlobVS.boundUAVTextures[vsUavIndex]; + outPipeline->uavTextureBindings[uavIndex].bindCount = shaderBlobVS.boundUAVTextureCounts[vsUavIndex]; + wcscpy_s(outPipeline->uavTextureBindings[uavIndex].name, converter.from_bytes(shaderBlobVS.boundUAVTextureNames[vsUavIndex]).c_str()); + ++uavIndex; + } + for (uint32_t psUavIndex = 0; psUavIndex < shaderBlobPS.uavTextureCount; ++psUavIndex) + { + outPipeline->uavTextureBindings[uavIndex].slotIndex = shaderBlobPS.boundUAVTextures[psUavIndex]; + outPipeline->uavTextureBindings[uavIndex].bindCount = shaderBlobPS.boundUAVTextureCounts[psUavIndex]; + wcscpy_s(outPipeline->uavTextureBindings[uavIndex].name, converter.from_bytes(shaderBlobPS.boundUAVTextureNames[psUavIndex]).c_str()); + ++uavIndex; + } + + uint32_t srvBufferIndex = 0; + for (uint32_t vsSrvIndex = 0; vsSrvIndex < shaderBlobVS.srvBufferCount; ++vsSrvIndex) + { + outPipeline->srvBufferBindings[srvBufferIndex].slotIndex = shaderBlobVS.boundSRVBuffers[vsSrvIndex]; + outPipeline->srvBufferBindings[srvBufferIndex].bindCount = shaderBlobVS.boundSRVBufferCounts[vsSrvIndex]; + wcscpy_s(outPipeline->srvBufferBindings[srvBufferIndex].name, converter.from_bytes(shaderBlobVS.boundSRVBufferNames[vsSrvIndex]).c_str()); + ++srvBufferIndex; + } + for (uint32_t psSrvIndex = 0; psSrvIndex < shaderBlobPS.srvBufferCount; ++psSrvIndex) + { + outPipeline->srvBufferBindings[srvBufferIndex].slotIndex = shaderBlobPS.boundSRVBuffers[psSrvIndex]; + outPipeline->srvBufferBindings[srvBufferIndex].bindCount = shaderBlobPS.boundSRVBufferCounts[psSrvIndex]; + wcscpy_s(outPipeline->srvBufferBindings[srvBufferIndex].name, converter.from_bytes(shaderBlobPS.boundSRVBufferNames[psSrvIndex]).c_str()); + ++srvBufferIndex; + } + + uint32_t uavBufferIndex = 0; + for (uint32_t vsUavIndex = 0; vsUavIndex < shaderBlobVS.uavBufferCount; ++vsUavIndex) + { + outPipeline->uavBufferBindings[uavBufferIndex].slotIndex = shaderBlobVS.boundUAVBuffers[vsUavIndex]; + outPipeline->uavBufferBindings[uavBufferIndex].bindCount = shaderBlobVS.boundUAVBufferCounts[vsUavIndex]; + wcscpy_s(outPipeline->uavBufferBindings[uavBufferIndex].name, converter.from_bytes(shaderBlobVS.boundUAVBufferNames[vsUavIndex]).c_str()); + ++uavBufferIndex; + } + for (uint32_t psUavIndex = 0; psUavIndex < shaderBlobPS.uavBufferCount; ++psUavIndex) + { + outPipeline->uavBufferBindings[uavBufferIndex].slotIndex = shaderBlobPS.boundUAVBuffers[psUavIndex]; + outPipeline->uavBufferBindings[uavBufferIndex].bindCount = shaderBlobPS.boundUAVBufferCounts[psUavIndex]; + wcscpy_s(outPipeline->uavBufferBindings[uavBufferIndex].name, converter.from_bytes(shaderBlobPS.boundUAVBufferNames[psUavIndex]).c_str()); + ++uavBufferIndex; + } + + uint32_t cbIndex = 0; + for (uint32_t vsCbIndex = 0; vsCbIndex < shaderBlobVS.cbvCount; ++vsCbIndex) + { + outPipeline->constantBufferBindings[cbIndex].slotIndex = shaderBlobVS.boundConstantBuffers[vsCbIndex]; + outPipeline->constantBufferBindings[cbIndex].bindCount = shaderBlobVS.boundConstantBufferCounts[vsCbIndex]; + wcscpy_s(outPipeline->constantBufferBindings[cbIndex].name, converter.from_bytes(shaderBlobVS.boundConstantBufferNames[vsCbIndex]).c_str()); + ++cbIndex; + } + for (uint32_t psCbIndex = 0; psCbIndex < shaderBlobPS.cbvCount; ++psCbIndex) + { + outPipeline->constantBufferBindings[cbIndex].slotIndex = shaderBlobPS.boundConstantBuffers[psCbIndex]; + outPipeline->constantBufferBindings[cbIndex].bindCount = shaderBlobPS.boundConstantBufferCounts[psCbIndex]; + wcscpy_s(outPipeline->constantBufferBindings[cbIndex].name, converter.from_bytes(shaderBlobPS.boundConstantBufferNames[psCbIndex]).c_str()); + ++cbIndex; + } + } + + ID3D12RootSignature* dx12RootSignature = reinterpret_cast(outPipeline->rootSignature); + + FfxSurfaceFormat ffxBackbufferFmt = pipelineDescription->backbufferFormat; + + // create the PSO + D3D12_GRAPHICS_PIPELINE_STATE_DESC dx12PipelineStateDescription = {}; + dx12PipelineStateDescription.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + dx12PipelineStateDescription.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + dx12PipelineStateDescription.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + dx12PipelineStateDescription.DepthStencilState.DepthEnable = FALSE; + dx12PipelineStateDescription.SampleMask = UINT_MAX; + dx12PipelineStateDescription.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + dx12PipelineStateDescription.SampleDesc = {1, 0}; + dx12PipelineStateDescription.NumRenderTargets = 1; + dx12PipelineStateDescription.RTVFormats[0] = ffxGetDX12FormatFromSurfaceFormat(ffxBackbufferFmt); + + dx12PipelineStateDescription.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + dx12PipelineStateDescription.pRootSignature = dx12RootSignature; + dx12PipelineStateDescription.VS.pShaderBytecode = shaderBlobVS.data; + dx12PipelineStateDescription.VS.BytecodeLength = shaderBlobVS.size; + dx12PipelineStateDescription.PS.pShaderBytecode = shaderBlobPS.data; + dx12PipelineStateDescription.PS.BytecodeLength = shaderBlobPS.size; + + if (FAILED(dx12Device->CreateGraphicsPipelineState(&dx12PipelineStateDescription, + IID_PPV_ARGS(reinterpret_cast(&outPipeline->pipeline))))) + return FFX_ERROR_BACKEND_API_ERROR; + } + else + { + FfxShaderBlob shaderBlob = {}; + ffxGetPermutationBlobByIndexFromSource(effect, pass, FFX_BIND_COMPUTE_SHADER_STAGE, permutationOptions, &shaderBlob); + FFX_ASSERT(shaderBlob.data && shaderBlob.size); + + // set up root signature + // easiest implementation: simply create one root signature per pipeline + // should add some management later on to avoid unnecessarily re-binding the root signature + { + FFX_ASSERT(pipelineDescription->samplerCount <= FFX_MAX_SAMPLERS); + const size_t samplerCount = pipelineDescription->samplerCount; + D3D12_STATIC_SAMPLER_DESC dx12SamplerDescriptions[FFX_MAX_SAMPLERS]; + for (uint32_t currentSamplerIndex = 0; currentSamplerIndex < samplerCount; ++currentSamplerIndex) + { + D3D12_STATIC_SAMPLER_DESC dx12SamplerDesc = {}; + + dx12SamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + dx12SamplerDesc.MinLOD = 0.f; + dx12SamplerDesc.MaxLOD = D3D12_FLOAT32_MAX; + dx12SamplerDesc.MipLODBias = 0.f; + dx12SamplerDesc.MaxAnisotropy = 16; + dx12SamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + dx12SamplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + dx12SamplerDesc.AddressU = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeU); + dx12SamplerDesc.AddressV = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeV); + dx12SamplerDesc.AddressW = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeW); + + switch (pipelineDescription->samplers[currentSamplerIndex].filter) + { + case FFX_FILTER_TYPE_MINMAGMIP_POINT: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + break; + case FFX_FILTER_TYPE_MINMAGMIP_LINEAR: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + break; + case FFX_FILTER_TYPE_MINMAGLINEARMIP_POINT: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; + break; + + default: + FFX_ASSERT_MESSAGE(false, "Unsupported filter type requested. Please implement"); + break; + } + + dx12SamplerDescriptions[currentSamplerIndex] = dx12SamplerDesc; + dx12SamplerDescriptions[currentSamplerIndex].ShaderRegister = (UINT)currentSamplerIndex; + } + + // storage for maximum number of descriptor ranges. + const int32_t maximumDescriptorRangeSize = 2; + D3D12_DESCRIPTOR_RANGE dx12Ranges[maximumDescriptorRangeSize] = {}; + int32_t currentDescriptorRangeIndex = 0; + + // storage for maximum number of root parameters. + const int32_t maximumRootParameters = 10; + D3D12_ROOT_PARAMETER dx12RootParameters[maximumRootParameters] = {}; + int32_t currentRootParameterIndex = 0; + + // Allocate a max of binding slots + int32_t uavCount = shaderBlob.uavBufferCount || shaderBlob.uavTextureCount ? FFX_MAX_RESOURCE_IDENTIFIER_COUNT : 0; + int32_t srvCount = shaderBlob.srvBufferCount || shaderBlob.srvTextureCount ? FFX_MAX_RESOURCE_IDENTIFIER_COUNT : 0; + if (uavCount > 0) + { + FFX_ASSERT(currentDescriptorRangeIndex < maximumDescriptorRangeSize); + D3D12_DESCRIPTOR_RANGE* dx12DescriptorRange = &dx12Ranges[currentDescriptorRangeIndex]; + memset(dx12DescriptorRange, 0, sizeof(D3D12_DESCRIPTOR_RANGE)); + dx12DescriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + dx12DescriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + dx12DescriptorRange->BaseShaderRegister = 0; + dx12DescriptorRange->NumDescriptors = uavCount; + currentDescriptorRangeIndex++; + + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* dx12RootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(dx12RootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + dx12RootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + dx12RootParameterSlot->DescriptorTable.NumDescriptorRanges = 1; + currentRootParameterIndex++; + } + + if (srvCount > 0) + { + FFX_ASSERT(currentDescriptorRangeIndex < maximumDescriptorRangeSize); + D3D12_DESCRIPTOR_RANGE* dx12DescriptorRange = &dx12Ranges[currentDescriptorRangeIndex]; + memset(dx12DescriptorRange, 0, sizeof(D3D12_DESCRIPTOR_RANGE)); + dx12DescriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + dx12DescriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + dx12DescriptorRange->BaseShaderRegister = 0; + dx12DescriptorRange->NumDescriptors = srvCount; + currentDescriptorRangeIndex++; + + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* dx12RootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(dx12RootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + dx12RootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + dx12RootParameterSlot->DescriptorTable.NumDescriptorRanges = 1; + currentRootParameterIndex++; + } + + // Setup the descriptor table bindings for the above + for (int32_t currentRangeIndex = 0; currentRangeIndex < currentDescriptorRangeIndex; currentRangeIndex++) + { + dx12RootParameters[currentRangeIndex].DescriptorTable.pDescriptorRanges = &dx12Ranges[currentRangeIndex]; + } + + // Setup root constants as push constants for dx12 + FFX_ASSERT(pipelineDescription->rootConstantBufferCount <= FFX_MAX_NUM_CONST_BUFFERS); + size_t rootConstantsSize = pipelineDescription->rootConstantBufferCount; + uint32_t rootConstants[FFX_MAX_NUM_CONST_BUFFERS]; + + for (uint32_t currentRootConstantIndex = 0; currentRootConstantIndex < pipelineDescription->rootConstantBufferCount; ++currentRootConstantIndex) + { + rootConstants[currentRootConstantIndex] = pipelineDescription->rootConstants[currentRootConstantIndex].size; + } + + for (int32_t currentRootConstantIndex = 0; currentRootConstantIndex < (int32_t)pipelineDescription->rootConstantBufferCount; + currentRootConstantIndex++) + { + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* rootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(rootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + rootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParameterSlot->Constants.ShaderRegister = currentRootConstantIndex; + currentRootParameterIndex++; + } + + D3D12_ROOT_SIGNATURE_DESC dx12RootSignatureDescription = {}; + dx12RootSignatureDescription.NumParameters = currentRootParameterIndex; + dx12RootSignatureDescription.pParameters = dx12RootParameters; + dx12RootSignatureDescription.NumStaticSamplers = (UINT)samplerCount; + dx12RootSignatureDescription.pStaticSamplers = dx12SamplerDescriptions; + + ID3DBlob* outBlob = nullptr; + ID3DBlob* errorBlob = nullptr; + + //Query D3D12SerializeRootSignature from d3d12.dll handle + typedef HRESULT(__stdcall * D3D12SerializeRootSignatureType)( + const D3D12_ROOT_SIGNATURE_DESC*, D3D_ROOT_SIGNATURE_VERSION, ID3DBlob**, ID3DBlob**); + + //Do not pass hD3D12 handle to the FreeLibrary function, as GetModuleHandle will not increment refcount + HMODULE d3d12ModuleHandle = GetModuleHandleW(L"D3D12.dll"); + + if (NULL != d3d12ModuleHandle) + { + D3D12SerializeRootSignatureType dx12SerializeRootSignatureType = + (D3D12SerializeRootSignatureType)GetProcAddress(d3d12ModuleHandle, "D3D12SerializeRootSignature"); + + if (nullptr != dx12SerializeRootSignatureType) + { + HRESULT result = dx12SerializeRootSignatureType(&dx12RootSignatureDescription, D3D_ROOT_SIGNATURE_VERSION_1, &outBlob, &errorBlob); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + + size_t blobSize = outBlob->GetBufferSize(); + int64_t* blobData = (int64_t*)outBlob->GetBufferPointer(); + + result = dx12Device->CreateRootSignature(0, + outBlob->GetBufferPointer(), + outBlob->GetBufferSize(), + IID_PPV_ARGS(reinterpret_cast(&outPipeline->rootSignature))); + + SafeRelease(outBlob); + SafeRelease(errorBlob); + + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + + + ID3D12RootSignature* dx12RootSignature = reinterpret_cast(outPipeline->rootSignature); + + // Only set the command signature if this is setup as an indirect workload + if (pipelineDescription->indirectWorkload) + { + D3D12_INDIRECT_ARGUMENT_DESC argumentDescs = {D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH}; + D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc = {}; + commandSignatureDesc.pArgumentDescs = &argumentDescs; + commandSignatureDesc.NumArgumentDescs = 1; + commandSignatureDesc.ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS); + + HRESULT result = dx12Device->CreateCommandSignature( + &commandSignatureDesc, nullptr, IID_PPV_ARGS(reinterpret_cast(&outPipeline->cmdSignature))); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + outPipeline->cmdSignature = nullptr; + } + + FFX_ASSERT(shaderBlob.srvTextureCount + shaderBlob.srvBufferCount <= FFX_MAX_NUM_SRVS); + FFX_ASSERT(shaderBlob.uavTextureCount + shaderBlob.uavBufferCount <= FFX_MAX_NUM_UAVS); + FFX_ASSERT(shaderBlob.cbvCount <= FFX_MAX_NUM_CONST_BUFFERS); + + // populate the pass. + outPipeline->srvTextureCount = shaderBlob.srvTextureCount; + outPipeline->uavTextureCount = shaderBlob.uavTextureCount; + outPipeline->srvBufferCount = shaderBlob.srvBufferCount; + outPipeline->uavBufferCount = shaderBlob.uavBufferCount; + + // Todo when needed + //outPipeline->samplerCount = shaderBlob.samplerCount; + //outPipeline->rtAccelStructCount= shaderBlob.rtAccelStructCount; + + outPipeline->constCount = shaderBlob.cbvCount; + std::wstring_convert> converter; + for (uint32_t srvIndex = 0; srvIndex < outPipeline->srvTextureCount; ++srvIndex) + { + outPipeline->srvTextureBindings[srvIndex].slotIndex = shaderBlob.boundSRVTextures[srvIndex]; + outPipeline->srvTextureBindings[srvIndex].bindCount = shaderBlob.boundSRVTextureCounts[srvIndex]; + wcscpy_s(outPipeline->srvTextureBindings[srvIndex].name, converter.from_bytes(shaderBlob.boundSRVTextureNames[srvIndex]).c_str()); + } + for (uint32_t uavIndex = 0; uavIndex < outPipeline->uavTextureCount; ++uavIndex) + { + outPipeline->uavTextureBindings[uavIndex].slotIndex = shaderBlob.boundUAVTextures[uavIndex]; + outPipeline->uavTextureBindings[uavIndex].bindCount = shaderBlob.boundUAVTextureCounts[uavIndex]; + wcscpy_s(outPipeline->uavTextureBindings[uavIndex].name, converter.from_bytes(shaderBlob.boundUAVTextureNames[uavIndex]).c_str()); + } + for (uint32_t srvIndex = 0; srvIndex < outPipeline->srvBufferCount; ++srvIndex) + { + outPipeline->srvBufferBindings[srvIndex].slotIndex = shaderBlob.boundSRVBuffers[srvIndex]; + outPipeline->srvBufferBindings[srvIndex].bindCount = shaderBlob.boundSRVBufferCounts[srvIndex]; + wcscpy_s(outPipeline->srvBufferBindings[srvIndex].name, converter.from_bytes(shaderBlob.boundSRVBufferNames[srvIndex]).c_str()); + } + for (uint32_t uavIndex = 0; uavIndex < outPipeline->uavBufferCount; ++uavIndex) + { + outPipeline->uavBufferBindings[uavIndex].slotIndex = shaderBlob.boundUAVBuffers[uavIndex]; + outPipeline->uavBufferBindings[uavIndex].bindCount = shaderBlob.boundUAVBufferCounts[uavIndex]; + wcscpy_s(outPipeline->uavBufferBindings[uavIndex].name, converter.from_bytes(shaderBlob.boundUAVBufferNames[uavIndex]).c_str()); + } + for (uint32_t cbIndex = 0; cbIndex < outPipeline->constCount; ++cbIndex) + { + outPipeline->constantBufferBindings[cbIndex].slotIndex = shaderBlob.boundConstantBuffers[cbIndex]; + outPipeline->constantBufferBindings[cbIndex].bindCount = shaderBlob.boundConstantBufferCounts[cbIndex]; + wcscpy_s(outPipeline->constantBufferBindings[cbIndex].name, converter.from_bytes(shaderBlob.boundConstantBufferNames[cbIndex]).c_str()); + } + + // create the PSO + D3D12_COMPUTE_PIPELINE_STATE_DESC dx12PipelineStateDescription = {}; + dx12PipelineStateDescription.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + dx12PipelineStateDescription.pRootSignature = dx12RootSignature; + dx12PipelineStateDescription.CS.pShaderBytecode = shaderBlob.data; + dx12PipelineStateDescription.CS.BytecodeLength = shaderBlob.size; + + if (FAILED(dx12Device->CreateComputePipelineState(&dx12PipelineStateDescription, + IID_PPV_ARGS(reinterpret_cast(&outPipeline->pipeline))))) + return FFX_ERROR_BACKEND_API_ERROR; + + // Set the pipeline name + reinterpret_cast(outPipeline->pipeline)->SetName(pipelineDescription->name); + } + + return FFX_OK; + } + + FfxCreatePipelineFunc fpFallback = nullptr; + + FfxErrorCode CreatePipelineFromSource(FfxInterface* backendInterface, + FfxEffect effect, + FfxPass pass, + uint32_t permutationOptions, + const FfxPipelineDescription* pipelineDescription, + FfxUInt32 effectContextId, + FfxPipelineState* outPipeline) + { + FfxErrorCode result = FFX_ERROR_BACKEND_API_ERROR; + + static bool bUseHLSL = true; + if (bUseHLSL) + { + result = CreatePipelineFromSourceInternal(backendInterface, effect, pass, permutationOptions, pipelineDescription, effectContextId, outPipeline); + } + // if we run into troubles compiling from source, try fallback to precompiled shader + if (result != FFX_OK) + { + FFX_ASSERT(false && "HLSL compile failed, reverting to pre-built pipeline"); + result = fpFallback(backendInterface, effect, pass, permutationOptions, pipelineDescription, effectContextId, outPipeline); + } + return result; + } + + void SetupFallback(FfxCreatePipelineFunc func) + { + fpFallback = func; + } +} diff --git a/samples/fsr/HLSLCompile/HLSLShaderCompiler.h b/samples/fsr/HLSLCompile/HLSLShaderCompiler.h new file mode 100644 index 00000000..eb47c0f8 --- /dev/null +++ b/samples/fsr/HLSLCompile/HLSLShaderCompiler.h @@ -0,0 +1,99 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "fsr2_DXC_IncludeHandler.h" + +#define WIN32_LEAN_AND_MEAN +#include "windows.h" + +#include + +#include +#include +#include +#include + +namespace HlslShaderCompiler +{ + // Safe release for interfaces + template + inline void SafeRelease(Interface*& pInterfaceToRelease) + { + if (pInterfaceToRelease != nullptr) + { + pInterfaceToRelease->Release(); + + pInterfaceToRelease = nullptr; + } + } + + template + inline void SafeDelete(Interface*& pInterfaceToDelete) + { + if (pInterfaceToDelete != nullptr) + { + delete pInterfaceToDelete; + pInterfaceToDelete = nullptr; + } + } + +#define DXIL_FOURCC(ch0, ch1, ch2, ch3) ( \ + (uint32_t)(uint8_t)(ch0) | (uint32_t)(uint8_t)(ch1) << 8 | \ + (uint32_t)(uint8_t)(ch2) << 16 | (uint32_t)(uint8_t)(ch3) << 24 \ + ) + + enum DxilFourCC { + DFCC_Container = DXIL_FOURCC('D', 'X', 'B', 'C'), // for back-compat with tools that look for DXBC containers + DFCC_ResourceDef = DXIL_FOURCC('R', 'D', 'E', 'F'), + DFCC_InputSignature = DXIL_FOURCC('I', 'S', 'G', '1'), + DFCC_OutputSignature = DXIL_FOURCC('O', 'S', 'G', '1'), + DFCC_PatchConstantSignature = DXIL_FOURCC('P', 'S', 'G', '1'), + DFCC_ShaderStatistics = DXIL_FOURCC('S', 'T', 'A', 'T'), + DFCC_ShaderDebugInfoDXIL = DXIL_FOURCC('I', 'L', 'D', 'B'), + DFCC_ShaderDebugName = DXIL_FOURCC('I', 'L', 'D', 'N'), + DFCC_FeatureInfo = DXIL_FOURCC('S', 'F', 'I', '0'), + DFCC_PrivateData = DXIL_FOURCC('P', 'R', 'I', 'V'), + DFCC_RootSignature = DXIL_FOURCC('R', 'T', 'S', '0'), + DFCC_DXIL = DXIL_FOURCC('D', 'X', 'I', 'L'), + DFCC_PipelineStateValidation = DXIL_FOURCC('P', 'S', 'V', '0'), + }; + + struct ShaderCompilationDesc + { + LPCWSTR EntryPoint; + LPCWSTR TargetProfile; + std::vector CompileArguments; + std::vector Defines; + }; + + FfxErrorCode CreatePipelineFromSource(FfxInterface* backendInterface, + FfxEffect effect, + FfxPass pass, + uint32_t permutationOptions, + const FfxPipelineDescription* pipelineDescription, + FfxUInt32 effectContextId, + FfxPipelineState* outPipeline); + + void SetupFallback(FfxCreatePipelineFunc func); + +} diff --git a/samples/fsr/HLSLCompile/shadercompiler.cpp b/samples/fsr/HLSLCompile/shadercompiler.cpp new file mode 100644 index 00000000..6c55c592 --- /dev/null +++ b/samples/fsr/HLSLCompile/shadercompiler.cpp @@ -0,0 +1,238 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "ShaderCompiler.h" +#include + +namespace FidelityFx +{ + void AddDefaultCompileArguments(std::vector& compileArguments) + { + // https://simoncoenen.com/blog/programming/graphics/DxcCompiling.html + //desc.compileArguments.push_back(L"-Gis"); // Force IEEE strictness + compileArguments.push_back(L"-Wno-for-redefinition"); // Disable "for redefinition" warning + + // Workaround: We want to keep an eye on warn_hlsl_implicit_vector_truncation, but it share the same toggle as the warn_hlsl_sema_minprecision_promotion and others. + // For debug build, enabling -Wconversion but disabling "-enable-16bit-types" as it causes flooding minprecision_promotion warnings. + //#ifndef _DEBUG + compileArguments.push_back(L"-enable-16bit-types"); // Enable 16bit types and disable min precision types. Available in HLSL 2018 and shader model 6.2 + //#endif + + //shaderDesc.CompileArguments.push_back(L"-I../SDK"); + +#if defined(_DEBUG) || defined(FFX_DEBUG_SHADERS) + compileArguments.push_back(L"-Qembed_debug"); // Embed PDB in shader container (must be used with /Zi) + compileArguments.push_back(L"-Zi"); // Enable debug information +#endif + } + + ShaderCompiler::ShaderCompiler() + { + } + + ShaderCompiler::~ShaderCompiler() + { + //SafeRelease(linker_); + //SafeRelease(includeHandler_); + //SafeRelease(reflection_); + + //SafeRelease(library_); + //SafeRelease(compiler_); + //SafeRelease(validator_); + + + //if (dll_) { + //FreeLibrary(dll_); + //} + } + + HRESULT ShaderCompiler::init(const wchar_t* pathDXCompiler_dll, const wchar_t* pathDXIL_dll) + { + HRESULT status = S_OK; + + HMODULE dllDXIL = LoadLibraryW(pathDXIL_dll); + dll_ = LoadLibraryW(pathDXCompiler_dll); + if (!dll_) { + //fmt::print(std::cerr, "Cannot load dxcompiler.dll\n"); + return E_FAIL; + } + + DxcCreateInstanceProc pfnDxcCreateInstance = DxcCreateInstanceProc(GetProcAddress(dll_, "DxcCreateInstance")); + if (pfnDxcCreateInstance == nullptr) + { + //fmt::print(std::cerr, "Failed to DxcCreateInstance address.\n"); + return E_FAIL; + } + + SafeRelease(validator_); + if (FAILED(pfnDxcCreateInstance(CLSID_DxcValidator, IID_PPV_ARGS(&validator_)))) { + //fmt::print(std::cerr, "Failed creating DxcValidator\n"); + status = E_FAIL; + } + + SafeRelease(compiler_); + if (FAILED(pfnDxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler_)))) { + //fmt::print(std::cerr, "Failed create DxcCompiler instance.\n"); + status = E_FAIL; + } + + SafeRelease(library_); + if (FAILED(pfnDxcCreateInstance(CLSID_DxcLibrary, IID_PPV_ARGS(&library_)))) { + //fmt::print(std::cerr, "Failed creating DxcLibrary instance.\n"); + status = E_FAIL; + } + + SafeRelease(reflection_); + if (FAILED(pfnDxcCreateInstance(CLSID_DxcContainerReflection, IID_PPV_ARGS(&reflection_)))) { + //fmt::print(std::cerr, "Failed creating DxcLibrary instance.\n"); + status = E_FAIL; + } + + SafeRelease(includeHandler_); + if (FAILED(library_->CreateIncludeHandler(&includeHandler_))) { + //fmt::print(std::cerr, "Failed creating Dxc include handler.\n"); + status = E_FAIL; + } + + SafeRelease(linker_); + if (FAILED(pfnDxcCreateInstance(CLSID_DxcLinker, IID_PPV_ARGS(&linker_)))) { + //fmt::print(std::cerr, "Failed creating DxcLinker instance.\n"); + status = E_FAIL; + } + + return status; + } + + HRESULT ShaderCompiler::validate(IDxcBlob* input, IDxcOperationResult** ppResult, UINT32 flags) + { + return validator_->Validate(input, flags, ppResult); + } + + IDxcContainerReflection* ShaderCompiler::dgbReflection() + { + return reflection_; + } + + HRESULT ShaderCompiler::compile(LPCWSTR FilePath, IDxcBlobEncoding* source, ShaderCompilationDesc* desc, IDxcBlob** ppResult) + { + HRESULT hr = E_FAIL; + std::wstring s; + for (UINT d = 0; d < (UINT)desc->Defines.size(); ++d) + { + s += L"-D"; + s += desc->Defines[d].Name; + s += L"="; + s += desc->Defines[d].Value; + s += L" "; + } + IDxcOperationResult* pResult = nullptr; + if (SUCCEEDED(hr = compiler_->Compile( + source, // program text + FilePath, // file name, mostly for error messages + desc->EntryPoint, // entry point function + desc->TargetProfile, // target profile + desc->CompileArguments.data(), // compilation arguments + (UINT)desc->CompileArguments.size(), // number of compilation arguments + desc->Defines.data(), // define arguments + (UINT)desc->Defines.size(), // number of define arguments + includeHandler_, // handler for #include directives + &pResult))) + { + HRESULT hrCompile = E_FAIL; + if (SUCCEEDED(hr = pResult->GetStatus(&hrCompile))) + { + if (SUCCEEDED(hrCompile)) + { + if (ppResult) + { + pResult->GetResult(ppResult); + hr = S_OK; + } + else + { + hr = E_FAIL; + } + } + else + { + hr = E_FAIL; + } + } + + // Always try and get the error buffer to display possible warnings. + IDxcBlobEncoding* pPrintBlob = nullptr; + if (SUCCEEDED(pResult->GetErrorBuffer(&pPrintBlob))) + { + // We can use the library to get our preferred encoding. + IDxcBlobEncoding* pPrintBlob16 = nullptr; + library_->GetBlobAsUtf16(pPrintBlob, &pPrintBlob16); + + std::wstring errString = static_cast(pPrintBlob16->GetBufferPointer()); + if (errString.length() > 0) { + std::wstringstream err; + err << L"SHADER_COMPILATION_INFO" << errString; + + OutputDebugStringW(err.str().c_str()); + } + SafeRelease(pPrintBlob16); + } + SafeRelease(pPrintBlob); + } + SafeRelease(pResult); + + return hr; + } + + HRESULT ShaderCompiler::compileFromFile(LPCWSTR FilePath, ShaderCompilationDesc* desc, IDxcBlob** ppResult) + { + HRESULT hr = E_FAIL; + + if (desc) + { + IDxcBlobEncoding* source = nullptr; + + if (SUCCEEDED(hr = library_->CreateBlobFromFile(FilePath, nullptr, &source))) + { + hr = compile(FilePath, source, desc, ppResult); + } + SafeRelease(source); + } + + return hr; + } + + HRESULT ShaderCompiler::compileFromString(std::string code, ShaderCompilationDesc* desc, IDxcBlob** ppResult) + { + HRESULT hr = E_FAIL; + + if (desc) + { + IDxcBlobEncoding* source = nullptr; + if (SUCCEEDED(hr = library_->CreateBlobWithEncodingFromPinned(code.data(), (UINT32)code.length(), CP_ACP, &source))) + { + hr = compile(L"NOT_SET", source, desc, ppResult); + } + SafeRelease(source); + } + + return hr; + } +} diff --git a/samples/fsr/HLSLCompile/shadercompiler.h b/samples/fsr/HLSLCompile/shadercompiler.h new file mode 100644 index 00000000..bfd62977 --- /dev/null +++ b/samples/fsr/HLSLCompile/shadercompiler.h @@ -0,0 +1,120 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "fsr2_DXC_IncludeHandler.h" + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include "windows.h" + +#include + +#include +#include +#include +#include + +namespace FidelityFx +{ + void AddDefaultCompileArguments(std::vector& compileArguments); + + // Safe release for interfaces + template + inline void SafeRelease(Interface*& pInterfaceToRelease) + { + if (pInterfaceToRelease != nullptr) + { + pInterfaceToRelease->Release(); + + pInterfaceToRelease = nullptr; + } + } + + template + inline void SafeDelete(Interface*& pInterfaceToDelete) + { + if (pInterfaceToDelete != nullptr) + { + delete pInterfaceToDelete; + pInterfaceToDelete = nullptr; + } + } + +#define DXIL_FOURCC(ch0, ch1, ch2, ch3) ( \ + (uint32_t)(uint8_t)(ch0) | (uint32_t)(uint8_t)(ch1) << 8 | \ + (uint32_t)(uint8_t)(ch2) << 16 | (uint32_t)(uint8_t)(ch3) << 24 \ + ) + + enum DxilFourCC { + DFCC_Container = DXIL_FOURCC('D', 'X', 'B', 'C'), // for back-compat with tools that look for DXBC containers + DFCC_ResourceDef = DXIL_FOURCC('R', 'D', 'E', 'F'), + DFCC_InputSignature = DXIL_FOURCC('I', 'S', 'G', '1'), + DFCC_OutputSignature = DXIL_FOURCC('O', 'S', 'G', '1'), + DFCC_PatchConstantSignature = DXIL_FOURCC('P', 'S', 'G', '1'), + DFCC_ShaderStatistics = DXIL_FOURCC('S', 'T', 'A', 'T'), + DFCC_ShaderDebugInfoDXIL = DXIL_FOURCC('I', 'L', 'D', 'B'), + DFCC_ShaderDebugName = DXIL_FOURCC('I', 'L', 'D', 'N'), + DFCC_FeatureInfo = DXIL_FOURCC('S', 'F', 'I', '0'), + DFCC_PrivateData = DXIL_FOURCC('P', 'R', 'I', 'V'), + DFCC_RootSignature = DXIL_FOURCC('R', 'T', 'S', '0'), + DFCC_DXIL = DXIL_FOURCC('D', 'X', 'I', 'L'), + DFCC_PipelineStateValidation = DXIL_FOURCC('P', 'S', 'V', '0'), + }; + + struct ShaderCompilationDesc + { + LPCWSTR EntryPoint; + LPCWSTR TargetProfile; + std::vector CompileArguments; + std::vector Defines; + }; + + class ShaderCompiler + { + IDxcLibrary* library_ = nullptr; + IDxcCompiler* compiler_ = nullptr; + IDxcLinker* linker_ = nullptr; + IDxcIncludeHandler* includeHandler_ = nullptr; + IDxcValidator* validator_ = nullptr; + IDxcContainerReflection* reflection_ = nullptr; + HMODULE dll_ = 0; + + HRESULT compile(LPCWSTR FilePath, IDxcBlobEncoding* source, ShaderCompilationDesc* desc, IDxcBlob** ppResult); + + public: + ShaderCompiler(); + ~ShaderCompiler(); + + HRESULT init(const wchar_t* pathDXCompiler_dll, const wchar_t* pathDXIL_dll); + + HRESULT compileFromFile(LPCWSTR FilePath, ShaderCompilationDesc* desc, IDxcBlob** ppResult); + HRESULT compileFromString(std::string code, ShaderCompilationDesc* desc, IDxcBlob** ppResult); + + HRESULT validate(IDxcBlob* input, IDxcOperationResult** ppResult, UINT32 flags = DxcValidatorFlags_InPlaceEdit); + + void disassemble(const void* pBuffer, size_t size); + + IDxcContainerReflection* dgbReflection(); + }; +} diff --git a/samples/fsr/config/fsrconfig.json b/samples/fsr/config/fsrconfig.json index 06df7851..6ce4bb82 100644 --- a/samples/fsr/config/fsrconfig.json +++ b/samples/fsr/config/fsrconfig.json @@ -1,5 +1,6 @@ { "FidelityFX FSR": { + "MotionVectorGeneration": "GBufferRenderModule", "RenderResources": { "ReactiveMask": { @@ -11,6 +12,30 @@ "Format": "R8_UNORM", "AllowUAV": true, "RenderResolution": false + }, + "UiTarget0_LDR8": { + "Format": "RGBA8_UNORM", + "RenderResolution": false + }, + "UiTarget1_LDR8": { + "Format": "RGBA8_UNORM", + "RenderResolution": false + }, + "UiTarget0_HDR10": { + "Format": "RGB10A2_UNORM", + "RenderResolution": false + }, + "UiTarget1_HDR10": { + "Format": "RGB10A2_UNORM", + "RenderResolution": false + }, + "UiTarget0_HDR16": { + "Format": "RGBA16_FLOAT", + "RenderResolution": false + }, + "UiTarget1_HDR16": { + "Format": "RGBA16_FLOAT", + "RenderResolution": false } }, @@ -19,10 +44,13 @@ "RasterShadowRenderModule", "GBufferRenderModule", "LightingRenderModule", + "AnimatedTexturesRenderModule", "TranslucencyRenderModule", "GPUParticleRenderModule", "TAARenderModule", "FSR2RenderModule", + "FSR3UpscaleRenderModule", + "FSR3RenderModule", "UpscaleRenderModule", "ToneMappingRenderModule", "FSR1RenderModule" @@ -52,7 +80,7 @@ "Emitters": [ { "Name": "Smoke", - "SpawnOffset": [ 0.0, 0.0, 1.4 ], + "SpawnOffset": [ 6.0, 0.0, 1.4 ], "SpawnOffsetVariance": [ 0.1, 0.0, 0.1 ], "SpawnVelocity": [ 0.0, 0.2, 0.0 ], "SpawnVelocityVariance": 1.0, @@ -69,7 +97,7 @@ }, { "Name": "Spark", - "SpawnOffset": [ 0.0, 0.0, -1.4 ], + "SpawnOffset": [ -3.0, 0.0, -1.4 ], "SpawnOffsetVariance": [ 0.05, 0.0, 0.05 ], "SpawnVelocity": [ 0.0, 4.0, 0.0 ], "SpawnVelocityVariance": 0.5, @@ -87,6 +115,12 @@ ] } ] + }, + + "FPSLimiter": { + "Enable": true, + "UseGPULimiter": false, + "TargetFPS": 60 } } } diff --git a/samples/fsr/fsr1rendermodule.cpp b/samples/fsr/fsr1rendermodule.cpp index bd588bd4..9514d6bf 100644 --- a/samples/fsr/fsr1rendermodule.cpp +++ b/samples/fsr/fsr1rendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "fsr1rendermodule.h" #include "validation_remap.h" #include "render/device.h" @@ -40,6 +40,21 @@ void FSR1RenderModule::Init(const json& initData) // Fetch needed resources m_pColorTarget = GetFramework()->GetColorTargetForCallback(GetName()); + switch (GetFramework()->GetSwapChain()->GetSwapChainDisplayMode()) + { + case DisplayMode::DISPLAYMODE_LDR: + m_pColorTarget = GetFramework()->GetRenderTexture(L"LDR8Color"); + break; + case DisplayMode::DISPLAYMODE_HDR10_2084: + case DisplayMode::DISPLAYMODE_FSHDR_2084: + m_pColorTarget = GetFramework()->GetRenderTexture(L"HDR10Color"); + break; + case DisplayMode::DISPLAYMODE_HDR10_SCRGB: + case DisplayMode::DISPLAYMODE_FSHDR_SCRGB: + m_pColorTarget = GetFramework()->GetRenderTexture(L"HDR16Color"); + break; + } + // Set the format to use for the intermediate resource when RCAS is enabled switch (m_pColorTarget->GetFormat()) @@ -99,7 +114,7 @@ void FSR1RenderModule::EnableModule(bool enabled) // Setup FidelityFX interface. const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_FSR1_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_FSR1_CONTEXT_COUNT); CauldronAssert(ASSERT_CRITICAL, errorCode == FFX_OK, L"Could not initialize the FidelityFX SDK backend"); diff --git a/samples/fsr/fsr1rendermodule.h b/samples/fsr/fsr1rendermodule.h index 614b5101..87fbd7ee 100644 --- a/samples/fsr/fsr1rendermodule.h +++ b/samples/fsr/fsr1rendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "render/rendermodule.h" diff --git a/samples/fsr/fsr2rendermodule.cpp b/samples/fsr/fsr2rendermodule.cpp index bd77d9ff..5169b2c8 100644 --- a/samples/fsr/fsr2rendermodule.cpp +++ b/samples/fsr/fsr2rendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "fsr2rendermodule.h" #include "validation_remap.h" #include "render/dynamicresourcepool.h" @@ -116,13 +116,27 @@ void FSR2RenderModule::EnableModule(bool enabled) // Setup Cauldron FidelityFX interface. const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_FSR2_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_FSR2_CONTEXT_COUNT); CauldronAssert(ASSERT_CRITICAL, errorCode == FFX_OK, L"Could not initialize the FidelityFX SDK backend"); // Create the FSR2 context UpdateFSR2Context(true); + // Set the jitter callback to use + CameraJitterCallback jitterCallback = [this](Vec2& values) { + // Increment jitter index for frame + ++m_JitterIndex; + + // Update FSR2 jitter for built in TAA + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + const int32_t jitterPhaseCount = ffxFsr2GetJitterPhaseCount(resInfo.RenderWidth, resInfo.DisplayWidth); + ffxFsr2GetJitterOffset(&m_JitterX, &m_JitterY, m_JitterIndex, jitterPhaseCount); + + values = Vec2(-2.f * m_JitterX / resInfo.RenderWidth, 2.f * m_JitterY / resInfo.RenderHeight); + }; + CameraComponent::SetJitterCallbackFunc(jitterCallback); + // ... and register UI elements for active upscaler GetUIManager()->RegisterUIElements(m_UISection); } @@ -139,6 +153,8 @@ void FSR2RenderModule::EnableModule(bool enabled) // Destroy the FidelityFX interface memory free(m_InitializationParameters.backendInterface.scratchBuffer); + CameraComponent::SetJitterCallbackFunc(nullptr); + // Deregister UI elements for inactive upscaler GetUIManager()->UnRegisterUIElements(m_UISection); } @@ -308,15 +324,6 @@ void FSR2RenderModule::Execute(double deltaTime, CommandList* pCmdList) const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); CameraComponent* pCamera = GetScene()->GetCurrentCamera(); - // Increment jitter index for frame - ++m_JitterIndex; - - // Update FSR2 jitter for built in TAA - float jitterX, jitterY; - const int32_t jitterPhaseCount = ffxFsr2GetJitterPhaseCount(resInfo.RenderWidth, resInfo.DisplayWidth); - ffxFsr2GetJitterOffset(&jitterX, &jitterY, m_JitterIndex, jitterPhaseCount); - pCamera->SetJitterValues({-2.f * jitterX / resInfo.RenderWidth, 2.f * jitterY / resInfo.RenderHeight}); - // All cauldron resources come into a render module in a generic read state (ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource) FfxFsr2DispatchDescription dispatchParameters = {}; dispatchParameters.commandList = ffxGetCommandList(pCmdList); @@ -344,8 +351,9 @@ void FSR2RenderModule::Execute(double deltaTime, CommandList* pCmdList) dispatchParameters.transparencyAndComposition = ffxGetResource(nullptr, L"FSR2_EmptyTransparencyAndCompositionMap", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); } - dispatchParameters.jitterOffset.x = jitterX; - dispatchParameters.jitterOffset.y = jitterY; + // Jitter is calculated earlier in the frame using a callback from the camera update + dispatchParameters.jitterOffset.x = -m_JitterX; + dispatchParameters.jitterOffset.y = -m_JitterY; dispatchParameters.motionVectorScale.x = resInfo.fRenderWidth(); dispatchParameters.motionVectorScale.y = resInfo.fRenderHeight(); dispatchParameters.reset = false; diff --git a/samples/fsr/fsr2rendermodule.h b/samples/fsr/fsr2rendermodule.h index 2771fb84..d0135a9d 100644 --- a/samples/fsr/fsr2rendermodule.h +++ b/samples/fsr/fsr2rendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "render/rendermodule.h" @@ -136,6 +136,8 @@ class FSR2RenderModule : public cauldron::RenderModule FSR2MaskMode m_MaskMode = FSR2MaskMode::Manual; float m_Sharpness = 0.8f; uint32_t m_JitterIndex = 0; + float m_JitterX = 0.f; + float m_JitterY = 0.f; bool m_UpscaleRatioEnabled = false; bool m_UseMask = true; diff --git a/samples/fsr/fsr3rendermodule.cpp b/samples/fsr/fsr3rendermodule.cpp new file mode 100644 index 00000000..f1691f94 --- /dev/null +++ b/samples/fsr/fsr3rendermodule.cpp @@ -0,0 +1,972 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "fsr3rendermodule.h" +#include "validation_remap.h" +#include "render/rendermodules/ui/uirendermodule.h" +#include "render/rasterview.h" +#include "render/dynamicresourcepool.h" +#include "render/parameterset.h" +#include "render/pipelineobject.h" +#include "render/rootsignature.h" +#include "render/swapchain.h" +#include "render/resourceviewallocator.h" +#include "core/scene.h" +#include "misc/assert.h" +#include "render/profiler.h" + +#include "core/win/framework_win.h" + +#ifdef FFX_API_DX12 +# include "render/dx12/swapchain_dx12.h" +# include "render/dx12/device_dx12.h" +# include "render/dx12/commandlist_dx12.h" +# include "render/dx12/resourceview_dx12.h" +#endif + +#include + +using namespace std; +using namespace cauldron; + +void FSR3RenderModule::Init(const json& initData) +{ + // Fetch needed resources + m_pColorTarget = cauldron::GetFramework()->GetColorTargetForCallback(GetName()); + m_pDepthTarget = cauldron::GetFramework()->GetRenderTexture(L"DepthTarget"); + + // Create render resolution opaque render target to use for auto-reactive mask generation + TextureDesc desc = m_pColorTarget->GetDesc(); + const ResolutionInfo& resInfo = cauldron::GetFramework()->GetResolutionInfo(); + desc.Width = resInfo.RenderWidth; + desc.Height = resInfo.RenderHeight; + desc.Name = L"FSR3_OpaqueTexture"; + m_pOpaqueTexture = GetDynamicResourcePool()->CreateRenderTexture(&desc, [](TextureDesc& desc, uint32_t displayWidth, uint32_t displayHeight, uint32_t renderingWidth, uint32_t renderingHeight) + { + desc.Width = renderingWidth; + desc.Height = renderingHeight; + }); + + // Assumed resources, need to check they are there + m_pMotionVectors = GetFramework()->GetRenderTexture(L"GBufferMotionVectorRT"); + m_pReactiveMask = GetFramework()->GetRenderTexture(L"ReactiveMask"); + m_pCompositionMask = GetFramework()->GetRenderTexture(L"TransCompMask"); + + // Create raster views on the reactive mask and composition masks (for clearing and rendering) + m_RasterViews.resize(2); + m_RasterViews[0] = GetRasterViewAllocator()->RequestRasterView(m_pReactiveMask, ViewDimension::Texture2D); + m_RasterViews[1] = GetRasterViewAllocator()->RequestRasterView(m_pCompositionMask, ViewDimension::Texture2D); + + // Set our render resolution function as that to use during resize to get render width/height from display width/height + m_pUpdateFunc = [this](uint32_t displayWidth, uint32_t displayHeight) { return this->UpdateResolution(displayWidth, displayHeight); }; + + ////////////////////////////////////////////////////////////////////////// + // Build UI + + // Build UI options, but don't register them yet. Registration/Deregistration will be controlled by enabling/disabling the render module + m_UISection.SectionName = "Upscaling"; // We will piggy-back on existing upscaling section" + + // Setup scale preset options + const char* preset[] = { "Native AA (1.0x)", "Quality (1.5x)", "Balanced (1.7x)", "Performance (2x)", "Ultra Performance (3x)", "Custom" }; + std::vector presetComboOptions; + for (int32_t i = 0; i < _countof(preset); ++i) + presetComboOptions.push_back(preset[i]); + std::function presetCallback = [this](void* pParams) { this->UpdatePreset(static_cast(pParams)); }; + m_UISection.AddCombo("Scale Preset", reinterpret_cast(&m_ScalePreset), &presetComboOptions, presetCallback); + + // Setup mip bias + std::function mipBiasCallback = [this](void* pParams) { this->UpdateMipBias(static_cast(pParams)); }; + m_UISection.AddFloatSlider("Mip LOD Bias", &m_MipBias, -5.f, 0.f, mipBiasCallback); + + // Setup scale factor (disabled for all but custom) + std::function ratioCallback = [this](void* pParams) { this->UpdateUpscaleRatio(static_cast(pParams)); }; + m_UISection.AddFloatSlider("Custom Scale", &m_UpscaleRatio, 1.f, 3.f, ratioCallback, &m_UpscaleRatioEnabled); + + // Reactive mask + const char* masks[] = { "Disabled", "Manual Reactive Mask Generation", "Autogen FSR3 Helper Function" }; + std::vector maskComboOptions; + for (int32_t i = 0; i < _countof(masks); ++i) + maskComboOptions.push_back(masks[i]); + m_UISection.AddCombo("Reactive Mask Mode", reinterpret_cast(&m_MaskMode), &maskComboOptions); + + // Use mask + m_UISection.AddCheckBox("Use Transparency and Composition Mask", &m_UseMask); + + // Sharpening + std::function sharpeningCallback = [this](void* pParams) { this->m_SharpnessEnabled = this->m_RCASSharpen; }; + m_UISection.AddCheckBox("RCAS Sharpening", &m_RCASSharpen, sharpeningCallback); + m_UISection.AddFloatSlider("Sharpness", &m_Sharpness, 0.f, 1.f, nullptr, &m_RCASSharpen); + +#if defined(FFX_API_DX12) + // Frame interpolation + m_UISection.AddCheckBox("Frame Interpolation", &m_FrameInterpolation, [this](void*) { + this->m_OfUiEnabled = this->m_FrameInterpolation && this->s_enableSoftwareMotionEstimation; + // Ask main loop to re-initialize. + this->m_NeedReInit = true; + }); + + m_UISection.AddCheckBox("Support Async Compute", &m_PendingEnableAsyncCompute, [this](void*) { + // Ask main loop to re-initialize. + this->m_NeedReInit = true; + }); + + m_UISection.AddCheckBox("Allow async compute", &m_AllowAsyncCompute, nullptr, &m_PendingEnableAsyncCompute); + + m_UISection.AddCheckBox("Use callback", &m_UseCallback, nullptr, &m_FrameInterpolation); + m_UISection.AddCheckBox("Draw tear lines", &m_DrawDebugTearLines, nullptr, &m_FrameInterpolation); + m_UISection.AddCheckBox("Draw debug view", &m_DrawDebugView, nullptr, &m_FrameInterpolation); + + std::vector uiRenderModeLabels = {"No UI handling (not recommended)", "UiTexture", "UiCallback", "Pre-Ui Backbuffer"}; + std::function uiRenderModeCallback = [this](void* pParams) { + UIRenderModule* uimod = static_cast(cauldron::GetFramework()->GetRenderModule("UIRenderModule")); + uimod->SetAsyncRender(s_uiRenderMode == 2); + uimod->SetRenderToTexture(s_uiRenderMode == 1); + uimod->SetCopyHudLessTexture(s_uiRenderMode == 3); + + this->m_NeedReInit = true; + }; + m_UISection.AddCombo("UI Composition Mode", &s_uiRenderMode, &uiRenderModeLabels, uiRenderModeCallback, &m_FrameInterpolation); + +#endif + ////////////////////////////////////////////////////////////////////////// + // Register additional execution callbacks during the frame + + // Register a post-lighting callback to copy opaque texture + ExecuteCallback callbackPreTrans = [this](double deltaTime, CommandList* pCmdList) { + this->PreTransCallback(deltaTime, pCmdList); + }; + ExecutionTuple callbackPreTransTuple = std::make_pair(L"FSR3RenderModule::PreTransCallback", std::make_pair(this, callbackPreTrans)); + GetFramework()->RegisterExecutionCallback(L"LightingRenderModule", false, callbackPreTransTuple); + + // Register a post-transparency callback to generate reactive mask + ExecuteCallback callbackPostTrans = [this](double deltaTime, CommandList* pCmdList) { + this->PostTransCallback(deltaTime, pCmdList); + }; + ExecutionTuple callbackPostTransTuple = std::make_pair(L"FSR3RenderModule::PostTransCallback", std::make_pair(this, callbackPostTrans)); + GetFramework()->RegisterExecutionCallback(L"TranslucencyRenderModule", false, callbackPostTransTuple); + + m_curUiTextureIndex = 0; + // Get the proper UI color target + switch (GetFramework()->GetSwapChain()->GetSwapChainDisplayMode()) + { + case DisplayMode::DISPLAYMODE_LDR: + m_pUiTexture[0] = GetFramework()->GetRenderTexture(L"UiTarget0_LDR8"); + m_pUiTexture[1] = GetFramework()->GetRenderTexture(L"UiTarget1_LDR8"); + break; + case DisplayMode::DISPLAYMODE_HDR10_2084: + case DisplayMode::DISPLAYMODE_FSHDR_2084: + m_pUiTexture[0] = GetFramework()->GetRenderTexture(L"UiTarget0_HDR10"); + m_pUiTexture[1] = GetFramework()->GetRenderTexture(L"UiTarget1_HDR10"); + break; + case DisplayMode::DISPLAYMODE_HDR10_SCRGB: + case DisplayMode::DISPLAYMODE_FSHDR_SCRGB: + m_pUiTexture[0] = GetFramework()->GetRenderTexture(L"UiTarget0_HDR16"); + m_pUiTexture[1] = GetFramework()->GetRenderTexture(L"UiTarget1_HDR16"); + break; + } + + // Create FrameInterpolationSwapchain + // Separate from FSR3 generation so it can be done when the engine creates the swapchain + // should not be created and destroyed with FSR3, as it requires a switch to windowed mode +#ifdef FFX_API_CAULDRON + // FSR3 not supported on cauldron backend, so proxy swapchain is not required +#elif defined(FFX_API_DX12) + //if (false) + { + // TODO: should check if FI swapchain already exists! + + // take control over the swapchain: first get the swapchain and set to NULL in engine + IDXGISwapChain4* dxgiSwapchain = cauldron::GetFramework()->GetSwapChain()->GetImpl()->DX12SwapChain(); + //m_InitializationParameters.fiDescription.swapchain = ffxGetSwapchainDX12(dxgiSwapchain); + dxgiSwapchain->AddRef(); + + dxgiSwapchain->GetDesc(&gameSwapChainDesc); + dxgiSwapchain->GetDesc1(&gameSwapChainDesc1); + dxgiSwapchain->GetFullscreenDesc(&gameFullscreenDesc); + + // Create frameinterpolation swapchain + cauldron::SwapChain* pSwapchain = GetFramework()->GetSwapChain(); + FfxSwapchain ffxSwapChain = ffxGetSwapchainDX12(pSwapchain->GetImpl()->DX12SwapChain()); + // make sure swapchain is not holding a ref to real swapchain + GetFramework()->GetSwapChain()->GetImpl()->SetDXGISwapChain(nullptr); + + ID3D12CommandQueue* pCmdQueue = GetDevice()->GetImpl()->DX12CmdQueue(CommandQueue::Graphics); + FfxCommandQueue ffxGameQueue = ffxGetCommandQueueDX12(pCmdQueue); + + ffxReplaceSwapchainForFrameinterpolation(ffxGameQueue, ffxSwapChain); + + // Set frameinterpolation swapchain to engine + IDXGISwapChain4* frameinterpolationSwapchain = ffxGetDX12SwapchainPtr(ffxSwapChain); + GetFramework()->GetSwapChain()->GetImpl()->SetDXGISwapChain(frameinterpolationSwapchain); + // Framework swapchain adds to the refcount, so we need to release the swapchain here + frameinterpolationSwapchain->Release(); + + // In case the app is handling Alt-Enter manually we need to update the window association after creating a different swapchain + IDXGIFactory7* factory = nullptr; + if (SUCCEEDED(frameinterpolationSwapchain->GetParent(IID_PPV_ARGS(&factory)))) + { + factory->MakeWindowAssociation(GetFramework()->GetInternal()->GetHWND(), DXGI_MWA_NO_WINDOW_CHANGES); + factory->Release(); + } + + // Lets do the same for HDR as well as it will need to be re initialized since swapchain was re created + { + GetFramework()->GetSwapChain()->SetHDRMetadataAndColorspace(); + } + } +#else + // FSR3 not supported on vulkan backend, so proxy swapchain is not required +#endif + + cauldron::SwapChain* swapchain = cauldron::GetFramework()->GetSwapChain(); + TextureDesc hudlessDesc = swapchain->GetBackBufferRT()->GetDesc(); + hudlessDesc.MipLevels = 1; + hudlessDesc.Name = L"FSR3_HudLessTexture0"; + hudlessDesc.Flags = ResourceFlags::AllowUnorderedAccess | ResourceFlags::AllowRenderTarget; + m_pHudLessTexture[0] = GetDynamicResourcePool()->CreateRenderTexture( + &hudlessDesc, [](TextureDesc& desc, uint32_t displayWidth, uint32_t displayHeight, uint32_t renderingWidth, uint32_t renderingHeight) { + desc.Width = displayWidth; + desc.Height = displayHeight; + }); + hudlessDesc.Name = L"FSR3_HudLessTexture1"; + m_pHudLessTexture[1] = GetDynamicResourcePool()->CreateRenderTexture( + &hudlessDesc, [](TextureDesc& desc, uint32_t displayWidth, uint32_t displayHeight, uint32_t renderingWidth, uint32_t renderingHeight) { + desc.Width = displayWidth; + desc.Height = displayHeight; + }); + + ////////////////////////////////////////////////////////////////////////// + // Finish up init + + // Start disabled as this will be enabled externally + SetModuleEnabled(false); + + // That's all we need for now + SetModuleReady(true); +} + +FSR3RenderModule::~FSR3RenderModule() +{ + // Protection + if (ModuleEnabled()) + EnableModule(false); // Destroy FSR context + + // ToDo: unset FrameinterpolationSwapchain +#ifdef FFX_API_CAULDRON + // FSR3 not supported in cauldron backend, so proxy swapchain destruction is not required +#elif defined(FFX_API_DX12) + //if (false) + { + cauldron::SwapChain* pSwapchain = GetFramework()->GetSwapChain(); + IDXGISwapChain4* pSwapChain4 = pSwapchain->GetImpl()->DX12SwapChain(); + pSwapChain4->AddRef(); + + DXGI_SWAP_CHAIN_DESC1 desc; + IDXGIFactory7* factory = nullptr; + ID3D12CommandQueue* pCmdQueue = GetDevice()->GetImpl()->DX12CmdQueue(CommandQueue::Graphics); + pSwapChain4->GetDesc1(&desc); + + // Setup a new swapchain for HWND and set it to cauldron + IDXGISwapChain1* pSwapChain1 = nullptr; + if (SUCCEEDED(pSwapChain4->GetParent(IID_PPV_ARGS(&factory)))) + { + GetFramework()->GetSwapChain()->GetImpl()->SetDXGISwapChain(nullptr); + pSwapChain4->Release(); + + if (SUCCEEDED(factory->CreateSwapChainForHwnd( + pCmdQueue, gameSwapChainDesc.OutputWindow, &gameSwapChainDesc1, &gameFullscreenDesc, nullptr, &pSwapChain1))) + { + if (SUCCEEDED(pSwapChain1->QueryInterface(IID_PPV_ARGS(&pSwapChain4)))) + { + GetFramework()->GetSwapChain()->GetImpl()->SetDXGISwapChain(pSwapChain4); + pSwapChain4->Release(); + } + pSwapChain1->Release(); + } + factory->MakeWindowAssociation(GetFramework()->GetInternal()->GetHWND(), DXGI_MWA_NO_WINDOW_CHANGES); + factory->Release(); + } + } +#else + // FSR3 not supported in native Vulkan backend, so proxy swapchain destruction is not required +#endif + + // Clear out raster views + m_RasterViews.clear(); +} + +void FSR3RenderModule::EnableModule(bool enabled) +{ + // If disabling the render module, we need to disable the upscaler with the framework + if (!enabled) + { + // Toggle this now so we avoid the context changes in OnResize + SetModuleEnabled(enabled); + + // Destroy the FSR3 context + UpdateFSR3Context(false); + + GetFramework()->EnableUpscaling(false); +#if FFX_API_DX12 + GetFramework()->EnableFrameInterpolation(false); +#endif + + UIRenderModule* uimod = static_cast(GetFramework()->GetRenderModule("UIRenderModule")); + uimod->SetAsyncRender(false); + uimod->SetRenderToTexture(false); + uimod->SetCopyHudLessTexture(false); + + if (ffxBackendInitialized_ == true) + { + for (auto i = 0; i < FSR3_BACKEND_COUNT; i++) + { + free(ffxFsr3Backends_[i].scratchBuffer); + ffxFsr3Backends_[i].scratchBuffer = nullptr; + } + ffxBackendInitialized_ = false; + } + + CameraComponent::SetJitterCallbackFunc(nullptr); + + // Deregister UI elements for inactive upscaler + GetUIManager()->UnRegisterUIElements(m_UISection); + } + else + { + UIRenderModule* uimod = static_cast(GetFramework()->GetRenderModule("UIRenderModule")); + uimod->SetAsyncRender(s_uiRenderMode == 2); + uimod->SetRenderToTexture(s_uiRenderMode == 1); + uimod->SetCopyHudLessTexture(s_uiRenderMode == 3); + + // Setup everything needed when activating FSR + // Will also enable upscaling + UpdatePreset(nullptr); + + // Toggle this now so we avoid the context changes in OnResize + SetModuleEnabled(enabled); + + // Setup Cauldron FidelityFX interface. + if (!ffxBackendInitialized_) + { + FfxErrorCode errorCode = 0; + + int effectCounts[] = {1, 1, 2}; + for (auto i = 0; i < FSR3_BACKEND_COUNT; i++) + { + const size_t scratchBufferSize = ffxGetScratchMemorySize(effectCounts[i]); + void* scratchBuffer = calloc(scratchBufferSize, 1); + memset(scratchBuffer, 0, scratchBufferSize); + errorCode |= ffxGetInterface(&ffxFsr3Backends_[i], GetDevice(), scratchBuffer, scratchBufferSize, effectCounts[i]); + } + + ffxBackendInitialized_ = (errorCode == FFX_OK); + FFX_ASSERT(ffxBackendInitialized_); + + m_InitializationParameters.backendInterfaceSharedResources = ffxFsr3Backends_[FSR3_BACKEND_SHARED_RESOURCES]; + m_InitializationParameters.backendInterfaceUpscaling = ffxFsr3Backends_[FSR3_BACKEND_UPSCALING]; + m_InitializationParameters.backendInterfaceFrameInterpolation = ffxFsr3Backends_[FSR3_BACKEND_FRAME_INTERPOLATION]; + } + + // Create the FSR3 context + UpdateFSR3Context(true); + + // Set the jitter callback to use + CameraJitterCallback jitterCallback = [this](Vec2& values) { + // Increment jitter index for frame + ++m_JitterIndex; + + // Update FSR3 jitter for built in TAA + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + const int32_t jitterPhaseCount = ffxFsr3GetJitterPhaseCount(resInfo.RenderWidth, resInfo.DisplayWidth); + ffxFsr3GetJitterOffset(&m_JitterX, &m_JitterY, m_JitterIndex, jitterPhaseCount); + + values = Vec2(-2.f * m_JitterX / resInfo.RenderWidth, 2.f * m_JitterY / resInfo.RenderHeight); + }; + CameraComponent::SetJitterCallbackFunc(jitterCallback); + + // ... and register UI elements for active upscaler + GetUIManager()->RegisterUIElements(m_UISection); + } +} + +void FSR3RenderModule::UpdatePreset(const int32_t* pOldPreset) +{ + switch (m_ScalePreset) + { + case FSR3ScalePreset::NativeAA: + m_UpscaleRatio = 1.0f; + break; + case FSR3ScalePreset::Quality: + m_UpscaleRatio = 1.5f; + break; + case FSR3ScalePreset::Balanced: + m_UpscaleRatio = 1.7f; + break; + case FSR3ScalePreset::Performance: + m_UpscaleRatio = 2.0f; + break; + case FSR3ScalePreset::UltraPerformance: + m_UpscaleRatio = 3.0f; + break; + case FSR3ScalePreset::Custom: + default: + // Leave the upscale ratio at whatever it was + break; + } + + // Update whether we can update the custom scale slider + m_UpscaleRatioEnabled = (m_ScalePreset == FSR3ScalePreset::Custom); + + // Update mip bias + float oldValue = m_MipBias; + if (m_ScalePreset != FSR3ScalePreset::Custom) + m_MipBias = cMipBias[static_cast(m_ScalePreset)]; + else + m_MipBias = std::log2f(1.f / m_UpscaleRatio) - 1.f + std::numeric_limits::epsilon(); + UpdateMipBias(&oldValue); + + // Update resolution since rendering ratios have changed + GetFramework()->EnableUpscaling(true, m_pUpdateFunc); +#if FFX_API_DX12 + GetFramework()->EnableFrameInterpolation(true); +#endif +} + +void FSR3RenderModule::UpdateUpscaleRatio(const float* pOldRatio) +{ + // Disable/Enable FSR3 since resolution ratios have changed + GetFramework()->EnableUpscaling(true, m_pUpdateFunc); +} + +void FSR3RenderModule::UpdateMipBias(const float* pOldBias) +{ + // Update the scene MipLODBias to use + GetScene()->SetMipLODBias(m_MipBias); +} + +void FSR3RenderModule::FfxMsgCallback(FfxMsgType type, const wchar_t* message) +{ + if (type == FFX_MESSAGE_TYPE_ERROR) + { + CauldronError(L"FSR3_API_DEBUG_ERROR: %s", message); + } + else if (type == FFX_MESSAGE_TYPE_WARNING) + { + CauldronWarning(L"FSR3_API_DEBUG_WARNING: %s", message); + } +} + +// copied from ffx_cauldron.cpp, needed for UI callback +static ResourceFormat CauldronGetSurfaceFormatFfx(FfxSurfaceFormat format) +{ + switch (format) + { + case FFX_SURFACE_FORMAT_UNKNOWN: + return ResourceFormat::Unknown; + case FFX_SURFACE_FORMAT_R32G32B32A32_TYPELESS: + return ResourceFormat::RGBA32_TYPELESS; + case FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT: + return ResourceFormat::RGBA32_FLOAT; + case FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT: + return ResourceFormat::RGBA16_FLOAT; + case FFX_SURFACE_FORMAT_R32G32_FLOAT: + return ResourceFormat::RG32_FLOAT; + case FFX_SURFACE_FORMAT_R32_UINT: + return ResourceFormat::R32_UINT; + case FFX_SURFACE_FORMAT_R8G8B8A8_TYPELESS: + return ResourceFormat::RGBA8_TYPELESS; + case FFX_SURFACE_FORMAT_R8G8B8A8_UNORM: + return ResourceFormat::RGBA8_UNORM; + case FFX_SURFACE_FORMAT_R8G8B8A8_SNORM: + return ResourceFormat::RGBA8_SNORM; + case FFX_SURFACE_FORMAT_R8G8B8A8_SRGB: + return ResourceFormat::RGBA8_SRGB; + case FFX_SURFACE_FORMAT_R11G11B10_FLOAT: + return ResourceFormat::RG11B10_FLOAT; + case FFX_SURFACE_FORMAT_R16G16_FLOAT: + return ResourceFormat::RG16_FLOAT; + case FFX_SURFACE_FORMAT_R16G16_UINT: + return ResourceFormat::RG16_UINT; + case FFX_SURFACE_FORMAT_R16G16_SINT: + return ResourceFormat::RG16_SINT; + case FFX_SURFACE_FORMAT_R16_FLOAT: + return ResourceFormat::R16_FLOAT; + case FFX_SURFACE_FORMAT_R16_UINT: + return ResourceFormat::R16_UINT; + case FFX_SURFACE_FORMAT_R16_UNORM: + return ResourceFormat::R16_UNORM; + case FFX_SURFACE_FORMAT_R16_SNORM: + return ResourceFormat::R16_SNORM; + case FFX_SURFACE_FORMAT_R8_UNORM: + return ResourceFormat::R8_UNORM; + case FFX_SURFACE_FORMAT_R8_UINT: + return ResourceFormat::R8_UINT; + case FFX_SURFACE_FORMAT_R8G8_UNORM: + return ResourceFormat::RG8_UNORM; + case FFX_SURFACE_FORMAT_R32_FLOAT: + return ResourceFormat::R32_FLOAT; + case FFX_SURFACE_FORMAT_R10G10B10A2_UNORM: + return ResourceFormat::RGB10A2_UNORM; + default: + FFX_ASSERT_MESSAGE(false, "FFXInterface: Cauldron: Unsupported format requested. Please implement."); + return ResourceFormat::Unknown; + } +} + +// copied from ffx_cauldron.cpp, needed for UI callback +static ResourceFlags CauldronGetResourceFlagsFfx(FfxResourceUsage flags) +{ + ResourceFlags cauldronResourceFlags = ResourceFlags::None; + + if (flags & FFX_RESOURCE_USAGE_RENDERTARGET) + cauldronResourceFlags |= ResourceFlags::AllowRenderTarget; + + if (flags & FFX_RESOURCE_USAGE_DEPTHTARGET) + cauldronResourceFlags |= ResourceFlags::AllowDepthStencil; + + if (flags & FFX_RESOURCE_USAGE_UAV) + cauldronResourceFlags |= ResourceFlags::AllowUnorderedAccess; + + if (flags & FFX_RESOURCE_USAGE_INDIRECT) + cauldronResourceFlags |= ResourceFlags::AllowIndirect; + + return cauldronResourceFlags; +} + +// copied from ffx_cauldron.cpp, MODIFIED!, needed for UI callback +static ResourceState CauldronGetStateFfx(FfxResourceStates state) +{ + switch (state) + { + case FFX_RESOURCE_STATE_UNORDERED_ACCESS: + return ResourceState::UnorderedAccess; + case FFX_RESOURCE_STATE_COMPUTE_READ: + return ResourceState::NonPixelShaderResource; + case FFX_RESOURCE_STATE_PIXEL_READ: + return ResourceState::PixelShaderResource; + case FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ: + return ResourceState(ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource); + case FFX_RESOURCE_STATE_COPY_SRC: + return ResourceState::CopySource; + case FFX_RESOURCE_STATE_COPY_DEST: + return ResourceState::CopyDest; + case FFX_RESOURCE_STATE_GENERIC_READ: + return (ResourceState)((uint32_t)ResourceState::NonPixelShaderResource | (uint32_t)ResourceState::PixelShaderResource); + case FFX_RESOURCE_STATE_INDIRECT_ARGUMENT: + return ResourceState::IndirectArgument; + case FFX_RESOURCE_STATE_PRESENT: + return ResourceState::Present; + default: + FFX_ASSERT_MESSAGE(false, "FFXInterface: Cauldron: Unsupported resource state requested. Please implement."); + return ResourceState::CommonResource; + } +} + +static ResourceView* AllocCPURenderView() +{ + ResourceView* retVal; + GetResourceViewAllocator()->AllocateCPURenderViews(&retVal); + return retVal; +} +#if FFX_API_DX12 +FfxErrorCode FSR3RenderModule::UiCompositionCallback(const FfxPresentCallbackDescription* params) +{ + FSR3RenderModule* fsr3mod = static_cast(GetFramework()->GetRenderModule("FSR3RenderModule")); + UIRenderModule* uimod = static_cast(GetFramework()->GetRenderModule("UIRenderModule")); + + if (fsr3mod->s_uiRenderMode != 2) + return FFX_ERROR_INVALID_ARGUMENT; + + // Reverse of validation_remap functions. + + // wrap everything in cauldron wrappers to allow backend agnostic execution of UI render. + ID3D12GraphicsCommandList2* pDxCmdList = reinterpret_cast(params->commandList); + CommandListInternal cmdList = {L"UI_CommandList", pDxCmdList, nullptr, CommandQueue::Graphics}; + ID3D12Resource* pRtResource = reinterpret_cast(params->outputSwapChainBuffer.resource); + ID3D12Resource* pBbResource = reinterpret_cast(params->currentBackBuffer.resource); + pRtResource->AddRef(); + GPUResourceInternal rtResource(pRtResource, L"UI_RenderTarget", CauldronGetStateFfx(params->outputSwapChainBuffer.state), false); + pBbResource->AddRef(); + GPUResourceInternal bbResource(pBbResource, L"BackBuffer", CauldronGetStateFfx(params->currentBackBuffer.state), false); + + std::vector barriers; + cauldron::ResourceState rtResourceState = CauldronGetStateFfx(params->outputSwapChainBuffer.state); + barriers = {Barrier::Transition(&rtResource, rtResourceState, ResourceState::CopyDest), + Barrier::Transition(&bbResource, CauldronGetStateFfx(params->currentBackBuffer.state), ResourceState::CopySource)}; + ResourceBarrier(&cmdList, (uint32_t)barriers.size(), barriers.data()); + + pDxCmdList->CopyResource(pRtResource, pBbResource); + + barriers[0].SourceState = barriers[0].DestState; + barriers[0].DestState = ResourceState::RenderTargetResource; + swap(barriers[1].SourceState, barriers[1].DestState); + ResourceBarrier(&cmdList, (uint32_t)barriers.size(), barriers.data()); + + // FIXME: this should be a member variable, but this is a static method. Need context param on this callback. + static ResourceView* pRtResourceView = AllocCPURenderView(); + + // Create and set RTV, required for async UI render. + FfxResourceDescription rdesc = params->outputSwapChainBuffer.description; + + TextureDesc rtResourceDesc = TextureDesc::Tex2D(L"UI_RenderTarget", + CauldronGetSurfaceFormatFfx(rdesc.format), + rdesc.width, + rdesc.height, + rdesc.depth, + rdesc.mipCount, + ResourceFlags::AllowRenderTarget); + pRtResourceView->BindTextureResource(&rtResource, rtResourceDesc, ResourceViewType::RTV, ViewDimension::Texture2D, 0, 1, 0); + pDxCmdList->OMSetRenderTargets(1, &pRtResourceView->GetViewInfo().GetImpl()->hCPUHandle, false, nullptr); + + SetAllResourceViewHeaps(&cmdList); + + uimod->ExecuteAsync(&cmdList); + + ResourceBarrier(&cmdList, 1, &Barrier::Transition(&rtResource, ResourceState::RenderTargetResource, rtResourceState)); + + return FFX_OK; +} +#endif + +void FSR3RenderModule::UpdateFSR3Context(bool enabled) +{ + if (enabled) + { + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + m_InitializationParameters.maxRenderSize.width = resInfo.RenderWidth; + m_InitializationParameters.maxRenderSize.height = resInfo.RenderHeight; + m_InitializationParameters.upscaleOutputSize.width = resInfo.DisplayWidth; + m_InitializationParameters.upscaleOutputSize.height = resInfo.DisplayHeight; + m_InitializationParameters.displaySize.width = resInfo.DisplayWidth; + m_InitializationParameters.displaySize.height = resInfo.DisplayHeight; + m_InitializationParameters.flags = FFX_FSR3_ENABLE_AUTO_EXPOSURE; + static bool s_InvertedDepth = GetConfig()->InvertedDepth; + if (s_InvertedDepth) + m_InitializationParameters.flags |= FFX_FSR3_ENABLE_DEPTH_INVERTED | FFX_FSR3_ENABLE_DEPTH_INFINITE; + m_InitializationParameters.flags |= FFX_FSR3_ENABLE_HIGH_DYNAMIC_RANGE; + +#if defined(FFX_API_DX12) + m_EnableAsyncCompute = m_PendingEnableAsyncCompute; + if (m_EnableAsyncCompute) + m_InitializationParameters.flags |= FFX_FSR3_ENABLE_ASYNC_WORKLOAD_SUPPORT; +#endif + + // Do eror checking in debug +#if defined(_DEBUG) + m_InitializationParameters.flags |= FFX_FSR3_ENABLE_DEBUG_CHECKING; + m_InitializationParameters.fpMessage = &FSR3RenderModule::FfxMsgCallback; +#endif // #if defined(_DEBUG) + + // Create the FSR3 context + { + + m_InitializationParameters.backBufferFormat = GetFfxSurfaceFormat(GetFramework()->GetSwapChain()->GetSwapChainFormat()); + + // create the context. + FfxErrorCode errorCode = ffxFsr3ContextCreate(&m_FSR3Context, &m_InitializationParameters); +#if defined(FFX_API_DX12) + FFX_ASSERT(errorCode == FFX_OK); + + cauldron::SwapChain* pSwapchain = GetFramework()->GetSwapChain(); + FfxSwapchain ffxSwapChain = ffxGetSwapchainDX12(pSwapchain->GetImpl()->DX12SwapChain()); + + // configure frame generation + FfxResourceDescription hudLessDesc = GetFfxResourceDescription(m_pHudLessTexture[m_curUiTextureIndex]->GetResource(), (FfxResourceUsage)0); + FfxResource hudLessResource = ffxGetResourceDX12(m_pHudLessTexture[m_curUiTextureIndex]->GetResource()->GetImpl()->DX12Resource(), hudLessDesc, L"FSR3_HudLessBackbuffer", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + + m_FrameGenerationConfig.frameGenerationEnabled = false; + m_FrameGenerationConfig.frameGenerationCallback = ffxFsr3DispatchFrameGeneration; + m_FrameGenerationConfig.presentCallback = (s_uiRenderMode == 2) ? UiCompositionCallback : nullptr; + m_FrameGenerationConfig.swapChain = ffxSwapChain; + m_FrameGenerationConfig.HUDLessColor = (s_uiRenderMode == 3) ? hudLessResource : FfxResource({}); + + errorCode = ffxFsr3ConfigureFrameGeneration(&m_FSR3Context, &m_FrameGenerationConfig); +#endif + FFX_ASSERT(errorCode == FFX_OK); + } + } + else + { +#if defined(FFX_API_DX12) + cauldron::SwapChain* pSwapchain = GetFramework()->GetSwapChain(); + FfxSwapchain ffxSwapChain = ffxGetSwapchainDX12(pSwapchain->GetImpl()->DX12SwapChain()); + + // disable frame generation before destroying context + // also unset present callback, HUDLessColor and UiTexture to have the swapchain only present the backbuffer + m_FrameGenerationConfig.frameGenerationEnabled = false; + m_FrameGenerationConfig.swapChain = ffxSwapChain; + m_FrameGenerationConfig.presentCallback = nullptr; + m_FrameGenerationConfig.HUDLessColor = FfxResource({}); + ffxFsr3ConfigureFrameGeneration(&m_FSR3Context, &m_FrameGenerationConfig); + + ffxRegisterFrameinterpolationUiResource(ffxSwapChain, FfxResource({})); +#endif + + // Destroy the FSR3 context + ffxFsr3ContextDestroy(&m_FSR3Context); + } +} + +ResolutionInfo FSR3RenderModule::UpdateResolution(uint32_t displayWidth, uint32_t displayHeight) +{ + return { static_cast((float)displayWidth / m_UpscaleRatio), + static_cast((float)displayHeight / m_UpscaleRatio), + displayWidth, displayHeight }; +} + +void FSR3RenderModule::OnResize(const ResolutionInfo& resInfo) +{ + if (!ModuleEnabled()) + return; + + // Need to recreate the FSR3 context on resource resize + UpdateFSR3Context(false); // Destroy + UpdateFSR3Context(true); // Re-create + + // Reset jitter index + m_JitterIndex = 0; +} + +void FSR3RenderModule::Execute(double deltaTime, CommandList* pCmdList) +{ + if (m_pHudLessTexture[m_curUiTextureIndex]->GetResource()->GetCurrentResourceState() != ResourceState::NonPixelShaderResource) + { + Barrier barrier = Barrier::Transition(m_pHudLessTexture[m_curUiTextureIndex]->GetResource(), + m_pHudLessTexture[m_curUiTextureIndex]->GetResource()->GetCurrentResourceState(), + ResourceState::NonPixelShaderResource); + ResourceBarrier(pCmdList, 1, &barrier); + } + + if (m_pUiTexture[m_curUiTextureIndex]->GetResource()->GetCurrentResourceState() != cauldron::ResourceState::ShaderResource) + { + std::vector barriers = {Barrier::Transition(m_pUiTexture[m_curUiTextureIndex]->GetResource(), + m_pUiTexture[m_curUiTextureIndex]->GetResource()->GetCurrentResourceState(), + ResourceState::ShaderResource)}; + ResourceBarrier(pCmdList, (uint32_t)barriers.size(), barriers.data()); + } + + GPUScopedProfileCapture sampleMarker(pCmdList, L"FFX FSR3 Upscaler"); + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + CameraComponent* pCamera = GetScene()->GetCurrentCamera(); + +#if FFX_API_DX12 + GPUResource* swapchainBackbuffer = GetFramework()->GetSwapChain()->GetBackBufferRT()->GetCurrentResource(); + FfxResourceDescription swapChainDesc = GetFfxResourceDescriptionDX12(swapchainBackbuffer->GetImpl()->DX12Resource()); + FfxResource backbuffer = ffxGetResourceDX12(swapchainBackbuffer->GetImpl()->DX12Resource(), swapChainDesc, L"SwapchainSurface", FFX_RESOURCE_STATE_PRESENT); + + IDXGISwapChain4* pSwapchain = GetFramework()->GetSwapChain()->GetImpl()->DX12SwapChain(); + //FfxResource interpolationOutput = ffxGetFrameinterpolationTextureDX12((FfxSwapchain)pSwapchain); + + // Upscale the scene first + { + // All cauldron resources come into a render module in a generic read state (ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource) + FfxFsr3DispatchUpscaleDescription dispatchParameters = {}; + dispatchParameters.commandList = ffxGetCommandList(pCmdList); + dispatchParameters.color = ffxGetResource(m_pColorTarget->GetResource(), L"FSR3_Input_OutputColor", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchParameters.depth = ffxGetResource(m_pDepthTarget->GetResource(), L"FSR3_InputDepth", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchParameters.motionVectors = ffxGetResource(m_pMotionVectors->GetResource(), L"FSR3_InputMotionVectors", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchParameters.exposure = ffxGetResource(nullptr, L"FSR3_InputExposure", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchParameters.upscaleOutput = dispatchParameters.color; + + if (m_MaskMode != FSR3MaskMode::Disabled) + { + dispatchParameters.reactive = ffxGetResource(m_pReactiveMask->GetResource(), L"FSR3_InputReactiveMap", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + } + else + { + dispatchParameters.reactive = ffxGetResource(nullptr, L"FSR3_EmptyInputReactiveMap", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + } + + if (m_UseMask) + { + dispatchParameters.transparencyAndComposition = + ffxGetResource(m_pCompositionMask->GetResource(), L"FSR3_TransparencyAndCompositionMap", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + } + else + { + dispatchParameters.transparencyAndComposition = + ffxGetResource(nullptr, L"FSR3_EmptyTransparencyAndCompositionMap", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + } + + // Jitter is calculated earlier in the frame using a callback from the camera update + dispatchParameters.jitterOffset.x = -m_JitterX; + dispatchParameters.jitterOffset.y = -m_JitterY; + dispatchParameters.motionVectorScale.x = resInfo.fRenderWidth(); + dispatchParameters.motionVectorScale.y = resInfo.fRenderHeight(); + dispatchParameters.reset = false; + dispatchParameters.enableSharpening = m_RCASSharpen; + dispatchParameters.sharpness = m_Sharpness; + + // Cauldron keeps time in seconds, but FSR expects miliseconds + dispatchParameters.frameTimeDelta = (float)deltaTime * 1000.f; + + dispatchParameters.preExposure = GetScene()->GetSceneExposure(); + dispatchParameters.renderSize.width = resInfo.RenderWidth; + dispatchParameters.renderSize.height = resInfo.RenderHeight; + + // Note, inverted depth and display mode are currently handled statically for the run of the sample. + // If they become changeable at runtime, we'll need to modify how this information is queried + static bool s_InvertedDepth = GetConfig()->InvertedDepth; + + // Setup camera params as required + dispatchParameters.cameraFovAngleVertical = pCamera->GetFovY(); + if (s_InvertedDepth) + { + dispatchParameters.cameraFar = pCamera->GetNearPlane(); + dispatchParameters.cameraNear = FLT_MAX; + } + else + { + dispatchParameters.cameraFar = pCamera->GetFarPlane(); + dispatchParameters.cameraNear = pCamera->GetNearPlane(); + } + + // Update frame generation config + FfxResourceDescription hudLessDesc = GetFfxResourceDescription(m_pHudLessTexture[m_curUiTextureIndex]->GetResource(), (FfxResourceUsage)0); + FfxResource hudLessResource = ffxGetResourceDX12(m_pHudLessTexture[m_curUiTextureIndex]->GetResource()->GetImpl()->DX12Resource(), + hudLessDesc, + L"FSR3_HudLessBackbuffer", + FFX_RESOURCE_STATE_COMPUTE_READ); + + m_FrameGenerationConfig.frameGenerationEnabled = m_FrameInterpolation; + m_FrameGenerationConfig.flags = 0; + m_FrameGenerationConfig.flags |= m_DrawDebugTearLines ? FFX_FSR3_FRAME_GENERATION_FLAG_DRAW_DEBUG_TEAR_LINES : 0; + m_FrameGenerationConfig.flags |= m_DrawDebugView ? FFX_FSR3_FRAME_GENERATION_FLAG_DRAW_DEBUG_VIEW : 0; + m_FrameGenerationConfig.HUDLessColor = (s_uiRenderMode == 3) ? hudLessResource : FfxResource({}); + m_FrameGenerationConfig.allowAsyncWorkloads = m_AllowAsyncCompute && m_EnableAsyncCompute; + m_FrameGenerationConfig.frameGenerationCallback = m_UseCallback ? ffxFsr3DispatchFrameGeneration : nullptr; + + ffxFsr3ConfigureFrameGeneration(&m_FSR3Context, &m_FrameGenerationConfig); + + FfxErrorCode errorCode = ffxFsr3ContextDispatchUpscale(&m_FSR3Context, &dispatchParameters); + FFX_ASSERT(errorCode == FFX_OK); + + + + FfxResource uiColor = (s_uiRenderMode == 1) + ? ffxGetResource(m_pUiTexture[m_curUiTextureIndex]->GetResource(), L"FSR3_UiTexture", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ) + : FfxResource({}); + cauldron::SwapChain* pSwapchain = GetFramework()->GetSwapChain(); + FfxSwapchain ffxSwapChain = ffxGetSwapchainDX12(pSwapchain->GetImpl()->DX12SwapChain()); + ffxRegisterFrameinterpolationUiResource(ffxSwapChain, uiColor); + +#if defined(FFX_API_DX12) + // Dispatch frame generation, if not using the callback + if (m_FrameInterpolation && !m_UseCallback) + { + FfxFrameGenerationDispatchDescription fgDesc{}; + +#if defined(FFX_API_DX12) + IDXGISwapChain4* dxgiSwapchain = GetFramework()->GetSwapChain()->GetImpl()->DX12SwapChain(); + ffxGetInterpolationCommandlist(ffxGetSwapchainDX12(dxgiSwapchain), fgDesc.commandList); +#endif + + fgDesc.presentColor = backbuffer; + fgDesc.numInterpolatedFrames = 1; + fgDesc.outputs[0] = ffxGetFrameinterpolationTextureDX12(ffxGetSwapchainDX12(dxgiSwapchain)); + ffxFsr3DispatchFrameGeneration(&fgDesc); + } +#endif + } + + // FidelityFX contexts modify the set resource view heaps, so set the cauldron one back + SetAllResourceViewHeaps(pCmdList); + + // We are now done with upscaling + GetFramework()->SetUpscalingState(UpscalerState::PostUpscale); +#endif +} + +void FSR3RenderModule::PreTransCallback(double deltaTime, cauldron::CommandList* pCmdList) +{ + GPUScopedProfileCapture sampleMarker(pCmdList, L"Pre-Trans (FSR3)"); + + std::vector barriers; + barriers.push_back(Barrier::Transition(m_pReactiveMask->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::RenderTargetResource)); + barriers.push_back(Barrier::Transition(m_pCompositionMask->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::RenderTargetResource)); + ResourceBarrier(pCmdList, static_cast(barriers.size()), barriers.data()); + + // We need to clear the reactive and composition masks before any translucencies are rendered into them + float clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + ClearRenderTarget(pCmdList, &m_RasterViews[0]->GetResourceView(), clearColor); + ClearRenderTarget(pCmdList, &m_RasterViews[1]->GetResourceView(), clearColor); + + barriers.clear(); + barriers.push_back(Barrier::Transition(m_pReactiveMask->GetResource(), ResourceState::RenderTargetResource, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + barriers.push_back(Barrier::Transition(m_pCompositionMask->GetResource(), ResourceState::RenderTargetResource, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + ResourceBarrier(pCmdList, static_cast(barriers.size()), barriers.data()); + + if (m_MaskMode != FSR3MaskMode::Auto) + return; + + barriers.clear(); + barriers.push_back(Barrier::Transition(m_pColorTarget->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::CopySource)); + barriers.push_back(Barrier::Transition(m_pOpaqueTexture->GetResource(), ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, ResourceState::CopyDest)); + ResourceBarrier(pCmdList, static_cast(barriers.size()), barriers.data()); + + // Copy the color render target before we apply translucency + TextureCopyDesc copyColor = TextureCopyDesc(m_pColorTarget->GetResource(), m_pOpaqueTexture->GetResource()); + CopyTextureRegion(pCmdList, ©Color); + + barriers.clear(); + barriers.push_back(Barrier::Transition(m_pColorTarget->GetResource(), ResourceState::CopySource, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + barriers.push_back(Barrier::Transition(m_pOpaqueTexture->GetResource(), ResourceState::CopyDest, ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + ResourceBarrier(pCmdList, static_cast(barriers.size()), barriers.data()); + + // update intex for UI doublebuffering + UIRenderModule* uimod = static_cast(GetFramework()->GetRenderModule("UIRenderModule")); + m_curUiTextureIndex = (++m_curUiTextureIndex) & 1; + uimod->SetUiSurfaceIndex(m_curUiTextureIndex); +} + +void FSR3RenderModule::PostTransCallback(double deltaTime, cauldron::CommandList* pCmdList) +{ + if (m_MaskMode != FSR3MaskMode::Auto) + return; + + GPUScopedProfileCapture sampleMarker(pCmdList, L"Gen Reactive Mask (FSR3)"); + + FfxFsr3GenerateReactiveDescription generateReactiveParameters = {}; + generateReactiveParameters.commandList = ffxGetCommandList(pCmdList); + generateReactiveParameters.colorOpaqueOnly = ffxGetResource(m_pOpaqueTexture->GetResource(), L"FSR3_Input_Opaque_Color", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + generateReactiveParameters.colorPreUpscale = ffxGetResource(m_pColorTarget->GetResource(), L"FSR3_Input_PreUpscaleColor", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + generateReactiveParameters.outReactive = ffxGetResource(m_pReactiveMask->GetResource(), L"FSR3_InputReactiveMask", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + generateReactiveParameters.renderSize.width = resInfo.RenderWidth; + generateReactiveParameters.renderSize.height = resInfo.RenderHeight; + + generateReactiveParameters.scale = 1.f; + generateReactiveParameters.cutoffThreshold = 0.2f; + generateReactiveParameters.binaryValue = 0.9f; + generateReactiveParameters.flags = FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_TONEMAP | + FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_THRESHOLD | + FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_USE_COMPONENTS_MAX; + + FfxErrorCode errorCode = ffxFsr3ContextGenerateReactiveMask(&m_FSR3Context, &generateReactiveParameters); + FFX_ASSERT(errorCode == FFX_OK); + + // FidelityFX contexts modify the set resource view heaps, so set the cauldron one back + SetAllResourceViewHeaps(pCmdList); +} + + diff --git a/samples/fsr/fsr3rendermodule.h b/samples/fsr/fsr3rendermodule.h new file mode 100644 index 00000000..fa009171 --- /dev/null +++ b/samples/fsr/fsr3rendermodule.h @@ -0,0 +1,174 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "render/rendermodule.h" +#include "core/framework.h" +#include "core/uimanager.h" + +#include + +#include + +#include +#include + +namespace cauldron +{ + class Texture; + class ParameterSet; + class ResourceView; + class RootSignature; +} + +class FSR3RenderModule : public cauldron::RenderModule +{ +public: + FSR3RenderModule() : RenderModule(L"FSR3RenderModule") {} + virtual ~FSR3RenderModule(); + + void Init(const json& initData); + void EnableModule(bool enabled) override; + void Execute(double deltaTime, cauldron::CommandList* pCmdList) override; + void PreTransCallback(double deltaTime, cauldron::CommandList* pCmdList); + void PostTransCallback(double deltaTime, cauldron::CommandList* pCmdList); + void OnResize(const cauldron::ResolutionInfo& resInfo) override; + + bool m_NeedReInit = false; + +private: + + enum class FSR3ScalePreset + { + NativeAA = 0, // 1.0f + Quality, // 1.5f + Balanced, // 1.7f + Performance, // 2.f + UltraPerformance, // 3.f + Custom // 1.f - 3.f range + }; + + enum class FSR3MaskMode + { + Disabled = 0, + Manual, + Auto + }; + + const float cMipBias[static_cast(FSR3ScalePreset::Custom)] = { + std::log2f(1.f / 1.0f) - 1.f + std::numeric_limits::epsilon(), + std::log2f(1.f / 1.5f) - 1.f + std::numeric_limits::epsilon(), + std::log2f(1.f / 1.7f) - 1.f + std::numeric_limits::epsilon(), + std::log2f(1.f / 2.0f) - 1.f + std::numeric_limits::epsilon(), + std::log2f(1.f / 3.0f) - 1.f + std::numeric_limits::epsilon() + }; + + static void FfxMsgCallback(FfxMsgType type, const wchar_t* message); +#if defined(FFX_API_DX12) + static FfxErrorCode UiCompositionCallback(const FfxPresentCallbackDescription* params); +#endif + + void UpdatePreset(const int32_t* pOldPreset); + void UpdateUpscaleRatio(const float* pOldRatio); + void UpdateMipBias(const float* pOldBias); + + cauldron::ResolutionInfo UpdateResolution(uint32_t displayWidth, uint32_t displayHeight); + void UpdateFSR3Context(bool enabled); + + FSR3ScalePreset m_ScalePreset = FSR3ScalePreset::Quality; + float m_UpscaleRatio = 2.f; + float m_MipBias = cMipBias[static_cast(FSR3ScalePreset::Quality)]; + FSR3MaskMode m_MaskMode = FSR3MaskMode::Manual; + float m_Sharpness = 0.8f; + uint32_t m_JitterIndex = 0; + float m_JitterX = 0.f; + float m_JitterY = 0.f; + + bool m_UpscaleRatioEnabled = false; + bool m_UseMask = true; + bool m_RCASSharpen = true; + bool m_SharpnessEnabled = false; + +#if defined(FFX_API_DX12) + bool m_OfRebuildPipelines = false; + + bool m_FrameInterpolation = true; + bool m_EnableAsyncCompute = true; + bool m_AllowAsyncCompute = true; + bool m_PendingEnableAsyncCompute = true; + bool m_UseCallback = true; + bool m_DrawDebugTearLines = true; + bool m_DrawDebugView = false; + bool m_OfUiEnabled = true; +#endif + + bool m_bUseHLSLShaders = true; + + // FSR3 Context members + FfxFrameGenerationConfig m_FrameGenerationConfig{}; + FfxFsr3ContextDescription m_InitializationParameters = {}; + FfxFsr3Context m_FSR3Context; + +#if defined(FFX_API_DX12) + // DX swapchain descriptors for recreation of "real" swapchain + DXGI_SWAP_CHAIN_DESC gameSwapChainDesc; + DXGI_SWAP_CHAIN_DESC1 gameSwapChainDesc1; + DXGI_SWAP_CHAIN_FULLSCREEN_DESC gameFullscreenDesc; +#endif + + // For UI params + cauldron::UISection m_UISection; + + // FSR3 resources + const cauldron::Texture* m_pColorTarget = nullptr; + const cauldron::Texture* m_pDepthTarget = nullptr; + const cauldron::Texture* m_pMotionVectors = nullptr; + const cauldron::Texture* m_pReactiveMask = nullptr; + const cauldron::Texture* m_pCompositionMask = nullptr; + const cauldron::Texture* m_pOpaqueTexture = nullptr; + + // Raster views for reactive/composition masks + std::vector m_RasterViews = {}; + cauldron::ResourceView* m_pUiTargetResourceView = nullptr; + + // For resolution updates + std::function m_pUpdateFunc = nullptr; + + void BuildOpticalFlowUI(); + bool s_enableSoftwareMotionEstimation = true; + int32_t s_uiRenderMode = 2; + + // Surfaces for different UI render modes + uint32_t m_curUiTextureIndex = 0; + const cauldron::Texture* m_pUiTexture[2] = {}; + const cauldron::Texture* m_pHudLessTexture[2] = {}; + + typedef enum Fsr3BackendTypes : uint32_t + { + FSR3_BACKEND_SHARED_RESOURCES, + FSR3_BACKEND_UPSCALING, + FSR3_BACKEND_FRAME_INTERPOLATION, + FSR3_BACKEND_COUNT + } Fsr3BackendTypes; + bool ffxBackendInitialized_ = false; + FfxInterface ffxFsr3Backends_[FSR3_BACKEND_COUNT] = {}; +}; diff --git a/samples/fsr/fsr3upscalerendermodule.cpp b/samples/fsr/fsr3upscalerendermodule.cpp new file mode 100644 index 00000000..2da0183d --- /dev/null +++ b/samples/fsr/fsr3upscalerendermodule.cpp @@ -0,0 +1,489 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "fsr3upscalerendermodule.h" +#include "validation_remap.h" +#include "render/dynamicresourcepool.h" +#include "render/profiler.h" +#include "render/rasterview.h" +#include "render/uploadheap.h" +#include "core/scene.h" + +#include + +using namespace cauldron; + +void FSR3UpscaleRenderModule::Init(const json& initData) +{ + // Fetch needed resources + m_pColorTarget = GetFramework()->GetColorTargetForCallback(GetName()); + m_pDepthTarget = GetFramework()->GetRenderTexture(L"DepthTarget"); + + // Create render resolution opaque render target to use for auto-reactive mask generation + TextureDesc desc = m_pColorTarget->GetDesc(); + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + desc.Width = resInfo.RenderWidth; + desc.Height = resInfo.RenderHeight; + desc.Name = L"FSR3Upscale_OpaqueTexture"; + m_pOpaqueTexture = GetDynamicResourcePool()->CreateRenderTexture(&desc, [](TextureDesc& desc, uint32_t displayWidth, uint32_t displayHeight, uint32_t renderingWidth, uint32_t renderingHeight) + { + desc.Width = renderingWidth; + desc.Height = renderingHeight; + }); + + // Assumed resources, need to check they are there + m_pMotionVectors = GetFramework()->GetRenderTexture(L"GBufferMotionVectorRT"); + m_pReactiveMask = GetFramework()->GetRenderTexture(L"ReactiveMask"); + m_pCompositionMask = GetFramework()->GetRenderTexture(L"TransCompMask"); + CauldronAssert(ASSERT_CRITICAL, m_pMotionVectors && m_pReactiveMask && m_pCompositionMask, L"Could not get one of the needed resources for FSR3Upscale Rendermodule."); + + // Create raster views on the reactive mask and composition masks (for clearing and rendering) + m_RasterViews.resize(2); + m_RasterViews[0] = GetRasterViewAllocator()->RequestRasterView(m_pReactiveMask, ViewDimension::Texture2D); + m_RasterViews[1] = GetRasterViewAllocator()->RequestRasterView(m_pCompositionMask, ViewDimension::Texture2D); + + // Set our render resolution function as that to use during resize to get render width/height from display width/height + m_pUpdateFunc = [this](uint32_t displayWidth, uint32_t displayHeight) { return this->UpdateResolution(displayWidth, displayHeight); }; + + // UI + InitUI(); + + // Register additional execution callbacks during the frame + + // Register a post-lighting callback to copy opaque texture + ExecuteCallback callbackPreTrans = [this](double deltaTime, CommandList* pCmdList) { + this->PreTransCallback(deltaTime, pCmdList); + }; + ExecutionTuple callbackPreTransTuple = std::make_pair(L"FSR3UpscaleRenderModule::PreTransCallback", std::make_pair(this, callbackPreTrans)); + GetFramework()->RegisterExecutionCallback(L"LightingRenderModule", false, callbackPreTransTuple); + + // Register a post-transparency callback to generate reactive mask + ExecuteCallback callbackPostTrans = [this](double deltaTime, CommandList* pCmdList) { + this->PostTransCallback(deltaTime, pCmdList); + }; + ExecutionTuple callbackPostTransTuple = std::make_pair(L"FSR3UpscaleRenderModule::PostTransCallback", std::make_pair(this, callbackPostTrans)); + GetFramework()->RegisterExecutionCallback(L"TranslucencyRenderModule", false, callbackPostTransTuple); + + ////////////////////////////////////////////////////////////////////////// + // Finish up init + + // Start disabled as this will be enabled externally + SetModuleEnabled(false); + + // That's all we need for now + SetModuleReady(true); +} + +FSR3UpscaleRenderModule::~FSR3UpscaleRenderModule() +{ + // Protection + if (ModuleEnabled()) + EnableModule(false); // Destroy FSR context +} + +void FSR3UpscaleRenderModule::EnableModule(bool enabled) +{ + // If disabling the render module, we need to disable the upscaler with the framework + if (enabled) + { + // Setup everything needed when activating FSR + // Will also enable upscaling + UpdatePreset(nullptr); + + // Toggle this now so we avoid the context changes in OnResize + SetModuleEnabled(enabled); + + // Setup Cauldron FidelityFX interface. + const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_FSR3_CONTEXT_COUNT); + void* scratchBuffer = calloc(scratchBufferSize, 1); + memset(scratchBuffer, 0, scratchBufferSize); + FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterfaceUpscaling, GetDevice(), scratchBuffer, scratchBufferSize, FFX_FSR3_CONTEXT_COUNT); + CauldronAssert(ASSERT_CRITICAL, errorCode == FFX_OK, L"Could not initialize the FidelityFX SDK backend"); + + // Create the FSR3 context + UpdateFSR3Context(true); + + // Set the jitter callback to use + CameraJitterCallback jitterCallback = [this](Vec2& values) { + // Increment jitter index for frame + ++m_JitterIndex; + + // Update FSR3 jitter for built in TAA + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + const int32_t jitterPhaseCount = ffxFsr3GetJitterPhaseCount(resInfo.RenderWidth, resInfo.DisplayWidth); + ffxFsr3GetJitterOffset(&m_JitterX, &m_JitterY, m_JitterIndex, jitterPhaseCount); + + values = Vec2(-2.f * m_JitterX / resInfo.RenderWidth, 2.f * m_JitterY / resInfo.RenderHeight); + }; + CameraComponent::SetJitterCallbackFunc(jitterCallback); + + // ... and register UI elements for active upscaler + GetUIManager()->RegisterUIElements(m_UISection); + } + else + { + // Toggle this now so we avoid the context changes in OnResize + SetModuleEnabled(enabled); + + GetFramework()->EnableUpscaling(false); + + // Destroy the FSR3 context + UpdateFSR3Context(false); + + // Destroy the FidelityFX interface memory + free(m_InitializationParameters.backendInterfaceUpscaling.scratchBuffer); + + CameraComponent::SetJitterCallbackFunc(nullptr); + + // Deregister UI elements for inactive upscaler + GetUIManager()->UnRegisterUIElements(m_UISection); + } +} + +void FSR3UpscaleRenderModule::InitUI() +{ + // Build UI options, but don't register them yet. Registration/Deregistration will be controlled by enabling/disabling the render module + m_UISection.SectionName = "Upscaling"; // We will piggy-back on existing upscaling section" + m_UISection.SectionType = UISectionType::Sample; + + // Setup scale preset options + const char* preset[] = {"Native AA (1.0x)", "Quality (1.5x)", "Balanced (1.7x)", "Performance (2x)", "Ultra Performance (3x)", "Custom"}; + std::vector presetComboOptions; + presetComboOptions.assign(preset, preset + _countof(preset)); + std::function presetCallback = [this](void* pParams) { this->UpdatePreset(static_cast(pParams)); }; + m_UISection.AddCombo("Scale Preset", reinterpret_cast(&m_ScalePreset), &presetComboOptions, presetCallback); + + // Setup mip bias + std::function mipBiasCallback = [this](void* pParams) { this->UpdateMipBias(static_cast(pParams)); }; + m_UISection.AddFloatSlider("Mip LOD Bias", &m_MipBias, -5.f, 0.f, mipBiasCallback); + + // Setup scale factor (disabled for all but custom) + std::function ratioCallback = [this](void* pParams) { this->UpdateUpscaleRatio(static_cast(pParams)); }; + m_UISection.AddFloatSlider("Custom Scale", &m_UpscaleRatio, 1.f, 3.f, ratioCallback, &m_UpscaleRatioEnabled); + + // Reactive mask + const char* masks[] = { "Disabled", "Manual Reactive Mask Generation", "Autogen FSR3 Helper Function" }; + std::vector maskComboOptions; + maskComboOptions.assign(masks, masks + _countof(masks)); + m_UISection.AddCombo("Reactive Mask Mode", reinterpret_cast(&m_MaskMode), &maskComboOptions); + + // Use mask + m_UISection.AddCheckBox("Use Transparency and Composition Mask", &m_UseMask); + + // Sharpening + m_UISection.AddCheckBox("RCAS Sharpening", &m_RCASSharpen); + m_UISection.AddFloatSlider("Sharpness", &m_Sharpness, 0.f, 1.f, nullptr, &m_RCASSharpen); +} + +void FSR3UpscaleRenderModule::UpdatePreset(const int32_t* pOldPreset) +{ + switch (m_ScalePreset) + { + case FSR3ScalePreset::NativeAA: + m_UpscaleRatio = 1.0f; + break; + case FSR3ScalePreset::Quality: + m_UpscaleRatio = 1.5f; + break; + case FSR3ScalePreset::Balanced: + m_UpscaleRatio = 1.7f; + break; + case FSR3ScalePreset::Performance: + m_UpscaleRatio = 2.0f; + break; + case FSR3ScalePreset::UltraPerformance: + m_UpscaleRatio = 3.0f; + break; + case FSR3ScalePreset::Custom: + default: + // Leave the upscale ratio at whatever it was + break; + } + + // Update whether we can update the custom scale slider + m_UpscaleRatioEnabled = (m_ScalePreset == FSR3ScalePreset::Custom); + + // Update mip bias + float oldValue = m_MipBias; + if (m_ScalePreset != FSR3ScalePreset::Custom) + m_MipBias = cMipBias[static_cast(m_ScalePreset)]; + else + m_MipBias = CalculateMipBias(m_UpscaleRatio); + UpdateMipBias(&oldValue); + + // Update resolution since rendering ratios have changed + GetFramework()->EnableUpscaling(true, m_pUpdateFunc); +} + +void FSR3UpscaleRenderModule::UpdateUpscaleRatio(const float* pOldRatio) +{ + // Disable/Enable FSR3 upscaler since resolution ratios have changed + GetFramework()->EnableUpscaling(true, m_pUpdateFunc); +} + +void FSR3UpscaleRenderModule::UpdateMipBias(const float* pOldBias) +{ + // Update the scene MipLODBias to use + GetScene()->SetMipLODBias(m_MipBias); +} + +void FSR3UpscaleRenderModule::FfxMsgCallback(FfxMsgType type, const wchar_t* message) +{ + if (type == FFX_MESSAGE_TYPE_ERROR) + { + CauldronWarning(L"FSR3_API_DEBUG_ERROR: %ls", message); + } + else if (type == FFX_MESSAGE_TYPE_WARNING) + { + CauldronWarning(L"FSR3_API_DEBUG_WARNING: %ls", message); + } +} + +void FSR3UpscaleRenderModule::UpdateFSR3Context(bool enabled) +{ + if (enabled) + { + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + m_InitializationParameters.maxRenderSize.width = resInfo.RenderWidth; + m_InitializationParameters.maxRenderSize.height = resInfo.RenderHeight; + m_InitializationParameters.upscaleOutputSize.width = resInfo.DisplayWidth; + m_InitializationParameters.upscaleOutputSize.height = resInfo.DisplayHeight; + m_InitializationParameters.displaySize.width = resInfo.DisplayWidth; + m_InitializationParameters.displaySize.height = resInfo.DisplayHeight; + + // Enable auto-exposure by default + m_InitializationParameters.flags = FFX_FSR3_ENABLE_AUTO_EXPOSURE; + + // initialize FSR3 for upscaling only + m_InitializationParameters.flags |= FFX_FSR3_ENABLE_UPSCALING_ONLY; + + // Note, inverted depth and display mode are currently handled statically for the run of the sample. + // If they become changeable at runtime, we'll need to modify how this information is queried + static bool s_InvertedDepth = GetConfig()->InvertedDepth; + + // Setup inverted depth flag according to sample usage + if (s_InvertedDepth) + m_InitializationParameters.flags |= FFX_FSR3_ENABLE_DEPTH_INVERTED | FFX_FSR3_ENABLE_DEPTH_INFINITE; + + // Input data is HDR + m_InitializationParameters.flags |= FFX_FSR3_ENABLE_HIGH_DYNAMIC_RANGE; + + // Do eror checking in debug + #if defined(_DEBUG) + m_InitializationParameters.flags |= FFX_FSR3_ENABLE_DEBUG_CHECKING; + m_InitializationParameters.fpMessage = &FSR3UpscaleRenderModule::FfxMsgCallback; + #endif // #if defined(_DEBUG) + + // Create the FSR3 context + FfxErrorCode errorCode = ffxFsr3ContextCreate(&m_FSR3Context, &m_InitializationParameters); + CauldronAssert(ASSERT_CRITICAL, errorCode == FFX_OK, L"Couldn't create the FidelityFX SDK FSR3 context."); + } + + else + { + // Destroy the FSR3 context + ffxFsr3ContextDestroy(&m_FSR3Context); + } +} + +ResolutionInfo FSR3UpscaleRenderModule::UpdateResolution(uint32_t displayWidth, uint32_t displayHeight) +{ + return { static_cast((float)displayWidth / m_UpscaleRatio), + static_cast((float)displayHeight / m_UpscaleRatio), + displayWidth, displayHeight }; +} + +void FSR3UpscaleRenderModule::OnResize(const ResolutionInfo& resInfo) +{ + if (!ModuleEnabled()) + return; + + // Need to recreate the FSR3 context on resource resize + UpdateFSR3Context(false); // Destroy + UpdateFSR3Context(true); // Re-create + + // Rest jitter index + m_JitterIndex = 0; +} + +void FSR3UpscaleRenderModule::Execute(double deltaTime, CommandList* pCmdList) +{ + GPUScopedProfileCapture sampleMarker(pCmdList, L"FFX FSR3"); + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + CameraComponent* pCamera = GetScene()->GetCurrentCamera(); + + // All cauldron resources come into a render module in a generic read state (ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource) + FfxFsr3DispatchUpscaleDescription dispatchParameters = {}; + dispatchParameters.commandList = ffxGetCommandList(pCmdList); + dispatchParameters.color = ffxGetResource(m_pColorTarget->GetResource(), L"FSR3_Input_OutputColor", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchParameters.depth = ffxGetResource(m_pDepthTarget->GetResource(), L"FSR3_InputDepth", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchParameters.motionVectors = ffxGetResource(m_pMotionVectors->GetResource(), L"FSR3_InputMotionVectors", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchParameters.exposure = ffxGetResource(nullptr, L"FSR3_InputExposure", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchParameters.upscaleOutput = dispatchParameters.color; + + if (m_MaskMode != FSR3MaskMode::Disabled) + { + dispatchParameters.reactive = ffxGetResource(m_pReactiveMask->GetResource(), L"FSR3_InputReactiveMap", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + } + else + { + dispatchParameters.reactive = ffxGetResource(nullptr, L"FSR3_EmptyInputReactiveMap", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + } + + if (m_UseMask) + { + dispatchParameters.transparencyAndComposition = ffxGetResource(m_pCompositionMask->GetResource(), L"FSR3_TransparencyAndCompositionMap", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + } + else + { + dispatchParameters.transparencyAndComposition = ffxGetResource(nullptr, L"FSR3_EmptyTransparencyAndCompositionMap", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + } + + // Jitter is calculated earlier in the frame using a callback from the camera update + dispatchParameters.jitterOffset.x = -m_JitterX; + dispatchParameters.jitterOffset.y = -m_JitterY; + dispatchParameters.motionVectorScale.x = resInfo.fRenderWidth(); + dispatchParameters.motionVectorScale.y = resInfo.fRenderHeight(); + dispatchParameters.reset = false; + dispatchParameters.enableSharpening = m_RCASSharpen; + dispatchParameters.sharpness = m_Sharpness; + + // Cauldron keeps time in seconds, but FSR expects miliseconds + dispatchParameters.frameTimeDelta = static_cast(deltaTime * 1000.f); + + dispatchParameters.preExposure = GetScene()->GetSceneExposure(); + dispatchParameters.renderSize.width = resInfo.RenderWidth; + dispatchParameters.renderSize.height = resInfo.RenderHeight; + + // Note, inverted depth and display mode are currently handled statically for the run of the sample. + // If they become changeable at runtime, we'll need to modify how this information is queried + static bool s_InvertedDepth = GetConfig()->InvertedDepth; + + // Setup camera params as required + dispatchParameters.cameraFovAngleVertical = pCamera->GetFovY(); + if (s_InvertedDepth) + { + dispatchParameters.cameraFar = pCamera->GetNearPlane(); + dispatchParameters.cameraNear = FLT_MAX; + } + else + { + dispatchParameters.cameraFar = pCamera->GetFarPlane(); + dispatchParameters.cameraNear = pCamera->GetNearPlane(); + } + + FfxErrorCode errorCode = ffxFsr3ContextDispatchUpscale(&m_FSR3Context, &dispatchParameters); + FFX_ASSERT(errorCode == FFX_OK); + + // FidelityFX contexts modify the set resource view heaps, so set the cauldron one back + SetAllResourceViewHeaps(pCmdList); + + // We are now done with upscaling + GetFramework()->SetUpscalingState(UpscalerState::PostUpscale); +} + +void FSR3UpscaleRenderModule::PreTransCallback(double deltaTime, cauldron::CommandList* pCmdList) +{ + GPUScopedProfileCapture sampleMarker(pCmdList, L"Pre-Trans (FSR3)"); + + std::vector barriers; + barriers.push_back(Barrier::Transition(m_pReactiveMask->GetResource(), + ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, + ResourceState::RenderTargetResource)); + barriers.push_back(Barrier::Transition(m_pCompositionMask->GetResource(), + ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, + ResourceState::RenderTargetResource)); + ResourceBarrier(pCmdList, static_cast(barriers.size()), barriers.data()); + + // We need to clear the reactive and composition masks before any translucencies are rendered into them + float clearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + ClearRenderTarget(pCmdList, &m_RasterViews[0]->GetResourceView(), clearColor); + ClearRenderTarget(pCmdList, &m_RasterViews[1]->GetResourceView(), clearColor); + + barriers.clear(); + barriers.push_back(Barrier::Transition(m_pReactiveMask->GetResource(), + ResourceState::RenderTargetResource, + ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + barriers.push_back(Barrier::Transition(m_pCompositionMask->GetResource(), + ResourceState::RenderTargetResource, + ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + ResourceBarrier(pCmdList, static_cast(barriers.size()), barriers.data()); + + if (m_MaskMode != FSR3MaskMode::Auto) + return; + + + // Copy the color render target before we apply translucency + { + barriers.clear(); + barriers.push_back(Barrier::Transition(m_pColorTarget->GetResource(), + ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, + ResourceState::CopySource)); + barriers.push_back(Barrier::Transition(m_pOpaqueTexture->GetResource(), + ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource, + ResourceState::CopyDest)); + ResourceBarrier(pCmdList, static_cast(barriers.size()), barriers.data()); + + TextureCopyDesc copyColor = TextureCopyDesc(m_pColorTarget->GetResource(), m_pOpaqueTexture->GetResource()); + CopyTextureRegion(pCmdList, ©Color); + } + + barriers.clear(); + barriers.push_back(Barrier::Transition(m_pColorTarget->GetResource(), + ResourceState::CopySource, + ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + barriers.push_back(Barrier::Transition(m_pOpaqueTexture->GetResource(), + ResourceState::CopyDest, + ResourceState::NonPixelShaderResource | ResourceState::PixelShaderResource)); + ResourceBarrier(pCmdList, static_cast(barriers.size()), barriers.data()); +} + +void FSR3UpscaleRenderModule::PostTransCallback(double deltaTime, cauldron::CommandList* pCmdList) +{ + if (m_MaskMode != FSR3MaskMode::Auto) + return; + + GPUScopedProfileCapture sampleMarker(pCmdList, L"Gen Reactive Mask (FSR3)"); + + FfxFsr3GenerateReactiveDescription generateReactiveParameters = {}; + generateReactiveParameters.commandList = ffxGetCommandList(pCmdList); + generateReactiveParameters.colorOpaqueOnly = ffxGetResource(m_pOpaqueTexture->GetResource(), L"FSR3_Input_Opaque_Color", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + generateReactiveParameters.colorPreUpscale = ffxGetResource(m_pColorTarget->GetResource(), L"FSR3_Input_PreUpscaleColor", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + generateReactiveParameters.outReactive = ffxGetResource(m_pReactiveMask->GetResource(), L"FSR3_InputReactiveMask", FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ); + + const ResolutionInfo& resInfo = GetFramework()->GetResolutionInfo(); + generateReactiveParameters.renderSize.width = resInfo.RenderWidth; + generateReactiveParameters.renderSize.height = resInfo.RenderHeight; + + generateReactiveParameters.scale = 1.f; + generateReactiveParameters.cutoffThreshold = 0.2f; + generateReactiveParameters.binaryValue = 0.9f; + generateReactiveParameters.flags = FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_TONEMAP | + FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_THRESHOLD | + FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_USE_COMPONENTS_MAX; + + FfxErrorCode errorCode = ffxFsr3ContextGenerateReactiveMask(&m_FSR3Context, &generateReactiveParameters); + FFX_ASSERT(errorCode == FFX_OK); + + // FidelityFX contexts modify the set resource view heaps, so set the cauldron one back + SetAllResourceViewHeaps(pCmdList); +} diff --git a/samples/fsr/fsr3upscalerendermodule.h b/samples/fsr/fsr3upscalerendermodule.h new file mode 100644 index 00000000..0cfd707a --- /dev/null +++ b/samples/fsr/fsr3upscalerendermodule.h @@ -0,0 +1,170 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "render/rendermodule.h" +#include "core/framework.h" +#include "core/uimanager.h" + +#include + +#include + +namespace cauldron +{ + class Texture; +} // namespace cauldron + +/// @defgroup FfxFsrSample FidelityFX Super Resolution Sample +/// Sample documentation for FidelityFX Super Resolution +/// +/// @ingroup SDKEffects + +/// @defgroup FSR3UpscaleRM FSR3UpscaleRenderModule +/// FSR3UpscaleRenderModule Reference Documentation +/// +/// @ingroup FfxFsrSample +/// @{ + +/** + * @class FSR3UpscaleRenderModule + * + * FSR3UpscaleRenderModule takes care of: + * - creating UI section that enable users to select upscaling options + * - creating GPU resources + * - clearing and/or generating the reactivity masks + * - dispatch workloads for upscaling using FSR 3 + */ +class FSR3UpscaleRenderModule : public cauldron::RenderModule +{ +public: + /** + * @brief Constructor with default behavior. + */ + FSR3UpscaleRenderModule() : RenderModule(L"FSR3UpscaleRenderModule") {} + + /** + * @brief Tear down the FSR 3 API Context and release resources. + */ + virtual ~FSR3UpscaleRenderModule(); + + /** + * @brief Initialize FSR 3 API Context, create resources, and setup UI section for FSR 3 Upscale. + */ + void Init(const json& initData); + + /** + * @brief If render module is enabled, initialize the FSR 3 API Context. If disabled, destroy the FSR 3 API Context. + */ + void EnableModule(bool enabled) override; + + /** + * @brief Setup parameters that the FSR 3 API needs this frame and then call the FFX Dispatch. + */ + void Execute(double deltaTime, cauldron::CommandList* pCmdList) override; + + /** + * @brief Recreate the FSR 3 API Context to resize internal resources. Called by the framework when the resolution changes. + */ + void OnResize(const cauldron::ResolutionInfo& resInfo) override; + +private: + + // Enum representing the FSR 3 quality modes. + enum class FSR3ScalePreset + { + NativeAA = 0, // 1.0f + Quality, // 1.5f + Balanced, // 1.7f + Performance, // 2.f + UltraPerformance, // 3.f + Custom // 1.f - 3.f range + }; + + // Enum representing the reactivity mask modes. + enum class FSR3MaskMode + { + Disabled = 0, + Manual, + Auto + }; + + // LUT of mip bias values corresponding to each FSR3ScalePreset value. + const float cMipBias[static_cast(FSR3ScalePreset::Custom)] = + { + CalculateMipBias(1.0f), + CalculateMipBias(1.5f), + CalculateMipBias(1.7f), + CalculateMipBias(2.0f), + CalculateMipBias(3.0f) + }; + + static void FfxMsgCallback(FfxMsgType type, const wchar_t* message); + + void InitUI(); + void UpdatePreset(const int32_t* pOldPreset); + void UpdateUpscaleRatio(const float* pOldRatio); + void UpdateMipBias(const float* pOldBias); + + cauldron::ResolutionInfo UpdateResolution(uint32_t displayWidth, uint32_t displayHeight); + void UpdateFSR3Context(bool enabled); + + void PreTransCallback(double deltaTime, cauldron::CommandList* pCmdList); + void PostTransCallback(double deltaTime, cauldron::CommandList* pCmdList); + + FSR3ScalePreset m_ScalePreset = FSR3ScalePreset::Quality; + float m_UpscaleRatio = 2.f; + float m_MipBias = cMipBias[static_cast(FSR3ScalePreset::Quality)]; + FSR3MaskMode m_MaskMode = FSR3MaskMode::Manual; + float m_Sharpness = 0.8f; + uint32_t m_JitterIndex = 0; + float m_JitterX = 0.f; + float m_JitterY = 0.f; + + bool m_UpscaleRatioEnabled = false; + bool m_UseMask = true; + bool m_RCASSharpen = true; + + // FidelityFX Super Resolution 3 information + FfxFsr3ContextDescription m_InitializationParameters = {}; + FfxFsr3Context m_FSR3Context; + + // For UI params + cauldron::UISection m_UISection; + + // FidelityFX Super Resolution 3 resources + const cauldron::Texture* m_pColorTarget = nullptr; + const cauldron::Texture* m_pDepthTarget = nullptr; + const cauldron::Texture* m_pMotionVectors = nullptr; + const cauldron::Texture* m_pReactiveMask = nullptr; + const cauldron::Texture* m_pCompositionMask = nullptr; + const cauldron::Texture* m_pOpaqueTexture = nullptr; + + // Raster views for reactive/composition masks + std::vector m_RasterViews = {}; + + // For resolution updates + std::function m_pUpdateFunc = nullptr; + +/// @} +}; diff --git a/samples/fsr/fsrsample.cpp b/samples/fsr/fsrsample.cpp index 780e2383..9bb16997 100644 --- a/samples/fsr/fsrsample.cpp +++ b/samples/fsr/fsrsample.cpp @@ -1,27 +1,29 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "fsrsample.h" #include "fsr2rendermodule.h" +#include "fsr3upscalerendermodule.h" +#include "fsr3rendermodule.h" #include "upscalerendermodule.h" #include "fsr1rendermodule.h" #include "upscalerendermodule.h" @@ -29,9 +31,11 @@ #include "rendermoduleregistry.h" #include "taa/taarendermodule.h" #include "translucency/translucencyrendermodule.h" +#include "render/rendermodules/ui/uirendermodule.h" #include "misc/fileio.h" #include "render/device.h" +#include "misc/assert.h" using namespace cauldron; @@ -61,6 +65,8 @@ void FSRSample::RegisterSampleModules() rendermodule::RegisterAvailableRenderModules(); // Register sample render modules + RenderModuleFactory::RegisterModule("FSR3RenderModule"); + RenderModuleFactory::RegisterModule("FSR3UpscaleRenderModule"); RenderModuleFactory::RegisterModule("FSR2RenderModule"); RenderModuleFactory::RegisterModule("FSR1RenderModule"); RenderModuleFactory::RegisterModule("UpscaleRenderModule"); @@ -71,12 +77,18 @@ int32_t FSRSample::DoSampleInit() { // Store pointers to various render modules m_pFSR2RenderModule = static_cast(GetFramework()->GetRenderModule("FSR2RenderModule")); + m_pFSR3UpscaleRenderModule = static_cast(GetFramework()->GetRenderModule("FSR3UpscaleRenderModule")); + m_pFSR3RenderModule = static_cast(GetFramework()->GetRenderModule("FSR3RenderModule")); m_pFSR1RenderModule = static_cast(GetFramework()->GetRenderModule("FSR1RenderModule")); m_pUpscaleRenderModule = static_cast(GetFramework()->GetRenderModule("UpscaleRenderModule")); m_pTAARenderModule = static_cast(GetFramework()->GetRenderModule("TAARenderModule")); m_pTransRenderModule = static_cast(GetFramework()->GetRenderModule("TranslucencyRenderModule")); + m_pTAARenderModule->EnableModule(false); + + CauldronAssert(ASSERT_CRITICAL, m_pFSR3RenderModule, L"FidelityFX FSR Sample: Error: Could not find FSR3 render module."); + CauldronAssert(ASSERT_CRITICAL, m_pFSR3UpscaleRenderModule, L"FidelityFX FSR Sample: Error: Could not find FSR3Upscale render module."); CauldronAssert(ASSERT_CRITICAL, m_pFSR2RenderModule, L"FidelityFX FSR Sample: Error: Could not find FSR2 render module."); CauldronAssert(ASSERT_CRITICAL, m_pFSR1RenderModule, L"FidelityFX FSR Sample: Error: Could not find FSR1 render module."); CauldronAssert(ASSERT_CRITICAL, m_pUpscaleRenderModule, L"FidelityFX FSR Sample: Error: Could not find upscale render module."); @@ -97,13 +109,31 @@ int32_t FSRSample::DoSampleInit() // Add additional exports for FSR to translucency pass m_pTransRenderModule->AddOptionalTransparencyOptions(transOptions); + // Set all other UI sections to collapse by default + for (auto& section : GetUIManager()->GetGeneralLayout()) + if (section.SectionName != "FPS Limiter") + section.defaultOpen = false; + // Register upscale method picker picker UISection uiSection; uiSection.SectionName = "Upscaling"; uiSection.SectionType = UISectionType::Sample; +#ifdef FFX_API_DX12 + // Setup upscale method options + const char* upscalers[] = {"Native", "Point", "Bilinear", "Bicubic", "FSR1", "FSR2", "FSR3Upscale", "FSR3"}; + std::vector comboOptions; + comboOptions.assign(upscalers, upscalers + _countof(upscalers)); + + // Add the section header + uiSection.AddCombo("Method", reinterpret_cast(&m_UIMethod), &comboOptions); + GetUIManager()->RegisterUIElements(uiSection); + + // Setup FSR3 as the default upscaler + m_UIMethod = UpscaleMethod::FSR3; +#else // Setup upscale method options - const char* upscalers[] = { "Native", "Point", "Bilinear", "Bicubic", "FSR1", "FSR2" }; + const char* upscalers[] = {"Native", "Point", "Bilinear", "Bicubic", "FSR1", "FSR2"}; std::vector comboOptions; comboOptions.assign(upscalers, upscalers + _countof(upscalers)); @@ -113,7 +143,9 @@ int32_t FSRSample::DoSampleInit() // Setup the default upscaler (FSR2 for now) m_UIMethod = UpscaleMethod::FSR2; +#endif SwitchUpscaler(m_UIMethod); + # return 0; } @@ -122,14 +154,19 @@ void FSRSample::SwitchUpscaler(UpscaleMethod newUpscaler) // Flush everything out of the pipe before disabling/enabling things GetDevice()->FlushAllCommandQueues(); + UpscaleMethod oldUpscaler = m_Method; m_Method = newUpscaler; // If we are switching methods, handle it now RenderModule* pOldUpscaler = m_pCurrentUpscaler; + + // Disable the old upscaler + if (pOldUpscaler) + pOldUpscaler->EnableModule(false); - // If old upscaler was FSR2, re-enable TAA render module as FSR2 disables it - if (pOldUpscaler == m_pFSR2RenderModule) - m_pTAARenderModule->EnableModule(true); + // Render UI to separate target for FSR3 + UIRenderModule* uimod = static_cast(GetFramework()->GetRenderModule("UIRenderModule")); + uimod->SetAsyncRender(m_Method == UpscaleMethod::FSR3); switch (m_Method) { @@ -148,18 +185,19 @@ void FSRSample::SwitchUpscaler(UpscaleMethod newUpscaler) break; case UpscaleMethod::FSR2: m_pCurrentUpscaler = m_pFSR2RenderModule; - // Also disable TAA render module - m_pTAARenderModule->EnableModule(false); + break; + case UpscaleMethod::FSR3UPSCALEONLY: + m_pCurrentUpscaler = m_pFSR3UpscaleRenderModule; + break; + case UpscaleMethod::FSR3: + m_pCurrentUpscaler = m_pFSR3RenderModule; + m_pFSR3RenderModule->m_NeedReInit = false; break; default: CauldronCritical(L"Unsupported upscaler requested."); break; } - // Disable the old upscaler - if (pOldUpscaler) - pOldUpscaler->EnableModule(false); - // Enable the new one if (m_pCurrentUpscaler) m_pCurrentUpscaler->EnableModule(true); @@ -169,7 +207,7 @@ void FSRSample::DoSampleUpdates(double deltaTime) { // Upscaler changes need to be done before the rest of the frame starts executing // as it relies on the upscale method being set for the frame and whatnot - if (m_UIMethod != m_Method) + if (m_UIMethod != m_Method || m_pFSR3RenderModule->m_NeedReInit) { m_Method = m_UIMethod; SwitchUpscaler(m_UIMethod); diff --git a/samples/fsr/fsrsample.h b/samples/fsr/fsrsample.h index 0129ac15..b83187ca 100644 --- a/samples/fsr/fsrsample.h +++ b/samples/fsr/fsrsample.h @@ -1,29 +1,31 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "core/framework.h" +class FSR3RenderModule; +class FSR3UpscaleRenderModule; class FSR2RenderModule; class FSR1RenderModule; class UpscaleRenderModule; @@ -76,6 +78,8 @@ class FSRSample : public cauldron::Framework Bicubic, FSR1, FSR2, + FSR3UPSCALEONLY, + FSR3, Count }; @@ -86,10 +90,12 @@ class FSRSample : public cauldron::Framework UpscaleMethod m_UIMethod = UpscaleMethod::Native; cauldron::RenderModule* m_pCurrentUpscaler = nullptr; - FSR2RenderModule* m_pFSR2RenderModule = nullptr; - FSR1RenderModule* m_pFSR1RenderModule = nullptr; - UpscaleRenderModule* m_pUpscaleRenderModule = nullptr; - TAARenderModule* m_pTAARenderModule = nullptr; + FSR3RenderModule* m_pFSR3RenderModule = nullptr; + FSR3UpscaleRenderModule* m_pFSR3UpscaleRenderModule = nullptr; + FSR2RenderModule* m_pFSR2RenderModule = nullptr; + FSR1RenderModule* m_pFSR1RenderModule = nullptr; + UpscaleRenderModule* m_pUpscaleRenderModule = nullptr; + TAARenderModule* m_pTAARenderModule = nullptr; TranslucencyRenderModule* m_pTransRenderModule = nullptr; /// @} diff --git a/samples/fsr/media/checkerboard.dds b/samples/fsr/media/checkerboard.dds new file mode 100644 index 0000000000000000000000000000000000000000..f1a6e7f6bfabac3015a8e9ad278a27174608fcfd GIT binary patch literal 87508 zcmeH~L2eUK6a>Gr%8nc%M*%4};5ta=<|acZ$r_|F_$^9~DM zwZ6POt)K6@eXghNr?s9x6% zrEdE6Z*j*r{%!+su+&Z8{w?nK#@}rK4wky<+rPyf-}t)?z`;^Cefzh#;~Rgs0XSId zrf>ficYNdTHUI}p-Sq9>;*M|p-3H)bshht2Tio%DzuN#DEOpbje~UZ5HhDxaXERDb0 zfW;kOH+}nugQf9z8?d!xr2aIiG~ZUYu~eBJcz9}bqr-)+F+j<1`({lmf1_`3~Q z-0^kOw|_WT8h^I|i#xt<`t}b8OXKf0U~$LSP2c|EU}^l_1}yIQy6M|L94w8$+knL# zUpIaGhl8c@cN?&{-7#@}tg;*PJI-rqkxSo-Mwm)~u` zI`{ax>HX(V`P~LMhnBkOJO37UeB6%rEdE6Z*j*r{%!+su+&Z8{w?nK#@}rK4wky<+rPyf-}t)?z`;^C zefzh#;~Rgs0XSIdrf>ficYNdTHUI}p-Sq9>;*M|p-3H)bshht2Tio%DzuN#DEOpbj ze~UZ5@pl`5gQafz_HS{=H~ww|aIn-(-~KJ`_{QID01lSA>Dzz(yA4>o!`DsU{@`F~ z{M`mD?)bXt+dmvEjlbJ~#T{Qaefx)lrSW$gu(;#vrf>gnur&T|0~U9D-Sq7r4wlB> zZNTD=ubaO8!@<({yA4>}@paR;e>hkgf42dPJHBrE_74Y3DxaXERDb0fW;kOH+}nugQf9z8?d!xr2aIiG~ZUYu~eBJcz9}bqr-)+F+ zj<1`({lmf1_`3~Q-0^kOw|_WT8h^I|i#xt<`t}cpd)4XrndZ)a)z$Kk{#XlQYoyn>8@$zWw+7o1MPy|Mu7YH#r0CZ`#1@{S$WGpWUCc)7Smk z{<=RWXQ2Jf8klt7{n!0BJAK`M?XUZ9at7Mptbs}Q-GBc57r&mLlQS@Tdi3v?N%uWJ z{pV-rf7U?fzx!u$24<(P`)AU9_fPjv`|GoWn|4q(7`Aw4~`)_vo=J(&V^Ly>@*ZYs}pZYs) zp!4INpJO`LpD(@txPi{Md%o-cxc~Y&?&o;jJs&$i_kDgk-^UGfzVG{d$M2ZmzMuUX zKKt)KTHZa+{r8X7$D`%l^X7Yc_}}kueIGvPt$)s~@56V~?E}61n%7+Z+U3{V@1IVm HzdnBf@>Y`w literal 0 HcmV?d00001 diff --git a/samples/fsr/media/composition_text.dds b/samples/fsr/media/composition_text.dds new file mode 100644 index 0000000000000000000000000000000000000000..4baf836ead10f96cf7e88b5e87f2d5022ae41bf9 GIT binary patch literal 1398144 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 z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHaf zKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_ z009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_< z0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHaf zKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_ z009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_< z0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHaf zKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_ z009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_< z0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV= 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 DhLItp literal 0 HcmV?d00001 diff --git a/samples/fsr/media/lion.jpg b/samples/fsr/media/lion.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e830649607218b436e955f5cf23b180628219259 GIT binary patch literal 357550 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 z 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≶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 BackbufferImg : register(t0); + +float4 BlitPS(float4 pos: SV_POSITION) : SV_Target +{ + return BackbufferImg[pos.xy]; +} + diff --git a/samples/fsr/shaders/upscalecommon.h b/samples/fsr/shaders/upscalecommon.h index 0c1ddf8d..07165415 100644 --- a/samples/fsr/shaders/upscalecommon.h +++ b/samples/fsr/shaders/upscalecommon.h @@ -1,22 +1,25 @@ -// AMD Cauldron code -// -// Copyright(c) 2023 Advanced Micro Devices, Inc.All rights reserved. +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +// 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 +// 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 : +// 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 +// 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 __cplusplus #pragma once #endif // __cplusplus diff --git a/samples/fsr/shaders/upscalecs.hlsl b/samples/fsr/shaders/upscalecs.hlsl index 8f3bbfe6..c7ce3eba 100644 --- a/samples/fsr/shaders/upscalecs.hlsl +++ b/samples/fsr/shaders/upscalecs.hlsl @@ -1,22 +1,25 @@ -// AMD Cauldron code -// -// Copyright(c) 2023 Advanced Micro Devices, Inc.All rights reserved. +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +// 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 +// 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 : +// 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 +// 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 "upscalecommon.h" //-------------------------------------------------------------------------------------- diff --git a/samples/fsr/upscalerendermodule.cpp b/samples/fsr/upscalerendermodule.cpp index 4eefab21..43c6a20d 100644 --- a/samples/fsr/upscalerendermodule.cpp +++ b/samples/fsr/upscalerendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "upscalerendermodule.h" #include diff --git a/samples/fsr/upscalerendermodule.h b/samples/fsr/upscalerendermodule.h index 5f2d0b45..b78a01ce 100644 --- a/samples/fsr/upscalerendermodule.h +++ b/samples/fsr/upscalerendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "render/rendermodule.h" diff --git a/samples/hybridreflections/CMakeLists.txt b/samples/hybridreflections/CMakeLists.txt index 5d99e0d9..ddf3eda5 100644 --- a/samples/hybridreflections/CMakeLists.txt +++ b/samples/hybridreflections/CMakeLists.txt @@ -1,3 +1,24 @@ +# This file is part of the FidelityFX SDK. +# +# Copyright (c) 2023 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. + # Declare project if (FFX_API STREQUAL CAULDRON) project(FFX_HYBRIDREFLECTIONS) diff --git a/samples/hybridreflections/hybridreflectionsrendermodule.cpp b/samples/hybridreflections/hybridreflectionsrendermodule.cpp index 32d8302d..1e93a260 100644 --- a/samples/hybridreflections/hybridreflectionsrendermodule.cpp +++ b/samples/hybridreflections/hybridreflectionsrendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "shaders/surfacerendercommon.h" #include "hybridreflectionsrendermodule.h" @@ -130,7 +130,7 @@ void HybridReflectionsRenderModule::Init(const json& initData) // Initialize the FFX backend const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_HYBRID_REFLECTIONS_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_BackendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_HYBRID_REFLECTIONS_CONTEXT_COUNT); FFX_ASSERT(errorCode == FFX_OK); diff --git a/samples/hybridreflections/hybridreflectionsrendermodule.h b/samples/hybridreflections/hybridreflectionsrendermodule.h index bd51813c..3b27bffa 100644 --- a/samples/hybridreflections/hybridreflectionsrendermodule.h +++ b/samples/hybridreflections/hybridreflectionsrendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "core/contentmanager.h" diff --git a/samples/hybridreflections/shaders/Common.hlsl b/samples/hybridreflections/shaders/Common.hlsl index e65101b8..3e461339 100644 --- a/samples/hybridreflections/shaders/Common.hlsl +++ b/samples/hybridreflections/shaders/Common.hlsl @@ -1,24 +1,24 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "commonintersect.hlsl" diff --git a/samples/hybridreflections/shaders/Declarations.h b/samples/hybridreflections/shaders/Declarations.h index b693e2bb..74377186 100644 --- a/samples/hybridreflections/shaders/Declarations.h +++ b/samples/hybridreflections/shaders/Declarations.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 DECLARATIONS_H #define DECLARATIONS_H diff --git a/samples/hybridreflections/shaders/Intersect.hlsl b/samples/hybridreflections/shaders/Intersect.hlsl index 4fd6f2bc..a8540864 100644 --- a/samples/hybridreflections/shaders/Intersect.hlsl +++ b/samples/hybridreflections/shaders/Intersect.hlsl @@ -1,24 +1,24 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "declarations.h" #include "common_types.h" #include "raytracinglightfunctions.hlsl" diff --git a/samples/hybridreflections/shaders/apply_reflections.hlsl b/samples/hybridreflections/shaders/apply_reflections.hlsl index 73233e88..53106a7a 100644 --- a/samples/hybridreflections/shaders/apply_reflections.hlsl +++ b/samples/hybridreflections/shaders/apply_reflections.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "declarations.h" #include "common_types.h" #include "commonintersect.hlsl" diff --git a/samples/hybridreflections/shaders/common_types.h b/samples/hybridreflections/shaders/common_types.h index 70a91656..76272b98 100644 --- a/samples/hybridreflections/shaders/common_types.h +++ b/samples/hybridreflections/shaders/common_types.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 COMMONTYPES_H #define COMMONTYPES_H diff --git a/samples/hybridreflections/shaders/copy_depth_and_reset_buffers.hlsl b/samples/hybridreflections/shaders/copy_depth_and_reset_buffers.hlsl index 97854a44..781f5f9b 100644 --- a/samples/hybridreflections/shaders/copy_depth_and_reset_buffers.hlsl +++ b/samples/hybridreflections/shaders/copy_depth_and_reset_buffers.hlsl @@ -1,24 +1,24 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "common_types.h" Texture2D g_gbuffer_depth : register(t0); diff --git a/samples/hybridreflections/shaders/copy_depth_and_reset_debug.hlsl b/samples/hybridreflections/shaders/copy_depth_and_reset_debug.hlsl new file mode 100644 index 00000000..f8d7c032 --- /dev/null +++ b/samples/hybridreflections/shaders/copy_depth_and_reset_debug.hlsl @@ -0,0 +1,46 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +Texture2D g_gbuffer_depth : register(t0); +RWTexture2D g_hiz : register(u0); +RWTexture2D g_debug_image : register(u1); + +[numthreads(32, 8, 1)] void main(uint group_index + : SV_GroupIndex, uint3 group_id + : SV_GroupID, uint3 dispatch_thread_id + : SV_DispatchThreadID) { + float2 depth_image_size = float2(0.0f, 0.0f); + g_gbuffer_depth.GetDimensions(depth_image_size.x, depth_image_size.y); + + for (int i = 0; i < 2; ++i) + { + for (int j = 0; j < 8; ++j) + { + uint2 idx = uint2(2 * dispatch_thread_id.x + i, 8 * dispatch_thread_id.y + j); + if (idx.x < depth_image_size.x && idx.y < depth_image_size.y) + { + g_hiz[idx] = g_gbuffer_depth[idx]; + g_debug_image[idx] = float4(0, 0, 0, 0); + } + } + } +} diff --git a/samples/hybridreflections/shaders/ffx_sssr_intersect.h b/samples/hybridreflections/shaders/ffx_sssr_intersect.h index 8c6e687b..e7a58145 100644 --- a/samples/hybridreflections/shaders/ffx_sssr_intersect.h +++ b/samples/hybridreflections/shaders/ffx_sssr_intersect.h @@ -1,26 +1,26 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FFX_SSSR_FLOAT_MAX 3.402823466e+38 #define FFX_SSSR_DEPTH_HIERARCHY_MAX_MIP 6 diff --git a/samples/hybridreflections/shaders/prepare_blue_noise.hlsl b/samples/hybridreflections/shaders/prepare_blue_noise.hlsl index ed1c5482..24105dbd 100644 --- a/samples/hybridreflections/shaders/prepare_blue_noise.hlsl +++ b/samples/hybridreflections/shaders/prepare_blue_noise.hlsl @@ -1,26 +1,26 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "declarations.h" #include "common_types.h" diff --git a/samples/hybridreflections/shaders/prepare_indirect_args_hw.hlsl b/samples/hybridreflections/shaders/prepare_indirect_args_hw.hlsl index 2e66ca4b..5ad73ba2 100644 --- a/samples/hybridreflections/shaders/prepare_indirect_args_hw.hlsl +++ b/samples/hybridreflections/shaders/prepare_indirect_args_hw.hlsl @@ -1,24 +1,24 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "declarations.h" RWByteAddressBuffer g_rw_ray_counter : register(u0); diff --git a/samples/hybridreflections/shaders/prepare_indirect_args_hybrid.hlsl b/samples/hybridreflections/shaders/prepare_indirect_args_hybrid.hlsl index 38abcd55..d9b4128e 100644 --- a/samples/hybridreflections/shaders/prepare_indirect_args_hybrid.hlsl +++ b/samples/hybridreflections/shaders/prepare_indirect_args_hybrid.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "declarations.h" #include "common_types.h" diff --git a/samples/hybridreflections/shaders/primary_ray_tracing.hlsl b/samples/hybridreflections/shaders/primary_ray_tracing.hlsl index 8d02e6cf..dc942e3a 100644 --- a/samples/hybridreflections/shaders/primary_ray_tracing.hlsl +++ b/samples/hybridreflections/shaders/primary_ray_tracing.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "declarations.h" #include "common_types.h" #include "raytracinglightfunctions.hlsl" diff --git a/samples/hybridreflections/shaders/sample_ggx_vndf.h b/samples/hybridreflections/shaders/sample_ggx_vndf.h index d9522d7d..b7a30e75 100644 --- a/samples/hybridreflections/shaders/sample_ggx_vndf.h +++ b/samples/hybridreflections/shaders/sample_ggx_vndf.h @@ -1,15 +1,16 @@ -// Copyright (c) 2018 Eric Heitz (the Authors). -// +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 @@ -18,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + float3 SampleGGXVNDF(float3 Ve, float alpha_x, float alpha_y, float U1, float U2) { // Input Ve: view direction // Input alpha_x, alpha_y: roughness parameters diff --git a/samples/hybridshadows/CMakeLists.txt b/samples/hybridshadows/CMakeLists.txt index f0215f3e..5f238a13 100644 --- a/samples/hybridshadows/CMakeLists.txt +++ b/samples/hybridshadows/CMakeLists.txt @@ -1,3 +1,24 @@ +# This file is part of the FidelityFX SDK. +# +# Copyright (c) 2023 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. + # Declare project if (FFX_API STREQUAL CAULDRON) project(FFX_HYBRIDSHADOWS) diff --git a/samples/hybridshadows/hybridshadowsrendermodule.cpp b/samples/hybridshadows/hybridshadowsrendermodule.cpp index 159b09b8..7dd42198 100644 --- a/samples/hybridshadows/hybridshadowsrendermodule.cpp +++ b/samples/hybridshadows/hybridshadowsrendermodule.cpp @@ -1,22 +1,25 @@ -// AMD Cauldron code -// -// Copyright(c) 2023 Advanced Micro Devices, Inc.All rights reserved. +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +// 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, sub-license, and / or sell +// 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 : +// 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 +// 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 "hybridshadowsrendermodule.h" #include "validation_remap.h" @@ -353,7 +356,7 @@ void HybridShadowsRenderModule::Init(const json&) // Setup FidelityFX interface. { const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_CLASSIFIER_CONTEXT_COUNT + FFX_DENOISER_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface( &m_SDKInterface, GetDevice(), diff --git a/samples/hybridshadows/hybridshadowsrendermodule.h b/samples/hybridshadows/hybridshadowsrendermodule.h index 7419731e..428c2ea0 100644 --- a/samples/hybridshadows/hybridshadowsrendermodule.h +++ b/samples/hybridshadows/hybridshadowsrendermodule.h @@ -1,21 +1,24 @@ -// AMD Cauldron code -// -// Copyright(c) 2023 Advanced Micro Devices, Inc.All rights reserved. +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +// 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, sub-license, and / or sell +// 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 : +// 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 +// 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 "render/rendermodule.h" diff --git a/samples/hybridshadows/shaders/copydebugraytracing.hlsl b/samples/hybridshadows/shaders/copydebugraytracing.hlsl index d33f8208..3a76abfd 100644 --- a/samples/hybridshadows/shaders/copydebugraytracing.hlsl +++ b/samples/hybridshadows/shaders/copydebugraytracing.hlsl @@ -1,22 +1,25 @@ -// AMD Cauldron code -// -// Copyright(c) 2023 Advanced Micro Devices, Inc.All rights reserved. +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +// 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 +// 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 : +// 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 +// 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. + RWTexture2D screenSpaceRayTracing : register(u0); RWTexture2D outputColor : register(u1); diff --git a/samples/hybridshadows/shaders/copydepth.hlsl b/samples/hybridshadows/shaders/copydepth.hlsl index b77eed2d..142cc0af 100644 --- a/samples/hybridshadows/shaders/copydepth.hlsl +++ b/samples/hybridshadows/shaders/copydepth.hlsl @@ -1,22 +1,25 @@ -// AMD Cauldron code -// -// Copyright(c) 2023 Advanced Micro Devices, Inc.All rights reserved. +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +// 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 +// 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 : +// 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 +// 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. + Texture2D gbufferDepth : register(t0); RWTexture2D depthCopy : register(u0); diff --git a/samples/hybridshadows/shaders/debugtiles.hlsl b/samples/hybridshadows/shaders/debugtiles.hlsl index e7fd378e..7a5e19ef 100644 --- a/samples/hybridshadows/shaders/debugtiles.hlsl +++ b/samples/hybridshadows/shaders/debugtiles.hlsl @@ -1,22 +1,25 @@ -// AMD Cauldron code -// -// Copyright(c) 2023 Advanced Micro Devices, Inc.All rights reserved. +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +// 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 +// 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 : +// 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 +// 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 "../shaders/raytracingcommon.hlsl" cbuffer cbTilesDebug : register(b0) diff --git a/samples/hybridshadows/shaders/resolveraytracing.hlsl b/samples/hybridshadows/shaders/resolveraytracing.hlsl index d2e9809d..5ff56741 100644 --- a/samples/hybridshadows/shaders/resolveraytracing.hlsl +++ b/samples/hybridshadows/shaders/resolveraytracing.hlsl @@ -1,22 +1,25 @@ -// AMD Cauldron code -// -// Copyright(c) 2023 Advanced Micro Devices, Inc.All rights reserved. +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +// 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 +// 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 : +// 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 +// 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 "../shaders/raytracingcommon.hlsl" //-------------------------------------------------------------------------------------- diff --git a/samples/hybridshadows/shaders/traceshadows.hlsl b/samples/hybridshadows/shaders/traceshadows.hlsl index 62bb686e..e7eef150 100644 --- a/samples/hybridshadows/shaders/traceshadows.hlsl +++ b/samples/hybridshadows/shaders/traceshadows.hlsl @@ -1,22 +1,25 @@ -// AMD Cauldron code -// -// Copyright(c) 2023 Advanced Micro Devices, Inc.All rights reserved. +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +// 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 +// 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 : +// 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 +// 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 "../shaders/raytracingcommon.hlsl" static const RAY_FLAG k_opaqueFlags diff --git a/samples/lens/CMakeLists.txt b/samples/lens/CMakeLists.txt index 1d3bfd07..ab4ea983 100644 --- a/samples/lens/CMakeLists.txt +++ b/samples/lens/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/lens/lensrendermodule.cpp b/samples/lens/lensrendermodule.cpp index 9003edb0..9e60f89e 100644 --- a/samples/lens/lensrendermodule.cpp +++ b/samples/lens/lensrendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "lensrendermodule.h" #include "validation_remap.h" @@ -126,7 +126,7 @@ void LensRenderModule::Init(const json& initData) // Initialize the FFX backend const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_LENS_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_LENS_CONTEXT_COUNT); FFX_ASSERT(errorCode == FFX_OK); diff --git a/samples/lens/lensrendermodule.h b/samples/lens/lensrendermodule.h index 514e0722..fd5e56f1 100644 --- a/samples/lens/lensrendermodule.h +++ b/samples/lens/lensrendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "render/rendermodule.h" diff --git a/samples/lpm/CMakeLists.txt b/samples/lpm/CMakeLists.txt index 6f362edd..ed620980 100644 --- a/samples/lpm/CMakeLists.txt +++ b/samples/lpm/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/lpm/lpmrendermodule.cpp b/samples/lpm/lpmrendermodule.cpp index daae187d..ab50e3a5 100644 --- a/samples/lpm/lpmrendermodule.cpp +++ b/samples/lpm/lpmrendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "lpmrendermodule.h" #include "validation_remap.h" @@ -46,6 +46,20 @@ void LPMRenderModule::Init(const json& initData) // Fetch needed resources m_pInputColor = GetFramework()->GetRenderTexture(L"HDR11Color"); + switch (GetFramework()->GetSwapChain()->GetSwapChainDisplayMode()) + { + case DisplayMode::DISPLAYMODE_LDR: + m_pInputColor = GetFramework()->GetRenderTexture(L"LDR8Color"); + break; + case DisplayMode::DISPLAYMODE_HDR10_2084: + case DisplayMode::DISPLAYMODE_FSHDR_2084: + m_pInputColor = GetFramework()->GetRenderTexture(L"HDR10Color"); + break; + case DisplayMode::DISPLAYMODE_HDR10_SCRGB: + case DisplayMode::DISPLAYMODE_FSHDR_SCRGB: + m_pInputColor = GetFramework()->GetRenderTexture(L"HDR16Color"); + break; + } CauldronAssert(ASSERT_CRITICAL, m_pInputColor != nullptr, L"Couldn't find the input texture for the tone mapper"); // Get the proper post tone map color target (these are the same now) @@ -90,7 +104,7 @@ void LPMRenderModule::Init(const json& initData) // Setup FidelityFX interface. const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_LPM_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_LPM_CONTEXT_COUNT); CauldronAssert(ASSERT_CRITICAL, errorCode == FFX_OK, L"Couldn't initialize the FidelityFX SDK backend interface."); diff --git a/samples/lpm/lpmrendermodule.h b/samples/lpm/lpmrendermodule.h index c8bc8364..e0ca01c2 100644 --- a/samples/lpm/lpmrendermodule.h +++ b/samples/lpm/lpmrendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "render/rendermodules/tonemapping/tonemappingrendermodule.h" diff --git a/samples/parallelsort/CMakeLists.txt b/samples/parallelsort/CMakeLists.txt index cda4a45f..04c5b990 100644 --- a/samples/parallelsort/CMakeLists.txt +++ b/samples/parallelsort/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/parallelsort/parallelsortrendermodule.cpp b/samples/parallelsort/parallelsortrendermodule.cpp index 42d7a2c5..05ab85e4 100644 --- a/samples/parallelsort/parallelsortrendermodule.cpp +++ b/samples/parallelsort/parallelsortrendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "parallelsortrendermodule.h" #include "shaders/parallelsort_common.h" @@ -38,6 +38,7 @@ #include "render/renderdefines.h" #include "render/rootsignature.h" #include "render/uploadheap.h" +#include "render/swapchain.h" #include @@ -51,7 +52,7 @@ void ParallelSortRenderModule::Init(const json& initData) // Setup FidelityFX interface. { const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_PARALLELSORT_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_PARALLELSORT_CONTEXT_COUNT); FFX_ASSERT(errorCode == FFX_OK); } @@ -128,6 +129,20 @@ void ParallelSortRenderModule::Init(const json& initData) // Create the pipeline and signature for verification pass m_pRenderTarget = GetFramework()->GetColorTargetForCallback(GetName()); + switch (GetFramework()->GetSwapChain()->GetSwapChainDisplayMode()) + { + case DisplayMode::DISPLAYMODE_LDR: + m_pRenderTarget = GetFramework()->GetRenderTexture(L"LDR8Color"); + break; + case DisplayMode::DISPLAYMODE_HDR10_2084: + case DisplayMode::DISPLAYMODE_FSHDR_2084: + m_pRenderTarget = GetFramework()->GetRenderTexture(L"HDR10Color"); + break; + case DisplayMode::DISPLAYMODE_HDR10_SCRGB: + case DisplayMode::DISPLAYMODE_FSHDR_SCRGB: + m_pRenderTarget = GetFramework()->GetRenderTexture(L"HDR16Color"); + break; + } CauldronAssert(ASSERT_CRITICAL, m_pRenderTarget != nullptr, L"Couldn't find or create the render target for ParallelSortRenderModule."); m_pRasterView = GetRasterViewAllocator()->RequestRasterView(m_pRenderTarget, ViewDimension::Texture2D); diff --git a/samples/parallelsort/parallelsortrendermodule.h b/samples/parallelsort/parallelsortrendermodule.h index 86672107..9038a16c 100644 --- a/samples/parallelsort/parallelsortrendermodule.h +++ b/samples/parallelsort/parallelsortrendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "render/rendermodule.h" diff --git a/samples/parallelsort/shaders/parallelsort_common.h b/samples/parallelsort/shaders/parallelsort_common.h index 0f3dd532..9c4ecf94 100644 --- a/samples/parallelsort/shaders/parallelsort_common.h +++ b/samples/parallelsort/shaders/parallelsort_common.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #pragma once #if __cplusplus diff --git a/samples/parallelsort/shaders/parallelsort_cs.hlsl b/samples/parallelsort/shaders/parallelsort_cs.hlsl index d89c0b5d..39d05e53 100644 --- a/samples/parallelsort/shaders/parallelsort_cs.hlsl +++ b/samples/parallelsort/shaders/parallelsort_cs.hlsl @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -20,6 +20,7 @@ // THE SOFTWARE. + //-------------------------------------------------------------------------------------- // ParallelSort Shaders/Includes //-------------------------------------------------------------------------------------- diff --git a/samples/parallelsort/shaders/parallelsort_verify.hlsl b/samples/parallelsort/shaders/parallelsort_verify.hlsl index 2f65ffbb..287b10bb 100644 --- a/samples/parallelsort/shaders/parallelsort_verify.hlsl +++ b/samples/parallelsort/shaders/parallelsort_verify.hlsl @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include "parallelsort_common.h" Texture2D ValidationTexture : register(t0); diff --git a/samples/spd/CMakeLists.txt b/samples/spd/CMakeLists.txt index 55d4c0dc..56c37ab1 100644 --- a/samples/spd/CMakeLists.txt +++ b/samples/spd/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/spd/shaders/spd_common.h b/samples/spd/shaders/spd_common.h index 9540d918..cb038e95 100644 --- a/samples/spd/shaders/spd_common.h +++ b/samples/spd/shaders/spd_common.h @@ -1,6 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -9,7 +10,7 @@ // 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 @@ -18,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #ifndef FFX_SPD_COMMON_H #define FFX_SPD_COMMON_H diff --git a/samples/spd/shaders/spd_cs_downsampler.hlsl b/samples/spd/shaders/spd_cs_downsampler.hlsl index ee00fb8a..fdb3958e 100644 --- a/samples/spd/shaders/spd_cs_downsampler.hlsl +++ b/samples/spd/shaders/spd_cs_downsampler.hlsl @@ -1,6 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -9,7 +10,7 @@ // 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 @@ -18,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include "spd_common.h" //-------------------------------------------------------------------------------------- diff --git a/samples/spd/shaders/spd_ps_downsampler.hlsl b/samples/spd/shaders/spd_ps_downsampler.hlsl index aff256cb..29b3edeb 100644 --- a/samples/spd/shaders/spd_ps_downsampler.hlsl +++ b/samples/spd/shaders/spd_ps_downsampler.hlsl @@ -1,6 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -9,7 +10,7 @@ // 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 @@ -18,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include "fullscreen.hlsl" #include "spd_common.h" diff --git a/samples/spd/shaders/spd_verify_results.hlsl b/samples/spd/shaders/spd_verify_results.hlsl index 37ea35ab..94eeb4aa 100644 --- a/samples/spd/shaders/spd_verify_results.hlsl +++ b/samples/spd/shaders/spd_verify_results.hlsl @@ -1,6 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -9,7 +10,7 @@ // 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 @@ -18,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include "spd_common.h" //-------------------------------------------------------------------------------------- diff --git a/samples/spd/spdrendermodule.cpp b/samples/spd/spdrendermodule.cpp index 60c65d23..19295a19 100644 --- a/samples/spd/spdrendermodule.cpp +++ b/samples/spd/spdrendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "spdrendermodule.h" #include "validation_remap.h" @@ -118,7 +118,7 @@ void SPDRenderModule::Init(const json& initData) // Initialize the FFX backend const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_SPD_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_SPD_CONTEXT_COUNT); FFX_ASSERT(errorCode == FFX_OK); diff --git a/samples/spd/spdrendermodule.h b/samples/spd/spdrendermodule.h index 0e002371..44c147bb 100644 --- a/samples/spd/spdrendermodule.h +++ b/samples/spd/spdrendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "render/rendermodule.h" diff --git a/samples/sssr/CMakeLists.txt b/samples/sssr/CMakeLists.txt index 01e2c426..263624d9 100644 --- a/samples/sssr/CMakeLists.txt +++ b/samples/sssr/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/sssr/shaders/sssr_apply_reflections.hlsl b/samples/sssr/shaders/sssr_apply_reflections.hlsl index 8e9067a2..198125ca 100644 --- a/samples/sssr/shaders/sssr_apply_reflections.hlsl +++ b/samples/sssr/shaders/sssr_apply_reflections.hlsl @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + /********************************************************************** Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. diff --git a/samples/sssr/shaders/sssr_apply_reflections_common.h b/samples/sssr/shaders/sssr_apply_reflections_common.h index 1c45e30f..4df3412c 100644 --- a/samples/sssr/shaders/sssr_apply_reflections_common.h +++ b/samples/sssr/shaders/sssr_apply_reflections_common.h @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 #ifdef __cplusplus diff --git a/samples/sssr/sssrrendermodule.cpp b/samples/sssr/sssrrendermodule.cpp index 1ae3b332..8f774565 100644 --- a/samples/sssr/sssrrendermodule.cpp +++ b/samples/sssr/sssrrendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "sssrrendermodule.h" #include "validation_remap.h" @@ -127,7 +127,7 @@ void SSSRRenderModule::Init(const json& initData) // Initialize the FFX backend const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_SSSR_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_SSSR_CONTEXT_COUNT); FFX_ASSERT(errorCode == FFX_OK); diff --git a/samples/sssr/sssrrendermodule.h b/samples/sssr/sssrrendermodule.h index 520d6135..138c8b56 100644 --- a/samples/sssr/sssrrendermodule.h +++ b/samples/sssr/sssrrendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "core/contentmanager.h" diff --git a/samples/validation_remap.h b/samples/validation_remap.h index 3a9eeec3..dd8986d1 100644 --- a/samples/validation_remap.h +++ b/samples/validation_remap.h @@ -79,6 +79,8 @@ inline FfxSurfaceFormat GetFfxSurfaceFormat(cauldron::ResourceFormat format) return FFX_SURFACE_FORMAT_R16G16_FLOAT; case (cauldron::ResourceFormat::RG16_UINT): return FFX_SURFACE_FORMAT_R16G16_UINT; + case (cauldron::ResourceFormat::RG16_SINT): + return FFX_SURFACE_FORMAT_R16G16_SINT; case (cauldron::ResourceFormat::R16_FLOAT): return FFX_SURFACE_FORMAT_R16_FLOAT; case (cauldron::ResourceFormat::R16_UINT): @@ -98,6 +100,8 @@ inline FfxSurfaceFormat GetFfxSurfaceFormat(cauldron::ResourceFormat format) return FFX_SURFACE_FORMAT_UNKNOWN; case cauldron::ResourceFormat::RGBA32_UINT: return FFX_SURFACE_FORMAT_R32G32B32A32_UINT; + case cauldron::ResourceFormat::RGB10A2_UNORM: + return FFX_SURFACE_FORMAT_R10G10B10A2_UNORM; default: FFX_ASSERT_MESSAGE(false, "ValidationRemap: Unsupported format requested. Please implement."); return FFX_SURFACE_FORMAT_UNKNOWN; @@ -190,7 +194,7 @@ inline FfxErrorCode ffxGetInterface(FfxInterface* backendInterface, cauldron::De #ifdef FFX_API_CAULDRON return ffxGetInterfaceCauldron(backendInterface, ffxGetDeviceCauldron(device), scratchBuffer, scratchBufferSize, maxContexts); #elif FFX_API_DX12 - return ffxGetInterfaceDX12(backendInterface, ffxGetDeviceDX12(device->GetImpl()->DX12Device()), scratchBuffer, scratchBufferSize, maxContexts); + return ffxGetInterfaceDX12(backendInterface, ffxGetDeviceDX12(device->GetImpl()->DX12Device()), scratchBuffer, scratchBufferSize, (uint32_t)maxContexts); #elif FFX_API_VK VkDeviceContext vkDeviceContext = { device->GetImpl()->VKDevice(), device->GetImpl()->VKPhysicalDevice(), vkGetDeviceProcAddr }; return ffxGetInterfaceVK(backendInterface, ffxGetDeviceVK(&vkDeviceContext), scratchBuffer, scratchBufferSize, maxContexts); @@ -227,3 +231,45 @@ inline FfxResource ffxGetResource(const cauldron::GPUResource* cauldronResource, cauldron::CauldronCritical(L"Unsupported API or Platform for FFX Validation Remap"); return FfxResource(); // Error } + +inline FfxErrorCode ffxReplaceSwapchainForFrameinterpolation(FfxCommandQueue gameQueue, FfxSwapchain& gameSwapChain) +{ +#ifdef FFX_API_CAULDRON + FFX_ASSERT_FAIL("FSR3 is not implemented for Cauldron backend, yet. Please use the native DX12 backend to test FSR3."); +#elif FFX_API_DX12 + return ffxReplaceSwapchainForFrameinterpolationDX12(gameQueue, gameSwapChain); +#elif FFX_API_VK + FFX_ASSERT(false && "Not Implemented!"); +#endif // FFX_API_CAULDRON + + cauldron::CauldronCritical(L"Unsupported API or Platform for FFX Validation Remap"); + return FFX_ERROR_BACKEND_API_ERROR; // Error +} + +inline FfxErrorCode ffxRegisterFrameinterpolationUiResource(FfxSwapchain gameSwapChain, FfxResource uiResource) +{ +#ifdef FFX_API_CAULDRON + FFX_ASSERT(false && "Not Implemented!"); +#elif FFX_API_DX12 + return ffxRegisterFrameinterpolationUiResourceDX12(gameSwapChain, uiResource); +#elif FFX_API_VK + FFX_ASSERT(false && "Not Implemented!"); +#endif // FFX_API_CAULDRON + + cauldron::CauldronCritical(L"Unsupported API or Platform for FFX Validation Remap"); + return FFX_ERROR_BACKEND_API_ERROR; // Error +} + +inline FfxErrorCode ffxGetInterpolationCommandlist(FfxSwapchain gameSwapChain, FfxCommandList& gameCommandlist) +{ +#ifdef FFX_API_CAULDRON + FFX_ASSERT(false && "Not Implemented!"); +#elif FFX_API_DX12 + return ffxGetFrameinterpolationCommandlistDX12(gameSwapChain, gameCommandlist); +#elif FFX_API_VK + FFX_ASSERT(false && "Not Implemented!"); +#endif // FFX_API_CAULDRON + + cauldron::CauldronCritical(L"Unsupported API or Platform for FFX Validation Remap"); + return FFX_ERROR_BACKEND_API_ERROR; // Error +} diff --git a/samples/vrs/CMakeLists.txt b/samples/vrs/CMakeLists.txt index ac5f9614..ccfbac9b 100644 --- a/samples/vrs/CMakeLists.txt +++ b/samples/vrs/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# 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 +# 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 diff --git a/samples/vrs/shaders/VrsOverlay.hlsl b/samples/vrs/shaders/VrsOverlay.hlsl index b236f17d..0f93b82d 100644 --- a/samples/vrs/shaders/VrsOverlay.hlsl +++ b/samples/vrs/shaders/VrsOverlay.hlsl @@ -1,6 +1,7 @@ -// AMD FidelityFX Variable Shading Sample code -// +// This file is part of the FidelityFX SDK. +// // Copyright (c) 2023 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 @@ -9,6 +10,7 @@ // 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 @@ -17,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + static const uint FFX_VARIABLESHADING_RATE1D_1X = 0x0; static const uint FFX_VARIABLESHADING_RATE1D_2X = 0x1; static const uint FFX_VARIABLESHADING_RATE1D_4X = 0x2; diff --git a/samples/vrs/shaders/motionvectorsps.hlsl b/samples/vrs/shaders/motionvectorsps.hlsl index 008c8a86..bf5ae371 100644 --- a/samples/vrs/shaders/motionvectorsps.hlsl +++ b/samples/vrs/shaders/motionvectorsps.hlsl @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // Portions Copyright 2023 Advanced Micro Devices, Inc.All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/samples/vrs/vrsrendermodule.cpp b/samples/vrs/vrsrendermodule.cpp index 62efab3f..dec090ec 100644 --- a/samples/vrs/vrsrendermodule.cpp +++ b/samples/vrs/vrsrendermodule.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "vrsrendermodule.h" #include "validation_remap.h" @@ -159,7 +159,7 @@ void VRSRenderModule::Init(const json& initData) // Initialize the FFX backend const size_t scratchBufferSize = ffxGetScratchMemorySize(FFX_VRS_CONTEXT_COUNT); - void* scratchBuffer = malloc(scratchBufferSize); + void* scratchBuffer = calloc(scratchBufferSize, 1); FfxErrorCode errorCode = ffxGetInterface(&m_InitializationParameters.backendInterface, GetDevice(), scratchBuffer, scratchBufferSize, FFX_VRS_CONTEXT_COUNT); FFX_ASSERT(errorCode == FFX_OK); } diff --git a/samples/vrs/vrsrendermodule.h b/samples/vrs/vrsrendermodule.h index ac6bab14..cbec6d31 100644 --- a/samples/vrs/vrsrendermodule.h +++ b/samples/vrs/vrsrendermodule.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 "core/contentmanager.h" diff --git a/sdk/BuildFidelityFXSDK.bat b/sdk/BuildFidelityFXSDK.bat index 8b6f9235..42a84c9f 100644 --- a/sdk/BuildFidelityFXSDK.bat +++ b/sdk/BuildFidelityFXSDK.bat @@ -34,7 +34,9 @@ if not exist build\ ( mkdir build ) cd build -cmake -A x64 .. -DFFX_API_CUSTOM=OFF -DFFX_ALL=ON -DFFX_AUTO_COMPILE_SHADERS=1 +cmake -A x64 .. -DFFX_API_CUSTOM=OFF -DFFX_ALL=ON -DFFX_AUTO_COMPILE_SHADERS=1 %* cmake --build ./ --config Debug --parallel 4 -- /p:CL_MPcount=16 cmake --build ./ --config Release --parallel 4 -- /p:CL_MPcount=16 -cd.. \ No newline at end of file +cmake --build ./ --config RelWithDebInfo --parallel 4 -- /p:CL_MPcount=16 + +cd.. diff --git a/sdk/BuildFidelityFXSDKSolution.bat b/sdk/BuildFidelityFXSDKSolution.bat index 8f070813..f0f37684 100644 --- a/sdk/BuildFidelityFXSDKSolution.bat +++ b/sdk/BuildFidelityFXSDKSolution.bat @@ -34,8 +34,8 @@ if not exist build\ ( mkdir build ) cd build -cmake -A x64 .. -DFFX_API_CUSTOM=OFF -DFFX_ALL=ON -DFFX_AUTO_COMPILE_SHADERS=1 +cmake -A x64 .. -DFFX_API_CUSTOM=OFF -DFFX_ALL=ON -DFFX_AUTO_COMPILE_SHADERS=1 %* cd.. :: Pause so the user can acknowledge any errors or other outputs from the build process -pause \ No newline at end of file +pause diff --git a/sdk/CMakeLists.txt b/sdk/CMakeLists.txt index 7d6aea44..175b587d 100644 --- a/sdk/CMakeLists.txt +++ b/sdk/CMakeLists.txt @@ -1,9 +1,9 @@ # This file is part of the FidelityFX SDK. # -# Copyright © 2023 Advanced Micro Devices, Inc. +# Copyright � 2023 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files(the “Software”), to deal +# 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 @@ -12,7 +12,7 @@ # 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 +# 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 @@ -25,7 +25,7 @@ cmake_minimum_required(VERSION 3.17) # Set configuration types based on what we are building for if (NOT FFX_API_CUSTOM) message(STATUS "Building FidelityFX SDK with DX12 & VK backends") - set(CMAKE_CONFIGURATION_TYPES Debug Release) + set(CMAKE_CONFIGURATION_TYPES Debug Release RelWithDebInfo) set(CMAKE_DEBUG_POSTFIX d) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -79,6 +79,7 @@ if (NOT FFX_API_CUSTOM) # Write both debug and release versions of the static libs to the /bin folder as they are uniquely named set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_HOME_DIRECTORY}/bin/ffx_sdk/) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_HOME_DIRECTORY}/bin/ffx_sdk/) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_HOME_DIRECTORY}/bin/ffx_sdk/) else() @@ -157,6 +158,10 @@ set(FFX_PUBLIC_SHADER_SOURCES project (FidelityFX-SDK) # Components +add_subdirectory(${FFX_COMPONENTS_PATH}/opticalflow) +add_subdirectory(${FFX_COMPONENTS_PATH}/frameinterpolation) +add_subdirectory(${FFX_COMPONENTS_PATH}/fsr3) +add_subdirectory(${FFX_COMPONENTS_PATH}/fsr3upscaler) add_subdirectory(${FFX_COMPONENTS_PATH}/fsr2) add_subdirectory(${FFX_COMPONENTS_PATH}/fsr1) add_subdirectory(${FFX_COMPONENTS_PATH}/spd) diff --git a/sdk/include/FidelityFX/gpu/blur/ffx_blur.h b/sdk/include/FidelityFX/gpu/blur/ffx_blur.h index efc33a23..c30e3fbc 100644 --- a/sdk/include/FidelityFX/gpu/blur/ffx_blur.h +++ b/sdk/include/FidelityFX/gpu/blur/ffx_blur.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_BLUR_H #define FFX_BLUR_H //_____________________________________________________________/\_______________________________________________________________ diff --git a/sdk/include/FidelityFX/gpu/blur/ffx_blur_blur.h b/sdk/include/FidelityFX/gpu/blur/ffx_blur_blur.h index e88e145a..5c1d9bdd 100644 --- a/sdk/include/FidelityFX/gpu/blur/ffx_blur_blur.h +++ b/sdk/include/FidelityFX/gpu/blur/ffx_blur_blur.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" FFX_BLUR_KERNEL_TYPE BlurLoadKernelWeight(FfxInt32 iKernelIndex) diff --git a/sdk/include/FidelityFX/gpu/blur/ffx_blur_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/blur/ffx_blur_callbacks_glsl.h index a1d6dcb1..80412ac9 100644 --- a/sdk/include/FidelityFX/gpu/blur/ffx_blur_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/blur/ffx_blur_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_blur_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/blur/ffx_blur_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/blur/ffx_blur_callbacks_hlsl.h index 70cb67d9..d818b10a 100644 --- a/sdk/include/FidelityFX/gpu/blur/ffx_blur_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/blur/ffx_blur_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_blur_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/blur/ffx_blur_resources.h b/sdk/include/FidelityFX/gpu/blur/ffx_blur_resources.h index c25f4523..9b78df13 100644 --- a/sdk/include/FidelityFX/gpu/blur/ffx_blur_resources.h +++ b/sdk/include/FidelityFX/gpu/blur/ffx_blur_resources.h @@ -1,26 +1,26 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_BLUR_RESOURCES_H #define FFX_BLUR_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_apply.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_apply.h index cc7be932..f5a33ed2 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_apply.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_apply.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #include "ffx_cacao_defines.h" #include "ffx_cacao_utils.h" diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_callbacks_glsl.h index 95665beb..91e95463 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_cacao_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_callbacks_hlsl.h index a2e22dd2..be13cbe0 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_cacao_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_defines.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_defines.h index dcf72093..20089647 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_defines.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_defines.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // Defines for constants common to both CACAO.cpp and CACAO.hlsl #ifndef FFX_CACAO_DEFINES_H diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_edge_sensitive_blur.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_edge_sensitive_blur.h index e4a8a8c9..64712c16 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_edge_sensitive_blur.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_edge_sensitive_blur.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #include "ffx_cacao_defines.h" #include "ffx_cacao_utils.h" diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_importance_map.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_importance_map.h index 65325183..ef819fc0 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_importance_map.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_importance_map.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #include "ffx_cacao_defines.h" #include "ffx_cacao_utils.h" diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_prepare.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_prepare.h index 1799248a..0d74f641 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_prepare.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_prepare.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #include "ffx_cacao_defines.h" #include "ffx_cacao_utils.h" diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_resources.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_resources.h index d7479078..d8d63f8d 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_resources.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_CACAO_RESOURCES_H #define FFX_CACAO_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_ssao_generation.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_ssao_generation.h index 5bbedbf2..c82a3ca2 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_ssao_generation.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_ssao_generation.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #include "ffx_cacao_defines.h" #include "ffx_cacao_utils.h" diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_upscale.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_upscale.h index ad2acba8..5fbfa92d 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_upscale.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_upscale.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #include "ffx_cacao_defines.h" #include "ffx_cacao_utils.h" diff --git a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_utils.h b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_utils.h index 3637f960..d71d18b1 100644 --- a/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_utils.h +++ b/sdk/include/FidelityFX/gpu/cacao/ffx_cacao_utils.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // packing/unpacking for edges; 2 bits per edge mean 4 gradient values (0, 0.33, 0.66, 1) for smoother transitions! FfxFloat32 FFX_CACAO_PackEdges(FfxFloat32x4 edgesLRTB) { diff --git a/sdk/include/FidelityFX/gpu/cas/ffx_cas.h b/sdk/include/FidelityFX/gpu/cas/ffx_cas.h index 2e462145..eecc158f 100644 --- a/sdk/include/FidelityFX/gpu/cas/ffx_cas.h +++ b/sdk/include/FidelityFX/gpu/cas/ffx_cas.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup FfxGPUCas FidelityFX CAS /// FidelityFX Contrast Adaptive Sharpening GPU documentation /// @@ -333,9 +333,9 @@ void casFilterNoScalingHalf( FfxFloat16x2 amplifyGreen = ffxSaturate(min(minimumGreen, FFX_BROADCAST_FLOAT16X2(2.0) - maximumGreen) * reciprocalMaximumGreen); FfxFloat16x2 amplifyBlue = ffxSaturate(min(minimumBlue, FFX_BROADCAST_FLOAT16X2(2.0) - maximumBlue) * reciprocalMaximumBlue); #else - FfxFloat16x2 amplifyRed = ffxSaturate(min(minimumRed, FFX_BROADCAST_FLOAT16X2(1.0) - maximumRed) * reciprocalMaximumRed); - FfxFloat16x2 amplifyGreen = ffxSaturate(min(minimumGreen, FFX_BROADCAST_FLOAT16X2(1.0) - maximumGreen) * reciprocalMaximumGreen); - FfxFloat16x2 amplifyBlue = ffxSaturate(min(minimumBlue, FFX_BROADCAST_FLOAT16X2(1.0) - maximumBlue) * reciprocalMaximumBlue); + FfxFloat16x2 amplifyRed = FfxFloat16x2(ffxSaturate(min(minimumRed, FFX_BROADCAST_FLOAT16X2(1.0) - maximumRed) * reciprocalMaximumRed)); + FfxFloat16x2 amplifyGreen = FfxFloat16x2(ffxSaturate(min(minimumGreen, FFX_BROADCAST_FLOAT16X2(1.0) - maximumGreen) * reciprocalMaximumGreen)); + FfxFloat16x2 amplifyBlue = FfxFloat16x2(ffxSaturate(min(minimumBlue, FFX_BROADCAST_FLOAT16X2(1.0) - maximumBlue) * reciprocalMaximumBlue)); #endif // #if defined(FFX_CAS_BETTER_DIAGONALS) // Shaping amount of sharpening. @@ -361,9 +361,9 @@ void casFilterNoScalingHalf( FfxFloat16x2 reciprocalWeight = ffxApproximateReciprocalMediumHalf(FFX_BROADCAST_FLOAT16X2(1.0) + FFX_BROADCAST_FLOAT16X2(4.0) * weightGreen); #endif // #if defined(FFX_CAS_USE_PRECISE_MATH) - outPixelRed = ffxSaturate((bR * weightGreen + dR * weightGreen + fR * weightGreen + hR * weightGreen + eR) * reciprocalWeight); - outPixelGreen = ffxSaturate((bG * weightGreen + dG * weightGreen + fG * weightGreen + hG * weightGreen + eG) * reciprocalWeight); - outPixelBlue = ffxSaturate((bB * weightGreen + dB * weightGreen + fB * weightGreen + hB * weightGreen + eB) * reciprocalWeight); + outPixelRed = FfxFloat16x2(ffxSaturate((bR * weightGreen + dR * weightGreen + fR * weightGreen + hR * weightGreen + eR) * reciprocalWeight)); + outPixelGreen = FfxFloat16x2(ffxSaturate((bG * weightGreen + dG * weightGreen + fG * weightGreen + hG * weightGreen + eG) * reciprocalWeight)); + outPixelBlue = FfxFloat16x2(ffxSaturate((bB * weightGreen + dB * weightGreen + fB * weightGreen + hB * weightGreen + eB) * reciprocalWeight)); } #endif // #if FFX_HALF == 1 @@ -1011,18 +1011,18 @@ void casFilterWithScalingHalf( FfxFloat16x2 ampkG = ffxSaturate(min(mnkG, FFX_BROADCAST_FLOAT16X2(2.0) - mxkG) * rcpMkG); FfxFloat16x2 ampkB = ffxSaturate(min(mnkB, FFX_BROADCAST_FLOAT16X2(2.0) - mxkB) * rcpMkB); #else - FfxFloat16x2 ampfR = ffxSaturate(min(minimumRed, FFX_BROADCAST_FLOAT16X2(1.0) - mxfR) * rcpMfR); - FfxFloat16x2 ampfG = ffxSaturate(min(minimumGreen, FFX_BROADCAST_FLOAT16X2(1.0) - mxfG) * rcpMfG); - FfxFloat16x2 ampfB = ffxSaturate(min(minimumBlue, FFX_BROADCAST_FLOAT16X2(1.0) - mxfB) * rcpMfB); - FfxFloat16x2 ampgR = ffxSaturate(min(mngR, FFX_BROADCAST_FLOAT16X2(1.0) - mxgR) * rcpMgR); - FfxFloat16x2 ampgG = ffxSaturate(min(mngG, FFX_BROADCAST_FLOAT16X2(1.0) - mxgG) * rcpMgG); - FfxFloat16x2 ampgB = ffxSaturate(min(mngB, FFX_BROADCAST_FLOAT16X2(1.0) - mxgB) * rcpMgB); - FfxFloat16x2 ampjR = ffxSaturate(min(mnjR, FFX_BROADCAST_FLOAT16X2(1.0) - mxjR) * rcpMjR); - FfxFloat16x2 ampjG = ffxSaturate(min(mnjG, FFX_BROADCAST_FLOAT16X2(1.0) - mxjG) * rcpMjG); - FfxFloat16x2 ampjB = ffxSaturate(min(mnjB, FFX_BROADCAST_FLOAT16X2(1.0) - mxjB) * rcpMjB); - FfxFloat16x2 ampkR = ffxSaturate(min(mnkR, FFX_BROADCAST_FLOAT16X2(1.0) - mxkR) * rcpMkR); - FfxFloat16x2 ampkG = ffxSaturate(min(mnkG, FFX_BROADCAST_FLOAT16X2(1.0) - mxkG) * rcpMkG); - FfxFloat16x2 ampkB = ffxSaturate(min(mnkB, FFX_BROADCAST_FLOAT16X2(1.0) - mxkB) * rcpMkB); + FfxFloat16x2 ampfR = FfxFloat16x2(ffxSaturate(min(minimumRed, FFX_BROADCAST_FLOAT16X2(1.0) - mxfR) * rcpMfR)); + FfxFloat16x2 ampfG = FfxFloat16x2(ffxSaturate(min(minimumGreen, FFX_BROADCAST_FLOAT16X2(1.0) - mxfG) * rcpMfG)); + FfxFloat16x2 ampfB = FfxFloat16x2(ffxSaturate(min(minimumBlue, FFX_BROADCAST_FLOAT16X2(1.0) - mxfB) * rcpMfB)); + FfxFloat16x2 ampgR = FfxFloat16x2(ffxSaturate(min(mngR, FFX_BROADCAST_FLOAT16X2(1.0) - mxgR) * rcpMgR)); + FfxFloat16x2 ampgG = FfxFloat16x2(ffxSaturate(min(mngG, FFX_BROADCAST_FLOAT16X2(1.0) - mxgG) * rcpMgG)); + FfxFloat16x2 ampgB = FfxFloat16x2(ffxSaturate(min(mngB, FFX_BROADCAST_FLOAT16X2(1.0) - mxgB) * rcpMgB)); + FfxFloat16x2 ampjR = FfxFloat16x2(ffxSaturate(min(mnjR, FFX_BROADCAST_FLOAT16X2(1.0) - mxjR) * rcpMjR)); + FfxFloat16x2 ampjG = FfxFloat16x2(ffxSaturate(min(mnjG, FFX_BROADCAST_FLOAT16X2(1.0) - mxjG) * rcpMjG)); + FfxFloat16x2 ampjB = FfxFloat16x2(ffxSaturate(min(mnjB, FFX_BROADCAST_FLOAT16X2(1.0) - mxjB) * rcpMjB)); + FfxFloat16x2 ampkR = FfxFloat16x2(ffxSaturate(min(mnkR, FFX_BROADCAST_FLOAT16X2(1.0) - mxkR) * rcpMkR)); + FfxFloat16x2 ampkG = FfxFloat16x2(ffxSaturate(min(mnkG, FFX_BROADCAST_FLOAT16X2(1.0) - mxkG) * rcpMkG)); + FfxFloat16x2 ampkB = FfxFloat16x2(ffxSaturate(min(mnkB, FFX_BROADCAST_FLOAT16X2(1.0) - mxkB) * rcpMkB)); #endif // Shaping amount of sharpening. @@ -1126,12 +1126,12 @@ void casFilterWithScalingHalf( FFX_BROADCAST_FLOAT16X2(2.0) * qloG + qfG + qgG + qjG + qkG); #endif // #if defined(FFX_CAS_USE_PRECISE_MATH) - pixR = ffxSaturate( - (bR * qbeG + eR * qbeG + cR * qchG + hR * qchG + iR * qinG + nR * qinG + lR * qloG + oR * qloG + fR * qfG + gR * qgG + jR * qjG + kR * qkG) * rcpWG); - pixG = ffxSaturate( - (bG * qbeG + eG * qbeG + cG * qchG + hG * qchG + iG * qinG + nG * qinG + lG * qloG + oG * qloG + fG * qfG + gG * qgG + jG * qjG + kG * qkG) * rcpWG); - pixB = ffxSaturate( - (bB * qbeG + eB * qbeG + cB * qchG + hB * qchG + iB * qinG + nB * qinG + lB * qloG + oB * qloG + fB * qfG + gB * qgG + jB * qjG + kB * qkG) * rcpWG); + pixR = FfxFloat16x2(ffxSaturate( + (bR * qbeG + eR * qbeG + cR * qchG + hR * qchG + iR * qinG + nR * qinG + lR * qloG + oR * qloG + fR * qfG + gR * qgG + jR * qjG + kR * qkG) * rcpWG)); + pixG = FfxFloat16x2(ffxSaturate( + (bG * qbeG + eG * qbeG + cG * qchG + hG * qchG + iG * qinG + nG * qinG + lG * qloG + oG * qloG + fG * qfG + gG * qgG + jG * qjG + kG * qkG) * rcpWG)); + pixB = FfxFloat16x2(ffxSaturate( + (bB * qbeG + eB * qbeG + cB * qchG + hB * qchG + iB * qinG + nB * qinG + lB * qloG + oB * qloG + fB * qfG + gB * qgG + jB * qjG + kB * qkG) * rcpWG)); } #endif // #if FFX_HALF == 1 diff --git a/sdk/include/FidelityFX/gpu/cas/ffx_cas_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/cas/ffx_cas_callbacks_glsl.h index 6b58b048..184eb974 100644 --- a/sdk/include/FidelityFX/gpu/cas/ffx_cas_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/cas/ffx_cas_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_cas_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/cas/ffx_cas_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/cas/ffx_cas_callbacks_hlsl.h index 8d48df89..1048f07c 100644 --- a/sdk/include/FidelityFX/gpu/cas/ffx_cas_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/cas/ffx_cas_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_cas_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/cas/ffx_cas_resources.h b/sdk/include/FidelityFX/gpu/cas/ffx_cas_resources.h index 4d74c633..286aa389 100644 --- a/sdk/include/FidelityFX/gpu/cas/ffx_cas_resources.h +++ b/sdk/include/FidelityFX/gpu/cas/ffx_cas_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_CAS_RESOURCES_H #define FFX_CAS_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/cas/ffx_cas_sharpen.h b/sdk/include/FidelityFX/gpu/cas/ffx_cas_sharpen.h index e2b5d63e..d1e9c7ea 100644 --- a/sdk/include/FidelityFX/gpu/cas/ffx_cas_sharpen.h +++ b/sdk/include/FidelityFX/gpu/cas/ffx_cas_sharpen.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #if FFX_HALF diff --git a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_common.h b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_common.h index c306bede..6bb310aa 100644 --- a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_common.h +++ b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_common.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #define TILE_SIZE_X 8 #define TILE_SIZE_Y 4 #define k_pushOff 4e-2f diff --git a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections.h b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections.h index bd1c72a5..06174b86 100644 --- a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections.h +++ b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #define TILE_CLASS_FULL_SW 0 #define TILE_CLASS_HALF_SW 1 #define TILE_CLASS_FULL_HW 2 diff --git a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_callbacks_glsl.h index dd5d62bf..c0b93817 100644 --- a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_callbacks_glsl.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include "ffx_classifier_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_callbacks_hlsl.h index 46260c62..420a9599 100644 --- a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_callbacks_hlsl.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include "ffx_classifier_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_common.h b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_common.h index 56cb905f..bb0ddb3d 100644 --- a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_common.h +++ b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_reflections_common.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + // Use hitcounter feedback #define FFX_CLASSIFIER_FLAGS_USE_HIT_COUNTER (1 << 0) // Traverse in screen space diff --git a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_resources.h b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_resources.h index 3236cfbe..c2632884 100644 --- a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_resources.h +++ b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_resources.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #ifndef FFX_CLASSIFIER_RESOURCES_H #define FFX_CLASSIFIER_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows.h b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows.h index 1c576d22..01d246c2 100644 --- a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows.h +++ b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + /// @defgroup FfxGPUClassifier FidelityFX Classifier /// /// FidelityFX Classifier GPU documentation /// diff --git a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows_callbacks_glsl.h index d9928085..5c5620f1 100644 --- a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows_callbacks_glsl.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include "ffx_classifier_resources.h" #include "ffx_core.h" diff --git a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows_callbacks_hlsl.h index e6d155d9..827ea978 100644 --- a/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/classifier/ffx_classifier_shadows_callbacks_hlsl.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include "ffx_classifier_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_callbacks_glsl.h index a86b6f89..8c68d5b5 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_denoiser_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_callbacks_hlsl.h index 3ad0cadf..9df600a8 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_denoiser_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_common.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_common.h index 2130dfac..9266bfdc 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_common.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_common.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_DNSR_REFLECTIONS_COMMON #define FFX_DNSR_REFLECTIONS_COMMON diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_config.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_config.h index 9d7066bc..1b27fe32 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_config.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_config.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_DNSR_REFLECTIONS_CONFIG #define FFX_DNSR_REFLECTIONS_CONFIG diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_prefilter.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_prefilter.h index 0e134958..7f1a00c5 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_prefilter.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_prefilter.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_DNSR_REFLECTIONS_PREFILTER #define FFX_DNSR_REFLECTIONS_PREFILTER diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_reproject.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_reproject.h index 29c8c15f..c4e357da 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_reproject.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_reproject.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_DNSR_REFLECTIONS_REPROJECT #define FFX_DNSR_REFLECTIONS_REPROJECT diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_resolve_temporal.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_resolve_temporal.h index 2c353504..3d78cb69 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_resolve_temporal.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_resolve_temporal.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_DNSR_REFLECTIONS_RESOLVE_TEMPORAL #define FFX_DNSR_REFLECTIONS_RESOLVE_TEMPORAL diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_resources.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_resources.h index ac0c010e..0c8b10fa 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_resources.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_SHADOWS_DENOISER_RESOURCES_H #define FFX_SHADOWS_DENOISER_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_glsl.h index d4125316..1ad5641a 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_glsl.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include "ffx_denoiser_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_hlsl.h index 2511109b..8f946da1 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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 "ffx_denoiser_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_filter.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_filter.h index 17af30d4..0f92f9d1 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_filter.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_filter.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : -// +// Copyright (c) 2023 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 +// +// 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 +// 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 FFX_DNSR_SHADOWS_FILTER_HLSL #define FFX_DNSR_SHADOWS_FILTER_HLSL diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_prepare.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_prepare.h index 4f511bed..1a031840 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_prepare.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_prepare.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_DNSR_SHADOWS_PREPARESHADOWMASK_HLSL #define FFX_DNSR_SHADOWS_PREPARESHADOWMASK_HLSL diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_tileclassification.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_tileclassification.h index 2aa1f423..369556de 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_tileclassification.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_tileclassification.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : -// +// Copyright (c) 2023 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 +// +// 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 +// 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 FFX_DNSR_SHADOWS_TILECLASSIFICATION_HLSL #define FFX_DNSR_SHADOWS_TILECLASSIFICATION_HLSL diff --git a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_util.h b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_util.h index d226f662..5d77db27 100644 --- a/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_util.h +++ b/sdk/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_util.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : -// +// Copyright (c) 2023 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 +// +// 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 +// 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 FFX_DNSR_SHADOWS_UTILS_HLSL #define FFX_DNSR_SHADOWS_UTILS_HLSL diff --git a/sdk/include/FidelityFX/gpu/dof/ffx_dof_blur.h b/sdk/include/FidelityFX/gpu/dof/ffx_dof_blur.h index 4fd72cb6..5b1f9282 100644 --- a/sdk/include/FidelityFX/gpu/dof/ffx_dof_blur.h +++ b/sdk/include/FidelityFX/gpu/dof/ffx_dof_blur.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #include "ffx_dof_common.h" diff --git a/sdk/include/FidelityFX/gpu/dof/ffx_dof_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/dof/ffx_dof_callbacks_glsl.h index 53c5d381..0ca3a0b2 100644 --- a/sdk/include/FidelityFX/gpu/dof/ffx_dof_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/dof/ffx_dof_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_dof_resources.h" #include "ffx_core.h" diff --git a/sdk/include/FidelityFX/gpu/dof/ffx_dof_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/dof/ffx_dof_callbacks_hlsl.h index 1abda8c9..02e2eb03 100644 --- a/sdk/include/FidelityFX/gpu/dof/ffx_dof_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/dof/ffx_dof_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_dof_resources.h" #include "ffx_core.h" #include "ffx_dof_common.h" diff --git a/sdk/include/FidelityFX/gpu/dof/ffx_dof_common.h b/sdk/include/FidelityFX/gpu/dof/ffx_dof_common.h index 451b115c..48a2ec45 100644 --- a/sdk/include/FidelityFX/gpu/dof/ffx_dof_common.h +++ b/sdk/include/FidelityFX/gpu/dof/ffx_dof_common.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_DOF_COMMON_H #define FFX_DOF_COMMON_H diff --git a/sdk/include/FidelityFX/gpu/dof/ffx_dof_composite.h b/sdk/include/FidelityFX/gpu/dof/ffx_dof_composite.h index e358f3dc..8273cdab 100644 --- a/sdk/include/FidelityFX/gpu/dof/ffx_dof_composite.h +++ b/sdk/include/FidelityFX/gpu/dof/ffx_dof_composite.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #include "ffx_dof_common.h" @@ -218,8 +218,8 @@ FfxHalfOpt4 FfxDofFinalCombineColors(FfxUInt32x2 coord, FfxUInt32x2 relCoord, Ff // if any FG sample has zero weight, the interpolation is invalid. if (minFgW == FfxHalfOpt(0)) fg.a = FfxHalfOpt(0); FfxHalfOpt c = FfxHalfOpt(2) * FfxHalfOpt(abs(FfxDofGetCoc(d))); // double it for full-res pixels - FfxHalfOpt c1 = ffxSaturate(c - FfxHalfOpt(0.5)); // lerp factor for full vs. fixed 1.5px blur - FfxHalfOpt c2 = ffxSaturate(c - FfxHalfOpt(1.5)); // lerp factor for prev vs. quarter res + FfxHalfOpt c1 = FfxHalfOpt(ffxSaturate(c - FfxHalfOpt(0.5))); // lerp factor for full vs. fixed 1.5px blur + FfxHalfOpt c2 = FfxHalfOpt(ffxSaturate(c - FfxHalfOpt(1.5))); // lerp factor for prev vs. quarter res if (fg.a > FfxHalfOpt(0.3)) c2 = FfxHalfOpt(1); if (bg.a == FfxHalfOpt(0)) c2 = FfxHalfOpt(0); FfxHalfOpt3 combinedColor = ffxLerp(full, fixBlurred, c1); diff --git a/sdk/include/FidelityFX/gpu/dof/ffx_dof_dilate_depth.h b/sdk/include/FidelityFX/gpu/dof/ffx_dof_dilate_depth.h index ed5f620f..57a9d94e 100644 --- a/sdk/include/FidelityFX/gpu/dof/ffx_dof_dilate_depth.h +++ b/sdk/include/FidelityFX/gpu/dof/ffx_dof_dilate_depth.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #include "ffx_dof_common.h" diff --git a/sdk/include/FidelityFX/gpu/dof/ffx_dof_downsample_color.h b/sdk/include/FidelityFX/gpu/dof/ffx_dof_downsample_color.h index 6ba03b46..aa92a418 100644 --- a/sdk/include/FidelityFX/gpu/dof/ffx_dof_downsample_color.h +++ b/sdk/include/FidelityFX/gpu/dof/ffx_dof_downsample_color.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #ifndef FFX_DOF_OPTION_MAX_MIP @@ -71,9 +71,9 @@ FfxFloat16x4 FfxDofDownsampleQuadH(FfxFloat16x4 v0, FfxFloat16x4 v1, FfxFloat16x FfxFloat16 c1 = v1.a; FfxFloat16 c2 = v2.a; FfxFloat16 c3 = v3.a; - FfxFloat16 w1 = ffxSaturate(FfxFloat16(1.0) - abs(c0 - c1)); - FfxFloat16 w2 = ffxSaturate(FfxFloat16(1.0) - abs(c0 - c2)); - FfxFloat16 w3 = ffxSaturate(FfxFloat16(1.0) - abs(c0 - c3)); + FfxFloat16 w1 = FfxFloat16(ffxSaturate(FfxFloat16(1.0) - abs(c0 - c1))); + FfxFloat16 w2 = FfxFloat16(ffxSaturate(FfxFloat16(1.0) - abs(c0 - c2))); + FfxFloat16 w3 = FfxFloat16(ffxSaturate(FfxFloat16(1.0) - abs(c0 - c3))); FfxFloat16x3 color = v0.rgb + w1 * v1.rgb + w2 * v2.rgb + w3 * v3.rgb; FfxFloat16 weights = FfxFloat16(1.0) + w1 + w2 + w3; return FfxFloat16x4(color / weights, c0); diff --git a/sdk/include/FidelityFX/gpu/dof/ffx_dof_downsample_depth.h b/sdk/include/FidelityFX/gpu/dof/ffx_dof_downsample_depth.h index b61c452d..854bd4ad 100644 --- a/sdk/include/FidelityFX/gpu/dof/ffx_dof_downsample_depth.h +++ b/sdk/include/FidelityFX/gpu/dof/ffx_dof_downsample_depth.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #include "ffx_dof_common.h" diff --git a/sdk/include/FidelityFX/gpu/dof/ffx_dof_resources.h b/sdk/include/FidelityFX/gpu/dof/ffx_dof_resources.h index 3bdd8b0a..1710470e 100644 --- a/sdk/include/FidelityFX/gpu/dof/ffx_dof_resources.h +++ b/sdk/include/FidelityFX/gpu/dof/ffx_dof_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_DOF_RESOURCES_H #define FFX_DOF_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/ffx_common_types.h b/sdk/include/FidelityFX/gpu/ffx_common_types.h index 6bf9d8e3..ec70e52f 100644 --- a/sdk/include/FidelityFX/gpu/ffx_common_types.h +++ b/sdk/include/FidelityFX/gpu/ffx_common_types.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_COMMON_TYPES_H #define FFX_COMMON_TYPES_H @@ -132,7 +132,7 @@ typedef uint32_t FfxUInt32x4[4]; /// @ingroup HLSLTypes typedef bool FfxBoolean; -#if FFX_HLSL_6_2 +#if FFX_HLSL_SM>=62 /// @defgroup HLSL62Types HLSL 6.2 And Above Types /// HLSL 6.2 and above type defines for all commonly used variables @@ -204,7 +204,7 @@ typedef int32_t3 FfxInt32x3; /// @ingroup HLSL62Types typedef int32_t4 FfxInt32x4; -#else // #if defined(FFX_HLSL_6_2) +#else // #if FFX_HLSL_SM>=62 /// @defgroup HLSLBaseTypes HLSL 6.1 And Below Types /// HLSL 6.1 and below type defines for all commonly used variables @@ -234,11 +234,11 @@ typedef int2 FfxInt32x2; typedef int3 FfxInt32x3; typedef int4 FfxInt32x4; -#endif // #if defined(FFX_HLSL_6_2) +#endif // #if FFX_HLSL_SM>=62 #if FFX_HALF -#if FFX_HLSL_6_2 +#if FFX_HLSL_SM >= 62 typedef float16_t FfxFloat16; typedef float16_t2 FfxFloat16x2; @@ -260,7 +260,7 @@ typedef int16_t FfxInt16; typedef int16_t2 FfxInt16x2; typedef int16_t3 FfxInt16x3; typedef int16_t4 FfxInt16x4; -#else // #if FFX_HLSL_6_2 +#else // #if FFX_HLSL_SM>=62 typedef min16float FfxFloat16; typedef min16float2 FfxFloat16x2; typedef min16float3 FfxFloat16x3; @@ -281,7 +281,7 @@ typedef min16int FfxInt16; typedef min16int2 FfxInt16x2; typedef min16int3 FfxInt16x3; typedef min16int4 FfxInt16x4; -#endif // #if FFX_HLSL_6_2 +#endif // #if FFX_HLSL_SM>=62 #endif // FFX_HALF @@ -332,11 +332,11 @@ typedef min16int4 FfxInt16x4; // Global toggles: // #define FFX_HALF (1) -// #define FFX_HLSL_6_2 (1) +// #define FFX_HLSL_SM (62) #if FFX_HALF -#if FFX_HLSL_6_2 +#if FFX_HLSL_SM >= 62 #define FFX_MIN16_SCALAR( TypeName, BaseComponentType ) typedef BaseComponentType##16_t TypeName; #define FFX_MIN16_VECTOR( TypeName, BaseComponentType, COL ) typedef vector TypeName; @@ -346,7 +346,7 @@ typedef min16int4 FfxInt16x4; #define FFX_16BIT_VECTOR( TypeName, BaseComponentType, COL ) typedef vector TypeName; #define FFX_16BIT_MATRIX( TypeName, BaseComponentType, ROW, COL ) typedef matrix TypeName; -#else //FFX_HLSL_6_2 +#else //FFX_HLSL_SM>=62 #define FFX_MIN16_SCALAR( TypeName, BaseComponentType ) typedef min16##BaseComponentType TypeName; #define FFX_MIN16_VECTOR( TypeName, BaseComponentType, COL ) typedef vector TypeName; @@ -356,7 +356,7 @@ typedef min16int4 FfxInt16x4; #define FFX_16BIT_VECTOR( TypeName, BaseComponentType, COL ) FFX_MIN16_VECTOR( TypeName, BaseComponentType, COL ); #define FFX_16BIT_MATRIX( TypeName, BaseComponentType, ROW, COL ) FFX_MIN16_MATRIX( TypeName, BaseComponentType, ROW, COL ); -#endif //FFX_HLSL_6_2 +#endif //FFX_HLSL_SM>=62 #else //FFX_HALF diff --git a/sdk/include/FidelityFX/gpu/ffx_core.h b/sdk/include/FidelityFX/gpu/ffx_core.h index 13f3bb67..02f6b3f6 100644 --- a/sdk/include/FidelityFX/gpu/ffx_core.h +++ b/sdk/include/FidelityFX/gpu/ffx_core.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup FfxGPU GPU /// The FidelityFX SDK GPU References /// @@ -48,6 +48,11 @@ #if !defined(FFX_CORE_H) #define FFX_CORE_H +#ifdef __hlsl_dx_compiler +#pragma dxc diagnostic push +#pragma dxc diagnostic ignored "-Wambig-lit-shift" +#endif //__hlsl_dx_compiler + #include "ffx_common_types.h" #if defined(FFX_CPU) @@ -67,4 +72,9 @@ #include "ffx_core_gpu_common_half.h" #include "ffx_core_portability.h" #endif // #if defined(FFX_GPU) + +#ifdef __hlsl_dx_compiler +#pragma dxc diagnostic pop +#endif //__hlsl_dx_compiler + #endif // #if !defined(FFX_CORE_H) diff --git a/sdk/include/FidelityFX/gpu/ffx_core_cpu.h b/sdk/include/FidelityFX/gpu/ffx_core_cpu.h index 2745ab9b..865258d4 100644 --- a/sdk/include/FidelityFX/gpu/ffx_core_cpu.h +++ b/sdk/include/FidelityFX/gpu/ffx_core_cpu.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// A define for a true value in a boolean expression. /// /// @ingroup CPUTypes diff --git a/sdk/include/FidelityFX/gpu/ffx_core_glsl.h b/sdk/include/FidelityFX/gpu/ffx_core_glsl.h index 2cb4de86..339d970d 100644 --- a/sdk/include/FidelityFX/gpu/ffx_core_glsl.h +++ b/sdk/include/FidelityFX/gpu/ffx_core_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : -// +// Copyright (c) 2023 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 +// +// 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 +// 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. + /// @defgroup GLSLCore GLSL Core /// GLSL core defines and functions /// diff --git a/sdk/include/FidelityFX/gpu/ffx_core_gpu_common.h b/sdk/include/FidelityFX/gpu/ffx_core_gpu_common.h index ce64053e..2f687df9 100644 --- a/sdk/include/FidelityFX/gpu/ffx_core_gpu_common.h +++ b/sdk/include/FidelityFX/gpu/ffx_core_gpu_common.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// A define for a true value in a boolean expression. /// /// @ingroup GPUCore @@ -45,6 +45,9 @@ /// @ingroup GPUCore #define FFX_PI (3.14159) +FFX_STATIC const FfxFloat32 FFX_FP16_MIN = 6.10e-05f; +FFX_STATIC const FfxFloat32 FFX_FP16_MAX = 65504.0f; +FFX_STATIC const FfxFloat32 FFX_TONEMAP_EPSILON = 1.0f / FFX_FP16_MAX; /// Compute the reciprocal of value. /// diff --git a/sdk/include/FidelityFX/gpu/ffx_core_gpu_common_half.h b/sdk/include/FidelityFX/gpu/ffx_core_gpu_common_half.h index 15913dea..4c73daf1 100644 --- a/sdk/include/FidelityFX/gpu/ffx_core_gpu_common_half.h +++ b/sdk/include/FidelityFX/gpu/ffx_core_gpu_common_half.h @@ -1,27 +1,27 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_HALF -#if FFX_HLSL_6_2 +#if FFX_HLSL_SM >= 62 /// A define value for 16bit positive infinity. /// /// @ingroup GPUCore @@ -41,7 +41,7 @@ /// /// @ingroup GPUCore #define FFX_NEGATIVE_INFINITY_HALF FFX_TO_FLOAT16(0xfc00u) -#endif // FFX_HLSL_6_2 +#endif // #if FFX_HLSL_SM>=62 /// Compute the min of two values. /// @@ -563,7 +563,7 @@ FfxFloat16x4 ffxCopySignBitHalf(FfxFloat16x4 d, FfxFloat16x4 s) /// @ingroup GPUCore FfxFloat16 ffxIsSignedHalf(FfxFloat16 m) { - return ffxSaturate(m * FFX_BROADCAST_FLOAT16(FFX_NEGATIVE_INFINITY_HALF)); + return FfxFloat16(ffxSaturate(m * FFX_BROADCAST_FLOAT16(FFX_NEGATIVE_INFINITY_HALF))); } /// A single operation to return the following: @@ -586,7 +586,7 @@ FfxFloat16 ffxIsSignedHalf(FfxFloat16 m) /// @ingroup GPUCore FfxFloat16x2 ffxIsSignedHalf(FfxFloat16x2 m) { - return ffxSaturate(m * FFX_BROADCAST_FLOAT16X2(FFX_NEGATIVE_INFINITY_HALF)); + return FfxFloat16x2(ffxSaturate(m * FFX_BROADCAST_FLOAT16X2(FFX_NEGATIVE_INFINITY_HALF))); } /// A single operation to return the following: @@ -609,7 +609,7 @@ FfxFloat16x2 ffxIsSignedHalf(FfxFloat16x2 m) /// @ingroup GPUCore FfxFloat16x3 ffxIsSignedHalf(FfxFloat16x3 m) { - return ffxSaturate(m * FFX_BROADCAST_FLOAT16X3(FFX_NEGATIVE_INFINITY_HALF)); + return FfxFloat16x3(ffxSaturate(m * FFX_BROADCAST_FLOAT16X3(FFX_NEGATIVE_INFINITY_HALF))); } /// A single operation to return the following: @@ -632,7 +632,7 @@ FfxFloat16x3 ffxIsSignedHalf(FfxFloat16x3 m) /// @ingroup GPUCore FfxFloat16x4 ffxIsSignedHalf(FfxFloat16x4 m) { - return ffxSaturate(m * FFX_BROADCAST_FLOAT16X4(FFX_NEGATIVE_INFINITY_HALF)); + return FfxFloat16x4(ffxSaturate(m * FFX_BROADCAST_FLOAT16X4(FFX_NEGATIVE_INFINITY_HALF))); } /// A single operation to return the following: @@ -650,7 +650,7 @@ FfxFloat16x4 ffxIsSignedHalf(FfxFloat16x4 m) /// @ingroup GPUCore FfxFloat16 ffxIsGreaterThanZeroHalf(FfxFloat16 m) { - return ffxSaturate(m * FFX_BROADCAST_FLOAT16(FFX_POSITIVE_INFINITY_HALF)); + return FfxFloat16(ffxSaturate(m * FFX_BROADCAST_FLOAT16(FFX_POSITIVE_INFINITY_HALF))); } /// A single operation to return the following: @@ -668,7 +668,7 @@ FfxFloat16 ffxIsGreaterThanZeroHalf(FfxFloat16 m) /// @ingroup GPUCore FfxFloat16x2 ffxIsGreaterThanZeroHalf(FfxFloat16x2 m) { - return ffxSaturate(m * FFX_BROADCAST_FLOAT16X2(FFX_POSITIVE_INFINITY_HALF)); + return FfxFloat16x2(ffxSaturate(m * FFX_BROADCAST_FLOAT16X2(FFX_POSITIVE_INFINITY_HALF))); } /// A single operation to return the following: @@ -686,7 +686,7 @@ FfxFloat16x2 ffxIsGreaterThanZeroHalf(FfxFloat16x2 m) /// @ingroup GPUCore FfxFloat16x3 ffxIsGreaterThanZeroHalf(FfxFloat16x3 m) { - return ffxSaturate(m * FFX_BROADCAST_FLOAT16X3(FFX_POSITIVE_INFINITY_HALF)); + return FfxFloat16x3(ffxSaturate(m * FFX_BROADCAST_FLOAT16X3(FFX_POSITIVE_INFINITY_HALF))); } /// A single operation to return the following: @@ -704,7 +704,7 @@ FfxFloat16x3 ffxIsGreaterThanZeroHalf(FfxFloat16x3 m) /// @ingroup GPUCore FfxFloat16x4 ffxIsGreaterThanZeroHalf(FfxFloat16x4 m) { - return ffxSaturate(m * FFX_BROADCAST_FLOAT16X4(FFX_POSITIVE_INFINITY_HALF)); + return FfxFloat16x4(ffxSaturate(m * FFX_BROADCAST_FLOAT16X4(FFX_POSITIVE_INFINITY_HALF))); } /// Convert a 16bit floating point value to sortable integer. @@ -2223,7 +2223,7 @@ FfxFloat16x4 ffxSignedZeroOneAndOrHalf(FfxFloat16x4 x, FfxFloat16x4 y) /// @ingroup GPUCore FfxFloat16 ffxZeroOneAndOrHalf(FfxFloat16 x, FfxFloat16 y, FfxFloat16 z) { - return ffxSaturate(x * y + z); + return FfxFloat16(ffxSaturate(x * y + z)); } /// Conditional free logic AND operation using two half-precision values followed by @@ -2239,7 +2239,7 @@ FfxFloat16 ffxZeroOneAndOrHalf(FfxFloat16 x, FfxFloat16 y, FfxFloat16 z) /// @ingroup GPUCore FfxFloat16x2 ffxZeroOneAndOrHalf(FfxFloat16x2 x, FfxFloat16x2 y, FfxFloat16x2 z) { - return ffxSaturate(x * y + z); + return FfxFloat16x2(ffxSaturate(x * y + z)); } /// Conditional free logic AND operation using two half-precision values followed by @@ -2255,7 +2255,7 @@ FfxFloat16x2 ffxZeroOneAndOrHalf(FfxFloat16x2 x, FfxFloat16x2 y, FfxFloat16x2 z) /// @ingroup GPUCore FfxFloat16x3 ffxZeroOneAndOrHalf(FfxFloat16x3 x, FfxFloat16x3 y, FfxFloat16x3 z) { - return ffxSaturate(x * y + z); + return FfxFloat16x3(ffxSaturate(x * y + z)); } /// Conditional free logic AND operation using two half-precision values followed by @@ -2271,7 +2271,7 @@ FfxFloat16x3 ffxZeroOneAndOrHalf(FfxFloat16x3 x, FfxFloat16x3 y, FfxFloat16x3 z) /// @ingroup GPUCore FfxFloat16x4 ffxZeroOneAndOrHalf(FfxFloat16x4 x, FfxFloat16x4 y, FfxFloat16x4 z) { - return ffxSaturate(x * y + z); + return FfxFloat16x4(ffxSaturate(x * y + z)); } /// Given a half-precision value, returns 1.0 if greater than zero and 0.0 if not. @@ -2284,7 +2284,7 @@ FfxFloat16x4 ffxZeroOneAndOrHalf(FfxFloat16x4 x, FfxFloat16x4 y, FfxFloat16x4 z) /// @ingroup GPUCore FfxFloat16 ffxZeroOneIsGreaterThanZeroHalf(FfxFloat16 x) { - return ffxSaturate(x * FFX_BROADCAST_FLOAT16(FFX_POSITIVE_INFINITY_HALF)); + return FfxFloat16(ffxSaturate(x * FFX_BROADCAST_FLOAT16(FFX_POSITIVE_INFINITY_HALF))); } /// Given a half-precision value, returns 1.0 if greater than zero and 0.0 if not. @@ -2297,7 +2297,7 @@ FfxFloat16 ffxZeroOneIsGreaterThanZeroHalf(FfxFloat16 x) /// @ingroup GPUCore FfxFloat16x2 ffxZeroOneIsGreaterThanZeroHalf(FfxFloat16x2 x) { - return ffxSaturate(x * FFX_BROADCAST_FLOAT16X2(FFX_POSITIVE_INFINITY_HALF)); + return FfxFloat16x2(ffxSaturate(x * FFX_BROADCAST_FLOAT16X2(FFX_POSITIVE_INFINITY_HALF))); } /// Given a half-precision value, returns 1.0 if greater than zero and 0.0 if not. @@ -2310,7 +2310,7 @@ FfxFloat16x2 ffxZeroOneIsGreaterThanZeroHalf(FfxFloat16x2 x) /// @ingroup GPUCore FfxFloat16x3 ffxZeroOneIsGreaterThanZeroHalf(FfxFloat16x3 x) { - return ffxSaturate(x * FFX_BROADCAST_FLOAT16X3(FFX_POSITIVE_INFINITY_HALF)); + return FfxFloat16x3(ffxSaturate(x * FFX_BROADCAST_FLOAT16X3(FFX_POSITIVE_INFINITY_HALF))); } /// Given a half-precision value, returns 1.0 if greater than zero and 0.0 if not. @@ -2323,7 +2323,7 @@ FfxFloat16x3 ffxZeroOneIsGreaterThanZeroHalf(FfxFloat16x3 x) /// @ingroup GPUCore FfxFloat16x4 ffxZeroOneIsGreaterThanZeroHalf(FfxFloat16x4 x) { - return ffxSaturate(x * FFX_BROADCAST_FLOAT16X4(FFX_POSITIVE_INFINITY_HALF)); + return FfxFloat16x4(ffxSaturate(x * FFX_BROADCAST_FLOAT16X4(FFX_POSITIVE_INFINITY_HALF))); } /// Conditional free logic signed NOT operation using two half-precision FfxFloat32 values. @@ -2508,7 +2508,7 @@ FfxFloat16x4 ffxZeroOneSelectHalf(FfxFloat16x4 x, FfxFloat16x4 y, FfxFloat16x4 z /// @ingroup GPUCore FfxFloat16 ffxZeroOneIsSignedHalf(FfxFloat16 x) { - return ffxSaturate(x * FFX_BROADCAST_FLOAT16(FFX_NEGATIVE_INFINITY_HALF)); + return FfxFloat16(ffxSaturate(x * FFX_BROADCAST_FLOAT16(FFX_NEGATIVE_INFINITY_HALF))); } /// Given a half-precision value, returns 1.0 if less than zero and 0.0 if not. @@ -2521,7 +2521,7 @@ FfxFloat16 ffxZeroOneIsSignedHalf(FfxFloat16 x) /// @ingroup GPUCore FfxFloat16x2 ffxZeroOneIsSignedHalf(FfxFloat16x2 x) { - return ffxSaturate(x * FFX_BROADCAST_FLOAT16X2(FFX_NEGATIVE_INFINITY_HALF)); + return FfxFloat16x2(ffxSaturate(x * FFX_BROADCAST_FLOAT16X2(FFX_NEGATIVE_INFINITY_HALF))); } /// Given a half-precision value, returns 1.0 if less than zero and 0.0 if not. @@ -2534,7 +2534,7 @@ FfxFloat16x2 ffxZeroOneIsSignedHalf(FfxFloat16x2 x) /// @ingroup GPUCore FfxFloat16x3 ffxZeroOneIsSignedHalf(FfxFloat16x3 x) { - return ffxSaturate(x * FFX_BROADCAST_FLOAT16X3(FFX_NEGATIVE_INFINITY_HALF)); + return FfxFloat16x3(ffxSaturate(x * FFX_BROADCAST_FLOAT16X3(FFX_NEGATIVE_INFINITY_HALF))); } /// Given a half-precision value, returns 1.0 if less than zero and 0.0 if not. @@ -2547,7 +2547,7 @@ FfxFloat16x3 ffxZeroOneIsSignedHalf(FfxFloat16x3 x) /// @ingroup GPUCore FfxFloat16x4 ffxZeroOneIsSignedHalf(FfxFloat16x4 x) { - return ffxSaturate(x * FFX_BROADCAST_FLOAT16X4(FFX_NEGATIVE_INFINITY_HALF)); + return FfxFloat16x4(ffxSaturate(x * FFX_BROADCAST_FLOAT16X4(FFX_NEGATIVE_INFINITY_HALF))); } /// Compute a Rec.709 color space. diff --git a/sdk/include/FidelityFX/gpu/ffx_core_hlsl.h b/sdk/include/FidelityFX/gpu/ffx_core_hlsl.h index 18f31472..8ea0eea4 100644 --- a/sdk/include/FidelityFX/gpu/ffx_core_hlsl.h +++ b/sdk/include/FidelityFX/gpu/ffx_core_hlsl.h @@ -1,30 +1,37 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : -// +// Copyright (c) 2023 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 +// +// 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 +// 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. + /// @defgroup HLSLCore HLSL Core /// HLSL core defines and functions /// /// @ingroup FfxHLSL +#define DECLARE_SRV_REGISTER(regIndex) t##regIndex +#define DECLARE_UAV_REGISTER(regIndex) u##regIndex +#define DECLARE_CB_REGISTER(regIndex) b##regIndex +#define FFX_DECLARE_SRV(regIndex) register(DECLARE_SRV_REGISTER(regIndex)) +#define FFX_DECLARE_UAV(regIndex) register(DECLARE_UAV_REGISTER(regIndex)) +#define FFX_DECLARE_CB(regIndex) register(DECLARE_CB_REGISTER(regIndex)) + /// A define for abstracting shared memory between shading languages. /// /// @ingroup HLSLCore @@ -1264,7 +1271,7 @@ FfxUInt32x2 FFX_MIN16_U4ToUint32x2(FFX_MIN16_U4 x) #define FFX_UINT16X2_TO_UINT32(x) FFX_MIN16_U2ToUint32(FFX_MIN16_U2(x)) #define FFX_UINT16X4_TO_UINT32X2(x) FFX_MIN16_U4ToUint32x2(FFX_MIN16_U4(x)) -#if defined(FFX_HLSL_6_2) && !defined(FFX_NO_16_BIT_CAST) +#if (FFX_HLSL_SM >= 62) && !defined(FFX_NO_16_BIT_CAST) #define FFX_TO_UINT16(x) asuint16(x) #define FFX_TO_UINT16X2(x) asuint16(x) #define FFX_TO_UINT16X3(x) asuint16(x) @@ -1274,9 +1281,9 @@ FfxUInt32x2 FFX_MIN16_U4ToUint32x2(FFX_MIN16_U4 x) #define FFX_TO_UINT16X2(a) FFX_MIN16_U2(FFX_TO_UINT16((a).x), FFX_TO_UINT16((a).y)) #define FFX_TO_UINT16X3(a) FFX_MIN16_U3(FFX_TO_UINT16((a).x), FFX_TO_UINT16((a).y), FFX_TO_UINT16((a).z)) #define FFX_TO_UINT16X4(a) FFX_MIN16_U4(FFX_TO_UINT16((a).x), FFX_TO_UINT16((a).y), FFX_TO_UINT16((a).z), FFX_TO_UINT16((a).w)) -#endif // #if defined(FFX_HLSL_6_2) && !defined(FFX_NO_16_BIT_CAST) +#endif // #if (FFX_HLSL_SM>=62) && !defined(FFX_NO_16_BIT_CAST) -#if defined(FFX_HLSL_6_2) && !defined(FFX_NO_16_BIT_CAST) +#if (FFX_HLSL_SM >= 62) && !defined(FFX_NO_16_BIT_CAST) #define FFX_TO_FLOAT16(x) asfloat16(x) #define FFX_TO_FLOAT16X2(x) asfloat16(x) #define FFX_TO_FLOAT16X3(x) asfloat16(x) @@ -1286,7 +1293,7 @@ FfxUInt32x2 FFX_MIN16_U4ToUint32x2(FFX_MIN16_U4 x) #define FFX_TO_FLOAT16X2(a) FFX_MIN16_F2(FFX_TO_FLOAT16((a).x), FFX_TO_FLOAT16((a).y)) #define FFX_TO_FLOAT16X3(a) FFX_MIN16_F3(FFX_TO_FLOAT16((a).x), FFX_TO_FLOAT16((a).y), FFX_TO_FLOAT16((a).z)) #define FFX_TO_FLOAT16X4(a) FFX_MIN16_F4(FFX_TO_FLOAT16((a).x), FFX_TO_FLOAT16((a).y), FFX_TO_FLOAT16((a).z), FFX_TO_FLOAT16((a).w)) -#endif // #if defined(FFX_HLSL_6_2) && !defined(FFX_NO_16_BIT_CAST) +#endif // #if (FFX_HLSL_SM>=62) && !defined(FFX_NO_16_BIT_CAST) //============================================================================================================================== #define FFX_BROADCAST_FLOAT16(a) FFX_MIN16_F(a) diff --git a/sdk/include/FidelityFX/gpu/ffx_core_portability.h b/sdk/include/FidelityFX/gpu/ffx_core_portability.h index 3c6dcf0e..84a62d6b 100644 --- a/sdk/include/FidelityFX/gpu/ffx_core_portability.h +++ b/sdk/include/FidelityFX/gpu/ffx_core_portability.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + FfxFloat32x3 opAAddOneF3(FfxFloat32x3 d, FfxFloat32x3 a, FfxFloat32 b) { d = a + ffxBroadcast3(b); diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation.h new file mode 100644 index 00000000..bd1e085a --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation.h @@ -0,0 +1,170 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_H +#define FFX_FRAMEINTERPOLATION_H + +struct InterpolationSourceColor +{ + FfxFloat32x3 fRaw; + FfxFloat32x3 fLinear; + FfxFloat32 fBilinearWeightSum; +}; + +InterpolationSourceColor SampleTextureBilinear(FfxInt32x2 iPxPos, Texture2D tex, FfxFloat32x2 fUv, FfxFloat32x2 fMotionVector, FfxInt32x2 texSize) +{ + InterpolationSourceColor result = (InterpolationSourceColor)0; + + FfxFloat32x2 fReprojectedUv = fUv + fMotionVector; + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fReprojectedUv, texSize); + + FfxFloat32x3 fColor = 0.0f; + FfxFloat32 fWeightSum = 0.0f; + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) { + + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, texSize)) { + + FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex]; + + fColor += tex[iSamplePos].rgb * fWeight; + fWeightSum += fWeight; + } + } + + //normalize colors + fColor = (fWeightSum != 0.0f) ? fColor / fWeightSum : FfxFloat32x3(0.0f, 0.0f, 0.0f); + + result.fRaw = fColor; + result.fLinear = RawRGBToLinear(fColor); + result.fBilinearWeightSum = fWeightSum; + + return result; +} + +void updateInPaintingWeight(inout FfxFloat32 fInPaintingWeight, FfxFloat32 fFactor) +{ + fInPaintingWeight = ffxSaturate(ffxMax(fInPaintingWeight, fFactor)); +} + +void computeInterpolatedColor(FfxUInt32x2 iPxPos, out FfxFloat32x3 fInterpolatedColor, inout FfxFloat32 fInPaintingWeight) +{ + const FfxFloat32x2 fUv = (FfxFloat32x2(iPxPos) + 0.5f) / DisplaySize(); + const FfxFloat32x2 fLrUv = fUv * (FfxFloat32x2(RenderSize()) / GetMaxRenderSize()); + + VectorFieldEntry gameMv; + LoadInpaintedGameFieldMv(fUv, gameMv); + + VectorFieldEntry ofMv; + SampleOpticalFlowMotionVectorField(fUv, ofMv); + + // Binarize disucclusion factor + FfxFloat32x2 fDisocclusionFactor = (ffxSaturate(SampleDisocclusionMask(fLrUv).xy) == 1.0f); + + InterpolationSourceColor fPrevColorGame = SampleTextureBilinear(iPxPos, PreviousBackbufferTexture(), fUv, +gameMv.fMotionVector, DisplaySize()); + InterpolationSourceColor fCurrColorGame = SampleTextureBilinear(iPxPos, CurrentBackbufferTexture(), fUv, -gameMv.fMotionVector, DisplaySize()); + + InterpolationSourceColor fPrevColorOF = SampleTextureBilinear(iPxPos, PreviousBackbufferTexture(), fUv, +ofMv.fMotionVector, DisplaySize()); + InterpolationSourceColor fCurrColorOF = SampleTextureBilinear(iPxPos, CurrentBackbufferTexture(), fUv, -ofMv.fMotionVector, DisplaySize()); + + FfxFloat32 fBilinearWeightSum = 0.0f; + FfxFloat32 fDisoccludedFactor = 0.0f; + + // Disocclusion logic + { + fDisocclusionFactor.x *= !gameMv.bNegOutside; + fDisocclusionFactor.y *= !gameMv.bPosOutside; + + // Inpaint in bi-directional disocclusion areas + updateInPaintingWeight(fInPaintingWeight, length(fDisocclusionFactor) <= FFX_FRAMEINTERPOLATION_EPSILON); + + FfxFloat32 t = 0.5f; + t += 0.5f * (1 - (fDisocclusionFactor.x)); + t -= 0.5f * (1 - (fDisocclusionFactor.y)); + + fInterpolatedColor = ffxLerp(fPrevColorGame.fRaw, fCurrColorGame.fRaw, ffxSaturate(t)); + fBilinearWeightSum = ffxLerp(fPrevColorGame.fBilinearWeightSum, fCurrColorGame.fBilinearWeightSum, ffxSaturate(t)); + + fDisoccludedFactor = ffxSaturate(1 - ffxMin(fDisocclusionFactor.x, fDisocclusionFactor.y)); + + if (fPrevColorGame.fBilinearWeightSum == 0.0f) + { + fInterpolatedColor = fCurrColorGame.fRaw; + fBilinearWeightSum = fCurrColorGame.fBilinearWeightSum; + } + else if (fCurrColorGame.fBilinearWeightSum == 0.0f) + { + fInterpolatedColor = fPrevColorGame.fRaw; + fBilinearWeightSum = fPrevColorGame.fBilinearWeightSum; + } + } + + { + + FfxFloat32 ofT = 0.5f; + + if (fPrevColorOF.fBilinearWeightSum > 0 && fCurrColorOF.fBilinearWeightSum > 0) + { + ofT = 0.5f; + } + else if (fPrevColorOF.fBilinearWeightSum > 0) + { + ofT = 0; + } else { + ofT = 1; + } + + const FfxFloat32x3 ofColor = ffxLerp(fPrevColorOF.fRaw, fCurrColorOF.fRaw, ofT); + + FfxFloat32 fOF_Sim = NormalizedDot3(fPrevColorOF.fRaw, fCurrColorOF.fRaw); + FfxFloat32 fGame_Sim = NormalizedDot3(fPrevColorGame.fRaw, fCurrColorGame.fRaw); + + fGame_Sim = ffxLerp(ffxMax(FFX_FRAMEINTERPOLATION_EPSILON, fGame_Sim), 1.0f, ffxSaturate(fDisoccludedFactor)); + FfxFloat32 fGameMvBias = ffxPow(ffxSaturate(fGame_Sim / ffxMax(FFX_FRAMEINTERPOLATION_EPSILON, fOF_Sim)), 1.0f); + + const FfxFloat32 fFrameIndexFactor = FrameIndexSinceLastReset() < 10.0f; + fGameMvBias = ffxLerp(fGameMvBias, 1.0f, fFrameIndexFactor); + + fInterpolatedColor = ffxLerp(ofColor, fInterpolatedColor, ffxSaturate(fGameMvBias)); + } +} + +void computeFrameinterpolation(FfxUInt32x2 iPxPos) +{ + FfxFloat32x3 fColor = FfxFloat32x3(0, 0, 0); + FfxFloat32 fInPaintingWeight = 0.0f; + + if (FrameIndexSinceLastReset() > 0) + { + computeInterpolatedColor(iPxPos, fColor, fInPaintingWeight); + } + else + { + fColor = LoadCurrentBackbuffer(iPxPos); + } + + StoreFrameinterpolationOutput(iPxPos, FfxFloat32x4(fColor, fInPaintingWeight)); +} + +#endif // FFX_FRAMEINTERPOLATION_H diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h new file mode 100644 index 00000000..9d9a9835 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h @@ -0,0 +1,689 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "ffx_frameinterpolation_resources.h" +#include "ffx_core.h" + +#define COUNTER_SPD 0 +#define COUNTER_FRAME_INDEX_SINCE_LAST_RESET 1 + + /////////////////////////////////////////////// + // declare CBs and CB accessors +/////////////////////////////////////////////// +#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION) + cbuffer cbFI : FFX_DECLARE_CB(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION) + { + FfxInt32x2 renderSize; + FfxInt32x2 displaySize; + + FfxFloat32x2 displaySizeRcp; + FfxFloat32 cameraNear; + FfxFloat32 cameraFar; + + FfxInt32x2 upscalerTargetSize; + FfxInt32 Mode; + FfxInt32 reset; + + FfxFloat32x4 fDeviceToViewDepth; + + FfxFloat32 deltaTime; + FfxFloat32x2 UNUSED; + FfxInt32 HUDLessAttachedFactor; + + FfxFloat32x2 opticalFlowScale; + FfxInt32 opticalFlowBlockSize; + FfxUInt32 dispatchFlags; + + FfxInt32 opticalFlowHalfResMode; + FfxInt32x2 maxRenderSize; + FfxInt32 NumInstances; + + FfxInt32x2 interpolationRectBase; + FfxInt32x2 interpolationRectSize; + + FfxFloat32x3 debugBarColor; + FfxUInt32 backBufferTransferFunction; + + FfxFloat32x2 minMaxLuminance; + FfxFloat32 fTanHalfFOV; + FfxInt32 _pad1; + } + + const FfxInt32x2 RenderSize() + { + return renderSize; + } + + const FfxInt32x2 DisplaySize() + { + return displaySize; + } + + const FfxBoolean Reset() + { + return reset == 1; + } + + FfxFloat32x4 DeviceToViewSpaceTransformFactors() + { + return fDeviceToViewDepth; + } + + FfxInt32x2 GetOpticalFlowSize() + { + FfxInt32x2 iOpticalFlowSize = (1.0f / opticalFlowScale) / FfxFloat32x2(opticalFlowBlockSize.xx); + + return iOpticalFlowSize; + } + + FfxInt32x2 GetOpticalFlowSize2() + { + return GetOpticalFlowSize() * 1; + } + + FfxFloat32x2 GetOpticalFlowScale() + { + return opticalFlowScale; + } + + FfxInt32 GetOpticalFlowBlockSize() + { + return opticalFlowBlockSize; + } + + FfxInt32 GetHUDLessAttachedFactor() + { + return HUDLessAttachedFactor; + } + + FfxUInt32 GetDispatchFlags() + { + return dispatchFlags; + } + + FfxInt32x2 GetMaxRenderSize() + { + return maxRenderSize; + } + + FfxInt32 GetOpticalFlowHalfResMode() + { + return opticalFlowHalfResMode; + } + + FfxFloat32x3 GetDebugBarColor() + { + return debugBarColor; + } + + FfxFloat32 TanHalfFoV() + { + return fTanHalfFOV; + } + + FfxUInt32 BackBufferTransferFunction() + { + return backBufferTransferFunction; + } + + FfxFloat32 MinLuminance() + { + return minMaxLuminance[0]; + } + + FfxFloat32 MaxLuminance() + { + return minMaxLuminance[1]; + } + +#endif + + + + + /////////////////////////////////////////////// + // declare samplers +/////////////////////////////////////////////// + + +SamplerState s_PointClamp : register(s0); +SamplerState s_LinearClamp : register(s1); + + /////////////////////////////////////////////// + // declare SRVs and SRV accessors +/////////////////////////////////////////////// + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_PREVIOUS_INTERPOLATION_SOURCE + Texture2D r_previous_interpolation_source : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_PREVIOUS_INTERPOLATION_SOURCE); + + FfxFloat32x3 LoadPreviousBackbuffer(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_previous_interpolation_source[iPxPos].rgb; + } + FfxFloat32x3 SamplePreviousBackbuffer(FFX_PARAMETER_IN FfxFloat32x2 fUv) + { + return r_previous_interpolation_source.SampleLevel(s_LinearClamp, fUv, 0).xyz; + } + Texture2D PreviousBackbufferTexture() + { + return r_previous_interpolation_source; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE + Texture2D r_current_interpolation_source : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE); + + FfxFloat32x3 LoadCurrentBackbuffer(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_current_interpolation_source[iPxPos].rgb; + } + FfxFloat32x3 SampleCurrentBackbuffer(FFX_PARAMETER_IN FfxFloat32x2 fUv) + { + return r_current_interpolation_source.SampleLevel(s_LinearClamp, fUv, 0).xyz; + } + Texture2D CurrentBackbufferTexture() + { + return r_current_interpolation_source; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS + Texture2D r_dilated_motion_vectors : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS); + + FfxFloat32x2 LoadDilatedMotionVector(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_dilated_motion_vectors[iPxPos].xy; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH + Texture2D r_dilated_depth : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH); + + FfxFloat32 LoadDilatedDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_dilated_depth[iPxPos].x; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME + Texture2D r_reconstructed_depth_previous_frame : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME); + + FfxFloat32 LoadReconstructedDepthPreviousFrame(FFX_PARAMETER_IN FfxInt32x2 iPxInput) + { + return asfloat(r_reconstructed_depth_previous_frame[iPxInput]); + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME + Texture2D r_reconstructed_depth_interpolated_frame : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME); + + FfxFloat32 LoadEstimatedInterpolationFrameDepth(FFX_PARAMETER_IN FfxInt32x2 iPxInput) + { + return asfloat(r_reconstructed_depth_interpolated_frame[iPxInput]); + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_DISOCCLUSION_MASK + Texture2D r_disocclusion_mask : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_DISOCCLUSION_MASK); + + FfxFloat32x4 LoadDisocclusionMask(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_disocclusion_mask[iPxPos]; + } + FfxFloat32x4 SampleDisocclusionMask(FFX_PARAMETER_IN FfxFloat32x2 fUv) + { + return r_disocclusion_mask.SampleLevel(s_LinearClamp, fUv, 0); + } +#endif + +#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y) + Texture2D r_game_motion_vector_field_x : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X); + Texture2D r_game_motion_vector_field_y : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y); + + FfxUInt32x2 LoadGameFieldMv(FFX_PARAMETER_IN FfxInt32x2 iPxSample) + { + FfxUInt32 packedX = r_game_motion_vector_field_x[iPxSample]; + FfxUInt32 packedY = r_game_motion_vector_field_y[iPxSample]; + + return FfxUInt32x2(packedX, packedY); + } +#endif + +#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y) + Texture2D r_optical_flow_motion_vector_field_x : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X); + Texture2D r_optical_flow_motion_vector_field_y : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y); + + FfxUInt32x2 LoadOpticalFlowFieldMv(FFX_PARAMETER_IN FfxInt32x2 iPxSample) + { + FfxUInt32 packedX = r_optical_flow_motion_vector_field_x[iPxSample]; + FfxUInt32 packedY = r_optical_flow_motion_vector_field_y[iPxSample]; + + return FfxUInt32x2(packedX, packedY); + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW + Texture2D r_optical_flow : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW); + + #if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION) + FfxFloat32x2 LoadOpticalFlow(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_optical_flow[iPxPos] * GetOpticalFlowScale(); + } + #endif +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_UPSAMPLED + Texture2D r_optical_flow_upsampled : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_UPSAMPLED); + + FfxFloat32x2 LoadOpticalFlowUpsampled(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_optical_flow_upsampled[iPxPos]; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE + Texture2D r_optical_flow_confidence : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE); + + FfxFloat32 LoadOpticalFlowConfidence(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_optical_flow_confidence[iPxPos].y; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION + Texture2D r_optical_flow_global_motion : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION); + + FfxUInt32 LoadOpticalFlowGlobalMotion(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_optical_flow_global_motion[iPxPos]; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION + Texture2D r_optical_flow_scd : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION); + + FfxUInt32 LoadOpticalFlowSceneChangeDetection(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_optical_flow_scd[iPxPos]; + } + + FfxBoolean HasSceneChanged() + { + #define SCD_OUTPUT_HISTORY_BITS_SLOT 1 + //if (FrameIndex() <= 5) // threshold according to original OpenCL code + //{ + // return 1.0; + //} + //else + { + // Report that the scene is changed if the change was detected in any of the + // 4 previous frames (0xfu - covers 4 history bits). + return (r_optical_flow_scd[FfxInt32x2(SCD_OUTPUT_HISTORY_BITS_SLOT, 0)] & 0xfu) != 0; + } + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_DEBUG + Texture2D r_optical_flow_debug : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_DEBUG); + + FfxFloat32x4 LoadOpticalFlowDebug(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_optical_flow_debug[iPxPos]; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OUTPUT + Texture2D r_output : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OUTPUT); + + FfxFloat32x4 LoadFrameInterpolationOutput(FFX_PARAMETER_IN FfxInt32x2 iPxInput) + { + return r_output[iPxInput]; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID + Texture2D r_inpainting_pyramid : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID); + + FfxFloat32x4 LoadInpaintingPyramid(FFX_PARAMETER_IN FfxInt32 mipLevel, FFX_PARAMETER_IN FfxUInt32x2 iPxInput) + { + return r_inpainting_pyramid.mips[mipLevel][iPxInput]; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_PRESENT_BACKBUFFER + Texture2D r_present_backbuffer : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_PRESENT_BACKBUFFER); + + FfxFloat32x4 LoadPresentBackbuffer(FFX_PARAMETER_IN FfxInt32x2 iPxInput) + { + return r_present_backbuffer[iPxInput]; + } + FfxFloat32x4 SamplePresentBackbuffer(FFX_PARAMETER_IN FfxFloat32x2 fUv) + { + return r_present_backbuffer.SampleLevel(s_LinearClamp, fUv, 0); + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_COUNTERS + Texture2D r_counters : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_COUNTERS); + + FfxUInt32 LoadCounter(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return r_counters[iPxPos]; + } + + const FfxUInt32 FrameIndexSinceLastReset() + { + return LoadCounter(FfxUInt32x2(COUNTER_FRAME_INDEX_SINCE_LAST_RESET, 0)); + } +#endif + + + + /////////////////////////////////////////////// + // declare UAVs and UAV accessors +/////////////////////////////////////////////// +#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT + RWTexture2D rw_output : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT); + + FfxFloat32x4 RWLoadFrameinterpolationOutput(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return rw_output[iPxPos]; + } + + void StoreFrameinterpolationOutput(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x4 val) + { + rw_output[iPxPos] = val; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_MOTION_VECTORS + RWTexture2D rw_dilated_motion_vectors : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_MOTION_VECTORS); + + FfxFloat32x2 RWLoadDilatedMotionVectors(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return rw_dilated_motion_vectors[iPxPos]; + } + + void StoreDilatedMotionVectors(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 val) + { + rw_dilated_motion_vectors[iPxPos] = val; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_DEPTH + RWTexture2D rw_dilated_depth : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_DEPTH); + + FfxFloat32 RWLoadDilatedDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return rw_dilated_depth[iPxPos]; + } + + void StoreDilatedDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32 val) + { + rw_dilated_depth[iPxPos] = val; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME + RWTexture2D rw_reconstructed_depth_previous_frame : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME); + + FfxUInt32 RWLoadReconstructedDepthPreviousFrame(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return ffxAsFloat(rw_reconstructed_depth_previous_frame[iPxPos]); + } + + void StoreReconstructedDepthPreviousFrame(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 value) + { + FfxUInt32 uDepth = ffxAsUInt32(value); + rw_reconstructed_depth_previous_frame[iPxPos] = uDepth; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME + RWTexture2D rw_reconstructed_depth_interpolated_frame : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME); + + FfxFloat32 RWLoadReconstructedDepthInterpolatedFrame(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return ffxAsFloat(rw_reconstructed_depth_interpolated_frame[iPxPos]); + } + + void StoreReconstructedDepthInterpolatedFrame(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32 value) + { + FfxUInt32 uDepth = ffxAsUInt32(value); + rw_reconstructed_depth_interpolated_frame[iPxPos] = uDepth; + } + + void UpdateReconstructedDepthInterpolatedFrame(FfxInt32x2 iPxSample, FfxFloat32 fDepth) + { + FfxUInt32 uDepth = ffxAsUInt32(fDepth); + +#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH + InterlockedMax(rw_reconstructed_depth_interpolated_frame[iPxSample], uDepth); +#else + InterlockedMin(rw_reconstructed_depth_interpolated_frame[iPxSample], uDepth); // min for standard, max for inverted depth +#endif + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_DISOCCLUSION_MASK + RWTexture2D rw_disocclusion_mask : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_DISOCCLUSION_MASK); + + FfxFloat32x2 RWLoadDisocclusionMask(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return rw_disocclusion_mask[iPxPos]; + } + + void StoreDisocclusionMask(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 val) + { + rw_disocclusion_mask[iPxPos] = val; + } +#endif + +#if defined(FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y) + + RWTexture2D rw_game_motion_vector_field_x : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X); + RWTexture2D rw_game_motion_vector_field_y : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y); + + FfxUInt32 RWLoadGameMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return rw_game_motion_vector_field_x[iPxPos]; + } + + void StoreGameMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val) + { + rw_game_motion_vector_field_x[iPxPos] = val; + } + + FfxUInt32 RWLoadGameMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return rw_game_motion_vector_field_y[iPxPos]; + } + + void StoreGameMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val) + { + rw_game_motion_vector_field_y[iPxPos] = val; + } + + void UpdateGameMotionVectorField(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32x2 packedVector) + { + InterlockedMax(rw_game_motion_vector_field_x[iPxPos], packedVector.x); + InterlockedMax(rw_game_motion_vector_field_y[iPxPos], packedVector.y); + } + + FfxUInt32 UpdateGameMotionVectorFieldEx(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32x2 packedVector) + { + FfxUInt32 uPreviousValueX = 0; + FfxUInt32 uPreviousValueY = 0; + InterlockedMax(rw_game_motion_vector_field_x[iPxPos], packedVector.x, uPreviousValueX); + InterlockedMax(rw_game_motion_vector_field_y[iPxPos], packedVector.y, uPreviousValueY); + + const FfxUInt32 uExistingVectorFieldEntry = ffxMax(uPreviousValueX, uPreviousValueY); + + return uExistingVectorFieldEntry; + } +#endif + +#if defined(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y) + + RWTexture2D rw_optical_flow_motion_vector_field_x : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X); + RWTexture2D rw_optical_flow_motion_vector_field_y : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y); + + FfxUInt32 RWLoadOpticalflowMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return rw_optical_flow_motion_vector_field_x[iPxPos]; + } + void StoreOpticalflowMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val) + { + rw_optical_flow_motion_vector_field_x[iPxPos] = val; + } + FfxUInt32 RWLoadOpticalflowMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return rw_optical_flow_motion_vector_field_y[iPxPos]; + } + void StoreOpticalflowMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val) + { + rw_optical_flow_motion_vector_field_y[iPxPos] = val; + } + void UpdateOpticalflowMotionVectorField(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxInt32x2 packedVector) + { + InterlockedMax(rw_optical_flow_motion_vector_field_x[iPxPos], packedVector.x); + InterlockedMax(rw_optical_flow_motion_vector_field_y[iPxPos], packedVector.y); + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_UPSAMPLED + RWTexture2D rw_optical_flow_upsampled : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_UPSAMPLED); + + FfxFloat32x2 RWLoadOpticalFlowUpsampled(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return rw_optical_flow_upsampled[iPxPos]; + } + + void StoreOpticalFlowUpsampled(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 value) + { + rw_optical_flow_upsampled[iPxPos] = value; + } +#endif + +#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS + globallycoherent RWTexture2D rw_counters : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS); + + FfxUInt32 RWLoadCounter(FFX_PARAMETER_IN FfxInt32x2 iPxPos) + { + return rw_counters[iPxPos]; + } + + void StoreCounter(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 counter) + { + rw_counters[iPxPos] = counter; + } + void AtomicIncreaseCounter(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_OUT FfxUInt32 oldVal) + { + InterlockedAdd(rw_counters[iPxPos], 1, oldVal); + } +#endif + + +#if defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_0) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_1) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_2) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_3) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_4) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_5) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_6) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_7) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_8) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_9) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_10) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_11) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_12) + + RWTexture2D rw_inpainting_pyramid0 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_0); + RWTexture2D rw_inpainting_pyramid1 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_1); + RWTexture2D rw_inpainting_pyramid2 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_2); + RWTexture2D rw_inpainting_pyramid3 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_3); + RWTexture2D rw_inpainting_pyramid4 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_4); + globallycoherent RWTexture2D rw_inpainting_pyramid5 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_5); + RWTexture2D rw_inpainting_pyramid6 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_6); + RWTexture2D rw_inpainting_pyramid7 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_7); + RWTexture2D rw_inpainting_pyramid8 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_8); + RWTexture2D rw_inpainting_pyramid9 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_9); + RWTexture2D rw_inpainting_pyramid10 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_10); + RWTexture2D rw_inpainting_pyramid11 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_11); + RWTexture2D rw_inpainting_pyramid12 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_12); + + + FfxFloat32x4 RWLoadInpaintingPyramid(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 index) + { + #define LOAD(idx) \ + if (index == idx) \ + { \ + return rw_inpainting_pyramid##idx[iPxPos]; \ + } + LOAD(0); + LOAD(1); + LOAD(2); + LOAD(3); + LOAD(4); + LOAD(5); + LOAD(6); + LOAD(7); + LOAD(8); + LOAD(9); + LOAD(10); + LOAD(11); + LOAD(12); + return 0; + + #undef LOAD + } + + void StoreInpaintingPyramid(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x4 outValue, FFX_PARAMETER_IN FfxUInt32 index) + { + #define STORE(idx) \ + if (index == idx) \ + { \ + rw_inpainting_pyramid##idx[iPxPos] = outValue; \ + } + + STORE(0); + STORE(1); + STORE(2); + STORE(3); + STORE(4); + STORE(5); + STORE(6); + STORE(7); + STORE(8); + STORE(9); + STORE(10); + STORE(11); + STORE(12); + + #undef STORE + } +#endif diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_common.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_common.h new file mode 100644 index 00000000..775a117d --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_common.h @@ -0,0 +1,405 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 !defined(FFX_FRAMEINTERPOLATION_COMMON_H) +#define FFX_FRAMEINTERPOLATION_COMMON_H + +#define FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG (1 << 0) + +FFX_STATIC const FfxFloat32 FFX_FRAMEINTERPOLATION_EPSILON = 1e-03f; +FFX_STATIC const FfxFloat32 FFX_FRAMEINTERPOLATION_FLT_MAX = 3.402823466e+38f; +FFX_STATIC const FfxFloat32 FFX_FRAMEINTERPOLATION_FLT_MIN = 1.175494351e-38f; + +FFX_STATIC const FfxFloat32 fReconstructedDepthBilinearWeightThreshold = FFX_FRAMEINTERPOLATION_EPSILON; + +FfxFloat32 RGBToLuma(FfxFloat32x3 fLinearRgb) +{ + return dot(fLinearRgb, FfxFloat32x3(0.2126f, 0.7152f, 0.0722f)); +} + +FfxFloat32 LinearRec2020ToLuminance(FfxFloat32x3 linearRec2020RGB) +{ + FfxFloat32 fY = 0.2627 * linearRec2020RGB.x + 0.678 * linearRec2020RGB.y + 0.0593 * linearRec2020RGB.z; + return fY; +} + +FfxFloat32x3 ffxscRGBToLinear(FfxFloat32x3 value, FfxFloat32 minLuminance, FfxFloat32 maxLuminance) +{ + FfxFloat32x3 p = value - ffxBroadcast3(minLuminance / 80.0f); + return p / ffxBroadcast3((maxLuminance - minLuminance) / 80.0f); +} + +FfxFloat32x3 RawRGBToLinear(FfxFloat32x3 fRawRgb) +{ + FfxFloat32x3 fLinearRgb; + + switch (BackBufferTransferFunction()) + { + case 0: + fLinearRgb = ffxLinearFromSrgb(fRawRgb); + break; + case 1: + fLinearRgb = ffxLinearFromPQ(fRawRgb) * (10000.0f / MaxLuminance()); + break; + case 2: + fLinearRgb = ffxscRGBToLinear(fRawRgb, MinLuminance(), MaxLuminance()); + break; + } + + return fLinearRgb; +} + +FfxFloat32 RawRGBToLuminance(FfxFloat32x3 fRawRgb) +{ + FfxFloat32 fLuminance = 0.0f; + + switch (BackBufferTransferFunction()) + { + case 0: + fLuminance = RGBToLuma(RawRGBToLinear(fRawRgb)); + break; + case 1: + fLuminance = LinearRec2020ToLuminance(RawRGBToLinear(fRawRgb)); + break; + case 2: + fLuminance = RGBToLuma(RawRGBToLinear(fRawRgb)); + break; + } + + return fLuminance; +} + +FfxFloat32 RawRGBToPerceivedLuma(FfxFloat32x3 fRawRgb) +{ + FfxFloat32 fLuminance = RawRGBToLuminance(fRawRgb); + + FfxFloat32 fPercievedLuminance = 0; + if (fLuminance <= 216.0f / 24389.0f) + { + fPercievedLuminance = fLuminance * (24389.0f / 27.0f); + } + else + { + fPercievedLuminance = ffxPow(fLuminance, 1.0f / 3.0f) * 116.0f - 16.0f; + } + + return fPercievedLuminance * 0.01f; +} + +struct BilinearSamplingData +{ + FfxInt32x2 iOffsets[4]; + FfxFloat32 fWeights[4]; + FfxInt32x2 iBasePos; +}; + +BilinearSamplingData GetBilinearSamplingData(FfxFloat32x2 fUv, FfxInt32x2 iSize) +{ + BilinearSamplingData data; + + FfxFloat32x2 fPxSample = (fUv * iSize) - FfxFloat32x2(0.5f, 0.5f); + data.iBasePos = FfxInt32x2(floor(fPxSample)); + FfxFloat32x2 fPxFrac = frac(fPxSample); + + data.iOffsets[0] = FfxInt32x2(0, 0); + data.iOffsets[1] = FfxInt32x2(1, 0); + data.iOffsets[2] = FfxInt32x2(0, 1); + data.iOffsets[3] = FfxInt32x2(1, 1); + + data.fWeights[0] = (1 - fPxFrac.x) * (1 - fPxFrac.y); + data.fWeights[1] = (fPxFrac.x) * (1 - fPxFrac.y); + data.fWeights[2] = (1 - fPxFrac.x) * (fPxFrac.y); + data.fWeights[3] = (fPxFrac.x) * (fPxFrac.y); + + return data; +} + +#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION) +FfxFloat32 ConvertFromDeviceDepthToViewSpace(FfxFloat32 fDeviceDepth) +{ + const FfxFloat32x4 deviceToViewDepth = DeviceToViewSpaceTransformFactors(); + return deviceToViewDepth[1] / (fDeviceDepth - deviceToViewDepth[0]); +} + +FfxFloat32x2 ComputeNdc(FfxFloat32x2 fPxPos, FfxInt32x2 iSize) +{ + return fPxPos / FfxFloat32x2(iSize) * FfxFloat32x2(2.0f, -2.0f) + FfxFloat32x2(-1.0f, 1.0f); +} + +FfxFloat32x3 GetViewSpacePosition(FfxInt32x2 iViewportPos, FfxInt32x2 iViewportSize, FfxFloat32 fDeviceDepth) +{ + const FfxFloat32x4 fDeviceToViewDepth = DeviceToViewSpaceTransformFactors(); + + const FfxFloat32 Z = ConvertFromDeviceDepthToViewSpace(fDeviceDepth); + + const FfxFloat32x2 fNdcPos = ComputeNdc(iViewportPos, iViewportSize); + const FfxFloat32 X = fDeviceToViewDepth[2] * fNdcPos.x * Z; + const FfxFloat32 Y = fDeviceToViewDepth[3] * fNdcPos.y * Z; + + return FfxFloat32x3(X, Y, Z); +} +#endif + +FfxBoolean IsOnScreen(FfxInt32x2 pos, FfxInt32x2 size) +{ + return all((FfxUInt32x2)pos < (FfxUInt32x2)size); +} + +FfxBoolean IsUvInside(FfxFloat32x2 fUv) +{ + return (fUv.x > 0.0f && fUv.x < 1.0f) && (fUv.y > 0.0f && fUv.y < 1.0f); +} + +FfxFloat32 MinDividedByMax(const FfxFloat32 v0, const FfxFloat32 v1) +{ + const FfxFloat32 m = ffxMax(v0, v1); + return m != 0 ? ffxMin(v0, v1) / m : 0; +} + +FfxFloat32 NormalizedDot3(const FfxFloat32x3 v0, const FfxFloat32x3 v1) +{ + FfxFloat32 fMaxLength = ffxMax(length(v0), length(v1)); + + return fMaxLength > 0.0f ? dot(v0 / fMaxLength, v1 / fMaxLength) : 1.0f; +} + +FfxFloat32 NormalizedDot2(const FfxFloat32x2 v0, const FfxFloat32x2 v1) +{ + FfxFloat32 fMaxLength = ffxMax(length(v0), length(v1)); + + return fMaxLength > 0.0f ? dot(v0 / fMaxLength, v1 / fMaxLength) : 1.0f; +} + +FfxFloat32 CalculateStaticContentFactor(FfxFloat32x3 fCurrentInterpolationSource, FfxFloat32x3 fPresentColor) +{ + const FfxFloat32x3 fFactor = ffxSaturate(FfxFloat32x3( + ffxSaturate((1.0f - MinDividedByMax(fCurrentInterpolationSource.r, fPresentColor.r)) / 0.1f), + ffxSaturate((1.0f - MinDividedByMax(fCurrentInterpolationSource.g, fPresentColor.g)) / 0.1f), + ffxSaturate((1.0f - MinDividedByMax(fCurrentInterpolationSource.b, fPresentColor.b)) / 0.1f) + )); + + return max(fFactor.x, max(fFactor.y, fFactor.z)); +} + +// +// MOTION VECTOR FIELD +// + +FFX_STATIC const FfxUInt32 MOTION_VECTOR_FIELD_ENTRY_BIT_COUNT = 32; + +// Make sure all bit counts add up to MOTION_VECTOR_FIELD_ENTRY_BIT_COUNT +FFX_STATIC const FfxUInt32 MOTION_VECTOR_FIELD_VECTOR_COEFFICIENT_BIT_COUNT = 16; +FFX_STATIC const FfxUInt32 MOTION_VECTOR_FIELD_PRIORITY_LOW_BIT_COUNT = 5; +FFX_STATIC const FfxUInt32 MOTION_VECTOR_FIELD_PRIORITY_HIGH_BIT_COUNT = 10; +FFX_STATIC const FfxUInt32 MOTION_VECTOR_PRIMARY_VECTOR_INDICATION_BIT_COUNT = 1; + +FFX_STATIC const FfxUInt32 MOTION_VECTOR_FIELD_PRIMARY_VECTOR_INDICATION_BIT = (1U << (MOTION_VECTOR_FIELD_ENTRY_BIT_COUNT - 1)); + +FFX_STATIC const FfxUInt32 PRIORITY_LOW_MAX = (1U << MOTION_VECTOR_FIELD_PRIORITY_LOW_BIT_COUNT) - 1; +FFX_STATIC const FfxUInt32 PRIORITY_HIGH_MAX = (1U << MOTION_VECTOR_FIELD_PRIORITY_HIGH_BIT_COUNT) - 1; + +FFX_STATIC const FfxUInt32 PRIORITY_LOW_OFFSET = MOTION_VECTOR_FIELD_VECTOR_COEFFICIENT_BIT_COUNT; +FFX_STATIC const FfxUInt32 PRIORITY_HIGH_OFFSET = PRIORITY_LOW_OFFSET + MOTION_VECTOR_FIELD_PRIORITY_LOW_BIT_COUNT; +FFX_STATIC const FfxUInt32 PRIMARY_VECTOR_INDICATION_OFFSET = PRIORITY_HIGH_OFFSET + MOTION_VECTOR_FIELD_PRIORITY_HIGH_BIT_COUNT; + +struct VectorFieldEntry +{ + FfxFloat32x2 fMotionVector; + FfxFloat32 uHighPriorityFactor; + FfxFloat32 uLowPriorityFactor; + FfxBoolean bValid; + FfxBoolean bPrimary; + FfxBoolean bSecondary; + FfxBoolean bInPainted; + FfxFloat32 fVelocity; + FfxBoolean bNegOutside; + FfxBoolean bPosOutside; +}; + +FfxBoolean PackedVectorFieldEntryIsPrimary(FfxUInt32 packedEntry) +{ + return ((packedEntry & MOTION_VECTOR_FIELD_PRIMARY_VECTOR_INDICATION_BIT) != 0); +} + +FfxUInt32x2 PackVectorFieldEntries(FfxBoolean bIsPrimary, FfxUInt32 uHighPriorityFactor, FfxUInt32 uLowPriorityFactor, FfxFloat32x2 fMotionVector) +{ + const FfxUInt32 uPriority = + (bIsPrimary * MOTION_VECTOR_FIELD_PRIMARY_VECTOR_INDICATION_BIT) + | ((uHighPriorityFactor & PRIORITY_HIGH_MAX) << PRIORITY_HIGH_OFFSET) + | ((uLowPriorityFactor & PRIORITY_LOW_MAX) << PRIORITY_LOW_OFFSET); + + FfxUInt32 packedX = uPriority | f32tof16(fMotionVector.x); + FfxUInt32 packedY = uPriority | f32tof16(fMotionVector.y); + + return FfxUInt32x2(packedX, packedY); +} + +void UnpackVectorFieldEntries(FfxUInt32x2 packed, out VectorFieldEntry vfElement) +{ + vfElement.uHighPriorityFactor = FfxFloat32((packed.x >> PRIORITY_HIGH_OFFSET) & PRIORITY_HIGH_MAX) / PRIORITY_HIGH_MAX; + vfElement.uLowPriorityFactor = FfxFloat32((packed.x >> PRIORITY_LOW_OFFSET) & PRIORITY_LOW_MAX) / PRIORITY_LOW_MAX; + + vfElement.bPrimary = PackedVectorFieldEntryIsPrimary(packed.x); + vfElement.bValid = (vfElement.uHighPriorityFactor > 0.0f); + vfElement.bSecondary = vfElement.bValid && !vfElement.bPrimary; + + // Reverse priority factor for secondary vectors + if (vfElement.bSecondary) + { + vfElement.uHighPriorityFactor = 1.0f - vfElement.uHighPriorityFactor; + } + + vfElement.fMotionVector.x = f16tof32(packed.x); + vfElement.fMotionVector.y = f16tof32(packed.y); + vfElement.bInPainted = false; +} + +// +// MOTION VECTOR FIELD +// + +#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID) +FfxFloat32x4 ComputeMvInpaintingLevel(FfxFloat32x2 fUv, const FfxInt32 iMipLevel, const FfxInt32x2 iTexSize) +{ + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv, iTexSize); + + FfxFloat32 fSum = 0.0f; + FfxFloat32x4 fColor = 0; + fColor.z = 0; + + const FfxFloat32 fMaxPriorityFactor = 1.0f; + + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) + { + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, iTexSize)) + { + FfxFloat32x4 fSample = LoadInpaintingPyramid(iMipLevel, iSamplePos); + + const FfxFloat32 fPriorityFactor = fSample.z; + const FfxFloat32 fValidMvFactor = (fSample.z > 0); + const FfxFloat32 fSampleWeight = bilinearInfo.fWeights[iSampleIndex] * fValidMvFactor * fPriorityFactor; + + fSum += fSampleWeight; + fColor += fSample * fSampleWeight; + } + } + + fColor /= (fSum > 0.0f) ? fSum : 1.0f; + + return fColor; +} +#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y) + +void LoadInpaintedGameFieldMv(FfxFloat32x2 fUv, out VectorFieldEntry vfElement) +{ + FfxInt32x2 iPxSample = fUv * RenderSize(); + FfxUInt32x2 packedGameFieldMv = LoadGameFieldMv(iPxSample); + UnpackVectorFieldEntries(packedGameFieldMv, vfElement); + + if (!vfElement.bValid) + { + //FfxFloat32x2 fUv = (FfxFloat32x2(iPxSample) + 0.5f) / RenderSize(); + FfxInt32x2 iTexSize = RenderSize(); + + FfxFloat32x4 fInPaintedVector = 0; + for (FfxInt32 iMipLevel = 0; iMipLevel < 11 && (fInPaintedVector.w == 0.0f); iMipLevel++) + { + iTexSize *= 0.5f; + + fInPaintedVector = ComputeMvInpaintingLevel(fUv, iMipLevel, iTexSize); + } + + vfElement.fMotionVector = fInPaintedVector.xy; + vfElement.uHighPriorityFactor = fInPaintedVector.z; + vfElement.uLowPriorityFactor = fInPaintedVector.w; + vfElement.bInPainted = true; + } + + vfElement.bNegOutside = !IsUvInside(fUv - vfElement.fMotionVector); + vfElement.bPosOutside = !IsUvInside(fUv + vfElement.fMotionVector); + vfElement.fVelocity = length(vfElement.fMotionVector); +} +#endif +#endif + +#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y) && \ + defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION) +void SampleOpticalFlowMotionVectorField(FfxFloat32x2 fUv, out VectorFieldEntry vfElement) +{ + const FfxFloat32 scaleFactor = 1.0f; + + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv, GetOpticalFlowSize2() * scaleFactor); + + vfElement = (VectorFieldEntry)0; + + FfxFloat32 fWeightSum = 0.0f; + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) + { + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, GetOpticalFlowSize2() * scaleFactor)) + { + const FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex]; + + VectorFieldEntry fOfVectorSample = (VectorFieldEntry)0; + FfxInt32x2 packedOpticalFlowMv = LoadOpticalFlowFieldMv(iSamplePos); + UnpackVectorFieldEntries(packedOpticalFlowMv, fOfVectorSample); + + vfElement.fMotionVector += fOfVectorSample.fMotionVector * fWeight; + vfElement.uHighPriorityFactor += fOfVectorSample.uHighPriorityFactor * fWeight; + vfElement.uLowPriorityFactor += fOfVectorSample.uLowPriorityFactor * fWeight; + + fWeightSum += fWeight; + } + } + + if (fWeightSum > 0.0f) + { + vfElement.fMotionVector /= fWeightSum; + vfElement.uHighPriorityFactor /= fWeightSum; + vfElement.uLowPriorityFactor /= fWeightSum; + } + + vfElement.bNegOutside = !IsUvInside(fUv - vfElement.fMotionVector); + vfElement.bPosOutside = !IsUvInside(fUv + vfElement.fMotionVector); + vfElement.fVelocity = length(vfElement.fMotionVector); +} +#endif + +FfxFloat32x3 Tonemap(FfxFloat32x3 fRgb) +{ + return fRgb / (ffxMax(ffxMax(0.f, fRgb.r), ffxMax(fRgb.g, fRgb.b)) + 1.f).xxx; +} + +FfxFloat32x3 InverseTonemap(FfxFloat32x3 fRgb) +{ + return fRgb / ffxMax(FFX_TONEMAP_EPSILON, 1.f - ffxMax(fRgb.r, ffxMax(fRgb.g, fRgb.b))).xxx; +} + +#endif //!defined(FFX_FRAMEINTERPOLATION_COMMON_H) diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid.h new file mode 100644 index 00000000..03d61e82 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid.h @@ -0,0 +1,121 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_COMPUTE_GAME_VECTOR_FIELD_INPAINTING_PYRAMID_H +#define FFX_FRAMEINTERPOLATION_COMPUTE_GAME_VECTOR_FIELD_INPAINTING_PYRAMID_H + +#include "ffx_frameinterpolation_common.h" +//-------------------------------------------------------------------------------------- +// Buffer definitions - global atomic counter +//-------------------------------------------------------------------------------------- + +FFX_GROUPSHARED FfxUInt32 spdCounter; +FFX_GROUPSHARED FfxFloat32 spdIntermediateR[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateG[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateB[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateA[16][16]; + +FfxFloat32x4 SpdLoadSourceImage(FfxFloat32x2 tex, FfxUInt32 slice) +{ + VectorFieldEntry gameMv; + FfxUInt32x2 packedGameFieldMv = LoadGameFieldMv(tex); + UnpackVectorFieldEntries(packedGameFieldMv, gameMv); + + return FfxFloat32x4(gameMv.fMotionVector, gameMv.uHighPriorityFactor, gameMv.uLowPriorityFactor) * (DisplaySize().x > 0);; +} + +FfxFloat32x4 SpdLoad(FfxFloat32x2 tex, FfxUInt32 slice) +{ + return RWLoadInpaintingPyramid(tex, 5); +} + +void SpdStore(FfxInt32x2 pix, FfxFloat32x4 outValue, FfxUInt32 index, FfxUInt32 slice) +{ + StoreInpaintingPyramid(pix, outValue, index); +} + +void SpdIncreaseAtomicCounter(FfxUInt32 slice) +{ + AtomicIncreaseCounter(FfxInt32x2(COUNTER_SPD, 0), spdCounter); +} + +FfxUInt32 SpdGetAtomicCounter() +{ + return spdCounter; +} +void SpdResetAtomicCounter(FfxUInt32 slice) +{ + StoreCounter(FfxInt32x2(COUNTER_SPD, 0), 0); +} + +FfxFloat32x4 SpdLoadIntermediate(FfxUInt32 x, FfxUInt32 y) +{ + return FfxFloat32x4( + spdIntermediateR[x][y], + spdIntermediateG[x][y], + spdIntermediateB[x][y], + spdIntermediateA[x][y]); +} + +void SpdStoreIntermediate(FfxUInt32 x, FfxUInt32 y, FfxFloat32x4 value) +{ + spdIntermediateR[x][y] = value.x; + spdIntermediateG[x][y] = value.y; + spdIntermediateB[x][y] = value.z; + spdIntermediateA[x][y] = value.w; +} + +FfxFloat32x4 SpdReduce4(FfxFloat32x4 v0, FfxFloat32x4 v1, FfxFloat32x4 v2, FfxFloat32x4 v3) +{ + FfxFloat32x4 vec = FfxFloat32x4(0,0,0,0); + + FfxFloat32 fWeightSum = 0.0f; +#define ADD(SAMPLE) { \ + FfxFloat32 fWeight = (SAMPLE.z > 0.0f); \ + vec += SAMPLE * fWeight; \ + fWeightSum += fWeight; \ + } + + ADD(v0); + ADD(v1); + ADD(v2); + ADD(v3); + + vec /= (fWeightSum > FFX_FRAMEINTERPOLATION_EPSILON) ? fWeightSum : 1.0f; + + return vec; +} + +#include "spd/ffx_spd.h" + +void computeFrameinterpolationGameVectorFieldInpaintingPyramid(FfxInt32x3 iGroupId, FfxInt32 iLocalIndex) +{ + SpdDownsample( + FfxUInt32x2(iGroupId.xy), + FfxUInt32(iLocalIndex), + FfxUInt32(NumMips()), + FfxUInt32(NumWorkGroups()), + FfxUInt32(iGroupId.z), + FfxUInt32x2(WorkGroupOffset())); +} + +#endif // FFX_FRAMEINTERPOLATION_COMPUTE_GAME_VECTOR_FIELD_INPAINTING_PYRAMID_H diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid.h new file mode 100644 index 00000000..c1c8c834 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid.h @@ -0,0 +1,113 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_COMPUTE_INPAINTING_PYRAMID_H +#define FFX_FRAMEINTERPOLATION_COMPUTE_INPAINTING_PYRAMID_H + +//-------------------------------------------------------------------------------------- +// Buffer definitions - global atomic counter +//-------------------------------------------------------------------------------------- + +FFX_GROUPSHARED FfxUInt32 spdCounter; +FFX_GROUPSHARED FfxFloat32 spdIntermediateR[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateG[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateB[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateA[16][16]; + +FfxFloat32x4 SpdLoadSourceImage(FfxFloat32x2 tex, FfxUInt32 slice) +{ + FfxFloat32x4 fColor = LoadFrameInterpolationOutput(tex) * (DisplaySize().x > 0); + + // reverse sample weights + fColor.w = ffxSaturate(1.0f - fColor.w); + + return fColor; +} + +FfxFloat32x4 SpdLoad(FfxFloat32x2 tex, FfxUInt32 slice) +{ + return RWLoadInpaintingPyramid(tex, 5); +} + +void SpdStore(FfxInt32x2 pix, FfxFloat32x4 outValue, FfxUInt32 index, FfxUInt32 slice) +{ + StoreInpaintingPyramid(pix, outValue, index); +} + +void SpdIncreaseAtomicCounter(FfxUInt32 slice) +{ + AtomicIncreaseCounter(FfxInt32x2(COUNTER_SPD,0), spdCounter); +} + +FfxUInt32 SpdGetAtomicCounter() +{ + return spdCounter; +} +void SpdResetAtomicCounter(FfxUInt32 slice) +{ + StoreCounter(FfxInt32x2(COUNTER_SPD, 0), 0); +} + +FfxFloat32x4 SpdLoadIntermediate(FfxUInt32 x, FfxUInt32 y) +{ + return FfxFloat32x4( + spdIntermediateR[x][y], + spdIntermediateG[x][y], + spdIntermediateB[x][y], + spdIntermediateA[x][y]); +} + +void SpdStoreIntermediate(FfxUInt32 x, FfxUInt32 y, FfxFloat32x4 value) +{ + spdIntermediateR[x][y] = value.x; + spdIntermediateG[x][y] = value.y; + spdIntermediateB[x][y] = value.z; + spdIntermediateA[x][y] = value.w; +} + +FfxFloat32x4 SpdReduce4(FfxFloat32x4 v0, FfxFloat32x4 v1, FfxFloat32x4 v2, FfxFloat32x4 v3) +{ + FfxFloat32x4 w = FfxFloat32x4(v0.w, v1.w, v2.w, v3.w); + + FfxFloat32 sum = (w[0] + w[1] + w[2] + w[3]); + + if (sum == 0.0f) { + return 0; + } + + return (v0 * w[0] + v1 * w[1] + v2 * w[2] + v3 * w[3]) / sum; +} + +#include "spd/ffx_spd.h" + +void computeFrameinterpolationInpaintingPyramid(FfxInt32x3 iGroupId, FfxInt32 iLocalIndex) +{ + SpdDownsample( + FfxUInt32x2(iGroupId.xy), + FfxUInt32(iLocalIndex), + FfxUInt32(mips), + FfxUInt32(numWorkGroups), + FfxUInt32(iGroupId.z), + FfxUInt32x2(workGroupOffset)); +} + +#endif // FFX_FRAMEINTERPOLATION_COMPUTE_INPAINTING_PYRAMID_H diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_debug_view.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_debug_view.h new file mode 100644 index 00000000..34b5b6a2 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_debug_view.h @@ -0,0 +1,163 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_DEBUG_VIEW_H +#define FFX_FRAMEINTERPOLATION_DEBUG_VIEW_H + +struct FfxFrameInterpolationDebugViewport +{ + FfxInt32x2 offset; + FfxInt32x2 size; +}; + +// Macro to cull and draw debug viewport +#define DRAW_VIEWPORT(function, pos, vp) \ + { \ + if (pointIsInsideViewport(pos, vp)) \ + { \ + function(pos, vp); \ + } \ + } + +FfxFloat32x2 getTransformedUv(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp) +{ + FfxFloat32x2 fUv = (FfxFloat32x2(iPxPos - vp.offset) + 0.5f) / vp.size; + + return fUv; +} + +FfxFloat32x4 getMotionVectorColor(FfxFloat32x2 fMotionVector) +{ + return FfxFloat32x4(0.5f + fMotionVector * DisplaySize() * 0.1f, 0.5f, 1.0f); +} + +FfxFloat32x4 getUnusedIndicationColor(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp) +{ + FfxInt32x2 basePos = iPxPos - vp.offset; + + FfxFloat32 ar = (FfxFloat32)vp.size.x / vp.size.y; + + return FfxFloat32x4(basePos.x == FfxInt32(basePos.y * ar), 0, 0, 1); +} + +void drawGameMotionVectorFieldVectors(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp) +{ + FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp); + + VectorFieldEntry gameMv; + LoadInpaintedGameFieldMv(fUv, gameMv); + + StoreFrameinterpolationOutput(iPxPos, getMotionVectorColor(gameMv.fMotionVector)); +} + +void drawGameMotionVectorFieldDepthPriority(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp) +{ + FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp); + + VectorFieldEntry gameMv; + LoadInpaintedGameFieldMv(fUv, gameMv); + + StoreFrameinterpolationOutput(iPxPos, FfxFloat32x4(0, gameMv.uHighPriorityFactor, 0, 1)); +} + +void drawOpticalFlowMotionVectorField(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp) +{ + FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp); + + VectorFieldEntry ofMv; + SampleOpticalFlowMotionVectorField(fUv, ofMv); + + StoreFrameinterpolationOutput(iPxPos, getMotionVectorColor(ofMv.fMotionVector)); +} + +void drawDisocclusionMask(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp) +{ + FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp); + + FfxFloat32x2 fLrUv = fUv * (FfxFloat32x2(RenderSize()) / GetMaxRenderSize()); + + FfxFloat32x2 fDisocclusionFactor = ffxSaturate(SampleDisocclusionMask(fLrUv).xy); + + StoreFrameinterpolationOutput(iPxPos, FfxFloat32x4(fDisocclusionFactor, 0, 1)); +} + +void drawPresentBackbuffer(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp) +{ + FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp); + + FfxFloat32x4 fPresentColor = getUnusedIndicationColor(iPxPos, vp); + + if (GetHUDLessAttachedFactor() == 1) + { + fPresentColor = SamplePresentBackbuffer(fUv); + } + + StoreFrameinterpolationOutput(iPxPos, fPresentColor); +} + +void drawCurrentInterpolationSource(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp) +{ + FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp); + + FfxFloat32x4 fCurrentBackBuffer = FfxFloat32x4(SampleCurrentBackbuffer(fUv), 1.0f); + + StoreFrameinterpolationOutput(iPxPos, fCurrentBackBuffer); +} + +FfxBoolean pointIsInsideViewport(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp) +{ + FfxInt32x2 extent = vp.offset + vp.size; + + return (iPxPos.x >= vp.offset.x && iPxPos.x < extent.x) && (iPxPos.y >= vp.offset.y && iPxPos.y < extent.y); +} + +void computeDebugView(FfxInt32x2 iPxPos) +{ +#define VIEWPORT_GRID_SIZE_X 3 +#define VIEWPORT_GRID_SIZE_Y 3 + + FfxFloat32x2 fViewportScale = FfxFloat32x2(1.0f / VIEWPORT_GRID_SIZE_X, 1.0f / VIEWPORT_GRID_SIZE_Y); + FfxInt32x2 iViewportSize = DisplaySize() * fViewportScale; + + // compute grid [y][x] for easier placement of viewports + FfxFrameInterpolationDebugViewport vp[VIEWPORT_GRID_SIZE_Y][VIEWPORT_GRID_SIZE_X]; + for (FfxInt32 y = 0; y < VIEWPORT_GRID_SIZE_Y; y++) + { + for (FfxInt32 x = 0; x < VIEWPORT_GRID_SIZE_X; x++) + { + vp[y][x].offset = iViewportSize * FfxInt32x2(x, y); + vp[y][x].size = iViewportSize; + } + } + + // top row + DRAW_VIEWPORT(drawGameMotionVectorFieldVectors, iPxPos, vp[0][0]); + DRAW_VIEWPORT(drawGameMotionVectorFieldDepthPriority, iPxPos, vp[0][1]); + DRAW_VIEWPORT(drawOpticalFlowMotionVectorField, iPxPos, vp[0][2]); + + // bottom row + DRAW_VIEWPORT(drawDisocclusionMask, iPxPos, vp[2][0]); + DRAW_VIEWPORT(drawCurrentInterpolationSource, iPxPos, vp[2][1]); + DRAW_VIEWPORT(drawPresentBackbuffer, iPxPos, vp[2][2]); +} + +#endif // FFX_FRAMEINTERPOLATION_DEBUG_VIEW_H diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.h new file mode 100644 index 00000000..2efe35b8 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_disocclusion_mask.h @@ -0,0 +1,141 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_DISOCCLUSION_MASK_H +#define FFX_FRAMEINTERPOLATION_DISOCCLUSION_MASK_H + +FFX_STATIC const FfxFloat32 DepthClipBaseScale = 1.0f; + +FfxFloat32 ComputeSampleDepthClip(FfxInt32x2 iPxSamplePos, FfxFloat32 fPreviousDepth, FfxFloat32 fPreviousDepthBilinearWeight, FfxFloat32 fCurrentDepthViewSpace) +{ + FfxFloat32 fPrevNearestDepthViewSpace = ConvertFromDeviceDepthToViewSpace(fPreviousDepth); + + // Depth separation logic ref: See "Minimum Triangle Separation for Correct Z-Buffer Occlusion" + // Intention: worst case of formula in Figure4 combined with Ksep factor in Section 4 + const FfxFloat32 fHalfViewportWidth = RenderSize().x * 0.5f; + FfxFloat32 fDepthThreshold = ffxMax(fCurrentDepthViewSpace, fPrevNearestDepthViewSpace); + + // WARNING: Ksep only works with reversed-z with infinite projection. + const FfxFloat32 Ksep = 1.37e-05f; + FfxFloat32 fRequiredDepthSeparation = Ksep * fDepthThreshold * TanHalfFoV() * fHalfViewportWidth; + FfxFloat32 fDepthDiff = fCurrentDepthViewSpace - fPrevNearestDepthViewSpace; + + FfxFloat32 fDepthClipFactor = (fDepthDiff > 0) ? ffxSaturate(fRequiredDepthSeparation / fDepthDiff) : 1.0f; + + return fPreviousDepthBilinearWeight * fDepthClipFactor * ffxLerp(1.0f, DepthClipBaseScale, ffxSaturate(fDepthDiff * fDepthDiff)); +} + +FfxFloat32 LoadEstimatedDepth(FfxUInt32 estimatedIndex, FfxInt32x2 iSamplePos) +{ + if (estimatedIndex == 0) + { + return LoadReconstructedDepthPreviousFrame(iSamplePos); + } + else if (estimatedIndex == 1) + { + return LoadDilatedDepth(iSamplePos); + } + + return 0; +} + +FfxFloat32 ComputeDepthClip(FfxUInt32 estimatedIndex, FfxFloat32x2 fUvSample, FfxFloat32 fCurrentDepthSample) +{ + FfxFloat32 fCurrentDepthViewSpace = ConvertFromDeviceDepthToViewSpace(fCurrentDepthSample); + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUvSample, RenderSize()); + + FfxFloat32 fDilatedSum = 0.0f; + FfxFloat32 fDepth = 0.0f; + FfxFloat32 fWeightSum = 0.0f; + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) { + + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, RenderSize())) { + const FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex]; + if (fWeight > fReconstructedDepthBilinearWeightThreshold) { + + const FfxFloat32 fPrevDepthSample = LoadEstimatedDepth(estimatedIndex, iSamplePos); + const FfxFloat32 fPrevNearestDepthViewSpace = ConvertFromDeviceDepthToViewSpace(fPrevDepthSample); + + const FfxFloat32 fDepthDiff = fCurrentDepthViewSpace - fPrevNearestDepthViewSpace; + + if (fDepthDiff > 0.0f) { + +#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH + const FfxFloat32 fPlaneDepth = ffxMin(fPrevDepthSample, fCurrentDepthSample); +#else + const FfxFloat32 fPlaneDepth = ffxMax(fPrevDepthSample, fCurrentDepthSample); +#endif + + const FfxFloat32x3 fCenter = GetViewSpacePosition(FfxInt32x2(RenderSize() * 0.5f), RenderSize(), fPlaneDepth); + const FfxFloat32x3 fCorner = GetViewSpacePosition(FfxInt32x2(0, 0), RenderSize(), fPlaneDepth); + + const FfxFloat32 fHalfViewportWidth = length(FfxFloat32x2(RenderSize())); + const FfxFloat32 fDepthThreshold = ffxMin(fCurrentDepthViewSpace, fPrevNearestDepthViewSpace); + + const FfxFloat32 Ksep = 1.37e-05f; + const FfxFloat32 Kfov = length(fCorner) / length(fCenter); + const FfxFloat32 fRequiredDepthSeparation = Ksep * Kfov * fHalfViewportWidth * fDepthThreshold; + + const FfxFloat32 fResolutionFactor = ffxSaturate(length(FfxFloat32x2(RenderSize())) / length(FfxFloat32x2(1920.0f, 1080.0f))); + const FfxFloat32 fPower = ffxLerp(1.0f, 3.0f, fResolutionFactor); + + fDepth += FfxFloat32((fRequiredDepthSeparation / fDepthDiff) >= 1.0f) * fWeight; + fWeightSum += fWeight; + } + } + } + } + + return (fWeightSum > 0.0f) ? ffxSaturate(1.0f - fDepth / fWeightSum) : 0.0f; +} + +void computeDisocclusionMask(FfxInt32x2 iPxPos) +{ + FfxFloat32 fDilatedDepth = LoadEstimatedInterpolationFrameDepth(iPxPos); + + FfxFloat32x2 fDepthUv = (iPxPos + 0.5f) / RenderSize(); + FfxFloat32 fCurrentDepthViewSpace = ConvertFromDeviceDepthToViewSpace(fDilatedDepth); + + VectorFieldEntry gameMv; + LoadInpaintedGameFieldMv(fDepthUv, gameMv); + + const FfxFloat32 fDepthClipInterpolatedToPrevious = 1.0f - ComputeDepthClip(0, fDepthUv + gameMv.fMotionVector, fDilatedDepth); + const FfxFloat32 fDepthClipInterpolatedToCurrent = 1.0f - ComputeDepthClip(1, fDepthUv - gameMv.fMotionVector, fDilatedDepth); + FfxFloat32x2 fDisocclusionMask = FfxFloat32x2(fDepthClipInterpolatedToPrevious, fDepthClipInterpolatedToCurrent); + + fDisocclusionMask = fDisocclusionMask >= FFX_FRAMEINTERPOLATION_EPSILON; + + // Avoid false disocclusion if primary game vector pointer outside screen area + const FfxFloat32x2 fSrcMotionVector = gameMv.fMotionVector * 2.0f; + const FfxInt32x2 iSamplePosPrevious = (fDepthUv + fSrcMotionVector) * RenderSize(); + fDisocclusionMask.x = ffxSaturate(fDisocclusionMask.x + !IsOnScreen(iSamplePosPrevious, RenderSize())); + + const FfxInt32x2 iSamplePosCurrent = (fDepthUv - fSrcMotionVector) * RenderSize(); + fDisocclusionMask.y = ffxSaturate(fDisocclusionMask.y + !IsOnScreen(iSamplePosCurrent, RenderSize())); + + StoreDisocclusionMask(iPxPos, fDisocclusionMask); +} + +#endif // FFX_FRAMEINTERPOLATION_DISOCCLUSION_MASK_H diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.h new file mode 100644 index 00000000..a7740066 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.h @@ -0,0 +1,114 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_GAME_MOTION_VECTOR_FIELD_H +#define FFX_FRAMEINTERPOLATION_GAME_MOTION_VECTOR_FIELD_H + +FfxUInt32 getPriorityFactorFromViewSpaceDepth(FfxFloat32 fViewSpaceDepthInMeters) +{ + fViewSpaceDepthInMeters = ffxPow(fViewSpaceDepthInMeters, 0.33f); + + FfxUInt32 uPriorityFactor = FfxFloat32(1 - (fViewSpaceDepthInMeters * (1.0f / (1.0f + fViewSpaceDepthInMeters)))) * PRIORITY_HIGH_MAX; + + return ffxMax(1, uPriorityFactor); +} + +void computeGameFieldMvs(FfxInt32x2 iPxPos) +{ + const FfxFloat32x2 fUv = FfxFloat32x2(FfxFloat32x2(iPxPos) + 0.5f) / RenderSize(); + const FfxFloat32 fDepthSample = LoadDilatedDepth(iPxPos); + const FfxFloat32x2 fGameMotionVector = LoadDilatedMotionVector(iPxPos); + const FfxFloat32x2 fMotionVectorHalf = fGameMotionVector * 0.5f; + const FfxFloat32x2 fInterpolatedLocationUv = fUv + fMotionVectorHalf; + + const FfxFloat32 fViewSpaceDepth = ConvertFromDeviceDepthToViewSpace(fDepthSample); + const FfxUInt32 uHighPriorityFactorPrimary = getPriorityFactorFromViewSpaceDepth(fViewSpaceDepth); + + FfxFloat32x3 prevBackbufferCol = SamplePreviousBackbuffer(fUv).xyz; + FfxFloat32x3 curBackbufferCol = SamplePreviousBackbuffer(fUv + fGameMotionVector).xyz; + FfxFloat32 prevLuma = 0.001f + RawRGBToLuminance(prevBackbufferCol); + FfxFloat32 currLuma = 0.001f + RawRGBToLuminance(curBackbufferCol); + + FfxUInt32 uLowPriorityFactor = round(ffxPow(MinDividedByMax(prevLuma, currLuma), 1.0f / 1.0f) * PRIORITY_LOW_MAX) + * IsUvInside(fUv + fGameMotionVector); + + // Update primary motion vectors + { + const FfxUInt32x2 packedVectorPrimary = PackVectorFieldEntries(true, uHighPriorityFactorPrimary, uLowPriorityFactor, fMotionVectorHalf); + + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fInterpolatedLocationUv, RenderSize()); + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) + { + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, RenderSize())) + { + UpdateGameMotionVectorField(iSamplePos, packedVectorPrimary); + } + } + } + + // Update secondary vectors + // Main purpose of secondary vectors is to improve quality of inpainted vectors + const FfxBoolean bWriteSecondaryVectors = length(fMotionVectorHalf * RenderSize()) > FFX_FRAMEINTERPOLATION_EPSILON; + if (bWriteSecondaryVectors) + { + FfxBoolean bWriteSecondary = true; + FfxUInt32 uNumPrimaryHits = 0; + const FfxFloat32 fSecondaryStepScale = length(1.0f / RenderSize()); + const FfxFloat32x2 fStepMv = normalize(fGameMotionVector); + const FfxFloat32 fBreakDist = length(fMotionVectorHalf); + + for (FfxFloat32 fMvScale = fSecondaryStepScale; fMvScale <= fBreakDist && bWriteSecondary; fMvScale += fSecondaryStepScale) + { + const FfxFloat32x2 fSecondaryLocationUv = fInterpolatedLocationUv - fStepMv * fMvScale; + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fSecondaryLocationUv, RenderSize()); + + // Reverse depth prio for secondary vectors + FfxUInt32 uHighPriorityFactorSecondary = ffxMax(1, PRIORITY_HIGH_MAX - uHighPriorityFactorPrimary); + + const FfxFloat32x2 fToCenter = normalize(FfxFloat32x2(0.5f, 0.5f) - fSecondaryLocationUv); + uLowPriorityFactor = ffxMax(0.0f, dot(fToCenter, fStepMv)) * PRIORITY_LOW_MAX; + const FfxUInt32x2 packedVectorSecondary = PackVectorFieldEntries(false, uHighPriorityFactorSecondary, uLowPriorityFactor, fMotionVectorHalf); + + // Only write secondary mvs to single bilinear location + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 1; iSampleIndex++) + { + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + bWriteSecondary &= IsOnScreen(iSamplePos, RenderSize()); + + if (bWriteSecondary) + { + const FfxUInt32 uExistingVectorFieldEntry = UpdateGameMotionVectorFieldEx(iSamplePos, packedVectorSecondary); + + uNumPrimaryHits += PackedVectorFieldEntryIsPrimary(uExistingVectorFieldEntry); + bWriteSecondary &= (uNumPrimaryHits <= 3); + } + } + } + } +} + +#endif // FFX_FRAMEINTERPOLATION_GAME_MOTION_VECTOR_FIELD_H diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_inpainting.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_inpainting.h new file mode 100644 index 00000000..1800a4c1 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_inpainting.h @@ -0,0 +1,141 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_INPAINTING_H +#define FFX_FRAMEINTERPOLATION_INPAINTING_H + +FfxFloat32x4 ComputeInpaintingLevel(FfxFloat32x2 fUv, const FfxInt32 iMipLevel, const FfxInt32x2 iTexSize) +{ + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv, iTexSize); + + FfxFloat32x4 fColor = 0.0f; + + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) { + + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, iTexSize)) { + + FfxFloat32x4 fSample = LoadInpaintingPyramid(iMipLevel, iSamplePos); + + const FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex] * (fSample.w > 0.0f); + + fColor += FfxFloat32x4(fSample.rgb * fWeight, fWeight); + } + } + + return fColor; +} + +FfxFloat32x3 ComputeInpainting(FfxInt32x2 iPxPos) +{ + FfxFloat32x2 fUv = (iPxPos + 0.5f) / (DisplaySize()); + + FfxFloat32x4 fColor = 0.0f; + FfxFloat32 fWeightSum = 0.0f; + FfxInt32x2 iTexSize = DisplaySize(); + + for (FfxInt32 iMipLevel = 0; iMipLevel < 10; iMipLevel++) { + + iTexSize *= 0.5f; + + FfxFloat32x4 fMipColor = ComputeInpaintingLevel(fUv, iMipLevel, iTexSize); + + if (fMipColor.w > 0.0f) { + const FfxFloat32x3 fNormalizedMipColor = fMipColor.rgb / fMipColor.w; + const FfxFloat32 fMipWeight = ffxPow(1.0f - iMipLevel / 10.0f, 3.0f) * fMipColor.w; + + fColor += float4(fNormalizedMipColor, 1.0f) * fMipWeight; + } + } + + return fColor.rgb / fColor.w; +} + +void drawDebug(FfxInt32x2 iPxPos, inout FfxFloat32x3 fColor, inout FfxBoolean bWriteColor) +{ + if (iPxPos.y < 32 && iPxPos.x < 64 && Reset()) + { + fColor.b = 1.f; + bWriteColor = true; + } + + if (iPxPos.y < 32 && iPxPos.x < 32 && HasSceneChanged()) + { + fColor.r = 1.f; + bWriteColor = true; + } + + if (iPxPos.x < 16) + { + fColor.g = 1.f; + bWriteColor = true; + } + if (iPxPos.x > DisplaySize().x - 16) + { + fColor += GetDebugBarColor(); + bWriteColor = true; + } +} + +void computeInpainting(FfxInt32x2 iPxPos) +{ + FfxBoolean bWriteColor = false; + FfxFloat32x4 fInterpolatedColor = RWLoadFrameinterpolationOutput(iPxPos); + + const FfxFloat32 fInPaintingWeight = fInterpolatedColor.w; + if (fInPaintingWeight > FFX_FRAMEINTERPOLATION_EPSILON) + { + fInterpolatedColor.rgb = ffxLerp(fInterpolatedColor.rgb, ComputeInpainting(iPxPos) * (DisplaySize().x > 0), fInPaintingWeight); + bWriteColor = true; + } + + if (GetHUDLessAttachedFactor() == 1) + { + const FfxFloat32x3 fCurrentInterpolationSource = LoadCurrentBackbuffer(iPxPos).rgb; + const FfxFloat32x3 fPresentColor = LoadPresentBackbuffer(iPxPos).rgb; + + if (any(abs(fCurrentInterpolationSource - fPresentColor) > 0.0f)) + { + const FfxFloat32 fStaticFactor = CalculateStaticContentFactor(RawRGBToLinear(fCurrentInterpolationSource), RawRGBToLinear(fPresentColor)); + + if (fStaticFactor > FFX_FRAMEINTERPOLATION_EPSILON) + { + fInterpolatedColor.rgb = ffxLerp(fInterpolatedColor.rgb, fPresentColor, fStaticFactor); + bWriteColor = true; + } + } + } + + if (GetDispatchFlags() & FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG) + { + drawDebug(iPxPos, fInterpolatedColor.rgb, bWriteColor); + } + + if (bWriteColor) + { + StoreFrameinterpolationOutput(iPxPos, FfxFloat32x4(fInterpolatedColor.rgb, 1.0f)); + } +} + +#endif // FFX_FRAMEINTERPOLATION_INPAINTING_H diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.h new file mode 100644 index 00000000..43a333fd --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.h @@ -0,0 +1,124 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_OPTICAL_FLOW_VECTOR_FIELD_H +#define FFX_FRAMEINTERPOLATION_OPTICAL_FLOW_VECTOR_FIELD_H + +void computeOpticalFlowFieldMvs(FfxUInt32x2 dtID, FfxFloat32x2 fOpticalFlowVector) +{ + FfxFloat32x2 fUv = FfxFloat32x2(FfxFloat32x2(dtID)+0.5f) / GetOpticalFlowSize2(); + + const FfxFloat32 scaleFactor = 1.0f; + FfxFloat32x2 fMotionVectorHalf = fOpticalFlowVector * 0.5f; + + FfxFloat32 fDilatedDepth = ConvertFromDeviceDepthToViewSpace(LoadDilatedDepth(dtID)); + + FfxFloat32x3 prevBackbufferCol = SamplePreviousBackbuffer(fUv).xyz; + FfxFloat32x3 curBackbufferCol = SampleCurrentBackbuffer(fUv + fOpticalFlowVector).xyz; + + FfxFloat32 prevLuma = 0.001f + RawRGBToLuminance(prevBackbufferCol); + FfxFloat32 currLuma = 0.001f + RawRGBToLuminance(curBackbufferCol); + + FfxFloat32 fVelocity = length(fOpticalFlowVector * DisplaySize()); + FfxUInt32 uHighPriorityFactor = (fVelocity > 1.0f) * ffxSaturate(fVelocity / length(DisplaySize() * 0.05f)) * PRIORITY_HIGH_MAX; + + if(uHighPriorityFactor > 0) { + FfxUInt32 uLowPriorityFactor = round(ffxPow(MinDividedByMax(prevLuma, currLuma), 1.0f / 1.0f) * PRIORITY_LOW_MAX) + * IsUvInside(fUv + fOpticalFlowVector); + + // Project current depth into previous frame locations. + // Push to all pixels having some contribution if reprojection is using bilinear logic. + + const FfxUInt32x2 packedVectorPrimary = PackVectorFieldEntries(true, uHighPriorityFactor, uLowPriorityFactor, fMotionVectorHalf); + + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv + fMotionVectorHalf, GetOpticalFlowSize2()); + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) + { + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, GetOpticalFlowSize2())) + { + UpdateOpticalflowMotionVectorField(iSamplePos, packedVectorPrimary); + } + } + } +} + +void computeOpticalFlowVectorField(FfxInt32x2 iPxPos) +{ + FfxFloat32x2 fOpticalFlowVector = 0; + FfxFloat32x2 fOpticalFlowVector3x3Avg = 0; + FfxInt32 size = 1; + FfxFloat32 sw = 0.0f; + + for(FfxInt32 y = -size; y <= size; y++) { + for(FfxInt32 x = -size; x <= size; x++) { + + FfxInt32x2 samplePos = iPxPos + FfxInt32x2(x, y); + + FfxFloat32x2 vs = LoadOpticalFlow(samplePos); + FfxFloat32 fConfidenceFactor = ffxMax(FFX_FRAMEINTERPOLATION_EPSILON, LoadOpticalFlowConfidence(samplePos)); + + + FfxFloat32 len = length(vs * DisplaySize()); + FfxFloat32 len_factor = ffxMax(0.0f, 512.0f - len) * (len > 1.0f); + FfxFloat32 w = len_factor; + + fOpticalFlowVector3x3Avg += vs * w; + + sw += w; + } + } + + fOpticalFlowVector3x3Avg /= sw; + + + sw = 0.0f; + for(FfxInt32 y = -size; y <= size; y++) { + for(FfxInt32 x = -size; x <= size; x++) { + + FfxInt32x2 samplePos = iPxPos + FfxInt32x2(x, y); + + FfxFloat32x2 vs = LoadOpticalFlow(samplePos); + + FfxFloat32 fConfidenceFactor = ffxMax(FFX_FRAMEINTERPOLATION_EPSILON, LoadOpticalFlowConfidence(samplePos)); + FfxFloat32 len = length(vs * DisplaySize()); + FfxFloat32 len_factor = ffxMax(0.0f, 512.0f - len) * (len > 1.0f); + + + FfxFloat32 w = ffxMax(0.0f, ffxPow(dot(fOpticalFlowVector3x3Avg, vs), 1.25f)) * len_factor; + + fOpticalFlowVector += vs * w; + sw += w; + } + } + + if (sw > FFX_FRAMEINTERPOLATION_EPSILON) + { + fOpticalFlowVector /= sw; + } + + computeOpticalFlowFieldMvs(iPxPos, fOpticalFlowVector); +} + +#endif // FFX_FRAMEINTERPOLATION_OPTICAL_FLOW_VECTOR_FIELD_H diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.h new file mode 100644 index 00000000..21b8cf44 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.h @@ -0,0 +1,59 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_RECONSTRUCT_PREVIOUS_DEPTH_H +#define FFX_FRAMEINTERPOLATION_RECONSTRUCT_PREVIOUS_DEPTH_H + +void ReconstructPrevDepth(FfxInt32x2 iPxPos, FfxUInt32 depthTarget, FfxFloat32 fDepth, FfxFloat32x2 fMotionVector, FfxInt32x2 iPxDepthSize) +{ + const FfxFloat32x2 fUv = (iPxPos + FfxFloat32(0.5)) / iPxDepthSize; + + // Project current depth into previous frame locations. + // Push to all pixels having some contribution if reprojection is using bilinear logic. + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv + fMotionVector, RenderSize()); + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) + { + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + const FfxFloat32 fSampleWeight = bilinearInfo.fWeights[iSampleIndex]; + + if (fSampleWeight > fReconstructedDepthBilinearWeightThreshold) + { + if (IsOnScreen(iSamplePos, RenderSize())) + { + if (depthTarget != 0) { + UpdateReconstructedDepthInterpolatedFrame(iSamplePos, fDepth); + } + } + } + } +} + +void reconstructPreviousDepth(FfxInt32x2 iPxPos) +{ + FfxFloat32x2 fMotionVector = LoadDilatedMotionVector(iPxPos); + FfxFloat32 fDilatedDepth = LoadDilatedDepth(iPxPos); + + ReconstructPrevDepth(iPxPos, 1, fDilatedDepth, fMotionVector * 0.5f, RenderSize()); +} + +#endif // FFX_FRAMEINTERPOLATION_RECONSTRUCT_PREVIOUS_DEPTH_H diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_resources.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_resources.h new file mode 100644 index 00000000..ecb0c28a --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_resources.h @@ -0,0 +1,90 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_RESOURCES_H +#define FFX_FRAMEINTERPOLATION_RESOURCES_H + +#if defined(FFX_CPU) || defined(FFX_GPU) +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_NULL 0 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OUTPUT 1 +//#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_BACKBUFFER 2 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PREVIOUS_INTERPOLATION_SOURCE 3 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_CURRENT_INTERPOLATION_SOURCE 4 + +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_0 5 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_1 6 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_2 7 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_3 8 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_4 9 + +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_DEPTH 10 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS 11 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 12 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 13 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DISOCCLUSION_MASK 14 + +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_X 15 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_Y 16 + +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 17 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 18 + +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_VECTOR 19 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_5 20 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_CONFIDENCE 21 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_GLOBAL_MOTION 22 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 23 + +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_6 25 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_7 26 + +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DEBUG_OUTPUT_0 27 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DEBUG_OUTPUT_1 28 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DEBUG_OUTPUT 29 + +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_8 30 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PRESENT_BACKBUFFER 31 + +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNTERS 32 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID 33 // same as FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_0 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_0 33 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_1 34 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_2 35 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_3 36 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_4 37 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_5 38 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_6 39 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_7 40 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_8 41 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_9 42 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_10 43 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_11 44 +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_12 45 + +#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNT 46 + +#define FFX_FRAMEINTERPOLATION_CONSTANTBUFFER_IDENTIFIER 0 +#define FFX_FRAMEINTERPOLATION_INPAINTING_PYRAMID_CONSTANTBUFFER_IDENTIFIER 1 + +#endif // #if defined(FFX_CPU) || defined(FFX_GPU) + +#endif //!defined( FFX_FRAMEINTERPOLATION_RESOURCES_H ) diff --git a/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_setup.h b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_setup.h new file mode 100644 index 00000000..584e3bf0 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_setup.h @@ -0,0 +1,49 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FRAMEINTERPOLATION_SETUP_H +#define FFX_FRAMEINTERPOLATION_SETUP_H + +void setupFrameinterpolationResources(FfxInt32x2 iPxPos) +{ + // Update reset counters + if (all(iPxPos == 0)) + { + if(Reset() || HasSceneChanged()) { + StoreCounter(FfxInt32x2(COUNTER_FRAME_INDEX_SINCE_LAST_RESET, 0), 0); + } else { + FfxUInt32 counter = RWLoadCounter(FfxInt32x2(COUNTER_FRAME_INDEX_SINCE_LAST_RESET, 0)); + StoreCounter(FfxInt32x2(COUNTER_FRAME_INDEX_SINCE_LAST_RESET, 0), counter + 1); + } + } + + // Reset resources + StoreGameMotionVectorFieldX(iPxPos, 0); + StoreGameMotionVectorFieldY(iPxPos, 0); + + StoreOpticalflowMotionVectorFieldX(iPxPos, 0); + StoreOpticalflowMotionVectorFieldY(iPxPos, 0); + + StoreDisocclusionMask(iPxPos, 0); +} + +#endif // FFX_FRAMEINTERPOLATION_SETUP_H diff --git a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1.h b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1.h index c41efefc..e780995f 100644 --- a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1.h +++ b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup FfxGPUFsr1 FidelityFX FSR1 /// FidelityFX Super Resolution 1 GPU documentation /// @@ -459,7 +459,7 @@ void FsrEasuSetH( FfxFloat16x2 dirX = lD - lB; dirPX += dirX * w; - lenX = ffxSaturate(abs(dirX) * lenX); + lenX = FfxFloat16x2(ffxSaturate(abs(dirX) * lenX)); lenX *= lenX; lenP += lenX * w; FfxFloat16x2 ec = lE - lC; @@ -468,7 +468,7 @@ void FsrEasuSetH( lenY = ffxReciprocalHalf(lenY); FfxFloat16x2 dirY = lE - lA; dirPY += dirY * w; - lenY = ffxSaturate(abs(dirY) * lenY); + lenY = FfxFloat16x2(ffxSaturate(abs(dirY) * lenY)); lenY *= lenY; lenP += lenY * w; } @@ -836,7 +836,7 @@ void FsrEasuH( FfxFloat16 hL=hB*FFX_BROADCAST_FLOAT16(0.5)+(hR*FFX_BROADCAST_FLOAT16(0.5)+hG); // Noise detection. FfxFloat16 nz=FFX_BROADCAST_FLOAT16(0.25)*bL+FFX_BROADCAST_FLOAT16(0.25)*dL+FFX_BROADCAST_FLOAT16(0.25)*fL+FFX_BROADCAST_FLOAT16(0.25)*hL-eL; - nz=ffxSaturate(abs(nz)*ffxApproximateReciprocalMediumHalf(ffxMax3Half(ffxMax3Half(bL,dL,eL),fL,hL)-ffxMin3Half(ffxMin3Half(bL,dL,eL),fL,hL))); + nz=FfxFloat16(ffxSaturate(abs(nz)*ffxApproximateReciprocalMediumHalf(ffxMax3Half(ffxMax3Half(bL,dL,eL),fL,hL)-ffxMin3Half(ffxMin3Half(bL,dL,eL),fL,hL)))); nz=FFX_BROADCAST_FLOAT16(-0.5)*nz+FFX_BROADCAST_FLOAT16(1.0); // Min and max of ring. FfxFloat16 mn4R=min(ffxMin3Half(bR,dR,fR),hR); @@ -1177,7 +1177,7 @@ void FsrEasuH( FfxFloat16x3 b = n + FFX_BROADCAST_FLOAT16X3(1.0 / 255.0); b = b * b; FfxFloat16x3 r = (c - b) * ffxApproximateReciprocalMediumHalf(a - b); - c = ffxSaturate(n + ffxIsGreaterThanZeroHalf(FFX_BROADCAST_FLOAT16X3(dit) - r) * FFX_BROADCAST_FLOAT16X3(1.0 / 255.0)); + c = FfxFloat16x3(ffxSaturate(n + ffxIsGreaterThanZeroHalf(FFX_BROADCAST_FLOAT16X3(dit) - r) * FFX_BROADCAST_FLOAT16X3(1.0 / 255.0))); } //------------------------------------------------------------------------------------------------------------------------------ void FsrTepdC10H(inout FfxFloat16x3 c, FfxFloat16 dit) @@ -1188,7 +1188,7 @@ void FsrEasuH( FfxFloat16x3 b = n + FFX_BROADCAST_FLOAT16X3(1.0 / 1023.0); b = b * b; FfxFloat16x3 r = (c - b) * ffxApproximateReciprocalMediumHalf(a - b); - c = ffxSaturate(n + ffxIsGreaterThanZeroHalf(FFX_BROADCAST_FLOAT16X3(dit) - r) * FFX_BROADCAST_FLOAT16X3(1.0 / 1023.0)); + c = FfxFloat16x3(ffxSaturate(n + ffxIsGreaterThanZeroHalf(FFX_BROADCAST_FLOAT16X3(dit) - r) * FFX_BROADCAST_FLOAT16X3(1.0 / 1023.0))); } //============================================================================================================================== // This computes dither for positions 'p' and 'p+{8,0}'. @@ -1224,9 +1224,9 @@ void FsrEasuH( FfxFloat16x2 rR = (cR - bR) * ffxApproximateReciprocalMediumHalf(aR - bR); FfxFloat16x2 rG = (cG - bG) * ffxApproximateReciprocalMediumHalf(aG - bG); FfxFloat16x2 rB = (cB - bB) * ffxApproximateReciprocalMediumHalf(aB - bB); - cR = ffxSaturate(nR + ffxIsGreaterThanZeroHalf(dit - rR) * FFX_BROADCAST_FLOAT16X2(1.0 / 255.0)); - cG = ffxSaturate(nG + ffxIsGreaterThanZeroHalf(dit - rG) * FFX_BROADCAST_FLOAT16X2(1.0 / 255.0)); - cB = ffxSaturate(nB + ffxIsGreaterThanZeroHalf(dit - rB) * FFX_BROADCAST_FLOAT16X2(1.0 / 255.0)); + cR = FfxFloat16x2(ffxSaturate(nR + ffxIsGreaterThanZeroHalf(dit - rR) * FFX_BROADCAST_FLOAT16X2(1.0 / 255.0))); + cG = FfxFloat16x2(ffxSaturate(nG + ffxIsGreaterThanZeroHalf(dit - rG) * FFX_BROADCAST_FLOAT16X2(1.0 / 255.0))); + cB = FfxFloat16x2(ffxSaturate(nB + ffxIsGreaterThanZeroHalf(dit - rB) * FFX_BROADCAST_FLOAT16X2(1.0 / 255.0))); } //------------------------------------------------------------------------------------------------------------------------------ void FsrTepdC10Hx2(inout FfxFloat16x2 cR,inout FfxFloat16x2 cG,inout FfxFloat16x2 cB,FfxFloat16x2 dit){ @@ -1245,8 +1245,8 @@ void FsrEasuH( FfxFloat16x2 rR=(cR-bR)*ffxApproximateReciprocalMediumHalf(aR-bR); FfxFloat16x2 rG=(cG-bG)*ffxApproximateReciprocalMediumHalf(aG-bG); FfxFloat16x2 rB=(cB-bB)*ffxApproximateReciprocalMediumHalf(aB-bB); - cR=ffxSaturate(nR+ffxIsGreaterThanZeroHalf(dit-rR)*FFX_BROADCAST_FLOAT16X2(1.0/1023.0)); - cG=ffxSaturate(nG+ffxIsGreaterThanZeroHalf(dit-rG)*FFX_BROADCAST_FLOAT16X2(1.0/1023.0)); - cB = ffxSaturate(nB + ffxIsGreaterThanZeroHalf(dit - rB) * FFX_BROADCAST_FLOAT16X2(1.0 / 1023.0)); + cR=FfxFloat16x2(ffxSaturate(nR+ffxIsGreaterThanZeroHalf(dit-rR)*FFX_BROADCAST_FLOAT16X2(1.0/1023.0))); + cG=FfxFloat16x2(ffxSaturate(nG+ffxIsGreaterThanZeroHalf(dit-rG)*FFX_BROADCAST_FLOAT16X2(1.0/1023.0))); + cB=FfxFloat16x2(ffxSaturate(nB + ffxIsGreaterThanZeroHalf(dit - rB) * FFX_BROADCAST_FLOAT16X2(1.0 / 1023.0))); } #endif diff --git a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_callbacks_glsl.h index 760074c7..374bf1c6 100644 --- a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_fsr1_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_callbacks_hlsl.h index bb2c265c..86a48387 100644 --- a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_fsr1_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_easu.h b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_easu.h index 392764d7..37b20b1a 100644 --- a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_easu.h +++ b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_easu.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define GROUP_SIZE 8 #define FSR_RCAS_DENOISE 1 diff --git a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_rcas.h b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_rcas.h index 4ceba015..1e33aaa2 100644 --- a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_rcas.h +++ b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_rcas.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define GROUP_SIZE 8 #define FSR_RCAS_DENOISE 1 diff --git a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_resources.h b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_resources.h index bcbb03c3..3c031914 100644 --- a/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_resources.h +++ b/sdk/include/FidelityFX/gpu/fsr1/ffx_fsr1_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_FSR1_RESOURCES_H #define FFX_FSR1_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_accumulate.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_accumulate.h index a5ace2c7..16357bd0 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_accumulate.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_accumulate.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_FSR2_ACCUMULATE_H #define FFX_FSR2_ACCUMULATE_H diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_callbacks_glsl.h index 89717dc9..fb0b2fa0 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_fsr2_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_callbacks_hlsl.h index 6eb5e664..9a1f1af9 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_fsr2_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_common.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_common.h index d6721998..39512c97 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_common.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_common.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 !defined(FFX_FSR2_COMMON_H) #define FFX_FSR2_COMMON_H diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_compute_luminance_pyramid.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_compute_luminance_pyramid.h index 3b87d9ac..69ee6be3 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_compute_luminance_pyramid.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_compute_luminance_pyramid.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + FFX_GROUPSHARED FfxUInt32 spdCounter; void SpdIncreaseAtomicCounter(FfxUInt32 slice) diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_depth_clip.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_depth_clip.h index ff8a44ea..d29721fe 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_depth_clip.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_depth_clip.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_FSR2_DEPTH_CLIP_H #define FFX_FSR2_DEPTH_CLIP_H diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_lock.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_lock.h index e2673141..2af7b4b2 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_lock.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_lock.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_FSR2_LOCK_H #define FFX_FSR2_LOCK_H diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_postprocess_lock_status.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_postprocess_lock_status.h index 1183edfb..61cd5dc3 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_postprocess_lock_status.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_postprocess_lock_status.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_FSR2_POSTPROCESS_LOCK_STATUS_H #define FFX_FSR2_POSTPROCESS_LOCK_STATUS_H diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_rcas.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_rcas.h index 4ef9bf06..77619a51 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_rcas.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_rcas.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define GROUP_SIZE 8 #define FSR_RCAS_DENOISE 1 diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_reconstruct_dilated_velocity_and_previous_depth.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_reconstruct_dilated_velocity_and_previous_depth.h index 4268c360..0835e510 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_reconstruct_dilated_velocity_and_previous_depth.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_reconstruct_dilated_velocity_and_previous_depth.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_FSR2_RECONSTRUCT_DILATED_VELOCITY_AND_PREVIOUS_DEPTH_H #define FFX_FSR2_RECONSTRUCT_DILATED_VELOCITY_AND_PREVIOUS_DEPTH_H diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_reproject.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_reproject.h index dd95a485..94645241 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_reproject.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_reproject.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_FSR2_REPROJECT_H #define FFX_FSR2_REPROJECT_H diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_resources.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_resources.h index 6cd1c8f0..b33cd4b7 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_resources.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_FSR2_RESOURCES_H #define FFX_FSR2_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_sample.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_sample.h index 54c7335e..d2777428 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_sample.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_sample.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_FSR2_SAMPLE_H #define FFX_FSR2_SAMPLE_H diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_tcr_autogen.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_tcr_autogen.h index 47ef1a3a..3d864bad 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_tcr_autogen.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_tcr_autogen.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define USE_YCOCG 1 #define fAutogenEpsilon 0.01f diff --git a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_upsample.h b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_upsample.h index 2fd62ed9..0b76938d 100644 --- a/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_upsample.h +++ b/sdk/include/FidelityFX/gpu/fsr2/ffx_fsr2_upsample.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C)2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_FSR2_UPSAMPLE_H #define FFX_FSR2_UPSAMPLE_H diff --git a/sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_callbacks_hlsl.h new file mode 100644 index 00000000..7f65e9e6 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_callbacks_hlsl.h @@ -0,0 +1,25 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "../fsr2/ffx_fsr2_callbacks_hlsl.h" +#include "ffx_fsr3_resources.h" diff --git a/sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_common.h b/sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_common.h new file mode 100644 index 00000000..e98fdda0 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_common.h @@ -0,0 +1,25 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "../fsr2/ffx_fsr2_common.h" +#include "../frameinterpolation/ffx_frameinterpolation_common.h" +#include "../opticalflow/ffx_opticalflow_common.h" diff --git a/sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_resources.h b/sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_resources.h new file mode 100644 index 00000000..2b00c075 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3/ffx_fsr3_resources.h @@ -0,0 +1,51 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FSR3_RESOURCES_H +#define FFX_FSR3_RESOURCES_H + +#include "../fsr2/ffx_fsr2_resources.h" +#include "../frameinterpolation/ffx_frameinterpolation_resources.h" + +#if defined(FFX_CPU) || defined(FFX_GPU) +#define FFX_FSR3_RESOURCE_IDENTIFIER_NULL 0 + +#define FFX_FSR3_RESOURCE_IDENTIFIER_OPTICAL_FLOW_VECTOR 1 +#define FFX_FSR3_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_OUTPUT 2 +#define FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_DEPTH_0 5 +#define FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS_0 6 +#define FFX_FSR3_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH_0 7 +#define FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_DEPTH_1 8 +#define FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS_1 9 +#define FFX_FSR3_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH_1 10 +#define FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_DEPTH_2 11 +#define FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS_2 12 +#define FFX_FSR3_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH_2 13 +#define FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_DEPTH_3 14 +#define FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS_3 15 +#define FFX_FSR3_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH_3 16 + +#define FFX_FSR3_RESOURCE_IDENTIFIER_COUNT 17 +#define FFX_FSR3_RESOURCE_IDENTIFIER_UPSCALED_COUNT 3 +#endif // #if defined(FFX_CPU) || defined(FFX_GPU) + +#endif //!defined( FFX_FSR2_RESOURCES_H ) diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_accumulate.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_accumulate.h new file mode 100644 index 00000000..c425de79 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_accumulate.h @@ -0,0 +1,288 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FSR3UPSCALER_ACCUMULATE_H +#define FFX_FSR3UPSCALER_ACCUMULATE_H + +FfxFloat32 GetPxHrVelocity(FfxFloat32x2 fMotionVector) +{ + return length(fMotionVector * DisplaySize()); +} +#if FFX_HALF +FFX_MIN16_F GetPxHrVelocity(FFX_MIN16_F2 fMotionVector) +{ + return length(fMotionVector * FFX_MIN16_F2(DisplaySize())); +} +#endif + +void Accumulate(const AccumulationPassCommonParams params, FFX_PARAMETER_INOUT FfxFloat32x3 fHistoryColor, FfxFloat32x3 fAccumulation, FFX_PARAMETER_IN FfxFloat32x4 fUpsampledColorAndWeight) +{ + // Aviod invalid values when accumulation and upsampled weight is 0 + fAccumulation = ffxMax(FSR3UPSCALER_EPSILON.xxx, fAccumulation + fUpsampledColorAndWeight.www); + +#if FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT + //YCoCg -> RGB -> Tonemap -> YCoCg (Use RGB tonemapper to avoid color desaturation) + fUpsampledColorAndWeight.xyz = RGBToYCoCg(Tonemap(YCoCgToRGB(fUpsampledColorAndWeight.xyz))); + fHistoryColor = RGBToYCoCg(Tonemap(YCoCgToRGB(fHistoryColor))); +#endif + + const FfxFloat32x3 fAlpha = fUpsampledColorAndWeight.www / fAccumulation; + fHistoryColor = ffxLerp(fHistoryColor, fUpsampledColorAndWeight.xyz, fAlpha); + + fHistoryColor = YCoCgToRGB(fHistoryColor); + +#if FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT + fHistoryColor = InverseTonemap(fHistoryColor); +#endif +} + +void RectifyHistory( + const AccumulationPassCommonParams params, + RectificationBox clippingBox, + FFX_PARAMETER_INOUT FfxFloat32x3 fHistoryColor, + FFX_PARAMETER_INOUT FfxFloat32x3 fAccumulation, + FfxFloat32 fLockContributionThisFrame, + FfxFloat32 fTemporalReactiveFactor, + FfxFloat32 fLumaInstabilityFactor) +{ + const FfxFloat32 fVecolityFactor = ffxSaturate(params.fHrVelocity / 20.0f); + const FfxFloat32 fBoxScaleT = ffxMax(params.fDepthClipFactor, ffxMax(params.fAccumulationMask, fVecolityFactor)); + const FfxFloat32 fBoxScale = ffxLerp(3.0f, 1.0f, fBoxScaleT); + + const FfxFloat32x3 fScaledBoxVec = clippingBox.boxVec * fBoxScale; + const FfxFloat32x3 boxMin = clippingBox.boxCenter - fScaledBoxVec; + const FfxFloat32x3 boxMax = clippingBox.boxCenter + fScaledBoxVec; + + if (any(FFX_GREATER_THAN(boxMin, fHistoryColor)) || any(FFX_GREATER_THAN(fHistoryColor, boxMax))) { + + const FfxFloat32x3 fClampedHistoryColor = clamp(fHistoryColor, boxMin, boxMax); + + FfxFloat32x3 fHistoryContribution = ffxMax(fLumaInstabilityFactor, fLockContributionThisFrame).xxx; + + const FfxFloat32 fReactiveFactor = params.fDilatedReactiveFactor; + const FfxFloat32 fReactiveContribution = 1.0f - ffxPow(fReactiveFactor, 1.0f / 2.0f); + fHistoryContribution *= fReactiveContribution; + + // Scale history color using rectification info, also using accumulation mask to avoid potential invalid color protection + fHistoryColor = ffxLerp(fClampedHistoryColor, fHistoryColor, ffxSaturate(fHistoryContribution)); + + // Scale accumulation using rectification info + const FfxFloat32x3 fAccumulationMin = ffxMin(fAccumulation, FFX_BROADCAST_FLOAT32X3(0.1f)); + fAccumulation = ffxLerp(fAccumulationMin, fAccumulation, ffxSaturate(fHistoryContribution)); + } +} + +void WriteUpscaledOutput(FfxInt32x2 iPxHrPos, FfxFloat32x3 fUpscaledColor) +{ + StoreUpscaledOutput(iPxHrPos, fUpscaledColor); +} + +void FinalizeLockStatus(const AccumulationPassCommonParams params, FfxFloat32x2 fLockStatus, FfxFloat32 fUpsampledWeight) +{ + // we expect similar motion for next frame + // kill lock if that location is outside screen, avoid locks to be clamped to screen borders + FfxFloat32x2 fEstimatedUvNextFrame = params.fHrUv - params.fMotionVector; + if (IsUvInside(fEstimatedUvNextFrame) == false) { + KillLock(fLockStatus); + } + else { + // Decrease lock lifetime + const FfxFloat32 fLifetimeDecreaseLanczosMax = FfxFloat32(JitterSequenceLength()) * FfxFloat32(fAverageLanczosWeightPerFrame); + const FfxFloat32 fLifetimeDecrease = FfxFloat32(fUpsampledWeight / fLifetimeDecreaseLanczosMax); + fLockStatus[LOCK_LIFETIME_REMAINING] = ffxMax(FfxFloat32(0), fLockStatus[LOCK_LIFETIME_REMAINING] - fLifetimeDecrease); + } + + StoreLockStatus(params.iPxHrPos, fLockStatus); +} + + +FfxFloat32x3 ComputeBaseAccumulationWeight(const AccumulationPassCommonParams params, FfxFloat32 fThisFrameReactiveFactor, FfxBoolean bInMotionLastFrame, FfxFloat32 fUpsampledWeight, LockState lockState) +{ + // Always assume max accumulation was reached + FfxFloat32 fBaseAccumulation = fMaxAccumulationLanczosWeight * FfxFloat32(params.bIsExistingSample) * (1.0f - fThisFrameReactiveFactor) * (1.0f - params.fDepthClipFactor); + + fBaseAccumulation = ffxMin(fBaseAccumulation, ffxLerp(fBaseAccumulation, fUpsampledWeight * 10.0f, ffxMax(FfxFloat32(bInMotionLastFrame), ffxSaturate(params.fHrVelocity * FfxFloat32(10))))); + + fBaseAccumulation = ffxMin(fBaseAccumulation, ffxLerp(fBaseAccumulation, fUpsampledWeight, ffxSaturate(params.fHrVelocity / FfxFloat32(20)))); + + return fBaseAccumulation.xxx; +} + +FfxFloat32 ComputeLumaInstabilityFactor(const AccumulationPassCommonParams params, RectificationBox clippingBox, FfxFloat32 fThisFrameReactiveFactor, FfxFloat32 fLuminanceDiff) +{ + const FfxFloat32 fUnormThreshold = 1.0f / 255.0f; + const FfxInt32 N_MINUS_1 = 0; + const FfxInt32 N_MINUS_2 = 1; + const FfxInt32 N_MINUS_3 = 2; + const FfxInt32 N_MINUS_4 = 3; + + FfxFloat32 fCurrentFrameLuma = clippingBox.boxCenter.x; + +#if FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT + fCurrentFrameLuma = fCurrentFrameLuma / (1.0f + ffxMax(0.0f, fCurrentFrameLuma)); +#endif + + fCurrentFrameLuma = round(fCurrentFrameLuma * 255.0f) / 255.0f; + + const FfxBoolean bSampleLumaHistory = (ffxMax(ffxMax(params.fDepthClipFactor, params.fAccumulationMask), fLuminanceDiff) < 0.1f) && (params.bIsNewSample == false); + FfxFloat32x4 fCurrentFrameLumaHistory = bSampleLumaHistory ? SampleLumaHistory(params.fReprojectedHrUv) : FFX_BROADCAST_FLOAT32X4(0.0f); + + FfxFloat32 fLumaInstability = 0.0f; + FfxFloat32 fDiffs0 = (fCurrentFrameLuma - fCurrentFrameLumaHistory[N_MINUS_1]); + + FfxFloat32 fMin = abs(fDiffs0); + + if (fMin >= fUnormThreshold) { + for (int i = N_MINUS_2; i <= N_MINUS_4; i++) { + FfxFloat32 fDiffs1 = (fCurrentFrameLuma - fCurrentFrameLumaHistory[i]); + + if (sign(fDiffs0) == sign(fDiffs1)) { + + // Scale difference to protect historically similar values + const FfxFloat32 fMinBias = 1.0f; + fMin = ffxMin(fMin, abs(fDiffs1) * fMinBias); + } + } + + const FfxFloat32 fBoxSize = clippingBox.boxVec.x; + const FfxFloat32 fBoxSizeFactor = ffxPow(ffxSaturate(fBoxSize / 0.1f), 6.0f); + + fLumaInstability = FfxFloat32(fMin != abs(fDiffs0)) * fBoxSizeFactor; + fLumaInstability = FfxFloat32(fLumaInstability > fUnormThreshold); + + fLumaInstability *= 1.0f - ffxMax(params.fAccumulationMask, ffxPow(fThisFrameReactiveFactor, 1.0f / 6.0f)); + } + + //shift history + fCurrentFrameLumaHistory[N_MINUS_4] = fCurrentFrameLumaHistory[N_MINUS_3]; + fCurrentFrameLumaHistory[N_MINUS_3] = fCurrentFrameLumaHistory[N_MINUS_2]; + fCurrentFrameLumaHistory[N_MINUS_2] = fCurrentFrameLumaHistory[N_MINUS_1]; + fCurrentFrameLumaHistory[N_MINUS_1] = fCurrentFrameLuma; + + StoreLumaHistory(params.iPxHrPos, fCurrentFrameLumaHistory); + + return fLumaInstability * FfxFloat32(fCurrentFrameLumaHistory[N_MINUS_4] != 0); +} + +FfxFloat32 ComputeTemporalReactiveFactor(const AccumulationPassCommonParams params, FfxFloat32 fTemporalReactiveFactor) +{ + FfxFloat32 fNewFactor = ffxMin(0.99f, fTemporalReactiveFactor); + + fNewFactor = ffxMax(fNewFactor, ffxLerp(fNewFactor, 0.4f, ffxSaturate(params.fHrVelocity))); + + fNewFactor = ffxMax(fNewFactor * fNewFactor, ffxMax(params.fDepthClipFactor * 0.1f, params.fDilatedReactiveFactor)); + + // Force reactive factor for new samples + fNewFactor = params.bIsNewSample ? 1.0f : fNewFactor; + + if (ffxSaturate(params.fHrVelocity * 10.0f) >= 1.0f) { + fNewFactor = ffxMax(FSR3UPSCALER_EPSILON, fNewFactor) * -1.0f; + } + + return fNewFactor; +} + +AccumulationPassCommonParams InitParams(FfxInt32x2 iPxHrPos) +{ + AccumulationPassCommonParams params; + + params.iPxHrPos = iPxHrPos; + const FfxFloat32x2 fHrUv = (iPxHrPos + 0.5f) / DisplaySize(); + params.fHrUv = fHrUv; + + const FfxFloat32x2 fLrUvJittered = fHrUv + Jitter() / RenderSize(); + params.fLrUv_HwSampler = ClampUv(fLrUvJittered, RenderSize(), MaxRenderSize()); + + params.fMotionVector = GetMotionVector(iPxHrPos, fHrUv); + params.fHrVelocity = GetPxHrVelocity(params.fMotionVector); + + ComputeReprojectedUVs(params, params.fReprojectedHrUv, params.bIsExistingSample); + + params.fDepthClipFactor = ffxSaturate(SampleDepthClip(params.fLrUv_HwSampler)); + + const FfxFloat32x2 fDilatedReactiveMasks = SampleDilatedReactiveMasks(params.fLrUv_HwSampler); + params.fDilatedReactiveFactor = fDilatedReactiveMasks.x; + params.fAccumulationMask = fDilatedReactiveMasks.y; + params.bIsResetFrame = (0 == FrameIndex()); + + params.bIsNewSample = (params.bIsExistingSample == false || params.bIsResetFrame); + + return params; +} + +void Accumulate(FfxInt32x2 iPxHrPos) +{ + const AccumulationPassCommonParams params = InitParams(iPxHrPos); + + FfxFloat32x3 fHistoryColor = FfxFloat32x3(0, 0, 0); + FfxFloat32x2 fLockStatus; + InitializeNewLockSample(fLockStatus); + + FfxFloat32 fTemporalReactiveFactor = 0.0f; + FfxBoolean bInMotionLastFrame = FFX_FALSE; + LockState lockState = { FFX_FALSE , FFX_FALSE }; + if (params.bIsExistingSample && !params.bIsResetFrame) { + ReprojectHistoryColor(params, fHistoryColor, fTemporalReactiveFactor, bInMotionLastFrame); + lockState = ReprojectHistoryLockStatus(params, fLockStatus); + } + + FfxFloat32 fThisFrameReactiveFactor = ffxMax(params.fDilatedReactiveFactor, fTemporalReactiveFactor); + + FfxFloat32 fLuminanceDiff = 0.0f; + FfxFloat32 fLockContributionThisFrame = 0.0f; + UpdateLockStatus(params, fThisFrameReactiveFactor, lockState, fLockStatus, fLockContributionThisFrame, fLuminanceDiff); + + // Load upsampled input color + RectificationBox clippingBox; + FfxFloat32x4 fUpsampledColorAndWeight = ComputeUpsampledColorAndWeight(params, clippingBox, fThisFrameReactiveFactor); + + const FfxFloat32 fLumaInstabilityFactor = ComputeLumaInstabilityFactor(params, clippingBox, fThisFrameReactiveFactor, fLuminanceDiff); + + + FfxFloat32x3 fAccumulation = ComputeBaseAccumulationWeight(params, fThisFrameReactiveFactor, bInMotionLastFrame, fUpsampledColorAndWeight.w, lockState); + + if (params.bIsNewSample) { + fHistoryColor = YCoCgToRGB(fUpsampledColorAndWeight.xyz); + } + else { + RectifyHistory(params, clippingBox, fHistoryColor, fAccumulation, fLockContributionThisFrame, fThisFrameReactiveFactor, fLumaInstabilityFactor); + + Accumulate(params, fHistoryColor, fAccumulation, fUpsampledColorAndWeight); + } + + fHistoryColor = UnprepareRgb(fHistoryColor, Exposure()); + + FinalizeLockStatus(params, fLockStatus, fUpsampledColorAndWeight.w); + + // Get new temporal reactive factor + fTemporalReactiveFactor = ComputeTemporalReactiveFactor(params, fThisFrameReactiveFactor); + + StoreInternalColorAndWeight(iPxHrPos, FfxFloat32x4(fHistoryColor, fTemporalReactiveFactor)); + + // Output final color when RCAS is disabled +#if FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING == 0 + WriteUpscaledOutput(iPxHrPos, fHistoryColor); +#endif + StoreNewLocks(iPxHrPos, 0); +} + +#endif // FFX_FSR3UPSCALER_ACCUMULATE_H diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h new file mode 100644 index 00000000..2d9b5c91 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_callbacks_glsl.h @@ -0,0 +1,856 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "ffx_fsr3upscaler_resources.h" + +#if defined(FFX_GPU) +#include "ffx_core.h" +#endif // #if defined(FFX_GPU) + +#if defined(FFX_GPU) +#ifndef FFX_PREFER_WAVE64 +#define FFX_PREFER_WAVE64 +#endif // FFX_PREFER_WAVE64 + +#if defined(FSR3UPSCALER_BIND_CB_FSR3UPSCALER) + layout (set = 0, binding = FSR3UPSCALER_BIND_CB_FSR3UPSCALER, std140) uniform cbFSR3UPSCALER_t + { + FfxInt32x2 iRenderSize; + FfxInt32x2 iMaxRenderSize; + FfxInt32x2 iDisplaySize; + FfxInt32x2 iInputColorResourceDimensions; + FfxInt32x2 iLumaMipDimensions; + FfxInt32 iLumaMipLevelToUse; + FfxInt32 iFrameIndex; + + FfxFloat32x4 fDeviceToViewDepth; + FfxFloat32x2 fJitter; + FfxFloat32x2 fMotionVectorScale; + FfxFloat32x2 fDownscaleFactor; + FfxFloat32x2 fMotionVectorJitterCancellation; + FfxFloat32 fPreExposure; + FfxFloat32 fPreviousFramePreExposure; + FfxFloat32 fTanHalfFOV; + FfxFloat32 fJitterSequenceLength; + FfxFloat32 fDeltaTime; + FfxFloat32 fDynamicResChangeFactor; + FfxFloat32 fViewSpaceToMetersFactor; + } cbFSR3Upscaler; + + +FfxInt32x2 RenderSize() +{ + return cbFSR3Upscaler.iRenderSize; +} + +FfxInt32x2 MaxRenderSize() +{ + return cbFSR3Upscaler.iMaxRenderSize; +} + +FfxInt32x2 DisplaySize() +{ + return cbFSR3Upscaler.iDisplaySize; +} + +FfxInt32x2 InputColorResourceDimensions() +{ + return cbFSR3Upscaler.iInputColorResourceDimensions; +} + +FfxInt32x2 LumaMipDimensions() +{ + return cbFSR3Upscaler.iLumaMipDimensions; +} + +FfxInt32 LumaMipLevelToUse() +{ + return cbFSR3Upscaler.iLumaMipLevelToUse; +} + +FfxInt32 FrameIndex() +{ + return cbFSR3Upscaler.iFrameIndex; +} + +FfxFloat32x4 DeviceToViewSpaceTransformFactors() +{ + return cbFSR3Upscaler.fDeviceToViewDepth; +} + +FfxFloat32x2 Jitter() +{ + return cbFSR3Upscaler.fJitter; +} + +FfxFloat32x2 MotionVectorScale() +{ + return cbFSR3Upscaler.fMotionVectorScale; +} + +FfxFloat32x2 DownscaleFactor() +{ + return cbFSR3Upscaler.fDownscaleFactor; +} + +FfxFloat32x2 MotionVectorJitterCancellation() +{ + return cbFSR3Upscaler.fMotionVectorJitterCancellation; +} + +FfxFloat32 PreExposure() +{ + return cbFSR3Upscaler.fPreExposure; +} + +FfxFloat32 PreviousFramePreExposure() +{ + return cbFSR3Upscaler.fPreviousFramePreExposure; +} + +FfxFloat32 TanHalfFoV() +{ + return cbFSR3Upscaler.fTanHalfFOV; +} + +FfxFloat32 JitterSequenceLength() +{ + return cbFSR3Upscaler.fJitterSequenceLength; +} + +FfxFloat32 DeltaTime() +{ + return cbFSR3Upscaler.fDeltaTime; +} + +FfxFloat32 DynamicResChangeFactor() +{ + return cbFSR3Upscaler.fDynamicResChangeFactor; +} + +FfxFloat32 ViewSpaceToMetersFactor() +{ + return cbFSR3Upscaler.fViewSpaceToMetersFactor; +} + +#endif // #if defined(FSR3UPSCALER_BIND_CB_FSR3UPSCALER) + + +#ifdef FSR3UPSCALER_BIND_CB_AUTOREACTIVE +layout(set = 0, binding = FSR3UPSCALER_BIND_CB_AUTOREACTIVE, std140) uniform cbGenerateReactive_t +{ + FfxFloat32 fTcThreshold; + FfxFloat32 fTcScale; + FfxFloat32 fReactiveScale; + FfxFloat32 fReactiveMax; +} cbGenerateReactive; + +FfxFloat32 TcThreshold() +{ + return cbGenerateReactive.fTcThreshold; +} + +FfxFloat32 TcScale() +{ + return cbGenerateReactive.fTcScale; +} + +FfxFloat32 ReactiveScale() +{ + return cbGenerateReactive.fReactiveScale; +} + +FfxFloat32 ReactiveMax() +{ + return cbGenerateReactive.fReactiveMax; +} +#endif // #ifdef FSR3UPSCALER_BIND_CB_AUTOREACTIVE + +#if defined(FSR3UPSCALER_BIND_CB_RCAS) +layout(set = 0, binding = FSR3UPSCALER_BIND_CB_RCAS, std140) uniform cbRCAS_t +{ + FfxUInt32x4 rcasConfig; +} cbRCAS; + +FfxUInt32x4 RCASConfig() +{ + return cbRCAS.rcasConfig; +} +#endif // #if defined(FSR3UPSCALER_BIND_CB_RCAS) + + +#if defined(FSR3UPSCALER_BIND_CB_REACTIVE) +layout(set = 0, binding = FSR3UPSCALER_BIND_CB_REACTIVE, std140) uniform cbGenerateReactive_t +{ + FfxFloat32 scale; + FfxFloat32 threshold; + FfxFloat32 binaryValue; + FfxUInt32 flags; +} cbGenerateReactive; + +FfxFloat32 GenReactiveScale() +{ + return cbGenerateReactive.scale; +} + +FfxFloat32 GenReactiveThreshold() +{ + return cbGenerateReactive.threshold; +} + +FfxFloat32 GenReactiveBinaryValue() +{ + return cbGenerateReactive.binaryValue; +} + +FfxUInt32 GenReactiveFlags() +{ + return cbGenerateReactive.flags; +} +#endif // #if defined(FSR3UPSCALER_BIND_CB_REACTIVE) + + +#if defined(FSR3UPSCALER_BIND_CB_SPD) +layout(set = 0, binding = FSR3UPSCALER_BIND_CB_SPD, std140) uniform cbSPD_t +{ + FfxUInt32 mips; + FfxUInt32 numWorkGroups; + FfxUInt32x2 workGroupOffset; + FfxUInt32x2 renderSize; +} cbSPD; + +FfxUInt32 MipCount() +{ + return cbSPD.mips; +} + +FfxUInt32 NumWorkGroups() +{ + return cbSPD.numWorkGroups; +} + +FfxUInt32x2 WorkGroupOffset() +{ + return cbSPD.workGroupOffset; +} + +FfxUInt32x2 SPD_RenderSize() +{ + return cbSPD.renderSize; +} +#endif // #if defined(FSR3UPSCALER_BIND_CB_SPD) + +layout (set = 0, binding = 1000) uniform sampler s_PointClamp; +layout (set = 0, binding = 1001) uniform sampler s_LinearClamp; + +// SRVs +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY) uniform texture2D r_input_opaque_only; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_COLOR) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_INPUT_COLOR) uniform texture2D r_input_color_jittered; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS) uniform texture2D r_input_motion_vectors; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_DEPTH) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_INPUT_DEPTH) uniform texture2D r_input_depth; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE) uniform texture2D r_input_exposure; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_AUTO_EXPOSURE) + layout(set = 0, binding = FSR3UPSCALER_BIND_SRV_AUTO_EXPOSURE) uniform texture2D r_auto_exposure; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_REACTIVE_MASK) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_REACTIVE_MASK) uniform texture2D r_reactive_mask; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK) uniform texture2D r_transparency_and_composition_mask; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH) uniform utexture2D r_reconstructed_previous_nearest_depth; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS) uniform texture2D r_dilated_motion_vectors; +#endif +#if defined (FSR3UPSCALER_BIND_SRV_PREVIOUS_DILATED_MOTION_VECTORS) + layout(set = 0, binding = FSR3UPSCALER_BIND_SRV_PREVIOUS_DILATED_MOTION_VECTORS) uniform texture2D r_previous_dilated_motion_vectors; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_DEPTH) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_DILATED_DEPTH) uniform texture2D r_dilated_depth; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_INTERNAL_UPSCALED) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_INTERNAL_UPSCALED) uniform texture2D r_internal_upscaled_color; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_LOCK_STATUS) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_LOCK_STATUS) uniform texture2D r_lock_status; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_LOCK_INPUT_LUMA) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_LOCK_INPUT_LUMA) uniform texture2D r_lock_input_luma; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_NEW_LOCKS) + layout(set = 0, binding = FSR3UPSCALER_BIND_SRV_NEW_LOCKS) uniform texture2D r_new_locks; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR) uniform texture2D r_prepared_input_color; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_LUMA_HISTORY) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_LUMA_HISTORY) uniform texture2D r_luma_history; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_RCAS_INPUT) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_RCAS_INPUT) uniform texture2D r_rcas_input; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_LANCZOS_LUT) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_LANCZOS_LUT) uniform texture2D r_lanczos_lut; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS) uniform texture2D r_imgMips; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_UPSCALE_MAXIMUM_BIAS_LUT) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_UPSCALE_MAXIMUM_BIAS_LUT) uniform texture2D r_upsample_maximum_bias_lut; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS) + layout (set = 0, binding = FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS) uniform texture2D r_dilated_reactive_masks; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_PREV_PRE_ALPHA_COLOR) + layout(set = 0, binding = FSR3UPSCALER_BIND_SRV_PREV_PRE_ALPHA_COLOR) uniform texture2D r_input_prev_color_pre_alpha; +#endif +#if defined(FSR3UPSCALER_BIND_SRV_PREV_POST_ALPHA_COLOR) + layout(set = 0, binding = FSR3UPSCALER_BIND_SRV_PREV_POST_ALPHA_COLOR) uniform texture2D r_input_prev_color_post_alpha; +#endif + +// UAV +#if defined FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH, r32ui) uniform uimage2D rw_reconstructed_previous_nearest_depth; +#endif +#if defined FSR3UPSCALER_BIND_UAV_DILATED_MOTION_VECTORS + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_DILATED_MOTION_VECTORS, rg16f) writeonly uniform image2D rw_dilated_motion_vectors; +#endif +#if defined FSR3UPSCALER_BIND_UAV_DILATED_DEPTH + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_DILATED_DEPTH, r16f) writeonly uniform image2D rw_dilated_depth; +#endif +#if defined FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED, rgba16f) writeonly uniform image2D rw_internal_upscaled_color; +#endif +#if defined FSR3UPSCALER_BIND_UAV_LOCK_STATUS + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_LOCK_STATUS, rg16f) uniform image2D rw_lock_status; +#endif +#if defined(FSR3UPSCALER_BIND_UAV_LOCK_INPUT_LUMA) + layout(set = 0, binding = FSR3UPSCALER_BIND_UAV_LOCK_INPUT_LUMA, r16f) writeonly uniform image2D rw_lock_input_luma; +#endif +#if defined FSR3UPSCALER_BIND_UAV_NEW_LOCKS + layout(set = 0, binding = FSR3UPSCALER_BIND_UAV_NEW_LOCKS, r8) uniform image2D rw_new_locks; +#endif +#if defined FSR3UPSCALER_BIND_UAV_PREPARED_INPUT_COLOR + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_PREPARED_INPUT_COLOR, rgba16) writeonly uniform image2D rw_prepared_input_color; +#endif +#if defined FSR3UPSCALER_BIND_UAV_LUMA_HISTORY + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_LUMA_HISTORY, rgba8) uniform image2D rw_luma_history; +#endif +#if defined FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT /* app controlled format */) writeonly uniform image2D rw_upscaled_output; +#endif +#if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE, r16f) coherent uniform image2D rw_img_mip_shading_change; +#endif +#if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5, r16f) coherent uniform image2D rw_img_mip_5; +#endif +#if defined FSR3UPSCALER_BIND_UAV_DILATED_REACTIVE_MASKS + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_DILATED_REACTIVE_MASKS, rg8) writeonly uniform image2D rw_dilated_reactive_masks; +#endif +#if defined FSR3UPSCALER_BIND_UAV_EXPOSURE + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_EXPOSURE, rg32f) uniform image2D rw_exposure; +#endif +#if defined FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE + layout(set = 0, binding = FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE, rg32f) uniform image2D rw_auto_exposure; +#endif +#if defined FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC + layout (set = 0, binding = FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC, r32ui) coherent uniform uimage2D rw_spd_global_atomic; +#endif + +#if defined FSR3UPSCALER_BIND_UAV_AUTOREACTIVE + layout(set = 0, binding = FSR3UPSCALER_BIND_UAV_AUTOREACTIVE, r32f) uniform image2D rw_output_autoreactive; +#endif +#if defined FSR3UPSCALER_BIND_UAV_AUTOCOMPOSITION + layout(set = 0, binding = FSR3UPSCALER_BIND_UAV_AUTOCOMPOSITION, r32f) uniform image2D rw_output_autocomposition; +#endif +#if defined FSR3UPSCALER_BIND_UAV_PREV_PRE_ALPHA_COLOR + layout(set = 0, binding = FSR3UPSCALER_BIND_UAV_PREV_PRE_ALPHA_COLOR, r11f_g11f_b10f) uniform image2D rw_output_prev_color_pre_alpha; +#endif +#if defined FSR3UPSCALER_BIND_UAV_PREV_POST_ALPHA_COLOR + layout(set = 0, binding = FSR3UPSCALER_BIND_UAV_PREV_POST_ALPHA_COLOR, r11f_g11f_b10f) uniform image2D rw_output_prev_color_post_alpha; +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS) +FfxFloat32 LoadMipLuma(FfxInt32x2 iPxPos, FfxInt32 mipLevel) +{ + return texelFetch(r_imgMips, iPxPos, FfxInt32(mipLevel)).r; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS) +FfxFloat32 SampleMipLuma(FfxFloat32x2 fUV, FfxInt32 mipLevel) +{ + return textureLod(sampler2D(r_imgMips, s_LinearClamp), fUV, FfxFloat32(mipLevel)).r; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_DEPTH) +FfxFloat32 LoadInputDepth(FfxInt32x2 iPxPos) +{ + return texelFetch(r_input_depth, iPxPos, 0).r; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_REACTIVE_MASK) +FfxFloat32 LoadReactiveMask(FfxInt32x2 iPxPos) +{ + return texelFetch(r_reactive_mask, FfxInt32x2(iPxPos), 0).r; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK) +FfxFloat32 LoadTransparencyAndCompositionMask(FfxUInt32x2 iPxPos) +{ + return texelFetch(r_transparency_and_composition_mask, FfxInt32x2(iPxPos), 0).r; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_COLOR) +FfxFloat32x3 LoadInputColor(FfxInt32x2 iPxPos) +{ + return texelFetch(r_input_color_jittered, iPxPos, 0).rgb; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_COLOR) +FfxFloat32x3 SampleInputColor(FfxFloat32x2 fUV) +{ + return textureLod(sampler2D(r_input_color_jittered, s_LinearClamp), fUV, 0.0f).rgb; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR) +FfxFloat32x3 LoadPreparedInputColor(FfxInt32x2 iPxPos) +{ + return texelFetch(r_prepared_input_color, iPxPos, 0).xyz; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS) +FfxFloat32x2 LoadInputMotionVector(FfxInt32x2 iPxDilatedMotionVectorPos) +{ + FfxFloat32x2 fSrcMotionVector = texelFetch(r_input_motion_vectors, iPxDilatedMotionVectorPos, 0).xy; + + FfxFloat32x2 fUvMotionVector = fSrcMotionVector * MotionVectorScale(); + +#if FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS + fUvMotionVector -= MotionVectorJitterCancellation(); +#endif + + return fUvMotionVector; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INTERNAL_UPSCALED) +FfxFloat32x4 LoadHistory(FfxInt32x2 iPxHistory) +{ + return texelFetch(r_internal_upscaled_color, iPxHistory, 0); +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_LUMA_HISTORY) +void StoreLumaHistory(FfxInt32x2 iPxPos, FfxFloat32x4 fLumaHistory) +{ + imageStore(rw_luma_history, FfxInt32x2(iPxPos), fLumaHistory); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_LUMA_HISTORY) +FfxFloat32x4 SampleLumaHistory(FfxFloat32x2 fUV) +{ + return textureLod(sampler2D(r_luma_history, s_LinearClamp), fUV, 0.0f); +} +#endif + +FfxFloat32x4 LoadRCAS_Input(FfxInt32x2 iPxPos) +{ +#if defined(FSR3UPSCALER_BIND_SRV_RCAS_INPUT) + return texelFetch(r_rcas_input, iPxPos, 0); +#else + return FfxFloat32x4(0.0); +#endif +} + +#if defined(FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED) +void StoreReprojectedHistory(FfxInt32x2 iPxHistory, FfxFloat32x4 fHistory) +{ + imageStore(rw_internal_upscaled_color, iPxHistory, fHistory); +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED) +void StoreInternalColorAndWeight(FfxInt32x2 iPxPos, FfxFloat32x4 fColorAndWeight) +{ + imageStore(rw_internal_upscaled_color, FfxInt32x2(iPxPos), fColorAndWeight); +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT) +void StoreUpscaledOutput(FfxInt32x2 iPxPos, FfxFloat32x3 fColor) +{ + imageStore(rw_upscaled_output, FfxInt32x2(iPxPos), FfxFloat32x4(fColor, 1.f)); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_LOCK_STATUS) +FfxFloat32x2 LoadLockStatus(FfxInt32x2 iPxPos) +{ + FfxFloat32x2 fLockStatus = texelFetch(r_lock_status, iPxPos, 0).rg; + + return fLockStatus; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_LOCK_STATUS) +void StoreLockStatus(FfxInt32x2 iPxPos, FfxFloat32x2 fLockstatus) +{ + imageStore(rw_lock_status, iPxPos, vec4(fLockstatus, 0.0f, 0.0f)); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_LOCK_INPUT_LUMA) +FfxFloat32 LoadLockInputLuma(FfxInt32x2 iPxPos) +{ + return texelFetch(r_lock_input_luma, iPxPos, 0).r; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_LOCK_INPUT_LUMA) +void StoreLockInputLuma(FfxInt32x2 iPxPos, FfxFloat32 fLuma) +{ + imageStore(rw_lock_input_luma, iPxPos, vec4(fLuma, 0, 0, 0)); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_NEW_LOCKS) +FfxFloat32 LoadNewLocks(FfxInt32x2 iPxPos) +{ + return texelFetch(r_new_locks, iPxPos, 0).r; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_NEW_LOCKS) +FfxFloat32 LoadRwNewLocks(FfxInt32x2 iPxPos) +{ + return imageLoad(rw_new_locks, iPxPos).r; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_NEW_LOCKS) +void StoreNewLocks(FfxInt32x2 iPxPos, FfxFloat32 newLock) +{ + imageStore(rw_new_locks, iPxPos, vec4(newLock, 0, 0, 0)); +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_PREPARED_INPUT_COLOR) +void StorePreparedInputColor(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x4 fTonemapped) +{ + imageStore(rw_prepared_input_color, iPxPos, fTonemapped); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR) +FfxFloat32 SampleDepthClip(FfxFloat32x2 fUV) +{ + return textureLod(sampler2D(r_prepared_input_color, s_LinearClamp), fUV, 0.0f).w; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_LOCK_STATUS) +FfxFloat32x2 SampleLockStatus(FfxFloat32x2 fUV) +{ + FfxFloat32x2 fLockStatus = textureLod(sampler2D(r_lock_status, s_LinearClamp), fUV, 0.0f).rg; + return fLockStatus; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_DEPTH) +FfxFloat32 LoadSceneDepth(FfxInt32x2 iPxInput) +{ + return texelFetch(r_input_depth, iPxInput, 0).r; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH) +FfxFloat32 LoadReconstructedPrevDepth(FfxInt32x2 iPxPos) +{ + return uintBitsToFloat(texelFetch(r_reconstructed_previous_nearest_depth, iPxPos, 0).r); +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH) +void StoreReconstructedDepth(FfxInt32x2 iPxSample, FfxFloat32 fDepth) +{ + FfxUInt32 uDepth = floatBitsToUint(fDepth); + + #if FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH + imageAtomicMax(rw_reconstructed_previous_nearest_depth, iPxSample, uDepth); + #else + imageAtomicMin(rw_reconstructed_previous_nearest_depth, iPxSample, uDepth); // min for standard, max for inverted depth + #endif +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH) +void SetReconstructedDepth(FfxInt32x2 iPxSample, FfxUInt32 uValue) +{ + imageStore(rw_reconstructed_previous_nearest_depth, iPxSample, uvec4(uValue, 0, 0, 0)); +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_DILATED_DEPTH) +void StoreDilatedDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32 fDepth) +{ + //FfxUInt32 uDepth = f32tof16(fDepth); + imageStore(rw_dilated_depth, iPxPos, vec4(fDepth, 0.0f, 0.0f, 0.0f)); +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_DILATED_MOTION_VECTORS) +void StoreDilatedMotionVector(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 fMotionVector) +{ + imageStore(rw_dilated_motion_vectors, iPxPos, vec4(fMotionVector, 0.0f, 0.0f)); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS) +FfxFloat32x2 LoadDilatedMotionVector(FfxInt32x2 iPxInput) +{ + return texelFetch(r_dilated_motion_vectors, iPxInput, 0).rg; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS) +FfxFloat32x2 SampleDilatedMotionVector(FfxFloat32x2 fUV) +{ + return textureLod(sampler2D(r_dilated_motion_vectors, s_LinearClamp), fUV, 0.0f).rg; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_PREVIOUS_DILATED_MOTION_VECTORS) +FfxFloat32x2 LoadPreviousDilatedMotionVector(FfxInt32x2 iPxInput) +{ + return texelFetch(r_previous_dilated_motion_vectors, iPxInput, 0).rg; +} + +FfxFloat32x2 SamplePreviousDilatedMotionVector(FfxFloat32x2 fUV) +{ + return textureLod(sampler2D(r_previous_dilated_motion_vectors, s_LinearClamp), fUV, 0.0f).xy; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_DEPTH) +FfxFloat32 LoadDilatedDepth(FfxInt32x2 iPxInput) +{ + return texelFetch(r_dilated_depth, iPxInput, 0).r; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE) +FfxFloat32 Exposure() +{ + FfxFloat32 exposure = texelFetch(r_input_exposure, FfxInt32x2(0, 0), 0).x; + + if (exposure == 0.0f) { + exposure = 1.0f; + } + + return exposure; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_AUTO_EXPOSURE) +FfxFloat32 AutoExposure() +{ + FfxFloat32 exposure = texelFetch(r_auto_exposure, FfxInt32x2(0, 0), 0).x; + + if (exposure == 0.0f) { + exposure = 1.0f; + } + + return exposure; +} +#endif + +FfxFloat32 SampleLanczos2Weight(FfxFloat32 x) +{ +#if defined(FSR3UPSCALER_BIND_SRV_LANCZOS_LUT) + return textureLod(sampler2D(r_lanczos_lut, s_LinearClamp), FfxFloat32x2(x / 2.0f, 0.5f), 0.0f).x; +#else + return 0.f; +#endif +} + +#if defined(FSR3UPSCALER_BIND_SRV_UPSCALE_MAXIMUM_BIAS_LUT) +FfxFloat32 SampleUpsampleMaximumBias(FfxFloat32x2 uv) +{ + // Stored as a SNORM, so make sure to multiply by 2 to retrieve the actual expected range. + return FfxFloat32(2.0f) * FfxFloat32(textureLod(sampler2D(r_upsample_maximum_bias_lut, s_LinearClamp), abs(uv) * 2.0f, 0.0f).r); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS) +FfxFloat32x2 SampleDilatedReactiveMasks(FfxFloat32x2 fUV) +{ + return textureLod(sampler2D(r_dilated_reactive_masks, s_LinearClamp), fUV, 0.0f).rg; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS) +FfxFloat32x2 LoadDilatedReactiveMasks(FFX_PARAMETER_IN FfxInt32x2 iPxPos) +{ + return texelFetch(r_dilated_reactive_masks, iPxPos, 0).rg; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_DILATED_REACTIVE_MASKS) +void StoreDilatedReactiveMasks(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 fDilatedReactiveMasks) +{ + imageStore(rw_dilated_reactive_masks, iPxPos, vec4(fDilatedReactiveMasks, 0.0f, 0.0f)); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY) +FfxFloat32x3 LoadOpaqueOnly(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos) +{ + return texelFetch(r_input_opaque_only, iPxPos, 0).xyz; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_PREV_PRE_ALPHA_COLOR) +FfxFloat32x3 LoadPrevPreAlpha(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos) +{ + return texelFetch(r_input_prev_color_pre_alpha, iPxPos, 0).xyz; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_PREV_POST_ALPHA_COLOR) +FfxFloat32x3 LoadPrevPostAlpha(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos) +{ + return texelFetch(r_input_prev_color_post_alpha, iPxPos, 0).xyz; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_AUTOREACTIVE) +#if defined(FSR3UPSCALER_BIND_UAV_AUTOCOMPOSITION) +void StoreAutoReactive(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos, FFX_PARAMETER_IN FFX_MIN16_F2 fReactive) +{ + imageStore(rw_output_autoreactive, iPxPos, vec4(FfxFloat32(fReactive.x), 0.0f, 0.0f, 0.0f)); + + imageStore(rw_output_autocomposition, iPxPos, vec4(FfxFloat32(fReactive.y), 0.0f, 0.0f, 0.0f)); +} +#endif +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_PREV_PRE_ALPHA_COLOR) +void StorePrevPreAlpha(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos, FFX_PARAMETER_IN FFX_MIN16_F3 color) +{ + imageStore(rw_output_prev_color_pre_alpha, iPxPos, vec4(color, 0.0f)); +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_PREV_POST_ALPHA_COLOR) +void StorePrevPostAlpha(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos, FFX_PARAMETER_IN FFX_MIN16_F3 color) +{ + imageStore(rw_output_prev_color_post_alpha, iPxPos, vec4(color, 0.0f)); +} +#endif + +FfxFloat32x2 SPD_LoadExposureBuffer() +{ +#if defined FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE + return imageLoad(rw_auto_exposure, ivec2(0, 0)).xy; +#else + return FfxFloat32x2(0.f, 0.f); +#endif // #if defined FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE +} + +void SPD_SetExposureBuffer(FfxFloat32x2 value) +{ +#if defined FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE + imageStore(rw_auto_exposure, ivec2(0, 0), vec4(value, 0.0f, 0.0f)); +#endif // #if defined FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE +} + +FfxFloat32x4 SPD_LoadMipmap5(FfxInt32x2 iPxPos) +{ +#if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 + return FfxFloat32x4(imageLoad(rw_img_mip_5, iPxPos).x, 0.0f, 0.0f, 0.0f); +#else + return FfxFloat32x4(0.f, 0.f, 0.f, 0.f); +#endif // #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 +} + +void SPD_SetMipmap(FfxInt32x2 iPxPos, FfxUInt32 slice, FfxFloat32 value) +{ + switch (slice) + { + case FFX_FSR3UPSCALER_SHADING_CHANGE_MIP_LEVEL: +#if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE + imageStore(rw_img_mip_shading_change, iPxPos, FfxFloat32x4(value, 0.0f, 0.0f, 0.0f)); +#endif // #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE + break; + case 5: +#if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 + imageStore(rw_img_mip_5, iPxPos, FfxFloat32x4(value, 0.0f, 0.0f, 0.0f)); +#endif // #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 + break; + default: + + // avoid flattened side effect +#if defined(FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE) + imageStore(rw_img_mip_shading_change, iPxPos, FfxFloat32x4(imageLoad(rw_img_mip_shading_change, iPxPos).x, 0.0f, 0.0f, 0.0f)); +#elif defined(FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5) + imageStore(rw_img_mip_5, iPxPos, FfxFloat32x4(imageLoad(rw_img_mip_5, iPxPos).x, 0.0f, 0.0f, 0.0f)); +#endif // #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE + break; + } +} + +void SPD_IncreaseAtomicCounter(inout FfxUInt32 spdCounter) +{ +#if defined FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC + spdCounter = imageAtomicAdd(rw_spd_global_atomic, ivec2(0, 0), 1); +#endif // #if defined FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC +} + +void SPD_ResetAtomicCounter() +{ +#if defined FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC + imageStore(rw_spd_global_atomic, ivec2(0, 0), uvec4(0)); +#endif // #if defined FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC +} + +#endif // #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h new file mode 100644 index 00000000..d915cef6 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h @@ -0,0 +1,912 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "ffx_fsr3upscaler_resources.h" + +#if defined(FFX_GPU) +#ifdef __hlsl_dx_compiler +#pragma dxc diagnostic push +#pragma dxc diagnostic ignored "-Wambig-lit-shift" +#endif //__hlsl_dx_compiler +#include "ffx_core.h" +#ifdef __hlsl_dx_compiler +#pragma dxc diagnostic pop +#endif //__hlsl_dx_compiler +#endif // #if defined(FFX_GPU) + +#if defined(FFX_GPU) +#ifndef FFX_PREFER_WAVE64 +#define FFX_PREFER_WAVE64 +#endif // FFX_PREFER_WAVE64 + +#if defined(FFX_GPU) +#pragma warning(disable: 3205) // conversion from larger type to smaller +#endif // #if defined(FFX_GPU) + +#define DECLARE_SRV_REGISTER(regIndex) t##regIndex +#define DECLARE_UAV_REGISTER(regIndex) u##regIndex +#define DECLARE_CB_REGISTER(regIndex) b##regIndex +#define FFX_FSR3UPSCALER_DECLARE_SRV(regIndex) register(DECLARE_SRV_REGISTER(regIndex)) +#define FFX_FSR3UPSCALER_DECLARE_UAV(regIndex) register(DECLARE_UAV_REGISTER(regIndex)) +#define FFX_FSR3UPSCALER_DECLARE_CB(regIndex) register(DECLARE_CB_REGISTER(regIndex)) + +#if defined(FSR3UPSCALER_BIND_CB_FSR3UPSCALER) + cbuffer cbFSR3Upscaler : FFX_FSR3UPSCALER_DECLARE_CB(FSR3UPSCALER_BIND_CB_FSR3UPSCALER) + { + FfxInt32x2 iRenderSize; + FfxInt32x2 iMaxRenderSize; + FfxInt32x2 iDisplaySize; + FfxInt32x2 iInputColorResourceDimensions; + FfxInt32x2 iLumaMipDimensions; + FfxInt32 iLumaMipLevelToUse; + FfxInt32 iFrameIndex; + + FfxFloat32x4 fDeviceToViewDepth; + FfxFloat32x2 fJitter; + FfxFloat32x2 fMotionVectorScale; + FfxFloat32x2 fDownscaleFactor; + FfxFloat32x2 fMotionVectorJitterCancellation; + FfxFloat32 fPreExposure; + FfxFloat32 fPreviousFramePreExposure; + FfxFloat32 fTanHalfFOV; + FfxFloat32 fJitterSequenceLength; + FfxFloat32 fDeltaTime; + FfxFloat32 fDynamicResChangeFactor; + FfxFloat32 fViewSpaceToMetersFactor; + }; + +#define FFX_FSR3UPSCALER_CONSTANT_BUFFER_1_SIZE (sizeof(cbFSR3Upscaler) / 4) // Number of 32-bit values. This must be kept in sync with the cbFSR3Upscaler size. + +/* Define getter functions in the order they are defined in the CB! */ +FfxInt32x2 RenderSize() +{ + return iRenderSize; +} + +FfxInt32x2 MaxRenderSize() +{ + return iMaxRenderSize; +} + +FfxInt32x2 DisplaySize() +{ + return iDisplaySize; +} + +FfxInt32x2 InputColorResourceDimensions() +{ + return iInputColorResourceDimensions; +} + +FfxInt32x2 LumaMipDimensions() +{ + return iLumaMipDimensions; +} + +FfxInt32 LumaMipLevelToUse() +{ + return iLumaMipLevelToUse; +} + +FfxInt32 FrameIndex() +{ + return iFrameIndex; +} + +FfxFloat32x2 Jitter() +{ + return fJitter; +} + +FfxFloat32x4 DeviceToViewSpaceTransformFactors() +{ + return fDeviceToViewDepth; +} + +FfxFloat32x2 MotionVectorScale() +{ + return fMotionVectorScale; +} + +FfxFloat32x2 DownscaleFactor() +{ + return fDownscaleFactor; +} + +FfxFloat32x2 MotionVectorJitterCancellation() +{ + return fMotionVectorJitterCancellation; +} + +FfxFloat32 PreExposure() +{ + return fPreExposure; +} + +FfxFloat32 PreviousFramePreExposure() +{ + return fPreviousFramePreExposure; +} + +FfxFloat32 TanHalfFoV() +{ + return fTanHalfFOV; +} + +FfxFloat32 JitterSequenceLength() +{ + return fJitterSequenceLength; +} + +FfxFloat32 DeltaTime() +{ + return fDeltaTime; +} + +FfxFloat32 DynamicResChangeFactor() +{ + return fDynamicResChangeFactor; +} + +FfxFloat32 ViewSpaceToMetersFactor() +{ + return fViewSpaceToMetersFactor; +} +#endif // #if defined(FSR3UPSCALER_BIND_CB_FSR3UPSCALER) + +#define FFX_FSR3UPSCALER_ROOTSIG_STRINGIFY(p) FFX_FSR3UPSCALER_ROOTSIG_STR(p) +#define FFX_FSR3UPSCALER_ROOTSIG_STR(p) #p +#define FFX_FSR3UPSCALER_ROOTSIG [RootSignature( "DescriptorTable(UAV(u0, numDescriptors = " FFX_FSR3UPSCALER_ROOTSIG_STRINGIFY(FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_COUNT) ")), " \ + "DescriptorTable(SRV(t0, numDescriptors = " FFX_FSR3UPSCALER_ROOTSIG_STRINGIFY(FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_COUNT) ")), " \ + "RootConstants(num32BitConstants=" FFX_FSR3UPSCALER_ROOTSIG_STRINGIFY(FFX_FSR3UPSCALER_CONSTANT_BUFFER_1_SIZE) ", b0), " \ + "StaticSampler(s0, filter = FILTER_MIN_MAG_MIP_POINT, " \ + "addressU = TEXTURE_ADDRESS_CLAMP, " \ + "addressV = TEXTURE_ADDRESS_CLAMP, " \ + "addressW = TEXTURE_ADDRESS_CLAMP, " \ + "comparisonFunc = COMPARISON_NEVER, " \ + "borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK), " \ + "StaticSampler(s1, filter = FILTER_MIN_MAG_MIP_LINEAR, " \ + "addressU = TEXTURE_ADDRESS_CLAMP, " \ + "addressV = TEXTURE_ADDRESS_CLAMP, " \ + "addressW = TEXTURE_ADDRESS_CLAMP, " \ + "comparisonFunc = COMPARISON_NEVER, " \ + "borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK)" )] + +#define FFX_FSR3UPSCALER_CONSTANT_BUFFER_2_SIZE 6 // Number of 32-bit values. This must be kept in sync with max( cbRCAS , cbSPD) size. + +#define FFX_FSR3UPSCALER_CB2_ROOTSIG [RootSignature( "DescriptorTable(UAV(u0, numDescriptors = " FFX_FSR3UPSCALER_ROOTSIG_STRINGIFY(FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_COUNT) ")), " \ + "DescriptorTable(SRV(t0, numDescriptors = " FFX_FSR3UPSCALER_ROOTSIG_STRINGIFY(FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_COUNT) ")), " \ + "RootConstants(num32BitConstants=" FFX_FSR3UPSCALER_ROOTSIG_STRINGIFY(FFX_FSR3UPSCALER_CONSTANT_BUFFER_1_SIZE) ", b0), " \ + "RootConstants(num32BitConstants=" FFX_FSR3UPSCALER_ROOTSIG_STRINGIFY(FFX_FSR3UPSCALER_CONSTANT_BUFFER_2_SIZE) ", b1), " \ + "StaticSampler(s0, filter = FILTER_MIN_MAG_MIP_POINT, " \ + "addressU = TEXTURE_ADDRESS_CLAMP, " \ + "addressV = TEXTURE_ADDRESS_CLAMP, " \ + "addressW = TEXTURE_ADDRESS_CLAMP, " \ + "comparisonFunc = COMPARISON_NEVER, " \ + "borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK), " \ + "StaticSampler(s1, filter = FILTER_MIN_MAG_MIP_LINEAR, " \ + "addressU = TEXTURE_ADDRESS_CLAMP, " \ + "addressV = TEXTURE_ADDRESS_CLAMP, " \ + "addressW = TEXTURE_ADDRESS_CLAMP, " \ + "comparisonFunc = COMPARISON_NEVER, " \ + "borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK)" )] +#if defined(FFX_FSR3UPSCALER_EMBED_ROOTSIG) +#define FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT FFX_FSR3UPSCALER_ROOTSIG +#define FFX_FSR3UPSCALER_EMBED_CB2_ROOTSIG_CONTENT FFX_FSR3UPSCALER_CB2_ROOTSIG +#else +#define FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +#define FFX_FSR3UPSCALER_EMBED_CB2_ROOTSIG_CONTENT +#endif // #if FFX_FSR3UPSCALER_EMBED_ROOTSIG + +#if defined(FSR3UPSCALER_BIND_CB_AUTOREACTIVE) +cbuffer cbGenerateReactive : FFX_FSR3UPSCALER_DECLARE_CB(FSR3UPSCALER_BIND_CB_AUTOREACTIVE) +{ + FfxFloat32 fTcThreshold; // 0.1 is a good starting value, lower will result in more TC pixels + FfxFloat32 fTcScale; + FfxFloat32 fReactiveScale; + FfxFloat32 fReactiveMax; +}; + +FfxFloat32 TcThreshold() +{ + return fTcThreshold; +} + +FfxFloat32 TcScale() +{ + return fTcScale; +} + +FfxFloat32 ReactiveScale() +{ + return fReactiveScale; +} + +FfxFloat32 ReactiveMax() +{ + return fReactiveMax; +} +#endif // #if defined(FSR3UPSCALER_BIND_CB_AUTOREACTIVE) + +#if defined(FSR3UPSCALER_BIND_CB_RCAS) +cbuffer cbRCAS : FFX_FSR3UPSCALER_DECLARE_CB(FSR3UPSCALER_BIND_CB_RCAS) +{ + FfxUInt32x4 rcasConfig; +}; + +FfxUInt32x4 RCASConfig() +{ + return rcasConfig; +} +#endif // #if defined(FSR3UPSCALER_BIND_CB_RCAS) + + +#if defined(FSR3UPSCALER_BIND_CB_REACTIVE) +cbuffer cbGenerateReactive : FFX_FSR3UPSCALER_DECLARE_CB(FSR3UPSCALER_BIND_CB_REACTIVE) +{ + FfxFloat32 gen_reactive_scale; + FfxFloat32 gen_reactive_threshold; + FfxFloat32 gen_reactive_binaryValue; + FfxUInt32 gen_reactive_flags; +}; + +FfxFloat32 GenReactiveScale() +{ + return gen_reactive_scale; +} + +FfxFloat32 GenReactiveThreshold() +{ + return gen_reactive_threshold; +} + +FfxFloat32 GenReactiveBinaryValue() +{ + return gen_reactive_binaryValue; +} + +FfxUInt32 GenReactiveFlags() +{ + return gen_reactive_flags; +} +#endif // #if defined(FSR3UPSCALER_BIND_CB_REACTIVE) + +#if defined(FSR3UPSCALER_BIND_CB_SPD) +cbuffer cbSPD : FFX_FSR3UPSCALER_DECLARE_CB(FSR3UPSCALER_BIND_CB_SPD) { + + FfxUInt32 mips; + FfxUInt32 numWorkGroups; + FfxUInt32x2 workGroupOffset; + FfxUInt32x2 renderSize; +}; + +FfxUInt32 MipCount() +{ + return mips; +} + +FfxUInt32 NumWorkGroups() +{ + return numWorkGroups; +} + +FfxUInt32x2 WorkGroupOffset() +{ + return workGroupOffset; +} + +FfxUInt32x2 SPD_RenderSize() +{ + return renderSize; +} +#endif // #if defined(FSR3UPSCALER_BIND_CB_SPD) + +SamplerState s_PointClamp : register(s0); +SamplerState s_LinearClamp : register(s1); + + // SRVs + #if defined FSR3UPSCALER_BIND_SRV_INPUT_COLOR + Texture2D r_input_color_jittered : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_COLOR); + #endif + #if defined FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY + Texture2D r_input_opaque_only : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY); + #endif + #if defined FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS + Texture2D r_input_motion_vectors : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS); + #endif + #if defined FSR3UPSCALER_BIND_SRV_INPUT_DEPTH + Texture2D r_input_depth : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_DEPTH); + #endif + #if defined FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE + Texture2D r_input_exposure : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE); + #endif + #if defined FSR3UPSCALER_BIND_SRV_AUTO_EXPOSURE + Texture2D r_auto_exposure : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_AUTO_EXPOSURE); + #endif + #if defined FSR3UPSCALER_BIND_SRV_REACTIVE_MASK + Texture2D r_reactive_mask : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_REACTIVE_MASK); + #endif + #if defined FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK + Texture2D r_transparency_and_composition_mask : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK); + #endif + #if defined FSR3UPSCALER_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH + Texture2D r_reconstructed_previous_nearest_depth : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH); + #endif + #if defined FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS + Texture2D r_dilated_motion_vectors : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS); + #endif + #if defined FSR3UPSCALER_BIND_SRV_PREVIOUS_DILATED_MOTION_VECTORS + Texture2D r_previous_dilated_motion_vectors : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_PREVIOUS_DILATED_MOTION_VECTORS); + #endif + #if defined FSR3UPSCALER_BIND_SRV_DILATED_DEPTH + Texture2D r_dilated_depth : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_DILATED_DEPTH); + #endif + #if defined FSR3UPSCALER_BIND_SRV_INTERNAL_UPSCALED + Texture2D r_internal_upscaled_color : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INTERNAL_UPSCALED); + #endif + #if defined FSR3UPSCALER_BIND_SRV_LOCK_STATUS + Texture2D r_lock_status : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_LOCK_STATUS); + #endif + #if defined FSR3UPSCALER_BIND_SRV_LOCK_INPUT_LUMA + Texture2D r_lock_input_luma : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_LOCK_INPUT_LUMA); + #endif + #if defined FSR3UPSCALER_BIND_SRV_NEW_LOCKS + Texture2D r_new_locks : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_NEW_LOCKS); + #endif + #if defined FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR + Texture2D r_prepared_input_color : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR); + #endif + #if defined FSR3UPSCALER_BIND_SRV_LUMA_HISTORY + Texture2D r_luma_history : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_LUMA_HISTORY); + #endif + #if defined FSR3UPSCALER_BIND_SRV_RCAS_INPUT + Texture2D r_rcas_input : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_RCAS_INPUT); + #endif + #if defined FSR3UPSCALER_BIND_SRV_LANCZOS_LUT + Texture2D r_lanczos_lut : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_LANCZOS_LUT); + #endif + #if defined FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS + Texture2D r_imgMips : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS); + #endif + #if defined FSR3UPSCALER_BIND_SRV_UPSCALE_MAXIMUM_BIAS_LUT + Texture2D r_upsample_maximum_bias_lut : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_UPSCALE_MAXIMUM_BIAS_LUT); + #endif + #if defined FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS + Texture2D r_dilated_reactive_masks : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS); + #endif + + #if defined FSR3UPSCALER_BIND_SRV_PREV_PRE_ALPHA_COLOR + Texture2D r_input_prev_color_pre_alpha : FFX_FSR3UPSCALER_DECLARE_SRV(FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR); + #endif + #if defined FSR3UPSCALER_BIND_SRV_PREV_POST_ALPHA_COLOR + Texture2D r_input_prev_color_post_alpha : FFX_FSR3UPSCALER_DECLARE_SRV(FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR); + #endif + + // UAV declarations + #if defined FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH + RWTexture2D rw_reconstructed_previous_nearest_depth : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH); + #endif + #if defined FSR3UPSCALER_BIND_UAV_DILATED_MOTION_VECTORS + RWTexture2D rw_dilated_motion_vectors : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_DILATED_MOTION_VECTORS); + #endif + #if defined FSR3UPSCALER_BIND_UAV_DILATED_DEPTH + RWTexture2D rw_dilated_depth : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_DILATED_DEPTH); + #endif + #if defined FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED + RWTexture2D rw_internal_upscaled_color : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED); + #endif + #if defined FSR3UPSCALER_BIND_UAV_LOCK_STATUS + RWTexture2D rw_lock_status : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_LOCK_STATUS); + #endif + #if defined FSR3UPSCALER_BIND_UAV_LOCK_INPUT_LUMA + RWTexture2D rw_lock_input_luma : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_LOCK_INPUT_LUMA); + #endif + #if defined FSR3UPSCALER_BIND_UAV_NEW_LOCKS + RWTexture2D rw_new_locks : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_NEW_LOCKS); + #endif + #if defined FSR3UPSCALER_BIND_UAV_PREPARED_INPUT_COLOR + RWTexture2D rw_prepared_input_color : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_PREPARED_INPUT_COLOR); + #endif + #if defined FSR3UPSCALER_BIND_UAV_LUMA_HISTORY + RWTexture2D rw_luma_history : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_LUMA_HISTORY); + #endif + #if defined FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT + RWTexture2D rw_upscaled_output : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT); + #endif + #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE + globallycoherent RWTexture2D rw_img_mip_shading_change : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE); + #endif + #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 + globallycoherent RWTexture2D rw_img_mip_5 : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5); + #endif + #if defined FSR3UPSCALER_BIND_UAV_DILATED_REACTIVE_MASKS + RWTexture2D rw_dilated_reactive_masks : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_DILATED_REACTIVE_MASKS); + #endif + #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE + RWTexture2D rw_exposure : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_EXPOSURE); + #endif + #if defined FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE + RWTexture2D rw_auto_exposure : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE); + #endif + #if defined FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC + globallycoherent RWTexture2D rw_spd_global_atomic : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC); + #endif + + #if defined FSR3UPSCALER_BIND_UAV_AUTOREACTIVE + RWTexture2D rw_output_autoreactive : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_AUTOREACTIVE); + #endif + #if defined FSR3UPSCALER_BIND_UAV_AUTOCOMPOSITION + RWTexture2D rw_output_autocomposition : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_AUTOCOMPOSITION); + #endif + #if defined FSR3UPSCALER_BIND_UAV_PREV_PRE_ALPHA_COLOR + RWTexture2D rw_output_prev_color_pre_alpha : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_PREV_PRE_ALPHA_COLOR); + #endif + #if defined FSR3UPSCALER_BIND_UAV_PREV_POST_ALPHA_COLOR + RWTexture2D rw_output_prev_color_post_alpha : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_PREV_POST_ALPHA_COLOR); + #endif + +#if defined(FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS) +FfxFloat32 LoadMipLuma(FfxUInt32x2 iPxPos, FfxUInt32 mipLevel) +{ + return r_imgMips.mips[mipLevel][iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS) +FfxFloat32 SampleMipLuma(FfxFloat32x2 fUV, FfxUInt32 mipLevel) +{ + return r_imgMips.SampleLevel(s_LinearClamp, fUV, mipLevel); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_DEPTH) +FfxFloat32 LoadInputDepth(FfxUInt32x2 iPxPos) +{ + return r_input_depth[iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_DEPTH) +FfxFloat32 SampleInputDepth(FfxFloat32x2 fUV) +{ + return r_input_depth.SampleLevel(s_LinearClamp, fUV, 0).x; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_REACTIVE_MASK) +FfxFloat32 LoadReactiveMask(FfxUInt32x2 iPxPos) +{ + return r_reactive_mask[iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK) +FfxFloat32 LoadTransparencyAndCompositionMask(FfxUInt32x2 iPxPos) +{ + return r_transparency_and_composition_mask[iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_COLOR) +FfxFloat32x3 LoadInputColor(FfxUInt32x2 iPxPos) +{ + return r_input_color_jittered[iPxPos].rgb; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_COLOR) +FfxFloat32x3 SampleInputColor(FfxFloat32x2 fUV) +{ + return r_input_color_jittered.SampleLevel(s_LinearClamp, fUV, 0).rgb; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR) +FfxFloat32x3 LoadPreparedInputColor(FfxUInt32x2 iPxPos) +{ + return r_prepared_input_color[iPxPos].xyz; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS) +FfxFloat32x2 LoadInputMotionVector(FfxUInt32x2 iPxDilatedMotionVectorPos) +{ + FfxFloat32x2 fSrcMotionVector = r_input_motion_vectors[iPxDilatedMotionVectorPos].xy; + + FfxFloat32x2 fUvMotionVector = fSrcMotionVector * MotionVectorScale(); + +#if FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS + fUvMotionVector -= MotionVectorJitterCancellation(); +#endif + + return fUvMotionVector; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INTERNAL_UPSCALED) +FfxFloat32x4 LoadHistory(FfxUInt32x2 iPxHistory) +{ + return r_internal_upscaled_color[iPxHistory]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_LUMA_HISTORY) +void StoreLumaHistory(FfxUInt32x2 iPxPos, FfxFloat32x4 fLumaHistory) +{ + rw_luma_history[iPxPos] = fLumaHistory; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_LUMA_HISTORY) +FfxFloat32x4 SampleLumaHistory(FfxFloat32x2 fUV) +{ + return r_luma_history.SampleLevel(s_LinearClamp, fUV, 0); +} +#endif + +FfxFloat32x4 LoadRCAS_Input(FfxInt32x2 iPxPos) +{ +#if defined(FSR3UPSCALER_BIND_SRV_RCAS_INPUT) + return r_rcas_input[iPxPos]; +#else + return 0.0; +#endif +} + +#if defined(FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED) +void StoreReprojectedHistory(FfxUInt32x2 iPxHistory, FfxFloat32x4 fHistory) +{ + rw_internal_upscaled_color[iPxHistory] = fHistory; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED) +void StoreInternalColorAndWeight(FfxUInt32x2 iPxPos, FfxFloat32x4 fColorAndWeight) +{ + rw_internal_upscaled_color[iPxPos] = fColorAndWeight; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT) +void StoreUpscaledOutput(FfxUInt32x2 iPxPos, FfxFloat32x3 fColor) +{ + rw_upscaled_output[iPxPos] = FfxFloat32x4(fColor, 1.f); +} +#endif + +//LOCK_LIFETIME_REMAINING == 0 +//Should make LockInitialLifetime() return a const 1.0f later +#if defined(FSR3UPSCALER_BIND_SRV_LOCK_STATUS) +FfxFloat32x2 LoadLockStatus(FfxUInt32x2 iPxPos) +{ + return r_lock_status[iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_LOCK_STATUS) +void StoreLockStatus(FfxUInt32x2 iPxPos, FfxFloat32x2 fLockStatus) +{ + rw_lock_status[iPxPos] = fLockStatus; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_LOCK_INPUT_LUMA) +FfxFloat32 LoadLockInputLuma(FfxUInt32x2 iPxPos) +{ + return r_lock_input_luma[iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_LOCK_INPUT_LUMA) +void StoreLockInputLuma(FfxUInt32x2 iPxPos, FfxFloat32 fLuma) +{ + rw_lock_input_luma[iPxPos] = fLuma; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_NEW_LOCKS) +FfxFloat32 LoadNewLocks(FfxUInt32x2 iPxPos) +{ + return r_new_locks[iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_NEW_LOCKS) +FfxFloat32 LoadRwNewLocks(FfxUInt32x2 iPxPos) +{ + return rw_new_locks[iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_NEW_LOCKS) +void StoreNewLocks(FfxUInt32x2 iPxPos, FfxFloat32 newLock) +{ + rw_new_locks[iPxPos] = newLock; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_PREPARED_INPUT_COLOR) +void StorePreparedInputColor(FFX_PARAMETER_IN FfxUInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x4 fTonemapped) +{ + rw_prepared_input_color[iPxPos] = fTonemapped; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR) +FfxFloat32 SampleDepthClip(FfxFloat32x2 fUV) +{ + return r_prepared_input_color.SampleLevel(s_LinearClamp, fUV, 0).w; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_LOCK_STATUS) +FfxFloat32x2 SampleLockStatus(FfxFloat32x2 fUV) +{ + FfxFloat32x2 fLockStatus = r_lock_status.SampleLevel(s_LinearClamp, fUV, 0); + return fLockStatus; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH) +FfxFloat32 LoadReconstructedPrevDepth(FfxUInt32x2 iPxPos) +{ + return asfloat(r_reconstructed_previous_nearest_depth[iPxPos]); +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH) +void StoreReconstructedDepth(FfxUInt32x2 iPxSample, FfxFloat32 fDepth) +{ + FfxUInt32 uDepth = asuint(fDepth); + + #if FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH + InterlockedMax(rw_reconstructed_previous_nearest_depth[iPxSample], uDepth); + #else + InterlockedMin(rw_reconstructed_previous_nearest_depth[iPxSample], uDepth); // min for standard, max for inverted depth + #endif +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH) +void SetReconstructedDepth(FfxUInt32x2 iPxSample, const FfxUInt32 uValue) +{ + rw_reconstructed_previous_nearest_depth[iPxSample] = uValue; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_DILATED_DEPTH) +void StoreDilatedDepth(FFX_PARAMETER_IN FfxUInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32 fDepth) +{ + rw_dilated_depth[iPxPos] = fDepth; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_DILATED_MOTION_VECTORS) +void StoreDilatedMotionVector(FFX_PARAMETER_IN FfxUInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 fMotionVector) +{ + rw_dilated_motion_vectors[iPxPos] = fMotionVector; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS) +FfxFloat32x2 LoadDilatedMotionVector(FfxUInt32x2 iPxInput) +{ + return r_dilated_motion_vectors[iPxInput].xy; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_PREVIOUS_DILATED_MOTION_VECTORS) +FfxFloat32x2 LoadPreviousDilatedMotionVector(FfxUInt32x2 iPxInput) +{ + return r_previous_dilated_motion_vectors[iPxInput].xy; +} + +FfxFloat32x2 SamplePreviousDilatedMotionVector(FfxFloat32x2 uv) +{ + return r_previous_dilated_motion_vectors.SampleLevel(s_LinearClamp, uv, 0).xy; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_DEPTH) +FfxFloat32 LoadDilatedDepth(FfxUInt32x2 iPxInput) +{ + return r_dilated_depth[iPxInput]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE) +FfxFloat32 Exposure() +{ + FfxFloat32 exposure = r_input_exposure[FfxUInt32x2(0, 0)].x; + + if (exposure == 0.0f) { + exposure = 1.0f; + } + + return exposure; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_AUTO_EXPOSURE) +FfxFloat32 AutoExposure() +{ + FfxFloat32 exposure = r_auto_exposure[FfxUInt32x2(0, 0)].x; + + if (exposure == 0.0f) { + exposure = 1.0f; + } + + return exposure; +} +#endif + +FfxFloat32 SampleLanczos2Weight(FfxFloat32 x) +{ +#if defined(FSR3UPSCALER_BIND_SRV_LANCZOS_LUT) + return r_lanczos_lut.SampleLevel(s_LinearClamp, FfxFloat32x2(x / 2, 0.5f), 0); +#else + return 0.f; +#endif +} + +#if defined(FSR3UPSCALER_BIND_SRV_UPSCALE_MAXIMUM_BIAS_LUT) +FfxFloat32 SampleUpsampleMaximumBias(FfxFloat32x2 uv) +{ + // Stored as a SNORM, so make sure to multiply by 2 to retrieve the actual expected range. + return FfxFloat32(2.0) * r_upsample_maximum_bias_lut.SampleLevel(s_LinearClamp, abs(uv) * 2.0, 0); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS) +FfxFloat32x2 SampleDilatedReactiveMasks(FfxFloat32x2 fUV) +{ + return r_dilated_reactive_masks.SampleLevel(s_LinearClamp, fUV, 0); +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS) +FfxFloat32x2 LoadDilatedReactiveMasks(FFX_PARAMETER_IN FfxUInt32x2 iPxPos) +{ + return r_dilated_reactive_masks[iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_DILATED_REACTIVE_MASKS) +void StoreDilatedReactiveMasks(FFX_PARAMETER_IN FfxUInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 fDilatedReactiveMasks) +{ + rw_dilated_reactive_masks[iPxPos] = fDilatedReactiveMasks; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY) +FfxFloat32x3 LoadOpaqueOnly(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos) +{ + return r_input_opaque_only[iPxPos].xyz; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_PREV_PRE_ALPHA_COLOR) +FfxFloat32x3 LoadPrevPreAlpha(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos) +{ + return r_input_prev_color_pre_alpha[iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_SRV_PREV_POST_ALPHA_COLOR) +FfxFloat32x3 LoadPrevPostAlpha(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos) +{ + return r_input_prev_color_post_alpha[iPxPos]; +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_AUTOREACTIVE) +#if defined(FSR3UPSCALER_BIND_UAV_AUTOCOMPOSITION) +void StoreAutoReactive(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos, FFX_PARAMETER_IN FFX_MIN16_F2 fReactive) +{ + rw_output_autoreactive[iPxPos] = fReactive.x; + + rw_output_autocomposition[iPxPos] = fReactive.y; +} +#endif +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_PREV_PRE_ALPHA_COLOR) +void StorePrevPreAlpha(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos, FFX_PARAMETER_IN FFX_MIN16_F3 color) +{ + rw_output_prev_color_pre_alpha[iPxPos] = color; + +} +#endif + +#if defined(FSR3UPSCALER_BIND_UAV_PREV_POST_ALPHA_COLOR) +void StorePrevPostAlpha(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos, FFX_PARAMETER_IN FFX_MIN16_F3 color) +{ + rw_output_prev_color_post_alpha[iPxPos] = color; +} +#endif + +FfxFloat32x2 SPD_LoadExposureBuffer() +{ +#if defined FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE + return rw_auto_exposure[FfxInt32x2(0, 0)]; +#else + return FfxFloat32x2(0.f, 0.f); +#endif // #if defined FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE +} + +void SPD_SetExposureBuffer(FfxFloat32x2 value) +{ +#if defined FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE + rw_auto_exposure[FfxInt32x2(0, 0)] = value; +#endif // #if defined FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE +} + +FfxFloat32x4 SPD_LoadMipmap5(FfxInt32x2 iPxPos) +{ +#if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 + return FfxFloat32x4(rw_img_mip_5[iPxPos], 0, 0, 0); +#else + return FfxFloat32x4(0.f, 0.f, 0.f, 0.f); +#endif // #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 +} + +void SPD_SetMipmap(FfxInt32x2 iPxPos, FfxUInt32 slice, FfxFloat32 value) +{ + switch (slice) + { + case FFX_FSR3UPSCALER_SHADING_CHANGE_MIP_LEVEL: +#if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE + rw_img_mip_shading_change[iPxPos] = value; +#endif // #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE + break; + case 5: +#if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 + rw_img_mip_5[iPxPos] = value; +#endif // #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 + break; + default: + + // avoid flattened side effect +#if defined(FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE) + rw_img_mip_shading_change[iPxPos] = rw_img_mip_shading_change[iPxPos]; +#elif defined(FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5) + rw_img_mip_5[iPxPos] = rw_img_mip_5[iPxPos]; +#endif // #if defined FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 + break; + } +} + +void SPD_IncreaseAtomicCounter(inout FfxUInt32 spdCounter) +{ +#if defined FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC + InterlockedAdd(rw_spd_global_atomic[FfxInt32x2(0, 0)], 1, spdCounter); +#endif // #if defined FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC +} + +void SPD_ResetAtomicCounter() +{ +#if defined FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC + rw_spd_global_atomic[FfxInt32x2(0, 0)] = 0; +#endif // #if defined FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC +} + +#endif // #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_common.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_common.h new file mode 100644 index 00000000..1f78a291 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_common.h @@ -0,0 +1,566 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 !defined(FFX_FSR3UPSCALER_COMMON_H) +#define FFX_FSR3UPSCALER_COMMON_H + +#if defined(FFX_CPU) || defined(FFX_GPU) +//Locks +#define LOCK_LIFETIME_REMAINING 0 +#define LOCK_TEMPORAL_LUMA 1 +#endif // #if defined(FFX_CPU) || defined(FFX_GPU) + +#if defined(FFX_GPU) +FFX_STATIC const FfxFloat32 FSR3UPSCALER_FP16_MIN = 6.10e-05f; +FFX_STATIC const FfxFloat32 FSR3UPSCALER_FP16_MAX = 65504.0f; +FFX_STATIC const FfxFloat32 FSR3UPSCALER_EPSILON = 1e-03f; +FFX_STATIC const FfxFloat32 FSR3UPSCALER_TONEMAP_EPSILON = 1.0f / FSR3UPSCALER_FP16_MAX; +FFX_STATIC const FfxFloat32 FSR3UPSCALER_FLT_MAX = 3.402823466e+38f; +FFX_STATIC const FfxFloat32 FSR3UPSCALER_FLT_MIN = 1.175494351e-38f; + +// treat vector truncation warnings as errors +#pragma warning(error: 3206) + +// suppress warnings +#pragma warning(disable: 3205) // conversion from larger type to smaller +#pragma warning(disable: 3571) // in ffxPow(f, e), f could be negative + +// Reconstructed depth usage +FFX_STATIC const FfxFloat32 fReconstructedDepthBilinearWeightThreshold = 0.01f; + +// Accumulation +FFX_STATIC const FfxFloat32 fUpsampleLanczosWeightScale = 1.0f / 12.0f; +FFX_STATIC const FfxFloat32 fMaxAccumulationLanczosWeight = 1.0f; +FFX_STATIC const FfxFloat32 fAverageLanczosWeightPerFrame = 0.74f * fUpsampleLanczosWeightScale; // Average lanczos weight for jitter accumulated samples +FFX_STATIC const FfxFloat32 fAccumulationMaxOnMotion = 3.0f * fUpsampleLanczosWeightScale; + +// Auto exposure +FFX_STATIC const FfxFloat32 resetAutoExposureAverageSmoothing = 1e8f; + +struct AccumulationPassCommonParams +{ + FfxInt32x2 iPxHrPos; + FfxFloat32x2 fHrUv; + FfxFloat32x2 fLrUv_HwSampler; + FfxFloat32x2 fMotionVector; + FfxFloat32x2 fReprojectedHrUv; + FfxFloat32 fHrVelocity; + FfxFloat32 fDepthClipFactor; + FfxFloat32 fDilatedReactiveFactor; + FfxFloat32 fAccumulationMask; + + FfxBoolean bIsResetFrame; + FfxBoolean bIsExistingSample; + FfxBoolean bIsNewSample; +}; + +struct LockState +{ + FfxBoolean NewLock; //Set for both unique new and re-locked new + FfxBoolean WasLockedPrevFrame; //Set to identify if the pixel was already locked (relock) +}; + +void InitializeNewLockSample(FFX_PARAMETER_OUT FfxFloat32x2 fLockStatus) +{ + fLockStatus = FfxFloat32x2(0, 0); +} + +#if FFX_HALF +void InitializeNewLockSample(FFX_PARAMETER_OUT FFX_MIN16_F2 fLockStatus) +{ + fLockStatus = FFX_MIN16_F2(0, 0); +} +#endif + + +void KillLock(FFX_PARAMETER_INOUT FfxFloat32x2 fLockStatus) +{ + fLockStatus[LOCK_LIFETIME_REMAINING] = 0; +} + +#if FFX_HALF +void KillLock(FFX_PARAMETER_INOUT FFX_MIN16_F2 fLockStatus) +{ + fLockStatus[LOCK_LIFETIME_REMAINING] = FFX_MIN16_F(0); +} +#endif + +struct RectificationBox +{ + FfxFloat32x3 boxCenter; + FfxFloat32x3 boxVec; + FfxFloat32x3 aabbMin; + FfxFloat32x3 aabbMax; + FfxFloat32 fBoxCenterWeight; +}; +#if FFX_HALF +struct RectificationBoxMin16 +{ + FFX_MIN16_F3 boxCenter; + FFX_MIN16_F3 boxVec; + FFX_MIN16_F3 aabbMin; + FFX_MIN16_F3 aabbMax; + FFX_MIN16_F fBoxCenterWeight; +}; +#endif + +void RectificationBoxReset(FFX_PARAMETER_INOUT RectificationBox rectificationBox) +{ + rectificationBox.fBoxCenterWeight = FfxFloat32(0); + + rectificationBox.boxCenter = FfxFloat32x3(0, 0, 0); + rectificationBox.boxVec = FfxFloat32x3(0, 0, 0); + rectificationBox.aabbMin = FfxFloat32x3(FSR3UPSCALER_FLT_MAX, FSR3UPSCALER_FLT_MAX, FSR3UPSCALER_FLT_MAX); + rectificationBox.aabbMax = -FfxFloat32x3(FSR3UPSCALER_FLT_MAX, FSR3UPSCALER_FLT_MAX, FSR3UPSCALER_FLT_MAX); +} +#if FFX_HALF +void RectificationBoxReset(FFX_PARAMETER_INOUT RectificationBoxMin16 rectificationBox) +{ + rectificationBox.fBoxCenterWeight = FFX_MIN16_F(0); + + rectificationBox.boxCenter = FFX_MIN16_F3(0, 0, 0); + rectificationBox.boxVec = FFX_MIN16_F3(0, 0, 0); + rectificationBox.aabbMin = FFX_MIN16_F3(FSR3UPSCALER_FP16_MAX, FSR3UPSCALER_FP16_MAX, FSR3UPSCALER_FP16_MAX); + rectificationBox.aabbMax = -FFX_MIN16_F3(FSR3UPSCALER_FP16_MAX, FSR3UPSCALER_FP16_MAX, FSR3UPSCALER_FP16_MAX); +} +#endif + +void RectificationBoxAddInitialSample(FFX_PARAMETER_INOUT RectificationBox rectificationBox, const FfxFloat32x3 colorSample, const FfxFloat32 fSampleWeight) +{ + rectificationBox.aabbMin = colorSample; + rectificationBox.aabbMax = colorSample; + + FfxFloat32x3 weightedSample = colorSample * fSampleWeight; + rectificationBox.boxCenter = weightedSample; + rectificationBox.boxVec = colorSample * weightedSample; + rectificationBox.fBoxCenterWeight = fSampleWeight; +} + +void RectificationBoxAddSample(FfxBoolean bInitialSample, FFX_PARAMETER_INOUT RectificationBox rectificationBox, const FfxFloat32x3 colorSample, const FfxFloat32 fSampleWeight) +{ + if (bInitialSample) { + RectificationBoxAddInitialSample(rectificationBox, colorSample, fSampleWeight); + } else { + rectificationBox.aabbMin = ffxMin(rectificationBox.aabbMin, colorSample); + rectificationBox.aabbMax = ffxMax(rectificationBox.aabbMax, colorSample); + + FfxFloat32x3 weightedSample = colorSample * fSampleWeight; + rectificationBox.boxCenter += weightedSample; + rectificationBox.boxVec += colorSample * weightedSample; + rectificationBox.fBoxCenterWeight += fSampleWeight; + } +} +#if FFX_HALF +void RectificationBoxAddInitialSample(FFX_PARAMETER_INOUT RectificationBoxMin16 rectificationBox, const FFX_MIN16_F3 colorSample, const FFX_MIN16_F fSampleWeight) +{ + rectificationBox.aabbMin = colorSample; + rectificationBox.aabbMax = colorSample; + + FFX_MIN16_F3 weightedSample = colorSample * fSampleWeight; + rectificationBox.boxCenter = weightedSample; + rectificationBox.boxVec = colorSample * weightedSample; + rectificationBox.fBoxCenterWeight = fSampleWeight; +} + +void RectificationBoxAddSample(FfxBoolean bInitialSample, FFX_PARAMETER_INOUT RectificationBoxMin16 rectificationBox, const FFX_MIN16_F3 colorSample, const FFX_MIN16_F fSampleWeight) +{ + if (bInitialSample) { + RectificationBoxAddInitialSample(rectificationBox, colorSample, fSampleWeight); + } else { + rectificationBox.aabbMin = ffxMin(rectificationBox.aabbMin, colorSample); + rectificationBox.aabbMax = ffxMax(rectificationBox.aabbMax, colorSample); + + FFX_MIN16_F3 weightedSample = colorSample * fSampleWeight; + rectificationBox.boxCenter += weightedSample; + rectificationBox.boxVec += colorSample * weightedSample; + rectificationBox.fBoxCenterWeight += fSampleWeight; + } +} +#endif + +void RectificationBoxComputeVarianceBoxData(FFX_PARAMETER_INOUT RectificationBox rectificationBox) +{ + rectificationBox.fBoxCenterWeight = (abs(rectificationBox.fBoxCenterWeight) > FfxFloat32(FSR3UPSCALER_EPSILON) ? rectificationBox.fBoxCenterWeight : FfxFloat32(1.f)); + rectificationBox.boxCenter /= rectificationBox.fBoxCenterWeight; + rectificationBox.boxVec /= rectificationBox.fBoxCenterWeight; + FfxFloat32x3 stdDev = sqrt(abs(rectificationBox.boxVec - rectificationBox.boxCenter * rectificationBox.boxCenter)); + rectificationBox.boxVec = stdDev; +} +#if FFX_HALF +void RectificationBoxComputeVarianceBoxData(FFX_PARAMETER_INOUT RectificationBoxMin16 rectificationBox) +{ + rectificationBox.fBoxCenterWeight = (abs(rectificationBox.fBoxCenterWeight) > FFX_MIN16_F(FSR3UPSCALER_EPSILON) ? rectificationBox.fBoxCenterWeight : FFX_MIN16_F(1.f)); + rectificationBox.boxCenter /= rectificationBox.fBoxCenterWeight; + rectificationBox.boxVec /= rectificationBox.fBoxCenterWeight; + FFX_MIN16_F3 stdDev = sqrt(abs(rectificationBox.boxVec - rectificationBox.boxCenter * rectificationBox.boxCenter)); + rectificationBox.boxVec = stdDev; +} +#endif + +FfxFloat32x3 SafeRcp3(FfxFloat32x3 v) +{ + return (all(FFX_NOT_EQUAL(v, FfxFloat32x3(0, 0, 0)))) ? (FfxFloat32x3(1, 1, 1) / v) : FfxFloat32x3(0, 0, 0); +} +#if FFX_HALF +FFX_MIN16_F3 SafeRcp3(FFX_MIN16_F3 v) +{ + return (all(FFX_NOT_EQUAL(v, FFX_MIN16_F3(0, 0, 0)))) ? (FFX_MIN16_F3(1, 1, 1) / v) : FFX_MIN16_F3(0, 0, 0); +} +#endif + +FfxFloat32 MinDividedByMax(const FfxFloat32 v0, const FfxFloat32 v1) +{ + const FfxFloat32 m = ffxMax(v0, v1); + return m != 0 ? ffxMin(v0, v1) / m : 0; +} + +#if FFX_HALF +FFX_MIN16_F MinDividedByMax(const FFX_MIN16_F v0, const FFX_MIN16_F v1) +{ + const FFX_MIN16_F m = ffxMax(v0, v1); + return m != FFX_MIN16_F(0) ? ffxMin(v0, v1) / m : FFX_MIN16_F(0); +} +#endif + +FfxFloat32x3 YCoCgToRGB(FfxFloat32x3 fYCoCg) +{ + FfxFloat32x3 fRgb; + + fRgb = FfxFloat32x3( + fYCoCg.x + fYCoCg.y - fYCoCg.z, + fYCoCg.x + fYCoCg.z, + fYCoCg.x - fYCoCg.y - fYCoCg.z); + + return fRgb; +} +#if FFX_HALF +FFX_MIN16_F3 YCoCgToRGB(FFX_MIN16_F3 fYCoCg) +{ + FFX_MIN16_F3 fRgb; + + fRgb = FFX_MIN16_F3( + fYCoCg.x + fYCoCg.y - fYCoCg.z, + fYCoCg.x + fYCoCg.z, + fYCoCg.x - fYCoCg.y - fYCoCg.z); + + return fRgb; +} +#endif + +FfxFloat32x3 RGBToYCoCg(FfxFloat32x3 fRgb) +{ + FfxFloat32x3 fYCoCg; + + fYCoCg = FfxFloat32x3( + 0.25f * fRgb.r + 0.5f * fRgb.g + 0.25f * fRgb.b, + 0.5f * fRgb.r - 0.5f * fRgb.b, + -0.25f * fRgb.r + 0.5f * fRgb.g - 0.25f * fRgb.b); + + return fYCoCg; +} +#if FFX_HALF +FFX_MIN16_F3 RGBToYCoCg(FFX_MIN16_F3 fRgb) +{ + FFX_MIN16_F3 fYCoCg; + + fYCoCg = FFX_MIN16_F3( + 0.25 * fRgb.r + 0.5 * fRgb.g + 0.25 * fRgb.b, + 0.5 * fRgb.r - 0.5 * fRgb.b, + -0.25 * fRgb.r + 0.5 * fRgb.g - 0.25 * fRgb.b); + + return fYCoCg; +} +#endif + +FfxFloat32 RGBToLuma(FfxFloat32x3 fLinearRgb) +{ + return dot(fLinearRgb, FfxFloat32x3(0.2126f, 0.7152f, 0.0722f)); +} +#if FFX_HALF +FFX_MIN16_F RGBToLuma(FFX_MIN16_F3 fLinearRgb) +{ + return dot(fLinearRgb, FFX_MIN16_F3(0.2126f, 0.7152f, 0.0722f)); +} +#endif + +FfxFloat32 RGBToPerceivedLuma(FfxFloat32x3 fLinearRgb) +{ + FfxFloat32 fLuminance = RGBToLuma(fLinearRgb); + + FfxFloat32 fPercievedLuminance = 0; + if (fLuminance <= 216.0f / 24389.0f) { + fPercievedLuminance = fLuminance * (24389.0f / 27.0f); + } + else { + fPercievedLuminance = ffxPow(fLuminance, 1.0f / 3.0f) * 116.0f - 16.0f; + } + + return fPercievedLuminance * 0.01f; +} +#if FFX_HALF +FFX_MIN16_F RGBToPerceivedLuma(FFX_MIN16_F3 fLinearRgb) +{ + FFX_MIN16_F fLuminance = RGBToLuma(fLinearRgb); + + FFX_MIN16_F fPercievedLuminance = FFX_MIN16_F(0); + if (fLuminance <= FFX_MIN16_F(216.0f / 24389.0f)) { + fPercievedLuminance = fLuminance * FFX_MIN16_F(24389.0f / 27.0f); + } + else { + fPercievedLuminance = ffxPow(fLuminance, FFX_MIN16_F(1.0f / 3.0f)) * FFX_MIN16_F(116.0f) - FFX_MIN16_F(16.0f); + } + + return fPercievedLuminance * FFX_MIN16_F(0.01f); +} +#endif + +FfxFloat32x3 Tonemap(FfxFloat32x3 fRgb) +{ + return fRgb / (ffxMax(ffxMax(0.f, fRgb.r), ffxMax(fRgb.g, fRgb.b)) + 1.f).xxx; +} + +FfxFloat32x3 InverseTonemap(FfxFloat32x3 fRgb) +{ + return fRgb / ffxMax(FSR3UPSCALER_TONEMAP_EPSILON, 1.f - ffxMax(fRgb.r, ffxMax(fRgb.g, fRgb.b))).xxx; +} + +#if FFX_HALF +FFX_MIN16_F3 Tonemap(FFX_MIN16_F3 fRgb) +{ + return fRgb / (ffxMax(ffxMax(FFX_MIN16_F(0.f), fRgb.r), ffxMax(fRgb.g, fRgb.b)) + FFX_MIN16_F(1.f)).xxx; +} + +FFX_MIN16_F3 InverseTonemap(FFX_MIN16_F3 fRgb) +{ + return fRgb / ffxMax(FFX_MIN16_F(FSR3UPSCALER_TONEMAP_EPSILON), FFX_MIN16_F(1.f) - ffxMax(fRgb.r, ffxMax(fRgb.g, fRgb.b))).xxx; +} +#endif + +FfxInt32x2 ClampLoad(FfxInt32x2 iPxSample, FfxInt32x2 iPxOffset, FfxInt32x2 iTextureSize) +{ + FfxInt32x2 result = iPxSample + iPxOffset; + result.x = (iPxOffset.x < 0) ? ffxMax(result.x, 0) : result.x; + result.x = (iPxOffset.x > 0) ? ffxMin(result.x, iTextureSize.x - 1) : result.x; + result.y = (iPxOffset.y < 0) ? ffxMax(result.y, 0) : result.y; + result.y = (iPxOffset.y > 0) ? ffxMin(result.y, iTextureSize.y - 1) : result.y; + return result; + + // return ffxMed3(iPxSample + iPxOffset, FfxInt32x2(0, 0), iTextureSize - FfxInt32x2(1, 1)); +} +#if FFX_HALF +FFX_MIN16_I2 ClampLoad(FFX_MIN16_I2 iPxSample, FFX_MIN16_I2 iPxOffset, FFX_MIN16_I2 iTextureSize) +{ + FFX_MIN16_I2 result = iPxSample + iPxOffset; + result.x = (iPxOffset.x < 0) ? ffxMax(result.x, FFX_MIN16_I(0)) : result.x; + result.x = (iPxOffset.x > 0) ? ffxMin(result.x, iTextureSize.x - FFX_MIN16_I(1)) : result.x; + result.y = (iPxOffset.y < 0) ? ffxMax(result.y, FFX_MIN16_I(0)) : result.y; + result.y = (iPxOffset.y > 0) ? ffxMin(result.y, iTextureSize.y - FFX_MIN16_I(1)) : result.y; + return result; + + // return ffxMed3Half(iPxSample + iPxOffset, FFX_MIN16_I2(0, 0), iTextureSize - FFX_MIN16_I2(1, 1)); +} +#endif + +FfxFloat32x2 ClampUv(FfxFloat32x2 fUv, FfxInt32x2 iTextureSize, FfxInt32x2 iResourceSize) +{ + const FfxFloat32x2 fSampleLocation = fUv * iTextureSize; + const FfxFloat32x2 fClampedLocation = ffxMax(FfxFloat32x2(0.5f, 0.5f), ffxMin(fSampleLocation, FfxFloat32x2(iTextureSize) - FfxFloat32x2(0.5f, 0.5f))); + const FfxFloat32x2 fClampedUv = fClampedLocation / FfxFloat32x2(iResourceSize); + + return fClampedUv; +} + +FfxBoolean IsOnScreen(FfxInt32x2 pos, FfxInt32x2 size) +{ + return all(FFX_LESS_THAN(FfxUInt32x2(pos), FfxUInt32x2(size))); +} +#if FFX_HALF +FfxBoolean IsOnScreen(FFX_MIN16_I2 pos, FFX_MIN16_I2 size) +{ + return all(FFX_LESS_THAN(FFX_MIN16_U2(pos), FFX_MIN16_U2(size))); +} +#endif + +FfxFloat32 ComputeAutoExposureFromLavg(FfxFloat32 Lavg) +{ + Lavg = exp(Lavg); + + const FfxFloat32 S = 100.0f; //ISO arithmetic speed + const FfxFloat32 K = 12.5f; + FfxFloat32 ExposureISO100 = log2((Lavg * S) / K); + + const FfxFloat32 q = 0.65f; + FfxFloat32 Lmax = (78.0f / (q * S)) * ffxPow(2.0f, ExposureISO100); + + return 1 / Lmax; +} +#if FFX_HALF +FFX_MIN16_F ComputeAutoExposureFromLavg(FFX_MIN16_F Lavg) +{ + Lavg = exp(Lavg); + + const FFX_MIN16_F S = FFX_MIN16_F(100.0f); //ISO arithmetic speed + const FFX_MIN16_F K = FFX_MIN16_F(12.5f); + const FFX_MIN16_F ExposureISO100 = log2((Lavg * S) / K); + + const FFX_MIN16_F q = FFX_MIN16_F(0.65f); + const FFX_MIN16_F Lmax = (FFX_MIN16_F(78.0f) / (q * S)) * ffxPow(FFX_MIN16_F(2.0f), ExposureISO100); + + return FFX_MIN16_F(1) / Lmax; +} +#endif + +FfxInt32x2 ComputeHrPosFromLrPos(FfxInt32x2 iPxLrPos) +{ + FfxFloat32x2 fSrcJitteredPos = FfxFloat32x2(iPxLrPos) + 0.5f - Jitter(); + FfxFloat32x2 fLrPosInHr = (fSrcJitteredPos / RenderSize()) * DisplaySize(); + FfxInt32x2 iPxHrPos = FfxInt32x2(floor(fLrPosInHr)); + return iPxHrPos; +} +#if FFX_HALF +FFX_MIN16_I2 ComputeHrPosFromLrPos(FFX_MIN16_I2 iPxLrPos) +{ + FFX_MIN16_F2 fSrcJitteredPos = FFX_MIN16_F2(iPxLrPos) + FFX_MIN16_F(0.5f) - FFX_MIN16_F2(Jitter()); + FFX_MIN16_F2 fLrPosInHr = (fSrcJitteredPos / FFX_MIN16_F2(RenderSize())) * FFX_MIN16_F2(DisplaySize()); + FFX_MIN16_I2 iPxHrPos = FFX_MIN16_I2(floor(fLrPosInHr)); + return iPxHrPos; +} +#endif + +FfxFloat32x2 ComputeNdc(FfxFloat32x2 fPxPos, FfxInt32x2 iSize) +{ + return fPxPos / FfxFloat32x2(iSize) * FfxFloat32x2(2.0f, -2.0f) + FfxFloat32x2(-1.0f, 1.0f); +} + +FfxFloat32 GetViewSpaceDepth(FfxFloat32 fDeviceDepth) +{ + const FfxFloat32x4 fDeviceToViewDepth = DeviceToViewSpaceTransformFactors(); + + // fDeviceToViewDepth details found in ffx_fsr3upscaler.cpp + return (fDeviceToViewDepth[1] / (fDeviceDepth - fDeviceToViewDepth[0])); +} + +FfxFloat32 GetViewSpaceDepthInMeters(FfxFloat32 fDeviceDepth) +{ + return GetViewSpaceDepth(fDeviceDepth) * ViewSpaceToMetersFactor(); +} + +FfxFloat32x3 GetViewSpacePosition(FfxInt32x2 iViewportPos, FfxInt32x2 iViewportSize, FfxFloat32 fDeviceDepth) +{ + const FfxFloat32x4 fDeviceToViewDepth = DeviceToViewSpaceTransformFactors(); + + const FfxFloat32 Z = GetViewSpaceDepth(fDeviceDepth); + + const FfxFloat32x2 fNdcPos = ComputeNdc(iViewportPos, iViewportSize); + const FfxFloat32 X = fDeviceToViewDepth[2] * fNdcPos.x * Z; + const FfxFloat32 Y = fDeviceToViewDepth[3] * fNdcPos.y * Z; + + return FfxFloat32x3(X, Y, Z); +} + +FfxFloat32x3 GetViewSpacePositionInMeters(FfxInt32x2 iViewportPos, FfxInt32x2 iViewportSize, FfxFloat32 fDeviceDepth) +{ + return GetViewSpacePosition(iViewportPos, iViewportSize, fDeviceDepth) * ViewSpaceToMetersFactor(); +} + +FfxFloat32 GetMaxDistanceInMeters() +{ +#if FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH + return GetViewSpaceDepth(0.0f) * ViewSpaceToMetersFactor(); +#else + return GetViewSpaceDepth(1.0f) * ViewSpaceToMetersFactor(); +#endif +} + +FfxFloat32x3 PrepareRgb(FfxFloat32x3 fRgb, FfxFloat32 fExposure, FfxFloat32 fPreExposure) +{ + fRgb /= fPreExposure; + fRgb *= fExposure; + + fRgb = clamp(fRgb, 0.0f, FSR3UPSCALER_FP16_MAX); + + return fRgb; +} + +FfxFloat32x3 UnprepareRgb(FfxFloat32x3 fRgb, FfxFloat32 fExposure) +{ + fRgb /= fExposure; + fRgb *= PreExposure(); + + return fRgb; +} + + +struct BilinearSamplingData +{ + FfxInt32x2 iOffsets[4]; + FfxFloat32 fWeights[4]; + FfxInt32x2 iBasePos; +}; + +BilinearSamplingData GetBilinearSamplingData(FfxFloat32x2 fUv, FfxInt32x2 iSize) +{ + BilinearSamplingData data; + + FfxFloat32x2 fPxSample = (fUv * iSize) - FfxFloat32x2(0.5f, 0.5f); + data.iBasePos = FfxInt32x2(floor(fPxSample)); + FfxFloat32x2 fPxFrac = ffxFract(fPxSample); + + data.iOffsets[0] = FfxInt32x2(0, 0); + data.iOffsets[1] = FfxInt32x2(1, 0); + data.iOffsets[2] = FfxInt32x2(0, 1); + data.iOffsets[3] = FfxInt32x2(1, 1); + + data.fWeights[0] = (1 - fPxFrac.x) * (1 - fPxFrac.y); + data.fWeights[1] = (fPxFrac.x) * (1 - fPxFrac.y); + data.fWeights[2] = (1 - fPxFrac.x) * (fPxFrac.y); + data.fWeights[3] = (fPxFrac.x) * (fPxFrac.y); + + return data; +} + +struct PlaneData +{ + FfxFloat32x3 fNormal; + FfxFloat32 fDistanceFromOrigin; +}; + +PlaneData GetPlaneFromPoints(FfxFloat32x3 fP0, FfxFloat32x3 fP1, FfxFloat32x3 fP2) +{ + PlaneData plane; + + FfxFloat32x3 v0 = fP0 - fP1; + FfxFloat32x3 v1 = fP0 - fP2; + plane.fNormal = normalize(cross(v0, v1)); + plane.fDistanceFromOrigin = -dot(fP0, plane.fNormal); + + return plane; +} + +FfxFloat32 PointToPlaneDistance(PlaneData plane, FfxFloat32x3 fPoint) +{ + return abs(dot(plane.fNormal, fPoint) + plane.fDistanceFromOrigin); +} + +#endif // #if defined(FFX_GPU) + +#endif //!defined(FFX_FSR3UPSCALER_COMMON_H) diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid.h new file mode 100644 index 00000000..d26cf234 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid.h @@ -0,0 +1,176 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +FFX_GROUPSHARED FfxUInt32 spdCounter; + +void SpdIncreaseAtomicCounter(FfxUInt32 slice) +{ + SPD_IncreaseAtomicCounter(spdCounter); +} + +FfxUInt32 SpdGetAtomicCounter() +{ + return spdCounter; +} + +void SpdResetAtomicCounter(FfxUInt32 slice) +{ + SPD_ResetAtomicCounter(); +} + +#ifndef SPD_PACKED_ONLY +FFX_GROUPSHARED FfxFloat32 spdIntermediateR[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateG[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateB[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateA[16][16]; + +FfxFloat32x4 SpdLoadSourceImage(FfxFloat32x2 tex, FfxUInt32 slice) +{ + FfxFloat32x2 fUv = (tex + 0.5f + Jitter()) / RenderSize(); + fUv = ClampUv(fUv, RenderSize(), InputColorResourceDimensions()); + FfxFloat32x3 fRgb = SampleInputColor(fUv); + + fRgb /= PreExposure(); + + //compute log luma + const FfxFloat32 fLogLuma = log(ffxMax(FSR3UPSCALER_EPSILON, RGBToLuma(fRgb))); + + // Make sure out of screen pixels contribute no value to the end result + const FfxFloat32 result = all(FFX_LESS_THAN(tex, RenderSize())) ? fLogLuma : 0.0f; + + return FfxFloat32x4(result, 0, 0, 0); +} + +FfxFloat32x4 SpdLoad(FfxInt32x2 tex, FfxUInt32 slice) +{ + return SPD_LoadMipmap5(tex); +} + +void SpdStore(FfxInt32x2 pix, FfxFloat32x4 outValue, FfxUInt32 index, FfxUInt32 slice) +{ + if (index == LumaMipLevelToUse() || index == 5) + { + SPD_SetMipmap(pix, index, outValue.r); + } + + if (index == MipCount() - 1) { //accumulate on 1x1 level + + if (all(FFX_EQUAL(pix, FfxInt32x2(0, 0)))) + { + FfxFloat32 prev = SPD_LoadExposureBuffer().y; + FfxFloat32 result = outValue.r; + + if (prev < resetAutoExposureAverageSmoothing) // Compare Lavg, so small or negative values + { + FfxFloat32 rate = 1.0f; + result = prev + (result - prev) * (1 - exp(-DeltaTime() * rate)); + } + FfxFloat32x2 spdOutput = FfxFloat32x2(ComputeAutoExposureFromLavg(result), result); + SPD_SetExposureBuffer(spdOutput); + } + } +} + +FfxFloat32x4 SpdLoadIntermediate(FfxUInt32 x, FfxUInt32 y) +{ + return FfxFloat32x4( + spdIntermediateR[x][y], + spdIntermediateG[x][y], + spdIntermediateB[x][y], + spdIntermediateA[x][y]); +} +void SpdStoreIntermediate(FfxUInt32 x, FfxUInt32 y, FfxFloat32x4 value) +{ + spdIntermediateR[x][y] = value.x; + spdIntermediateG[x][y] = value.y; + spdIntermediateB[x][y] = value.z; + spdIntermediateA[x][y] = value.w; +} +FfxFloat32x4 SpdReduce4(FfxFloat32x4 v0, FfxFloat32x4 v1, FfxFloat32x4 v2, FfxFloat32x4 v3) +{ + return (v0 + v1 + v2 + v3) * 0.25f; +} +#endif + +// define fetch and store functions Packed +#if FFX_HALF + +FFX_GROUPSHARED FfxFloat16x2 spdIntermediateRG[16][16]; +FFX_GROUPSHARED FfxFloat16x2 spdIntermediateBA[16][16]; + +FfxFloat16x4 SpdLoadSourceImageH(FfxFloat32x2 tex, FfxUInt32 slice) +{ + return FfxFloat16x4(0, 0, 0, 0); +} + +FfxFloat16x4 SpdLoadH(FfxInt32x2 p, FfxUInt32 slice) +{ + return FfxFloat16x4(0, 0, 0, 0); +} + +void SpdStoreH(FfxInt32x2 p, FfxFloat16x4 value, FfxUInt32 mip, FfxUInt32 slice) +{ +} + +FfxFloat16x4 SpdLoadIntermediateH(FfxUInt32 x, FfxUInt32 y) +{ + return FfxFloat16x4( + spdIntermediateRG[x][y].x, + spdIntermediateRG[x][y].y, + spdIntermediateBA[x][y].x, + spdIntermediateBA[x][y].y); +} + +void SpdStoreIntermediateH(FfxUInt32 x, FfxUInt32 y, FfxFloat16x4 value) +{ + spdIntermediateRG[x][y] = value.xy; + spdIntermediateBA[x][y] = value.zw; +} + +FfxFloat16x4 SpdReduce4H(FfxFloat16x4 v0, FfxFloat16x4 v1, FfxFloat16x4 v2, FfxFloat16x4 v3) +{ + return (v0 + v1 + v2 + v3) * FfxFloat16(0.25); +} +#endif + +#include "spd/ffx_spd.h" + +void ComputeAutoExposure(FfxUInt32x3 WorkGroupId, FfxUInt32 LocalThreadIndex) +{ +#if FFX_HALF + SpdDownsampleH( + FfxUInt32x2(WorkGroupId.xy), + FfxUInt32(LocalThreadIndex), + FfxUInt32(MipCount()), + FfxUInt32(NumWorkGroups()), + FfxUInt32(WorkGroupId.z), + FfxUInt32x2(WorkGroupOffset())); +#else + SpdDownsample( + FfxUInt32x2(WorkGroupId.xy), + FfxUInt32(LocalThreadIndex), + FfxUInt32(MipCount()), + FfxUInt32(NumWorkGroups()), + FfxUInt32(WorkGroupId.z), + FfxUInt32x2(WorkGroupOffset())); +#endif +} diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_depth_clip.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_depth_clip.h new file mode 100644 index 00000000..53763c85 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_depth_clip.h @@ -0,0 +1,259 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FSR3UPSCALER_DEPTH_CLIP_H +#define FFX_FSR3UPSCALER_DEPTH_CLIP_H + +FFX_STATIC const FfxFloat32 DepthClipBaseScale = 4.0f; + +FfxFloat32 ComputeDepthClip(FfxFloat32x2 fUvSample, FfxFloat32 fCurrentDepthSample) +{ + FfxFloat32 fCurrentDepthViewSpace = GetViewSpaceDepth(fCurrentDepthSample); + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUvSample, RenderSize()); + + FfxFloat32 fDilatedSum = 0.0f; + FfxFloat32 fDepth = 0.0f; + FfxFloat32 fWeightSum = 0.0f; + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) { + + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset; + + if (IsOnScreen(iSamplePos, RenderSize())) { + const FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex]; + if (fWeight > fReconstructedDepthBilinearWeightThreshold) { + + const FfxFloat32 fPrevDepthSample = LoadReconstructedPrevDepth(iSamplePos); + const FfxFloat32 fPrevNearestDepthViewSpace = GetViewSpaceDepth(fPrevDepthSample); + + const FfxFloat32 fDepthDiff = fCurrentDepthViewSpace - fPrevNearestDepthViewSpace; + + if (fDepthDiff > 0.0f) { + +#if FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH + const FfxFloat32 fPlaneDepth = ffxMin(fPrevDepthSample, fCurrentDepthSample); +#else + const FfxFloat32 fPlaneDepth = ffxMax(fPrevDepthSample, fCurrentDepthSample); +#endif + + const FfxFloat32x3 fCenter = GetViewSpacePosition(FfxInt32x2(RenderSize() * 0.5f), RenderSize(), fPlaneDepth); + const FfxFloat32x3 fCorner = GetViewSpacePosition(FfxInt32x2(0, 0), RenderSize(), fPlaneDepth); + + const FfxFloat32 fHalfViewportWidth = length(FfxFloat32x2(RenderSize())); + const FfxFloat32 fDepthThreshold = ffxMax(fCurrentDepthViewSpace, fPrevNearestDepthViewSpace); + + const FfxFloat32 Ksep = 1.37e-05f; + const FfxFloat32 Kfov = length(fCorner) / length(fCenter); + const FfxFloat32 fRequiredDepthSeparation = Ksep * Kfov * fHalfViewportWidth * fDepthThreshold; + + const FfxFloat32 fResolutionFactor = ffxSaturate(length(FfxFloat32x2(RenderSize())) / length(FfxFloat32x2(1920.0f, 1080.0f))); + const FfxFloat32 fPower = ffxLerp(1.0f, 3.0f, fResolutionFactor); + fDepth += ffxPow(ffxSaturate(FfxFloat32(fRequiredDepthSeparation / fDepthDiff)), fPower) * fWeight; + fWeightSum += fWeight; + } + } + } + } + + return (fWeightSum > 0) ? ffxSaturate(1.0f - fDepth / fWeightSum) : 0.0f; +} + +FfxFloat32 ComputeMotionDivergence(FfxInt32x2 iPxPos, FfxInt32x2 iPxInputMotionVectorSize) +{ + FfxFloat32 minconvergence = 1.0f; + + FfxFloat32x2 fMotionVectorNucleus = LoadInputMotionVector(iPxPos); + FfxFloat32 fNucleusVelocityLr = length(fMotionVectorNucleus * RenderSize()); + FfxFloat32 fMaxVelocityUv = length(fMotionVectorNucleus); + + const FfxFloat32 MotionVectorVelocityEpsilon = 1e-02f; + + if (fNucleusVelocityLr > MotionVectorVelocityEpsilon) { + for (FfxInt32 y = -1; y <= 1; ++y) { + for (FfxInt32 x = -1; x <= 1; ++x) { + + FfxInt32x2 sp = ClampLoad(iPxPos, FfxInt32x2(x, y), iPxInputMotionVectorSize); + + FfxFloat32x2 fMotionVector = LoadInputMotionVector(sp); + FfxFloat32 fVelocityUv = length(fMotionVector); + + fMaxVelocityUv = ffxMax(fVelocityUv, fMaxVelocityUv); + fVelocityUv = ffxMax(fVelocityUv, fMaxVelocityUv); + minconvergence = ffxMin(minconvergence, dot(fMotionVector / fVelocityUv, fMotionVectorNucleus / fVelocityUv)); + } + } + } + + return ffxSaturate(1.0f - minconvergence) * ffxSaturate(fMaxVelocityUv / 0.01f); +} + +FfxFloat32 ComputeDepthDivergence(FfxInt32x2 iPxPos) +{ + const FfxFloat32 fMaxDistInMeters = GetMaxDistanceInMeters(); + FfxFloat32 fDepthMax = 0.0f; + FfxFloat32 fDepthMin = fMaxDistInMeters; + + FfxInt32 iMaxDistFound = 0; + + for (FfxInt32 y = -1; y < 2; y++) { + for (FfxInt32 x = -1; x < 2; x++) { + + const FfxInt32x2 iOffset = FfxInt32x2(x, y); + const FfxInt32x2 iSamplePos = iPxPos + iOffset; + + const FfxFloat32 fOnScreenFactor = IsOnScreen(iSamplePos, RenderSize()) ? 1.0f : 0.0f; + FfxFloat32 fDepth = GetViewSpaceDepthInMeters(LoadDilatedDepth(iSamplePos)) * fOnScreenFactor; + + iMaxDistFound |= FfxInt32(fMaxDistInMeters == fDepth); + + fDepthMin = ffxMin(fDepthMin, fDepth); + fDepthMax = ffxMax(fDepthMax, fDepth); + } + } + + return (1.0f - fDepthMin / fDepthMax) * (FfxBoolean(iMaxDistFound) ? 0.0f : 1.0f); +} + +FfxFloat32 ComputeTemporalMotionDivergence(FfxInt32x2 iPxPos) +{ + const FfxFloat32x2 fUv = FfxFloat32x2(iPxPos + 0.5f) / RenderSize(); + + FfxFloat32x2 fMotionVector = LoadDilatedMotionVector(iPxPos); + FfxFloat32x2 fReprojectedUv = fUv + fMotionVector; + fReprojectedUv = ClampUv(fReprojectedUv, RenderSize(), MaxRenderSize()); + FfxFloat32x2 fPrevMotionVector = SamplePreviousDilatedMotionVector(fReprojectedUv); + + float fPxDistance = length(fMotionVector * DisplaySize()); + return fPxDistance > 1.0f ? ffxLerp(0.0f, 1.0f - ffxSaturate(length(fPrevMotionVector) / length(fMotionVector)), ffxSaturate(ffxPow(fPxDistance / 20.0f, 3.0f))) : 0; +} + +void PreProcessReactiveMasks(FfxInt32x2 iPxLrPos, FfxFloat32 fMotionDivergence) +{ + // Compensate for bilinear sampling in accumulation pass + + FfxFloat32x3 fReferenceColor = LoadInputColor(iPxLrPos).xyz; + FfxFloat32x2 fReactiveFactor = FfxFloat32x2(0.0f, fMotionDivergence); + + float fMasksSum = 0.0f; + + FfxFloat32x3 fColorSamples[9]; + FfxFloat32 fReactiveSamples[9]; + FfxFloat32 fTransparencyAndCompositionSamples[9]; + + FFX_UNROLL + for (FfxInt32 y = -1; y < 2; y++) { + FFX_UNROLL + for (FfxInt32 x = -1; x < 2; x++) { + + const FfxInt32x2 sampleCoord = ClampLoad(iPxLrPos, FfxInt32x2(x, y), FfxInt32x2(RenderSize())); + + FfxInt32 sampleIdx = (y + 1) * 3 + x + 1; + + FfxFloat32x3 fColorSample = LoadInputColor(sampleCoord).xyz; + FfxFloat32 fReactiveSample = LoadReactiveMask(sampleCoord); + FfxFloat32 fTransparencyAndCompositionSample = LoadTransparencyAndCompositionMask(sampleCoord); + + fColorSamples[sampleIdx] = fColorSample; + fReactiveSamples[sampleIdx] = fReactiveSample; + fTransparencyAndCompositionSamples[sampleIdx] = fTransparencyAndCompositionSample; + + fMasksSum += (fReactiveSample + fTransparencyAndCompositionSample); + } + } + + if (fMasksSum > 0) + { + for (FfxInt32 sampleIdx = 0; sampleIdx < 9; sampleIdx++) + { + FfxFloat32x3 fColorSample = fColorSamples[sampleIdx]; + FfxFloat32 fReactiveSample = fReactiveSamples[sampleIdx]; + FfxFloat32 fTransparencyAndCompositionSample = fTransparencyAndCompositionSamples[sampleIdx]; + + const FfxFloat32 fMaxLenSq = ffxMax(dot(fReferenceColor, fReferenceColor), dot(fColorSample, fColorSample)); + const FfxFloat32 fSimilarity = dot(fReferenceColor, fColorSample) / fMaxLenSq; + + // Increase power for non-similar samples + const FfxFloat32 fPowerBiasMax = 6.0f; + const FfxFloat32 fSimilarityPower = 1.0f + (fPowerBiasMax - fSimilarity * fPowerBiasMax); + const FfxFloat32 fWeightedReactiveSample = ffxPow(fReactiveSample, fSimilarityPower); + const FfxFloat32 fWeightedTransparencyAndCompositionSample = ffxPow(fTransparencyAndCompositionSample, fSimilarityPower); + + fReactiveFactor = ffxMax(fReactiveFactor, FfxFloat32x2(fWeightedReactiveSample, fWeightedTransparencyAndCompositionSample)); + } + } + + StoreDilatedReactiveMasks(iPxLrPos, fReactiveFactor); +} + +FfxFloat32x3 ComputePreparedInputColor(FfxInt32x2 iPxLrPos) +{ + //We assume linear data. if non-linear input (sRGB, ...), + //then we should convert to linear first and back to sRGB on output. + FfxFloat32x3 fRgb = ffxMax(FfxFloat32x3(0, 0, 0), LoadInputColor(iPxLrPos)); + + fRgb = PrepareRgb(fRgb, Exposure(), PreExposure()); + + const FfxFloat32x3 fPreparedYCoCg = RGBToYCoCg(fRgb); + + return fPreparedYCoCg; +} + +FfxFloat32 EvaluateSurface(FfxInt32x2 iPxPos, FfxFloat32x2 fMotionVector) +{ + FfxFloat32 d0 = GetViewSpaceDepth(LoadReconstructedPrevDepth(iPxPos + FfxInt32x2(0, -1))); + FfxFloat32 d1 = GetViewSpaceDepth(LoadReconstructedPrevDepth(iPxPos + FfxInt32x2(0, 0))); + FfxFloat32 d2 = GetViewSpaceDepth(LoadReconstructedPrevDepth(iPxPos + FfxInt32x2(0, 1))); + + return 1.0f - FfxFloat32(((d0 - d1) > (d1 * 0.01f)) && ((d1 - d2) > (d2 * 0.01f))); +} + +void DepthClip(FfxInt32x2 iPxPos) +{ + FfxFloat32x2 fDepthUv = (iPxPos + 0.5f) / RenderSize(); + FfxFloat32x2 fMotionVector = LoadDilatedMotionVector(iPxPos); + + // Discard tiny mvs + fMotionVector *= FfxFloat32(length(fMotionVector * DisplaySize()) > 0.01f); + + const FfxFloat32x2 fDilatedUv = fDepthUv + fMotionVector; + const FfxFloat32 fDilatedDepth = LoadDilatedDepth(iPxPos); + const FfxFloat32 fCurrentDepthViewSpace = GetViewSpaceDepth(LoadInputDepth(iPxPos)); + + // Compute prepared input color and depth clip + FfxFloat32 fDepthClip = ComputeDepthClip(fDilatedUv, fDilatedDepth) * EvaluateSurface(iPxPos, fMotionVector); + FfxFloat32x3 fPreparedYCoCg = ComputePreparedInputColor(iPxPos); + StorePreparedInputColor(iPxPos, FfxFloat32x4(fPreparedYCoCg, fDepthClip)); + + // Compute dilated reactive mask +#if FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS + FfxInt32x2 iSamplePos = iPxPos; +#else + FfxInt32x2 iSamplePos = ComputeHrPosFromLrPos(iPxPos); +#endif + + FfxFloat32 fMotionDivergence = ComputeMotionDivergence(iSamplePos, RenderSize()); + FfxFloat32 fTemporalMotionDifference = ffxSaturate(ComputeTemporalMotionDivergence(iPxPos) - ComputeDepthDivergence(iPxPos)); + + PreProcessReactiveMasks(iPxPos, ffxMax(fTemporalMotionDifference, fMotionDivergence)); +} + +#endif //!defined( FFX_FSR3UPSCALER_DEPTH_CLIPH ) diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_lock.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_lock.h new file mode 100644 index 00000000..e1a0d06e --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_lock.h @@ -0,0 +1,116 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FSR3UPSCALER_LOCK_H +#define FFX_FSR3UPSCALER_LOCK_H + +void ClearResourcesForNextFrame(in FfxInt32x2 iPxHrPos) +{ + if (all(FFX_LESS_THAN(iPxHrPos, FfxInt32x2(RenderSize())))) + { +#if FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH + const FfxUInt32 farZ = 0x0; +#else + const FfxUInt32 farZ = 0x3f800000; +#endif + SetReconstructedDepth(iPxHrPos, farZ); + } +} + +FfxBoolean ComputeThinFeatureConfidence(FfxInt32x2 pos) +{ + const FfxInt32 RADIUS = 1; + + FfxFloat32 fNucleus = LoadLockInputLuma(pos); + + FfxFloat32 similar_threshold = 1.05f; + FfxFloat32 dissimilarLumaMin = FSR3UPSCALER_FLT_MAX; + FfxFloat32 dissimilarLumaMax = 0; + + /* + 0 1 2 + 3 4 5 + 6 7 8 + */ + + #define SETBIT(x) (1U << x) + + FfxUInt32 mask = SETBIT(4); //flag fNucleus as similar + + const FfxUInt32 uNumRejectionMasks = 4; + const FfxUInt32 uRejectionMasks[uNumRejectionMasks] = { + SETBIT(0) | SETBIT(1) | SETBIT(3) | SETBIT(4), //Upper left + SETBIT(1) | SETBIT(2) | SETBIT(4) | SETBIT(5), //Upper right + SETBIT(3) | SETBIT(4) | SETBIT(6) | SETBIT(7), //Lower left + SETBIT(4) | SETBIT(5) | SETBIT(7) | SETBIT(8), //Lower right + }; + + FfxInt32 idx = 0; + FFX_UNROLL + for (FfxInt32 y = -RADIUS; y <= RADIUS; y++) { + FFX_UNROLL + for (FfxInt32 x = -RADIUS; x <= RADIUS; x++, idx++) { + if (x == 0 && y == 0) continue; + + FfxInt32x2 samplePos = ClampLoad(pos, FfxInt32x2(x, y), FfxInt32x2(RenderSize())); + + FfxFloat32 sampleLuma = LoadLockInputLuma(samplePos); + FfxFloat32 difference = ffxMax(sampleLuma, fNucleus) / ffxMin(sampleLuma, fNucleus); + + if (difference > 0 && (difference < similar_threshold)) { + mask |= SETBIT(idx); + } else { + dissimilarLumaMin = ffxMin(dissimilarLumaMin, sampleLuma); + dissimilarLumaMax = ffxMax(dissimilarLumaMax, sampleLuma); + } + } + } + + FfxBoolean isRidge = fNucleus > dissimilarLumaMax || fNucleus < dissimilarLumaMin; + + if (FFX_FALSE == isRidge) { + + return false; + } + + FFX_UNROLL + for (FfxInt32 i = 0; i < 4; i++) { + + if ((mask & uRejectionMasks[i]) == uRejectionMasks[i]) { + return false; + } + } + + return true; +} + +void ComputeLock(FfxInt32x2 iPxLrPos) +{ + if (ComputeThinFeatureConfidence(iPxLrPos)) + { + StoreNewLocks(ComputeHrPosFromLrPos(iPxLrPos), 1.f); + } + + // ClearResourcesForNextFrame(iPxLrPos); +} + +#endif // FFX_FSR3UPSCALER_LOCK_H diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_postprocess_lock_status.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_postprocess_lock_status.h new file mode 100644 index 00000000..37091135 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_postprocess_lock_status.h @@ -0,0 +1,107 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FSR3UPSCALER_POSTPROCESS_LOCK_STATUS_H +#define FFX_FSR3UPSCALER_POSTPROCESS_LOCK_STATUS_H + +FfxFloat32x4 WrapShadingChangeLuma(FfxInt32x2 iPxSample) +{ + return FfxFloat32x4(LoadMipLuma(iPxSample, LumaMipLevelToUse()), 0, 0, 0); +} + +#if FFX_HALF +FFX_MIN16_F4 WrapShadingChangeLuma(FFX_MIN16_I2 iPxSample) +{ + return FFX_MIN16_F4(LoadMipLuma(iPxSample, LumaMipLevelToUse()), 0, 0, 0); +} +#endif + +#if FFX_FSR3UPSCALER_OPTION_POSTPROCESSLOCKSTATUS_SAMPLERS_USE_DATA_HALF && FFX_HALF +DeclareCustomFetchBilinearSamplesMin16(FetchShadingChangeLumaSamples, WrapShadingChangeLuma) +#else +DeclareCustomFetchBicubicSamples(FetchShadingChangeLumaSamples, WrapShadingChangeLuma) +#endif +DeclareCustomTextureSample(ShadingChangeLumaSample, Lanczos2, FetchShadingChangeLumaSamples) + +FfxFloat32 GetShadingChangeLuma(FfxInt32x2 iPxHrPos, FfxFloat32x2 fUvCoord) +{ + FfxFloat32 fShadingChangeLuma = 0; + +#if 0 + fShadingChangeLuma = Exposure() * exp(ShadingChangeLumaSample(fUvCoord, LumaMipDimensions()).x); +#else + + const FfxFloat32 fDiv = FfxFloat32(2u << LumaMipLevelToUse()); + FfxInt32x2 iMipRenderSize = FfxInt32x2(RenderSize() / fDiv); + + fUvCoord = ClampUv(fUvCoord, iMipRenderSize, LumaMipDimensions()); + fShadingChangeLuma = Exposure() * exp(FfxFloat32(SampleMipLuma(fUvCoord, LumaMipLevelToUse()))); +#endif + + fShadingChangeLuma = ffxPow(fShadingChangeLuma, 1.0f / 6.0f); + + return fShadingChangeLuma; +} + +void UpdateLockStatus(AccumulationPassCommonParams params, + FFX_PARAMETER_INOUT FfxFloat32 fReactiveFactor, LockState state, + FFX_PARAMETER_INOUT FfxFloat32x2 fLockStatus, + FFX_PARAMETER_OUT FfxFloat32 fLockContributionThisFrame, + FFX_PARAMETER_OUT FfxFloat32 fLuminanceDiff) { + + const FfxFloat32 fShadingChangeLuma = GetShadingChangeLuma(params.iPxHrPos, params.fHrUv); + + //init temporal shading change factor, init to -1 or so in reproject to know if "true new"? + fLockStatus[LOCK_TEMPORAL_LUMA] = (fLockStatus[LOCK_TEMPORAL_LUMA] == FfxFloat32(0.0f)) ? fShadingChangeLuma : fLockStatus[LOCK_TEMPORAL_LUMA]; + + FfxFloat32 fPreviousShadingChangeLuma = fLockStatus[LOCK_TEMPORAL_LUMA]; + + fLuminanceDiff = 1.0f - MinDividedByMax(fPreviousShadingChangeLuma, fShadingChangeLuma); + + if (state.NewLock) { + fLockStatus[LOCK_TEMPORAL_LUMA] = fShadingChangeLuma; + + fLockStatus[LOCK_LIFETIME_REMAINING] = (fLockStatus[LOCK_LIFETIME_REMAINING] != 0.0f) ? 2.0f : 1.0f; + } + else if(fLockStatus[LOCK_LIFETIME_REMAINING] <= 1.0f) { + fLockStatus[LOCK_TEMPORAL_LUMA] = ffxLerp(fLockStatus[LOCK_TEMPORAL_LUMA], FfxFloat32(fShadingChangeLuma), 0.5f); + } + else { + if (fLuminanceDiff > 0.1f) { + KillLock(fLockStatus); + } + } + + fReactiveFactor = ffxMax(fReactiveFactor, ffxSaturate((fLuminanceDiff - 0.1f) * 10.0f)); + fLockStatus[LOCK_LIFETIME_REMAINING] *= (1.0f - fReactiveFactor); + + fLockStatus[LOCK_LIFETIME_REMAINING] *= ffxSaturate(1.0f - params.fAccumulationMask); + fLockStatus[LOCK_LIFETIME_REMAINING] *= FfxFloat32(params.fDepthClipFactor < 0.1f); + + // Compute this frame lock contribution + const FfxFloat32 fLifetimeContribution = ffxSaturate(fLockStatus[LOCK_LIFETIME_REMAINING] - 1.0f); + const FfxFloat32 fShadingChangeContribution = ffxSaturate(MinDividedByMax(fLockStatus[LOCK_TEMPORAL_LUMA], fShadingChangeLuma)); + + fLockContributionThisFrame = ffxSaturate(ffxSaturate(fLifetimeContribution * 4.0f) * fShadingChangeContribution); +} + +#endif //!defined( FFX_FSR3UPSCALER_POSTPROCESS_LOCK_STATUS_H ) diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_rcas.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_rcas.h new file mode 100644 index 00000000..77619a51 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_rcas.h @@ -0,0 +1,67 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define GROUP_SIZE 8 +#define FSR_RCAS_DENOISE 1 + +#include "ffx_core.h" + +void WriteUpscaledOutput(FFX_MIN16_U2 iPxHrPos, FfxFloat32x3 fUpscaledColor) +{ + StoreUpscaledOutput(FFX_MIN16_I2(iPxHrPos), fUpscaledColor); +} + +#define FSR_RCAS_F 1 +FfxFloat32x4 FsrRcasLoadF(FfxInt32x2 p) +{ + FfxFloat32x4 fColor = LoadRCAS_Input(p); + + fColor.rgb = PrepareRgb(fColor.rgb, Exposure(), PreExposure()); + + return fColor; +} +void FsrRcasInputF(inout FfxFloat32 r, inout FfxFloat32 g, inout FfxFloat32 b) {} + +#include "fsr1/ffx_fsr1.h" + +void CurrFilter(FFX_MIN16_U2 pos) +{ + FfxFloat32x3 c; + FsrRcasF(c.r, c.g, c.b, pos, RCASConfig()); + + c = UnprepareRgb(c, Exposure()); + + WriteUpscaledOutput(pos, c); +} + +void RCAS(FfxUInt32x3 LocalThreadId, FfxUInt32x3 WorkGroupId, FfxUInt32x3 Dtid) +{ + // Do remapping of local xy in workgroup for a more PS-like swizzle pattern. + FfxUInt32x2 gxy = ffxRemapForQuad(LocalThreadId.x) + FfxUInt32x2(WorkGroupId.x << 4u, WorkGroupId.y << 4u); + CurrFilter(FFX_MIN16_U2(gxy)); + gxy.x += 8u; + CurrFilter(FFX_MIN16_U2(gxy)); + gxy.y += 8u; + CurrFilter(FFX_MIN16_U2(gxy)); + gxy.x -= 8u; + CurrFilter(FFX_MIN16_U2(gxy)); +} diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_reconstruct_dilated_velocity_and_previous_depth.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_reconstruct_dilated_velocity_and_previous_depth.h new file mode 100644 index 00000000..a822dfc5 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_reconstruct_dilated_velocity_and_previous_depth.h @@ -0,0 +1,146 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FSR3UPSCALER_RECONSTRUCT_DILATED_VELOCITY_AND_PREVIOUS_DEPTH_H +#define FFX_FSR3UPSCALER_RECONSTRUCT_DILATED_VELOCITY_AND_PREVIOUS_DEPTH_H + +void ReconstructPrevDepth(FfxInt32x2 iPxPos, FfxFloat32 fDepth, FfxFloat32x2 fMotionVector, FfxInt32x2 iPxDepthSize) +{ + fMotionVector *= FfxFloat32(length(fMotionVector * DisplaySize()) > 0.1f); + + FfxFloat32x2 fUv = (iPxPos + FfxFloat32(0.5)) / iPxDepthSize; + FfxFloat32x2 fReprojectedUv = fUv + fMotionVector; + + BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fReprojectedUv, RenderSize()); + + // Project current depth into previous frame locations. + // Push to all pixels having some contribution if reprojection is using bilinear logic. + for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) { + + const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex]; + FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex]; + + if (fWeight > fReconstructedDepthBilinearWeightThreshold) { + + FfxInt32x2 iStorePos = bilinearInfo.iBasePos + iOffset; + if (IsOnScreen(iStorePos, iPxDepthSize)) { + StoreReconstructedDepth(iStorePos, fDepth); + } + } + } +} + +void FindNearestDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxInt32x2 iPxSize, FFX_PARAMETER_OUT FfxFloat32 fNearestDepth, FFX_PARAMETER_OUT FfxInt32x2 fNearestDepthCoord) +{ + const FfxInt32 iSampleCount = 9; + const FfxInt32x2 iSampleOffsets[iSampleCount] = { + FfxInt32x2(+0, +0), + FfxInt32x2(+1, +0), + FfxInt32x2(+0, +1), + FfxInt32x2(+0, -1), + FfxInt32x2(-1, +0), + FfxInt32x2(-1, +1), + FfxInt32x2(+1, +1), + FfxInt32x2(-1, -1), + FfxInt32x2(+1, -1), + }; + + // pull out the depth loads to allow SC to batch them + FfxFloat32 depth[9]; + FfxInt32 iSampleIndex = 0; + FFX_UNROLL + for (iSampleIndex = 0; iSampleIndex < iSampleCount; ++iSampleIndex) { + + FfxInt32x2 iPos = iPxPos + iSampleOffsets[iSampleIndex]; + depth[iSampleIndex] = LoadInputDepth(iPos); + } + + // find closest depth + fNearestDepthCoord = iPxPos; + fNearestDepth = depth[0]; + FFX_UNROLL + for (iSampleIndex = 1; iSampleIndex < iSampleCount; ++iSampleIndex) { + + FfxInt32x2 iPos = iPxPos + iSampleOffsets[iSampleIndex]; + if (IsOnScreen(iPos, iPxSize)) { + + FfxFloat32 fNdDepth = depth[iSampleIndex]; +#if FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH + if (fNdDepth > fNearestDepth) { +#else + if (fNdDepth < fNearestDepth) { +#endif + fNearestDepthCoord = iPos; + fNearestDepth = fNdDepth; + } + } + } +} + +FfxFloat32 ComputeLockInputLuma(FfxInt32x2 iPxLrPos) +{ + //We assume linear data. if non-linear input (sRGB, ...), + //then we should convert to linear first and back to sRGB on output. + FfxFloat32x3 fRgb = ffxMax(FfxFloat32x3(0, 0, 0), LoadInputColor(iPxLrPos)); + + // Use internal auto exposure for locking logic + fRgb /= PreExposure(); + fRgb *= Exposure(); + +#if FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT + fRgb = Tonemap(fRgb); +#endif + + //compute luma used to lock pixels, if used elsewhere the ffxPow must be moved! + const FfxFloat32 fLockInputLuma = ffxPow(RGBToPerceivedLuma(fRgb), FfxFloat32(1.0 / 6.0)); + + return fLockInputLuma; +} + +void ReconstructAndDilate(FfxInt32x2 iPxLrPos) +{ + FfxFloat32 fDilatedDepth; + FfxInt32x2 iNearestDepthCoord; + + FindNearestDepth(iPxLrPos, RenderSize(), fDilatedDepth, iNearestDepthCoord); + +#if FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS + FfxInt32x2 iSamplePos = iPxLrPos; + FfxInt32x2 iMotionVectorPos = iNearestDepthCoord; +#else + FfxInt32x2 iSamplePos = ComputeHrPosFromLrPos(iPxLrPos); + FfxInt32x2 iMotionVectorPos = ComputeHrPosFromLrPos(iNearestDepthCoord); +#endif + + FfxFloat32x2 fDilatedMotionVector = LoadInputMotionVector(iMotionVectorPos); + + StoreDilatedDepth(iPxLrPos, fDilatedDepth); + StoreDilatedMotionVector(iPxLrPos, fDilatedMotionVector); + + ReconstructPrevDepth(iPxLrPos, fDilatedDepth, fDilatedMotionVector, RenderSize()); + + FfxFloat32 fLockInputLuma = ComputeLockInputLuma(iPxLrPos); + StoreLockInputLuma(iPxLrPos, fLockInputLuma); +} + + +#endif //!defined( FFX_FSR3UPSCALER_RECONSTRUCT_DILATED_VELOCITY_AND_PREVIOUS_DEPTH_H ) diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_reproject.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_reproject.h new file mode 100644 index 00000000..29b75843 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_reproject.h @@ -0,0 +1,137 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FSR3UPSCALER_REPROJECT_H +#define FFX_FSR3UPSCALER_REPROJECT_H + +#ifndef FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE +#define FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE 0 // Reference +#endif + +FfxFloat32x4 WrapHistory(FfxInt32x2 iPxSample) +{ + return LoadHistory(iPxSample); +} + +#if FFX_HALF +FFX_MIN16_F4 WrapHistory(FFX_MIN16_I2 iPxSample) +{ + return FFX_MIN16_F4(LoadHistory(iPxSample)); +} +#endif + + +#if FFX_FSR3UPSCALER_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF && FFX_HALF +DeclareCustomFetchBicubicSamplesMin16(FetchHistorySamples, WrapHistory) +DeclareCustomTextureSampleMin16(HistorySample, FFX_FSR3UPSCALER_GET_LANCZOS_SAMPLER1D(FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE), FetchHistorySamples) +#else +DeclareCustomFetchBicubicSamples(FetchHistorySamples, WrapHistory) +DeclareCustomTextureSample(HistorySample, FFX_FSR3UPSCALER_GET_LANCZOS_SAMPLER1D(FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE), FetchHistorySamples) +#endif + +FfxFloat32x4 WrapLockStatus(FfxInt32x2 iPxSample) +{ + FfxFloat32x4 fSample = FfxFloat32x4(LoadLockStatus(iPxSample), 0.0f, 0.0f); + return fSample; +} + +#if FFX_HALF +FFX_MIN16_F4 WrapLockStatus(FFX_MIN16_I2 iPxSample) +{ + FFX_MIN16_F4 fSample = FFX_MIN16_F4(LoadLockStatus(iPxSample), 0.0, 0.0); + + return fSample; +} +#endif + +#if 1 +#if FFX_FSR3UPSCALER_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF && FFX_HALF +DeclareCustomFetchBilinearSamplesMin16(FetchLockStatusSamples, WrapLockStatus) +DeclareCustomTextureSampleMin16(LockStatusSample, Bilinear, FetchLockStatusSamples) +#else +DeclareCustomFetchBilinearSamples(FetchLockStatusSamples, WrapLockStatus) +DeclareCustomTextureSample(LockStatusSample, Bilinear, FetchLockStatusSamples) +#endif +#else +#if FFX_FSR3UPSCALER_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF && FFX_HALF +DeclareCustomFetchBicubicSamplesMin16(FetchLockStatusSamples, WrapLockStatus) +DeclareCustomTextureSampleMin16(LockStatusSample, FFX_FSR3UPSCALER_GET_LANCZOS_SAMPLER1D(FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE), FetchLockStatusSamples) +#else +DeclareCustomFetchBicubicSamples(FetchLockStatusSamples, WrapLockStatus) +DeclareCustomTextureSample(LockStatusSample, FFX_FSR3UPSCALER_GET_LANCZOS_SAMPLER1D(FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE), FetchLockStatusSamples) +#endif +#endif + +FfxFloat32x2 GetMotionVector(FfxInt32x2 iPxHrPos, FfxFloat32x2 fHrUv) +{ +#if FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS + FfxFloat32x2 fDilatedMotionVector = LoadDilatedMotionVector(FFX_MIN16_I2(fHrUv * RenderSize())); +#else + FfxFloat32x2 fDilatedMotionVector = LoadInputMotionVector(iPxHrPos); +#endif + + return fDilatedMotionVector; +} + +FfxBoolean IsUvInside(FfxFloat32x2 fUv) +{ + return (fUv.x >= 0.0f && fUv.x <= 1.0f) && (fUv.y >= 0.0f && fUv.y <= 1.0f); +} + +void ComputeReprojectedUVs(const AccumulationPassCommonParams params, FFX_PARAMETER_OUT FfxFloat32x2 fReprojectedHrUv, FFX_PARAMETER_OUT FfxBoolean bIsExistingSample) +{ + fReprojectedHrUv = params.fHrUv + params.fMotionVector; + + bIsExistingSample = IsUvInside(fReprojectedHrUv); +} + +void ReprojectHistoryColor(const AccumulationPassCommonParams params, FFX_PARAMETER_OUT FfxFloat32x3 fHistoryColor, FFX_PARAMETER_OUT FfxFloat32 fTemporalReactiveFactor, FFX_PARAMETER_OUT FfxBoolean bInMotionLastFrame) +{ + FfxFloat32x4 fHistory = HistorySample(params.fReprojectedHrUv, DisplaySize()); + + fHistoryColor = PrepareRgb(fHistory.rgb, Exposure(), PreviousFramePreExposure()); + + fHistoryColor = RGBToYCoCg(fHistoryColor); + + //Compute temporal reactivity info + fTemporalReactiveFactor = ffxSaturate(abs(fHistory.w)); + bInMotionLastFrame = (fHistory.w < 0.0f); +} + +LockState ReprojectHistoryLockStatus(const AccumulationPassCommonParams params, FFX_PARAMETER_OUT FfxFloat32x2 fReprojectedLockStatus) +{ + LockState state = { FFX_FALSE, FFX_FALSE }; + const FfxFloat32 fNewLockIntensity = LoadRwNewLocks(params.iPxHrPos); + state.NewLock = fNewLockIntensity > (127.0f / 255.0f); + + FfxFloat32 fInPlaceLockLifetime = state.NewLock ? fNewLockIntensity : 0; + + fReprojectedLockStatus = SampleLockStatus(params.fReprojectedHrUv); + + if (fReprojectedLockStatus[LOCK_LIFETIME_REMAINING] != FfxFloat32(0.0f)) { + state.WasLockedPrevFrame = true; + } + + return state; +} + +#endif //!defined( FFX_FSR3UPSCALER_REPROJECT_H ) diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_resources.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_resources.h new file mode 100644 index 00000000..d98cfcc0 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_resources.h @@ -0,0 +1,104 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FSR3UPSCALER_RESOURCES_H +#define FFX_FSR3UPSCALER_RESOURCES_H + +#if defined(FFX_CPU) || defined(FFX_GPU) +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL 0 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_OPAQUE_ONLY 1 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_COLOR 2 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_MOTION_VECTORS 3 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_DEPTH 4 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_EXPOSURE 5 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_REACTIVE_MASK 6 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_TRANSPARENCY_AND_COMPOSITION_MASK 7 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH 8 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS 9 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_DEPTH 10 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR 11 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS 12 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NEW_LOCKS 13 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREPARED_INPUT_COLOR 14 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY 15 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DEBUG_OUTPUT 16 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LANCZOS_LUT 17 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SPD_ATOMIC_COUNT 18 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_UPSCALED_OUTPUT 19 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RCAS_INPUT 20 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS_1 21 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS_2 22 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR_1 23 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR_2 24 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_REACTIVITY 25 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_TRANSPARENCY_AND_COMPOSITION 26 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTITIER_UPSAMPLE_MAXIMUM_BIAS_LUT 27 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_REACTIVE_MASKS 28 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE 29 // same as FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_0 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_0 29 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_1 30 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_2 31 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_3 32 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_4 33 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_5 34 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_6 35 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_7 36 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_8 37 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_9 38 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_10 39 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_11 40 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_12 41 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_EXPOSURE 42 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTO_EXPOSURE 43 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTOREACTIVE 44 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTOCOMPOSITION_DEPRECATED 45 + +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR 46 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR 47 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR_1 48 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR_1 49 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR_2 50 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR_2 51 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREVIOUS_DILATED_MOTION_VECTORS 52 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY_1 53 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY_2 54 +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_INPUT_LUMA 55 + +// Shading change detection mip level setting, value must be in the range [FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_0, FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_12] +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_SHADING_CHANGE FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_4 +#define FFX_FSR3UPSCALER_SHADING_CHANGE_MIP_LEVEL (FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_SHADING_CHANGE - FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE) + +#define FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_COUNT 56 + +#define FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_FSR3UPSCALER 0 +#define FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_SPD 1 +#define FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_RCAS 2 +#define FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_GENREACTIVE 3 + +#define FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_TONEMAP 1 +#define FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_INVERSETONEMAP 2 +#define FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_THRESHOLD 4 +#define FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_USE_COMPONENTS_MAX 8 + +#endif // #if defined(FFX_CPU) || defined(FFX_GPU) + +#endif //!defined( FFX_FSR3UPSCALER_RESOURCES_H ) diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_sample.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_sample.h new file mode 100644 index 00000000..d33f70cf --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_sample.h @@ -0,0 +1,606 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FSR3UPSCALER_SAMPLE_H +#define FFX_FSR3UPSCALER_SAMPLE_H + +// suppress warnings +#ifdef FFX_HLSL +#pragma warning(disable: 4008) // potentially divide by zero +#endif //FFX_HLSL + +struct FetchedBilinearSamples { + + FfxFloat32x4 fColor00; + FfxFloat32x4 fColor10; + + FfxFloat32x4 fColor01; + FfxFloat32x4 fColor11; +}; + +struct FetchedBicubicSamples { + + FfxFloat32x4 fColor00; + FfxFloat32x4 fColor10; + FfxFloat32x4 fColor20; + FfxFloat32x4 fColor30; + + FfxFloat32x4 fColor01; + FfxFloat32x4 fColor11; + FfxFloat32x4 fColor21; + FfxFloat32x4 fColor31; + + FfxFloat32x4 fColor02; + FfxFloat32x4 fColor12; + FfxFloat32x4 fColor22; + FfxFloat32x4 fColor32; + + FfxFloat32x4 fColor03; + FfxFloat32x4 fColor13; + FfxFloat32x4 fColor23; + FfxFloat32x4 fColor33; +}; + +#if FFX_HALF +struct FetchedBilinearSamplesMin16 { + + FFX_MIN16_F4 fColor00; + FFX_MIN16_F4 fColor10; + + FFX_MIN16_F4 fColor01; + FFX_MIN16_F4 fColor11; +}; + +struct FetchedBicubicSamplesMin16 { + + FFX_MIN16_F4 fColor00; + FFX_MIN16_F4 fColor10; + FFX_MIN16_F4 fColor20; + FFX_MIN16_F4 fColor30; + + FFX_MIN16_F4 fColor01; + FFX_MIN16_F4 fColor11; + FFX_MIN16_F4 fColor21; + FFX_MIN16_F4 fColor31; + + FFX_MIN16_F4 fColor02; + FFX_MIN16_F4 fColor12; + FFX_MIN16_F4 fColor22; + FFX_MIN16_F4 fColor32; + + FFX_MIN16_F4 fColor03; + FFX_MIN16_F4 fColor13; + FFX_MIN16_F4 fColor23; + FFX_MIN16_F4 fColor33; +}; +#else //FFX_HALF +#define FetchedBicubicSamplesMin16 FetchedBicubicSamples +#define FetchedBilinearSamplesMin16 FetchedBilinearSamples +#endif //FFX_HALF + +FfxFloat32x4 Linear(FfxFloat32x4 A, FfxFloat32x4 B, FfxFloat32 t) +{ + return A + (B - A) * t; +} + +FfxFloat32x4 Bilinear(FetchedBilinearSamples BilinearSamples, FfxFloat32x2 fPxFrac) +{ + FfxFloat32x4 fColorX0 = Linear(BilinearSamples.fColor00, BilinearSamples.fColor10, fPxFrac.x); + FfxFloat32x4 fColorX1 = Linear(BilinearSamples.fColor01, BilinearSamples.fColor11, fPxFrac.x); + FfxFloat32x4 fColorXY = Linear(fColorX0, fColorX1, fPxFrac.y); + return fColorXY; +} + +#if FFX_HALF +FFX_MIN16_F4 Linear(FFX_MIN16_F4 A, FFX_MIN16_F4 B, FFX_MIN16_F t) +{ + return A + (B - A) * t; +} + +FFX_MIN16_F4 Bilinear(FetchedBilinearSamplesMin16 BilinearSamples, FFX_MIN16_F2 fPxFrac) +{ + FFX_MIN16_F4 fColorX0 = Linear(BilinearSamples.fColor00, BilinearSamples.fColor10, fPxFrac.x); + FFX_MIN16_F4 fColorX1 = Linear(BilinearSamples.fColor01, BilinearSamples.fColor11, fPxFrac.x); + FFX_MIN16_F4 fColorXY = Linear(fColorX0, fColorX1, fPxFrac.y); + return fColorXY; +} +#endif + +FfxFloat32 Lanczos2NoClamp(FfxFloat32 x) +{ + const FfxFloat32 PI = 3.141592653589793f; // TODO: share SDK constants + return abs(x) < FSR3UPSCALER_EPSILON ? 1.f : (sin(PI * x) / (PI * x)) * (sin(0.5f * PI * x) / (0.5f * PI * x)); +} + +FfxFloat32 Lanczos2(FfxFloat32 x) +{ + x = ffxMin(abs(x), 2.0f); + return Lanczos2NoClamp(x); +} + +#if FFX_HALF + +#if 0 +FFX_MIN16_F Lanczos2NoClamp(FFX_MIN16_F x) +{ + const FFX_MIN16_F PI = FFX_MIN16_F(3.141592653589793f); // TODO: share SDK constants + return abs(x) < FFX_MIN16_F(FSR3UPSCALER_EPSILON) ? FFX_MIN16_F(1.f) : (sin(PI * x) / (PI * x)) * (sin(FFX_MIN16_F(0.5f) * PI * x) / (FFX_MIN16_F(0.5f) * PI * x)); +} +#endif + +FFX_MIN16_F Lanczos2(FFX_MIN16_F x) +{ + x = ffxMin(abs(x), FFX_MIN16_F(2.0f)); + return FFX_MIN16_F(Lanczos2NoClamp(x)); +} +#endif //FFX_HALF + +// FSR1 lanczos approximation. Input is x*x and must be <= 4. +FfxFloat32 Lanczos2ApproxSqNoClamp(FfxFloat32 x2) +{ + FfxFloat32 a = (2.0f / 5.0f) * x2 - 1; + FfxFloat32 b = (1.0f / 4.0f) * x2 - 1; + return ((25.0f / 16.0f) * a * a - (25.0f / 16.0f - 1)) * (b * b); +} + +#if FFX_HALF +FFX_MIN16_F Lanczos2ApproxSqNoClamp(FFX_MIN16_F x2) +{ + FFX_MIN16_F a = FFX_MIN16_F(2.0f / 5.0f) * x2 - FFX_MIN16_F(1); + FFX_MIN16_F b = FFX_MIN16_F(1.0f / 4.0f) * x2 - FFX_MIN16_F(1); + return (FFX_MIN16_F(25.0f / 16.0f) * a * a - FFX_MIN16_F(25.0f / 16.0f - 1)) * (b * b); +} +#endif //FFX_HALF + +FfxFloat32 Lanczos2ApproxSq(FfxFloat32 x2) +{ + x2 = ffxMin(x2, 4.0f); + return Lanczos2ApproxSqNoClamp(x2); +} + +#if FFX_HALF +FFX_MIN16_F Lanczos2ApproxSq(FFX_MIN16_F x2) +{ + x2 = ffxMin(x2, FFX_MIN16_F(4.0f)); + return Lanczos2ApproxSqNoClamp(x2); +} +#endif //FFX_HALF + +FfxFloat32 Lanczos2ApproxNoClamp(FfxFloat32 x) +{ + return Lanczos2ApproxSqNoClamp(x * x); +} + +#if FFX_HALF +FFX_MIN16_F Lanczos2ApproxNoClamp(FFX_MIN16_F x) +{ + return Lanczos2ApproxSqNoClamp(x * x); +} +#endif //FFX_HALF + +FfxFloat32 Lanczos2Approx(FfxFloat32 x) +{ + return Lanczos2ApproxSq(x * x); +} + +#if FFX_HALF +FFX_MIN16_F Lanczos2Approx(FFX_MIN16_F x) +{ + return Lanczos2ApproxSq(x * x); +} +#endif //FFX_HALF + +FfxFloat32 Lanczos2_UseLUT(FfxFloat32 x) +{ + return SampleLanczos2Weight(abs(x)); +} + +#if FFX_HALF +FFX_MIN16_F Lanczos2_UseLUT(FFX_MIN16_F x) +{ + return FFX_MIN16_F(SampleLanczos2Weight(abs(x))); +} +#endif //FFX_HALF + +FfxFloat32x4 Lanczos2_UseLUT(FfxFloat32x4 fColor0, FfxFloat32x4 fColor1, FfxFloat32x4 fColor2, FfxFloat32x4 fColor3, FfxFloat32 t) +{ + FfxFloat32 fWeight0 = Lanczos2_UseLUT(-1.f - t); + FfxFloat32 fWeight1 = Lanczos2_UseLUT(-0.f - t); + FfxFloat32 fWeight2 = Lanczos2_UseLUT(+1.f - t); + FfxFloat32 fWeight3 = Lanczos2_UseLUT(+2.f - t); + return (fWeight0 * fColor0 + fWeight1 * fColor1 + fWeight2 * fColor2 + fWeight3 * fColor3) / (fWeight0 + fWeight1 + fWeight2 + fWeight3); +} +#if FFX_HALF +FFX_MIN16_F4 Lanczos2_UseLUT(FFX_MIN16_F4 fColor0, FFX_MIN16_F4 fColor1, FFX_MIN16_F4 fColor2, FFX_MIN16_F4 fColor3, FFX_MIN16_F t) +{ + FFX_MIN16_F fWeight0 = Lanczos2_UseLUT(FFX_MIN16_F(-1.f) - t); + FFX_MIN16_F fWeight1 = Lanczos2_UseLUT(FFX_MIN16_F(-0.f) - t); + FFX_MIN16_F fWeight2 = Lanczos2_UseLUT(FFX_MIN16_F(+1.f) - t); + FFX_MIN16_F fWeight3 = Lanczos2_UseLUT(FFX_MIN16_F(+2.f) - t); + return (fWeight0 * fColor0 + fWeight1 * fColor1 + fWeight2 * fColor2 + fWeight3 * fColor3) / (fWeight0 + fWeight1 + fWeight2 + fWeight3); +} +#endif + +FfxFloat32x4 Lanczos2(FfxFloat32x4 fColor0, FfxFloat32x4 fColor1, FfxFloat32x4 fColor2, FfxFloat32x4 fColor3, FfxFloat32 t) +{ + FfxFloat32 fWeight0 = Lanczos2(-1.f - t); + FfxFloat32 fWeight1 = Lanczos2(-0.f - t); + FfxFloat32 fWeight2 = Lanczos2(+1.f - t); + FfxFloat32 fWeight3 = Lanczos2(+2.f - t); + return (fWeight0 * fColor0 + fWeight1 * fColor1 + fWeight2 * fColor2 + fWeight3 * fColor3) / (fWeight0 + fWeight1 + fWeight2 + fWeight3); +} + +FfxFloat32x4 Lanczos2(FetchedBicubicSamples Samples, FfxFloat32x2 fPxFrac) +{ + FfxFloat32x4 fColorX0 = Lanczos2(Samples.fColor00, Samples.fColor10, Samples.fColor20, Samples.fColor30, fPxFrac.x); + FfxFloat32x4 fColorX1 = Lanczos2(Samples.fColor01, Samples.fColor11, Samples.fColor21, Samples.fColor31, fPxFrac.x); + FfxFloat32x4 fColorX2 = Lanczos2(Samples.fColor02, Samples.fColor12, Samples.fColor22, Samples.fColor32, fPxFrac.x); + FfxFloat32x4 fColorX3 = Lanczos2(Samples.fColor03, Samples.fColor13, Samples.fColor23, Samples.fColor33, fPxFrac.x); + FfxFloat32x4 fColorXY = Lanczos2(fColorX0, fColorX1, fColorX2, fColorX3, fPxFrac.y); + + // Deringing + + // TODO: only use 4 by checking jitter + const FfxInt32 iDeringingSampleCount = 4; + const FfxFloat32x4 fDeringingSamples[4] = { + Samples.fColor11, + Samples.fColor21, + Samples.fColor12, + Samples.fColor22, + }; + + FfxFloat32x4 fDeringingMin = fDeringingSamples[0]; + FfxFloat32x4 fDeringingMax = fDeringingSamples[0]; + + FFX_UNROLL + for (FfxInt32 iSampleIndex = 1; iSampleIndex < iDeringingSampleCount; ++iSampleIndex) { + + fDeringingMin = ffxMin(fDeringingMin, fDeringingSamples[iSampleIndex]); + fDeringingMax = ffxMax(fDeringingMax, fDeringingSamples[iSampleIndex]); + } + + fColorXY = clamp(fColorXY, fDeringingMin, fDeringingMax); + + return fColorXY; +} + +#if FFX_HALF +FFX_MIN16_F4 Lanczos2(FFX_MIN16_F4 fColor0, FFX_MIN16_F4 fColor1, FFX_MIN16_F4 fColor2, FFX_MIN16_F4 fColor3, FFX_MIN16_F t) +{ + FFX_MIN16_F fWeight0 = Lanczos2(FFX_MIN16_F(-1.f) - t); + FFX_MIN16_F fWeight1 = Lanczos2(FFX_MIN16_F(-0.f) - t); + FFX_MIN16_F fWeight2 = Lanczos2(FFX_MIN16_F(+1.f) - t); + FFX_MIN16_F fWeight3 = Lanczos2(FFX_MIN16_F(+2.f) - t); + return (fWeight0 * fColor0 + fWeight1 * fColor1 + fWeight2 * fColor2 + fWeight3 * fColor3) / (fWeight0 + fWeight1 + fWeight2 + fWeight3); +} + +FFX_MIN16_F4 Lanczos2(FetchedBicubicSamplesMin16 Samples, FFX_MIN16_F2 fPxFrac) +{ + FFX_MIN16_F4 fColorX0 = Lanczos2(Samples.fColor00, Samples.fColor10, Samples.fColor20, Samples.fColor30, fPxFrac.x); + FFX_MIN16_F4 fColorX1 = Lanczos2(Samples.fColor01, Samples.fColor11, Samples.fColor21, Samples.fColor31, fPxFrac.x); + FFX_MIN16_F4 fColorX2 = Lanczos2(Samples.fColor02, Samples.fColor12, Samples.fColor22, Samples.fColor32, fPxFrac.x); + FFX_MIN16_F4 fColorX3 = Lanczos2(Samples.fColor03, Samples.fColor13, Samples.fColor23, Samples.fColor33, fPxFrac.x); + FFX_MIN16_F4 fColorXY = Lanczos2(fColorX0, fColorX1, fColorX2, fColorX3, fPxFrac.y); + + // Deringing + + // TODO: only use 4 by checking jitter + const FfxInt32 iDeringingSampleCount = 4; + const FFX_MIN16_F4 fDeringingSamples[4] = { + Samples.fColor11, + Samples.fColor21, + Samples.fColor12, + Samples.fColor22, + }; + + FFX_MIN16_F4 fDeringingMin = fDeringingSamples[0]; + FFX_MIN16_F4 fDeringingMax = fDeringingSamples[0]; + + FFX_UNROLL + for (FfxInt32 iSampleIndex = 1; iSampleIndex < iDeringingSampleCount; ++iSampleIndex) + { + fDeringingMin = ffxMin(fDeringingMin, fDeringingSamples[iSampleIndex]); + fDeringingMax = ffxMax(fDeringingMax, fDeringingSamples[iSampleIndex]); + } + + fColorXY = clamp(fColorXY, fDeringingMin, fDeringingMax); + + return fColorXY; +} +#endif //FFX_HALF + + +FfxFloat32x4 Lanczos2LUT(FetchedBicubicSamples Samples, FfxFloat32x2 fPxFrac) +{ + FfxFloat32x4 fColorX0 = Lanczos2_UseLUT(Samples.fColor00, Samples.fColor10, Samples.fColor20, Samples.fColor30, fPxFrac.x); + FfxFloat32x4 fColorX1 = Lanczos2_UseLUT(Samples.fColor01, Samples.fColor11, Samples.fColor21, Samples.fColor31, fPxFrac.x); + FfxFloat32x4 fColorX2 = Lanczos2_UseLUT(Samples.fColor02, Samples.fColor12, Samples.fColor22, Samples.fColor32, fPxFrac.x); + FfxFloat32x4 fColorX3 = Lanczos2_UseLUT(Samples.fColor03, Samples.fColor13, Samples.fColor23, Samples.fColor33, fPxFrac.x); + FfxFloat32x4 fColorXY = Lanczos2_UseLUT(fColorX0, fColorX1, fColorX2, fColorX3, fPxFrac.y); + + // Deringing + + // TODO: only use 4 by checking jitter + const FfxInt32 iDeringingSampleCount = 4; + const FfxFloat32x4 fDeringingSamples[4] = { + Samples.fColor11, + Samples.fColor21, + Samples.fColor12, + Samples.fColor22, + }; + + FfxFloat32x4 fDeringingMin = fDeringingSamples[0]; + FfxFloat32x4 fDeringingMax = fDeringingSamples[0]; + + FFX_UNROLL + for (FfxInt32 iSampleIndex = 1; iSampleIndex < iDeringingSampleCount; ++iSampleIndex) { + + fDeringingMin = ffxMin(fDeringingMin, fDeringingSamples[iSampleIndex]); + fDeringingMax = ffxMax(fDeringingMax, fDeringingSamples[iSampleIndex]); + } + + fColorXY = clamp(fColorXY, fDeringingMin, fDeringingMax); + + return fColorXY; +} + +#if FFX_HALF +FFX_MIN16_F4 Lanczos2LUT(FetchedBicubicSamplesMin16 Samples, FFX_MIN16_F2 fPxFrac) +{ + FFX_MIN16_F4 fColorX0 = Lanczos2_UseLUT(Samples.fColor00, Samples.fColor10, Samples.fColor20, Samples.fColor30, fPxFrac.x); + FFX_MIN16_F4 fColorX1 = Lanczos2_UseLUT(Samples.fColor01, Samples.fColor11, Samples.fColor21, Samples.fColor31, fPxFrac.x); + FFX_MIN16_F4 fColorX2 = Lanczos2_UseLUT(Samples.fColor02, Samples.fColor12, Samples.fColor22, Samples.fColor32, fPxFrac.x); + FFX_MIN16_F4 fColorX3 = Lanczos2_UseLUT(Samples.fColor03, Samples.fColor13, Samples.fColor23, Samples.fColor33, fPxFrac.x); + FFX_MIN16_F4 fColorXY = Lanczos2_UseLUT(fColorX0, fColorX1, fColorX2, fColorX3, fPxFrac.y); + + // Deringing + + // TODO: only use 4 by checking jitter + const FfxInt32 iDeringingSampleCount = 4; + const FFX_MIN16_F4 fDeringingSamples[4] = { + Samples.fColor11, + Samples.fColor21, + Samples.fColor12, + Samples.fColor22, + }; + + FFX_MIN16_F4 fDeringingMin = fDeringingSamples[0]; + FFX_MIN16_F4 fDeringingMax = fDeringingSamples[0]; + + FFX_UNROLL + for (FfxInt32 iSampleIndex = 1; iSampleIndex < iDeringingSampleCount; ++iSampleIndex) + { + fDeringingMin = ffxMin(fDeringingMin, fDeringingSamples[iSampleIndex]); + fDeringingMax = ffxMax(fDeringingMax, fDeringingSamples[iSampleIndex]); + } + + fColorXY = clamp(fColorXY, fDeringingMin, fDeringingMax); + + return fColorXY; +} +#endif //FFX_HALF + + + +FfxFloat32x4 Lanczos2Approx(FfxFloat32x4 fColor0, FfxFloat32x4 fColor1, FfxFloat32x4 fColor2, FfxFloat32x4 fColor3, FfxFloat32 t) +{ + FfxFloat32 fWeight0 = Lanczos2ApproxNoClamp(-1.f - t); + FfxFloat32 fWeight1 = Lanczos2ApproxNoClamp(-0.f - t); + FfxFloat32 fWeight2 = Lanczos2ApproxNoClamp(+1.f - t); + FfxFloat32 fWeight3 = Lanczos2ApproxNoClamp(+2.f - t); + return (fWeight0 * fColor0 + fWeight1 * fColor1 + fWeight2 * fColor2 + fWeight3 * fColor3) / (fWeight0 + fWeight1 + fWeight2 + fWeight3); +} + +#if FFX_HALF +FFX_MIN16_F4 Lanczos2Approx(FFX_MIN16_F4 fColor0, FFX_MIN16_F4 fColor1, FFX_MIN16_F4 fColor2, FFX_MIN16_F4 fColor3, FFX_MIN16_F t) +{ + FFX_MIN16_F fWeight0 = Lanczos2ApproxNoClamp(FFX_MIN16_F(-1.f) - t); + FFX_MIN16_F fWeight1 = Lanczos2ApproxNoClamp(FFX_MIN16_F(-0.f) - t); + FFX_MIN16_F fWeight2 = Lanczos2ApproxNoClamp(FFX_MIN16_F(+1.f) - t); + FFX_MIN16_F fWeight3 = Lanczos2ApproxNoClamp(FFX_MIN16_F(+2.f) - t); + return (fWeight0 * fColor0 + fWeight1 * fColor1 + fWeight2 * fColor2 + fWeight3 * fColor3) / (fWeight0 + fWeight1 + fWeight2 + fWeight3); +} +#endif //FFX_HALF + +FfxFloat32x4 Lanczos2Approx(FetchedBicubicSamples Samples, FfxFloat32x2 fPxFrac) +{ + FfxFloat32x4 fColorX0 = Lanczos2Approx(Samples.fColor00, Samples.fColor10, Samples.fColor20, Samples.fColor30, fPxFrac.x); + FfxFloat32x4 fColorX1 = Lanczos2Approx(Samples.fColor01, Samples.fColor11, Samples.fColor21, Samples.fColor31, fPxFrac.x); + FfxFloat32x4 fColorX2 = Lanczos2Approx(Samples.fColor02, Samples.fColor12, Samples.fColor22, Samples.fColor32, fPxFrac.x); + FfxFloat32x4 fColorX3 = Lanczos2Approx(Samples.fColor03, Samples.fColor13, Samples.fColor23, Samples.fColor33, fPxFrac.x); + FfxFloat32x4 fColorXY = Lanczos2Approx(fColorX0, fColorX1, fColorX2, fColorX3, fPxFrac.y); + + // Deringing + + // TODO: only use 4 by checking jitter + const FfxInt32 iDeringingSampleCount = 4; + const FfxFloat32x4 fDeringingSamples[4] = { + Samples.fColor11, + Samples.fColor21, + Samples.fColor12, + Samples.fColor22, + }; + + FfxFloat32x4 fDeringingMin = fDeringingSamples[0]; + FfxFloat32x4 fDeringingMax = fDeringingSamples[0]; + + FFX_UNROLL + for (FfxInt32 iSampleIndex = 1; iSampleIndex < iDeringingSampleCount; ++iSampleIndex) + { + fDeringingMin = ffxMin(fDeringingMin, fDeringingSamples[iSampleIndex]); + fDeringingMax = ffxMax(fDeringingMax, fDeringingSamples[iSampleIndex]); + } + + fColorXY = clamp(fColorXY, fDeringingMin, fDeringingMax); + + return fColorXY; +} + +#if FFX_HALF +FFX_MIN16_F4 Lanczos2Approx(FetchedBicubicSamplesMin16 Samples, FFX_MIN16_F2 fPxFrac) +{ + FFX_MIN16_F4 fColorX0 = Lanczos2Approx(Samples.fColor00, Samples.fColor10, Samples.fColor20, Samples.fColor30, fPxFrac.x); + FFX_MIN16_F4 fColorX1 = Lanczos2Approx(Samples.fColor01, Samples.fColor11, Samples.fColor21, Samples.fColor31, fPxFrac.x); + FFX_MIN16_F4 fColorX2 = Lanczos2Approx(Samples.fColor02, Samples.fColor12, Samples.fColor22, Samples.fColor32, fPxFrac.x); + FFX_MIN16_F4 fColorX3 = Lanczos2Approx(Samples.fColor03, Samples.fColor13, Samples.fColor23, Samples.fColor33, fPxFrac.x); + FFX_MIN16_F4 fColorXY = Lanczos2Approx(fColorX0, fColorX1, fColorX2, fColorX3, fPxFrac.y); + + // Deringing + + // TODO: only use 4 by checking jitter + const FfxInt32 iDeringingSampleCount = 4; + const FFX_MIN16_F4 fDeringingSamples[4] = { + Samples.fColor11, + Samples.fColor21, + Samples.fColor12, + Samples.fColor22, + }; + + FFX_MIN16_F4 fDeringingMin = fDeringingSamples[0]; + FFX_MIN16_F4 fDeringingMax = fDeringingSamples[0]; + + FFX_UNROLL + for (FfxInt32 iSampleIndex = 1; iSampleIndex < iDeringingSampleCount; ++iSampleIndex) + { + fDeringingMin = ffxMin(fDeringingMin, fDeringingSamples[iSampleIndex]); + fDeringingMax = ffxMax(fDeringingMax, fDeringingSamples[iSampleIndex]); + } + + fColorXY = clamp(fColorXY, fDeringingMin, fDeringingMax); + + return fColorXY; +} +#endif + +// Clamp by offset direction. Assuming iPxSample is already in range and iPxOffset is compile time constant. +FfxInt32x2 ClampCoord(FfxInt32x2 iPxSample, FfxInt32x2 iPxOffset, FfxInt32x2 iTextureSize) +{ + FfxInt32x2 result = iPxSample + iPxOffset; + result.x = (iPxOffset.x < 0) ? ffxMax(result.x, 0) : result.x; + result.x = (iPxOffset.x > 0) ? ffxMin(result.x, iTextureSize.x - 1) : result.x; + result.y = (iPxOffset.y < 0) ? ffxMax(result.y, 0) : result.y; + result.y = (iPxOffset.y > 0) ? ffxMin(result.y, iTextureSize.y - 1) : result.y; + return result; +} +#if FFX_HALF +FFX_MIN16_I2 ClampCoord(FFX_MIN16_I2 iPxSample, FFX_MIN16_I2 iPxOffset, FFX_MIN16_I2 iTextureSize) +{ + FFX_MIN16_I2 result = iPxSample + iPxOffset; + result.x = (iPxOffset.x < FFX_MIN16_I(0)) ? ffxMax(result.x, FFX_MIN16_I(0)) : result.x; + result.x = (iPxOffset.x > FFX_MIN16_I(0)) ? ffxMin(result.x, iTextureSize.x - FFX_MIN16_I(1)) : result.x; + result.y = (iPxOffset.y < FFX_MIN16_I(0)) ? ffxMax(result.y, FFX_MIN16_I(0)) : result.y; + result.y = (iPxOffset.y > FFX_MIN16_I(0)) ? ffxMin(result.y, iTextureSize.y - FFX_MIN16_I(1)) : result.y; + return result; +} +#endif //FFX_HALF + + +#define DeclareCustomFetchBicubicSamplesWithType(SampleType, TextureType, AddrType, Name, LoadTexture) \ + SampleType Name(AddrType iPxSample, AddrType iTextureSize) \ + { \ + SampleType Samples; \ + \ + Samples.fColor00 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(-1, -1), iTextureSize))); \ + Samples.fColor10 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+0, -1), iTextureSize))); \ + Samples.fColor20 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+1, -1), iTextureSize))); \ + Samples.fColor30 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+2, -1), iTextureSize))); \ + \ + Samples.fColor01 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(-1, +0), iTextureSize))); \ + Samples.fColor11 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+0, +0), iTextureSize))); \ + Samples.fColor21 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+1, +0), iTextureSize))); \ + Samples.fColor31 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+2, +0), iTextureSize))); \ + \ + Samples.fColor02 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(-1, +1), iTextureSize))); \ + Samples.fColor12 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+0, +1), iTextureSize))); \ + Samples.fColor22 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+1, +1), iTextureSize))); \ + Samples.fColor32 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+2, +1), iTextureSize))); \ + \ + Samples.fColor03 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(-1, +2), iTextureSize))); \ + Samples.fColor13 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+0, +2), iTextureSize))); \ + Samples.fColor23 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+1, +2), iTextureSize))); \ + Samples.fColor33 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+2, +2), iTextureSize))); \ + \ + return Samples; \ + } + +#define DeclareCustomFetchBicubicSamples(Name, LoadTexture) \ + DeclareCustomFetchBicubicSamplesWithType(FetchedBicubicSamples, FfxFloat32x4, FfxInt32x2, Name, LoadTexture) + +#define DeclareCustomFetchBicubicSamplesMin16(Name, LoadTexture) \ + DeclareCustomFetchBicubicSamplesWithType(FetchedBicubicSamplesMin16, FFX_MIN16_F4, FfxInt32x2, Name, LoadTexture) + +#define DeclareCustomFetchBilinearSamplesWithType(SampleType, TextureType,AddrType, Name, LoadTexture) \ + SampleType Name(AddrType iPxSample, AddrType iTextureSize) \ + { \ + SampleType Samples; \ + Samples.fColor00 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+0, +0), iTextureSize))); \ + Samples.fColor10 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+1, +0), iTextureSize))); \ + Samples.fColor01 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+0, +1), iTextureSize))); \ + Samples.fColor11 = TextureType(LoadTexture(ClampCoord(iPxSample, AddrType(+1, +1), iTextureSize))); \ + return Samples; \ + } + +#define DeclareCustomFetchBilinearSamples(Name, LoadTexture) \ + DeclareCustomFetchBilinearSamplesWithType(FetchedBilinearSamples, FfxFloat32x4, FfxInt32x2, Name, LoadTexture) + +#define DeclareCustomFetchBilinearSamplesMin16(Name, LoadTexture) \ + DeclareCustomFetchBilinearSamplesWithType(FetchedBilinearSamplesMin16, FFX_MIN16_F4, FfxInt32x2, Name, LoadTexture) + +// BE CAREFUL: there is some precision issues and (3253, 125) leading to (3252.9989778, 125.001102) +// is common, so iPxSample can "jitter" +#define DeclareCustomTextureSample(Name, InterpolateSamples, FetchSamples) \ + FfxFloat32x4 Name(FfxFloat32x2 fUvSample, FfxInt32x2 iTextureSize) \ + { \ + FfxFloat32x2 fPxSample = (fUvSample * FfxFloat32x2(iTextureSize)) - FfxFloat32x2(0.5f, 0.5f); \ + /* Clamp base coords */ \ + fPxSample.x = ffxMax(0.0f, ffxMin(FfxFloat32(iTextureSize.x), fPxSample.x)); \ + fPxSample.y = ffxMax(0.0f, ffxMin(FfxFloat32(iTextureSize.y), fPxSample.y)); \ + /* */ \ + FfxInt32x2 iPxSample = FfxInt32x2(floor(fPxSample)); \ + FfxFloat32x2 fPxFrac = ffxFract(fPxSample); \ + FfxFloat32x4 fColorXY = FfxFloat32x4(InterpolateSamples(FetchSamples(iPxSample, iTextureSize), fPxFrac)); \ + return fColorXY; \ + } + +#define DeclareCustomTextureSampleMin16(Name, InterpolateSamples, FetchSamples) \ + FFX_MIN16_F4 Name(FfxFloat32x2 fUvSample, FfxInt32x2 iTextureSize) \ + { \ + FfxFloat32x2 fPxSample = (fUvSample * FfxFloat32x2(iTextureSize)) - FfxFloat32x2(0.5f, 0.5f); \ + /* Clamp base coords */ \ + fPxSample.x = ffxMax(0.0f, ffxMin(FfxFloat32(iTextureSize.x), fPxSample.x)); \ + fPxSample.y = ffxMax(0.0f, ffxMin(FfxFloat32(iTextureSize.y), fPxSample.y)); \ + /* */ \ + FfxInt32x2 iPxSample = FfxInt32x2(floor(fPxSample)); \ + FFX_MIN16_F2 fPxFrac = FFX_MIN16_F2(ffxFract(fPxSample)); \ + FFX_MIN16_F4 fColorXY = FFX_MIN16_F4(InterpolateSamples(FetchSamples(iPxSample, iTextureSize), fPxFrac)); \ + return fColorXY; \ + } + +#define FFX_FSR3UPSCALER_CONCAT_ID(x, y) x ## y +#define FFX_FSR3UPSCALER_CONCAT(x, y) FFX_FSR3UPSCALER_CONCAT_ID(x, y) +#define FFX_FSR3UPSCALER_SAMPLER_1D_0 Lanczos2 +#define FFX_FSR3UPSCALER_SAMPLER_1D_1 Lanczos2LUT +#define FFX_FSR3UPSCALER_SAMPLER_1D_2 Lanczos2Approx + +#define FFX_FSR3UPSCALER_GET_LANCZOS_SAMPLER1D(x) FFX_FSR3UPSCALER_CONCAT(FFX_FSR3UPSCALER_SAMPLER_1D_, x) + +#endif //!defined( FFX_FSR3UPSCALER_SAMPLE_H ) diff --git a/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_upsample.h b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_upsample.h new file mode 100644 index 00000000..47e7ccf5 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/fsr3upscaler/ffx_fsr3upscaler_upsample.h @@ -0,0 +1,195 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_FSR3UPSCALER_UPSAMPLE_H +#define FFX_FSR3UPSCALER_UPSAMPLE_H + +FFX_STATIC const FfxUInt32 iLanczos2SampleCount = 16; + +void Deringing(RectificationBox clippingBox, FFX_PARAMETER_INOUT FfxFloat32x3 fColor) +{ + fColor = clamp(fColor, clippingBox.aabbMin, clippingBox.aabbMax); +} +#if FFX_HALF +void Deringing(RectificationBoxMin16 clippingBox, FFX_PARAMETER_INOUT FFX_MIN16_F3 fColor) +{ + fColor = clamp(fColor, clippingBox.aabbMin, clippingBox.aabbMax); +} +#endif + +#ifndef FFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE +#define FFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE 2 // Approximate +#endif + +FfxFloat32 GetUpsampleLanczosWeight(FfxFloat32x2 fSrcSampleOffset, FfxFloat32 fKernelWeight) +{ + FfxFloat32x2 fSrcSampleOffsetBiased = fSrcSampleOffset * fKernelWeight.xx; +#if FFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE == 0 // LANCZOS_TYPE_REFERENCE + FfxFloat32 fSampleWeight = Lanczos2(length(fSrcSampleOffsetBiased)); +#elif FFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE == 1 // LANCZOS_TYPE_LUT + FfxFloat32 fSampleWeight = Lanczos2_UseLUT(length(fSrcSampleOffsetBiased)); +#elif FFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE == 2 // LANCZOS_TYPE_APPROXIMATE + FfxFloat32 fSampleWeight = Lanczos2ApproxSq(dot(fSrcSampleOffsetBiased, fSrcSampleOffsetBiased)); +#else +#error "Invalid Lanczos type" +#endif + return fSampleWeight; +} + +#if FFX_HALF +FFX_MIN16_F GetUpsampleLanczosWeight(FFX_MIN16_F2 fSrcSampleOffset, FFX_MIN16_F fKernelWeight) +{ + FFX_MIN16_F2 fSrcSampleOffsetBiased = fSrcSampleOffset * fKernelWeight.xx; +#if FFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE == 0 // LANCZOS_TYPE_REFERENCE + FFX_MIN16_F fSampleWeight = Lanczos2(length(fSrcSampleOffsetBiased)); +#elif FFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE == 1 // LANCZOS_TYPE_LUT + FFX_MIN16_F fSampleWeight = Lanczos2_UseLUT(length(fSrcSampleOffsetBiased)); +#elif FFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE == 2 // LANCZOS_TYPE_APPROXIMATE + FFX_MIN16_F fSampleWeight = Lanczos2ApproxSq(dot(fSrcSampleOffsetBiased, fSrcSampleOffsetBiased)); + + // To Test: Save reciproqual sqrt compute + // FfxFloat32 fSampleWeight = Lanczos2Sq_UseLUT(dot(fSrcSampleOffsetBiased, fSrcSampleOffsetBiased)); +#else +#error "Invalid Lanczos type" +#endif + return fSampleWeight; +} +#endif + +FfxFloat32 ComputeMaxKernelWeight() { + const FfxFloat32 fKernelSizeBias = 1.0f; + + FfxFloat32 fKernelWeight = FfxFloat32(1) + (FfxFloat32(1.0f) / FfxFloat32x2(DownscaleFactor()) - FfxFloat32(1)).x * FfxFloat32(fKernelSizeBias); + + return ffxMin(FfxFloat32(1.99f), fKernelWeight); +} + +FfxFloat32x4 ComputeUpsampledColorAndWeight(const AccumulationPassCommonParams params, + FFX_PARAMETER_INOUT RectificationBox clippingBox, FfxFloat32 fReactiveFactor) +{ + #if FFX_FSR3UPSCALER_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF && FFX_HALF + #include "ffx_fsr3upscaler_force16_begin.h" + #endif + // We compute a sliced lanczos filter with 2 lobes (other slices are accumulated temporaly) + FfxFloat32x2 fDstOutputPos = FfxFloat32x2(params.iPxHrPos) + FFX_BROADCAST_FLOAT32X2(0.5f); // Destination resolution output pixel center position + FfxFloat32x2 fSrcOutputPos = fDstOutputPos * DownscaleFactor(); // Source resolution output pixel center position + FfxInt32x2 iSrcInputPos = FfxInt32x2(floor(fSrcOutputPos)); // TODO: what about weird upscale factors... + + #if FFX_FSR3UPSCALER_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF && FFX_HALF + #include "ffx_fsr3upscaler_force16_end.h" + #endif + + FfxFloat32x3 fSamples[iLanczos2SampleCount]; + + FfxFloat32x2 fSrcUnjitteredPos = (FfxFloat32x2(iSrcInputPos) + FfxFloat32x2(0.5f, 0.5f)) - Jitter(); // This is the un-jittered position of the sample at offset 0,0 + + FfxInt32x2 offsetTL; + offsetTL.x = (fSrcUnjitteredPos.x > fSrcOutputPos.x) ? FfxInt32(-2) : FfxInt32(-1); + offsetTL.y = (fSrcUnjitteredPos.y > fSrcOutputPos.y) ? FfxInt32(-2) : FfxInt32(-1); + + //Load samples + // If fSrcUnjitteredPos.y > fSrcOutputPos.y, indicates offsetTL.y = -2, sample offset Y will be [-2, 1], clipbox will be rows [1, 3]. + // Flip row# for sampling offset in this case, so first 0~2 rows in the sampled array can always be used for computing the clipbox. + // This reduces branch or cmove on sampled colors, but moving this overhead to sample position / weight calculation time which apply to less values. + const FfxBoolean bFlipRow = fSrcUnjitteredPos.y > fSrcOutputPos.y; + const FfxBoolean bFlipCol = fSrcUnjitteredPos.x > fSrcOutputPos.x; + + FfxFloat32x2 fOffsetTL = FfxFloat32x2(offsetTL); + + FFX_UNROLL + for (FfxInt32 row = 0; row < 3; row++) { + + FFX_UNROLL + for (FfxInt32 col = 0; col < 3; col++) { + FfxInt32 iSampleIndex = col + (row << 2); + + FfxInt32x2 sampleColRow = FfxInt32x2(bFlipCol ? (3 - col) : col, bFlipRow ? (3 - row) : row); + FfxInt32x2 iSrcSamplePos = FfxInt32x2(iSrcInputPos) + offsetTL + sampleColRow; + + const FfxInt32x2 sampleCoord = ClampLoad(iSrcSamplePos, FfxInt32x2(0, 0), FfxInt32x2(RenderSize())); + + fSamples[iSampleIndex] = LoadPreparedInputColor(FfxInt32x2(sampleCoord)); + } + } + + FfxFloat32x4 fColorAndWeight = FfxFloat32x4(0.0f, 0.0f, 0.0f, 0.0f); + + FfxFloat32x2 fBaseSampleOffset = FfxFloat32x2(fSrcUnjitteredPos - fSrcOutputPos); + + // Identify how much of each upsampled color to be used for this frame + const FfxFloat32 fKernelReactiveFactor = ffxMax(fReactiveFactor, FfxFloat32(params.bIsNewSample)); + const FfxFloat32 fKernelBiasMax = ComputeMaxKernelWeight() * (1.0f - fKernelReactiveFactor); + + const FfxFloat32 fKernelBiasMin = ffxMax(1.0f, ((1.0f + fKernelBiasMax) * 0.3f)); + const FfxFloat32 fKernelBiasFactor = ffxMax(0.0f, ffxMax(0.25f * params.fDepthClipFactor, fKernelReactiveFactor)); + const FfxFloat32 fKernelBias = ffxLerp(fKernelBiasMax, fKernelBiasMin, fKernelBiasFactor); + + const FfxFloat32 fRectificationCurveBias = ffxLerp(-2.0f, -3.0f, ffxSaturate(params.fHrVelocity / 50.0f)); + + FFX_UNROLL + for (FfxInt32 row = 0; row < 3; row++) { + FFX_UNROLL + for (FfxInt32 col = 0; col < 3; col++) { + FfxInt32 iSampleIndex = col + (row << 2); + + const FfxInt32x2 sampleColRow = FfxInt32x2(bFlipCol ? (3 - col) : col, bFlipRow ? (3 - row) : row); + const FfxFloat32x2 fOffset = fOffsetTL + FfxFloat32x2(sampleColRow); + FfxFloat32x2 fSrcSampleOffset = fBaseSampleOffset + fOffset; + + FfxInt32x2 iSrcSamplePos = FfxInt32x2(iSrcInputPos) + FfxInt32x2(offsetTL) + sampleColRow; + + const FfxFloat32 fOnScreenFactor = FfxFloat32(IsOnScreen(FfxInt32x2(iSrcSamplePos), FfxInt32x2(RenderSize()))); + FfxFloat32 fSampleWeight = fOnScreenFactor * FfxFloat32(GetUpsampleLanczosWeight(fSrcSampleOffset, fKernelBias)); + + fColorAndWeight += FfxFloat32x4(fSamples[iSampleIndex] * fSampleWeight, fSampleWeight); + + // Update rectification box + { + const FfxFloat32 fSrcSampleOffsetSq = dot(fSrcSampleOffset, fSrcSampleOffset); + const FfxFloat32 fBoxSampleWeight = exp(fRectificationCurveBias * fSrcSampleOffsetSq); + + const FfxBoolean bInitialSample = (row == 0) && (col == 0); + RectificationBoxAddSample(bInitialSample, clippingBox, fSamples[iSampleIndex], fBoxSampleWeight); + } + } + } + + RectificationBoxComputeVarianceBoxData(clippingBox); + + fColorAndWeight.w *= FfxFloat32(fColorAndWeight.w > FSR3UPSCALER_EPSILON); + + if (fColorAndWeight.w > FSR3UPSCALER_EPSILON) { + // Normalize for deringing (we need to compare colors) + fColorAndWeight.xyz = fColorAndWeight.xyz / fColorAndWeight.w; + fColorAndWeight.w *= fUpsampleLanczosWeightScale; + + Deringing(clippingBox, fColorAndWeight.xyz); + } + + #if FFX_FSR3UPSCALER_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF && FFX_HALF + #include "ffx_fsr3upscaler_force16_end.h" + #endif + + return fColorAndWeight; +} + +#endif //!defined( FFX_FSR3UPSCALER_UPSAMPLE_H ) diff --git a/sdk/include/FidelityFX/gpu/lens/ffx_lens.h b/sdk/include/FidelityFX/gpu/lens/ffx_lens.h index dba6a9b4..ddd2e8f9 100644 --- a/sdk/include/FidelityFX/gpu/lens/ffx_lens.h +++ b/sdk/include/FidelityFX/gpu/lens/ffx_lens.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup FfxGPULens FidelityFX Lens /// /// FidelityFX Lens GPU documentation /// diff --git a/sdk/include/FidelityFX/gpu/lens/ffx_lens_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/lens/ffx_lens_callbacks_glsl.h index 98942568..6e28a05d 100644 --- a/sdk/include/FidelityFX/gpu/lens/ffx_lens_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/lens/ffx_lens_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_lens_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/lens/ffx_lens_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/lens/ffx_lens_callbacks_hlsl.h index de35ee7b..26fab69e 100644 --- a/sdk/include/FidelityFX/gpu/lens/ffx_lens_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/lens/ffx_lens_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_lens_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/lens/ffx_lens_resources.h b/sdk/include/FidelityFX/gpu/lens/ffx_lens_resources.h index 16b18411..4ba4a58d 100644 --- a/sdk/include/FidelityFX/gpu/lens/ffx_lens_resources.h +++ b/sdk/include/FidelityFX/gpu/lens/ffx_lens_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_LENS_RESOURCES_H #define FFX_LENS_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/lpm/ffx_lpm.h b/sdk/include/FidelityFX/gpu/lpm/ffx_lpm.h index 7645d8d0..915042b6 100644 --- a/sdk/include/FidelityFX/gpu/lpm/ffx_lpm.h +++ b/sdk/include/FidelityFX/gpu/lpm/ffx_lpm.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup FfxGPULpm FidelityFX LPM /// FidelityFX Luma Preserving Mapper GPU documentation /// @@ -920,34 +920,34 @@ void LpmMapH(inout FfxFloat16x2 colorR, ratioB *= rcpMax; } - ratioR = min(max(FFX_BROADCAST_FLOAT16X2(softGap.x), ffxSaturate(ratioR * FFX_BROADCAST_FLOAT16X2(-softGap.x) + ratioR)), - ffxSaturate(FFX_BROADCAST_FLOAT16X2(softGap.x) * exp2(ratioR * FFX_BROADCAST_FLOAT16X2(softGap.y)))); - ratioG = min(max(FFX_BROADCAST_FLOAT16X2(softGap.x), ffxSaturate(ratioG * FFX_BROADCAST_FLOAT16X2(-softGap.x) + ratioG)), - ffxSaturate(FFX_BROADCAST_FLOAT16X2(softGap.x) * exp2(ratioG * FFX_BROADCAST_FLOAT16X2(softGap.y)))); - ratioB = min(max(FFX_BROADCAST_FLOAT16X2(softGap.x), ffxSaturate(ratioB * FFX_BROADCAST_FLOAT16X2(-softGap.x) + ratioB)), - ffxSaturate(FFX_BROADCAST_FLOAT16X2(softGap.x) * exp2(ratioB * FFX_BROADCAST_FLOAT16X2(softGap.y)))); + ratioR = FfxFloat16x2(min(max(FFX_BROADCAST_FLOAT16X2(softGap.x), ffxSaturate(ratioR * FFX_BROADCAST_FLOAT16X2(-softGap.x) + ratioR)), + ffxSaturate(FFX_BROADCAST_FLOAT16X2(softGap.x) * exp2(ratioR * FFX_BROADCAST_FLOAT16X2(softGap.y))))); + ratioG = FfxFloat16x2(min(max(FFX_BROADCAST_FLOAT16X2(softGap.x), ffxSaturate(ratioG * FFX_BROADCAST_FLOAT16X2(-softGap.x) + ratioG)), + ffxSaturate(FFX_BROADCAST_FLOAT16X2(softGap.x) * exp2(ratioG * FFX_BROADCAST_FLOAT16X2(softGap.y))))); + ratioB = FfxFloat16x2(min(max(FFX_BROADCAST_FLOAT16X2(softGap.x), ffxSaturate(ratioB * FFX_BROADCAST_FLOAT16X2(-softGap.x) + ratioB)), + ffxSaturate(FFX_BROADCAST_FLOAT16X2(softGap.x) * exp2(ratioB * FFX_BROADCAST_FLOAT16X2(softGap.y))))); } FfxFloat16x2 lumaRatio = ratioR * FFX_BROADCAST_FLOAT16X2(lumaT.r) + ratioG * FFX_BROADCAST_FLOAT16X2(lumaT.g) + ratioB * FFX_BROADCAST_FLOAT16X2(lumaT.b); - FfxFloat16x2 ratioScale = ffxSaturate(luma * ffxReciprocalHalf(lumaRatio)); - colorR = ffxSaturate(ratioR * ratioScale); - colorG = ffxSaturate(ratioG * ratioScale); - colorB = ffxSaturate(ratioB * ratioScale); + FfxFloat16x2 ratioScale = FfxFloat16x2(ffxSaturate(luma * ffxReciprocalHalf(lumaRatio))); + colorR = FfxFloat16x2(ffxSaturate(ratioR * ratioScale)); + colorG = FfxFloat16x2(ffxSaturate(ratioG * ratioScale)); + colorB = FfxFloat16x2(ffxSaturate(ratioB * ratioScale)); FfxFloat16x2 capR = FFX_BROADCAST_FLOAT16X2(-crosstalk.r) * colorR + FFX_BROADCAST_FLOAT16X2(crosstalk.r); FfxFloat16x2 capG = FFX_BROADCAST_FLOAT16X2(-crosstalk.g) * colorG + FFX_BROADCAST_FLOAT16X2(crosstalk.g); FfxFloat16x2 capB = FFX_BROADCAST_FLOAT16X2(-crosstalk.b) * colorB + FFX_BROADCAST_FLOAT16X2(crosstalk.b); - FfxFloat16x2 lumaAdd = ffxSaturate((-colorB) * FFX_BROADCAST_FLOAT16X2(lumaT.b) + - ((-colorR) * FFX_BROADCAST_FLOAT16X2(lumaT.r) + ((-colorG) * FFX_BROADCAST_FLOAT16X2(lumaT.g) + luma))); + FfxFloat16x2 lumaAdd = FfxFloat16x2(ffxSaturate((-colorB) * FFX_BROADCAST_FLOAT16X2(lumaT.b) + + ((-colorR) * FFX_BROADCAST_FLOAT16X2(lumaT.r) + ((-colorG) * FFX_BROADCAST_FLOAT16X2(lumaT.g) + luma)))); FfxFloat16x2 t = lumaAdd * ffxReciprocalHalf(capG * FFX_BROADCAST_FLOAT16X2(lumaT.g) + (capR * FFX_BROADCAST_FLOAT16X2(lumaT.r) + (capB * FFX_BROADCAST_FLOAT16X2(lumaT.b)))); - colorR = ffxSaturate(t * capR + colorR); - colorG = ffxSaturate(t * capG + colorG); - colorB = ffxSaturate(t * capB + colorB); - lumaAdd = ffxSaturate((-colorB) * FFX_BROADCAST_FLOAT16X2(lumaT.b) + - ((-colorR) * FFX_BROADCAST_FLOAT16X2(lumaT.r) + ((-colorG) * FFX_BROADCAST_FLOAT16X2(lumaT.g) + luma))); - colorR = ffxSaturate(lumaAdd * FFX_BROADCAST_FLOAT16X2(rcpLumaT.r) + colorR); - colorG = ffxSaturate(lumaAdd * FFX_BROADCAST_FLOAT16X2(rcpLumaT.g) + colorG); - colorB = ffxSaturate(lumaAdd * FFX_BROADCAST_FLOAT16X2(rcpLumaT.b) + colorB); + colorR = FfxFloat16x2(ffxSaturate(t * capR + colorR)); + colorG = FfxFloat16x2(ffxSaturate(t * capG + colorG)); + colorB = FfxFloat16x2(ffxSaturate(t * capB + colorB)); + lumaAdd = FfxFloat16x2(ffxSaturate((-colorB) * FFX_BROADCAST_FLOAT16X2(lumaT.b) + + ((-colorR) * FFX_BROADCAST_FLOAT16X2(lumaT.r) + ((-colorG) * FFX_BROADCAST_FLOAT16X2(lumaT.g) + luma)))); + colorR = FfxFloat16x2(ffxSaturate(lumaAdd * FFX_BROADCAST_FLOAT16X2(rcpLumaT.r) + colorR)); + colorG = FfxFloat16x2(ffxSaturate(lumaAdd * FFX_BROADCAST_FLOAT16X2(rcpLumaT.g) + colorG)); + colorB = FfxFloat16x2(ffxSaturate(lumaAdd * FFX_BROADCAST_FLOAT16X2(rcpLumaT.b) + colorB)); if (con2) { @@ -956,12 +956,12 @@ void LpmMapH(inout FfxFloat16x2 colorR, ratioB = colorB; if (clip) { - colorR = ffxSaturate(ratioR * FFX_BROADCAST_FLOAT16X2(con2R.r) + - (ratioG * FFX_BROADCAST_FLOAT16X2(con2R.g) + (ratioB * FFX_BROADCAST_FLOAT16X2(con2R.b)))); - colorG = ffxSaturate(ratioG * FFX_BROADCAST_FLOAT16X2(con2G.g) + - (ratioR * FFX_BROADCAST_FLOAT16X2(con2G.r) + (ratioB * FFX_BROADCAST_FLOAT16X2(con2G.b)))); - colorB = ffxSaturate(ratioB * FFX_BROADCAST_FLOAT16X2(con2B.b) + - (ratioG * FFX_BROADCAST_FLOAT16X2(con2B.g) + (ratioR * FFX_BROADCAST_FLOAT16X2(con2B.r)))); + colorR = FfxFloat16x2(ffxSaturate(ratioR * FFX_BROADCAST_FLOAT16X2(con2R.r) + + (ratioG * FFX_BROADCAST_FLOAT16X2(con2R.g) + (ratioB * FFX_BROADCAST_FLOAT16X2(con2R.b))))); + colorG = FfxFloat16x2(ffxSaturate(ratioG * FFX_BROADCAST_FLOAT16X2(con2G.g) + + (ratioR * FFX_BROADCAST_FLOAT16X2(con2G.r) + (ratioB * FFX_BROADCAST_FLOAT16X2(con2G.b))))); + colorB = FfxFloat16x2(ffxSaturate(ratioB * FFX_BROADCAST_FLOAT16X2(con2B.b) + + (ratioG * FFX_BROADCAST_FLOAT16X2(con2B.g) + (ratioR * FFX_BROADCAST_FLOAT16X2(con2B.r))))); } else { diff --git a/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_callbacks_glsl.h index 577230d8..d1174c9a 100644 --- a/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_lpm_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_callbacks_hlsl.h index fffd2325..22e8b544 100644 --- a/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_lpm_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_filter.h b/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_filter.h index fdfb552e..526cdbbe 100644 --- a/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_filter.h +++ b/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_filter.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #define LPM_NO_SETUP 1 diff --git a/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_resources.h b/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_resources.h index 489d795a..afb6db64 100644 --- a/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_resources.h +++ b/sdk/include/FidelityFX/gpu/lpm/ffx_lpm_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_LPM_RESOURCES_H #define FFX_LPM_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_callbacks_hlsl.h new file mode 100644 index 00000000..6963b46a --- /dev/null +++ b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_callbacks_hlsl.h @@ -0,0 +1,568 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_OPTICALFLOW_CALLBACKS_HLSL_H +#define FFX_OPTICALFLOW_CALLBACKS_HLSL_H + +#if defined(FFX_GPU) +#ifdef __hlsl_dx_compiler +#pragma dxc diagnostic push +#pragma dxc diagnostic ignored "-Wambig-lit-shift" +#endif //__hlsl_dx_compiler +#include "ffx_core.h" +#ifdef __hlsl_dx_compiler +#pragma dxc diagnostic pop +#endif //__hlsl_dx_compiler + +#define FFX_OPTICALFLOW_USE_MSAD4_INSTRUCTION 1 +#define FFX_OPTICALFLOW_FIX_TOP_LEFT_BIAS 1 +#define FFX_OPTICALFLOW_USE_HEURISTICS 1 +#define FFX_OPTICALFLOW_BLOCK_SIZE 8 +#define FFX_LOCAL_SEARCH_FALLBACK 1 + +// perf optimization for h/w not supporting accelerated msad4() +#if !defined(FFX_PREFER_WAVE64) && defined(FFX_OPTICALFLOW_USE_MSAD4_INSTRUCTION) +#undef FFX_OPTICALFLOW_USE_MSAD4_INSTRUCTION +#endif + +#include "opticalflow/ffx_opticalflow_common.h" + +#ifndef FFX_PREFER_WAVE64 +#define FFX_PREFER_WAVE64 +#endif + +#pragma warning(disable: 3205) // conversion from larger type to smaller + +#define DECLARE_SRV_REGISTER(regIndex) t##regIndex +#define DECLARE_UAV_REGISTER(regIndex) u##regIndex +#define DECLARE_CB_REGISTER(regIndex) b##regIndex +#define FFX_OPTICALFLOW_DECLARE_SRV(regIndex) register(DECLARE_SRV_REGISTER(regIndex)) +#define FFX_OPTICALFLOW_DECLARE_UAV(regIndex) register(DECLARE_UAV_REGISTER(regIndex)) +#define FFX_OPTICALFLOW_DECLARE_CB(regIndex) register(DECLARE_CB_REGISTER(regIndex)) + +#if defined(FFX_OPTICALFLOW_BIND_CB_COMMON) + cbuffer cbOF : FFX_OPTICALFLOW_DECLARE_CB(FFX_OPTICALFLOW_BIND_CB_COMMON) + { + FfxInt32x2 iInputLumaResolution; + FfxUInt32 uOpticalFlowPyramidLevel; + FfxUInt32 uOpticalFlowPyramidLevelCount; + + FfxUInt32 iFrameIndex; + FfxUInt32 backbufferTransferFunction; + FfxFloat32x2 minMaxLuminance; + }; +#define FFX_OPTICALFLOW_CONSTANT_BUFFER_1_SIZE 8 + +#endif //FFX_OPTICALFLOW_BIND_CB_COMMON + +#define FFX_OPTICALFLOW_DESCRIPTOR_COUNT 32 + +#define FFX_OPTICALFLOW_ROOTSIG_STRINGIFY(p) FFX_OPTICALFLOW_ROOTSIG_STR(p) +#define FFX_OPTICALFLOW_ROOTSIG_STR(p) #p +#define FFX_OPTICALFLOW_ROOTSIG [RootSignature( "DescriptorTable(UAV(u0, numDescriptors = " FFX_OPTICALFLOW_ROOTSIG_STRINGIFY(FFX_OPTICALFLOW_DESCRIPTOR_COUNT) ")), " \ + "DescriptorTable(SRV(t0, numDescriptors = " FFX_OPTICALFLOW_ROOTSIG_STRINGIFY(FFX_OPTICALFLOW_DESCRIPTOR_COUNT) ")), " \ + "RootConstants(num32BitConstants=" FFX_OPTICALFLOW_ROOTSIG_STRINGIFY(FFX_OPTICALFLOW_CONSTANT_BUFFER_1_SIZE) ", b0), " \ + "StaticSampler(s0, filter = FILTER_MIN_MAG_MIP_POINT, " \ + "addressU = TEXTURE_ADDRESS_CLAMP, " \ + "addressV = TEXTURE_ADDRESS_CLAMP, " \ + "addressW = TEXTURE_ADDRESS_CLAMP, " \ + "comparisonFunc = COMPARISON_NEVER, " \ + "borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK), " \ + "StaticSampler(s1, filter = FILTER_MIN_MAG_MIP_LINEAR, " \ + "addressU = TEXTURE_ADDRESS_CLAMP, " \ + "addressV = TEXTURE_ADDRESS_CLAMP, " \ + "addressW = TEXTURE_ADDRESS_CLAMP, " \ + "comparisonFunc = COMPARISON_NEVER, " \ + "borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK)" )] + +#define FFX_OPTICALFLOW_CONSTANT_BUFFER_2_SIZE 8 + +#define FFX_OPTICALFLOW_CB2_ROOTSIG [RootSignature( "DescriptorTable(UAV(u0, numDescriptors = " FFX_OPTICALFLOW_ROOTSIG_STRINGIFY(FFX_OPTICALFLOW_DESCRIPTOR_COUNT) ")), " \ + "DescriptorTable(SRV(t0, numDescriptors = " FFX_OPTICALFLOW_ROOTSIG_STRINGIFY(FFX_OPTICALFLOW_DESCRIPTOR_COUNT) ")), " \ + "RootConstants(num32BitConstants=" FFX_OPTICALFLOW_ROOTSIG_STRINGIFY(FFX_OPTICALFLOW_CONSTANT_BUFFER_2_SIZE) ", b0), " \ + "StaticSampler(s0, filter = FILTER_MIN_MAG_MIP_POINT, " \ + "addressU = TEXTURE_ADDRESS_CLAMP, " \ + "addressV = TEXTURE_ADDRESS_CLAMP, " \ + "addressW = TEXTURE_ADDRESS_CLAMP, " \ + "comparisonFunc = COMPARISON_NEVER, " \ + "borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK), " \ + "StaticSampler(s1, filter = FILTER_MIN_MAG_MIP_LINEAR, " \ + "addressU = TEXTURE_ADDRESS_CLAMP, " \ + "addressV = TEXTURE_ADDRESS_CLAMP, " \ + "addressW = TEXTURE_ADDRESS_CLAMP, " \ + "comparisonFunc = COMPARISON_NEVER, " \ + "borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK)" )] +#if defined(FFX_OPTICALFLOW_EMBED_ROOTSIG) +#define FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT FFX_OPTICALFLOW_ROOTSIG +#define FFX_OPTICALFLOW_EMBED_CB2_ROOTSIG_CONTENT FFX_OPTICALFLOW_CB2_ROOTSIG +#else +#define FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +#define FFX_OPTICALFLOW_EMBED_CB2_ROOTSIG_CONTENT +#endif // #if FFX_OPTICALFLOW_EMBED_ROOTSIG + +FfxInt32x2 DisplaySize() +{ + return iInputLumaResolution; +} + +FfxUInt32 FrameIndex() +{ + return iFrameIndex; +} + +FfxBoolean CrossedSceneChangeThreshold(FfxFloat32 sceneChangeValue) +{ + return sceneChangeValue > 0.45f; +} + +FfxUInt32 OpticalFlowPyramidLevel() +{ + return uOpticalFlowPyramidLevel; +} + +FfxUInt32 OpticalFlowPyramidLevelCount() +{ + return uOpticalFlowPyramidLevelCount; +} + +FfxInt32x2 OpticalFlowHistogramMaxVelocity() +{ + const FfxInt32 searchRadius = 8; + FfxInt32 scale = FfxInt32(1) << (OpticalFlowPyramidLevelCount() - 1 - OpticalFlowPyramidLevel()); + FfxInt32 maxVelocity = searchRadius * scale; + return FfxInt32x2(maxVelocity, maxVelocity); +} + + #if defined FFX_OPTICALFLOW_BIND_SRV_INPUT_COLOR + Texture2D r_input_color : FFX_OPTICALFLOW_DECLARE_SRV(FFX_OPTICALFLOW_BIND_SRV_INPUT_COLOR); + #endif + #if defined FFX_OPTICALFLOW_BIND_SRV_INPUT_MOTION_VECTORS + Texture2D r_input_motion_vectors : FFX_OPTICALFLOW_DECLARE_SRV(FFX_OPTICALFLOW_BIND_SRV_INPUT_MOTION_VECTORS); + #endif + #if defined FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_INPUT + Texture2D r_optical_flow_input : FFX_OPTICALFLOW_DECLARE_SRV(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_INPUT); + #endif + #if defined FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS_INPUT + Texture2D r_optical_flow_previous_input : FFX_OPTICALFLOW_DECLARE_SRV(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS_INPUT); + #endif + #if defined FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW + Texture2D r_optical_flow : FFX_OPTICALFLOW_DECLARE_SRV(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW); + #endif + #if defined FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS + Texture2D r_optical_flow_previous : FFX_OPTICALFLOW_DECLARE_SRV(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS); + #endif + #if defined FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_ADDITIONAL_INFO + Texture2D r_optical_flow_additional_info : FFX_OPTICALFLOW_DECLARE_SRV(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_ADDITIONAL_INFO); + #endif + #if defined FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_ADDITIONAL_INFO_PREVIOUS + Texture2D r_optical_flow_additional_info_previous : FFX_OPTICALFLOW_DECLARE_SRV(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_ADDITIONAL_INFO_PREVIOUS); + #endif + #if defined FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_HISTOGRAM + Texture2D r_optical_flow_histogram : FFX_OPTICALFLOW_DECLARE_SRV(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_HISTOGRAM); + #endif + #if defined FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION_SEARCH + Texture2D r_optical_flow_global_motion_search : FFX_OPTICALFLOW_DECLARE_SRV(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION_SEARCH); + #endif + + // UAV declarations + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT + RWTexture2D rw_optical_flow_input : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_1 + globallycoherent RWTexture2D rw_optical_flow_input_level_1 : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_1); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_2 + globallycoherent RWTexture2D rw_optical_flow_input_level_2 : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_2); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_3 + globallycoherent RWTexture2D rw_optical_flow_input_level_3 : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_3); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_4 + globallycoherent RWTexture2D rw_optical_flow_input_level_4 : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_4); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_5 + globallycoherent RWTexture2D rw_optical_flow_input_level_5 : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_5); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_6 + globallycoherent RWTexture2D rw_optical_flow_input_level_6 : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_6); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW + RWTexture2D rw_optical_flow : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_NEXT_LEVEL + RWTexture2D rw_optical_flow_next_level : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_NEXT_LEVEL); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_ADDITIONAL_INFO + RWTexture2D rw_optical_flow_additional_info : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_ADDITIONAL_INFO); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_ADDITIONAL_INFO_NEXT_LEVEL + RWTexture2D rw_optical_flow_additional_info_next_level : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_ADDITIONAL_INFO_NEXT_LEVEL); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_HISTOGRAM + RWTexture2D rw_optical_flow_histogram : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_HISTOGRAM); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_GLOBAL_MOTION_SEARCH + globallycoherent RWTexture2D rw_optical_flow_global_motion_search: FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_GLOBAL_MOTION_SEARCH); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_HISTOGRAM + RWTexture2D rw_optical_flow_scd_histogram : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_HISTOGRAM); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM + RWTexture2D rw_optical_flow_scd_previous_histogram : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_TEMP + RWTexture2D rw_optical_flow_scd_temp : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_TEMP); + #endif + #if defined FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT + RWTexture2D rw_optical_flow_scd_output : FFX_OPTICALFLOW_DECLARE_UAV(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT); + #endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_INPUT_COLOR) +FfxFloat32x4 LoadInputColor(FfxUInt32x2 iPxHistory) +{ + return r_input_color[iPxHistory]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_INPUT_MOTION_VECTORS) +FfxFloat32x2 LoadGameMotionVector(FfxInt32x2 iPxPos) +{ + FfxFloat32x2 positionScale = FfxFloat32x2(RenderSize()) / DisplaySize(); + return r_input_motion_vectors[iPxPos * positionScale] * motionVectorScale / positionScale; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT) +void StoreOpticalFlowInput(FfxInt32x2 iPxPos, FfxUInt32 fLuma) +{ + rw_optical_flow_input[iPxPos] = fLuma; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_INPUT) +FfxUInt32 LoadOpticalFlowInput(FfxInt32x2 iPxPos) +{ +#if FFX_OPTICALFLOW_USE_MSAD4_INSTRUCTION == 1 + return max(1, r_optical_flow_input[iPxPos]); +#else + return r_optical_flow_input[iPxPos]; +#endif +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT) +FfxUInt32 LoadRwOpticalFlowInput(FfxInt32x2 iPxPos) +{ + return rw_optical_flow_input[iPxPos]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS_INPUT) +FfxUInt32 LoadOpticalFlowPreviousInput(FfxInt32x2 iPxPos) +{ +#if FFX_OPTICALFLOW_USE_MSAD4_INSTRUCTION == 1 + return max(1, r_optical_flow_previous_input[iPxPos]); +#else + return r_optical_flow_previous_input[iPxPos]; +#endif +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW) +FfxInt32x2 LoadOpticalFlow(FfxInt32x2 iPxPos) +{ + return r_optical_flow[iPxPos]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW) +FfxInt32x2 LoadRwOpticalFlow(FfxInt32x2 iPxPos) +{ + return rw_optical_flow[iPxPos]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS) +FfxInt32x2 LoadPreviousOpticalFlow(FfxInt32x2 iPxPos) +{ + return r_optical_flow_previous[iPxPos]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW) +void StoreOpticalFlow(FfxInt32x2 iPxPos, FfxInt32x2 motionVector) +{ + rw_optical_flow[iPxPos] = motionVector; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_NEXT_LEVEL) +void StoreOpticalFlowNextLevel(FfxInt32x2 iPxPos, FfxInt32x2 motionVector) +{ + rw_optical_flow_next_level[iPxPos] = motionVector; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_ADDITIONAL_INFO) +FfxUInt32x2 LoadOpticalFlowAdditionalInfo(FfxInt32x2 iPxPos) +{ + return r_optical_flow_additional_info[iPxPos]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_ADDITIONAL_INFO) +FfxUInt32x2 LoadRwOpticalFlowAdditionalInfo(FfxInt32x2 iPxPos) +{ + return rw_optical_flow_additional_info[iPxPos]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_ADDITIONAL_INFO_PREVIOUS) +FfxUInt32x2 LoadPreviousOpticalFlowAdditionalInfo(FfxInt32x2 iPxPos) +{ + return r_optical_flow_additional_info_previous[iPxPos]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_ADDITIONAL_INFO) +void StoreOpticalFlowAdditionalInfo(FfxInt32x2 iPxPos, FfxUInt32x2 additionalInfo) +{ + rw_optical_flow_additional_info[iPxPos] = additionalInfo; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_ADDITIONAL_INFO_NEXT_LEVEL) +void StoreOpticalFlowNextLevelAdditionalInfo(FfxInt32x2 iPxPos, FfxUInt32x2 additionalInfo) +{ + rw_optical_flow_additional_info_next_level[iPxPos] = additionalInfo; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_HISTOGRAM) +FfxUInt32 LoadOpticalFlowHistogram(FfxInt32x2 iBucketId) +{ + return r_optical_flow_histogram[iBucketId]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_HISTOGRAM) +void AtomicIncrementOpticalFlowHistogram(FfxInt32x2 iBucketId) +{ + InterlockedAdd(rw_optical_flow_histogram[iBucketId], 1); +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION_SEARCH) +FfxInt32x2 LoadGlobalMotionVector() +{ + FfxInt32 vx = FfxInt32(r_optical_flow_global_motion_search[FfxInt32x2(0, 0)]); + FfxInt32 vy = FfxInt32(r_optical_flow_global_motion_search[FfxInt32x2(1, 0)]); + return FfxInt32x2(vx, vy); +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_GLOBAL_MOTION_SEARCH) +FfxInt32x2 LoadRwGlobalMotionVector() +{ + FfxInt32 vx = FfxInt32(rw_optical_flow_global_motion_search[FfxInt32x2(0, 0)]); + FfxInt32 vy = FfxInt32(rw_optical_flow_global_motion_search[FfxInt32x2(1, 0)]); + return FfxInt32x2(vx, vy); +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_GLOBAL_MOTION_SEARCH) +FfxUInt32 LoadGlobalMotionValue(FfxInt32 index) +{ + return rw_optical_flow_global_motion_search[FfxInt32x2(index, 0)]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_GLOBAL_MOTION_SEARCH) +void StoreGlobalMotionValue(FfxInt32 index, FfxUInt32 value) +{ + rw_optical_flow_global_motion_search[FfxInt32x2(index, 0)] = value; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_GLOBAL_MOTION_SEARCH) +FfxUInt32 AtomicIncrementGlobalMotionValue(FfxInt32 index) +{ + FfxUInt32 initialValue; + InterlockedAdd(rw_optical_flow_global_motion_search[FfxInt32x2(index, 0)], 1, initialValue); + return initialValue; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_HISTOGRAM) +FfxUInt32 LoadRwSCDHistogram(FfxInt32 iIndex) +{ + return rw_optical_flow_scd_histogram[FfxInt32x2(iIndex, 0)]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_HISTOGRAM) +void StoreSCDHistogram(FfxInt32 iIndex, FfxUInt32 value) +{ + rw_optical_flow_scd_histogram[FfxInt32x2(iIndex, 0)] = value; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_HISTOGRAM) +void AtomicIncrementSCDHistogram(FfxInt32 iIndex, FfxUInt32 valueToAdd) +{ + InterlockedAdd(rw_optical_flow_scd_histogram[FfxInt32x2(iIndex, 0)], valueToAdd); +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM) +FfxFloat32 LoadRwSCDPreviousHistogram(FfxInt32 iIndex) +{ + return rw_optical_flow_scd_previous_histogram[FfxInt32x2(iIndex, 0)]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM) +void StoreSCDPreviousHistogram(FfxInt32 iIndex, FfxFloat32 value) +{ + rw_optical_flow_scd_previous_histogram[FfxInt32x2(iIndex, 0)] = value; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_TEMP) +FfxUInt32 LoadRwSCDTemp(FfxInt32 iIndex) +{ + return rw_optical_flow_scd_temp[FfxInt32x2(iIndex, 0)]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_TEMP) +void AtomicIncrementSCDTemp(FfxInt32 iIndex, FfxUInt32 valueToAdd) +{ + InterlockedAdd(rw_optical_flow_scd_temp[FfxInt32x2(iIndex, 0)], valueToAdd); +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_TEMP) +void ResetSCDTemp() +{ + rw_optical_flow_scd_temp[FfxInt32x2(0, 0)] = 0; + rw_optical_flow_scd_temp[FfxInt32x2(1, 0)] = 0; + rw_optical_flow_scd_temp[FfxInt32x2(2, 0)] = 0; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT) +FfxUInt32 LoadRwSCDOutput(FfxInt32 iIndex) +{ + return rw_optical_flow_scd_output[FfxInt32x2(iIndex, 0)]; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT) +void StoreSCDOutput(FfxInt32 iIndex, FfxUInt32 value) +{ + rw_optical_flow_scd_output[FfxInt32x2(iIndex, 0)] = value; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT) +FfxUInt32 AtomicIncrementSCDOutput(FfxInt32 iIndex, FfxUInt32 valueToAdd) +{ + FfxUInt32 initialValue; + InterlockedAdd(rw_optical_flow_scd_output[FfxInt32x2(iIndex, 0)], valueToAdd, initialValue); + return initialValue; +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_DEBUG_VISUALIZATION) +void StoreDebugVisualization(FfxUInt32x2 iPxPos, FfxFloat32x3 fColor) +{ + rw_debug_visualization[iPxPos] = FfxFloat32x4(fColor, 1.f); +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT) +FfxFloat32 GetSceneChangeValue() +{ + if (FrameIndex() <= 5) + return 1.0; + else + return ffxAsFloat(LoadRwSCDOutput(SCD_OUTPUT_SCENE_CHANGE_SLOT)); +} + +FfxBoolean IsSceneChanged() +{ + if (FrameIndex() <= 5) + { + return 1.0; + } + else + { + return (LoadRwSCDOutput(SCD_OUTPUT_HISTORY_BITS_SLOT) & 0xfu) != 0; + } +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_INPUT) +FfxUInt32 LoadFirstImagePackedLuma(FfxInt32x2 iPxPos) +{ + const FfxInt32 lumaTextureWidth = DisplaySize().x >> OpticalFlowPyramidLevel(); + const FfxInt32 lumaTextureHeight = DisplaySize().y >> OpticalFlowPyramidLevel(); + + FfxInt32x2 adjustedPos = FfxInt32x2( + ffxClamp(iPxPos.x, 0, lumaTextureWidth - 4), + ffxClamp(iPxPos.y, 0, lumaTextureHeight - 1) + ); + + FfxUInt32 luma0 = LoadOpticalFlowInput(adjustedPos + FfxInt32x2(0, 0)); + FfxUInt32 luma1 = LoadOpticalFlowInput(adjustedPos + FfxInt32x2(1, 0)); + FfxUInt32 luma2 = LoadOpticalFlowInput(adjustedPos + FfxInt32x2(2, 0)); + FfxUInt32 luma3 = LoadOpticalFlowInput(adjustedPos + FfxInt32x2(3, 0)); + + return GetPackedLuma(lumaTextureWidth, iPxPos.x, luma0, luma1, luma2, luma3); +} +#endif + +#if defined(FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS_INPUT) +FfxUInt32 LoadSecondImagePackedLuma(FfxInt32x2 iPxPos) +{ + const FfxInt32 lumaTextureWidth = DisplaySize().x >> OpticalFlowPyramidLevel(); + const FfxInt32 lumaTextureHeight = DisplaySize().y >> OpticalFlowPyramidLevel(); + + FfxInt32x2 adjustedPos = FfxInt32x2( + ffxClamp(iPxPos.x, 0, lumaTextureWidth - 4), + ffxClamp(iPxPos.y, 0, lumaTextureHeight - 1) + ); + + FfxUInt32 luma0 = LoadOpticalFlowPreviousInput(adjustedPos + FfxInt32x2(0, 0)); + FfxUInt32 luma1 = LoadOpticalFlowPreviousInput(adjustedPos + FfxInt32x2(1, 0)); + FfxUInt32 luma2 = LoadOpticalFlowPreviousInput(adjustedPos + FfxInt32x2(2, 0)); + FfxUInt32 luma3 = LoadOpticalFlowPreviousInput(adjustedPos + FfxInt32x2(3, 0)); + + return GetPackedLuma(lumaTextureWidth, iPxPos.x, luma0, luma1, luma2, luma3); +} +#endif + +#endif // #if defined(FFX_GPU) + +#endif // FFX_OPTICALFLOW_CALLBACKS_HLSL_H diff --git a/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_common.h b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_common.h new file mode 100644 index 00000000..c5373d18 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_common.h @@ -0,0 +1,103 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 !defined(FFX_OPTICALFLOW_COMMON_H) +#define FFX_OPTICALFLOW_COMMON_H + +#if defined(FFX_GPU) + +#define FFX_ALL_MEMORY_BARRIER AllMemoryBarrierWithGroupSync + +#ifndef FFX_GROUP_MEMORY_BARRIER +#define FFX_GROUP_MEMORY_BARRIER GroupMemoryBarrierWithGroupSync +#endif + +#define SCD_OUTPUT_SCENE_CHANGE_SLOT 0 +#define SCD_OUTPUT_HISTORY_BITS_SLOT 1 +#define SCD_OUTPUT_COMPLETED_WORKGROUPS_SLOT 2 + +#define ffxClamp(x, a, b) (ffxMax(a, ffxMin(b, x))) + +FfxUInt32 GetPackedLuma(FfxInt32 width, FfxInt32 x, FfxUInt32 luma0, FfxUInt32 luma1, FfxUInt32 luma2, FfxUInt32 luma3) +{ + FfxUInt32 packedLuma = luma0 | (luma1 << 8) | (luma2 << 16) | (luma3 << 24); + + if (x < 0) + { + FfxUInt32 outOfScreenFiller = packedLuma & 0xffu; + if (x <= -1) + packedLuma = (packedLuma << 8) | outOfScreenFiller; + if (x <= -2) + packedLuma = (packedLuma << 8) | outOfScreenFiller; + if (x <= -3) + packedLuma = (packedLuma << 8) | outOfScreenFiller; + } + else if (x > width - 4) + { + FfxUInt32 outOfScreenFiller = packedLuma & 0xff000000u; + if (x >= width - 3) + packedLuma = (packedLuma >> 8) | outOfScreenFiller; + if (x >= width - 2) + packedLuma = (packedLuma >> 8) | outOfScreenFiller; + if (x >= width - 1) + packedLuma = (packedLuma >> 8) | outOfScreenFiller; + } + return packedLuma; +} + +FfxUInt32 Sad(FfxUInt32 a, FfxUInt32 b) +{ +#if FFX_OPTICALFLOW_USE_MSAD4_INSTRUCTION == 1 + return msad4(a, FfxUInt32x2(b, 0), FfxUInt32x4(0, 0, 0, 0)).x; +#else + return abs(FfxInt32((a >> 0) & 0xffu) - FfxInt32((b >> 0) & 0xffu)) + + abs(FfxInt32((a >> 8) & 0xffu) - FfxInt32((b >> 8) & 0xffu)) + + abs(FfxInt32((a >> 16) & 0xffu) - FfxInt32((b >> 16) & 0xffu)) + + abs(FfxInt32((a >> 24) & 0xffu) - FfxInt32((b >> 24) & 0xffu)); +#endif +} + +FfxUInt32x4 QSad(FfxUInt32 a0, FfxUInt32 a1, FfxUInt32 b) +{ +#if FFX_OPTICALFLOW_USE_MSAD4_INSTRUCTION == 1 + return msad4(b, FfxUInt32x2(a0, a1), FfxUInt32x4(0, 0, 0, 0)); +#else + FfxUInt32x4 sad; + sad.x = Sad(a0, b); + + a0 = (a0 >> 8) | ((a1 & 0xffu) << 24); + a1 >>= 8; + sad.y = Sad(a0, b); + + a0 = (a0 >> 8) | ((a1 & 0xffu) << 24); + a1 >>= 8; + sad.z = Sad(a0, b); + + a0 = (a0 >> 8) | ((a1 & 0xffu) << 24); + sad.w = Sad(a0, b); + return sad; +#endif +} + +#endif // #if defined(FFX_GPU) + +#endif //!defined(FFX_OPTICALFLOW_COMMON_H) diff --git a/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_luminance_pyramid.h b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_luminance_pyramid.h new file mode 100644 index 00000000..b68199e5 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_luminance_pyramid.h @@ -0,0 +1,99 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_OPTICALFLOW_COMPUTE_LUMINANCE_PYRAMID_H +#define FFX_OPTICALFLOW_COMPUTE_LUMINANCE_PYRAMID_H + +FFX_GROUPSHARED FfxFloat32 spdIntermediateR[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateG[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateB[16][16]; +FFX_GROUPSHARED FfxFloat32 spdIntermediateA[16][16]; + +FfxFloat32x4 SpdLoadSourceImage(FfxFloat32x2 tex, FfxUInt32 slice) +{ + FfxFloat32 luma = LoadRwOpticalFlowInput(FfxInt32x2(tex)); + return FfxFloat32x4(luma, 0, 0, 0); +} + +FfxFloat32x4 SpdLoad(FfxInt32x2 tex, FfxUInt32 slice) +{ + return FfxFloat32x4(0, 0, 0, 0); +} + +void SpdStore(FfxInt32x2 pix, FfxFloat32x4 outValue, FfxUInt32 index, FfxUInt32 slice) +{ + SPD_SetMipmap(pix, index, outValue.r); +} + +void SpdIncreaseAtomicCounter(FfxUInt32 slice) +{ +} + +FfxUInt32 SpdGetAtomicCounter() +{ + return 0; +} + +void SpdResetAtomicCounter(FfxUInt32 slice) +{ + SPD_ResetAtomicCounter(); +} + +FfxFloat32x4 SpdLoadIntermediate(FfxUInt32 x, FfxUInt32 y) +{ + return FfxFloat32x4( + spdIntermediateR[x][y], + spdIntermediateG[x][y], + spdIntermediateB[x][y], + spdIntermediateA[x][y]); +} +void SpdStoreIntermediate(FfxUInt32 x, FfxUInt32 y, FfxFloat32x4 value) +{ + spdIntermediateR[x][y] = value.x; + spdIntermediateG[x][y] = value.y; + spdIntermediateB[x][y] = value.z; + spdIntermediateA[x][y] = value.w; +} +FfxFloat32x4 SpdReduce4(FfxFloat32x4 v0, FfxFloat32x4 v1, FfxFloat32x4 v2, FfxFloat32x4 v3) +{ + return (v0 + v1 + v2 + v3) * 0.25; +} + +#ifdef FFX_HALF +#undef FFX_HALF +#endif + +// https://github.com/GPUOpen-Effects/FidelityFX-SPD/blob/master/docs/FidelityFX_SPD.pdf +#include "spd/ffx_spd.h" + +void ComputeOpticalFlowInputPyramid(FfxInt32x2 iGroupId, FfxInt32 iLocalIndex) +{ + SpdDownsample( + FfxUInt32x2(iGroupId.xy), + FfxUInt32(iLocalIndex), + 6, // mip levels to generate + FfxUInt32(NumWorkGroups()), + 1 // single slice + ); +} + +#endif // FFX_OPTICALFLOW_COMPUTE_LUMINANCE_PYRAMID_H diff --git a/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_optical_flow_v5.h b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_optical_flow_v5.h new file mode 100644 index 00000000..304a864e --- /dev/null +++ b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_optical_flow_v5.h @@ -0,0 +1,279 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_OPTICALFLOW_COMPUTE_OPTICAL_FLOW_V5_H +#define FFX_OPTICALFLOW_COMPUTE_OPTICAL_FLOW_V5_H + +#define CompareSize (4 * 2) +#define BlockSizeY 8 +#define BlockSizeX 8 +#define ThreadCount (4 * 16) +#define SearchRadiusX (8) +#define SearchRadiusY (8) +#define BlockCount 2 + +#define SearchBufferSizeX ((CompareSize + SearchRadiusX*2)/4) +#define SearchBufferSizeY (CompareSize + SearchRadiusY*2) + +FFX_GROUPSHARED FfxUInt32 pixels[CompareSize][CompareSize / 4]; +FFX_GROUPSHARED FfxUInt32 searchBuffer[1][SearchBufferSizeY * SearchBufferSizeX]; +#define bankBreaker 1 +FFX_GROUPSHARED FfxUInt32 sadMapBuffer[4][SearchRadiusY * 2][(SearchRadiusX * 2) / 4 + bankBreaker]; + +#define MaxWaves 2 +FFX_GROUPSHARED FfxUInt32 sWaveSad[MaxWaves]; +FFX_GROUPSHARED FfxUInt32 sWaveMin[MaxWaves]; + +FfxUInt32 BlockSad64(FfxUInt32 blockSadSum, FfxInt32 iLocalIndex, FfxInt32 iLaneToBlockId, FfxInt32 block) +{ + if (iLaneToBlockId != block) + { + blockSadSum = 0u; + } + blockSadSum = WaveActiveSum(blockSadSum); + + if (WaveGetLaneCount() == 32) + { + FfxInt32 waveId = iLocalIndex >> 5u; + if (WaveIsFirstLane()) + { + sWaveSad[waveId] = blockSadSum; + } + FFX_GROUP_MEMORY_BARRIER(); + blockSadSum += sWaveSad[waveId ^ 1]; + } + + return blockSadSum; +} + +FfxUInt32 SadMapMinReduction256(FfxInt32x2 iSearchId, FfxInt32 iLocalIndex) +{ + FfxUInt32 min01 = ffxMin(sadMapBuffer[0][iSearchId.y][iSearchId.x], sadMapBuffer[1][iSearchId.y][iSearchId.x]); + FfxUInt32 min23 = ffxMin(sadMapBuffer[2][iSearchId.y][iSearchId.x], sadMapBuffer[3][iSearchId.y][iSearchId.x]); + FfxUInt32 min0123 = ffxMin(min01, min23); + min0123 = WaveActiveMin(min0123); + + if (WaveGetLaneCount() == 32) + { + FfxInt32 waveId = iLocalIndex >> 5u; + + if (WaveIsFirstLane()) + { + sWaveMin[waveId] = min0123; + } + FFX_GROUP_MEMORY_BARRIER(); + min0123 = ffxMin(min0123, sWaveMin[waveId ^ 1]); + } + + return min0123; +} + +void LoadSearchBuffer(FfxInt32 iLocalIndex, FfxInt32x2 iPxPosShifted) +{ + FfxInt32 baseX = (iPxPosShifted.x - SearchRadiusX); + FfxInt32 baseY = (iPxPosShifted.y - SearchRadiusY); + + for (FfxInt32 id = iLocalIndex; id < SearchBufferSizeX * SearchBufferSizeY; id += ThreadCount) + { + FfxInt32 idx = id % SearchBufferSizeX; + FfxInt32 idy = id / SearchBufferSizeX; + FfxInt32 x = baseX + idx * 4; + FfxInt32 y = baseY + idy; + searchBuffer[0][id] = LoadSecondImagePackedLuma(FfxInt32x2(x, y)); + } + FFX_GROUP_MEMORY_BARRIER(); +} + +FfxUInt32x4 CalculateQSads2(FfxInt32x2 iSearchId) +{ + FfxUInt32x4 sad = ffxBroadcast4(0u); + +#if FFX_OPTICALFLOW_USE_MSAD4_INSTRUCTION == 1 + + FfxInt32 idx = iSearchId.y * 6 + iSearchId.x; + + sad = msad4(pixels[0][0], FfxUInt32x2(searchBuffer[0][idx], searchBuffer[0][idx + 1]), sad); + sad = msad4(pixels[0][1], FfxUInt32x2(searchBuffer[0][idx + 1], searchBuffer[0][idx + 2]), sad); + idx += 6; + sad = msad4(pixels[1][0], FfxUInt32x2(searchBuffer[0][idx], searchBuffer[0][idx + 1]), sad); + sad = msad4(pixels[1][1], FfxUInt32x2(searchBuffer[0][idx + 1], searchBuffer[0][idx + 2]), sad); + idx += 6; + sad = msad4(pixels[2][0], FfxUInt32x2(searchBuffer[0][idx], searchBuffer[0][idx + 1]), sad); + sad = msad4(pixels[2][1], FfxUInt32x2(searchBuffer[0][idx + 1], searchBuffer[0][idx + 2]), sad); + idx += 6; + sad = msad4(pixels[3][0], FfxUInt32x2(searchBuffer[0][idx], searchBuffer[0][idx + 1]), sad); + sad = msad4(pixels[3][1], FfxUInt32x2(searchBuffer[0][idx + 1], searchBuffer[0][idx + 2]), sad); + idx += 6; + sad = msad4(pixels[4][0], FfxUInt32x2(searchBuffer[0][idx], searchBuffer[0][idx + 1]), sad); + sad = msad4(pixels[4][1], FfxUInt32x2(searchBuffer[0][idx + 1], searchBuffer[0][idx + 2]), sad); + idx += 6; + sad = msad4(pixels[5][0], FfxUInt32x2(searchBuffer[0][idx], searchBuffer[0][idx + 1]), sad); + sad = msad4(pixels[5][1], FfxUInt32x2(searchBuffer[0][idx + 1], searchBuffer[0][idx + 2]), sad); + idx += 6; + sad = msad4(pixels[6][0], FfxUInt32x2(searchBuffer[0][idx], searchBuffer[0][idx + 1]), sad); + sad = msad4(pixels[6][1], FfxUInt32x2(searchBuffer[0][idx + 1], searchBuffer[0][idx + 2]), sad); + idx += 6; + sad = msad4(pixels[7][0], FfxUInt32x2(searchBuffer[0][idx], searchBuffer[0][idx + 1]), sad); + sad = msad4(pixels[7][1], FfxUInt32x2(searchBuffer[0][idx + 1], searchBuffer[0][idx + 2]), sad); + +#else + for (FfxInt32 dy = 0; dy < CompareSize; dy++) + { + FfxInt32 rowOffset = (iSearchId.y + dy) * SearchBufferSizeX; + FfxUInt32 a0 = searchBuffer[0][rowOffset + iSearchId.x]; + FfxUInt32 a1 = searchBuffer[0][rowOffset + iSearchId.x + 1]; + FfxUInt32 a2 = searchBuffer[0][rowOffset + iSearchId.x + 2]; + sad += QSad(a0, a1, pixels[dy][0]); + sad += QSad(a1, a2, pixels[dy][1]); + } +#endif + + return sad; +} + +FfxUInt32x2 abs_2(FfxInt32x2 val) +{ + FfxInt32x2 tmp = val; + FfxInt32x2 mask = tmp >> 31; + FfxUInt32x2 res = (tmp + mask) ^ mask; + return res; +} + +FfxUInt32 EncodeSearchCoord(FfxInt32x2 coord) +{ +#if FFX_OPTICALFLOW_FIX_TOP_LEFT_BIAS == 1 + uint2 absCoord = abs_2(coord - 8); + return FfxUInt32(absCoord.y << 12) | FfxUInt32(absCoord.x << 8) | FfxUInt32(coord.y << 4) | FfxUInt32(coord.x); +#else //FFX_OPTICALFLOW_FIX_TOP_LEFT_BIAS == 1 + return FfxUInt32(coord.y << 8) | FfxUInt32(coord.x); +#endif //FFX_OPTICALFLOW_FIX_TOP_LEFT_BIAS == 1 +} + +FfxInt32x2 DecodeSearchCoord(FfxUInt32 bits) +{ +#if FFX_OPTICALFLOW_FIX_TOP_LEFT_BIAS == 1 + FfxInt32 dx = FfxInt32(bits & 0xfu) - SearchRadiusX; + FfxInt32 dy = FfxInt32((bits >> 4) & 0xfu) - SearchRadiusY; + + return FfxInt32x2(dx, dy); +#else + FfxInt32 dx = FfxInt32(bits & 0xffu) - SearchRadiusX; + FfxInt32 dy = FfxInt32((bits >> 8) & 0xffu) - SearchRadiusY; + + return FfxInt32x2(dx, dy); +#endif +} + +void PrepareSadMap(FfxInt32x2 iSearchId, FfxUInt32x4 qsad) +{ + sadMapBuffer[0][iSearchId.y][iSearchId.x] = (qsad.x << 16) | EncodeSearchCoord(FfxInt32x2(iSearchId.x * 4 + 0, iSearchId.y)); + sadMapBuffer[1][iSearchId.y][iSearchId.x] = (qsad.y << 16) | EncodeSearchCoord(FfxInt32x2(iSearchId.x * 4 + 1, iSearchId.y)); + sadMapBuffer[2][iSearchId.y][iSearchId.x] = (qsad.z << 16) | EncodeSearchCoord(FfxInt32x2(iSearchId.x * 4 + 2, iSearchId.y)); + sadMapBuffer[3][iSearchId.y][iSearchId.x] = (qsad.w << 16) | EncodeSearchCoord(FfxInt32x2(iSearchId.x * 4 + 3, iSearchId.y)); + FFX_GROUP_MEMORY_BARRIER(); +} + + +uint ABfe(uint src, uint off, uint bits) { uint mask = (1u << bits) - 1u; return (src >> off) & mask; } +uint ABfi(uint src, uint ins, uint mask) { return (ins & mask) | (src & (~mask)); } +uint ABfiM(uint src, uint ins, uint bits) { uint mask = (1u << bits) - 1u; return (ins & mask) | (src & (~mask)); } +void MapThreads(in FfxInt32x2 iGroupId, in FfxInt32 iLocalIndex, + out FfxInt32x2 iSearchId, out FfxInt32x2 iPxPos, out FfxInt32 iLaneToBlockId) +{ + iSearchId = FfxInt32x2(ABfe(iLocalIndex, 0u, 2u), ABfe(iLocalIndex, 2u, 4u)); + iLaneToBlockId = FfxInt32(ABfe(iLocalIndex, 1u, 1u) | (ABfe(iLocalIndex, 5u, 1u) << 1u)); + iPxPos = (iGroupId << 4u) + iSearchId * FfxInt32x2(4, 1); +} + +void ComputeOpticalFlowAdvanced(FfxInt32x2 iGlobalId, FfxInt32x2 iLocalId, FfxInt32x2 iGroupId, FfxInt32 iLocalIndex) +{ + FfxInt32x2 iSearchId; + FfxInt32x2 iPxPos; + FfxInt32 iLaneToBlockId; + MapThreads(iGroupId, iLocalIndex, iSearchId, iPxPos, iLaneToBlockId); + + FfxInt32x2 currentOFPos = iPxPos >> 3u; + + if (IsSceneChanged()) + { + if ((iSearchId.y & 0b111) == 0 && (iSearchId.x & 0b1) == 0) + { + StoreOpticalFlow(currentOFPos, FfxInt32x2(0, 0)); + } + + return; + } + + const FfxBoolean bUsePredictionFromPreviousLevel = (OpticalFlowPyramidLevel() != OpticalFlowPyramidLevelCount() - 1); + + FfxUInt32 packedLuma_4blocks = LoadFirstImagePackedLuma(iPxPos); + +#if FFX_LOCAL_SEARCH_FALLBACK == 1 + FfxUInt32 prevPackedLuma_4blocks = LoadSecondImagePackedLuma(iPxPos); + FfxUInt32 sad_4blocks = Sad(packedLuma_4blocks, prevPackedLuma_4blocks); +#endif //FFX_LOCAL_SEARCH_FALLBACK + + FfxInt32x2 ofGroupOffset = iGroupId << 1u; + FfxInt32x2 pixelGroupOffset = iGroupId << 4u; + + FfxInt32x2 blockId; + for (blockId.y = 0; blockId.y < BlockCount; blockId.y++) + { + for (blockId.x = 0; blockId.x < BlockCount; blockId.x++) + { + FfxInt32x2 currentVector = LoadRwOpticalFlow(ofGroupOffset + blockId); + if (!bUsePredictionFromPreviousLevel) + { + currentVector = FfxInt32x2(0, 0); + } + + if (iLaneToBlockId == blockId.y * 2 + blockId.x) + { + pixels[iSearchId.y & 0b111][iSearchId.x & 0b1] = packedLuma_4blocks; + } + + LoadSearchBuffer(iLocalIndex, pixelGroupOffset + blockId * 8 + currentVector); + + FfxUInt32x4 qsad = CalculateQSads2(iSearchId); + + PrepareSadMap(iSearchId, qsad); + FfxUInt32 minSad = SadMapMinReduction256(iSearchId, iLocalIndex); + + FfxInt32x2 minSadCoord = DecodeSearchCoord(minSad); + FfxInt32x2 newVector = currentVector + minSadCoord; + +#if FFX_LOCAL_SEARCH_FALLBACK == 1 + FfxUInt32 blockSadSum = BlockSad64(sad_4blocks, iLocalIndex, iLaneToBlockId, blockId.x + blockId.y * 2); + if (OpticalFlowPyramidLevel() == 0 && blockSadSum <= (minSad >> 16u)) + { + newVector = FfxInt32x2(0, 0); + } +#endif //FFX_LOCAL_SEARCH_FALLBACK + + { + StoreOpticalFlow(ofGroupOffset + blockId, newVector); + } + } + } +} + +#endif // FFX_OPTICALFLOW_COMPUTE_OPTICAL_FLOW_V5_H diff --git a/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_scd_divergence.h b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_scd_divergence.h new file mode 100644 index 00000000..ce272d2a --- /dev/null +++ b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_compute_scd_divergence.h @@ -0,0 +1,159 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_OPTICALFLOW_COMPUTE_SCD_DIVERGENCE_H +#define FFX_OPTICALFLOW_COMPUTE_SCD_DIVERGENCE_H + +FFX_GROUPSHARED FfxFloat32 sourceHistogram[256]; +FFX_GROUPSHARED FfxFloat32 filteredHistogram[256]; +FFX_GROUPSHARED FfxFloat32 tempBuffer[256]; +FFX_GROUPSHARED FfxFloat32x2 tempBuffer2[256]; + +void ComputeSCDHistogramsDivergence(FfxInt32x3 iGlobalId, FfxInt32x2 iLocalId, FfxInt32 iLocalIndex, FfxInt32x2 iGroupId, FfxInt32x2 iGroupSize) +{ + FFX_STATIC const FfxFloat32 Factor = 1000000.0; + FFX_STATIC const FfxInt32 WhereToStop = 3*9 - 1; + FFX_STATIC const FfxInt32 HistogramCount = 3 * 3; + + FFX_STATIC const FfxFloat32 Kernel[] = { + 0.0088122291, 0.027143577, 0.065114059, 0.12164907, 0.17699835, 0.20056541 + }; + + sourceHistogram[iLocalIndex] = FfxFloat32(LoadRwSCDHistogram(iGlobalId.x)); + FFX_GROUP_MEMORY_BARRIER(); + + const FfxInt32 kernelShift = -5; + const FfxInt32 indexToRead = iLocalIndex + kernelShift; + + FfxFloat32 val = 0.0; + val += Kernel[0] * sourceHistogram[ffxClamp(indexToRead + 0, 0, 255)]; + val += Kernel[1] * sourceHistogram[ffxClamp(indexToRead + 1, 0, 255)]; + val += Kernel[2] * sourceHistogram[ffxClamp(indexToRead + 2, 0, 255)]; + val += Kernel[3] * sourceHistogram[ffxClamp(indexToRead + 3, 0, 255)]; + val += Kernel[4] * sourceHistogram[ffxClamp(indexToRead + 4, 0, 255)]; + val += Kernel[5] * sourceHistogram[ffxClamp(indexToRead + 5, 0, 255)]; + val += Kernel[4] * sourceHistogram[ffxClamp(indexToRead + 6, 0, 255)]; + val += Kernel[3] * sourceHistogram[ffxClamp(indexToRead + 7, 0, 255)]; + val += Kernel[2] * sourceHistogram[ffxClamp(indexToRead + 8, 0, 255)]; + val += Kernel[1] * sourceHistogram[ffxClamp(indexToRead + 9, 0, 255)]; + val += Kernel[0] * sourceHistogram[ffxClamp(indexToRead + 10, 0, 255)]; + + val += 1.0; + + if (iGlobalId.y == 0) + { + if (iLocalIndex == 0) + filteredHistogram[255] = 1.0; + else + filteredHistogram[iLocalIndex - 1] = val; + } + else if (iGlobalId.y == 1) + { + filteredHistogram[iLocalIndex] = val; + } + else if (iGlobalId.y == 2) + { + if (iLocalIndex == 255) + filteredHistogram[0] = 1.0; + else + filteredHistogram[iLocalIndex + 1] = val; + } + FFX_GROUP_MEMORY_BARRIER(); + + tempBuffer[iLocalIndex] = filteredHistogram[iLocalIndex]; + FFX_GROUP_MEMORY_BARRIER(); + + if (iLocalIndex < 128) tempBuffer[iLocalIndex] += tempBuffer[iLocalIndex + 128]; + FFX_GROUP_MEMORY_BARRIER(); + + if (iLocalIndex < 64) tempBuffer[iLocalIndex] += tempBuffer[iLocalIndex + 64]; + FFX_GROUP_MEMORY_BARRIER(); + + if (iLocalIndex < 32) tempBuffer[iLocalIndex] += tempBuffer[iLocalIndex + 32]; + if (iLocalIndex < 16) tempBuffer[iLocalIndex] += tempBuffer[iLocalIndex + 16]; + if (iLocalIndex < 8 ) tempBuffer[iLocalIndex] += tempBuffer[iLocalIndex + 8]; + if (iLocalIndex < 4 ) tempBuffer[iLocalIndex] += tempBuffer[iLocalIndex + 4]; + if (iLocalIndex < 2 ) tempBuffer[iLocalIndex] += tempBuffer[iLocalIndex + 2]; + if (iLocalIndex < 1 ) tempBuffer[iLocalIndex] += tempBuffer[iLocalIndex + 1]; + FFX_GROUP_MEMORY_BARRIER(); + + filteredHistogram[iLocalIndex] /= tempBuffer[0]; + + FfxFloat32 currentFilteredHistogramsValue = filteredHistogram[iLocalIndex]; + FfxFloat32 previousHistogramsValue = LoadRwSCDPreviousHistogram(iGlobalId.x); + + tempBuffer2[iLocalIndex] = FfxFloat32x2( + currentFilteredHistogramsValue * log(currentFilteredHistogramsValue / previousHistogramsValue), + previousHistogramsValue * log(previousHistogramsValue / currentFilteredHistogramsValue) + ); + FFX_GROUP_MEMORY_BARRIER(); + + if (iLocalIndex < 128) tempBuffer2[iLocalIndex] += tempBuffer2[iLocalIndex + 128]; + FFX_GROUP_MEMORY_BARRIER(); + + if (iLocalIndex < 64) tempBuffer2[iLocalIndex] += tempBuffer2[iLocalIndex + 64]; + FFX_GROUP_MEMORY_BARRIER(); + + if (iLocalIndex < 32) tempBuffer2[iLocalIndex] += tempBuffer2[iLocalIndex + 32]; + if (iLocalIndex < 16) tempBuffer2[iLocalIndex] += tempBuffer2[iLocalIndex + 16]; + if (iLocalIndex < 8 ) tempBuffer2[iLocalIndex] += tempBuffer2[iLocalIndex + 8]; + if (iLocalIndex < 4 ) tempBuffer2[iLocalIndex] += tempBuffer2[iLocalIndex + 4]; + if (iLocalIndex < 2 ) tempBuffer2[iLocalIndex] += tempBuffer2[iLocalIndex + 2]; + + if (iLocalIndex == 0) + { + FfxFloat32x2 sum = tempBuffer2[0] + tempBuffer2[1]; + + FfxFloat32 resFloat = 1 - exp(-(abs(sum.x) + abs(sum.y))); + FfxUInt32 resUInt = (resFloat / FfxFloat32(HistogramCount)) * Factor; + AtomicIncrementSCDTemp(iGlobalId.y, resUInt); + + FfxUInt32 oldFinishedGroupCount = AtomicIncrementSCDOutput(SCD_OUTPUT_COMPLETED_WORKGROUPS_SLOT, 1); + if (oldFinishedGroupCount == WhereToStop) + { + FfxUInt32 res0 = LoadRwSCDTemp(0); + FfxUInt32 res1 = LoadRwSCDTemp(1); + FfxUInt32 res2 = LoadRwSCDTemp(2); + FfxFloat32 sceneChangeValue = ffxMin(res0, ffxMin(res1, res2)) / Factor; + + FfxUInt32 history = LoadRwSCDOutput(SCD_OUTPUT_HISTORY_BITS_SLOT) << 1; + if (CrossedSceneChangeThreshold(sceneChangeValue)) + { + history |= 1; + } + StoreSCDOutput(SCD_OUTPUT_SCENE_CHANGE_SLOT, ffxAsUInt32(sceneChangeValue)); + StoreSCDOutput(SCD_OUTPUT_HISTORY_BITS_SLOT, history); + StoreSCDOutput(SCD_OUTPUT_COMPLETED_WORKGROUPS_SLOT, 0); + + ResetSCDTemp(); + } + } + + if (iGlobalId.y == 1) + { + StoreSCDPreviousHistogram(iGlobalId.x, currentFilteredHistogramsValue); + + StoreSCDHistogram(iGlobalId.x, 0); + } +} + +#endif // FFX_OPTICALFLOW_COMPUTE_SCD_DIVERGENCE_H diff --git a/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_filter_optical_flow_v5.h b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_filter_optical_flow_v5.h new file mode 100644 index 00000000..ba25c11f --- /dev/null +++ b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_filter_optical_flow_v5.h @@ -0,0 +1,58 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_OPTICALFLOW_FILTER_OPTICAL_FLOW_V5_H +#define FFX_OPTICALFLOW_FILTER_OPTICAL_FLOW_V5_H + +void FilterOpticalFlow(FfxInt32x2 iGlobalId, FfxInt32x2 iLocalId, FfxInt32x2 iGroupId, FfxInt32 iLocalIndex) +{ + FfxInt32x2 tmpMV[9]; + FfxInt32 idx = 0; + for (int xx = -1; xx < 2; xx++) + { + for (int yy = -1; yy < 2; yy++) + { + + tmpMV[idx] = LoadPreviousOpticalFlow(iGlobalId + FfxInt32x2(xx, yy)); + idx++; + } + } + + uint ret = 0xFFFFFFFF; + for (int i = 0; i < 9; ++i) + { + uint tmp = 0; + for (int j = 0; j < 9; ++j) + { + FfxInt32x2 delta = tmpMV[i] - tmpMV[j]; + tmp = delta.x * delta.x + (delta.y * delta.y + tmp); + } + + ret = min(((tmp) << 4) | i, ret); + } + + int minIdx = ret & 0xF; + + StoreOpticalFlow(iGlobalId, tmpMV[minIdx]); +} + +#endif // FFX_OPTICALFLOW_FILTER_OPTICAL_FLOW_V5_H diff --git a/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_generate_scd_histogram.h b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_generate_scd_histogram.h new file mode 100644 index 00000000..e3470175 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_generate_scd_histogram.h @@ -0,0 +1,85 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_OPTICALFLOW_GENERATE_SCD_HISTOGRAM_H +#define FFX_OPTICALFLOW_GENERATE_SCD_HISTOGRAM_H + +#define LBASE 10 + +FFX_GROUPSHARED FfxUInt32 buffer[256 * LBASE]; + +void GenerateSceneChangeDetectionHistogram(FfxInt32x3 iGlobalId, FfxInt32x2 iLocalId, FfxInt32 iLocalIndex, FfxInt32x2 iGroupId, FfxInt32x2 iGroupSize) +{ + FFX_STATIC const FfxUInt32 HistogramsPerDim = 3; + + FfxUInt32 divX = DisplaySize().x / HistogramsPerDim; + FfxUInt32 divY = DisplaySize().y / HistogramsPerDim; + + FfxUInt32 nx = iGlobalId.z % HistogramsPerDim; + FfxUInt32 ny = iGlobalId.z / HistogramsPerDim; + FfxUInt32 startX = divX * nx; + FfxUInt32 startY = divY * ny; + FfxUInt32 stopX = startX + divX; + FfxUInt32 stopY = startY + divY; + + const FfxUInt32 bufferOffset = iLocalIndex * LBASE; + + for (FfxInt32 i = 0; i < LBASE; i++) + { + buffer[bufferOffset + i] = 0; + } + FFX_GROUP_MEMORY_BARRIER(); + + FfxInt32x2 coord = FfxInt32x2(startX + (4 * iGlobalId.x), startY + iGlobalId.y); + if (coord.x < stopX) + { + for (; coord.y < stopY; coord.y += 128) + { + FfxUInt32x4 color = FfxUInt32x4( + LoadOpticalFlowInput(coord + FfxInt32x2(0, 0)), + LoadOpticalFlowInput(coord + FfxInt32x2(1, 0)), + LoadOpticalFlowInput(coord + FfxInt32x2(2, 0)), + LoadOpticalFlowInput(coord + FfxInt32x2(3, 0)) + ); + color *= LBASE; + + FfxUInt32 scramblingOffset = iLocalIndex % LBASE; + + InterlockedAdd(buffer[color.x + scramblingOffset], 1); + InterlockedAdd(buffer[color.y + scramblingOffset], 1); + InterlockedAdd(buffer[color.z + scramblingOffset], 1); + InterlockedAdd(buffer[color.w + scramblingOffset], 1); + } + } + FFX_GROUP_MEMORY_BARRIER(); + + FfxUInt32 value = 0; + for (FfxInt32 i = 0; i < LBASE; i++) + { + value += buffer[bufferOffset + i]; + } + + FfxUInt32 histogramStart = (iGroupSize.x * iGroupSize.y) * iGlobalId.z; + AtomicIncrementSCDHistogram(histogramStart + iLocalIndex, value); +} + +#endif // FFX_OPTICALFLOW_GENERATE_SCD_HISTOGRAM_H diff --git a/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_prepare_luma.h b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_prepare_luma.h new file mode 100644 index 00000000..bd994a9a --- /dev/null +++ b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_prepare_luma.h @@ -0,0 +1,105 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_OPTICALFLOW_PREPARE_LUMA_H +#define FFX_OPTICALFLOW_PREPARE_LUMA_H + +FfxFloat32 LuminanceToPerceivedLuminance(FfxFloat32 fLuminance) +{ + FfxFloat32 fPercievedLuminance = 0; + if (fLuminance <= 216.0f / 24389.0f) { + fPercievedLuminance = fLuminance * (24389.0f / 27.0f); + } + else { + fPercievedLuminance = ffxPow(fLuminance, 1.0f / 3.0f) * 116.0f - 16.0f; + } + + return fPercievedLuminance * 0.01f; +} + +FfxFloat32 LinearLdrToLuminance(FfxFloat32x3 linearRec709RGB) +{ + FfxFloat32 fY = 0.2126 * linearRec709RGB.x + 0.7152 * linearRec709RGB.y + 0.0722 * linearRec709RGB.z; + return fY; +} + +FfxFloat32 LinearRec2020ToLuminance(FfxFloat32x3 linearRec2020RGB) +{ + FfxFloat32 fY = 0.2627 * linearRec2020RGB.x + 0.678 * linearRec2020RGB.y + 0.0593 * linearRec2020RGB.z; + return fY; +} + +FfxFloat32 PQCorrectedHdrToLuminance(FfxFloat32x3 pq, FfxFloat32 maxLuminance) +{ + FfxFloat32 fY = LinearRec2020ToLuminance(ffxLinearFromPQ(pq) * (10000.0f / maxLuminance)); + return fY; +} + +FfxFloat32x3 ffxscRGBToLinear(FfxFloat32x3 value, FfxFloat32 minLuminance, FfxFloat32 maxLuminance) +{ + FfxFloat32x3 p = value - ffxBroadcast3(minLuminance / 80.0f); + return p / ffxBroadcast3((maxLuminance - minLuminance) / 80.0f); +} + +FfxFloat32 SCRGBCorrectedHdrToLuminance(FfxFloat32x3 scRGB, FfxFloat32 minLuminance, FfxFloat32 maxLuminance) +{ + FfxFloat32 fY = LinearLdrToLuminance(ffxscRGBToLinear(scRGB, minLuminance, maxLuminance)); + return fY; +} + +void PrepareLuma(FfxInt32x2 iGlobalId, FfxInt32 iLocalIndex) +{ +#define PixelsPerThreadX 2 +#define PixelsPerThreadY 2 +#pragma unroll + for (int y = 0; y < PixelsPerThreadY; y++) + { +#pragma unroll + for (int x = 0; x < PixelsPerThreadX; x++) + { + int2 pos = iGlobalId * int2(PixelsPerThreadX, PixelsPerThreadY) + int2(x, y); + FfxInt32x2 iPxHrPos = pos; + FfxFloat32 fY = 0.0; + + FfxFloat32x3 inputColor = LoadInputColor(iPxHrPos).rgb; + + if (backbufferTransferFunction == 0) + { + fY = LinearLdrToLuminance(inputColor); + } + else if (backbufferTransferFunction == 1) + { + fY = PQCorrectedHdrToLuminance(inputColor, minMaxLuminance[1]); + fY = LuminanceToPerceivedLuminance(fY); + } + else if (backbufferTransferFunction == 2) + { + fY = SCRGBCorrectedHdrToLuminance(inputColor, minMaxLuminance[0], minMaxLuminance[1]); + fY = LuminanceToPerceivedLuminance(fY); + } + + StoreOpticalFlowInput(pos, fY * 255); + } + } +} + +#endif // FFX_OPTICALFLOW_PREPARE_LUMA_H diff --git a/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_resources.h b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_resources.h new file mode 100644 index 00000000..128c2087 --- /dev/null +++ b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_resources.h @@ -0,0 +1,73 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_OPTICALFLOW_RESOURCES_H +#define FFX_OPTICALFLOW_RESOURCES_H + +#if defined(FFX_CPU) || defined(FFX_GPU) + +#define FFX_OF_RESOURCE_IDENTIFIER_NULL 0 + +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1 1 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_1 2 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_2 3 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_3 4 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_4 5 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_5 6 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_6 7 + +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2 8 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_1 9 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_2 10 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_3 11 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_4 12 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_5 13 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_6 14 + +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1 15 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_1 16 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_2 17 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_3 18 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_4 19 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_5 20 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_6 21 + +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2 22 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_1 23 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_2 24 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_3 25 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_4 26 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_5 27 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_6 28 + +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_HISTOGRAM 29 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM 30 +#define FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_TEMP 31 + +#define FFX_OF_RESOURCE_IDENTIFIER_COUNT 32 + +#define FFX_OPTICALFLOW_CONSTANTBUFFER_IDENTIFIER 0 +#define FFX_OPTICALFLOW_CONSTANTBUFFER_IDENTIFIER_SPD 1 + +#endif // #if defined(FFX_CPU) || defined(FFX_GPU) + +#endif //!defined( FFX_OPTICALFLOW_RESOURCES_H ) diff --git a/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_v5.h b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_v5.h new file mode 100644 index 00000000..3cfebd6f --- /dev/null +++ b/sdk/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_v5.h @@ -0,0 +1,99 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 FFX_OPTICALFLOW_SCALE_OPTICAL_FLOW_ADVANCED_V5_H +#define FFX_OPTICALFLOW_SCALE_OPTICAL_FLOW_ADVANCED_V5_H + +#define WG_WIDTH FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define WG_HEIGHT FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define WG_DEPTH FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +FFX_GROUPSHARED FfxInt32x2 nearestVectors[4][WG_HEIGHT][WG_WIDTH]; +FFX_GROUPSHARED FfxUInt32 localRegion[4][WG_HEIGHT][WG_WIDTH]; +FFX_GROUPSHARED FfxUInt32 sads[4][WG_HEIGHT][WG_WIDTH]; + +void ScaleOpticalFlowAdvanced(FfxInt32x3 iGlobalId, FfxInt32x3 iLocalId) +{ + if (IsSceneChanged()) + { + StoreOpticalFlowNextLevel(iGlobalId.xy, FfxInt32x2(0, 0)); + + return; + } + + int xOffset = (iLocalId.z % 2) - 1 + iGlobalId.x % 2; + int yOffset = (iLocalId.z / 2) - 1 + iGlobalId.y % 2; + + FfxInt32x2 srcOFPos = FfxInt32x2( + (iGlobalId.x / 2) + xOffset, + (iGlobalId.y / 2) + yOffset + ); + + FfxInt32x2 nearestVector = LoadOpticalFlow(srcOFPos); + nearestVectors[iLocalId.z][iLocalId.y][iLocalId.x] = nearestVector * 2; + + int maxY = 4; + for (int n = iLocalId.z; n < maxY; n += WG_DEPTH) + { + { + FfxInt32x2 lumaPos = FfxInt32x2((iGlobalId.x) * 4, iGlobalId.y * maxY + n); + FfxUInt32 firstPixel = LoadFirstImagePackedLuma(lumaPos); + localRegion[n][iLocalId.y][iLocalId.x] = firstPixel; + } + } + FFX_GROUP_MEMORY_BARRIER(); + + uint sad = 0; + for (int n = 0; n < maxY; n++) + { + { + FfxInt32x2 lumaPos = FfxInt32x2((iGlobalId.x) * 4, (iGlobalId.y * maxY + n)) + nearestVector; + FfxUInt32 secondPixel = LoadSecondImagePackedLuma(lumaPos); + sad += Sad(localRegion[n][iLocalId.y][iLocalId.x], secondPixel); + } + } + sads[iLocalId.z][iLocalId.y][iLocalId.x] = sad; + + FFX_GROUP_MEMORY_BARRIER(); + + { + if (iLocalId.z == 0) + { + uint bestSad = 0xffffffff; + uint bestId = 0; + + for (int n = 0; n < 4; n++) + { + if ((sads[n][iLocalId.y][iLocalId.x]) < bestSad) + { + bestSad = sads[n][iLocalId.y][iLocalId.x]; + bestId = n; + } + } + + FfxInt32x2 outputVector = nearestVectors[bestId][iLocalId.y][iLocalId.x]; + + StoreOpticalFlowNextLevel(iGlobalId.xy, outputVector); + } + } +} + +#endif // FFX_OPTICALFLOW_SCALE_OPTICAL_FLOW_ADVANCED_V5_H diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort.h index e7338d1e..32998430 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup FfxGPUParallelSort FidelityFX Parallel Sort /// FidelityFX Parallel Sort GPU documentation /// diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_callbacks_glsl.h index 9311bb27..ac2a3eb5 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_parallelsort_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_callbacks_hlsl.h index 372654ff..0009168b 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_parallelsort_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_common.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_common.h index 23f7a2b2..936f3e15 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_common.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_common.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + FfxUInt32 FfxNumBlocksPerThreadGroup() { return NumBlocksPerThreadGroup(); diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_reduce.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_reduce.h index bb915fee..052851ba 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_reduce.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_reduce.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #if FFX_PARALLELSORT_OPTION_HAS_PAYLOAD diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_resources.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_resources.h index ff2ab621..0ef8dea3 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_resources.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_PARALLELSORT_RESOURCES_H #define FFX_PARALLELSORT_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scan.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scan.h index bd6daffd..d50ee5bb 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scan.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scan.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #if FFX_PARALLELSORT_OPTION_HAS_PAYLOAD diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scan_add.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scan_add.h index 5feb545a..75206337 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scan_add.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scan_add.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #if FFX_PARALLELSORT_OPTION_HAS_PAYLOAD diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scatter.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scatter.h index b79d05b6..da3bec97 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scatter.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_scatter.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #if FFX_PARALLELSORT_OPTION_HAS_PAYLOAD diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_setup_indirect_args.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_setup_indirect_args.h index d7897061..a0640ddc 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_setup_indirect_args.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_setup_indirect_args.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #if FFX_PARALLELSORT_OPTION_HAS_PAYLOAD diff --git a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_sum.h b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_sum.h index 582be69f..42e775aa 100644 --- a/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_sum.h +++ b/sdk/include/FidelityFX/gpu/parallelsort/ffx_parallelsort_sum.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #if FFX_PARALLELSORT_OPTION_HAS_PAYLOAD diff --git a/sdk/include/FidelityFX/gpu/reflection-dnsr/ffx_denoiser_reflections_common.h b/sdk/include/FidelityFX/gpu/reflection-dnsr/ffx_denoiser_reflections_common.h index 5e96d86c..83162dbb 100644 --- a/sdk/include/FidelityFX/gpu/reflection-dnsr/ffx_denoiser_reflections_common.h +++ b/sdk/include/FidelityFX/gpu/reflection-dnsr/ffx_denoiser_reflections_common.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_DNSR_REFLECTIONS_COMMON #define FFX_DNSR_REFLECTIONS_COMMON diff --git a/sdk/include/FidelityFX/gpu/reflection-dnsr/ffx_denoiser_reflections_config.h b/sdk/include/FidelityFX/gpu/reflection-dnsr/ffx_denoiser_reflections_config.h index 52865850..1b27fe32 100644 --- a/sdk/include/FidelityFX/gpu/reflection-dnsr/ffx_denoiser_reflections_config.h +++ b/sdk/include/FidelityFX/gpu/reflection-dnsr/ffx_denoiser_reflections_config.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_DNSR_REFLECTIONS_CONFIG #define FFX_DNSR_REFLECTIONS_CONFIG diff --git a/sdk/include/FidelityFX/gpu/spd/ffx_spd.h b/sdk/include/FidelityFX/gpu/spd/ffx_spd.h index 0fc67c5d..cbb39829 100644 --- a/sdk/include/FidelityFX/gpu/spd/ffx_spd.h +++ b/sdk/include/FidelityFX/gpu/spd/ffx_spd.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup FfxGPUSpd FidelityFX SPD /// FidelityFX Single Pass Downsampler 2.0 GPU documentation /// diff --git a/sdk/include/FidelityFX/gpu/spd/ffx_spd_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/spd/ffx_spd_callbacks_glsl.h index 30192ad5..fbdcd57e 100644 --- a/sdk/include/FidelityFX/gpu/spd/ffx_spd_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/spd/ffx_spd_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_spd_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/spd/ffx_spd_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/spd/ffx_spd_callbacks_hlsl.h index 8dd5e663..9c97480e 100644 --- a/sdk/include/FidelityFX/gpu/spd/ffx_spd_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/spd/ffx_spd_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_spd_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/spd/ffx_spd_downsample.h b/sdk/include/FidelityFX/gpu/spd/ffx_spd_downsample.h index 75ec4934..f07b6b43 100644 --- a/sdk/include/FidelityFX/gpu/spd/ffx_spd_downsample.h +++ b/sdk/include/FidelityFX/gpu/spd/ffx_spd_downsample.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_core.h" #if FFX_HALF diff --git a/sdk/include/FidelityFX/gpu/spd/ffx_spd_resources.h b/sdk/include/FidelityFX/gpu/spd/ffx_spd_resources.h index 7011aeb1..64182a05 100644 --- a/sdk/include/FidelityFX/gpu/spd/ffx_spd_resources.h +++ b/sdk/include/FidelityFX/gpu/spd/ffx_spd_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_SPD_RESOURCES_H #define FFX_SPD_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_callbacks_glsl.h index db8bc672..7d09a1d9 100644 --- a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_sssr_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_callbacks_hlsl.h index 607e00a6..8aa17bbc 100644 --- a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_sssr_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_classify_tiles.h b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_classify_tiles.h index d5f5373a..0c5e79b7 100644 --- a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_classify_tiles.h +++ b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_classify_tiles.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_sssr_common.h" #include "../reflection-dnsr/ffx_denoiser_reflections_common.h" diff --git a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_common.h b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_common.h index a178544e..6fb5136e 100644 --- a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_common.h +++ b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_common.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + //=== Common functions of the SssrSample === void UnpackRayCoords(FfxUInt32 packed, FFX_PARAMETER_OUT FfxUInt32x2 ray_coord, FFX_PARAMETER_OUT FfxBoolean copy_horizontal, FFX_PARAMETER_OUT FfxBoolean copy_vertical, FFX_PARAMETER_OUT FfxBoolean copy_diagonal) { diff --git a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_depth_downsample.h b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_depth_downsample.h index f656f918..d5072cc9 100644 --- a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_depth_downsample.h +++ b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_depth_downsample.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + FFX_GROUPSHARED FfxUInt32 spdCounter; FFX_GROUPSHARED FfxFloat32 spdIntermediate[16][16]; diff --git a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_intersect.h b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_intersect.h index 6e3aed63..6acad2de 100644 --- a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_intersect.h +++ b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_intersect.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_sssr_common.h" #define M_PI 3.14159265358979f diff --git a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_prepare_blue_noise_texture.h b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_prepare_blue_noise_texture.h index b64e7975..92f8fd60 100644 --- a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_prepare_blue_noise_texture.h +++ b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_prepare_blue_noise_texture.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_sssr_common.h" #define GOLDEN_RATIO 1.61803398875f diff --git a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_prepare_indirect_args.h b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_prepare_indirect_args.h index e5e8f4a8..4c310bb7 100644 --- a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_prepare_indirect_args.h +++ b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_prepare_indirect_args.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + void PrepareIndirectArgs() { { // Prepare intersection args FfxUInt32 ray_count = FFX_SSSR_GetRayCounter(0); diff --git a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_resources.h b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_resources.h index 8eeaa604..9281e99b 100644 --- a/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_resources.h +++ b/sdk/include/FidelityFX/gpu/sssr/ffx_sssr_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_SSSR2_RESOURCES_H #define FFX_SSSR2_RESOURCES_H diff --git a/sdk/include/FidelityFX/gpu/vrs/ffx_variable_shading.h b/sdk/include/FidelityFX/gpu/vrs/ffx_variable_shading.h index 40acf594..a597500d 100644 --- a/sdk/include/FidelityFX/gpu/vrs/ffx_variable_shading.h +++ b/sdk/include/FidelityFX/gpu/vrs/ffx_variable_shading.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup FfxGPUVrs FidelityFX VRS /// FidelityFX Variable Shading GPU documentation /// diff --git a/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_callbacks_glsl.h b/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_callbacks_glsl.h index 617eb12d..60c6892f 100644 --- a/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_callbacks_glsl.h +++ b/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_callbacks_glsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_vrs_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_callbacks_hlsl.h b/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_callbacks_hlsl.h index 236c53b8..3d939d9e 100644 --- a/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_callbacks_hlsl.h +++ b/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_callbacks_hlsl.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 "ffx_vrs_resources.h" #if defined(FFX_GPU) diff --git a/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_resources.h b/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_resources.h index aad8933e..1edcc508 100644 --- a/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_resources.h +++ b/sdk/include/FidelityFX/gpu/vrs/ffx_vrs_resources.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 FFX_VRS_RESOURCES_H #define FFX_VRS_RESOURCES_H diff --git a/sdk/include/FidelityFX/host/backends/dx12/d3dx12.h b/sdk/include/FidelityFX/host/backends/dx12/d3dx12.h index 629c3988..e6710876 100644 --- a/sdk/include/FidelityFX/host/backends/dx12/d3dx12.h +++ b/sdk/include/FidelityFX/host/backends/dx12/d3dx12.h @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + //********************************************************* // // Copyright (c) Microsoft. All rights reserved. diff --git a/sdk/include/FidelityFX/host/backends/dx12/ffx_dx12.h b/sdk/include/FidelityFX/host/backends/dx12/ffx_dx12.h index c591320e..bc7337b4 100644 --- a/sdk/include/FidelityFX/host/backends/dx12/ffx_dx12.h +++ b/sdk/include/FidelityFX/host/backends/dx12/ffx_dx12.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup DX12Backend DX12 Backend /// FidelityFX SDK native backend implementation for DirectX 12. /// @@ -28,6 +28,7 @@ #pragma once #include +#include #include #if defined(__cplusplus) @@ -74,7 +75,7 @@ FFX_API FfxErrorCode ffxGetInterfaceDX12( FfxDevice device, void* scratchBuffer, size_t scratchBufferSize, - size_t maxContexts); + uint32_t maxContexts); /// Create a FfxCommandList from a ID3D12CommandList. /// @@ -97,11 +98,49 @@ FFX_API FfxCommandList ffxGetCommandListDX12(ID3D12CommandList* cmdList); /// An abstract FidelityFX resources. /// /// @ingroup DX12Backend -FFX_API FfxResource ffxGetResourceDX12(ID3D12Resource* dx12Resource, +FFX_API FfxResource ffxGetResourceDX12(const ID3D12Resource* dx12Resource, FfxResourceDescription ffxResDescription, wchar_t* ffxResName, FfxResourceStates state = FFX_RESOURCE_STATE_COMPUTE_READ); +FFX_API FfxSurfaceFormat ffxGetSurfaceFormatDX12(DXGI_FORMAT format); + +FFX_API FfxResourceDescription GetFfxResourceDescriptionDX12(ID3D12Resource* pResource); + +FFX_API FfxCommandQueue ffxGetCommandQueueDX12(ID3D12CommandQueue* pCommandQueue); + +FFX_API FfxSwapchain ffxGetSwapchainDX12(IDXGISwapChain4* pSwapchain); + +FFX_API IDXGISwapChain4* ffxGetDX12SwapchainPtr(FfxSwapchain ffxSwapchain); + +FFX_API FfxErrorCode ffxReplaceSwapchainForFrameinterpolationDX12(FfxCommandQueue gameQueue, FfxSwapchain& gameSwapChain); + +FFX_API FfxErrorCode ffxCreateFrameinterpolationSwapchainDX12(const DXGI_SWAP_CHAIN_DESC* desc, + ID3D12CommandQueue* queue, + IDXGIFactory* dxgiFactory, + FfxSwapchain& outGameSwapChain); + +FFX_API FfxErrorCode ffxCreateFrameinterpolationSwapchainForHwndDX12(HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* desc1, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* fullscreenDesc, + ID3D12CommandQueue* queue, + IDXGIFactory* dxgiFactory, + FfxSwapchain& outGameSwapChain); + +FFX_API FfxErrorCode ffxWaitForPresents(FfxSwapchain gameSwapChain); +FFX_API FfxErrorCode ffxRegisterFrameinterpolationUiResourceDX12(FfxSwapchain gameSwapChain, FfxResource uiResource); +FFX_API FfxErrorCode ffxGetFrameinterpolationCommandlistDX12(FfxSwapchain gameSwapChain, FfxCommandList& gameCommandlist); +FFX_API FfxResource ffxGetFrameinterpolationTextureDX12(FfxSwapchain gameSwapChain); + +FFX_API FfxErrorCode ffxSetFrameGenerationConfigToSwapchainDX12(FfxFrameGenerationConfig const* config); + +struct FfxFrameInterpolationContext; +struct FfxFsr2Context; + +typedef FfxErrorCode (*FfxCreateFiSwapchain)(FfxFrameInterpolationContext* fiContext, FfxDevice device, FfxCommandQueue gameQueue, FfxSwapchain& swapchain); + +typedef FfxErrorCode (*FfxReleaseFiSwapchain)(FfxFrameInterpolationContext* fiContext, FfxSwapchain* outRealSwapchain); + #if defined(__cplusplus) } #endif // #if defined(__cplusplus) diff --git a/sdk/include/FidelityFX/host/backends/dx12/license.txt b/sdk/include/FidelityFX/host/backends/dx12/license.txt index 31db5faf..d56d590d 100644 --- a/sdk/include/FidelityFX/host/backends/dx12/license.txt +++ b/sdk/include/FidelityFX/host/backends/dx12/license.txt @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + The MIT License (MIT) Copyright (c) 2023 Microsoft diff --git a/sdk/include/FidelityFX/host/backends/vk/ffx_vk.h b/sdk/include/FidelityFX/host/backends/vk/ffx_vk.h index 405d5dcd..02e0ad62 100644 --- a/sdk/include/FidelityFX/host/backends/vk/ffx_vk.h +++ b/sdk/include/FidelityFX/host/backends/vk/ffx_vk.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup VKBackend Vulkan Backend /// FidelityFX SDK native backend implementation for Vulkan. /// diff --git a/sdk/include/FidelityFX/host/ffx_assert.h b/sdk/include/FidelityFX/host/ffx_assert.h index 65f3fd73..11718eca 100644 --- a/sdk/include/FidelityFX/host/ffx_assert.h +++ b/sdk/include/FidelityFX/host/ffx_assert.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 diff --git a/sdk/include/FidelityFX/host/ffx_blur.h b/sdk/include/FidelityFX/host/ffx_blur.h index 00bb9834..47933874 100644 --- a/sdk/include/FidelityFX/host/ffx_blur.h +++ b/sdk/include/FidelityFX/host/ffx_blur.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup ffxBlur FidelityFX Blur /// FidelityFX Blur runtime library /// diff --git a/sdk/include/FidelityFX/host/ffx_cacao.h b/sdk/include/FidelityFX/host/ffx_cacao.h index e6558d49..52132d81 100644 --- a/sdk/include/FidelityFX/host/ffx_cacao.h +++ b/sdk/include/FidelityFX/host/ffx_cacao.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 diff --git a/sdk/include/FidelityFX/host/ffx_cas.h b/sdk/include/FidelityFX/host/ffx_cas.h index ae63c7df..f1eedf83 100644 --- a/sdk/include/FidelityFX/host/ffx_cas.h +++ b/sdk/include/FidelityFX/host/ffx_cas.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // @defgroup CAS #pragma once diff --git a/sdk/include/FidelityFX/host/ffx_classifier.h b/sdk/include/FidelityFX/host/ffx_classifier.h index e7049115..06951b15 100644 --- a/sdk/include/FidelityFX/host/ffx_classifier.h +++ b/sdk/include/FidelityFX/host/ffx_classifier.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + // @defgroup Classifier #pragma once diff --git a/sdk/include/FidelityFX/host/ffx_denoiser.h b/sdk/include/FidelityFX/host/ffx_denoiser.h index 3f80600f..e9540e08 100644 --- a/sdk/include/FidelityFX/host/ffx_denoiser.h +++ b/sdk/include/FidelityFX/host/ffx_denoiser.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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 the interface for the backend of the Denoiser API. @@ -55,7 +55,7 @@ /// The size of the context specified in 32bit values. /// /// @ingroup Denoiser -#define FFX_DENOISER_CONTEXT_SIZE (20014) +#define FFX_DENOISER_CONTEXT_SIZE (20018) #if defined(__cplusplus) extern "C" { diff --git a/sdk/include/FidelityFX/host/ffx_dof.h b/sdk/include/FidelityFX/host/ffx_dof.h index 41993148..aa553582 100644 --- a/sdk/include/FidelityFX/host/ffx_dof.h +++ b/sdk/include/FidelityFX/host/ffx_dof.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // @defgroup DOF #pragma once diff --git a/sdk/include/FidelityFX/host/ffx_error.h b/sdk/include/FidelityFX/host/ffx_error.h index 8875eccb..d1d466fe 100644 --- a/sdk/include/FidelityFX/host/ffx_error.h +++ b/sdk/include/FidelityFX/host/ffx_error.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 diff --git a/sdk/include/FidelityFX/host/ffx_frameinterpolation.h b/sdk/include/FidelityFX/host/ffx_frameinterpolation.h new file mode 100644 index 00000000..8b17cb26 --- /dev/null +++ b/sdk/include/FidelityFX/host/ffx_frameinterpolation.h @@ -0,0 +1,242 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +// @defgroup FRAMEINTERPOLATION + +#pragma once + +// Include the interface for the backend of the Frameinterpolation API. +#include + +/// FidelityFX Frameinterpolation major version. +/// +/// @ingroup FRAMEINTERPOLATIONFRAMEINTERPOLATION +#define FFX_FRAMEINTERPOLATION_VERSION_MAJOR (1) + +/// FidelityFX Frameinterpolation minor version. +/// +/// @ingroup FRAMEINTERPOLATIONFRAMEINTERPOLATION +#define FFX_FRAMEINTERPOLATION_VERSION_MINOR (0) + +/// FidelityFX Frameinterpolation patch version. +/// +/// @ingroup FRAMEINTERPOLATIONFRAMEINTERPOLATION +#define FFX_FRAMEINTERPOLATION_VERSION_PATCH (0) + +/// FidelityFX Frame Interpolation context count +/// +/// Defines the number of internal effect contexts required by Frame Interpolation +/// +/// @ingroup ffxFrameInterpolation +#define FFX_FRAMEINTERPOLATION_CONTEXT_COUNT (1) + +/// The size of the context specified in 32bit values. +/// +/// @ingroup FRAMEINTERPOLATIONFRAMEINTERPOLATION +#define FFX_FRAMEINTERPOLATION_CONTEXT_SIZE (FFX_SDK_DEFAULT_CONTEXT_SIZE) + +#if defined(__cplusplus) +extern "C" { +#endif // #if defined(__cplusplus) + +/// An enumeration of all the passes which constitute the FSR3 algorithm. +/// +/// FSR3 is implemented as a composite of several compute passes each +/// computing a key part of the final result. Each call to the +/// FfxFsr3ScheduleGpuJobFunc callback function will +/// correspond to a single pass included in FfxFsr3Pass. For a +/// more comprehensive description of each pass, please refer to the FSR3 +/// reference documentation. +/// +/// Please note in some cases e.g.: FFX_FSR3_PASS_ACCUMULATE +/// and FFX_FSR3_PASS_ACCUMULATE_SHARPEN either one pass or the +/// other will be used (they are mutually exclusive). The choice of which will +/// depend on the way the FfxFsr3Context is created and the +/// precise contents of FfxFsr3DispatchParamters each time a call +/// is made to ffxFsr3ContextDispatch. +/// +/// @ingroup FRAMEINTERPOLATIONFRAMEINTERPOLATION +typedef enum FfxFrameInterpolationPass +{ + FFX_FRAMEINTERPOLATION_PASS_SETUP, + FFX_FRAMEINTERPOLATION_PASS_RECONSTRUCT_PREV_DEPTH, + FFX_FRAMEINTERPOLATION_PASS_GAME_MOTION_VECTOR_FIELD, + FFX_FRAMEINTERPOLATION_PASS_OPTICAL_FLOW_VECTOR_FIELD, + FFX_FRAMEINTERPOLATION_PASS_DISOCCLUSION_MASK, + FFX_FRAMEINTERPOLATION_PASS_INTERPOLATION, + FFX_FRAMEINTERPOLATION_PASS_INPAINTING_PYRAMID, + FFX_FRAMEINTERPOLATION_PASS_INPAINTING, + FFX_FRAMEINTERPOLATION_PASS_GAME_VECTOR_FIELD_INPAINTING_PYRAMID, + FFX_FRAMEINTERPOLATION_PASS_DEBUG_VIEW, + FFX_FRAMEINTERPOLATION_PASS_COUNT ///< The number of passes performed by FrameInterpolation. +} FfxFrameInterpolationPass; + +// forward declarations +struct FfxFrameInterpolationContext; + +/// An enumeration of bit flags used when creating a +/// FfxFrameInterpolationContext. See FfxFrameInterpolationContextDescription. +/// +/// @ingroup FRAMEINTERPOLATIONFRAMEINTERPOLATION +typedef enum FfxFrameInterpolationInitializationFlagBits { + + FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED = (1<<0), ///< A bit indicating that the input depth buffer data provided is inverted [1..0]. + FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INFINITE = (1<<1), ///< A bit indicating that the input depth buffer data provided is using an infinite far plane. + FFX_FRAMEINTERPOLATION_ENABLE_TEXTURE1D_USAGE = (1<<2), ///< A bit indicating that the backend should use 1D textures. + FFX_FRAMEINTERPOLATION_ENABLE_HDR_COLOR_INPUT = (1<<3) ///< A bit indicating that HDR values are present in the imaging pipeline. +} FfxFrameInterpolationInitializationFlagBits; + +/// A structure encapsulating the parameters required to initialize +/// FidelityFX Frameinterpolation upscaling. +/// +/// @ingroup FRAMEINTERPOLATION +typedef struct FfxFrameInterpolationContextDescription { + + FfxInterface backendInterface; ///< A set of pointers to the backend implementation for FidelityFX SDK + + uint32_t flags; ///< A collection of FfxFrameInterpolationInitializationFlagBits. + FfxDimensions2D maxRenderSize; ///< The maximum size that rendering will be performed at. + FfxDimensions2D displaySize; ///< The size of the presentation resolution + FfxSurfaceFormat backBufferFormat; +} FfxFrameInterpolationContextDescription; + +/// A structure encapsulating the FidelityFX Super Resolution 2 context. +/// +/// This sets up an object which contains all persistent internal data and +/// resources that are required by FSR3. +/// +/// The FfxFsr3Context object should have a lifetime matching +/// your use of FSR3. Before destroying the FSR3 context care should be taken +/// to ensure the GPU is not accessing the resources created or used by FSR3. +/// It is therefore recommended that the GPU is idle before destroying the +/// FSR3 context. +/// +/// @ingroup FRAMEINTERPOLATION +typedef struct FfxFrameInterpolationContext +{ + uint32_t data[FFX_FRAMEINTERPOLATION_CONTEXT_SIZE]; ///< An opaque set of uint32_t which contain the data for the context. +} FfxFrameInterpolationContext; + + +/// Create a FidelityFX Super Resolution 2 context from the parameters +/// programmed to the FfxFsr3CreateParams structure. +/// +/// The context structure is the main object used to interact with the FSR3 +/// API, and is responsible for the management of the internal resources used +/// by the FSR3 algorithm. When this API is called, multiple calls will be +/// made via the pointers contained in the callbacks structure. +/// These callbacks will attempt to retreive the device capabilities, and +/// create the internal resources, and pipelines required by FSR3's +/// frame-to-frame function. Depending on the precise configuration used when +/// creating the FfxFsr3Context a different set of resources and +/// pipelines might be requested via the callback functions. +/// +/// The flags included in the flags field of +/// FfxFsr3Context how match the configuration of your +/// application as well as the intended use of FSR3. It is important that these +/// flags are set correctly (as well as a correct programmed +/// FfxFsr3DispatchDescription) to ensure correct operation. It is +/// recommended to consult the overview documentation for further details on +/// how FSR3 should be integerated into an application. +/// +/// When the FfxFsr3Context is created, you should use the +/// ffxFsr3ContextDispatch function each frame where FSR3 +/// upscaling should be applied. See the documentation of +/// ffxFsr3ContextDispatch for more details. +/// +/// The FfxFsr3Context should be destroyed when use of it is +/// completed, typically when an application is unloaded or FSR3 upscaling is +/// disabled by a user. To destroy the FSR3 context you should call +/// ffxFsr3ContextDestroy. +/// +/// @param [out] context A pointer to a FfxFsr3Context structure to populate. +/// @param [in] contextDescription A pointer to a FfxFsr3ContextDescription structure. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_CODE_NULL_POINTER The operation failed because either context or contextDescription was NULL. +/// @retval +/// FFX_ERROR_INCOMPLETE_INTERFACE The operation failed because the FfxFsr3ContextDescription.callbacks was not fully specified. +/// @retval +/// FFX_ERROR_BACKEND_API_ERROR The operation failed because of an error returned from the backend. +/// +/// @ingroup FRAMEINTERPOLATION +FFX_API FfxErrorCode ffxFrameInterpolationContextCreate(FfxFrameInterpolationContext* context, FfxFrameInterpolationContextDescription* contextDescription); + +typedef enum FfxFrameInterpolationDispatchFlags +{ + FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_TEAR_LINES = (1 << 0), ///< A bit indicating that the debug tear lines will be drawn to the interpolated output. + FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_VIEW = (1 << 1), ///< A bit indicating that the interpolated output resource will contain debug views with relevant information. +} FfxFrameInterpolationDispatchFlags; + +typedef struct FfxFrameInterpolationDispatchDescription { + + uint32_t flags; ///< combination of FfxFrameInterpolationDispatchFlags + FfxCommandList commandList; ///< The FfxCommandList to record frame interpolation commands into. + FfxDimensions2D displaySize; ///< The destination output dimensions + FfxDimensions2D renderSize; ///< The dimensions used to render game content, dilatedDepth, dilatedMotionVectors are expected to be of ths size. + FfxResource currentBackBuffer; ///< The current presentation color, if currentBackBuffer_HUDLess is not used, this will be used as interpolation source data. + FfxResource currentBackBuffer_HUDLess; ///< The current presentation color without HUD content, when use it will be used as interpolation source data. + FfxResource output; ///< The output resource where to store the interpolated result. + FfxResource dilatedDepth; ///< The dilated depth buffer data (see example computation in the FfxFsr3Upscaler effect) + FfxResource dilatedMotionVectors; ///< The dilated motion vector data (see example computation in the FfxFsr3Upscaler effect) + FfxResource reconstructPrevNearDepth; ///< The estimated previous frame depth buffer (see example computation in the FfxFsr3Upscaler effect) + + FfxRect2D interpolationRect; ///< The area of the backbuffer that should be used for interpolation in case only a part of the screen is used e.g. due to movie bars + + FfxResource opticalFlowVector; ///< The optical flow motion vectors (see example computation in the FfxOpticalFlow effect) + FfxResource opticalFlowSceneChangeDetection; ///< The optical flow scene change detection data + FfxDimensions2D opticalFlowBufferSize; ///< The optical flow motion vector resource dimensions + FfxFloatCoords2D opticalFlowScale; ///< The optical flow motion vector scale factor, used to scale resoure values into [0.0,1.0] range. + int opticalFlowBlockSize; ///< The optical flow block dimension size + + float cameraNear; ///< The distance to the near plane of the camera. + float cameraFar; ///< The distance to the far plane of the camera. This is used only used in case of non infinite depth. + float cameraFovAngleVertical; ///< The camera angle field of view in the vertical direction (expressed in radians). + float viewSpaceToMetersFactor; ///< The unit to scale view space coordinates to meters. + + float frameTimeDelta; ///< The time elapsed since the last frame (expressed in milliseconds). + bool reset; ///< A boolean value which when set to true, indicates the camera has moved discontinuously. + + FfxBackbufferTransferFunction backBufferTransferFunction; ///< The transfer function use to convert interpolation source color data to linear RGB. + float minMaxLuminance[2]; ///< Min and max luminance values, used when converting HDR colors to linear RGB + +} FfxFrameInterpolationDispatchDescription; + +FFX_API FfxErrorCode ffxFrameInterpolationDispatch(FfxFrameInterpolationContext* context, const FfxFrameInterpolationDispatchDescription* params); + +/// Destroy the FidelityFX Super Resolution context. +/// +/// @param [out] context A pointer to a FfxFsr3Context structure to destroy. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_CODE_NULL_POINTER The operation failed because either context was NULL. +/// +/// @ingroup FRAMEINTERPOLATION +FFX_API FfxErrorCode ffxFrameInterpolationContextDestroy(FfxFrameInterpolationContext* context); + +#if defined(__cplusplus) +} +#endif // #if defined(__cplusplus) diff --git a/sdk/include/FidelityFX/host/ffx_fsr1.h b/sdk/include/FidelityFX/host/ffx_fsr1.h index 1b9d88e5..a06858ca 100644 --- a/sdk/include/FidelityFX/host/ffx_fsr1.h +++ b/sdk/include/FidelityFX/host/ffx_fsr1.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + /// @defgroup ffxFsr1 FidelityFX FSR1 /// FidelityFX Super Resolution 1 runtime library /// diff --git a/sdk/include/FidelityFX/host/ffx_fsr2.h b/sdk/include/FidelityFX/host/ffx_fsr2.h index 3be82be0..3711ed84 100644 --- a/sdk/include/FidelityFX/host/ffx_fsr2.h +++ b/sdk/include/FidelityFX/host/ffx_fsr2.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 the interface for the backend of the FSR2 API. @@ -55,7 +55,7 @@ /// The size of the context specified in 32bit values. /// /// @ingroup ffxFsr2 -#define FFX_FSR2_CONTEXT_SIZE (24576) +#define FFX_FSR2_CONTEXT_SIZE (FFX_SDK_DEFAULT_CONTEXT_SIZE) #if defined(__cplusplus) extern "C" { diff --git a/sdk/include/FidelityFX/host/ffx_fsr3.h b/sdk/include/FidelityFX/host/ffx_fsr3.h new file mode 100644 index 00000000..d4d00e00 --- /dev/null +++ b/sdk/include/FidelityFX/host/ffx_fsr3.h @@ -0,0 +1,503 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +// @defgroup FSR3 + +#pragma once + +// Include the interface for the backend of the FSR3 API. +#include +#include +#include +#include + +/// FidelityFX Super Resolution 3 major version. +/// +/// @ingroup FSR3 +#define FFX_FSR3_VERSION_MAJOR (3) + +/// FidelityFX Super Resolution 0 minor version. +/// +/// @ingroup FSR3 +#define FFX_FSR3_VERSION_MINOR (0) + +/// FidelityFX Super Resolution 0 patch version. +/// +/// @ingroup FSR3 +#define FFX_FSR3_VERSION_PATCH (3) + +/// FidelityFX Super Resolution 3 context count +/// +/// Defines the number of internal effect contexts required by FSR3 (+1 for proxy swapchain) +/// +/// @ingroup ffxFsr3 +#define FFX_FSR3_CONTEXT_COUNT (FFX_FSR3UPSCALER_CONTEXT_COUNT + FFX_OPTICALFLOW_CONTEXT_COUNT + FFX_FRAMEINTERPOLATION_CONTEXT_COUNT + 1) + +/// The size of the context specified in 32bit values. +/// +/// @ingroup FSR3 +#define FFX_FSR3_CONTEXT_SIZE (16536) + +#if defined(__cplusplus) +extern "C" { +#endif // #if defined(__cplusplus) + +///// An enumeration of all the passes which constitute the FSR3 algorithm. +///// +///// FSR3 is implemented as a composite of several compute passes each +///// computing a key part of the final result. Each call to the +///// FfxFsr3ScheduleGpuJobFunc callback function will +///// correspond to a single pass included in FfxFsr3Pass. For a +///// more comprehensive description of each pass, please refer to the FSR3 +///// reference documentation. +///// +///// Please note in some cases e.g.: FFX_FSR3_PASS_ACCUMULATE +///// and FFX_FSR3_PASS_ACCUMULATE_SHARPEN either one pass or the +///// other will be used (they are mutually exclusive). The choice of which will +///// depend on the way the FfxFsr3Context is created and the +///// precise contents of FfxFsr3DispatchParamters each time a call +///// is made to ffxFsr3ContextDispatch. +///// +///// @ingroup FSR3 +//typedef enum FfxFsr3Pass +//{ +// // no special FSR3 pipelines +// +// FFX_FSR3_PASS_COUNT ///< The number of passes performed by FSR3. +//} FfxFsr3Pass; + +/// An enumeration of all the quality modes supported by FidelityFX Super +/// Resolution 2 upscaling. +/// +/// In order to provide a consistent user experience across multiple +/// applications which implement FSR3. It is strongly recommended that the +/// following preset scaling factors are made available through your +/// application's user interface. +/// +/// If your application does not expose the notion of preset scaling factors +/// for upscaling algorithms (perhaps instead implementing a fixed ratio which +/// is immutable) or implementing a more dynamic scaling scheme (such as +/// dynamic resolution scaling), then there is no need to use these presets. +/// +/// Please note that FFX_FSR3_QUALITY_MODE_ULTRA_PERFORMANCE is +/// an optional mode which may introduce significant quality degradation in the +/// final image. As such it is recommended that you evaluate the final results +/// of using this scaling mode before deciding if you should include it in your +/// application. +/// +/// @ingroup FSR3 +typedef enum FfxFsr3QualityMode { + + FFX_FSR3_QUALITY_MODE_QUALITY = 1, ///< Perform upscaling with a per-dimension upscaling ratio of 1.5x. + FFX_FSR3_QUALITY_MODE_BALANCED = 2, ///< Perform upscaling with a per-dimension upscaling ratio of 1.7x. + FFX_FSR3_QUALITY_MODE_PERFORMANCE = 3, ///< Perform upscaling with a per-dimension upscaling ratio of 2.0x. + FFX_FSR3_QUALITY_MODE_ULTRA_PERFORMANCE = 4 ///< Perform upscaling with a per-dimension upscaling ratio of 3.0x. +} FfxFsr3QualityMode; + +/// An enumeration of bit flags used when creating a +/// FfxFsr3Context. See FfxFsr3ContextDescription. +/// +/// @ingroup FSR3 +typedef enum FfxFsr3InitializationFlagBits { + + FFX_FSR3_ENABLE_HIGH_DYNAMIC_RANGE = (1<<0), ///< A bit indicating if the input color data provided to all inputs is using a high-dynamic range. + FFX_FSR3_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS = (1<<1), ///< A bit indicating if the motion vectors are rendered at display resolution. + FFX_FSR3_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION = (1<<2), ///< A bit indicating that the motion vectors have the jittering pattern applied to them. + FFX_FSR3_ENABLE_DEPTH_INVERTED = (1<<3), ///< A bit indicating that the input depth buffer data provided is inverted [1..0]. + FFX_FSR3_ENABLE_DEPTH_INFINITE = (1<<4), ///< A bit indicating that the input depth buffer data provided is using an infinite far plane. + FFX_FSR3_ENABLE_AUTO_EXPOSURE = (1<<5), ///< A bit indicating if automatic exposure should be applied to input color data. + FFX_FSR3_ENABLE_DYNAMIC_RESOLUTION = (1<<6), ///< A bit indicating that the application uses dynamic resolution scaling. + FFX_FSR3_ENABLE_TEXTURE1D_USAGE = (1<<7), ///< A bit indicating that the backend should use 1D textures. + FFX_FSR3_ENABLE_DEBUG_CHECKING = (1<<8), ///< A bit indicating that the runtime should check some API values and report issues. + FFX_FSR3_ENABLE_UPSCALING_ONLY = (1<<9), ///, A bit indicating that the context will only be used for upscaling + FFX_FSR3_ENABLE_HDR_UPSCALE_SDR_FINALOUTPUT = (1<<10), ///, A bit indicating if the input color data provided to UPSCALE is using a high-dynamic range, final output SDR. + FFX_FSR3_ENABLE_SDR_UPSCALE_HDR_FINALOUTPUT = (1<<11), ///, A bit indicating if the input color data provided to UPSCALE is using SDR, final output is high-dynamic range. + FFX_FSR3_ENABLE_ASYNC_WORKLOAD_SUPPORT = (1<<12), +} FfxFsr3InitializationFlagBits; + +typedef enum FfxFsr3FrameGenerationFlags +{ + FFX_FSR3_FRAME_GENERATION_FLAG_DRAW_DEBUG_TEAR_LINES = FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_TEAR_LINES, ///< A bit indicating that the debug tear lines will be drawn to the interpolated output. + FFX_FSR3_FRAME_GENERATION_FLAG_DRAW_DEBUG_VIEW = FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_VIEW, ///< A bit indicating that the interpolated output resource will contain debug views with relevant information. +} FfxFsr3FrameGenerationFlags; + +/// A structure encapsulating the parameters required to initialize FidelityFX +/// Super Resolution 3 upscaling. +/// +/// @ingroup FSR3 +typedef struct FfxFsr3ContextDescription { + uint32_t flags; ///< A collection of FfxFsr3InitializationFlagBits. + FfxDimensions2D maxRenderSize; ///< The maximum size that rendering will be performed at. + FfxDimensions2D upscaleOutputSize; ///< The size of the presentation resolution targeted by the upscaling process. + FfxDimensions2D displaySize; ///< The size of the presentation resolution targeted by the frame interpolation process. + FfxInterface backendInterfaceSharedResources; ///< A set of pointers to the backend implementation for FidelityFX SDK + FfxInterface backendInterfaceUpscaling; ///< A set of pointers to the backend implementation for FidelityFX SDK + FfxInterface backendInterfaceFrameInterpolation; ///< A set of pointers to the backend implementation for FidelityFX SDK + FfxFsr3UpscalerMessage fpMessage; ///< A pointer to a function that can recieve messages from the runtime. + + FfxSurfaceFormat backBufferFormat; ///< The format of the swapchain surface + +} FfxFsr3ContextDescription; + +/// A structure encapsulating the parameters for dispatching the various passes +/// of FidelityFX Super Resolution 3. +/// +/// @ingroup FSR3 +typedef struct FfxFsr3DispatchUpscaleDescription { + + FfxCommandList commandList; ///< The FfxCommandList to record FSR2 rendering commands into. + FfxResource color; ///< A FfxResource containing the color buffer for the current frame (at render resolution). + FfxResource depth; ///< A FfxResource containing 32bit depth values for the current frame (at render resolution). + FfxResource motionVectors; ///< A FfxResource containing 2-dimensional motion vectors (at render resolution if FFX_FSR2_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS is not set). + FfxResource exposure; ///< A optional FfxResource containing a 1x1 exposure value. + FfxResource reactive; ///< A optional FfxResource containing alpha value of reactive objects in the scene. + FfxResource transparencyAndComposition; ///< A optional FfxResource containing alpha value of special objects in the scene. + FfxResource upscaleOutput; ///< A FfxResource containing the output color buffer for the current frame (at presentation resolution). + FfxFloatCoords2D jitterOffset; ///< The subpixel jitter offset applied to the camera. + FfxFloatCoords2D motionVectorScale; ///< The scale factor to apply to motion vectors. + FfxDimensions2D renderSize; ///< The resolution that was used for rendering the input resources. + bool enableSharpening; ///< Enable an additional sharpening pass. + float sharpness; ///< The sharpness value between 0 and 1, where 0 is no additional sharpness and 1 is maximum additional sharpness. + float frameTimeDelta; ///< The time elapsed since the last frame (expressed in milliseconds). + float preExposure; ///< The pre exposure value (must be > 0.0f) + bool reset; ///< A boolean value which when set to true, indicates the camera has moved discontinuously. + float cameraNear; ///< The distance to the near plane of the camera. + float cameraFar; ///< The distance to the far plane of the camera. This is used only used in case of non infinite depth. + float cameraFovAngleVertical; ///< The camera angle field of view in the vertical direction (expressed in radians). + float viewSpaceToMetersFactor; ///< The scale factor to convert view space units to meters +} FfxFsr3DispatchUpscaleDescription; + +FFX_API FfxErrorCode ffxFsr3DispatchFrameGeneration(const FfxFrameGenerationDispatchDescription* desc); + +/// A structure encapsulating the parameters for automatic generation of a reactive mask +/// +/// @ingroup FSR3 +typedef struct FfxFsr3GenerateReactiveDescription { + + FfxCommandList commandList; ///< The FfxCommandList to record FSR3 rendering commands into. + FfxResource colorOpaqueOnly; ///< A FfxResource containing the opaque only color buffer for the current frame (at render resolution). + FfxResource colorPreUpscale; ///< A FfxResource containing the opaque+translucent color buffer for the current frame (at render resolution). + FfxResource outReactive; ///< A FfxResource containing the surface to generate the reactive mask into. + FfxDimensions2D renderSize; ///< The resolution that was used for rendering the input resources. + float scale; ///< A value to scale the output + float cutoffThreshold; ///< A threshold value to generate a binary reactive mask + float binaryValue; + uint32_t flags; ///< Flags to determine how to generate the reactive mask +} FfxFsr3GenerateReactiveDescription; + +/// A structure encapsulating the FidelityFX Super Resolution 3 context. +/// +/// This sets up an object which contains all persistent internal data and +/// resources that are required by FSR3. +/// +/// The FfxFsr3Context object should have a lifetime matching +/// your use of FSR3. Before destroying the FSR3 context care should be taken +/// to ensure the GPU is not accessing the resources created or used by FSR3. +/// It is therefore recommended that the GPU is idle before destroying the +/// FSR3 context. +/// +/// @ingroup FSR3 +typedef struct FfxFsr3Context +{ + uint32_t data[ FFX_FSR3UPSCALER_CONTEXT_SIZE + + FFX_OPTICALFLOW_CONTEXT_SIZE + + FFX_FRAMEINTERPOLATION_CONTEXT_SIZE + + (16536)]; ///< An opaque set of uint32_t which contain the data for the context. +} FfxFsr3Context; + +/// Create a FidelityFX Super Resolution 3 context from the parameters +/// programmed to the FfxFsr3CreateParams structure. +/// +/// The context structure is the main object used to interact with the FSR3 +/// API, and is responsible for the management of the internal resources used +/// by the FSR3 algorithm. When this API is called, multiple calls will be +/// made via the pointers contained in the callbacks structure. +/// These callbacks will attempt to retreive the device capabilities, and +/// create the internal resources, and pipelines required by FSR3's +/// frame-to-frame function. Depending on the precise configuration used when +/// creating the FfxFsr3Context a different set of resources and +/// pipelines might be requested via the callback functions. +/// +/// The flags included in the flags field of +/// FfxFsr3Context how match the configuration of your +/// application as well as the intended use of FSR3. It is important that these +/// flags are set correctly (as well as a correct programmed +/// FfxFsr3DispatchDescription) to ensure correct operation. It is +/// recommended to consult the overview documentation for further details on +/// how FSR3 should be integerated into an application. +/// +/// When the FfxFsr3Context is created, you should use the +/// ffxFsr3ContextDispatch function each frame where FSR3 +/// upscaling should be applied. See the documentation of +/// ffxFsr3ContextDispatch for more details. +/// +/// The FfxFsr3Context should be destroyed when use of it is +/// completed, typically when an application is unloaded or FSR3 upscaling is +/// disabled by a user. To destroy the FSR3 context you should call +/// ffxFsr3ContextDestroy. +/// +/// @param [out] context A pointer to a FfxFsr3Context structure to populate. +/// @param [in] contextDescription A pointer to a FfxFsr3ContextDescription structure. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_CODE_NULL_POINTER The operation failed because either context or contextDescription was NULL. +/// @retval +/// FFX_ERROR_INCOMPLETE_INTERFACE The operation failed because the FfxFsr3ContextDescription.callbacks was not fully specified. +/// @retval +/// FFX_ERROR_BACKEND_API_ERROR The operation failed because of an error returned from the backend. +/// +/// @ingroup FSR3 +FFX_API FfxErrorCode ffxFsr3ContextCreate(FfxFsr3Context* context, FfxFsr3ContextDescription* contextDescription); + + +/// Dispatch the various passes that constitute FidelityFX Super Resolution 3 Upscaling. +/// +/// FSR3 is a composite effect, meaning that it is compromised of multiple +/// constituent passes (implemented as one or more clears, copies and compute +/// dispatches). The ffxFsr3ContextDispatchUpscale function is the +/// function which (via the use of the functions contained in the +/// callbacks field of the FfxFsr3Context +/// structure) utlimately generates the sequence of graphics API calls required +/// each frame. +/// +/// As with the creation of the FfxFsr3Context correctly +/// programming the dispatchParams is key to ensuring +/// the correct operation of FSR3. It is particularly important to ensure that +/// camera jitter is correctly applied to your application's projection matrix +/// (or camera origin for raytraced applications). FSR3 provides the +/// ffxFsr3GetJitterPhaseCount and +/// ffxFsr3GetJitterOffset entry points to help applications +/// correctly compute the camera jitter. Whatever jitter pattern is used by the +/// application it should be correctly programmed to the +/// jitterOffset field of the dispatchParams +/// structure. For more guidance on camera jitter please consult the +/// documentation for ffxFsr3GetJitterOffset as well as the +/// accompanying overview documentation for FSR3. +/// +/// @param [in] context A pointer to a FfxFsr3Context structure. +/// @param [in] dispatchParams A pointer to a FfxFsr3DispatchUpscaleDescription structure. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_CODE_NULL_POINTER The operation failed because either context or dispatchParams was NULL. +/// @retval +/// FFX_ERROR_OUT_OF_RANGE The operation failed because dispatchParams.renderSize was larger than the maximum render resolution. +/// @retval +/// FFX_ERROR_NULL_DEVICE The operation failed because the device inside the context was NULL. +/// @retval +/// FFX_ERROR_BACKEND_API_ERROR The operation failed because of an error returned from the backend. +/// +/// @ingroup FSR3 +FFX_API FfxErrorCode ffxFsr3ContextDispatchUpscale(FfxFsr3Context* context, const FfxFsr3DispatchUpscaleDescription* dispatchParams); + +FFX_API FfxErrorCode ffxFsr3SkipPresent(FfxFsr3Context* context); + +/// A helper function generate a Reactive mask from an opaque only texure and one containing translucent objects. +/// +/// @param [in] context A pointer to a FfxFsr3Context structure. +/// @param [in] params A pointer to a FfxFsr3GenerateReactiveDescription structure +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// +/// @ingroup FSR3 +FFX_API FfxErrorCode ffxFsr3ContextGenerateReactiveMask(FfxFsr3Context* context, const FfxFsr3GenerateReactiveDescription* params); + +FFX_API FfxErrorCode ffxFsr3ConfigureFrameGeneration(FfxFsr3Context* context, const FfxFrameGenerationConfig* config); + +/// Destroy the FidelityFX Super Resolution context. +/// +/// @param [out] context A pointer to a FfxFsr3Context structure to destroy. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_CODE_NULL_POINTER The operation failed because either context was NULL. +/// +/// @ingroup FSR3 +FFX_API FfxErrorCode ffxFsr3ContextDestroy(FfxFsr3Context* context); + +/// Get the upscale ratio from the quality mode. +/// +/// The following table enumerates the mapping of the quality modes to +/// per-dimension scaling ratios. +/// +/// Quality preset | Scale factor +/// ----------------------------------------------------- | ------------- +/// FFX_FSR3_QUALITY_MODE_NATIVEAA | 1.0x +/// FFX_FSR3_QUALITY_MODE_QUALITY | 1.5x +/// FFX_FSR3_QUALITY_MODE_BALANCED | 1.7x +/// FFX_FSR3_QUALITY_MODE_PERFORMANCE | 2.0x +/// FFX_FSR3_QUALITY_MODE_ULTRA_PERFORMANCE | 3.0x +/// +/// Passing an invalid qualityMode will return 0.0f. +/// +/// @param [in] qualityMode The quality mode preset. +/// +/// @returns +/// The upscaling the per-dimension upscaling ratio for +/// qualityMode according to the table above. +/// +/// @ingroup FSR3 +FFX_API float ffxFsr3GetUpscaleRatioFromQualityMode(FfxFsr3QualityMode qualityMode); + +/// A helper function to calculate the rendering resolution from a target +/// resolution and desired quality level. +/// +/// This function applies the scaling factor returned by +/// ffxFsr3GetUpscaleRatioFromQualityMode to each dimension. +/// +/// @param [out] renderWidth A pointer to a uint32_t which will hold the calculated render resolution width. +/// @param [out] renderHeight A pointer to a uint32_t which will hold the calculated render resolution height. +/// @param [in] displayWidth The target display resolution width. +/// @param [in] displayHeight The target display resolution height. +/// @param [in] qualityMode The desired quality mode for FSR 2 upscaling. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_INVALID_POINTER Either renderWidth or renderHeight was NULL. +/// @retval +/// FFX_ERROR_INVALID_ENUM An invalid quality mode was specified. +/// +/// @ingroup FSR3 +FFX_API FfxErrorCode ffxFsr3GetRenderResolutionFromQualityMode( + uint32_t* renderWidth, + uint32_t* renderHeight, + uint32_t displayWidth, + uint32_t displayHeight, + FfxFsr3QualityMode qualityMode); + +/// A helper function to calculate the jitter phase count from display +/// resolution. +/// +/// For more detailed information about the application of camera jitter to +/// your application's rendering please refer to the +/// ffxFsr3GetJitterOffset function. +/// +/// The table below shows the jitter phase count which this function +/// would return for each of the quality presets. +/// +/// Quality preset | Scale factor | Phase count +/// ----------------------------------------------------- | ------------- | --------------- +/// FFX_FSR3_QUALITY_MODE_QUALITY | 1.5x | 18 +/// FFX_FSR3_QUALITY_MODE_BALANCED | 1.7x | 23 +/// FFX_FSR3_QUALITY_MODE_PERFORMANCE | 2.0x | 32 +/// FFX_FSR3_QUALITY_MODE_ULTRA_PERFORMANCE | 3.0x | 72 +/// Custom | [1..n]x | ceil(8*n^2) +/// +/// @param [in] renderWidth The render resolution width. +/// @param [in] displayWidth The display resolution width. +/// +/// @returns +/// The jitter phase count for the scaling factor between renderWidth and displayWidth. +/// +/// @ingroup FSR3 +FFX_API int32_t ffxFsr3GetJitterPhaseCount(int32_t renderWidth, int32_t displayWidth); + +/// A helper function to calculate the subpixel jitter offset. +/// +/// FSR3 relies on the application to apply sub-pixel jittering while rendering. +/// This is typically included in the projection matrix of the camera. To make +/// the application of camera jitter simple, the FSR3 API provides a small set +/// of utility function which computes the sub-pixel jitter offset for a +/// particular frame within a sequence of separate jitter offsets. To begin, the +/// index within the jitter phase must be computed. To calculate the +/// sequence's length, you can call the ffxFsr3GetJitterPhaseCount +/// function. The index should be a value which is incremented each frame modulo +/// the length of the sequence computed by ffxFsr3GetJitterPhaseCount. +/// The index within the jitter phase is passed to +/// ffxFsr3GetJitterOffset via the index parameter. +/// +/// This function uses a Halton(2,3) sequence to compute the jitter offset. +/// The ultimate index used for the sequence is index % +/// phaseCount. +/// +/// It is important to understand that the values returned from the +/// ffxFsr3GetJitterOffset function are in unit pixel space, and +/// in order to composite this correctly into a projection matrix we must +/// convert them into projection offsets. This is done as per the pseudo code +/// listing which is shown below. +/// +/// const int32_t jitterPhaseCount = ffxFsr3GetJitterPhaseCount(renderWidth, displayWidth); +/// +/// float jitterX = 0; +/// float jitterY = 0; +/// ffxFsr3GetJitterOffset(&jitterX, &jitterY, index, jitterPhaseCount); +/// +/// const float jitterX = 2.0f * jitterX / (float)renderWidth; +/// const float jitterY = -2.0f * jitterY / (float)renderHeight; +/// const Matrix4 jitterTranslationMatrix = translateMatrix(Matrix3::identity, Vector3(jitterX, jitterY, 0)); +/// const Matrix4 jitteredProjectionMatrix = jitterTranslationMatrix * projectionMatrix; +/// +/// Jitter should be applied to all rendering. This includes opaque, alpha +/// transparent, and raytraced objects. For rasterized objects, the sub-pixel +/// jittering values calculated by the iffxFsr3GetJitterOffset +/// function can be applied to the camera projection matrix which is ultimately +/// used to perform transformations during vertex shading. For raytraced +/// rendering, the sub-pixel jitter should be applied to the ray's origin, +/// often the camera's position. +/// +/// Whether you elect to use the ffxFsr3GetJitterOffset function +/// or your own sequence generator, you must program the +/// jitterOffset field of the +/// FfxFsr3DispatchParameters structure in order to inform FSR3 +/// of the jitter offset that has been applied in order to render each frame. +/// +/// If not using the recommended ffxFsr3GetJitterOffset function, +/// care should be taken that your jitter sequence never generates a null vector; +/// that is value of 0 in both the X and Y dimensions. +/// +/// @param [out] outX A pointer to a float which will contain the subpixel jitter offset for the x dimension. +/// @param [out] outY A pointer to a float which will contain the subpixel jitter offset for the y dimension. +/// @param [in] index The index within the jitter sequence. +/// @param [in] phaseCount The length of jitter phase. See ffxFsr3GetJitterPhaseCount. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_INVALID_POINTER Either outX or outY was NULL. +/// @retval +/// FFX_ERROR_INVALID_ARGUMENT Argument phaseCount must be greater than 0. +/// +/// @ingroup FSR3 +FFX_API FfxErrorCode ffxFsr3GetJitterOffset(float* outX, float* outY, int32_t index, int32_t phaseCount); + +/// A helper function to check if a resource is +/// FFX_FSR3_RESOURCE_IDENTIFIER_NULL. +/// +/// @param [in] resource A FfxResource. +/// +/// @returns +/// true The resource was not FFX_FSR3_RESOURCE_IDENTIFIER_NULL. +/// @returns +/// false The resource was FFX_FSR3_RESOURCE_IDENTIFIER_NULL. +/// +/// @ingroup FSR3 +FFX_API bool ffxFsr3ResourceIsNull(FfxResource resource); + +#if defined(__cplusplus) +} +#endif // #if defined(__cplusplus) diff --git a/sdk/include/FidelityFX/host/ffx_fsr3upscaler.h b/sdk/include/FidelityFX/host/ffx_fsr3upscaler.h new file mode 100644 index 00000000..83bee5d9 --- /dev/null +++ b/sdk/include/FidelityFX/host/ffx_fsr3upscaler.h @@ -0,0 +1,527 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 the interface for the backend of the FSR3 API. +#include +#include + +/// @defgroup ffxFsr3Upscaler FidelityFX FSR3 +/// FidelityFX Super Resolution 3 runtime library +/// +/// @ingroup SDKComponents + +/// FidelityFX Super Resolution 3 major version. +/// +/// @ingroup ffxFsr3Upscaler +#define FFX_FSR3UPSCALER_VERSION_MAJOR (3) + +/// FidelityFX Super Resolution 3 minor version. +/// +/// @ingroup ffxFsr3Upscaler +#define FFX_FSR3UPSCALER_VERSION_MINOR (0) + +/// FidelityFX Super Resolution 3 patch version. +/// +/// @ingroup ffxFsr3Upscaler +#define FFX_FSR3UPSCALER_VERSION_PATCH (3) + +/// FidelityFX Super Resolution 3 context count +/// +/// Defines the number of internal effect contexts required by FSR3 +/// +/// @ingroup ffxFsr3Upscaler +#define FFX_FSR3UPSCALER_CONTEXT_COUNT 1 + +/// The size of the context specified in 32bit values. +/// +/// @ingroup ffxFsr3Upscaler +#define FFX_FSR3UPSCALER_CONTEXT_SIZE (FFX_SDK_DEFAULT_CONTEXT_SIZE) + +#if defined(__cplusplus) +extern "C" { +#endif // #if defined(__cplusplus) + +/// An enumeration of all the passes which constitute the FSR3 algorithm. +/// +/// FSR3 is implemented as a composite of several compute passes each +/// computing a key part of the final result. Each call to the +/// FfxFsr3UpscalerScheduleGpuJobFunc callback function will +/// correspond to a single pass included in FfxFsr3UpscalerPass. For a +/// more comprehensive description of each pass, please refer to the FSR3 +/// reference documentation. +/// +/// Please note in some cases e.g.: FFX_FSR3UPSCALER_PASS_ACCUMULATE +/// and FFX_FSR3UPSCALER_PASS_ACCUMULATE_SHARPEN either one pass or the +/// other will be used (they are mutually exclusive). The choice of which will +/// depend on the way the FfxFsr3UpscalerContext is created and the +/// precise contents of FfxFsr3UpscalerDispatchParamters each time a call +/// is made to ffxFsr3UpscalerContextDispatch. +/// +/// @ingroup ffxFsr3Upscaler +typedef enum FfxFsr3UpscalerPass +{ + + FFX_FSR3UPSCALER_PASS_DEPTH_CLIP, ///< A pass which performs depth clipping. + FFX_FSR3UPSCALER_PASS_RECONSTRUCT_PREVIOUS_DEPTH, ///< A pass which performs reconstruction of previous frame's depth. + FFX_FSR3UPSCALER_PASS_LOCK, ///< A pass which calculates pixel locks. + FFX_FSR3UPSCALER_PASS_ACCUMULATE, ///< A pass which performs upscaling. + FFX_FSR3UPSCALER_PASS_ACCUMULATE_SHARPEN, ///< A pass which performs upscaling when sharpening is used. + FFX_FSR3UPSCALER_PASS_RCAS, ///< A pass which performs sharpening. + FFX_FSR3UPSCALER_PASS_COMPUTE_LUMINANCE_PYRAMID, ///< A pass which generates the luminance mipmap chain for the current frame. + FFX_FSR3UPSCALER_PASS_GENERATE_REACTIVE, ///< An optional pass to generate a reactive mask. + FFX_FSR3UPSCALER_PASS_TCR_AUTOGENERATE, ///< DEPRECATED - NO LONGER SUPPORTED + + FFX_FSR3UPSCALER_PASS_COUNT ///< The number of passes performed by FSR3. +} FfxFsr3UpscalerPass; + +/// An enumeration of all the quality modes supported by FidelityFX Super +/// Resolution 3 upscaling. +/// +/// In order to provide a consistent user experience across multiple +/// applications which implement FSR3. It is strongly recommended that the +/// following preset scaling factors are made available through your +/// application's user interface. +/// +/// If your application does not expose the notion of preset scaling factors +/// for upscaling algorithms (perhaps instead implementing a fixed ratio which +/// is immutable) or implementing a more dynamic scaling scheme (such as +/// dynamic resolution scaling), then there is no need to use these presets. +/// +/// Please note that FFX_FSR3UPSCALER_QUALITY_MODE_ULTRA_PERFORMANCE is +/// an optional mode which may introduce significant quality degradation in the +/// final image. As such it is recommended that you evaluate the final results +/// of using this scaling mode before deciding if you should include it in your +/// application. +/// +/// @ingroup ffxFsr3Upscaler +typedef enum FfxFsr3UpscalerQualityMode { + FFX_FSR3UPSCALER_QUALITY_MODE_NATIVEAA = 0, ///< Perform upscaling with a per-dimension upscaling ratio of 1.0x. + FFX_FSR3UPSCALER_QUALITY_MODE_QUALITY = 1, ///< Perform upscaling with a per-dimension upscaling ratio of 1.5x. + FFX_FSR3UPSCALER_QUALITY_MODE_BALANCED = 2, ///< Perform upscaling with a per-dimension upscaling ratio of 1.7x. + FFX_FSR3UPSCALER_QUALITY_MODE_PERFORMANCE = 3, ///< Perform upscaling with a per-dimension upscaling ratio of 2.0x. + FFX_FSR3UPSCALER_QUALITY_MODE_ULTRA_PERFORMANCE = 4 ///< Perform upscaling with a per-dimension upscaling ratio of 3.0x. +} FfxFsr3UpscalerQualityMode; + +/// An enumeration of bit flags used when creating a +/// FfxFsr3UpscalerContext. See FfxFsr3UpscalerContextDescription. +/// +/// @ingroup ffxFsr3Upscaler +typedef enum FfxFsr3UpscalerInitializationFlagBits { + + FFX_FSR3UPSCALER_ENABLE_HIGH_DYNAMIC_RANGE = (1<<0), ///< A bit indicating if the input color data provided is using a high-dynamic range. + FFX_FSR3UPSCALER_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS = (1<<1), ///< A bit indicating if the motion vectors are rendered at display resolution. + FFX_FSR3UPSCALER_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION = (1<<2), ///< A bit indicating that the motion vectors have the jittering pattern applied to them. + FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED = (1<<3), ///< A bit indicating that the input depth buffer data provided is inverted [1..0]. + FFX_FSR3UPSCALER_ENABLE_DEPTH_INFINITE = (1<<4), ///< A bit indicating that the input depth buffer data provided is using an infinite far plane. + FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE = (1<<5), ///< A bit indicating if automatic exposure should be applied to input color data. + FFX_FSR3UPSCALER_ENABLE_DYNAMIC_RESOLUTION = (1<<6), ///< A bit indicating that the application uses dynamic resolution scaling. + FFX_FSR3UPSCALER_ENABLE_TEXTURE1D_USAGE = (1<<7), ///< A bit indicating that the backend should use 1D textures. + FFX_FSR3UPSCALER_ENABLE_DEBUG_CHECKING = (1<<8), ///< A bit indicating that the runtime should check some API values and report issues. +} FfxFsr3UpscalerInitializationFlagBits; + +/// Pass a string message +/// +/// Used for debug messages. +/// +/// @param [in] type The type of message. +/// @param [in] message A string message to pass. +/// +/// +/// @ingroup ffxFsr3Upscaler +typedef void(*FfxFsr3UpscalerMessage)( + FfxMsgType type, + const wchar_t* message); + +/// A structure encapsulating the parameters required to initialize FidelityFX +/// Super Resolution 3 upscaling. +/// +/// @ingroup ffxFsr3Upscaler +typedef struct FfxFsr3UpscalerContextDescription { + + uint32_t flags; ///< A collection of FfxFsr3UpscalerInitializationFlagBits. + FfxDimensions2D maxRenderSize; ///< The maximum size that rendering will be performed at. + FfxDimensions2D displaySize; ///< The size of the presentation resolution targeted by the upscaling process. + FfxInterface backendInterface; ///< A set of pointers to the backend implementation for FidelityFX SDK + FfxFsr3UpscalerMessage fpMessage; ///< A pointer to a function that can receive messages from the runtime. +} FfxFsr3UpscalerContextDescription; + +/// A structure encapsulating the parameters for dispatching the various passes +/// of FidelityFX Super Resolution 3. +/// +/// @ingroup ffxFsr3Upscaler +typedef struct FfxFsr3UpscalerDispatchDescription { + + FfxCommandList commandList; ///< The FfxCommandList to record FSR3 rendering commands into. + FfxResource color; ///< A FfxResource containing the color buffer for the current frame (at render resolution). + FfxResource depth; ///< A FfxResource containing 32bit depth values for the current frame (at render resolution). + FfxResource motionVectors; ///< A FfxResource containing 2-dimensional motion vectors (at render resolution if FFX_FSR3UPSCALER_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS is not set). + FfxResource exposure; ///< A optional FfxResource containing a 1x1 exposure value. + FfxResource reactive; ///< A optional FfxResource containing alpha value of reactive objects in the scene. + FfxResource transparencyAndComposition; ///< A optional FfxResource containing alpha value of special objects in the scene. + FfxResource dilatedDepth; ///< A FfxResource allocated as described in FfxFsr3UpscalerSharedResourceDescriptions that is used to emit dilated depth and share with following effects. + FfxResource dilatedMotionVectors; ///< A FfxResource allocated as described in FfxFsr3UpscalerSharedResourceDescriptions that is used to emit dilated motion vectors and share with following effects. + FfxResource reconstructedPrevNearestDepth; ///< A FfxResource allocated as described in FfxFsr3UpscalerSharedResourceDescriptions that is used to emit reconstructed previous nearest depth and share with following effects. + FfxResource output; ///< A FfxResource containing the output color buffer for the current frame (at presentation resolution). + FfxFloatCoords2D jitterOffset; ///< The subpixel jitter offset applied to the camera. + FfxFloatCoords2D motionVectorScale; ///< The scale factor to apply to motion vectors. + FfxDimensions2D renderSize; ///< The resolution that was used for rendering the input resources. + bool enableSharpening; ///< Enable an additional sharpening pass. + float sharpness; ///< The sharpness value between 0 and 1, where 0 is no additional sharpness and 1 is maximum additional sharpness. + float frameTimeDelta; ///< The time elapsed since the last frame (expressed in milliseconds). + float preExposure; ///< The pre exposure value (must be > 0.0f) + bool reset; ///< A boolean value which when set to true, indicates the camera has moved discontinuously. + float cameraNear; ///< The distance to the near plane of the camera. + float cameraFar; ///< The distance to the far plane of the camera. + float cameraFovAngleVertical; ///< The camera angle field of view in the vertical direction (expressed in radians). + float viewSpaceToMetersFactor; ///< The scale factor to convert view space units to meters +} FfxFsr3UpscalerDispatchDescription; + +/// A structure encapsulating the parameters for automatic generation of a reactive mask +/// +/// @ingroup ffxFsr3Upscaler +typedef struct FfxFsr3UpscalerGenerateReactiveDescription { + + FfxCommandList commandList; ///< The FfxCommandList to record FSR3 rendering commands into. + FfxResource colorOpaqueOnly; ///< A FfxResource containing the opaque only color buffer for the current frame (at render resolution). + FfxResource colorPreUpscale; ///< A FfxResource containing the opaque+translucent color buffer for the current frame (at render resolution). + FfxResource outReactive; ///< A FfxResource containing the surface to generate the reactive mask into. + FfxDimensions2D renderSize; ///< The resolution that was used for rendering the input resources. + float scale; ///< A value to scale the output + float cutoffThreshold; ///< A threshold value to generate a binary reactive mask + float binaryValue; ///< A value to set for the binary reactive mask + uint32_t flags; ///< Flags to determine how to generate the reactive mask +} FfxFsr3UpscalerGenerateReactiveDescription; + +/// A structure encapsulating the resource descriptions for shared resources for this effect. +/// +/// @ingroup ffxFsr3Upscaler +typedef struct FfxFsr3UpscalerSharedResourceDescriptions { + + FfxCreateResourceDescription reconstructedPrevNearestDepth; ///< The FfxCreateResourceDescription for allocating the reconstructedPrevNearestDepth shared resource. + FfxCreateResourceDescription dilatedDepth; ///< The FfxCreateResourceDescription for allocating the dilatedDepth shared resource. + FfxCreateResourceDescription dilatedMotionVectors; ///< The FfxCreateResourceDescription for allocating the dilatedMotionVectors shared resource. +} FfxFsr3UpscalerSharedResourceDescriptions; + +/// A structure encapsulating the FidelityFX Super Resolution 3 context. +/// +/// This sets up an object which contains all persistent internal data and +/// resources that are required by FSR3. +/// +/// The FfxFsr3UpscalerContext object should have a lifetime matching +/// your use of FSR3. Before destroying the FSR3 context care should be taken +/// to ensure the GPU is not accessing the resources created or used by FSR3. +/// It is therefore recommended that the GPU is idle before destroying the +/// FSR3 context. +/// +/// @ingroup ffxFsr3Upscaler +typedef struct FfxFsr3UpscalerContext +{ + uint32_t data[FFX_FSR3UPSCALER_CONTEXT_SIZE]; ///< An opaque set of uint32_t which contain the data for the context. +} FfxFsr3UpscalerContext; + + +/// Create a FidelityFX Super Resolution 3 context from the parameters +/// programmed to the FfxFsr3UpscalerCreateParams structure. +/// +/// The context structure is the main object used to interact with the FSR3 +/// API, and is responsible for the management of the internal resources used +/// by the FSR3 algorithm. When this API is called, multiple calls will be +/// made via the pointers contained in the callbacks structure. +/// These callbacks will attempt to retreive the device capabilities, and +/// create the internal resources, and pipelines required by FSR3's +/// frame-to-frame function. Depending on the precise configuration used when +/// creating the FfxFsr3UpscalerContext a different set of resources and +/// pipelines might be requested via the callback functions. +/// +/// The flags included in the flags field of +/// FfxFsr3UpscalerContext how match the configuration of your +/// application as well as the intended use of FSR3. It is important that these +/// flags are set correctly (as well as a correct programmed +/// FfxFsr3UpscalerDispatchDescription) to ensure correct operation. It is +/// recommended to consult the overview documentation for further details on +/// how FSR3 should be integerated into an application. +/// +/// When the FfxFsr3UpscalerContext is created, you should use the +/// ffxFsr3UpscalerContextDispatch function each frame where FSR3 +/// upscaling should be applied. See the documentation of +/// ffxFsr3UpscalerContextDispatch for more details. +/// +/// The FfxFsr3UpscalerContext should be destroyed when use of it is +/// completed, typically when an application is unloaded or FSR3 upscaling is +/// disabled by a user. To destroy the FSR3 context you should call +/// ffxFsr3UpscalerContextDestroy. +/// +/// @param [out] pContext A pointer to a FfxFsr3UpscalerContext structure to populate. +/// @param [in] pContextDescription A pointer to a FfxFsr3UpscalerContextDescription structure. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_CODE_NULL_POINTER The operation failed because either context or contextDescription was NULL. +/// @retval +/// FFX_ERROR_INCOMPLETE_INTERFACE The operation failed because the FfxFsr3UpscalerContextDescription.callbacks was not fully specified. +/// @retval +/// FFX_ERROR_BACKEND_API_ERROR The operation failed because of an error returned from the backend. +/// +/// @ingroup ffxFsr3Upscaler +FFX_API FfxErrorCode ffxFsr3UpscalerContextCreate(FfxFsr3UpscalerContext* pContext, const FfxFsr3UpscalerContextDescription* pContextDescription); + +/// Provides the descriptions for shared resources that must be allocated for this effect. +/// +/// @param [in] context A pointer to a FfxFsr3UpscalerContext structure. +/// @param [out] SharedResources A pointer to a FfxFsr3UpscalerSharedResourceDescriptions to populate. +/// +/// @returns +/// FFX_OK The operation completed successfully. +/// @returns +/// Anything else The operation failed. +/// +/// @ingroup ffxFsr3Upscaler +FFX_API FfxErrorCode ffxFsr3UpscalerGetSharedResourceDescriptions(FfxFsr3UpscalerContext* context, FfxFsr3UpscalerSharedResourceDescriptions* SharedResources); + +/// Dispatch the various passes that constitute FidelityFX Super Resolution 3. +/// +/// FSR3 is a composite effect, meaning that it is compromised of multiple +/// constituent passes (implemented as one or more clears, copies and compute +/// dispatches). The ffxFsr3UpscalerContextDispatch function is the +/// function which (via the use of the functions contained in the +/// callbacks field of the FfxFsr3UpscalerContext +/// structure) utlimately generates the sequence of graphics API calls required +/// each frame. +/// +/// As with the creation of the FfxFsr3UpscalerContext correctly +/// programming the FfxFsr3UpscalerDispatchDescription is key to ensuring +/// the correct operation of FSR3. It is particularly important to ensure that +/// camera jitter is correctly applied to your application's projection matrix +/// (or camera origin for raytraced applications). FSR3 provides the +/// ffxFsr3UpscalerGetJitterPhaseCount and +/// ffxFsr3UpscalerGetJitterOffset entry points to help applications +/// correctly compute the camera jitter. Whatever jitter pattern is used by the +/// application it should be correctly programmed to the +/// jitterOffset field of the dispatchDescription +/// structure. For more guidance on camera jitter please consult the +/// documentation for ffxFsr3UpscalerGetJitterOffset as well as the +/// accompanying overview documentation for FSR3. +/// +/// @param [in] pContext A pointer to a FfxFsr3UpscalerContext structure. +/// @param [in] pDispatchDescription A pointer to a FfxFsr3UpscalerDispatchDescription structure. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_CODE_NULL_POINTER The operation failed because either context or dispatchDescription was NULL. +/// @retval +/// FFX_ERROR_OUT_OF_RANGE The operation failed because dispatchDescription.renderSize was larger than the maximum render resolution. +/// @retval +/// FFX_ERROR_NULL_DEVICE The operation failed because the device inside the context was NULL. +/// @retval +/// FFX_ERROR_BACKEND_API_ERROR The operation failed because of an error returned from the backend. +/// +/// @ingroup ffxFsr3Upscaler +FFX_API FfxErrorCode ffxFsr3UpscalerContextDispatch(FfxFsr3UpscalerContext* pContext, const FfxFsr3UpscalerDispatchDescription* pDispatchDescription); + +/// A helper function generate a Reactive mask from an opaque only texure and one containing translucent objects. +/// +/// @param [in] pContext A pointer to a FfxFsr3UpscalerContext structure. +/// @param [in] pParams A pointer to a FfxFsr3UpscalerGenerateReactiveDescription structure +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// +/// @ingroup ffxFsr3Upscaler +FFX_API FfxErrorCode ffxFsr3UpscalerContextGenerateReactiveMask(FfxFsr3UpscalerContext* pContext, const FfxFsr3UpscalerGenerateReactiveDescription* pParams); + +/// Destroy the FidelityFX Super Resolution context. +/// +/// @param [out] pContext A pointer to a FfxFsr3UpscalerContext structure to destroy. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_CODE_NULL_POINTER The operation failed because either context was NULL. +/// +/// @ingroup ffxFsr3Upscaler +FFX_API FfxErrorCode ffxFsr3UpscalerContextDestroy(FfxFsr3UpscalerContext* pContext); + +/// Get the upscale ratio from the quality mode. +/// +/// The following table enumerates the mapping of the quality modes to +/// per-dimension scaling ratios. +/// +/// Quality preset | Scale factor +/// ----------------------------------------------------- | ------------- +/// FFX_FSR3UPSCALER_QUALITY_MODE_QUALITY | 1.5x +/// FFX_FSR3UPSCALER_QUALITY_MODE_BALANCED | 1.7x +/// FFX_FSR3UPSCALER_QUALITY_MODE_PERFORMANCE | 2.0x +/// FFX_FSR3UPSCALER_QUALITY_MODE_ULTRA_PERFORMANCE | 3.0x +/// +/// Passing an invalid qualityMode will return 0.0f. +/// +/// @param [in] qualityMode The quality mode preset. +/// +/// @returns +/// The upscaling the per-dimension upscaling ratio for +/// qualityMode according to the table above. +/// +/// @ingroup ffxFsr3Upscaler +FFX_API float ffxFsr3UpscalerGetUpscaleRatioFromQualityMode(FfxFsr3UpscalerQualityMode qualityMode); + +/// A helper function to calculate the rendering resolution from a target +/// resolution and desired quality level. +/// +/// This function applies the scaling factor returned by +/// ffxFsr3UpscalerGetUpscaleRatioFromQualityMode to each dimension. +/// +/// @param [out] pRenderWidth A pointer to a uint32_t which will hold the calculated render resolution width. +/// @param [out] pRenderHeight A pointer to a uint32_t which will hold the calculated render resolution height. +/// @param [in] displayWidth The target display resolution width. +/// @param [in] displayHeight The target display resolution height. +/// @param [in] qualityMode The desired quality mode for FSR 2 upscaling. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_INVALID_POINTER Either renderWidth or renderHeight was NULL. +/// @retval +/// FFX_ERROR_INVALID_ENUM An invalid quality mode was specified. +/// +/// @ingroup ffxFsr3Upscaler +FFX_API FfxErrorCode ffxFsr3UpscalerGetRenderResolutionFromQualityMode( + uint32_t* pRenderWidth, + uint32_t* pRenderHeight, + uint32_t displayWidth, + uint32_t displayHeight, + FfxFsr3UpscalerQualityMode qualityMode); + +/// A helper function to calculate the jitter phase count from display +/// resolution. +/// +/// For more detailed information about the application of camera jitter to +/// your application's rendering please refer to the +/// ffxFsr3UpscalerGetJitterOffset function. +/// +/// The table below shows the jitter phase count which this function +/// would return for each of the quality presets. +/// +/// Quality preset | Scale factor | Phase count +/// ----------------------------------------------------- | ------------- | --------------- +/// FFX_FSR3UPSCALER_QUALITY_MODE_QUALITY | 1.5x | 18 +/// FFX_FSR3UPSCALER_QUALITY_MODE_BALANCED | 1.7x | 23 +/// FFX_FSR3UPSCALER_QUALITY_MODE_PERFORMANCE | 2.0x | 32 +/// FFX_FSR3UPSCALER_QUALITY_MODE_ULTRA_PERFORMANCE | 3.0x | 72 +/// Custom | [1..n]x | ceil(8*n^2) +/// +/// @param [in] renderWidth The render resolution width. +/// @param [in] displayWidth The display resolution width. +/// +/// @returns +/// The jitter phase count for the scaling factor between renderWidth and displayWidth. +/// +/// @ingroup ffxFsr3Upscaler +FFX_API int32_t ffxFsr3UpscalerGetJitterPhaseCount(int32_t renderWidth, int32_t displayWidth); + +/// A helper function to calculate the subpixel jitter offset. +/// +/// FSR3 relies on the application to apply sub-pixel jittering while rendering. +/// This is typically included in the projection matrix of the camera. To make +/// the application of camera jitter simple, the FSR3 API provides a small set +/// of utility function which computes the sub-pixel jitter offset for a +/// particular frame within a sequence of separate jitter offsets. To begin, the +/// index within the jitter phase must be computed. To calculate the +/// sequence's length, you can call the ffxFsr3UpscalerGetJitterPhaseCount +/// function. The index should be a value which is incremented each frame modulo +/// the length of the sequence computed by ffxFsr3UpscalerGetJitterPhaseCount. +/// The index within the jitter phase is passed to +/// ffxFsr3UpscalerGetJitterOffset via the index parameter. +/// +/// This function uses a Halton(2,3) sequence to compute the jitter offset. +/// The ultimate index used for the sequence is index % +/// phaseCount. +/// +/// It is important to understand that the values returned from the +/// ffxFsr3UpscalerGetJitterOffset function are in unit pixel space, and +/// in order to composite this correctly into a projection matrix we must +/// convert them into projection offsets. This is done as per the pseudo code +/// listing which is shown below. +/// +/// const int32_t jitterPhaseCount = ffxFsr3UpscalerGetJitterPhaseCount(renderWidth, displayWidth); +/// +/// float jitterX = 0; +/// float jitterY = 0; +/// ffxFsr3UpscalerGetJitterOffset(&jitterX, &jitterY, index, jitterPhaseCount); +/// +/// const float jitterX = 2.0f * jitterX / (float)renderWidth; +/// const float jitterY = -2.0f * jitterY / (float)renderHeight; +/// const Matrix4 jitterTranslationMatrix = translateMatrix(Matrix3::identity, Vector3(jitterX, jitterY, 0)); +/// const Matrix4 jitteredProjectionMatrix = jitterTranslationMatrix * projectionMatrix; +/// +/// Jitter should be applied to all rendering. This includes opaque, alpha +/// transparent, and raytraced objects. For rasterized objects, the sub-pixel +/// jittering values calculated by the iffxFsr3UpscalerGetJitterOffset +/// function can be applied to the camera projection matrix which is ultimately +/// used to perform transformations during vertex shading. For raytraced +/// rendering, the sub-pixel jitter should be applied to the ray's origin, +/// often the camera's position. +/// +/// Whether you elect to use the ffxFsr3UpscalerGetJitterOffset function +/// or your own sequence generator, you must program the +/// jitterOffset field of the +/// FfxFsr3UpscalerDispatchParameters structure in order to inform FSR3 +/// of the jitter offset that has been applied in order to render each frame. +/// +/// If not using the recommended ffxFsr3UpscalerGetJitterOffset function, +/// care should be taken that your jitter sequence never generates a null vector; +/// that is value of 0 in both the X and Y dimensions. +/// +/// @param [out] pOutX A pointer to a float which will contain the subpixel jitter offset for the x dimension. +/// @param [out] pOutY A pointer to a float which will contain the subpixel jitter offset for the y dimension. +/// @param [in] index The index within the jitter sequence. +/// @param [in] phaseCount The length of jitter phase. See ffxFsr3UpscalerGetJitterPhaseCount. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_INVALID_POINTER Either outX or outY was NULL. +/// @retval +/// FFX_ERROR_INVALID_ARGUMENT Argument phaseCount must be greater than 0. +/// +/// @ingroup ffxFsr3Upscaler +FFX_API FfxErrorCode ffxFsr3UpscalerGetJitterOffset(float* pOutX, float* pOutY, int32_t index, int32_t phaseCount); + +/// A helper function to check if a resource is +/// FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL. +/// +/// @param [in] resource A FfxResource. +/// +/// @returns +/// true The resource was not FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL. +/// @returns +/// false The resource was FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL. +/// +/// @ingroup ffxFsr3Upscaler +FFX_API bool ffxFsr3UpscalerResourceIsNull(FfxResource resource); + +#if defined(__cplusplus) +} +#endif // #if defined(__cplusplus) diff --git a/sdk/include/FidelityFX/host/ffx_fx.h b/sdk/include/FidelityFX/host/ffx_fx.h index 9b68fa0c..32f9b438 100644 --- a/sdk/include/FidelityFX/host/ffx_fx.h +++ b/sdk/include/FidelityFX/host/ffx_fx.h @@ -1,39 +1,43 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 /// @defgroup SDKComponents Effect Components /// Runtime FidelityFX Effect Components that compile and link to calling effect libraries /// /// @ingroup ffxSDK -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include diff --git a/sdk/include/FidelityFX/host/ffx_interface.h b/sdk/include/FidelityFX/host/ffx_interface.h index bf6fc4cb..3a7277af 100644 --- a/sdk/include/FidelityFX/host/ffx_interface.h +++ b/sdk/include/FidelityFX/host/ffx_interface.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : -// +// Copyright (c) 2023 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 +// +// 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 +// 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 @@ -56,38 +56,13 @@ FFX_FORWARD_DECLARE(FfxInterface); /// FidelityFX SDK patch version. /// /// @ingroup FfxInterface -#define FFX_SDK_VERSION_PATCH (0) +#define FFX_SDK_VERSION_PATCH (1) /// Macro to pack a FidelityFX SDK version id together. /// /// @ingroup FfxInterface #define FFX_SDK_MAKE_VERSION( major, minor, patch ) ( ( major << 22 ) | ( minor << 12 ) | patch ) -/// An enumeration of all the effects which constitute the FidelityFX SDK. -/// -/// Dictates what effect shader blobs to fetch for pipeline creation -/// -/// @ingroup FfxInterface -typedef enum FfxEffect -{ - - FFX_EFFECT_FSR2 = 0, ///< FidelityFX Super Resolution v2 - FFX_EFFECT_FSR1, ///< FidelityFX Super Resolution - FFX_EFFECT_SPD, ///< FidelityFX Single Pass Downsampler - FFX_EFFECT_BLUR, ///< FidelityFX Blur - FFX_EFFECT_CACAO, ///< FidelityFX Combined Adaptive Compute Ambient Occlusion - FFX_EFFECT_CAS, ///< FidelityFX Contrast Adaptive Sharpening - FFX_EFFECT_DENOISER, ///< FidelityFX Denoiser - FFX_EFFECT_LENS, ///< FidelityFX Lens - FFX_EFFECT_PARALLEL_SORT, ///< FidelityFX Parallel Sort - FFX_EFFECT_SSSR, ///< FidelityFX Stochastic Screen Space Reflections - FFX_EFFECT_VARIABLE_SHADING, ///< FidelityFX Variable Shading - FFX_EFFECT_LPM, ///< FidelityFX Luma Preserving Mapper - FFX_EFFECT_DOF, ///< FidelityFX Depth of Field - FFX_EFFECT_CLASSIFIER ///< FidelityFX Classifier - -} FfxEffect; - /// Stand in type for FfxPass /// /// These will be defined for each effect individually (i.e. FfxFsr2Pass). @@ -290,6 +265,7 @@ typedef FfxResourceDescription (*FfxGetResourceDescriptionFunc)( /// /// @param [in] backendInterface A pointer to the backend interface. /// @param [in] resource A pointer to a FfxResource object. +/// @param [in] effectContextId The context space to be used for the effect in question. /// /// @retval /// FFX_OK The operation completed successfully. @@ -299,7 +275,8 @@ typedef FfxResourceDescription (*FfxGetResourceDescriptionFunc)( /// @ingroup FfxInterface typedef FfxErrorCode (*FfxDestroyResourceFunc)( FfxInterface* backendInterface, - FfxResourceInternal resource); + FfxResourceInternal resource, + FfxUInt32 effectContextId); /// Create a render pipeline. /// @@ -327,6 +304,12 @@ typedef FfxErrorCode (*FfxCreatePipelineFunc)( FfxUInt32 effectContextId, FfxPipelineState* outPipeline); +typedef FfxErrorCode(*FfxGetPermutationBlobByIndexFunc)(FfxEffect effectId, + FfxPass passId, + FfxBindStage bindStage, + uint32_t permutationOptions, + FfxShaderBlob* outBlob); + /// Destroy a render pipeline. /// /// @param [in] backendInterface A pointer to the backend interface. @@ -390,6 +373,23 @@ typedef FfxErrorCode (*FfxExecuteGpuJobsFunc)( FfxInterface* backendInterface, FfxCommandList commandList); +typedef FfxErrorCode(*FfxPresentCallbackFunc)(const FfxPresentCallbackDescription* params); +typedef FfxErrorCode(*FfxFrameGenerationDispatchFunc)(const FfxFrameGenerationDispatchDescription* params); + +typedef struct FfxFrameGenerationConfig +{ + FfxSwapchain swapChain; + FfxPresentCallbackFunc presentCallback; + FfxFrameGenerationDispatchFunc frameGenerationCallback; + bool frameGenerationEnabled; + bool allowAsyncWorkloads; + FfxResource HUDLessColor; + FfxUInt32 flags; + bool onlyPresentInterpolated; +} FfxFrameGenerationConfig; + +typedef FfxErrorCode (*ffxSwapChainConfigureFrameGenerationFunc)(FfxFrameGenerationConfig const* config); + /// A structure encapsulating the interface between the core implementation of /// the FfxInterface and any graphics API that it should ultimately call. /// @@ -448,9 +448,11 @@ typedef struct FfxInterface { FfxGetResourceDescriptionFunc fpGetResourceDescription; ///< A callback function to retrieve a resource description. FfxDestroyResourceFunc fpDestroyResource; ///< A callback function to destroy a resource. FfxCreatePipelineFunc fpCreatePipeline; ///< A callback function to create a render or compute pipeline. + FfxGetPermutationBlobByIndexFunc fpGetPermutationBlobByIndex; FfxDestroyPipelineFunc fpDestroyPipeline; ///< A callback function to destroy a render or compute pipeline. FfxScheduleGpuJobFunc fpScheduleGpuJob; ///< A callback function to schedule a render job. FfxExecuteGpuJobsFunc fpExecuteGpuJobs; ///< A callback function to execute all queued render jobs. + ffxSwapChainConfigureFrameGenerationFunc fpSwapChainConfigureFrameGeneration; ///< A callback function to configure swap chain present callback. void* scratchBuffer; ///< A preallocated buffer for memory utilized internally by the backend. size_t scratchBufferSize; ///< Size of the buffer pointed to by scratchBuffer. diff --git a/sdk/include/FidelityFX/host/ffx_lens.h b/sdk/include/FidelityFX/host/ffx_lens.h index 7861e618..0691d96e 100644 --- a/sdk/include/FidelityFX/host/ffx_lens.h +++ b/sdk/include/FidelityFX/host/ffx_lens.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // @defgroup Lens #pragma once diff --git a/sdk/include/FidelityFX/host/ffx_lpm.h b/sdk/include/FidelityFX/host/ffx_lpm.h index a24c6be5..b5bba927 100644 --- a/sdk/include/FidelityFX/host/ffx_lpm.h +++ b/sdk/include/FidelityFX/host/ffx_lpm.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // @defgroup LPM #pragma once diff --git a/sdk/include/FidelityFX/host/ffx_opticalflow.h b/sdk/include/FidelityFX/host/ffx_opticalflow.h new file mode 100644 index 00000000..f18a6dda --- /dev/null +++ b/sdk/include/FidelityFX/host/ffx_opticalflow.h @@ -0,0 +1,202 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +// @defgroup OpticalFlow + +#pragma once + +// Include the interface for the backend of the OpticalFlow API. +#include + +/// FidelityFX OpticalFlow major version. +/// +/// @ingroup ffxOpticalflow +#define FFX_OPTICALFLOW_VERSION_MAJOR (1) + +/// FidelityFX OpticalFlow minor version. +/// +/// @ingroup ffxOpticalflow +#define FFX_OPTICALFLOW_VERSION_MINOR (0) + +/// FidelityFX OpticalFlow patch version. +/// +/// @ingroup ffxOpticalflow +#define FFX_OPTICALFLOW_VERSION_PATCH (0) + +/// FidelityFX Optical Flow context count +/// +/// Defines the number of internal effect contexts required by Optical Flow +/// +/// @ingroup ffxOpticalFlow +#define FFX_OPTICALFLOW_CONTEXT_COUNT (1) + +/// The size of the context specified in 32bit size units. +/// +/// @ingroup ffxOpticalflow +#define FFX_OPTICALFLOW_CONTEXT_SIZE (FFX_SDK_DEFAULT_CONTEXT_SIZE) + +#if defined(__cplusplus) +extern "C" { +#endif // #if defined(__cplusplus) + +/// An enumeration of all the passes which constitute the OpticalFlow algorithm. +/// +/// @ingroup ffxOpticalflow +typedef enum FfxOpticalflowPass +{ + FFX_OPTICALFLOW_PASS_PREPARE_LUMA = 0, + FFX_OPTICALFLOW_PASS_GENERATE_OPTICAL_FLOW_INPUT_PYRAMID, + FFX_OPTICALFLOW_PASS_GENERATE_SCD_HISTOGRAM, + FFX_OPTICALFLOW_PASS_COMPUTE_SCD_DIVERGENCE, + FFX_OPTICALFLOW_PASS_COMPUTE_OPTICAL_FLOW_ADVANCED_V5, + FFX_OPTICALFLOW_PASS_FILTER_OPTICAL_FLOW_V5, + FFX_OPTICALFLOW_PASS_SCALE_OPTICAL_FLOW_ADVANCED_V5, + + FFX_OPTICALFLOW_PASS_COUNT +} FfxOpticalflowPass; + +/// An enumeration of bit flags used when creating a +/// FfxOpticalflowContext. See FfxOpticalflowDispatchDescription. +/// +/// @ingroup ffxOpticalflow +typedef enum FfxOpticalflowInitializationFlagBits +{ + FFX_OPTICALFLOW_ENABLE_TEXTURE1D_USAGE = (1 << 0), + +} FfxOpticalflowInitializationFlagBits; + +/// A structure encapsulating the parameters required to initialize +/// FidelityFX OpticalFlow. +/// +/// @ingroup ffxOpticalflow +typedef struct FfxOpticalflowContextDescription { + + FfxInterface backendInterface; ///< A set of pointers to the backend implementation for FidelityFX SDK + uint32_t flags; ///< A collection of FfxOpticalflowInitializationFlagBits. + FfxDimensions2D resolution; +} FfxOpticalflowContextDescription; + +/// A structure encapsulating the parameters for dispatching the various passes +/// of FidelityFX Opticalflow. +/// +/// @ingroup ffxOpticalflow +typedef struct FfxOpticalflowDispatchDescription +{ + FfxCommandList commandList; ///< The FfxCommandList to record rendering commands into. + FfxResource color; ///< A FfxResource containing the input color buffer + FfxResource opticalFlowVector; ///< A FfxResource containing the output motion buffer + FfxResource opticalFlowSCD; ///< A FfxResource containing the output scene change detection buffer + bool reset; ///< A boolean value which when set to true, indicates the camera has moved discontinuously. + int backbufferTransferFunction; + FfxFloatCoords2D minMaxLuminance; +} FfxOpticalflowDispatchDescription; + +typedef struct FfxOpticalflowSharedResourceDescriptions { + + FfxCreateResourceDescription opticalFlowVector; + FfxCreateResourceDescription opticalFlowSCD; + +} FfxOpticalflowSharedResourceDescriptions; + +/// A structure encapsulating the FidelityFX OpticalFlow context. +/// +/// This sets up an object which contains all persistent internal data and +/// resources that are required by OpticalFlow. +/// +/// The FfxOpticalflowContext object should have a lifetime matching +/// your use of OpticalFlow. Before destroying the OpticalFlow context care should be taken +/// to ensure the GPU is not accessing the resources created or used by OpticalFlow. +/// It is therefore recommended that the GPU is idle before destroying OpticalFlow +/// OpticalFlow context. +/// +/// @ingroup ffxOpticalflow +typedef struct FfxOpticalflowContext +{ + uint32_t data[FFX_OPTICALFLOW_CONTEXT_SIZE]; ///< An opaque set of uint32_t which contain the data for the context. +} FfxOpticalflowContext; + + +/// Create a FidelityFX OpticalFlow context from the parameters +/// programmed to the FfxOpticalflowContextDescription structure. +/// +/// The context structure is the main object used to interact with the OpticalFlow +/// API, and is responsible for the management of the internal resources used +/// by the OpticalFlow algorithm. When this API is called, multiple calls will be +/// made via the pointers contained in the callbacks structure. +/// These callbacks will attempt to retreive the device capabilities, and +/// create the internal resources, and pipelines required by OpticalFlow's +/// frame-to-frame function. Depending on the precise configuration used when +/// creating the FfxOpticalflowContext a different set of resources and +/// pipelines might be requested via the callback functions. +/// +/// The flags included in the flags field of +/// FfxOpticalflowContext how match the configuration of your +/// application as well as the intended use of OpticalFlow. It is important that these +/// flags are set correctly (as well as a correct programmed +/// FfxOpticalflowContextDescription) to ensure correct operation. It is +/// recommended to consult the overview documentation for further details on +/// how OpticalFlow should be integerated into an application. +/// +/// When the FfxOpticalflowContext is created, you should use the +/// ffxOpticalflowContextDispatch function each frame where FSR3 +/// upscaling should be applied. See the documentation of +/// ffxOpticalflowContextDispatch for more details. +/// +/// The FfxOpticalflowContext should be destroyed when use of it is +/// completed, typically when an application is unloaded or OpticalFlow is +/// disabled by a user. To destroy the OpticalFlow context you should call +/// ffxOpticalflowContextDestroy. +/// +/// @param [out] context A pointer to a FfxOpticalflowContext structure to populate. +/// @param [in] contextDescription A pointer to a FfxOpticalflowContextDescription structure. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_CODE_NULL_POINTER The operation failed because either context or contextDescription was NULL. +/// @retval +/// FFX_ERROR_INCOMPLETE_INTERFACE The operation failed because the FfxOpticalflowContextDescription.callbacks was not fully specified. +/// @retval +/// FFX_ERROR_BACKEND_API_ERROR The operation failed because of an error returned from the backend. +/// +/// @ingroup ffxOpticalflow +FFX_API FfxErrorCode ffxOpticalflowContextCreate(FfxOpticalflowContext* context, FfxOpticalflowContextDescription* contextDescription); + +FFX_API FfxErrorCode ffxOpticalflowGetSharedResourceDescriptions(FfxOpticalflowContext* context, FfxOpticalflowSharedResourceDescriptions* SharedResources); + +FFX_API FfxErrorCode ffxOpticalflowContextDispatch(FfxOpticalflowContext* context, const FfxOpticalflowDispatchDescription* dispatchDescription); + +/// Destroy the FidelityFX OpticalFlow context. +/// +/// @param [out] context A pointer to a FfxOpticalflowContext structure to destroy. +/// +/// @retval +/// FFX_OK The operation completed successfully. +/// @retval +/// FFX_ERROR_CODE_NULL_POINTER The operation failed because either context was NULL. +/// +/// @ingroup ffxOpticalflow +FFX_API FfxErrorCode ffxOpticalflowContextDestroy(FfxOpticalflowContext* context); + +#if defined(__cplusplus) +} +#endif // #if defined(__cplusplus) diff --git a/sdk/include/FidelityFX/host/ffx_parallelsort.h b/sdk/include/FidelityFX/host/ffx_parallelsort.h index c4da90a5..bdf9dfe3 100644 --- a/sdk/include/FidelityFX/host/ffx_parallelsort.h +++ b/sdk/include/FidelityFX/host/ffx_parallelsort.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // @defgroup PARALLEL_SORT #pragma once diff --git a/sdk/include/FidelityFX/host/ffx_spd.h b/sdk/include/FidelityFX/host/ffx_spd.h index 776d4873..badb47b3 100644 --- a/sdk/include/FidelityFX/host/ffx_spd.h +++ b/sdk/include/FidelityFX/host/ffx_spd.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // @defgroup FSR2 #pragma once diff --git a/sdk/include/FidelityFX/host/ffx_sssr.h b/sdk/include/FidelityFX/host/ffx_sssr.h index df29560e..be0194c4 100644 --- a/sdk/include/FidelityFX/host/ffx_sssr.h +++ b/sdk/include/FidelityFX/host/ffx_sssr.h @@ -1,26 +1,26 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 the interface for the backend of the SSSR API. @@ -57,7 +57,7 @@ /// The size of the context specified in 32bit values. /// /// @ingroup FfxSssr -#define FFX_SSSR_CONTEXT_SIZE (32270) +#define FFX_SSSR_CONTEXT_SIZE (32276) #if defined(__cplusplus) extern "C" { diff --git a/sdk/include/FidelityFX/host/ffx_types.h b/sdk/include/FidelityFX/host/ffx_types.h index f8d5437d..64494df9 100644 --- a/sdk/include/FidelityFX/host/ffx_types.h +++ b/sdk/include/FidelityFX/host/ffx_types.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : -// +// Copyright (c) 2023 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 +// +// 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 +// 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 @@ -51,6 +51,8 @@ #define FFX_API __declspec(dllexport) #endif // #if defined (FFX_GCC) +#define FFX_SDK_DEFAULT_CONTEXT_SIZE (1024 * 128) + /// Maximum supported number of simultaneously bound SRVs. /// /// @ingroup Defines @@ -82,7 +84,7 @@ /// Maximum number of resources per effect context /// /// @ingroup Defines -#define FFX_MAX_RESOURCE_COUNT (64) +#define FFX_MAX_RESOURCE_COUNT (128) /// Maximum number of passes per effect component /// @@ -227,28 +229,31 @@ typedef uint32_t FfxUInt32x4[4]; /// @ingroup SDKTypes typedef enum FfxSurfaceFormat { - FFX_SURFACE_FORMAT_UNKNOWN, ///< Unknown format - FFX_SURFACE_FORMAT_R32G32B32A32_TYPELESS, ///< 32 bit per channel, 4 channel typeless format - FFX_SURFACE_FORMAT_R32G32B32A32_UINT, ///< 32 bit per channel, 4 channel uint format - FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT, ///< 32 bit per channel, 4 channel float format - FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, ///< 16 bit per channel, 4 channel float format - FFX_SURFACE_FORMAT_R32G32_FLOAT, ///< 32 bit per channel, 2 channel float format - FFX_SURFACE_FORMAT_R8_UINT, ///< 8 bit per channel, 1 channel float format - FFX_SURFACE_FORMAT_R32_UINT, ///< 32 bit per channel, 1 channel float format - FFX_SURFACE_FORMAT_R8G8B8A8_TYPELESS, ///< 8 bit per channel, 4 channel float format - FFX_SURFACE_FORMAT_R8G8B8A8_UNORM, ///< 8 bit per channel, 4 channel unsigned normalized format - FFX_SURFACE_FORMAT_R8G8B8A8_SNORM, ///< 8 bit per channel, 4 channel signed normalized format - FFX_SURFACE_FORMAT_R8G8B8A8_SRGB, ///< 8 bit per channel, 4 channel srgb normalized - FFX_SURFACE_FORMAT_R11G11B10_FLOAT, ///< 32 bit 3 channel float format - FFX_SURFACE_FORMAT_R16G16_FLOAT, ///< 16 bit per channel, 2 channel float format - FFX_SURFACE_FORMAT_R16G16_UINT, ///< 16 bit per channel, 2 channel unsigned int format - FFX_SURFACE_FORMAT_R16_FLOAT, ///< 16 bit per channel, 1 channel float format - FFX_SURFACE_FORMAT_R16_UINT, ///< 16 bit per channel, 1 channel unsigned int format - FFX_SURFACE_FORMAT_R16_UNORM, ///< 16 bit per channel, 1 channel unsigned normalized format - FFX_SURFACE_FORMAT_R16_SNORM, ///< 16 bit per channel, 1 channel signed normalized format - FFX_SURFACE_FORMAT_R8_UNORM, ///< 8 bit per channel, 1 channel unsigned normalized format - FFX_SURFACE_FORMAT_R8G8_UNORM, ///< 8 bit per channel, 2 channel unsigned normalized format - FFX_SURFACE_FORMAT_R32_FLOAT ///< 32 bit per channel, 1 channel float format + FFX_SURFACE_FORMAT_UNKNOWN, ///< Unknown format + FFX_SURFACE_FORMAT_R32G32B32A32_TYPELESS, ///< 32 bit per channel, 4 channel typeless format + FFX_SURFACE_FORMAT_R32G32B32A32_UINT, ///< 32 bit per channel, 4 channel uint format + FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT, ///< 32 bit per channel, 4 channel float format + FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, ///< 16 bit per channel, 4 channel float format + FFX_SURFACE_FORMAT_R32G32_FLOAT, ///< 32 bit per channel, 2 channel float format + FFX_SURFACE_FORMAT_R8_UINT, ///< 8 bit per channel, 1 channel float format + FFX_SURFACE_FORMAT_R32_UINT, ///< 32 bit per channel, 1 channel float format + FFX_SURFACE_FORMAT_R10G10B10A2_UNORM, ///< 10 bit per RGB channel with 2 bit alpha, 4 channel unsigned normalized format + FFX_SURFACE_FORMAT_R8G8B8A8_TYPELESS, ///< 8 bit per channel, 4 channel float format + FFX_SURFACE_FORMAT_R8G8B8A8_UNORM, ///< 8 bit per channel, 4 channel unsigned normalized format + FFX_SURFACE_FORMAT_R8G8B8A8_SNORM, ///< 8 bit per channel, 4 channel signed normalized format + FFX_SURFACE_FORMAT_R8G8B8A8_SRGB, ///< 8 bit per channel, 4 channel srgb normalized + FFX_SURFACE_FORMAT_R11G11B10_FLOAT, ///< 32 bit 3 channel float format + FFX_SURFACE_FORMAT_R16G16_FLOAT, ///< 16 bit per channel, 2 channel float format + FFX_SURFACE_FORMAT_R16G16_UINT, ///< 16 bit per channel, 2 channel unsigned int format + FFX_SURFACE_FORMAT_R16G16_SINT, ///< 16 bit per channel, 2 channel signed int format + FFX_SURFACE_FORMAT_R16_FLOAT, ///< 16 bit per channel, 1 channel float format + FFX_SURFACE_FORMAT_R16_UINT, ///< 16 bit per channel, 1 channel unsigned int format + FFX_SURFACE_FORMAT_R16_UNORM, ///< 16 bit per channel, 1 channel unsigned normalized format + FFX_SURFACE_FORMAT_R16_SNORM, ///< 16 bit per channel, 1 channel signed normalized format + FFX_SURFACE_FORMAT_R8_UNORM, ///< 8 bit per channel, 1 channel unsigned normalized format + FFX_SURFACE_FORMAT_R8G8_UNORM, ///< 8 bit per channel, 2 channel unsigned normalized format + FFX_SURFACE_FORMAT_R8G8_UINT, ///< 8 bit per channel, 2 channel unsigned integer format + FFX_SURFACE_FORMAT_R32_FLOAT ///< 32 bit per channel, 1 channel float format } FfxSurfaceFormat; /// An enumeration of resource usage. @@ -269,14 +274,17 @@ typedef enum FfxResourceUsage { /// @ingroup SDKTypes typedef enum FfxResourceStates { - FFX_RESOURCE_STATE_UNORDERED_ACCESS = (1<<0), ///< Indicates a resource is in the state to be used as UAV. - FFX_RESOURCE_STATE_COMPUTE_READ = (1 << 1), ///< Indicates a resource is in the state to be read by compute shaders. - FFX_RESOURCE_STATE_PIXEL_READ = (1 << 2), ///< Indicates a resource is in the state to be read by pixel shaders. - FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ = (FFX_RESOURCE_STATE_PIXEL_READ | FFX_RESOURCE_STATE_COMPUTE_READ), ///< Indicates a resource is in the state to be read by pixel or compute shaders. - FFX_RESOURCE_STATE_COPY_SRC = (1 << 3), ///< Indicates a resource is in the state to be used as source in a copy command. - FFX_RESOURCE_STATE_COPY_DEST = (1 << 4), ///< Indicates a resource is in the state to be used as destination in a copy command. - FFX_RESOURCE_STATE_GENERIC_READ = (FFX_RESOURCE_STATE_COPY_SRC | FFX_RESOURCE_STATE_COMPUTE_READ), ///< Indicates a resource is in generic (slow) read state. - FFX_RESOURCE_STATE_INDIRECT_ARGUMENT = (1 << 5),///< Indicates a resource is in the state to be used as an indirect command argument + FFX_RESOURCE_STATE_COMMON = (1 << 0), + FFX_RESOURCE_STATE_UNORDERED_ACCESS = (1 << 1), ///< Indicates a resource is in the state to be used as UAV. + FFX_RESOURCE_STATE_COMPUTE_READ = (1 << 2), ///< Indicates a resource is in the state to be read by compute shaders. + FFX_RESOURCE_STATE_PIXEL_READ = (1 << 3), ///< Indicates a resource is in the state to be read by pixel shaders. + FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ = (FFX_RESOURCE_STATE_PIXEL_READ | FFX_RESOURCE_STATE_COMPUTE_READ), ///< Indicates a resource is in the state to be read by pixel or compute shaders. + FFX_RESOURCE_STATE_COPY_SRC = (1 << 4), ///< Indicates a resource is in the state to be used as source in a copy command. + FFX_RESOURCE_STATE_COPY_DEST = (1 << 5), ///< Indicates a resource is in the state to be used as destination in a copy command. + FFX_RESOURCE_STATE_GENERIC_READ = (FFX_RESOURCE_STATE_COPY_SRC | FFX_RESOURCE_STATE_COMPUTE_READ), ///< Indicates a resource is in generic (slow) read state. + FFX_RESOURCE_STATE_INDIRECT_ARGUMENT = (1 << 6), ///< Indicates a resource is in the state to be used as an indirect command argument + FFX_RESOURCE_STATE_PRESENT = (1 << 7), ///< Indicates a resource is in the state to be used to present to the swap chain + FFX_RESOURCE_STATE_RENDER_TARGET = (1 << 8), ///< Indicates a resource is in the state to be used as render target } FfxResourceStates; /// An enumeration of surface dimensions. @@ -387,6 +395,8 @@ typedef enum FfxGpuJobType { FFX_GPU_JOB_CLEAR_FLOAT = 0, ///< The GPU job is performing a floating-point clear. FFX_GPU_JOB_COPY = 1, ///< The GPU job is performing a copy. FFX_GPU_JOB_COMPUTE = 2, ///< The GPU job is performing a compute dispatch. + FFX_GPU_JOB_BARRIER = 3, ///< The GPU job is performing a barrier. + } FfxGpuJobType; /// An enumeration for various descriptor types @@ -431,11 +441,49 @@ typedef enum FfxMsgType { FFX_MESSAGE_TYPE_COUNT } FfxMsgType; +/// An enumeration of all the effects which constitute the FidelityFX SDK. +/// +/// Dictates what effect shader blobs to fetch for pipeline creation +/// +/// @ingroup FfxInterface +typedef enum FfxEffect +{ + + FFX_EFFECT_FSR2 = 0, ///< FidelityFX Super Resolution v2 + FFX_EFFECT_FSR1, ///< FidelityFX Super Resolution + FFX_EFFECT_SPD, ///< FidelityFX Single Pass Downsampler + FFX_EFFECT_BLUR, ///< FidelityFX Blur + FFX_EFFECT_CACAO, ///< FidelityFX Combined Adaptive Compute Ambient Occlusion + FFX_EFFECT_CAS, ///< FidelityFX Contrast Adaptive Sharpening + FFX_EFFECT_DENOISER, ///< FidelityFX Denoiser + FFX_EFFECT_LENS, ///< FidelityFX Lens + FFX_EFFECT_PARALLEL_SORT, ///< FidelityFX Parallel Sort + FFX_EFFECT_SSSR, ///< FidelityFX Stochastic Screen Space Reflections + FFX_EFFECT_VARIABLE_SHADING, ///< FidelityFX Variable Shading + FFX_EFFECT_LPM, ///< FidelityFX Luma Preserving Mapper + FFX_EFFECT_DOF, ///< FidelityFX Depth of Field + FFX_EFFECT_CLASSIFIER, ///< FidelityFX Classifier + FFX_EFFECT_FSR3UPSCALER, ///< FidelityFX Super Resolution v3 + FFX_EFFECT_FRAMEINTERPOLATION, ///< FidelityFX Frame Interpolation, part of FidelityFX Super Resolution v3 + FFX_EFFECT_OPTICALFLOW, ///< FidelityFX Optical Flow, part of FidelityFX Super Resolution v3 + +} FfxEffect; + +typedef enum FfxBackbufferTransferFunction { + FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB, + FFX_BACKBUFFER_TRANSFER_FUNCTION_PQ, + FFX_BACKBUFFER_TRANSFER_FUNCTION_SCRGB +} FfxBackbufferTransferFunction; + /// A typedef representing the graphics device. /// /// @ingroup SDKTypes typedef void* FfxDevice; +typedef void* FfxCommandQueue; + +typedef void* FfxSwapchain; + /// A typedef representing a command list or command buffer. /// /// @ingroup SDKTypes @@ -486,6 +534,17 @@ typedef struct FfxIntCoords2D { int32_t y; ///< The y coordinate of a 2-dimensional point. } FfxIntCoords2D; +/// A structure encapsulating a 2-dimensional rect. +/// +/// @ingroup SDKTypes +typedef struct FfxRect2D +{ + int32_t left; + int32_t top; + int32_t width; + int32_t height; +} FfxRect2D; + /// A structure encapsulating a 2-dimensional set of floating point coordinates. /// /// @ingroup SDKTypes @@ -684,6 +743,7 @@ typedef struct FfxPipelineDescription { wchar_t name[64]; ///< Pipeline name with which to name the pipeline object FfxBindStage stage; ///< The stage(s) for which this pipeline is being built uint32_t indirectWorkload; ///< Whether this pipeline has an indirect workload + FfxSurfaceFormat backbufferFormat; ///< For raster pipelines this contains the backbuffer format } FfxPipelineDescription; /// A structure containing the data required to create a barrier @@ -691,6 +751,7 @@ typedef struct FfxPipelineDescription { /// @ingroup SDKTypes typedef struct FfxBarrierDescription { + FfxResourceInternal resource; FfxBarrierType barrierType; FfxResourceStates currentState; FfxResourceStates newState; @@ -738,6 +799,21 @@ typedef struct FfxComputeJobDescription { wchar_t cbNames[FFX_MAX_NUM_CONST_BUFFERS][64]; } FfxComputeJobDescription; +typedef struct FfxRasterJobDescription +{ + FfxPipelineState pipeline; ///< Raster pipeline for the render job. + uint32_t numVertices; + FfxResourceInternal renderTarget; + + FfxResourceInternal srvTextures[FFX_MAX_NUM_SRVS]; ///< SRV resources to be bound in the compute job. + wchar_t srvTextureNames[FFX_MAX_NUM_SRVS][64]; + FfxResourceInternal uavTextures[FFX_MAX_NUM_UAVS]; ///< UAV resources to be bound in the compute job. + uint32_t uavTextureMips[FFX_MAX_NUM_UAVS]; ///< Mip level of UAV resources to be bound in the compute job. + wchar_t uavTextureNames[FFX_MAX_NUM_UAVS][64]; + FfxConstantBuffer cbs[FFX_MAX_NUM_CONST_BUFFERS]; ///< Constant buffers to be bound in the compute job. + wchar_t cbNames[FFX_MAX_NUM_CONST_BUFFERS][64]; +} FfxRasterJobDescription; + /// A structure describing a copy render job. /// /// @ingroup SDKTypes @@ -758,6 +834,8 @@ typedef struct FfxGpuJobDescription{ FfxClearFloatJobDescription clearJobDescriptor; ///< Clear job descriptor. Valid when jobType is FFX_RENDER_JOB_CLEAR_FLOAT. FfxCopyJobDescription copyJobDescriptor; ///< Copy job descriptor. Valid when jobType is FFX_RENDER_JOB_COPY. FfxComputeJobDescription computeJobDescriptor; ///< Compute job descriptor. Valid when jobType is FFX_RENDER_JOB_COMPUTE. + FfxRasterJobDescription rasterJobDescriptor; + FfxBarrierDescription barrierDescriptor; }; } FfxGpuJobDescription; @@ -834,6 +912,26 @@ typedef struct FfxShaderBlob { } FfxShaderBlob; +typedef struct FfxPresentCallbackDescription +{ + FfxDevice device; + FfxCommandList commandList; + FfxResource currentBackBuffer; + FfxResource currentUI; + FfxResource outputSwapChainBuffer; + bool isInterpolatedFrame; +} FfxPresentCallbackDescription; + +typedef struct FfxFrameGenerationDispatchDescription { + FfxCommandList commandList; + FfxResource presentColor; + FfxResource outputs[4]; + uint32_t numInterpolatedFrames; + bool reset; + FfxBackbufferTransferFunction backBufferTransferFunction; + float minMaxLuminance[2]; +} FfxFrameGenerationDispatchDescription; + #ifdef __cplusplus } #endif // #ifdef __cplusplus diff --git a/sdk/include/FidelityFX/host/ffx_util.h b/sdk/include/FidelityFX/host/ffx_util.h index 5b470b97..123cd196 100644 --- a/sdk/include/FidelityFX/host/ffx_util.h +++ b/sdk/include/FidelityFX/host/ffx_util.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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 diff --git a/sdk/include/FidelityFX/host/ffx_vrs.h b/sdk/include/FidelityFX/host/ffx_vrs.h index 79a386c7..a8cecf31 100644 --- a/sdk/include/FidelityFX/host/ffx_vrs.h +++ b/sdk/include/FidelityFX/host/ffx_vrs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. // -// 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 : -// +// Copyright (c) 2023 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 +// +// 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 +// 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. + // @defgroup VRS #pragma once @@ -57,7 +57,7 @@ /// The size of the context specified in 32bit values. /// /// @ingroup FfxVrs -#define FFX_VRS_CONTEXT_SIZE (2672) +#define FFX_VRS_CONTEXT_SIZE (2676) #if defined(__cplusplus) extern "C" { diff --git a/sdk/src/backends/dx12/CMakeLists.txt b/sdk/src/backends/dx12/CMakeLists.txt index c31838e3..2733b5ed 100644 --- a/sdk/src/backends/dx12/CMakeLists.txt +++ b/sdk/src/backends/dx12/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. -# +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# +# 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 +# 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 @@ -65,7 +64,7 @@ function(compile_shaders EXECUTABLE BASE_ARGS DX12_BASE_ARGS PERMUTATION_ARGS IN # Wave32 add_custom_command( OUTPUT ${WAVE32_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME} -DFFX_HALF=0 -T cs_6_2 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME} -DFFX_HALF=0 -T cs_6_2 -DFFX_HLSL_SM=62 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ${PASS_SHADER} DEPFILE ${WAVE32_PERMUTATION_HEADER}.d @@ -75,7 +74,7 @@ function(compile_shaders EXECUTABLE BASE_ARGS DX12_BASE_ARGS PERMUTATION_ARGS IN # Wave64 add_custom_command( OUTPUT ${WAVE64_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64 "-DFFX_PREFER_WAVE64=\"[WaveSize(64)]\"" -DFFX_HALF=0 -T cs_6_6 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64 "-DFFX_PREFER_WAVE64=\"[WaveSize(64)]\"" -DFFX_HALF=0 -T cs_6_6 -DFFX_HLSL_SM=66 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ${PASS_SHADER} DEPFILE ${WAVE64_PERMUTATION_HEADER}.d @@ -85,7 +84,7 @@ function(compile_shaders EXECUTABLE BASE_ARGS DX12_BASE_ARGS PERMUTATION_ARGS IN # Wave32 16-bit add_custom_command( OUTPUT ${WAVE32_16BIT_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 -enable-16bit-types -T cs_6_2 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 -enable-16bit-types -T cs_6_2 -DFFX_HLSL_SM=62 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ${PASS_SHADER} DEPFILE ${WAVE32_16BIT_PERMUTATION_HEADER}.d @@ -95,7 +94,7 @@ function(compile_shaders EXECUTABLE BASE_ARGS DX12_BASE_ARGS PERMUTATION_ARGS IN # Wave64 16-bit add_custom_command( OUTPUT ${WAVE64_16BIT_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit "-DFFX_PREFER_WAVE64=\"[WaveSize(64)]\"" -DFFX_HALF=1 -enable-16bit-types -T cs_6_6 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit "-DFFX_PREFER_WAVE64=\"[WaveSize(64)]\"" -DFFX_HALF=1 -enable-16bit-types -T cs_6_6 -DFFX_HLSL_SM=66 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ${PASS_SHADER} DEPFILE ${WAVE64_16BIT_PERMUTATION_HEADER}.d @@ -106,7 +105,7 @@ function(compile_shaders EXECUTABLE BASE_ARGS DX12_BASE_ARGS PERMUTATION_ARGS IN # Wave32 add_custom_command( OUTPUT ${WAVE32_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME} -DFFX_HALF=0 -T cs_6_2 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME} -DFFX_HALF=0 -T cs_6_2 -DFFX_HLSL_SM=62 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ${PASS_SHADER} ) @@ -115,7 +114,7 @@ function(compile_shaders EXECUTABLE BASE_ARGS DX12_BASE_ARGS PERMUTATION_ARGS IN # Wave64 add_custom_command( OUTPUT ${WAVE64_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64 "-DFFX_PREFER_WAVE64=\"[WaveSize(64)]\"" -DFFX_HALF=0 -T cs_6_6 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64 "-DFFX_PREFER_WAVE64=\"[WaveSize(64)]\"" -DFFX_HALF=0 -T cs_6_6 -DFFX_HLSL_SM=66 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ${PASS_SHADER} ) @@ -124,7 +123,7 @@ function(compile_shaders EXECUTABLE BASE_ARGS DX12_BASE_ARGS PERMUTATION_ARGS IN # Wave32 16-bit add_custom_command( OUTPUT ${WAVE32_16BIT_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 -enable-16bit-types -T cs_6_2 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_16bit -DFFX_HALF=1 -enable-16bit-types -T cs_6_2 -DFFX_HLSL_SM=62 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ${PASS_SHADER} ) @@ -133,7 +132,7 @@ function(compile_shaders EXECUTABLE BASE_ARGS DX12_BASE_ARGS PERMUTATION_ARGS IN # Wave64 16-bit add_custom_command( OUTPUT ${WAVE64_16BIT_PERMUTATION_HEADER} - COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit "-DFFX_PREFER_WAVE64=\"[WaveSize(64)]\"" -DFFX_HALF=1 -enable-16bit-types -T cs_6_6 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} + COMMAND ${EXECUTABLE} ${SC_ARGS} -name=${PASS_SHADER_FILENAME}_wave64_16bit "-DFFX_PREFER_WAVE64=\"[WaveSize(64)]\"" -DFFX_HALF=1 -enable-16bit-types -T cs_6_6 -DFFX_HLSL_SM=66 ${COMPILE_INCLUDE_ARGS} -output=${FFX_PASS_SHADER_OUTPUT_PATH} ${PASS_SHADER} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ${PASS_SHADER} ) @@ -157,8 +156,14 @@ endmacro() file(GLOB PUBLIC_SHADERS FFX_PUBLIC_SHADER_SOURCES + "${FFX_GPU_PATH}/frameinterpolation/*.h" + "${FFX_GPU_PATH}/frameinterpolation/*.hlsl" + "${FFX_GPU_PATH}/opticalflow/*.h" + "${FFX_GPU_PATH}/opticalflow/*.hlsl" "${FFX_GPU_PATH}/fsr2/*.h" "${FFX_GPU_PATH}/fsr2/*.hlsl" + "${FFX_GPU_PATH}/fsr3upscaler/*.h" + "${FFX_GPU_PATH}/fsr3upscaler/*.hlsl" "${FFX_GPU_PATH}/fsr1/*.h" "${FFX_GPU_PATH}/fsr1/*.hlsl" "${FFX_GPU_PATH}/spd/*.h" @@ -193,14 +198,23 @@ file(GLOB PRIVATE_SOURCE "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/" "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/" "${CMAKE_CURRENT_SOURCE_DIR}/*.h" - "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") + "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/FrameInterpolationSwapchain/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/FrameInterpolationSwapchain/*.cpp" +) if (FFX_FSR OR FFX_ALL) set(FFX_FSR_PRIVATE_SOURCE "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr1_shaderblobs.h" "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr1_shaderblobs.cpp" "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr2_shaderblobs.h" - "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr2_shaderblobs.cpp") + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr2_shaderblobs.cpp" + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr3upscaler_shaderblobs.h" + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_fsr3upscaler_shaderblobs.cpp" + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_frameinterpolation_shaderblobs.h" + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_frameinterpolation_shaderblobs.cpp" + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_opticalflow_shaderblobs.h" + "${FFX_SRC_BACKENDS_PATH}/shared/blob_accessors/ffx_opticalflow_shaderblobs.cpp") list(APPEND PRIVATE_SOURCE ${FFX_FSR_PRIVATE_SOURCE}) endif() @@ -315,12 +329,17 @@ source_group("public_shaders" FILES ${PUBLIC_SHADERS}) get_filename_component(FFX_PASS_SHADER_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/../shaders/dx12 ABSOLUTE) target_include_directories(ffx_backend_dx12_${FFX_PLATFORM_NAME} PUBLIC ${FFX_INCLUDE_PATH}) +target_include_directories(ffx_backend_dx12_${FFX_PLATFORM_NAME} PUBLIC ${FFX_LIB_PATH}) target_include_directories(ffx_backend_dx12_${FFX_PLATFORM_NAME} PUBLIC ${FFX_PASS_SHADER_OUTPUT_PATH}) target_include_directories(ffx_backend_dx12_${FFX_PLATFORM_NAME} PRIVATE ${FFX_COMPONENTS_PATH}) target_include_directories(ffx_backend_dx12_${FFX_PLATFORM_NAME} PRIVATE ${FFX_SHARED_PATH}) target_include_directories(ffx_backend_dx12_${FFX_PLATFORM_NAME} PRIVATE "${FFX_SRC_BACKENDS_PATH}/shared") target_include_directories(ffx_backend_dx12_${FFX_PLATFORM_NAME} PRIVATE ${FFX_PASS_SHADER_OUTPUT_PATH}) +if (NOT FFX_BUILD_AS_DLL) + target_link_libraries (ffx_backend_dx12_${FFX_PLATFORM_NAME} pixlib) +endif() + set_source_files_properties(${PRIVATE_SHADERS} PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties(${PUBLIC_SHADERS} PROPERTIES HEADER_FILE_ONLY TRUE) @@ -340,8 +359,28 @@ endif() # add pass shaders for all the components if (FFX_FSR OR FFX_ALL) target_compile_definitions(ffx_backend_dx12_${FFX_PLATFORM_NAME} PRIVATE FFX_FSR) + + # FFX_FSR3 is currently only defined in DX12 native backend + target_compile_definitions(ffx_backend_dx12_${FFX_PLATFORM_NAME} PRIVATE FFX_FSR3) + include (CMakeShadersFrameinterpolation.txt) + include (CMakeShadersOpticalflow.txt) + include (CMakeShadersFSR3Upscaler.txt) include (CMakeShadersFSR2.txt) include (CMakeShadersFSR1.txt) + +# ADD_CUSTOM_TARGET(copy-shaders-FSR2 ALL +# COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/src/backends/dx12/shaders/fsr2 ${CMAKE_BINARY_DIR}/../bin/ffx_sdk/passes_fsr2) +# ADD_CUSTOM_TARGET(copy-shaders-FSR3 ALL +# COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/src/backends/dx12/shaders/fsr3upscaler ${CMAKE_BINARY_DIR}/../bin/ffx_sdk/passes_fsr3upscaler) +# ADD_CUSTOM_TARGET(copy-shaders-OF ALL +# COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/src/backends/dx12/shaders/opticalflow ${CMAKE_BINARY_DIR}/../bin/ffx_sdk/passes_opticalflow) +# ADD_CUSTOM_TARGET(copy-shaders-FI ALL +# COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/src/backends/dx12/shaders/frameinterpolation ${CMAKE_BINARY_DIR}/../bin/ffx_sdk/passes_frameinterpolation) + +# add_dependencies(copy-shaders-FSR2 ffx_backend_dx12_${FFX_PLATFORM_NAME}) +# add_dependencies(copy-shaders-FSR3 ffx_backend_dx12_${FFX_PLATFORM_NAME}) +# add_dependencies(copy-shaders-OF ffx_backend_dx12_${FFX_PLATFORM_NAME}) +# add_dependencies(copy-shaders-FI ffx_backend_dx12_${FFX_PLATFORM_NAME}) endif() if (FFX_SPD OR FFX_ALL) diff --git a/sdk/src/backends/dx12/CMakeShadersBlur.txt b/sdk/src/backends/dx12/CMakeShadersBlur.txt index bd87f772..6b6c5a2d 100644 --- a/sdk/src/backends/dx12/CMakeShadersBlur.txt +++ b/sdk/src/backends/dx12/CMakeShadersBlur.txt @@ -1,30 +1,29 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. # -# 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 : +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # -# The above copyright notice and this permission notice shall be included in +# 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 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. set(BLUR_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(BLUR_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(BLUR_PERMUTATION_ARGS -DFFX_BLUR_OPTION_KERNEL_DIMENSION={3,5,7,9,11,13,15,17,19,21} diff --git a/sdk/src/backends/dx12/CMakeShadersCACAO.txt b/sdk/src/backends/dx12/CMakeShadersCACAO.txt index 10ea5a43..27baefd5 100644 --- a/sdk/src/backends/dx12/CMakeShadersCACAO.txt +++ b/sdk/src/backends/dx12/CMakeShadersCACAO.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. -# +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# +# 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 +# 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 @@ -24,7 +23,7 @@ set(CACAO_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(CACAO_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(CACAO_PERMUTATION_ARGS -DFFX_CACAO_OPTION_APPLY_SMART={0,1} diff --git a/sdk/src/backends/dx12/CMakeShadersCAS.txt b/sdk/src/backends/dx12/CMakeShadersCAS.txt index c92d051d..a0164058 100644 --- a/sdk/src/backends/dx12/CMakeShadersCAS.txt +++ b/sdk/src/backends/dx12/CMakeShadersCAS.txt @@ -1,30 +1,29 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. # -# 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 : +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # -# The above copyright notice and this permission notice shall be included in +# 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 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. set(CAS_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(CAS_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(CAS_PERMUTATION_ARGS -DFFX_CAS_OPTION_SHARPEN_ONLY={0,1} diff --git a/sdk/src/backends/dx12/CMakeShadersClassifier.txt b/sdk/src/backends/dx12/CMakeShadersClassifier.txt index e041a353..65750e39 100644 --- a/sdk/src/backends/dx12/CMakeShadersClassifier.txt +++ b/sdk/src/backends/dx12/CMakeShadersClassifier.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. -# +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# +# 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 +# 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 @@ -24,7 +23,7 @@ set(CLASSIFIER_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(CLASSIFIER_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(CLASSIFIER_PERMUTATION_ARGS -DFFX_CLASSIFIER_OPTION_INVERTED_DEPTH={0,1} diff --git a/sdk/src/backends/dx12/CMakeShadersDOF.txt b/sdk/src/backends/dx12/CMakeShadersDOF.txt index b882b52a..2e4fb274 100644 --- a/sdk/src/backends/dx12/CMakeShadersDOF.txt +++ b/sdk/src/backends/dx12/CMakeShadersDOF.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. -# +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# +# 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 +# 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 @@ -24,7 +23,7 @@ set(DOF_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(DOF_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(DOF_PERMUTATION_ARGS -DFFX_DOF_OPTION_MAX_RING_MERGE_LOG={0,1} diff --git a/sdk/src/backends/dx12/CMakeShadersDenoiser.txt b/sdk/src/backends/dx12/CMakeShadersDenoiser.txt index 4e62c90c..90072d3e 100644 --- a/sdk/src/backends/dx12/CMakeShadersDenoiser.txt +++ b/sdk/src/backends/dx12/CMakeShadersDenoiser.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. -# +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# +# 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 +# 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 @@ -24,7 +23,7 @@ set(DENOISER_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(DENOISER_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(DENOISER_PERMUTATION_ARGS -DFFX_DENOISER_OPTION_INVERTED_DEPTH={0,1}) diff --git a/sdk/src/backends/dx12/CMakeShadersFSR1.txt b/sdk/src/backends/dx12/CMakeShadersFSR1.txt index c68b1002..92dbedbf 100644 --- a/sdk/src/backends/dx12/CMakeShadersFSR1.txt +++ b/sdk/src/backends/dx12/CMakeShadersFSR1.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. -# +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# +# 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 +# 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 @@ -24,7 +23,7 @@ set(FSR1_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(FSR1_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(FSR1_PERMUTATION_ARGS # Reproject can use either reference lanczos or LUT diff --git a/sdk/src/backends/dx12/CMakeShadersFSR2.txt b/sdk/src/backends/dx12/CMakeShadersFSR2.txt index 47bbeb1c..4fabedfa 100644 --- a/sdk/src/backends/dx12/CMakeShadersFSR2.txt +++ b/sdk/src/backends/dx12/CMakeShadersFSR2.txt @@ -1,23 +1,22 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. # -# 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 : +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # -# The above copyright notice and this permission notice shall be included in +# 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 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. set(FSR2_BASE_ARGS @@ -33,7 +32,7 @@ set(FSR2_BASE_ARGS -DFFX_FSR2_OPTION_UPSAMPLE_USE_LANCZOS_TYPE=2) set(FSR2_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(FSR2_PERMUTATION_ARGS # Reproject can use either reference lanczos or LUT diff --git a/sdk/src/backends/dx12/CMakeShadersFSR3Upscaler.txt b/sdk/src/backends/dx12/CMakeShadersFSR3Upscaler.txt new file mode 100644 index 00000000..96c155e2 --- /dev/null +++ b/sdk/src/backends/dx12/CMakeShadersFSR3Upscaler.txt @@ -0,0 +1,57 @@ +# This file is part of the FidelityFX SDK. +# +# Copyright (c) 2023 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. + +set(FSR3UPSCALER_BASE_ARGS + -reflection -deps=gcc -DFFX_GPU=1 + + # Only reprojection is to do half for now + -DFFX_FSR3UPSCALER_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF=0 + -DFFX_FSR3UPSCALER_OPTION_ACCUMULATE_SAMPLERS_USE_DATA_HALF=0 + -DFFX_FSR3UPSCALER_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF=1 + -DFFX_FSR3UPSCALER_OPTION_POSTPROCESSLOCKSTATUS_SAMPLERS_USE_DATA_HALF=0 + + # Upsample uses lanczos approximation + -DFFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE=2) + +set(FSR3UPSCALER_DX12_BASE_ARGS + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) + +set(FSR3UPSCALER_PERMUTATION_ARGS + # Reproject can use either reference lanczos or LUT + -DFFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE={0,1} + -DFFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT={0,1} + -DFFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS={0,1} + -DFFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS={0,1} + -DFFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH={0,1} + -DFFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING={0,1}) + +set(FSR3UPSCALER_INCLUDE_ARGS + "${FFX_GPU_PATH}" + "${FFX_GPU_PATH}/fsr3upscaler") + +file(GLOB FSR3UPSCALER_SHADERS + "shaders/fsr3upscaler/*.hlsl") + +# compile all the shaders +compile_shaders("${FFX_SC_EXECUTABLE}" "${FSR3UPSCALER_BASE_ARGS}" "${FSR3UPSCALER_DX12_BASE_ARGS}" "${FSR3UPSCALER_PERMUTATION_ARGS}" "${FSR3UPSCALER_INCLUDE_ARGS}" "${FSR3UPSCALER_SHADERS}" FSR3UPSCALER_PERMUTATION_OUTPUTS) + +# add the header files they generate to the main list of dependencies +add_shader_output("${FSR3UPSCALER_PERMUTATION_OUTPUTS}") diff --git a/sdk/src/backends/dx12/CMakeShadersFrameinterpolation.txt b/sdk/src/backends/dx12/CMakeShadersFrameinterpolation.txt new file mode 100644 index 00000000..cae2e96c --- /dev/null +++ b/sdk/src/backends/dx12/CMakeShadersFrameinterpolation.txt @@ -0,0 +1,49 @@ +# This file is part of the FidelityFX SDK. +# +# Copyright (c) 2023 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. + +set(FRAMEINTERPOLATION_BASE_ARGS + -DFFX_FRAMEINTERPOLATION_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF=0 + -DFFX_FRAMEINTERPOLATION_OPTION_ACCUMULATE_SAMPLERS_USE_DATA_HALF=0 + -DFFX_FRAMEINTERPOLATION_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF=1 + -DFFX_FRAMEINTERPOLATION_OPTION_POSTPROCESSLOCKSTATUS_SAMPLERS_USE_DATA_HALF=0 + # Upsample uses lanczos approximation + -DFFX_FRAMEINTERPOLATION_OPTION_UPSAMPLE_USE_LANCZOS_TYPE=2 + -reflection -deps=gcc -DFFX_GPU=1 ) + +set(FRAMEINTERPOLATION_DX12_BASE_ARGS + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) + +set(FRAMEINTERPOLATION_PERMUTATION_ARGS + # Reproject can use either reference lanczos or LUT + -DFFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH={0,1}) + +set(FRAMEINTERPOLATION_INCLUDE_ARGS + "${FFX_GPU_PATH}" + "${FFX_GPU_PATH}/frameinterpolation") + +file(GLOB FRAMEINTERPOLATION_SHADERS + "shaders/frameinterpolation/*.hlsl") + +# compile all the shaders +compile_shaders("${FFX_SC_EXECUTABLE}" "${FRAMEINTERPOLATION_BASE_ARGS}" "${FRAMEINTERPOLATION_DX12_BASE_ARGS}" "${FRAMEINTERPOLATION_PERMUTATION_ARGS}" "${FRAMEINTERPOLATION_INCLUDE_ARGS}" "${FRAMEINTERPOLATION_SHADERS}" FRAMEINTERPOLATION_PERMUTATION_OUTPUTS) + +# add the header files they generate to the main list of dependencies +add_shader_output("${FRAMEINTERPOLATION_PERMUTATION_OUTPUTS}") diff --git a/sdk/src/backends/dx12/CMakeShadersLENS.txt b/sdk/src/backends/dx12/CMakeShadersLENS.txt index 33351b73..91f9b64d 100644 --- a/sdk/src/backends/dx12/CMakeShadersLENS.txt +++ b/sdk/src/backends/dx12/CMakeShadersLENS.txt @@ -1,30 +1,29 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. # -# 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 : +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # -# The above copyright notice and this permission notice shall be included in +# 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 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. set(LENS_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(LENS_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(LENS_PERMUTATION_ARGS -DFFX_LENS_OPTION_LINEAR_SAMPLE={0,1} diff --git a/sdk/src/backends/dx12/CMakeShadersLPM.txt b/sdk/src/backends/dx12/CMakeShadersLPM.txt index a7170659..305d3304 100644 --- a/sdk/src/backends/dx12/CMakeShadersLPM.txt +++ b/sdk/src/backends/dx12/CMakeShadersLPM.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. -# +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# +# 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 +# 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 @@ -24,7 +23,7 @@ set(LPM_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(LPM_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(LPM_INCLUDE_ARGS "${FFX_GPU_PATH}" diff --git a/sdk/src/backends/dx12/CMakeShadersOpticalflow.txt b/sdk/src/backends/dx12/CMakeShadersOpticalflow.txt new file mode 100644 index 00000000..5cade964 --- /dev/null +++ b/sdk/src/backends/dx12/CMakeShadersOpticalflow.txt @@ -0,0 +1,50 @@ +# This file is part of the FidelityFX SDK. +# +# Copyright (c) 2023 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. + +set(OPTICALFLOW_BASE_ARGS + -reflection -deps=gcc -DFFX_GPU=1) + +set(OPTICALFLOW_DX12_BASE_ARGS + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) + +set(OPTICALFLOW_PERMUTATION_ARGS + -DFFX_OPTICALFLOW_OPTION_HDR_COLOR_INPUT={0,1} + ) + +set(OPTICALFLOW_INCLUDE_ARGS + "${FFX_GPU_PATH}" + "${FFX_GPU_PATH}/opticalflow") + +file(GLOB OPTICALFLOW_SHADERS + "shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.hlsl" + "shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.hlsl" + "shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.hlsl" + "shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.hlsl" + "shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.hlsl" + "shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.hlsl" + "shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.hlsl" +) + +# compile all the shaders +compile_shaders("${FFX_SC_EXECUTABLE}" "${OPTICALFLOW_BASE_ARGS}" "${OPTICALFLOW_DX12_BASE_ARGS}" "${OPTICALFLOW_PERMUTATION_ARGS}" "${OPTICALFLOW_INCLUDE_ARGS}" "${OPTICALFLOW_SHADERS}" OPTICALFLOW_PERMUTATION_OUTPUTS) + +# add the header files they generate to the main list of dependencies +add_shader_output("${OPTICALFLOW_PERMUTATION_OUTPUTS}") diff --git a/sdk/src/backends/dx12/CMakeShadersParallelSort.txt b/sdk/src/backends/dx12/CMakeShadersParallelSort.txt index 5570871d..8f365af3 100644 --- a/sdk/src/backends/dx12/CMakeShadersParallelSort.txt +++ b/sdk/src/backends/dx12/CMakeShadersParallelSort.txt @@ -1,30 +1,29 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. # -# 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 : +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # -# The above copyright notice and this permission notice shall be included in +# 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 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. set(PARALLELSORT_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(PARALLELSORT_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(PARALLELSORT_PERMUTATION_ARGS -DFFX_PARALLELSORT_OPTION_HAS_PAYLOAD={0,1} diff --git a/sdk/src/backends/dx12/CMakeShadersSPD.txt b/sdk/src/backends/dx12/CMakeShadersSPD.txt index b56bb3ef..2aeaddb1 100644 --- a/sdk/src/backends/dx12/CMakeShadersSPD.txt +++ b/sdk/src/backends/dx12/CMakeShadersSPD.txt @@ -1,30 +1,29 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. # -# 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 : +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # -# The above copyright notice and this permission notice shall be included in +# 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 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. set(SPD_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(SPD_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(SPD_PERMUTATION_ARGS -DFFX_SPD_OPTION_LINEAR_SAMPLE={0,1} diff --git a/sdk/src/backends/dx12/CMakeShadersSSSR.txt b/sdk/src/backends/dx12/CMakeShadersSSSR.txt index d20be71c..5bc084c2 100644 --- a/sdk/src/backends/dx12/CMakeShadersSSSR.txt +++ b/sdk/src/backends/dx12/CMakeShadersSSSR.txt @@ -1,30 +1,29 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. # -# 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 : +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # -# The above copyright notice and this permission notice shall be included in +# 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 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. set(SSSR_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(SSSR_DX12_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(SSSR_PERMUTATION_ARGS -DFFX_SSSR_OPTION_INVERTED_DEPTH={0,1}) diff --git a/sdk/src/backends/dx12/CMakeShadersVRS.txt b/sdk/src/backends/dx12/CMakeShadersVRS.txt index 4cedb248..654d8e6b 100644 --- a/sdk/src/backends/dx12/CMakeShadersVRS.txt +++ b/sdk/src/backends/dx12/CMakeShadersVRS.txt @@ -1,30 +1,29 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. # -# 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 : +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # -# The above copyright notice and this permission notice shall be included in +# 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 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. set(VRS_BASE_ARGS -reflection -deps=gcc -DFFX_GPU=1) set(VRS_CAULDRON_BASE_ARGS - -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1 -DFFX_HLSL_6_2=1) + -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_HLSL=1) set(VRS_PERMUTATION_ARGS -DFFX_VRS_OPTION_ADDITIONALSHADINGRATES={0,1} diff --git a/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12.cpp b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12.cpp new file mode 100644 index 00000000..580c8674 --- /dev/null +++ b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12.cpp @@ -0,0 +1,1569 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include "FrameInterpolationSwapChainDX12.h" + +#include +#include "FrameInterpolationSwapchainDX12_UiComposition.h" + +FfxErrorCode ffxRegisterFrameinterpolationUiResourceDX12(FfxSwapchain gameSwapChain, FfxResource uiResource) +{ + IDXGISwapChain4* swapChain = ffxGetDX12SwapchainPtr(gameSwapChain); + + FrameInterpolationSwapChainDX12* framinterpolationSwapchain = nullptr; + if (SUCCEEDED(swapChain->QueryInterface(IID_PPV_ARGS(&framinterpolationSwapchain)))) + { + framinterpolationSwapchain->registerUiResource(uiResource); + + SafeRelease(framinterpolationSwapchain); + + return FFX_OK; + } + + return FFX_ERROR_INVALID_ARGUMENT; +} + +FFX_API FfxErrorCode ffxSetFrameGenerationConfigToSwapchainDX12(FfxFrameGenerationConfig const* config) +{ + FfxErrorCode result = FFX_ERROR_INVALID_ARGUMENT; + + if (config->swapChain) + { + IDXGISwapChain4* swapChain = ffxGetDX12SwapchainPtr(config->swapChain); + FrameInterpolationSwapChainDX12* framinterpolationSwapchain = nullptr; + if (SUCCEEDED(swapChain->QueryInterface(IID_PPV_ARGS(&framinterpolationSwapchain)))) + { + framinterpolationSwapchain->setFrameGenerationConfig(config); + + SafeRelease(framinterpolationSwapchain); + + result = FFX_OK; + } + } + + return result; +} + +FfxResource ffxGetFrameinterpolationTextureDX12(FfxSwapchain gameSwapChain) +{ + FfxResource res = { nullptr }; + IDXGISwapChain4* swapChain = ffxGetDX12SwapchainPtr(gameSwapChain); + FrameInterpolationSwapChainDX12* framinterpolationSwapchain = nullptr; + if (SUCCEEDED(swapChain->QueryInterface(IID_PPV_ARGS(&framinterpolationSwapchain)))) + { + res = framinterpolationSwapchain->interpolationOutput(0); + + SafeRelease(framinterpolationSwapchain); + } + return res; +} + +FfxErrorCode ffxGetFrameinterpolationCommandlistDX12(FfxSwapchain gameSwapChain, FfxCommandList& gameCommandlist) +{ + // 1) query FrameInterpolationSwapChainDX12 from gameSwapChain + // 2) call FrameInterpolationSwapChainDX12::getInterpolationCommandList() + IDXGISwapChain4* swapChain = ffxGetDX12SwapchainPtr(gameSwapChain); + + FrameInterpolationSwapChainDX12* framinterpolationSwapchain = nullptr; + if (SUCCEEDED(swapChain->QueryInterface(IID_PPV_ARGS(&framinterpolationSwapchain)))) + { + gameCommandlist = framinterpolationSwapchain->getInterpolationCommandList(); + + SafeRelease(framinterpolationSwapchain); + + return FFX_OK; + } + + return FFX_ERROR_INVALID_ARGUMENT; +} + +FfxErrorCode ffxReplaceSwapchainForFrameinterpolationDX12(FfxCommandQueue gameQueue, FfxSwapchain& gameSwapChain) +{ + FfxErrorCode status = FFX_ERROR_INVALID_ARGUMENT; + IDXGISwapChain4* dxgiGameSwapChain = reinterpret_cast(gameSwapChain); + FFX_ASSERT(dxgiGameSwapChain); + + ID3D12CommandQueue* queue = reinterpret_cast(gameQueue); + FFX_ASSERT(queue); + + // we just need the desc, release the real swapchain as we'll replace that with one doing frameinterpolation + HWND hWnd; + DXGI_SWAP_CHAIN_DESC1 desc1; + DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc; + if (SUCCEEDED(dxgiGameSwapChain->GetDesc1(&desc1)) && + SUCCEEDED(dxgiGameSwapChain->GetFullscreenDesc(&fullscreenDesc)) && + SUCCEEDED(dxgiGameSwapChain->GetHwnd(&hWnd)) + ) + { + FFX_ASSERT_MESSAGE(fullscreenDesc.Windowed == TRUE, "Illegal to release a fullscreen swap chain."); + + IDXGIFactory* dxgiFactory = getDXGIFactoryFromSwapChain(dxgiGameSwapChain); + SafeRelease(dxgiGameSwapChain); + + FfxSwapchain proxySwapChain; + status = ffxCreateFrameinterpolationSwapchainForHwndDX12(hWnd, &desc1, &fullscreenDesc, queue, dxgiFactory, proxySwapChain); + if (status == FFX_OK) + { + gameSwapChain = proxySwapChain; + } + + SafeRelease(dxgiFactory); + } + + return status; +} + +FfxErrorCode ffxCreateFrameinterpolationSwapchainDX12(const DXGI_SWAP_CHAIN_DESC* desc, + ID3D12CommandQueue* queue, + IDXGIFactory* dxgiFactory, + FfxSwapchain& outGameSwapChain) +{ + FFX_ASSERT(desc); + FFX_ASSERT(queue); + FFX_ASSERT(dxgiFactory); + + DXGI_SWAP_CHAIN_DESC1 desc1{}; + desc1.Width = desc->BufferDesc.Width; + desc1.Height = desc->BufferDesc.Height; + desc1.Format = desc->BufferDesc.Format; + desc1.SampleDesc = desc->SampleDesc; + desc1.BufferUsage = desc->BufferUsage; + desc1.BufferCount = desc->BufferCount; + desc1.SwapEffect = desc->SwapEffect; + desc1.Flags = desc->Flags; + + // for clarity, params not part of DXGI_SWAP_CHAIN_DESC + // implicit behavior of DXGI when you call the IDXGIFactory::CreateSwapChain + desc1.Scaling = DXGI_SCALING_STRETCH; + desc1.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + desc1.Stereo = FALSE; + + DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc{}; + fullscreenDesc.Scaling = desc->BufferDesc.Scaling; + fullscreenDesc.RefreshRate = desc->BufferDesc.RefreshRate; + fullscreenDesc.ScanlineOrdering = desc->BufferDesc.ScanlineOrdering; + fullscreenDesc.Windowed = desc->Windowed; + + return ffxCreateFrameinterpolationSwapchainForHwndDX12(desc->OutputWindow, &desc1, &fullscreenDesc, queue, dxgiFactory, outGameSwapChain); +} + +FfxErrorCode ffxCreateFrameinterpolationSwapchainForHwndDX12(HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* desc1, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* fullscreenDesc, + ID3D12CommandQueue* queue, + IDXGIFactory* dxgiFactory, + FfxSwapchain& outGameSwapChain) +{ + // don't assert fullscreenDesc, nullptr valid + FFX_ASSERT(hWnd != 0); + FFX_ASSERT(desc1); + FFX_ASSERT(queue); + FFX_ASSERT(dxgiFactory); + + FfxErrorCode err = FFX_ERROR_INVALID_ARGUMENT; + + IDXGIFactory2* dxgiFactory2 = nullptr; + if (SUCCEEDED(dxgiFactory->QueryInterface(IID_PPV_ARGS(&dxgiFactory2)))) + { + // Create proxy swapchain + FrameInterpolationSwapChainDX12* fiSwapchain = new FrameInterpolationSwapChainDX12(); + if (fiSwapchain) + { + if (SUCCEEDED(fiSwapchain->init(hWnd, desc1, fullscreenDesc, queue, dxgiFactory2))) + { + outGameSwapChain = ffxGetSwapchainDX12(fiSwapchain); + + err = FFX_OK; + } + else + { + delete fiSwapchain; + err = FFX_ERROR_INVALID_ARGUMENT; + } + } + else + { + err = FFX_ERROR_OUT_OF_MEMORY; + } + + SafeRelease(dxgiFactory2); + } + + return err; +} + +FfxErrorCode ffxWaitForPresents(FfxSwapchain gameSwapChain) +{ + IDXGISwapChain4* swapChain = ffxGetDX12SwapchainPtr(gameSwapChain); + + FrameInterpolationSwapChainDX12* framinterpolationSwapchain; + if (SUCCEEDED(swapChain->QueryInterface(IID_PPV_ARGS(&framinterpolationSwapchain)))) + { + framinterpolationSwapchain->waitForPresents(); + SafeRelease(framinterpolationSwapchain); + + return FFX_OK; + } + + return FFX_ERROR_INVALID_ARGUMENT; +} + +void setSwapChainBufferResourceInfo(IDXGISwapChain4* swapChain, bool isInterpolated) +{ + uint32_t currBackbufferIndex = swapChain->GetCurrentBackBufferIndex(); + ID3D12Resource* swapchainBackbuffer = nullptr; + + if (SUCCEEDED(swapChain->GetBuffer(currBackbufferIndex, IID_PPV_ARGS(&swapchainBackbuffer)))) + { + FfxFrameInterpolationSwapChainResourceInfo info{}; + info.version = FFX_FRAME_INTERPOLATION_SWAP_CHAIN_VERSION; + info.isInterpolated = isInterpolated; + HRESULT hr = swapchainBackbuffer->SetPrivateData(IID_IFfxFrameInterpolationSwapChainResourceInfo, sizeof(info), &info); + FFX_ASSERT(SUCCEEDED(hr)); + + /* + usage example: + + FfxFrameInterpolationSwapChainResourceInfo info{}; + UINT size = sizeof(info); + if (SUCCEEDED(swapchainBackbuffer->GetPrivateData(IID_IFfxFrameInterpolationSwapChainResourceInfo, &size, &info))) { + + } else { + // buffer was not presented using proxy swapchain + } + */ + + SafeRelease(swapchainBackbuffer); + } +} + +HRESULT compositeSwapChainFrame(FrameinterpolationPresentInfo* presenter, PacingData* pacingEntry, uint32_t frameID) +{ + const PacingData::FrameInfo& frameInfo = pacingEntry->frames[frameID]; + + presenter->presentQueue->Wait(presenter->interpolationFence, frameInfo.interpolationCompletedFenceValue); + + if (pacingEntry->presentCallback) + { + auto gpuCommands = presenter->commandPool.get(presenter->presentQueue, L"compositeSwapChainFrame"); + + uint32_t currBackbufferIndex = presenter->swapChain->GetCurrentBackBufferIndex(); + ID3D12Resource* swapchainBackbuffer = nullptr; + presenter->swapChain->GetBuffer(currBackbufferIndex, IID_PPV_ARGS(&swapchainBackbuffer)); + + FfxPresentCallbackDescription desc{}; + desc.commandList = ffxGetCommandListDX12(gpuCommands->reset()); + desc.device = presenter->device; + desc.isInterpolatedFrame = frameID != PacingData::FrameIdentifier::Real; + desc.outputSwapChainBuffer = ffxGetResourceDX12(swapchainBackbuffer, GetFfxResourceDescriptionDX12(swapchainBackbuffer), nullptr, FFX_RESOURCE_STATE_PRESENT); + desc.currentBackBuffer = frameInfo.resource; + desc.currentUI = pacingEntry->uiSurface; + + pacingEntry->presentCallback(&desc); + + gpuCommands->execute(true); + + SafeRelease(swapchainBackbuffer); + } + + presenter->presentQueue->Signal(presenter->compositionFence, frameInfo.presentIndex); + + return S_OK; +} + +void presentToSwapChain(FrameinterpolationPresentInfo* presenter, PacingData* pacingEntry, uint32_t frameID) +{ + const PacingData::FrameInfo& frameInfo = pacingEntry->frames[frameID]; + + const UINT uSyncInterval = pacingEntry->vsync ? 1 : 0; + const bool bExclusiveFullscreen = isExclusiveFullscreen(presenter->swapChain); + const bool bSetAllowTearingFlag = pacingEntry->tearingSupported && !bExclusiveFullscreen && (0 == uSyncInterval); + const UINT uFlags = bSetAllowTearingFlag * DXGI_PRESENT_ALLOW_TEARING; + + presenter->swapChain->Present(uSyncInterval, uFlags); + + // tick frames sent for presentation + presenter->presentQueue->Signal(presenter->presentFence, frameInfo.presentIndex); +} + +DWORD WINAPI presenterThread(LPVOID param) +{ + FrameinterpolationPresentInfo* presenter = static_cast(param); + + if (presenter) + { + UINT64 numFramesSentForPresentation = 0; + + while (!presenter->shutdown) + { + + WaitForSingleObject(presenter->pacerEvent, INFINITE); + + if (!presenter->shutdown) + { + EnterCriticalSection(&presenter->criticalSectionScheduledFrame); + + PacingData entry = presenter->scheduledPresents; + presenter->scheduledPresents.invalidate(); + + LeaveCriticalSection(&presenter->criticalSectionScheduledFrame); + + if (entry.numFramesToPresent > 0) + { + // we might have dropped entries so have to update here, otherwise we might deadlock + presenter->presentQueue->Signal(presenter->presentFence, entry.numFramesSentForPresentationBase); + presenter->presentQueue->Wait(presenter->gameFence, entry.gameFenceValue); + + for (uint32_t frameID = 0; frameID < PacingData::FrameIdentifier::Count; frameID++) + { + const PacingData::FrameInfo& frameInfo = entry.frames[frameID]; + if (frameInfo.doPresent) + { + compositeSwapChainFrame(presenter, &entry, frameID); + + // signal replacement buffer availability + if (frameInfo.presentIndex == entry.replacementBufferFenceSignal) + { + presenter->presentQueue->Signal(presenter->replacementBufferFence, entry.replacementBufferFenceSignal); + } + + waitForPerformanceCount(frameInfo.presentQpcTarget); + + presentToSwapChain(presenter, &entry, frameID); + } + } + + numFramesSentForPresentation = entry.numFramesSentForPresentationBase + entry.numFramesToPresent; + } + } + } + + waitForFenceValue(presenter->presentFence, numFramesSentForPresentation); + } + + return 0; +} + +DWORD WINAPI interpolationThread(LPVOID param) +{ + FrameinterpolationPresentInfo* presenter = static_cast(param); + + if (presenter) + { + HANDLE presenterThreadHandle = CreateThread(nullptr, 0, presenterThread, param, 0, nullptr); + FFX_ASSERT(presenterThreadHandle != NULL); + + if (presenterThreadHandle != 0) + { + SetThreadPriority(presenterThreadHandle, THREAD_PRIORITY_HIGHEST); + SetThreadDescription(presenterThreadHandle, L"AMD FSR Presenter Thread"); + + SimpleMovingAverage<2, double> frameTime{}; + SimpleMovingAverage<2, double> compositionTime{}; + + int64_t previousQpc = 0; + + while (!presenter->shutdown) + { + WaitForSingleObject(presenter->presentEvent, INFINITE); + + if (!presenter->shutdown) + { + EnterCriticalSection(&presenter->criticalSectionScheduledFrame); + + PacingData entry = presenter->scheduledInterpolations; + presenter->scheduledInterpolations.invalidate(); + + LeaveCriticalSection(&presenter->criticalSectionScheduledFrame); + + waitForFenceValue(presenter->interpolationFence, + entry.frames[PacingData::FrameIdentifier::Interpolated_1].interpolationCompletedFenceValue); + SetEvent(presenter->interpolationEvent); + + int64_t currentQpc = 0; + QueryPerformanceCounter(reinterpret_cast(¤tQpc)); + + const double deltaQpc = double(currentQpc - previousQpc) * (previousQpc > 0); + previousQpc = currentQpc; + + // reset pacing averaging if delta > 10 fps, + int64_t qpcFrequency; + QueryPerformanceFrequency(reinterpret_cast(&qpcFrequency)); + const float fTimeoutInSeconds = 0.1f; + double deltaQpcResetThreashold = double(qpcFrequency * fTimeoutInSeconds); + if (deltaQpc > deltaQpcResetThreashold) + { + frameTime.reset(); + compositionTime.reset(); + } + else + { + frameTime.update(deltaQpc); + } + + // set presentation time for the real frame + const int64_t deltaToUse = int64_t(frameTime.getAverage() * 0.5) + int64_t(compositionTime.getAverage()); + entry.frames[PacingData::FrameIdentifier::Real].presentQpcTarget = currentQpc + deltaToUse; + + // schedule presents + EnterCriticalSection(&presenter->criticalSectionScheduledFrame); + presenter->scheduledPresents = entry; + LeaveCriticalSection(&presenter->criticalSectionScheduledFrame); + SetEvent(presenter->pacerEvent); + + // estimate gpu composition time if both interpolated and real frames are to be presented + if (entry.vsync == false && + entry.frames[PacingData::FrameIdentifier::Interpolated_1].doPresent && + entry.frames[PacingData::FrameIdentifier::Real].doPresent) + { + int64_t compositionBeginQpc = 0; + int64_t compositionEndQpc = 0; + + // wait for interpolated frame present to finish + waitForFenceValue(presenter->presentFence, entry.frames[PacingData::FrameIdentifier::Interpolated_1].presentIndex); + QueryPerformanceCounter(reinterpret_cast(&compositionBeginQpc)); + + // wait for real frame composition to finish + waitForFenceValue(presenter->compositionFence, entry.frames[PacingData::FrameIdentifier::Real].presentIndex); + QueryPerformanceCounter(reinterpret_cast(&compositionEndQpc)); + + const double duration = double(compositionEndQpc - compositionBeginQpc); + compositionTime.update(duration); + } + else + { + compositionTime.reset(); + } + } + } + + // signal event to allow thread to finish + SetEvent(presenter->pacerEvent); + WaitForSingleObject(presenterThreadHandle, INFINITE); + SafeCloseHandle(presenterThreadHandle); + } + } + + return 0; +} + +bool FrameInterpolationSwapChainDX12::verifyBackbufferDuplicateResources() +{ + HRESULT hr = S_OK; + + ID3D12Device8* device = nullptr; + ID3D12Resource* buffer = nullptr; + if (SUCCEEDED(real()->GetBuffer(0, IID_PPV_ARGS(&buffer)))) + { + if (SUCCEEDED(buffer->GetDevice(IID_PPV_ARGS(&device)))) + { + auto bufferDesc = buffer->GetDesc(); + + D3D12_HEAP_PROPERTIES heapProperties{}; + D3D12_HEAP_FLAGS heapFlags; + buffer->GetHeapProperties(&heapProperties, &heapFlags); + + heapFlags &= ~D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES; + heapFlags &= ~D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES; + heapFlags &= ~D3D12_HEAP_FLAG_DENY_BUFFERS; + heapFlags &= ~D3D12_HEAP_FLAG_ALLOW_DISPLAY; + + for (size_t i = 0; i < gameBufferCount_; i++) + { + if (replacementSwapBuffers_[i].resource == nullptr) + { + // create game render output resource + if (FAILED(device->CreateCommittedResource(&heapProperties, + heapFlags, + &bufferDesc, + D3D12_RESOURCE_STATE_PRESENT, + nullptr, + IID_PPV_ARGS(&replacementSwapBuffers_[i].resource)))) + { + hr |= E_FAIL; + } + else + { + replacementSwapBuffers_[i].resource->SetName(L"AMD FSR Replacement BackBuffer"); + } + } + } + + for (size_t i = 0; i < _countof(interpolationOutputs_); i++) + { + // create interpolation output resource + bufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + if (interpolationOutputs_[i].resource == nullptr) + { + if (FAILED(device->CreateCommittedResource( + &heapProperties, heapFlags, &bufferDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(&interpolationOutputs_[i].resource)))) + { + hr |= E_FAIL; + } + else + { + interpolationOutputs_[i].resource->SetName(L"AMD FSR Interpolation Output"); + } + } + } + + SafeRelease(device); + } + + SafeRelease(realBackBuffer0_); + realBackBuffer0_ = buffer; + } + + return SUCCEEDED(hr); +} + +HRESULT FrameInterpolationSwapChainDX12::init(HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* desc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* fullscreenDesc, + ID3D12CommandQueue* queue, + IDXGIFactory2* dxgiFactory) +{ + FFX_ASSERT(desc); + FFX_ASSERT(queue); + FFX_ASSERT(dxgiFactory); + + // store values we modify, to return when application asks for info + gameBufferCount_ = desc->BufferCount; + gameFlags_ = desc->Flags; + gameSwapEffect_ = desc->SwapEffect; + + // set default ui composition / frame interpolation present function + presentCallback_ = ffxFrameInterpolationUiComposition; + + HRESULT hr = E_FAIL; + + if (SUCCEEDED(queue->GetDevice(IID_PPV_ARGS(&presentInfo_.device)))) + { + presentInfo_.gameQueue = queue; + + InitializeCriticalSection(&criticalSection_); + InitializeCriticalSection(&presentInfo_.criticalSectionScheduledFrame); + presentInfo_.presentEvent = CreateEvent(NULL, FALSE, FALSE, nullptr); + presentInfo_.interpolationEvent = CreateEvent(NULL, FALSE, TRUE, nullptr); + presentInfo_.pacerEvent = CreateEvent(NULL, FALSE, FALSE,nullptr); + tearingSupported_ = isTearingSupported(dxgiFactory); + + // Create presentation queue + D3D12_COMMAND_QUEUE_DESC presentQueueDesc = queue->GetDesc(); + presentQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + presentQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + presentQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH; + presentQueueDesc.NodeMask = 0; + presentInfo_.device->CreateCommandQueue(&presentQueueDesc, IID_PPV_ARGS(&presentInfo_.presentQueue)); + presentInfo_.presentQueue->SetName(L"AMD FSR PresentQueue"); + + // Setup pass-through swapchain default state is disabled/passthrough + IDXGISwapChain1* pSwapChain1 = nullptr; + + DXGI_SWAP_CHAIN_DESC1 realDesc = getInterpolationEnabledSwapChainDescription(desc); + hr = dxgiFactory->CreateSwapChainForHwnd(presentInfo_.presentQueue, hWnd, &realDesc, fullscreenDesc, nullptr, &pSwapChain1); + if (SUCCEEDED(hr) && queue) + { + if (SUCCEEDED(hr = pSwapChain1->QueryInterface(IID_PPV_ARGS(&presentInfo_.swapChain)))) + { + // Register proxy swapchain to the real swap chain object + presentInfo_.swapChain->SetPrivateData(IID_IFfxFrameInterpolationSwapChain, sizeof(FrameInterpolationSwapChainDX12*), this); + + SafeRelease(pSwapChain1); + } + else + { + FFX_ASSERT(hr == S_OK); + return hr; + } + } + else + { + FFX_ASSERT(hr == S_OK); + return hr; + } + + // init min and lax luminance according to monitor metadata + // in case app doesn't set it through SetHDRMetadata + getMonitorLuminanceRange(presentInfo_.swapChain, &minLuminance_, &maxLuminance_); + + presentInfo_.device->CreateFence(gameFenceValue_, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&presentInfo_.gameFence)); + presentInfo_.gameFence->SetName(L"AMD FSR GameFence"); + + presentInfo_.device->CreateFence(interpolationFenceValue_, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&presentInfo_.interpolationFence)); + presentInfo_.interpolationFence->SetName(L"AMD FSR InterpolationFence"); + + presentInfo_.device->CreateFence(framesSentForPresentation_, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&presentInfo_.presentFence)); + presentInfo_.presentFence->SetName(L"AMD FSR PresentFence"); + + presentInfo_.device->CreateFence(framesSentForPresentation_, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&presentInfo_.replacementBufferFence)); + presentInfo_.replacementBufferFence->SetName(L"AMD FSR ReplacementBufferFence"); + + presentInfo_.device->CreateFence(framesSentForPresentation_, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&presentInfo_.compositionFence)); + presentInfo_.compositionFence->SetName(L"AMD FSR CompositionFence"); + + replacementFrameLatencyWaitableObjectHandle_ = CreateEvent(0, FALSE, TRUE, nullptr); + + // Create interpolation queue + D3D12_COMMAND_QUEUE_DESC queueDesc = queue->GetDesc(); + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH; + queueDesc.NodeMask = 0; + presentInfo_.device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&presentInfo_.asyncComputeQueue)); + presentInfo_.asyncComputeQueue->SetName(L"AMD FSR AsyncComputeQueue"); + + // Default to dispatch interpolation workloads on the game queue + presentInfo_.interpolationQueue = presentInfo_.gameQueue; + } + + return hr; +} + +FrameInterpolationSwapChainDX12::FrameInterpolationSwapChainDX12() +{ + +} + +FrameInterpolationSwapChainDX12::~FrameInterpolationSwapChainDX12() +{ + shutdown(); +} + +UINT FrameInterpolationSwapChainDX12::getInterpolationEnabledSwapChainFlags(UINT nonAdjustedFlags) +{ + UINT flags = nonAdjustedFlags; + flags &= ~DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + + if (tearingSupported_) + { + flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + } + + return flags; +} + +DXGI_SWAP_CHAIN_DESC1 FrameInterpolationSwapChainDX12::getInterpolationEnabledSwapChainDescription(const DXGI_SWAP_CHAIN_DESC1* nonAdjustedDesc) +{ + DXGI_SWAP_CHAIN_DESC1 fiDesc = *nonAdjustedDesc; + + // adjust swap chain descriptor to fit FI requirements + fiDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + fiDesc.BufferCount = 3; + fiDesc.Flags = getInterpolationEnabledSwapChainFlags(fiDesc.Flags); + + return fiDesc; +} + +IDXGISwapChain4* FrameInterpolationSwapChainDX12::real() +{ + return presentInfo_.swapChain; +} + +HRESULT FrameInterpolationSwapChainDX12::shutdown() +{ + //m_pDevice will be nullptr already shutdown + if (presentInfo_.device) + { + releaseUiBlitGpuResources(); + + destroyReplacementResources(); + + killPresenterThread(); + SafeCloseHandle(presentInfo_.presentEvent); + SafeCloseHandle(presentInfo_.interpolationEvent); + SafeCloseHandle(presentInfo_.pacerEvent); + + + presentInfo_.interpolationQueue->Signal(presentInfo_.interpolationFence, ++interpolationFenceValue_); + waitForFenceValue(presentInfo_.interpolationFence, interpolationFenceValue_); + SafeRelease(presentInfo_.asyncComputeQueue); + SafeRelease(presentInfo_.presentQueue); + + SafeRelease(presentInfo_.interpolationFence); + SafeRelease(presentInfo_.presentFence); + SafeRelease(presentInfo_.replacementBufferFence); + SafeRelease(presentInfo_.compositionFence); + + UINT sc_refCount = SafeRelease(presentInfo_.swapChain); + + waitForFenceValue(presentInfo_.gameFence, gameFenceValue_); + SafeRelease(presentInfo_.gameFence); + + DeleteCriticalSection(&criticalSection_); + DeleteCriticalSection(&presentInfo_.criticalSectionScheduledFrame); + + UINT device_refCount = SafeRelease(presentInfo_.device); + } + + return S_OK; +} + +bool FrameInterpolationSwapChainDX12::killPresenterThread() +{ + if (interpolationThreadHandle_ != NULL) + { + // prepare present CPU thread for shutdown + presentInfo_.shutdown = true; + + // signal event to allow thread to finish + SetEvent(presentInfo_.presentEvent); + WaitForSingleObject(interpolationThreadHandle_, INFINITE); + SafeCloseHandle(interpolationThreadHandle_); + } + + return interpolationThreadHandle_ == nullptr; +} + +bool FrameInterpolationSwapChainDX12::spawnPresenterThread() +{ + if (interpolationThreadHandle_ == NULL) + { + presentInfo_.shutdown = false; + interpolationThreadHandle_ = CreateThread(nullptr, 0, interpolationThread, reinterpret_cast(&presentInfo_), 0, nullptr); + + FFX_ASSERT(interpolationThreadHandle_ != NULL); + + if (interpolationThreadHandle_ != 0) + { + SetThreadPriority(interpolationThreadHandle_, THREAD_PRIORITY_HIGHEST); + SetThreadDescription(interpolationThreadHandle_, L"AMD FSR Interpolation Thread"); + } + + SetEvent(presentInfo_.interpolationEvent); + } + + return interpolationThreadHandle_ != NULL; +} + +void FrameInterpolationSwapChainDX12::discardOutstandingInterpolationCommandLists() +{ + // drop any outstanding interpolaton command lists + for (int i = 0; i < _countof(registeredInterpolationCommandLists_); i++) + { + if (registeredInterpolationCommandLists_[i] != nullptr) + { + registeredInterpolationCommandLists_[i]->drop(true); + registeredInterpolationCommandLists_[i] = nullptr; + } + } +} + +void FrameInterpolationSwapChainDX12::setFrameGenerationConfig(FfxFrameGenerationConfig const* config) +{ + FFX_ASSERT(config); + EnterCriticalSection(&criticalSection_); + + FfxPresentCallbackFunc inputPresentCallback = (nullptr != config->presentCallback) ? config->presentCallback : ffxFrameInterpolationUiComposition; + ID3D12CommandQueue* inputInterpolationQueue = config->allowAsyncWorkloads ? presentInfo_.asyncComputeQueue : presentInfo_.gameQueue; + + presentInterpolatedOnly_ = config->onlyPresentInterpolated; + + if (presentInfo_.interpolationQueue != inputInterpolationQueue) + { + waitForPresents(); + discardOutstandingInterpolationCommandLists(); + + // change interpolation queue and reset fence value + presentInfo_.interpolationQueue = inputInterpolationQueue; + interpolationFenceValue_ = 0; + presentInfo_.interpolationQueue->Signal(presentInfo_.interpolationFence, interpolationFenceValue_); + } + + if (interpolationEnabled_ != config->frameGenerationEnabled || + presentCallback_ != inputPresentCallback || + frameGenerationCallback_ != config->frameGenerationCallback) + { + waitForPresents(); + presentCallback_ = inputPresentCallback; + frameGenerationCallback_ = config->frameGenerationCallback; + + // handle interpolation mode change + if (interpolationEnabled_ != config->frameGenerationEnabled) + { + interpolationEnabled_ = config->frameGenerationEnabled; + if (interpolationEnabled_) + { + frameInterpolationResetCondition_ = true; + nextPresentWaitValue_ = framesSentForPresentation_; + + spawnPresenterThread(); + } + else + { + killPresenterThread(); + } + } + } + + LeaveCriticalSection(&criticalSection_); +} + +bool FrameInterpolationSwapChainDX12::destroyReplacementResources() +{ + HRESULT hr = S_OK; + + EnterCriticalSection(&criticalSection_); + + waitForPresents(); + + const bool recreatePresenterThread = interpolationThreadHandle_ != nullptr; + if (recreatePresenterThread) + { + killPresenterThread(); + } + + discardOutstandingInterpolationCommandLists(); + + { + for (size_t i = 0; i < _countof(replacementSwapBuffers_); i++) + { + replacementSwapBuffers_[i].destroy(); + } + SafeRelease(realBackBuffer0_); + + for (size_t i = 0; i < _countof(interpolationOutputs_); i++) + { + interpolationOutputs_[i].destroy(); + } + } + + // reset counters used in buffer management + framesSentForPresentation_ = 0; + nextPresentWaitValue_ = 0; + replacementSwapBufferIndex_ = 0; + presentCount_ = 0; + interpolationFenceValue_ = 0; + gameFenceValue_ = 0; + + presentInfo_.gameFence->Signal(gameFenceValue_); + presentInfo_.interpolationFence->Signal(interpolationFenceValue_); + presentInfo_.presentFence->Signal(framesSentForPresentation_); + presentInfo_.replacementBufferFence->Signal(framesSentForPresentation_); + presentInfo_.compositionFence->Signal(framesSentForPresentation_); + frameInterpolationResetCondition_ = true; + + if (recreatePresenterThread) + { + spawnPresenterThread(); + } + + discardOutstandingInterpolationCommandLists(); + + LeaveCriticalSection(&criticalSection_); + + return SUCCEEDED(hr); +} + +bool FrameInterpolationSwapChainDX12::waitForPresents() +{ + // wait for interpolation to finish + waitForFenceValue(presentInfo_.gameFence, gameFenceValue_); + waitForFenceValue(presentInfo_.interpolationFence, interpolationFenceValue_); + waitForFenceValue(presentInfo_.presentFence, framesSentForPresentation_); + + return true; +} + +FfxResource FrameInterpolationSwapChainDX12::interpolationOutput(int index) +{ + index = interpolationBufferIndex_; + + FfxResourceDescription interpolateDesc = GetFfxResourceDescriptionDX12(interpolationOutputs_[index].resource); + return ffxGetResourceDX12(interpolationOutputs_[index].resource, interpolateDesc, nullptr, FFX_RESOURCE_STATE_UNORDERED_ACCESS); +} + +//IUnknown +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::QueryInterface(REFIID riid, void** ppvObject) +{ + const GUID guidReplacements[] = { + __uuidof(this), + IID_IUnknown, + IID_IDXGIObject, + IID_IDXGIDeviceSubObject, + IID_IDXGISwapChain, + IID_IDXGISwapChain1, + IID_IDXGISwapChain2, + IID_IDXGISwapChain3, + IID_IDXGISwapChain4, + IID_IFfxFrameInterpolationSwapChain + }; + + for (auto guid : guidReplacements) + { + if (IsEqualGUID(riid, guid) == TRUE) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + } + + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::AddRef() +{ + InterlockedIncrement(&refCount_); + + return refCount_; +} + +ULONG STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::Release() +{ + ULONG ref = InterlockedDecrement(&refCount_); + if (ref != 0) + { + return refCount_; + } + + delete this; + + return 0; +} + +// IDXGIObject +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::SetPrivateData(REFGUID Name, UINT DataSize, const void* pData) +{ + return real()->SetPrivateData(Name, DataSize, pData); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::SetPrivateDataInterface(REFGUID Name, const IUnknown* pUnknown) +{ + return real()->SetPrivateDataInterface(Name, pUnknown); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetPrivateData(REFGUID Name, UINT* pDataSize, void* pData) +{ + return real()->GetPrivateData(Name, pDataSize, pData); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetParent(REFIID riid, void** ppParent) +{ + return real()->GetParent(riid, ppParent); +} + +// IDXGIDeviceSubObject +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetDevice(REFIID riid, void** ppDevice) +{ + return real()->GetDevice(riid, ppDevice); +} + +void FrameInterpolationSwapChainDX12::registerUiResource(FfxResource uiResource) +{ + EnterCriticalSection(&criticalSection_); + + presentInfo_.currentUiSurface = uiResource; + + LeaveCriticalSection(&criticalSection_); +} + +void FrameInterpolationSwapChainDX12::presentPassthrough(UINT SyncInterval, UINT Flags) +{ + ID3D12Resource* dx12SwapchainBuffer = nullptr; + UINT currentBackBufferIndex = presentInfo_.swapChain->GetCurrentBackBufferIndex(); + presentInfo_.swapChain->GetBuffer(currentBackBufferIndex, IID_PPV_ARGS(&dx12SwapchainBuffer)); + + auto passthroughList = presentInfo_.commandPool.get(presentInfo_.presentQueue, L"passthroughList()"); + auto list = passthroughList->reset(); + + ID3D12Resource* dx12ResourceSrc = replacementSwapBuffers_[replacementSwapBufferIndex_].resource; + ID3D12Resource* dx12ResourceDst = dx12SwapchainBuffer; + + D3D12_TEXTURE_COPY_LOCATION dx12SourceLocation = {}; + dx12SourceLocation.pResource = dx12ResourceSrc; + dx12SourceLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dx12SourceLocation.SubresourceIndex = 0; + + D3D12_TEXTURE_COPY_LOCATION dx12DestinationLocation = {}; + dx12DestinationLocation.pResource = dx12ResourceDst; + dx12DestinationLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dx12DestinationLocation.SubresourceIndex = 0; + + D3D12_RESOURCE_BARRIER barriers[2] = {}; + barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barriers[0].Transition.pResource = dx12ResourceSrc; + barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; + + barriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barriers[1].Transition.pResource = dx12ResourceDst; + barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; + list->ResourceBarrier(_countof(barriers), barriers); + + list->CopyResource(dx12ResourceDst, dx12ResourceSrc); + + for (int i = 0; i < _countof(barriers); ++i) + { + D3D12_RESOURCE_STATES tmpStateBefore = barriers[i].Transition.StateBefore; + barriers[i].Transition.StateBefore = barriers[i].Transition.StateAfter; + barriers[i].Transition.StateAfter = tmpStateBefore; + } + + list->ResourceBarrier(_countof(barriers), barriers); + + passthroughList->execute(true); + + presentInfo_.presentQueue->Signal(presentInfo_.replacementBufferFence, ++framesSentForPresentation_); + + setSwapChainBufferResourceInfo(presentInfo_.swapChain, false); + presentInfo_.swapChain->Present(SyncInterval, Flags); + + presentInfo_.presentQueue->Signal(presentInfo_.presentFence, framesSentForPresentation_); + presentInfo_.gameQueue->Wait(presentInfo_.presentFence, framesSentForPresentation_); + + SafeRelease(dx12SwapchainBuffer); +} + +void FrameInterpolationSwapChainDX12::presentWithUiComposition(UINT SyncInterval, UINT Flags) +{ + auto uiCompositionList = presentInfo_.commandPool.get(presentInfo_.presentQueue, L"uiCompositionList()"); + auto list = uiCompositionList->reset(); + + ID3D12Resource* dx12SwapchainBuffer = nullptr; + UINT currentBackBufferIndex = presentInfo_.swapChain->GetCurrentBackBufferIndex(); + presentInfo_.swapChain->GetBuffer(currentBackBufferIndex, IID_PPV_ARGS(&dx12SwapchainBuffer)); + + FfxResourceDescription outBufferDesc = GetFfxResourceDescriptionDX12(dx12SwapchainBuffer); + FfxResourceDescription inBufferDesc = GetFfxResourceDescriptionDX12(replacementSwapBuffers_[replacementSwapBufferIndex_].resource); + + FfxPresentCallbackDescription desc{}; + desc.commandList = ffxGetCommandListDX12(list); + desc.device = presentInfo_.device; + desc.isInterpolatedFrame = false; + desc.outputSwapChainBuffer = ffxGetResourceDX12(dx12SwapchainBuffer, outBufferDesc, nullptr, FFX_RESOURCE_STATE_PRESENT); + desc.currentBackBuffer = ffxGetResourceDX12(replacementSwapBuffers_[replacementSwapBufferIndex_].resource, inBufferDesc, nullptr, FFX_RESOURCE_STATE_PRESENT); + desc.currentUI = presentInfo_.currentUiSurface; + presentCallback_(&desc); + + uiCompositionList->execute(true); + + presentInfo_.presentQueue->Signal(presentInfo_.replacementBufferFence, ++framesSentForPresentation_); + + setSwapChainBufferResourceInfo(presentInfo_.swapChain, false); + presentInfo_.swapChain->Present(SyncInterval, Flags); + + presentInfo_.presentQueue->Signal(presentInfo_.presentFence, framesSentForPresentation_); + presentInfo_.gameQueue->Wait(presentInfo_.presentFence, framesSentForPresentation_); + + SafeRelease(dx12SwapchainBuffer); +} + +void FrameInterpolationSwapChainDX12::dispatchInterpolationCommands(FfxResource* pInterpolatedFrame, FfxResource* pRealFrame) +{ + FFX_ASSERT(pInterpolatedFrame); + FFX_ASSERT(pRealFrame); + + const UINT currentBackBufferIndex = GetCurrentBackBufferIndex(); + ID3D12Resource* pCurrentBackBuffer = replacementSwapBuffers_[currentBackBufferIndex].resource; + FfxResourceDescription gameFrameDesc = GetFfxResourceDescriptionDX12(pCurrentBackBuffer); + FfxResource backbuffer = ffxGetResourceDX12(replacementSwapBuffers_[currentBackBufferIndex].resource, gameFrameDesc, nullptr, FFX_RESOURCE_STATE_PRESENT); + + *pRealFrame = backbuffer; + + // interpolation queue must wait for output resource to become available + presentInfo_.interpolationQueue->Wait(presentInfo_.compositionFence, interpolationOutputs_[interpolationBufferIndex_].availabilityFenceValue); + + auto pRegisteredCommandList = registeredInterpolationCommandLists_[currentBackBufferIndex]; + if (pRegisteredCommandList != nullptr) + { + pRegisteredCommandList->execute(true); + + presentInfo_.interpolationQueue->Signal(presentInfo_.interpolationFence, ++interpolationFenceValue_); + + *pInterpolatedFrame = interpolationOutput(); + } + else { + Dx12Commands* interpolationCommandList = presentInfo_.commandPool.get(presentInfo_.interpolationQueue, L"getInterpolationCommandList()"); + auto dx12CommandList = interpolationCommandList->reset(); + + FfxFrameGenerationDispatchDescription desc{}; + desc.commandList = dx12CommandList; + desc.outputs[0] = interpolationOutput(); + desc.presentColor = backbuffer; + desc.reset = frameInterpolationResetCondition_; + desc.numInterpolatedFrames = 1; + desc.backBufferTransferFunction = static_cast(backBufferTransferFunction_); + desc.minMaxLuminance[0] = minLuminance_; + desc.minMaxLuminance[1] = maxLuminance_; + + if (frameGenerationCallback_(&desc) == FFX_OK) + { + interpolationCommandList->execute(true); + + presentInfo_.interpolationQueue->Signal(presentInfo_.interpolationFence, ++interpolationFenceValue_); + } + + // reset condition if at least one frame was interpolated + if (desc.numInterpolatedFrames > 0) + { + frameInterpolationResetCondition_ = false; + *pInterpolatedFrame = interpolationOutput(); + } + } +} + +void FrameInterpolationSwapChainDX12::presentInterpolated(UINT SyncInterval, UINT Flags) +{ + const bool bVsync = SyncInterval > 0; + + // interpolation needs to wait for the game queue + presentInfo_.gameQueue->Signal(presentInfo_.gameFence, ++gameFenceValue_); + presentInfo_.interpolationQueue->Wait(presentInfo_.gameFence, gameFenceValue_); + + FfxResource interpolatedFrame{}, realFrame{}; + dispatchInterpolationCommands(&interpolatedFrame, &realFrame); + + EnterCriticalSection(&presentInfo_.criticalSectionScheduledFrame); + + PacingData entry{}; + entry.presentCallback = presentCallback_; + entry.uiSurface = presentInfo_.currentUiSurface; + entry.vsync = bVsync; + entry.tearingSupported = tearingSupported_; + entry.numFramesSentForPresentationBase = framesSentForPresentation_; + entry.gameFenceValue = gameFenceValue_; + + // interpolated + PacingData::FrameInfo& fiInterpolated = entry.frames[PacingData::FrameIdentifier::Interpolated_1]; + if (interpolatedFrame.resource != nullptr) + { + fiInterpolated.doPresent = true; + fiInterpolated.resource = interpolatedFrame; + fiInterpolated.interpolationCompletedFenceValue = interpolationFenceValue_; + fiInterpolated.presentIndex = ++framesSentForPresentation_; + } + + // real + if (!presentInterpolatedOnly_) + { + PacingData::FrameInfo& fiReal = entry.frames[PacingData::FrameIdentifier::Real]; + if (realFrame.resource != nullptr) + { + fiReal.doPresent = true; + fiReal.resource = realFrame; + fiReal.presentIndex = ++framesSentForPresentation_; + } + } + + entry.replacementBufferFenceSignal = framesSentForPresentation_; + entry.numFramesToPresent = UINT32(framesSentForPresentation_ - entry.numFramesSentForPresentationBase); + + interpolationOutputs_[interpolationBufferIndex_].availabilityFenceValue = entry.numFramesSentForPresentationBase + fiInterpolated.doPresent; + + presentInfo_.scheduledInterpolations = entry; + LeaveCriticalSection(&presentInfo_.criticalSectionScheduledFrame); + + // Set event to kick off async CPU present thread + SetEvent(presentInfo_.presentEvent); + + // hold the replacement object back until previous frame or interpolated is presented + nextPresentWaitValue_ = entry.numFramesSentForPresentationBase; + + UINT64 frameLatencyObjectWaitValue = (entry.numFramesSentForPresentationBase - 1) * (entry.numFramesSentForPresentationBase > 0); + FFX_ASSERT(SUCCEEDED(presentInfo_.presentFence->SetEventOnCompletion(frameLatencyObjectWaitValue, replacementFrameLatencyWaitableObjectHandle_))); + +} + +// IDXGISwapChain1 +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::Present(UINT SyncInterval, UINT Flags) +{ + if (Flags & DXGI_PRESENT_TEST) + { + return presentInfo_.swapChain->Present(SyncInterval, Flags); + } + + EnterCriticalSection(&criticalSection_); + + const UINT currentBackBufferIndex = GetCurrentBackBufferIndex(); + + // determine what present path to execute + const bool fgCallbackConfigured = frameGenerationCallback_ != nullptr; + const bool fgCommandListConfigured = registeredInterpolationCommandLists_[currentBackBufferIndex] != nullptr; + const bool runInterpolation = interpolationEnabled_ && (fgCallbackConfigured || fgCommandListConfigured); + + if (runInterpolation) + { + WaitForSingleObject(presentInfo_.interpolationEvent, INFINITE); + + presentInfo_.gameQueue->Signal(presentInfo_.gameFence, ++gameFenceValue_); + + presentInterpolated(SyncInterval, Flags); + } + else + { + // if no interpolation, then we copied directly to the swapchain. Render UI, present and be done + presentInfo_.gameQueue->Signal(presentInfo_.gameFence, ++gameFenceValue_); + presentInfo_.presentQueue->Wait(presentInfo_.gameFence, gameFenceValue_); + + if (presentCallback_ != nullptr) + { + presentWithUiComposition(SyncInterval, Flags); + } + else + { + presentPassthrough(SyncInterval, Flags); + } + + // respect game provided latency settings + UINT64 frameLatencyObjectWaitValue = (framesSentForPresentation_ - gameMaximumFrameLatency_) * (framesSentForPresentation_ >= gameMaximumFrameLatency_); + FFX_ASSERT(SUCCEEDED(presentInfo_.presentFence->SetEventOnCompletion(frameLatencyObjectWaitValue, replacementFrameLatencyWaitableObjectHandle_))); + } + + replacementSwapBuffers_[currentBackBufferIndex].availabilityFenceValue = framesSentForPresentation_; + + // Unregister any potential command list + registeredInterpolationCommandLists_[currentBackBufferIndex] = nullptr; + presentCount_++; + interpolationBufferIndex_ = presentCount_ % _countof(interpolationOutputs_); + + //update active backbuffer and block when no buffer is available + replacementSwapBufferIndex_ = presentCount_ % gameBufferCount_; + + LeaveCriticalSection(&criticalSection_); + + waitForFenceValue(presentInfo_.replacementBufferFence, replacementSwapBuffers_[replacementSwapBufferIndex_].availabilityFenceValue); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetBuffer(UINT Buffer, REFIID riid, void** ppSurface) +{ + EnterCriticalSection(&criticalSection_); + + HRESULT hr = E_FAIL; + + if (riid == IID_ID3D12Resource || riid == IID_ID3D12Resource1 || riid == IID_ID3D12Resource2) + { + if (verifyBackbufferDuplicateResources()) + { + ID3D12Resource* pBuffer = replacementSwapBuffers_[Buffer].resource; + + pBuffer->AddRef(); + *ppSurface = pBuffer; + + hr = S_OK; + } + } + + LeaveCriticalSection(&criticalSection_); + + return hr; +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::SetFullscreenState(BOOL Fullscreen, IDXGIOutput* pTarget) +{ + return real()->SetFullscreenState(Fullscreen, pTarget); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetFullscreenState(BOOL* pFullscreen, IDXGIOutput** ppTarget) +{ + return real()->GetFullscreenState(pFullscreen, ppTarget); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetDesc(DXGI_SWAP_CHAIN_DESC* pDesc) +{ + HRESULT hr = real()->GetDesc(pDesc); + + // hide interpolation swapchaindesc to keep FI transparent for ISV + if (SUCCEEDED(hr)) + { + //update values we changed + pDesc->BufferCount = gameBufferCount_; + pDesc->Flags = gameFlags_; + pDesc->SwapEffect = gameSwapEffect_; + } + + return hr; +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) +{ + destroyReplacementResources(); + + EnterCriticalSection(&criticalSection_); + + const UINT fiAdjustedFlags = getInterpolationEnabledSwapChainFlags(SwapChainFlags); + + // update params expected by the application + gameBufferCount_ = BufferCount; + gameFlags_ = SwapChainFlags; + + HRESULT hr = real()->ResizeBuffers(0 /* preserve count */, Width, Height, NewFormat, fiAdjustedFlags); + + LeaveCriticalSection(&criticalSection_); + + return hr; +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::ResizeTarget(const DXGI_MODE_DESC* pNewTargetParameters) +{ + return real()->ResizeTarget(pNewTargetParameters); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetContainingOutput(IDXGIOutput** ppOutput) +{ + HRESULT hr = DXGI_ERROR_INVALID_CALL; + + if (ppOutput) + { + *ppOutput = getMostRelevantOutputFromSwapChain(real()); + hr = S_OK; + } + + return hr; +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetFrameStatistics(DXGI_FRAME_STATISTICS* pStats) +{ + return real()->GetFrameStatistics(pStats); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetLastPresentCount(UINT* pLastPresentCount) +{ + return real()->GetLastPresentCount(pLastPresentCount); +} + +// IDXGISwapChain1 +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetDesc1(DXGI_SWAP_CHAIN_DESC1* pDesc) +{ + HRESULT hr = real()->GetDesc1(pDesc); + + // hide interpolation swapchaindesc to keep FI transparent for ISV + if (SUCCEEDED(hr)) + { + //update values we changed + pDesc->BufferCount = gameBufferCount_; + pDesc->Flags = gameFlags_; + pDesc->SwapEffect = gameSwapEffect_; + } + + return hr; +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetFullscreenDesc(DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc) +{ + return real()->GetFullscreenDesc(pDesc); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetHwnd(HWND* pHwnd) +{ + return real()->GetHwnd(pHwnd); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetCoreWindow(REFIID refiid, void** ppUnk) +{ + return real()->GetCoreWindow(refiid, ppUnk); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::Present1(UINT SyncInterval, UINT PresentFlags, const DXGI_PRESENT_PARAMETERS* pPresentParameters) +{ + return Present(SyncInterval, PresentFlags); +} + +BOOL STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::IsTemporaryMonoSupported(void) +{ + return real()->IsTemporaryMonoSupported(); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetRestrictToOutput(IDXGIOutput** ppRestrictToOutput) +{ + return real()->GetRestrictToOutput(ppRestrictToOutput); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::SetBackgroundColor(const DXGI_RGBA* pColor) +{ + return real()->SetBackgroundColor(pColor); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetBackgroundColor(DXGI_RGBA* pColor) +{ + return real()->GetBackgroundColor(pColor); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::SetRotation(DXGI_MODE_ROTATION Rotation) +{ + return real()->SetRotation(Rotation); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetRotation(DXGI_MODE_ROTATION* pRotation) +{ + return real()->GetRotation(pRotation); +} + +// IDXGISwapChain2 +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::SetSourceSize(UINT Width, UINT Height) +{ + return real()->SetSourceSize(Width, Height); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetSourceSize(UINT* pWidth, UINT* pHeight) +{ + return real()->GetSourceSize(pWidth, pHeight); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::SetMaximumFrameLatency(UINT MaxLatency) +{ + // store value, so correct value is returned if game asks for it + gameMaximumFrameLatency_ = MaxLatency; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetMaximumFrameLatency(UINT* pMaxLatency) +{ + if (pMaxLatency) + { + *pMaxLatency = gameMaximumFrameLatency_; + } + + return pMaxLatency ? S_OK : DXGI_ERROR_INVALID_CALL; +} + +HANDLE STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetFrameLatencyWaitableObject(void) +{ + return replacementFrameLatencyWaitableObjectHandle_; +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::SetMatrixTransform(const DXGI_MATRIX_3X2_F* pMatrix) +{ + return real()->SetMatrixTransform(pMatrix); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetMatrixTransform(DXGI_MATRIX_3X2_F* pMatrix) +{ + return real()->GetMatrixTransform(pMatrix); +} + +// IDXGISwapChain3 +UINT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::GetCurrentBackBufferIndex(void) +{ + EnterCriticalSection(&criticalSection_); + + UINT result = (UINT)replacementSwapBufferIndex_; + + LeaveCriticalSection(&criticalSection_); + + return result; +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::CheckColorSpaceSupport(DXGI_COLOR_SPACE_TYPE ColorSpace, UINT* pColorSpaceSupport) +{ + return real()->CheckColorSpaceSupport(ColorSpace, pColorSpaceSupport); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::SetColorSpace1(DXGI_COLOR_SPACE_TYPE ColorSpace) +{ + switch (ColorSpace) + { + case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709: + backBufferTransferFunction_ = FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB; + break; + case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020: + backBufferTransferFunction_ = FFX_BACKBUFFER_TRANSFER_FUNCTION_PQ; + break; + case DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709: + backBufferTransferFunction_ = FFX_BACKBUFFER_TRANSFER_FUNCTION_SCRGB; + break; + default: + break; + } + + return real()->SetColorSpace1(ColorSpace); +} + +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::ResizeBuffers1( + UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT Format, UINT SwapChainFlags, const UINT* pCreationNodeMask, IUnknown* const* ppPresentQueue) +{ + FFX_ASSERT_MESSAGE(false, "AMD FSR Frame interpolaton proxy swapchain: ResizeBuffers1 currently not supported."); + + return S_OK; +} + +// IDXGISwapChain4 +HRESULT STDMETHODCALLTYPE FrameInterpolationSwapChainDX12::SetHDRMetaData(DXGI_HDR_METADATA_TYPE Type, UINT Size, void* pMetaData) +{ + if (Size > 0 && pMetaData != nullptr) + { + DXGI_HDR_METADATA_HDR10* HDR10MetaData = NULL; + + switch (Type) + { + case DXGI_HDR_METADATA_TYPE_NONE: + break; + case DXGI_HDR_METADATA_TYPE_HDR10: + HDR10MetaData = static_cast(pMetaData); + break; + case DXGI_HDR_METADATA_TYPE_HDR10PLUS: + break; + } + + FFX_ASSERT_MESSAGE(HDR10MetaData != NULL, "FSR3 Frame interpolaton pxory swapchain: could not initialize HDR metadata"); + + if (HDR10MetaData) + { + minLuminance_ = HDR10MetaData->MinMasteringLuminance / 10000.0f; + maxLuminance_ = float(HDR10MetaData->MaxMasteringLuminance); + } + } + + return real()->SetHDRMetaData(Type, Size, pMetaData); +} + +ID3D12GraphicsCommandList* FrameInterpolationSwapChainDX12::getInterpolationCommandList() +{ + EnterCriticalSection(&criticalSection_); + + ID3D12GraphicsCommandList* dx12CommandList = nullptr; + + // store active backbuffer index to the command list, used to verify list usage later + if (interpolationEnabled_) { + ID3D12Resource* currentBackBuffer = nullptr; + const UINT currentBackBufferIndex = GetCurrentBackBufferIndex(); + if (SUCCEEDED(GetBuffer(currentBackBufferIndex, IID_PPV_ARGS(¤tBackBuffer)))) + { + Dx12Commands* registeredCommands = registeredInterpolationCommandLists_[currentBackBufferIndex]; + + // drop if already existing + if (registeredCommands != nullptr) + { + registeredCommands->drop(true); + registeredCommands = nullptr; + } + + registeredCommands = presentInfo_.commandPool.get(presentInfo_.interpolationQueue, L"getInterpolationCommandList()"); + FFX_ASSERT(registeredCommands); + + dx12CommandList = registeredCommands->reset(); + + registeredInterpolationCommandLists_[currentBackBufferIndex] = registeredCommands; + + SafeRelease(currentBackBuffer); + } + } + + LeaveCriticalSection(&criticalSection_); + + return dx12CommandList; +} diff --git a/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12.h b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12.h new file mode 100644 index 00000000..0885ed4a --- /dev/null +++ b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12.h @@ -0,0 +1,263 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include +#include + +#include +#include + +#include "FrameInterpolationSwapchainDX12_Helpers.h" + +#include +#include + +#define FFX_FRAME_INTERPOLATION_SWAP_CHAIN_VERSION 1 +#define FFX_FRAME_INTERPOLATION_SWAP_CHAIN_MAX_BUFFER_COUNT 6 + +typedef struct PacingData +{ + FfxPresentCallbackFunc presentCallback = nullptr; + FfxResource uiSurface; + + bool vsync; + bool tearingSupported; + + UINT64 gameFenceValue; + UINT64 replacementBufferFenceSignal; + UINT64 numFramesSentForPresentationBase; + UINT32 numFramesToPresent; + + typedef enum FrameIdentifier + { + Interpolated_1, + Real, + Count + } FrameIdentifier; + + struct FrameInfo + { + bool doPresent; + FfxResource resource; + UINT64 interpolationCompletedFenceValue; + UINT64 presentIndex; + UINT64 presentQpcTarget; + }; + + FrameInfo frames[FrameIdentifier::Count]; + + void invalidate() + { + memset(this, 0, sizeof(PacingData)); + } +} PacingData; + +typedef struct FrameinterpolationPresentInfo +{ + CRITICAL_SECTION criticalSectionScheduledFrame; + ID3D12Device8* device = nullptr; + IDXGISwapChain4* swapChain = nullptr; + Dx12CommandPool<8> commandPool; + + PacingData scheduledInterpolations; + PacingData scheduledPresents; + FfxResource currentUiSurface; + + ID3D12CommandQueue* interpolationQueue = nullptr; + ID3D12CommandQueue* asyncComputeQueue = nullptr; + ID3D12CommandQueue* gameQueue = nullptr; + ID3D12CommandQueue* presentQueue = nullptr; + + ID3D12Fence* gameFence = nullptr; + ID3D12Fence* interpolationFence = nullptr; + ID3D12Fence* presentFence = nullptr; + ID3D12Fence* replacementBufferFence = nullptr; + ID3D12Fence* compositionFence = nullptr; + + HANDLE presentEvent = 0; + HANDLE interpolationEvent = 0; + HANDLE pacerEvent = 0; + + volatile bool shutdown = false; +} FrameinterpolationPresentInfo; + +typedef struct ReplacementResource +{ + ID3D12Resource* resource = nullptr; + UINT64 availabilityFenceValue = 0; + + void destroy() + { + SafeRelease(resource); + availabilityFenceValue = 0; + } +} ReplacementResource; + +// {BEED74B2-282E-4AA3-BBF7-534560507A45} +static const GUID IID_IFfxFrameInterpolationSwapChain = { 0xbeed74b2, 0x282e, 0x4aa3, {0xbb, 0xf7, 0x53, 0x45, 0x60, 0x50, 0x7a, 0x45} }; +// {548CA0F7-DD5A-4CBC-BE21-7B0415E34907} +static const GUID IID_IFfxFrameInterpolationSwapChainResourceInfo = {0x548ca0f7, 0xdd5a, 0x4cbc, {0xbe, 0x21, 0x7b, 0x4, 0x15, 0xe3, 0x49, 0x7}}; + +typedef struct FfxFrameInterpolationSwapChainResourceInfo +{ + int version; + bool isInterpolated; +} FfxFrameInterpolationSwapChainResourceInfo; + +class DECLSPEC_UUID("BEED74B2-282E-4AA3-BBF7-534560507A45") FrameInterpolationSwapChainDX12 : public IDXGISwapChain4 +{ +protected: + HRESULT shutdown(); + UINT getInterpolationEnabledSwapChainFlags(UINT nonAdjustedFlags); + DXGI_SWAP_CHAIN_DESC1 getInterpolationEnabledSwapChainDescription(const DXGI_SWAP_CHAIN_DESC1* nonAdjustedDesc); + + FrameinterpolationPresentInfo presentInfo_ = {}; + + CRITICAL_SECTION criticalSection_{}; + + UINT gameBufferCount_ = 0; + UINT gameFlags_ = 0; + DXGI_SWAP_EFFECT gameSwapEffect_ = DXGI_SWAP_EFFECT_FLIP_DISCARD; + UINT gameMaximumFrameLatency_ = 1; // default is 1 + ID3D12Resource* realBackBuffer0_ = nullptr; //hold reference to avoid DXGI deadlock on Windows 10 + + HANDLE replacementFrameLatencyWaitableObjectHandle_ = 0; + + UINT64 interpolationFenceValue_ = 0; + UINT64 gameFenceValue_ = 0; + bool frameInterpolationResetCondition_ = false; + + Dx12Commands* registeredInterpolationCommandLists_[FFX_FRAME_INTERPOLATION_SWAP_CHAIN_MAX_BUFFER_COUNT] = {}; + ReplacementResource replacementSwapBuffers_[FFX_FRAME_INTERPOLATION_SWAP_CHAIN_MAX_BUFFER_COUNT] = {}; + ReplacementResource interpolationOutputs_[2] = {}; + int replacementSwapBufferIndex_ = 0; + int interpolationBufferIndex_ = 0; + UINT64 presentCount_ = 0; + + bool tearingSupported_ = false; + bool interpolationEnabled_ = false; + bool presentInterpolatedOnly_ = false; + + UINT64 framesSentForPresentation_ = 0; + UINT64 nextPresentWaitValue_ = 0; + HANDLE interpolationThreadHandle_ = 0; + ULONG refCount_ = 1; + + UINT backBufferTransferFunction_ = 0; + float minLuminance_ = 0.0f; + float maxLuminance_ = 0.0f; + + FfxPresentCallbackFunc presentCallback_ = nullptr; + FfxFrameGenerationDispatchFunc frameGenerationCallback_ = nullptr; + + void presentPassthrough(UINT SyncInterval, UINT Flags); + void presentWithUiComposition(UINT SyncInterval, UINT Flags); + + void dispatchInterpolationCommands(FfxResource* pInterpolatedFrame, FfxResource* pRealFrame); + void presentInterpolated(UINT SyncInterval, UINT Flags); + + bool verifyBackbufferDuplicateResources(); + bool destroyReplacementResources(); + bool killPresenterThread(); + bool spawnPresenterThread(); + void discardOutstandingInterpolationCommandLists(); + + IDXGISwapChain4* real(); + +public: + void setFrameGenerationConfig(FfxFrameGenerationConfig const* config); + bool waitForPresents(); + + FfxResource interpolationOutput(int index = 0); + ID3D12GraphicsCommandList* getInterpolationCommandList(); + + void registerUiResource(FfxResource uiResource); + + FrameInterpolationSwapChainDX12(); + virtual ~FrameInterpolationSwapChainDX12(); + + HRESULT init( + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* swapChainDesc1, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* fullscreenDesc, + ID3D12CommandQueue* queue, + IDXGIFactory2* dxgiFactory); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + + // IDXGIObject + virtual HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID Name, UINT DataSize, const void* pData); + virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(REFGUID Name, const IUnknown * pUnknown); + virtual HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID Name, UINT * pDataSize, void* pData); + virtual HRESULT STDMETHODCALLTYPE GetParent(REFIID riid, void** ppParent); + + // IDXGIDeviceSubObject + virtual HRESULT STDMETHODCALLTYPE GetDevice(REFIID riid, void** ppDevice); + + // IDXGISwapChain1 + virtual HRESULT STDMETHODCALLTYPE Present(UINT SyncInterval, UINT Flags); + virtual HRESULT STDMETHODCALLTYPE GetBuffer(UINT Buffer, REFIID riid, void** ppSurface); + virtual HRESULT STDMETHODCALLTYPE SetFullscreenState(BOOL Fullscreen, IDXGIOutput * pTarget); + virtual HRESULT STDMETHODCALLTYPE GetFullscreenState(BOOL * pFullscreen, IDXGIOutput * *ppTarget); + virtual HRESULT STDMETHODCALLTYPE GetDesc(DXGI_SWAP_CHAIN_DESC * pDesc); + virtual HRESULT STDMETHODCALLTYPE ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags); + virtual HRESULT STDMETHODCALLTYPE ResizeTarget(const DXGI_MODE_DESC * pNewTargetParameters); + virtual HRESULT STDMETHODCALLTYPE GetContainingOutput(IDXGIOutput * *ppOutput); + virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics(DXGI_FRAME_STATISTICS * pStats); + virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount(UINT * pLastPresentCount); + + // IDXGISwapChain1 + virtual HRESULT STDMETHODCALLTYPE GetDesc1(DXGI_SWAP_CHAIN_DESC1 * pDesc); + virtual HRESULT STDMETHODCALLTYPE GetFullscreenDesc(DXGI_SWAP_CHAIN_FULLSCREEN_DESC * pDesc); + virtual HRESULT STDMETHODCALLTYPE GetHwnd(HWND * pHwnd); + virtual HRESULT STDMETHODCALLTYPE GetCoreWindow(REFIID refiid, void** ppUnk); + virtual HRESULT STDMETHODCALLTYPE Present1(UINT SyncInterval, UINT PresentFlags, const DXGI_PRESENT_PARAMETERS * pPresentParameters); + virtual BOOL STDMETHODCALLTYPE IsTemporaryMonoSupported(void); + virtual HRESULT STDMETHODCALLTYPE GetRestrictToOutput(IDXGIOutput * *ppRestrictToOutput); + virtual HRESULT STDMETHODCALLTYPE SetBackgroundColor(const DXGI_RGBA * pColor); + virtual HRESULT STDMETHODCALLTYPE GetBackgroundColor(DXGI_RGBA * pColor); + virtual HRESULT STDMETHODCALLTYPE SetRotation(DXGI_MODE_ROTATION Rotation); + virtual HRESULT STDMETHODCALLTYPE GetRotation(DXGI_MODE_ROTATION * pRotation); + + // IDXGISwapChain2 + virtual HRESULT STDMETHODCALLTYPE SetSourceSize(UINT Width, UINT Height); + virtual HRESULT STDMETHODCALLTYPE GetSourceSize(UINT * pWidth, UINT * pHeight); + virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(UINT MaxLatency); + virtual HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(UINT * pMaxLatency); + virtual HANDLE STDMETHODCALLTYPE GetFrameLatencyWaitableObject(void); + virtual HRESULT STDMETHODCALLTYPE SetMatrixTransform(const DXGI_MATRIX_3X2_F * pMatrix); + virtual HRESULT STDMETHODCALLTYPE GetMatrixTransform(DXGI_MATRIX_3X2_F * pMatrix); + + // IDXGISwapChain3 + virtual UINT STDMETHODCALLTYPE GetCurrentBackBufferIndex(void); + virtual HRESULT STDMETHODCALLTYPE CheckColorSpaceSupport(DXGI_COLOR_SPACE_TYPE ColorSpace, UINT * pColorSpaceSupport); + virtual HRESULT STDMETHODCALLTYPE SetColorSpace1(DXGI_COLOR_SPACE_TYPE ColorSpace); + virtual HRESULT STDMETHODCALLTYPE ResizeBuffers1(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT Format, UINT SwapChainFlags, const UINT * pCreationNodeMask, IUnknown* const* ppPresentQueue); + + // IDXGISwapChain4 + virtual HRESULT STDMETHODCALLTYPE SetHDRMetaData(DXGI_HDR_METADATA_TYPE Type, UINT Size, void* pMetaData); +}; diff --git a/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_Helpers.cpp b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_Helpers.cpp new file mode 100644 index 00000000..915bf530 --- /dev/null +++ b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_Helpers.cpp @@ -0,0 +1,199 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include + + +#include "FrameInterpolationSwapchainDX12_Helpers.h" + +#include +#pragma comment(lib, "Dwmapi.lib") + +IDXGIFactory* getDXGIFactoryFromSwapChain(IDXGISwapChain* swapChain) +{ + IDXGIFactory* factory = nullptr; + if (FAILED(swapChain->GetParent(IID_PPV_ARGS(&factory)))) { + + } + + return factory; +} + +void waitForPerformanceCount(const int64_t targetCount) +{ + int64_t currentCount = 0; + do + { + QueryPerformanceCounter(reinterpret_cast(¤tCount)); + } while (currentCount < targetCount); +} + +bool waitForFenceValue(ID3D12Fence* fence, UINT64 value, DWORD dwMilliseconds) +{ + bool status = false; + + if (fence) + { + if (dwMilliseconds == INFINITE) + { + while (fence->GetCompletedValue() < value); + status = true; + } + else + { + status = fence->GetCompletedValue() >= value; + + if (!status) + { + HANDLE handle = CreateEvent(0, false, false, 0); + + if (isValidHandle(handle)) + { + //Wait until command queue is done. + if (!status) + { + if (SUCCEEDED(fence->SetEventOnCompletion(value, handle))) + { + status = (WaitForSingleObject(handle, dwMilliseconds) == WAIT_OBJECT_0); + } + } + + CloseHandle(handle); + } + } + } + } + + return status; +} + +bool isTearingSupported(IDXGIFactory* dxgiFactory) +{ + BOOL bTearingSupported = FALSE; + + IDXGIFactory5* pFactory5 = nullptr; + if (dxgiFactory && SUCCEEDED(dxgiFactory->QueryInterface(IID_PPV_ARGS(&pFactory5)))) + { + + if (SUCCEEDED(pFactory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &bTearingSupported, sizeof(bTearingSupported)))) { + + } + + SafeRelease(pFactory5); + } + + return bTearingSupported == TRUE; +} + +inline bool isValidHandle(HANDLE handle) +{ + return handle != NULL; +} + +bool isExclusiveFullscreen(IDXGISwapChain* swapChain) +{ + bool bIsExclusiveFullscreen = false; + + BOOL isFullscreen = FALSE; + if (SUCCEEDED(swapChain->GetFullscreenState(&isFullscreen, nullptr))) + { + bIsExclusiveFullscreen = (isFullscreen == TRUE); + } + + return bIsExclusiveFullscreen; +} + +IDXGIOutput6* getMostRelevantOutputFromSwapChain(IDXGISwapChain* swapChain) +{ + IDXGIOutput6* pOutput6 = nullptr; + + IDXGIFactory* pFactory = getDXGIFactoryFromSwapChain(swapChain); + if (pFactory) + { + DXGI_SWAP_CHAIN_DESC desc{}; + if (SUCCEEDED(swapChain->GetDesc(&desc))) + { + UINT largestArea = 0; + RECT windowRect{}; + if (GetWindowRect(desc.OutputWindow, &windowRect) == TRUE) + { + UINT adapterIdx = 0; + IDXGIAdapter* pAdapter = nullptr; + while (pFactory->EnumAdapters(adapterIdx++, &pAdapter) != DXGI_ERROR_NOT_FOUND) + { + UINT outputIdx = 0; + IDXGIOutput* pOutput = nullptr; + while (pAdapter->EnumOutputs(outputIdx++, &pOutput) != DXGI_ERROR_NOT_FOUND) + { + DXGI_OUTPUT_DESC outputDesc{}; + if (SUCCEEDED(pOutput->GetDesc(&outputDesc))) + { + RECT intersection{}; + if (IntersectRect(&intersection, &windowRect, &outputDesc.DesktopCoordinates) == TRUE) + { + UINT area = (intersection.right - intersection.left) * (intersection.bottom - intersection.top); + + if (area > largestArea) + { + SafeRelease(pOutput6); + if (SUCCEEDED(pOutput->QueryInterface(IID_PPV_ARGS(&pOutput6)))) + { + largestArea = area; + } + } + } + } + + SafeRelease(pOutput); + } + + SafeRelease(pAdapter); + } + } + } + SafeRelease(pFactory); + } + + return pOutput6; +} + +bool getMonitorLuminanceRange(IDXGISwapChain* swapChain, float *outMinLuminance, float *outMaxLuminance) +{ + bool bResult = false; + + IDXGIOutput6* dxgiOutput = getMostRelevantOutputFromSwapChain(swapChain); + + if (dxgiOutput) + { + DXGI_OUTPUT_DESC1 outputDesc1; + if (SUCCEEDED(dxgiOutput->GetDesc1(&outputDesc1))) + { + *outMinLuminance = outputDesc1.MinLuminance; + *outMaxLuminance = outputDesc1.MaxLuminance; + bResult = true; + } + SafeRelease(dxgiOutput); + } + + return bResult; +} diff --git a/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_Helpers.h b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_Helpers.h new file mode 100644 index 00000000..1ab51e66 --- /dev/null +++ b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_Helpers.h @@ -0,0 +1,283 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include +#include + +#include +#include + +#include + +IDXGIFactory* getDXGIFactoryFromSwapChain(IDXGISwapChain* swapChain); +bool isExclusiveFullscreen(IDXGISwapChain* swapChain); +void waitForPerformanceCount(const int64_t targetCount); +bool waitForFenceValue(ID3D12Fence* fence, UINT64 value, DWORD dwMilliseconds = INFINITE); +bool isTearingSupported(IDXGIFactory* dxgiFactory); +bool getMonitorLuminanceRange(IDXGISwapChain* swapChain, float* outMinLuminance, float* outMaxLuminance); +inline bool isValidHandle(HANDLE handle); +IDXGIOutput6* getMostRelevantOutputFromSwapChain(IDXGISwapChain* swapChain); + + // Safe release for interfaces +template +inline UINT SafeRelease(Interface*& pInterfaceToRelease) +{ + UINT refCount = -1; + if (pInterfaceToRelease != nullptr) + { + refCount = pInterfaceToRelease->Release(); + + pInterfaceToRelease = nullptr; + } + + return refCount; +} + +inline void SafeCloseHandle(HANDLE& handle) +{ + if (handle) + { + CloseHandle(handle); + handle = 0; + } +} + +class Dx12Commands +{ + ID3D12CommandQueue* queue_ = nullptr; + ID3D12CommandAllocator* allocator_ = nullptr; + ID3D12GraphicsCommandList* list_ = nullptr; + ID3D12Fence* fence_ = nullptr; + UINT64 availableFenceValue_ = 0; + +public: + void release() + { + SafeRelease(allocator_); + SafeRelease(list_); + SafeRelease(fence_); + } + +public: + ~Dx12Commands() + { + release(); + } + + bool initiated() + { + return allocator_ != nullptr; + } + + bool verify(ID3D12CommandQueue* pQueue) + { + HRESULT hr = initiated() ? S_OK : E_FAIL; + + if (FAILED(hr)) + { + ID3D12Device* device = nullptr; + if (SUCCEEDED(pQueue->GetDevice(IID_PPV_ARGS(&device)))) + { + D3D12_COMMAND_QUEUE_DESC queueDesc = pQueue->GetDesc(); + if (SUCCEEDED(device->CreateCommandAllocator(queueDesc.Type, IID_PPV_ARGS(&allocator_)))) + { + allocator_->SetName(L"Dx12CommandPool::Allocator"); + if (SUCCEEDED(device->CreateCommandList(queueDesc.NodeMask, queueDesc.Type, allocator_, nullptr, IID_PPV_ARGS(&list_)))) + { + allocator_->SetName(L"Dx12CommandPool::Commandlist"); + list_->Close(); + + if (SUCCEEDED(device->CreateFence(availableFenceValue_, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence_)))) + { + hr = S_OK; + } + } + } + + SafeRelease(device); + } + } + + if (FAILED(hr)) + { + release(); + } + + return SUCCEEDED(hr); + } + + void occupy(ID3D12CommandQueue* pQueue, const wchar_t* name) + { + availableFenceValue_++; + queue_ = pQueue; + allocator_->SetName(name); + list_->SetName(name); + fence_->SetName(name); + } + + ID3D12GraphicsCommandList* reset() + { + if (SUCCEEDED(allocator_->Reset())) + { + if (SUCCEEDED(list_->Reset(allocator_, nullptr))) + { + } + } + + return list_; + } + + ID3D12GraphicsCommandList* list() + { + return list_; + } + + void execute(bool listIsOpen = false) + { + if (listIsOpen) + { + list_->Close(); + } + + ID3D12CommandList* pListsToExec[] = {list_}; + queue_->ExecuteCommandLists(_countof(pListsToExec), pListsToExec); + queue_->Signal(fence_, availableFenceValue_); + } + + void drop(bool listIsOpen = false) + { + if (listIsOpen) + { + list()->Close(); + } + queue_->Signal(fence_, availableFenceValue_); + } + + bool available() + { + return fence_->GetCompletedValue() >= availableFenceValue_; + } +}; + +template +class Dx12CommandPool +{ +public: + +private: + CRITICAL_SECTION criticalSection_{}; + Dx12Commands buffer[4 /* D3D12_COMMAND_LIST_TYPE_COPY == 3 */][Capacity] = {}; + +public: + + Dx12CommandPool() + { + InitializeCriticalSection(&criticalSection_); + } + + ~Dx12CommandPool() + { + EnterCriticalSection(&criticalSection_); + + for (size_t type = 0; type < 4; type++) + { + for (size_t idx = 0; idx < Capacity; idx++) + { + auto& cmds = buffer[type][idx]; + while (cmds.initiated() && !cmds.available()) + { + // wait for list to be idling + } + cmds.release(); + } + } + + LeaveCriticalSection(&criticalSection_); + + DeleteCriticalSection(&criticalSection_); + } + + Dx12Commands* get(ID3D12CommandQueue* pQueue, const wchar_t* name) + { + D3D12_COMMAND_QUEUE_DESC queueDesc = pQueue->GetDesc(); + + EnterCriticalSection(&criticalSection_); + + Dx12Commands* pCommands = nullptr; + for (size_t idx = 0; idx < Capacity && (pCommands == nullptr); idx++) + { + auto& cmds = buffer[queueDesc.Type][idx]; + if (cmds.verify(pQueue) && cmds.available()) + { + pCommands = &cmds; + } + } + + FFX_ASSERT(pCommands); + + pCommands->occupy(pQueue, name); + LeaveCriticalSection(&criticalSection_); + + return pCommands; + } +}; + +template +struct SimpleMovingAverage +{ + Type history[Size] = {}; + unsigned int idx = 0; + unsigned int updateCount = 0; + + Type getAverage() + { + Type average = 0.f; + unsigned int iterations = (updateCount >= Size) ? Size : updateCount; + + if (iterations > 0) + { + for (size_t i = 0; i < iterations; i++) + { + average += history[i]; + } + average /= iterations; + } + + return average; + } + + void reset() + { + updateCount = 0; + idx = 0; + } + + void update(Type newValue) + { + history[idx] = newValue; + idx = (idx + 1) % Size; + updateCount++; + } +}; diff --git a/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_UiComposition.cpp b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_UiComposition.cpp new file mode 100644 index 00000000..54fa0397 --- /dev/null +++ b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_UiComposition.cpp @@ -0,0 +1,357 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "d3d12.h" +#include "FrameInterpolationSwapchainDX12_Helpers.h" +#include "FrameInterpolationSwapchainDX12_UiComposition.h" + +#include "FrameInterpolationSwapchainUiCompositionVS.h" +#include "FrameInterpolationSwapchainUiCompositionPS.h" + +typedef HRESULT(__stdcall* D3D12SerializeVersionedRootSignatureType)(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignature, + ID3DBlob** ppBlob, + ID3DBlob** ppErrorBlob); + +ID3D12RootSignature* s_uiCompositionRootSignature; +ID3D12PipelineState* s_uiCompositionPipeline; +uint32_t s_uiCompositionDescRingBufferSize; +uint32_t s_uiCompositionDescRingBufferBase; +ID3D12DescriptorHeap* s_uiCompositionDescRingBuffer; +uint32_t s_uiCompositionNextRtvDescriptor; +ID3D12DescriptorHeap* s_uiCompositionDescHeapRtvCpu; + +// create the pipeline state to use for UI composition +// pretty similar to FfxCreatePipelineFunc +FfxErrorCodes CreateUiCompositionPipeline(ID3D12Device* dx12Device, DXGI_FORMAT fmt) +{ + D3D12_DESCRIPTOR_RANGE1 range; + range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + range.NumDescriptors = 2; + range.BaseShaderRegister = 0; + range.RegisterSpace = 0; + range.Flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE; + range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + D3D12_ROOT_PARAMETER1 rootParameters; + rootParameters.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParameters.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + rootParameters.DescriptorTable.NumDescriptorRanges = 1; + rootParameters.DescriptorTable.pDescriptorRanges = ⦥ + + D3D12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc; + rootSignatureDesc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; + rootSignatureDesc.Desc_1_1.NumParameters = 1; + rootSignatureDesc.Desc_1_1.pParameters = &rootParameters; + rootSignatureDesc.Desc_1_1.NumStaticSamplers = 0; + rootSignatureDesc.Desc_1_1.pStaticSamplers = nullptr; + rootSignatureDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + + ID3D12RootSignature* dx12RootSignature; + ID3DBlob* signature = nullptr; + ID3DBlob* error = nullptr; + HMODULE d3d12ModuleHandle = GetModuleHandleW(L"D3D12.dll"); + if (NULL != d3d12ModuleHandle) + { + D3D12SerializeVersionedRootSignatureType d3d12SerializeVersionedRootSignatureFunc = + (D3D12SerializeVersionedRootSignatureType)GetProcAddress(d3d12ModuleHandle, "D3D12SerializeVersionedRootSignature"); + + if (nullptr != d3d12SerializeVersionedRootSignatureFunc) + { + HRESULT result = d3d12SerializeVersionedRootSignatureFunc(&rootSignatureDesc, &signature, &error); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + + result = dx12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&dx12RootSignature)); + SafeRelease(signature); + SafeRelease(error); + + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + return FFX_ERROR_BACKEND_API_ERROR; + } + + // create the PSO + D3D12_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D12_FILL_MODE_SOLID; + rasterDesc.CullMode = D3D12_CULL_MODE_BACK; + rasterDesc.FrontCounterClockwise = FALSE; + rasterDesc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + rasterDesc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + rasterDesc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + rasterDesc.ForcedSampleCount = 0; + rasterDesc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + + D3D12_BLEND_DESC blendDesc; + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = FALSE; + const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = { + FALSE, + FALSE, + D3D12_BLEND_ONE, + D3D12_BLEND_ZERO, + D3D12_BLEND_OP_ADD, + D3D12_BLEND_ONE, + D3D12_BLEND_ZERO, + D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL, + }; + for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) + blendDesc.RenderTarget[i] = defaultRenderTargetBlendDesc; + + D3D12_DEPTH_STENCIL_DESC depthStencilDesc; + depthStencilDesc.DepthEnable = TRUE; + depthStencilDesc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D12_COMPARISON_FUNC_LESS; + depthStencilDesc.StencilEnable = FALSE; + depthStencilDesc.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK; + depthStencilDesc.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK; + const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp = {D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS}; + depthStencilDesc.FrontFace = defaultStencilOp; + depthStencilDesc.BackFace = defaultStencilOp; + + D3D12_GRAPHICS_PIPELINE_STATE_DESC dx12PipelineStateDescription = {}; + dx12PipelineStateDescription.RasterizerState = rasterDesc; + dx12PipelineStateDescription.BlendState = blendDesc; + dx12PipelineStateDescription.DepthStencilState = depthStencilDesc; + dx12PipelineStateDescription.DepthStencilState.DepthEnable = FALSE; + dx12PipelineStateDescription.SampleMask = UINT_MAX; + dx12PipelineStateDescription.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + dx12PipelineStateDescription.SampleDesc = {1, 0}; + dx12PipelineStateDescription.NumRenderTargets = 1; + dx12PipelineStateDescription.RTVFormats[0] = fmt; + + dx12PipelineStateDescription.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + dx12PipelineStateDescription.pRootSignature = dx12RootSignature; + dx12PipelineStateDescription.VS.pShaderBytecode = g_mainVS; + dx12PipelineStateDescription.VS.BytecodeLength = sizeof(g_mainVS); + dx12PipelineStateDescription.PS.pShaderBytecode = g_mainPS; + dx12PipelineStateDescription.PS.BytecodeLength = sizeof(g_mainPS); + s_uiCompositionRootSignature = dx12RootSignature; + if (FAILED(dx12Device->CreateGraphicsPipelineState(&dx12PipelineStateDescription, + IID_PPV_ARGS(reinterpret_cast(&s_uiCompositionPipeline))))) + return FFX_ERROR_BACKEND_API_ERROR; + return FFX_OK; +} + +FfxErrorCodes verifyUiBlitGpuResources(ID3D12Device* dx12Device, DXGI_FORMAT fmt) +{ + FFX_ASSERT(nullptr != dx12Device); + + if (nullptr == s_uiCompositionPipeline) + { + FfxErrorCodes res = CreateUiCompositionPipeline(dx12Device, fmt); + if (res != S_OK) + return res; + } + + if (nullptr == s_uiCompositionDescRingBuffer) + { + D3D12_DESCRIPTOR_HEAP_DESC descHeap = {}; + descHeap.NumDescriptors = 8; // 4 frames, 2 SRV each should be enough + descHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + descHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + descHeap.NodeMask = 0; + s_uiCompositionDescRingBufferSize = descHeap.NumDescriptors; + s_uiCompositionDescRingBufferBase = 0; + if(FAILED(dx12Device->CreateDescriptorHeap(&descHeap, IID_PPV_ARGS(&s_uiCompositionDescRingBuffer)))) + return FFX_ERROR_BACKEND_API_ERROR; + } + + if (nullptr == s_uiCompositionDescHeapRtvCpu) + { + D3D12_DESCRIPTOR_HEAP_DESC descHeap = {}; + descHeap.NumDescriptors = 4; + descHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + descHeap.NodeMask = 0; + descHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + if(FAILED(dx12Device->CreateDescriptorHeap(&descHeap, IID_PPV_ARGS(&s_uiCompositionDescHeapRtvCpu)))) + return FFX_ERROR_BACKEND_API_ERROR; + } + + return FFX_OK; +} + +void releaseUiBlitGpuResources() +{ + SafeRelease(s_uiCompositionRootSignature); + SafeRelease(s_uiCompositionPipeline); + + SafeRelease(s_uiCompositionDescRingBuffer); + s_uiCompositionDescRingBufferSize = 0; + s_uiCompositionDescRingBufferBase = 0; + + SafeRelease(s_uiCompositionDescHeapRtvCpu); + s_uiCompositionNextRtvDescriptor = 0; +} + +FFX_API FfxErrorCode ffxFrameInterpolationUiComposition(const FfxPresentCallbackDescription* params) +{ + ID3D12Device* dx12Device = reinterpret_cast(params->device); + ID3D12Resource* pRtResource = (ID3D12Resource*)(params->outputSwapChainBuffer.resource); + + FFX_ASSERT(nullptr != dx12Device); + FFX_ASSERT(nullptr != pRtResource); + + // blit backbuffer and composit UI using a VS/PS pass + D3D12_RESOURCE_DESC desc = pRtResource->GetDesc(); + + FfxErrorCode res = verifyUiBlitGpuResources(dx12Device, desc.Format); + if (res != FFX_OK) + return res; + + ID3D12CommandList* pCommandList = reinterpret_cast(params->commandList); + ID3D12GraphicsCommandList* pCmdList = (ID3D12GraphicsCommandList*)pCommandList; + ID3D12PipelineState* dx12PipelineStateObject = s_uiCompositionPipeline; + ID3D12Resource* pResBackbuffer = (ID3D12Resource*)(params->currentBackBuffer.resource); + ID3D12Resource* pResUI = (ID3D12Resource*)(params->currentUI.resource); + + FFX_ASSERT(nullptr != pCommandList); + FFX_ASSERT(nullptr != pCmdList); + FFX_ASSERT(nullptr != dx12PipelineStateObject); + FFX_ASSERT(nullptr != pResBackbuffer); + + if (nullptr == pResUI) + { + // just do a resource copy to the real swapchain + D3D12_RESOURCE_BARRIER barriers[2] = {}; + barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barriers[0].Transition.pResource = pResBackbuffer; + barriers[0].Transition.StateBefore = ffxGetDX12StateFromResourceState(params->currentBackBuffer.state); + barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; + + barriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barriers[1].Transition.pResource = pRtResource; + barriers[1].Transition.StateBefore = ffxGetDX12StateFromResourceState(params->outputSwapChainBuffer.state); + barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; + pCmdList->ResourceBarrier(_countof(barriers), barriers); + + pCmdList->CopyResource(pRtResource, pResBackbuffer); + + for (int i = 0; i < _countof(barriers); ++i) + { + D3D12_RESOURCE_STATES tmpStateBefore = barriers[i].Transition.StateBefore; + barriers[i].Transition.StateBefore = barriers[i].Transition.StateAfter; + barriers[i].Transition.StateAfter = tmpStateBefore; + } + + pCmdList->ResourceBarrier(_countof(barriers), barriers); + } + else + { + D3D12_RESOURCE_BARRIER barriers[3] = {}; + barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barriers[0].Transition.pResource = pResBackbuffer; + barriers[0].Transition.StateBefore = ffxGetDX12StateFromResourceState(params->currentBackBuffer.state); + barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + barriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barriers[1].Transition.pResource = pResUI; + barriers[1].Transition.StateBefore = ffxGetDX12StateFromResourceState(params->currentUI.state); + barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + barriers[2].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barriers[2].Transition.pResource = pRtResource; + barriers[2].Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barriers[2].Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + pCmdList->ResourceBarrier(_countof(barriers), barriers); + + // set root signature + pCmdList->SetGraphicsRootSignature(s_uiCompositionRootSignature); + + // set descriptor heap + ID3D12DescriptorHeap* dx12DescriptorHeap = reinterpret_cast(s_uiCompositionDescRingBuffer); + pCmdList->SetDescriptorHeaps(1, &dx12DescriptorHeap); + + D3D12_RENDER_TARGET_VIEW_DESC colorDesc = {}; + colorDesc.Format = desc.Format; + colorDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + colorDesc.Texture2D.MipSlice = 0; + colorDesc.Texture2D.PlaneSlice = 0; + + // set up the descriptor table + D3D12_GPU_DESCRIPTOR_HANDLE gpuView = dx12DescriptorHeap->GetGPUDescriptorHandleForHeapStart(); + gpuView.ptr += s_uiCompositionDescRingBufferBase * dx12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + D3D12_CPU_DESCRIPTOR_HANDLE cpuView = dx12DescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + cpuView.ptr += s_uiCompositionDescRingBufferBase * dx12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + D3D12_RESOURCE_DESC bbDesc = pResBackbuffer->GetDesc(); + + D3D12_SHADER_RESOURCE_VIEW_DESC dx12SrvDescription = {}; + dx12SrvDescription.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + dx12SrvDescription.Format = bbDesc.Format; + dx12SrvDescription.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + dx12SrvDescription.Texture2D.MipLevels = pResBackbuffer->GetDesc().MipLevels; + dx12Device->CreateShaderResourceView(pResBackbuffer, &dx12SrvDescription, cpuView); + + cpuView.ptr += dx12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + const D3D12_RESOURCE_DESC uiDesc = pResUI->GetDesc(); + dx12SrvDescription.Format = uiDesc.Format; + dx12SrvDescription.Texture2D.MipLevels = uiDesc.MipLevels; + dx12Device->CreateShaderResourceView(pResUI, &dx12SrvDescription, cpuView); + + s_uiCompositionDescRingBufferBase = (s_uiCompositionDescRingBufferBase + 2) & 7; + pCmdList->SetGraphicsRootDescriptorTable(0, gpuView); + + D3D12_CPU_DESCRIPTOR_HANDLE backbufferRTV = s_uiCompositionDescHeapRtvCpu->GetCPUDescriptorHandleForHeapStart(); + backbufferRTV.ptr += s_uiCompositionNextRtvDescriptor * dx12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + s_uiCompositionNextRtvDescriptor = (s_uiCompositionNextRtvDescriptor + 1) & 3; + dx12Device->CreateRenderTargetView(pRtResource, &colorDesc, backbufferRTV); + + D3D12_RESOURCE_DESC backBufferDesc = pRtResource->GetDesc(); + D3D12_VIEWPORT vpd = {0.0f, 0.0f, static_cast(backBufferDesc.Width), static_cast(backBufferDesc.Height), 0.0f, 1.0f}; + D3D12_RECT srd = {0, 0, (LONG)backBufferDesc.Width, (LONG)backBufferDesc.Height}; + + pCmdList->OMSetRenderTargets(1, &backbufferRTV, true, NULL); + pCmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + pCmdList->SetPipelineState(dx12PipelineStateObject); + pCmdList->RSSetViewports(1, &vpd); + pCmdList->RSSetScissorRects(1, &srd); + pCmdList->DrawInstanced(3, 1, 0, 0); + + for (int i = 0; i < _countof(barriers); ++i) + { + D3D12_RESOURCE_STATES tmpStateBefore = barriers[i].Transition.StateBefore; + barriers[i].Transition.StateBefore = barriers[i].Transition.StateAfter; + barriers[i].Transition.StateAfter = tmpStateBefore; + } + + pCmdList->ResourceBarrier(_countof(barriers), barriers); + } + + return FFX_OK; +} diff --git a/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_UiComposition.h b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_UiComposition.h new file mode 100644 index 00000000..d75c6ca3 --- /dev/null +++ b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12_UiComposition.h @@ -0,0 +1,30 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +void releaseUiBlitGpuResources(); + +D3D12_RESOURCE_STATES ffxGetDX12StateFromResourceState(FfxResourceStates state); + +FFX_API FfxErrorCode ffxFrameInterpolationUiComposition(const FfxPresentCallbackDescription* params); diff --git a/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiComposition.hlsl b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiComposition.hlsl new file mode 100644 index 00000000..f84842fc --- /dev/null +++ b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiComposition.hlsl @@ -0,0 +1,37 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +Texture2D r_currBB : register(t0); +Texture2D r_uiTexture : register(t1); + +float4 mainVS(uint vertexId : SV_VertexID) : SV_POSITION +{ + return float4((int) (vertexId & 1) * 4 - 1, (int) (vertexId & 2) * (-2) + 1, 0.5, 1); +} + +float4 mainPS(float4 vPosition : SV_POSITION) : SV_Target +{ + float3 color = r_currBB[vPosition.xy].rgb; + float4 guiColor = r_uiTexture[vPosition.xy]; + + return float4(lerp(color, guiColor.rgb, guiColor.a), 1); +} diff --git a/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiCompositionPS.h b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiCompositionPS.h new file mode 100644 index 00000000..b10306e8 --- /dev/null +++ b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiCompositionPS.h @@ -0,0 +1,474 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 0 +; +; Input signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_Position 0 xyzw 0 POS float xy +; +; +; Output signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_Target 0 xyzw 0 TARGET float xyzw +; +; shader hash: 3e4ab44bf2df6e4dc30a8dc1fdb1bf50 +; +; Pipeline Runtime Information: +; +; Pixel Shader +; DepthOutput=0 +; SampleFrequency=0 +; +; +; Input signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_Position 0 noperspective +; +; Output signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_Target 0 +; +; Buffer Definitions: +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; r_currBB texture f32 2d T0 t0 1 +; r_uiTexture texture f32 2d T1 t1 1 +; +; +; ViewId state: +; +; Number of inputs: 4, outputs: 4 +; Outputs dependent on ViewId: { } +; Inputs contributing to computation of Outputs: +; output 0 depends on inputs: { 0, 1 } +; output 1 depends on inputs: { 0, 1 } +; output 2 depends on inputs: { 0, 1 } +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +%dx.types.Handle = type { i8* } +%dx.types.ResRet.f32 = type { float, float, float, float, i32 } +%"class.Texture2D >" = type { <4 x float>, %"class.Texture2D >::mips_type" } +%"class.Texture2D >::mips_type" = type { i32 } + +define void @mainPS() { + %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 1, i32 1, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %3 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %5 = fptoui float %3 to i32 + %6 = fptoui float %4 to i32 + %7 = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %2, i32 0, i32 %5, i32 %6, i32 undef, i32 undef, i32 undef, i32 undef) ; TextureLoad(srv,mipLevelOrSampleCount,coord0,coord1,coord2,offset0,offset1,offset2) + %8 = extractvalue %dx.types.ResRet.f32 %7, 0 + %9 = extractvalue %dx.types.ResRet.f32 %7, 1 + %10 = extractvalue %dx.types.ResRet.f32 %7, 2 + %11 = call %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32 66, %dx.types.Handle %1, i32 0, i32 %5, i32 %6, i32 undef, i32 undef, i32 undef, i32 undef) ; TextureLoad(srv,mipLevelOrSampleCount,coord0,coord1,coord2,offset0,offset1,offset2) + %12 = extractvalue %dx.types.ResRet.f32 %11, 0 + %13 = extractvalue %dx.types.ResRet.f32 %11, 1 + %14 = extractvalue %dx.types.ResRet.f32 %11, 2 + %15 = extractvalue %dx.types.ResRet.f32 %11, 3 + %16 = fsub fast float %12, %8 + %17 = fsub fast float %13, %9 + %18 = fsub fast float %14, %10 + %19 = fmul fast float %16, %15 + %20 = fmul fast float %17, %15 + %21 = fmul fast float %18, %15 + %22 = fadd fast float %19, %8 + %23 = fadd fast float %20, %9 + %24 = fadd fast float %21, %10 + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %22) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %23) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %24) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float 1.000000e+00) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + ret void +} + +; Function Attrs: nounwind readnone +declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0 + +; Function Attrs: nounwind +declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1 + +; Function Attrs: nounwind readonly +declare %dx.types.ResRet.f32 @dx.op.textureLoad.f32(i32, %dx.types.Handle, i32, i32, i32, i32, i32, i32, i32) #2 + +; Function Attrs: nounwind readonly +declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2 + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } +attributes #2 = { nounwind readonly } + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!2} +!dx.shaderModel = !{!3} +!dx.resources = !{!4} +!dx.viewIdState = !{!9} +!dx.entryPoints = !{!10} + +!0 = !{!"dxcoob 1.7.2212.12 (8c9d92be7)"} +!1 = !{i32 1, i32 0} +!2 = !{i32 1, i32 7} +!3 = !{!"ps", i32 6, i32 0} +!4 = !{!5, null, null, null} +!5 = !{!6, !8} +!6 = !{i32 0, %"class.Texture2D >"* undef, !"", i32 0, i32 0, i32 1, i32 2, i32 0, !7} +!7 = !{i32 0, i32 9} +!8 = !{i32 1, %"class.Texture2D >"* undef, !"", i32 0, i32 1, i32 1, i32 2, i32 0, !7} +!9 = !{[6 x i32] [i32 4, i32 4, i32 7, i32 7, i32 0, i32 0]} +!10 = !{void ()* @mainPS, !"mainPS", !11, !4, null} +!11 = !{!12, !16, null} +!12 = !{!13} +!13 = !{i32 0, !"SV_Position", i8 9, i8 3, !14, i8 4, i32 1, i8 4, i32 0, i8 0, !15} +!14 = !{i32 0} +!15 = !{i32 3, i32 3} +!16 = !{!17} +!17 = !{i32 0, !"SV_Target", i8 9, i8 16, !14, i8 0, i32 1, i8 4, i32 0, i8 0, !18} +!18 = !{i32 3, i32 15} + +#endif + +const unsigned char g_mainPS[] = { + 0x44, 0x58, 0x42, 0x43, 0xe1, 0x9c, 0x07, 0xd7, 0x72, 0x1b, 0x61, 0x5e, + 0x4c, 0x50, 0x36, 0x4e, 0x95, 0x67, 0x06, 0x7c, 0x01, 0x00, 0x00, 0x00, + 0x78, 0x0e, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, + 0x7c, 0x01, 0x00, 0x00, 0xb4, 0x07, 0x00, 0x00, 0xd0, 0x07, 0x00, 0x00, + 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0xb0, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x03, 0x03, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x10, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, + 0x30, 0x06, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, + 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x18, 0x06, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, + 0x83, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, + 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, + 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, + 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, + 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, + 0xe4, 0x48, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, + 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, + 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, + 0x6d, 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, + 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, + 0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, + 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, + 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x60, 0x23, 0x00, + 0x25, 0x00, 0x14, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, + 0xc6, 0x20, 0x84, 0x14, 0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1, + 0x9b, 0x86, 0xcb, 0x9f, 0xb0, 0x87, 0x90, 0xfc, 0x95, 0x90, 0x56, 0x62, + 0xf2, 0x8b, 0xdb, 0x46, 0xc5, 0x18, 0x63, 0x10, 0x2a, 0xf7, 0x0c, 0x97, + 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0x21, 0xd0, 0x0c, 0x0b, 0x81, 0x82, 0x55, + 0x14, 0x45, 0x18, 0x21, 0x84, 0x10, 0x42, 0xa8, 0xcd, 0x11, 0x04, 0xc5, + 0x60, 0xa4, 0x10, 0xf2, 0x08, 0x0e, 0x04, 0x0c, 0x23, 0x10, 0xc3, 0x4c, + 0x6d, 0x30, 0x0e, 0xec, 0x10, 0x0e, 0xf3, 0x30, 0x0f, 0x6e, 0x40, 0x0b, + 0xe5, 0x80, 0x0f, 0xf4, 0x50, 0x0f, 0xf2, 0x50, 0x0e, 0x72, 0x40, 0x0a, + 0x7c, 0x60, 0x0f, 0xe5, 0x30, 0x0e, 0xf4, 0xf0, 0x0e, 0xf2, 0xc0, 0x07, + 0xe6, 0xc0, 0x0e, 0xef, 0x10, 0x0e, 0xf4, 0xc0, 0x06, 0x60, 0x40, 0x07, + 0x7e, 0x00, 0x06, 0x7e, 0xa0, 0x07, 0x7a, 0xd0, 0x0e, 0xe9, 0x00, 0x0f, + 0xf3, 0xf0, 0x0b, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x28, 0x20, 0x33, + 0x89, 0xc1, 0x38, 0xb0, 0x43, 0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, + 0x94, 0x03, 0x3e, 0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39, 0xc8, 0x01, 0x29, + 0xf0, 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, + 0x98, 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, + 0xf8, 0x01, 0x18, 0xf8, 0x01, 0x12, 0x26, 0xa5, 0x9a, 0x06, 0x04, 0x00, + 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, + 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, + 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, + 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, + 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, + 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, + 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, + 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, + 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, + 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, + 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, + 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, + 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, + 0x81, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x0b, 0x04, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, + 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, + 0x25, 0x30, 0x02, 0x50, 0x0c, 0x45, 0x50, 0x12, 0x65, 0x50, 0x1e, 0x65, + 0x51, 0x3a, 0x85, 0x40, 0xa5, 0x24, 0xca, 0xa0, 0x10, 0x46, 0x00, 0x0a, + 0x84, 0xec, 0x0c, 0x00, 0xdd, 0xb1, 0x0c, 0x82, 0x38, 0x0e, 0x00, 0x00, + 0x79, 0x18, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, + 0x46, 0x02, 0x13, 0x44, 0x8f, 0x0c, 0x6f, 0xec, 0xed, 0x4d, 0x0c, 0x24, + 0xc6, 0xe5, 0xc6, 0x45, 0x46, 0x26, 0x46, 0xc6, 0x25, 0x46, 0x06, 0x04, + 0x05, 0x67, 0x2c, 0x87, 0x2c, 0x47, 0x46, 0xac, 0xec, 0x26, 0x65, 0x43, + 0x10, 0x4c, 0x10, 0x88, 0x62, 0x82, 0x40, 0x18, 0x1b, 0x84, 0x81, 0xd8, + 0x20, 0x10, 0x04, 0x05, 0xb8, 0xb9, 0x09, 0x02, 0x71, 0x6c, 0x18, 0x0e, + 0x84, 0x98, 0x20, 0x58, 0x14, 0x11, 0xb9, 0xaf, 0xb1, 0x3a, 0x39, 0x39, + 0x21, 0xa1, 0x09, 0x02, 0x81, 0x4c, 0x10, 0x88, 0x64, 0x83, 0x40, 0x34, + 0x1b, 0x12, 0x42, 0x59, 0x08, 0x62, 0x60, 0x08, 0x87, 0x8b, 0xdc, 0x57, + 0x5d, 0x1a, 0x55, 0x19, 0x1e, 0x5d, 0x9d, 0x5c, 0xd9, 0x86, 0x64, 0x50, + 0x20, 0x62, 0x18, 0x18, 0xc2, 0xd9, 0x20, 0x3c, 0xd1, 0x06, 0x42, 0x02, + 0x00, 0x60, 0x82, 0x20, 0x00, 0x1b, 0x80, 0x0d, 0x03, 0x51, 0x55, 0x1b, + 0x02, 0x6b, 0xc3, 0x30, 0x50, 0xd7, 0x04, 0xe1, 0xaa, 0x36, 0x04, 0x19, + 0x8d, 0xb6, 0xb0, 0x34, 0x37, 0xa8, 0x29, 0x2e, 0x53, 0x56, 0x5f, 0x50, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x13, 0x84, 0xe2, 0x99, 0x20, + 0x14, 0xd0, 0x86, 0x80, 0x98, 0x20, 0x14, 0xd1, 0x04, 0xa1, 0x90, 0x26, + 0x08, 0x84, 0xb2, 0x41, 0x10, 0x03, 0x31, 0xd8, 0xb0, 0x10, 0x5c, 0xe7, + 0x7d, 0x60, 0x30, 0x80, 0x01, 0x11, 0x06, 0x63, 0xb0, 0x21, 0x20, 0x03, + 0x26, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x13, 0x84, + 0x62, 0x9a, 0x20, 0x10, 0xcb, 0x06, 0x41, 0x0c, 0xd0, 0x60, 0xc3, 0x42, + 0x98, 0x41, 0x77, 0x06, 0x5f, 0x18, 0x0c, 0x60, 0x40, 0x84, 0x41, 0x1a, + 0x6c, 0x08, 0xd4, 0x60, 0xc3, 0x50, 0x06, 0x6b, 0x00, 0x6c, 0x28, 0xa8, + 0x8d, 0x0d, 0x26, 0x80, 0x86, 0x19, 0xdb, 0x5b, 0x18, 0xdd, 0xdc, 0x04, + 0x81, 0x60, 0x58, 0xa4, 0xb9, 0xcd, 0xd1, 0xcd, 0x4d, 0x10, 0x88, 0x86, + 0xc6, 0x5c, 0xda, 0xd9, 0x17, 0x1b, 0x19, 0x8d, 0xb9, 0xb4, 0xb3, 0xaf, + 0x39, 0xba, 0x09, 0x02, 0xe1, 0x10, 0xa1, 0x2b, 0xc3, 0xfb, 0x62, 0x7b, + 0x0b, 0x23, 0xdb, 0xa0, 0xb8, 0xc1, 0x1b, 0xc0, 0x41, 0x1c, 0xc8, 0x01, + 0x33, 0x07, 0x74, 0x50, 0x07, 0x4c, 0x15, 0x36, 0x36, 0xbb, 0x36, 0x97, + 0x34, 0xb2, 0x32, 0x37, 0xba, 0x29, 0x41, 0x50, 0x85, 0x0c, 0xcf, 0xc5, + 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x6d, 0x4a, 0x40, 0x34, 0x21, 0xc3, + 0x73, 0xb1, 0x0b, 0x63, 0xb3, 0x2b, 0x93, 0x9b, 0x12, 0x14, 0x75, 0xc8, + 0xf0, 0x5c, 0xe6, 0xd0, 0xc2, 0xc8, 0xca, 0xe4, 0x9a, 0xde, 0xc8, 0xca, + 0xd8, 0xa6, 0x04, 0x48, 0x19, 0x32, 0x3c, 0x17, 0xb9, 0xb2, 0xb9, 0xb7, + 0x3a, 0xb9, 0xb1, 0xb2, 0xb9, 0x29, 0x81, 0x54, 0x89, 0x0c, 0xcf, 0x85, + 0x2e, 0x0f, 0xae, 0x2c, 0xc8, 0xcd, 0xed, 0x8d, 0x2e, 0x8c, 0x2e, 0xed, + 0xcd, 0x6d, 0x6e, 0x4a, 0x70, 0xd5, 0x21, 0xc3, 0x73, 0xb1, 0x4b, 0x2b, + 0xbb, 0x4b, 0x22, 0x9b, 0xa2, 0x0b, 0xa3, 0x2b, 0x9b, 0x12, 0x64, 0x75, + 0xc8, 0xf0, 0x5c, 0xca, 0xdc, 0xe8, 0xe4, 0xf2, 0xa0, 0xde, 0xd2, 0xdc, + 0xe8, 0xe6, 0xa6, 0x04, 0x6c, 0xd0, 0x85, 0x0c, 0xcf, 0x65, 0xec, 0xad, + 0xce, 0x8d, 0xae, 0x4c, 0x6e, 0x6e, 0x4a, 0x50, 0x07, 0x00, 0x00, 0x00, + 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, + 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, + 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, + 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, + 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, + 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, + 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, + 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, + 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, + 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, + 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, + 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, + 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, + 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, + 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, + 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, + 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, + 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, + 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, + 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, + 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, + 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, + 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, + 0x03, 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, + 0xe0, 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, + 0xc0, 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, + 0x71, 0x20, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x46, 0x20, 0x0d, 0x97, + 0xef, 0x3c, 0xbe, 0x10, 0x11, 0xc0, 0x44, 0x84, 0x40, 0x33, 0x2c, 0x84, + 0x05, 0x4c, 0xc3, 0xe5, 0x3b, 0x8f, 0xbf, 0x38, 0xc0, 0x20, 0x36, 0x0f, + 0x35, 0xf9, 0xc5, 0x6d, 0x9b, 0x40, 0x35, 0x5c, 0xbe, 0xf3, 0xf8, 0xd2, + 0xe4, 0x44, 0x04, 0x4a, 0x4d, 0x0f, 0x35, 0xf9, 0xc5, 0x6d, 0xdb, 0x40, + 0x35, 0x5c, 0xbe, 0xf3, 0xf8, 0x13, 0x71, 0x4d, 0x54, 0x44, 0x94, 0x0e, + 0x30, 0xf8, 0xc5, 0x6d, 0x1b, 0x80, 0xc1, 0x00, 0x48, 0x93, 0xb2, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x4a, 0xb4, 0x4b, 0xf2, 0xdf, 0x6e, 0x4d, + 0xc3, 0x0a, 0x8d, 0xc1, 0xfd, 0xb1, 0xbf, 0x50, 0x44, 0x58, 0x49, 0x4c, + 0xa0, 0x06, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, + 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x88, 0x06, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, + 0x9f, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, + 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, + 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, + 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, + 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, + 0xe4, 0x48, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, + 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, + 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, + 0x6d, 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, + 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, + 0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, + 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, + 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x60, 0x23, 0x00, + 0x25, 0x00, 0x14, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, + 0xc6, 0x20, 0x84, 0x14, 0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1, + 0x9b, 0x86, 0xcb, 0x9f, 0xb0, 0x87, 0x90, 0xfc, 0x95, 0x90, 0x56, 0x62, + 0xf2, 0x8b, 0xdb, 0x46, 0xc5, 0x18, 0x63, 0x10, 0x2a, 0xf7, 0x0c, 0x97, + 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0x21, 0xd0, 0x0c, 0x0b, 0x81, 0x82, 0x55, + 0x14, 0x45, 0x18, 0x21, 0x84, 0x10, 0x42, 0xa8, 0xcd, 0x11, 0x04, 0xc5, + 0x60, 0xa4, 0x10, 0xf2, 0x08, 0x0e, 0x04, 0x0c, 0x23, 0x10, 0xc3, 0x4c, + 0x6d, 0x30, 0x0e, 0xec, 0x10, 0x0e, 0xf3, 0x30, 0x0f, 0x6e, 0x40, 0x0b, + 0xe5, 0x80, 0x0f, 0xf4, 0x50, 0x0f, 0xf2, 0x50, 0x0e, 0x72, 0x40, 0x0a, + 0x7c, 0x60, 0x0f, 0xe5, 0x30, 0x0e, 0xf4, 0xf0, 0x0e, 0xf2, 0xc0, 0x07, + 0xe6, 0xc0, 0x0e, 0xef, 0x10, 0x0e, 0xf4, 0xc0, 0x06, 0x60, 0x40, 0x07, + 0x7e, 0x00, 0x06, 0x7e, 0xa0, 0x07, 0x7a, 0xd0, 0x0e, 0xe9, 0x00, 0x0f, + 0xf3, 0xf0, 0x0b, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x28, 0x20, 0x33, + 0x89, 0xc1, 0x38, 0xb0, 0x43, 0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, + 0x94, 0x03, 0x3e, 0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39, 0xc8, 0x01, 0x29, + 0xf0, 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, + 0x98, 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, + 0xf8, 0x01, 0x18, 0xf8, 0x01, 0x12, 0x26, 0xa5, 0x9a, 0x06, 0x04, 0x00, + 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, + 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, + 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, + 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, + 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, + 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, + 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, + 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, + 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, + 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, + 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, + 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, + 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, + 0x81, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x0b, 0x04, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, + 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, + 0x25, 0x30, 0x02, 0x50, 0x0e, 0xc5, 0x50, 0x04, 0x25, 0x51, 0x06, 0xe5, + 0x41, 0xa5, 0x24, 0xca, 0xa0, 0x10, 0x46, 0x00, 0x0a, 0x84, 0xec, 0x0c, + 0x00, 0xdd, 0xb1, 0x0c, 0x82, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x79, 0x18, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, + 0x46, 0x02, 0x13, 0x44, 0x8f, 0x0c, 0x6f, 0xec, 0xed, 0x4d, 0x0c, 0x24, + 0xc6, 0xe5, 0xc6, 0x45, 0x46, 0x26, 0x46, 0xc6, 0x25, 0x46, 0x06, 0x04, + 0x05, 0x67, 0x2c, 0x87, 0x2c, 0x47, 0x46, 0xac, 0xec, 0x26, 0x65, 0x43, + 0x10, 0x4c, 0x10, 0x88, 0x62, 0x82, 0x40, 0x18, 0x1b, 0x84, 0x81, 0x98, + 0x20, 0x10, 0xc7, 0x06, 0x61, 0x30, 0x28, 0xc0, 0xcd, 0x4d, 0x10, 0x08, + 0x64, 0xc3, 0x80, 0x24, 0xc4, 0x04, 0xc1, 0x92, 0x08, 0x4c, 0x10, 0x88, + 0x64, 0x82, 0x40, 0x28, 0x1b, 0x04, 0xc2, 0xd9, 0x90, 0x10, 0x0b, 0x43, + 0x10, 0x43, 0x43, 0x3c, 0x1b, 0x92, 0x61, 0x61, 0x88, 0x61, 0x68, 0x88, + 0x67, 0x83, 0x00, 0x45, 0x1b, 0x08, 0x09, 0x00, 0x80, 0x09, 0xc2, 0x35, + 0x6d, 0x08, 0xa8, 0x09, 0x82, 0x00, 0xd0, 0x68, 0x0b, 0x4b, 0x73, 0x83, + 0x9a, 0xe2, 0x32, 0x65, 0xf5, 0x05, 0xf5, 0x36, 0x97, 0x46, 0x97, 0xf6, + 0xe6, 0x36, 0x41, 0x28, 0x9a, 0x09, 0x42, 0xe1, 0x6c, 0x08, 0x88, 0x09, + 0x42, 0xf1, 0x4c, 0x10, 0x0a, 0x68, 0x82, 0x40, 0x2c, 0x1b, 0x04, 0xcf, + 0xdb, 0xb0, 0x10, 0x58, 0xa6, 0x6d, 0xdc, 0xc0, 0x11, 0xdd, 0xb7, 0x21, + 0x00, 0x03, 0x26, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x13, 0x84, 0x22, 0x9a, 0x20, 0x10, 0xcc, 0x06, 0xc1, 0x23, 0x83, 0x0d, + 0x0b, 0x21, 0x06, 0xd9, 0x18, 0x6c, 0xdd, 0xc0, 0x11, 0x5d, 0x19, 0x6c, + 0x08, 0xcc, 0x60, 0xc3, 0x10, 0x06, 0x67, 0x00, 0x6c, 0x28, 0xac, 0x0b, + 0x0d, 0x26, 0xa0, 0x0a, 0x1b, 0x9b, 0x5d, 0x9b, 0x4b, 0x1a, 0x59, 0x99, + 0x1b, 0xdd, 0x94, 0x20, 0xa8, 0x42, 0x86, 0xe7, 0x62, 0x57, 0x26, 0x37, + 0x97, 0xf6, 0xe6, 0x36, 0x25, 0x20, 0x9a, 0x90, 0xe1, 0xb9, 0xd8, 0x85, + 0xb1, 0xd9, 0x95, 0xc9, 0x4d, 0x09, 0x8c, 0x3a, 0x64, 0x78, 0x2e, 0x73, + 0x68, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x53, 0x82, + 0xa4, 0x0c, 0x19, 0x9e, 0x8b, 0x5c, 0xd9, 0xdc, 0x5b, 0x9d, 0xdc, 0x58, + 0xd9, 0xdc, 0x94, 0x40, 0xaa, 0x43, 0x86, 0xe7, 0x62, 0x97, 0x56, 0x76, + 0x97, 0x44, 0x36, 0x45, 0x17, 0x46, 0x57, 0x36, 0x25, 0xa0, 0xea, 0x90, + 0xe1, 0xb9, 0x94, 0xb9, 0xd1, 0xc9, 0xe5, 0x41, 0xbd, 0xa5, 0xb9, 0xd1, + 0xcd, 0x4d, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, + 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, + 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, + 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, + 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, + 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, + 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, + 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, + 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, + 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, + 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, + 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, + 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, + 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, + 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, + 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, + 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, + 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, + 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, + 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, + 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, + 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, + 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, + 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, + 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, + 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x46, 0x20, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x10, + 0x11, 0xc0, 0x44, 0x84, 0x40, 0x33, 0x2c, 0x84, 0x05, 0x4c, 0xc3, 0xe5, + 0x3b, 0x8f, 0xbf, 0x38, 0xc0, 0x20, 0x36, 0x0f, 0x35, 0xf9, 0xc5, 0x6d, + 0x9b, 0x40, 0x35, 0x5c, 0xbe, 0xf3, 0xf8, 0xd2, 0xe4, 0x44, 0x04, 0x4a, + 0x4d, 0x0f, 0x35, 0xf9, 0xc5, 0x6d, 0xdb, 0x40, 0x35, 0x5c, 0xbe, 0xf3, + 0xf8, 0x13, 0x71, 0x4d, 0x54, 0x44, 0x94, 0x0e, 0x30, 0xf8, 0xc5, 0x6d, + 0x1b, 0x80, 0xc1, 0x00, 0x48, 0x93, 0xb2, 0x00, 0x61, 0x20, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0xf4, 0x46, 0x00, 0x88, 0xcc, 0x00, 0x94, 0x42, + 0xc9, 0x15, 0x42, 0x11, 0x06, 0x50, 0x29, 0x81, 0x22, 0xa0, 0x31, 0x46, + 0x00, 0x82, 0x20, 0x88, 0x7f, 0x00, 0x00, 0x00, 0x23, 0x06, 0x09, 0x00, + 0x82, 0x60, 0x00, 0x65, 0x46, 0x83, 0x61, 0xc9, 0x88, 0x41, 0x02, 0x80, + 0x20, 0x18, 0x40, 0xda, 0xe1, 0x60, 0x98, 0x32, 0x62, 0x90, 0x00, 0x20, + 0x08, 0x06, 0x86, 0x77, 0x64, 0xd9, 0xa3, 0x8c, 0x18, 0x24, 0x00, 0x08, + 0x82, 0x81, 0xf1, 0x21, 0x9a, 0x66, 0x2c, 0x27, 0x90, 0x39, 0x81, 0xcc, + 0x88, 0x41, 0x03, 0x80, 0x20, 0x18, 0x34, 0x60, 0xa0, 0x14, 0x9d, 0x10, + 0x38, 0x8e, 0xe3, 0x8c, 0x26, 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c, 0x26, + 0x0c, 0xc2, 0x88, 0x41, 0x03, 0x80, 0x20, 0x18, 0x34, 0x64, 0xe0, 0x28, + 0x61, 0x60, 0x14, 0x92, 0x24, 0x49, 0xa3, 0x09, 0x01, 0x30, 0x9a, 0x20, + 0x04, 0xa3, 0x09, 0x83, 0x30, 0x9a, 0x40, 0x0c, 0x46, 0x20, 0xf1, 0x31, + 0x02, 0x89, 0x8f, 0x11, 0x48, 0x7c, 0x6c, 0x20, 0xe4, 0x63, 0x43, 0x21, + 0x1f, 0x1b, 0x0c, 0xf9, 0xd8, 0xe0, 0xc0, 0xc7, 0x06, 0x07, 0x3e, 0x36, + 0x38, 0xf0, 0x19, 0x31, 0x48, 0x00, 0x10, 0x04, 0x03, 0x64, 0x0e, 0xbe, + 0x37, 0x78, 0x83, 0x32, 0x18, 0x46, 0x0c, 0x12, 0x00, 0x04, 0xc1, 0x00, + 0x99, 0x83, 0xef, 0x0d, 0xde, 0x60, 0x13, 0x46, 0x0c, 0x12, 0x00, 0x04, + 0xc1, 0x00, 0x99, 0x83, 0xef, 0x0d, 0xde, 0x40, 0x0b, 0x46, 0x0c, 0x12, + 0x00, 0x04, 0xc1, 0x00, 0x99, 0x83, 0xef, 0x0d, 0xde, 0xe0, 0x0c, 0x32, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiCompositionVS.h b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiCompositionVS.h new file mode 100644 index 00000000..b74c4c19 --- /dev/null +++ b/sdk/src/backends/dx12/FrameInterpolationSwapchain/FrameInterpolationSwapchainUiCompositionVS.h @@ -0,0 +1,368 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 0 +; +; Input signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_VertexID 0 x 0 VERTID uint x +; +; +; Output signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_Position 0 xyzw 0 POS float xyzw +; +; shader hash: 9c9250b58d999f98fcf99aa27bc96e66 +; +; Pipeline Runtime Information: +; +; Vertex Shader +; OutputPositionPresent=1 +; +; +; Input signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_VertexID 0 +; +; Output signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_Position 0 noperspective +; +; Buffer Definitions: +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; +; +; ViewId state: +; +; Number of inputs: 1, outputs: 4 +; Outputs dependent on ViewId: { } +; Inputs contributing to computation of Outputs: +; output 0 depends on inputs: { 0 } +; output 1 depends on inputs: { 0 } +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +define void @mainVS() { + %1 = call i32 @dx.op.loadInput.i32(i32 4, i32 0, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %2 = shl i32 %1, 2 + %3 = and i32 %2, 4 + %4 = add nsw i32 %3, -1 + %5 = sitofp i32 %4 to float + %6 = and i32 %1, 2 + %7 = mul nsw i32 %6, -2 + %8 = or i32 %7, 1 + %9 = sitofp i32 %8 to float + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %5) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %9) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float 5.000000e-01) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float 1.000000e+00) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + ret void +} + +; Function Attrs: nounwind readnone +declare i32 @dx.op.loadInput.i32(i32, i32, i32, i8, i32) #0 + +; Function Attrs: nounwind +declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1 + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!2} +!dx.shaderModel = !{!3} +!dx.viewIdState = !{!4} +!dx.entryPoints = !{!5} + +!0 = !{!"dxcoob 1.7.2212.12 (8c9d92be7)"} +!1 = !{i32 1, i32 0} +!2 = !{i32 1, i32 7} +!3 = !{!"vs", i32 6, i32 0} +!4 = !{[3 x i32] [i32 1, i32 4, i32 3]} +!5 = !{void ()* @mainVS, !"mainVS", !6, null, null} +!6 = !{!7, !11, null} +!7 = !{!8} +!8 = !{i32 0, !"SV_VertexID", i8 5, i8 1, !9, i8 0, i32 1, i8 1, i32 0, i8 0, !10} +!9 = !{i32 0} +!10 = !{i32 3, i32 1} +!11 = !{!12} +!12 = !{i32 0, !"SV_Position", i8 9, i8 3, !9, i8 4, i32 1, i8 4, i32 0, i8 0, !13} +!13 = !{i32 3, i32 15} + +#endif + +const unsigned char g_mainVS[] = { + 0x44, 0x58, 0x42, 0x43, 0x7e, 0x51, 0x30, 0xd0, 0x50, 0x04, 0x8b, 0xe5, + 0xc0, 0xfa, 0xc6, 0x82, 0x54, 0x28, 0xad, 0x26, 0x01, 0x00, 0x00, 0x00, + 0x38, 0x0b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, + 0x48, 0x01, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x48, 0x06, 0x00, 0x00, + 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x56, 0x65, 0x72, 0x74, 0x65, + 0x78, 0x49, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x00, 0x50, 0x53, 0x56, 0x30, 0x7c, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x41, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x03, 0x03, 0x04, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xdc, 0x04, 0x00, 0x00, + 0x60, 0x00, 0x01, 0x00, 0x37, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, + 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc4, 0x04, 0x00, 0x00, + 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x2e, 0x01, 0x00, 0x00, + 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, + 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, + 0x80, 0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, + 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14, 0x20, + 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, + 0x11, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, + 0x04, 0x21, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, + 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x01, 0x00, 0x00, 0x00, + 0x49, 0x18, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, + 0x20, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x32, 0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, + 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, + 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x30, 0x23, 0x00, 0x25, 0x00, 0x8a, 0x39, + 0x02, 0x30, 0x98, 0x23, 0x40, 0x8a, 0x31, 0x33, 0x43, 0x43, 0x35, 0x03, + 0x50, 0x0c, 0x98, 0x19, 0x3a, 0xc2, 0x81, 0x80, 0x1c, 0x18, 0x00, 0x00, + 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, + 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, + 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, + 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, + 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, + 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, + 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, + 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, + 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, + 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, + 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, + 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x05, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x02, 0x01, + 0x0c, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, + 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x9a, 0x12, 0x18, 0x01, 0x28, + 0x86, 0x32, 0x28, 0x8f, 0x22, 0x28, 0x8e, 0x42, 0x20, 0x2a, 0x85, 0x12, + 0x18, 0x01, 0x28, 0x89, 0x32, 0x28, 0x04, 0xda, 0xb1, 0x86, 0x80, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, + 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x8f, 0x0c, 0x6f, 0xec, + 0xed, 0x4d, 0x0c, 0x24, 0xc6, 0xe5, 0xc6, 0x45, 0x46, 0x26, 0x46, 0xc6, + 0x25, 0x46, 0x06, 0x04, 0x05, 0x67, 0x2c, 0x87, 0x2c, 0x47, 0x46, 0xac, + 0xec, 0x26, 0x65, 0x43, 0x10, 0x4c, 0x10, 0x86, 0x61, 0x82, 0x30, 0x10, + 0x1b, 0x84, 0x81, 0xd8, 0x20, 0x10, 0x04, 0x05, 0xbb, 0xb9, 0x09, 0xc2, + 0x50, 0x6c, 0x18, 0x0e, 0x84, 0x98, 0x20, 0x08, 0xc0, 0x06, 0x60, 0xc3, + 0x40, 0x2c, 0xcb, 0x86, 0x80, 0xd9, 0x30, 0x0c, 0x4a, 0x33, 0x41, 0x58, + 0xa2, 0x0d, 0xc1, 0x43, 0xa3, 0x2d, 0x2c, 0xcd, 0xcd, 0x6a, 0x8a, 0xcb, + 0x94, 0xd5, 0x97, 0x55, 0x99, 0x1c, 0x5d, 0x19, 0x5e, 0x12, 0xd1, 0x04, + 0x81, 0x58, 0x26, 0x08, 0x04, 0xb3, 0x21, 0x20, 0x26, 0x08, 0x44, 0x33, + 0x41, 0x18, 0x8c, 0x0d, 0xc2, 0x35, 0x6c, 0x58, 0x08, 0x69, 0xa2, 0x2a, + 0x6b, 0xa0, 0x08, 0x0b, 0xdb, 0x10, 0x64, 0x5c, 0xa6, 0xac, 0xbe, 0xa0, + 0xde, 0xe6, 0xd2, 0xe8, 0xd2, 0xde, 0xdc, 0x26, 0x08, 0x84, 0x33, 0x41, + 0x20, 0x9e, 0x09, 0x02, 0x01, 0x4d, 0x10, 0x86, 0x63, 0x83, 0x70, 0x7d, + 0x1b, 0x16, 0x62, 0xe3, 0xba, 0xca, 0x1b, 0x3c, 0xc2, 0x02, 0x83, 0x0d, + 0x41, 0x18, 0x6c, 0x18, 0x34, 0x31, 0x00, 0x36, 0x14, 0x4a, 0x34, 0x06, + 0x00, 0x40, 0xc3, 0x8c, 0xed, 0x2d, 0x8c, 0x6e, 0x6e, 0x82, 0x30, 0x20, + 0x2c, 0xd2, 0xdc, 0xe6, 0xe8, 0xe6, 0x26, 0x08, 0x43, 0x42, 0x22, 0xcd, + 0x8d, 0x6e, 0x8e, 0xc6, 0x5c, 0xda, 0xd9, 0x17, 0x1b, 0x19, 0x8d, 0xb9, + 0xb4, 0xb3, 0xaf, 0x39, 0xba, 0x09, 0xc2, 0xa0, 0xb0, 0xa8, 0x4b, 0x73, + 0xa3, 0x9b, 0xdb, 0xc0, 0x94, 0x81, 0x19, 0x9c, 0x01, 0x1a, 0xa4, 0x81, + 0x19, 0xa8, 0xc1, 0xb0, 0x06, 0x6c, 0xd0, 0x06, 0x6c, 0x50, 0x85, 0x8d, + 0xcd, 0xae, 0xcd, 0x25, 0x8d, 0xac, 0xcc, 0x8d, 0x6e, 0x4a, 0x10, 0x54, + 0x21, 0xc3, 0x73, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x9b, 0x12, + 0x10, 0x4d, 0xc8, 0xf0, 0x5c, 0xec, 0xc2, 0xd8, 0xec, 0xca, 0xe4, 0xa6, + 0x04, 0x45, 0x1d, 0x32, 0x3c, 0x97, 0x39, 0xb4, 0x30, 0xb2, 0x32, 0xb9, + 0xa6, 0x37, 0xb2, 0x32, 0xb6, 0x29, 0x01, 0x52, 0x89, 0x0c, 0xcf, 0x85, + 0x2e, 0x0f, 0xae, 0x2c, 0xc8, 0xcd, 0xed, 0x8d, 0x2e, 0x8c, 0x2e, 0xed, + 0xcd, 0x6d, 0x6e, 0x4a, 0xd0, 0xd4, 0x21, 0xc3, 0x73, 0xb1, 0x4b, 0x2b, + 0xbb, 0x4b, 0x22, 0x9b, 0xa2, 0x0b, 0xa3, 0x2b, 0x9b, 0x12, 0x3c, 0x75, + 0xc8, 0xf0, 0x5c, 0xca, 0xdc, 0xe8, 0xe4, 0xf2, 0xa0, 0xde, 0xd2, 0xdc, + 0xe8, 0xe6, 0xa6, 0x04, 0x63, 0xd0, 0x85, 0x0c, 0xcf, 0x65, 0xec, 0xad, + 0xce, 0x8d, 0xae, 0x4c, 0x6e, 0x6e, 0x4a, 0xd0, 0x06, 0x00, 0x00, 0x00, + 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, + 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, + 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, + 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, + 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, + 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, + 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, + 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, + 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, + 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, + 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, + 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, + 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, + 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, + 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, + 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, + 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, + 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, + 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, + 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, + 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, + 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, + 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, + 0x03, 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, + 0xe0, 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, + 0xc0, 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, + 0x71, 0x20, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x16, 0x30, 0x0d, 0x97, + 0xef, 0x3c, 0xfe, 0xe2, 0x00, 0x83, 0xd8, 0x3c, 0xd4, 0xe4, 0x23, 0xb7, + 0x6d, 0x02, 0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, + 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x00, 0x06, 0x03, 0x20, 0xcd, + 0xcb, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x92, 0x50, 0xb5, + 0x8d, 0x99, 0x9f, 0x98, 0xfc, 0xf9, 0x9a, 0xa2, 0x7b, 0xc9, 0x6e, 0x66, + 0x44, 0x58, 0x49, 0x4c, 0xe8, 0x04, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, + 0x3a, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0xd0, 0x04, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, + 0x21, 0x0c, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, + 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, + 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, + 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, + 0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, + 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x22, 0xc4, 0x50, + 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, 0x06, + 0x51, 0x18, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x20, 0x01, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x00, 0x00, 0x00, + 0x89, 0x20, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, + 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, + 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, + 0x10, 0x30, 0x23, 0x00, 0x25, 0x00, 0x8a, 0x39, 0x02, 0x30, 0x98, 0x23, + 0x40, 0x8a, 0x31, 0x33, 0x43, 0x43, 0x35, 0x03, 0x50, 0x0c, 0x98, 0x19, + 0x3a, 0xc2, 0x81, 0x80, 0x1c, 0x18, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, + 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, + 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, + 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, + 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, + 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, + 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, + 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, + 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, + 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, + 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, + 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, + 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x86, 0x3c, 0x05, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x02, 0x01, 0x0b, 0x00, 0x00, 0x00, + 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, + 0xc6, 0x04, 0x43, 0x9a, 0x12, 0x18, 0x01, 0x28, 0x87, 0x62, 0x28, 0x83, + 0xf2, 0x20, 0x2a, 0x85, 0x12, 0x18, 0x01, 0x28, 0x89, 0x32, 0x28, 0x04, + 0xda, 0xb1, 0x86, 0x80, 0x18, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, + 0x46, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, + 0x8f, 0x0c, 0x6f, 0xec, 0xed, 0x4d, 0x0c, 0x24, 0xc6, 0xe5, 0xc6, 0x45, + 0x46, 0x26, 0x46, 0xc6, 0x25, 0x46, 0x06, 0x04, 0x05, 0x67, 0x2c, 0x87, + 0x2c, 0x47, 0x46, 0xac, 0xec, 0x26, 0x65, 0x43, 0x10, 0x4c, 0x10, 0x86, + 0x61, 0x82, 0x30, 0x10, 0x1b, 0x84, 0x81, 0x98, 0x20, 0x0c, 0xc5, 0x06, + 0x61, 0x30, 0x28, 0xd8, 0xcd, 0x4d, 0x10, 0x06, 0x63, 0xc3, 0x80, 0x24, + 0xc4, 0x04, 0x61, 0x79, 0x36, 0x04, 0xcb, 0x04, 0x41, 0x00, 0x68, 0xb4, + 0x85, 0xa5, 0xb9, 0x59, 0x4d, 0x71, 0x99, 0xb2, 0xfa, 0xb2, 0x2a, 0x93, + 0xa3, 0x2b, 0xc3, 0x4b, 0x22, 0x9a, 0x20, 0x10, 0xc9, 0x04, 0x81, 0x50, + 0x36, 0x04, 0xc4, 0x04, 0x81, 0x58, 0x26, 0x08, 0xc3, 0xb1, 0x41, 0xa0, + 0x86, 0x0d, 0x0b, 0xf1, 0x40, 0x91, 0x34, 0x0d, 0x11, 0x31, 0x55, 0x1b, + 0x02, 0x8b, 0xcb, 0x94, 0xd5, 0x17, 0xd4, 0xdb, 0x5c, 0x1a, 0x5d, 0xda, + 0x9b, 0xdb, 0x04, 0x81, 0x60, 0x26, 0x08, 0x44, 0x33, 0x41, 0x20, 0x9c, + 0x09, 0xc2, 0x80, 0x6c, 0x10, 0x28, 0x6e, 0xc3, 0x42, 0x60, 0x99, 0x26, + 0x6d, 0xc3, 0x46, 0x4c, 0xdd, 0x86, 0xc0, 0xdb, 0x30, 0x5c, 0x1f, 0xb0, + 0xa1, 0x68, 0x1c, 0x30, 0x00, 0x80, 0x2a, 0x6c, 0x6c, 0x76, 0x6d, 0x2e, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x53, 0x82, 0xa0, 0x0a, 0x19, 0x9e, 0x8b, + 0x5d, 0x99, 0xdc, 0x5c, 0xda, 0x9b, 0xdb, 0x94, 0x80, 0x68, 0x42, 0x86, + 0xe7, 0x62, 0x17, 0xc6, 0x66, 0x57, 0x26, 0x37, 0x25, 0x30, 0xea, 0x90, + 0xe1, 0xb9, 0xcc, 0xa1, 0x85, 0x91, 0x95, 0xc9, 0x35, 0xbd, 0x91, 0x95, + 0xb1, 0x4d, 0x09, 0x92, 0x3a, 0x64, 0x78, 0x2e, 0x76, 0x69, 0x65, 0x77, + 0x49, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x82, 0xa5, 0x0e, 0x19, + 0x9e, 0x4b, 0x99, 0x1b, 0x9d, 0x5c, 0x1e, 0xd4, 0x5b, 0x9a, 0x1b, 0xdd, + 0xdc, 0x94, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, + 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, + 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, + 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, + 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, + 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, + 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, + 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, + 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, + 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, + 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, + 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, + 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, + 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, + 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, + 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, + 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, + 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, + 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, + 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, + 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, + 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, + 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, + 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, + 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, + 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x16, 0x30, 0x0d, 0x97, 0xef, 0x3c, 0xfe, 0xe2, + 0x00, 0x83, 0xd8, 0x3c, 0xd4, 0xe4, 0x23, 0xb7, 0x6d, 0x02, 0xd5, 0x70, + 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, + 0x17, 0xb7, 0x6d, 0x00, 0x06, 0x03, 0x20, 0xcd, 0xcb, 0x02, 0x00, 0x00, + 0x61, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, + 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x34, 0xa5, 0x50, 0x08, + 0x45, 0x30, 0x03, 0x50, 0x03, 0x55, 0x40, 0x54, 0x04, 0x74, 0x63, 0x04, + 0x20, 0x08, 0x82, 0xf0, 0x37, 0x46, 0x00, 0x82, 0x20, 0x88, 0x7f, 0x00, + 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x50, 0x60, 0x48, 0x55, 0x39, 0x46, + 0x05, 0xc8, 0x55, 0xa0, 0xa8, 0x05, 0x08, 0x08, 0x2e, 0x38, 0xab, 0x82, + 0x51, 0x0b, 0x14, 0x11, 0x54, 0xd0, 0xed, 0x05, 0x67, 0x23, 0x06, 0x09, + 0x00, 0x82, 0x60, 0x80, 0x80, 0x81, 0xe4, 0x79, 0x57, 0x31, 0x62, 0x90, + 0x00, 0x20, 0x08, 0x06, 0x08, 0x18, 0x48, 0x9e, 0x87, 0x05, 0x23, 0x06, + 0x09, 0x00, 0x82, 0x60, 0x80, 0x80, 0x81, 0xe4, 0x79, 0xcc, 0x32, 0x62, + 0x90, 0x00, 0x20, 0x08, 0x06, 0x08, 0x18, 0x48, 0x9e, 0x57, 0x29, 0x08, + 0x00, 0x00, 0x00, 0x00 +}; diff --git a/sdk/src/backends/dx12/FrameInterpolationSwapchain/recompileUiCompositionHLSL.bat b/sdk/src/backends/dx12/FrameInterpolationSwapchain/recompileUiCompositionHLSL.bat new file mode 100644 index 00000000..997c19af --- /dev/null +++ b/sdk/src/backends/dx12/FrameInterpolationSwapchain/recompileUiCompositionHLSL.bat @@ -0,0 +1,4 @@ +@REM regenerates the header files containing the shaderblobs for the ui composition blit +@REM only needs to be run when the shader is changed +..\..\..\..\tools\ffx_shader_compiler\libs\dxc\bin\x64\dxc.exe -Fh FrameInterpolationSwapchainUiCompositionVS.h -T vs_6_0 -E mainVS FrameInterpolationSwapchainUiComposition.hlsl +..\..\..\..\tools\ffx_shader_compiler\libs\dxc\bin\x64\dxc.exe -Fh FrameInterpolationSwapchainUiCompositionPS.h -T ps_6_0 -E mainPS FrameInterpolationSwapchainUiComposition.hlsl diff --git a/sdk/src/backends/dx12/GPUTimestamps.cpp b/sdk/src/backends/dx12/GPUTimestamps.cpp new file mode 100644 index 00000000..55776c5b --- /dev/null +++ b/sdk/src/backends/dx12/GPUTimestamps.cpp @@ -0,0 +1,134 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include "GPUTimestamps.h" + +namespace CAULDRON_DX12 +{ + void GPUTimestamps::Verify(ID3D12Device* pDevice, uint32_t numberOfBackBuffers) + { + if (!m_pBuffer) { + m_NumberOfBackBuffers = numberOfBackBuffers; + + D3D12_QUERY_HEAP_DESC queryHeapDesc = {}; + queryHeapDesc.Count = MaxValuesPerFrame * numberOfBackBuffers; + queryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP; + queryHeapDesc.NodeMask = 0; + pDevice->CreateQueryHeap(&queryHeapDesc, IID_PPV_ARGS(&m_pQueryHeap)); + + D3D12_HEAP_PROPERTIES heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK); + D3D12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(uint64_t) * numberOfBackBuffers * MaxValuesPerFrame); + pDevice->CreateCommittedResource( + &heapProperties, + D3D12_HEAP_FLAG_NONE, + &resourceDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&m_pBuffer)); + } + //SetName(m_pBuffer, "GPUTimestamps::m_pBuffer"); + } + + void GPUTimestamps::OnDestroy() + { + if (m_pBuffer) + m_pBuffer->Release(); + + if (m_pQueryHeap) + m_pQueryHeap->Release(); + } + + void GPUTimestamps::GetTimeStamp(ID3D12GraphicsCommandList *pCommandList, const char *label) + { + uint32_t numMeasurements = (uint32_t)m_labels[m_frame].size(); + pCommandList->EndQuery(m_pQueryHeap, D3D12_QUERY_TYPE_TIMESTAMP, m_frame*MaxValuesPerFrame + numMeasurements); + m_labels[m_frame].push_back(label); + } + + void GPUTimestamps::GetTimeStampUser(const TimeStamp& ts) + { + m_cpuTimeStamps[m_frame].push_back(ts); + } + + void GPUTimestamps::CollectTimings(ID3D12GraphicsCommandList *pCommandList) + { + uint32_t numMeasurements = (uint32_t)m_labels[m_frame].size(); + + pCommandList->ResolveQueryData(m_pQueryHeap, D3D12_QUERY_TYPE_TIMESTAMP, m_frame*MaxValuesPerFrame, numMeasurements, m_pBuffer, m_frame * MaxValuesPerFrame* sizeof(UINT64)); + } + + void GPUTimestamps::OnBeginFrame(UINT64 gpuTicksPerSecond, std::vector *pTimestamps) + { + std::vector &cpuTimeStamps = m_cpuTimeStamps[m_frame]; + std::vector &gpuLabels = m_labels[m_frame]; + + pTimestamps->clear(); + pTimestamps->reserve(cpuTimeStamps.size() + gpuLabels.size()); + + // copy CPU timestamps + // + for (uint32_t i = 0; i < cpuTimeStamps.size(); i++) + { + pTimestamps->push_back(cpuTimeStamps[i]); + } + + // copy GPU timestamps + // + uint32_t numMeasurements = (uint32_t)gpuLabels.size(); + if (numMeasurements > 0) + { + double microsecondsPerTick = 1000000.0 / (double)gpuTicksPerSecond; + + uint32_t ini = MaxValuesPerFrame * m_frame; + uint32_t fin = MaxValuesPerFrame * (m_frame + 1); + + CD3DX12_RANGE readRange(ini * sizeof(UINT64), fin * sizeof(UINT64)); + UINT64 *pTimingsBuffer = NULL; + m_pBuffer->Map(0, &readRange, reinterpret_cast(&pTimingsBuffer)); + + UINT64 *pTimingsInTicks = &pTimingsBuffer[ini]; + + for (uint32_t i = 1; i < numMeasurements; i++) + { + TimeStamp ts = { gpuLabels[i], float(microsecondsPerTick * (double)(pTimingsInTicks[i] - pTimingsInTicks[i-1])) }; + pTimestamps->push_back(ts); + } + + // compute total + TimeStamp ts = { "Total GPU Time", float(microsecondsPerTick * (double)(pTimingsInTicks[numMeasurements - 1] - pTimingsInTicks[0])) }; + pTimestamps->push_back(ts); + + CD3DX12_RANGE writtenRange(0, 0); + m_pBuffer->Unmap(0, &writtenRange); + } + + // we always need to clear these ones + cpuTimeStamps.clear(); + gpuLabels.clear(); + } + + void GPUTimestamps::OnEndFrame() + { + m_frame = (m_frame + 1) % m_NumberOfBackBuffers; + } +} diff --git a/sdk/src/backends/dx12/GPUTimestamps.h b/sdk/src/backends/dx12/GPUTimestamps.h new file mode 100644 index 00000000..b53356bb --- /dev/null +++ b/sdk/src/backends/dx12/GPUTimestamps.h @@ -0,0 +1,72 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include +#include + +struct TimeStamp +{ + std::string m_label; + float m_microseconds = 0.0f; +}; + +namespace CAULDRON_DX12 +{ + // In DX12 timestamps are written by the GPU into a system memory resource. + // Its similar to a 'dynamic' buffer but this time it is the GPU who is writing + // and CPU is who is reading. Hence we need a sort of ring buffer to make sure + // we are reading from a chunk of the buffer that is not written to by the GPU + // + + // This class helps insert queries in the command buffer and readback the results. + // The tricky part in fact is reading back the results without stalling the GPU. + // For that it splits the readback heap in pieces and it reads + // from the last used chuck. + + class GPUTimestamps + { + public: + void Verify(ID3D12Device *pDevice, uint32_t numberOfBackBuffers); + void OnDestroy(); + + void GetTimeStamp(ID3D12GraphicsCommandList *pCommandList, const char *label); + void GetTimeStampUser(const TimeStamp &ts); + void CollectTimings(ID3D12GraphicsCommandList *pCommandList); + + void OnBeginFrame(UINT64 gpuTicksPerSecond, std::vector *pTimestamps); + void OnEndFrame(); + + private: + const uint32_t MaxValuesPerFrame = 128; + + ID3D12Resource *m_pBuffer = NULL; + ID3D12QueryHeap *m_pQueryHeap = NULL; + + uint32_t m_frame = 0; + uint32_t m_NumberOfBackBuffers = 0; + + std::vector m_labels[5]; + std::vector m_cpuTimeStamps[5]; + }; +} diff --git a/sdk/src/backends/dx12/ffx_dx12.cpp b/sdk/src/backends/dx12/ffx_dx12.cpp index a21db9dd..c80ae8e3 100644 --- a/sdk/src/backends/dx12/ffx_dx12.cpp +++ b/sdk/src/backends/dx12/ffx_dx12.cpp @@ -1,32 +1,33 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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 #include #include #include #include -#include +#include <../src/backends/shared/ffx_shader_blobs.h> #include // convert string to wstring +#include // DX12 prototypes for functions in the backend interface FfxUInt32 GetSDKVersionDX12(FfxInterface* backendInterface); @@ -34,7 +35,7 @@ FfxErrorCode CreateBackendContextDX12(FfxInterface* backendInterface, FfxUInt32* FfxErrorCode GetDeviceCapabilitiesDX12(FfxInterface* backendInterface, FfxDeviceCapabilities* deviceCapabilities); FfxErrorCode DestroyBackendContextDX12(FfxInterface* backendInterface, FfxUInt32 effectContextId); FfxErrorCode CreateResourceDX12(FfxInterface* backendInterface, const FfxCreateResourceDescription* desc, FfxUInt32 effectContextId, FfxResourceInternal* outTexture); -FfxErrorCode DestroyResourceDX12(FfxInterface* backendInterface, FfxResourceInternal resource); +FfxErrorCode DestroyResourceDX12(FfxInterface* backendInterface, FfxResourceInternal resource, FfxUInt32 effectContextId); FfxErrorCode RegisterResourceDX12(FfxInterface* backendInterface, const FfxResource* inResource, FfxUInt32 effectContextId, FfxResourceInternal* outResourceInternal); FfxResource GetResourceDX12(FfxInterface* backendInterface, FfxResourceInternal resource); FfxErrorCode UnregisterResourcesDX12(FfxInterface* backendInterface, FfxCommandList commandList, FfxUInt32 effectContextId); @@ -46,10 +47,6 @@ FfxErrorCode ExecuteGpuJobsDX12(FfxInterface* backendInterface, FfxCommandList c #define FFX_MAX_RESOURCE_IDENTIFIER_COUNT (128) -// To track parallel effect context usage -static uint32_t s_BackendRefCount = 0; -static size_t s_MaxEffectContexts = 0; - typedef struct BackendContext_DX12 { // store for resources and resourceViews @@ -67,11 +64,17 @@ typedef struct BackendContext_DX12 { uint32_t uavDescCount; } Resource; + uint32_t refCount; + uint32_t maxEffectContexts; + ID3D12Device* device = nullptr; FfxGpuJobDescription* pGpuJobs; uint32_t gpuJobCount; + uint32_t nextRtvDescriptor; + ID3D12DescriptorHeap* descHeapRtvCpu; + ID3D12DescriptorHeap* descHeapSrvCpu; ID3D12DescriptorHeap* descHeapUavCpu; ID3D12DescriptorHeap* descHeapUavGpu; @@ -84,6 +87,7 @@ typedef struct BackendContext_DX12 { ID3D12Resource* constantBufferResource; uint32_t constantBufferSize; uint32_t constantBufferOffset; + std::mutex constantBufferMutex; D3D12_RESOURCE_BARRIER barriers[FFX_MAX_BARRIERS]; uint32_t barrierCount; @@ -131,11 +135,8 @@ FfxErrorCode ffxGetInterfaceDX12( FfxDevice device, void* scratchBuffer, size_t scratchBufferSize, - size_t maxContexts) { + uint32_t maxContexts) { - FFX_RETURN_ON_ERROR( - !s_BackendRefCount, - FFX_ERROR_BACKEND_API_ERROR); FFX_RETURN_ON_ERROR( backendInterface, FFX_ERROR_INVALID_POINTER); @@ -157,19 +158,30 @@ FfxErrorCode ffxGetInterfaceDX12( backendInterface->fpUnregisterResources = UnregisterResourcesDX12; backendInterface->fpGetResourceDescription = GetResourceDescriptorDX12; backendInterface->fpCreatePipeline = CreatePipelineDX12; + backendInterface->fpGetPermutationBlobByIndex = ffxGetPermutationBlobByIndex; backendInterface->fpDestroyPipeline = DestroyPipelineDX12; backendInterface->fpScheduleGpuJob = ScheduleGpuJobDX12; backendInterface->fpExecuteGpuJobs = ExecuteGpuJobsDX12; + backendInterface->fpSwapChainConfigureFrameGeneration = ffxSetFrameGenerationConfigToSwapchainDX12; // Memory assignments backendInterface->scratchBuffer = scratchBuffer; backendInterface->scratchBufferSize = scratchBufferSize; + BackendContext_DX12* backendContext = (BackendContext_DX12*)backendInterface->scratchBuffer; + + FFX_RETURN_ON_ERROR( + !backendContext->refCount, + FFX_ERROR_BACKEND_API_ERROR); + + // Clear everything out + memset(backendContext, 0, sizeof(*backendContext)); + // Set the device backendInterface->device = device; // Assign the max number of contexts we'll be using - s_MaxEffectContexts = maxContexts; + backendContext->maxEffectContexts = (uint32_t)maxContexts; return FFX_OK; } @@ -181,13 +193,13 @@ FfxCommandList ffxGetCommandListDX12(ID3D12CommandList* cmdList) } // register a DX12 resource to the backend -FfxResource ffxGetResourceDX12(ID3D12Resource* dx12Resource, +FfxResource ffxGetResourceDX12(const ID3D12Resource* dx12Resource, FfxResourceDescription ffxResDescription, wchar_t* ffxResName, FfxResourceStates state /*=FFX_RESOURCE_STATE_COMPUTE_READ*/) { FfxResource resource = {}; - resource.resource = reinterpret_cast(dx12Resource); + resource.resource = reinterpret_cast(const_cast(dx12Resource)); resource.state = state; resource.description = ffxResDescription; @@ -284,8 +296,15 @@ static DXGI_FORMAT convertFormatSrv(DXGI_FORMAT format) case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_UNORM; - // Colors can map as is + // Handle Color + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + return DXGI_FORMAT_R8G8B8A8_UNORM; + + // Others can map as is default: + return format; } } @@ -294,13 +313,13 @@ D3D12_RESOURCE_STATES ffxGetDX12StateFromResourceState(FfxResourceStates state) { switch (state) { - case(FFX_RESOURCE_STATE_GENERIC_READ): + case (FFX_RESOURCE_STATE_GENERIC_READ): return D3D12_RESOURCE_STATE_GENERIC_READ; - case(FFX_RESOURCE_STATE_UNORDERED_ACCESS): + case (FFX_RESOURCE_STATE_UNORDERED_ACCESS): return D3D12_RESOURCE_STATE_UNORDERED_ACCESS; case (FFX_RESOURCE_STATE_PIXEL_COMPUTE_READ): return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - case(FFX_RESOURCE_STATE_COMPUTE_READ): + case (FFX_RESOURCE_STATE_COMPUTE_READ): return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; case (FFX_RESOURCE_STATE_PIXEL_READ): return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; @@ -310,6 +329,12 @@ D3D12_RESOURCE_STATES ffxGetDX12StateFromResourceState(FfxResourceStates state) return D3D12_RESOURCE_STATE_COPY_DEST; case FFX_RESOURCE_STATE_INDIRECT_ARGUMENT: return D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT; + case FFX_RESOURCE_STATE_PRESENT: + return D3D12_RESOURCE_STATE_PRESENT; + case FFX_RESOURCE_STATE_COMMON: + return D3D12_RESOURCE_STATE_COMMON; + case FFX_RESOURCE_STATE_RENDER_TARGET: + return D3D12_RESOURCE_STATE_RENDER_TARGET; default: FFX_ASSERT_MESSAGE(false, "Resource state not yet supported"); return D3D12_RESOURCE_STATE_COMMON; @@ -320,43 +345,53 @@ DXGI_FORMAT ffxGetDX12FormatFromSurfaceFormat(FfxSurfaceFormat surfaceFormat) { switch (surfaceFormat) { - case(FFX_SURFACE_FORMAT_R32G32B32A32_TYPELESS): + case (FFX_SURFACE_FORMAT_R32G32B32A32_TYPELESS): return DXGI_FORMAT_R32G32B32A32_TYPELESS; - case(FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT): + case (FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT): return DXGI_FORMAT_R32G32B32A32_FLOAT; - case(FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT): + case (FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT): return DXGI_FORMAT_R16G16B16A16_FLOAT; - case(FFX_SURFACE_FORMAT_R32G32_FLOAT): + case (FFX_SURFACE_FORMAT_R32G32_FLOAT): return DXGI_FORMAT_R32G32_FLOAT; - case(FFX_SURFACE_FORMAT_R32_UINT): + case (FFX_SURFACE_FORMAT_R32_UINT): return DXGI_FORMAT_R32_UINT; - case(FFX_SURFACE_FORMAT_R8G8B8A8_TYPELESS): + case(FFX_SURFACE_FORMAT_R10G10B10A2_UNORM): + return DXGI_FORMAT_R10G10B10A2_UNORM; + case (FFX_SURFACE_FORMAT_R8G8B8A8_TYPELESS): return DXGI_FORMAT_R8G8B8A8_TYPELESS; - case(FFX_SURFACE_FORMAT_R8G8B8A8_UNORM): + case (FFX_SURFACE_FORMAT_R8G8B8A8_UNORM): return DXGI_FORMAT_R8G8B8A8_UNORM; - case(FFX_SURFACE_FORMAT_R8G8B8A8_SNORM): + case (FFX_SURFACE_FORMAT_R8G8B8A8_SRGB): + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + case (FFX_SURFACE_FORMAT_R8G8B8A8_SNORM): return DXGI_FORMAT_R8G8B8A8_SNORM; - case(FFX_SURFACE_FORMAT_R11G11B10_FLOAT): + case (FFX_SURFACE_FORMAT_R11G11B10_FLOAT): return DXGI_FORMAT_R11G11B10_FLOAT; - case(FFX_SURFACE_FORMAT_R16G16_FLOAT): + case (FFX_SURFACE_FORMAT_R16G16_FLOAT): return DXGI_FORMAT_R16G16_FLOAT; - case(FFX_SURFACE_FORMAT_R16G16_UINT): + case (FFX_SURFACE_FORMAT_R16G16_UINT): return DXGI_FORMAT_R16G16_UINT; - case(FFX_SURFACE_FORMAT_R16_FLOAT): + case (FFX_SURFACE_FORMAT_R16G16_SINT): + return DXGI_FORMAT_R16G16_SINT; + case (FFX_SURFACE_FORMAT_R16_FLOAT): return DXGI_FORMAT_R16_FLOAT; - case(FFX_SURFACE_FORMAT_R16_UINT): + case (FFX_SURFACE_FORMAT_R16_UINT): return DXGI_FORMAT_R16_UINT; - case(FFX_SURFACE_FORMAT_R16_UNORM): + case (FFX_SURFACE_FORMAT_R16_UNORM): return DXGI_FORMAT_R16_UNORM; - case(FFX_SURFACE_FORMAT_R16_SNORM): + case (FFX_SURFACE_FORMAT_R16_SNORM): return DXGI_FORMAT_R16_SNORM; - case(FFX_SURFACE_FORMAT_R8_UNORM): + case (FFX_SURFACE_FORMAT_R8_UNORM): return DXGI_FORMAT_R8_UNORM; - case(FFX_SURFACE_FORMAT_R8G8_UNORM): + case (FFX_SURFACE_FORMAT_R8_UINT): + return DXGI_FORMAT_R8_UINT; + case (FFX_SURFACE_FORMAT_R8G8_UINT): + return DXGI_FORMAT_R8G8_UINT; + case (FFX_SURFACE_FORMAT_R8G8_UNORM): return DXGI_FORMAT_R8G8_UNORM; - case(FFX_SURFACE_FORMAT_R32_FLOAT): + case (FFX_SURFACE_FORMAT_R32_FLOAT): return DXGI_FORMAT_R32_FLOAT; - case(FFX_SURFACE_FORMAT_UNKNOWN): + case (FFX_SURFACE_FORMAT_UNKNOWN): return DXGI_FORMAT_UNKNOWN; default: @@ -381,39 +416,107 @@ FfxSurfaceFormat ffxGetSurfaceFormatDX12(DXGI_FORMAT format) return FFX_SURFACE_FORMAT_R32G32B32A32_TYPELESS; case(DXGI_FORMAT_R32G32B32A32_FLOAT): return FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT; + case DXGI_FORMAT_R32G32B32A32_UINT: + return FFX_SURFACE_FORMAT_R32G32B32A32_UINT; + //case DXGI_FORMAT_R32G32B32A32_SINT: + //case DXGI_FORMAT_R32G32B32_TYPELESS: + //case DXGI_FORMAT_R32G32B32_FLOAT: + //case DXGI_FORMAT_R32G32B32_UINT: + //case DXGI_FORMAT_R32G32B32_SINT: + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: case(DXGI_FORMAT_R16G16B16A16_FLOAT): return FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT; - case(DXGI_FORMAT_R32G32_FLOAT): + //case DXGI_FORMAT_R16G16B16A16_UNORM: + //case DXGI_FORMAT_R16G16B16A16_UINT: + //case DXGI_FORMAT_R16G16B16A16_SNORM: + //case DXGI_FORMAT_R16G16B16A16_SINT: + + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: return FFX_SURFACE_FORMAT_R32G32_FLOAT; - case(DXGI_FORMAT_R32_UINT): - return FFX_SURFACE_FORMAT_R32_UINT; - case(DXGI_FORMAT_D32_FLOAT): - case(DXGI_FORMAT_R32_FLOAT): + //case DXGI_FORMAT_R32G32_FLOAT: + //case DXGI_FORMAT_R32G32_UINT: + //case DXGI_FORMAT_R32G32_SINT: + + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: return FFX_SURFACE_FORMAT_R32_FLOAT; - case(DXGI_FORMAT_R8G8B8A8_TYPELESS): + + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + return FFX_SURFACE_FORMAT_R32_UINT; + + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + return FFX_SURFACE_FORMAT_R8_UINT; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + return FFX_SURFACE_FORMAT_R10G10B10A2_UNORM; + //case DXGI_FORMAT_R10G10B10A2_UINT: + + case (DXGI_FORMAT_R11G11B10_FLOAT): + return FFX_SURFACE_FORMAT_R11G11B10_FLOAT; + + case (DXGI_FORMAT_R8G8B8A8_TYPELESS): return FFX_SURFACE_FORMAT_R8G8B8A8_TYPELESS; - case(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB): - return FFX_SURFACE_FORMAT_R8G8B8A8_SRGB; - case(DXGI_FORMAT_R8G8B8A8_UNORM): + case (DXGI_FORMAT_R8G8B8A8_UNORM): return FFX_SURFACE_FORMAT_R8G8B8A8_UNORM; - case(DXGI_FORMAT_R11G11B10_FLOAT): - return FFX_SURFACE_FORMAT_R11G11B10_FLOAT; - case(DXGI_FORMAT_R16G16_FLOAT): + case (DXGI_FORMAT_R8G8B8A8_UNORM_SRGB): + return FFX_SURFACE_FORMAT_R8G8B8A8_SRGB; + //case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + return FFX_SURFACE_FORMAT_R8G8B8A8_SNORM; + + case DXGI_FORMAT_R16G16_TYPELESS: + case (DXGI_FORMAT_R16G16_FLOAT): return FFX_SURFACE_FORMAT_R16G16_FLOAT; - case(DXGI_FORMAT_R16G16_UINT): + //case DXGI_FORMAT_R16G16_UNORM: + case (DXGI_FORMAT_R16G16_UINT): return FFX_SURFACE_FORMAT_R16G16_UINT; - case(DXGI_FORMAT_R16_FLOAT): + //case DXGI_FORMAT_R16G16_SNORM + //case DXGI_FORMAT_R16G16_SINT + + //case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R32_UINT: + return FFX_SURFACE_FORMAT_R32_UINT; + case DXGI_FORMAT_R32_TYPELESS: + case(DXGI_FORMAT_D32_FLOAT): + case(DXGI_FORMAT_R32_FLOAT): + return FFX_SURFACE_FORMAT_R32_FLOAT; + + case DXGI_FORMAT_R8G8_TYPELESS: + case (DXGI_FORMAT_R8G8_UINT): + return FFX_SURFACE_FORMAT_R8G8_UINT; + //case DXGI_FORMAT_R8G8_UNORM: + //case DXGI_FORMAT_R8G8_SNORM: + //case DXGI_FORMAT_R8G8_SINT: + + case DXGI_FORMAT_R16_TYPELESS: + case (DXGI_FORMAT_R16_FLOAT): return FFX_SURFACE_FORMAT_R16_FLOAT; - case(DXGI_FORMAT_R16_UINT): + case (DXGI_FORMAT_R16_UINT): return FFX_SURFACE_FORMAT_R16_UINT; - case(DXGI_FORMAT_R16_UNORM): + case DXGI_FORMAT_D16_UNORM: + case (DXGI_FORMAT_R16_UNORM): return FFX_SURFACE_FORMAT_R16_UNORM; - case(DXGI_FORMAT_R16_SNORM): + case (DXGI_FORMAT_R16_SNORM): return FFX_SURFACE_FORMAT_R16_SNORM; - case(DXGI_FORMAT_R8_UNORM): + //case DXGI_FORMAT_R16_SINT: + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_A8_UNORM: return FFX_SURFACE_FORMAT_R8_UNORM; - case(DXGI_FORMAT_R8_UINT): + case DXGI_FORMAT_R8_UINT: return FFX_SURFACE_FORMAT_R8_UINT; + //case DXGI_FORMAT_R8_SNORM: + //case DXGI_FORMAT_R8_SINT: + //case DXGI_FORMAT_R1_UNORM: + case(DXGI_FORMAT_UNKNOWN): return FFX_SURFACE_FORMAT_UNKNOWN; default: @@ -422,6 +525,81 @@ FfxSurfaceFormat ffxGetSurfaceFormatDX12(DXGI_FORMAT format) } } +bool IsDepthDX12(DXGI_FORMAT format) +{ + return (format == DXGI_FORMAT_D16_UNORM) || + (format == DXGI_FORMAT_D32_FLOAT) || + (format == DXGI_FORMAT_D24_UNORM_S8_UINT) || + (format == DXGI_FORMAT_D32_FLOAT_S8X24_UINT); +} + +FfxResourceDescription GetFfxResourceDescriptionDX12(ID3D12Resource* pResource) +{ + FfxResourceDescription resourceDescription = {}; + + // This is valid + if (!pResource) + return resourceDescription; + + if (pResource) + { + D3D12_RESOURCE_DESC desc = pResource->GetDesc(); + + if( desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + resourceDescription.flags = FFX_RESOURCE_FLAGS_NONE; + resourceDescription.usage = FFX_RESOURCE_USAGE_UAV; + resourceDescription.width = (uint32_t)desc.Width; + resourceDescription.height = (uint32_t)desc.Height; + resourceDescription.format = ffxGetSurfaceFormatDX12(desc.Format); + + // What should we initialize this to?? No case for this yet + resourceDescription.depth = 0; + resourceDescription.mipCount = 0; + + // Set the type + resourceDescription.type = FFX_RESOURCE_TYPE_BUFFER; + } + else + { + // Set flags properly for resource registration + resourceDescription.flags = FFX_RESOURCE_FLAGS_NONE; + resourceDescription.usage = IsDepthDX12(desc.Format) ? FFX_RESOURCE_USAGE_DEPTHTARGET : FFX_RESOURCE_USAGE_READ_ONLY; + if ((desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) == D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) + resourceDescription.usage = (FfxResourceUsage)(resourceDescription.usage | FFX_RESOURCE_USAGE_UAV); + + resourceDescription.width = (uint32_t)desc.Width; + resourceDescription.height = (uint32_t)desc.Height; + resourceDescription.depth = desc.DepthOrArraySize; + resourceDescription.mipCount = desc.MipLevels; + resourceDescription.format = ffxGetSurfaceFormatDX12(desc.Format); + + switch (desc.Dimension) + { + case D3D12_RESOURCE_DIMENSION_TEXTURE1D: + resourceDescription.type = FFX_RESOURCE_TYPE_TEXTURE1D; + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE2D: + if (desc.DepthOrArraySize == 1) + resourceDescription.type = FFX_RESOURCE_TYPE_TEXTURE2D; + else if (desc.DepthOrArraySize == 6) + resourceDescription.type = FFX_RESOURCE_TYPE_TEXTURE_CUBE; + else + resourceDescription.type = FFX_RESOURCE_TYPE_TEXTURE2D; + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + resourceDescription.type = FFX_RESOURCE_TYPE_TEXTURE3D; + break; + default: + FFX_ASSERT_MESSAGE(false, "FFXInterface: Cauldron: Unsupported texture dimension requested. Please implement."); + break; + } + } + } + + return resourceDescription; +} + ID3D12Resource* getDX12ResourcePtr(BackendContext_DX12* backendContext, int32_t resourceIndex) { FFX_ASSERT(NULL != backendContext); @@ -491,10 +669,9 @@ FfxErrorCode CreateBackendContextDX12(FfxInterface* backendInterface, FfxUInt32* BackendContext_DX12* backendContext = (BackendContext_DX12*)backendInterface->scratchBuffer; // Set things up if this is the first invocation - if (!s_BackendRefCount) { + if (!backendContext->refCount) { - // Clear everything out - memset(backendContext, 0, sizeof(*backendContext)); + new (&backendContext->constantBufferMutex) std::mutex(); if (dx12Device != NULL) { @@ -503,9 +680,9 @@ FfxErrorCode CreateBackendContextDX12(FfxInterface* backendInterface, FfxUInt32* } // Map all of our pointers - uint32_t gpuJobDescArraySize = FFX_ALIGN_UP(s_MaxEffectContexts * FFX_MAX_GPU_JOBS * sizeof(FfxGpuJobDescription), sizeof(uint32_t)); - uint32_t resourceArraySize = FFX_ALIGN_UP(s_MaxEffectContexts * FFX_MAX_RESOURCE_COUNT * sizeof(BackendContext_DX12::Resource), sizeof(uint64_t)); - uint32_t contextArraySize = FFX_ALIGN_UP(s_MaxEffectContexts * sizeof(BackendContext_DX12::EffectContext), sizeof(uint32_t)); + uint32_t gpuJobDescArraySize = FFX_ALIGN_UP(backendContext->maxEffectContexts * FFX_MAX_GPU_JOBS * sizeof(FfxGpuJobDescription), sizeof(uint32_t)); + uint32_t resourceArraySize = FFX_ALIGN_UP(backendContext->maxEffectContexts * FFX_MAX_RESOURCE_COUNT * sizeof(BackendContext_DX12::Resource), sizeof(uint64_t)); + uint32_t contextArraySize = FFX_ALIGN_UP(backendContext->maxEffectContexts * sizeof(BackendContext_DX12::EffectContext), sizeof(uint32_t)); uint8_t* pMem = (uint8_t*)((BackendContext_DX12*)(backendContext + 1)); // Map gpu job array @@ -524,7 +701,7 @@ FfxErrorCode CreateBackendContextDX12(FfxInterface* backendInterface, FfxUInt32* // CPUVisible D3D12_DESCRIPTOR_HEAP_DESC descHeap; - descHeap.NumDescriptors = FFX_MAX_RESOURCE_COUNT * s_MaxEffectContexts; + descHeap.NumDescriptors = FFX_MAX_RESOURCE_COUNT * backendContext->maxEffectContexts; descHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; descHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; descHeap.NodeMask = 0; @@ -537,17 +714,26 @@ FfxErrorCode CreateBackendContextDX12(FfxInterface* backendInterface, FfxUInt32* result = dx12Device->CreateDescriptorHeap(&descHeap, IID_PPV_ARGS(&backendContext->descHeapUavGpu)); // descriptor ring buffer - descHeap.NumDescriptors = FFX_RING_BUFFER_SIZE * s_MaxEffectContexts; + descHeap.NumDescriptors = FFX_RING_BUFFER_SIZE * backendContext->maxEffectContexts; backendContext->descRingBufferSize = descHeap.NumDescriptors; backendContext->descRingBufferBase = 0; result = dx12Device->CreateDescriptorHeap(&descHeap, IID_PPV_ARGS(&backendContext->descRingBuffer)); + // RTV descriptor heap to raster jobs + descHeap.NumDescriptors = 8; + descHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + descHeap.NodeMask = 0; + descHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + dx12Device->CreateDescriptorHeap(&descHeap, IID_PPV_ARGS(&backendContext->descHeapRtvCpu)); + + std::lock_guard cbLock{backendContext->constantBufferMutex}; // create dynamic ring buffer for constant uploads backendContext->constantBufferSize = FFX_ALIGN_UP(FFX_MAX_CONST_SIZE, 256) * - s_MaxEffectContexts * FFX_MAX_PASS_COUNT * FFX_MAX_QUEUED_FRAMES; // Size aligned to 256 + backendContext->maxEffectContexts * FFX_MAX_PASS_COUNT * FFX_MAX_QUEUED_FRAMES; // Size aligned to 256 CD3DX12_RESOURCE_DESC constDesc = CD3DX12_RESOURCE_DESC::Buffer(backendContext->constantBufferSize); - TIF(dx12Device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, + CD3DX12_HEAP_PROPERTIES heap(D3D12_HEAP_TYPE_UPLOAD); + TIF(dx12Device->CreateCommittedResource(&heap, D3D12_HEAP_FLAG_NONE, &constDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&backendContext->constantBufferResource))); backendContext->constantBufferResource->SetName(L"FFX_DX12_DynamicRingBuffer"); @@ -559,10 +745,10 @@ FfxErrorCode CreateBackendContextDX12(FfxInterface* backendInterface, FfxUInt32* } // Increment the ref count - ++s_BackendRefCount; + ++backendContext->refCount; // Get an available context id - for (size_t i = 0; i < s_MaxEffectContexts; ++i) { + for (uint32_t i = 0; i < backendContext->maxEffectContexts; ++i) { if (!backendContext->pEffectContexts[i].active) { *effectContextId = i; @@ -669,14 +855,15 @@ FfxErrorCode DestroyBackendContextDX12(FfxInterface* backendInterface, FfxUInt32 { FFX_ASSERT(NULL != backendInterface); BackendContext_DX12* backendContext = (BackendContext_DX12*)backendInterface->scratchBuffer; + FFX_ASSERT(backendContext->refCount > 0); // Delete any resources allocated by this context BackendContext_DX12::EffectContext& effectContext = backendContext->pEffectContexts[effectContextId]; - for (int32_t currentStaticResourceIndex = effectContextId * FFX_MAX_RESOURCE_COUNT; currentStaticResourceIndex < effectContext.nextStaticResource; ++currentStaticResourceIndex) { + for (uint32_t currentStaticResourceIndex = effectContextId * FFX_MAX_RESOURCE_COUNT; currentStaticResourceIndex < (uint32_t)effectContext.nextStaticResource; ++currentStaticResourceIndex) { if (backendContext->pResources[currentStaticResourceIndex].resourcePtr) { FFX_ASSERT_MESSAGE(false, "FFXInterface: DX12: SDK Resource was not destroyed prior to destroying the backend context. There is a resource leak."); - FfxResourceInternal internalResource = { currentStaticResourceIndex }; - DestroyResourceDX12(backendInterface, internalResource); + FfxResourceInternal internalResource = { (int32_t)currentStaticResourceIndex }; + DestroyResourceDX12(backendInterface, internalResource, effectContextId); } } @@ -685,18 +872,21 @@ FfxErrorCode DestroyBackendContextDX12(FfxInterface* backendInterface, FfxUInt32 effectContext.active = false; // Decrement ref count - --s_BackendRefCount; + --backendContext->refCount; - if (!s_BackendRefCount) { + if (!backendContext->refCount) { // release constant buffer pool backendContext->constantBufferResource->Unmap(0, nullptr); backendContext->constantBufferResource->Release(); - backendContext->constantBufferMem = nullptr; - backendContext->constantBufferOffset = 0; - backendContext->constantBufferSize = 0; + backendContext->constantBufferMem = nullptr; + backendContext->constantBufferOffset = 0; + backendContext->constantBufferSize = 0; + backendContext->gpuJobCount = 0; + backendContext->barrierCount = 0; // release heaps + backendContext->descHeapRtvCpu->Release(); backendContext->descHeapSrvCpu->Release(); backendContext->descHeapUavCpu->Release(); backendContext->descHeapUavGpu->Release(); @@ -823,7 +1013,7 @@ FfxErrorCode CreateResourceDX12( uint8_t* dst = static_cast(uploadBufferData); for (uint32_t currentRowIndex = 0; currentRowIndex < createResourceDescription->resourceDescription.height; ++currentRowIndex) { - memcpy(dst, src, rowSizeInBytes); + memcpy(dst, src, (size_t)rowSizeInBytes); src += rowSizeInBytes; dst += dx12Footprint.Footprint.RowPitch; } @@ -1035,19 +1225,73 @@ FfxErrorCode CreateResourceDX12( FfxErrorCode DestroyResourceDX12( FfxInterface* backendInterface, - FfxResourceInternal resource) + FfxResourceInternal resource, + FfxUInt32 effectContextId) { FFX_ASSERT(NULL != backendInterface); BackendContext_DX12* backendContext = (BackendContext_DX12*)backendInterface->scratchBuffer; - ID3D12Resource* dx12Resource = getDX12ResourcePtr(backendContext, resource.internalIndex); + BackendContext_DX12::EffectContext& effectContext = backendContext->pEffectContexts[effectContextId]; + if ((resource.internalIndex >= int32_t(effectContextId * FFX_MAX_RESOURCE_COUNT)) && (resource.internalIndex < int32_t(effectContext.nextStaticResource))) { + ID3D12Resource* dx12Resource = getDX12ResourcePtr(backendContext, resource.internalIndex); + + if (dx12Resource) { + dx12Resource->Release(); + backendContext->pResources[resource.internalIndex].resourcePtr = nullptr; + } + + return FFX_OK; + } - if (dx12Resource) { - dx12Resource->Release(); - backendContext->pResources[resource.internalIndex].resourcePtr = nullptr; - } + return FFX_ERROR_OUT_OF_RANGE; +} - return FFX_OK; +DXGI_FORMAT patchDxgiFormatWithFfxUsage(DXGI_FORMAT dxResFmt, FfxSurfaceFormat ffxFmt) +{ + DXGI_FORMAT fromFfx = ffxGetDX12FormatFromSurfaceFormat(ffxFmt); + DXGI_FORMAT fmt = dxResFmt; + + switch (fmt) + { + // fixup typeless formats with what is passed in the ffxSurfaceFormat + case DXGI_FORMAT_UNKNOWN: + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + return fromFfx; + + // fixup RGBA8 with SRGB flag passed in the ffxSurfaceFormat + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return fromFfx; + + // fixup depth formats as ffxGetDX12FormatFromSurfaceFormat will result in wrong format + case DXGI_FORMAT_D32_FLOAT: + return DXGI_FORMAT_R32_FLOAT; + + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; + + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + + case DXGI_FORMAT_D16_UNORM: + return DXGI_FORMAT_R16_UNORM; + + default: + break; + } + return fmt; } FfxErrorCode RegisterResourceDX12( @@ -1093,10 +1337,14 @@ FfxErrorCode RegisterResourceDX12( D3D12_UNORDERED_ACCESS_VIEW_DESC dx12UavDescription = {}; D3D12_SHADER_RESOURCE_VIEW_DESC dx12SrvDescription = {}; D3D12_RESOURCE_DESC dx12Desc = dx12Resource->GetDesc(); - dx12UavDescription.Format = convertFormatUav(dx12Desc.Format); + + // we still want to respect the format provided in the description for SRGB or TYPELESS resources + DXGI_FORMAT descFormat = patchDxgiFormatWithFfxUsage(dx12Desc.Format, inFfxResource->description.format); + + dx12UavDescription.Format = convertFormatUav(descFormat); // Will support something other than this only where there is an actual need for it dx12SrvDescription.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - dx12SrvDescription.Format = convertFormatSrv(dx12Desc.Format); + dx12SrvDescription.Format = convertFormatSrv(descFormat); bool requestArrayView = FFX_CONTAINS_FLAG(inFfxResource->description.usage, FFX_RESOURCE_USAGE_ARRAYVIEW); @@ -1207,6 +1455,7 @@ FfxErrorCode RegisterResourceDX12( backendResource->uavDescCount = 1; backendResource->uavDescIndex = effectContext.nextDynamicUavDescriptor--; + dx12UavDescription.Format = DXGI_FORMAT_UNKNOWN; dx12UavDescription.Buffer.FirstElement = 0; dx12UavDescription.Buffer.StructureByteStride = backendResource->resourceDescription.stride; dx12UavDescription.Buffer.NumElements = backendResource->resourceDescription.size / backendResource->resourceDescription.stride; @@ -1226,7 +1475,7 @@ FfxErrorCode RegisterResourceDX12( dx12SrvDescription.Buffer.StructureByteStride = backendResource->resourceDescription.stride; dx12SrvDescription.Buffer.NumElements = backendResource->resourceDescription.size / backendResource->resourceDescription.stride; D3D12_CPU_DESCRIPTOR_HANDLE dx12CpuHandle = backendContext->descHeapSrvCpu->GetCPUDescriptorHandleForHeapStart(); - dx12CpuHandle.ptr = outFfxResourceInternal->internalIndex * dx12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + dx12CpuHandle.ptr += outFfxResourceInternal->internalIndex * dx12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); dx12Device->CreateShaderResourceView(dx12Resource, &dx12SrvDescription, dx12CpuHandle); backendResource->srvDescIndex = outFfxResourceInternal->internalIndex; } @@ -1383,251 +1632,603 @@ FfxErrorCode CreatePipelineDX12( BackendContext_DX12* backendContext = (BackendContext_DX12*)backendInterface->scratchBuffer; ID3D12Device* dx12Device = backendContext->device; - FfxShaderBlob shaderBlob = { }; - ffxGetPermutationBlobByIndex(effect, pass, permutationOptions, &shaderBlob); - FFX_ASSERT(shaderBlob.data && shaderBlob.size); - - // set up root signature - // easiest implementation: simply create one root signature per pipeline - // should add some management later on to avoid unnecessarily re-binding the root signature + if (pipelineDescription->stage == FfxBindStage(FFX_BIND_VERTEX_SHADER_STAGE | FFX_BIND_PIXEL_SHADER_STAGE)) { - FFX_ASSERT(pipelineDescription->samplerCount <= FFX_MAX_SAMPLERS); - const size_t samplerCount = pipelineDescription->samplerCount; - D3D12_STATIC_SAMPLER_DESC dx12SamplerDescriptions[FFX_MAX_SAMPLERS]; - for (uint32_t currentSamplerIndex = 0; currentSamplerIndex < samplerCount; ++currentSamplerIndex) { - - D3D12_STATIC_SAMPLER_DESC dx12SamplerDesc = {}; - - dx12SamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; - dx12SamplerDesc.MinLOD = 0.f; - dx12SamplerDesc.MaxLOD = D3D12_FLOAT32_MAX; - dx12SamplerDesc.MipLODBias = 0.f; - dx12SamplerDesc.MaxAnisotropy = 16; - dx12SamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; - dx12SamplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - dx12SamplerDesc.AddressU = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeU); - dx12SamplerDesc.AddressV = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeV); - dx12SamplerDesc.AddressW = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeW); - - switch (pipelineDescription->samplers[currentSamplerIndex].filter) + // create rasterPipeline + FfxShaderBlob shaderBlobVS = {}; + backendInterface->fpGetPermutationBlobByIndex(effect, pass, FFX_BIND_VERTEX_SHADER_STAGE, permutationOptions, &shaderBlobVS); + FFX_ASSERT(shaderBlobVS.data && shaderBlobVS.size); + + FfxShaderBlob shaderBlobPS = {}; + backendInterface->fpGetPermutationBlobByIndex(effect, pass, FFX_BIND_PIXEL_SHADER_STAGE, permutationOptions, &shaderBlobPS); + FFX_ASSERT(shaderBlobPS.data && shaderBlobPS.size); + + { + // set up root signature + // easiest implementation: simply create one root signature per pipeline + // should add some management later on to avoid unnecessarily re-binding the root signature { - case FFX_FILTER_TYPE_MINMAGMIP_POINT: - dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; - break; - case FFX_FILTER_TYPE_MINMAGMIP_LINEAR: - dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; - break; - case FFX_FILTER_TYPE_MINMAGLINEARMIP_POINT: - dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; - break; + FFX_ASSERT(pipelineDescription->samplerCount <= FFX_MAX_SAMPLERS); + const size_t samplerCount = pipelineDescription->samplerCount; + D3D12_STATIC_SAMPLER_DESC dx12SamplerDescriptions[FFX_MAX_SAMPLERS]; + for (uint32_t currentSamplerIndex = 0; currentSamplerIndex < samplerCount; ++currentSamplerIndex) + { + D3D12_STATIC_SAMPLER_DESC dx12SamplerDesc = {}; + + dx12SamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + dx12SamplerDesc.MinLOD = 0.f; + dx12SamplerDesc.MaxLOD = D3D12_FLOAT32_MAX; + dx12SamplerDesc.MipLODBias = 0.f; + dx12SamplerDesc.MaxAnisotropy = 16; + dx12SamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + dx12SamplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + dx12SamplerDesc.AddressU = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeU); + dx12SamplerDesc.AddressV = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeV); + dx12SamplerDesc.AddressW = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeW); + + switch (pipelineDescription->samplers[currentSamplerIndex].filter) + { + case FFX_FILTER_TYPE_MINMAGMIP_POINT: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + break; + case FFX_FILTER_TYPE_MINMAGMIP_LINEAR: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + break; + case FFX_FILTER_TYPE_MINMAGLINEARMIP_POINT: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; + break; - default: - FFX_ASSERT_MESSAGE(false, "Unsupported filter type requested. Please implement"); - break; + default: + FFX_ASSERT_MESSAGE(false, "Unsupported filter type requested. Please implement"); + break; + } + + dx12SamplerDescriptions[currentSamplerIndex] = dx12SamplerDesc; + dx12SamplerDescriptions[currentSamplerIndex].ShaderRegister = (UINT)currentSamplerIndex; + } + + // storage for maximum number of descriptor ranges. + const int32_t maximumDescriptorRangeSize = 2; + D3D12_DESCRIPTOR_RANGE dx12Ranges[maximumDescriptorRangeSize] = {}; + int32_t currentDescriptorRangeIndex = 0; + + // storage for maximum number of root parameters. + const int32_t maximumRootParameters = 10; + D3D12_ROOT_PARAMETER dx12RootParameters[maximumRootParameters] = {}; + int32_t currentRootParameterIndex = 0; + + // Allocate a max of binding slots + int32_t uavCount = shaderBlobVS.uavBufferCount || shaderBlobVS.uavTextureCount || shaderBlobVS.uavBufferCount || shaderBlobVS.uavTextureCount + ? FFX_MAX_RESOURCE_IDENTIFIER_COUNT + : 0; + int32_t srvCount = shaderBlobVS.srvBufferCount || shaderBlobVS.srvTextureCount || shaderBlobPS.srvBufferCount || shaderBlobPS.srvTextureCount + ? FFX_MAX_RESOURCE_IDENTIFIER_COUNT + : 0; + if (uavCount > 0) + { + FFX_ASSERT(currentDescriptorRangeIndex < maximumDescriptorRangeSize); + D3D12_DESCRIPTOR_RANGE* dx12DescriptorRange = &dx12Ranges[currentDescriptorRangeIndex]; + memset(dx12DescriptorRange, 0, sizeof(D3D12_DESCRIPTOR_RANGE)); + dx12DescriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + dx12DescriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + dx12DescriptorRange->BaseShaderRegister = 0; + dx12DescriptorRange->NumDescriptors = uavCount; + currentDescriptorRangeIndex++; + + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* dx12RootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(dx12RootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + dx12RootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + dx12RootParameterSlot->DescriptorTable.NumDescriptorRanges = 1; + currentRootParameterIndex++; + } + + if (srvCount > 0) + { + FFX_ASSERT(currentDescriptorRangeIndex < maximumDescriptorRangeSize); + D3D12_DESCRIPTOR_RANGE* dx12DescriptorRange = &dx12Ranges[currentDescriptorRangeIndex]; + memset(dx12DescriptorRange, 0, sizeof(D3D12_DESCRIPTOR_RANGE)); + dx12DescriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + dx12DescriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + dx12DescriptorRange->BaseShaderRegister = 0; + dx12DescriptorRange->NumDescriptors = srvCount; + currentDescriptorRangeIndex++; + + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* dx12RootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(dx12RootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + dx12RootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + dx12RootParameterSlot->DescriptorTable.NumDescriptorRanges = 1; + currentRootParameterIndex++; + } + + // Setup the descriptor table bindings for the above + for (int32_t currentRangeIndex = 0; currentRangeIndex < currentDescriptorRangeIndex; currentRangeIndex++) + { + dx12RootParameters[currentRangeIndex].DescriptorTable.pDescriptorRanges = &dx12Ranges[currentRangeIndex]; + } + + // Setup root constants as push constants for dx12 + FFX_ASSERT(pipelineDescription->rootConstantBufferCount <= FFX_MAX_NUM_CONST_BUFFERS); + size_t rootConstantsSize = pipelineDescription->rootConstantBufferCount; + uint32_t rootConstants[FFX_MAX_NUM_CONST_BUFFERS]; + + for (uint32_t currentRootConstantIndex = 0; currentRootConstantIndex < pipelineDescription->rootConstantBufferCount; ++currentRootConstantIndex) + { + rootConstants[currentRootConstantIndex] = pipelineDescription->rootConstants[currentRootConstantIndex].size; + } + + for (int32_t currentRootConstantIndex = 0; currentRootConstantIndex < (int32_t)pipelineDescription->rootConstantBufferCount; + currentRootConstantIndex++) + { + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* rootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(rootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + rootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParameterSlot->Constants.ShaderRegister = currentRootConstantIndex; + currentRootParameterIndex++; + } + + D3D12_ROOT_SIGNATURE_DESC dx12RootSignatureDescription = {}; + dx12RootSignatureDescription.NumParameters = currentRootParameterIndex; + dx12RootSignatureDescription.pParameters = dx12RootParameters; + dx12RootSignatureDescription.NumStaticSamplers = (UINT)samplerCount; + dx12RootSignatureDescription.pStaticSamplers = dx12SamplerDescriptions; + + ID3DBlob* outBlob = nullptr; + ID3DBlob* errorBlob = nullptr; + + //Query D3D12SerializeRootSignature from d3d12.dll handle + typedef HRESULT(__stdcall * D3D12SerializeRootSignatureType)( + const D3D12_ROOT_SIGNATURE_DESC*, D3D_ROOT_SIGNATURE_VERSION, ID3DBlob**, ID3DBlob**); + + //Do not pass hD3D12 handle to the FreeLibrary function, as GetModuleHandle will not increment refcount + HMODULE d3d12ModuleHandle = GetModuleHandleW(L"D3D12.dll"); + + if (NULL != d3d12ModuleHandle) + { + D3D12SerializeRootSignatureType dx12SerializeRootSignatureType = + (D3D12SerializeRootSignatureType)GetProcAddress(d3d12ModuleHandle, "D3D12SerializeRootSignature"); + + if (nullptr != dx12SerializeRootSignatureType) + { + HRESULT result = dx12SerializeRootSignatureType(&dx12RootSignatureDescription, D3D_ROOT_SIGNATURE_VERSION_1, &outBlob, &errorBlob); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + + size_t blobSize = outBlob->GetBufferSize(); + int64_t* blobData = (int64_t*)outBlob->GetBufferPointer(); + + result = dx12Device->CreateRootSignature(0, + outBlob->GetBufferPointer(), + outBlob->GetBufferSize(), + IID_PPV_ARGS(reinterpret_cast(&outPipeline->rootSignature))); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + return FFX_ERROR_BACKEND_API_ERROR; + } } - dx12SamplerDescriptions[currentSamplerIndex] = dx12SamplerDesc; - dx12SamplerDescriptions[currentSamplerIndex].ShaderRegister = (UINT)currentSamplerIndex; - } + ID3D12RootSignature* dx12RootSignature = reinterpret_cast(outPipeline->rootSignature); - // storage for maximum number of descriptor ranges. - const int32_t maximumDescriptorRangeSize = 2; - D3D12_DESCRIPTOR_RANGE dx12Ranges[maximumDescriptorRangeSize] = {}; - int32_t currentDescriptorRangeIndex = 0; - - // storage for maximum number of root parameters. - const int32_t maximumRootParameters = 10; - D3D12_ROOT_PARAMETER dx12RootParameters[maximumRootParameters] = {}; - int32_t currentRootParameterIndex = 0; - - // Allocate a max of binding slots - int32_t uavCount = shaderBlob.uavBufferCount || shaderBlob.uavTextureCount ? FFX_MAX_RESOURCE_IDENTIFIER_COUNT : 0; - int32_t srvCount = shaderBlob.srvBufferCount || shaderBlob.srvTextureCount ? FFX_MAX_RESOURCE_IDENTIFIER_COUNT : 0; - if (uavCount > 0) { - - FFX_ASSERT(currentDescriptorRangeIndex < maximumDescriptorRangeSize); - D3D12_DESCRIPTOR_RANGE* dx12DescriptorRange = &dx12Ranges[currentDescriptorRangeIndex]; - memset(dx12DescriptorRange, 0, sizeof(D3D12_DESCRIPTOR_RANGE)); - dx12DescriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - dx12DescriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; - dx12DescriptorRange->BaseShaderRegister = 0; - dx12DescriptorRange->NumDescriptors = uavCount; - currentDescriptorRangeIndex++; - - FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); - D3D12_ROOT_PARAMETER* dx12RootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; - memset(dx12RootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); - dx12RootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - dx12RootParameterSlot->DescriptorTable.NumDescriptorRanges = 1; - currentRootParameterIndex++; - } + // Only set the command signature if this is setup as an indirect workload + if (pipelineDescription->indirectWorkload) + { + D3D12_INDIRECT_ARGUMENT_DESC argumentDescs = {D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH}; + D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc = {}; + commandSignatureDesc.pArgumentDescs = &argumentDescs; + commandSignatureDesc.NumArgumentDescs = 1; + commandSignatureDesc.ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS); + + HRESULT result = dx12Device->CreateCommandSignature( + &commandSignatureDesc, nullptr, IID_PPV_ARGS(reinterpret_cast(&outPipeline->cmdSignature))); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + outPipeline->cmdSignature = nullptr; + } - if (srvCount > 0) { - - FFX_ASSERT(currentDescriptorRangeIndex < maximumDescriptorRangeSize); - D3D12_DESCRIPTOR_RANGE* dx12DescriptorRange = &dx12Ranges[currentDescriptorRangeIndex]; - memset(dx12DescriptorRange, 0, sizeof(D3D12_DESCRIPTOR_RANGE)); - dx12DescriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - dx12DescriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - dx12DescriptorRange->BaseShaderRegister = 0; - dx12DescriptorRange->NumDescriptors = srvCount; - currentDescriptorRangeIndex++; - - FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); - D3D12_ROOT_PARAMETER* dx12RootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; - memset(dx12RootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); - dx12RootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - dx12RootParameterSlot->DescriptorTable.NumDescriptorRanges = 1; - currentRootParameterIndex++; - } + FFX_ASSERT(shaderBlobVS.srvTextureCount + shaderBlobVS.srvBufferCount + shaderBlobPS.srvTextureCount + shaderBlobPS.srvBufferCount <= + FFX_MAX_NUM_SRVS); + FFX_ASSERT(shaderBlobVS.uavTextureCount + shaderBlobVS.uavBufferCount + shaderBlobPS.uavTextureCount + shaderBlobPS.uavBufferCount <= + FFX_MAX_NUM_UAVS); + FFX_ASSERT(shaderBlobVS.cbvCount + shaderBlobPS.cbvCount <= FFX_MAX_NUM_CONST_BUFFERS); + + // populate the pass. + outPipeline->srvTextureCount = shaderBlobVS.srvTextureCount + shaderBlobPS.srvTextureCount; + outPipeline->uavTextureCount = shaderBlobVS.uavTextureCount + shaderBlobPS.uavTextureCount; + outPipeline->srvBufferCount = shaderBlobVS.srvBufferCount + shaderBlobPS.srvBufferCount; + outPipeline->uavBufferCount = shaderBlobVS.uavBufferCount + shaderBlobPS.uavBufferCount; + outPipeline->constCount = shaderBlobVS.cbvCount + shaderBlobPS.cbvCount; + + // Todo when needed + //outPipeline->samplerCount = shaderBlob.samplerCount; + //outPipeline->rtAccelStructCount= shaderBlob.rtAccelStructCount; + + std::wstring_convert> converter; + uint32_t srvIndex = 0; + for (uint32_t vsSrvIndex = 0; vsSrvIndex < shaderBlobVS.srvTextureCount; ++vsSrvIndex) + { + outPipeline->srvTextureBindings[srvIndex].slotIndex = shaderBlobVS.boundSRVTextures[vsSrvIndex]; + outPipeline->srvTextureBindings[srvIndex].bindCount = shaderBlobVS.boundSRVTextureCounts[vsSrvIndex]; + wcscpy_s(outPipeline->srvTextureBindings[srvIndex].name, converter.from_bytes(shaderBlobVS.boundSRVTextureNames[vsSrvIndex]).c_str()); + ++srvIndex; + } + for (uint32_t psSrvIndex = 0; psSrvIndex < shaderBlobPS.srvTextureCount; ++psSrvIndex) + { + outPipeline->srvTextureBindings[srvIndex].slotIndex = shaderBlobPS.boundSRVTextures[psSrvIndex]; + outPipeline->srvTextureBindings[srvIndex].bindCount = shaderBlobPS.boundSRVTextureCounts[psSrvIndex]; + wcscpy_s(outPipeline->srvTextureBindings[srvIndex].name, converter.from_bytes(shaderBlobPS.boundSRVTextureNames[psSrvIndex]).c_str()); + ++srvIndex; + } - // Setup the descriptor table bindings for the above - for (int32_t currentRangeIndex = 0; currentRangeIndex < currentDescriptorRangeIndex; currentRangeIndex++) { + uint32_t uavIndex = 0; + for (uint32_t vsUavIndex = 0; vsUavIndex < shaderBlobVS.uavTextureCount; ++vsUavIndex) + { + outPipeline->uavTextureBindings[uavIndex].slotIndex = shaderBlobVS.boundUAVTextures[vsUavIndex]; + outPipeline->uavTextureBindings[uavIndex].bindCount = shaderBlobVS.boundUAVTextureCounts[vsUavIndex]; + wcscpy_s(outPipeline->uavTextureBindings[uavIndex].name, converter.from_bytes(shaderBlobVS.boundUAVTextureNames[vsUavIndex]).c_str()); + ++uavIndex; + } + for (uint32_t psUavIndex = 0; psUavIndex < shaderBlobPS.uavTextureCount; ++psUavIndex) + { + outPipeline->uavTextureBindings[uavIndex].slotIndex = shaderBlobPS.boundUAVTextures[psUavIndex]; + outPipeline->uavTextureBindings[uavIndex].bindCount = shaderBlobPS.boundUAVTextureCounts[psUavIndex]; + wcscpy_s(outPipeline->uavTextureBindings[uavIndex].name, converter.from_bytes(shaderBlobPS.boundUAVTextureNames[psUavIndex]).c_str()); + ++uavIndex; + } - dx12RootParameters[currentRangeIndex].DescriptorTable.pDescriptorRanges = &dx12Ranges[currentRangeIndex]; + uint32_t srvBufferIndex = 0; + for (uint32_t vsSrvIndex = 0; vsSrvIndex < shaderBlobVS.srvBufferCount; ++vsSrvIndex) + { + outPipeline->srvBufferBindings[srvBufferIndex].slotIndex = shaderBlobVS.boundSRVBuffers[vsSrvIndex]; + outPipeline->srvBufferBindings[srvBufferIndex].bindCount = shaderBlobVS.boundSRVBufferCounts[vsSrvIndex]; + wcscpy_s(outPipeline->srvBufferBindings[srvBufferIndex].name, converter.from_bytes(shaderBlobVS.boundSRVBufferNames[vsSrvIndex]).c_str()); + ++srvBufferIndex; + } + for (uint32_t psSrvIndex = 0; psSrvIndex < shaderBlobPS.srvBufferCount; ++psSrvIndex) + { + outPipeline->srvBufferBindings[srvBufferIndex].slotIndex = shaderBlobPS.boundSRVBuffers[psSrvIndex]; + outPipeline->srvBufferBindings[srvBufferIndex].bindCount = shaderBlobPS.boundSRVBufferCounts[psSrvIndex]; + wcscpy_s(outPipeline->srvBufferBindings[srvBufferIndex].name, converter.from_bytes(shaderBlobPS.boundSRVBufferNames[psSrvIndex]).c_str()); + ++srvBufferIndex; + } + + uint32_t uavBufferIndex = 0; + for (uint32_t vsUavIndex = 0; vsUavIndex < shaderBlobVS.uavBufferCount; ++vsUavIndex) + { + outPipeline->uavBufferBindings[uavBufferIndex].slotIndex = shaderBlobVS.boundUAVBuffers[vsUavIndex]; + outPipeline->uavBufferBindings[uavBufferIndex].bindCount = shaderBlobVS.boundUAVBufferCounts[vsUavIndex]; + wcscpy_s(outPipeline->uavBufferBindings[uavBufferIndex].name, converter.from_bytes(shaderBlobVS.boundUAVBufferNames[vsUavIndex]).c_str()); + ++uavBufferIndex; + } + for (uint32_t psUavIndex = 0; psUavIndex < shaderBlobPS.uavBufferCount; ++psUavIndex) + { + outPipeline->uavBufferBindings[uavBufferIndex].slotIndex = shaderBlobPS.boundUAVBuffers[psUavIndex]; + outPipeline->uavBufferBindings[uavBufferIndex].bindCount = shaderBlobPS.boundUAVBufferCounts[psUavIndex]; + wcscpy_s(outPipeline->uavBufferBindings[uavBufferIndex].name, converter.from_bytes(shaderBlobPS.boundUAVBufferNames[psUavIndex]).c_str()); + ++uavBufferIndex; + } + + uint32_t cbIndex = 0; + for (uint32_t vsCbIndex = 0; vsCbIndex < shaderBlobVS.cbvCount; ++vsCbIndex) + { + outPipeline->constantBufferBindings[cbIndex].slotIndex = shaderBlobVS.boundConstantBuffers[vsCbIndex]; + outPipeline->constantBufferBindings[cbIndex].bindCount = shaderBlobVS.boundConstantBufferCounts[vsCbIndex]; + wcscpy_s(outPipeline->constantBufferBindings[cbIndex].name, converter.from_bytes(shaderBlobVS.boundConstantBufferNames[vsCbIndex]).c_str()); + ++cbIndex; + } + for (uint32_t psCbIndex = 0; psCbIndex < shaderBlobPS.cbvCount; ++psCbIndex) + { + outPipeline->constantBufferBindings[cbIndex].slotIndex = shaderBlobPS.boundConstantBuffers[psCbIndex]; + outPipeline->constantBufferBindings[cbIndex].bindCount = shaderBlobPS.boundConstantBufferCounts[psCbIndex]; + wcscpy_s(outPipeline->constantBufferBindings[cbIndex].name, converter.from_bytes(shaderBlobPS.boundConstantBufferNames[psCbIndex]).c_str()); + ++cbIndex; + } } - // Setup root constants as push constants for dx12 - FFX_ASSERT(pipelineDescription->rootConstantBufferCount <= FFX_MAX_NUM_CONST_BUFFERS); - size_t rootConstantsSize = pipelineDescription->rootConstantBufferCount; - uint32_t rootConstants[FFX_MAX_NUM_CONST_BUFFERS]; + ID3D12RootSignature* dx12RootSignature = reinterpret_cast(outPipeline->rootSignature); + + FfxSurfaceFormat ffxBackbufferFmt = pipelineDescription->backbufferFormat; + + // create the PSO + D3D12_GRAPHICS_PIPELINE_STATE_DESC dx12PipelineStateDescription = {}; + dx12PipelineStateDescription.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + dx12PipelineStateDescription.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + dx12PipelineStateDescription.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + dx12PipelineStateDescription.DepthStencilState.DepthEnable = FALSE; + dx12PipelineStateDescription.SampleMask = UINT_MAX; + dx12PipelineStateDescription.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + dx12PipelineStateDescription.SampleDesc = {1, 0}; + dx12PipelineStateDescription.NumRenderTargets = 1; + dx12PipelineStateDescription.RTVFormats[0] = ffxGetDX12FormatFromSurfaceFormat(ffxBackbufferFmt); + + dx12PipelineStateDescription.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + dx12PipelineStateDescription.pRootSignature = dx12RootSignature; + dx12PipelineStateDescription.VS.pShaderBytecode = shaderBlobVS.data; + dx12PipelineStateDescription.VS.BytecodeLength = shaderBlobVS.size; + dx12PipelineStateDescription.PS.pShaderBytecode = shaderBlobPS.data; + dx12PipelineStateDescription.PS.BytecodeLength = shaderBlobPS.size; + + if (FAILED(dx12Device->CreateGraphicsPipelineState(&dx12PipelineStateDescription, + IID_PPV_ARGS(reinterpret_cast(&outPipeline->pipeline))))) + return FFX_ERROR_BACKEND_API_ERROR; - for (uint32_t currentRootConstantIndex = 0; currentRootConstantIndex < pipelineDescription->rootConstantBufferCount; ++currentRootConstantIndex) { + } + else + { + FfxShaderBlob shaderBlob = {}; + backendInterface->fpGetPermutationBlobByIndex(effect, pass, FFX_BIND_COMPUTE_SHADER_STAGE, permutationOptions, &shaderBlob); + FFX_ASSERT(shaderBlob.data&& shaderBlob.size); - rootConstants[currentRootConstantIndex] = pipelineDescription->rootConstants[currentRootConstantIndex].size; - } + // set up root signature + // easiest implementation: simply create one root signature per pipeline + // should add some management later on to avoid unnecessarily re-binding the root signature + { + FFX_ASSERT(pipelineDescription->samplerCount <= FFX_MAX_SAMPLERS); + const size_t samplerCount = pipelineDescription->samplerCount; + D3D12_STATIC_SAMPLER_DESC dx12SamplerDescriptions[FFX_MAX_SAMPLERS]; + for (uint32_t currentSamplerIndex = 0; currentSamplerIndex < samplerCount; ++currentSamplerIndex) + { + D3D12_STATIC_SAMPLER_DESC dx12SamplerDesc = {}; + + dx12SamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + dx12SamplerDesc.MinLOD = 0.f; + dx12SamplerDesc.MaxLOD = D3D12_FLOAT32_MAX; + dx12SamplerDesc.MipLODBias = 0.f; + dx12SamplerDesc.MaxAnisotropy = 16; + dx12SamplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + dx12SamplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + dx12SamplerDesc.AddressU = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeU); + dx12SamplerDesc.AddressV = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeV); + dx12SamplerDesc.AddressW = FfxGetAddressModeDX12(pipelineDescription->samplers[currentSamplerIndex].addressModeW); + + switch (pipelineDescription->samplers[currentSamplerIndex].filter) + { + case FFX_FILTER_TYPE_MINMAGMIP_POINT: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + break; + case FFX_FILTER_TYPE_MINMAGMIP_LINEAR: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + break; + case FFX_FILTER_TYPE_MINMAGLINEARMIP_POINT: + dx12SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; + break; + + default: + FFX_ASSERT_MESSAGE(false, "Unsupported filter type requested. Please implement"); + break; + } - for (int32_t currentRootConstantIndex = 0; currentRootConstantIndex < (int32_t)pipelineDescription->rootConstantBufferCount; currentRootConstantIndex++) { + dx12SamplerDescriptions[currentSamplerIndex] = dx12SamplerDesc; + dx12SamplerDescriptions[currentSamplerIndex].ShaderRegister = (UINT)currentSamplerIndex; + } - FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); - D3D12_ROOT_PARAMETER* rootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; - memset(rootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); - rootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; - rootParameterSlot->Constants.ShaderRegister = currentRootConstantIndex; - currentRootParameterIndex++; - } + // storage for maximum number of descriptor ranges. + const int32_t maximumDescriptorRangeSize = 2; + D3D12_DESCRIPTOR_RANGE dx12Ranges[maximumDescriptorRangeSize] = {}; + int32_t currentDescriptorRangeIndex = 0; - D3D12_ROOT_SIGNATURE_DESC dx12RootSignatureDescription = {}; - dx12RootSignatureDescription.NumParameters = currentRootParameterIndex; - dx12RootSignatureDescription.pParameters = dx12RootParameters; - dx12RootSignatureDescription.NumStaticSamplers = (UINT)samplerCount; - dx12RootSignatureDescription.pStaticSamplers = dx12SamplerDescriptions; + // storage for maximum number of root parameters. + const int32_t maximumRootParameters = 10; + D3D12_ROOT_PARAMETER dx12RootParameters[maximumRootParameters] = {}; + int32_t currentRootParameterIndex = 0; - ID3DBlob* outBlob = nullptr; - ID3DBlob* errorBlob = nullptr; + // Allocate a max of binding slots + int32_t uavCount = shaderBlob.uavBufferCount || shaderBlob.uavTextureCount ? FFX_MAX_RESOURCE_IDENTIFIER_COUNT : 0; + int32_t srvCount = shaderBlob.srvBufferCount || shaderBlob.srvTextureCount ? FFX_MAX_RESOURCE_IDENTIFIER_COUNT : 0; + if (uavCount > 0) + { + FFX_ASSERT(currentDescriptorRangeIndex < maximumDescriptorRangeSize); + D3D12_DESCRIPTOR_RANGE* dx12DescriptorRange = &dx12Ranges[currentDescriptorRangeIndex]; + memset(dx12DescriptorRange, 0, sizeof(D3D12_DESCRIPTOR_RANGE)); + dx12DescriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + dx12DescriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + dx12DescriptorRange->BaseShaderRegister = 0; + dx12DescriptorRange->NumDescriptors = uavCount; + currentDescriptorRangeIndex++; + + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* dx12RootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(dx12RootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + dx12RootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + dx12RootParameterSlot->DescriptorTable.NumDescriptorRanges = 1; + currentRootParameterIndex++; + } - //Query D3D12SerializeRootSignature from d3d12.dll handle - typedef HRESULT(__stdcall* D3D12SerializeRootSignatureType)(const D3D12_ROOT_SIGNATURE_DESC*, D3D_ROOT_SIGNATURE_VERSION, ID3DBlob**, ID3DBlob**); + if (srvCount > 0) + { + FFX_ASSERT(currentDescriptorRangeIndex < maximumDescriptorRangeSize); + D3D12_DESCRIPTOR_RANGE* dx12DescriptorRange = &dx12Ranges[currentDescriptorRangeIndex]; + memset(dx12DescriptorRange, 0, sizeof(D3D12_DESCRIPTOR_RANGE)); + dx12DescriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + dx12DescriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + dx12DescriptorRange->BaseShaderRegister = 0; + dx12DescriptorRange->NumDescriptors = srvCount; + currentDescriptorRangeIndex++; + + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* dx12RootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(dx12RootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + dx12RootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + dx12RootParameterSlot->DescriptorTable.NumDescriptorRanges = 1; + currentRootParameterIndex++; + } - //Do not pass hD3D12 handle to the FreeLibrary function, as GetModuleHandle will not increment refcount - HMODULE d3d12ModuleHandle = GetModuleHandleW(L"D3D12.dll"); + // Setup the descriptor table bindings for the above + for (int32_t currentRangeIndex = 0; currentRangeIndex < currentDescriptorRangeIndex; currentRangeIndex++) + { + dx12RootParameters[currentRangeIndex].DescriptorTable.pDescriptorRanges = &dx12Ranges[currentRangeIndex]; + } - if (NULL != d3d12ModuleHandle) { + // Setup root constants as push constants for dx12 + FFX_ASSERT(pipelineDescription->rootConstantBufferCount <= FFX_MAX_NUM_CONST_BUFFERS); + size_t rootConstantsSize = pipelineDescription->rootConstantBufferCount; + uint32_t rootConstants[FFX_MAX_NUM_CONST_BUFFERS]; - D3D12SerializeRootSignatureType dx12SerializeRootSignatureType = (D3D12SerializeRootSignatureType)GetProcAddress(d3d12ModuleHandle, "D3D12SerializeRootSignature"); + for (uint32_t currentRootConstantIndex = 0; currentRootConstantIndex < pipelineDescription->rootConstantBufferCount; ++currentRootConstantIndex) + { + rootConstants[currentRootConstantIndex] = pipelineDescription->rootConstants[currentRootConstantIndex].size; + } - if (nullptr != dx12SerializeRootSignatureType) { + for (int32_t currentRootConstantIndex = 0; currentRootConstantIndex < (int32_t)pipelineDescription->rootConstantBufferCount; + currentRootConstantIndex++) + { + FFX_ASSERT(currentRootParameterIndex < maximumRootParameters); + D3D12_ROOT_PARAMETER* rootParameterSlot = &dx12RootParameters[currentRootParameterIndex]; + memset(rootParameterSlot, 0, sizeof(D3D12_ROOT_PARAMETER)); + rootParameterSlot->ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParameterSlot->Constants.ShaderRegister = currentRootConstantIndex; + currentRootParameterIndex++; + } - HRESULT result = dx12SerializeRootSignatureType(&dx12RootSignatureDescription, D3D_ROOT_SIGNATURE_VERSION_1, &outBlob, &errorBlob); - if (FAILED(result)) { + D3D12_ROOT_SIGNATURE_DESC dx12RootSignatureDescription = {}; + dx12RootSignatureDescription.NumParameters = currentRootParameterIndex; + dx12RootSignatureDescription.pParameters = dx12RootParameters; + dx12RootSignatureDescription.NumStaticSamplers = (UINT)samplerCount; + dx12RootSignatureDescription.pStaticSamplers = dx12SamplerDescriptions; - return FFX_ERROR_BACKEND_API_ERROR; - } + ID3DBlob* outBlob = nullptr; + ID3DBlob* errorBlob = nullptr; - size_t blobSize = outBlob->GetBufferSize(); - int64_t* blobData = (int64_t*)outBlob->GetBufferPointer(); + //Query D3D12SerializeRootSignature from d3d12.dll handle + typedef HRESULT(__stdcall * D3D12SerializeRootSignatureType)(const D3D12_ROOT_SIGNATURE_DESC*, D3D_ROOT_SIGNATURE_VERSION, ID3DBlob**, ID3DBlob**); - result = dx12Device->CreateRootSignature(0, outBlob->GetBufferPointer(), outBlob->GetBufferSize(), IID_PPV_ARGS(reinterpret_cast(&outPipeline->rootSignature))); - if (FAILED(result)) { + //Do not pass hD3D12 handle to the FreeLibrary function, as GetModuleHandle will not increment refcount + HMODULE d3d12ModuleHandle = GetModuleHandleW(L"D3D12.dll"); + if (NULL != d3d12ModuleHandle) + { + D3D12SerializeRootSignatureType dx12SerializeRootSignatureType = + (D3D12SerializeRootSignatureType)GetProcAddress(d3d12ModuleHandle, "D3D12SerializeRootSignature"); + + if (nullptr != dx12SerializeRootSignatureType) + { + HRESULT result = dx12SerializeRootSignatureType(&dx12RootSignatureDescription, D3D_ROOT_SIGNATURE_VERSION_1, &outBlob, &errorBlob); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + + size_t blobSize = outBlob->GetBufferSize(); + int64_t* blobData = (int64_t*)outBlob->GetBufferPointer(); + + result = dx12Device->CreateRootSignature(0, + outBlob->GetBufferPointer(), + outBlob->GetBufferSize(), + IID_PPV_ARGS(reinterpret_cast(&outPipeline->rootSignature))); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { return FFX_ERROR_BACKEND_API_ERROR; } - } else { + } + else + { return FFX_ERROR_BACKEND_API_ERROR; } - } else { - return FFX_ERROR_BACKEND_API_ERROR; } - } - - ID3D12RootSignature* dx12RootSignature = reinterpret_cast(outPipeline->rootSignature); - - // Only set the command signature if this is setup as an indirect workload - if (pipelineDescription->indirectWorkload) - { - D3D12_INDIRECT_ARGUMENT_DESC argumentDescs = { D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH }; - D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc = {}; - commandSignatureDesc.pArgumentDescs = &argumentDescs; - commandSignatureDesc.NumArgumentDescs = 1; - commandSignatureDesc.ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS); - HRESULT result = dx12Device->CreateCommandSignature(&commandSignatureDesc, nullptr, IID_PPV_ARGS(reinterpret_cast(&outPipeline->cmdSignature))); - if (FAILED(result)) { + ID3D12RootSignature* dx12RootSignature = reinterpret_cast(outPipeline->rootSignature); - return FFX_ERROR_BACKEND_API_ERROR; + // Only set the command signature if this is setup as an indirect workload + if (pipelineDescription->indirectWorkload) + { + D3D12_INDIRECT_ARGUMENT_DESC argumentDescs = {D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH}; + D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc = {}; + commandSignatureDesc.pArgumentDescs = &argumentDescs; + commandSignatureDesc.NumArgumentDescs = 1; + commandSignatureDesc.ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS); + + HRESULT result = dx12Device->CreateCommandSignature( + &commandSignatureDesc, nullptr, IID_PPV_ARGS(reinterpret_cast(&outPipeline->cmdSignature))); + if (FAILED(result)) + { + return FFX_ERROR_BACKEND_API_ERROR; + } + } + else + { + outPipeline->cmdSignature = nullptr; } - } - else - { - outPipeline->cmdSignature = nullptr; - } - // populate the pass. - outPipeline->srvTextureCount = shaderBlob.srvTextureCount; - outPipeline->uavTextureCount = shaderBlob.uavTextureCount; - outPipeline->srvBufferCount = shaderBlob.srvBufferCount; - outPipeline->uavBufferCount = shaderBlob.uavBufferCount; + // populate the pass. + outPipeline->srvTextureCount = shaderBlob.srvTextureCount; + outPipeline->uavTextureCount = shaderBlob.uavTextureCount; + outPipeline->srvBufferCount = shaderBlob.srvBufferCount; + outPipeline->uavBufferCount = shaderBlob.uavBufferCount; - // Todo when needed - //outPipeline->samplerCount = shaderBlob.samplerCount; - //outPipeline->rtAccelStructCount= shaderBlob.rtAccelStructCount; + // Todo when needed + //outPipeline->samplerCount = shaderBlob.samplerCount; + //outPipeline->rtAccelStructCount= shaderBlob.rtAccelStructCount; - outPipeline->constCount = shaderBlob.cbvCount; - std::wstring_convert> converter; - for (uint32_t srvIndex = 0; srvIndex < outPipeline->srvTextureCount; ++srvIndex) - { - outPipeline->srvTextureBindings[srvIndex].slotIndex = shaderBlob.boundSRVTextures[srvIndex]; - outPipeline->srvTextureBindings[srvIndex].bindCount = shaderBlob.boundSRVTextureCounts[srvIndex]; - wcscpy_s(outPipeline->srvTextureBindings[srvIndex].name, converter.from_bytes(shaderBlob.boundSRVTextureNames[srvIndex]).c_str()); - } - for (uint32_t uavIndex = 0; uavIndex < outPipeline->uavTextureCount; ++uavIndex) - { - outPipeline->uavTextureBindings[uavIndex].slotIndex = shaderBlob.boundUAVTextures[uavIndex]; - outPipeline->uavTextureBindings[uavIndex].bindCount = shaderBlob.boundUAVTextureCounts[uavIndex]; - wcscpy_s(outPipeline->uavTextureBindings[uavIndex].name, converter.from_bytes(shaderBlob.boundUAVTextureNames[uavIndex]).c_str()); - } - for (uint32_t srvIndex = 0; srvIndex < outPipeline->srvBufferCount; ++srvIndex) - { - outPipeline->srvBufferBindings[srvIndex].slotIndex = shaderBlob.boundSRVBuffers[srvIndex]; - outPipeline->srvBufferBindings[srvIndex].bindCount = shaderBlob.boundSRVBufferCounts[srvIndex]; - wcscpy_s(outPipeline->srvBufferBindings[srvIndex].name, converter.from_bytes(shaderBlob.boundSRVBufferNames[srvIndex]).c_str()); - } - for (uint32_t uavIndex = 0; uavIndex < outPipeline->uavBufferCount; ++uavIndex) - { - outPipeline->uavBufferBindings[uavIndex].slotIndex = shaderBlob.boundUAVBuffers[uavIndex]; - outPipeline->uavBufferBindings[uavIndex].bindCount = shaderBlob.boundUAVBufferCounts[uavIndex]; - wcscpy_s(outPipeline->uavBufferBindings[uavIndex].name, converter.from_bytes(shaderBlob.boundUAVBufferNames[uavIndex]).c_str()); - } - for (uint32_t cbIndex = 0; cbIndex < outPipeline->constCount; ++cbIndex) - { - outPipeline->constantBufferBindings[cbIndex].slotIndex = shaderBlob.boundConstantBuffers[cbIndex]; - outPipeline->constantBufferBindings[cbIndex].bindCount = shaderBlob.boundConstantBufferCounts[cbIndex]; - wcscpy_s(outPipeline->constantBufferBindings[cbIndex].name, converter.from_bytes(shaderBlob.boundConstantBufferNames[cbIndex]).c_str()); - } - - // create the PSO - D3D12_COMPUTE_PIPELINE_STATE_DESC dx12PipelineStateDescription = {}; - dx12PipelineStateDescription.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - dx12PipelineStateDescription.pRootSignature = dx12RootSignature; - dx12PipelineStateDescription.CS.pShaderBytecode = shaderBlob.data; - dx12PipelineStateDescription.CS.BytecodeLength = shaderBlob.size; + outPipeline->constCount = shaderBlob.cbvCount; + std::wstring_convert> converter; + for (uint32_t srvIndex = 0; srvIndex < outPipeline->srvTextureCount; ++srvIndex) + { + outPipeline->srvTextureBindings[srvIndex].slotIndex = shaderBlob.boundSRVTextures[srvIndex]; + outPipeline->srvTextureBindings[srvIndex].bindCount = shaderBlob.boundSRVTextureCounts[srvIndex]; + wcscpy_s(outPipeline->srvTextureBindings[srvIndex].name, converter.from_bytes(shaderBlob.boundSRVTextureNames[srvIndex]).c_str()); + } + for (uint32_t uavIndex = 0; uavIndex < outPipeline->uavTextureCount; ++uavIndex) + { + outPipeline->uavTextureBindings[uavIndex].slotIndex = shaderBlob.boundUAVTextures[uavIndex]; + outPipeline->uavTextureBindings[uavIndex].bindCount = shaderBlob.boundUAVTextureCounts[uavIndex]; + wcscpy_s(outPipeline->uavTextureBindings[uavIndex].name, converter.from_bytes(shaderBlob.boundUAVTextureNames[uavIndex]).c_str()); + } + for (uint32_t srvIndex = 0; srvIndex < outPipeline->srvBufferCount; ++srvIndex) + { + outPipeline->srvBufferBindings[srvIndex].slotIndex = shaderBlob.boundSRVBuffers[srvIndex]; + outPipeline->srvBufferBindings[srvIndex].bindCount = shaderBlob.boundSRVBufferCounts[srvIndex]; + wcscpy_s(outPipeline->srvBufferBindings[srvIndex].name, converter.from_bytes(shaderBlob.boundSRVBufferNames[srvIndex]).c_str()); + } + for (uint32_t uavIndex = 0; uavIndex < outPipeline->uavBufferCount; ++uavIndex) + { + outPipeline->uavBufferBindings[uavIndex].slotIndex = shaderBlob.boundUAVBuffers[uavIndex]; + outPipeline->uavBufferBindings[uavIndex].bindCount = shaderBlob.boundUAVBufferCounts[uavIndex]; + wcscpy_s(outPipeline->uavBufferBindings[uavIndex].name, converter.from_bytes(shaderBlob.boundUAVBufferNames[uavIndex]).c_str()); + } + for (uint32_t cbIndex = 0; cbIndex < outPipeline->constCount; ++cbIndex) + { + outPipeline->constantBufferBindings[cbIndex].slotIndex = shaderBlob.boundConstantBuffers[cbIndex]; + outPipeline->constantBufferBindings[cbIndex].bindCount = shaderBlob.boundConstantBufferCounts[cbIndex]; + wcscpy_s(outPipeline->constantBufferBindings[cbIndex].name, converter.from_bytes(shaderBlob.boundConstantBufferNames[cbIndex]).c_str()); + } - if (FAILED(dx12Device->CreateComputePipelineState(&dx12PipelineStateDescription, IID_PPV_ARGS(reinterpret_cast(&outPipeline->pipeline))))) - return FFX_ERROR_BACKEND_API_ERROR; + // create the PSO + D3D12_COMPUTE_PIPELINE_STATE_DESC dx12PipelineStateDescription = {}; + dx12PipelineStateDescription.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + dx12PipelineStateDescription.pRootSignature = dx12RootSignature; + dx12PipelineStateDescription.CS.pShaderBytecode = shaderBlob.data; + dx12PipelineStateDescription.CS.BytecodeLength = shaderBlob.size; - // Set the pipeline name - reinterpret_cast(outPipeline->pipeline)->SetName(pipelineDescription->name); + if (FAILED(dx12Device->CreateComputePipelineState(&dx12PipelineStateDescription, + IID_PPV_ARGS(reinterpret_cast(&outPipeline->pipeline))))) + return FFX_ERROR_BACKEND_API_ERROR; + // Set the pipeline name + reinterpret_cast(outPipeline->pipeline)->SetName(pipelineDescription->name); + } return FFX_OK; } @@ -1732,7 +2333,7 @@ static FfxErrorCode executeGpuJobCompute(BackendContext_DX12* backendContext, Ff if (maximumUavIndex) { // check if this fits into the ringbuffer, loop if not fitting - if (backendContext->descRingBufferBase + maximumUavIndex + 1 > FFX_RING_BUFFER_SIZE * s_MaxEffectContexts) + if (backendContext->descRingBufferBase + maximumUavIndex + 1 > FFX_RING_BUFFER_SIZE * backendContext->maxEffectContexts) backendContext->descRingBufferBase = 0; D3D12_GPU_DESCRIPTOR_HANDLE gpuView = dx12DescriptorHeap->GetGPUDescriptorHandleForHeapStart(); @@ -1813,7 +2414,7 @@ static FfxErrorCode executeGpuJobCompute(BackendContext_DX12* backendContext, Ff if (maximumSrvIndex) { // check if this fits into the ringbuffer, loop if not fitting - if (backendContext->descRingBufferBase + maximumSrvIndex + 1 > FFX_RING_BUFFER_SIZE * s_MaxEffectContexts) { + if (backendContext->descRingBufferBase + maximumSrvIndex + 1 > FFX_RING_BUFFER_SIZE * backendContext->maxEffectContexts) { backendContext->descRingBufferBase = 0; } @@ -1896,6 +2497,7 @@ static FfxErrorCode executeGpuJobCompute(BackendContext_DX12* backendContext, Ff // copy data to constant buffer and bind { + std::lock_guard cbLock{backendContext->constantBufferMutex}; for (uint32_t currentRootConstantIndex = 0; currentRootConstantIndex < job->computeJobDescriptor.pipeline.constCount; ++currentRootConstantIndex) { uint32_t size = FFX_ALIGN_UP(job->computeJobDescriptor.cbs[currentRootConstantIndex].num32BitEntries * sizeof(uint32_t), 256); @@ -1906,8 +2508,9 @@ static FfxErrorCode executeGpuJobCompute(BackendContext_DX12* backendContext, Ff void* pBuffer = (void*)((uint8_t*)(backendContext->constantBufferMem) + backendContext->constantBufferOffset); memcpy(pBuffer, job->computeJobDescriptor.cbs[currentRootConstantIndex].data, job->computeJobDescriptor.cbs[currentRootConstantIndex].num32BitEntries * sizeof(uint32_t)); + uint32_t slotIndex = job->computeJobDescriptor.pipeline.constantBufferBindings[currentRootConstantIndex].slotIndex; D3D12_GPU_VIRTUAL_ADDRESS bufferViewDesc = backendContext->constantBufferResource->GetGPUVirtualAddress() + backendContext->constantBufferOffset; - dx12CommandList->SetComputeRootConstantBufferView(descriptorTableIndex + currentRootConstantIndex, bufferViewDesc); + dx12CommandList->SetComputeRootConstantBufferView(descriptorTableIndex + slotIndex, bufferViewDesc); // update the offset backendContext->constantBufferOffset += size; @@ -1982,6 +2585,22 @@ static FfxErrorCode executeGpuJobCopy(BackendContext_DX12* backendContext, FfxGp return FFX_OK; } +static FfxErrorCode executeGpuJobBarrier(BackendContext_DX12* backendContext, FfxGpuJobDescription* job, ID3D12Device* dx12Device, ID3D12GraphicsCommandList* dx12CommandList) +{ + ID3D12Resource* dx12ResourceSrc = getDX12ResourcePtr(backendContext, job->barrierDescriptor.resource.internalIndex); + D3D12_RESOURCE_DESC dx12ResourceDescriptionSrc = dx12ResourceSrc->GetDesc(); + + addBarrier(backendContext, &job->barrierDescriptor.resource, job->barrierDescriptor.newState); + flushBarriers(backendContext, dx12CommandList); + + return FFX_OK; +} + +static FfxErrorCode executeGpuJobTimestamp(BackendContext_DX12* backendContext, FfxGpuJobDescription* job, ID3D12Device* dx12Device, ID3D12GraphicsCommandList* dx12CommandList) +{ + return FFX_OK; +} + static FfxErrorCode executeGpuJobClearFloat(BackendContext_DX12* backendContext, FfxGpuJobDescription* job, ID3D12Device* dx12Device, ID3D12GraphicsCommandList* dx12CommandList) { uint32_t idx = job->clearJobDescriptor.target.internalIndex; @@ -2000,8 +2619,12 @@ static FfxErrorCode executeGpuJobClearFloat(BackendContext_DX12* backendContext, addBarrier(backendContext, &job->clearJobDescriptor.target, FFX_RESOURCE_STATE_UNORDERED_ACCESS); flushBarriers(backendContext, dx12CommandList); - - dx12CommandList->ClearUnorderedAccessViewFloat(dx12GpuHandle, dx12CpuHandle, dx12Resource, job->clearJobDescriptor.color, 0, nullptr); + uint32_t clearColorAsUint[4]; + clearColorAsUint[0] = reinterpret_cast (job->clearJobDescriptor.color[0]); + clearColorAsUint[1] = reinterpret_cast (job->clearJobDescriptor.color[1]); + clearColorAsUint[2] = reinterpret_cast (job->clearJobDescriptor.color[2]); + clearColorAsUint[3] = reinterpret_cast (job->clearJobDescriptor.color[3]); + dx12CommandList->ClearUnorderedAccessViewUint(dx12GpuHandle, dx12CpuHandle, dx12Resource, clearColorAsUint, 0, nullptr); return FFX_OK; } @@ -2037,6 +2660,10 @@ FfxErrorCode ExecuteGpuJobsDX12( errorCode = executeGpuJobCompute(backendContext, GpuJob, dx12Device, dx12CommandList); break; + case FFX_GPU_JOB_BARRIER: + errorCode = executeGpuJobBarrier(backendContext, GpuJob, dx12Device, dx12CommandList); + break; + default: break; } @@ -2051,3 +2678,94 @@ FfxErrorCode ExecuteGpuJobsDX12( return FFX_OK; } + +FfxCommandQueue ffxGetCommandQueueDX12(ID3D12CommandQueue* pCommandQueue) +{ + FFX_ASSERT(nullptr != pCommandQueue); + return reinterpret_cast(pCommandQueue); +} + +FfxSwapchain ffxGetSwapchainDX12(IDXGISwapChain4* pSwapchain) +{ + FFX_ASSERT(nullptr != pSwapchain); + return reinterpret_cast(pSwapchain); +} + +IDXGISwapChain4* ffxGetDX12SwapchainPtr(FfxSwapchain ffxSwapchain) +{ + return reinterpret_cast(ffxSwapchain); +} + +#include +#include +#include "FrameInterpolationSwapchain/FrameInterpolationSwapchainDX12.h" + + +// fix up format in case resource passed to FSR2 was created as typeless +static DXGI_FORMAT convertFormat(DXGI_FORMAT format) +{ + switch (format) + { + // Handle Depth + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; + case DXGI_FORMAT_D32_FLOAT: + return DXGI_FORMAT_R32_FLOAT; + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + case DXGI_FORMAT_D16_UNORM: + return DXGI_FORMAT_R16_UNORM; + + // Handle color: assume FLOAT for 16 and 32 bit channels, else UNORM + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + case DXGI_FORMAT_R32G32B32_TYPELESS: + return DXGI_FORMAT_R32G32B32_FLOAT; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case DXGI_FORMAT_R32G32_TYPELESS: + return DXGI_FORMAT_R32G32_FLOAT; + case DXGI_FORMAT_R16G16_TYPELESS: + return DXGI_FORMAT_R16G16_FLOAT; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + return DXGI_FORMAT_R10G10B10A2_UNORM; + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + case DXGI_FORMAT_R32_TYPELESS: + return DXGI_FORMAT_R32_FLOAT; + case DXGI_FORMAT_R8G8_TYPELESS: + return DXGI_FORMAT_R8G8_UNORM; + case DXGI_FORMAT_R16_TYPELESS: + return DXGI_FORMAT_R16_FLOAT; + case DXGI_FORMAT_R8_TYPELESS: + return DXGI_FORMAT_R8_UNORM; + default: + return format; + } +} + +static DXGI_FORMAT sRgbFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + default: + return format; + } +} diff --git a/sdk/src/backends/dx12/shaders/blur/ffx_blur_pass.hlsl b/sdk/src/backends/dx12/shaders/blur/ffx_blur_pass.hlsl index 0867b546..82273637 100644 --- a/sdk/src/backends/dx12/shaders/blur/ffx_blur_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/blur/ffx_blur_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // BLUR pass // SRV 0 : BLUR_InputSrc : r_input_src // UAV 0 : BLUR_Output : rw_output diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_non_smart_half_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_non_smart_half_pass.hlsl index 33e20a94..d397a530 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_non_smart_half_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_non_smart_half_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_OUTPUT 8 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_non_smart_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_non_smart_pass.hlsl index 672f1cfd..566dec28 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_non_smart_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_non_smart_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_OUTPUT 8 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_pass.hlsl index 16b7923f..d7661ea3 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_apply_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_OUTPUT 8 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_clear_load_counter_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_clear_load_counter_pass.hlsl index 1505d945..d8bd25f4 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_clear_load_counter_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_clear_load_counter_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_UAV_LOAD_COUNTER 4 #define CACAO_BIND_CB_CACAO 0 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_1_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_1_pass.hlsl index 755dbbe6..e358d366 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_1_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_1_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_2_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_2_pass.hlsl index f3f2d79a..13c65133 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_2_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_2_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_3_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_3_pass.hlsl index 8025a6d0..d75d6e1a 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_3_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_3_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_4_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_4_pass.hlsl index 7fbe9335..decface1 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_4_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_4_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_5_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_5_pass.hlsl index 09c220e3..2ff01129 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_5_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_5_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_6_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_6_pass.hlsl index a7ae3b2b..0156c8b3 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_6_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_6_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_7_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_7_pass.hlsl index aae42a2b..3fbc4e9a 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_7_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_7_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_8_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_8_pass.hlsl index 2b652489..8cafad5e 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_8_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_edge_sensitive_blur_8_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 #define CACAO_BIND_UAV_SSAO_BUFFER_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_a_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_a_pass.hlsl index dbd870cf..ac1a2262 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_a_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_a_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PONG 3 #define CACAO_BIND_SRV_IMPORTANCE_MAP 4 #define CACAO_BIND_SRV_IMPORTANCE_MAP_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_b_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_b_pass.hlsl index 5d026206..6e12fb89 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_b_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_b_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PONG 3 #define CACAO_BIND_SRV_IMPORTANCE_MAP 4 #define CACAO_BIND_SRV_IMPORTANCE_MAP_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_pass.hlsl index 87564e76..527b55c0 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_importance_map_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_SSAO_BUFFER_PONG 3 #define CACAO_BIND_SRV_IMPORTANCE_MAP 4 #define CACAO_BIND_SRV_IMPORTANCE_MAP_PONG 7 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q0_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q0_pass.hlsl index 7e997b1d..6985dbda 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q0_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q0_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_LOAD_COUNTER 0 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_DEINTERLEAVED_NORMALS 2 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q1_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q1_pass.hlsl index 1331cfe6..a9cdbc10 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q1_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q1_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_LOAD_COUNTER 0 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_DEINTERLEAVED_NORMALS 2 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q2_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q2_pass.hlsl index b446a3e3..b7b770b7 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q2_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q2_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_LOAD_COUNTER 0 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_DEINTERLEAVED_NORMALS 2 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q3_base_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q3_base_pass.hlsl index 71f87c86..018b6e9b 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q3_base_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q3_base_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_LOAD_COUNTER 0 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_DEINTERLEAVED_NORMALS 2 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q3_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q3_pass.hlsl index 74345fe4..e60a5b49 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q3_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_generate_q3_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_LOAD_COUNTER 0 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_DEINTERLEAVED_NORMALS 2 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_and_mips_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_and_mips_pass.hlsl index 6876a7b6..1c1acaa5 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_and_mips_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_and_mips_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_half_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_half_pass.hlsl index 82340a3a..9dde3252 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_half_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_half_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_pass.hlsl index ad09d94a..387af5ae 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_depths_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_normals_from_input_normals_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_normals_from_input_normals_pass.hlsl index 2eec0b74..b93ed006 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_normals_from_input_normals_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_normals_from_input_normals_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_normals_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_normals_pass.hlsl index dda234c8..6d0e8ce9 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_normals_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_downsampled_normals_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_and_mips_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_and_mips_pass.hlsl index 1f54dc30..b94a5306 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_and_mips_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_and_mips_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_half_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_half_pass.hlsl index 50596765..0aeb24be 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_half_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_half_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_pass.hlsl index cdbcb57c..e5dfbc44 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_depths_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_normals_from_input_normals_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_normals_from_input_normals_pass.hlsl index 55032fd9..7cc13919 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_normals_from_input_normals_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_normals_from_input_normals_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_normals_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_normals_pass.hlsl index d1a504d4..ab0dba66 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_normals_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_prepare_native_normals_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_NORMAL_IN 6 #define CACAO_BIND_UAV_DEPTH_DOWNSAMPLED_MIPS 1 diff --git a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_upscale_bilateral_5x5_pass.hlsl b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_upscale_bilateral_5x5_pass.hlsl index e7bdad5e..dd84db1e 100644 --- a/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_upscale_bilateral_5x5_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cacao/ffx_cacao_upscale_bilateral_5x5_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define CACAO_BIND_SRV_DEPTH_IN 5 #define CACAO_BIND_SRV_DEINTERLEAVED_DEPTHS 1 #define CACAO_BIND_SRV_SSAO_BUFFER_PING 8 diff --git a/sdk/src/backends/dx12/shaders/cas/ffx_cas_sharpen_pass.hlsl b/sdk/src/backends/dx12/shaders/cas/ffx_cas_sharpen_pass.hlsl index 5178c6d3..b344dd1a 100644 --- a/sdk/src/backends/dx12/shaders/cas/ffx_cas_sharpen_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/cas/ffx_cas_sharpen_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // CAS pass // SRV 0 : CAS_InputColor : r_input_color // UAV 0 : CAS_OutputColor : rw__output_color diff --git a/sdk/src/backends/dx12/shaders/classifier/ffx_classifier_reflections_pass.hlsl b/sdk/src/backends/dx12/shaders/classifier/ffx_classifier_reflections_pass.hlsl index f09f2ac3..26b18e7b 100644 --- a/sdk/src/backends/dx12/shaders/classifier/ffx_classifier_reflections_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/classifier/ffx_classifier_reflections_pass.hlsl @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #define FFX_WAVE 1 #define CLASSIFIER_BIND_SRV_INPUT_NORMAL 0 diff --git a/sdk/src/backends/dx12/shaders/classifier/ffx_classifier_shadows_pass.hlsl b/sdk/src/backends/dx12/shaders/classifier/ffx_classifier_shadows_pass.hlsl index e5afdd1d..19e55b4a 100644 --- a/sdk/src/backends/dx12/shaders/classifier/ffx_classifier_shadows_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/classifier/ffx_classifier_shadows_pass.hlsl @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + // Classifier pass // CB 0 : cbClassifier // SRV 0 : CLASSIFIER_Depth : r_input_depth diff --git a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_0_pass.hlsl b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_0_pass.hlsl index 1eec1683..d385d77f 100644 --- a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_0_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_0_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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. + #define DENOISER_SHADOWS_BIND_SRV_DEPTH 0 #define DENOISER_SHADOWS_BIND_SRV_NORMAL 1 #define DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT 2 diff --git a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_1_pass.hlsl b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_1_pass.hlsl index a2cd9f81..e1fe9243 100644 --- a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_1_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_1_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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. + #define DENOISER_SHADOWS_BIND_SRV_DEPTH 0 #define DENOISER_SHADOWS_BIND_SRV_NORMAL 1 #define DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT 2 diff --git a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_2_pass.hlsl b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_2_pass.hlsl index 66e47dce..d0f3192b 100644 --- a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_2_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_filter_soft_shadows_2_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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. + #define DENOISER_SHADOWS_BIND_SRV_DEPTH 0 #define DENOISER_SHADOWS_BIND_SRV_NORMAL 1 #define DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT 2 diff --git a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_prefilter_reflections_pass.hlsl b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_prefilter_reflections_pass.hlsl index 3776cb4c..92910d81 100644 --- a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_prefilter_reflections_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_prefilter_reflections_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define DENOISER_BIND_SRV_INPUT_DEPTH_HIERARCHY 2 #define DENOISER_BIND_SRV_INPUT_NORMAL 4 #define DENOISER_BIND_SRV_RADIANCE 7 diff --git a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_prepare_shadow_mask_pass.hlsl b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_prepare_shadow_mask_pass.hlsl index 27079314..d82fba0d 100644 --- a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_prepare_shadow_mask_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_prepare_shadow_mask_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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. + #define FFX_WAVE 1 #define DENOISER_SHADOWS_BIND_SRV_INPUT_HIT_MASK_RESULTS 0 diff --git a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_reproject_reflections_pass.hlsl b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_reproject_reflections_pass.hlsl index 9fb572e1..d8605a5a 100644 --- a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_reproject_reflections_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_reproject_reflections_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define DENOISER_BIND_SRV_INPUT_DEPTH_HIERARCHY 2 #define DENOISER_BIND_SRV_INPUT_MOTION_VECTORS 3 #define DENOISER_BIND_SRV_INPUT_NORMAL 4 diff --git a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_resolve_temporal_reflections_pass.hlsl b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_resolve_temporal_reflections_pass.hlsl index 7f292af3..4328bf9e 100644 --- a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_resolve_temporal_reflections_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_resolve_temporal_reflections_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define DENOISER_BIND_SRV_RADIANCE 7 #define DENOISER_BIND_SRV_RADIANCE_HISTORY 8 #define DENOISER_BIND_SRV_VARIANCE 9 diff --git a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_shadows_tile_classification_pass.hlsl b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_shadows_tile_classification_pass.hlsl index 46a39aee..f4af2a80 100644 --- a/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_shadows_tile_classification_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/denoiser/ffx_denoiser_shadows_tile_classification_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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. + #define FFX_WAVE 1 #define DENOISER_SHADOWS_BIND_SRV_DEPTH 0 diff --git a/sdk/src/backends/dx12/shaders/dof/ffx_dof_blur_pass.hlsl b/sdk/src/backends/dx12/shaders/dof/ffx_dof_blur_pass.hlsl index a848cd2e..d3300ce9 100644 --- a/sdk/src/backends/dx12/shaders/dof/ffx_dof_blur_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/dof/ffx_dof_blur_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FFX_DOF_BIND_CB_DOF 0 #define FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR 0 #define FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS 1 diff --git a/sdk/src/backends/dx12/shaders/dof/ffx_dof_composite_pass.hlsl b/sdk/src/backends/dx12/shaders/dof/ffx_dof_composite_pass.hlsl index 69b9e3e1..65ad29c1 100644 --- a/sdk/src/backends/dx12/shaders/dof/ffx_dof_composite_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/dof/ffx_dof_composite_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FFX_DOF_BIND_CB_DOF 0 #if !FFX_DOF_OPTION_COMBINE_IN_PLACE diff --git a/sdk/src/backends/dx12/shaders/dof/ffx_dof_dilate_pass.hlsl b/sdk/src/backends/dx12/shaders/dof/ffx_dof_dilate_pass.hlsl index d620c262..81ac2f40 100644 --- a/sdk/src/backends/dx12/shaders/dof/ffx_dof_dilate_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/dof/ffx_dof_dilate_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FFX_DOF_BIND_CB_DOF 0 #define FFX_DOF_BIND_UAV_INTERNAL_RADIUS 0 #define FFX_DOF_BIND_UAV_INTERNAL_DILATED_RADIUS 1 diff --git a/sdk/src/backends/dx12/shaders/dof/ffx_dof_downsample_color_pass.hlsl b/sdk/src/backends/dx12/shaders/dof/ffx_dof_downsample_color_pass.hlsl index 443268e8..50917dd7 100644 --- a/sdk/src/backends/dx12/shaders/dof/ffx_dof_downsample_color_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/dof/ffx_dof_downsample_color_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FFX_DOF_BIND_CB_DOF 0 #define FFX_DOF_BIND_SRV_INPUT_COLOR 0 #define FFX_DOF_BIND_SRV_INPUT_DEPTH 1 diff --git a/sdk/src/backends/dx12/shaders/dof/ffx_dof_downsample_depth_pass.hlsl b/sdk/src/backends/dx12/shaders/dof/ffx_dof_downsample_depth_pass.hlsl index 79365bd3..d565fa88 100644 --- a/sdk/src/backends/dx12/shaders/dof/ffx_dof_downsample_depth_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/dof/ffx_dof_downsample_depth_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FFX_DOF_BIND_CB_DOF 0 #define FFX_DOF_BIND_SRV_INPUT_DEPTH 0 #define FFX_DOF_BIND_UAV_INTERNAL_RADIUS 0 diff --git a/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.hlsl b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.hlsl new file mode 100644 index 00000000..445cefdd --- /dev/null +++ b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass.hlsl @@ -0,0 +1,92 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_0 1 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_1 2 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_2 3 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_3 4 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_4 5 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_5 6 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_6 7 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_7 8 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_8 9 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_9 10 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_10 11 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_11 12 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_12 13 + +#define FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION 0 + +#ifdef FFX_HALF + #undef FFX_HALF + #define FFX_HALF 0 +#endif + +#include "frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h" +#include "frameinterpolation/ffx_frameinterpolation_common.h" + + +#define FI_BIND_CB_INPAINTING_PYRAMID 1 +cbuffer cbInpaintingPyramid : FFX_DECLARE_CB(FI_BIND_CB_INPAINTING_PYRAMID) +{ + FfxUInt32 mips; + FfxUInt32 numWorkGroups; + FfxUInt32x2 workGroupOffset; +} + +FfxUInt32 NumMips() +{ + return mips; +} +FfxUInt32 NumWorkGroups() +{ + return numWorkGroups; +} +FfxUInt32x2 WorkGroupOffset() +{ + return workGroupOffset; +} + +#include "frameinterpolation/ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid.h" + +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS +#define FFX_FRAMEINTERPOLATION_NUM_THREADS [numthreads(FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH, FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT, FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS + +FFX_FRAMEINTERPOLATION_NUM_THREADS +void CS(FfxUInt32x3 WorkGroupId : SV_GroupID, FfxUInt32 LocalThreadIndex : SV_GroupIndex) +{ + computeFrameinterpolationGameVectorFieldInpaintingPyramid(WorkGroupId, LocalThreadIndex); +} diff --git a/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.hlsl b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.hlsl new file mode 100644 index 00000000..b956f6b4 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid_pass.hlsl @@ -0,0 +1,90 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OUTPUT 0 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_0 1 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_1 2 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_2 3 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_3 4 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_4 5 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_5 6 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_6 7 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_7 8 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_8 9 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_9 10 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_10 11 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_11 12 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_12 13 + +#define FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION 0 + +#ifdef FFX_HALF + #undef FFX_HALF + #define FFX_HALF 0 +#endif + +#include "frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h" +#include "frameinterpolation/ffx_frameinterpolation_common.h" + +#define FI_BIND_CB_INPAINTING_PYRAMID 1 +cbuffer cbInpaintingPyramid : FFX_DECLARE_CB(FI_BIND_CB_INPAINTING_PYRAMID) +{ + FfxUInt32 mips; + FfxUInt32 numWorkGroups; + FfxUInt32x2 workGroupOffset; +} + +FfxUInt32 NumMips() +{ + return mips; +} +FfxUInt32 NumWorkGroups() +{ + return numWorkGroups; +} +FfxUInt32x2 WorkGroupOffset() +{ + return workGroupOffset; +} + +#include "frameinterpolation/ffx_frameinterpolation_compute_inpainting_pyramid.h" + +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS +#define FFX_FRAMEINTERPOLATION_NUM_THREADS [numthreads(FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH, FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT, FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS + +FFX_FRAMEINTERPOLATION_NUM_THREADS +void CS(FfxUInt32x3 WorkGroupId : SV_GroupID, FfxUInt32 LocalThreadIndex : SV_GroupIndex) +{ + computeFrameinterpolationInpaintingPyramid(WorkGroupId, LocalThreadIndex); +} diff --git a/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_debug_view_pass.hlsl b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_debug_view_pass.hlsl new file mode 100644 index 00000000..3fc5ca59 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_debug_view_pass.hlsl @@ -0,0 +1,58 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DISOCCLUSION_MASK 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PRESENT_BACKBUFFER 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE 7 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT 0 + +#define FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION 0 + +#include "frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h" +#include "frameinterpolation/ffx_frameinterpolation_common.h" +#include "frameinterpolation/ffx_frameinterpolation_debug_view.h" + +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS +#define FFX_FRAMEINTERPOLATION_NUM_THREADS [numthreads(FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH, FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT, FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS + +FFX_FRAMEINTERPOLATION_NUM_THREADS +void CS(FfxInt32x2 iPxPos : SV_DispatchThreadID) +{ + computeDebugView(iPxPos); +} diff --git a/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask_pass.hlsl b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask_pass.hlsl new file mode 100644 index 00000000..6cadf7bf --- /dev/null +++ b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_disocclusion_mask_pass.hlsl @@ -0,0 +1,55 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 5 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_DISOCCLUSION_MASK 0 + +#define FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION 0 + +#include "frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h" +#include "frameinterpolation/ffx_frameinterpolation_common.h" +#include "frameinterpolation/ffx_frameinterpolation_disocclusion_mask.h" + +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS +#define FFX_FRAMEINTERPOLATION_NUM_THREADS [numthreads(FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH, FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT, FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS + +FFX_FRAMEINTERPOLATION_NUM_THREADS +void CS(FfxInt32x2 iPxPos : SV_DispatchThreadID) +{ + computeDisocclusionMask(iPxPos); +} diff --git a/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field_pass.hlsl b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field_pass.hlsl new file mode 100644 index 00000000..88dd9cc9 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_game_motion_vector_field_pass.hlsl @@ -0,0 +1,54 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PREVIOUS_INTERPOLATION_SOURCE 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE 3 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y 1 + +#define FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION 0 + +#include "frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h" +#include "frameinterpolation/ffx_frameinterpolation_common.h" +#include "frameinterpolation/ffx_frameinterpolation_game_motion_vector_field.h" + +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS +#define FFX_FRAMEINTERPOLATION_NUM_THREADS [numthreads(FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH, FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT, FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS + +FFX_FRAMEINTERPOLATION_NUM_THREADS +void CS(FfxInt32x2 iPxPos : SV_DispatchThreadID) +{ + computeGameFieldMvs(iPxPos); +} diff --git a/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.hlsl b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.hlsl new file mode 100644 index 00000000..9be55692 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_inpainting_pass.hlsl @@ -0,0 +1,54 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PRESENT_BACKBUFFER 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE 3 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT 0 + +#define FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION 0 + +#include "frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h" +#include "frameinterpolation/ffx_frameinterpolation_common.h" +#include "frameinterpolation/ffx_frameinterpolation_inpainting.h" + +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS +#define FFX_FRAMEINTERPOLATION_NUM_THREADS [numthreads(FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH, FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT, FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS + +FFX_FRAMEINTERPOLATION_NUM_THREADS +void CS(FfxInt32x2 iPxPos : SV_DispatchThreadID) +{ + computeInpainting(iPxPos); +} diff --git a/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field_pass.hlsl b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field_pass.hlsl new file mode 100644 index 00000000..81d5c565 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field_pass.hlsl @@ -0,0 +1,55 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PREVIOUS_INTERPOLATION_SOURCE 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE 4 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 1 + +#define FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION 0 + +#include "frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h" +#include "frameinterpolation/ffx_frameinterpolation_common.h" +#include "frameinterpolation/ffx_frameinterpolation_optical_flow_vector_field.h" + +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS +#define FFX_FRAMEINTERPOLATION_NUM_THREADS [numthreads(FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH, FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT, FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS + +FFX_FRAMEINTERPOLATION_NUM_THREADS +void CS(FfxInt32x2 iPxPos : SV_DispatchThreadID) +{ + computeOpticalFlowVectorField(iPxPos); +} diff --git a/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_pass.hlsl b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_pass.hlsl new file mode 100644 index 00000000..988f69b4 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_pass.hlsl @@ -0,0 +1,58 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_PREVIOUS_INTERPOLATION_SOURCE 4 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE 5 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DISOCCLUSION_MASK 6 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID 7 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_COUNTERS 8 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT 0 + +#define FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION 0 + +#include "frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h" +#include "frameinterpolation/ffx_frameinterpolation_common.h" +#include "frameinterpolation/ffx_frameinterpolation.h" + +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS +#define FFX_FRAMEINTERPOLATION_NUM_THREADS [numthreads(FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH, FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT, FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS + +FFX_FRAMEINTERPOLATION_NUM_THREADS +void CS(FfxInt32x2 iPxPos : SV_DispatchThreadID) +{ + computeFrameinterpolation(iPxPos); +} diff --git a/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth_pass.hlsl b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth_pass.hlsl new file mode 100644 index 00000000..116d5ee4 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth_pass.hlsl @@ -0,0 +1,53 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS 0 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH 1 +#define FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE 2 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 0 + +#define FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION 0 + +#include "frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h" +#include "frameinterpolation/ffx_frameinterpolation_common.h" +#include "frameinterpolation/ffx_frameinterpolation_reconstruct_previous_depth.h" + +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS +#define FFX_FRAMEINTERPOLATION_NUM_THREADS [numthreads(FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH, FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT, FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS + +FFX_FRAMEINTERPOLATION_NUM_THREADS +void CS(FfxInt32x2 iPxPos : SV_DispatchThreadID) +{ + reconstructPreviousDepth(iPxPos); +} diff --git a/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_setup_pass.hlsl b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_setup_pass.hlsl new file mode 100644 index 00000000..14ee6e62 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/frameinterpolation/ffx_frameinterpolation_setup_pass.hlsl @@ -0,0 +1,55 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 0 + +#define FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X 0 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y 1 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 2 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 3 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_DISOCCLUSION_MASK 4 +#define FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS 5 + +#define FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION 0 + +#include "frameinterpolation/ffx_frameinterpolation_callbacks_hlsl.h" +#include "frameinterpolation/ffx_frameinterpolation_common.h" +#include "frameinterpolation/ffx_frameinterpolation_setup.h" + +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT +#ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#define FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH +#ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS +#define FFX_FRAMEINTERPOLATION_NUM_THREADS [numthreads(FFX_FRAMEINTERPOLATION_THREAD_GROUP_WIDTH, FFX_FRAMEINTERPOLATION_THREAD_GROUP_HEIGHT, FFX_FRAMEINTERPOLATION_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FRAMEINTERPOLATION_NUM_THREADS + +FFX_FRAMEINTERPOLATION_NUM_THREADS +void CS(FfxInt32x2 iPxPos : SV_DispatchThreadID) +{ + setupFrameinterpolationResources(iPxPos); +} diff --git a/sdk/src/backends/dx12/shaders/fsr1/ffx_fsr1_easu_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr1/ffx_fsr1_easu_pass.hlsl index 2c7213f1..65b8340a 100644 --- a/sdk/src/backends/dx12/shaders/fsr1/ffx_fsr1_easu_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/fsr1/ffx_fsr1_easu_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // FSR1 pass 1 // SRV 0 : FSR1_InputColor : r_input_color // UAV 0 : FSR1_InternalUpscaled : rw_internal_upscaled_color (if doing RCAS) diff --git a/sdk/src/backends/dx12/shaders/fsr1/ffx_fsr1_rcas_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr1/ffx_fsr1_rcas_pass.hlsl index 1cf046f2..0b1f3736 100644 --- a/sdk/src/backends/dx12/shaders/fsr1/ffx_fsr1_rcas_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/fsr1/ffx_fsr1_rcas_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // FSR1 pass 2 (optional RCAS) // SRV 0 : FSR1_InternalUpscaled : r_internal_upscaled_color // UAV 0 : FSR1_UpscaledOutput : rw_upscaled_output diff --git a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_accumulate_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_accumulate_pass.hlsl index 841efdee..233e63d5 100644 --- a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_accumulate_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_accumulate_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FSR2_BIND_SRV_INPUT_EXPOSURE 0 #define FSR2_BIND_SRV_DILATED_REACTIVE_MASKS 1 #if FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS diff --git a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.hlsl index c7cd6748..31621431 100644 --- a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FSR2_BIND_SRV_INPUT_OPAQUE_ONLY 0 #define FSR2_BIND_SRV_INPUT_COLOR 1 diff --git a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.hlsl index 524ad1bc..ea6d7ac3 100644 --- a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FSR2_BIND_SRV_INPUT_COLOR 0 #define FSR2_BIND_UAV_SPD_GLOBAL_ATOMIC 0 diff --git a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_debug_blit.hlsl b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_debug_blit.hlsl new file mode 100644 index 00000000..9c0d7018 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_debug_blit.hlsl @@ -0,0 +1,49 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +Texture2D r_in : register(t0); +RWTexture2D rw_out : register(u0); + +cbuffer cbBlit0 : register(b0) { + + int g_outChannelRed; + int g_outChannelGreen; + int g_outChannelBlue; + float2 outChannelRedMinMax; + float2 outChannelGreenMinMax; + float2 outChannelBlueMinMax; +}; + +[numthreads(8, 8, 1)] +void CS(uint3 globalID : SV_DispatchThreadID) +{ + float4 srcColor = r_in[globalID.xy]; + + // remap channels + float4 dstColor = float4(srcColor[g_outChannelRed], srcColor[g_outChannelGreen], srcColor[g_outChannelBlue], 1.f); + + // apply offset and scale + dstColor.rgb -= float3(outChannelRedMinMax.x, outChannelGreenMinMax.x, outChannelBlueMinMax.x); + dstColor.rgb /= float3(outChannelRedMinMax.y - outChannelRedMinMax.x, outChannelGreenMinMax.y - outChannelGreenMinMax.x, outChannelBlueMinMax.y - outChannelBlueMinMax.x); + + rw_out[globalID.xy] = float4(dstColor); +} diff --git a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_depth_clip_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_depth_clip_pass.hlsl index 9e25245e..aa871e2b 100644 --- a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_depth_clip_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_depth_clip_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FSR2_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH 0 #define FSR2_BIND_SRV_DILATED_MOTION_VECTORS 1 #define FSR2_BIND_SRV_DILATED_DEPTH 2 diff --git a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_lock_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_lock_pass.hlsl index 838f692a..61d74c83 100644 --- a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_lock_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_lock_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FSR2_BIND_SRV_LOCK_INPUT_LUMA 0 #define FSR2_BIND_UAV_NEW_LOCKS 0 diff --git a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_rcas_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_rcas_pass.hlsl index abe76b46..5dc70a80 100644 --- a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_rcas_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_rcas_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FSR2_BIND_SRV_INPUT_EXPOSURE 0 #define FSR2_BIND_SRV_RCAS_INPUT 1 diff --git a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.hlsl index be39334d..179f34e2 100644 --- a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FSR2_BIND_SRV_INPUT_MOTION_VECTORS 0 #define FSR2_BIND_SRV_INPUT_DEPTH 1 #define FSR2_BIND_SRV_INPUT_COLOR 2 diff --git a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.hlsl index 2d3295db..88889d80 100644 --- a/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + #define FSR2_BIND_SRV_INPUT_OPAQUE_ONLY 0 #define FSR2_BIND_SRV_INPUT_COLOR 1 #define FSR2_BIND_SRV_INPUT_MOTION_VECTORS 2 diff --git a/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.hlsl new file mode 100644 index 00000000..d2f1b322 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_accumulate_pass.hlsl @@ -0,0 +1,79 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 0 +#define FSR3UPSCALER_BIND_SRV_DILATED_REACTIVE_MASKS 1 +#if FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS +#define FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS 2 +#else +#define FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS 2 +#endif +#define FSR3UPSCALER_BIND_SRV_INTERNAL_UPSCALED 3 +#define FSR3UPSCALER_BIND_SRV_LOCK_STATUS 4 +#define FSR3UPSCALER_BIND_SRV_PREPARED_INPUT_COLOR 5 +#define FSR3UPSCALER_BIND_SRV_LANCZOS_LUT 6 +#define FSR3UPSCALER_BIND_SRV_UPSCALE_MAXIMUM_BIAS_LUT 7 +#define FSR3UPSCALER_BIND_SRV_SCENE_LUMINANCE_MIPS 8 +#define FSR3UPSCALER_BIND_SRV_AUTO_EXPOSURE 9 +#define FSR3UPSCALER_BIND_SRV_LUMA_HISTORY 10 + +#define FSR3UPSCALER_BIND_UAV_INTERNAL_UPSCALED 0 +#define FSR3UPSCALER_BIND_UAV_LOCK_STATUS 1 +#define FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT 2 +#define FSR3UPSCALER_BIND_UAV_NEW_LOCKS 3 +#define FSR3UPSCALER_BIND_UAV_LUMA_HISTORY 4 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_upsample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_postprocess_lock_status.h" +#include "fsr3upscaler/ffx_fsr3upscaler_reproject.h" +#include "fsr3upscaler/ffx_fsr3upscaler_accumulate.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_PREFER_WAVE64 +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +void CS(uint2 uGroupId : SV_GroupID, uint2 uGroupThreadId : SV_GroupThreadID) +{ + const uint GroupRows = (uint(DisplaySize().y) + FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT - 1) / FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT; + uGroupId.y = GroupRows - uGroupId.y - 1; + + uint2 uDispatchThreadId = uGroupId * uint2(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT) + uGroupThreadId; + + Accumulate(uDispatchThreadId); +} diff --git a/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.hlsl new file mode 100644 index 00000000..0d6e2ebb --- /dev/null +++ b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_autogen_reactive_pass.hlsl @@ -0,0 +1,77 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY 0 +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 1 + +#define FSR3UPSCALER_BIND_UAV_AUTOREACTIVE 0 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 +#define FSR3UPSCALER_BIND_CB_REACTIVE 1 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +void CS(uint2 uGroupId : SV_GroupID, uint2 uGroupThreadId : SV_GroupThreadID) +{ + uint2 uDispatchThreadId = uGroupId * uint2(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT) + uGroupThreadId; + + float3 ColorPreAlpha = LoadOpaqueOnly( FFX_MIN16_I2(uDispatchThreadId) ).rgb; + float3 ColorPostAlpha = LoadInputColor(uDispatchThreadId).rgb; + + if (GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_TONEMAP) + { + ColorPreAlpha = Tonemap(ColorPreAlpha); + ColorPostAlpha = Tonemap(ColorPostAlpha); + } + + if (GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_INVERSETONEMAP) + { + ColorPreAlpha = InverseTonemap(ColorPreAlpha); + ColorPostAlpha = InverseTonemap(ColorPostAlpha); + } + + float out_reactive_value = 0.f; + float3 delta = abs(ColorPostAlpha - ColorPreAlpha); + + out_reactive_value = (GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_USE_COMPONENTS_MAX) ? max(delta.x, max(delta.y, delta.z)) : length(delta); + out_reactive_value *= GenReactiveScale(); + + out_reactive_value = (GenReactiveFlags() & FFX_FSR3UPSCALER_AUTOREACTIVEFLAGS_APPLY_THRESHOLD) ? (out_reactive_value < GenReactiveThreshold() ? 0 : GenReactiveBinaryValue()) : out_reactive_value; + + rw_output_autoreactive[uDispatchThreadId] = out_reactive_value; +} diff --git a/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.hlsl new file mode 100644 index 00000000..93b73326 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid_pass.hlsl @@ -0,0 +1,55 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 0 + +#define FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC 0 +#define FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE 1 +#define FSR3UPSCALER_BIND_UAV_EXPOSURE_MIP_5 2 +#define FSR3UPSCALER_BIND_UAV_AUTO_EXPOSURE 3 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 +#define FSR3UPSCALER_BIND_CB_SPD 1 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_compute_luminance_pyramid.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_CB2_ROOTSIG_CONTENT +void CS(uint3 WorkGroupId : SV_GroupID, uint LocalThreadIndex : SV_GroupIndex) +{ + ComputeAutoExposure(WorkGroupId, LocalThreadIndex); +} diff --git a/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.hlsl new file mode 100644 index 00000000..70cc7ba0 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_depth_clip_pass.hlsl @@ -0,0 +1,67 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH 0 +#define FSR3UPSCALER_BIND_SRV_DILATED_MOTION_VECTORS 1 +#define FSR3UPSCALER_BIND_SRV_DILATED_DEPTH 2 +#define FSR3UPSCALER_BIND_SRV_REACTIVE_MASK 3 +#define FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK 4 +#define FSR3UPSCALER_BIND_SRV_PREVIOUS_DILATED_MOTION_VECTORS 5 +#define FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS 6 +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 7 +#define FSR3UPSCALER_BIND_SRV_INPUT_DEPTH 8 +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 9 + +#define FSR3UPSCALER_BIND_UAV_DILATED_REACTIVE_MASKS 0 +#define FSR3UPSCALER_BIND_UAV_PREPARED_INPUT_COLOR 1 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_depth_clip.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_PREFER_WAVE64 +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +void CS( + int2 iGroupId : SV_GroupID, + int2 iDispatchThreadId : SV_DispatchThreadID, + int2 iGroupThreadId : SV_GroupThreadID, + int iGroupIndex : SV_GroupIndex) +{ + DepthClip(iDispatchThreadId); +} diff --git a/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.hlsl new file mode 100644 index 00000000..26b28f01 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_lock_pass.hlsl @@ -0,0 +1,56 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_LOCK_INPUT_LUMA 0 + +#define FSR3UPSCALER_BIND_UAV_NEW_LOCKS 0 +#define FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH 1 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_lock.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_PREFER_WAVE64 +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +void CS(uint2 uGroupId : SV_GroupID, uint2 uGroupThreadId : SV_GroupThreadID) +{ + uint2 uDispatchThreadId = uGroupId * uint2(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT) + uGroupThreadId; + + ComputeLock(uDispatchThreadId); +} diff --git a/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.hlsl new file mode 100644 index 00000000..bebdeb38 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_rcas_pass.hlsl @@ -0,0 +1,53 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 0 +#define FSR3UPSCALER_BIND_SRV_RCAS_INPUT 1 + +#define FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT 0 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 +#define FSR3UPSCALER_BIND_CB_RCAS 1 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_rcas.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 64 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_CB2_ROOTSIG_CONTENT +void CS(uint3 LocalThreadId : SV_GroupThreadID, uint3 WorkGroupId : SV_GroupID, uint3 Dtid : SV_DispatchThreadID) +{ + RCAS(LocalThreadId, WorkGroupId, Dtid); +} diff --git a/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.hlsl b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.hlsl new file mode 100644 index 00000000..f277fd16 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/fsr3upscaler/ffx_fsr3upscaler_reconstruct_previous_depth_pass.hlsl @@ -0,0 +1,64 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS 0 +#define FSR3UPSCALER_BIND_SRV_INPUT_DEPTH 1 +#define FSR3UPSCALER_BIND_SRV_INPUT_COLOR 2 +#define FSR3UPSCALER_BIND_SRV_INPUT_EXPOSURE 3 + +#define FSR3UPSCALER_BIND_UAV_RECONSTRUCTED_PREV_NEAREST_DEPTH 0 +#define FSR3UPSCALER_BIND_UAV_DILATED_MOTION_VECTORS 1 +#define FSR3UPSCALER_BIND_UAV_DILATED_DEPTH 2 +#define FSR3UPSCALER_BIND_UAV_LOCK_INPUT_LUMA 3 + +#define FSR3UPSCALER_BIND_CB_FSR3UPSCALER 0 + +#include "fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h" +#include "fsr3upscaler/ffx_fsr3upscaler_common.h" +#include "fsr3upscaler/ffx_fsr3upscaler_sample.h" +#include "fsr3upscaler/ffx_fsr3upscaler_reconstruct_dilated_velocity_and_previous_depth.h" + +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#define FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT 8 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT +#ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#define FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH +#ifndef FFX_FSR3UPSCALER_NUM_THREADS +#define FFX_FSR3UPSCALER_NUM_THREADS [numthreads(FFX_FSR3UPSCALER_THREAD_GROUP_WIDTH, FFX_FSR3UPSCALER_THREAD_GROUP_HEIGHT, FFX_FSR3UPSCALER_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_FSR3UPSCALER_NUM_THREADS + +FFX_PREFER_WAVE64 +FFX_FSR3UPSCALER_NUM_THREADS +FFX_FSR3UPSCALER_EMBED_ROOTSIG_CONTENT +void CS( + int2 iGroupId : SV_GroupID, + int2 iDispatchThreadId : SV_DispatchThreadID, + int2 iGroupThreadId : SV_GroupThreadID, + int iGroupIndex : SV_GroupIndex +) +{ + ReconstructAndDilate(iDispatchThreadId); +} diff --git a/sdk/src/backends/dx12/shaders/lens/ffx_lens_pass.hlsl b/sdk/src/backends/dx12/shaders/lens/ffx_lens_pass.hlsl index 18dc6935..d00b428c 100644 --- a/sdk/src/backends/dx12/shaders/lens/ffx_lens_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/lens/ffx_lens_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // Lens pass // SRV 0 : LENS_InputTexture : r_input_texture // UAV 0 : LENS_OutputTexture : rw_output_texture diff --git a/sdk/src/backends/dx12/shaders/lpm/ffx_lpm_filter_pass.hlsl b/sdk/src/backends/dx12/shaders/lpm/ffx_lpm_filter_pass.hlsl index f93a8c1c..7f5fdfca 100644 --- a/sdk/src/backends/dx12/shaders/lpm/ffx_lpm_filter_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/lpm/ffx_lpm_filter_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // LPM pass 1 // SRV 0 : LPM_InputColor : r_input_color // UAV 0 : LPM_OutputColor : rw_output_color diff --git a/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.hlsl b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.hlsl new file mode 100644 index 00000000..80e6aefc --- /dev/null +++ b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_luminance_pyramid_pass.hlsl @@ -0,0 +1,107 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_1 1 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_2 2 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_3 3 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_4 4 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_5 5 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT_LEVEL_6 6 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 +#define FFX_OPTICALFLOW_BIND_CB_SPD 1 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" + +cbuffer cbOF_SPD : FFX_OPTICALFLOW_DECLARE_CB(FFX_OPTICALFLOW_BIND_CB_SPD) { + + uint mips; + uint numWorkGroups; + uint2 workGroupOffset; + uint numWorkGroupOpticalFlowInputPyramid; + uint pad0_; + uint pad1_; + uint pad2_; +}; + +uint NumWorkGroups() +{ + return numWorkGroupOpticalFlowInputPyramid; +} + +void SPD_SetMipmap(int2 iPxPos, int index, float value) +{ + switch (index) + { + case 0: + rw_optical_flow_input_level_1[iPxPos] = value; + break; + case 1: + rw_optical_flow_input_level_2[iPxPos] = value; + break; + case 2: + rw_optical_flow_input_level_3[iPxPos] = value; + break; + case 3: + rw_optical_flow_input_level_4[iPxPos] = value; + break; + case 4: + rw_optical_flow_input_level_5[iPxPos] = value; + break; + case 5: + rw_optical_flow_input_level_6[iPxPos] = value; + break; + } +} + +void SPD_IncreaseAtomicCounter(inout uint spdCounter) +{ +} + +void SPD_ResetAtomicCounter() +{ +} + +#include "opticalflow/ffx_opticalflow_compute_luminance_pyramid.h" + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_OPTICALFLOW_NUM_THREADS + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_CB2_ROOTSIG_CONTENT +void CS(int2 iGlobalId : SV_DispatchThreadID, + int2 iGroupId : SV_GroupID, + int iLocalIndex : SV_GroupIndex) +{ + ComputeOpticalFlowInputPyramid(iGroupId, iLocalIndex); +} diff --git a/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.hlsl b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.hlsl new file mode 100644 index 00000000..8e3f344f --- /dev/null +++ b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_optical_flow_advanced_pass_v5.hlsl @@ -0,0 +1,61 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_INPUT 0 +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS_INPUT 1 + +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT 1 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" + +#ifndef FFX_OPTICALFLOW_BLOCK_SIZE +#define FFX_OPTICALFLOW_BLOCK_SIZE 8 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 64 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH + +#include "opticalflow/ffx_opticalflow_compute_optical_flow_v5.h" + +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_OPTICALFLOW_NUM_THREADS + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_PREFER_WAVE64 +void CS(int2 iGlobalId : SV_DispatchThreadID, + int2 iLocalId : SV_GroupThreadID, + int2 iGroupId : SV_GroupID, + int iLocalIndex : SV_GroupIndex) +{ + ComputeOpticalFlowAdvanced(iGlobalId, iLocalId, iGroupId, iLocalIndex); +} diff --git a/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.hlsl b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.hlsl new file mode 100644 index 00000000..d2890f88 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_compute_scd_divergence_pass.hlsl @@ -0,0 +1,56 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_HISTOGRAM 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM 1 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_TEMP 2 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT 3 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" +#include "opticalflow/ffx_opticalflow_compute_scd_divergence.h" + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 256 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_OPTICALFLOW_NUM_THREADS + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_PREFER_WAVE64 +void CS(int3 iGlobalId : SV_DispatchThreadID, + int2 iLocalId : SV_GroupThreadID, + int2 iGroupId : SV_GroupID, + int iLocalIndex : SV_GroupIndex) +{ + int2 iGroupSize = int2(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT); + ComputeSCDHistogramsDivergence(iGlobalId, iLocalId, iLocalIndex, iGroupId, iGroupSize); +} diff --git a/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.hlsl b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.hlsl new file mode 100644 index 00000000..b4ad4230 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_filter_optical_flow_pass_v5.hlsl @@ -0,0 +1,56 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS 0 + +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW 0 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 16 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 4 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif // #ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH + +#include "opticalflow/ffx_opticalflow_filter_optical_flow_v5.h" + +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif // #ifndef FFX_OPTICALFLOW_NUM_THREADS + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_PREFER_WAVE64 +void CS(int2 iGlobalId : SV_DispatchThreadID, + int2 iLocalId : SV_GroupThreadID, + int2 iGroupId : SV_GroupID, + int iLocalIndex : SV_GroupIndex) +{ + FilterOpticalFlow(iGlobalId, iLocalId, iGroupId, iLocalIndex); +} diff --git a/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.hlsl b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.hlsl new file mode 100644 index 00000000..06caa41f --- /dev/null +++ b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_generate_scd_histogram_pass.hlsl @@ -0,0 +1,54 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_INPUT 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_HISTOGRAM 0 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" +#include "opticalflow/ffx_opticalflow_generate_scd_histogram.h" + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 32 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 8 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_PREFER_WAVE64 +void CS(int3 iGlobalId : SV_DispatchThreadID, + int2 iLocalId : SV_GroupThreadID, + int2 iGroupId : SV_GroupID, + int iLocalIndex : SV_GroupIndex) +{ + int2 iGroupSize = int2(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT); + GenerateSceneChangeDetectionHistogram(iGlobalId, iLocalId, iLocalIndex, iGroupId, iGroupSize); +} diff --git a/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.hlsl b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.hlsl new file mode 100644 index 00000000..8ec06230 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_prepare_luma_pass.hlsl @@ -0,0 +1,50 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_SRV_INPUT_COLOR 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_INPUT 0 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 16 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 16 +#endif +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 1 +#endif +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif + +#include "opticalflow/ffx_opticalflow_prepare_luma.h" + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +void CS(int2 iGlobalId : SV_DispatchThreadID, int iLocalIndex : SV_GroupIndex) +{ + PrepareLuma(iGlobalId, iLocalIndex); +} diff --git a/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.hlsl b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.hlsl new file mode 100644 index 00000000..4386ba71 --- /dev/null +++ b/sdk/src/backends/dx12/shaders/opticalflow/ffx_opticalflow_scale_optical_flow_advanced_pass_v5.hlsl @@ -0,0 +1,62 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_INPUT 0 +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW_PREVIOUS_INPUT 1 +#define FFX_OPTICALFLOW_BIND_SRV_OPTICAL_FLOW 2 + +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_NEXT_LEVEL 0 +#define FFX_OPTICALFLOW_BIND_UAV_OPTICAL_FLOW_SCD_OUTPUT 1 + +#define FFX_OPTICALFLOW_BIND_CB_COMMON 0 + +#include "opticalflow/ffx_opticalflow_callbacks_hlsl.h" + +#ifndef FFX_OPTICALFLOW_BLOCK_SIZE +#define FFX_OPTICALFLOW_BLOCK_SIZE 8 +#endif + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_WIDTH +#define FFX_OPTICALFLOW_THREAD_GROUP_WIDTH 4 +#endif + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT +#define FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT 4 +#endif + +#ifndef FFX_OPTICALFLOW_THREAD_GROUP_DEPTH +#define FFX_OPTICALFLOW_THREAD_GROUP_DEPTH 4 +#endif + +#include "opticalflow/ffx_opticalflow_scale_optical_flow_advanced_v5.h" + +#ifndef FFX_OPTICALFLOW_NUM_THREADS +#define FFX_OPTICALFLOW_NUM_THREADS [numthreads(FFX_OPTICALFLOW_THREAD_GROUP_WIDTH, FFX_OPTICALFLOW_THREAD_GROUP_HEIGHT, FFX_OPTICALFLOW_THREAD_GROUP_DEPTH)] +#endif + +FFX_OPTICALFLOW_NUM_THREADS +FFX_OPTICALFLOW_EMBED_ROOTSIG_CONTENT +FFX_PREFER_WAVE64 +void CS(int3 iGlobalId : SV_DispatchThreadID, int3 iLocalId : SV_GroupThreadID) +{ + ScaleOpticalFlowAdvanced(iGlobalId, iLocalId); +} diff --git a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_reduce_pass.hlsl b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_reduce_pass.hlsl index 83d31b53..317953c5 100644 --- a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_reduce_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_reduce_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // Parallel Sort Reduce Pass // UAV 0 : ParallelSort_Sum_Table : rw_sum_table // UAV 1 : ParallelSort_Reduce_Table : rw_reduce_table diff --git a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scan_add_pass.hlsl b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scan_add_pass.hlsl index 63a3c564..110c6f7a 100644 --- a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scan_add_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scan_add_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // Parallel Sort Scan Add Pass // UAV 0 : ParallelSort_Scan_Source : rw_scan_source // UAV 1 : ParallelSort_Scan_Dest : rw_scan_dest diff --git a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scan_pass.hlsl b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scan_pass.hlsl index 9aa0e45e..5ffc72ce 100644 --- a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scan_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scan_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // Parallel Sort Scan Pass // UAV 0 : ParallelSort_Scan_Source : rw_scan_source // UAV 1 : ParallelSort_Scan_Dest : rw_scan_dest diff --git a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scatter_pass.hlsl b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scatter_pass.hlsl index a79df79b..f492390c 100644 --- a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scatter_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_scatter_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // Parallel Sort Scatter Pass // UAV 0 : ParallelSort_Source_Keys : rw_source_keys // UAV 1 : ParallelSort_Dest_Keys : rw_dest_keys diff --git a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_setup_indirect_args_pass.hlsl b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_setup_indirect_args_pass.hlsl index 72deb7a1..36f09d5f 100644 --- a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_setup_indirect_args_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_setup_indirect_args_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // Setup Indirect Args Pass // UAV 0 : ParallelSort_Indirect_Count_Scatter_Args : rw_count_scatter_args // UAV 1 : ParallelSort_Indirect_Reduce_Scan_Args : rw_reduce_scan_args diff --git a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_sum_pass.hlsl b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_sum_pass.hlsl index 7f350291..446e1e12 100644 --- a/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_sum_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/parallelsort/ffx_parallelsort_sum_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // Parallel Sort Sum Pass // UAV 0 : ParallelSort_Source_Keys : rw_source_keys // UAV 1 : ParallelSort_Sum_Table : rw_sum_table diff --git a/sdk/src/backends/dx12/shaders/spd/ffx_spd_downsample_pass.hlsl b/sdk/src/backends/dx12/shaders/spd/ffx_spd_downsample_pass.hlsl index c58e10d4..db99eee3 100644 --- a/sdk/src/backends/dx12/shaders/spd/ffx_spd_downsample_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/spd/ffx_spd_downsample_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // SPD pass // SRV 0 : SPD_InputDownsampleSrc : r_input_downsample_src // UAV 0 : SPD_InternalGlobalAtomic : rw_internal_global_atomic diff --git a/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_classify_tiles_pass.hlsl b/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_classify_tiles_pass.hlsl index b871caea..d943f080 100644 --- a/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_classify_tiles_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_classify_tiles_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FFX_WAVE 1 #define SSSR_BIND_SRV_INPUT_NORMAL 0 diff --git a/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_depth_downsample_pass.hlsl b/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_depth_downsample_pass.hlsl index 5798d968..8a170e27 100644 --- a/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_depth_downsample_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_depth_downsample_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define SSSR_BIND_SRV_INPUT_DEPTH 0 #define SSSR_BIND_UAV_SPD_GLOBAL_ATOMIC 1 diff --git a/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_intersect_pass.hlsl b/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_intersect_pass.hlsl index fd6da33c..919d5aaa 100644 --- a/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_intersect_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_intersect_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define FFX_WAVE 1 #define SSSR_BIND_SRV_INPUT_COLOR 0 diff --git a/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_prepare_blue_noise_texture_pass.hlsl b/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_prepare_blue_noise_texture_pass.hlsl index 86313ee1..f1ce2b17 100644 --- a/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_prepare_blue_noise_texture_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_prepare_blue_noise_texture_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define SSSR_BIND_SRV_SOBOL_BUFFER 0 #define SSSR_BIND_SRV_SCRAMBLING_TILE_BUFFER 1 diff --git a/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_prepare_indirect_args_pass.hlsl b/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_prepare_indirect_args_pass.hlsl index eede5f25..72812c8e 100644 --- a/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_prepare_indirect_args_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/sssr/ffx_sssr_prepare_indirect_args_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + #define SSSR_BIND_UAV_RAY_COUNTER 0 #define SSSR_BIND_UAV_INTERSECTION_PASS_INDIRECT_ARGS 1 diff --git a/sdk/src/backends/dx12/shaders/vrs/ffx_vrs_imagegen_pass.hlsl b/sdk/src/backends/dx12/shaders/vrs/ffx_vrs_imagegen_pass.hlsl index f033ff09..d1c0f04d 100644 --- a/sdk/src/backends/dx12/shaders/vrs/ffx_vrs_imagegen_pass.hlsl +++ b/sdk/src/backends/dx12/shaders/vrs/ffx_vrs_imagegen_pass.hlsl @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. // -// 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 : +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // -// The above copyright notice and this permission notice shall be included in +// 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 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. + // Texture definitions // RWTexture2D imgDestination : register(u0); // Texture2D texColor : register(t0); diff --git a/sdk/src/backends/shared/blob_accessors/ffx_blur_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_blur_shaderblobs.cpp index fc51dc30..9a5fefdf 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_blur_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_blur_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_blur_shaderblobs.h" #include "blur/ffx_blur_private.h" @@ -120,7 +120,7 @@ FfxErrorCode blurGetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_blur_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_blur_shaderblobs.h index 14bfc3c5..9f86226a 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_blur_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_blur_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_cacao_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_cacao_shaderblobs.cpp index 1f411050..e3198378 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_cacao_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_cacao_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_cacao_shaderblobs.h" #include "cacao/ffx_cacao_private.h" @@ -954,7 +954,7 @@ FfxErrorCode cacaoGetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_cacao_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_cacao_shaderblobs.h index 40154c5d..530eac17 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_cacao_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_cacao_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_cas_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_cas_shaderblobs.cpp index b8912750..3f7e0b01 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_cas_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_cas_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_cas_shaderblobs.h" #include "cas/ffx_cas_private.h" @@ -104,7 +104,7 @@ FfxErrorCode casGetPermutationBlobByIndex(FfxCasPass passId, uint32_t permutatio } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_cas_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_cas_shaderblobs.h index 9609ed27..8b593d20 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_cas_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_cas_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_classifier_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_classifier_shaderblobs.cpp index d1997276..4b537363 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_classifier_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_classifier_shaderblobs.cpp @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include #include "ffx_classifier_shaderblobs.h" #include "classifier/ffx_classifier_private.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_classifier_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_classifier_shaderblobs.h index 1492de62..24d2f8d6 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_classifier_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_classifier_shaderblobs.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #pragma once #include "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_denoiser_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_denoiser_shaderblobs.cpp index 965e4f8c..d0f6dd21 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_denoiser_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_denoiser_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// +// 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 +// 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 #include "ffx_denoiser_shaderblobs.h" #include "denoiser/ffx_denoiser_private.h" @@ -371,7 +371,7 @@ FfxErrorCode denoiserGetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_denoiser_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_denoiser_shaderblobs.h index f032aaca..a135a9dd 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_denoiser_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_denoiser_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_dof_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_dof_shaderblobs.cpp index 77d37035..ee3c4c02 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_dof_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_dof_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_dof_shaderblobs.h" #include "dof/ffx_dof_private.h" @@ -241,7 +241,7 @@ FfxErrorCode dofGetPermutationBlobByIndex(FfxDofPass passId, uint32_t permutatio { FFX_ASSERT_FAIL("Invalid pass id"); // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_ERROR_INVALID_ENUM; } FfxShaderBlob blob = (g_pass_getter_map[passId])(permutationOptions, isWave64, is16bit); diff --git a/sdk/src/backends/shared/blob_accessors/ffx_dof_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_dof_shaderblobs.h index a60ea718..cab4efa3 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_dof_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_dof_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_frameinterpolation_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_frameinterpolation_shaderblobs.cpp new file mode 100644 index 00000000..5498dcd6 --- /dev/null +++ b/sdk/src/backends/shared/blob_accessors/ffx_frameinterpolation_shaderblobs.cpp @@ -0,0 +1,349 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +#define FFX_CPU +#include +#include "ffx_frameinterpolation_shaderblobs.h" +#include "frameinterpolation/ffx_frameinterpolation_private.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // for memset + +#if defined(POPULATE_PERMUTATION_KEY) +#undef POPULATE_PERMUTATION_KEY +#endif // #if defined(POPULATE_PERMUTATION_KEY) +#define POPULATE_PERMUTATION_KEY(options, key) \ + key.index = 0;\ + key.FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH = FFX_CONTAINS_FLAG(options, FRAMEINTERPOLATION_SHADER_PERMUTATION_DEPTH_INVERTED); + +static FfxShaderBlob FrameInterpolationGetSetupPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_frameinterpolation_setup_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_frameinterpolation_setup_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_setup_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_frameinterpolation_setup_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_setup_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob FrameInterpolationGetGameMotionVectorFieldPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_frameinterpolation_game_motion_vector_field_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_frameinterpolation_game_motion_vector_field_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_game_motion_vector_field_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_frameinterpolation_game_motion_vector_field_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_game_motion_vector_field_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob FrameInterpolationGetOpticalFlowVectorFieldPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_frameinterpolation_optical_flow_vector_field_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_frameinterpolation_optical_flow_vector_field_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_optical_flow_vector_field_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_frameinterpolation_optical_flow_vector_field_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_optical_flow_vector_field_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob FrameInterpolationGetReconstructPrevDepthPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_frameinterpolation_reconstruct_previous_depth_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_frameinterpolation_reconstruct_previous_depth_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_reconstruct_previous_depth_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_frameinterpolation_reconstruct_previous_depth_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_reconstruct_previous_depth_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob FrameInterpolationGetDisocclusionMaskPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_frameinterpolation_disocclusion_mask_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_frameinterpolation_disocclusion_mask_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_disocclusion_mask_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_frameinterpolation_disocclusion_mask_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_disocclusion_mask_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob FrameInterpolationGetComputeInpaintingPyramidPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_frameinterpolation_compute_inpainting_pyramid_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_frameinterpolation_compute_inpainting_pyramid_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_compute_inpainting_pyramid_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_frameinterpolation_compute_inpainting_pyramid_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_compute_inpainting_pyramid_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob FrameInterpolationGetFiPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_frameinterpolation_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_frameinterpolation_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_frameinterpolation_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob FrameInterpolationGetComputeGameVectorFieldInpaintingPyramidPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob FrameInterpolationGetInpaintingPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_frameinterpolation_inpainting_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_frameinterpolation_inpainting_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_inpainting_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_frameinterpolation_inpainting_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_inpainting_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob FrameInterpolationGetDebugViewPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_frameinterpolation_inpainting_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_frameinterpolation_debug_view_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_debug_view_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_frameinterpolation_debug_view_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_frameinterpolation_debug_view_pass_PermutationInfo, tableIndex); + } +} + +FfxErrorCode frameInterpolationGetPermutationBlobByIndex(FfxFrameInterpolationPass passId, + FfxBindStage stageId, + uint32_t permutationOptions, FfxShaderBlob* outBlob) +{ + + bool isWave64 = FFX_CONTAINS_FLAG(permutationOptions, FRAMEINTERPOLATION_SHADER_PERMUTATION_FORCE_WAVE64); + bool is16bit = FFX_CONTAINS_FLAG(permutationOptions, FRAMEINTERPOLATION_SHADER_PERMUTATION_ALLOW_FP16); + + switch (passId) { + + case FFX_FRAMEINTERPOLATION_PASS_SETUP: + { + FfxShaderBlob blob = FrameInterpolationGetSetupPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FRAMEINTERPOLATION_PASS_RECONSTRUCT_PREV_DEPTH: + { + FfxShaderBlob blob = FrameInterpolationGetReconstructPrevDepthPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FRAMEINTERPOLATION_PASS_GAME_MOTION_VECTOR_FIELD: + { + FfxShaderBlob blob = FrameInterpolationGetGameMotionVectorFieldPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FRAMEINTERPOLATION_PASS_OPTICAL_FLOW_VECTOR_FIELD: + { + FfxShaderBlob blob = FrameInterpolationGetOpticalFlowVectorFieldPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FRAMEINTERPOLATION_PASS_DISOCCLUSION_MASK: + { + FfxShaderBlob blob = FrameInterpolationGetDisocclusionMaskPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FRAMEINTERPOLATION_PASS_GAME_VECTOR_FIELD_INPAINTING_PYRAMID: + { + FfxShaderBlob blob = FrameInterpolationGetComputeGameVectorFieldInpaintingPyramidPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FRAMEINTERPOLATION_PASS_INPAINTING_PYRAMID: + { + FfxShaderBlob blob = FrameInterpolationGetComputeInpaintingPyramidPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FRAMEINTERPOLATION_PASS_INTERPOLATION: + { + FfxShaderBlob blob = FrameInterpolationGetFiPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FRAMEINTERPOLATION_PASS_INPAINTING: + { + FfxShaderBlob blob = FrameInterpolationGetInpaintingPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FRAMEINTERPOLATION_PASS_DEBUG_VIEW: + { + FfxShaderBlob blob = FrameInterpolationGetDebugViewPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + default: + FFX_ASSERT_FAIL("Should never reach here."); + break; + } + + // return an empty blob + memset(outBlob, 0, sizeof(FfxShaderBlob)); + return FFX_OK; +} diff --git a/sdk/src/backends/shared/blob_accessors/ffx_frameinterpolation_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_frameinterpolation_shaderblobs.h new file mode 100644 index 00000000..fbee8249 --- /dev/null +++ b/sdk/src/backends/shared/blob_accessors/ffx_frameinterpolation_shaderblobs.h @@ -0,0 +1,42 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "../ffx_shader_blobs.h" +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif // #if defined(__cplusplus) + +// Get a DX12 shader blob for the specified pass and permutation index. +FfxErrorCode frameInterpolationGetPermutationBlobByIndex( + FfxFrameInterpolationPass passId, + FfxBindStage stageId, + uint32_t permutationOptions, + FfxShaderBlob* outBlob); + +#if defined(__cplusplus) +} +#endif // #if defined(__cplusplus) diff --git a/sdk/src/backends/shared/blob_accessors/ffx_fsr1_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_fsr1_shaderblobs.cpp index fe858e35..8a51939a 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_fsr1_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_fsr1_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_fsr1_shaderblobs.h" #include "fsr1/ffx_fsr1_private.h" @@ -141,7 +141,7 @@ FfxErrorCode fsr1GetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_fsr1_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_fsr1_shaderblobs.h index 0d7840a3..140fda3e 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_fsr1_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_fsr1_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_fsr2_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_fsr2_shaderblobs.cpp index 15a33f20..782bcbed 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_fsr2_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_fsr2_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_fsr2_shaderblobs.h" #include "fsr2/ffx_fsr2_private.h" @@ -382,7 +382,7 @@ FfxErrorCode fsr2GetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_fsr2_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_fsr2_shaderblobs.h index 821cdca1..1f267e00 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_fsr2_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_fsr2_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_fsr3upscaler_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_fsr3upscaler_shaderblobs.cpp new file mode 100644 index 00000000..e146d4bd --- /dev/null +++ b/sdk/src/backends/shared/blob_accessors/ffx_fsr3upscaler_shaderblobs.cpp @@ -0,0 +1,344 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include "ffx_fsr3upscaler_shaderblobs.h" +#include "fsr3upscaler/ffx_fsr3upscaler_private.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include // for memset + +#if defined(POPULATE_PERMUTATION_KEY) +#undef POPULATE_PERMUTATION_KEY +#endif // #if defined(POPULATE_PERMUTATION_KEY) +#define POPULATE_PERMUTATION_KEY(options, key) \ +key.index = 0; \ +key.FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE = FFX_CONTAINS_FLAG(options, FSR3UPSCALER_SHADER_PERMUTATION_USE_LANCZOS_TYPE); \ +key.FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT = FFX_CONTAINS_FLAG(options, FSR3UPSCALER_SHADER_PERMUTATION_HDR_COLOR_INPUT); \ +key.FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS = FFX_CONTAINS_FLAG(options, FSR3UPSCALER_SHADER_PERMUTATION_LOW_RES_MOTION_VECTORS); \ +key.FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS = FFX_CONTAINS_FLAG(options, FSR3UPSCALER_SHADER_PERMUTATION_JITTER_MOTION_VECTORS); \ +key.FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH = FFX_CONTAINS_FLAG(options, FSR3UPSCALER_SHADER_PERMUTATION_DEPTH_INVERTED); \ +key.FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING = FFX_CONTAINS_FLAG(options, FSR3UPSCALER_SHADER_PERMUTATION_ENABLE_SHARPENING); + +static FfxShaderBlob fsr3UpscalerGetDepthClipPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + + ffx_fsr3upscaler_depth_clip_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) { + + if (is16bit) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_depth_clip_pass_wave64_16bit_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_depth_clip_pass_wave64_16bit_PermutationInfo, tableIndex); + } else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_depth_clip_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_depth_clip_pass_wave64_PermutationInfo, tableIndex); + } + } else { + + if (is16bit) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_depth_clip_pass_16bit_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_depth_clip_pass_16bit_PermutationInfo, tableIndex); + } else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_depth_clip_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_depth_clip_pass_PermutationInfo, tableIndex); + } + } +} + +static FfxShaderBlob fsr3UpscalerGetReconstructPreviousDepthPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + + ffx_fsr3upscaler_reconstruct_previous_depth_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) { + + if (is16bit) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_reconstruct_previous_depth_pass_wave64_16bit_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_reconstruct_previous_depth_pass_wave64_16bit_PermutationInfo, tableIndex); + } else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_reconstruct_previous_depth_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_reconstruct_previous_depth_pass_wave64_PermutationInfo, tableIndex); + } + } else { + + if (is16bit) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_reconstruct_previous_depth_pass_16bit_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_reconstruct_previous_depth_pass_16bit_PermutationInfo, tableIndex); + } else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_reconstruct_previous_depth_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_reconstruct_previous_depth_pass_PermutationInfo, tableIndex); + } + } +} + +static FfxShaderBlob fsr3UpscalerGetLockPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + + ffx_fsr3upscaler_lock_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) { + + if (is16bit) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_lock_pass_wave64_16bit_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_lock_pass_wave64_16bit_PermutationInfo, tableIndex); + } else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_lock_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_lock_pass_wave64_PermutationInfo, tableIndex); + } + } else { + + if (is16bit) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_lock_pass_16bit_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_lock_pass_16bit_PermutationInfo, tableIndex); + } else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_lock_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_lock_pass_PermutationInfo, tableIndex); + } + } +} + +static FfxShaderBlob fsr3UpscalerGetAccumulatePassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + + ffx_fsr3upscaler_accumulate_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) { + + if (is16bit) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_accumulate_pass_wave64_16bit_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_accumulate_pass_wave64_16bit_PermutationInfo, tableIndex); + } else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_accumulate_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_accumulate_pass_wave64_PermutationInfo, tableIndex); + } + } else { + + if (is16bit) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_accumulate_pass_16bit_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_accumulate_pass_16bit_PermutationInfo, tableIndex); + } else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_accumulate_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_accumulate_pass_PermutationInfo, tableIndex); + } + } +} + +static FfxShaderBlob fsr3UpscalerGetRCASPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + + ffx_fsr3upscaler_rcas_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_rcas_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_rcas_pass_wave64_PermutationInfo, tableIndex); + + } else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_rcas_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_rcas_pass_PermutationInfo, tableIndex); + + } +} + +static FfxShaderBlob fsr3UpscalerGetComputeLuminancePyramidPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + + ffx_fsr3upscaler_compute_luminance_pyramid_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_compute_luminance_pyramid_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_compute_luminance_pyramid_pass_wave64_PermutationInfo, tableIndex); + } else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_compute_luminance_pyramid_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_compute_luminance_pyramid_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob fsr3UpscalerGetAutogenReactivePassPermutationBlobByIndex( + uint32_t permutationOptions, + bool isWave64, + bool is16bit) { + + ffx_fsr3upscaler_autogen_reactive_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) { + + if (is16bit) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_autogen_reactive_pass_wave64_16bit_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_autogen_reactive_pass_wave64_16bit_PermutationInfo, tableIndex); + } + else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_autogen_reactive_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_autogen_reactive_pass_wave64_PermutationInfo, tableIndex); + } + } + else { + + if (is16bit) { + + const int32_t tableIndex = g_ffx_fsr3upscaler_autogen_reactive_pass_16bit_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_autogen_reactive_pass_16bit_PermutationInfo, tableIndex); + } + else { + + const int32_t tableIndex = g_ffx_fsr3upscaler_autogen_reactive_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_fsr3upscaler_autogen_reactive_pass_PermutationInfo, tableIndex); + } + } +} + +FfxErrorCode fsr3UpscalerGetPermutationBlobByIndex( + FfxFsr3UpscalerPass passId, + uint32_t permutationOptions, + FfxShaderBlob* outBlob) { + + bool isWave64 = FFX_CONTAINS_FLAG(permutationOptions, FSR3UPSCALER_SHADER_PERMUTATION_FORCE_WAVE64); + bool is16bit = FFX_CONTAINS_FLAG(permutationOptions, FSR3UPSCALER_SHADER_PERMUTATION_ALLOW_FP16); + + switch (passId) { + + case FFX_FSR3UPSCALER_PASS_DEPTH_CLIP: + { + FfxShaderBlob blob = fsr3UpscalerGetDepthClipPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FSR3UPSCALER_PASS_RECONSTRUCT_PREVIOUS_DEPTH: + { + FfxShaderBlob blob = fsr3UpscalerGetReconstructPreviousDepthPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FSR3UPSCALER_PASS_LOCK: + { + FfxShaderBlob blob = fsr3UpscalerGetLockPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FSR3UPSCALER_PASS_ACCUMULATE: + case FFX_FSR3UPSCALER_PASS_ACCUMULATE_SHARPEN: + { + FfxShaderBlob blob = fsr3UpscalerGetAccumulatePassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FSR3UPSCALER_PASS_RCAS: + { + FfxShaderBlob blob = fsr3UpscalerGetRCASPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FSR3UPSCALER_PASS_COMPUTE_LUMINANCE_PYRAMID: + { + FfxShaderBlob blob = fsr3UpscalerGetComputeLuminancePyramidPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_FSR3UPSCALER_PASS_GENERATE_REACTIVE: + { + FfxShaderBlob blob = fsr3UpscalerGetAutogenReactivePassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + default: + FFX_ASSERT_FAIL("Should never reach here."); + break; + } + + // return an empty blob + memset(outBlob, 0, sizeof(FfxShaderBlob)); + return FFX_OK; +} diff --git a/sdk/src/backends/shared/blob_accessors/ffx_fsr3upscaler_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_fsr3upscaler_shaderblobs.h new file mode 100644 index 00000000..97eead51 --- /dev/null +++ b/sdk/src/backends/shared/blob_accessors/ffx_fsr3upscaler_shaderblobs.h @@ -0,0 +1,41 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "../ffx_shader_blobs.h" +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif // #if defined(__cplusplus) + +// Get a DX12 shader blob for the specified pass and permutation index. +FfxErrorCode fsr3UpscalerGetPermutationBlobByIndex( + FfxFsr3UpscalerPass passId, + uint32_t permutationOptions, + FfxShaderBlob* outBlob); + +#if defined(__cplusplus) +} +#endif // #if defined(__cplusplus) diff --git a/sdk/src/backends/shared/blob_accessors/ffx_lens_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_lens_shaderblobs.cpp index 3fa0edd0..e6351c12 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_lens_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_lens_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_lens_shaderblobs.h" #include "lens/ffx_lens_private.h" @@ -92,7 +92,7 @@ FfxErrorCode lensGetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_lens_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_lens_shaderblobs.h index 98af84ec..54eee654 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_lens_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_lens_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_lpm_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_lpm_shaderblobs.cpp index e058f736..e75d435e 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_lpm_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_lpm_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_lpm_shaderblobs.h" #include "lpm/ffx_lpm_private.h" @@ -88,7 +88,7 @@ FfxErrorCode lpmGetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_lpm_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_lpm_shaderblobs.h index 74d9ecdd..1d6506c9 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_lpm_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_lpm_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_opticalflow_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_opticalflow_shaderblobs.cpp new file mode 100644 index 00000000..3f184385 --- /dev/null +++ b/sdk/src/backends/shared/blob_accessors/ffx_opticalflow_shaderblobs.cpp @@ -0,0 +1,265 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include "ffx_opticalflow_shaderblobs.h" +#include "opticalflow/ffx_opticalflow_private.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + + +#include // for memset + +#if defined(POPULATE_PERMUTATION_KEY) +#undef POPULATE_PERMUTATION_KEY +#endif // #if defined(POPULATE_PERMUTATION_KEY) +#define POPULATE_PERMUTATION_KEY(options, key) \ + key.index = 0; \ + key.FFX_OPTICALFLOW_OPTION_HDR_COLOR_INPUT = FFX_CONTAINS_FLAG(options, OPTICALFLOW_HDR_COLOR_INPUT); + +static FfxShaderBlob opticalflowGetComputeLuminancePyramidPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_opticalflow_compute_luminance_pyramid_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_opticalflow_compute_luminance_pyramid_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_compute_luminance_pyramid_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_opticalflow_compute_luminance_pyramid_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_compute_luminance_pyramid_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob opticalflowGetComputeScdDivergencePassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_opticalflow_compute_scd_divergence_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_opticalflow_compute_scd_divergence_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_compute_scd_divergence_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_opticalflow_compute_scd_divergence_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_compute_scd_divergence_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob opticalflowGetGenerateScdHistogramPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_opticalflow_generate_scd_histogram_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_opticalflow_generate_scd_histogram_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_generate_scd_histogram_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_opticalflow_generate_scd_histogram_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_generate_scd_histogram_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob opticalflowGetPrepareLumaPassPermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_opticalflow_prepare_luma_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_opticalflow_prepare_luma_pass_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_prepare_luma_pass_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_opticalflow_prepare_luma_pass_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_prepare_luma_pass_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob opticalflowGetComputeOpticalFlowAdvancedPassV5PermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_opticalflow_prepare_luma_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_opticalflow_compute_optical_flow_advanced_pass_v5_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_compute_optical_flow_advanced_pass_v5_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_opticalflow_compute_optical_flow_advanced_pass_v5_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_compute_optical_flow_advanced_pass_v5_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob opticalflowGetFilterOpticalFlowPassV5PermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_opticalflow_prepare_luma_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_opticalflow_filter_optical_flow_pass_v5_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_filter_optical_flow_pass_v5_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_opticalflow_filter_optical_flow_pass_v5_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_filter_optical_flow_pass_v5_PermutationInfo, tableIndex); + } +} + +static FfxShaderBlob opticalflowGetScaleOpticalFlowAdvancedPassV5PermutationBlobByIndex(uint32_t permutationOptions, bool isWave64, bool is16bit) +{ + ffx_opticalflow_prepare_luma_pass_PermutationKey key; + + POPULATE_PERMUTATION_KEY(permutationOptions, key); + + if (isWave64) + { + const int32_t tableIndex = g_ffx_opticalflow_scale_optical_flow_advanced_pass_v5_wave64_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_scale_optical_flow_advanced_pass_v5_wave64_PermutationInfo, tableIndex); + } + else + { + const int32_t tableIndex = g_ffx_opticalflow_scale_optical_flow_advanced_pass_v5_IndirectionTable[key.index]; + return POPULATE_SHADER_BLOB_FFX(g_ffx_opticalflow_scale_optical_flow_advanced_pass_v5_PermutationInfo, tableIndex); + } +} + +FfxErrorCode opticalflowGetPermutationBlobByIndex( + FfxOpticalflowPass passId, + uint32_t permutationOptions, + FfxShaderBlob* outBlob) { + + bool isWave64 = FFX_CONTAINS_FLAG(permutationOptions, OPTICALFLOW_SHADER_PERMUTATION_FORCE_WAVE64); + bool is16bit = FFX_CONTAINS_FLAG(permutationOptions, OPTICALFLOW_SHADER_PERMUTATION_ALLOW_FP16); + + switch (passId) { + + case FFX_OPTICALFLOW_PASS_PREPARE_LUMA: + { + FfxShaderBlob blob = opticalflowGetPrepareLumaPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_OPTICALFLOW_PASS_GENERATE_OPTICAL_FLOW_INPUT_PYRAMID: + { + FfxShaderBlob blob = opticalflowGetComputeLuminancePyramidPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_OPTICALFLOW_PASS_GENERATE_SCD_HISTOGRAM: + { + FfxShaderBlob blob = opticalflowGetGenerateScdHistogramPassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_OPTICALFLOW_PASS_COMPUTE_SCD_DIVERGENCE: + { + FfxShaderBlob blob = opticalflowGetComputeScdDivergencePassPermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_OPTICALFLOW_PASS_COMPUTE_OPTICAL_FLOW_ADVANCED_V5: + { + FfxShaderBlob blob = opticalflowGetComputeOpticalFlowAdvancedPassV5PermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_OPTICALFLOW_PASS_FILTER_OPTICAL_FLOW_V5: + { + FfxShaderBlob blob = opticalflowGetFilterOpticalFlowPassV5PermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + case FFX_OPTICALFLOW_PASS_SCALE_OPTICAL_FLOW_ADVANCED_V5: + { + FfxShaderBlob blob = opticalflowGetScaleOpticalFlowAdvancedPassV5PermutationBlobByIndex(permutationOptions, isWave64, is16bit); + memcpy(outBlob, &blob, sizeof(FfxShaderBlob)); + return FFX_OK; + } + + default: + FFX_ASSERT_FAIL("Should never reach here."); + break; + } + + // return an empty blob + memset(outBlob, 0, sizeof(FfxShaderBlob)); + return FFX_OK; +} diff --git a/sdk/src/backends/shared/blob_accessors/ffx_opticalflow_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_opticalflow_shaderblobs.h new file mode 100644 index 00000000..27105be3 --- /dev/null +++ b/sdk/src/backends/shared/blob_accessors/ffx_opticalflow_shaderblobs.h @@ -0,0 +1,41 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 "../ffx_shader_blobs.h" +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif // #if defined(__cplusplus) + +// Get a DX12 shader blob for the specified pass and permutation index. +FfxErrorCode opticalflowGetPermutationBlobByIndex( + FfxOpticalflowPass passId, + uint32_t permutationOptions, + FfxShaderBlob* outBlob); + +#if defined(__cplusplus) +} +#endif // #if defined(__cplusplus) diff --git a/sdk/src/backends/shared/blob_accessors/ffx_parallelsort_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_parallelsort_shaderblobs.cpp index c4f560eb..c2040f76 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_parallelsort_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_parallelsort_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_parallelsort_shaderblobs.h" #include "parallelsort/ffx_parallelsort_private.h" @@ -219,7 +219,7 @@ FfxErrorCode parallelSortGetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_parallelsort_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_parallelsort_shaderblobs.h index 1ca0813f..02987089 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_parallelsort_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_parallelsort_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_spd_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_spd_shaderblobs.cpp index 89748762..caafd399 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_spd_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_spd_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_spd_shaderblobs.h" #include "spd/ffx_spd_private.h" @@ -107,7 +107,7 @@ FfxErrorCode spdGetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_spd_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_spd_shaderblobs.h index ac9409a6..078e1843 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_spd_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_spd_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_sssr_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_sssr_shaderblobs.cpp index bca658f4..8394710f 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_sssr_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_sssr_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_sssr_shaderblobs.h" #include "sssr/ffx_sssr_private.h" @@ -271,7 +271,7 @@ FfxErrorCode sssrGetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_sssr_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_sssr_shaderblobs.h index ec1b876d..1a921bb0 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_sssr_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_sssr_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/blob_accessors/ffx_vrs_shaderblobs.cpp b/sdk/src/backends/shared/blob_accessors/ffx_vrs_shaderblobs.cpp index f3452850..224623e2 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_vrs_shaderblobs.cpp +++ b/sdk/src/backends/shared/blob_accessors/ffx_vrs_shaderblobs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include "ffx_vrs_shaderblobs.h" #include "vrs/ffx_vrs_private.h" @@ -101,7 +101,7 @@ FfxErrorCode vrsGetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/blob_accessors/ffx_vrs_shaderblobs.h b/sdk/src/backends/shared/blob_accessors/ffx_vrs_shaderblobs.h index 5747f851..4275a4d1 100644 --- a/sdk/src/backends/shared/blob_accessors/ffx_vrs_shaderblobs.h +++ b/sdk/src/backends/shared/blob_accessors/ffx_vrs_shaderblobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 "../ffx_shader_blobs.h" diff --git a/sdk/src/backends/shared/ffx_shader_blobs.cpp b/sdk/src/backends/shared/ffx_shader_blobs.cpp index 38c02904..721bf000 100644 --- a/sdk/src/backends/shared/ffx_shader_blobs.cpp +++ b/sdk/src/backends/shared/ffx_shader_blobs.cpp @@ -1,30 +1,33 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// +// 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 +// 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 "ffx_shader_blobs.h" #if defined(FFX_FSR) || defined(FFX_ALL) +#include "blob_accessors/ffx_fsr3upscaler_shaderblobs.h" #include "blob_accessors/ffx_fsr2_shaderblobs.h" #include "blob_accessors/ffx_fsr1_shaderblobs.h" +#include "blob_accessors/ffx_frameinterpolation_shaderblobs.h" +#include "blob_accessors/ffx_opticalflow_shaderblobs.h" #endif // #if defined(FFX_FSR) || defined(FFX_ALL) #if defined(FFX_SPD) || defined(FFX_ALL) @@ -79,7 +82,8 @@ FfxErrorCode ffxGetPermutationBlobByIndex( FfxEffect effectId, - FfxPass passId, + FfxPass passId, + FfxBindStage stageId, uint32_t permutationOptions, FfxShaderBlob* outBlob) { @@ -89,9 +93,16 @@ FfxErrorCode ffxGetPermutationBlobByIndex( #if defined(FFX_FSR) || defined(FFX_ALL) case FFX_EFFECT_FSR2: return fsr2GetPermutationBlobByIndex((FfxFsr2Pass)passId, permutationOptions, outBlob); - case FFX_EFFECT_FSR1: return fsr1GetPermutationBlobByIndex((FfxFsr1Pass)passId, permutationOptions, outBlob); + #if defined(FFX_FSR3) + case FFX_EFFECT_FSR3UPSCALER: + return fsr3UpscalerGetPermutationBlobByIndex((FfxFsr3UpscalerPass)passId, permutationOptions, outBlob); + case FFX_EFFECT_FRAMEINTERPOLATION: + return frameInterpolationGetPermutationBlobByIndex((FfxFrameInterpolationPass)passId, stageId, permutationOptions, outBlob); + case FFX_EFFECT_OPTICALFLOW: + return opticalflowGetPermutationBlobByIndex((FfxOpticalflowPass)passId, permutationOptions, outBlob); + #endif #endif // #if defined(FFX_FSR) || defined(FFX_ALL) #if defined(FFX_SPD) || defined(FFX_ALL) @@ -159,7 +170,7 @@ FfxErrorCode ffxGetPermutationBlobByIndex( } // return an empty blob - memset(&outBlob, 0, sizeof(FfxShaderBlob)); + memset(outBlob, 0, sizeof(FfxShaderBlob)); return FFX_OK; } diff --git a/sdk/src/backends/shared/ffx_shader_blobs.h b/sdk/src/backends/shared/ffx_shader_blobs.h index f0e7db16..d8197518 100644 --- a/sdk/src/backends/shared/ffx_shader_blobs.h +++ b/sdk/src/backends/shared/ffx_shader_blobs.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 @@ -34,6 +34,7 @@ struct FfxShaderBlob; // Get a shader blob for the specified effect, pass, and permutation index. FfxErrorCode ffxGetPermutationBlobByIndex(FfxEffect effectId, FfxPass passId, + FfxBindStage bindStage, uint32_t permutationOptions, FfxShaderBlob* outBlob); diff --git a/sdk/src/backends/vk/CMakeLists.txt b/sdk/src/backends/vk/CMakeLists.txt index 83c267a2..7a2c09eb 100644 --- a/sdk/src/backends/vk/CMakeLists.txt +++ b/sdk/src/backends/vk/CMakeLists.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. -# +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +# # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# +# 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 +# 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 @@ -224,14 +223,14 @@ CheckVulkanSDKVersion() file(GLOB PUBLIC_SHADERS FFX_PUBLIC_SHADER_SOURCES - "${FFX_GPU_PATH}/fsr2/*.h" + "${FFX_GPU_PATH}/fsr2/*.h" "${FFX_GPU_PATH}/fsr2/*.glsl" "${FFX_GPU_PATH}/fsr1/*.h" - "${FFX_GPU_PATH}/fsr1/*.glsl" + "${FFX_GPU_PATH}/fsr1/*.glsl" "${FFX_GPU_PATH}/spd/*.h" - "${FFX_GPU_PATH}/spd/*.glsl" - "${FFX_GPU_PATH}/lpm/*.h" - "${FFX_GPU_PATH}/lpm/*.glsl" + "${FFX_GPU_PATH}/spd/*.glsl" + "${FFX_GPU_PATH}/lpm/*.h" + "${FFX_GPU_PATH}/lpm/*.glsl" "${FFX_GPU_PATH}/cacao/*.h" "${FFX_GPU_PATH}/cacao/*.glsl" "${FFX_GPU_PATH}/cas/*.h" diff --git a/sdk/src/backends/vk/CMakeShadersBLUR.txt b/sdk/src/backends/vk/CMakeShadersBLUR.txt index 84f8e38a..6f87e13a 100644 --- a/sdk/src/backends/vk/CMakeShadersBLUR.txt +++ b/sdk/src/backends/vk/CMakeShadersBLUR.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersCACAO.txt b/sdk/src/backends/vk/CMakeShadersCACAO.txt index d8f75f34..974dedeb 100644 --- a/sdk/src/backends/vk/CMakeShadersCACAO.txt +++ b/sdk/src/backends/vk/CMakeShadersCACAO.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersCAS.txt b/sdk/src/backends/vk/CMakeShadersCAS.txt index 7f164d69..122e2ae4 100644 --- a/sdk/src/backends/vk/CMakeShadersCAS.txt +++ b/sdk/src/backends/vk/CMakeShadersCAS.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersClassifier.txt b/sdk/src/backends/vk/CMakeShadersClassifier.txt index 34db0dd2..f48f936a 100644 --- a/sdk/src/backends/vk/CMakeShadersClassifier.txt +++ b/sdk/src/backends/vk/CMakeShadersClassifier.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. -# +# +# Copyright (c) 2023 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 +# 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 +# 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 : -# +# 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 +# +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersDOF.txt b/sdk/src/backends/vk/CMakeShadersDOF.txt index c2da4531..ba9143ad 100644 --- a/sdk/src/backends/vk/CMakeShadersDOF.txt +++ b/sdk/src/backends/vk/CMakeShadersDOF.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersDenoiser.txt b/sdk/src/backends/vk/CMakeShadersDenoiser.txt index 9cf40824..410f449d 100644 --- a/sdk/src/backends/vk/CMakeShadersDenoiser.txt +++ b/sdk/src/backends/vk/CMakeShadersDenoiser.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. -# +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +# # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersFSR1.txt b/sdk/src/backends/vk/CMakeShadersFSR1.txt index f199ed04..9251ddc3 100644 --- a/sdk/src/backends/vk/CMakeShadersFSR1.txt +++ b/sdk/src/backends/vk/CMakeShadersFSR1.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersFSR2.txt b/sdk/src/backends/vk/CMakeShadersFSR2.txt index 296e637f..d28cd21e 100644 --- a/sdk/src/backends/vk/CMakeShadersFSR2.txt +++ b/sdk/src/backends/vk/CMakeShadersFSR2.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersLENS.txt b/sdk/src/backends/vk/CMakeShadersLENS.txt index 7a2d38a2..5894c6da 100644 --- a/sdk/src/backends/vk/CMakeShadersLENS.txt +++ b/sdk/src/backends/vk/CMakeShadersLENS.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersLPM.txt b/sdk/src/backends/vk/CMakeShadersLPM.txt index 889f25b0..f890b312 100644 --- a/sdk/src/backends/vk/CMakeShadersLPM.txt +++ b/sdk/src/backends/vk/CMakeShadersLPM.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersParallelSort.txt b/sdk/src/backends/vk/CMakeShadersParallelSort.txt index e60778cc..21d150f5 100644 --- a/sdk/src/backends/vk/CMakeShadersParallelSort.txt +++ b/sdk/src/backends/vk/CMakeShadersParallelSort.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersSPD.txt b/sdk/src/backends/vk/CMakeShadersSPD.txt index 5eadbb69..766ed20e 100644 --- a/sdk/src/backends/vk/CMakeShadersSPD.txt +++ b/sdk/src/backends/vk/CMakeShadersSPD.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersSSSR.txt b/sdk/src/backends/vk/CMakeShadersSSSR.txt index 17543389..a1c5f4d9 100644 --- a/sdk/src/backends/vk/CMakeShadersSSSR.txt +++ b/sdk/src/backends/vk/CMakeShadersSSSR.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/CMakeShadersVRS.txt b/sdk/src/backends/vk/CMakeShadersVRS.txt index f38b1750..8c4780c9 100644 --- a/sdk/src/backends/vk/CMakeShadersVRS.txt +++ b/sdk/src/backends/vk/CMakeShadersVRS.txt @@ -1,20 +1,19 @@ # This file is part of the FidelityFX SDK. -# -# Copyright © 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 diff --git a/sdk/src/backends/vk/ffx_vk.cpp b/sdk/src/backends/vk/ffx_vk.cpp index 020905ae..af382076 100644 --- a/sdk/src/backends/vk/ffx_vk.cpp +++ b/sdk/src/backends/vk/ffx_vk.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright © 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// +// 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 +// 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 #include #include @@ -33,7 +33,7 @@ FfxErrorCode CreateBackendContextVK(FfxInterface* backendInterface, Ff FfxErrorCode GetDeviceCapabilitiesVK(FfxInterface* backendInterface, FfxDeviceCapabilities* deviceCapabilities); FfxErrorCode DestroyBackendContextVK(FfxInterface* backendInterface, FfxUInt32 effectContextId); FfxErrorCode CreateResourceVK(FfxInterface* backendInterface, const FfxCreateResourceDescription* desc, FfxUInt32 effectContextId, FfxResourceInternal* outTexture); -FfxErrorCode DestroyResourceVK(FfxInterface* backendInterface, FfxResourceInternal resource); +FfxErrorCode DestroyResourceVK(FfxInterface* backendInterface, FfxResourceInternal resource, FfxUInt32 effectContextId); FfxErrorCode RegisterResourceVK(FfxInterface* backendInterface, const FfxResource* inResource, FfxUInt32 effectContextId, FfxResourceInternal* outResourceInternal); FfxResource GetResourceVK(FfxInterface* backendInterface, FfxResourceInternal resource); FfxErrorCode UnregisterResourcesVK(FfxInterface* backendInterface, FfxCommandList commandList, FfxUInt32 effectContextId); @@ -1131,7 +1131,7 @@ FfxErrorCode DestroyBackendContextVK(FfxInterface* backendInterface, FfxUInt32 e if (backendContext->pResources[currentStaticResourceIndex].imageResource != VK_NULL_HANDLE) { FFX_ASSERT_MESSAGE(false, "FFXInterface: Vulkan: SDK Resource was not destroyed prior to destroying the backend context. There is a resource leak."); FfxResourceInternal internalResource = { currentStaticResourceIndex }; - DestroyResourceVK(backendInterface, internalResource); + DestroyResourceVK(backendInterface, internalResource, effectContextId); } } @@ -1460,12 +1460,14 @@ FfxErrorCode CreateResourceVK( return FFX_OK; } -FfxErrorCode DestroyResourceVK(FfxInterface* backendInterface, FfxResourceInternal resource) +FfxErrorCode DestroyResourceVK(FfxInterface* backendInterface, FfxResourceInternal resource, FfxUInt32 effectContextId) { FFX_ASSERT(backendInterface != nullptr); BackendContext_VK* backendContext = (BackendContext_VK*)backendInterface->scratchBuffer; + BackendContext_VK::EffectContext& effectContext = backendContext->pEffectContexts[effectContextId]; - if (resource.internalIndex != -1) + if (resource.internalIndex != -1 && + ((resource.internalIndex >= int32_t(effectContextId * FFX_MAX_RESOURCE_COUNT)) && (resource.internalIndex < int32_t(effectContext.nextStaticResource)))) { BackendContext_VK::Resource& backgroundResource = backendContext->pResources[resource.internalIndex]; @@ -1818,7 +1820,7 @@ FfxErrorCode CreatePipelineVK(FfxInterface* backendInterface, // start by fetching the shader blob FfxShaderBlob shaderBlob = { }; - ffxGetPermutationBlobByIndex(effect, pass, permutationOptions, &shaderBlob); + ffxGetPermutationBlobByIndex(effect, pass, FFX_BIND_COMPUTE_SHADER_STAGE, permutationOptions, &shaderBlob); FFX_ASSERT(shaderBlob.data && shaderBlob.size); ////////////////////////////////////////////////////////////////////////// diff --git a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_accumulate_pass.glsl b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_accumulate_pass.glsl index ac915ef1..3445506a 100644 --- a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_accumulate_pass.glsl +++ b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_accumulate_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// of this softwareand 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 @@ -12,7 +12,7 @@ // The above copyright noticeand 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 +// 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 diff --git a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.glsl b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.glsl index a92559e3..5a1f8c96 100644 --- a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.glsl +++ b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_autogen_reactive_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// of this softwareand 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 @@ -12,7 +12,7 @@ // The above copyright noticeand 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 +// 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 diff --git a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.glsl b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.glsl index cd0b4d48..a7f0df1f 100644 --- a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.glsl +++ b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// of this softwareand 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 @@ -12,7 +12,7 @@ // The above copyright noticeand 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 +// 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 diff --git a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_depth_clip_pass.glsl b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_depth_clip_pass.glsl index cf038e13..58ba11cb 100644 --- a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_depth_clip_pass.glsl +++ b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_depth_clip_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// of this softwareand 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 @@ -12,7 +12,7 @@ // The above copyright noticeand 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 +// 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 diff --git a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_lock_pass.glsl b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_lock_pass.glsl index e0854afc..be22cde6 100644 --- a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_lock_pass.glsl +++ b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_lock_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// of this softwareand 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 @@ -12,7 +12,7 @@ // The above copyright noticeand 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 +// 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 diff --git a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_rcas_pass.glsl b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_rcas_pass.glsl index 3a464cbc..b73f1f95 100644 --- a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_rcas_pass.glsl +++ b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_rcas_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// of this softwareand 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 @@ -12,7 +12,7 @@ // The above copyright noticeand 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 +// 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 diff --git a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.glsl b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.glsl index c9d803d0..211f693a 100644 --- a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.glsl +++ b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_reconstruct_previous_depth_pass.glsl @@ -3,7 +3,7 @@ // Copyright © 2023 Advanced Micro Devices, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// of this softwareand 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 @@ -12,7 +12,7 @@ // The above copyright noticeand 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 +// 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 diff --git a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.glsl b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.glsl index 3f17526a..ffbe7524 100644 --- a/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.glsl +++ b/sdk/src/backends/vk/shaders/fsr2/ffx_fsr2_tcr_autogen_pass.glsl @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. // // Copyright © 2023 Advanced Micro Devices, Inc. -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this softwareand associated documentation files(the “Software”), to deal // in the Software without restriction, including without limitation the rights @@ -11,7 +11,7 @@ // // The above copyright noticeand 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 diff --git a/sdk/src/components/blur/CMakeLists.txt b/sdk/src/components/blur/CMakeLists.txt index 06f353da..fdce2e4e 100644 --- a/sdk/src/components/blur/CMakeLists.txt +++ b/sdk/src/components/blur/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_BLUR OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/blur/ffx_blur.cpp b/sdk/src/components/blur/ffx_blur.cpp index 2fb78712..55fa8de7 100644 --- a/sdk/src/components/blur/ffx_blur.cpp +++ b/sdk/src/components/blur/ffx_blur.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 // for wstring #include // for memset #include // for _countof diff --git a/sdk/src/components/blur/ffx_blur_private.h b/sdk/src/components/blur/ffx_blur_private.h index bc13b2a6..d7d2fb1a 100644 --- a/sdk/src/components/blur/ffx_blur_private.h +++ b/sdk/src/components/blur/ffx_blur_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 diff --git a/sdk/src/components/cacao/CMakeLists.txt b/sdk/src/components/cacao/CMakeLists.txt index decf5c9e..900b814c 100644 --- a/sdk/src/components/cacao/CMakeLists.txt +++ b/sdk/src/components/cacao/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_CACAO OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/cacao/ffx_cacao.cpp b/sdk/src/components/cacao/ffx_cacao.cpp index 3dd51148..bf8aecb8 100644 --- a/sdk/src/components/cacao/ffx_cacao.cpp +++ b/sdk/src/components/cacao/ffx_cacao.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 // memcpy #include // cos, sin #include @@ -828,7 +828,7 @@ static FfxErrorCode cacaoRelease(FfxCacaoContext_Private* context) for (uint32_t i = 0; i < FFX_CACAO_RESOURCE_IDENTIFIER_COUNT; ++i) { - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->textures[i]); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->textures[i], context->effectContextId); } // Destroy the context diff --git a/sdk/src/components/cacao/ffx_cacao_private.h b/sdk/src/components/cacao/ffx_cacao_private.h index bda6ec15..7e9e14e0 100644 --- a/sdk/src/components/cacao/ffx_cacao_private.h +++ b/sdk/src/components/cacao/ffx_cacao_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 diff --git a/sdk/src/components/cas/CMakeLists.txt b/sdk/src/components/cas/CMakeLists.txt index 1a4d6cd8..71d9553f 100644 --- a/sdk/src/components/cas/CMakeLists.txt +++ b/sdk/src/components/cas/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_CAS OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/cas/ffx_cas.cpp b/sdk/src/components/cas/ffx_cas.cpp index 1d868a58..939fbd06 100644 --- a/sdk/src/components/cas/ffx_cas.cpp +++ b/sdk/src/components/cas/ffx_cas.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 // for memset #include // for _countof #include // for fabs, abs, sinf, sqrt, etc. diff --git a/sdk/src/components/cas/ffx_cas_private.h b/sdk/src/components/cas/ffx_cas_private.h index e4fb93ea..784a1561 100644 --- a/sdk/src/components/cas/ffx_cas_private.h +++ b/sdk/src/components/cas/ffx_cas_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 diff --git a/sdk/src/components/classifier/CMakeLists.txt b/sdk/src/components/classifier/CMakeLists.txt index 68ac572f..449e434f 100644 --- a/sdk/src/components/classifier/CMakeLists.txt +++ b/sdk/src/components/classifier/CMakeLists.txt @@ -1,7 +1,7 @@ # This file is part of the FidelityFX SDK. -# +# # Copyright (c) 2023 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 @@ -10,7 +10,7 @@ # 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 @@ -20,7 +20,6 @@ # THE SOFTWARE. if (FFX_CLASSIFIER OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/classifier/ffx_classifier.cpp b/sdk/src/components/classifier/ffx_classifier.cpp index 1fe2e4aa..9045c681 100644 --- a/sdk/src/components/classifier/ffx_classifier.cpp +++ b/sdk/src/components/classifier/ffx_classifier.cpp @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #include // for memset #include // for _countof #include // for fabs, abs, sinf, sqrt, etc. diff --git a/sdk/src/components/classifier/ffx_classifier_private.h b/sdk/src/components/classifier/ffx_classifier_private.h index 62750c48..8deda7f4 100644 --- a/sdk/src/components/classifier/ffx_classifier_private.h +++ b/sdk/src/components/classifier/ffx_classifier_private.h @@ -1,7 +1,7 @@ // This file is part of the FidelityFX SDK. -// +// // Copyright (c) 2023 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 @@ -10,7 +10,7 @@ // 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 @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + #pragma once #include diff --git a/sdk/src/components/denoiser/CMakeLists.txt b/sdk/src/components/denoiser/CMakeLists.txt index 5dc6083f..6cd16c21 100644 --- a/sdk/src/components/denoiser/CMakeLists.txt +++ b/sdk/src/components/denoiser/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_DENOISER OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/denoiser/ffx_denoiser.cpp b/sdk/src/components/denoiser/ffx_denoiser.cpp index ab4a4e27..7cb535fd 100644 --- a/sdk/src/components/denoiser/ffx_denoiser.cpp +++ b/sdk/src/components/denoiser/ffx_denoiser.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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 // for memset #include // for _countof #include // for fabs, abs, sinf, sqrt, etc. @@ -960,7 +960,7 @@ static FfxErrorCode denoiserRelease(FfxDenoiserContext_Private* context) // release internal resources for (int32_t currentResourceIndex = 0; currentResourceIndex < FFX_DENOISER_RESOURCE_IDENTIFIER_COUNT; ++currentResourceIndex) { - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[currentResourceIndex]); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[currentResourceIndex], context->effectContextId); } // Destroy the context diff --git a/sdk/src/components/denoiser/ffx_denoiser_private.h b/sdk/src/components/denoiser/ffx_denoiser_private.h index dcd5db33..35a1ceb2 100644 --- a/sdk/src/components/denoiser/ffx_denoiser_private.h +++ b/sdk/src/components/denoiser/ffx_denoiser_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. -// +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// +// 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 +// 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 diff --git a/sdk/src/components/dof/CMakeLists.txt b/sdk/src/components/dof/CMakeLists.txt index 6ef8c78d..d9e42625 100644 --- a/sdk/src/components/dof/CMakeLists.txt +++ b/sdk/src/components/dof/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_DOF OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/dof/ffx_dof.cpp b/sdk/src/components/dof/ffx_dof.cpp index c5016b9b..9048e594 100644 --- a/sdk/src/components/dof/ffx_dof.cpp +++ b/sdk/src/components/dof/ffx_dof.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 // for memset #include // for _countof #include // for fabs, abs, sinf, sqrt, etc. @@ -438,13 +438,13 @@ static FfxErrorCode dofRelease(FfxDofContext_Private* context) context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_OUTPUT_COLOR] = { FFX_DOF_RESOURCE_IDENTIFIER_NULL }; // Release internal resources - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_BILAT_COLOR]); - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_RADIUS]); - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_DILATED_RADIUS]); - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_NEAR]); - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_FAR]); - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_GLOBALS]); - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_GLOBALS]); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_BILAT_COLOR], context->effectContextId); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_RADIUS], context->effectContextId); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_DILATED_RADIUS], context->effectContextId); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_NEAR], context->effectContextId); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_FAR], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_GLOBALS], context->effectContextId); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_GLOBALS], context->effectContextId); // Destroy the context context->contextDescription.backendInterface.fpDestroyBackendContext(&context->contextDescription.backendInterface, context->effectContextId); diff --git a/sdk/src/components/dof/ffx_dof_private.h b/sdk/src/components/dof/ffx_dof_private.h index a0f9a1d6..5e1bebaa 100644 --- a/sdk/src/components/dof/ffx_dof_private.h +++ b/sdk/src/components/dof/ffx_dof_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 diff --git a/sdk/src/components/frameinterpolation/CMakeLists.txt b/sdk/src/components/frameinterpolation/CMakeLists.txt new file mode 100644 index 00000000..13fa9b70 --- /dev/null +++ b/sdk/src/components/frameinterpolation/CMakeLists.txt @@ -0,0 +1,56 @@ +# This file is part of the FidelityFX SDK. +# +# Copyright (c) 2023 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 (FFX_FI OR FFX_FSR2 OR FFX_FSR3 OR FFX_ALL) + # Shared sources + set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) + + # Private sources + file(GLOB PRIVATE_SOURCES + # NOTE that ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp(h)" can also be used instead + # simply including effect name in the path for emphasis + "${FFX_COMPONENTS_PATH}/frameinterpolation/*.cpp" + "${FFX_COMPONENTS_PATH}/frameinterpolation/*.h") + + # Public source + file(GLOB PUBLIC_SOURCES + "${FFX_HOST_PATH}/frameinterpolation/*.h" + "${FFX_HOST_PATH}/frameinterpolation/*.cpp") + list(APPEND PUBLIC_SOURCES ${FFX_PUBLIC_SOURCES}) + + if (FFX_BUILD_AS_DLL) + add_library(ffx_frameinterpolation_${FFX_PLATFORM_NAME} SHARED ${SHARED_SOURCES} ${PRIVATE_SOURCES} ${PUBLIC_SOURCES}) + else() + add_library(ffx_frameinterpolation_${FFX_PLATFORM_NAME} STATIC ${SHARED_SOURCES} ${PRIVATE_SOURCES} ${PUBLIC_SOURCES}) + endif() + + # API + source_group("shared_source" FILES ${SHARED_SOURCES}) + source_group("private_source" FILES ${PRIVATE_SOURCES}) + source_group("public_source" FILES ${PUBLIC_SOURCES}) + + target_include_directories(ffx_frameinterpolation_${FFX_PLATFORM_NAME} PUBLIC ${FFX_INCLUDE_PATH}) + target_include_directories(ffx_frameinterpolation_${FFX_PLATFORM_NAME} PUBLIC ${FFX_SHARED_PATH}) + + set_source_files_properties(${SHADERS} PROPERTIES HEADER_FILE_ONLY TRUE) + set_target_properties(ffx_frameinterpolation_${FFX_PLATFORM_NAME} PROPERTIES FOLDER Components) + +endif() \ No newline at end of file diff --git a/sdk/src/components/frameinterpolation/ffx_frameinterpolation.cpp b/sdk/src/components/frameinterpolation/ffx_frameinterpolation.cpp new file mode 100644 index 00000000..1b3c0365 --- /dev/null +++ b/sdk/src/components/frameinterpolation/ffx_frameinterpolation.cpp @@ -0,0 +1,848 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 // for max used inside SPD CPU code. +#include // for fabs, abs, sinf, sqrt, etc. +#include // for memset +#include // for FLT_EPSILON +#include + +#define FFX_CPU + +#include +#include +#include + +#include "ffx_frameinterpolation_private.h" + +// max queued frames for descriptor management +static const uint32_t FSR3_MAX_QUEUED_FRAMES = 16; + +// lists to map shader resource bindpoint name to resource identifier +typedef struct ResourceBinding +{ + uint32_t index; + wchar_t name[64]; +}ResourceBinding; + +static const ResourceBinding srvResourceBindingTable[] = +{ + // Frame Interpolation textures + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_DEPTH, L"r_dilated_depth"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS, L"r_dilated_motion_vectors"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME, L"r_reconstructed_depth_previous_frame"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME, L"r_reconstructed_depth_interpolated_frame"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PREVIOUS_INTERPOLATION_SOURCE, L"r_previous_interpolation_source"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_CURRENT_INTERPOLATION_SOURCE, L"r_current_interpolation_source"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DISOCCLUSION_MASK, L"r_disocclusion_mask"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_X, L"r_game_motion_vector_field_x"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_Y, L"r_game_motion_vector_field_y"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X, L"r_optical_flow_motion_vector_field_x"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y, L"r_optical_flow_motion_vector_field_y"}, + + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_VECTOR, L"r_optical_flow"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_CONFIDENCE, L"r_optical_flow_confidence"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_GLOBAL_MOTION, L"r_optical_flow_global_motion"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCENE_CHANGE_DETECTION, L"r_optical_flow_scd"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OUTPUT, L"r_output"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID, L"r_inpainting_pyramid"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PRESENT_BACKBUFFER, L"r_present_backbuffer"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNTERS, L"r_counters"}, +}; + +static const ResourceBinding uavResourceBindingTable[] = +{ + // Frame Interpolation textures + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_DEPTH, L"rw_dilated_depth"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS, L"rw_dilated_motion_vectors"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME, L"rw_reconstructed_depth_previous_frame"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME, L"rw_reconstructed_depth_interpolated_frame"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OUTPUT, L"rw_output"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DISOCCLUSION_MASK, L"rw_disocclusion_mask"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_X, L"rw_game_motion_vector_field_x"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_Y, L"rw_game_motion_vector_field_y"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X, L"rw_optical_flow_motion_vector_field_x"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y, L"rw_optical_flow_motion_vector_field_y"}, + + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNTERS, L"rw_counters"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_0, L"rw_inpainting_pyramid0"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_1, L"rw_inpainting_pyramid1"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_2, L"rw_inpainting_pyramid2"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_3, L"rw_inpainting_pyramid3"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_4, L"rw_inpainting_pyramid4"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_5, L"rw_inpainting_pyramid5"}, // extra declaration, as this is globallycoherent + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_6, L"rw_inpainting_pyramid6"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_7, L"rw_inpainting_pyramid7"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_8, L"rw_inpainting_pyramid8"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_9, L"rw_inpainting_pyramid9"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_10, L"rw_inpainting_pyramid10"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_11, L"rw_inpainting_pyramid11"}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_12, L"rw_inpainting_pyramid12"}, +}; + +static const ResourceBinding cbResourceBindingTable[] = +{ + {FFX_FRAMEINTERPOLATION_CONSTANTBUFFER_IDENTIFIER, L"cbFI"}, + {FFX_FRAMEINTERPOLATION_INPAINTING_PYRAMID_CONSTANTBUFFER_IDENTIFIER, L"cbInpaintingPyramid"}, +}; + +// Broad structure of the root signature. +typedef enum FrameInterpolationRootSignatureLayout { + + FRAMEINTERPOLATION_ROOT_SIGNATURE_LAYOUT_UAVS, + FRAMEINTERPOLATION_ROOT_SIGNATURE_LAYOUT_SRVS, + FRAMEINTERPOLATION_ROOT_SIGNATURE_LAYOUT_CONSTANTS, + FRAMEINTERPOLATION_ROOT_SIGNATURE_LAYOUT_CONSTANTS_REGISTER_1, + FRAMEINTERPOLATION_ROOT_SIGNATURE_LAYOUT_PARAMETER_COUNT +} FrameInterpolationRootSignatureLayout; + +typedef union FrameInterpolationSecondaryUnion +{ + InpaintingPyramidConstants inpaintingPyramidConstants; +} FrameInterpolationSecondaryUnion; + +FfxConstantBuffer globalFrameInterpolationConstantBuffers[] = { + {sizeof(FrameInterpolationConstants) / sizeof(uint32_t)}, + {sizeof(InpaintingPyramidConstants) / sizeof(uint32_t)} +}; + +// Lanczos +static float lanczos2(float value) +{ + return abs(value) < FFX_EPSILON ? 1.f : (sinf(FFX_PI * value) / (FFX_PI * value)) * (sinf(0.5f * FFX_PI * value) / (0.5f * FFX_PI * value)); +} + +// Calculate halton number for index and base. +static float halton(int32_t index, int32_t base) +{ + float f = 1.0f, result = 0.0f; + + for (int32_t currentIndex = index; currentIndex > 0;) { + + f /= (float)base; + result = result + f * (float)(currentIndex % base); + currentIndex = (uint32_t)(floorf((float)(currentIndex) / (float)(base))); + } + + return result; +} + +static FfxErrorCode patchResourceBindings(FfxPipelineState* inoutPipeline) +{ + for (uint32_t srvIndex = 0; srvIndex < inoutPipeline->srvTextureCount; ++srvIndex) + { + int32_t mapIndex = 0; + for (mapIndex = 0; mapIndex < _countof(srvResourceBindingTable); ++mapIndex) + { + if (0 == wcscmp(srvResourceBindingTable[mapIndex].name, inoutPipeline->srvTextureBindings[srvIndex].name)) + break; + } + if (mapIndex == _countof(srvResourceBindingTable)) + return FFX_ERROR_INVALID_ARGUMENT; + + inoutPipeline->srvTextureBindings[srvIndex].resourceIdentifier = srvResourceBindingTable[mapIndex].index; + } + + // check for UAVs where mip chains are to be bound + for (uint32_t uavIndex = 0; uavIndex < inoutPipeline->uavTextureCount; ++uavIndex) + { + int32_t mapIndex = 0; + for (mapIndex = 0; mapIndex < _countof(uavResourceBindingTable); ++mapIndex) + { + if (0 == wcscmp(uavResourceBindingTable[mapIndex].name, inoutPipeline->uavTextureBindings[uavIndex].name)) + break; + } + if (mapIndex == _countof(uavResourceBindingTable)) + return FFX_ERROR_INVALID_ARGUMENT; + + inoutPipeline->uavTextureBindings[uavIndex].resourceIdentifier = uavResourceBindingTable[mapIndex].index; + } + inoutPipeline->uavTextureCount = inoutPipeline->uavTextureCount; + + for (uint32_t cbIndex = 0; cbIndex < inoutPipeline->constCount; ++cbIndex) + { + int32_t mapIndex = 0; + for (mapIndex = 0; mapIndex < _countof(cbResourceBindingTable); ++mapIndex) + { + if (0 == wcscmp(cbResourceBindingTable[mapIndex].name, inoutPipeline->constantBufferBindings[cbIndex].name)) + break; + } + if (mapIndex == _countof(cbResourceBindingTable)) + return FFX_ERROR_INVALID_ARGUMENT; + + inoutPipeline->constantBufferBindings[cbIndex].resourceIdentifier = cbResourceBindingTable[mapIndex].index; + } + + return FFX_OK; +} + +static uint32_t getPipelinePermutationFlags(uint32_t contextFlags, FfxPass passId, bool fp16, bool force64, bool useLut) +{ + // work out what permutation to load. + uint32_t flags = 0; + flags |= (contextFlags & FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED) ? FRAMEINTERPOLATION_SHADER_PERMUTATION_DEPTH_INVERTED : 0; + flags |= (force64) ? FRAMEINTERPOLATION_SHADER_PERMUTATION_FORCE_WAVE64 : 0; + flags |= (fp16) ? FRAMEINTERPOLATION_SHADER_PERMUTATION_ALLOW_FP16 : 0; + return flags; +} + +static FfxErrorCode createPipelineStates(FfxFrameInterpolationContext_Private* context) +{ + FFX_ASSERT(context); + + FfxPipelineDescription pipelineDescription = {}; + pipelineDescription.contextFlags = context->contextDescription.flags; + pipelineDescription.stage = FFX_BIND_COMPUTE_SHADER_STAGE; + + // Samplers + pipelineDescription.samplerCount = 2; + FfxSamplerDescription samplerDescs[2] = { + {FFX_FILTER_TYPE_MINMAGMIP_POINT, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_BIND_COMPUTE_SHADER_STAGE}, + {FFX_FILTER_TYPE_MINMAGMIP_LINEAR, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_BIND_COMPUTE_SHADER_STAGE}}; + pipelineDescription.samplers = samplerDescs; + + // Root constants + pipelineDescription.rootConstantBufferCount = 2; + FfxRootConstantDescription rootConstantDescs[2] = + { + {sizeof(FrameInterpolationConstants) / sizeof(uint32_t), FFX_BIND_COMPUTE_SHADER_STAGE}, + {sizeof(InpaintingPyramidConstants) / sizeof(uint32_t), FFX_BIND_COMPUTE_SHADER_STAGE} + }; + pipelineDescription.rootConstants = rootConstantDescs; + + // Query device capabilities + FfxDeviceCapabilities capabilities; + context->contextDescription.backendInterface.fpGetDeviceCapabilities(&context->contextDescription.backendInterface, &capabilities); + + // Setup a few options used to determine permutation flags + bool haveShaderModel66 = capabilities.minimumSupportedShaderModel >= FFX_SHADER_MODEL_6_6; + bool supportedFP16 = capabilities.fp16Supported; + bool canForceWave64 = false; + bool useLut = false; + + const uint32_t waveLaneCountMin = capabilities.waveLaneCountMin; + const uint32_t waveLaneCountMax = capabilities.waveLaneCountMax; + if (waveLaneCountMin == 32 && waveLaneCountMax == 64) + { + useLut = true; + canForceWave64 = haveShaderModel66; + } + else + canForceWave64 = false; + + // Work out what permutation to load. + uint32_t contextFlags = context->contextDescription.flags; + + // Set up pipeline descriptor (basically RootSignature and binding) + auto CreateComputePipeline = [&](FfxPass pass, const wchar_t* name, FfxPipelineState* pipeline) -> FfxErrorCode { + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, pipeline, context->effectContextId); + wcscpy_s(pipelineDescription.name, name); + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline( + &context->contextDescription.backendInterface, + FFX_EFFECT_FRAMEINTERPOLATION, + pass, + getPipelinePermutationFlags(contextFlags, pass, supportedFP16, canForceWave64, useLut), + &pipelineDescription, + context->effectContextId, + pipeline)); + patchResourceBindings(pipeline); + + return FFX_OK; + }; + + auto CreateRasterPipeline = [&](FfxPass pass, const wchar_t* name, FfxPipelineState* pipeline) -> FfxErrorCode { + wcscpy_s(pipelineDescription.name, name); + pipelineDescription.stage = (FfxBindStage)(FFX_BIND_VERTEX_SHADER_STAGE | FFX_BIND_PIXEL_SHADER_STAGE); + pipelineDescription.backbufferFormat = context->contextDescription.backBufferFormat; + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline( + &context->contextDescription.backendInterface, + FFX_EFFECT_FRAMEINTERPOLATION, + pass, + getPipelinePermutationFlags(contextFlags, pass, supportedFP16, canForceWave64, useLut), + &pipelineDescription, + context->effectContextId, + pipeline)); + + return FFX_OK; + }; + + // Frame Interpolation Pipelines + CreateComputePipeline(FFX_FRAMEINTERPOLATION_PASS_SETUP, L"SETUP", &context->pipelineFiSetup); + CreateComputePipeline(FFX_FRAMEINTERPOLATION_PASS_RECONSTRUCT_PREV_DEPTH, L"RECONSTRUCT_PREV_DEPTH", &context->pipelineFiReconstructPreviousDepth); + CreateComputePipeline(FFX_FRAMEINTERPOLATION_PASS_GAME_MOTION_VECTOR_FIELD, L"GAME_MOTION_VECTOR_FIELD", &context->pipelineFiGameMotionVectorField); + CreateComputePipeline(FFX_FRAMEINTERPOLATION_PASS_OPTICAL_FLOW_VECTOR_FIELD, L"OPTICAL_FLOW_VECTOR_FIELD", &context->pipelineFiOpticalFlowVectorField); + CreateComputePipeline(FFX_FRAMEINTERPOLATION_PASS_DISOCCLUSION_MASK, L"DISOCCLUSION_MASK", &context->pipelineFiDisocclusionMask); + CreateComputePipeline(FFX_FRAMEINTERPOLATION_PASS_INTERPOLATION, L"INTERPOLATION", &context->pipelineFiScfi); + CreateComputePipeline(FFX_FRAMEINTERPOLATION_PASS_INPAINTING_PYRAMID, L"INPAINTING_PYRAMID", &context->pipelineInpaintingPyramid); + CreateComputePipeline(FFX_FRAMEINTERPOLATION_PASS_INPAINTING, L"INPAINTING", &context->pipelineInpainting); + CreateComputePipeline(FFX_FRAMEINTERPOLATION_PASS_GAME_VECTOR_FIELD_INPAINTING_PYRAMID, L"GAME_VECTOR_FIELD_INPAINTING_PYRAMID", & context->pipelineGameVectorFieldInpaintingPyramid); + CreateComputePipeline(FFX_FRAMEINTERPOLATION_PASS_DEBUG_VIEW, L"DEBUG_VIEW", &context->pipelineDebugView); + + return FFX_OK; +} + +static FfxErrorCode frameinterpolationCreate(FfxFrameInterpolationContext_Private* context, const FfxFrameInterpolationContextDescription* contextDescription) +{ + FFX_ASSERT(context); + FFX_ASSERT(contextDescription); + + // Setup the data for implementation. + memset(context, 0, sizeof(FfxFrameInterpolationContext_Private)); + context->device = contextDescription->backendInterface.device; + + memcpy(&context->contextDescription, contextDescription, sizeof(FfxFrameInterpolationContextDescription)); + + // Create the context. + FfxErrorCode errorCode = context->contextDescription.backendInterface.fpCreateBackendContext(&context->contextDescription.backendInterface, &context->effectContextId); + FFX_RETURN_ON_ERROR(errorCode == FFX_OK, errorCode); + + // call out for device caps. + errorCode = context->contextDescription.backendInterface.fpGetDeviceCapabilities(&context->contextDescription.backendInterface, &context->deviceCapabilities); + FFX_RETURN_ON_ERROR(errorCode == FFX_OK, errorCode); + + // set defaults + context->firstExecution = true; + + context->constants.maxRenderSize[0] = contextDescription->maxRenderSize.width; + context->constants.maxRenderSize[1] = contextDescription->maxRenderSize.height; + context->constants.displaySize[0] = contextDescription->displaySize.width; + context->constants.displaySize[1] = contextDescription->displaySize.height; + context->constants.displaySizeRcp[0] = 1.0f / contextDescription->displaySize.width; + context->constants.displaySizeRcp[1] = 1.0f / contextDescription->displaySize.height; + context->constants.interpolationRectBase[0] = 0; + context->constants.interpolationRectBase[1] = 0; + context->constants.interpolationRectSize[0] = contextDescription->displaySize.width; + context->constants.interpolationRectSize[1] = contextDescription->displaySize.height; + + // generate the data for the LUT. + const uint32_t lanczos2LutWidth = 128; + int16_t lanczos2Weights[lanczos2LutWidth] = { }; + + for (uint32_t currentLanczosWidthIndex = 0; currentLanczosWidthIndex < lanczos2LutWidth; currentLanczosWidthIndex++) { + + const float x = 2.0f * currentLanczosWidthIndex / float(lanczos2LutWidth - 1); + const float y = lanczos2(x); + lanczos2Weights[currentLanczosWidthIndex] = int16_t(roundf(y * 32767.0f)); + } + + uint8_t defaultReactiveMaskData = 0U; + uint32_t atomicInitData[2] = { 0, 0 }; + float defaultExposure[] = { 0.0f, 0.0f }; + const FfxResourceType texture1dResourceType = (context->contextDescription.flags & FFX_FRAMEINTERPOLATION_ENABLE_TEXTURE1D_USAGE) ? FFX_RESOURCE_TYPE_TEXTURE1D : FFX_RESOURCE_TYPE_TEXTURE2D; + + // declare internal resources needed + const FfxInternalResourceDescription internalSurfaceDesc[] = { + + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME, L"FI_ReconstructedDepthInterpolatedFrame", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R32_UINT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_X, L"FI_GameMotionVectorFieldX", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R32_UINT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_Y, L"FI_GameMotionVectorFieldY", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R32_UINT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID, L"FI_InpaintingPyramid", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, contextDescription->displaySize.width / 2, contextDescription->displaySize.height / 2, 0, FFX_RESOURCE_FLAGS_ALIASABLE }, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNTERS, L"FI_Counters", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R32_UINT, 2, 1, 1, FFX_RESOURCE_FLAGS_ALIASABLE, sizeof(atomicInitData), atomicInitData }, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X, L"FI_OpticalFlowMotionVectorFieldX", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R32_UINT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y, L"FI_OpticalFlowMotionVectorFieldY", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R32_UINT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PREVIOUS_INTERPOLATION_SOURCE, L"FI_PreviousInterpolationSouce", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + contextDescription->backBufferFormat, contextDescription->displaySize.width, contextDescription->displaySize.height, 1, FFX_RESOURCE_FLAGS_NONE}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DISOCCLUSION_MASK, L"FI_DisocclusionMask", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8G8_UNORM, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE}, + }; + + // clear the SRV resources to NULL. + memset(context->srvResources, 0, sizeof(context->srvResources)); + + for (int32_t currentSurfaceIndex = 0; currentSurfaceIndex < FFX_ARRAY_ELEMENTS(internalSurfaceDesc); ++currentSurfaceIndex) { + + const FfxInternalResourceDescription* currentSurfaceDescription = &internalSurfaceDesc[currentSurfaceIndex]; + const FfxResourceType resourceType = currentSurfaceDescription->height > 1 ? FFX_RESOURCE_TYPE_TEXTURE2D : texture1dResourceType; + const FfxResourceDescription resourceDescription = { resourceType, currentSurfaceDescription->format, currentSurfaceDescription->width, currentSurfaceDescription->height, 1, currentSurfaceDescription->mipCount, FFX_RESOURCE_FLAGS_NONE, currentSurfaceDescription->usage }; + FfxResourceStates initialState = FFX_RESOURCE_STATE_UNORDERED_ACCESS; + if (currentSurfaceDescription->usage == FFX_RESOURCE_USAGE_READ_ONLY) initialState = FFX_RESOURCE_STATE_COMPUTE_READ; + if (currentSurfaceDescription->usage == FFX_RESOURCE_USAGE_RENDERTARGET) initialState = FFX_RESOURCE_STATE_COMMON; + + const FfxCreateResourceDescription createResourceDescription = { FFX_HEAP_TYPE_DEFAULT, resourceDescription, initialState, currentSurfaceDescription->initDataSize, currentSurfaceDescription->initData, currentSurfaceDescription->name, currentSurfaceDescription->id }; + + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreateResource(&context->contextDescription.backendInterface, &createResourceDescription, context->effectContextId, &context->srvResources[currentSurfaceDescription->id])); + } + + // copy resources to uavResrouces list + memcpy(context->uavResources, context->srvResources, sizeof(context->srvResources)); + + // avoid compiling pipelines on first render + { + context->refreshPipelineStates = false; + errorCode = createPipelineStates(context); + FFX_RETURN_ON_ERROR(errorCode == FFX_OK, errorCode); + } + return FFX_OK; +} + +static FfxErrorCode frameinterpolationRelease(FfxFrameInterpolationContext_Private* context) +{ + FFX_ASSERT(context); + + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineFiSetup, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineFiReconstructPreviousDepth, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineFiGameMotionVectorField, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineFiOpticalFlowVectorField, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineFiDisocclusionMask, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineFiScfi, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineInpaintingPyramid, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineInpainting, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineGameVectorFieldInpaintingPyramid, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineDebugView, context->effectContextId); + + // unregister resources not created internally + context->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_CURRENT_INTERPOLATION_SOURCE] = {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_NULL}; + context->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_VECTOR] = {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_NULL}; + context->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_CONFIDENCE] = {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_NULL}; + context->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_GLOBAL_MOTION] = {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_NULL}; + context->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCENE_CHANGE_DETECTION] = {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_NULL}; + context->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OUTPUT] = {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_NULL}; + context->uavResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OUTPUT] = {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_NULL}; + + // Release the copy resources for those that had init data + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNTERS], context->effectContextId); + + // release internal resources + for (int32_t currentResourceIndex = 0; currentResourceIndex < FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNT; ++currentResourceIndex) { + + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[currentResourceIndex], context->effectContextId); + } + + // Destroy the context + context->contextDescription.backendInterface.fpDestroyBackendContext(&context->contextDescription.backendInterface, context->effectContextId); + + return FFX_OK; +} + +static void scheduleDispatch(FfxFrameInterpolationContext_Private* context, const FfxPipelineState* pipeline, uint32_t dispatchX, uint32_t dispatchY) +{ + FfxComputeJobDescription jobDescriptor = {}; + + for (uint32_t currentShaderResourceViewIndex = 0; currentShaderResourceViewIndex < pipeline->srvTextureCount; ++currentShaderResourceViewIndex) + { + const uint32_t currentResourceId = pipeline->srvTextureBindings[currentShaderResourceViewIndex].resourceIdentifier; + const FfxResourceInternal currentResource = context->srvResources[currentResourceId]; + jobDescriptor.srvTextures[currentShaderResourceViewIndex] = currentResource; + wcscpy_s(jobDescriptor.srvTextureNames[currentShaderResourceViewIndex], pipeline->srvTextureBindings[currentShaderResourceViewIndex].name); + } + + for (uint32_t currentUnorderedAccessViewIndex = 0; currentUnorderedAccessViewIndex < pipeline->uavTextureCount; ++currentUnorderedAccessViewIndex) { + + const uint32_t currentResourceId = pipeline->uavTextureBindings[currentUnorderedAccessViewIndex].resourceIdentifier; + wcscpy_s(jobDescriptor.uavTextureNames[currentUnorderedAccessViewIndex], pipeline->uavTextureBindings[currentUnorderedAccessViewIndex].name); + + if (currentResourceId >= FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_0 && currentResourceId <= FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_12) + { + const FfxResourceInternal currentResource = context->uavResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID]; + jobDescriptor.uavTextures[currentUnorderedAccessViewIndex] = currentResource; + jobDescriptor.uavTextureMips[currentUnorderedAccessViewIndex] = currentResourceId - FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_0; + } + else + { + const FfxResourceInternal currentResource = context->uavResources[currentResourceId]; + jobDescriptor.uavTextures[currentUnorderedAccessViewIndex] = currentResource; + jobDescriptor.uavTextureMips[currentUnorderedAccessViewIndex] = 0; + } + } + + jobDescriptor.dimensions[0] = dispatchX; + jobDescriptor.dimensions[1] = dispatchY; + jobDescriptor.dimensions[2] = 1; + jobDescriptor.pipeline = *pipeline; + + for (uint32_t currentRootConstantIndex = 0; currentRootConstantIndex < pipeline->constCount; ++currentRootConstantIndex) { + wcscpy_s(jobDescriptor.cbNames[currentRootConstantIndex], pipeline->constantBufferBindings[currentRootConstantIndex].name); + jobDescriptor.cbs[currentRootConstantIndex] = globalFrameInterpolationConstantBuffers[pipeline->constantBufferBindings[currentRootConstantIndex].resourceIdentifier]; + } + + FfxGpuJobDescription dispatchJob = { FFX_GPU_JOB_COMPUTE }; + dispatchJob.computeJobDescriptor = jobDescriptor; + + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &dispatchJob); +} + +FfxErrorCode ffxFrameInterpolationContextCreate(FfxFrameInterpolationContext* context, FfxFrameInterpolationContextDescription* contextDescription) +{ + // zero context memory + //memset(context, 0, sizeof(FfxFrameinterpolationContext)); + + // check pointers are valid. + FFX_RETURN_ON_ERROR( + context, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + contextDescription, + FFX_ERROR_INVALID_POINTER); + + // validate that all callbacks are set for the interface + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.fpGetDeviceCapabilities, FFX_ERROR_INCOMPLETE_INTERFACE); + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.fpCreateBackendContext, FFX_ERROR_INCOMPLETE_INTERFACE); + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.fpDestroyBackendContext, FFX_ERROR_INCOMPLETE_INTERFACE); + + // if a scratch buffer is declared, then we must have a size + if (contextDescription->backendInterface.scratchBuffer) { + + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.scratchBufferSize, FFX_ERROR_INCOMPLETE_INTERFACE); + } + + // ensure the context is large enough for the internal context. + FFX_STATIC_ASSERT(sizeof(FfxFrameInterpolationContext) >= sizeof(FfxFrameInterpolationContext_Private)); + + // create the context. + FfxFrameInterpolationContext_Private* contextPrivate = (FfxFrameInterpolationContext_Private*)(context); + FfxErrorCode errorCode = frameinterpolationCreate(contextPrivate, contextDescription); + + return errorCode; +} + +FfxErrorCode ffxFrameInterpolationContextDestroy(FfxFrameInterpolationContext* context) +{ + FFX_RETURN_ON_ERROR( + context, + FFX_ERROR_INVALID_POINTER); + + // destroy the context. + FfxFrameInterpolationContext_Private* contextPrivate = (FfxFrameInterpolationContext_Private*)(context); + const FfxErrorCode errorCode = frameinterpolationRelease(contextPrivate); + + return errorCode; +} + +FfxErrorCode ffxFrameInterpolationContextEnqueueRefreshPipelineRequest(FfxFrameInterpolationContext* context) +{ + FFX_RETURN_ON_ERROR( + context, + FFX_ERROR_INVALID_POINTER); + + FfxFrameInterpolationContext_Private* contextPrivate = (FfxFrameInterpolationContext_Private*)context; + contextPrivate->refreshPipelineStates = true; + + return FFX_OK; +} + +static void setupDeviceDepthToViewSpaceDepthParams(FfxFrameInterpolationContext_Private* context, const FfxFrameInterpolationRenderDescription* params, FrameInterpolationConstants* constants) +{ + const bool bInverted = (context->contextDescription.flags & FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED) == FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED; + const bool bInfinite = (context->contextDescription.flags & FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INFINITE) == FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INFINITE; + + // make sure it has no impact if near and far plane values are swapped in dispatch params + // the flags "inverted" and "infinite" will decide what transform to use + float fMin = FFX_MINIMUM(params->cameraNear, params->cameraFar); + float fMax = FFX_MAXIMUM(params->cameraNear, params->cameraFar); + + if (bInverted) { + float tmp = fMin; + fMin = fMax; + fMax = tmp; + } + + // a 0 0 0 x + // 0 b 0 0 y + // 0 0 c d z + // 0 0 e 0 1 + + const float fQ = fMax / (fMin - fMax); + const float d = -1.0f; // for clarity + + const float matrix_elem_c[2][2] = { + fQ, // non reversed, non infinite + -1.0f - FLT_EPSILON, // non reversed, infinite + fQ, // reversed, non infinite + 0.0f + FLT_EPSILON // reversed, infinite + }; + + const float matrix_elem_e[2][2] = { + fQ * fMin, // non reversed, non infinite + -fMin - FLT_EPSILON, // non reversed, infinite + fQ * fMin, // reversed, non infinite + fMax, // reversed, infinite + }; + + constants->deviceToViewDepth[0] = d * matrix_elem_c[bInverted][bInfinite]; + constants->deviceToViewDepth[1] = matrix_elem_e[bInverted][bInfinite] * params->viewSpaceToMetersFactor; + + // revert x and y coords + const float aspect = params->renderSize.width / float(params->renderSize.height); + const float cotHalfFovY = cosf(0.5f * params->cameraFovAngleVertical) / sinf(0.5f * params->cameraFovAngleVertical); + const float a = cotHalfFovY / aspect; + const float b = cotHalfFovY; + + constants->deviceToViewDepth[2] = (1.0f / a); + constants->deviceToViewDepth[3] = (1.0f / b); + +} + +static const float debugBarColorSequence[] = { + 0.0f, 1.0f, 1.0f, // teal + 1.0f, 0.42f, 0.0f, // orange + 0.0f, 0.16f, 1.0f, // blue + 0.74f, 1.0f, 0.0f, // lime + 0.68f, 0.0f, 1.0f, // purple + 0.0f, 1.0f, 0.1f, // green + 1.0f, 1.0f, 0.48f // bright yellow +}; +const size_t debugBarColorSequenceLength = 7; + +FFX_API FfxErrorCode ffxFrameInterpolationDispatch(FfxFrameInterpolationContext* context, const FfxFrameInterpolationDispatchDescription* params) +{ + FfxFrameInterpolationContext_Private* contextPrivate = (FfxFrameInterpolationContext_Private*)(context); + const FfxFrameInterpolationRenderDescription* renderDesc = &contextPrivate->renderDescription; + + if (contextPrivate->refreshPipelineStates) { + + createPipelineStates(contextPrivate); + contextPrivate->refreshPipelineStates = false; + } + + contextPrivate->constants.renderSize[0] = params->renderSize.width; + contextPrivate->constants.renderSize[1] = params->renderSize.height; + contextPrivate->constants.displaySize[0] = params->displaySize.width; + contextPrivate->constants.displaySize[1] = params->displaySize.height; + contextPrivate->constants.displaySizeRcp[0] = 1.0f / params->displaySize.width; + contextPrivate->constants.displaySizeRcp[1] = 1.0f / params->displaySize.height; + contextPrivate->constants.upscalerTargetSize[0] = params->displaySize.width; + contextPrivate->constants.upscalerTargetSize[1] = params->displaySize.height; + contextPrivate->constants.Mode = 0; + contextPrivate->constants.Reset = params->reset; + contextPrivate->constants.deltaTime = params->frameTimeDelta; + contextPrivate->constants.HUDLessAttachedFactor = params->currentBackBuffer_HUDLess.resource ? 1 : 0; + + contextPrivate->constants.opticalFlowScale[0] = params->opticalFlowScale.x; + contextPrivate->constants.opticalFlowScale[1] = params->opticalFlowScale.y; + contextPrivate->constants.opticalFlowBlockSize = params->opticalFlowBlockSize;// displaySize.width / params->opticalFlowBufferSize.width; + contextPrivate->constants.dispatchFlags = params->flags; + + contextPrivate->constants.cameraNear = params->cameraNear; + contextPrivate->constants.cameraFar = params->cameraFar; + + contextPrivate->constants.interpolationRectBase[0] = params->interpolationRect.left; + contextPrivate->constants.interpolationRectBase[1] = params->interpolationRect.top; + contextPrivate->constants.interpolationRectSize[0] = params->interpolationRect.width; + contextPrivate->constants.interpolationRectSize[1] = params->interpolationRect.height; + + // Debug bar + static size_t dbgIdx = 0; + memcpy(contextPrivate->constants.debugBarColor, &debugBarColorSequence[dbgIdx * 3], 3 * sizeof(float)); + dbgIdx = (dbgIdx + 1) % debugBarColorSequenceLength; + + contextPrivate->constants.backBufferTransferFunction = params->backBufferTransferFunction; + contextPrivate->constants.minMaxLuminance[0] = params->minMaxLuminance[0]; + contextPrivate->constants.minMaxLuminance[1] = params->minMaxLuminance[1]; + + const float aspectRatio = (float)params->renderSize.width / (float)params->renderSize.height; + const float cameraAngleHorizontal = atan(tan(params->cameraFovAngleVertical / 2) * aspectRatio) * 2; + contextPrivate->constants.fTanHalfFOV = tanf(cameraAngleHorizontal * 0.5f); + + contextPrivate->renderDescription.cameraFar = params->cameraFar; + contextPrivate->renderDescription.cameraNear = params->cameraNear; + contextPrivate->renderDescription.viewSpaceToMetersFactor = (params->viewSpaceToMetersFactor > 0.0f) ? params->viewSpaceToMetersFactor : 1.0f; + contextPrivate->renderDescription.cameraFovAngleVertical = params->cameraFovAngleVertical; + contextPrivate->renderDescription.renderSize = params->renderSize; + contextPrivate->renderDescription.upscaleSize = params->displaySize; + setupDeviceDepthToViewSpaceDepthParams(contextPrivate, renderDesc, &contextPrivate->constants); + + memcpy(&globalFrameInterpolationConstantBuffers[FFX_FRAMEINTERPOLATION_CONSTANTBUFFER_IDENTIFIER].data, + &contextPrivate->constants, + globalFrameInterpolationConstantBuffers[FFX_FRAMEINTERPOLATION_CONSTANTBUFFER_IDENTIFIER].num32BitEntries * sizeof(uint32_t)); + + if (contextPrivate->constants.HUDLessAttachedFactor == 1) { + + FFX_ASSERT_MESSAGE(params->currentBackBuffer.description.format == params->currentBackBuffer_HUDLess.description.format, "HUDLess and Backbuffer resource formats have to be identical."); + + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->currentBackBuffer, contextPrivate->effectContextId, &contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PRESENT_BACKBUFFER]); + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->currentBackBuffer_HUDLess, contextPrivate->effectContextId, &contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_CURRENT_INTERPOLATION_SOURCE]); + } + else { + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->currentBackBuffer, contextPrivate->effectContextId, &contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_CURRENT_INTERPOLATION_SOURCE]); + } + + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->dilatedDepth, contextPrivate->effectContextId, &contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_DEPTH]); + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->dilatedMotionVectors, contextPrivate->effectContextId, &contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS]); + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->reconstructPrevNearDepth, contextPrivate->effectContextId, &contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME]); + + // Register output as SRV and UAV + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->output, contextPrivate->effectContextId, &contextPrivate->uavResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OUTPUT]); + contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OUTPUT] = contextPrivate->uavResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OUTPUT]; + + // set optical flow buffers + if (params->opticalFlowScale.x > 0) + { + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->opticalFlowVector, contextPrivate->effectContextId, &contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_VECTOR]); + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->opticalFlowSceneChangeDetection, contextPrivate->effectContextId, &contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCENE_CHANGE_DETECTION]); + } + else + { + contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_CONFIDENCE] = {}; + contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_GLOBAL_MOTION] = {}; + contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCENE_CHANGE_DETECTION] = {}; + contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_VECTOR] = {}; + } + + uint32_t displayDispatchSizeX = uint32_t(params->displaySize.width + 7) / 8; + uint32_t displayDispatchSizeY = uint32_t(params->displaySize.height + 7) / 8; + + uint32_t renderDispatchSizeX = uint32_t(params->renderSize.width + 7) / 8; + uint32_t renderDispatchSizeY = uint32_t(params->renderSize.height + 7) / 8; + + uint32_t opticalFlowDispatchSizeX = uint32_t(params->displaySize.width / float(params->opticalFlowBlockSize) + 7) / 8; + uint32_t opticalFlowDispatchSizeY = uint32_t(params->displaySize.height / float(params->opticalFlowBlockSize) + 7) / 8; + // Schedule work for the interpolation command list + { + // clear estimated depth resources + { + FfxGpuJobDescription clearJob = {FFX_GPU_JOB_CLEAR_FLOAT}; + + const bool bInverted = (contextPrivate->contextDescription.flags & FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED) == FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED; + const float clearDepthValue[]{bInverted ? 0.f : 1.f, bInverted ? 0.f : 1.f, bInverted ? 0.f : 1.f, bInverted ? 0.f : 1.f}; + memcpy(clearJob.clearJobDescriptor.color, clearDepthValue, 4 * sizeof(float)); + + clearJob.clearJobDescriptor.target = contextPrivate->uavResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME]; + contextPrivate->contextDescription.backendInterface.fpScheduleGpuJob(&contextPrivate->contextDescription.backendInterface, &clearJob); + } + + scheduleDispatch(contextPrivate, &contextPrivate->pipelineFiSetup, renderDispatchSizeX, renderDispatchSizeY); + scheduleDispatch(contextPrivate, &contextPrivate->pipelineFiReconstructPreviousDepth, renderDispatchSizeX, renderDispatchSizeY); + scheduleDispatch(contextPrivate, &contextPrivate->pipelineFiGameMotionVectorField, renderDispatchSizeX, renderDispatchSizeY); + + // game vector field inpainting pyramid + auto scheduleDispatchGameVectorFieldInpaintingPyramid = [&]() { + // Auto exposure + uint32_t dispatchThreadGroupCountXY[2]; + uint32_t workGroupOffset[2]; + uint32_t numWorkGroupsAndMips[2]; + uint32_t rectInfo[4] = {0, 0, params->renderSize.width, params->renderSize.height}; + ffxSpdSetup(dispatchThreadGroupCountXY, workGroupOffset, numWorkGroupsAndMips, rectInfo); + + // downsample + contextPrivate->inpaintingPyramidContants.numworkGroups = numWorkGroupsAndMips[0]; + contextPrivate->inpaintingPyramidContants.mips = numWorkGroupsAndMips[1]; + contextPrivate->inpaintingPyramidContants.workGroupOffset[0] = workGroupOffset[0]; + contextPrivate->inpaintingPyramidContants.workGroupOffset[1] = workGroupOffset[1]; + + memcpy(&globalFrameInterpolationConstantBuffers[FFX_FRAMEINTERPOLATION_INPAINTING_PYRAMID_CONSTANTBUFFER_IDENTIFIER].data, + &contextPrivate->inpaintingPyramidContants, + globalFrameInterpolationConstantBuffers[FFX_FRAMEINTERPOLATION_INPAINTING_PYRAMID_CONSTANTBUFFER_IDENTIFIER].num32BitEntries * + sizeof(uint32_t)); + + scheduleDispatch(contextPrivate, &contextPrivate->pipelineGameVectorFieldInpaintingPyramid, dispatchThreadGroupCountXY[0], dispatchThreadGroupCountXY[1]); + }; + scheduleDispatchGameVectorFieldInpaintingPyramid(); + + scheduleDispatch(contextPrivate, &contextPrivate->pipelineFiOpticalFlowVectorField, opticalFlowDispatchSizeX, opticalFlowDispatchSizeY); + + scheduleDispatch(contextPrivate, &contextPrivate->pipelineFiDisocclusionMask, renderDispatchSizeX, renderDispatchSizeY); + scheduleDispatch(contextPrivate, &contextPrivate->pipelineFiScfi, displayDispatchSizeX, displayDispatchSizeY); + + // inpainting pyramid + { + // Auto exposure + uint32_t dispatchThreadGroupCountXY[2]; + uint32_t workGroupOffset[2]; + uint32_t numWorkGroupsAndMips[2]; + uint32_t rectInfo[4] = { 0, 0, params->displaySize.width, params->displaySize.height }; + ffxSpdSetup(dispatchThreadGroupCountXY, workGroupOffset, numWorkGroupsAndMips, rectInfo); + + // downsample + contextPrivate->inpaintingPyramidContants.numworkGroups = numWorkGroupsAndMips[0]; + contextPrivate->inpaintingPyramidContants.mips = numWorkGroupsAndMips[1]; + contextPrivate->inpaintingPyramidContants.workGroupOffset[0] = workGroupOffset[0]; + contextPrivate->inpaintingPyramidContants.workGroupOffset[1] = workGroupOffset[1]; + + memcpy(&globalFrameInterpolationConstantBuffers[FFX_FRAMEINTERPOLATION_INPAINTING_PYRAMID_CONSTANTBUFFER_IDENTIFIER].data, + &contextPrivate->inpaintingPyramidContants, + globalFrameInterpolationConstantBuffers[FFX_FRAMEINTERPOLATION_INPAINTING_PYRAMID_CONSTANTBUFFER_IDENTIFIER].num32BitEntries * sizeof(uint32_t)); + + scheduleDispatch(contextPrivate, &contextPrivate->pipelineInpaintingPyramid, dispatchThreadGroupCountXY[0], dispatchThreadGroupCountXY[1]); + } + + scheduleDispatch(contextPrivate, &contextPrivate->pipelineInpainting, displayDispatchSizeX, displayDispatchSizeY); + + if (params->flags & FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_VIEW) + { + scheduleDispatchGameVectorFieldInpaintingPyramid(); + scheduleDispatch(contextPrivate, &contextPrivate->pipelineDebugView, displayDispatchSizeX, displayDispatchSizeY); + } + + // store current buffer + { + FfxGpuJobDescription copyJobs[] = { {FFX_GPU_JOB_COPY} }; + FfxResourceInternal copySources[_countof(copyJobs)] = { contextPrivate->srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_CURRENT_INTERPOLATION_SOURCE] }; + FfxResourceInternal destSources[_countof(copyJobs)] = { contextPrivate->uavResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PREVIOUS_INTERPOLATION_SOURCE] }; + + for (int i = 0; i < _countof(copyJobs); ++i) + { + copyJobs[i].copyJobDescriptor.src = copySources[i]; + copyJobs[i].copyJobDescriptor.dst = destSources[i]; + contextPrivate->contextDescription.backendInterface.fpScheduleGpuJob(&contextPrivate->contextDescription.backendInterface, ©Jobs[i]); + } + } + + // declare internal resources needed + struct FfxInternalResourceStates + { + FfxUInt32 id; + FfxResourceUsage usage; + }; + const FfxInternalResourceStates internalSurfaceDesc[] = { + + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME, FFX_RESOURCE_USAGE_UAV}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_X, FFX_RESOURCE_USAGE_UAV}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_Y, FFX_RESOURCE_USAGE_UAV}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID, FFX_RESOURCE_USAGE_UAV}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNTERS, FFX_RESOURCE_USAGE_UAV}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X, FFX_RESOURCE_USAGE_UAV}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y, FFX_RESOURCE_USAGE_UAV}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PREVIOUS_INTERPOLATION_SOURCE, FFX_RESOURCE_USAGE_UAV}, + {FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DISOCCLUSION_MASK, FFX_RESOURCE_USAGE_UAV}, + }; + + for (int32_t currentSurfaceIndex = 0; currentSurfaceIndex < FFX_ARRAY_ELEMENTS(internalSurfaceDesc); ++currentSurfaceIndex) { + + const FfxInternalResourceStates* currentSurfaceDescription = &internalSurfaceDesc[currentSurfaceIndex]; + FfxResourceStates initialState = FFX_RESOURCE_STATE_UNORDERED_ACCESS; + if (currentSurfaceDescription->usage == FFX_RESOURCE_USAGE_READ_ONLY) initialState = FFX_RESOURCE_STATE_COMPUTE_READ; + if (currentSurfaceDescription->usage == FFX_RESOURCE_USAGE_RENDERTARGET) initialState = FFX_RESOURCE_STATE_COMMON; + + FfxGpuJobDescription barrier = {FFX_GPU_JOB_BARRIER}; + barrier.barrierDescriptor.resource = contextPrivate->srvResources[currentSurfaceDescription->id]; + barrier.barrierDescriptor.subResourceID = 0; + barrier.barrierDescriptor.newState = (currentSurfaceDescription->id == FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNTERS) ? FFX_RESOURCE_STATE_COPY_DEST : initialState; + barrier.barrierDescriptor.barrierType = FFX_BARRIER_TYPE_TRANSITION; + contextPrivate->contextDescription.backendInterface.fpScheduleGpuJob(&contextPrivate->contextDescription.backendInterface, &barrier); + } + + // schedule optical flow and frame interpolation + contextPrivate->contextDescription.backendInterface.fpExecuteGpuJobs(&contextPrivate->contextDescription.backendInterface, params->commandList); + } + + // release dynamic resources + contextPrivate->contextDescription.backendInterface.fpUnregisterResources(&contextPrivate->contextDescription.backendInterface, params->commandList, contextPrivate->effectContextId); + + return FFX_OK; +} diff --git a/sdk/src/components/frameinterpolation/ffx_frameinterpolation_private.h b/sdk/src/components/frameinterpolation/ffx_frameinterpolation_private.h new file mode 100644 index 00000000..8ce8233f --- /dev/null +++ b/sdk/src/components/frameinterpolation/ffx_frameinterpolation_private.h @@ -0,0 +1,135 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 + +/// An enumeration of all the permutations that can be passed to the FSR3 algorithm. +/// +/// FSR3 features are organized through a set of pre-defined compile +/// permutation options that need to be specified. Which shader blob +/// is returned for pipeline creation will be determined by what combination +/// of shader permutations are enabled. +/// +/// @ingroup FRAMEINTERPOLATION +typedef enum FrameInterpolationShaderPermutationOptions +{ + FRAMEINTERPOLATION_SHADER_PERMUTATION_DEPTH_INVERTED = (1 << 1), ///< Indicates input resources were generated with inverted depth + FRAMEINTERPOLATION_SHADER_PERMUTATION_FORCE_WAVE64 = (1 << 2), ///< doesn't map to a define, selects different table + FRAMEINTERPOLATION_SHADER_PERMUTATION_ALLOW_FP16 = (1 << 3), ///< Enables fast math computations where possible +} FrameInterpolationShaderPermutationOptions; + +typedef struct FrameInterpolationConstants +{ + int32_t renderSize[2]; + int32_t displaySize[2]; + + float displaySizeRcp[2]; + float cameraNear; + float cameraFar; + + int32_t upscalerTargetSize[2]; // how is that different from display size? + int Mode; + int Reset; + + float deviceToViewDepth[4]; + + float deltaTime; + float UNUSED__[2]; + int HUDLessAttachedFactor; + + float opticalFlowScale[2]; + int32_t opticalFlowBlockSize; + uint32_t dispatchFlags; + + int opticalFlowHalfResMode; + int32_t maxRenderSize[2]; + int numInstances; + + int32_t interpolationRectBase[2]; + int32_t interpolationRectSize[2]; + + float debugBarColor[3]; + uint32_t backBufferTransferFunction; + + float minMaxLuminance[2]; + float fTanHalfFOV; + float _pad1; +} FrameInterpolationConstants; + +typedef struct InpaintingPyramidConstants { + + uint32_t mips; + uint32_t numworkGroups; + uint32_t workGroupOffset[2]; +} InpaintingPyramidConstants; + +struct FfxDeviceCapabilities; +struct FfxPipelineState; +struct FfxResource; + +typedef struct FfxFrameInterpolationRenderDescription +{ + FfxDimensions2D renderSize; + FfxDimensions2D upscaleSize; + + float cameraNear; + float cameraFar; + float cameraFovAngleVertical; + float viewSpaceToMetersFactor; + + FfxFloatCoords2D motionVectorScale; ///< The scale factor to apply to motion vectors. +} FfxFrameInterpolationRenderDescription; + +// FfxFsr3Context_Private +// The private implementation of the FSR3 context. +typedef struct FfxFrameInterpolationContext_Private { + + FfxFrameInterpolationContextDescription contextDescription; + FfxUInt32 effectContextId; + FfxFrameInterpolationRenderDescription renderDescription; + FrameInterpolationConstants constants; + InpaintingPyramidConstants inpaintingPyramidContants; + FfxDevice device; + FfxDeviceCapabilities deviceCapabilities; + + // FrameInterpolation Pipelines + FfxPipelineState pipelineFiSetup; + FfxPipelineState pipelineFiReconstructPreviousDepth; + FfxPipelineState pipelineFiGameMotionVectorField; + FfxPipelineState pipelineFiOpticalFlowVectorField; + FfxPipelineState pipelineFiDisocclusionMask; + FfxPipelineState pipelineFiScfi; + FfxPipelineState pipelineInpaintingPyramid; + FfxPipelineState pipelineInpainting; + FfxPipelineState pipelineGameVectorFieldInpaintingPyramid; + FfxPipelineState pipelineDebugView; + + // 2 arrays of resources, as e.g. FFX_FSR3_RESOURCE_IDENTIFIER_LOCK_STATUS will use different resources when bound as SRV vs when bound as UAV + FfxResourceInternal srvResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNT]; + FfxResourceInternal uavResources[FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNT]; + + bool firstExecution; + bool refreshPipelineStates; + +} FfxFrameInterpolationContext_Private; diff --git a/sdk/src/components/fsr1/CMakeLists.txt b/sdk/src/components/fsr1/CMakeLists.txt index e6893bf0..398aae96 100644 --- a/sdk/src/components/fsr1/CMakeLists.txt +++ b/sdk/src/components/fsr1/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_FSR1 OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/fsr1/ffx_fsr1.cpp b/sdk/src/components/fsr1/ffx_fsr1.cpp index 7c93ad8f..64727630 100644 --- a/sdk/src/components/fsr1/ffx_fsr1.cpp +++ b/sdk/src/components/fsr1/ffx_fsr1.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 // for memset #include // for _countof #include // for fabs, abs, sinf, sqrt, etc. @@ -323,7 +323,7 @@ static FfxErrorCode fsr1Release(FfxFsr1Context_Private* context) context->srvResources[FFX_FSR1_RESOURCE_IDENTIFIER_UPSCALED_OUTPUT] = { FFX_FSR1_RESOURCE_IDENTIFIER_NULL }; // Release internal resource - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR1_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR]); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR1_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR], context->effectContextId); // Destroy the context context->contextDescription.backendInterface.fpDestroyBackendContext(&context->contextDescription.backendInterface, context->effectContextId); diff --git a/sdk/src/components/fsr1/ffx_fsr1_private.h b/sdk/src/components/fsr1/ffx_fsr1_private.h index a9c3e055..c33dadda 100644 --- a/sdk/src/components/fsr1/ffx_fsr1_private.h +++ b/sdk/src/components/fsr1/ffx_fsr1_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 diff --git a/sdk/src/components/fsr2/CMakeLists.txt b/sdk/src/components/fsr2/CMakeLists.txt index 880f51f8..c4f98391 100644 --- a/sdk/src/components/fsr2/CMakeLists.txt +++ b/sdk/src/components/fsr2/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_FSR2 OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/fsr2/ffx_fsr2.cpp b/sdk/src/components/fsr2/ffx_fsr2.cpp index c62d2582..19ec281b 100644 --- a/sdk/src/components/fsr2/ffx_fsr2.cpp +++ b/sdk/src/components/fsr2/ffx_fsr2.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 // for max used inside SPD CPU code. #include // for fabs, abs, sinf, sqrt, etc. #include // for memset @@ -671,16 +671,16 @@ static FfxErrorCode fsr2Release(FfxFsr2Context_Private* context) context->srvResources[FFX_FSR2_RESOURCE_IDENTIFIER_UPSCALED_OUTPUT] = { FFX_FSR2_RESOURCE_IDENTIFIER_NULL }; // Release the copy resources for those that had init data - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR2_RESOURCE_IDENTIFIER_SPD_ATOMIC_COUNT]); - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR2_RESOURCE_IDENTIFIER_LANCZOS_LUT]); - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR2_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_REACTIVITY]); - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR2_RESOURCE_IDENTITIER_UPSAMPLE_MAXIMUM_BIAS_LUT]); - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR2_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_EXPOSURE]); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR2_RESOURCE_IDENTIFIER_SPD_ATOMIC_COUNT], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR2_RESOURCE_IDENTIFIER_LANCZOS_LUT], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR2_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_REACTIVITY], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR2_RESOURCE_IDENTITIER_UPSAMPLE_MAXIMUM_BIAS_LUT], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR2_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_EXPOSURE], context->effectContextId); // release internal resources for (int32_t currentResourceIndex = 0; currentResourceIndex < FFX_FSR2_RESOURCE_IDENTIFIER_COUNT; ++currentResourceIndex) { - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[currentResourceIndex]); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[currentResourceIndex], context->effectContextId); } // Destroy the context diff --git a/sdk/src/components/fsr2/ffx_fsr2_maximum_bias.h b/sdk/src/components/fsr2/ffx_fsr2_maximum_bias.h index 60d39414..ad1dfc69 100644 --- a/sdk/src/components/fsr2/ffx_fsr2_maximum_bias.h +++ b/sdk/src/components/fsr2/ffx_fsr2_maximum_bias.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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. + // @internal #pragma once diff --git a/sdk/src/components/fsr2/ffx_fsr2_private.h b/sdk/src/components/fsr2/ffx_fsr2_private.h index 57ca04ff..3aba6322 100644 --- a/sdk/src/components/fsr2/ffx_fsr2_private.h +++ b/sdk/src/components/fsr2/ffx_fsr2_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 diff --git a/sdk/src/components/fsr3/CMakeLists.txt b/sdk/src/components/fsr3/CMakeLists.txt new file mode 100644 index 00000000..f8ec3875 --- /dev/null +++ b/sdk/src/components/fsr3/CMakeLists.txt @@ -0,0 +1,59 @@ +# This file is part of the FidelityFX SDK. +# +# Copyright (c) 2023 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 (FFX_FSR2 OR FFX_FSR3 OR FFX_ALL) + # Shared sources + set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) + + # Private sources + file(GLOB PRIVATE_SOURCES + # NOTE that ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp(h)" can also be used instead + # simply including effect name in the path for emphasis + "${FFX_COMPONENTS_PATH}/fsr3/*.cpp" + "${FFX_COMPONENTS_PATH}/fsr3/*.h") + + # Public source + file(GLOB PUBLIC_SOURCES + "${FFX_HOST_PATH}/fsr3/*.h" + "${FFX_HOST_PATH}/fsr3/*.cpp") + list(APPEND PUBLIC_SOURCES ${FFX_PUBLIC_SOURCES}) + + if (FFX_BUILD_AS_DLL) + add_library(ffx_fsr3_${FFX_PLATFORM_NAME} SHARED ${SHARED_SOURCES} ${PRIVATE_SOURCES} ${PUBLIC_SOURCES}) + else() + add_library(ffx_fsr3_${FFX_PLATFORM_NAME} STATIC ${SHARED_SOURCES} ${PRIVATE_SOURCES} ${PUBLIC_SOURCES}) + endif() + + # API + source_group("shared_source" FILES ${SHARED_SOURCES}) + source_group("private_source" FILES ${PRIVATE_SOURCES}) + source_group("public_source" FILES ${PUBLIC_SOURCES}) + + # Dependencies + target_link_libraries(ffx_fsr3_${FFX_PLATFORM_NAME} PRIVATE ffx_fsr3upscaler_${FFX_PLATFORM_NAME} ffx_opticalflow_${FFX_PLATFORM_NAME} ffx_frameinterpolation_${FFX_PLATFORM_NAME}) + + target_include_directories(ffx_fsr3_${FFX_PLATFORM_NAME} PUBLIC ${FFX_INCLUDE_PATH}) + target_include_directories(ffx_fsr3_${FFX_PLATFORM_NAME} PUBLIC ${FFX_SHARED_PATH}) + + set_source_files_properties(${SHADERS} PROPERTIES HEADER_FILE_ONLY TRUE) + set_target_properties(ffx_fsr3_${FFX_PLATFORM_NAME} PROPERTIES FOLDER Components) + +endif() diff --git a/sdk/src/components/fsr3/ffx_fsr3.cpp b/sdk/src/components/fsr3/ffx_fsr3.cpp new file mode 100644 index 00000000..748f5bc7 --- /dev/null +++ b/sdk/src/components/fsr3/ffx_fsr3.cpp @@ -0,0 +1,447 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 // for max used inside SPD CPU code. +#include // for fabs, abs, sinf, sqrt, etc. +#include // for memset +#include // for FLT_EPSILON +#include +#include +#define FFX_CPU +#include +#include +#include +#include "../frameinterpolation/ffx_frameinterpolation_private.h" + +#include "ffx_fsr3_maximum_bias.h" + +#include "ffx_fsr3_private.h" + +// To track only one context is present, also used in fi dispatch callback +static FfxFsr3Context* s_Context = nullptr; + +FfxErrorCode ffxFsr3ContextCreate(FfxFsr3Context* context, FfxFsr3ContextDescription* contextDescription) +{ + FFX_STATIC_ASSERT(sizeof(FfxFsr3Context) >= sizeof(FfxFsr3Context_Private)); + FfxErrorCode ret = FFX_OK; + FfxFsr3Context_Private* contextPrivate = (FfxFsr3Context_Private*)(context); + + // Prepare backend + { + memset(context, 0, sizeof(FfxFsr3Context)); + + // check pointers are valid. + FFX_RETURN_ON_ERROR( + context, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + contextDescription, + FFX_ERROR_INVALID_POINTER); + + contextPrivate->description = *contextDescription; + + contextPrivate->backendInterfaceSharedResources = contextDescription->backendInterfaceSharedResources; + contextPrivate->backendInterfaceUpscaling = contextDescription->backendInterfaceUpscaling; + contextPrivate->backendInterfaceFrameInterpolation = contextDescription->backendInterfaceFrameInterpolation; + + contextPrivate->upscalingOnly = (contextDescription->flags & FFX_FSR3_ENABLE_UPSCALING_ONLY) != 0; + contextPrivate->asyncWorkloadSupported = (contextDescription->flags & FFX_FSR3_ENABLE_ASYNC_WORKLOAD_SUPPORT) != 0; + contextPrivate->sharedResourceCount = contextPrivate->asyncWorkloadSupported ? FSR3_MAX_QUEUED_FRAMES : 1; + + // validate that all callbacks are set for the backend interfaces + const FfxUInt32 numBackendsToVerify = contextPrivate->upscalingOnly ? 1 : 3; + FfxInterface* backendsToVerify[] = { + &contextPrivate->backendInterfaceUpscaling, + &contextPrivate->backendInterfaceSharedResources, + &contextPrivate->backendInterfaceFrameInterpolation + }; + + for(FfxUInt32 i = 0; i < numBackendsToVerify; i++) + { + FfxInterface* backend = backendsToVerify[i]; + FFX_RETURN_ON_ERROR(backend, FFX_ERROR_INCOMPLETE_INTERFACE); + FFX_RETURN_ON_ERROR(backend->fpGetDeviceCapabilities, FFX_ERROR_INCOMPLETE_INTERFACE); + FFX_RETURN_ON_ERROR(backend->fpCreateBackendContext, FFX_ERROR_INCOMPLETE_INTERFACE); + FFX_RETURN_ON_ERROR(backend->fpDestroyBackendContext, FFX_ERROR_INCOMPLETE_INTERFACE); + + // if a scratch buffer is declared, then we must have a size + if (backend->scratchBuffer) { + FFX_RETURN_ON_ERROR(backend->scratchBufferSize, FFX_ERROR_INCOMPLETE_INTERFACE); + } + } + + if (!contextPrivate->upscalingOnly) + { + FFX_VALIDATE(contextPrivate->backendInterfaceSharedResources.fpCreateBackendContext(&contextPrivate->backendInterfaceSharedResources, &contextPrivate->effectContextIdSharedResources)); + } + else + { + contextPrivate->backendInterfaceSharedResources = contextPrivate->backendInterfaceUpscaling; + contextDescription->backendInterfaceSharedResources = contextDescription->backendInterfaceUpscaling; + } + } + + // set up FSR3 Upscaler + // ensure we're actually creating an FSR3 Upscaler context, not the creationfunction that reroutes to ffxFsr3ContextCreate + { + FfxFsr3UpscalerContextDescription upDesc = {}; + upDesc.flags = 0; + upDesc.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_HIGH_DYNAMIC_RANGE) ? FFX_FSR3UPSCALER_ENABLE_HIGH_DYNAMIC_RANGE : 0; + upDesc.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS) ? FFX_FSR3UPSCALER_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS : 0; + upDesc.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION) ? FFX_FSR3UPSCALER_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION : 0; + upDesc.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_DEPTH_INVERTED) ? FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED : 0; + upDesc.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_DEPTH_INFINITE) ? FFX_FSR3UPSCALER_ENABLE_DEPTH_INFINITE : 0; + upDesc.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_AUTO_EXPOSURE) ? FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE : 0; + upDesc.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_DYNAMIC_RESOLUTION) ? FFX_FSR3UPSCALER_ENABLE_DYNAMIC_RESOLUTION : 0; + upDesc.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_TEXTURE1D_USAGE) ? FFX_FSR3UPSCALER_ENABLE_TEXTURE1D_USAGE : 0; + upDesc.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_DEBUG_CHECKING) ? FFX_FSR3UPSCALER_ENABLE_DEBUG_CHECKING : 0; + upDesc.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_HDR_UPSCALE_SDR_FINALOUTPUT) ? FFX_FSR3UPSCALER_ENABLE_HIGH_DYNAMIC_RANGE : 0; + upDesc.maxRenderSize = contextDescription->maxRenderSize; + upDesc.displaySize = contextDescription->upscaleOutputSize; + upDesc.backendInterface = contextDescription->backendInterfaceUpscaling; + upDesc.fpMessage = contextDescription->fpMessage; + FFX_VALIDATE(ffxFsr3UpscalerContextCreate(&contextPrivate->upscalerContext, &upDesc)); + } + + if (!contextPrivate->upscalingOnly) { + + FfxOpticalflowContextDescription ofDescription = {}; + ofDescription.backendInterface = contextDescription->backendInterfaceFrameInterpolation; + ofDescription.resolution = contextDescription->displaySize; + ofDescription.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_TEXTURE1D_USAGE) ? FFX_OPTICALFLOW_ENABLE_TEXTURE1D_USAGE : 0; + + // set up Opticalflow + FFX_VALIDATE(ffxOpticalflowContextCreate(&contextPrivate->ofContext, &ofDescription)); + + FfxFrameInterpolationContextDescription fiDescription = {}; + fiDescription.backendInterface = contextDescription->backendInterfaceFrameInterpolation; + fiDescription.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_DEPTH_INVERTED) ? FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED : 0; + fiDescription.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_DEPTH_INFINITE) ? FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INFINITE : 0; + fiDescription.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_TEXTURE1D_USAGE) ? FFX_FRAMEINTERPOLATION_ENABLE_TEXTURE1D_USAGE : 0; + fiDescription.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_HIGH_DYNAMIC_RANGE) ? FFX_FRAMEINTERPOLATION_ENABLE_HDR_COLOR_INPUT : 0; + fiDescription.flags |= (contextDescription->flags & FFX_FSR3_ENABLE_SDR_UPSCALE_HDR_FINALOUTPUT) ? FFX_FRAMEINTERPOLATION_ENABLE_HDR_COLOR_INPUT : 0; + fiDescription.maxRenderSize = contextDescription->maxRenderSize; + fiDescription.displaySize = contextDescription->displaySize; + fiDescription.backBufferFormat = contextDescription->backBufferFormat; + + // set up Frameinterpolation + FFX_VALIDATE(ffxFrameInterpolationContextCreate(&contextPrivate->fiContext, &fiDescription)); + + // set up optical flow resources + FfxOpticalflowSharedResourceDescriptions ofResourceDescs = {}; + FFX_VALIDATE(ffxOpticalflowGetSharedResourceDescriptions(&contextPrivate->ofContext, &ofResourceDescs)); + + FFX_VALIDATE(contextDescription->backendInterfaceSharedResources.fpCreateResource( + &contextDescription->backendInterfaceSharedResources, &ofResourceDescs.opticalFlowVector, contextPrivate->effectContextIdSharedResources, &contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_OPTICAL_FLOW_VECTOR])); + FFX_VALIDATE(contextDescription->backendInterfaceSharedResources.fpCreateResource( + &contextDescription->backendInterfaceSharedResources, &ofResourceDescs.opticalFlowSCD, contextPrivate->effectContextIdSharedResources, &contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_OUTPUT])); + } + + // set up FSR3Upscaler resources + { + FfxFsr3UpscalerSharedResourceDescriptions fs3UpscalerResourceDescs = {}; + FFX_VALIDATE(ffxFsr3UpscalerGetSharedResourceDescriptions(&contextPrivate->upscalerContext, &fs3UpscalerResourceDescs)); + + wchar_t Name[256] = {}; + for (FfxUInt32 i = 0; i < contextPrivate->sharedResourceCount; i++) + { + FfxCreateResourceDescription dilD = fs3UpscalerResourceDescs.dilatedDepth; + swprintf(Name, 255, L"%s%d", fs3UpscalerResourceDescs.dilatedDepth.name, i); + dilD.name = Name; + FFX_VALIDATE(contextDescription->backendInterfaceSharedResources.fpCreateResource( + &contextDescription->backendInterfaceSharedResources, &dilD, contextPrivate->effectContextIdSharedResources, &contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_DEPTH_0 + (i * FFX_FSR3_RESOURCE_IDENTIFIER_UPSCALED_COUNT)])); + + FfxCreateResourceDescription dilMVs = fs3UpscalerResourceDescs.dilatedMotionVectors; + swprintf(Name, 255, L"%s%d", fs3UpscalerResourceDescs.dilatedMotionVectors.name, i); + dilMVs.name = Name; + FFX_VALIDATE(contextDescription->backendInterfaceSharedResources.fpCreateResource( + &contextDescription->backendInterfaceSharedResources, &dilMVs, contextPrivate->effectContextIdSharedResources, &contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS_0 + (i * FFX_FSR3_RESOURCE_IDENTIFIER_UPSCALED_COUNT)])); + + FfxCreateResourceDescription recND = fs3UpscalerResourceDescs.reconstructedPrevNearestDepth; + swprintf(Name, 255, L"%s%d", fs3UpscalerResourceDescs.reconstructedPrevNearestDepth.name, i); + recND.name = Name; + FFX_VALIDATE(contextDescription->backendInterfaceSharedResources.fpCreateResource( + &contextDescription->backendInterfaceSharedResources, &recND, contextPrivate->effectContextIdSharedResources, &contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH_0 + (i * FFX_FSR3_RESOURCE_IDENTIFIER_UPSCALED_COUNT)])); + } + } + + return ret; +} + +FfxErrorCode ffxFsr3ContextGenerateReactiveMask(FfxFsr3Context* context, const FfxFsr3GenerateReactiveDescription* params) +{ + FfxFsr3Context_Private* contextPrivate = (FfxFsr3Context_Private*)(context); + + FfxFsr3UpscalerGenerateReactiveDescription fsr3Params; + + fsr3Params.commandList = params->commandList; + fsr3Params.colorOpaqueOnly = params->colorOpaqueOnly; + fsr3Params.colorPreUpscale = params->colorPreUpscale; + fsr3Params.outReactive = params->outReactive; + fsr3Params.renderSize = params->renderSize; + fsr3Params.scale = params->scale; + fsr3Params.cutoffThreshold = params->cutoffThreshold; + fsr3Params.binaryValue = params->binaryValue; + fsr3Params.flags = params->flags; + + return ffxFsr3UpscalerContextGenerateReactiveMask(&contextPrivate->upscalerContext, &fsr3Params); +} + +FfxErrorCode ffxFsr3DispatchFrameGeneration(const FfxFrameGenerationDispatchDescription* callbackDesc) +{ + FfxErrorCode errorCode = FFX_OK; + + FFX_RETURN_ON_ERROR(s_Context, FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR(callbackDesc, FFX_ERROR_INVALID_POINTER); + + FfxFsr3Context_Private* contextPrivate = (FfxFsr3Context_Private*)(s_Context); + + FfxUInt32 sharedResourceIndexFrameInterpolation = contextPrivate->frameIndexFrameGeneration % contextPrivate->sharedResourceCount; + contextPrivate->frameIndexFrameGeneration++; + + FFX_ASSERT_MESSAGE(contextPrivate->frameIndexFrameGeneration <= contextPrivate->frameIndexUpscaling, "FSR3 Frame interpolaton dispatch: Frame interpolation may not run ahead of upscaling."); + FFX_ASSERT_MESSAGE(!contextPrivate->asyncWorkloadSupported || ((contextPrivate->frameIndexUpscaling - contextPrivate->frameIndexFrameGeneration) <= 1), + "FSR3 Frame interpolaton dispatch: Frame upscaling too far ahead of frame interpolation."); + + const FfxFsr3DispatchUpscaleDescription* upscaleDesc = &contextPrivate->upscaleDescriptions[sharedResourceIndexFrameInterpolation]; + const bool bReset = upscaleDesc->reset || callbackDesc->reset || (contextPrivate->skippedPresentsCount > 0); + contextPrivate->skippedPresentsCount = 0; + + // Optical flow + { + FfxOpticalflowDispatchDescription ofDispatchDesc{}; + ofDispatchDesc.commandList = callbackDesc->commandList; + ofDispatchDesc.color = callbackDesc->presentColor; + if (contextPrivate->HUDLess_color.resource) + { + ofDispatchDesc.color = contextPrivate->HUDLess_color; + } + ofDispatchDesc.reset = bReset; + ofDispatchDesc.backbufferTransferFunction = callbackDesc->backBufferTransferFunction; + ofDispatchDesc.minMaxLuminance.x = callbackDesc->minMaxLuminance[0]; + ofDispatchDesc.minMaxLuminance.y = callbackDesc->minMaxLuminance[1]; + ofDispatchDesc.opticalFlowVector = contextPrivate->backendInterfaceSharedResources.fpGetResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_OPTICAL_FLOW_VECTOR]); + ofDispatchDesc.opticalFlowSCD = contextPrivate->backendInterfaceSharedResources.fpGetResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_OUTPUT]); + + errorCode |= ffxOpticalflowContextDispatch(&contextPrivate->ofContext, &ofDispatchDesc); + } + + // Frame interpolation + { + FfxFrameInterpolationDispatchDescription fiDispatchDesc{}; + + // don't dispatch interpolation async for now: use the same commandlist for copy and interpolate + fiDispatchDesc.commandList = callbackDesc->commandList; + fiDispatchDesc.displaySize.width = callbackDesc->presentColor.description.width; + fiDispatchDesc.displaySize.height = callbackDesc->presentColor.description.height; + fiDispatchDesc.currentBackBuffer = callbackDesc->presentColor; + fiDispatchDesc.currentBackBuffer_HUDLess = contextPrivate->HUDLess_color; + + fiDispatchDesc.renderSize = upscaleDesc->renderSize; + fiDispatchDesc.output = callbackDesc->outputs[0]; + fiDispatchDesc.opticalFlowVector = contextPrivate->backendInterfaceSharedResources.fpGetResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_OPTICAL_FLOW_VECTOR]); + fiDispatchDesc.opticalFlowSceneChangeDetection = contextPrivate->backendInterfaceSharedResources.fpGetResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_OUTPUT]); + fiDispatchDesc.opticalFlowBlockSize = 8; + fiDispatchDesc.opticalFlowScale = { 1.f / fiDispatchDesc.displaySize.width, 1.f / fiDispatchDesc.displaySize.height }; + fiDispatchDesc.frameTimeDelta = upscaleDesc->frameTimeDelta; + fiDispatchDesc.reset = bReset; + fiDispatchDesc.cameraNear = upscaleDesc->cameraNear; + fiDispatchDesc.cameraFar = upscaleDesc->cameraFar; + fiDispatchDesc.viewSpaceToMetersFactor = upscaleDesc->viewSpaceToMetersFactor; + fiDispatchDesc.cameraFovAngleVertical = upscaleDesc->cameraFovAngleVertical; + fiDispatchDesc.dilatedDepth = contextPrivate->backendInterfaceSharedResources.fpGetResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_DEPTH_0 + (sharedResourceIndexFrameInterpolation * FFX_FSR3_RESOURCE_IDENTIFIER_UPSCALED_COUNT)]); + fiDispatchDesc.dilatedMotionVectors = contextPrivate->backendInterfaceSharedResources.fpGetResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS_0 + (sharedResourceIndexFrameInterpolation * FFX_FSR3_RESOURCE_IDENTIFIER_UPSCALED_COUNT)]); + fiDispatchDesc.reconstructPrevNearDepth = contextPrivate->backendInterfaceSharedResources.fpGetResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH_0 + (sharedResourceIndexFrameInterpolation * FFX_FSR3_RESOURCE_IDENTIFIER_UPSCALED_COUNT)]); + + fiDispatchDesc.interpolationRect.left = 0; + fiDispatchDesc.interpolationRect.top = 0; + fiDispatchDesc.interpolationRect.width = callbackDesc->presentColor.description.width; + fiDispatchDesc.interpolationRect.height = callbackDesc->presentColor.description.height; + + if (contextPrivate->frameGenerationFlags & FFX_FSR3_FRAME_GENERATION_FLAG_DRAW_DEBUG_TEAR_LINES) + { + fiDispatchDesc.flags |= FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_TEAR_LINES; + } + + if (contextPrivate->frameGenerationFlags & FFX_FSR3_FRAME_GENERATION_FLAG_DRAW_DEBUG_VIEW) + { + fiDispatchDesc.flags |= FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_VIEW; + } + + fiDispatchDesc.backBufferTransferFunction = callbackDesc->backBufferTransferFunction; + fiDispatchDesc.minMaxLuminance[0] = callbackDesc->minMaxLuminance[0]; + fiDispatchDesc.minMaxLuminance[1] = callbackDesc->minMaxLuminance[1]; + + errorCode |= ffxFrameInterpolationDispatch(&contextPrivate->fiContext, &fiDispatchDesc); + } + + return errorCode; +} + +FfxErrorCode ffxFsr3ContextDispatchUpscale(FfxFsr3Context* context, const FfxFsr3DispatchUpscaleDescription* dispatchParams) +{ + FFX_RETURN_ON_ERROR(context, FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR(dispatchParams, FFX_ERROR_INVALID_POINTER); + + FfxFsr3Context_Private* contextPrivate = (FfxFsr3Context_Private*)(context); + + contextPrivate->deltaTime = FFX_MAXIMUM(0.0f, FFX_MINIMUM(1.0f, dispatchParams->frameTimeDelta / 1000.0f)); + + FfxUInt32 sharedResourceIndexUpscaling = contextPrivate->frameIndexUpscaling % contextPrivate->sharedResourceCount; + contextPrivate->frameIndexUpscaling++; + + // dispatch FSR3 + FfxFsr3UpscalerDispatchDescription fsr3DispatchParams; + fsr3DispatchParams.commandList = dispatchParams->commandList; + fsr3DispatchParams.color = dispatchParams->color; + fsr3DispatchParams.depth = dispatchParams->depth; + fsr3DispatchParams.motionVectors = dispatchParams->motionVectors; + fsr3DispatchParams.exposure = dispatchParams->exposure; + fsr3DispatchParams.reactive = dispatchParams->reactive; + fsr3DispatchParams.transparencyAndComposition = dispatchParams->transparencyAndComposition; + fsr3DispatchParams.dilatedDepth = contextPrivate->backendInterfaceSharedResources.fpGetResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_DEPTH_0 + (sharedResourceIndexUpscaling * FFX_FSR3_RESOURCE_IDENTIFIER_UPSCALED_COUNT)]); + fsr3DispatchParams.dilatedMotionVectors = contextPrivate->backendInterfaceSharedResources.fpGetResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS_0 + (sharedResourceIndexUpscaling * FFX_FSR3_RESOURCE_IDENTIFIER_UPSCALED_COUNT)]); + fsr3DispatchParams.reconstructedPrevNearestDepth = contextPrivate->backendInterfaceSharedResources.fpGetResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH_0 + (sharedResourceIndexUpscaling * FFX_FSR3_RESOURCE_IDENTIFIER_UPSCALED_COUNT)]); + fsr3DispatchParams.output = dispatchParams->upscaleOutput; + fsr3DispatchParams.jitterOffset = dispatchParams->jitterOffset; + fsr3DispatchParams.motionVectorScale = dispatchParams->motionVectorScale; + fsr3DispatchParams.renderSize = dispatchParams->renderSize; + fsr3DispatchParams.enableSharpening = dispatchParams->enableSharpening; + fsr3DispatchParams.sharpness = dispatchParams->sharpness; + fsr3DispatchParams.frameTimeDelta = dispatchParams->frameTimeDelta; + fsr3DispatchParams.preExposure = dispatchParams->preExposure; + fsr3DispatchParams.reset = dispatchParams->reset; + fsr3DispatchParams.cameraNear = dispatchParams->cameraNear; + fsr3DispatchParams.cameraFar = dispatchParams->cameraFar; + fsr3DispatchParams.cameraFovAngleVertical = dispatchParams->cameraFovAngleVertical; + + fsr3DispatchParams.viewSpaceToMetersFactor = dispatchParams->viewSpaceToMetersFactor; + + // store dispatch params, re-used in frame interpolation + contextPrivate->upscaleDescriptions[sharedResourceIndexUpscaling] = *dispatchParams; + + return ffxFsr3UpscalerContextDispatch(&contextPrivate->upscalerContext, &fsr3DispatchParams); +} + +FFX_API FfxErrorCode ffxFsr3SkipPresent(FfxFsr3Context* context) +{ + FFX_RETURN_ON_ERROR(context, FFX_ERROR_INVALID_POINTER); + + FfxFsr3Context_Private* contextPrivate = (FfxFsr3Context_Private*)(context); + contextPrivate->frameIndexFrameGeneration = contextPrivate->frameIndexUpscaling; + contextPrivate->skippedPresentsCount++; + + return FFX_OK; +} + +FfxErrorCode ffxFsr3ConfigureFrameGeneration(FfxFsr3Context* context, const FfxFrameGenerationConfig* config) +{ + FfxFsr3Context_Private* contextPrivate = (FfxFsr3Context_Private*)(context); + + FFX_ASSERT(config); + FFX_ASSERT_MESSAGE(false == contextPrivate->upscalingOnly, "Illegal to call ffxFsr3SetInterpolationMode when FFX_FSR3_ENABLE_UPSCALING_ONLY flag is set."); + FFX_ASSERT_MESSAGE(!contextPrivate->frameGenerationEnabled || !config->allowAsyncWorkloads || contextPrivate->asyncWorkloadSupported, + "Illegal to allow async workload when context was created without FFX_FSR3_ENABLE_ASYNC_WORKLOAD_SUPPORT flag set."); + + FfxFrameGenerationConfig patchedConfig = *config; + + contextPrivate->frameGenerationFlags = patchedConfig.flags; + contextPrivate->HUDLess_color = patchedConfig.HUDLessColor; + + if (patchedConfig.flags & FFX_FSR3_FRAME_GENERATION_FLAG_DRAW_DEBUG_VIEW) + { + patchedConfig.onlyPresentInterpolated = true; + } + + // reset shared resource indices + if (contextPrivate->frameGenerationEnabled != patchedConfig.frameGenerationEnabled) + { + contextPrivate->frameGenerationEnabled = patchedConfig.frameGenerationEnabled; + contextPrivate->frameIndexUpscaling = 0; + contextPrivate->frameIndexFrameGeneration = 0; + + if (contextPrivate->frameGenerationEnabled) { + FFX_ASSERT(nullptr == s_Context); + s_Context = context; + } + else if (s_Context == context) { + s_Context = nullptr; + } + } + + return contextPrivate->backendInterfaceSharedResources.fpSwapChainConfigureFrameGeneration(&patchedConfig); +} + +FfxErrorCode ffxFsr3ContextDestroy(FfxFsr3Context* context) +{ + FfxFsr3Context_Private* contextPrivate = (FfxFsr3Context_Private*)(context); + + for (FfxUInt32 i = 0; i < FFX_FSR3_RESOURCE_IDENTIFIER_COUNT; i++) + { + FFX_VALIDATE(contextPrivate->backendInterfaceSharedResources.fpDestroyResource(&contextPrivate->backendInterfaceSharedResources, contextPrivate->upscalerResources[i], contextPrivate->effectContextIdSharedResources)); + } + + if (!contextPrivate->upscalingOnly) { + FFX_VALIDATE(ffxFrameInterpolationContextDestroy(&contextPrivate->fiContext)); + + FFX_VALIDATE(ffxOpticalflowContextDestroy(&contextPrivate->ofContext)); + } + + FFX_VALIDATE(ffxFsr3UpscalerContextDestroy(&contextPrivate->upscalerContext)); + + if (!contextPrivate->upscalingOnly) + { + FFX_VALIDATE(contextPrivate->backendInterfaceSharedResources.fpDestroyBackendContext(&contextPrivate->backendInterfaceSharedResources, contextPrivate->effectContextIdSharedResources)); + } + + if (s_Context == context) { + s_Context = nullptr; + } + + return FFX_OK; +} + +float ffxFsr3GetUpscaleRatioFromQualityMode(FfxFsr3QualityMode qualityMode) +{ + return ffxFsr3UpscalerGetUpscaleRatioFromQualityMode((FfxFsr3UpscalerQualityMode)qualityMode); +} + +FfxErrorCode ffxFsr3GetRenderResolutionFromQualityMode( + uint32_t* renderWidth, uint32_t* renderHeight, uint32_t displayWidth, uint32_t displayHeight, FfxFsr3QualityMode qualityMode) +{ + return ffxFsr3UpscalerGetRenderResolutionFromQualityMode( renderWidth, renderHeight, displayWidth, displayHeight, (FfxFsr3UpscalerQualityMode) qualityMode); +} + +int32_t ffxFsr3GetJitterPhaseCount(int32_t renderWidth, int32_t displayWidth) +{ + return ffxFsr3UpscalerGetJitterPhaseCount(renderWidth, displayWidth); +} + +FfxErrorCode ffxFsr3GetJitterOffset(float* outX, float* outY, int32_t index, int32_t phaseCount) +{ + return ffxFsr3UpscalerGetJitterOffset(outX, outY, index, phaseCount); +} + +FFX_API bool ffxFsr3ResourceIsNull(FfxResource resource) +{ + return ffxFsr3UpscalerResourceIsNull(resource); +} diff --git a/sdk/src/components/fsr3/ffx_fsr3_maximum_bias.h b/sdk/src/components/fsr3/ffx_fsr3_maximum_bias.h new file mode 100644 index 00000000..9080a2a5 --- /dev/null +++ b/sdk/src/components/fsr3/ffx_fsr3_maximum_bias.h @@ -0,0 +1,47 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +// @internal + +#pragma once + +static const int32_t FFX_FSR3_MAXIMUM_BIAS_TEXTURE_WIDTH = 16; +static const int32_t FFX_FSR3_MAXIMUM_BIAS_TEXTURE_HEIGHT = 16; +static const float ffxFsr3MaximumBias[] = { + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.876f, 1.809f, 1.772f, 1.753f, 1.748f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.869f, 1.801f, 1.764f, 1.745f, 1.739f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.976f, 1.841f, 1.774f, 1.737f, 1.716f, 1.71f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.914f, 1.784f, 1.716f, 1.673f, 1.649f, 1.641f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.793f, 1.676f, 1.604f, 1.562f, 1.54f, 1.533f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.802f, 1.619f, 1.536f, 1.492f, 1.467f, 1.454f, 1.449f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.812f, 1.575f, 1.496f, 1.456f, 1.432f, 1.416f, 1.408f, 1.405f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.555f, 1.479f, 1.438f, 1.413f, 1.398f, 1.387f, 1.381f, 1.379f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.812f, 1.555f, 1.474f, 1.43f, 1.404f, 1.387f, 1.376f, 1.368f, 1.363f, 1.362f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.802f, 1.575f, 1.479f, 1.43f, 1.401f, 1.382f, 1.369f, 1.36f, 1.354f, 1.351f, 1.35f, + 2.0f, 2.0f, 1.976f, 1.914f, 1.793f, 1.619f, 1.496f, 1.438f, 1.404f, 1.382f, 1.367f, 1.357f, 1.349f, 1.344f, 1.341f, 1.34f, + 1.876f, 1.869f, 1.841f, 1.784f, 1.676f, 1.536f, 1.456f, 1.413f, 1.387f, 1.369f, 1.357f, 1.347f, 1.341f, 1.336f, 1.333f, 1.332f, + 1.809f, 1.801f, 1.774f, 1.716f, 1.604f, 1.492f, 1.432f, 1.398f, 1.376f, 1.36f, 1.349f, 1.341f, 1.335f, 1.33f, 1.328f, 1.327f, + 1.772f, 1.764f, 1.737f, 1.673f, 1.562f, 1.467f, 1.416f, 1.387f, 1.368f, 1.354f, 1.344f, 1.336f, 1.33f, 1.326f, 1.323f, 1.323f, + 1.753f, 1.745f, 1.716f, 1.649f, 1.54f, 1.454f, 1.408f, 1.381f, 1.363f, 1.351f, 1.341f, 1.333f, 1.328f, 1.323f, 1.321f, 1.32f, + 1.748f, 1.739f, 1.71f, 1.641f, 1.533f, 1.449f, 1.405f, 1.379f, 1.362f, 1.35f, 1.34f, 1.332f, 1.327f, 1.323f, 1.32f, 1.319f, + +}; diff --git a/sdk/src/components/fsr3/ffx_fsr3_private.h b/sdk/src/components/fsr3/ffx_fsr3_private.h new file mode 100644 index 00000000..ddc2829b --- /dev/null +++ b/sdk/src/components/fsr3/ffx_fsr3_private.h @@ -0,0 +1,62 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 +#include +#include +#include +#include + +// max queued frames for descriptor management +#define FSR3_MAX_QUEUED_FRAMES 2 + +// FfxFsr3Context_Private +// The private implementation of the FSR3 context. +// Actually this is only a container for Upscaler+Frameinterpolation+OpticalFlow +typedef struct FfxFsr3Context_Private { + FfxFsr3ContextDescription description; + FfxInterface backendInterfaceSharedResources; + FfxInterface backendInterfaceUpscaling; + FfxInterface backendInterfaceFrameInterpolation; + FfxFsr3UpscalerContext upscalerContext; + FfxOpticalflowContext ofContext; + FfxFrameInterpolationContext fiContext; + FfxResourceInternal upscalerResources[FFX_FSR3_RESOURCE_IDENTIFIER_COUNT]; + FfxUInt32 effectContextIdSharedResources; + FfxUInt32 effectContextIdUpscaling; + FfxUInt32 effectContextIdFrameGeneration; + float deltaTime; + bool upscalingOnly; + bool asyncWorkloadSupported; + FfxUInt32 sharedResourceCount; + FfxUInt32 frameIndexUpscaling; + FfxUInt32 frameIndexFrameGeneration; + FfxUInt32 skippedPresentsCount; + + FfxResource HUDLess_color; + + bool frameGenerationEnabled; + int32_t frameGenerationFlags; + FfxFsr3DispatchUpscaleDescription upscaleDescriptions[FSR3_MAX_QUEUED_FRAMES]; + +} FfxFsr3Context_Private; diff --git a/sdk/src/components/fsr3upscaler/CMakeLists.txt b/sdk/src/components/fsr3upscaler/CMakeLists.txt new file mode 100644 index 00000000..e8e511e7 --- /dev/null +++ b/sdk/src/components/fsr3upscaler/CMakeLists.txt @@ -0,0 +1,55 @@ +# This file is part of the FidelityFX SDK. +# +# Copyright (c) 2023 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 (FFX_FSR3UPSCALER OR FFX_FSR2 OR FFX_FSR3 OR FFX_ALL) + # Shared sources + set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) + + # Private sources + file(GLOB PRIVATE_SOURCES + # NOTE that ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp(h)" can also be used instead + # simply including effect name in the path for emphasis + "${FFX_COMPONENTS_PATH}/fsr3upscaler/*.cpp" + "${FFX_COMPONENTS_PATH}/fsr3upscaler/*.h") + + # Public source + file(GLOB PUBLIC_SOURCES + "${FFX_HOST_PATH}/ffx_fsr3upscaler.h") + list(APPEND PUBLIC_SOURCES ${FFX_PUBLIC_SOURCES}) + + if (FFX_BUILD_AS_DLL) + add_library(ffx_fsr3upscaler_${FFX_PLATFORM_NAME} SHARED ${SHARED_SOURCES} ${PRIVATE_SOURCES} ${PUBLIC_SOURCES}) + else() + add_library(ffx_fsr3upscaler_${FFX_PLATFORM_NAME} STATIC ${SHARED_SOURCES} ${PRIVATE_SOURCES} ${PUBLIC_SOURCES}) + endif() + + # API + source_group("shared_source" FILES ${SHARED_SOURCES}) + source_group("private_source" FILES ${PRIVATE_SOURCES}) + source_group("public_source" FILES ${PUBLIC_SOURCES}) + + target_include_directories(ffx_fsr3upscaler_${FFX_PLATFORM_NAME} PUBLIC ${FFX_INCLUDE_PATH}) + target_include_directories(ffx_fsr3upscaler_${FFX_PLATFORM_NAME} PUBLIC ${FFX_SHARED_PATH}) + + set_source_files_properties(${SHADERS} PROPERTIES HEADER_FILE_ONLY TRUE) + set_target_properties(ffx_fsr3upscaler_${FFX_PLATFORM_NAME} PROPERTIES FOLDER Components) + +endif() \ No newline at end of file diff --git a/sdk/src/components/fsr3upscaler/ffx_fsr3upscaler.cpp b/sdk/src/components/fsr3upscaler/ffx_fsr3upscaler.cpp new file mode 100644 index 00000000..ab8166ba --- /dev/null +++ b/sdk/src/components/fsr3upscaler/ffx_fsr3upscaler.cpp @@ -0,0 +1,1301 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 // for max used inside SPD CPU code. +#include // for fabs, abs, sinf, sqrt, etc. +#include // for memset +#include // for FLT_EPSILON +#include +#define FFX_CPU +#include +#include +#include +#include +#include +#include + +#include "ffx_fsr3upscaler_maximum_bias.h" + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wunused-variable" +#endif + +// max queued frames for descriptor management +static const uint32_t FSR3UPSCALER_MAX_QUEUED_FRAMES = 16; + +#include "ffx_fsr3upscaler_private.h" + +// lists to map shader resource bindpoint name to resource identifier +typedef struct ResourceBinding +{ + uint32_t index; + wchar_t name[64]; +}ResourceBinding; + +static const ResourceBinding srvTextureBindingTable[] = +{ + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_COLOR, L"r_input_color_jittered"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_OPAQUE_ONLY, L"r_input_opaque_only"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_MOTION_VECTORS, L"r_input_motion_vectors"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_DEPTH, L"r_input_depth" }, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_EXPOSURE, L"r_input_exposure"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTO_EXPOSURE, L"r_auto_exposure"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_REACTIVE_MASK, L"r_reactive_mask"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_TRANSPARENCY_AND_COMPOSITION_MASK, L"r_transparency_and_composition_mask"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH, L"r_reconstructed_previous_nearest_depth"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS, L"r_dilated_motion_vectors"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREVIOUS_DILATED_MOTION_VECTORS, L"r_previous_dilated_motion_vectors"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_DEPTH, L"r_dilated_depth"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR, L"r_internal_upscaled_color"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS, L"r_lock_status"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREPARED_INPUT_COLOR, L"r_prepared_input_color"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY, L"r_luma_history" }, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RCAS_INPUT, L"r_rcas_input"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LANCZOS_LUT, L"r_lanczos_lut"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE, L"r_imgMips"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_SHADING_CHANGE, L"r_img_mip_shading_change"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_5, L"r_img_mip_5"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTITIER_UPSAMPLE_MAXIMUM_BIAS_LUT, L"r_upsample_maximum_bias_lut"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_REACTIVE_MASKS, L"r_dilated_reactive_masks"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NEW_LOCKS, L"r_new_locks"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_INPUT_LUMA, L"r_lock_input_luma"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR, L"r_input_prev_color_pre_alpha"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR, L"r_input_prev_color_post_alpha"}, +}; + +static const ResourceBinding uavTextureBindingTable[] = +{ + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH, L"rw_reconstructed_previous_nearest_depth"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS, L"rw_dilated_motion_vectors"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_DEPTH, L"rw_dilated_depth"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR, L"rw_internal_upscaled_color"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS, L"rw_lock_status"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREPARED_INPUT_COLOR, L"rw_prepared_input_color"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY, L"rw_luma_history"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_UPSCALED_OUTPUT, L"rw_upscaled_output"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_SHADING_CHANGE, L"rw_img_mip_shading_change"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_5, L"rw_img_mip_5"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_REACTIVE_MASKS, L"rw_dilated_reactive_masks"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTO_EXPOSURE, L"rw_auto_exposure"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SPD_ATOMIC_COUNT, L"rw_spd_global_atomic"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NEW_LOCKS, L"rw_new_locks"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_INPUT_LUMA, L"rw_lock_input_luma"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR, L"rw_output_prev_color_pre_alpha"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR, L"rw_output_prev_color_post_alpha"}, + {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTOREACTIVE, L"rw_output_autoreactive"}, +}; + +static const ResourceBinding constantBufferBindingTable[] = +{ + {FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_FSR3UPSCALER, L"cbFSR3Upscaler"}, + {FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_SPD, L"cbSPD"}, + {FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_RCAS, L"cbRCAS"}, + {FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_GENREACTIVE, L"cbGenerateReactive"}, +}; + +typedef struct Fsr3UpscalerRcasConstants { + + uint32_t rcasConfig[4]; +} FfxRcasConstants; + +typedef struct Fsr3UpscalerSpdConstants { + + uint32_t mips; + uint32_t numworkGroups; + uint32_t workGroupOffset[2]; + uint32_t renderSize[2]; +} Fsr3UpscalerSpdConstants; + +typedef struct Fsr3UpscalerGenerateReactiveConstants +{ + float scale; + float threshold; + float binaryValue; + uint32_t flags; + +} Fsr3UpscalerGenerateReactiveConstants; + +typedef struct Fsr3UpscalerGenerateReactiveConstants2 +{ + float autoTcThreshold; + float autoTcScale; + float autoReactiveScale; + float autoReactiveMax; + +} Fsr3UpscalerGenerateReactiveConstants2; + +typedef union Fsr3UpscalerSecondaryUnion { + + Fsr3UpscalerRcasConstants rcas; + Fsr3UpscalerSpdConstants spd; + Fsr3UpscalerGenerateReactiveConstants2 autogenReactive; +} Fsr3UpscalerSecondaryUnion; + +FfxConstantBuffer globalFsr3UpscalerConstantBuffers[4] = { + { sizeof(Fsr3UpscalerConstants) / sizeof(uint32_t) }, + { sizeof(Fsr3UpscalerSpdConstants) / sizeof(uint32_t) }, + { sizeof(Fsr3UpscalerRcasConstants) / sizeof(uint32_t) }, + { sizeof(Fsr3UpscalerGenerateReactiveConstants) / sizeof(uint32_t) } +}; + +// Lanczos +static float lanczos2(float value) +{ + return abs(value) < FFX_EPSILON ? 1.f : (sinf(FFX_PI * value) / (FFX_PI * value)) * (sinf(0.5f * FFX_PI * value) / (0.5f * FFX_PI * value)); +} + +// Calculate halton number for index and base. +static float halton(int32_t index, int32_t base) +{ + float f = 1.0f, result = 0.0f; + + for (int32_t currentIndex = index; currentIndex > 0;) { + + f /= (float)base; + result = result + f * (float)(currentIndex % base); + currentIndex = (uint32_t)(floorf((float)(currentIndex) / (float)(base))); + } + + return result; +} + +static void fsr3upscalerDebugCheckDispatch(FfxFsr3UpscalerContext_Private* context, const FfxFsr3UpscalerDispatchDescription* params) +{ + if (params->commandList == nullptr) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_ERROR, L"commandList is null"); + } + + if (params->color.resource == nullptr) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_ERROR, L"color resource is null"); + } + + if (params->depth.resource == nullptr) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_ERROR, L"depth resource is null"); + } + + if (params->motionVectors.resource == nullptr) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_ERROR, L"motionVectors resource is null"); + } + + if (params->exposure.resource != nullptr) + { + if ((context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE) == FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, L"exposure resource provided, however auto exposure flag is present"); + } + } + + if (params->output.resource == nullptr) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_ERROR, L"output resource is null"); + } + + if (fabs(params->jitterOffset.x) > 1.0f || fabs(params->jitterOffset.y) > 1.0f) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, L"jitterOffset contains value outside of expected range [-1.0, 1.0]"); + } + + if ((params->motionVectorScale.x > (float)context->contextDescription.maxRenderSize.width) || + (params->motionVectorScale.y > (float)context->contextDescription.maxRenderSize.height)) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, L"motionVectorScale contains scale value greater than maxRenderSize"); + } + if ((params->motionVectorScale.x == 0.0f) || + (params->motionVectorScale.y == 0.0f)) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, L"motionVectorScale contains zero scale value"); + } + + if ((params->renderSize.width > context->contextDescription.maxRenderSize.width) || + (params->renderSize.height > context->contextDescription.maxRenderSize.height)) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, L"renderSize is greater than context maxRenderSize"); + } + if ((params->renderSize.width == 0) || + (params->renderSize.height == 0)) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, L"renderSize contains zero dimension"); + } + + if (params->sharpness < 0.0f || params->sharpness > 1.0f) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, L"sharpness contains value outside of expected range [0.0, 1.0]"); + } + + if (params->frameTimeDelta < 1.0f) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, L"frameTimeDelta is less than 1.0f - this value should be milliseconds (~16.6f for 60fps)"); + } + + if (params->preExposure == 0.0f) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_ERROR, L"preExposure provided as 0.0f which is invalid"); + } + + bool infiniteDepth = (context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_DEPTH_INFINITE) == FFX_FSR3UPSCALER_ENABLE_DEPTH_INFINITE; + bool inverseDepth = (context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED) == FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED; + + if (inverseDepth) + { + if (params->cameraNear < params->cameraFar) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, + L"FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED flag is present yet cameraNear is less than cameraFar"); + } + if (infiniteDepth) + { + if (params->cameraNear != FLT_MAX) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, + L"FFX_FSR3UPSCALER_ENABLE_DEPTH_INFINITE and FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED present, yet cameraNear != FLT_MAX"); + } + } + if (params->cameraFar < 0.075f) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, + L"FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED present, cameraFar value is very low which may result in depth separation artefacting"); + } + } + else + { + if (params->cameraNear > params->cameraFar) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, + L"cameraNear is greater than cameraFar in non-inverted-depth context"); + } + if (infiniteDepth) + { + if (params->cameraFar != FLT_MAX) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, + L"FFX_FSR3UPSCALER_ENABLE_DEPTH_INFINITE present, yet cameraFar != FLT_MAX"); + } + } + if (params->cameraNear < 0.075f) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_WARNING, + L"cameraNear value is very low which may result in depth separation artefacting"); + } + } + + if (params->cameraFovAngleVertical <= 0.0f) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_ERROR, L"cameraFovAngleVertical is 0.0f - this value should be > 0.0f"); + } + if (params->cameraFovAngleVertical > FFX_PI) + { + context->contextDescription.fpMessage(FFX_MESSAGE_TYPE_ERROR, L"cameraFovAngleVertical is greater than 180 degrees/PI"); + } +} + +static FfxErrorCode patchResourceBindings(FfxPipelineState* inoutPipeline) +{ + for (uint32_t srvIndex = 0; srvIndex < inoutPipeline->srvTextureCount; ++srvIndex) + { + int32_t mapIndex = 0; + for (mapIndex = 0; mapIndex < _countof(srvTextureBindingTable); ++mapIndex) + { + if (0 == wcscmp(srvTextureBindingTable[mapIndex].name, inoutPipeline->srvTextureBindings[srvIndex].name)) + break; + } + if (mapIndex == _countof(srvTextureBindingTable)) + return FFX_ERROR_INVALID_ARGUMENT; + + inoutPipeline->srvTextureBindings[srvIndex].resourceIdentifier = srvTextureBindingTable[mapIndex].index; + } + + for (uint32_t uavIndex = 0; uavIndex < inoutPipeline->uavTextureCount; ++uavIndex) + { + int32_t mapIndex = 0; + for (mapIndex = 0; mapIndex < _countof(uavTextureBindingTable); ++mapIndex) + { + if (0 == wcscmp(uavTextureBindingTable[mapIndex].name, inoutPipeline->uavTextureBindings[uavIndex].name)) + break; + } + if (mapIndex == _countof(uavTextureBindingTable)) + return FFX_ERROR_INVALID_ARGUMENT; + + inoutPipeline->uavTextureBindings[uavIndex].resourceIdentifier = uavTextureBindingTable[mapIndex].index; + } + + for (uint32_t cbIndex = 0; cbIndex < inoutPipeline->constCount; ++cbIndex) + { + int32_t mapIndex = 0; + for (mapIndex = 0; mapIndex < _countof(constantBufferBindingTable); ++mapIndex) + { + if (0 == wcscmp(constantBufferBindingTable[mapIndex].name, inoutPipeline->constantBufferBindings[cbIndex].name)) + break; + } + if (mapIndex == _countof(constantBufferBindingTable)) + return FFX_ERROR_INVALID_ARGUMENT; + + inoutPipeline->constantBufferBindings[cbIndex].resourceIdentifier = constantBufferBindingTable[mapIndex].index; + } + + return FFX_OK; +} + +static uint32_t getPipelinePermutationFlags(uint32_t contextFlags, FfxFsr3UpscalerPass passId, bool fp16, bool force64, bool useLut) +{ + // work out what permutation to load. + uint32_t flags = 0; + flags |= (contextFlags & FFX_FSR3UPSCALER_ENABLE_HIGH_DYNAMIC_RANGE) ? FSR3UPSCALER_SHADER_PERMUTATION_HDR_COLOR_INPUT : 0; + flags |= (contextFlags & FFX_FSR3UPSCALER_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS) ? 0 : FSR3UPSCALER_SHADER_PERMUTATION_LOW_RES_MOTION_VECTORS; + flags |= (contextFlags & FFX_FSR3UPSCALER_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION) ? FSR3UPSCALER_SHADER_PERMUTATION_JITTER_MOTION_VECTORS : 0; + flags |= (contextFlags & FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED) ? FSR3UPSCALER_SHADER_PERMUTATION_DEPTH_INVERTED : 0; + flags |= (passId == FFX_FSR3UPSCALER_PASS_ACCUMULATE_SHARPEN) ? FSR3UPSCALER_SHADER_PERMUTATION_ENABLE_SHARPENING : 0; + flags |= (useLut) ? FSR3UPSCALER_SHADER_PERMUTATION_USE_LANCZOS_TYPE : 0; + flags |= (force64) ? FSR3UPSCALER_SHADER_PERMUTATION_FORCE_WAVE64 : 0; + flags |= (fp16 && (passId != FFX_FSR3UPSCALER_PASS_RCAS)) ? FSR3UPSCALER_SHADER_PERMUTATION_ALLOW_FP16 : 0; + return flags; +} + +static FfxErrorCode createPipelineStates(FfxFsr3UpscalerContext_Private* context) +{ + FFX_ASSERT(context); + + FfxPipelineDescription pipelineDescription = {}; + pipelineDescription.contextFlags = context->contextDescription.flags; + pipelineDescription.stage = FFX_BIND_COMPUTE_SHADER_STAGE; + + // Samplers + pipelineDescription.samplerCount = 2; + FfxSamplerDescription samplerDescs[2] = { { FFX_FILTER_TYPE_MINMAGMIP_POINT, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_BIND_COMPUTE_SHADER_STAGE }, + { FFX_FILTER_TYPE_MINMAGMIP_LINEAR, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_BIND_COMPUTE_SHADER_STAGE} }; + pipelineDescription.samplers = samplerDescs; + + // Root constants + pipelineDescription.rootConstantBufferCount = 2; + FfxRootConstantDescription rootConstantDescs[2] = { {sizeof(Fsr3UpscalerConstants) / sizeof(uint32_t), FFX_BIND_COMPUTE_SHADER_STAGE }, + { sizeof(Fsr3UpscalerSecondaryUnion) / sizeof(uint32_t), FFX_BIND_COMPUTE_SHADER_STAGE } }; + pipelineDescription.rootConstants = rootConstantDescs; + + // Query device capabilities + FfxDeviceCapabilities capabilities; + context->contextDescription.backendInterface.fpGetDeviceCapabilities(&context->contextDescription.backendInterface, &capabilities); + + // Setup a few options used to determine permutation flags + bool haveShaderModel66 = capabilities.minimumSupportedShaderModel >= FFX_SHADER_MODEL_6_6; + bool supportedFP16 = capabilities.fp16Supported; + bool canForceWave64 = false; + bool useLut = false; + + const uint32_t waveLaneCountMin = capabilities.waveLaneCountMin; + const uint32_t waveLaneCountMax = capabilities.waveLaneCountMax; + if (waveLaneCountMin == 32 && waveLaneCountMax == 64) + { + useLut = true; + canForceWave64 = haveShaderModel66; + } + else + canForceWave64 = false; + + // Work out what permutation to load. + uint32_t contextFlags = context->contextDescription.flags; + + // Set up pipeline descriptor (basically RootSignature and binding) + wcscpy_s(pipelineDescription.name, L"FSR3-LUM_PYRAMID"); + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline(&context->contextDescription.backendInterface, FFX_EFFECT_FSR3UPSCALER, FFX_FSR3UPSCALER_PASS_COMPUTE_LUMINANCE_PYRAMID, + getPipelinePermutationFlags(contextFlags, FFX_FSR3UPSCALER_PASS_COMPUTE_LUMINANCE_PYRAMID, supportedFP16, canForceWave64, useLut), + &pipelineDescription, context->effectContextId, &context->pipelineComputeLuminancePyramid)); + wcscpy_s(pipelineDescription.name, L"FSR3-RCAS"); + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline(&context->contextDescription.backendInterface, FFX_EFFECT_FSR3UPSCALER, FFX_FSR3UPSCALER_PASS_RCAS, + getPipelinePermutationFlags(contextFlags, FFX_FSR3UPSCALER_PASS_RCAS, supportedFP16, canForceWave64, useLut), + &pipelineDescription, context->effectContextId, &context->pipelineRCAS)); + wcscpy_s(pipelineDescription.name, L"FSR3-GEN_REACTIVE"); + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline(&context->contextDescription.backendInterface, FFX_EFFECT_FSR3UPSCALER, FFX_FSR3UPSCALER_PASS_GENERATE_REACTIVE, + getPipelinePermutationFlags(contextFlags, FFX_FSR3UPSCALER_PASS_GENERATE_REACTIVE, supportedFP16, canForceWave64, useLut), + &pipelineDescription, context->effectContextId, &context->pipelineGenerateReactive)); + + pipelineDescription.rootConstantBufferCount = 1; + + wcscpy_s(pipelineDescription.name, L"FSR3-DEPTH_CLIP"); + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline(&context->contextDescription.backendInterface, FFX_EFFECT_FSR3UPSCALER, FFX_FSR3UPSCALER_PASS_DEPTH_CLIP, + getPipelinePermutationFlags(contextFlags, FFX_FSR3UPSCALER_PASS_DEPTH_CLIP, supportedFP16, canForceWave64, useLut), + &pipelineDescription, context->effectContextId, &context->pipelineDepthClip)); + wcscpy_s(pipelineDescription.name, L"FSR3-RECON_PREV_DEPTH"); + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline(&context->contextDescription.backendInterface, FFX_EFFECT_FSR3UPSCALER, FFX_FSR3UPSCALER_PASS_RECONSTRUCT_PREVIOUS_DEPTH, + getPipelinePermutationFlags(contextFlags, FFX_FSR3UPSCALER_PASS_RECONSTRUCT_PREVIOUS_DEPTH, supportedFP16, canForceWave64, useLut), + &pipelineDescription, context->effectContextId, &context->pipelineReconstructPreviousDepth)); + wcscpy_s(pipelineDescription.name, L"FSR3-LOCK"); + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline(&context->contextDescription.backendInterface, FFX_EFFECT_FSR3UPSCALER, FFX_FSR3UPSCALER_PASS_LOCK, + getPipelinePermutationFlags(contextFlags, FFX_FSR3UPSCALER_PASS_LOCK, supportedFP16, canForceWave64, useLut), + &pipelineDescription, context->effectContextId, &context->pipelineLock)); + wcscpy_s(pipelineDescription.name, L"FSR3-ACCUMULATE"); + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline(&context->contextDescription.backendInterface, FFX_EFFECT_FSR3UPSCALER, FFX_FSR3UPSCALER_PASS_ACCUMULATE, + getPipelinePermutationFlags(contextFlags, FFX_FSR3UPSCALER_PASS_ACCUMULATE, supportedFP16, canForceWave64, useLut), + &pipelineDescription, context->effectContextId, &context->pipelineAccumulate)); + wcscpy_s(pipelineDescription.name, L"FSR3-ACCUM_SHARP"); + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline(&context->contextDescription.backendInterface, FFX_EFFECT_FSR3UPSCALER, FFX_FSR3UPSCALER_PASS_ACCUMULATE_SHARPEN, + getPipelinePermutationFlags(contextFlags, FFX_FSR3UPSCALER_PASS_ACCUMULATE_SHARPEN, supportedFP16, canForceWave64, useLut), + &pipelineDescription, context->effectContextId, &context->pipelineAccumulateSharpen)); + + // for each pipeline: re-route/fix-up IDs based on names + FFX_VALIDATE(patchResourceBindings(&context->pipelineDepthClip)); + FFX_VALIDATE(patchResourceBindings(&context->pipelineReconstructPreviousDepth)); + FFX_VALIDATE(patchResourceBindings(&context->pipelineLock)); + FFX_VALIDATE(patchResourceBindings(&context->pipelineAccumulate)); + FFX_VALIDATE(patchResourceBindings(&context->pipelineComputeLuminancePyramid)); + FFX_VALIDATE(patchResourceBindings(&context->pipelineAccumulateSharpen)); + FFX_VALIDATE(patchResourceBindings(&context->pipelineRCAS)); + FFX_VALIDATE(patchResourceBindings(&context->pipelineGenerateReactive)); + FFX_VALIDATE(patchResourceBindings(&context->pipelineTcrAutogenerate)); + + return FFX_OK; +} + +static FfxErrorCode generateReactiveMaskInternal(FfxFsr3UpscalerContext_Private* contextPrivate, const FfxFsr3UpscalerDispatchDescription* params); + +static FfxErrorCode fsr3upscalerCreate(FfxFsr3UpscalerContext_Private* context, const FfxFsr3UpscalerContextDescription* contextDescription) +{ + FFX_ASSERT(context); + FFX_ASSERT(contextDescription); + + // Setup the data for implementation. + memset(context, 0, sizeof(FfxFsr3UpscalerContext_Private)); + context->device = contextDescription->backendInterface.device; + + memcpy(&context->contextDescription, contextDescription, sizeof(FfxFsr3UpscalerContextDescription)); + + // Create the context. + FfxErrorCode errorCode = context->contextDescription.backendInterface.fpCreateBackendContext(&context->contextDescription.backendInterface, &context->effectContextId); + FFX_RETURN_ON_ERROR(errorCode == FFX_OK, errorCode); + + // call out for device caps. + errorCode = context->contextDescription.backendInterface.fpGetDeviceCapabilities(&context->contextDescription.backendInterface, &context->deviceCapabilities); + FFX_RETURN_ON_ERROR(errorCode == FFX_OK, errorCode); + + // set defaults + context->firstExecution = true; + context->resourceFrameIndex = 0; + + context->constants.displaySize[0] = contextDescription->displaySize.width; + context->constants.displaySize[1] = contextDescription->displaySize.height; + + // generate the data for the LUT. + const uint32_t lanczos2LutWidth = 128; + int16_t lanczos2Weights[lanczos2LutWidth] = { }; + + for (uint32_t currentLanczosWidthIndex = 0; currentLanczosWidthIndex < lanczos2LutWidth; currentLanczosWidthIndex++) { + + const float x = 2.0f * currentLanczosWidthIndex / float(lanczos2LutWidth - 1); + const float y = lanczos2(x); + lanczos2Weights[currentLanczosWidthIndex] = int16_t(roundf(y * 32767.0f)); + } + + // upload path only supports R16_SNORM, let's go and convert + int16_t maximumBias[FFX_FSR3UPSCALER_MAXIMUM_BIAS_TEXTURE_WIDTH * FFX_FSR3UPSCALER_MAXIMUM_BIAS_TEXTURE_HEIGHT]; + for (uint32_t i = 0; i < FFX_FSR3UPSCALER_MAXIMUM_BIAS_TEXTURE_WIDTH * FFX_FSR3UPSCALER_MAXIMUM_BIAS_TEXTURE_HEIGHT; ++i) { + + maximumBias[i] = int16_t(roundf(ffxFsr3UpscalerMaximumBias[i] / 2.0f * 32767.0f)); + } + + uint8_t defaultReactiveMaskData = 0U; + uint32_t atomicInitData = 0U; + float defaultExposure[] = { 0.0f, 0.0f }; + const FfxResourceType texture1dResourceType = (context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_TEXTURE1D_USAGE) ? FFX_RESOURCE_TYPE_TEXTURE1D : FFX_RESOURCE_TYPE_TEXTURE2D; + + // declare internal resources needed + const FfxInternalResourceDescription internalSurfaceDesc[] = { + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREPARED_INPUT_COLOR, L"FSR3UPSCALER_PreparedInputColor", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_ALIASABLE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREVIOUS_DILATED_MOTION_VECTORS, L"FSR3UPSCALER_PreviousDilatedVelocity", FFX_RESOURCE_TYPE_TEXTURE2D, (FfxResourceUsage)(FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV), + FFX_SURFACE_FORMAT_R16G16_FLOAT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS_1, L"FSR3UPSCALER_LockStatus1", FFX_RESOURCE_TYPE_TEXTURE2D, (FfxResourceUsage)(FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV), + FFX_SURFACE_FORMAT_R16G16_FLOAT, contextDescription->displaySize.width, contextDescription->displaySize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS_2, L"FSR3UPSCALER_LockStatus2", FFX_RESOURCE_TYPE_TEXTURE2D, (FfxResourceUsage)(FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV), + FFX_SURFACE_FORMAT_R16G16_FLOAT, contextDescription->displaySize.width, contextDescription->displaySize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_INPUT_LUMA, L"FSR3UPSCALER_LockInputLuma", FFX_RESOURCE_TYPE_TEXTURE2D, (FfxResourceUsage)(FFX_RESOURCE_USAGE_UAV), + FFX_SURFACE_FORMAT_R16_FLOAT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_ALIASABLE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NEW_LOCKS, L"FSR3UPSCALER_NewLocks", FFX_RESOURCE_TYPE_TEXTURE2D, (FfxResourceUsage)(FFX_RESOURCE_USAGE_UAV), + FFX_SURFACE_FORMAT_R8_UNORM, contextDescription->displaySize.width, contextDescription->displaySize.height, 1, FFX_RESOURCE_FLAGS_ALIASABLE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR_1, L"FSR3UPSCALER_InternalUpscaled1", FFX_RESOURCE_TYPE_TEXTURE2D, (FfxResourceUsage)(FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV), + FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, contextDescription->displaySize.width, contextDescription->displaySize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR_2, L"FSR3UPSCALER_InternalUpscaled2", FFX_RESOURCE_TYPE_TEXTURE2D, (FfxResourceUsage)(FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV), + FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, contextDescription->displaySize.width, contextDescription->displaySize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE, L"FSR3UPSCALER_ExposureMips", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16_FLOAT, contextDescription->maxRenderSize.width / 2, contextDescription->maxRenderSize.height / 2, 0, FFX_RESOURCE_FLAGS_ALIASABLE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY_1, L"FSR3UPSCALER_LumaHistory1", FFX_RESOURCE_TYPE_TEXTURE2D, (FfxResourceUsage)(FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV), + FFX_SURFACE_FORMAT_R8G8B8A8_UNORM, contextDescription->displaySize.width, contextDescription->displaySize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY_2, L"FSR3UPSCALER_LumaHistory2", FFX_RESOURCE_TYPE_TEXTURE2D, (FfxResourceUsage)(FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV), + FFX_SURFACE_FORMAT_R8G8B8A8_UNORM, contextDescription->displaySize.width, contextDescription->displaySize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SPD_ATOMIC_COUNT, L"FSR3UPSCALER_SpdAtomicCounter", FFX_RESOURCE_TYPE_TEXTURE2D, (FfxResourceUsage)(FFX_RESOURCE_USAGE_UAV), + FFX_SURFACE_FORMAT_R32_UINT, 1, 1, 1, FFX_RESOURCE_FLAGS_ALIASABLE, sizeof(atomicInitData), &atomicInitData }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_REACTIVE_MASKS, L"FSR3UPSCALER_DilatedReactiveMasks", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8G8_UNORM, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_ALIASABLE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LANCZOS_LUT, L"FSR3UPSCALER_LanczosLutData", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_READ_ONLY, + FFX_SURFACE_FORMAT_R16_SNORM, lanczos2LutWidth, 1, 1, FFX_RESOURCE_FLAGS_NONE, sizeof(lanczos2Weights), lanczos2Weights }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_REACTIVITY, L"FSR3UPSCALER_DefaultReactiviyMask", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_READ_ONLY, + FFX_SURFACE_FORMAT_R8_UNORM, 1, 1, 1, FFX_RESOURCE_FLAGS_NONE, sizeof(defaultReactiveMaskData), &defaultReactiveMaskData }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTITIER_UPSAMPLE_MAXIMUM_BIAS_LUT, L"FSR3UPSCALER_MaximumUpsampleBias", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_READ_ONLY, + FFX_SURFACE_FORMAT_R16_SNORM, FFX_FSR3UPSCALER_MAXIMUM_BIAS_TEXTURE_WIDTH, FFX_FSR3UPSCALER_MAXIMUM_BIAS_TEXTURE_HEIGHT, 1, FFX_RESOURCE_FLAGS_NONE, sizeof(maximumBias), maximumBias }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_EXPOSURE, L"FSR3UPSCALER_DefaultExposure", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_READ_ONLY, + FFX_SURFACE_FORMAT_R32G32_FLOAT, 1, 1, 1, FFX_RESOURCE_FLAGS_NONE, sizeof(defaultExposure), defaultExposure }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTO_EXPOSURE, L"FSR3UPSCALER_AutoExposure", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R32G32_FLOAT, 1, 1, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR_1, L"FSR3UPSCALER_PrevPreAlpha0", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R11G11B10_FLOAT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR_1, L"FSR3UPSCALER_PrevPostAlpha0", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R11G11B10_FLOAT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR_2, L"FSR3UPSCALER_PrevPreAlpha1", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R11G11B10_FLOAT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR_2, L"FSR3UPSCALER_PrevPostAlpha1", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R11G11B10_FLOAT, contextDescription->maxRenderSize.width, contextDescription->maxRenderSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + }; + + // clear the SRV resources to NULL. + memset(context->srvResources, 0, sizeof(context->srvResources)); + + for (int32_t currentSurfaceIndex = 0; currentSurfaceIndex < FFX_ARRAY_ELEMENTS(internalSurfaceDesc); ++currentSurfaceIndex) { + + const FfxInternalResourceDescription* currentSurfaceDescription = &internalSurfaceDesc[currentSurfaceIndex]; + const FfxResourceType resourceType = internalSurfaceDesc[currentSurfaceIndex].type; + const FfxResourceDescription resourceDescription = { resourceType, currentSurfaceDescription->format, currentSurfaceDescription->width, currentSurfaceDescription->height, 1, currentSurfaceDescription->mipCount, FFX_RESOURCE_FLAGS_NONE, currentSurfaceDescription->usage }; + const FfxResourceStates initialState = (currentSurfaceDescription->usage == FFX_RESOURCE_USAGE_READ_ONLY) ? FFX_RESOURCE_STATE_COMPUTE_READ : FFX_RESOURCE_STATE_UNORDERED_ACCESS; + const FfxCreateResourceDescription createResourceDescription = { FFX_HEAP_TYPE_DEFAULT, resourceDescription, initialState, currentSurfaceDescription->initDataSize, currentSurfaceDescription->initData, currentSurfaceDescription->name, currentSurfaceDescription->id }; + + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreateResource(&context->contextDescription.backendInterface, &createResourceDescription, context->effectContextId, &context->srvResources[currentSurfaceDescription->id])); + } + + // copy resources to uavResrouces list + memcpy(context->uavResources, context->srvResources, sizeof(context->srvResources)); + + // avoid compiling pipelines on first render + { + errorCode = createPipelineStates(context); + FFX_RETURN_ON_ERROR(errorCode == FFX_OK, errorCode); + } + return FFX_OK; +} + +static FfxErrorCode fsr3upscalerRelease(FfxFsr3UpscalerContext_Private* context) +{ + FFX_ASSERT(context); + + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineDepthClip, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineReconstructPreviousDepth, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineLock, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineAccumulate, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineAccumulateSharpen, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineRCAS, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineComputeLuminancePyramid, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineGenerateReactive, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineTcrAutogenerate, context->effectContextId); + + // unregister resources not created internally + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_OPAQUE_ONLY] = {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL}; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_COLOR] = { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL }; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_DEPTH] = { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL }; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_MOTION_VECTORS] = { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL }; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_EXPOSURE] = { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL }; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_REACTIVE_MASK] = { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL }; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_TRANSPARENCY_AND_COMPOSITION_MASK] = { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL }; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS] = { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL }; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR] = { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL }; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RCAS_INPUT] = { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL }; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_UPSCALED_OUTPUT] = { FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL }; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH] = {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL}; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS] = {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL}; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_DEPTH] = {FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_NULL}; + + + // Release the copy resources for those that had init data + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SPD_ATOMIC_COUNT], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LANCZOS_LUT], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_REACTIVITY], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTITIER_UPSAMPLE_MAXIMUM_BIAS_LUT], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_EXPOSURE], context->effectContextId); + + // release internal resources + for (int32_t currentResourceIndex = 0; currentResourceIndex < FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_COUNT; ++currentResourceIndex) { + + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[currentResourceIndex], context->effectContextId); + } + + // Destroy the context + context->contextDescription.backendInterface.fpDestroyBackendContext(&context->contextDescription.backendInterface, context->effectContextId); + + return FFX_OK; +} + +static void setupDeviceDepthToViewSpaceDepthParams(FfxFsr3UpscalerContext_Private* context, const FfxFsr3UpscalerDispatchDescription* params) +{ + const bool bInverted = (context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED) == FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED; + const bool bInfinite = (context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_DEPTH_INFINITE) == FFX_FSR3UPSCALER_ENABLE_DEPTH_INFINITE; + + // make sure it has no impact if near and far plane values are swapped in dispatch params + // the flags "inverted" and "infinite" will decide what transform to use + float fMin = FFX_MINIMUM(params->cameraNear, params->cameraFar); + float fMax = FFX_MAXIMUM(params->cameraNear, params->cameraFar); + + if (bInverted) { + float tmp = fMin; + fMin = fMax; + fMax = tmp; + } + + // a 0 0 0 x + // 0 b 0 0 y + // 0 0 c d z + // 0 0 e 0 1 + + const float fQ = fMax / (fMin - fMax); + const float d = -1.0f; // for clarity + + const float matrix_elem_c[2][2] = { + fQ, // non reversed, non infinite + -1.0f - FLT_EPSILON, // non reversed, infinite + fQ, // reversed, non infinite + 0.0f + FLT_EPSILON // reversed, infinite + }; + + const float matrix_elem_e[2][2] = { + fQ * fMin, // non reversed, non infinite + -fMin - FLT_EPSILON, // non reversed, infinite + fQ * fMin, // reversed, non infinite + fMax, // reversed, infinite + }; + + context->constants.deviceToViewDepth[0] = d * matrix_elem_c[bInverted][bInfinite]; + context->constants.deviceToViewDepth[1] = matrix_elem_e[bInverted][bInfinite]; + + // revert x and y coords + const float aspect = params->renderSize.width / float(params->renderSize.height); + const float cotHalfFovY = cosf(0.5f * params->cameraFovAngleVertical) / sinf(0.5f * params->cameraFovAngleVertical); + const float a = cotHalfFovY / aspect; + const float b = cotHalfFovY; + + context->constants.deviceToViewDepth[2] = (1.0f / a); + context->constants.deviceToViewDepth[3] = (1.0f / b); +} + +static void scheduleDispatch(FfxFsr3UpscalerContext_Private* context, const FfxFsr3UpscalerDispatchDescription* params, const FfxPipelineState* pipeline, uint32_t dispatchX, uint32_t dispatchY) +{ + FfxComputeJobDescription jobDescriptor = {}; + + for (uint32_t currentShaderResourceViewIndex = 0; currentShaderResourceViewIndex < pipeline->srvTextureCount; ++currentShaderResourceViewIndex) { + + const uint32_t currentResourceId = pipeline->srvTextureBindings[currentShaderResourceViewIndex].resourceIdentifier; + const FfxResourceInternal currentResource = context->srvResources[currentResourceId]; + jobDescriptor.srvTextures[currentShaderResourceViewIndex] = currentResource; + wcscpy_s(jobDescriptor.srvTextureNames[currentShaderResourceViewIndex], pipeline->srvTextureBindings[currentShaderResourceViewIndex].name); + } + + for (uint32_t currentUnorderedAccessViewIndex = 0; currentUnorderedAccessViewIndex < pipeline->uavTextureCount; ++currentUnorderedAccessViewIndex) { + + const uint32_t currentResourceId = pipeline->uavTextureBindings[currentUnorderedAccessViewIndex].resourceIdentifier; + wcscpy_s(jobDescriptor.uavTextureNames[currentUnorderedAccessViewIndex], pipeline->uavTextureBindings[currentUnorderedAccessViewIndex].name); + + if (currentResourceId >= FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_0 && currentResourceId <= FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_12) + { + const FfxResourceInternal currentResource = context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE]; + jobDescriptor.uavTextures[currentUnorderedAccessViewIndex] = currentResource; + jobDescriptor.uavTextureMips[currentUnorderedAccessViewIndex] = currentResourceId - FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE_MIPMAP_0; + } + else + { + const FfxResourceInternal currentResource = context->uavResources[currentResourceId]; + jobDescriptor.uavTextures[currentUnorderedAccessViewIndex] = currentResource; + jobDescriptor.uavTextureMips[currentUnorderedAccessViewIndex] = 0; + } + } + + jobDescriptor.dimensions[0] = dispatchX; + jobDescriptor.dimensions[1] = dispatchY; + jobDescriptor.dimensions[2] = 1; + jobDescriptor.pipeline = *pipeline; + + for (uint32_t currentRootConstantIndex = 0; currentRootConstantIndex < pipeline->constCount; ++currentRootConstantIndex) { + wcscpy_s( jobDescriptor.cbNames[currentRootConstantIndex], pipeline->constantBufferBindings[currentRootConstantIndex].name); + jobDescriptor.cbs[currentRootConstantIndex] = globalFsr3UpscalerConstantBuffers[pipeline->constantBufferBindings[currentRootConstantIndex].resourceIdentifier]; + } + + FfxGpuJobDescription dispatchJob = { FFX_GPU_JOB_COMPUTE }; + dispatchJob.computeJobDescriptor = jobDescriptor; + + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &dispatchJob); +} + +FFX_API FfxErrorCode ffxFsr3UpscalerGetSharedResourceDescriptions(FfxFsr3UpscalerContext* context, FfxFsr3UpscalerSharedResourceDescriptions* SharedResources) +{ + FFX_RETURN_ON_ERROR( + context, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + SharedResources, + FFX_ERROR_INVALID_POINTER); + + FfxFsr3UpscalerContext_Private* contextPrivate = (FfxFsr3UpscalerContext_Private*)(context); + SharedResources->dilatedDepth = { FFX_HEAP_TYPE_DEFAULT, { FFX_RESOURCE_TYPE_TEXTURE2D, FFX_SURFACE_FORMAT_R32_FLOAT, contextPrivate->contextDescription.maxRenderSize.width, contextPrivate->contextDescription.maxRenderSize.height, 1, 1, FFX_RESOURCE_FLAGS_ALIASABLE, (FfxResourceUsage)(FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV) }, + FFX_RESOURCE_STATE_UNORDERED_ACCESS, 0, nullptr, L"FSR3UPSCALER_DilatedDepth", FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_DEPTH }; + SharedResources->dilatedMotionVectors = { FFX_HEAP_TYPE_DEFAULT, { FFX_RESOURCE_TYPE_TEXTURE2D, FFX_SURFACE_FORMAT_R16G16_FLOAT, contextPrivate->contextDescription.maxRenderSize.width, contextPrivate->contextDescription.maxRenderSize.height, 1, 1, FFX_RESOURCE_FLAGS_ALIASABLE, (FfxResourceUsage)(FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV) }, + FFX_RESOURCE_STATE_UNORDERED_ACCESS, 0, nullptr, L"FSR3UPSCALER_DilatedVelocity", FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS }; + SharedResources->reconstructedPrevNearestDepth = { FFX_HEAP_TYPE_DEFAULT, { FFX_RESOURCE_TYPE_TEXTURE2D, FFX_SURFACE_FORMAT_R32_UINT, contextPrivate->contextDescription.maxRenderSize.width, contextPrivate->contextDescription.maxRenderSize.height, 1, 1, FFX_RESOURCE_FLAGS_ALIASABLE, (FfxResourceUsage)(FFX_RESOURCE_USAGE_UAV) }, + FFX_RESOURCE_STATE_UNORDERED_ACCESS, 0, nullptr, L"FSR3UPSCALER_ReconstructedPrevNearestDepth", FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH }; + + return FFX_OK; +} + +static FfxErrorCode fsr3upscalerDispatch(FfxFsr3UpscalerContext_Private* context, const FfxFsr3UpscalerDispatchDescription* params) +{ + + if ((context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_DEBUG_CHECKING) == FFX_FSR3UPSCALER_ENABLE_DEBUG_CHECKING) + { + fsr3upscalerDebugCheckDispatch(context, params); + } + + // take a short cut to the command list + FfxCommandList commandList = params->commandList; + + if (context->firstExecution) + { + FfxGpuJobDescription clearJob = { FFX_GPU_JOB_CLEAR_FLOAT }; + + const float clearValuesToZeroFloat[]{ 0.f, 0.f, 0.f, 0.f }; + memcpy(clearJob.clearJobDescriptor.color, clearValuesToZeroFloat, 4 * sizeof(float)); + + clearJob.clearJobDescriptor.target = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS_1]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS_2]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREPARED_INPUT_COLOR]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + } + + // Prepare per frame descriptor tables + const bool isOddFrame = !!(context->resourceFrameIndex & 1); + const uint32_t currentCpuOnlyTableBase = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_COUNT : 0; + const uint32_t currentGpuTableBase = 2 * FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_COUNT * context->resourceFrameIndex; + const uint32_t lockStatusSrvResourceIndex = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS_2 : FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS_1; + const uint32_t lockStatusUavResourceIndex = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS_1 : FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS_2; + const uint32_t upscaledColorSrvResourceIndex = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR_2 : FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR_1; + const uint32_t upscaledColorUavResourceIndex = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR_1 : FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR_2; + const uint32_t lumaHistorySrvResourceIndex = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY_2 : FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY_1; + const uint32_t lumaHistoryUavResourceIndex = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY_1 : FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY_2; + + const uint32_t prevPreAlphaColorSrvResourceIndex = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR_2 : FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR_1; + const uint32_t prevPreAlphaColorUavResourceIndex = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR_1 : FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR_2; + const uint32_t prevPostAlphaColorSrvResourceIndex = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR_2 : FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR_1; + const uint32_t prevPostAlphaColorUavResourceIndex = isOddFrame ? FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR_1 : FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR_2; + + const bool resetAccumulation = params->reset || context->firstExecution; + context->firstExecution = false; + + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->color, context->effectContextId, &context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_COLOR]); + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->depth, context->effectContextId, &context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_DEPTH]); + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->motionVectors, context->effectContextId, &context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_MOTION_VECTORS]); + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->dilatedMotionVectors, context->effectContextId, &context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS]); + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->dilatedMotionVectors, context->effectContextId, &context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS]); + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->dilatedDepth, context->effectContextId, &context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_DEPTH]); + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->dilatedDepth, context->effectContextId, &context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_DEPTH]); + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->reconstructedPrevNearestDepth, context->effectContextId, &context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH]); + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->reconstructedPrevNearestDepth, context->effectContextId, &context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH]); + + // if auto exposure is enabled use the auto exposure SRV, otherwise what the app sends. + if (context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE) { + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_EXPOSURE] = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTO_EXPOSURE]; + } else { + if (ffxFsr3UpscalerResourceIsNull(params->exposure)) { + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_EXPOSURE] = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_EXPOSURE]; + } else { + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->exposure, context->effectContextId, &context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_EXPOSURE]); + } + } + + if (ffxFsr3UpscalerResourceIsNull(params->reactive)) { + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_REACTIVE_MASK] = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_REACTIVITY]; + } + else { + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->reactive, context->effectContextId, &context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_REACTIVE_MASK]); + } + + if (ffxFsr3UpscalerResourceIsNull(params->transparencyAndComposition)) { + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_TRANSPARENCY_AND_COMPOSITION_MASK] = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_DEFAULT_REACTIVITY]; + } else { + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->transparencyAndComposition, context->effectContextId, &context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_TRANSPARENCY_AND_COMPOSITION_MASK]); + } + + context->contextDescription.backendInterface.fpRegisterResource(&context->contextDescription.backendInterface, ¶ms->output, context->effectContextId, &context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_UPSCALED_OUTPUT]); + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS] = context->srvResources[lockStatusSrvResourceIndex]; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR] = context->srvResources[upscaledColorSrvResourceIndex]; + context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS] = context->uavResources[lockStatusUavResourceIndex]; + context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INTERNAL_UPSCALED_COLOR] = context->uavResources[upscaledColorUavResourceIndex]; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RCAS_INPUT] = context->uavResources[upscaledColorUavResourceIndex]; + + context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY] = context->uavResources[lumaHistoryUavResourceIndex]; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LUMA_HISTORY] = context->srvResources[lumaHistorySrvResourceIndex]; + + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR] = context->srvResources[prevPreAlphaColorSrvResourceIndex]; + context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_PRE_ALPHA_COLOR] = context->uavResources[prevPreAlphaColorUavResourceIndex]; + context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR] = context->srvResources[prevPostAlphaColorSrvResourceIndex]; + context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREV_POST_ALPHA_COLOR] = context->uavResources[prevPostAlphaColorUavResourceIndex]; + + // actual resource size may differ from render/display resolution (e.g. due to Hw/API restrictions), so query the descriptor for UVs adjustment + const FfxResourceDescription resourceDescInputColor = context->contextDescription.backendInterface.fpGetResourceDescription(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_COLOR]); + const FfxResourceDescription resourceDescLockStatus = context->contextDescription.backendInterface.fpGetResourceDescription(&context->contextDescription.backendInterface, context->srvResources[lockStatusSrvResourceIndex]); + const FfxResourceDescription resourceDescReactiveMask = context->contextDescription.backendInterface.fpGetResourceDescription(&context->contextDescription.backendInterface, context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_REACTIVE_MASK]); + FFX_ASSERT(resourceDescInputColor.type == FFX_RESOURCE_TYPE_TEXTURE2D); + FFX_ASSERT(resourceDescLockStatus.type == FFX_RESOURCE_TYPE_TEXTURE2D); + + context->constants.jitterOffset[0] = params->jitterOffset.x; + context->constants.jitterOffset[1] = params->jitterOffset.y; + context->constants.renderSize[0] = int32_t(params->renderSize.width ? params->renderSize.width : resourceDescInputColor.width); + context->constants.renderSize[1] = int32_t(params->renderSize.height ? params->renderSize.height : resourceDescInputColor.height); + context->constants.maxRenderSize[0] = int32_t(context->contextDescription.maxRenderSize.width); + context->constants.maxRenderSize[1] = int32_t(context->contextDescription.maxRenderSize.height); + context->constants.inputColorResourceDimensions[0] = resourceDescInputColor.width; + context->constants.inputColorResourceDimensions[1] = resourceDescInputColor.height; + + // compute the horizontal FOV for the shader from the vertical one. + const float aspectRatio = (float)params->renderSize.width / (float)params->renderSize.height; + const float cameraAngleHorizontal = atan(tan(params->cameraFovAngleVertical / 2) * aspectRatio) * 2; + context->constants.tanHalfFOV = tanf(cameraAngleHorizontal * 0.5f); + context->constants.viewSpaceToMetersFactor = (params->viewSpaceToMetersFactor > 0.0f) ? params->viewSpaceToMetersFactor : 1.0f; + + // compute params to enable device depth to view space depth computation in shader + setupDeviceDepthToViewSpaceDepthParams(context, params); + + // To be updated if resource is larger than the actual image size + context->constants.downscaleFactor[0] = float(context->constants.renderSize[0]) / context->contextDescription.displaySize.width; + context->constants.downscaleFactor[1] = float(context->constants.renderSize[1]) / context->contextDescription.displaySize.height; + context->constants.previousFramePreExposure = context->constants.preExposure; + context->constants.preExposure = (params->preExposure != 0) ? params->preExposure : 1.0f; + + // motion vector data + const int32_t* motionVectorsTargetSize = (context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS) ? context->constants.displaySize : context->constants.renderSize; + + context->constants.motionVectorScale[0] = (params->motionVectorScale.x / motionVectorsTargetSize[0]); + context->constants.motionVectorScale[1] = (params->motionVectorScale.y / motionVectorsTargetSize[1]); + + // compute jitter cancellation + if (context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION) { + + context->constants.motionVectorJitterCancellation[0] = (context->previousJitterOffset[0] - context->constants.jitterOffset[0]) / motionVectorsTargetSize[0]; + context->constants.motionVectorJitterCancellation[1] = (context->previousJitterOffset[1] - context->constants.jitterOffset[1]) / motionVectorsTargetSize[1]; + + context->previousJitterOffset[0] = context->constants.jitterOffset[0]; + context->previousJitterOffset[1] = context->constants.jitterOffset[1]; + } + + // lock data, assuming jitter sequence length computation for now + const int32_t jitterPhaseCount = ffxFsr3UpscalerGetJitterPhaseCount(params->renderSize.width, context->contextDescription.displaySize.width); + + // init on first frame + if (resetAccumulation || context->constants.jitterPhaseCount == 0) { + context->constants.jitterPhaseCount = (float)jitterPhaseCount; + } else { + const int32_t jitterPhaseCountDelta = (int32_t)(jitterPhaseCount - context->constants.jitterPhaseCount); + if (jitterPhaseCountDelta > 0) { + context->constants.jitterPhaseCount++; + } else if (jitterPhaseCountDelta < 0) { + context->constants.jitterPhaseCount--; + } + } + + // convert delta time to seconds and clamp to [0, 1]. + context->constants.deltaTime = FFX_MAXIMUM(0.0f, FFX_MINIMUM(1.0f, params->frameTimeDelta / 1000.0f)); + + if (resetAccumulation) { + context->constants.frameIndex = 0; + } else { + context->constants.frameIndex++; + } + + // shading change usage of the SPD mip levels. + context->constants.lumaMipLevelToUse = uint32_t(FFX_FSR3UPSCALER_SHADING_CHANGE_MIP_LEVEL); + + const float mipDiv = float(2 << context->constants.lumaMipLevelToUse); + context->constants.lumaMipDimensions[0] = uint32_t(context->constants.maxRenderSize[0] / mipDiv); + context->constants.lumaMipDimensions[1] = uint32_t(context->constants.maxRenderSize[1] / mipDiv); + + // reactive mask bias + const int32_t threadGroupWorkRegionDim = 8; + const int32_t dispatchSrcX = (context->constants.renderSize[0] + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + const int32_t dispatchSrcY = (context->constants.renderSize[1] + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + const int32_t dispatchDstX = (context->contextDescription.displaySize.width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + const int32_t dispatchDstY = (context->contextDescription.displaySize.height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + + // Clear reconstructed depth for max depth store. + if (resetAccumulation) { + + FfxGpuJobDescription clearJob = { FFX_GPU_JOB_CLEAR_FLOAT }; + + // LockStatus resource has no sign bit, callback functions are compensating for this. + // Clearing the resource must follow the same logic. + float clearValuesLockStatus[4]{}; + clearValuesLockStatus[LOCK_LIFETIME_REMAINING] = 0.0f; + clearValuesLockStatus[LOCK_TEMPORAL_LUMA] = 0.0f; + + memcpy(clearJob.clearJobDescriptor.color, clearValuesLockStatus, 4 * sizeof(float)); + clearJob.clearJobDescriptor.target = context->srvResources[lockStatusSrvResourceIndex]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + + const float clearValuesToZeroFloat[]{ 0.f, 0.f, 0.f, 0.f }; + memcpy(clearJob.clearJobDescriptor.color, clearValuesToZeroFloat, 4 * sizeof(float)); + clearJob.clearJobDescriptor.target = context->srvResources[upscaledColorSrvResourceIndex]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + + clearJob.clearJobDescriptor.target = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_SCENE_LUMINANCE]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + + //if (context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_AUTO_EXPOSURE) + // Auto exposure always used to track luma changes in locking logic + { + const float clearValuesExposure[]{ -1.f, 1e8f, 0.f, 0.f }; + memcpy(clearJob.clearJobDescriptor.color, clearValuesExposure, 4 * sizeof(float)); + clearJob.clearJobDescriptor.target = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTO_EXPOSURE]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + } + } + + { + FfxGpuJobDescription clearJob = {FFX_GPU_JOB_CLEAR_FLOAT}; + // FSR3: need to clear here since we need the content of this surface for frameinterpolation + // so clearing in the lock pass is not an option + const bool bInverted = (context->contextDescription.flags & FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED) == FFX_FSR3UPSCALER_ENABLE_DEPTH_INVERTED; + const float clearDepthValue[]{bInverted ? 0.f : 1.f, bInverted ? 0.f : 1.f, bInverted ? 0.f : 1.f, bInverted ? 0.f : 1.f}; + memcpy(clearJob.clearJobDescriptor.color, clearDepthValue, 4 * sizeof(float)); + clearJob.clearJobDescriptor.target = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_RECONSTRUCTED_PREVIOUS_NEAREST_DEPTH]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + } + // Auto exposure + uint32_t dispatchThreadGroupCountXY[2]; + uint32_t workGroupOffset[2]; + uint32_t numWorkGroupsAndMips[2]; + uint32_t rectInfo[4] = { 0, 0, params->renderSize.width, params->renderSize.height }; + ffxSpdSetup(dispatchThreadGroupCountXY, workGroupOffset, numWorkGroupsAndMips, rectInfo); + + // downsample + Fsr3UpscalerSpdConstants luminancePyramidConstants; + luminancePyramidConstants.numworkGroups = numWorkGroupsAndMips[0]; + luminancePyramidConstants.mips = numWorkGroupsAndMips[1]; + luminancePyramidConstants.workGroupOffset[0] = workGroupOffset[0]; + luminancePyramidConstants.workGroupOffset[1] = workGroupOffset[1]; + luminancePyramidConstants.renderSize[0] = params->renderSize.width; + luminancePyramidConstants.renderSize[1] = params->renderSize.height; + + // compute the constants. + Fsr3UpscalerRcasConstants rcasConsts = {}; + const float sharpenessRemapped = (-2.0f * params->sharpness) + 2.0f; + FsrRcasCon(rcasConsts.rcasConfig, sharpenessRemapped); + + // initialize constantBuffers data + memcpy(&globalFsr3UpscalerConstantBuffers[FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_FSR3UPSCALER].data, &context->constants, globalFsr3UpscalerConstantBuffers[FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_FSR3UPSCALER].num32BitEntries * sizeof(uint32_t)); + memcpy(&globalFsr3UpscalerConstantBuffers[FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_SPD].data, &luminancePyramidConstants, globalFsr3UpscalerConstantBuffers[FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_SPD].num32BitEntries * sizeof(uint32_t)); + memcpy(&globalFsr3UpscalerConstantBuffers[FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_RCAS].data, &rcasConsts, globalFsr3UpscalerConstantBuffers[FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_RCAS].num32BitEntries * sizeof(uint32_t)); + + + scheduleDispatch(context, params, &context->pipelineComputeLuminancePyramid, dispatchThreadGroupCountXY[0], dispatchThreadGroupCountXY[1]); + scheduleDispatch(context, params, &context->pipelineReconstructPreviousDepth, dispatchSrcX, dispatchSrcY); + scheduleDispatch(context, params, &context->pipelineDepthClip, dispatchSrcX, dispatchSrcY); + + const bool sharpenEnabled = params->enableSharpening; + + scheduleDispatch(context, params, &context->pipelineLock, dispatchSrcX, dispatchSrcY); + scheduleDispatch(context, params, sharpenEnabled ? &context->pipelineAccumulateSharpen : &context->pipelineAccumulate, dispatchDstX, dispatchDstY); + + // RCAS + if (sharpenEnabled) { + + // dispatch RCAS + const int32_t threadGroupWorkRegionDimRCAS = 16; + const int32_t dispatchX = (context->contextDescription.displaySize.width + (threadGroupWorkRegionDimRCAS - 1)) / threadGroupWorkRegionDimRCAS; + const int32_t dispatchY = (context->contextDescription.displaySize.height + (threadGroupWorkRegionDimRCAS - 1)) / threadGroupWorkRegionDimRCAS; + scheduleDispatch(context, params, &context->pipelineRCAS, dispatchX, dispatchY); + } + + // Schedule work for the copy/setup command list + { + FfxGpuJobDescription copyJob = {FFX_GPU_JOB_COPY}; + copyJob.copyJobDescriptor.src = context->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS]; + copyJob.copyJobDescriptor.dst = context->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_PREVIOUS_DILATED_MOTION_VECTORS]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, ©Job); + } + + context->resourceFrameIndex = (context->resourceFrameIndex + 1) % FSR3UPSCALER_MAX_QUEUED_FRAMES; + + // Fsr3UpscalerMaxQueuedFrames must be an even number. + FFX_STATIC_ASSERT((FSR3UPSCALER_MAX_QUEUED_FRAMES & 1) == 0); + + context->contextDescription.backendInterface.fpExecuteGpuJobs(&context->contextDescription.backendInterface, commandList); + + // release dynamic resources + context->contextDescription.backendInterface.fpUnregisterResources(&context->contextDescription.backendInterface, commandList, context->effectContextId); + + return FFX_OK; +} + +FFX_API FfxErrorCode ffxFsr3UpscalerContextCreate(FfxFsr3UpscalerContext* context, const FfxFsr3UpscalerContextDescription* contextDescription) +{ + // zero context memory + memset(context, 0, sizeof(FfxFsr3UpscalerContext)); + + // check pointers are valid. + FFX_RETURN_ON_ERROR( + context, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + contextDescription, + FFX_ERROR_INVALID_POINTER); + + // validate that all callbacks are set for the interface + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.fpGetDeviceCapabilities, FFX_ERROR_INCOMPLETE_INTERFACE); + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.fpCreateBackendContext, FFX_ERROR_INCOMPLETE_INTERFACE); + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.fpDestroyBackendContext, FFX_ERROR_INCOMPLETE_INTERFACE); + + // if a scratch buffer is declared, then we must have a size + if (contextDescription->backendInterface.scratchBuffer) { + + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.scratchBufferSize, FFX_ERROR_INCOMPLETE_INTERFACE); + } + + // ensure the context is large enough for the internal context. + FFX_STATIC_ASSERT(sizeof(FfxFsr3UpscalerContext) >= sizeof(FfxFsr3UpscalerContext_Private)); + + // create the context. + FfxFsr3UpscalerContext_Private* contextPrivate = (FfxFsr3UpscalerContext_Private*)(context); + const FfxErrorCode errorCode = fsr3upscalerCreate(contextPrivate, contextDescription); + + return errorCode; +} + +FfxErrorCode ffxFsr3UpscalerContextDestroy(FfxFsr3UpscalerContext* context) +{ + FFX_RETURN_ON_ERROR( + context, + FFX_ERROR_INVALID_POINTER); + + // destroy the context. + FfxFsr3UpscalerContext_Private* contextPrivate = (FfxFsr3UpscalerContext_Private*)(context); + const FfxErrorCode errorCode = fsr3upscalerRelease(contextPrivate); + return errorCode; +} + +FfxErrorCode ffxFsr3UpscalerContextDispatch(FfxFsr3UpscalerContext* context, const FfxFsr3UpscalerDispatchDescription* dispatchParams) +{ + FFX_RETURN_ON_ERROR( + context, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + dispatchParams, + FFX_ERROR_INVALID_POINTER); + + FfxFsr3UpscalerContext_Private* contextPrivate = (FfxFsr3UpscalerContext_Private*)(context); + + // validate that renderSize is within the maximum. + FFX_RETURN_ON_ERROR( + dispatchParams->renderSize.width <= contextPrivate->contextDescription.maxRenderSize.width, + FFX_ERROR_OUT_OF_RANGE); + FFX_RETURN_ON_ERROR( + dispatchParams->renderSize.height <= contextPrivate->contextDescription.maxRenderSize.height, + FFX_ERROR_OUT_OF_RANGE); + FFX_RETURN_ON_ERROR( + contextPrivate->device, + FFX_ERROR_NULL_DEVICE); + + // dispatch the FSR3 passes. + const FfxErrorCode errorCode = fsr3upscalerDispatch(contextPrivate, dispatchParams); + return errorCode; +} + +FFX_API float ffxFsr3UpscalerGetUpscaleRatioFromQualityMode(FfxFsr3UpscalerQualityMode qualityMode) +{ + switch (qualityMode) { + case FFX_FSR3UPSCALER_QUALITY_MODE_NATIVEAA: + return 1.0f; + case FFX_FSR3UPSCALER_QUALITY_MODE_QUALITY: + return 1.5f; + case FFX_FSR3UPSCALER_QUALITY_MODE_BALANCED: + return 1.7f; + case FFX_FSR3UPSCALER_QUALITY_MODE_PERFORMANCE: + return 2.0f; + case FFX_FSR3UPSCALER_QUALITY_MODE_ULTRA_PERFORMANCE: + return 3.0f; + default: + return 0.0f; + } +} + +FFX_API FfxErrorCode ffxFsr3UpscalerGetRenderResolutionFromQualityMode( + uint32_t* renderWidth, + uint32_t* renderHeight, + uint32_t displayWidth, + uint32_t displayHeight, + FfxFsr3UpscalerQualityMode qualityMode) +{ + FFX_RETURN_ON_ERROR( + renderWidth, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + renderHeight, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + FFX_FSR3UPSCALER_QUALITY_MODE_NATIVEAA <= qualityMode && qualityMode <= FFX_FSR3UPSCALER_QUALITY_MODE_ULTRA_PERFORMANCE, + FFX_ERROR_INVALID_ENUM); + + // scale by the predefined ratios in each dimension. + const float ratio = ffxFsr3UpscalerGetUpscaleRatioFromQualityMode(qualityMode); + const uint32_t scaledDisplayWidth = (uint32_t)((float)displayWidth / ratio); + const uint32_t scaledDisplayHeight = (uint32_t)((float)displayHeight / ratio); + *renderWidth = scaledDisplayWidth; + *renderHeight = scaledDisplayHeight; + + return FFX_OK; +} + +int32_t ffxFsr3UpscalerGetJitterPhaseCount(int32_t renderWidth, int32_t displayWidth) +{ + const float basePhaseCount = 8.0f; + const int32_t jitterPhaseCount = int32_t(basePhaseCount * pow((float(displayWidth) / renderWidth), 2.0f)); + return jitterPhaseCount; +} + +FfxErrorCode ffxFsr3UpscalerGetJitterOffset(float* outX, float* outY, int32_t index, int32_t phaseCount) +{ + FFX_RETURN_ON_ERROR( + outX, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + outY, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + phaseCount > 0, + FFX_ERROR_INVALID_ARGUMENT); + + const float x = halton((index % phaseCount) + 1, 2) - 0.5f; + const float y = halton((index % phaseCount) + 1, 3) - 0.5f; + + *outX = x; + *outY = y; + return FFX_OK; +} + +FFX_API bool ffxFsr3UpscalerResourceIsNull(FfxResource resource) +{ + return resource.resource == NULL; +} + +FfxErrorCode ffxFsr3UpscalerContextGenerateReactiveMask(FfxFsr3UpscalerContext* context, const FfxFsr3UpscalerGenerateReactiveDescription* params) +{ + FFX_RETURN_ON_ERROR( + context, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + params, + FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR( + params->commandList, + FFX_ERROR_INVALID_POINTER); + + FfxFsr3UpscalerContext_Private* contextPrivate = (FfxFsr3UpscalerContext_Private*)(context); + + FFX_RETURN_ON_ERROR( + contextPrivate->device, + FFX_ERROR_NULL_DEVICE); + + // take a short cut to the command list + FfxCommandList commandList = params->commandList; + + FfxPipelineState* pipeline = &contextPrivate->pipelineGenerateReactive; + + const int32_t threadGroupWorkRegionDim = 8; + const int32_t dispatchSrcX = (params->renderSize.width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + const int32_t dispatchSrcY = (params->renderSize.height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + + FfxComputeJobDescription jobDescriptor = {}; + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->colorOpaqueOnly, contextPrivate->effectContextId, &contextPrivate->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_OPAQUE_ONLY]); + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->colorPreUpscale, contextPrivate->effectContextId, &contextPrivate->srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_INPUT_COLOR]); + contextPrivate->contextDescription.backendInterface.fpRegisterResource(&contextPrivate->contextDescription.backendInterface, ¶ms->outReactive, contextPrivate->effectContextId, &contextPrivate->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTOREACTIVE]); + + jobDescriptor.uavTextures[0] = contextPrivate->uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_AUTOREACTIVE]; + + wcscpy_s(jobDescriptor.srvTextureNames[0], pipeline->srvTextureBindings[0].name); + wcscpy_s(jobDescriptor.srvTextureNames[1], pipeline->srvTextureBindings[1].name); + wcscpy_s(jobDescriptor.uavTextureNames[0], pipeline->uavTextureBindings[0].name); + + jobDescriptor.dimensions[0] = dispatchSrcX; + jobDescriptor.dimensions[1] = dispatchSrcY; + jobDescriptor.dimensions[2] = 1; + jobDescriptor.pipeline = *pipeline; + + for (uint32_t currentShaderResourceViewIndex = 0; currentShaderResourceViewIndex < pipeline->srvTextureCount; ++currentShaderResourceViewIndex) { + + const uint32_t currentResourceId = pipeline->srvTextureBindings[currentShaderResourceViewIndex].resourceIdentifier; + const FfxResourceInternal currentResource = contextPrivate->srvResources[currentResourceId]; + jobDescriptor.srvTextures[currentShaderResourceViewIndex] = currentResource; + wcscpy_s(jobDescriptor.srvTextureNames[currentShaderResourceViewIndex], pipeline->srvTextureBindings[currentShaderResourceViewIndex].name); + } + + Fsr3UpscalerGenerateReactiveConstants genReactiveConsts = {}; + genReactiveConsts.scale = params->scale; + genReactiveConsts.threshold = params->cutoffThreshold; + genReactiveConsts.binaryValue = params->binaryValue; + genReactiveConsts.flags = params->flags; + + memcpy(&globalFsr3UpscalerConstantBuffers[FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_GENREACTIVE].data, + &genReactiveConsts, + globalFsr3UpscalerConstantBuffers[FFX_FSR3UPSCALER_CONSTANTBUFFER_IDENTIFIER_GENREACTIVE].num32BitEntries * sizeof(uint32_t)); + + for (uint32_t currentRootConstantIndex = 0; currentRootConstantIndex < pipeline->constCount; ++currentRootConstantIndex) + { + wcscpy_s(jobDescriptor.cbNames[currentRootConstantIndex], pipeline->constantBufferBindings[currentRootConstantIndex].name); + jobDescriptor.cbs[currentRootConstantIndex] = globalFsr3UpscalerConstantBuffers[pipeline->constantBufferBindings[currentRootConstantIndex].resourceIdentifier]; + } + + FfxGpuJobDescription dispatchJob = { FFX_GPU_JOB_COMPUTE }; + dispatchJob.computeJobDescriptor = jobDescriptor; + + contextPrivate->contextDescription.backendInterface.fpScheduleGpuJob(&contextPrivate->contextDescription.backendInterface, &dispatchJob); + + contextPrivate->contextDescription.backendInterface.fpExecuteGpuJobs(&contextPrivate->contextDescription.backendInterface, commandList); + + // release dynamic resources + contextPrivate->contextDescription.backendInterface.fpUnregisterResources(&contextPrivate->contextDescription.backendInterface, commandList, contextPrivate->effectContextId); + + return FFX_OK; +} diff --git a/sdk/src/components/fsr3upscaler/ffx_fsr3upscaler_maximum_bias.h b/sdk/src/components/fsr3upscaler/ffx_fsr3upscaler_maximum_bias.h new file mode 100644 index 00000000..5a75cbc6 --- /dev/null +++ b/sdk/src/components/fsr3upscaler/ffx_fsr3upscaler_maximum_bias.h @@ -0,0 +1,47 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + + +// @internal + +#pragma once + +static const int32_t FFX_FSR3UPSCALER_MAXIMUM_BIAS_TEXTURE_WIDTH = 16; +static const int32_t FFX_FSR3UPSCALER_MAXIMUM_BIAS_TEXTURE_HEIGHT = 16; +static const float ffxFsr3UpscalerMaximumBias[] = { + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.876f, 1.809f, 1.772f, 1.753f, 1.748f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.869f, 1.801f, 1.764f, 1.745f, 1.739f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.976f, 1.841f, 1.774f, 1.737f, 1.716f, 1.71f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.914f, 1.784f, 1.716f, 1.673f, 1.649f, 1.641f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.793f, 1.676f, 1.604f, 1.562f, 1.54f, 1.533f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.802f, 1.619f, 1.536f, 1.492f, 1.467f, 1.454f, 1.449f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.812f, 1.575f, 1.496f, 1.456f, 1.432f, 1.416f, 1.408f, 1.405f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.555f, 1.479f, 1.438f, 1.413f, 1.398f, 1.387f, 1.381f, 1.379f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.812f, 1.555f, 1.474f, 1.43f, 1.404f, 1.387f, 1.376f, 1.368f, 1.363f, 1.362f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.802f, 1.575f, 1.479f, 1.43f, 1.401f, 1.382f, 1.369f, 1.36f, 1.354f, 1.351f, 1.35f, + 2.0f, 2.0f, 1.976f, 1.914f, 1.793f, 1.619f, 1.496f, 1.438f, 1.404f, 1.382f, 1.367f, 1.357f, 1.349f, 1.344f, 1.341f, 1.34f, + 1.876f, 1.869f, 1.841f, 1.784f, 1.676f, 1.536f, 1.456f, 1.413f, 1.387f, 1.369f, 1.357f, 1.347f, 1.341f, 1.336f, 1.333f, 1.332f, + 1.809f, 1.801f, 1.774f, 1.716f, 1.604f, 1.492f, 1.432f, 1.398f, 1.376f, 1.36f, 1.349f, 1.341f, 1.335f, 1.33f, 1.328f, 1.327f, + 1.772f, 1.764f, 1.737f, 1.673f, 1.562f, 1.467f, 1.416f, 1.387f, 1.368f, 1.354f, 1.344f, 1.336f, 1.33f, 1.326f, 1.323f, 1.323f, + 1.753f, 1.745f, 1.716f, 1.649f, 1.54f, 1.454f, 1.408f, 1.381f, 1.363f, 1.351f, 1.341f, 1.333f, 1.328f, 1.323f, 1.321f, 1.32f, + 1.748f, 1.739f, 1.71f, 1.641f, 1.533f, 1.449f, 1.405f, 1.379f, 1.362f, 1.35f, 1.34f, 1.332f, 1.327f, 1.323f, 1.32f, 1.319f, + +}; diff --git a/sdk/src/components/fsr3upscaler/ffx_fsr3upscaler_private.h b/sdk/src/components/fsr3upscaler/ffx_fsr3upscaler_private.h new file mode 100644 index 00000000..97b3064b --- /dev/null +++ b/sdk/src/components/fsr3upscaler/ffx_fsr3upscaler_private.h @@ -0,0 +1,106 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 + +/// An enumeration of all the permutations that can be passed to the FSR3 Upscaler algorithm. +/// +/// FSR3 Upscaler features are organized through a set of pre-defined compile +/// permutation options that need to be specified. Which shader blob +/// is returned for pipeline creation will be determined by what combination +/// of shader permutations are enabled. +/// +/// @ingroup FSR3Upscaler +typedef enum Fs3UpscalerShaderPermutationOptions +{ + FSR3UPSCALER_SHADER_PERMUTATION_USE_LANCZOS_TYPE = (1 << 0), ///< Off means reference, On means LUT + FSR3UPSCALER_SHADER_PERMUTATION_HDR_COLOR_INPUT = (1 << 1), ///< Enables the HDR code path + FSR3UPSCALER_SHADER_PERMUTATION_LOW_RES_MOTION_VECTORS = (1 << 2), ///< Indicates low resolution motion vectors provided + FSR3UPSCALER_SHADER_PERMUTATION_JITTER_MOTION_VECTORS = (1 << 3), ///< Indicates motion vectors were generated with jitter + FSR3UPSCALER_SHADER_PERMUTATION_DEPTH_INVERTED = (1 << 4), ///< Indicates input resources were generated with inverted depth + FSR3UPSCALER_SHADER_PERMUTATION_ENABLE_SHARPENING = (1 << 5), ///< Enables a supplementary sharpening pass + FSR3UPSCALER_SHADER_PERMUTATION_FORCE_WAVE64 = (1 << 6), ///< doesn't map to a define, selects different table + FSR3UPSCALER_SHADER_PERMUTATION_ALLOW_FP16 = (1 << 7), ///< Enables fast math computations where possible +} Fs3UpscalerShaderPermutationOptions; + +// Constants for FSR3 Upscaler dispatches. Must be kept in sync with cbFSR3Upscaler in ffx_fsr2_callbacks_hlsl.h +typedef struct Fsr3UpscalerConstants { + + int32_t renderSize[2]; + int32_t maxRenderSize[2]; + int32_t displaySize[2]; + int32_t inputColorResourceDimensions[2]; + int32_t lumaMipDimensions[2]; + int32_t lumaMipLevelToUse; + int32_t frameIndex; + + float deviceToViewDepth[4]; + float jitterOffset[2]; + float motionVectorScale[2]; + float downscaleFactor[2]; + float motionVectorJitterCancellation[2]; + float preExposure; + float previousFramePreExposure; + float tanHalfFOV; + float jitterPhaseCount; + float deltaTime; + float dynamicResChangeFactor; + float viewSpaceToMetersFactor; +} Fsr3UpscalerConstants; + +struct FfxFsr3UpscalerContextDescription; +struct FfxDeviceCapabilities; +struct FfxPipelineState; + +// FfxFsr3UpscalerContext_Private +// The private implementation of the FSR3 Upscaler context. +typedef struct FfxFsr3UpscalerContext_Private { + + FfxFsr3UpscalerContextDescription contextDescription; + FfxUInt32 effectContextId; + Fsr3UpscalerConstants constants; + FfxDevice device; + FfxDeviceCapabilities deviceCapabilities; + FfxPipelineState pipelineDepthClip; + FfxPipelineState pipelineReconstructPreviousDepth; + FfxPipelineState pipelineLock; + FfxPipelineState pipelineAccumulate; + FfxPipelineState pipelineAccumulateSharpen; + FfxPipelineState pipelineRCAS; + FfxPipelineState pipelineComputeLuminancePyramid; + FfxPipelineState pipelineGenerateReactive; + FfxPipelineState pipelineTcrAutogenerate; + + // 2 arrays of resources, as e.g. FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_LOCK_STATUS will use different resources when bound as SRV vs when bound as UAV + FfxResourceInternal srvResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_COUNT]; + FfxResourceInternal uavResources[FFX_FSR3UPSCALER_RESOURCE_IDENTIFIER_COUNT]; + + bool firstExecution; + uint32_t resourceFrameIndex; + float previousJitterOffset[2]; + int32_t jitterPhaseCountRemaining; + +} FfxFsr3UpscalerContext_Private; + +// declare fsr3UpscalerCreate so it can be used from fsr3 +FFX_API FfxErrorCode fsr3UpscalerCreate(FfxFsr3UpscalerContext_Private* context, const FfxFsr3UpscalerContextDescription* contextDescription); diff --git a/sdk/src/components/lens/CMakeLists.txt b/sdk/src/components/lens/CMakeLists.txt index a67f5e80..649d90e4 100644 --- a/sdk/src/components/lens/CMakeLists.txt +++ b/sdk/src/components/lens/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_LENS OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/lens/ffx_lens.cpp b/sdk/src/components/lens/ffx_lens.cpp index 3a22bb6f..4f10f075 100644 --- a/sdk/src/components/lens/ffx_lens.cpp +++ b/sdk/src/components/lens/ffx_lens.cpp @@ -1,26 +1,26 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 // for memset #include // for fabs, abs, sinf, sqrt, etc. @@ -283,8 +283,8 @@ static FfxErrorCode lensRelease(FfxLensContext_Private* context) context->uavResources[FFX_LENS_RESOURCE_IDENTIFIER_OUTPUT_TEXTURE] = { FFX_LENS_RESOURCE_IDENTIFIER_NULL }; // Release internal resources and copy resource - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_LENS_RESOURCE_IDENTIFIER_INPUT_TEXTURE]); - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_LENS_RESOURCE_IDENTIFIER_INPUT_TEXTURE]); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_LENS_RESOURCE_IDENTIFIER_INPUT_TEXTURE], context->effectContextId); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_LENS_RESOURCE_IDENTIFIER_INPUT_TEXTURE], context->effectContextId); // Destroy the context context->contextDescription.backendInterface.fpDestroyBackendContext(&context->contextDescription.backendInterface, context->effectContextId); diff --git a/sdk/src/components/lens/ffx_lens_private.h b/sdk/src/components/lens/ffx_lens_private.h index 297d5234..ff7e8a86 100644 --- a/sdk/src/components/lens/ffx_lens_private.h +++ b/sdk/src/components/lens/ffx_lens_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 diff --git a/sdk/src/components/lpm/CMakeLists.txt b/sdk/src/components/lpm/CMakeLists.txt index 1f55efc9..dd0ffdf8 100644 --- a/sdk/src/components/lpm/CMakeLists.txt +++ b/sdk/src/components/lpm/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_LPM OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/lpm/ffx_lpm.cpp b/sdk/src/components/lpm/ffx_lpm.cpp index 56f1eea4..6968acad 100644 --- a/sdk/src/components/lpm/ffx_lpm.cpp +++ b/sdk/src/components/lpm/ffx_lpm.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 // for memset #include // for _countof #include // for fabs, abs, sinf, sqrt, etc. diff --git a/sdk/src/components/lpm/ffx_lpm_private.h b/sdk/src/components/lpm/ffx_lpm_private.h index 3f29c413..d6ac69dd 100644 --- a/sdk/src/components/lpm/ffx_lpm_private.h +++ b/sdk/src/components/lpm/ffx_lpm_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 diff --git a/sdk/src/components/opticalflow/CMakeLists.txt b/sdk/src/components/opticalflow/CMakeLists.txt new file mode 100644 index 00000000..239042e7 --- /dev/null +++ b/sdk/src/components/opticalflow/CMakeLists.txt @@ -0,0 +1,56 @@ +# This file is part of the FidelityFX SDK. +# +# Copyright (c) 2023 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 (FFX_OF OR FFX_FI OR FFX_FSR2 OR FFX_FSR3 OR FFX_ALL) + # Shared sources + set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) + + # Private sources + file(GLOB PRIVATE_SOURCES + # NOTE that ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp(h)" can also be used instead + # simply including effect name in the path for emphasis + "${FFX_COMPONENTS_PATH}/opticalflow/*.cpp" + "${FFX_COMPONENTS_PATH}/opticalflow/*.h") + + # Public source + file(GLOB PUBLIC_SOURCES + "${FFX_HOST_PATH}/opticalflow/*.h" + "${FFX_HOST_PATH}/opticalflow/*.cpp") + list(APPEND PUBLIC_SOURCES ${FFX_PUBLIC_SOURCES}) + + if (FFX_BUILD_AS_DLL) + add_library(ffx_opticalflow_${FFX_PLATFORM_NAME} SHARED ${SHARED_SOURCES} ${PRIVATE_SOURCES} ${PUBLIC_SOURCES}) + else() + add_library(ffx_opticalflow_${FFX_PLATFORM_NAME} STATIC ${SHARED_SOURCES} ${PRIVATE_SOURCES} ${PUBLIC_SOURCES}) + endif() + + # API + source_group("shared_source" FILES ${SHARED_SOURCES}) + source_group("private_source" FILES ${PRIVATE_SOURCES}) + source_group("public_source" FILES ${PUBLIC_SOURCES}) + + target_include_directories(ffx_opticalflow_${FFX_PLATFORM_NAME} PUBLIC ${FFX_INCLUDE_PATH}) + target_include_directories(ffx_opticalflow_${FFX_PLATFORM_NAME} PUBLIC ${FFX_SHARED_PATH}) + + set_source_files_properties(${SHADERS} PROPERTIES HEADER_FILE_ONLY TRUE) + set_target_properties(ffx_opticalflow_${FFX_PLATFORM_NAME} PROPERTIES FOLDER Components) + +endif() diff --git a/sdk/src/components/opticalflow/ffx_opticalflow.cpp b/sdk/src/components/opticalflow/ffx_opticalflow.cpp new file mode 100644 index 00000000..d03f1fb7 --- /dev/null +++ b/sdk/src/components/opticalflow/ffx_opticalflow.cpp @@ -0,0 +1,889 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 // for max used inside SPD CPU code. +#include // for fabs, abs, sinf, sqrt, etc. +#include // for memset +#include // for FLT_EPSILON +#include "FidelityFX/host/ffx_opticalflow.h" + +#define FFX_CPU +#include +#include +#include +#include + +#define FFX_OPTICALFLOW_MAX_QUEUED_FRAMES 16 + +#include "ffx_opticalflow_private.h" + +typedef struct Binding +{ + uint32_t index; + wchar_t name[64]; +}Binding; + +static const Binding srvBindingNames[] = +{ + {FFX_OF_BINDING_IDENTIFIER_INPUT_COLOR, L"r_input_color"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT, L"r_optical_flow_input"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_PREVIOUS_INPUT, L"r_optical_flow_previous_input"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW, L"r_optical_flow"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_PREVIOUS, L"r_optical_flow_previous"}, +}; + +static const Binding uavBindingNames[] = +{ + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT, L"rw_optical_flow_input"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_1, L"rw_optical_flow_input_level_1"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_2, L"rw_optical_flow_input_level_2"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_3, L"rw_optical_flow_input_level_3"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_4, L"rw_optical_flow_input_level_4"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_5, L"rw_optical_flow_input_level_5"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_6, L"rw_optical_flow_input_level_6"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW, L"rw_optical_flow"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_NEXT_LEVEL, L"rw_optical_flow_next_level"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_HISTOGRAM, L"rw_optical_flow_scd_histogram"}, // scene change detection histogram + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM, L"rw_optical_flow_scd_previous_histogram"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_TEMP, L"rw_optical_flow_scd_temp"}, + {FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_OUTPUT, L"rw_optical_flow_scd_output"}, +}; + +static const Binding cbBindingNames[] = +{ + {FFX_OPTICALFLOW_CONSTANTBUFFER_IDENTIFIER, L"cbOF"}, + {FFX_OPTICALFLOW_CONSTANTBUFFER_IDENTIFIER_SPD, L"cbOF_SPD"} +}; + +// Broad structure of the root signature. +typedef enum OpticalFlowRootSignatureLayout { + + OPTICALFLOW_ROOT_SIGNATURE_LAYOUT_UAVS, + OPTICALFLOW_ROOT_SIGNATURE_LAYOUT_SRVS, + OPTICALFLOW_ROOT_SIGNATURE_LAYOUT_CONSTANTS, + OPTICALFLOW_ROOT_SIGNATURE_LAYOUT_CONSTANTS_REGISTER_1, + OPTICALFLOW_ROOT_SIGNATURE_LAYOUT_PARAMETER_COUNT +} OpticalFlowRootSignatureLayout; + +typedef struct OpticalFlowSpdConstants +{ + uint32_t mips; + uint32_t numworkGroups; + uint32_t workGroupOffset[2]; + + uint32_t numworkGroupsOpticalFlowInputPyramid; + uint32_t pad0_; + uint32_t pad1_; + uint32_t pad2_; + +} OpticalFlowSpdConstants; + +FfxConstantBuffer globalOpticalflowConstantBuffers[] = +{ + {sizeof(OpticalflowConstants) / sizeof(uint32_t)}, + {sizeof(OpticalFlowSpdConstants) / sizeof(uint32_t)}, +}; + +static FfxErrorCode patchResourceBindings(FfxPipelineState* inoutPipeline) +{ + for (uint32_t srvIndex = 0; srvIndex < inoutPipeline->srvTextureCount; ++srvIndex) + { + int32_t mapIndex = 0; + for (mapIndex = 0; mapIndex < _countof(srvBindingNames); ++mapIndex) + { + if (0 == wcscmp(srvBindingNames[mapIndex].name, inoutPipeline->srvTextureBindings[srvIndex].name)) + break; + } + FFX_ASSERT(mapIndex < _countof(srvBindingNames)); + if (mapIndex == _countof(srvBindingNames)) + return FFX_ERROR_INVALID_ARGUMENT; + + inoutPipeline->srvTextureBindings[srvIndex].resourceIdentifier = srvBindingNames[mapIndex].index; + } + + for (uint32_t uavIndex = 0; uavIndex < inoutPipeline->uavTextureCount; ++uavIndex) + { + int32_t mapIndex = 0; + for (mapIndex = 0; mapIndex < _countof(uavBindingNames); ++mapIndex) + { + if (0 == wcscmp(uavBindingNames[mapIndex].name, inoutPipeline->uavTextureBindings[uavIndex].name)) + break; + } + FFX_ASSERT(mapIndex < _countof(uavBindingNames)); + if (mapIndex == _countof(uavBindingNames)) + return FFX_ERROR_INVALID_ARGUMENT; + + inoutPipeline->uavTextureBindings[uavIndex].resourceIdentifier = uavBindingNames[mapIndex].index; + } + + for (uint32_t cbIndex = 0; cbIndex < inoutPipeline->constCount; ++cbIndex) + { + int32_t mapIndex = 0; + for (mapIndex = 0; mapIndex < _countof(cbBindingNames); ++mapIndex) + { + if (0 == wcscmp(cbBindingNames[mapIndex].name, inoutPipeline->constantBufferBindings[cbIndex].name)) + break; + } + FFX_ASSERT(mapIndex < _countof(cbBindingNames)); + if (mapIndex == _countof(cbBindingNames)) + return FFX_ERROR_INVALID_ARGUMENT; + + inoutPipeline->constantBufferBindings[cbIndex].resourceIdentifier = cbBindingNames[mapIndex].index; + } + + return FFX_OK; +} + +static uint32_t getPipelinePermutationFlags(uint32_t contextFlags, FfxPass passId, bool fp16, bool force64, bool useLut) +{ + uint32_t flags = 0; + flags |= (force64) ? OPTICALFLOW_SHADER_PERMUTATION_FORCE_WAVE64 : 0; + flags |= (fp16) ? OPTICALFLOW_SHADER_PERMUTATION_ALLOW_FP16 : 0; + return flags; +} + +static FfxErrorCode createPipelineStates(FfxOpticalflowContext_Private* context) +{ + FFX_ASSERT(context); + + constexpr size_t samplerCount = 2; + FfxSamplerDescription samplerDescs[samplerCount] = { + {FFX_FILTER_TYPE_MINMAGMIP_POINT, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_BIND_COMPUTE_SHADER_STAGE}, + {FFX_FILTER_TYPE_MINMAGMIP_LINEAR, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_ADDRESS_MODE_CLAMP, FFX_BIND_COMPUTE_SHADER_STAGE} }; + + const size_t rootConstantCount = 2; + FfxRootConstantDescription rootConstantDescs[2] = { {globalOpticalflowConstantBuffers[0].num32BitEntries, FFX_BIND_COMPUTE_SHADER_STAGE}, + {globalOpticalflowConstantBuffers[1].num32BitEntries, FFX_BIND_COMPUTE_SHADER_STAGE} }; + FfxPipelineDescription pipelineDescription = {}; + pipelineDescription.stage = FFX_BIND_COMPUTE_SHADER_STAGE; + pipelineDescription.contextFlags = context->contextDescription.flags; + pipelineDescription.samplerCount = samplerCount; + pipelineDescription.samplers = samplerDescs; + pipelineDescription.rootConstantBufferCount = rootConstantCount; + pipelineDescription.rootConstants = rootConstantDescs; + + FfxDeviceCapabilities capabilities; + context->contextDescription.backendInterface.fpGetDeviceCapabilities(&context->contextDescription.backendInterface, &capabilities); + + bool haveShaderModel66 = capabilities.minimumSupportedShaderModel >= FFX_SHADER_MODEL_6_6; + bool supportedFP16 = capabilities.fp16Supported; + bool canForceWave64 = false; + bool useLut = false; + + const uint32_t waveLaneCountMin = capabilities.waveLaneCountMin; + const uint32_t waveLaneCountMax = capabilities.waveLaneCountMax; + if (waveLaneCountMin == 32 && waveLaneCountMax == 64) + { + useLut = true; + canForceWave64 = haveShaderModel66; + } + else + canForceWave64 = false; + + uint32_t contextFlags = context->contextDescription.flags; + + auto CreateComputePipeline = [&](FfxPass pass, const wchar_t* name, FfxPipelineState* pipeline) -> FfxErrorCode { + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, pipeline, context->effectContextId); + wcscpy_s(pipelineDescription.name, name); + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreatePipeline( + &context->contextDescription.backendInterface, + FFX_EFFECT_OPTICALFLOW, + pass, + getPipelinePermutationFlags(contextFlags, pass, supportedFP16, canForceWave64, useLut), + &pipelineDescription, + context->effectContextId, + pipeline)); + + patchResourceBindings(pipeline); + return FFX_OK; + }; + +#define EAN(pass) pass, L#pass + CreateComputePipeline(EAN(FFX_OPTICALFLOW_PASS_GENERATE_OPTICAL_FLOW_INPUT_PYRAMID), &context->pipelineGenerateOpticalFlowInputPyramid); + pipelineDescription.rootConstantBufferCount = 1; + CreateComputePipeline(EAN(FFX_OPTICALFLOW_PASS_PREPARE_LUMA), &context->pipelinePrepareLuma); + CreateComputePipeline(EAN(FFX_OPTICALFLOW_PASS_GENERATE_SCD_HISTOGRAM), &context->pipelineGenerateSCDHistogram); + CreateComputePipeline(EAN(FFX_OPTICALFLOW_PASS_COMPUTE_SCD_DIVERGENCE), &context->pipelineComputeSCDDivergence); + CreateComputePipeline(EAN(FFX_OPTICALFLOW_PASS_COMPUTE_OPTICAL_FLOW_ADVANCED_V5), &context->pipelineComputeOpticalFlowAdvancedV5); + CreateComputePipeline(EAN(FFX_OPTICALFLOW_PASS_FILTER_OPTICAL_FLOW_V5), &context->pipelineFilterOpticalFlowV5); + CreateComputePipeline(EAN(FFX_OPTICALFLOW_PASS_SCALE_OPTICAL_FLOW_ADVANCED_V5), &context->pipelineScaleOpticalFlowAdvancedV5); + + return FFX_OK; +} + +constexpr uint32_t OpticalFlowMaxPyramidLevels = 7; +constexpr uint32_t HistogramBins = 256; +constexpr uint32_t HistogramsPerDim = 3; +constexpr uint32_t HistogramShifts = 3; + +static FfxDimensions2D GetOpticalFlowTextureSize(const FfxDimensions2D& displaySize, const uint32_t opticalFlowBlockSize) +{ + uint32_t width = (displaySize.width + opticalFlowBlockSize - 1) / opticalFlowBlockSize; + uint32_t height = (displaySize.height + opticalFlowBlockSize - 1) / opticalFlowBlockSize; + return { width, height }; +} + +static FfxDimensions2D GetOpticalFlowHistogramSize(int level) +{ + const uint32_t searchRadius = 8; + uint32_t maxVelocity = searchRadius * (1 << (OpticalFlowMaxPyramidLevels - 1 - level)); + uint32_t binsPerDimension = 2 * maxVelocity + 1; + return { binsPerDimension, binsPerDimension }; +} + +static FfxDimensions2D GetGlobalMotionSearchDispatchSize(int level) +{ + const uint32_t threadGroupSizeX = 16; + const uint32_t threadGroupSizeY = 16; + const FfxDimensions2D opticalFlowHistogramSize = GetOpticalFlowHistogramSize(level); + const uint32_t additionalElementsDueToShiftsX = opticalFlowHistogramSize.width / threadGroupSizeX; + const uint32_t additionalElementsDueToShiftsY = opticalFlowHistogramSize.height / threadGroupSizeY; + const uint32_t dispatchX = (opticalFlowHistogramSize.width + additionalElementsDueToShiftsX + threadGroupSizeX - 1) / threadGroupSizeX; + const uint32_t dispatchY = (opticalFlowHistogramSize.height + additionalElementsDueToShiftsY + threadGroupSizeY - 1) / threadGroupSizeY; + return { dispatchX, dispatchY }; +} + +static uint32_t GetSCDHistogramTextureWidth() +{ + return HistogramBins * (HistogramsPerDim * HistogramsPerDim); +} + +static FfxErrorCode opticalflowCreate(FfxOpticalflowContext_Private* context, const FfxOpticalflowContextDescription* contextDescription) +{ + FFX_ASSERT(context); + FFX_ASSERT(contextDescription); + FfxErrorCode errorCode = FFX_OK; + + memset(context, 0, sizeof(FfxOpticalflowContext_Private)); + context->device = contextDescription->backendInterface.device; + + memcpy(&context->contextDescription, contextDescription, sizeof(FfxOpticalflowContextDescription)); + + errorCode = context->contextDescription.backendInterface.fpCreateBackendContext(&context->contextDescription.backendInterface, &context->effectContextId); + FFX_RETURN_ON_ERROR(errorCode == FFX_OK, errorCode); + + errorCode = context->contextDescription.backendInterface.fpGetDeviceCapabilities(&context->contextDescription.backendInterface, &context->deviceCapabilities); + FFX_RETURN_ON_ERROR(errorCode == FFX_OK, errorCode); + + context->firstExecution = true; + context->resourceFrameIndex = 0; + + context->constants.inputLumaResolution[0] = context->contextDescription.resolution.width; + context->constants.inputLumaResolution[1] = context->contextDescription.resolution.height; + + FfxDimensions2D opticalFlowInputTextureSize = context->contextDescription.resolution; + + uint32_t atomicInitData = 0U; + const FfxResourceType texture1dResourceType = (context->contextDescription.flags & FFX_OPTICALFLOW_ENABLE_TEXTURE1D_USAGE) ? FFX_RESOURCE_TYPE_TEXTURE1D : FFX_RESOURCE_TYPE_TEXTURE2D; + + uint32_t minBlockSize = 8; + const FfxDimensions2D opticalFlowTextureSize = GetOpticalFlowTextureSize(contextDescription->resolution, minBlockSize); + + const FfxDimensions2D opticalFlowLevel1TextureSize = { FFX_ALIGN_UP(opticalFlowTextureSize.width, 2) / 2, FFX_ALIGN_UP(opticalFlowTextureSize.height, 2) / 2 }; + const FfxDimensions2D opticalFlowLevel2TextureSize = { FFX_ALIGN_UP(opticalFlowLevel1TextureSize.width, 2) / 2, FFX_ALIGN_UP(opticalFlowLevel1TextureSize.height, 2) / 2 }; + const FfxDimensions2D opticalFlowLevel3TextureSize = { FFX_ALIGN_UP(opticalFlowLevel2TextureSize.width, 2) / 2, FFX_ALIGN_UP(opticalFlowLevel2TextureSize.height, 2) / 2 }; + const FfxDimensions2D opticalFlowLevel4TextureSize = { FFX_ALIGN_UP(opticalFlowLevel3TextureSize.width, 2) / 2, FFX_ALIGN_UP(opticalFlowLevel3TextureSize.height, 2) / 2 }; + const FfxDimensions2D opticalFlowLevel5TextureSize = { FFX_ALIGN_UP(opticalFlowLevel4TextureSize.width, 2) / 2, FFX_ALIGN_UP(opticalFlowLevel4TextureSize.height, 2) / 2 }; + const FfxDimensions2D opticalFlowLevel6TextureSize = { FFX_ALIGN_UP(opticalFlowLevel5TextureSize.width, 2) / 2, FFX_ALIGN_UP(opticalFlowLevel5TextureSize.height, 2) / 2 }; + const FfxDimensions2D opticalFlowLevel7TextureSize = { FFX_ALIGN_UP(opticalFlowLevel6TextureSize.width, 2) / 2, FFX_ALIGN_UP(opticalFlowLevel6TextureSize.height, 2) / 2 }; + + const FfxDimensions2D opticalFlowHistogramTextureSize = GetOpticalFlowHistogramSize(0); + + const FfxDimensions2D globalMotionSearchMaxDispatchSize = GetGlobalMotionSearchDispatchSize(0); + const uint32_t globalMotionSearchTextureWidth = 4 + (globalMotionSearchMaxDispatchSize.width * globalMotionSearchMaxDispatchSize.height); + + const FfxInternalResourceDescription internalSurfaceDesc[] = { + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1, L"OPTICALFLOW_OpticalFlowInput1", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width, opticalFlowInputTextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_1, L"OPTICALFLOW_OpticalFlowInput1Level1", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 1, opticalFlowInputTextureSize.height >> 1, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_2, L"OPTICALFLOW_OpticalFlowInput1Level2", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 2, opticalFlowInputTextureSize.height >> 2, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_3, L"OPTICALFLOW_OpticalFlowInput1Level3", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 3, opticalFlowInputTextureSize.height >> 3, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_4, L"OPTICALFLOW_OpticalFlowInput1Level4", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 4, opticalFlowInputTextureSize.height >> 4, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_5, L"OPTICALFLOW_OpticalFlowInput1Level5", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 5, opticalFlowInputTextureSize.height >> 5, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_6, L"OPTICALFLOW_OpticalFlowInput1Level6", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 6, opticalFlowInputTextureSize.height >> 6, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2, L"OPTICALFLOW_OpticalFlowInput2", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width, opticalFlowInputTextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_1, L"OPTICALFLOW_OpticalFlowInput2Level1", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 1, opticalFlowInputTextureSize.height >> 1, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_2, L"OPTICALFLOW_OpticalFlowInput2Level2", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 2, opticalFlowInputTextureSize.height >> 2, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_3, L"OPTICALFLOW_OpticalFlowInput2Level3", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 3, opticalFlowInputTextureSize.height >> 3, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_4, L"OPTICALFLOW_OpticalFlowInput2Level4", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 4, opticalFlowInputTextureSize.height >> 4, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_5, L"OPTICALFLOW_OpticalFlowInput2Level5", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 5, opticalFlowInputTextureSize.height >> 5, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_6, L"OPTICALFLOW_OpticalFlowInput2Level6", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R8_UINT, opticalFlowInputTextureSize.width >> 6, opticalFlowInputTextureSize.height >> 6, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1, L"OPTICALFLOW_OpticalFlow1", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowTextureSize.width, opticalFlowTextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_1, L"OPTICALFLOW_OpticalFlow1Level1", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel1TextureSize.width, opticalFlowLevel1TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_2, L"OPTICALFLOW_OpticalFlow1Level2", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel2TextureSize.width, opticalFlowLevel2TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_3, L"OPTICALFLOW_OpticalFlow1Level3", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel3TextureSize.width, opticalFlowLevel3TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_4, L"OPTICALFLOW_OpticalFlow1Level4", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel4TextureSize.width, opticalFlowLevel4TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_5, L"OPTICALFLOW_OpticalFlow1Level5", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel5TextureSize.width, opticalFlowLevel5TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1_LEVEL_6, L"OPTICALFLOW_OpticalFlow1Level6", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel6TextureSize.width, opticalFlowLevel6TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2, L"OPTICALFLOW_OpticalFlow2", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowTextureSize.width, opticalFlowTextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_1, L"OPTICALFLOW_OpticalFlow2Level1", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel1TextureSize.width, opticalFlowLevel1TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_2, L"OPTICALFLOW_OpticalFlow2Level2", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel2TextureSize.width, opticalFlowLevel2TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_3, L"OPTICALFLOW_OpticalFlow2Level3", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel3TextureSize.width, opticalFlowLevel3TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_4, L"OPTICALFLOW_OpticalFlow2Level4", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel4TextureSize.width, opticalFlowLevel4TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_5, L"OPTICALFLOW_OpticalFlow2Level5", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel5TextureSize.width, opticalFlowLevel5TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2_LEVEL_6, L"OPTICALFLOW_OpticalFlow2Level6", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowLevel6TextureSize.width, opticalFlowLevel6TextureSize.height, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_HISTOGRAM, L"OPTICALFLOW_OpticalFlowSCDHistogram", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R32_UINT, GetSCDHistogramTextureWidth(), 1, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM, L"OPTICALFLOW_OpticalFlowSCDPreviousHistogram", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R32_FLOAT, GetSCDHistogramTextureWidth(), 1, 1, FFX_RESOURCE_FLAGS_NONE }, + + { FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_TEMP, L"OPTICALFLOW_OpticalFlowSCDTemp", FFX_RESOURCE_TYPE_TEXTURE2D, FFX_RESOURCE_USAGE_UAV, + FFX_SURFACE_FORMAT_R32_UINT, 3, 1, 1, FFX_RESOURCE_FLAGS_NONE }, + }; + + memset(context->resources, 0, sizeof(context->resources)); + + for (int32_t currentSurfaceIndex = 0; currentSurfaceIndex < FFX_ARRAY_ELEMENTS(internalSurfaceDesc); ++currentSurfaceIndex) { + + const FfxInternalResourceDescription* currentSurfaceDescription = &internalSurfaceDesc[currentSurfaceIndex]; + const FfxResourceType resourceType = currentSurfaceDescription->height > 1 ? FFX_RESOURCE_TYPE_TEXTURE2D : texture1dResourceType; + const FfxResourceDescription resourceDescription = { + resourceType, currentSurfaceDescription->format, + currentSurfaceDescription->width, currentSurfaceDescription->height, 1, + currentSurfaceDescription->mipCount, FFX_RESOURCE_FLAGS_NONE, currentSurfaceDescription->usage }; + const FfxResourceStates initialState = FFX_RESOURCE_STATE_COMMON; + const FfxCreateResourceDescription createResourceDescription = { + FFX_HEAP_TYPE_DEFAULT, resourceDescription, initialState, currentSurfaceDescription->initDataSize, currentSurfaceDescription->initData, + currentSurfaceDescription->name, currentSurfaceDescription->id }; + + FFX_VALIDATE(context->contextDescription.backendInterface.fpCreateResource( + &context->contextDescription.backendInterface, + &createResourceDescription, + context->effectContextId, + &context->resources[currentSurfaceDescription->id])); + } + + memset(context->srvBindings, 0, sizeof(context->srvBindings)); + memset(context->uavBindings, 0, sizeof(context->uavBindings)); + + { + context->refreshPipelineStates = false; + errorCode = createPipelineStates(context); + FFX_RETURN_ON_ERROR(errorCode == FFX_OK, errorCode); + } + + return FFX_OK; +} + +static FfxErrorCode opticalflowRelease(FfxOpticalflowContext_Private* context) +{ + FFX_ASSERT(context); + + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelinePrepareLuma, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineGenerateOpticalFlowInputPyramid, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineGenerateSCDHistogram, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineComputeSCDDivergence, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineComputeOpticalFlowAdvancedV5, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineFilterOpticalFlowV5, context->effectContextId); + ffxSafeReleasePipeline(&context->contextDescription.backendInterface, &context->pipelineScaleOpticalFlowAdvancedV5, context->effectContextId); + + for (int32_t currentResourceIndex = 0; currentResourceIndex < FFX_OF_RESOURCE_IDENTIFIER_COUNT; ++currentResourceIndex) { + + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->resources[currentResourceIndex], context->effectContextId); + } + + context->contextDescription.backendInterface.fpDestroyBackendContext(&context->contextDescription.backendInterface, context->effectContextId); + + return FFX_OK; +} + +static void scheduleDispatch(FfxOpticalflowContext_Private* context, const FfxPipelineState* pipeline, const std::string& pipelineName, uint32_t dispatchX, uint32_t dispatchY, uint32_t dispatchZ = 1) +{ + FfxComputeJobDescription jobDescriptor = {}; + + for (uint32_t currentShaderResourceViewIndex = 0; currentShaderResourceViewIndex < pipeline->srvTextureCount; ++currentShaderResourceViewIndex) { + + const uint32_t bindingIdentifier = pipeline->srvTextureBindings[currentShaderResourceViewIndex].resourceIdentifier; + const FfxResourceInternal currentResource = context->srvBindings[bindingIdentifier]; + jobDescriptor.srvTextures[currentShaderResourceViewIndex] = currentResource; + wcscpy_s(jobDescriptor.srvTextureNames[currentShaderResourceViewIndex], pipeline->srvTextureBindings[currentShaderResourceViewIndex].name); + + FFX_ASSERT(bindingIdentifier != FFX_OF_BINDING_IDENTIFIER_NULL); + FFX_ASSERT(bindingIdentifier < FFX_OF_BINDING_IDENTIFIER_COUNT); + FFX_ASSERT(currentResource.internalIndex != 0); + } + + for (uint32_t currentUnorderedAccessViewIndex = 0; currentUnorderedAccessViewIndex < pipeline->uavTextureCount; ++currentUnorderedAccessViewIndex) { + + const uint32_t bindingIdentifier = pipeline->uavTextureBindings[currentUnorderedAccessViewIndex].resourceIdentifier; + const FfxResourceInternal currentResource = context->uavBindings[bindingIdentifier]; + jobDescriptor.uavTextures[currentUnorderedAccessViewIndex] = currentResource; + jobDescriptor.uavTextureMips[currentUnorderedAccessViewIndex] = 0; + wcscpy_s(jobDescriptor.uavTextureNames[currentUnorderedAccessViewIndex], pipeline->uavTextureBindings[currentUnorderedAccessViewIndex].name); + + FFX_ASSERT(bindingIdentifier != FFX_OF_BINDING_IDENTIFIER_NULL); + FFX_ASSERT(bindingIdentifier < FFX_OF_BINDING_IDENTIFIER_COUNT); + FFX_ASSERT(currentResource.internalIndex != 0); + } + + jobDescriptor.dimensions[0] = dispatchX; + jobDescriptor.dimensions[1] = dispatchY; + jobDescriptor.dimensions[2] = dispatchZ; + jobDescriptor.pipeline = *pipeline; + + for (uint32_t currentRootConstantIndex = 0; currentRootConstantIndex < pipeline->constCount; ++currentRootConstantIndex) { + wcscpy_s(jobDescriptor.cbNames[currentRootConstantIndex], pipeline->constantBufferBindings[currentRootConstantIndex].name); + jobDescriptor.cbs[currentRootConstantIndex] = globalOpticalflowConstantBuffers[pipeline->constantBufferBindings[currentRootConstantIndex].resourceIdentifier]; + } + + FfxGpuJobDescription dispatchJob = { FFX_GPU_JOB_COMPUTE }; + dispatchJob.computeJobDescriptor = jobDescriptor; + + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &dispatchJob); +} + +static FfxErrorCode dispatch(FfxOpticalflowContext_Private* context, const FfxOpticalflowDispatchDescription* params) +{ + context->contextDescription.backendInterface.fpRegisterResource( + &context->contextDescription.backendInterface, + ¶ms->opticalFlowVector, + context->effectContextId, + &context->uavBindings[FFX_OF_BINDING_IDENTIFIER_SHARED_OPTICAL_FLOW_VECTOR]); + context->contextDescription.backendInterface.fpRegisterResource( + &context->contextDescription.backendInterface, + ¶ms->opticalFlowSCD, + context->effectContextId, + &context->uavBindings[FFX_OF_BINDING_IDENTIFIER_SHARED_OPTICAL_FLOW_SCD_OUTPUT]); + + context->contextDescription.backendInterface.fpRegisterResource( + &context->contextDescription.backendInterface, + ¶ms->color, + context->effectContextId, + &context->srvBindings[FFX_OF_BINDING_IDENTIFIER_INPUT_COLOR]); + + FfxCommandList commandList = params->commandList; + int advancedAlgorithmIterations = 7; + uint32_t opticalFlowBlockSize = 8; + + if (context->refreshPipelineStates) { + + context->refreshPipelineStates = false; + + const FfxErrorCode errorCode = createPipelineStates(context); + FFX_RETURN_ON_ERROR(errorCode == FFX_OK, errorCode); + } + + const FfxResourceDescription resourceDescInputColor = context->contextDescription.backendInterface.fpGetResourceDescription( + &context->contextDescription.backendInterface, + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_INPUT_COLOR]); + FFX_ASSERT(resourceDescInputColor.type == FFX_RESOURCE_TYPE_TEXTURE2D); + + context->constants.backbufferTransferFunction = params->backbufferTransferFunction; + context->constants.minMaxLuminance[0] = params->minMaxLuminance.x; + context->constants.minMaxLuminance[1] = params->minMaxLuminance.y; + + const bool resetAccumulation = params->reset || context->firstExecution; + context->firstExecution = false; + + if (resetAccumulation) { + context->constants.frameIndex = 0; + } + else { + context->constants.frameIndex++; + } + + if (resetAccumulation) + { + const float clearValuesToZeroFloat[]{ 0.f, 0.f, 0.f, 0.f }; + FfxGpuJobDescription clearJob = { FFX_GPU_JOB_CLEAR_FLOAT }; + memcpy(clearJob.clearJobDescriptor.color, clearValuesToZeroFloat, 4 * sizeof(float)); + + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_TEMP]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->uavBindings[FFX_OF_BINDING_IDENTIFIER_SHARED_OPTICAL_FLOW_SCD_OUTPUT]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_HISTOGRAM]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_1]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_2]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_3]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_4]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_5]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1_LEVEL_6]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_1]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_2]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_3]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_4]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_5]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + clearJob.clearJobDescriptor.target = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2_LEVEL_6]; + context->contextDescription.backendInterface.fpScheduleGpuJob(&context->contextDescription.backendInterface, &clearJob); + } + + uint32_t resolutionMultiplier = 1; + + FfxUInt32x2 threadGroupSizeOpticalFlowInputPyramid; + FfxUInt32x2 workGroupOffset; + FfxUInt32x2 numWorkGroupsAndMips; + FfxUInt32x4 rectInfo = { 0, 0, + context->contextDescription.resolution.width * resolutionMultiplier, + context->contextDescription.resolution.height * resolutionMultiplier }; + ffxSpdSetup(threadGroupSizeOpticalFlowInputPyramid, workGroupOffset, numWorkGroupsAndMips, rectInfo, 4); + + OpticalFlowSpdConstants luminancePyramidConstants; + luminancePyramidConstants.numworkGroups = numWorkGroupsAndMips[0]; + luminancePyramidConstants.mips = numWorkGroupsAndMips[1]; + luminancePyramidConstants.workGroupOffset[0] = workGroupOffset[0]; + luminancePyramidConstants.workGroupOffset[1] = workGroupOffset[1]; + luminancePyramidConstants.numworkGroupsOpticalFlowInputPyramid = numWorkGroupsAndMips[0]; + + memcpy(&globalOpticalflowConstantBuffers[FFX_OPTICALFLOW_CONSTANTBUFFER_IDENTIFIER].data, &context->constants, globalOpticalflowConstantBuffers[FFX_OPTICALFLOW_CONSTANTBUFFER_IDENTIFIER].num32BitEntries * sizeof(uint32_t)); + memcpy(&globalOpticalflowConstantBuffers[FFX_OPTICALFLOW_CONSTANTBUFFER_IDENTIFIER_SPD].data, &luminancePyramidConstants, globalOpticalflowConstantBuffers[FFX_OPTICALFLOW_CONSTANTBUFFER_IDENTIFIER_SPD].num32BitEntries * sizeof(uint32_t)); + + { + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_HISTOGRAM] = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_HISTOGRAM]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM] = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_TEMP] = context->resources[FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCD_TEMP]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_OUTPUT] = context->uavBindings[FFX_OF_BINDING_IDENTIFIER_SHARED_OPTICAL_FLOW_SCD_OUTPUT]; + + const bool isOddFrame = !!(context->resourceFrameIndex & 1); + + uint32_t opticalFlowInputResourceIndex = isOddFrame ? FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2 : FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1; + uint32_t opticalFlowPreviousInputResourceIndex = isOddFrame ? FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1 : FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2; + + uint32_t opticalFlowResourceIndex = isOddFrame ? FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2 : FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1; + uint32_t opticalFlowPreviousResourceIndex = isOddFrame ? FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1 : FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2; + + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT] = context->resources[opticalFlowInputResourceIndex]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_1] = context->resources[opticalFlowInputResourceIndex + 1]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_2] = context->resources[opticalFlowInputResourceIndex + 2]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_3] = context->resources[opticalFlowInputResourceIndex + 3]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_4] = context->resources[opticalFlowInputResourceIndex + 4]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_5] = context->resources[opticalFlowInputResourceIndex + 5]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_6] = context->resources[opticalFlowInputResourceIndex + 6]; + + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT] = context->resources[opticalFlowInputResourceIndex]; + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_PREVIOUS_INPUT] = context->resources[opticalFlowPreviousInputResourceIndex]; + + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW] = context->resources[opticalFlowResourceIndex]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW] = context->resources[opticalFlowResourceIndex]; + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_PREVIOUS] = context->resources[opticalFlowPreviousResourceIndex]; + + { + int32_t threadGroupSizeX = 16; + int32_t threadGroupSizeY = 16; + uint32_t threadPixelsX = 2; + uint32_t threadPixelsY = 2; + int32_t dispatchX = ((context->contextDescription.resolution.width + (threadPixelsX - 1)) / threadPixelsX + (threadGroupSizeX - 1)) / threadGroupSizeX; + int32_t dispatchY = ((context->contextDescription.resolution.height + (threadPixelsY - 1)) / threadPixelsY + (threadGroupSizeY - 1)) / threadGroupSizeY; + std::string pipelineName = "OF PrepareLuma"; + scheduleDispatch(context, &context->pipelinePrepareLuma, pipelineName, dispatchX, dispatchY); + } + + { + { + std::string pipelineName = "OF GenerateOpticalFlowInputPyramid"; + scheduleDispatch(context, &context->pipelineGenerateOpticalFlowInputPyramid, pipelineName, + threadGroupSizeOpticalFlowInputPyramid[0], + threadGroupSizeOpticalFlowInputPyramid[1] + ); + } + + { + { + const uint32_t threadGroupSizeX = 32; + const uint32_t threadGroupSizeY = 8; + const uint32_t strataWidth = (context->contextDescription.resolution.width / 4) / HistogramsPerDim; + const uint32_t strataHeight = context->contextDescription.resolution.height / HistogramsPerDim; + const uint32_t dispatchX = (strataWidth + threadGroupSizeX - 1) / threadGroupSizeX; + const uint32_t dispatchY = 16; + const uint32_t dispatchZ = HistogramsPerDim * HistogramsPerDim; + std::string pipelineName = "OF GenerateSCDHistogram"; + scheduleDispatch(context, &context->pipelineGenerateSCDHistogram, pipelineName, dispatchX, dispatchY, dispatchZ); + } + { + const uint32_t dispatchX = HistogramsPerDim * HistogramsPerDim; + const uint32_t dispatchY = HistogramShifts; + std::string pipelineName = "OF ComputeSCDDivergence"; + scheduleDispatch(context, &context->pipelineComputeSCDDivergence, pipelineName, dispatchX, dispatchY); + } + } + + FfxDimensions2D opticalFlowTextureSizes[OpticalFlowMaxPyramidLevels]; + const int pyramidMaxIterations = advancedAlgorithmIterations; + FFX_ASSERT(pyramidMaxIterations <= OpticalFlowMaxPyramidLevels); + + opticalFlowTextureSizes[0] = GetOpticalFlowTextureSize(context->contextDescription.resolution, opticalFlowBlockSize); + for (int i = 1; i < pyramidMaxIterations; i++) + { + opticalFlowTextureSizes[i] = { + (opticalFlowTextureSizes[i - 1].width + 1) / 2, + (opticalFlowTextureSizes[i - 1].height + 1) / 2 + }; + } + + for (int level = pyramidMaxIterations - 1; level >= 0; level--) + { + bool isOddLevel = !!(level & 1); + + uint32_t opticalFlowInputResourceIndexA = isOddFrame ? FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2 : FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1; + uint32_t opticalFlowInputResourceIndexB = isOddFrame ? FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_1 : FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_INPUT_2; + uint32_t opticalFlowResourceIndexA = (isOddFrame != isOddLevel) ? FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2 : FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1; + uint32_t opticalFlowResourceIndexB = (isOddFrame != isOddLevel) ? FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_1 : FFX_OF_RESOURCE_IDENTIFIER_OPTICAL_FLOW_2; + context->constants.opticalFlowPyramidLevel = level; + context->constants.opticalFlowPyramidLevelCount = pyramidMaxIterations; + + memcpy(&globalOpticalflowConstantBuffers[FFX_OPTICALFLOW_CONSTANTBUFFER_IDENTIFIER].data, &context->constants, globalOpticalflowConstantBuffers[FFX_OPTICALFLOW_CONSTANTBUFFER_IDENTIFIER].num32BitEntries * sizeof(uint32_t)); + + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT] = context->resources[opticalFlowInputResourceIndexA + level]; + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_PREVIOUS_INPUT] = context->resources[opticalFlowInputResourceIndexB + level]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW] = context->resources[opticalFlowResourceIndexA + level]; + + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_PREVIOUS] = context->resources[opticalFlowResourceIndexB + level]; + + { + const FfxUInt32 inputLumaWidth = ffxMax(context->contextDescription.resolution.width >> level, 1); + const FfxUInt32 inputLumaHeight = ffxMax(context->contextDescription.resolution.height >> level, 1); + std::string pipelineName = "OF " + std::to_string(level) + " Search"; + + { + uint32_t threadPixels = 4; + FFX_ASSERT(opticalFlowBlockSize >= threadPixels); + uint32_t threadGroupSizeX = 4; + uint32_t threadGroupSizeY = 16; + uint32_t threadGroupSize = 64; + uint32_t dispatchX = ((inputLumaWidth + threadPixels - 1) / threadPixels * threadGroupSizeY + (threadGroupSize - 1)) / threadGroupSize; + uint32_t dispatchY = (inputLumaHeight + (threadGroupSizeY - 1)) / threadGroupSizeY; + scheduleDispatch(context, &context->pipelineComputeOpticalFlowAdvancedV5, pipelineName, dispatchX, dispatchY); + } + } + + { + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_PREVIOUS] = context->resources[opticalFlowResourceIndexA + level]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW] = context->resources[opticalFlowResourceIndexB + level]; + } + + { + if (level == 0) + { + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW] = context->uavBindings[FFX_OF_BINDING_IDENTIFIER_SHARED_OPTICAL_FLOW_VECTOR]; + } + + const uint32_t levelWidth = opticalFlowTextureSizes[level].width; + const uint32_t levelHeight = opticalFlowTextureSizes[level].height; + + const uint32_t threadGroupSizeX = 16; + const uint32_t threadGroupSizeY = 4; + const uint32_t dispatchX = (levelWidth + threadGroupSizeX - 1) / threadGroupSizeX; + const uint32_t dispatchY = (levelHeight + threadGroupSizeY - 1) / threadGroupSizeY; + std::string pipelineName = "OF " + std::to_string(level) + " Filter"; + + { + scheduleDispatch(context, &context->pipelineFilterOpticalFlowV5, pipelineName, dispatchX, dispatchY); + } + } + + if (level > 0) + { + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_ALIAS_LEVEL_1 + level - 1] = context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW]; + } + + if (level > 0) + { + { + context->srvBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW] = context->resources[opticalFlowResourceIndexB + level]; + context->uavBindings[FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_NEXT_LEVEL] = level > 0 ? context->resources[opticalFlowResourceIndexB + level - 1] : FfxResourceInternal{ FFX_OF_RESOURCE_IDENTIFIER_NULL }; + } + + FFX_ASSERT(opticalFlowBlockSize >= 2); + const uint32_t nextLevelWidth = opticalFlowTextureSizes[level - 1].width; + const uint32_t nextLevelHeight = opticalFlowTextureSizes[level - 1].height; + + const uint32_t threadGroupSizeX = opticalFlowBlockSize / 2; + const uint32_t threadGroupSizeY = opticalFlowBlockSize / 2; + const uint32_t threadGroupSizeZ = 4; + const uint32_t dispatchX = (nextLevelWidth + threadGroupSizeX - 1) / threadGroupSizeX; + const uint32_t dispatchY = (nextLevelHeight + threadGroupSizeY - 1) / threadGroupSizeY; + const uint32_t dispatchZ = 1; + std::string pipelineName = "OF " + std::to_string(level) + " Scale"; + + { + const uint32_t dispatchX = (nextLevelWidth + 3) / 4; + const uint32_t dispatchY = (nextLevelHeight + 3) / 4; + scheduleDispatch(context, &context->pipelineScaleOpticalFlowAdvancedV5, pipelineName, dispatchX, dispatchY, dispatchZ); + } + } + } + } + } + + context->resourceFrameIndex = (context->resourceFrameIndex + 1) % FFX_OPTICALFLOW_MAX_QUEUED_FRAMES; + + FFX_VALIDATE(context->contextDescription.backendInterface.fpExecuteGpuJobs(&context->contextDescription.backendInterface, commandList)); + + context->contextDescription.backendInterface.fpUnregisterResources(&context->contextDescription.backendInterface, commandList, context->effectContextId); + + return FFX_OK; +} + +FfxErrorCode ffxOpticalflowContextCreate(FfxOpticalflowContext* context, FfxOpticalflowContextDescription* contextDescription) +{ + FFX_RETURN_ON_ERROR(context, FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR(contextDescription, FFX_ERROR_INVALID_POINTER); + + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.fpGetDeviceCapabilities, FFX_ERROR_INCOMPLETE_INTERFACE); + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.fpCreateBackendContext, FFX_ERROR_INCOMPLETE_INTERFACE); + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.fpDestroyBackendContext, FFX_ERROR_INCOMPLETE_INTERFACE); + + if (contextDescription->backendInterface.scratchBuffer) { + + FFX_RETURN_ON_ERROR(contextDescription->backendInterface.scratchBufferSize, FFX_ERROR_INCOMPLETE_INTERFACE); + } + + FFX_STATIC_ASSERT(sizeof(FfxOpticalflowContext) >= sizeof(FfxOpticalflowContext_Private)); + + FfxOpticalflowContext_Private* contextPrivate = (FfxOpticalflowContext_Private*)(context); + FfxErrorCode errorCode = opticalflowCreate(contextPrivate, contextDescription); + + return errorCode; +} + +FfxErrorCode ffxOpticalflowContextDestroy(FfxOpticalflowContext* context) +{ + FFX_RETURN_ON_ERROR(context, FFX_ERROR_INVALID_POINTER); + + FfxOpticalflowContext_Private* contextPrivate = (FfxOpticalflowContext_Private*)(context); + const FfxErrorCode errorCode = opticalflowRelease(contextPrivate); + + return errorCode; +} + +FFX_API bool ffxOpticalflowResourceIsNull(FfxResource resource) +{ + return resource.resource == NULL; +} + +FFX_API FfxErrorCode ffxOpticalflowGetSharedResourceDescriptions(FfxOpticalflowContext* context, FfxOpticalflowSharedResourceDescriptions* SharedResources) +{ + FFX_RETURN_ON_ERROR(context, FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR(SharedResources, FFX_ERROR_INVALID_POINTER); + + FfxOpticalflowContext_Private* contextPrivate = (FfxOpticalflowContext_Private*)(context); + const FfxDimensions2D opticalFlowTextureSize = GetOpticalFlowTextureSize(contextPrivate->contextDescription.resolution, 8); + const FfxDimensions2D globalMotionSearchMaxDispatchSize = GetGlobalMotionSearchDispatchSize(0); + const uint32_t globalMotionSearchTextureWidth = 4 /* predefined slots */ + (globalMotionSearchMaxDispatchSize.width * globalMotionSearchMaxDispatchSize.height); + + SharedResources->opticalFlowVector = { + FFX_HEAP_TYPE_DEFAULT, + { FFX_RESOURCE_TYPE_TEXTURE2D, FFX_SURFACE_FORMAT_R16G16_SINT, opticalFlowTextureSize.width, opticalFlowTextureSize.height, 1, 1, FFX_RESOURCE_FLAGS_NONE, FFX_RESOURCE_USAGE_UAV }, + FFX_RESOURCE_STATE_UNORDERED_ACCESS, 0, nullptr, L"OPTICALFLOW_Result", 0 }; + + SharedResources->opticalFlowSCD = { + FFX_HEAP_TYPE_DEFAULT, + { FFX_RESOURCE_TYPE_TEXTURE2D, FFX_SURFACE_FORMAT_R32_UINT, 3, 1, 1, 1, FFX_RESOURCE_FLAGS_NONE, FFX_RESOURCE_USAGE_UAV }, + FFX_RESOURCE_STATE_UNORDERED_ACCESS, 0, nullptr, L"OPTICALFLOW_SCDOutput", 0 }; + + return FFX_OK; +} + +FfxErrorCode ffxOpticalflowContextDispatch(FfxOpticalflowContext* context, const FfxOpticalflowDispatchDescription* dispatchParams) +{ + FFX_RETURN_ON_ERROR(context, FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR(dispatchParams, FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR(dispatchParams->commandList, FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR(!ffxOpticalflowResourceIsNull(dispatchParams->color), FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR(dispatchParams->color.description.type == FFX_RESOURCE_TYPE_TEXTURE2D, FFX_ERROR_INVALID_ARGUMENT); + FFX_RETURN_ON_ERROR(!ffxOpticalflowResourceIsNull(dispatchParams->opticalFlowVector), FFX_ERROR_INVALID_POINTER); + FFX_RETURN_ON_ERROR(!ffxOpticalflowResourceIsNull(dispatchParams->opticalFlowSCD), FFX_ERROR_INVALID_POINTER); + + FfxOpticalflowContext_Private* contextPrivate = (FfxOpticalflowContext_Private*)(context); + + FFX_RETURN_ON_ERROR(contextPrivate->device, FFX_ERROR_NULL_DEVICE); + FFX_RETURN_ON_ERROR(dispatchParams->color.description.width <= contextPrivate->contextDescription.resolution.width, FFX_ERROR_INVALID_ARGUMENT); + FFX_RETURN_ON_ERROR(dispatchParams->color.description.height <= contextPrivate->contextDescription.resolution.height, FFX_ERROR_INVALID_ARGUMENT); + + const FfxErrorCode errorCode = dispatch(contextPrivate, dispatchParams); + return errorCode; +} + diff --git a/sdk/src/components/opticalflow/ffx_opticalflow_private.h b/sdk/src/components/opticalflow/ffx_opticalflow_private.h new file mode 100644 index 00000000..d607bf28 --- /dev/null +++ b/sdk/src/components/opticalflow/ffx_opticalflow_private.h @@ -0,0 +1,106 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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 + +#define FFX_CPU +#include + +typedef enum OpticalFlowBindingIdentifiers +{ + FFX_OF_BINDING_IDENTIFIER_NULL = 0, + FFX_OF_BINDING_IDENTIFIER_INPUT_COLOR, + + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_1, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_2, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_3, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_4, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_5, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_INPUT_LEVEL_6, + + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_PREVIOUS_INPUT, + + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_HISTOGRAM, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_PREVIOUS_HISTOGRAM, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_TEMP, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_SCD_OUTPUT, + + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_NEXT_LEVEL, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_PREVIOUS, + + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_ALIAS_LEVEL_1, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_ALIAS_LEVEL_2, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_ALIAS_LEVEL_3, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_ALIAS_LEVEL_4, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_ALIAS_LEVEL_5, + FFX_OF_BINDING_IDENTIFIER_OPTICAL_FLOW_ALIAS_LEVEL_6, + + FFX_OF_BINDING_IDENTIFIER_SHARED_OPTICAL_FLOW_VECTOR, + FFX_OF_BINDING_IDENTIFIER_SHARED_OPTICAL_FLOW_SCD_OUTPUT, + + FFX_OF_BINDING_IDENTIFIER_COUNT +} OpticalFlowBindingIdentifiers; + +typedef enum OpticalflowShaderPermutationOptions +{ + OPTICALFLOW_SHADER_PERMUTATION_FORCE_WAVE64 = (1 << 0), ///< doesn't map to a define, selects different table + OPTICALFLOW_SHADER_PERMUTATION_ALLOW_FP16 = (1 << 1), ///< Enables fast math computations where possible + OPTICALFLOW_HDR_COLOR_INPUT = (1 << 2), +} OpticalflowShaderPermutationOptions; + +typedef struct OpticalflowConstants +{ + int32_t inputLumaResolution[2]; + uint32_t opticalFlowPyramidLevel; + uint32_t opticalFlowPyramidLevelCount; + + int32_t frameIndex; + uint32_t backbufferTransferFunction; + float minMaxLuminance[2]; +} OpticalflowConstants; + +typedef struct FfxOpticalflowContext_Private +{ + FfxOpticalflowContextDescription contextDescription; + FfxUInt32 effectContextId; + OpticalflowConstants constants; + FfxDevice device; + FfxDeviceCapabilities deviceCapabilities; + + FfxPipelineState pipelinePrepareLuma; + FfxPipelineState pipelineGenerateOpticalFlowInputPyramid; + FfxPipelineState pipelineGenerateSCDHistogram; + FfxPipelineState pipelineComputeSCDDivergence; + FfxPipelineState pipelineComputeOpticalFlowAdvancedV5; + FfxPipelineState pipelineFilterOpticalFlowV5; + FfxPipelineState pipelineScaleOpticalFlowAdvancedV5; + + FfxResourceInternal resources[FFX_OF_RESOURCE_IDENTIFIER_COUNT]; + FfxResourceInternal srvBindings[FFX_OF_BINDING_IDENTIFIER_COUNT]; + FfxResourceInternal uavBindings[FFX_OF_BINDING_IDENTIFIER_COUNT]; + + bool firstExecution; + bool refreshPipelineStates; + uint32_t resourceFrameIndex; +} FfxOpticalflowContext_Private; diff --git a/sdk/src/components/parallelsort/CMakeLists.txt b/sdk/src/components/parallelsort/CMakeLists.txt index 8d3872f0..b3021b3c 100644 --- a/sdk/src/components/parallelsort/CMakeLists.txt +++ b/sdk/src/components/parallelsort/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_PARALLEL_SORT OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/parallelsort/ffx_parallelsort.cpp b/sdk/src/components/parallelsort/ffx_parallelsort.cpp index 56f180df..bc8e5cc5 100644 --- a/sdk/src/components/parallelsort/ffx_parallelsort.cpp +++ b/sdk/src/components/parallelsort/ffx_parallelsort.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 // for memset #include // for _countof @@ -465,7 +465,7 @@ static FfxErrorCode parallelSortRelease(FfxParallelSortContext_Private* context) // release internal resources for (int32_t currentResourceIndex = 0; currentResourceIndex < FFX_PARALLELSORT_RESOURCE_IDENTIFIER_COUNT; ++currentResourceIndex) { - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[currentResourceIndex]); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[currentResourceIndex], context->effectContextId); } // Destroy the context diff --git a/sdk/src/components/parallelsort/ffx_parallelsort_private.h b/sdk/src/components/parallelsort/ffx_parallelsort_private.h index 5cdf01ce..08931a9b 100644 --- a/sdk/src/components/parallelsort/ffx_parallelsort_private.h +++ b/sdk/src/components/parallelsort/ffx_parallelsort_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 #include diff --git a/sdk/src/components/spd/CMakeLists.txt b/sdk/src/components/spd/CMakeLists.txt index 291c85ed..c35029cb 100644 --- a/sdk/src/components/spd/CMakeLists.txt +++ b/sdk/src/components/spd/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_SPD OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/spd/ffx_spd.cpp b/sdk/src/components/spd/ffx_spd.cpp index fdf5b7f0..323bd449 100644 --- a/sdk/src/components/spd/ffx_spd.cpp +++ b/sdk/src/components/spd/ffx_spd.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 // for memset #include // for _countof #include // for fabs, abs, sinf, sqrt, etc. @@ -392,8 +392,8 @@ static FfxErrorCode spdRelease(FfxSpdContext_Private* context) context->srvResources[FFX_SPD_RESOURCE_IDENTIFIER_INPUT_DOWNSAMPLE_SRC_MIPMAP_12] = { FFX_SPD_RESOURCE_IDENTIFIER_NULL }; // Release internal resources and copy resource - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SPD_RESOURCE_IDENTIFIER_INTERNAL_GLOBAL_ATOMIC]); - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SPD_RESOURCE_IDENTIFIER_INTERNAL_GLOBAL_ATOMIC]); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SPD_RESOURCE_IDENTIFIER_INTERNAL_GLOBAL_ATOMIC], context->effectContextId); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SPD_RESOURCE_IDENTIFIER_INTERNAL_GLOBAL_ATOMIC], context->effectContextId); // Destroy the context context->contextDescription.backendInterface.fpDestroyBackendContext(&context->contextDescription.backendInterface, context->effectContextId); diff --git a/sdk/src/components/spd/ffx_spd_private.h b/sdk/src/components/spd/ffx_spd_private.h index da6fe364..9fad44d5 100644 --- a/sdk/src/components/spd/ffx_spd_private.h +++ b/sdk/src/components/spd/ffx_spd_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 diff --git a/sdk/src/components/sssr/CMakeLists.txt b/sdk/src/components/sssr/CMakeLists.txt index 39c90150..5bb42692 100644 --- a/sdk/src/components/sssr/CMakeLists.txt +++ b/sdk/src/components/sssr/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_SSSR OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) @@ -49,6 +47,9 @@ if (FFX_SSSR OR FFX_ALL) source_group("private_source" FILES ${PRIVATE_SOURCES}) source_group("public_source" FILES ${PUBLIC_SOURCES}) + # Dependencies + target_link_libraries(ffx_sssr_${FFX_PLATFORM_NAME} PRIVATE ffx_denoiser_${FFX_PLATFORM_NAME}) + target_include_directories(ffx_sssr_${FFX_PLATFORM_NAME} PUBLIC ${FFX_INCLUDE_PATH}) target_include_directories(ffx_sssr_${FFX_PLATFORM_NAME} PUBLIC ${FFX_SHARED_PATH}) diff --git a/sdk/src/components/sssr/ffx_sssr.cpp b/sdk/src/components/sssr/ffx_sssr.cpp index be4f9e60..2fd22514 100644 --- a/sdk/src/components/sssr/ffx_sssr.cpp +++ b/sdk/src/components/sssr/ffx_sssr.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 // for memset #include // for ceil, log2 #include // for max @@ -375,15 +375,15 @@ static FfxErrorCode sssrRelease(FfxSssrContext_Private* context) context->srvResources[FFX_SSSR_RESOURCE_IDENTIFIER_OUTPUT] = { FFX_SSSR_RESOURCE_IDENTIFIER_NULL }; // Release the copy resources for those that had init data - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SSSR_RESOURCE_IDENTIFIER_SOBOL_BUFFER]); - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SSSR_RESOURCE_IDENTIFIER_SCRAMBLING_TILE_BUFFER]); - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SSSR_RESOURCE_IDENTIFIER_SPD_GLOBAL_ATOMIC]); - ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SSSR_RESOURCE_IDENTIFIER_RAY_COUNTER]); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SSSR_RESOURCE_IDENTIFIER_SOBOL_BUFFER], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SSSR_RESOURCE_IDENTIFIER_SCRAMBLING_TILE_BUFFER], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SSSR_RESOURCE_IDENTIFIER_SPD_GLOBAL_ATOMIC], context->effectContextId); + ffxSafeReleaseCopyResource(&context->contextDescription.backendInterface, context->srvResources[FFX_SSSR_RESOURCE_IDENTIFIER_RAY_COUNTER], context->effectContextId); // release internal resources for (int32_t currentResourceIndex = 0; currentResourceIndex < FFX_SSSR_RESOURCE_IDENTIFIER_COUNT; ++currentResourceIndex) { - ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[currentResourceIndex]); + ffxSafeReleaseResource(&context->contextDescription.backendInterface, context->srvResources[currentResourceIndex], context->effectContextId); } FFX_ASSERT(ffxDenoiserContextDestroy(&context->denoiserContext) == FFX_OK); diff --git a/sdk/src/components/sssr/ffx_sssr_private.h b/sdk/src/components/sssr/ffx_sssr_private.h index 14580821..97a7d38d 100644 --- a/sdk/src/components/sssr/ffx_sssr_private.h +++ b/sdk/src/components/sssr/ffx_sssr_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 #include diff --git a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_128spp.cpp b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_128spp.cpp index b5e65ba8..b25aca0c 100644 --- a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_128spp.cpp +++ b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_128spp.cpp @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // An Owen-scrambled Sobol sequence of 256 samples of 256 dimensions static const int sobol_256spp_256d[256*256] = {32,226,72,70,57,171,246,75,112,81,109,239,120,101,230,103,103,41,249,86,253,99,132,184,214,147,128,248,17,149,163,17,60,40,169,196,77,79,102,23,250,77,75,151,95,123,234,198,25,26,184,114,230,188,105,18,231,233,175,151,19,174,202,71,84,229,247,148,182,127,92,14,41,112,162,253,35,101,137,30,111,134,95,122,28,2,41,254,181,91,101,188,145,31,166,38,53,193,1,122,99,86,178,36,198,169,113,255,97,221,227,231,29,100,30,141,250,254,16,157,2,220,187,95,181,125,207,187,105,119,156,41,16,194,93,216,227,124,138,90,227,1,88,153,233,69,120,36,19,189,120,4,185,220,185,109,184,96,247,173,210,227,54,3,18,9,139,213,156,57,61,101,37,247,21,201,10,143,11,38,146,18,118,129,95,191,75,207,12,252,238,104,47,39,190,229,31,56,20,127,42,178,100,141,93,222,192,247,186,7,224,161,72,100,87,69,218,44,25,195,185,118,179,123,231,170,96,225,204,52,117,60,3,86,25,143,230,18,11,165,72,188,158,3,66,105,50,200,226,145,227,45,183,62,82,176,191,36,248,191,189,122,96,185,146,166,203,78,144,189,67,174,154,182,86,169,90,236,101,40,71,107,81,93,159,82,75,230,157,191,34,35,235,139,150,193,10,142,217,77,154,249,74,13,196,248,56,154,27,6,242,226,105,94,66,67,145,112,31,145,133,68,21,0,44,212,254,153,183,238,98,102,145,199,100,213,196,52,131,141,216,209,236,122,58,249,188,108,8,206,62,199,207,103,160,247,207,255,101,185,1,113,223,126,182,0,50,93,250,174,194,18,65,111,206,104,156,3,48,195,122,212,10,101,235,200,13,183,173,7,192,3,101,228,84,168,121,241,205,122,115,132,155,242,215,22,236,242,69,35,48,245,3,175,68,57,4,15,226,155,222,140,54,48,80,200,194,149,213,68,225,14,182,122,147,195,69,166,191,17,176,58,222,58,190,70,66,153,196,215,121,123,176,190,161,145,203,121,255,27,207,28,113,22,44,232,46,84,181,131,245,220,27,202,161,38,94,208,39,143,52,5,154,85,121,139,226,223,159,246,170,56,94,209,188,71,205,76,16,233,168,172,200,37,19,123,120,202,28,175,232,88,120,107,157,198,111,253,18,24,36,35,43,169,199,197,137,194,12,238,138,232,17,17,58,115,39,234,4,164,225,215,14,185,232,76,215,171,142,206,206,132,90,31,130,24,0,165,34,91,126,113,64,202,144,114,132,125,58,184,234,211,246,238,168,7,1,172,169,218,67,29,185,66,73,49,222,167,243,189,36,116,23,223,219,200,84,67,94,53,79,26,202,204,91,180,221,166,106,18,207,17,128,137,246,235,162,13,129,130,49,76,104,189,138,55,174,71,152,49,116,204,207,103,198,147,225,142,79,8,172,59,234,225,192,168,181,144,185,6,233,243,61,123,46,55,44,16,228,79,156,235,190,115,61,162,115,182,122,230,138,204,140,86,173,80,99,207,211,181,23,141,152,17,180,35,121,168,67,205,107,74,55,229,234,210,6,94,48,186,210,189,2,200,190,181,227,128,211,225,215,228,74,7,188,195,36,82,10,131,96,99,138,63,1,210,39,134,153,112,72,163,196,55,126,37,125,107,234,166,129,80,61,97,121,20,123,222,3,155,219,62,49,207,87,182,26,214,167,142,89,38,36,112,87,100,56,245,240,152,23,7,237,11,185,206,233,203,131,42,53,35,60,40,211,114,9,13,189,130,196,210,173,39,208,56,110,34,240,65,75,234,76,73,34,39,2,118,174,237,52,194,197,28,155,161,135,180,200,3,89,210,26,154,145,45,57,54,85,26,118,207,212,58,101,69,202,184,36,234,219,155,41,29,80,22,193,175,145,100,50,29,149,166,168,162,213,130,36,25,234,78,84,97,191,139,95,156,9,12,41,97,110,222,8,16,250,161,130,45,111,195,83,213,16,141,154,48,124,175,89,25,27,9,172,242,51,167,76,109,69,107,23,80,23,166,12,16,180,156,182,238,148,249,59,130,75,122,59,134,240,69,220,21,230,47,1,124,66,180,77,247,147,103,66,98,211,96,105,213,127,178,144,102,213,33,247,141,232,67,62,86,230,222,146,68,122,27,147,7,85,69,31,22,67,67,78,13,149,221,57,121,176,133,161,84,201,146,119,196,217,19,132,52,76,135,247,107,29,131,248,220,156,248,29,41,36,202,174,136,253,191,226,91,179,96,69,213,172,0,206,75,192,54,69,120,138,218,171,185,232,211,139,8,31,11,50,119,28,197,83,158,170,229,244,195,190,23,213,87,70,17,102,197,39,59,88,152,234,95,106,29,195,236,114,136,6,159,105,101,2,119,184,47,212,218,188,165,163,138,174,114,71,54,127,64,183,39,51,42,209,202,106,96,215,154,56,33,102,25,62,111,9,49,4,98,142,198,128,138,13,74,95,229,42,164,19,175,179,111,138,19,157,125,94,34,221,103,246,144,141,176,129,201,55,100,23,12,139,33,227,91,223,224,69,120,83,245,50,57,190,21,54,86,245,95,250,34,71,249,100,201,144,16,221,0,40,74,133,38,145,48,217,119,132,34,138,67,161,62,221,126,108,207,140,42,156,13,224,198,142,19,55,85,254,155,140,168,250,58,118,137,42,78,8,48,89,195,167,91,243,246,88,23,22,206,17,190,56,125,171,116,245,129,121,57,144,228,159,197,243,217,239,86,188,152,88,239,112,120,245,119,147,189,25,128,240,72,208,29,162,23,152,24,143,226,136,174,171,58,178,10,5,250,209,239,88,62,34,251,156,163,231,247,102,112,46,48,61,233,24,71,54,73,12,81,195,243,115,138,145,194,164,135,148,51,201,104,74,24,78,107,65,246,118,159,165,130,206,34,157,177,180,10,126,163,167,129,75,0,149,115,172,21,242,139,162,170,92,238,35,46,24,108,101,62,26,147,180,210,227,166,103,149,188,192,92,115,141,161,120,90,231,250,181,130,208,232,151,157,141,208,27,81,82,42,162,244,186,62,163,6,254,94,107,138,123,144,14,216,138,235,104,135,98,77,82,57,47,77,171,213,192,134,69,226,93,197,9,63,181,197,169,22,248,190,55,178,250,167,76,157,101,170,138,94,156,44,12,155,102,133,133,149,43,224,51,130,44,138,3,195,25,161,29,216,1,188,160,73,4,196,125,240,92,88,50,192,176,234,39,109,96,39,60,165,226,80,248,179,232,244,141,102,81,131,110,19,206,225,222,115,198,63,195,251,19,155,77,51,194,251,124,13,77,69,106,112,114,187,126,67,222,81,227,163,80,172,25,70,205,111,48,160,111,165,112,243,47,236,107,81,15,83,95,132,80,133,178,116,87,10,195,139,151,122,44,82,111,24,234,156,187,202,250,20,233,186,204,184,154,149,117,78,205,119,71,166,192,239,88,148,154,229,200,139,163,129,12,155,167,252,50,198,46,106,221,91,235,75,2,14,240,122,62,178,218,42,223,213,6,17,212,242,32,190,96,163,121,63,228,65,111,229,63,70,140,232,221,248,216,80,5,145,12,27,33,195,86,111,42,125,70,44,232,82,209,40,234,168,224,215,215,133,247,128,76,248,178,34,253,61,204,193,105,44,227,66,45,238,159,16,241,67,99,178,235,181,68,204,234,144,58,40,132,125,203,25,204,148,151,253,195,198,81,8,54,248,148,248,58,54,235,82,71,67,181,212,241,43,111,111,202,69,166,200,66,87,245,207,70,112,64,26,240,149,82,86,28,104,17,59,72,154,106,1,173,59,21,204,184,231,15,224,161,253,174,78,249,25,217,35,144,180,57,102,174,57,138,227,125,141,246,16,35,201,173,170,31,107,205,169,59,19,52,209,226,49,136,168,13,238,63,53,78,203,68,18,146,228,165,245,244,84,215,78,230,167,83,239,15,210,34,99,90,184,143,187,50,98,95,182,121,47,53,112,15,53,239,130,105,66,142,11,185,224,203,20,44,156,28,197,195,65,118,36,206,88,55,37,18,112,9,20,231,73,6,11,225,79,180,145,124,204,29,245,148,198,53,210,171,103,53,215,106,111,154,237,107,2,249,79,145,126,255,255,53,222,196,57,237,131,6,63,45,70,68,190,191,12,210,247,162,41,135,184,234,206,153,176,115,255,114,178,110,24,25,66,114,55,29,79,253,67,124,245,37,236,13,88,232,186,18,143,178,59,5,237,10,249,253,37,88,46,134,71,53,74,172,186,69,137,11,154,60,68,120,125,100,91,182,239,177,38,28,125,208,165,38,150,207,244,41,88,127,241,251,168,84,195,111,37,211,165,113,3,212,184,180,207,48,52,204,171,213,128,154,138,218,69,214,154,99,201,203,109,93,71,190,5,99,1,72,173,15,149,49,253,51,82,171,179,114,131,68,114,133,15,104,227,141,109,39,68,225,130,50,51,133,154,148,48,28,230,9,43,157,50,133,203,239,37,160,233,120,54,20,116,57,174,116,158,45,8,196,14,200,80,203,212,233,1,0,88,172,214,196,22,192,224,142,138,146,230,105,100,153,155,112,241,124,26,71,253,143,4,191,50,49,88,226,25,142,141,13,12,50,159,122,211,42,168,23,217,253,218,151,135,3,152,114,102,191,76,186,42,124,70,19,56,25,85,234,58,57,225,230,253,56,194,107,134,142,201,213,43,14,33,242,16,141,205,196,99,143,100,115,5,99,128,100,221,174,110,191,83,165,164,78,60,124,209,199,63,185,120,175,43,3,24,40,153,1,83,147,223,112,72,242,148,166,115,36,138,42,13,63,1,45,173,225,83,121,19,23,208,171,146,240,108,150,3,213,83,210,238,72,120,80,197,2,4,159,197,138,216,19,178,24,173,212,237,169,129,129,102,51,63,203,142,11,134,180,207,105,98,133,253,20,224,6,126,194,167,33,132,90,101,179,113,216,222,132,30,88,23,229,210,85,6,154,226,252,17,39,174,208,255,8,11,252,159,110,195,86,250,59,161,218,31,140,167,41,33,201,143,250,68,82,205,44,4,77,43,214,212,60,82,214,41,44,125,236,152,34,64,133,184,58,145,227,65,70,73,166,49,21,158,242,114,42,75,209,36,72,188,192,146,223,138,76,27,235,115,153,105,169,96,209,231,4,33,105,226,175,187,91,218,12,73,168,214,254,98,208,113,214,116,177,49,34,94,22,127,175,12,155,193,56,187,115,187,240,136,234,206,189,250,115,219,154,17,52,62,198,63,225,81,77,90,127,246,219,192,106,223,78,102,88,142,46,208,156,230,196,67,182,18,112,210,126,198,59,15,234,166,243,77,61,149,24,223,70,245,142,178,199,101,195,190,109,78,244,224,12,84,52,158,184,88,212,155,159,128,187,54,48,209,190,202,157,70,122,109,33,221,124,227,1,196,124,121,163,138,238,25,129,134,83,111,124,60,142,46,143,48,85,63,5,77,46,251,193,209,81,108,149,108,1,47,137,175,85,106,148,27,204,145,104,3,152,84,228,215,113,141,6,117,115,151,206,248,61,43,182,198,76,88,12,222,132,75,73,8,205,190,32,12,159,70,205,4,158,0,107,220,104,90,223,181,80,7,111,166,130,16,168,145,218,242,101,35,165,172,12,217,239,157,76,37,238,176,63,124,243,45,101,181,191,200,64,186,170,42,104,154,191,224,67,145,240,72,82,103,93,108,220,251,36,178,110,145,98,136,83,2,171,177,220,23,98,221,2,160,216,219,237,90,105,255,48,157,136,55,102,122,181,7,225,55,229,254,215,169,94,22,44,65,136,50,190,151,198,54,132,81,245,106,71,91,141,176,162,15,210,33,14,140,108,81,17,135,249,17,44,15,121,28,16,114,178,210,7,129,250,11,239,18,86,203,161,124,2,185,178,83,110,168,3,81,125,80,149,8,67,30,212,0,129,8,77,255,114,243,68,8,119,210,232,104,244,127,165,159,26,176,206,160,228,34,116,10,3,91,65,149,163,43,43,44,171,113,113,223,206,17,63,64,215,216,94,118,5,139,66,201,213,30,120,149,18,236,99,41,81,175,245,1,7,171,209,151,134,28,32,122,201,13,18,46,236,215,113,188,192,221,39,69,117,121,255,119,26,59,142,121,126,238,179,163,183,245,98,199,32,46,39,137,236,232,52,138,4,60,86,83,12,100,44,195,49,107,228,105,56,183,18,177,222,50,189,188,97,197,148,94,99,1,198,221,121,206,54,31,212,145,62,73,77,213,189,38,66,13,139,69,173,57,26,11,176,245,141,166,141,203,10,48,45,201,17,131,241,115,13,165,235,28,129,88,72,36,124,169,128,6,145,10,109,219,198,187,90,149,67,215,68,116,33,56,204,217,236,231,0,205,84,97,113,175,30,185,95,187,166,164,123,103,0,218,18,150,180,103,151,153,146,97,15,161,171,246,252,131,198,186,58,55,210,93,58,157,3,142,220,98,50,202,151,2,115,205,200,3,236,146,210,233,71,222,129,198,18,131,29,157,152,63,201,45,197,253,170,121,124,232,64,197,112,22,208,106,99,54,41,247,146,135,234,142,177,3,38,157,234,222,46,189,233,76,41,150,255,135,82,99,244,246,187,81,215,16,76,188,188,104,156,21,239,255,206,97,35,217,194,13,70,106,106,238,171,232,93,223,145,190,50,39,144,48,13,113,146,151,178,156,18,131,231,168,108,178,224,7,44,122,98,87,166,65,220,174,138,98,95,93,188,127,246,195,136,215,160,201,137,35,217,167,126,219,175,109,180,111,127,222,93,69,133,2,58,198,186,238,108,57,157,101,174,249,26,46,210,254,251,76,43,197,209,161,52,197,28,246,173,229,35,43,13,81,122,34,245,212,223,50,135,69,70,192,171,78,9,135,189,54,168,232,131,250,208,59,227,252,247,231,40,235,203,254,51,25,198,223,165,81,140,141,67,194,180,31,194,172,47,195,56,153,118,221,30,217,17,85,154,184,122,15,130,179,86,8,37,33,200,95,144,73,175,68,185,197,128,182,154,171,147,182,86,172,23,236,20,92,194,110,253,124,133,82,127,206,92,34,108,69,170,47,61,41,87,108,218,3,244,7,124,51,153,83,186,164,116,154,85,123,43,135,177,107,28,189,81,241,214,189,235,233,142,6,109,183,130,75,79,107,99,67,31,164,248,227,114,159,230,115,116,115,252,33,75,4,171,191,217,88,245,156,203,48,239,140,253,211,46,184,136,34,21,248,161,128,156,16,88,64,71,34,174,125,70,164,125,92,205,214,79,157,199,223,143,214,138,213,150,169,17,16,181,95,200,208,91,91,55,125,7,1,39,91,6,103,252,246,22,71,110,149,236,73,1,247,51,2,168,88,124,234,86,100,6,94,1,17,215,157,34,238,126,194,222,109,67,175,96,45,252,99,58,3,34,192,251,95,240,36,188,243,191,229,74,164,55,171,108,239,73,208,140,114,46,244,36,30,33,56,14,209,94,86,28,9,153,30,23,102,165,252,98,77,72,233,22,126,152,98,40,246,35,93,137,114,191,114,200,54,214,8,238,145,43,119,180,186,55,74,170,232,166,247,56,233,9,162,16,241,95,47,5,109,72,125,67,35,130,55,138,75,157,246,85,244,3,230,60,226,159,12,234,155,160,180,119,243,253,179,202,194,53,218,65,208,230,212,71,228,29,49,220,31,146,244,249,84,46,237,203,93,171,73,33,115,46,109,10,163,137,73,18,133,213,236,174,230,216,119,127,80,199,18,100,180,236,191,127,152,158,226,45,72,70,181,106,90,21,229,46,41,109,55,237,81,0,158,169,63,40,22,85,246,181,235,161,180,28,175,136,87,132,184,54,121,185,69,89,58,20,54,81,101,87,37,251,152,4,162,108,113,248,178,219,151,240,144,158,242,185,138,4,34,148,255,250,66,75,144,141,25,248,244,89,180,203,97,141,149,179,129,213,186,64,101,242,119,130,121,108,230,198,74,228,155,96,237,140,201,158,44,127,161,120,219,94,11,95,27,145,80,184,107,215,88,252,32,89,59,97,159,249,183,75,131,180,65,184,179,85,80,88,74,128,53,126,191,54,169,0,133,100,248,196,158,91,121,110,12,248,130,87,248,186,85,136,101,181,0,90,45,34,227,84,17,40,96,221,187,167,131,112,48,70,62,240,138,78,245,248,226,203,255,32,242,246,141,200,17,167,32,151,12,72,159,221,190,56,115,237,233,226,113,71,228,167,60,113,127,28,174,27,176,227,160,77,221,157,64,14,166,82,60,78,7,91,16,214,169,78,222,97,33,229,210,4,255,104,234,42,181,7,177,190,23,40,135,53,67,63,28,151,60,167,81,21,190,110,214,160,222,51,228,87,83,113,220,46,182,163,193,79,214,249,120,197,244,197,169,252,20,33,253,246,46,198,16,208,35,110,5,37,236,172,149,234,155,32,36,8,249,70,224,226,40,16,146,131,224,173,250,111,102,227,160,196,255,167,81,196,62,24,6,39,4,245,139,98,158,201,247,5,6,2,61,92,5,65,70,24,206,135,30,246,146,155,22,29,247,25,112,186,5,208,134,240,95,137,29,48,148,222,92,36,165,248,10,244,222,158,131,46,156,217,243,219,101,123,98,209,124,89,178,16,48,173,142,241,134,127,160,217,64,134,35,244,28,253,59,26,10,212,162,143,252,94,0,198,0,16,156,116,145,64,255,206,234,251,104,250,213,247,171,89,86,125,48,237,216,196,160,45,90,227,12,33,58,31,88,200,117,101,36,105,135,49,134,64,181,233,40,63,100,189,192,13,48,58,159,183,105,34,162,170,166,132,83,141,116,29,39,216,84,29,224,211,54,145,251,248,148,150,203,26,51,179,47,134,175,80,66,223,24,221,52,170,59,241,37,95,232,183,15,162,203,144,221,60,248,8,211,255,78,249,55,59,23,131,11,165,152,182,82,168,71,89,48,249,78,107,182,117,73,21,79,42,128,232,89,103,207,13,224,32,236,175,138,201,54,26,98,122,91,253,144,222,108,171,101,120,208,168,40,29,46,64,23,171,248,115,40,80,28,107,143,65,188,142,205,155,234,86,121,157,124,23,44,177,188,201,222,229,244,169,241,155,62,102,187,15,28,49,168,157,29,135,202,9,160,102,125,112,184,31,209,162,114,13,130,215,93,15,255,110,50,54,19,144,98,47,46,170,252,210,5,161,176,69,185,97,187,253,94,124,215,85,69,73,136,150,68,137,217,52,113,151,241,70,44,102,126,10,143,167,133,81,239,233,109,73,171,141,93,133,112,185,133,103,206,49,208,130,79,127,234,48,173,231,82,200,74,68,194,188,185,26,56,199,134,122,3,153,227,174,245,23,34,49,20,68,184,202,1,232,252,31,171,45,85,7,114,187,66,203,169,98,117,144,15,165,104,143,111,174,100,197,60,7,53,248,238,100,12,162,96,40,189,247,101,64,57,57,14,195,114,229,155,228,32,111,37,141,8,8,163,2,223,6,96,54,144,175,85,141,51,77,41,60,192,113,15,103,101,44,30,102,189,100,251,227,71,37,62,123,4,63,119,25,116,47,205,191,156,1,106,136,248,37,151,162,72,226,41,208,133,69,146,114,137,43,245,90,115,117,90,122,134,180,218,136,10,36,210,53,138,90,139,213,130,56,173,119,174,71,72,213,138,87,171,101,156,110,0,164,38,191,156,215,148,220,106,138,50,237,54,37,49,215,127,45,81,226,61,181,195,147,154,208,170,94,34,8,228,121,71,182,239,63,56,65,244,0,70,162,73,198,63,16,134,216,58,187,203,234,115,44,209,105,127,183,130,74,82,203,219,128,128,162,13,47,106,252,31,56,155,184,119,56,139,70,241,3,104,153,43,183,28,68,241,224,25,154,52,51,131,108,142,150,13,106,43,251,166,76,47,218,150,11,125,109,109,179,145,213,217,241,16,32,208,48,33,217,59,171,245,248,174,34,191,77,111,183,221,49,141,59,221,76,224,103,190,107,171,215,232,44,84,133,236,88,227,175,24,57,144,252,229,182,140,36,219,42,92,101,187,212,188,34,205,167,99,168,91,224,154,187,112,52,190,62,212,191,250,250,68,229,248,142,143,161,185,243,117,222,69,61,162,247,179,140,133,135,164,217,144,222,8,114,20,240,161,44,27,187,82,122,237,53,167,43,2,215,122,219,61,163,54,181,154,176,222,239,12,13,63,88,213,167,98,162,94,254,89,113,112,242,88,158,65,229,215,16,126,234,96,129,34,233,231,85,152,90,16,97,32,90,134,18,131,114,130,148,249,76,135,186,171,103,192,83,45,100,96,36,88,217,197,165,86,194,168,112,149,125,108,133,112,117,199,26,221,35,245,88,233,9,113,47,138,31,61,114,47,51,32,197,55,17,175,164,93,204,223,215,203,221,224,147,103,78,214,230,214,71,214,220,169,117,39,0,147,198,108,242,153,155,144,235,250,162,35,53,61,45,156,227,244,108,123,32,227,129,77,252,146,213,168,197,237,147,123,38,228,75,144,165,144,102,113,198,22,145,14,101,195,177,43,62,151,113,96,81,189,204,180,207,197,24,72,76,135,127,181,246,81,18,167,113,85,184,62,190,140,86,209,148,134,111,32,60,108,33,233,115,99,216,239,112,146,92,217,236,252,213,215,98,122,215,64,175,155,179,121,195,7,207,252,163,51,58,143,187,255,188,122,6,199,73,36,149,218,141,142,43,108,99,2,232,187,65,216,24,169,125,102,148,113,59,233,176,194,207,77,204,245,20,43,145,104,88,88,212,187,237,152,64,18,141,254,53,255,111,53,61,62,49,143,145,197,10,207,36,198,166,88,7,199,42,201,145,219,135,53,239,108,162,82,202,181,4,255,82,23,38,141,213,120,0,218,105,2,141,120,255,138,20,27,255,97,202,151,0,166,227,16,196,48,139,91,164,4,170,177,243,27,154,220,212,167,205,179,84,245,205,50,51,155,45,39,99,124,70,27,48,182,173,3,26,38,214,1,26,23,216,248,214,89,78,142,7,44,2,118,103,73,72,202,187,222,242,74,37,84,166,251,191,67,11,231,116,61,33,17,96,93,116,165,173,88,153,105,123,125,159,243,89,143,66,211,213,23,47,204,192,2,231,229,224,32,30,45,9,31,149,216,137,119,152,34,22,131,206,47,216,201,89,197,58,66,204,67,92,0,150,199,161,213,185,96,252,164,78,46,247,41,134,48,118,14,77,30,250,176,12,138,96,58,51,142,9,249,103,99,29,247,189,31,126,29,86,211,201,108,216,195,90,32,119,124,219,207,128,192,119,91,217,60,215,24,182,244,100,241,153,24,3,99,115,167,33,25,239,186,42,198,202,179,57,117,112,11,208,212,50,26,170,22,148,206,252,232,159,56,64,37,184,40,232,109,62,164,199,64,198,112,56,71,12,215,108,220,20,211,118,70,182,19,212,219,182,104,5,188,255,61,162,241,25,176,78,25,176,239,21,205,246,214,246,86,45,101,158,9,252,149,38,59,72,225,119,121,209,20,85,6,84,253,24,182,126,20,150,105,176,238,54,59,96,46,28,214,21,80,112,19,118,125,115,134,244,30,35,230,238,255,199,220,32,200,9,142,2,182,14,101,191,176,143,96,217,200,124,194,43,105,61,93,143,135,53,12,228,233,30,150,173,228,73,179,184,84,21,117,63,245,231,49,129,29,249,46,23,172,195,94,36,76,227,246,71,159,188,8,88,119,49,177,156,203,88,101,195,170,151,183,106,100,9,246,64,254,1,90,4,9,163,154,231,88,68,182,99,67,75,171,107,142,196,79,237,114,70,178,128,33,83,168,67,129,82,214,135,38,206,41,152,140,168,52,239,28,171,28,29,180,246,185,183,243,85,129,112,168,63,139,133,0,162,86,166,48,132,244,159,151,235,175,64,110,168,85,97,233,11,62,25,177,16,57,124,63,250,59,218,136,209,136,192,23,168,160,206,65,84,30,73,213,235,181,104,66,27,98,126,183,219,93,200,115,84,141,57,55,20,131,91,14,228,85,181,19,4,110,176,90,101,40,91,107,155,7,70,21,114,154,141,146,125,246,64,1,216,213,232,23,143,224,115,244,247,144,186,71,134,69,183,141,25,186,91,29,145,163,250,202,181,57,216,172,131,228,242,181,187,52,94,218,252,4,118,44,52,124,160,37,176,17,218,121,140,191,107,102,91,222,49,91,229,106,179,221,170,200,88,38,138,167,10,48,157,47,99,57,137,88,76,206,141,214,208,48,80,226,18,227,6,175,180,63,107,247,251,197,59,51,247,13,109,209,162,206,192,125,112,94,235,247,26,88,14,126,241,225,249,81,162,7,157,238,150,138,24,69,121,155,219,17,169,180,218,93,230,99,92,139,53,179,145,30,14,205,171,75,247,49,194,3,14,177,24,222,122,30,75,174,121,243,104,233,244,81,4,47,70,43,206,113,229,119,231,49,72,144,78,214,29,193,41,75,14,97,19,84,148,246,3,250,243,7,246,233,153,48,135,226,204,199,93,210,3,97,11,106,117,170,122,92,97,150,179,177,220,46,59,17,151,242,160,233,237,81,78,255,87,243,237,113,135,216,131,97,197,224,41,142,85,234,243,135,58,152,220,191,227,149,78,77,30,82,167,63,217,43,227,106,173,223,128,161,49,70,29,184,169,178,179,124,224,2,243,210,229,112,103,15,29,78,229,91,9,68,198,94,135,241,207,69,183,229,46,78,63,189,93,163,10,91,172,13,205,180,217,216,102,237,239,3,217,247,218,0,147,130,158,175,242,39,94,23,238,221,229,211,72,140,103,207,7,73,10,200,247,155,254,35,165,152,2,137,237,154,128,235,215,210,1,132,104,143,128,91,191,225,241,171,220,16,165,209,59,10,1,128,151,229,116,17,20,188,108,57,196,105,197,5,64,216,75,255,49,10,35,243,39,238,142,201,1,32,8,28,116,21,216,226,89,90,231,210,128,81,149,93,249,111,150,128,11,228,231,236,178,74,34,174,187,230,84,78,197,136,17,197,25,242,154,123,24,78,245,178,254,76,70,182,72,15,115,54,62,10,89,172,129,113,97,148,204,240,100,172,169,122,13,95,182,26,184,25,191,255,250,250,137,18,19,72,145,135,112,125,227,63,65,26,54,228,181,30,158,27,191,9,236,168,115,248,144,187,132,253,45,84,154,196,103,30,149,123,53,42,206,172,146,175,44,203,69,239,45,147,0,121,103,125,132,136,192,38,62,79,29,241,17,151,110,28,38,221,234,230,228,182,64,241,144,165,124,145,120,49,50,129,18,33,242,212,143,68,167,109,134,179,113,176,85,93,87,105,133,15,66,249,8,43,9,147,72,30,6,2,85,185,204,160,20,76,70,119,163,67,200,121,228,185,204,22,48,31,122,177,123,93,159,108,114,65,90,91,67,95,139,6,187,3,78,142,38,96,61,68,23,146,93,32,245,153,131,61,126,1,194,201,158,51,161,172,0,176,76,143,229,81,201,36,157,210,139,109,215,12,9,41,152,243,188,240,144,194,27,114,193,162,39,43,9,203,46,137,76,217,93,125,215,74,43,75,0,153,246,95,88,44,134,248,43,87,166,46,133,1,77,197,205,206,31,50,102,178,248,22,226,192,156,203,195,155,193,32,35,158,173,76,75,79,240,112,7,161,130,162,85,225,67,223,15,127,53,24,49,231,201,248,16,114,146,228,17,178,247,166,162,2,32,180,41,188,9,197,103,77,246,35,30,71,112,6,222,168,64,60,248,242,61,201,130,219,58,182,38,143,103,45,104,219,7,121,119,138,183,148,149,107,216,169,2,89,111,185,120,49,74,173,174,35,38,194,214,86,32,216,229,123,41,64,108,178,152,13,174,71,86,192,147,84,112,246,98,151,238,63,210,134,112,5,28,254,154,125,236,82,78,22,114,230,212,88,97,54,211,70,203,48,159,59,21,36,55,56,141,194,247,133,160,138,224,66,180,74,137,37,94,5,120,135,170,119,209,147,221,28,19,215,139,29,199,87,234,102,225,111,74,180,27,169,131,129,29,44,138,81,235,206,181,229,133,192,201,163,110,48,203,245,95,200,183,29,29,31,255,74,216,148,92,109,191,130,29,236,248,204,126,228,208,76,200,13,128,197,198,255,211,23,197,132,124,133,71,155,21,132,233,191,189,212,255,108,47,94,109,53,232,234,95,174,83,223,18,188,255,239,215,139,141,51,127,243,199,103,111,117,45,101,67,184,104,196,20,34,25,184,251,144,47,226,217,214,217,125,47,52,41,242,113,104,13,56,74,44,166,36,63,154,133,145,18,80,160,124,59,47,48,219,63,43,134,67,115,238,189,252,67,6,164,83,181,123,230,213,252,7,222,130,221,30,79,68,34,162,2,61,134,162,207,49,146,161,216,82,98,181,190,57,57,164,128,97,121,148,131,128,152,66,106,247,15,154,148,82,42,174,142,17,249,123,23,138,78,106,245,159,202,19,26,160,50,138,153,136,182,101,89,247,195,169,69,220,50,155,45,140,251,248,183,139,84,17,44,98,83,13,102,234,106,135,22,255,212,246,163,28,11,251,123,18,5,150,221,6,2,137,17,176,56,215,12,166,187,52,149,11,97,119,140,245,13,201,20,98,80,27,26,125,126,58,232,231,83,52,195,75,116,248,147,230,123,171,77,81,168,163,120,39,158,18,54,60,212,117,67,148,122,151,78,51,30,88,27,152,83,92,191,105,162,106,233,12,27,116,4,53,100,189,242,253,169,182,10,105,196,84,229,122,141,80,15,0,38,26,50,176,229,18,32,169,241,202,190,190,225,100,193,44,196,209,193,83,89,43,228,8,127,48,9,221,186,199,251,97,138,218,190,131,202,206,62,148,128,44,48,107,164,177,57,149,171,214,244,57,198,194,87,179,232,10,17,65,243,255,109,19,208,42,55,68,178,164,84,21,57,206,5,27,252,203,144,108,90,231,137,198,221,204,164,204,56,73,223,129,127,246,244,144,140,13,229,195,199,39,42,93,103,202,8,45,68,203,17,186,154,9,154,228,59,255,134,120,125,170,90,18,141,31,17,116,10,189,48,63,147,112,188,11,184,92,95,253,180,92,80,106,57,112,187,229,228,69,3,1,47,47,72,146,48,135,37,111,82,27,20,77,157,222,115,123,120,119,159,196,99,7,116,57,222,119,79,79,212,213,215,145,225,154,187,25,22,126,89,170,169,123,159,94,29,177,63,137,207,167,192,97,134,193,17,236,199,8,35,214,220,156,72,183,180,8,63,200,171,93,216,103,110,145,159,209,158,236,233,50,228,220,144,113,159,214,222,157,156,27,133,183,240,127,191,28,41,222,148,155,247,32,97,96,128,237,98,236,159,107,157,192,176,19,81,248,145,219,183,179,73,178,81,38,137,81,108,189,148,180,164,63,244,107,140,13,253,2,84,88,16,121,200,120,77,203,104,24,207,202,194,62,253,155,102,96,168,116,28,237,163,138,91,149,34,82,230,211,109,230,176,130,28,82,186,233,159,99,238,249,81,38,106,243,246,4,63,80,43,104,47,1,253,236,84,79,158,5,81,26,18,242,70,42,11,229,216,154,236,16,203,159,227,7,207,120,26,197,81,87,177,4,32,197,147,111,255,229,91,211,194,195,230,35,169,151,31,196,33,181,120,192,254,71,84,152,228,208,209,129,98,55,39,210,144,146,192,231,249,121,170,81,218,202,197,150,149,234,93,90,178,167,209,244,86,25,140,141,156,206,14,247,240,217,14,39,99,82,121,16,119,157,210,169,220,50,58,255,48,130,189,120,154,59,60,85,94,135,23,15,171,6,31,212,224,89,73,100,179,91,61,170,128,28,33,227,9,149,128,12,110,120,44,9,52,192,4,24,65,221,114,24,77,109,0,237,94,4,42,232,84,150,134,32,50,33,84,234,130,136,89,117,253,79,60,135,69,29,50,128,196,38,41,43,37,78,168,73,163,249,45,207,177,76,38,115,76,143,118,145,106,166,6,142,230,193,147,145,87,195,222,73,219,219,89,33,68,237,118,120,146,164,74,130,237,16,47,79,228,9,153,184,5,127,80,182,81,105,196,51,244,192,237,160,118,200,191,94,235,152,191,202,161,231,171,19,116,102,94,206,253,175,4,193,18,70,53,214,98,123,181,137,167,190,84,96,169,2,204,232,54,221,169,175,186,172,137,170,75,32,249,57,119,86,19,52,123,234,142,11,108,19,58,84,98,250,242,114,170,31,205,195,117,12,243,41,93,222,0,101,219,102,129,196,192,91,8,186,233,243,37,194,183,162,121,59,93,71,52,178,114,96,72,252,185,254,109,31,107,112,168,64,226,160,216,43,49,74,50,139,112,148,135,148,88,184,35,26,29,171,245,47,96,61,39,146,159,194,252,57,202,244,245,218,216,18,29,71,237,39,25,197,164,184,67,97,53,45,16,218,207,244,97,249,96,167,93,62,103,162,164,67,186,159,2,26,136,32,184,9,167,169,183,210,72,43,253,167,72,211,171,205,117,92,82,32,5,197,107,8,68,106,237,8,142,148,101,227,90,210,67,13,252,233,3,242,79,95,172,175,195,246,251,254,247,71,7,224,252,37,255,4,158,178,131,23,77,77,22,178,114,155,151,162,207,53,98,63,132,143,232,73,194,185,91,243,57,47,83,36,154,42,31,150,56,15,33,40,14,111,70,137,225,158,138,108,119,114,255,48,176,231,182,51,219,163,86,122,80,104,197,169,107,181,97,55,228,63,47,73,106,27,23,65,207,177,34,218,221,147,192,237,165,74,89,152,255,181,169,250,226,99,10,232,6,181,45,3,222,174,26,248,155,12,199,237,65,205,85,22,125,164,146,124,17,73,140,71,36,57,173,173,157,157,161,35,164,157,190,71,67,29,142,133,206,231,64,185,95,111,65,166,220,233,245,73,242,25,16,29,223,124,142,199,177,13,24,198,245,218,190,115,38,32,45,236,12,96,101,63,17,230,151,217,117,234,153,112,111,91,162,196,247,185,166,60,2,8,145,56,160,48,175,226,250,67,51,132,106,42,213,138,119,167,9,240,25,8,56,22,165,218,9,62,218,121,29,43,177,130,210,166,150,15,220,225,225,152,34,255,104,115,223,108,131,55,250,255,49,92,130,20,179,218,73,38,116,122,102,17,118,237,183,109,65,232,122,235,4,68,3,245,160,150,224,73,183,115,6,100,124,166,210,201,82,249,142,15,23,20,60,118,137,170,181,229,205,108,201,240,169,87,195,99,76,138,15,228,158,47,216,146,8,248,175,110,207,39,94,180,173,250,47,24,2,201,150,241,233,238,16,120,75,140,84,49,212,106,98,213,162,86,181,76,170,35,124,116,48,164,197,74,131,117,229,28,19,139,154,0,123,202,110,178,10,79,113,166,22,172,117,191,54,48,27,183,59,223,105,57,148,54,241,188,72,118,58,255,33,235,238,206,33,254,197,162,45,154,226,221,57,145,225,19,36,11,164,245,79,188,132,50,190,248,255,75,183,214,242,69,109,232,147,130,166,70,86,58,124,161,96,88,92,166,32,184,117,117,232,148,14,163,81,163,242,0,239,41,82,240,105,189,74,68,200,164,195,85,62,74,56,226,196,41,2,105,154,95,205,207,232,106,98,226,99,112,210,188,162,203,188,28,65,78,18,252,134,93,120,74,188,64,154,12,133,146,228,14,25,9,13,157,22,83,145,169,201,189,221,137,49,232,138,179,182,165,146,2,109,172,21,172,40,157,230,199,70,170,17,231,133,250,192,45,75,214,33,111,3,120,209,54,12,206,159,226,150,136,96,94,25,66,56,178,106,7,73,214,104,156,236,28,249,93,15,229,9,0,132,16,69,155,125,179,207,94,14,13,244,207,241,54,32,52,63,98,162,154,191,75,209,229,33,193,255,57,31,229,86,153,43,207,166,165,245,54,40,212,29,222,70,136,130,40,74,185,218,104,130,108,129,245,188,86,215,76,131,33,190,168,234,99,175,11,251,216,73,187,108,44,255,201,238,119,247,44,86,81,235,45,3,57,216,75,34,73,180,36,35,240,164,214,36,117,135,41,119,211,38,76,81,196,8,21,97,136,235,119,71,123,36,176,199,227,228,108,128,149,137,5,164,77,148,159,81,47,176,108,234,54,46,235,56,167,178,84,254,105,129,190,49,65,57,236,213,149,152,10,85,206,195,221,92,221,54,74,114,134,198,83,208,132,62,75,99,76,23,147,221,170,238,47,2,231,238,159,31,157,21,230,120,116,37,205,171,183,193,105,172,143,117,1,93,76,23,54,218,89,41,8,34,70,14,172,247,13,165,93,149,104,106,13,209,88,202,31,127,1,56,213,196,57,128,219,160,128,36,102,11,50,241,144,120,109,249,181,6,101,158,193,159,198,121,72,53,117,201,226,238,36,19,89,190,170,97,242,166,133,255,187,116,117,149,110,240,34,46,115,10,173,23,253,193,26,88,218,204,250,37,212,109,250,201,191,194,118,95,136,247,161,207,241,204,135,2,78,149,74,112,131,147,47,174,61,6,17,165,170,245,205,230,27,4,219,42,253,132,224,5,105,216,149,164,189,139,111,218,70,124,62,36,131,167,58,160,166,166,15,182,6,55,43,51,18,46,56,174,90,10,0,14,29,74,85,33,208,147,69,176,90,198,106,36,37,30,25,35,124,178,130,4,84,25,198,20,229,53,83,27,191,7,155,221,115,87,5,220,83,80,84,102,251,48,221,102,199,149,98,72,199,4,97,43,61,78,97,140,141,115,8,36,76,209,170,73,151,35,27,50,135,70,240,173,0,121,54,23,163,78,109,212,129,93,171,216,134,28,83,113,141,233,192,101,187,144,201,55,84,241,226,162,50,111,152,243,114,9,111,93,4,89,234,55,65,28,241,78,143,188,189,252,70,80,238,69,204,212,181,122,171,109,189,186,144,136,240,116,95,234,155,53,70,170,203,113,36,46,45,134,195,163,140,104,104,25,181,136,167,116,55,237,25,77,120,91,44,239,159,52,190,41,227,220,175,171,101,213,127,105,222,163,58,68,40,210,118,247,1,76,42,20,189,248,76,43,113,25,81,37,26,154,234,25,226,251,39,69,143,3,138,235,220,47,9,31,25,63,195,193,72,173,92,80,43,152,143,80,74,126,49,33,238,113,228,171,168,241,82,49,174,116,73,94,130,72,230,253,161,187,183,237,195,41,153,143,130,252,152,169,147,185,106,2,207,13,134,90,175,141,157,242,255,161,154,42,107,178,145,195,16,211,119,181,175,211,84,142,39,77,187,239,159,12,177,186,243,150,95,140,58,167,52,103,146,158,98,247,173,141,219,214,180,87,55,184,155,216,203,67,81,243,45,171,219,220,110,144,106,5,138,225,212,232,110,202,220,68,84,250,115,120,118,200,167,154,108,73,90,190,72,34,47,249,229,114,4,80,142,144,22,68,254,128,128,196,171,194,100,131,176,168,30,203,107,42,65,59,156,176,21,156,53,86,125,203,58,216,87,127,233,238,153,162,195,175,35,133,212,69,25,61,96,246,99,19,132,120,219,58,140,93,223,248,9,43,246,147,166,10,33,40,237,26,6,87,228,81,182,159,34,234,48,74,27,30,186,36,136,63,92,110,3,131,130,27,239,155,0,156,219,146,232,148,189,133,204,227,35,102,6,13,242,251,69,127,251,171,127,248,242,116,126,174,84,115,6,193,135,29,128,225,230,162,23,222,79,106,4,26,156,61,251,88,57,81,76,237,7,19,107,37,95,147,230,99,193,76,98,87,252,124,217,105,200,201,204,245,189,226,154,95,54,19,34,64,85,66,163,243,6,203,46,201,0,174,183,154,181,226,46,152,199,255,75,54,243,29,83,133,231,240,6,21,38,68,184,253,109,54,23,224,31,102,11,112,103,43,17,38,125,238,71,104,161,159,219,136,215,196,141,170,10,56,156,93,207,152,188,114,22,157,0,165,25,138,205,58,248,67,193,58,28,147,32,38,229,221,175,114,14,42,161,2,223,231,204,164,6,92,49,52,64,37,164,223,252,197,118,55,243,108,10,158,239,219,175,244,102,22,194,134,212,9,249,244,43,86,97,41,53,9,224,110,61,250,140,202,187,95,171,204,21,221,58,141,24,176,120,96,194,232,84,28,125,246,218,142,73,131,254,249,22,179,71,110,208,97,247,139,162,171,64,251,79,190,180,190,186,29,110,165,88,119,225,30,58,64,49,68,45,83,93,122,136,199,146,158,106,5,211,222,64,64,160,74,72,185,138,112,186,135,133,95,31,236,77,86,54,59,235,32,245,245,133,152,27,233,115,154,253,233,222,36,218,216,218,211,137,127,103,199,95,165,151,234,33,228,72,167,103,13,43,119,38,71,23,218,227,177,230,222,214,149,81,102,246,94,251,84,233,90,116,77,26,118,194,122,55,75,208,137,52,159,238,73,8,33,157,218,178,213,108,45,131,207,210,31,144,133,204,239,144,183,230,251,195,57,195,154,39,61,36,39,117,126,121,69,224,198,15,198,98,59,82,181,202,28,149,49,219,53,48,163,19,164,57,251,219,61,159,235,12,121,100,151,160,191,93,194,90,22,119,28,191,219,210,170,234,145,2,111,53,86,140,171,46,232,231,111,18,43,83,2,142,131,38,36,99,174,3,26,169,105,31,214,250,212,191,8,1,141,69,73,158,180,248,93,117,146,242,10,188,63,7,61,149,69,118,161,141,117,25,193,18,187,220,194,82,13,30,5,225,194,158,252,56,159,129,5,240,0,213,85,67,54,209,242,151,41,141,172,187,12,215,255,6,5,126,185,11,225,35,202,5,182,98,154,26,217,237,193,140,136,38,71,118,166,44,17,223,179,101,97,16,153,33,21,204,15,219,189,120,219,24,117,23,4,153,22,143,40,174,238,185,27,159,69,251,1,227,108,218,69,111,198,184,236,14,216,136,208,115,154,211,47,149,116,98,114,40,90,83,116,92,109,38,134,140,104,157,197,116,57,122,111,5,224,4,175,201,244,62,210,203,188,216,230,131,214,184,164,54,48,242,179,251,201,77,16,77,13,77,23,34,66,146,24,12,187,238,151,92,139,64,114,217,125,244,175,10,155,138,118,58,245,52,121,17,241,62,231,105,214,169,120,184,4,155,16,20,12,215,206,40,237,161,186,68,63,141,166,178,6,127,126,151,70,195,245,163,96,91,23,138,173,211,99,103,164,14,51,246,20,75,76,135,150,74,215,220,71,15,76,77,215,250,38,227,176,76,17,15,179,232,18,19,165,54,194,146,187,110,158,216,55,66,145,232,119,152,61,63,121,155,194,202,244,22,81,66,36,140,38,108,209,21,139,25,159,255,185,60,117,9,245,95,46,99,220,27,61,151,235,253,38,161,64,188,88,189,117,249,42,176,56,54,107,62,80,240,135,153,86,180,137,121,111,177,208,196,3,194,236,106,173,82,40,195,1,146,180,204,141,11,192,120,252,52,4,116,199,14,254,104,216,4,219,7,221,233,33,47,34,247,94,0,104,240,54,18,128,85,240,255,179,195,197,161,240,178,242,197,103,68,166,60,95,131,245,148,198,163,124,209,39,120,42,206,15,106,91,118,113,89,19,66,66,241,200,64,65,37,82,169,139,136,203,234,192,172,175,27,160,244,10,91,4,183,109,177,183,93,233,92,26,227,67,87,232,184,97,234,202,240,80,213,42,133,15,68,206,0,206,110,170,227,223,113,90,208,60,11,93,245,151,50,51,86,152,199,229,35,248,13,119,64,238,165,152,108,70,48,149,157,110,249,189,25,187,246,251,124,64,0,176,165,128,174,39,200,94,100,193,34,233,19,192,83,39,177,228,74,234,195,128,251,203,238,192,16,66,200,223,179,30,106,195,189,26,217,157,142,161,132,38,20,179,217,79,34,97,189,231,106,19,144,223,172,39,206,91,192,115,254,111,141,170,103,121,61,72,101,60,110,173,73,193,25,89,206,122,137,151,213,60,169,7,42,226,224,249,190,43,17,190,187,240,163,77,26,192,162,70,170,154,216,20,183,212,229,81,56,157,247,123,219,168,91,21,53,107,174,135,98,32,176,146,78,98,190,30,232,190,171,107,188,254,223,5,25,58,134,150,36,28,218,134,107,40,253,245,199,11,1,191,26,173,238,5,142,204,170,161,157,127,172,254,27,185,235,87,15,3,74,170,36,195,132,163,3,126,33,178,173,141,106,23,111,96,111,124,164,68,230,2,210,18,190,148,45,70,148,194,38,160,67,130,166,172,81,5,91,142,239,190,58,3,102,81,212,68,68,73,134,6,117,116,100,47,57,100,207,232,224,125,32,30,193,162,117,36,57,8,27,203,56,199,110,251,56,35,162,240,157,224,0,42,206,199,201,33,95,5,127,132,29,178,152,101,166,1,242,99,155,248,47,71,180,75,84,99,65,91,32,31,136,206,52,48,74,184,208,83,85,179,51,105,125,87,66,145,207,127,71,239,255,157,126,120,139,232,35,64,70,128,118,191,41,217,7,185,86,117,216,187,163,194,206,174,218,56,214,58,160,248,111,154,70,17,108,212,91,199,245,32,108,125,43,198,192,38,68,101,100,147,129,87,52,240,50,91,92,218,108,127,101,155,228,123,77,147,41,86,207,159,139,140,93,22,169,163,63,89,236,154,98,131,93,39,55,237,122,107,6,174,184,202,126,27,199,141,16,52,167,250,44,52,64,134,244,66,235,39,127,190,88,127,61,105,107,157,35,59,146,10,14,155,241,227,170,104,180,47,95,20,235,236,196,100,29,66,255,252,236,249,128,214,5,234,40,241,34,234,45,47,166,217,121,36,243,35,251,23,126,3,133,136,164,113,22,69,236,180,239,139,48,255,146,161,48,135,129,150,245,193,181,210,85,120,4,249,147,174,66,17,136,154,208,148,214,82,198,29,171,4,223,212,84,104,93,95,153,151,59,52,212,150,113,85,179,189,60,151,118,28,93,220,49,114,124,228,164,99,165,40,1,5,200,121,138,132,77,15,5,21,162,216,252,37,141,224,202,125,209,225,242,62,177,195,93,254,238,77,226,148,168,119,167,195,151,180,25,60,215,48,166,94,44,45,114,159,78,24,155,132,119,38,31,231,227,51,37,35,33,239,40,171,12,250,68,190,248,231,228,59,213,61,15,65,53,179,92,176,23,172,176,32,72,135,37,241,24,107,242,184,186,57,99,239,241,14,0,114,211,202,79,176,88,52,130,56,18,75,55,22,208,79,100,1,57,105,53,174,100,13,234,232,158,118,211,9,144,128,160,76,177,166,10,90,95,110,144,254,243,190,208,135,184,198,226,200,27,9,38,241,0,208,210,237,180,2,22,149,157,19,155,249,21,3,55,195,149,105,206,24,110,148,19,249,58,78,186,176,25,100,216,4,198,194,104,71,150,103,193,54,223,28,146,80,51,157,194,14,178,180,189,161,192,44,225,168,111,47,225,151,43,100,26,191,125,146,222,221,199,216,186,126,173,89,90,229,77,60,34,228,75,219,182,85,232,170,22,24,130,197,101,20,253,116,141,176,241,34,223,208,190,53,49,201,93,144,151,241,108,236,120,86,232,128,234,238,83,111,80,172,96,67,34,128,6,29,10,136,122,7,204,83,50,186,1,23,79,169,21,92,114,15,132,236,51,188,123,139,240,236,199,67,208,132,52,13,194,187,174,29,120,140,151,198,252,88,147,102,219,35,162,73,126,98,77,213,8,169,217,193,210,100,239,19,153,49,43,252,194,75,228,65,143,184,39,77,42,202,171,40,113,137,164,157,33,120,131,63,197,218,5,250,238,192,175,128,92,206,161,173,254,238,133,100,158,136,16,101,127,238,52,208,92,82,3,217,66,93,246,228,193,254,74,72,78,122,33,105,54,8,66,93,246,194,222,27,194,33,125,31,125,186,243,13,92,218,44,36,132,226,180,89,124,205,104,135,159,122,252,15,162,223,62,10,250,171,0,131,127,85,178,231,79,207,40,253,46,196,118,242,128,72,35,191,117,82,21,59,50,253,123,77,220,143,104,20,203,224,176,13,252,32,28,67,43,91,75,244,94,186,135,19,180,199,223,127,142,98,37,239,28,103,87,65,235,18,238,103,120,238,30,86,59,98,172,2,220,161,99,43,3,209,122,161,55,146,255,1,36,249,99,184,3,3,168,72,232,46,73,223,106,79,159,210,38,156,147,51,126,50,165,108,52,49,96,42,238,80,99,70,146,206,224,54,97,97,16,213,14,248,251,126,49,66,87,134,179,227,232,143,91,185,125,0,158,183,5,242,48,7,152,160,171,198,163,34,181,199,170,68,125,93,97,109,136,230,150,33,113,56,104,7,226,175,49,100,51,84,213,22,135,7,237,200,148,72,116,142,163,153,122,86,4,164,15,210,118,24,67,210,223,220,137,144,48,144,180,185,234,2,241,154,213,43,109,156,143,172,26,128,135,231,119,24,217,131,61,148,77,141,150,92,115,120,2,154,217,75,86,241,208,171,108,103,82,89,209,129,238,172,132,255,207,27,146,164,74,184,68,92,141,13,124,214,138,185,244,149,236,189,182,103,67,87,10,32,216,220,143,80,210,206,245,104,149,139,20,55,5,113,172,207,125,29,89,249,19,112,108,14,88,182,201,165,18,10,245,121,6,178,148,34,12,59,196,61,173,239,178,241,33,155,25,242,134,32,227,233,188,135,113,163,52,64,251,178,224,118,246,79,167,5,63,212,177,112,180,80,242,169,49,210,21,134,141,17,157,190,91,64,227,91,38,133,159,225,105,247,226,195,200,172,31,220,215,170,68,107,20,234,183,178,143,56,158,107,86,223,172,215,193,84,10,65,89,99,158,61,203,224,96,108,213,54,164,149,13,125,118,120,95,189,114,57,41,211,241,237,209,190,6,62,79,184,242,245,149,195,91,85,198,131,178,227,71,202,112,154,51,82,29,130,223,121,113,6,199,251,129,30,201,68,187,181,197,35,52,79,104,12,235,40,127,72,62,197,101,25,50,235,135,22,61,18,204,9,17,58,139,193,112,118,161,34,157,65,113,190,135,176,140,117,20,216,176,111,50,116,217,162,214,180,80,45,31,21,53,93,2,228,123,100,207,17,230,207,97,240,183,85,31,41,46,45,3,43,72,155,187,165,203,128,67,28,120,236,54,20,65,238,109,110,179,222,136,198,17,77,149,130,251,103,177,204,150,184,189,37,5,55,241,217,14,130,255,116,126,175,235,144,116,140,66,14,51,205,67,99,220,51,208,79,206,154,127,22,85,71,77,215,145,255,44,243,64,209,227,67,73,110,151,218,87,197,55,237,118,245,39,169,244,170,245,203,108,245,142,50,189,176,80,21,202,93,146,1,53,148,177,158,56,213,31,235,149,163,76,7,160,96,185,175,209,247,27,135,158,217,147,16,10,240,197,137,20,206,239,82,56,27,22,220,198,2,89,79,127,31,142,1,6,55,182,200,142,137,107,201,174,111,181,210,207,62,30,104,243,208,79,121,233,86,23,51,192,246,38,237,63,185,68,166,75,123,229,116,251,234,207,59,122,231,68,113,211,62,70,25,143,151,209,232,208,160,147,131,216,54,242,90,239,63,40,144,174,63,16,36,202,26,114,183,89,217,89,136,230,91,48,252,125,202,164,150,89,145,56,123,247,12,54,155,187,186,61,40,196,208,28,136,119,101,36,210,226,52,175,235,200,109,39,72,109,208,243,138,191,212,112,241,255,140,84,135,41,149,18,74,71,117,169,225,47,36,251,47,104,143,61,234,88,50,148,255,119,218,157,33,205,193,198,233,229,11,62,162,92,119,220,137,255,123,184,226,35,157,8,174,39,63,216,248,137,225,131,8,2,82,204,80,214,39,91,209,189,161,6,81,144,36,198,76,197,109,194,10,4,72,54,53,184,115,91,225,10,11,168,200,46,218,124,246,135,15,89,53,166,8,241,71,83,123,154,209,50,174,37,55,123,83,140,20,54,44,56,182,163,26,6,6,190,38,53,147,232,222,149,68,107,255,157,252,151,137,92,252,145,148,33,103,9,72,231,13,116,195,38,2,23,236,159,143,19,6,218,213,124,179,244,182,30,110,173,19,168,90,131,57,252,205,106,250,34,115,21,156,227,2,178,233,51,164,166,165,72,112,14,41,93,38,111,111,37,191,106,207,33,185,185,90,72,233,134,236,98,171,160,112,169,40,190,94,93,171,234,98,137,93,127,65,248,80,186,131,116,191,197,63,31,50,255,195,58,34,142,54,220,246,198,63,55,183,44,126,0,217,209,232,158,8,7,110,86,107,240,61,28,52,138,97,149,20,247,180,192,143,33,83,155,177,22,187,216,48,139,83,169,139,99,123,154,74,125,236,38,59,46,27,30,157,211,15,232,203,47,94,136,56,194,51,139,205,174,21,161,217,7,160,227,59,236,156,91,143,154,27,42,117,22,168,18,246,201,35,37,107,157,58,5,158,76,100,112,62,84,117,50,22,6,96,111,120,207,116,151,161,13,67,239,116,206,98,64,136,103,8,201,197,9,81,239,18,226,93,190,46,81,229,232,167,200,193,215,90,182,212,93,78,67,26,105,97,197,49,164,150,52,143,248,121,13,95,217,227,206,14,80,200,179,171,10,146,200,142,90,137,125,253,146,71,131,33,45,48,69,241,119,153,254,188,241,25,222,97,30,63,46,136,159,57,134,89,0,129,234,189,184,64,200,208,245,48,167,116,134,99,230,3,164,217,19,159,106,99,97,202,22,164,70,66,13,97,32,58,239,114,37,9,60,59,67,157,37,172,251,50,177,13,116,63,7,119,74,90,248,108,175,187,95,134,112,101,157,132,160,143,70,245,232,144,69,184,106,150,9,184,122,224,32,162,162,167,166,203,10,237,99,78,75,217,159,250,237,184,75,97,163,68,55,215,93,14,236,225,12,141,49,8,40,126,117,77,135,80,77,205,97,75,21,26,145,221,123,172,2,182,77,86,93,204,86,114,144,92,13,141,25,97,222,15,100,182,160,159,142,35,220,49,107,187,208,137,105,153,135,0,174,222,172,239,170,133,207,178,208,164,230,211,2,139,92,32,192,133,89,232,32,239,245,110,166,136,37,21,196,131,79,242,98,209,25,180,252,102,119,100,85,102,115,189,106,122,226,157,178,221,143,154,92,187,57,68,241,18,33,225,250,134,114,116,72,134,250,27,40,97,219,30,86,74,184,102,193,26,66,181,24,165,153,255,190,75,185,18,121,114,85,220,59,224,145,174,176,36,67,144,74,196,161,88,9,48,79,220,4,67,25,232,105,176,32,242,28,201,66,116,178,36,164,218,208,31,240,68,239,166,138,242,198,226,27,136,232,255,174,210,152,60,200,61,15,238,2,218,231,198,130,236,180,235,65,221,66,82,162,92,235,251,20,38,65,92,156,106,85,0,144,25,182,28,226,88,153,34,253,19,27,116,90,101,248,35,202,216,184,19,35,2,94,8,209,254,66,212,135,68,219,185,32,107,225,25,227,136,211,138,181,174,112,128,190,66,165,251,135,185,108,40,159,222,177,26,58,26,148,218,89,13,15,27,236,24,118,78,33,185,174,168,219,230,119,230,179,169,161,57,118,97,227,203,9,125,55,136,197,112,94,138,136,230,112,204,245,136,116,59,13,75,68,121,43,122,9,22,252,149,172,182,118,113,61,53,171,44,42,118,178,166,69,222,44,157,34,128,126,179,24,154,159,106,149,17,227,58,143,176,241,222,56,42,62,181,26,208,33,24,30,33,112,83,127,84,65,41,251,206,115,178,2,222,106,153,209,238,98,208,200,210,177,133,86,65,23,104,110,177,161,96,79,57,142,162,15,207,173,153,56,254,250,73,76,74,43,36,200,57,145,60,95,227,21,147,221,41,171,192,107,234,251,74,126,3,247,128,122,243,153,128,202,238,189,17,198,179,70,97,245,190,200,231,176,186,98,217,254,45,230,228,185,78,204,155,64,247,183,255,152,161,26,12,21,183,209,199,194,177,1,221,95,77,76,253,203,104,7,192,167,209,180,50,138,227,189,182,231,239,238,168,59,221,119,154,107,247,102,200,51,40,120,192,133,47,249,238,189,123,233,117,188,210,82,68,72,178,111,103,77,144,205,181,97,1,172,166,152,242,0,187,181,174,188,39,82,5,75,21,213,113,66,102,62,173,169,132,21,120,138,226,211,39,44,143,160,126,74,108,191,13,117,58,148,234,239,194,161,161,156,231,240,170,77,120,106,63,168,175,231,243,60,192,181,236,20,52,239,78,141,78,130,59,219,80,208,24,37,165,109,209,49,251,9,62,80,50,249,181,232,42,228,47,166,191,144,176,206,148,242,148,153,182,121,24,128,65,137,42,161,119,66,94,240,11,55,102,122,7,205,142,144,144,180,47,60,218,192,149,85,15,213,83,8,79,215,104,8,209,172,222,200,242,28,255,51,185,167,33,226,26,65,147,100,114,222,54,27,170,212,207,83,56,170,37,126,121,14,18,40,231,4,14,164,248,6,110,118,48,51,83,228,76,3,131,87,77,86,163,48,72,194,109,53,105,118,111,198,140,133,34,20,119,56,35,236,7,170,176,164,95,86,183,232,105,108,7,25,169,127,50,26,86,83,94,101,58,219,72,205,46,231,78,158,94,221,190,147,92,96,224,0,30,65,191,21,237,118,106,224,247,161,116,33,41,10,92,81,248,232,191,41,72,116,171,89,110,208,62,230,196,11,67,172,81,188,8,212,62,255,199,22,201,68,20,120,21,90,72,70,211,251,61,232,5,238,147,16,91,225,65,103,178,238,63,246,157,100,192,170,206,249,101,28,25,120,125,225,94,105,146,218,75,10,178,103,244,73,77,174,18,113,205,198,233,5,88,129,66,64,72,137,118,81,217,130,206,156,174,224,223,115,249,164,10,160,47,237,255,135,146,236,13,99,71,63,62,20,134,132,135,155,27,21,239,159,60,195,224,248,123,205,45,147,225,233,72,95,151,236,249,144,43,148,51,197,175,100,140,185,170,200,234,37,87,113,85,41,197,41,164,33,181,64,228,58,125,41,220,43,111,47,37,139,69,75,126,166,210,12,7,175,6,63,122,236,237,156,149,142,254,174,11,37,215,82,200,54,62,74,43,2,249,172,218,115,203,91,14,165,110,103,178,200,5,226,141,45,42,68,130,198,173,253,230,217,122,113,39,163,182,160,231,100,179,40,207,8,27,212,22,174,85,58,27,55,118,83,118,244,201,68,167,205,50,31,36,17,250,228,187,200,203,159,109,44,83,197,240,214,82,128,207,62,237,127,108,238,226,36,190,44,152,27,248,90,79,254,43,191,182,206,138,179,239,133,27,56,192,25,166,40,83,172,241,62,178,172,53,58,205,73,6,139,66,50,24,22,193,232,205,173,161,67,139,236,13,114,239,156,46,253,12,218,238,6,255,169,98,117,8,215,156,102,178,212,208,18,175,147,108,96,73,71,115,87,75,254,77,61,212,49,252,42,72,23,95,49,206,208,189,203,240,139,4,56,101,109,139,204,117,23,213,104,47,1,254,115,179,25,96,58,221,157,53,112,19,110,172,118,168,11,21,171,109,123,100,79,124,202,172,155,236,144,86,224,44,183,119,167,51,180,139,191,76,201,173,212,215,120,148,255,149,110,69,229,152,112,197,133,178,122,15,23,55,103,67,13,152,239,59,168,53,175,130,232,143,236,0,96,95,206,91,141,167,127,199,149,82,51,222,51,43,148,225,183,56,32,68,76,97,35,154,233,207,47,2,29,114,143,36,159,81,168,169,22,163,74,208,233,149,204,129,138,138,13,48,180,42,41,155,141,156,228,19,71,135,137,63,119,146,67,61,236,133,52,209,164,39,67,110,28,5,36,100,159,52,79,220,118,89,126,230,63,180,117,243,165,179,147,209,255,162,97,177,43,45,86,56,48,223,195,122,39,130,118,8,183,36,55,42,221,83,72,74,95,130,91,23,121,226,221,206,241,204,44,105,177,188,105,190,84,106,225,244,183,44,76,188,169,150,98,155,208,244,161,94,75,232,173,64,126,153,184,124,75,229,87,31,209,154,93,125,64,53,167,155,250,167,122,169,184,231,14,34,61,208,47,179,182,194,37,87,240,10,125,2,26,125,232,189,207,199,3,153,204,157,148,33,93,160,134,67,238,203,126,198,203,210,112,25,199,23,136,192,135,207,227,224,213,125,17,93,230,177,178,164,152,162,80,107,50,52,221,42,20,128,143,202,168,22,91,223,159,118,214,249,29,184,124,24,124,1,183,54,43,61,91,155,116,241,94,157,187,60,100,244,97,97,177,9,57,90,72,245,38,31,86,172,41,102,15,35,39,4,233,141,9,165,41,137,229,44,122,16,181,99,178,84,124,207,34,140,41,145,250,172,186,100,100,156,162,5,126,187,160,57,183,240,17,46,181,44,120,144,141,151,142,129,195,192,11,203,241,78,134,142,214,106,198,94,141,84,62,51,127,110,9,65,150,68,221,157,131,236,130,114,10,128,197,13,157,252,8,165,223,138,108,179,156,231,156,82,132,196,202,13,64,69,92,110,180,238,15,125,240,30,231,134,56,66,31,193,191,100,72,106,233,11,113,8,121,238,178,117,107,157,215,58,43,212,236,53,215,214,1,16,192,173,175,231,62,113,26,94,248,47,30,36,232,160,227,75,161,127,33,5,192,210,69,155,249,190,217,224,42,17,77,54,231,20,45,5,116,154,154,80,74,148,126,85,137,13,59,123,226,167,20,148,24,19,123,17,78,46,126,232,255,147,20,83,85,103,16,86,141,246,211,162,58,245,162,77,31,51,40,174,164,117,38,201,18,8,240,124,226,180,213,190,92,223,249,184,227,8,168,86,142,19,66,247,142,54,135,218,13,197,216,225,152,61,155,156,171,88,150,158,129,132,144,138,13,21,166,17,156,62,40,147,131,134,66,228,77,177,184,53,207,92,208,3,16,2,45,215,154,73,196,92,47,104,0,94,23,103,132,206,81,105,63,84,231,7,205,95,148,128,250,142,158,42,49,223,26,22,72,27,211,39,245,201,245,4,127,48,221,21,121,201,223,108,209,6,93,31,85,112,207,74,123,201,78,249,139,38,60,134,47,225,21,74,31,177,146,41,144,16,100,28,219,207,21,104,154,200,135,169,238,147,227,243,217,211,187,109,182,74,223,148,201,132,46,26,159,121,196,145,148,161,153,126,127,103,44,44,215,135,248,8,157,23,184,220,82,173,81,229,136,173,243,230,69,68,158,137,156,73,166,209,116,155,166,231,141,186,187,84,175,227,63,227,13,18,245,222,185,2,9,97,179,58,174,246,67,94,255,153,44,100,138,172,19,5,67,221,82,20,224,61,104,222,44,53,106,82,147,130,225,31,218,140,64,109,45,5,216,165,119,100,159,228,18,213,150,192,59,85,135,249,36,228,230,57,28,67,206,105,230,148,212,28,106,92,97,2,31,152,107,208,11,10,205,238,102,126,66,83,190,233,77,232,77,96,85,249,251,119,192,179,5,0,198,67,127,22,157,78,146,64,204,6,39,200,12,229,227,234,242,193,195,141,125,107,248,143,210,251,18,220,67,240,110,48,114,110,15,160,241,14,133,152,132,225,44,134,92,88,11,167,164,225,12,234,164,92,9,175,74,190,164,193,157,232,4,137,216,80,165,124,20,254,221,2,198,63,217,156,135,119,4,178,58,153,215,139,67,52,172,206,47,40,75,33,86,67,63,41,10,20,37,237,37,156,4,13,25,23,201,228,9,237,67,16,22,116,17,184,162,203,188,227,13,110,65,231,79,200,61,118,207,68,161,90,71,47,113,31,224,165,90,23,21,239,63,80,176,54,103,99,60,125,72,207,90,110,231,121,225,205,35,28,16,137,252,136,94,179,14,97,157,227,66,82,219,137,26,78,157,181,147,28,161,251,43,196,201,53,245,149,152,194,86,91,70,203,91,114,199,241,212,180,125,44,131,135,116,26,132,69,27,84,222,132,88,96,163,119,62,129,249,230,33,147,28,124,23,172,231,132,144,182,235,125,193,70,233,206,77,27,210,203,223,213,95,105,230,117,205,214,164,126,23,240,10,34,237,211,43,162,138,230,118,192,86,247,125,167,215,62,26,113,209,175,19,231,246,167,150,22,44,69,31,236,205,198,210,214,123,93,60,9,175,131,96,145,71,92,190,209,201,225,103,43,204,242,98,253,129,95,56,223,107,29,87,165,180,44,49,28,37,42,83,215,122,91,126,77,38,243,71,213,191,223,14,76,247,97,110,190,120,147,167,234,237,10,98,148,45,218,3,23,117,15,148,142,173,118,236,90,31,27,85,54,188,202,253,43,102,109,130,17,8,239,241,89,212,14,29,172,179,90,8,104,5,203,117,188,43,184,167,54,8,100,136,17,55,201,102,193,221,245,173,86,65,162,176,40,92,214,101,18,82,59,131,63,156,187,219,65,190,115,172,242,52,181,80,109,165,136,98,148,149,152,234,86,143,132,100,239,159,119,163,250,30,130,119,190,45,58,208,104,161,144,10,202,200,31,177,215,242,236,78,3,151,34,8,16,172,231,112,71,159,168,32,208,230,50,84,234,214,40,92,65,60,148,117,76,216,111,91,121,177,66,86,123,55,54,126,46,118,241,103,105,245,89,242,0,0,166,87,7,145,164,227,90,30,10,4,88,64,114,70,127,14,161,218,198,16,35,230,115,54,65,108,190,175,186,252,79,33,24,82,118,130,249,181,253,61,28,154,77,227,209,111,63,61,68,223,162,41,90,176,37,114,169,199,77,160,219,199,22,79,240,212,158,243,217,226,74,158,215,193,166,204,82,135,0,106,12,155,150,113,241,197,33,205,6,16,19,118,164,194,115,243,112,162,251,134,203,122,124,61,242,68,140,200,131,168,172,123,48,70,132,227,199,3,196,130,48,55,231,64,216,195,86,36,160,233,137,145,108,224,93,218,61,107,191,138,171,13,215,212,65,223,117,85,120,109,207,141,12,23,221,175,68,130,129,185,138,67,225,85,127,85,215,75,146,79,69,133,10,129,210,51,71,147,116,11,104,76,194,87,78,137,12,108,185,53,10,210,35,135,33,203,224,96,175,47,98,138,83,60,163,16,100,51,21,186,245,7,153,128,164,73,27,189,195,13,61,255,96,12,174,169,37,39,235,177,224,137,71,128,240,63,137,238,255,68,185,212,135,190,156,240,184,158,113,210,241,119,224,63,177,236,63,172,135,117,74,27,187,227,253,246,222,134,197,251,197,243,107,188,160,85,252,111,4,141,195,243,91,73,226,144,131,109,136,10,172,209,186,95,172,96,107,43,22,44,176,226,122,100,50,28,65,163,62,235,88,16,254,97,48,250,64,155,101,21,83,64,255,189,98,142,60,20,184,3,54,87,20,50,178,254,138,105,53,169,141,5,88,57,244,207,138,191,208,185,54,87,134,70,182,197,77,248,201,118,133,148,231,106,241,215,91,61,184,61,250,9,140,91,66,203,141,93,171,166,65,183,29,234,196,85,230,194,177,148,240,126,71,14,92,212,2,120,179,141,11,42,166,15,45,196,187,30,249,247,104,244,5,25,126,208,252,253,157,224,36,138,145,222,221,213,15,204,112,217,50,193,215,194,2,248,214,48,43,229,7,204,79,218,223,82,137,114,228,41,220,68,157,35,245,242,213,255,141,189,192,243,63,72,119,222,107,252,230,192,211,47,186,209,144,213,221,185,22,152,208,54,130,76,100,242,54,210,211,40,29,189,40,7,183,252,209,130,240,76,107,14,110,35,151,57,0,187,180,78,210,153,198,18,212,33,205,72,211,89,150,175,136,7,138,13,18,93,226,93,52,171,126,188,165,113,29,15,231,234,11,67,54,164,115,158,58,48,20,202,65,198,247,224,202,190,45,10,153,146,148,150,218,67,157,27,190,197,15,182,135,56,130,43,203,209,174,134,100,81,179,58,182,229,1,155,224,135,148,214,99,38,92,212,220,49,17,170,248,161,123,88,92,5,119,19,210,149,12,254,121,21,140,38,10,247,25,4,22,186,68,1,211,221,109,182,103,137,4,242,129,66,67,138,61,50,131,83,208,81,53,132,36,86,63,33,62,142,250,210,195,68,246,210,84,77,150,182,48,140,129,1,24,195,122,107,160,22,129,227,250,27,102,21,127,52,229,47,19,58,21,47,132,85,233,11,183,119,3,54,223,94,30,168,153,3,202,62,170,29,46,235,105,186,122,192,71,128,73,149,47,98,46,122,34,64,101,76,177,160,154,47,174,96,118,108,73,203,121,15,19,101,72,99,177,70,118,219,124,182,128,41,154,76,22,204,166,120,224,174,35,27,29,63,8,248,217,183,247,192,11,141,178,28,4,184,73,111,64,221,65,220,21,145,34,163,79,94,28,225,40,146,182,182,2,244,18,250,136,64,65,3,121,52,149,19,150,105,221,244,244,247,77,249,155,100,216,128,178,170,122,153,140,221,2,88,211,227,255,108,191,91,6,185,100,148,31,75,245,179,229,46,107,30,214,20,93,198,142,86,108,83,131,235,38,107,38,203,229,248,160,22,216,41,215,22,55,59,211,156,38,76,79,202,176,49,88,161,162,206,46,81,83,200,99,138,117,40,110,2,84,142,165,212,63,185,183,35,165,96,218,110,177,40,36,21,19,181,76,171,145,175,144,249,115,42,97,99,152,49,128,122,54,8,136,236,196,46,137,181,211,218,83,112,177,64,193,136,89,220,176,221,204,172,174,154,77,96,166,191,132,59,141,90,169,6,46,45,84,193,160,209,49,6,199,255,3,129,73,146,92,31,226,30,164,12,7,148,241,217,3,113,226,199,81,146,95,141,45,176,205,253,233,128,78,74,123,244,138,154,234,99,11,241,18,251,174,123,196,122,254,82,210,2,90,216,87,97,38,253,160,197,255,134,152,168,162,17,72,133,41,122,235,85,154,133,172,162,240,103,107,149,216,192,182,55,27,163,94,52,129,61,154,61,11,135,223,222,154,217,53,135,124,181,120,2,41,107,239,28,32,232,45,27,51,86,176,14,7,40,249,170,100,67,101,131,23,151,200,74,151,82,184,146,40,7,64,240,146,253,80,218,150,108,16,186,224,225,98,8,166,177,252,0,35,95,107,137,80,130,116,129,161,149,37,52,149,240,167,11,50,129,134,80,126,16,233,201,206,97,186,68,205,245,254,241,139,20,5,89,162,39,98,188,107,186,119,233,101,250,245,150,241,120,191,39,29,12,121,31,198,242,252,230,85,160,112,172,171,128,29,103,65,246,39,126,74,92,140,142,56,181,82,101,195,59,71,4,8,9,42,98,180,136,41,26,56,252,4,230,102,239,251,161,183,106,22,54,238,250,59,61,243,9,189,77,195,254,119,234,124,186,211,5,26,88,176,159,87,101,242,100,179,102,218,39,85,82,118,109,146,144,225,73,28,78,77,189,135,29,192,12,95,153,113,248,50,171,113,241,189,121,194,155,247,109,70,124,72,61,27,79,56,185,218,51,155,130,98,183,1,100,60,85,55,160,158,110,41,58,63,216,176,49,228,195,87,118,254,105,223,41,138,84,41,78,214,111,49,206,175,91,190,57,25,68,120,22,127,85,81,202,226,197,123,156,169,249,12,182,148,31,115,211,146,41,208,248,249,197,188,103,47,138,8,117,43,130,28,28,102,44,149,38,221,176,211,11,76,148,186,176,252,87,62,69,3,88,80,123,168,196,245,128,224,186,224,99,220,46,237,181,88,159,161,175,204,237,160,154,13,131,12,99,88,171,231,111,242,238,194,193,15,3,254,152,148,114,131,215,216,106,245,73,197,176,147,149,25,185,200,252,52,225,236,86,240,34,22,76,102,243,132,148,11,204,125,58,185,37,184,188,4,169,89,249,104,232,254,3,96,102,68,177,242,8,251,188,177,100,48,1,248,177,185,181,108,161,130,117,35,229,28,94,131,105,31,242,158,200,167,63,124,21,55,142,139,10,202,5,82,209,8,37,48,22,47,237,174,182,254,11,32,46,255,142,78,113,207,192,187,172,174,16,156,90,26,138,142,57,129,2,59,148,175,197,194,242,205,81,57,214,199,206,60,204,225,254,113,28,148,222,242,209,101,104,98,108,237,223,49,114,212,129,78,146,78,208,40,162,230,188,127,198,195,47,15,146,82,173,159,186,217,133,148,237,194,5,33,102,245,90,65,8,165,35,12,231,205,62,97,232,36,7,127,30,119,233,149,99,221,178,173,102,226,168,250,196,60,181,5,125,126,243,158,64,110,37,30,195,162,229,136,241,198,229,105,88,85,49,14,96,84,216,55,253,53,92,172,24,38,54,35,37,50,118,149,84,244,199,203,56,87,218,44,100,7,25,135,147,55,101,115,200,99,37,8,239,72,221,30,76,8,86,146,55,44,91,241,31,111,230,90,185,168,144,245,50,43,46,238,33,229,223,34,244,14,118,219,103,141,110,249,21,49,255,202,251,214,126,66,144,34,95,94,195,240,131,109,100,123,73,158,69,82,217,206,59,169,190,31,185,211,83,88,73,74,185,229,228,147,57,21,198,39,234,143,84,167,170,144,247,206,56,43,55,104,193,157,220,89,125,173,151,17,4,10,18,124,244,41,133,194,59,11,202,98,174,212,26,19,95,71,26,82,242,133,85,125,4,131,36,108,37,250,255,99,63,15,53,173,129,255,175,83,105,132,142,35,4,243,133,67,237,220,88,25,169,219,83,229,33,83,46,251,0,111,226,87,41,226,98,245,208,93,251,94,207,210,41,146,56,119,137,32,0,61,212,6,161,219,144,112,202,88,124,132,83,197,240,185,196,152,34,202,136,59,198,165,5,136,11,246,158,60,3,176,105,203,207,70,162,187,45,160,39,60,82,115,113,239,37,166,188,235,215,222,227,65,73,188,70,178,98,215,247,7,12,10,4,216,139,202,178,125,231,103,79,61,127,58,10,202,75,42,107,139,214,172,4,14,3,23,73,247,52,158,78,61,218,235,79,191,182,70,127,157,34,208,242,177,248,153,110,42,50,168,186,212,159,202,174,245,161,60,197,47,221,200,111,195,231,35,136,145,196,62,119,52,247,41,50,41,64,94,231,136,149,213,174,127,157,61,143,47,166,152,59,245,186,16,70,32,201,49,239,157,90,225,122,138,88,158,93,59,121,246,69,151,25,182,189,199,100,74,131,123,99,103,185,138,240,169,255,83,8,240,13,159,156,5,223,181,247,243,244,179,90,207,159,36,69,34,174,29,39,12,198,108,220,130,2,10,203,188,206,67,116,209,27,67,170,198,93,113,250,14,198,254,196,37,146,198,0,245,162,19,196,105,30,136,94,211,48,61,213,53,160,236,102,140,240,236,1,246,124,73,73,184,88,243,157,125,154,77,39,104,111,1,205,78,22,233,44,37,253,92,198,51,8,211,150,43,192,106,122,208,21,123,140,14,148,222,144,217,194,15,242,120,80,45,66,71,74,147,132,37,185,45,165,41,76,166,143,130,134,3,4,15,104,214,102,179,162,238,195,200,235,20,223,172,249,110,37,43,216,136,128,232,235,48,215,2,250,173,82,109,146,30,125,217,231,73,206,65,2,40,45,35,163,248,230,102,19,67,102,0,76,64,7,130,23,167,105,28,152,26,73,234,15,36,35,231,146,205,50,217,164,199,154,192,15,19,80,26,30,181,14,197,12,131,88,61,140,86,85,233,182,210,78,143,77,63,177,30,176,10,224,14,137,130,162,84,191,108,227,75,85,115,237,159,119,222,168,131,18,13,22,92,110,176,134,71,180,31,116,154,111,4,116,74,59,2,191,75,114,181,184,238,106,236,202,251,63,247,48,35,155,172,61,122,174,26,38,3,176,42,15,71,195,153,55,66,191,33,169,177,220,36,95,177,66,86,173,31,180,219,166,178,139,120,139,67,88,25,238,233,169,169,111,163,217,54,29,44,34,138,236,199,35,50,82,214,30,125,91,25,222,65,137,125,96,232,78,167,209,68,71,70,1,22,163,34,202,200,71,113,235,157,41,14,32,110,171,235,197,174,10,51,158,251,44,98,199,201,196,168,50,201,99,205,245,153,75,169,17,143,154,52,222,138,28,173,86,92,134,115,136,220,131,85,171,122,218,117,190,117,143,79,26,121,10,50,45,80,241,33,4,253,140,1,159,201,105,123,35,133,81,59,236,16,238,109,215,10,124,211,64,112,180,147,203,106,142,69,97,205,162,177,217,151,174,189,239,69,50,30,166,238,219,120,79,225,197,121,127,91,215,89,102,17,39,158,213,94,164,254,49,125,216,191,222,90,38,224,214,242,60,2,38,241,139,218,34,185,186,30,206,33,43,38,242,81,191,12,1,200,96,167,125,197,194,127,129,244,184,30,74,74,196,174,229,224,226,124,52,137,122,146,108,187,169,127,72,111,131,243,79,149,236,134,103,137,212,161,44,61,183,188,103,150,96,95,88,187,167,31,213,185,63,128,70,10,58,47,69,155,112,231,242,129,19,78,116,74,152,85,44,128,199,241,148,56,48,27,194,180,191,35,170,227,179,166,110,172,88,208,185,53,153,120,109,155,216,205,172,159,59,191,94,49,209,213,90,125,246,132,153,163,89,50,28,91,141,185,11,4,229,210,18,79,36,117,191,90,231,97,92,89,193,98,201,7,9,252,3,100,157,87,134,164,29,218,54,7,117,232,97,226,74,185,43,135,78,199,151,206,137,157,244,201,49,137,164,23,115,134,121,92,128,224,192,100,154,252,124,146,17,129,44,130,237,65,159,194,35,88,56,132,29,163,200,91,112,118,35,100,76,112,87,180,233,171,69,124,62,161,232,54,66,129,248,193,47,232,197,143,236,112,36,132,61,97,179,231,60,124,4,220,161,114,16,84,196,143,200,58,98,2,255,8,3,222,42,146,204,234,68,199,78,202,173,32,215,30,242,64,32,250,49,111,31,174,191,209,40,51,55,101,12,137,212,116,140,72,132,52,104,204,245,218,122,29,236,175,188,112,137,112,129,225,22,84,118,55,75,104,13,207,51,243,102,148,120,49,86,192,53,173,30,143,161,0,187,160,141,185,32,104,37,221,242,44,29,27,162,135,12,4,205,239,98,8,217,237,81,207,29,240,169,209,6,80,56,120,99,193,90,244,235,14,45,162,130,224,62,152,96,147,9,238,188,49,82,151,207,8,240,126,39,228,192,121,199,227,52,238,238,69,130,134,174,90,34,126,176,133,63,234,79,219,126,186,224,106,183,242,244,90,180,161,17,110,155,66,109,222,205,83,121,103,49,85,234,220,198,98,67,0,50,194,21,182,193,118,19,220,4,173,96,221,203,40,186,232,98,162,37,12,169,225,26,229,12,71,121,194,162,100,159,139,30,0,151,86,14,131,219,129,154,212,170,79,126,26,171,90,92,239,0,106,79,97,213,183,128,12,238,216,30,67,114,73,64,191,22,179,225,12,252,220,234,87,55,51,145,66,34,63,168,252,148,87,47,176,54,228,85,152,226,61,198,41,76,94,182,131,134,142,127,97,14,232,78,147,107,91,23,55,184,220,0,132,128,230,214,41,253,146,45,59,69,244,78,228,127,47,234,235,212,197,152,203,251,16,167,93,153,46,245,207,238,82,246,96,131,4,123,250,67,9,15,63,198,214,205,18,51,223,238,190,104,69,185,188,1,61,168,132,22,21,224,86,237,119,49,15,228,241,216,161,180,19,252,22,109,144,133,49,21,97,145,73,250,32,160,0,103,179,235,69,26,206,44,140,184,97,110,167,21,84,228,112,18,154,24,41,60,232,190,168,43,72,248,82,221,13,138,79,89,140,122,61,117,232,17,75,243,217,88,218,235,50,96,182,174,230,168,249,99,90,3,240,143,171,128,49,247,62,32,242,216,73,239,88,172,30,77,172,78,40,138,46,152,178,103,92,139,57,224,167,208,14,63,245,78,69,235,225,103,133,134,96,22,32,104,77,117,153,192,206,38,183,221,117,253,207,240,211,16,89,105,251,119,74,144,222,156,150,154,58,135,38,58,165,24,125,4,181,205,243,117,226,156,243,80,70,66,176,146,37,197,55,215,99,87,148,92,191,170,198,29,60,48,57,132,232,226,100,191,28,143,184,235,205,69,47,243,18,71,89,96,148,5,68,98,120,4,46,222,166,248,156,123,31,13,147,244,29,153,133,248,130,207,112,2,139,131,49,115,58,120,121,244,170,19,97,201,192,75,161,137,127,83,157,78,253,58,222,224,220,83,182,11,236,101,153,140,34,113,36,254,143,112,151,78,23,46,155,32,170,178,239,64,77,243,128,127,240,27,82,213,68,205,87,27,42,124,75,156,9,234,4,161,210,181,7,140,130,78,31,105,100,208,169,223,62,105,229,132,50,56,128,226,5,184,254,213,116,54,2,93,233,67,132,34,39,179,133,27,209,227,163,127,21,38,10,175,140,28,114,70,190,173,123,166,31,176,23,83,27,2,64,147,250,217,95,1,100,211,238,42,151,65,188,182,234,61,134,64,31,245,14,173,167,214,244,223,242,182,230,208,180,241,228,142,135,251,1,188,189,100,175,18,181,117,35,14,102,136,20,208,168,235,41,228,102,112,204,114,197,137,63,144,1,174,122,8,52,194,119,247,169,229,16,103,124,105,126,128,30,165,102,132,107,24,55,253,220,212,101,202,129,150,144,2,88,195,9,152,160,243,97,168,80,228,18,168,79,186,193,151,206,197,164,32,6,58,126,128,178,154,122,20,188,81,123,96,6,46,214,149,107,24,177,129,255,208,247,29,66,228,212,126,81,168,1,76,131,174,108,141,122,248,24,107,113,170,68,235,117,129,83,56,163,148,130,79,104,185,22,138,198,242,77,180,102,47,117,225,233,90,16,225,8,163,241,112,173,15,227,176,197,136,139,114,202,96,151,63,60,96,154,107,17,147,224,206,248,93,53,106,235,229,60,87,165,173,67,60,192,40,25,38,154,183,128,195,41,187,21,254,166,61,76,158,20,29,63,194,131,191,180,111,32,193,245,193,122,94,224,84,142,94,172,150,192,219,151,49,107,61,164,252,204,72,119,227,21,253,120,84,60,176,113,224,172,24,196,92,64,19,6,114,3,127,121,48,40,3,60,52,74,110,225,56,14,140,23,179,58,129,206,230,166,25,190,123,31,5,201,50,253,204,94,174,116,91,166,97,216,90,145,201,152,88,164,18,19,17,202,204,251,146,159,61,233,43,209,63,240,241,168,94,78,86,211,0,62,97,12,204,199,62,218,65,64,9,170,91,210,0,191,56,249,81,51,140,84,246,229,192,59,27,87,104,195,108,174,216,168,188,98,234,57,57,162,193,13,190,155,45,124,40,58,32,99,14,179,68,39,112,92,159,159,36,201,2,226,129,171,120,102,185,148,114,152,162,196,181,56,69,182,37,197,98,228,38,41,142,10,57,84,197,160,183,210,236,9,42,214,224,63,62,31,118,26,251,177,236,185,210,104,244,19,251,195,113,141,34,50,255,204,42,56,117,66,203,139,249,119,14,28,203,175,32,42,245,180,104,11,154,25,127,248,60,200,28,180,91,39,244,161,108,240,140,189,72,32,119,76,235,30,100,46,74,250,110,234,232,192,243,51,124,39,251,186,123,64,23,149,105,161,56,180,49,163,245,34,42,187,145,64,13,82,135,95,186,146,44,214,135,104,194,94,110,93,178,242,130,21,226,63,156,184,127,204,241,167,193,180,9,237,106,90,105,165,19,198,246,140,189,35,66,77,27,170,145,237,170,99,161,189,234,238,51,219,82,212,214,32,43,128,193,45,163,2,216,44,192,84,104,92,99,93,116,94,163,255,90,174,176,184,147,127,46,68,22,63,23,62,151,173,125,237,52,101,54,144,205,184,145,103,197,86,53,11,127,158,118,175,217,13,86,251,47,11,230,181,185,174,212,134,254,17,229,174,154,246,87,107,230,55,252,104,84,104,251,201,66,110,183,24,71,54,10,178,175,12,182,18,163,73,203,244,85,216,175,129,81,60,17,112,71,155,136,34,122,134,137,245,172,152,64,127,55,97,0,148,116,138,88,45,172,16,250,169,10,55,168,155,249,246,117,74,112,183,220,144,84,127,245,255,79,75,162,219,9,150,235,53,199,122,194,58,198,192,83,66,183,114,7,36,198,143,179,218,40,178,248,218,185,108,140,103,50,91,31,235,191,230,109,62,140,189,224,31,241,31,255,48,167,106,18,242,164,95,24,208,232,159,107,188,95,66,187,61,92,245,43,201,191,135,1,41,19,255,103,156,115,9,219,112,48,74,62,113,152,120,196,200,133,105,206,67,75,26,102,159,159,237,244,74,119,46,70,217,24,102,5,82,212,11,224,67,44,241,148,125,122,140,30,141,56,185,122,202,228,228,152,203,143,221,92,116,168,69,113,89,106,187,215,201,255,151,132,143,105,97,52,138,102,179,146,194,72,5,11,142,16,31,119,218,54,11,45,117,143,78,191,169,116,115,101,231,67,196,81,203,175,126,36,74,3,153,52,15,176,118,87,2,10,235,166,166,25,217,24,97,56,174,121,208,62,83,81,159,25,1,81,67,213,89,71,34,140,83,221,7,159,118,96,172,176,235,249,185,28,97,166,17,64,245,165,23,63,251,128,105,12,76,148,92,91,188,236,238,25,184,58,203,60,22,171,192,183,224,144,158,173,39,61,188,92,76,155,181,102,5,187,207,150,94,58,3,250,36,236,210,151,254,24,164,165,111,28,108,229,47,22,146,124,12,137,148,24,184,174,127,13,247,114,83,177,100,178,209,116,247,77,184,99,249,116,52,90,208,48,242,239,23,251,172,248,54,133,62,24,240,90,110,209,64,19,65,231,127,36,40,74,61,89,232,108,40,133,183,241,255,164,20,180,249,37,233,11,144,123,198,10,134,56,30,115,232,181,188,113,167,11,26,133,132,207,13,144,114,236,85,141,70,151,42,10,176,211,160,243,33,210,57,247,197,33,32,215,207,152,153,82,222,95,87,217,232,251,9,157,52,92,92,186,221,244,36,132,244,171,126,222,212,178,213,118,239,52,68,215,228,157,37,229,77,151,40,95,205,177,209,250,59,223,193,65,135,147,161,220,60,30,20,221,12,251,251,237,115,218,76,211,222,227,113,244,133,150,144,25,141,230,202,17,219,118,142,8,254,249,111,8,74,66,92,214,206,5,252,176,47,65,208,174,127,25,182,208,254,125,215,136,104,95,122,148,47,160,24,171,217,115,108,36,46,111,121,54,209,200,78,201,242,47,82,146,153,116,84,30,151,175,199,2,189,89,106,30,113,219,11,101,233,191,165,1,168,238,15,156,187,76,114,205,125,10,232,251,59,152,234,16,241,125,111,195,40,170,83,198,62,219,137,128,20,195,25,33,235,77,95,39,151,116,175,239,44,250,171,84,173,154,211,23,212,157,160,162,208,164,16,244,147,14,14,17,6,104,150,53,108,250,78,227,27,137,22,252,98,238,175,243,37,70,13,183,79,164,152,113,101,78,244,30,197,103,210,103,214,38,156,171,0,17,21,28,178,30,168,20,31,200,208,51,52,113,15,151,103,235,237,40,10,81,34,216,193,173,182,231,138,223,70,74,110,140,135,128,67,193,157,182,109,142,223,157,163,206,148,192,228,100,183,148,130,219,246,217,18,184,83,27,227,178,40,188,85,136,45,33,244,69,87,159,128,40,97,108,157,0,46,148,60,23,222,235,38,205,188,53,18,244,187,182,168,183,237,144,27,24,195,130,65,220,216,15,20,137,249,27,41,218,232,246,197,92,106,119,80,113,188,192,30,233,34,219,39,146,187,114,27,18,165,104,236,249,38,44,105,166,205,230,49,128,243,36,251,113,40,38,25,215,224,120,27,235,159,12,92,34,87,109,158,74,60,6,136,178,187,38,91,137,86,88,121,201,214,195,151,83,64,228,135,143,158,147,97,176,188,111,251,247,113,197,192,23,113,9,177,188,15,65,193,111,153,189,107,45,251,63,75,15,75,144,12,21,147,41,0,174,131,76,50,32,230,156,172,12,21,217,99,174,122,176,90,142,255,218,205,218,102,252,254,211,225,2,68,190,66,50,226,64,173,14,103,174,112,42,47,226,144,59,125,110,69,123,255,9,156,24,136,238,168,115,76,198,25,170,142,181,178,27,82,125,25,38,98,50,248,232,139,82,51,79,162,74,26,73,204,26,40,13,40,2,73,96,105,177,92,99,35,99,110,56,185,105,177,205,31,100,153,114,150,60,150,252,43,129,210,116,71,159,252,129,54,152,242,65,180,226,15,50,224,127,124,175,143,91,38,46,62,8,22,59,186,178,38,77,246,103,48,216,212,109,56,156,174,127,24,51,123,161,249,178,142,219,27,68,158,78,254,94,242,73,34,240,204,200,93,216,7,25,228,165,205,3,19,2,181,77,104,175,11,217,230,194,135,111,69,253,161,56,50,214,192,155,137,146,17,189,167,202,57,121,74,241,142,45,201,161,154,57,125,92,44,130,241,88,74,115,124,14,144,36,13,187,40,11,139,4,59,158,157,206,13,92,151,135,1,219,94,61,152,173,99,202,240,172,225,103,253,248,69,184,171,34,33,169,218,245,125,15,58,199,178,40,202,80,134,75,170,110,92,65,6,58,200,15,51,116,102,229,188,24,164,185,80,221,62,235,227,1,238,159,158,44,47,211,248,136,211,153,57,241,104,231,90,19,39,187,253,118,187,69,91,208,213,90,157,249,110,157,246,186,4,46,212,11,235,27,55,22,236,16,139,224,123,76,76,174,18,156,21,2,25,59,83,147,157,186,202,18,243,139,77,192,205,43,11,67,231,130,169,53,171,6,241,244,138,2,96,125,93,209,194,120,187,162,104,129,237,118,242,149,94,212,207,222,141,202,202,204,103,231,34,132,92,157,95,239,176,202,195,185,87,154,63,219,10,215,8,146,73,190,222,17,110,27,90,35,66,27,93,191,17,12,120,158,138,224,58,68,152,169,243,48,157,252,163,132,148,157,222,184,145,161,202,141,123,93,61,82,14,213,82,53,66,165,100,215,10,77,207,216,139,35,208,176,63,63,80,219,7,147,222,36,12,252,16,92,225,56,96,70,218,129,99,205,25,99,208,253,109,43,104,153,0,224,39,192,163,67,138,85,157,8,128,148,197,89,194,87,99,206,81,141,47,214,217,156,211,187,184,220,33,32,20,31,143,48,136,147,54,141,147,129,53,91,215,115,208,74,187,36,225,92,30,238,23,79,195,80,124,161,28,40,129,212,156,128,13,94,16,64,122,47,166,181,116,236,218,16,106,162,20,12,250,106,59,75,168,173,41,229,75,239,230,135,79,240,61,106,144,243,222,80,207,8,155,238,226,204,246,25,2,83,116,227,42,121,189,61,88,237,200,221,66,111,84,209,44,204,5,74,21,249,236,194,187,52,103,164,109,114,191,27,0,240,99,60,253,103,92,69,90,87,109,109,138,61,171,55,129,98,152,62,65,82,93,47,130,95,171,12,145,48,243,4,220,47,118,144,188,144,153,224,242,141,144,94,218,128,144,77,106,98,182,215,118,91,73,238,22,122,110,3,109,89,91,34,0,57,72,86,228,158,153,209,235,58,200,213,223,68,254,49,210,128,11,87,0,207,25,93,183,141,193,9,142,11,15,213,209,90,220,249,117,222,163,188,42,116,162,111,235,175,70,29,243,205,184,46,214,112,219,68,27,190,37,228,13,196,98,127,58,220,90,248,241,41,128,82,170,102,78,72,99,103,47,49,238,210,203,217,40,130,83,98,143,81,119,52,173,166,24,234,61,253,11,147,118,189,128,69,161,207,122,161,251,67,139,246,0,44,109,95,241,166,224,177,225,201,10,38,201,24,44,192,55,22,191,109,159,167,39,67,213,33,100,6,197,183,223,105,223,51,37,21,232,53,7,12,64,243,13,77,22,76,175,156,127,201,50,147,144,135,179,71,59,88,161,195,29,23,213,184,66,77,202,54,134,198,21,205,74,59,68,197,2,150,28,192,219,164,192,158,231,193,240,26,176,33,136,97,129,95,91,76,114,79,86,97,220,135,80,233,39,150,150,27,223,206,160,84,151,120,226,45,231,200,167,121,200,46,1,132,39,112,88,96,85,173,249,29,67,46,208,224,131,84,81,64,218,16,15,12,243,215,86,157,212,204,147,221,26,11,10,114,75,9,240,8,16,58,152,196,219,149,51,8,94,225,203,7,157,156,249,220,220,207,80,128,47,103,189,58,38,83,183,122,51,230,254,146,160,37,235,226,233,55,164,177,33,246,224,67,54,25,126,27,216,100,83,102,46,231,99,215,206,57,243,30,174,54,153,209,116,17,156,121,215,104,69,33,59,37,187,95,75,158,233,68,148,64,236,174,32,201,143,189,99,126,50,216,65,155,184,98,84,102,243,47,178,99,59,227,198,213,53,206,39,35,180,9,162,212,58,190,48,80,234,176,124,165,130,234,100,117,5,245,122,210,159,134,31,165,144,196,154,81,131,130,236,180,4,23,225,45,144,92,99,117,71,130,142,141,103,81,168,211,2,123,203,171,59,133,24,46,169,116,160,216,233,44,215,66,201,119,51,58,75,50,68,116,127,170,113,129,55,193,109,155,237,246,191,189,150,135,24,5,204,65,201,86,15,202,87,40,122,227,52,245,82,182,54,65,104,165,101,190,208,117,246,203,163,168,171,35,67,186,170,221,100,63,0,206,157,229,28,237,147,132,88,91,215,64,64,22,48,88,246,232,140,146,211,199,110,230,207,238,78,66,78,104,253,244,227,114,94,210,30,6,33,43,1,110,176,2,156,178,126,202,213,183,124,213,218,56,96,100,54,192,53,69,60,180,73,48,142,15,85,251,191,216,147,246,47,251,203,203,138,14,174,9,73,186,102,220,0,200,22,56,137,234,117,155,105,229,151,192,129,193,93,234,222,103,57,195,107,240,92,18,180,41,23,23,255,255,135,26,222,109,47,129,205,129,52,192,82,153,195,24,72,58,156,127,159,210,114,67,196,173,239,17,84,216,115,57,151,70,218,133,179,61,149,175,160,128,222,103,91,202,239,92,198,173,251,58,186,236,105,215,23,167,254,58,4,21,22,17,213,211,230,47,195,183,154,245,187,224,165,236,107,184,195,149,49,79,138,158,97,201,64,138,145,249,37,253,56,175,148,83,197,74,69,186,47,38,63,14,241,224,30,52,152,74,163,144,190,253,92,176,164,109,217,165,118,19,56,214,162,10,193,213,18,95,72,55,150,22,199,50,196,111,155,204,32,122,25,68,234,156,43,178,92,160,204,83,138,2,184,248,7,132,201,144,69,176,216,12,49,175,55,89,163,91,23,159,27,226,183,111,153,13,35,140,237,237,170,126,119,171,55,105,81,53,55,142,131,46,39,136,83,145,158,216,192,73,71,22,117,124,243,85,81,130,52,28,216,143,226,153,141,3,162,141,249,125,8,119,27,65,133,135,123,117,71,161,45,130,255,194,160,178,21,123,106,105,199,3,146,205,115,157,18,61,181,226,101,151,234,244,10,17,216,104,186,3,215,32,157,200,151,190,41,62,181,74,5,160,213,185,70,97,253,164,115,81,108,228,207,4,144,210,54,224,36,93,21,210,109,58,54,121,127,235,182,110,122,161,24,48,114,193,83,31,221,109,136,70,83,212,203,195,232,231,69,5,55,157,106,77,101,19,58,55,127,91,240,85,64,11,229,155,10,93,177,2,144,20,75,121,186,81,171,50,1,196,62,217,231,16,206,250,186,173,24,60,218,230,99,216,36,3,103,61,237,73,61,170,38,35,224,158,166,103,119,128,4,5,152,194,141,234,113,149,54,196,25,235,18,81,227,137,137,138,115,20,204,38,189,115,69,224,31,135,6,32,171,72,87,42,144,71,72,255,171,79,132,159,83,151,209,62,152,25,79,133,19,172,154,90,84,80,101,131,150,37,245,195,199,210,235,98,122,229,215,7,164,79,63,62,80,142,144,161,189,235,24,212,200,109,145,185,104,122,29,112,81,147,15,4,108,147,244,184,155,249,18,80,201,174,227,93,226,109,63,7,17,14,209,141,194,160,30,170,18,60,144,32,224,177,0,106,248,126,107,84,185,179,106,146,13,238,80,251,18,50,96,122,216,217,112,187,148,102,111,47,244,158,22,39,76,59,150,43,22,117,202,253,88,26,166,126,243,142,239,81,69,185,255,93,56,20,32,232,185,22,217,19,198,221,159,42,176,105,127,180,90,189,136,213,241,120,92,0,77,136,165,142,142,126,142,164,219,231,41,237,134,253,191,235,254,252,57,52,25,89,120,215,145,142,87,152,149,107,177,79,86,176,4,105,59,150,254,14,74,110,116,206,16,0,218,98,156,66,18,10,16,202,136,15,80,236,236,233,75,132,186,168,174,233,16,240,124,0,189,243,98,252,33,121,215,44,173,199,127,71,233,97,165,227,102,12,62,59,225,180,119,55,117,95,159,229,177,99,143,111,247,182,37,180,23,219,51,67,250,113,124,122,213,160,93,82,156,170,252,0,1,76,22,11,250,91,147,112,1,233,251,21,112,60,137,25,215,114,231,83,28,55,129,94,198,200,247,80,156,163,198,211,214,235,239,111,210,160,137,128,181,114,163,61,8,94,83,46,49,30,181,239,140,222,109,66,167,226,89,159,32,73,145,21,222,213,65,62,66,94,137,206,128,169,236,73,167,141,150,232,238,36,44,136,68,28,4,21,153,225,253,254,31,210,190,138,17,5,228,142,90,163,91,64,60,208,230,70,88,201,198,140,171,37,112,143,83,251,39,36,63,189,48,135,196,100,189,76,124,37,117,179,153,183,236,97,94,72,5,144,76,23,71,22,137,91,101,17,51,31,37,37,248,167,248,202,225,125,28,24,192,51,67,242,20,243,183,110,138,211,210,110,39,221,189,226,241,100,225,217,111,128,6,152,234,156,179,79,2,139,150,103,51,47,252,21,104,71,84,83,243,17,144,151,52,96,128,26,163,179,77,162,97,109,136,128,106,219,50,111,229,203,148,252,102,19,181,220,239,169,7,60,6,173,111,160,55,24,162,69,223,39,186,222,104,184,206,203,0,68,178,244,108,51,107,230,205,176,248,207,12,225,122,184,184,1,99,226,173,135,71,136,45,243,127,168,160,134,31,180,45,53,1,213,36,43,83,51,59,61,115,223,67,123,54,86,38,128,71,198,210,179,241,150,253,253,1,26,104,127,234,182,86,121,188,19,134,211,19,249,75,96,210,137,255,175,48,38,23,82,107,180,73,87,97,17,31,217,160,77,243,143,164,224,77,154,152,148,205,66,240,48,168,156,21,103,19,214,154,17,173,156,16,31,18,63,134,224,211,145,46,114,33,113,105,125,72,78,202,25,183,28,255,45,63,169,16,225,2,237,156,45,254,223,125,195,250,99,49,156,250,188,216,169,104,171,157,188,114,72,110,29,153,187,99,254,51,237,255,23,98,131,248,193,121,59,142,7,176,78,52,182,134,170,136,125,40,234,245,225,74,212,208,176,105,253,8,32,143,69,180,249,246,10,31,176,129,144,255,199,193,59,12,181,231,207,169,241,243,19,253,220,49,45,195,42,147,102,239,117,186,240,63,156,184,43,225,119,87,44,38,11,106,231,241,208,145,167,222,147,22,240,37,62,139,30,249,0,209,78,164,84,131,254,178,126,91,170,226,29,73,170,154,101,221,202,18,92,146,134,178,38,195,106,88,228,86,86,172,34,113,89,4,85,139,78,39,3,161,49,94,245,107,21,206,162,64,240,35,201,126,89,226,156,229,141,165,29,4,22,197,202,125,44,200,64,176,137,55,95,167,234,104,86,244,217,45,234,206,4,6,171,85,146,235,237,168,81,103,77,204,104,16,110,90,132,100,240,72,96,188,201,254,56,43,229,76,8,144,250,190,182,102,89,64,104,238,222,184,173,138,130,235,233,91,226,30,237,38,236,194,116,180,36,198,97,37,242,32,60,224,15,13,203,190,121,127,41,1,108,205,117,79,104,173,232,164,128,0,31,193,82,164,115,1,175,199,50,22,0,215,136,87,212,105,174,240,47,27,51,93,165,183,61,96,31,150,125,70,38,192,85,215,191,65,159,42,123,59,211,210,39,96,64,53,80,103,134,214,75,89,23,40,114,4,148,61,56,175,176,119,180,61,162,119,184,21,110,204,103,52,202,109,151,202,204,240,215,165,116,96,52,113,64,112,42,171,54,172,169,69,253,44,153,24,232,19,141,73,3,80,141,143,57,23,209,218,79,5,176,20,117,197,223,97,0,0,216,103,205,251,42,189,173,104,182,224,240,187,184,90,150,165,151,54,237,248,21,195,252,26,86,186,43,130,85,173,165,88,77,47,61,60,251,197,177,40,114,201,153,72,161,39,61,136,217,22,39,227,180,112,20,184,0,22,255,248,87,132,120,113,8,6,226,212,166,57,112,185,75,15,83,79,196,106,136,205,5,59,250,63,35,80,140,176,236,196,248,3,221,98,250,104,32,99,152,165,109,139,192,40,49,68,14,50,89,102,202,12,64,120,114,49,227,205,144,18,43,180,65,47,167,89,67,145,180,44,241,173,23,232,86,141,103,210,72,240,225,180,133,221,238,4,125,161,121,44,204,5,162,64,34,84,167,152,247,154,190,162,116,71,83,180,181,174,3,151,227,180,162,28,198,133,1,195,199,54,251,220,4,182,126,209,15,24,207,187,240,50,11,120,250,158,87,125,246,74,64,175,190,21,150,255,202,170,125,38,228,16,24,166,186,7,113,0,133,182,112,138,188,2,24,120,236,10,76,154,89,48,23,228,159,219,144,219,209,76,59,25,100,202,46,203,178,117,252,97,240,97,42,143,205,52,199,220,7,0,109,217,139,126,170,178,227,213,192,16,171,133,173,237,240,186,6,14,155,94,157,194,99,123,174,181,74,164,126,56,178,0,172,77,163,74,172,53,5,161,130,161,162,149,232,150,69,170,172,59,70,142,112,87,58,16,192,67,8,250,29,140,221,17,117,167,133,43,180,141,157,214,18,131,114,105,147,206,25,138,207,188,30,41,9,97,113,247,123,251,56,165,182,239,95,79,152,45,113,160,213,230,249,227,167,149,52,172,156,182,242,134,61,19,90,144,248,100,252,168,76,213,246,126,123,175,8,114,218,41,247,90,229,94,238,86,73,43,35,42,116,168,217,75,167,166,122,230,82,130,255,164,51,9,86,79,111,49,152,198,132,96,62,12,131,23,66,96,51,213,29,13,144,20,26,228,66,41,228,68,254,126,173,192,51,62,41,184,136,182,93,102,144,250,65,236,200,19,121,182,87,125,72,97,132,164,29,130,211,26,115,217,177,199,35,54,132,98,87,138,188,229,34,130,240,81,186,231,130,41,17,74,64,27,41,169,251,229,192,38,247,81,85,224,10,181,80,164,164,112,73,150,53,119,166,144,157,52,98,187,48,28,64,77,33,237,100,1,46,123,40,27,232,128,105,190,126,27,132,205,16,107,184,30,187,240,29,128,81,177,9,175,37,159,188,53,109,59,15,33,102,39,182,31,73,163,176,14,150,178,216,231,41,152,253,100,240,46,106,181,137,111,240,101,204,74,57,134,179,49,230,134,124,152,70,64,166,43,65,203,80,53,157,166,39,138,142,243,74,145,217,9,194,93,128,67,93,129,161,161,254,211,189,239,205,32,171,253,118,141,204,240,183,222,146,198,220,187,58,201,238,218,179,206,89,183,40,198,33,53,38,40,144,216,247,161,189,216,173,9,22,72,148,174,45,3,127,35,125,111,140,15,207,119,246,38,244,195,69,85,106,121,28,241,125,124,103,116,108,152,84,133,165,68,92,5,189,160,223,125,159,69,84,91,214,24,52,36,207,180,152,8,156,70,209,194,220,165,138,212,192,246,132,124,186,64,218,179,23,131,210,117,7,15,197,250,249,187,104,74,19,195,232,168,66,171,125,133,252,89,123,236,67,152,150,187,82,161,241,29,160,206,15,254,101,201,34,79,182,6,88,237,204,67,3,24,199,64,58,22,71,118,31,80,235,148,111,111,74,248,229,15,0,160,215,0,121,227,15,243,58,122,251,203,236,223,102,217,235,105,113,239,209,206,227,198,166,116,250,85,48,71,14,78,216,2,167,129,129,240,167,56,89,118,161,125,49,228,56,221,13,219,207,36,68,253,27,45,219,117,151,229,111,247,206,97,173,132,8,74,182,16,125,54,238,31,46,244,50,250,3,216,182,42,120,67,61,39,106,101,23,248,21,80,151,115,41,105,95,47,32,90,53,3,164,31,12,113,105,26,135,101,186,43,191,173,143,177,4,75,109,96,7,121,5,231,218,250,45,96,254,193,146,225,251,238,21,240,27,207,43,187,7,61,254,195,234,210,152,46,241,186,188,216,234,82,179,109,61,190,139,211,58,36,74,149,107,249,150,196,71,226,167,232,40,42,19,152,17,194,16,94,5,11,57,37,43,99,98,248,81,211,60,69,192,80,94,225,241,197,53,76,100,1,166,253,132,17,3,72,232,72,214,60,18,151,159,15,167,78,27,76,142,22,21,129,121,10,185,35,246,49,165,218,73,182,236,65,1,175,236,230,71,209,189,163,164,179,194,209,86,6,180,219,147,94,15,212,246,83,21,183,250,40,230,78,222,159,74,94,13,20,247,51,90,218,253,125,50,81,72,93,1,200,50,199,223,192,197,223,38,208,98,122,118,7,82,178,154,193,50,199,199,7,184,231,120,39,2,232,41,182,32,75,56,236,176,5,0,113,190,13,109,1,175,212,249,89,21,130,204,162,228,119,244,190,87,252,151,13,40,209,103,93,95,199,103,141,133,122,94,189,161,222,26,229,214,114,137,110,97,84,81,251,213,80,122,215,144,113,154,105,12,130,191,24,0,226,159,46,86,119,142,104,231,72,118,224,91,195,94,179,212,168,32,243,2,25,219,4,197,34,167,252,198,18,155,87,88,62,165,118,253,176,96,152,186,128,214,140,226,59,11,113,104,102,96,136,126,9,13,140,165,46,116,134,52,249,105,131,168,226,83,93,216,194,247,236,251,159,42,118,243,93,85,175,120,106,134,75,146,217,187,183,49,138,190,5,189,3,203,106,166,110,104,108,70,111,165,41,203,34,212,254,32,10,2,238,30,243,126,47,119,175,63,107,73,75,131,105,17,54,253,158,128,179,196,198,64,151,178,55,47,159,191,106,78,234,208,198,108,42,131,2,33,44,121,43,48,137,107,252,205,15,84,242,200,169,148,239,199,117,248,6,151,51,83,45,149,57,75,160,202,27,122,235,14,50,90,135,90,94,140,171,241,123,236,90,200,243,190,6,111,165,246,139,34,141,151,172,38,34,66,201,218,83,110,52,12,146,6,26,248,102,120,174,193,25,147,171,152,87,174,79,55,208,166,73,111,90,214,25,117,239,102,226,213,182,128,93,49,129,174,3,2,180,9,250,166,8,32,141,187,26,55,157,229,144,64,195,91,154,133,56,176,6,198,60,119,115,232,70,213,143,59,250,97,136,50,75,125,198,19,151,141,168,48,163,47,67,211,114,119,103,69,9,119,244,236,196,164,248,228,69,215,205,245,16,57,177,244,43,224,109,172,45,14,5,161,195,63,81,38,117,19,125,248,179,103,199,168,84,151,192,55,216,72,96,43,117,199,103,51,202,42,177,40,169,84,157,153,173,244,141,108,142,38,188,53,35,151,221,147,12,148,111,151,129,212,37,253,142,191,152,21,241,153,150,30,71,95,49,124,83,150,47,109,169,199,96,70,141,167,74,79,11,152,159,93,215,159,185,141,249,140,114,217,75,87,133,177,114,114,27,32,86,10,246,20,157,127,160,164,227,79,194,177,107,49,142,179,84,144,135,178,81,30,7,228,120,116,11,103,210,83,15,94,77,40,116,144,27,125,81,192,231,217,112,4,184,78,6,144,65,184,221,84,114,52,150,241,217,130,114,219,252,15,34,244,209,76,178,193,231,229,38,137,147,0,147,242,150,26,33,32,28,132,60,63,134,221,9,214,135,97,120,217,109,78,130,199,253,153,215,234,19,186,201,199,169,20,132,151,74,179,54,65,25,171,126,126,88,23,247,222,39,52,65,85,45,245,229,214,38,98,14,0,10,216,42,17,230,34,91,84,144,209,31,186,211,140,175,188,80,202,99,174,124,88,40,32,214,235,133,253,145,179,186,102,42,135,61,67,235,163,133,41,35,25,168,87,141,24,186,210,233,150,19,220,120,81,123,169,245,18,197,27,207,176,15,197,115,139,69,152,82,211,148,77,184,232,173,29,253,46,123,173,245,217,54,231,135,218,236,101,196,45,109,136,189,206,68,215,214,77,251,43,39,224,144,62,135,50,114,247,67,110,247,38,143,220,5,1,173,142,88,7,149,152,225,194,10,114,152,121,105,239,242,249,117,29,172,2,39,98,218,33,31,69,93,11,210,222,132,40,251,162,173,144,13,165,165,242,181,202,215,89,196,228,253,39,70,73,153,144,63,184,211,2,204,107,51,166,197,173,14,15,96,66,141,11,12,244,148,50,16,214,9,8,52,6,165,105,91,184,10,10,62,135,250,200,159,69,227,229,86,98,229,73,27,200,217,108,233,211,81,90,93,45,50,50,149,19,35,23,116,202,113,21,211,33,217,140,128,86,228,185,130,140,104,87,180,174,131,213,254,48,90,67,239,159,204,139,229,42,236,142,82,151,187,165,11,12,150,53,56,10,76,97,213,117,217,51,242,133,135,229,78,117,95,26,31,69,32,138,147,70,226,136,42,0,8,199,224,233,35,206,48,207,61,99,52,101,204,118,143,245,236,120,33,226,57,223,53,32,255,6,236,127,223,89,137,99,84,204,80,106,20,237,64,149,193,65,7,41,202,120,56,115,112,137,35,254,243,28,47,4,229,33,115,177,48,219,231,48,63,139,95,214,209,6,170,197,116,222,104,88,254,141,16,48,222,226,9,47,121,65,188,142,38,129,229,60,122,25,131,229,78,249,211,139,93,199,181,248,231,247,38,161,131,223,146,216,88,123,189,77,186,220,2,185,53,173,226,101,153,213,103,171,140,207,44,51,120,168,36,182,213,176,87,166,170,61,250,49,139,249,215,135,168,170,59,95,118,142,249,166,177,121,94,175,159,219,228,219,117,28,222,43,180,225,108,140,7,25,5,94,45,171,5,65,137,255,40,123,190,89,181,94,76,172,91,161,197,240,85,79,172,28,47,57,205,233,102,137,143,28,155,20,20,157,41,148,175,43,167,5,82,171,148,109,247,237,236,176,176,124,1,158,189,93,168,51,115,231,208,228,55,164,123,212,27,25,190,38,1,120,25,153,91,236,95,116,67,210,173,224,156,220,91,207,120,91,114,212,191,71,198,205,146,136,65,91,33,204,192,154,155,243,71,11,55,239,100,89,204,247,199,59,120,22,68,109,137,194,203,81,61,247,11,226,242,210,155,195,209,1,193,108,163,178,20,22,170,30,148,214,80,229,153,91,103,246,237,10,245,110,211,150,205,98,239,92,94,71,206,91,253,204,90,157,216,152,35,148,167,8,201,167,24,239,191,158,102,23,131,159,64,99,81,159,58,193,185,68,1,28,24,38,198,132,80,191,19,122,235,99,129,100,49,253,29,52,194,32,108,106,166,243,179,53,189,96,59,73,241,61,32,223,84,218,118,59,32,64,9,98,239,207,219,101,38,106,54,148,148,25,5,50,107,106,152,242,117,192,102,56,184,19,232,133,157,243,182,52,144,217,94,101,153,221,88,157,52,224,159,93,159,71,2,115,200,230,116,202,177,236,75,20,176,16,39,147,24,150,195,21,251,77,57,185,113,216,168,48,127,164,56,104,92,23,85,141,159,93,53,192,103,163,130,24,85,85,160,61,246,23,185,196,18,158,228,129,148,126,206,52,198,191,182,12,98,112,31,56,160,62,208,196,234,1,56,249,23,61,115,25,164,254,151,45,11,124,107,53,151,131,221,52,249,185,90,5,4,129,177,134,168,239,37,50,111,225,178,53,251,9,5,87,32,111,75,239,38,160,33,50,128,211,5,250,31,61,177,31,115,182,221,118,33,225,75,165,5,43,89,152,62,217,185,246,122,194,98,47,193,42,74,46,144,111,16,231,76,88,151,7,93,68,144,237,82,117,206,167,239,6,137,55,125,14,88,92,201,143,148,62,216,55,224,150,178,38,77,42,167,163,233,124,131,220,55,50,219,117,225,244,220,233,124,27,133,246,213,86,54,152,29,92,98,226,98,54,110,144,186,41,161,225,72,199,30,105,121,160,56,141,23,100,40,88,208,169,32,196,122,95,231,57,244,199,120,13,232,165,250,170,24,34,231,23,205,33,18,214,128,56,165,14,48,104,223,133,183,73,58,100,111,112,115,239,70,81,81,38,94,88,232,164,212,242,0,59,114,36,133,89,252,41,204,37,193,144,244,255,242,124,20,131,112,126,131,187,205,71,229,86,90,197,199,245,45,120,190,56,223,164,63,177,75,188,238,180,176,137,182,95,221,29,158,104,4,224,38,183,94,172,67,44,62,168,237,218,85,159,58,25,168,173,108,204,228,81,18,145,207,176,19,10,212,78,133,108,169,178,117,11,19,155,152,200,117,243,99,143,126,93,75,167,4,103,249,245,27,30,184,78,162,35,174,200,4,59,119,138,195,58,130,59,179,147,48,207,134,201,207,31,90,145,168,212,195,79,220,16,253,80,24,42,159,61,178,241,81,140,246,198,225,166,94,74,63,254,3,218,93,2,74,194,239,192,68,55,75,132,51,79,200,162,72,133,34,87,86,7,157,235,37,94,78,191,150,81,213,162,147,20,232,243,173,36,1,244,91,3,192,10,224,194,229,74,147,19,192,165,168,153,5,127,230,113,185,206,127,146,80,114,246,179,16,31,90,0,242,254,82,189,36,246,211,7,118,168,33,154,220,184,107,101,40,150,196,194,242,253,216,72,132,210,147,230,224,198,34,75,25,74,233,205,159,168,6,197,50,217,127,251,94,27,0,89,55,171,138,10,197,251,46,127,84,139,97,212,131,44,89,5,181,154,11,223,2,106,249,29,222,72,44,89,57,56,8,138,102,140,86,159,219,77,239,32,203,126,142,214,192,72,16,119,161,71,155,250,58,115,189,112,51,213,249,25,85,78,170,171,102,164,103,133,109,37,229,130,167,116,64,21,234,76,246,89,206,141,235,89,223,141,56,47,168,166,97,190,26,197,70,97,133,200,148,53,45,183,39,129,38,122,174,116,58,75,115,221,204,101,52,24,94,177,14,237,2,172,234,210,8,208,25,77,235,113,24,108,216,242,184,180,255,173,101,240,51,246,200,240,13,156,209,93,60,66,170,252,82,230,13,215,146,117,255,210,7,34,122,10,106,156,176,21,68,222,248,33,83,152,206,191,60,18,158,149,114,74,41,60,203,244,210,249,189,212,25,25,75,131,95,76,207,254,188,23,124,249,162,255,170,137,0,81,97,181,221,127,2,120,240,234,80,28,115,105,158,136,89,77,135,103,255,251,8,186,242,63,176,164,122,8,11,128,19,58,243,8,212,252,204,84,170,108,158,179,247,0,254,32,87,139,213,136,45,180,92,145,67,92,246,247,205,97,103,87,101,163,137,0,61,23,230,147,218,153,102,235,104,17,24,246,70,190,79,179,238,178,41,56,128,115,241,148,114,229,173,144,63,54,151,123,191,45,145,222,89,230,29,59,34,163,123,120,56,34,137,149,161,32,221,255,87,39,50,57,112,84,159,209,51,170,143,167,190,117,145,202,12,127,248,132,142,52,118,154,247,22,242,179,161,240,146,155,7,176,79,18,1,228,242,227,81,34,121,92,236,105,176,207,233,51,86,159,119,70,173,14,42,103,31,241,149,157,98,49,61,96,106,94,142,12,146,88,63,16,173,84,14,216,170,188,7,119,188,94,156,24,78,218,117,39,252,216,201,136,241,118,24,231,164,15,9,211,193,68,14,9,140,214,99,95,235,172,219,136,83,12,95,75,88,48,152,236,153,95,137,236,38,125,35,176,220,87,52,101,106,40,172,224,140,105,118,201,227,143,43,59,162,152,247,197,72,70,232,183,21,160,2,64,169,41,69,166,102,52,189,217,130,19,196,230,34,133,35,31,17,193,45,252,112,79,79,223,99,168,154,14,19,74,179,41,246,27,199,128,101,54,80,252,173,165,241,80,26,204,142,255,57,94,25,56,246,22,133,229,144,110,212,118,251,36,49,81,254,183,116,222,99,70,181,22,74,96,199,161,124,176,7,199,9,56,128,64,200,185,222,37,225,144,156,152,22,99,76,208,43,99,207,169,146,220,182,136,30,96,166,118,49,125,40,132,106,49,212,158,91,55,84,208,213,75,63,190,113,71,83,98,109,21,176,11,204,253,157,79,106,111,232,239,253,187,98,141,32,52,39,209,183,100,176,183,32,232,137,209,189,13,67,230,44,99,233,235,31,211,62,149,120,185,114,79,123,8,153,151,112,255,65,154,228,16,226,177,21,18,10,146,172,134,181,123,4,253,122,188,229,98,89,112,147,19,145,108,246,176,210,201,128,231,96,230,39,140,7,175,246,144,253,114,34,223,14,48,134,160,78,112,135,138,197,142,208,213,221,156,197,198,131,42,169,203,191,140,36,205,131,59,11,239,147,205,235,193,132,59,199,198,42,204,244,120,24,172,221,253,85,141,118,110,76,153,91,146,222,142,200,251,52,172,145,250,47,123,86,49,253,220,27,77,170,51,36,179,148,26,32,251,162,197,246,163,248,65,123,233,68,194,166,153,206,118,238,22,134,49,13,218,176,11,183,124,197,148,169,251,224,80,11,209,166,233,229,19,220,114,244,144,246,17,131,119,108,78,6,26,238,121,82,13,57,179,139,149,164,255,235,181,20,240,76,155,71,61,89,192,100,16,244,93,71,199,139,70,203,107,44,233,154,66,40,255,1,15,20,206,89,244,23,68,123,164,177,175,187,170,150,195,150,44,96,99,142,169,220,220,197,235,124,72,198,60,112,180,196,35,190,154,107,29,177,10,243,111,210,61,157,156,223,255,101,5,210,27,224,15,23,138,119,65,201,139,134,84,70,122,22,204,153,5,193,108,54,149,173,173,37,200,81,229,93,72,7,45,14,51,177,85,166,96,189,55,43,70,88,172,251,17,221,163,81,62,196,216,14,31,82,46,38,65,125,42,32,4,9,145,100,31,102,106,231,86,31,167,246,39,11,28,118,34,92,179,80,65,191,115,43,247,211,118,115,124,156,122,145,222,177,73,161,7,117,51,20,29,178,100,26,127,202,208,177,209,121,101,140,194,20,229,139,123,55,186,209,31,33,39,115,64,97,128,152,60,147,70,35,97,4,156,87,181,58,244,132,109,115,229,91,215,10,28,25,21,57,163,234,21,101,81,18,220,78,130,105,85,41,164,78,228,156,201,182,234,93,221,241,194,212,66,84,4,11,81,116,94,234,37,200,8,214,228,253,58,205,250,62,168,189,1,46,223,0,158,154,29,127,247,188,25,193,165,228,117,234,121,149,167,254,11,3,15,12,91,42,46,11,240,230,134,120,108,46,58,63,23,230,140,113,173,206,94,55,63,20,187,32,255,142,32,192,135,161,231,95,115,204,50,125,129,245,15,153,89,124,35,87,200,91,78,68,126,100,158,103,224,232,192,132,174,34,19,19,48,139,182,247,255,70,88,227,139,253,31,10,222,62,188,140,85,169,143,143,14,29,108,159,46,98,211,30,129,63,149,77,230,246,61,181,103,153,124,242,214,63,70,78,193,78,208,159,94,20,59,30,81,88,112,124,123,183,101,239,217,86,232,137,59,250,5,110,107,71,27,31,15,33,62,200,161,218,153,82,134,5,7,141,180,7,152,169,23,182,33,150,252,223,90,209,54,177,15,50,19,8,253,37,226,84,143,33,164,230,38,215,102,42,156,198,36,35,149,175,75,79,102,252,69,215,7,165,103,252,189,221,18,204,32,86,110,22,47,74,38,247,11,126,5,145,242,247,20,9,190,177,121,79,16,110,73,41,45,141,3,247,35,3,252,191,45,7,156,127,115,198,74,194,5,25,124,110,61,109,115,151,84,72,182,140,170,23,217,123,133,98,143,18,53,128,55,78,61,89,152,214,253,63,133,196,183,215,107,107,158,245,129,15,153,169,246,158,65,172,8,47,226,30,126,10,64,163,175,108,218,130,19,89,235,34,206,150,176,199,6,140,234,201,165,130,107,208,64,112,36,44,115,250,199,236,204,60,127,43,124,225,163,49,76,103,210,254,126,180,82,44,230,68,93,12,246,201,186,72,190,172,76,128,42,173,0,221,120,14,150,19,197,121,163,71,111,214,183,143,24,187,70,13,255,228,250,134,173,209,183,166,208,21,225,94,109,145,98,70,255,76,151,190,150,183,152,248,238,224,187,111,4,2,111,236,73,135,133,67,34,193,94,52,159,42,187,59,38,75,152,72,134,112,236,191,233,150,43,156,14,167,70,226,7,114,200,31,140,164,33,84,232,169,15,96,172,175,192,57,229,71,227,101,139,17,90,45,154,32,255,204,159,141,200,159,147,45,152,135,128,51,11,78,181,154,83,92,144,157,134,244,234,140,201,95,218,104,165,146,35,28,223,139,111,128,149,30,162,119,191,217,136,196,219,138,212,22,168,182,19,118,34,168,68,234,104,231,59,166,128,52,254,212,215,218,117,66,31,249,88,61,78,33,130,242,94,66,17,169,102,100,130,251,1,125,169,71,110,165,239,246,162,251,220,185,184,20,76,133,171,122,57,219,218,181,169,220,38,166,27,206,53,166,180,135,172,64,7,187,131,182,110,67,34,191,25,145,197,184,217,30,140,72,15,212,194,123,34,239,194,64,110,117,35,199,82,17,157,252,230,226,228,44,151,158,81,101,191,59,18,175,143,139,235,12,185,50,15,106,29,143,82,247,211,52,208,35,153,64,11,50,37,13,38,232,128,45,104,62,240,201,122,137,83,140,250,178,64,142,202,168,54,119,221,215,71,166,35,108,71,223,239,99,153,12,8,134,64,200,182,235,107,96,111,231,153,200,254,189,247,49,93,127,4,200,77,43,160,120,224,252,243,224,46,190,166,143,82,46,207,86,235,116,203,190,88,18,55,121,70,227,215,107,69,58,245,221,133,33,73,230,34,36,254,49,127,129,180,253,175,209,180,54,94,124,96,104,97,243,225,38,248,166,230,189,233,78,38,61,122,43,51,76,9,219,127,1,239,79,151,48,213,26,208,118,80,108,178,180,167,38,224,5,87,106,12,73,252,109,195,190,244,1,237,106,212,236,116,74,192,255,121,219,152,67,18,77,38,21,51,27,121,200,196,0,84,219,179,46,124,54,85,12,179,49,241,46,197,14,33,28,79,227,246,94,112,66,187,209,230,116,161,40,15,78,57,156,110,138,178,73,41,255,178,62,43,236,180,171,248,21,243,240,13,110,71,67,79,176,57,76,207,194,20,219,223,36,60,83,50,200,87,245,137,235,132,89,144,67,4,174,55,221,14,212,138,175,187,209,186,54,80,178,238,243,36,9,199,108,128,111,120,61,208,105,53,44,233,236,78,63,226,71,197,238,242,101,100,227,70,160,209,41,198,56,65,115,138,237,132,126,95,23,46,122,98,177,164,159,251,98,212,145,111,203,95,36,21,53,163,88,57,51,139,255,60,181,38,187,107,75,128,165,215,232,130,56,103,173,192,192,119,72,104,142,246,79,232,200,17,207,225,61,55,106,74,61,126,180,229,233,187,223,190,82,11,232,15,84,52,13,98,154,199,134,191,227,132,219,235,17,230,249,92,249,34,165,54,132,101,234,209,220,66,6,69,181,50,132,160,155,246,171,5,167,56,49,27,175,90,222,36,13,217,116,128,9,151,3,203,43,43,40,205,132,14,248,28,88,180,107,146,95,19,175,0,109,41,170,148,148,54,179,0,71,101,59,99,221,143,205,42,59,156,112,136,31,59,18,231,136,191,41,46,122,77,101,152,172,123,108,116,111,53,229,4,163,218,156,39,171,198,100,223,236,90,205,126,143,72,67,138,159,241,118,154,239,154,219,34,182,123,33,163,113,46,15,249,238,36,50,215,132,241,226,207,196,181,96,162,212,88,224,190,81,179,12,136,146,122,238,83,129,26,72,105,125,20,146,253,67,112,232,12,188,96,52,161,160,121,241,50,77,49,218,20,78,169,246,196,95,213,12,11,243,170,71,1,244,78,233,115,143,34,201,250,23,100,9,97,17,4,211,193,128,42,106,170,138,9,75,28,208,247,157,32,4,210,106,87,15,97,167,209,22,160,123,52,183,148,194,21,14,53,212,119,43,76,147,154,56,43,175,79,109,103,68,93,115,95,230,242,89,230,162,136,47,37,79,109,220,24,217,83,40,241,45,113,250,138,133,115,120,72,115,222,65,36,226,44,1,172,128,192,152,113,44,162,139,24,194,114,139,90,162,31,228,198,129,96,97,224,87,232,183,43,193,104,251,129,67,148,240,227,100,4,27,202,89,241,226,221,189,142,102,74,1,234,197,88,247,95,217,142,161,58,118,124,174,252,162,242,248,126,19,199,138,191,202,209,59,204,127,100,65,187,50,108,197,107,107,205,55,228,48,246,168,68,28,74,186,102,54,116,29,188,57,221,206,122,202,240,151,15,23,162,146,91,12,88,51,69,3,110,205,52,5,186,49,46,171,126,221,23,30,236,45,162,17,198,211,238,177,147,106,5,203,206,78,143,1,167,153,96,15,225,28,219,223,209,68,221,218,102,32,19,138,90,130,254,63,73,240,165,99,150,83,198,65,210,22,92,216,204,186,182,213,249,35,2,80,190,138,101,47,225,210,232,29,85,90,174,228,82,244,173,189,193,47,20,238,93,189,172,27,25,87,244,243,224,87,201,186,153,42,69,160,195,77,180,136,128,231,197,161,163,94,0,191,87,57,125,254,155,170,223,110,165,95,181,188,82,153,240,68,118,58,137,253,184,248,35,170,207,20,197,246,93,21,36,48,195,147,75,92,94,166,34,77,198,225,189,122,91,111,136,32,138,146,132,33,113,35,32,184,97,10,255,132,98,61,203,100,65,30,160,150,30,85,22,8,32,101,187,142,240,176,3,67,219,207,113,202,242,213,177,61,155,141,225,69,7,10,3,184,65,132,69,241,149,214,97,91,168,150,187,136,18,190,15,66,134,232,239,202,169,247,10,160,246,157,238,77,41,185,221,165,157,108,94,145,231,229,169,101,1,167,15,161,20,158,211,139,204,107,228,206,211,185,65,246,158,167,12,107,190,45,182,28,192,44,106,148,62,159,222,82,10,227,237,251,3,151,152,139,76,162,183,169,202,107,181,200,129,195,124,71,208,135,234,26,203,154,53,208,137,99,150,100,142,114,50,153,183,126,133,1,253,9,202,235,65,46,106,126,8,5,105,93,53,17,35,209,62,117,114,152,57,29,66,71,127,2,130,103,158,7,17,86,195,64,229,219,75,195,212,33,209,50,154,59,27,177,135,24,163,107,219,137,197,220,7,153,96,131,0,65,187,83,25,18,15,100,245,27,6,174,119,25,182,124,115,158,7,84,182,105,34,75,231,222,190,48,233,221,49,119,79,153,174,200,28,223,87,37,72,254,237,189,199,23,239,255,69,27,152,251,104,233,142,231,80,48,149,197,234,170,200,149,73,120,9,20,212,128,69,99,144,23,22,83,89,207,47,19,17,198,156,214,226,55,130,85,146,54,5,58,224,214,6,27,36,31,164,126,182,225,53,4,52,100,11,28,220,125,41,101,102,215,188,97,6,55,113,252,140,78,81,115,58,203,129,115,132,109,206,21,68,78,20,128,95,62,34,72,211,75,41,78,234,223,115,175,57,229,107,227,179,9,162,15,86,211,207,126,44,120,162,65,99,15,187,57,91,18,41,138,119,15,37,90,138,187,40,13,121,164,30,26,160,7,116,143,9,149,10,228,215,85,75,134,113,241,72,248,12,116,160,177,187,166,188,208,252,178,182,169,220,121,139,203,135,116,198,224,193,215,214,189,110,168,68,129,130,192,8,226,15,122,181,16,37,227,17,156,38,246,249,4,89,193,12,237,32,109,66,52,139,50,235,10,231,210,19,204,191,161,192,238,27,142,203,62,146,194,119,135,132,70,245,214,127,209,179,254,19,43,72,110,124,118,71,34,142,134,163,182,130,140,131,160,56,194,13,10,6,8,136,131,171,206,237,108,163,127,8,17,208,116,17,165,125,236,166,45,180,115,123,110,117,255,84,33,201,176,66,60,220,2,92,128,59,50,147,27,232,7,251,48,118,128,215,225,182,113,163,1,165,184,212,132,246,28,57,13,84,140,97,222,230,172,120,254,160,216,70,239,215,0,111,160,68,51,0,31,109,79,49,38,221,94,95,37,226,200,239,75,160,227,1,122,27,49,244,122,133,67,125,60,12,216,60,89,219,92,146,252,169,205,31,71,112,119,174,142,76,205,10,173,28,31,26,119,222,159,151,151,214,150,124,197,51,174,17,3,58,240,120,130,175,51,87,155,106,76,197,143,86,226,95,45,72,196,34,230,99,248,121,236,163,207,67,132,152,165,42,252,107,111,171,10,114,221,71,94,190,87,197,251,236,116,86,60,82,253,64,166,236,178,150,126,252,230,179,186,45,52,123,29,16,175,237,157,13,213,215,69,153,217,233,51,38,227,186,80,200,188,65,110,196,78,3,202,66,175,161,253,111,249,120,23,44,176,170,211,138,243,128,128,115,108,85,27,23,107,91,1,212,31,154,136,228,166,30,96,59,92,34,162,61,242,225,232,47,195,154,45,144,74,125,246,69,128,166,229,187,39,196,152,5,66,133,189,18,245,235,31,214,153,14,205,11,130,1,238,167,83,107,14,41,235,8,139,62,37,74,87,110,189,142,226,150,1,219,52,58,115,150,62,55,66,239,30,11,157,138,57,159,200,148,184,237,250,169,248,88,159,137,188,98,30,50,189,59,15,225,149,129,184,102,146,114,254,181,178,143,54,171,186,63,219,29,83,52,76,222,208,189,242,11,81,188,87,249,54,213,162,246,147,7,72,54,22,48,119,146,108,131,16,194,137,175,45,132,109,33,243,243,40,190,135,54,116,177,29,228,193,151,91,207,114,183,37,198,58,44,53,196,42,118,27,144,95,155,137,80,255,233,76,228,204,81,135,24,99,82,230,130,134,134,90,185,64,21,78,113,200,124,44,66,8,202,250,219,158,245,90,117,100,130,99,79,193,113,76,66,140,147,91,76,194,35,42,183,235,58,162,251,48,190,103,86,96,173,72,202,179,222,118,203,182,225,42,46,211,245,250,204,238,192,46,2,210,178,141,212,84,160,233,228,60,100,58,151,244,252,138,108,189,119,187,104,222,9,36,11,182,33,204,41,164,233,176,152,233,86,233,50,206,99,64,128,110,66,233,201,123,179,225,189,88,55,210,152,178,238,149,204,213,200,212,190,228,170,205,255,165,46,209,51,91,74,229,36,181,120,52,6,82,169,229,225,218,231,110,222,218,6,179,193,106,30,34,243,244,157,149,112,198,254,119,89,250,217,97,62,28,209,188,203,80,211,129,242,222,66,129,254,133,112,29,113,174,62,6,239,237,224,23,116,214,189,215,75,239,171,17,204,68,178,19,31,37,201,108,153,71,126,166,217,28,201,87,186,193,62,200,110,44,41,74,172,66,60,174,120,134,18,85,137,113,240,138,170,198,225,97,115,26,202,243,51,96,31,18,185,179,52,52,98,63,170,11,216,247,18,9,35,203,107,220,12,6,21,178,236,232,102,112,57,211,73,9,28,24,100,146,157,25,199,182,169,71,71,6,60,175,82,210,8,190,110,18,136,70,15,43,13,60,52,12,43,123,111,248,2,36,45,160,215,73,52,54,36,80,105,210,238,113,115,116,84,251,91,72,109,192,195,188,108,51,89,2,189,86,142,28,210,69,246,138,253,85,224,49,223,6,47,125,40,72,173,56,214,70,132,134,51,244,168,101,112,151,126,77,102,143,239,4,13,116,106,10,103,119,126,65,6,31,18,107,68,76,241,127,130,133,186,61,250,68,253,189,150,134,117,83,51,83,25,187,118,78,134,35,123,184,148,245,53,68,14,88,131,0,68,159,141,48,76,196,130,198,34,56,19,203,64,75,87,26,133,28,73,19,242,167,183,2,251,172,114,9,7,155,151,79,86,68,141,54,101,212,74,210,65,219,237,175,83,252,71,245,207,108,46,196,105,180,46,85,217,5,128,221,226,157,62,176,224,25,140,26,228,142,51,187,96,116,42,92,18,197,211,133,4,0,207,161,141,187,60,8,215,220,174,187,41,153,27,83,242,133,205,30,135,7,207,178,168,111,3,85,173,149,137,68,187,204,184,237,209,59,41,154,36,35,7,212,199,183,241,25,178,86,195,41,137,201,81,164,246,218,251,180,218,161,189,193,147,17,147,15,78,69,23,170,86,93,28,58,170,81,208,143,20,240,63,182,158,203,197,94,135,254,11,135,124,183,89,193,71,88,184,98,208,164,134,197,140,75,234,159,83,20,177,109,123,195,118,229,245,116,207,220,6,11,187,253,37,198,220,195,29,176,38,46,67,200,232,90,245,23,105,165,133,57,29,208,185,232,69,180,3,5,19,111,91,226,98,197,90,102,20,243,203,137,88,156,217,18,24,141,253,17,194,150,75,120,212,232,5,187,191,80,176,71,27,94,71,149,230,108,103,17,129,248,166,186,196,171,152,249,136,146,130,38,204,223,106,175,46,105,241,113,125,212,159,243,233,110,229,177,187,141,186,157,99,212,232,218,25,58,4,212,122,110,11,236,187,184,12,168,127,135,212,37,81,184,79,102,171,143,151,189,158,113,56,80,94,110,58,223,118,37,73,53,158,134,151,251,250,216,143,88,233,8,206,211,238,115,195,53,186,238,140,128,150,50,225,14,236,49,195,224,75,85,229,24,20,244,72,136,144,15,96,152,6,156,158,133,144,200,229,50,186,234,205,77,101,31,5,147,136,55,31,158,100,141,179,213,225,15,161,176,225,156,40,169,60,57,227,45,170,44,97,107,83,178,31,102,192,84,212,43,159,32,188,252,47,248,53,6,68,8,126,187,27,46,133,214,4,199,153,29,177,123,35,170,100,66,253,178,46,37,206,97,62,17,208,98,178,195,223,64,76,251,94,132,241,102,36,130,182,53,98,94,253,122,211,197,204,144,195,101,203,40,158,215,192,102,44,87,233,61,81,147,158,79,117,222,27,26,219,168,15,59,142,65,113,172,49,253,190,191,188,12,59,244,226,238,7,59,116,34,120,56,20,118,83,59,78,142,79,43,150,41,207,228,35,234,182,14,86,50,120,254,31,74,82,5,29,39,173,104,87,10,249,237,158,29,211,250,239,50,64,90,200,107,209,100,26,135,182,38,139,177,27,64,6,87,21,235,204,230,235,222,248,48,156,212,204,138,22,36,123,3,40,93,25,200,55,162,51,116,3,140,58,246,81,78,59,89,103,138,23,220,89,171,48,48,203,181,80,163,171,109,173,17,34,188,238,42,205,32,106,18,122,80,8,247,127,26,32,148,141,138,226,57,27,129,234,74,40,235,202,6,106,127,1,11,117,117,236,240,123,227,139,185,241,205,42,57,186,237,83,21,90,3,25,88,42,109,224,140,238,11,177,108,46,111,28,229,139,95,217,72,101,173,235,131,28,2,85,51,19,52,105,218,235,176,84,57,140,165,80,238,93,92,6,47,138,188,132,100,36,219,223,236,201,112,201,190,0,20,146,68,95,16,147,1,52,108,54,185,188,154,104,247,173,127,160,214,230,207,56,112,98,105,62,42,66,97,101,47,220,193,114,23,202,61,21,118,64,16,191,112,119,123,20,117,173,202,70,39,239,112,202,66,142,163,211,106,89,2,97,150,55,78,226,111,190,170,144,53,195,72,96,89,229,178,153,130,164,161,86,154,154,21,95,120,12,31,122,50,142,245,189,124,17,218,35,201,75,20,203,234,97,11,70,151,3,185,169,71,243,91,56,248,117,103,8,162,90,14,193,33,124,194,169,48,150,40,80,127,37,151,74,195,221,99,145,74,172,228,150,120,147,204,160,67,110,187,30,236,197,101,7,127,128,115,7,243,235,20,66,101,40,114,136,254,206,220,67,96,231,89,65,202,234,82,8,131,187,238,220,213,142,223,77,25,167,69,68,87,110,101,200,142,51,26,234,143,164,214,134,215,222,141,23,42,75,147,88,211,199,154,201,24,72,202,13,136,234,25,52,120,254,136,185,193,163,187,133,84,93,81,133,177,73,126,136,46,251,136,144,180,33,34,18,230,128,47,79,79,106,150,8,58,160,248,106,132,183,215,17,146,173,177,243,32,65,1,175,14,45,235,55,127,69,29,175,177,184,199,168,231,173,143,212,218,44,28,243,157,87,243,247,193,142,155,49,191,221,140,235,246,53,125,204,139,60,232,18,220,63,106,61,252,172,154,140,47,208,189,55,163,20,44,108,250,50,252,255,204,45,52,2,76,66,64,241,107,21,163,134,187,242,247,136,203,1,7,118,226,244,67,198,15,238,194,74,9,230,186,185,49,162,49,71,168,31,130,160,103,223,244,225,108,133,142,123,181,164,114,112,172,100,229,165,150,250,57,212,15,63,204,70,163,4,98,111,152,45,37,45,245,228,45,244,111,124,250,163,197,120,243,232,117,56,154,191,145,196,141,125,8,55,90,132,216,85,224,174,60,253,201,63,198,114,202,235,236,103,174,176,192,65,93,161,74,226,65,222,241,126,119,113,174,16,71,68,19,253,160,250,79,117,231,129,159,61,132,104,164,251,78,110,48,246,12,36,172,100,111,152,87,36,40,95,115,60,227,74,123,204,149,244,119,65,162,114,102,121,19,155,249,117,248,51,151,33,42,115,199,237,144,43,180,51,121,129,23,83,127,226,56,9,32,222,44,201,44,21,7,249,122,183,224,239,85,204,10,181,91,19,103,103,133,205,12,229,38,97,31,108,141,82,255,186,32,185,59,95,66,45,15,41,179,36,56,178,53,39,230,128,252,12,104,165,98,132,4,223,238,44,36,222,188,218,52,250,146,212,148,237,85,68,175,72,79,155,38,36,230,62,122,67,208,138,241,5,49,158,119,106,100,178,247,61,154,161,134,111,198,28,192,44,150,189,7,205,154,142,45,190,172,69,107,176,36,105,64,30,153,120,233,138,210,10,19,201,37,119,182,152,85,43,37,56,68,199,14,82,214,220,245,249,231,141,77,20,190,252,61,102,166,209,230,24,109,225,229,78,195,145,93,109,32,127,163,49,126,248,87,165,80,47,35,155,3,51,50,146,244,105,171,122,226,62,82,242,157,209,37,222,157,224,156,21,73,10,238,198,123,110,60,209,122,158,82,5,221,166,227,119,183,251,80,175,245,112,156,150,175,183,247,162,53,159,213,33,71,40,168,227,104,244,244,210,154,12,114,234,6,153,36,147,203,170,108,85,64,250,110,225,137,2,143,243,163,40,173,220,191,63,210,108,131,154,142,83,175,46,56,41,236,83,221,81,161,144,135,172,99,88,139,115,229,148,143,162,9,203,12,44,238,102,165,234,230,179,179,242,16,227,158,20,196,203,126,102,121,194,246,105,131,73,192,81,122,192,229,32,52,68,139,60,16,102,94,4,190,236,77,238,222,73,240,221,6,252,179,240,56,85,108,237,167,95,168,223,161,49,28,186,57,93,43,203,125,223,42,221,67,47,174,96,56,99,204,115,41,252,252,106,153,180,228,242,100,155,42,105,108,181,215,47,150,176,81,36,192,211,244,135,162,127,189,201,80,62,117,91,125,58,245,215,9,16,165,134,52,42,43,225,155,28,21,189,76,85,226,216,155,133,105,120,60,145,152,6,52,150,149,2,255,255,126,255,45,36,58,37,21,112,25,5,210,187,69,74,195,46,226,170,12,90,154,7,142,228,89,148,22,211,1,150,132,252,99,19,215,135,242,15,150,0,17,251,192,38,133,71,164,62,161,144,240,178,62,63,254,50,137,26,207,233,156,52,145,94,86,239,132,26,146,181,46,165,248,100,14,76,252,16,214,130,195,166,67,120,113,30,255,126,197,11,57,108,130,66,163,177,70,30,223,117,244,53,44,13,86,39,70,58,213,212,230,152,164,76,152,10,227,3,6,230,216,73,88,108,91,245,126,137,58,224,132,168,129,199,254,247,134,142,56,81,168,160,119,44,222,123,230,189,204,92,245,18,227,172,58,240,174,149,68,71,210,183,169,241,146,73,86,210,216,156,250,239,161,219,212,210,69,48,33,137,81,185,192,218,197,2,122,26,76,13,121,61,31,44,239,37,158,126,254,241,131,26,167,224,67,133,125,52,204,195,141,119,131,208,214,151,86,54,137,139,144,178,173,220,170,156,70,125,66,38,125,127,135,146,246,160,95,230,1,248,184,55,65,56,225,139,169,106,17,246,153,98,119,248,67,85,148,28,157,200,233,186,149,138,180,147,37,42,212,190,28,189,109,117,242,168,56,133,17,29,241,89,218,5,242,81,50,61,166,175,124,106,47,237,20,201,235,69,95,202,35,243,79,223,34,85,47,100,252,168,29,171,20,189,109,65,14,156,71,195,246,94,104,211,21,29,195,84,33,131,207,221,120,139,57,78,126,88,195,191,172,133,96,242,110,140,236,227,76,154,55,32,134,193,20,204,21,192,232,157,224,147,175,193,96,9,127,18,107,239,96,240,98,139,149,104,92,151,196,170,198,104,185,117,179,26,20,72,48,36,47,32,86,42,189,173,80,71,219,151,79,181,88,45,26,191,38,133,45,54,131,31,109,115,161,163,34,38,89,40,49,173,198,48,17,40,39,121,77,90,70,42,251,130,168,125,184,76,60,95,94,136,227,248,145,210,226,191,137,247,72,210,17,141,52,5,102,220,23,111,146,114,218,208,22,105,9,130,97,83,57,25,228,137,6,99,12,24,29,89,25,101,217,133,196,253,246,158,114,75,8,90,142,28,147,19,22,164,240,205,1,21,145,19,225,61,98,21,22,215,32,158,9,44,97,148,104,201,219,76,43,45,162,73,151,252,188,155,192,134,113,103,109,255,54,42,206,24,76,87,154,98,187,78,193,50,86,191,222,86,162,165,38,191,118,117,72,31,6,174,147,231,105,158,70,133,79,138,223,55,73,210,90,194,194,112,167,14,253,133,160,197,234,193,24,75,239,106,47,115,70,102,75,122,123,87,158,185,162,180,84,210,222,141,172,125,211,117,181,155,250,182,51,247,178,100,123,8,8,173,224,246,222,40,35,31,171,203,195,36,34,6,53,171,105,219,106,216,77,18,130,182,37,225,3,235,196,203,114,168,7,2,10,14,230,118,6,134,118,20,184,145,213,218,127,110,182,193,145,91,202,110,11,96,118,1,8,96,103,167,236,180,15,141,151,253,100,7,112,25,70,89,121,233,178,158,234,47,68,162,185,146,146,7,74,2,17,238,108,171,91,64,92,173,85,82,121,240,175,136,132,26,123,225,64,169,132,53,192,187,113,8,165,133,192,249,61,166,108,170,2,175,11,243,183,162,93,109,51,151,40,206,39,150,0,84,130,215,29,211,96,200,244,193,206,63,137,9,225,205,195,93,147,70,125,177,146,164,76,247,0,61,118,12,73,75,151,145,218,82,180,207,112,233,175,169,104,180,29,149,4,129,248,70,10,159,34,67,208,4,235,146,205,128,223,104,17,16,189,72,150,29,148,21,85,152,237,97,200,84,57,234,9,165,16,73,40,118,10,18,222,171,43,231,169,211,149,179,250,145,227,129,66,53,2,35,228,99,7,1,101,161,122,247,98,103,47,32,194,21,66,228,215,171,211,95,93,47,71,164,197,154,72,46,73,190,186,131,152,104,252,1,237,94,154,240,6,67,188,57,183,3,28,30,181,14,142,247,193,242,88,231,188,86,198,130,125,97,9,115,137,196,6,38,94,170,51,157,253,197,152,195,181,150,253,125,49,6,217,29,102,120,252,248,217,191,232,176,151,7,118,12,126,164,219,67,123,72,16,146,223,203,183,0,196,87,186,185,173,67,246,204,171,20,21,86,98,182,253,7,186,6,120,189,118,3,229,237,60,53,90,120,139,87,229,79,153,85,139,16,81,100,189,150,202,125,164,42,132,10,163,190,85,177,69,169,181,85,186,64,77,182,99,209,185,183,19,5,1,24,167,247,211,71,7,154,124,136,40,199,61,196,217,202,170,170,93,64,20,178,234,247,41,59,124,192,158,211,128,28,144,37,95,61,108,113,150,27,161,102,97,250,86,162,10,193,27,201,55,193,56,84,164,176,59,172,180,2,117,209,83,226,255,156,104,115,80,9,171,177,196,38,252,19,138,252,29,242,231,74,93,205,161,41,158,79,204,211,0,30,248,42,125,237,167,151,3,163,35,219,102,225,38,80,160,246,91,202,15,81,5,104,108,210,239,193,131,146,27,150,17,171,71,221,84,112,204,146,94,186,237,255,206,118,141,107,20,169,226,15,43,75,224,52,120,186,0,134,235,166,30,237,98,31,139,146,29,104,64,56,3,249,66,92,147,217,211,9,31,96,178,69,148,227,230,101,236,243,45,246,172,39,229,59,69,106,63,147,212,148,179,217,10,220,19,61,36,147,54,173,248,250,238,79,181,163,211,105,11,79,136,249,56,91,202,219,147,180,212,42,140,52,110,222,216,92,215,61,213,55,188,33,239,190,201,255,96,1,215,85,244,86,49,152,17,180,172,68,196,115,71,107,182,243,219,136,48,23,116,210,242,8,233,123,235,101,169,61,55,63,1,51,205,161,189,96,59,52,218,197,250,26,88,73,52,217,104,199,216,234,189,209,12,232,29,210,128,20,244,127,219,15,204,123,222,84,167,249,54,43,174,28,118,186,210,116,176,58,78,38,166,130,144,219,92,43,91,180,1,195,20,39,139,0,25,240,204,75,61,178,95,199,10,3,136,139,50,249,155,86,95,70,214,41,166,76,132,6,166,146,35,118,145,100,203,149,154,211,215,94,104,5,44,83,183,45,251,89,212,57,197,144,82,87,170,120,45,105,80,129,100,131,159,10,127,221,163,246,63,192,154,53,205,6,127,117,223,24,147,216,93,28,239,163,214,221,158,12,149,255,83,88,41,136,165,138,1,254,6,44,25,143,22,104,150,94,24,196,25,238,193,216,170,71,103,76,33,52,211,45,205,235,134,41,248,86,65,9,32,255,32,95,30,250,243,251,43,119,170,184,85,107,38,21,98,231,54,218,226,16,72,174,6,221,38,211,120,221,119,117,120,67,209,251,33,84,155,163,163,47,53,96,15,51,76,204,87,153,85,170,54,66,113,12,174,34,104,136,90,62,76,103,210,150,82,37,200,148,44,89,113,229,33,173,240,114,61,21,131,193,157,216,181,193,207,219,29,42,99,21,186,158,11,145,155,4,216,22,244,162,245,120,63,128,57,117,241,213,60,251,251,149,87,153,99,63,22,75,81,103,103,239,199,225,110,110,88,38,125,240,116,161,226,53,38,183,2,223,68,221,87,205,73,201,187,129,82,39,35,166,109,116,96,250,15,15,242,104,227,86,21,140,48,172,188,54,214,185,33,4,199,217,220,218,185,44,244,170,133,64,135,231,135,80,159,130,65,112,36,250,209,241,226,74,174,130,199,202,217,218,87,161,162,130,254,242,150,34,63,117,178,224,76,211,80,201,111,72,69,137,93,62,24,23,249,115,80,83,95,17,166,84,223,132,120,6,53,34,199,208,205,80,109,133,213,92,49,18,214,230,123,245,73,80,228,94,106,241,165,216,84,255,96,177,178,90,92,5,219,185,153,238,208,136,79,150,15,232,139,179,52,146,235,158,62,239,136,154,45,92,190,176,19,91,40,214,152,149,209,222,247,97,175,74,250,98,231,204,211,233,2,168,136,18,202,254,144,196,95,80,187,220,123,31,164,176,207,23,248,81,3,174,138,206,65,83,36,29,70,32,71,21,227,157,254,228,2,4,215,71,27,252,9,219,49,49,23,248,163,43,170,192,126,75,198,97,91,38,182,93,204,141,250,187,145,128,158,103,88,73,178,191,233,253,231,3,169,38,117,163,181,44,217,91,138,15,239,82,140,19,78,13,168,212,227,46,202,225,130,28,150,211,105,239,25,243,208,76,174,52,37,170,87,125,141,221,90,95,41,51,53,205,112,75,54,129,102,51,87,222,28,117,188,154,174,103,66,55,95,247,97,127,31,107,22,117,195,115,97,108,19,52,70,179,212,190,15,8,213,49,139,119,170,201,169,8,199,203,166,183,90,134,185,169,133,135,9,251,66,104,187,220,182,164,82,21,125,132,197,116,14,169,241,211,104,107,169,17,246,140,46,235,236,23,84,93,180,72,214,10,39,185,197,170,73,30,43,35,75,114,202,126,143,2,127,114,206,107,25,116,183,11,43,3,146,183,121,214,79,26,240,70,203,45,88,74,11,137,245,21,38,44,66,143,61,168,69,76,204,92,186,121,203,15,46,213,237,131,23,220,68,52,188,111,185,48,81,35,208,159,218,44,76,71,236,152,61,103,92,247,136,123,88,196,109,213,91,97,190,88,164,237,171,59,217,231,230,51,149,191,114,162,41,91,249,249,25,109,183,231,25,48,30,35,44,156,199,26,146,144,26,85,40,82,54,83,253,102,88,29,52,114,160,176,0,95,4,217,205,123,143,97,62,149,15,178,195,166,156,183,183,170,183,54,232,197,211,241,7,215,241,86,159,151,161,98,116,91,139,14,111,22,41,155,5,43,72,245,246,20,196,27,62,112,149,21,253,42,111,173,148,25,42,199,41,53,84,169,17,246,92,25,211,161,41,159,252,62,243,4,19,121,43,66,199,74,28,208,193,205,33,126,84,173,30,16,26,179,244,95,188,90,6,16,178,251,191,203,121,130,161,12,52,170,24,14,141,2,163,190,6,52,205,187,57,245,252,9,53,65,132,246,126,90,3,26,54,238,222,74,237,35,163,214,83,43,254,139,112,244,74,15,241,20,255,217,117,129,81,233,181,187,160,29,30,245,145,199,163,29,171,87,228,222,50,229,60,139,23,152,179,33,23,124,180,100,223,209,21,191,93,240,166,209,66,67,28,158,237,190,62,80,188,131,151,72,22,159,212,121,139,49,254,184,106,134,122,77,103,165,81,70,69,174,0,7,179,26,152,234,23,37,155,212,120,59,223,226,216,189,170,9,42,206,10,123,140,130,214,229,149,218,74,215,152,151,235,170,53,33,209,190,193,105,61,182,108,226,176,32,213,78,117,106,23,56,121,61,82,213,107,121,107,114,185,20,99,151,57,44,105,153,238,174,24,192,241,254,251,80,193,143,221,0,58,227,109,190,129,185,22,131,37,221,129,34,101,144,152,33,250,198,183,73,236,69,174,215,68,64,181,94,33,132,40,149,248,252,133,191,99,245,130,21,43,49,211,224,204,33,169,240,230,120,107,228,46,140,168,241,32,17,95,48,147,101,16,176,251,83,160,253,105,171,56,79,198,139,36,48,144,120,99,236,171,235,56,117,196,171,178,244,170,61,79,183,32,202,66,50,130,211,99,78,199,73,255,242,30,138,199,156,129,107,187,182,255,144,201,230,138,199,111,154,10,126,232,144,99,117,187,160,97,221,177,191,5,239,139,181,240,32,249,247,61,216,207,154,217,224,246,49,118,3,194,107,197,233,3,242,99,182,58,45,151,176,238,101,118,57,44,123,195,112,61,129,140,199,98,25,86,104,2,141,220,161,128,109,32,8,89,147,249,11,246,14,255,195,81,233,46,89,37,122,225,211,69,132,120,138,169,254,0,72,208,116,247,244,60,55,28,135,15,11,28,174,65,40,253,148,181,6,57,220,134,224,205,255,225,22,228,49,200,228,182,179,141,237,217,9,47,114,203,57,24,173,236,15,100,174,120,178,73,84,236,141,45,188,142,252,66,85,56,248,161,247,21,240,209,145,198,24,158,227,106,158,18,248,204,21,1,99,35,91,187,157,228,98,106,35,231,158,103,53,119,135,62,168,207,48,5,118,236,117,255,204,65,60,49,102,180,55,82,149,17,205,214,182,198,223,77,55,234,99,156,29,161,90,22,138,7,126,240,213,226,110,63,214,97,71,161,203,216,10,31,25,62,71,223,163,238,97,14,115,144,121,112,103,4,186,16,66,51,105,110,65,111,32,206,82,213,231,74,107,199,255,85,48,249,19,123,45,142,3,104,77,86,181,99,8,158,50,3,108,43,23,113,246,189,180,107,134,24,9,137,36,178,9,176,197,63,33,63,164,220,217,243,175,16,197,210,28,16,109,192,143,193,240,252,44,124,8,108,179,168,171,135,107,32,216,49,136,123,109,133,33,176,167,185,189,30,120,210,5,211,14,127,118,199,147,121,246,58,33,239,172,251,87,223,152,144,13,169,216,65,87,59,132,210,118,116,30,68,72,68,155,103,230,81,33,26,21,82,14,73,251,183,147,86,222,194,97,44,169,244,82,155,95,253,205,116,91,165,44,64,31,163,242,253,93,23,26,209,14,33,97,62,148,115,63,247,111,137,13,9,163,215,243,223,218,10,114,82,195,219,233,24,117,167,173,231,13,156,77,46,231,130,200,122,169,91,49,229,215,250,140,73,229,240,44,212,41,117,112,31,126,218,196,58,241,101,147,26,195,148,98,153,198,104,87,90,149,128,60,239,177,50,49,11,242,239,230,196,182,89,101,80,215,168,143,70,48,53,53,215,22,99,194,129,245,128,163,40,102,25,14,99,189,152,35,135,13,16,105,137,188,32,226,246,176,38,30,36,65,146,145,240,83,103,2,107,133,21,172,41,239,28,250,134,170,228,80,43,122,211,87,111,228,168,29,171,79,69,62,152,18,69,203,96,169,144,83,50,37,65,208,1,113,46,2,67,73,221,2,181,73,185,209,20,163,237,141,222,221,69,220,155,12,177,239,150,84,234,58,111,225,3,31,187,110,139,78,139,234,186,202,73,72,34,125,59,43,206,220,68,6,49,123,14,147,144,206,60,95,31,173,236,244,239,64,11,119,89,226,7,117,175,218,115,104,165,195,209,202,140,132,15,6,115,213,209,69,238,7,89,37,249,156,158,67,124,208,100,194,232,148,52,214,125,166,99,224,152,46,109,187,234,230,51,60,189,191,120,28,13,67,152,105,230,40,147,153,215,16,149,231,51,170,159,88,97,228,216,161,34,87,65,129,153,213,186,140,150,104,113,164,25,120,246,58,78,221,124,33,179,135,7,220,233,68,9,15,123,101,187,131,139,95,177,234,29,215,24,57,107,53,194,252,161,247,70,224,245,22,104,10,41,39,213,190,186,249,159,32,28,196,55,153,225,205,18,72,227,70,120,101,199,237,132,225,10,124,88,154,151,215,153,67,177,100,244,99,169,37,127,97,122,188,216,217,79,187,227,87,69,243,42,139,151,228,79,141,154,88,240,7,29,255,165,129,150,70,173,212,207,194,245,243,54,210,111,168,77,71,140,61,28,64,106,8,196,60,68,154,18,110,22,252,63,172,163,34,138,138,105,145,101,244,110,11,75,95,244,220,224,140,191,243,85,79,137,128,246,173,146,28,1,68,146,131,190,104,107,105,10,183,141,149,204,59,176,190,91,3,180,254,33,47,24,58,4,53,177,211,193,103,6,161,57,156,191,177,108,76,83,185,133,20,167,103,26,75,148,54,239,124,182,71,95,160,157,60,112,22,149,136,53,82,150,241,250,192,35,199,124,207,79,66,84,131,7,63,140,114,16,166,158,30,0,73,131,202,144,116,46,50,92,60,23,147,147,14,236,195,64,128,205,63,248,146,1,49,182,30,96,166,149,196,243,131,88,93,119,167,118,22,137,56,179,169,223,194,48,235,4,196,19,7,210,55,75,235,92,247,15,83,174,53,132,172,34,214,91,205,147,70,34,195,103,132,175,68,245,7,227,205,122,160,7,72,137,123,51,243,8,7,82,113,179,53,171,249,151,156,75,82,204,101,194,53,247,2,201,39,125,151,8,4,189,190,40,95,41,72,181,116,99,58,100,136,118,164,13,191,107,164,69,39,229,204,2,248,254,87,112,64,247,106,105,66,193,73,104,67,75,181,248,105,39,227,153,139,164,41,215,76,244,118,95,99,56,13,94,20,67,33,205,238,108,249,81,105,60,177,18,155,229,73,173,205,78,164,144,180,161,191,210,203,150,190,16,55,228,110,203,212,118,15,103,25,67,152,199,2,36,17,117,201,129,88,197,112,153,188,44,58,196,160,131,198,150,19,223,209,224,90,127,231,71,1,40,82,195,12,242,223,233,211,68,210,32,176,1,106,119,179,211,33,221,107,210,194,227,213,88,3,122,19,130,145,199,16,66,179,41,215,40,18,133,40,191,25,49,31,101,27,16,11,60,119,20,186,217,168,204,250,28,173,159,38,166,106,2,35,49,133,30,16,174,41,134,5,154,247,72,247,171,23,225,89,228,141,14,221,122,56,188,54,252,90,121,252,169,8,168,27,59,138,8,245,70,122,230,65,165,140,117,136,206,11,169,209,146,240,8,234,87,27,21,119,136,227,84,138,65,172,42,227,109,202,167,67,219,148,125,32,179,242,176,224,42,235,163,145,195,63,145,122,135,21,164,85,133,249,38,87,145,90,3,151,203,189,99,172,189,248,86,207,193,226,138,44,42,179,190,99,83,127,92,185,32,159,58,246,239,241,246,235,227,205,219,169,42,77,149,0,212,210,172,47,174,68,122,133,7,78,152,86,30,65,58,84,65,40,113,125,213,150,112,146,1,46,218,175,242,206,243,3,22,233,246,135,129,96,57,130,15,151,104,91,220,169,42,107,34,44,14,229,23,97,55,219,134,96,213,252,133,227,120,195,1,46,17,86,212,120,130,91,248,166,233,51,66,254,106,183,117,42,44,36,169,196,204,173,91,96,109,228,171,28,189,45,250,183,121,167,12,164,164,245,225,177,164,170,138,139,161,93,90,83,85,26,198,104,106,203,108,131,144,196,153,22,188,229,99,101,228,68,84,115,35,112,19,129,18,184,189,228,220,191,206,106,106,126,188,176,42,150,208,166,249,215,76,49,78,167,49,137,16,206,210,203,31,206,130,158,233,143,12,168,123,152,246,181,110,5,9,143,33,8,20,72,188,117,52,80,18,200,90,101,236,228,207,56,241,5,217,53,40,86,180,67,214,216,113,227,232,42,4,123,161,29,225,131,69,60,164,193,158,200,54,177,14,32,137,153,25,110,144,200,246,156,194,61,16,88,79,24,113,181,5,133,88,82,165,176,38,251,156,45,231,111,141,37,120,107,195,254,51,23,243,143,18,30,92,222,216,31,27,168,49,204,158,75,50,29,108,173,189,227,162,147,5,233,159,187,189,71,11,14,221,15,68,223,60,234,186,227,182,193,229,131,242,98,115,34,126,30,59,20,56,101,249,9,38,148,110,79,181,179,181,29,240,61,110,204,161,242,160,184,30,38,49,180,136,78,22,156,1,249,192,217,132,67,3,250,243,132,141,231,10,84,231,97,122,73,28,88,116,105,213,193,202,47,183,216,19,80,71,55,14,123,32,194,193,121,208,234,113,73,234,146,93,189,196,164,129,140,201,122,187,60,67,10,121,125,17,246,192,134,16,58,220,3,66,88,63,127,197,206,164,85,151,11,143,43,109,35,215,25,113,90,99,90,205,22,209,122,41,112,244,206,253,59,161,241,168,251,89,190,186,151,193,3,142,219,1,102,68,147,87,145,74,157,223,203,18,248,51,21,219,92,9,251,196,149,82,153,103,27,151,252,54,21,4,47,205,56,172,183,3,29,202,225,83,16,70,15,21,227,219,225,178,248,157,53,135,57,185,163,37,123,167,126,80,187,41,181,17,191,207,228,71,37,158,205,118,62,248,250,194,59,71,214,167,103,233,25,73,205,178,231,128,78,53,113,28,73,140,86,87,88,87,238,196,137,77,234,138,39,195,39,117,89,71,3,123,115,108,182,175,148,180,142,193,159,155,141,71,168,172,98,136,187,112,36,25,146,98,217,160,17,34,77,55,98,189,208,173,74,117,181,200,124,182,123,12,56,62,149,214,75,112,112,107,126,242,224,85,234,235,172,131,250,233,229,99,14,92,194,36,21,156,167,172,215,243,141,214,57,79,177,104,94,207,160,8,3,102,237,50,84,126,223,147,92,211,221,196,52,130,24,176,159,132,65,156,131,71,126,4,33,143,91,104,28,50,153,209,95,181,28,75,113,70,67,27,109,192,39,174,135,252,172,218,211,94,160,62,199,154,79,251,16,22,195,15,22,140,253,36,242,85,72,147,22,121,33,25,195,83,123,67,179,160,66,85,146,45,114,228,93,116,57,55,217,212,216,31,50,167,229,242,19,107,240,57,124,255,142,191,249,148,74,39,163,43,156,151,201,207,220,46,185,27,203,141,137,15,92,5,101,198,159,181,2,84,128,42,9,10,185,221,175,55,128,247,131,98,98,146,152,8,240,110,121,15,67,233,2,21,145,83,105,182,127,239,100,153,185,165,225,124,59,119,26,175,192,81,4,98,42,93,184,200,34,68,13,134,123,5,43,164,167,218,32,67,79,70,4,196,254,131,50,201,157,133,80,79,208,242,155,224,237,252,110,27,249,238,45,235,77,229,182,93,205,123,32,5,3,78,154,69,213,117,216,130,198,46,105,47,78,76,255,250,230,254,99,106,218,110,21,186,185,71,173,236,91,67,119,59,38,141,202,223,39,183,153,239,2,113,168,121,123,54,217,55,237,94,11,1,190,38,16,170,216,147,239,88,254,229,245,220,108,102,247,55,229,237,173,167,179,231,185,82,226,109,53,81,87,15,55,217,69,204,109,3,164,126,143,193,42,141,227,90,36,226,83,128,215,12,177,216,190,140,85,129,225,224,25,74,141,225,41,192,131,60,180,130,169,191,124,58,1,135,224,63,27,9,138,244,124,167,199,35,2,120,62,25,218,238,78,254,29,125,60,19,72,168,31,194,52,28,70,137,193,242,203,2,91,43,138,248,5,135,204,165,116,67,10,198,121,98,100,238,143,43,94,209,39,162,232,129,176,41,254,158,40,195,167,51,206,48,151,123,55,64,65,233,220,176,238,73,3,129,139,129,242,194,88,95,199,147,187,75,237,229,171,30,89,115,154,239,165,169,235,59,98,63,177,91,115,84,142,203,97,103,79,66,2,91,157,207,14,45,246,75,211,46,69,228,42,158,158,132,228,178,36,163,98,194,69,11,37,186,217,155,206,244,54,125,9,122,128,237,37,159,232,91,68,159,92,116,153,244,199,136,214,88,171,186,117,98,60,171,163,232,45,147,151,123,170,237,130,250,83,244,253,125,237,248,178,237,111,15,63,154,122,147,51,15,60,204,111,139,245,231,228,185,51,36,176,237,79,48,4,150,130,163,59,120,29,126,54,40,104,116,142,238,121,237,189,107,191,35,8,119,113,131,109,108,173,24,9,142,108,8,49,51,202,146,192,173,17,1,241,218,187,124,164,246,139,220,70,143,192,138,152,227,175,189,77,209,86,106,63,119,2,159,194,2,163,89,30,119,83,127,152,98,60,123,145,96,155,67,36,124,94,20,93,243,98,219,253,143,238,124,45,39,226,10,242,116,227,184,129,242,21,192,51,94,97,231,64,148,237,211,59,177,198,10,216,238,62,4,109,230,168,9,132,240,215,0,86,29,251,174,78,233,243,27,50,92,197,253,214,2,123,146,246,222,140,146,148,108,237,15,4,222,247,156,154,132,10,40,151,8,10,70,114,132,181,145,136,176,233,7,169,57,111,204,90,220,67,215,132,40,150,216,152,69,54,80,43,171,67,46,100,140,33,185,115,58,154,35,242,247,6,43,31,174,39,80,101,216,73,40,132,227,201,14,85,37,194,50,3,146,118,78,76,36,211,88,24,220,98,14,33,120,148,222,160,20,160,118,195,167,167,92,128,37,5,53,38,72,206,146,123,57,213,135,200,109,71,35,239,160,169,225,222,136,217,153,92,67,165,51,105,189,47,203,155,237,217,9,216,232,29,225,177,49,205,230,232,177,124,66,19,114,207,198,114,64,45,161,124,66,110,85,157,81,102,32,22,83,53,111,196,27,133,196,169,162,223,120,126,235,105,163,132,221,206,150,110,214,226,227,26,172,30,160,193,251,235,130,209,125,165,77,58,39,115,187,196,165,24,148,33,237,15,73,76,51,191,88,212,165,137,89,220,47,35,108,174,114,48,214,113,39,163,180,185,63,88,233,112,0,120,241,137,168,24,63,138,54,82,207,177,179,66,101,46,177,222,3,52,49,103,68,5,246,78,182,234,55,35,29,9,19,192,144,78,132,224,162,148,96,89,62,61,109,6,178,98,241,196,88,167,22,196,56,11,139,35,94,112,213,134,206,158,24,179,145,144,24,250,44,149,253,67,210,8,0,244,166,243,0,180,234,155,46,191,122,41,93,142,70,154,56,201,66,159,207,162,193,63,26,46,204,221,206,29,100,232,161,225,87,106,130,47,154,66,253,50,33,4,103,71,134,239,65,137,220,222,90,200,221,145,253,16,73,125,66,213,113,239,82,209,96,85,98,196,87,143,30,250,24,217,92,120,23,123,71,64,51,243,204,192,239,147,75,30,170,32,161,187,95,176,78,235,9,173,103,112,9,93,39,55,89,66,223,135,55,158,58,28,249,4,53,46,175,138,48,65,135,70,136,1,162,20,77,236,103,41,150,88,60,162,162,221,75,62,108,114,118,100,40,120,101,241,122,160,0,109,225,54,161,239,188,6,149,136,139,198,177,179,32,43,126,52,149,57,217,226,136,215,201,55,32,213,229,87,28,109,36,223,42,151,98,71,107,140,255,230,206,183,84,127,109,108,57,226,37,11,140,188,250,216,82,32,241,186,122,68,173,128,81,29,57,2,23,81,10,233,198,238,113,91,11,7,17,184,180,159,230,116,147,143,120,21,24,1,220,118,49,16,80,204,12,78,41,111,117,193,98,56,148,193,219,160,156,230,56,126,1,172,183,95,204,229,202,75,218,108,245,33,254,8,58,127,98,209,197,176,100,60,110,139,133,80,43,42,133,200,12,216,121,186,89,171,171,252,220,132,121,46,180,75,79,8,157,91,112,112,34,247,193,147,132,119,236,30,223,101,129,132,197,45,134,84,202,92,249,70,208,211,158,206,209,216,202,106,106,96,1,80,249,182,103,247,124,85,169,42,212,67,245,112,214,156,147,143,216,186,202,197,119,5,230,23,226,199,79,150,253,252,85,1,193,145,96,212,15,165,73,246,244,50,249,165,95,254,252,112,62,100,237,167,234,181,238,164,135,224,175,19,225,82,153,135,122,209,81,59,123,165,21,127,99,54,56,18,153,226,205,161,95,202,7,79,126,124,92,208,244,46,5,176,227,206,200,16,140,97,250,131,187,54,34,117,52,52,206,150,201,200,182,45,201,225,80,46,100,113,199,193,12,116,224,253,59,85,244,248,161,239,199,164,208,63,114,103,163,167,185,246,203,19,33,102,53,236,108,3,205,170,155,230,73,204,142,178,233,7,187,171,191,137,254,60,149,218,98,40,42,87,10,3,146,207,162,67,113,25,173,141,27,217,143,225,97,164,2,208,116,57,181,180,112,233,183,114,62,110,197,29,79,155,213,7,115,94,60,229,43,83,79,119,171,196,20,78,239,233,51,87,6,32,5,59,166,121,176,193,0,2,145,150,183,130,7,36,179,159,57,212,66,179,111,151,174,27,202,58,35,12,121,174,29,17,69,244,46,87,1,173,238,194,40,107,180,147,157,209,184,241,104,251,123,242,164,42,31,93,118,82,79,189,47,105,102,158,30,210,164,16,47,140,226,212,235,70,176,78,30,247,193,162,137,19,102,181,9,248,156,29,149,41,73,2,34,88,183,198,106,254,34,124,19,150,32,99,71,253,14,190,121,107,200,168,38,114,205,153,112,139,204,16,149,101,168,127,70,40,156,157,78,179,113,220,4,46,194,124,96,187,139,83,36,28,169,50,209,88,176,134,217,219,55,18,186,165,170,11,175,60,216,24,132,95,218,101,75,194,66,64,184,1,56,29,86,92,86,243,122,204,124,185,21,219,37,111,68,82,178,41,69,127,186,121,223,219,84,41,169,105,54,165,5,128,102,12,67,130,217,46,97,233,254,216,57,121,145,39,46,34,136,82,175,114,153,215,16,119,138,116,45,137,136,230,59,132,221,97,0,150,250,153,211,18,141,254,212,157,9,45,217,191,16,24,133,130,194,151,189,230,92,187,55,12,247,187,8,115,13,29,222,207,59,92,230,24,146,39,165,2,54,188,107,162,190,178,185,22,188,187,172,42,164,239,225,92,55,26,237,230,59,0,75,13,33,47,250,12,161,72,4,185,159,244,163,208,129,102,176,239,178,99,211,97,92,241,234,19,85,70,42,189,55,130,151,119,38,50,126,239,231,40,153,124,51,220,63,234,208,163,211,170,63,37,231,40,152,183,204,90,227,246,208,8,196,85,209,243,92,102,174,199,27,110,145,27,1,158,35,176,107,152,163,227,75,21,184,120,238,57,155,201,3,194,165,57,117,211,136,236,17,128,98,177,93,111,46,94,137,155,5,70,101,212,42,190,79,218,62,143,123,151,171,59,185,175,9,185,245,254,235,130,177,69,252,61,157,29,229,105,128,229,192,180,37,158,214,254,13,129,64,53,209,247,56,140,241,97,250,119,174,250,204,68,97,184,208,29,20,117,25,12,105,234,224,76,223,115,197,177,7,235,247,19,42,20,85,78,15,81,181,192,153,4,160,176,82,106,67,212,194,132,240,190,45,126,79,192,122,42,28,239,165,14,139,14,152,62,129,78,48,66,45,207,97,240,165,178,129,234,169,234,59,12,218,46,249,54,76,20,225,254,11,128,237,242,61,101,16,36,207,202,13,244,205,77,104,204,51,50,1,5,95,211,151,110,251,255,185,191,151,167,102,140,98,163,129,27,38,60,101,197,176,252,212,232,136,208,157,118,51,83,111,209,188,223,78,130,47,24,91,236,170,159,121,55,3,202,0,155,212,180,173,74,37,161,201,91,108,166,174,27,239,60,20,65,158,225,185,85,89,127,76,244,27,86,150,160,201,13,106,79,143,68,200,236,55,107,243,76,149,215,188,118,183,198,159,26,140,136,153,211,173,159,16,57,139,31,93,149,70,6,141,53,112,164,6,184,239,106,159,222,67,158,26,121,136,223,39,46,140,67,170,202,95,88,179,214,186,212,140,8,12,94,34,77,226,17,17,162,210,225,20,151,177,74,9,100,126,170,73,142,33,144,154,131,151,205,235,28,118,190,6,137,98,50,237,7,94,230,246,133,250,179,160,199,89,103,9,203,111,37,216,185,171,40,117,6,107,87,133,165,172,22,140,220,186,41,97,187,57,196,102,220,15,169,194,254,170,33,237,69,78,127,4,30,119,51,251,153,50,179,106,153,232,131,96,100,243,32,78,78,223,191,150,158,39,30,201,43,12,220,233,103,223,247,156,210,213,52,75,203,102,114,46,35,81,55,175,89,207,53,66,198,247,164,132,51,64,124,120,125,108,35,3,184,185,202,162,122,93,58,198,11,176,146,221,62,6,92,250,135,230,38,135,125,76,89,22,140,243,110,14,212,252,94,85,234,86,142,168,158,28,94,124,183,180,213,174,80,170,142,88,83,48,201,169,249,109,156,83,4,161,186,46,235,85,83,86,244,7,52,58,188,19,124,117,35,105,13,185,191,47,252,142,77,194,147,27,235,193,126,138,65,32,134,118,24,227,33,219,142,48,59,235,147,8,183,94,74,184,233,4,78,44,55,20,167,190,216,145,187,105,253,135,93,68,15,204,76,81,176,255,140,229,106,248,29,154,109,79,247,240,181,62,181,2,28,187,26,136,254,180,92,158,140,81,194,11,245,237,48,28,57,112,87,48,233,185,13,251,113,29,199,152,222,226,254,232,119,199,120,251,113,224,226,89,162,215,74,115,227,118,145,197,176,156,161,226,233,79,170,203,163,113,106,144,108,25,85,163,91,129,143,75,216,56,51,156,13,106,116,79,121,79,152,139,128,156,169,174,94,228,172,49,115,235,134,42,145,67,107,214,122,8,49,156,210,218,178,151,67,247,169,0,56,164,44,222,132,125,193,90,153,10,15,29,69,159,229,98,193,181,138,65,215,14,65,89,116,209,247,174,22,72,27,141,214,94,36,169,203,34,123,25,192,248,196,238,148,225,225,253,59,44,43,96,2,26,21,96,123,202,184,253,55,162,172,81,29,95,172,11,133,235,129,224,183,94,71,85,29,23,65,246,242,222,224,109,136,62,63,145,107,248,167,160,195,242,204,135,237,253,107,53,91,77,34,207,186,102,102,84,28,14,44,194,39,232,156,245,132,232,76,102,63,206,240,49,132,118,211,1,70,75,30,42,3,149,207,174,223,160,227,64,221,207,62,64,74,186,97,163,201,85,231,33,84,76,132,47,66,189,73,137,21,77,184,234,168,231,171,247,76,32,229,1,138,186,116,5,60,65,8,57,133,57,165,125,190,51,105,242,89,1,141,234,53,168,34,89,88,55,63,52,10,226,116,30,115,175,214,74,234,133,248,48,242,17,47,155,75,131,130,124,207,192,199,156,142,142,119,122,3,15,49,119,155,82,80,171,180,19,29,133,31,247,222,9,245,206,244,22,69,12,85,112,250,23,97,212,191,32,152,5,115,206,31,197,19,250,138,219,130,3,84,216,78,11,80,213,13,161,199,128,136,64,7,53,223,221,247,108,10,139,128,47,36,225,149,145,94,106,22,86,14,62,13,43,181,226,188,243,228,218,231,144,137,51,46,13,237,21,72,193,233,132,28,220,20,8,4,122,72,237,253,246,222,239,176,0,105,79,66,248,100,211,232,18,217,109,127,11,57,83,34,123,20,60,137,153,193,152,195,96,127,130,205,193,250,201,146,44,174,91,40,108,105,104,231,248,136,114,61,136,124,241,31,128,186,165,230,218,248,76,54,35,51,13,80,241,46,59,34,214,111,253,168,149,252,124,4,81,171,131,110,58,165,172,223,166,5,45,240,154,11,195,26,117,137,238,192,41,98,219,74,113,235,25,234,46,9,144,57,228,196,138,122,230,73,229,42,31,24,18,166,217,131,24,95,177,251,18,240,249,10,235,122,112,16,73,162,6,70,8,231,108,54,87,216,194,174,60,128,244,234,190,212,213,146,128,244,187,133,74,29,128,195,60,234,120,57,168,116,97,234,156,164,173,42,225,70,177,38,184,43,121,148,186,19,207,224,19,253,214,102,184,227,77,205,223,63,242,184,142,75,134,48,96,96,243,151,83,50,87,123,186,147,177,176,62,113,237,99,50,108,201,126,185,218,219,219,241,171,55,44,28,194,49,254,72,63,140,63,178,112,216,15,3,183,189,172,230,154,116,254,246,200,73,82,76,41,15,168,132,147,25,115,46,90,151,15,180,193,60,237,178,105,74,47,191,86,59,221,105,248,98,26,140,49,149,76,146,83,229,173,71,134,78,113,171,186,136,69,240,102,228,167,251,86,198,107,167,79,180,215,210,44,58,98,143,79,188,44,133,107,54,248,165,231,104,149,127,120,62,61,159,252,239,41,101,177,140,108,77,90,49,230,151,125,115,153,80,213,191,17,98,59,202,149,108,239,233,23,177,26,245,216,97,198,111,31,75,248,67,177,55,207,157,212,233,20,69,111,167,232,80,21,144,9,32,199,43,200,181,141,195,9,143,237,154,121,175,158,247,124,39,117,184,48,30,51,103,4,19,16,28,84,98,72,251,204,19,32,194,90,236,170,52,202,181,96,92,120,59,184,47,169,66,177,66,217,150,2,50,182,17,7,131,32,76,227,116,70,174,42,90,163,89,35,33,148,41,240,228,253,31,107,201,210,198,152,13,86,70,112,248,225,121,155,252,134,99,239,2,8,98,108,44,76,227,160,213,104,141,16,130,205,118,253,123,220,48,200,187,80,35,114,62,45,188,107,29,79,220,169,244,147,158,70,102,122,231,232,149,243,55,230,115,28,185,83,39,179,237,221,41,170,240,44,143,39,216,163,87,213,39,157,118,225,99,80,190,57,171,200,20,2,7,166,112,211,127,0,69,167,84,159,62,190,37,46,1,194,192,152,94,188,50,203,38,220,128,2,108,156,32,255,174,254,89,135,44,97,26,237,37,203,70,32,238,3,218,163,213,145,32,244,50,67,233,217,30,131,135,205,0,46,29,143,192,99,180,144,34,96,7,74,212,164,44,215,190,88,252,138,84,97,50,251,203,44,252,175,247,178,155,79,180,28,8,80,184,205,211,9,119,150,32,91,150,4,102,212,89,217,117,71,241,163,146,90,113,142,34,228,139,182,236,101,97,47,152,88,91,161,47,37,246,4,92,89,174,210,15,82,44,118,249,82,198,192,155,172,220,91,168,190,233,35,204,84,24,113,139,102,112,42,108,124,19,27,148,60,159,78,38,239,90,234,5,193,172,28,58,20,182,11,43,162,123,82,184,178,167,19,172,101,106,3,69,146,204,136,46,70,35,133,166,103,74,245,222,246,76,109,232,173,160,36,50,39,140,112,227,59,10,18,127,30,232,161,113,146,233,102,248,171,205,245,154,98,101,53,109,65,36,82,31,241,200,111,216,27,255,10,48,237,213,82,221,17,250,248,215,19,150,56,175,233,19,230,30,233,199,3,100,121,176,189,175,63,20,231,105,113,121,51,88,188,231,109,177,58,34,9,199,121,226,157,183,76,219,41,224,204,61,144,124,88,115,7,214,74,179,178,42,119,144,76,98,58,171,185,134,98,123,177,87,100,213,183,165,147,22,29,151,19,74,146,102,107,158,201,189,0,79,185,36,105,84,104,73,152,103,132,228,196,39,102,113,158,255,56,212,198,37,172,139,31,238,98,184,182,42,69,108,194,245,23,205,45,21,76,115,162,181,174,59,213,233,59,240,184,32,212,226,199,126,11,205,232,217,187,51,197,98,94,117,94,105,152,41,48,22,181,8,146,134,207,30,237,255,240,248,183,191,187,67,210,16,185,191,54,193,2,218,22,99,176,191,233,78,247,165,4,231,131,62,37,109,244,76,194,155,129,212,66,0,101,223,162,211,13,80,169,217,16,68,4,155,216,61,35,76,162,144,217,34,209,73,249,250,253,186,140,124,41,237,124,22,168,97,40,95,47,38,188,204,216,150,184,229,185,174,113,3,154,126,238,50,165,170,12,27,209,53,157,76,118,81,252,10,140,31,103,160,43,171,6,65,205,225,154,85,121,76,216,228,29,241,184,200,160,225,86,4,199,137,80,222,199,30,9,163,177,222,131,91,24,3,147,148,250,20,157,246,166,73,41,246,240,159,85,53,172,227,255,239,211,188,78,85,210,198,63,175,149,47,251,126,139,167,245,143,5,212,41,111,52,133,173,37,114,122,63,214,212,6,98,213,169,140,241,226,233,95,47,169,91,89,117,116,228,30,78,123,163,137,11,19,142,70,121,166,215,141,20,57,100,202,75,131,150,222,136,204,79,199,205,220,46,9,129,92,116,55,148,224,138,82,32,255,250,251,59,239,99,130,13,77,106,233,191,37,70,164,141,160,195,95,192,54,39,178,189,46,17,135,160,255,198,62,249,69,57,5,74,22,165,134,209,143,179,8,28,219,212,141,148,242,233,231,171,234,72,186,111,252,84,120,130,253,206,225,145,123,88,19,194,150,24,168,247,191,92,162,203,56,94,55,72,199,142,76,50,37,253,13,142,159,201,100,153,149,243,217,240,192,204,254,66,239,13,23,161,166,210,210,120,35,7,141,179,109,83,57,146,163,16,195,195,129,214,39,34,155,158,29,244,128,143,18,233,121,150,87,80,227,145,22,207,133,15,10,172,79,48,176,209,68,66,116,22,167,251,162,90,108,98,148,98,84,46,164,185,106,48,68,247,163,112,24,15,78,105,58,173,251,63,10,252,91,83,158,57,178,63,21,40,113,231,82,251,191,134,27,71,131,203,150,222,121,48,211,181,0,62,91,119,123,77,252,183,63,204,142,239,211,87,244,129,213,2,81,221,210,104,182,252,35,116,91,198,172,132,76,148,89,3,74,8,96,232,19,70,18,232,128,18,145,133,229,23,13,93,175,174,68,105,55,192,81,168,1,142,132,193,37,99,188,243,51,14,26,6,195,29,149,159,115,77,169,235,22,66,101,37,224,43,146,152,141,191,222,67,12,74,51,124,129,141,11,37,97,10,50,79,112,123,54,180,89,156,10,237,145,90,99,35,116,84,163,249,196,70,103,144,16,14,13,233,42,5,213,163,203,205,92,6,212,210,195,46,141,24,15,1,215,71,30,31,0,4,24,15,93,217,35,228,173,104,78,117,69,140,243,168,119,62,223,200,171,123,57,184,88,64,53,21,153,201,0,115,146,22,119,84,228,16,189,124,213,148,92,15,178,58,83,69,87,213,137,150,254,92,197,211,157,193,255,150,115,3,222,48,64,41,28,208,245,211,29,135,30,54,205,250,93,94,57,155,196,37,151,90,109,165,11,249,203,106,37,64,103,100,206,108,40,181,36,238,104,208,241,13,26,75,32,133,101,47,132,226,199,174,3,139,186,102,206,19,21,6,166,44,184,63,7,255,61,155,90,233,60,161,86,176,23,97,194,237,176,234,251,116,25,226,11,145,130,13,179,158,222,252,26,235,132,202,117,229,195,232,158,52,183,96,47,219,235,210,51,146,103,15,241,22,194,84,73,169,183,142,81,87,203,6,251,105,254,2,56,164,156,137,219,71,205,59,144,217,70,38,73,57,73,70,131,114,20,249,181,50,184,200,127,251,28,30,92,166,20,252,156,141,128,223,214,176,136,154,210,238,245,131,123,1,114,106,160,197,74,57,4,101,162,185,66,93,219,192,225,68,181,231,74,140,180,121,162,114,142,129,187,73,66,192,218,128,28,39,134,251,0,243,48,55,112,205,204,80,144,149,109,100,247,179,224,228,198,89,225,7,131,170,203,32,130,21,23,249,122,134,208,160,239,23,10,91,107,175,27,56,59,104,18,71,209,245,4,165,227,203,178,69,1,114,130,119,193,171,64,18,182,174,155,16,84,193,55,150,153,90,251,6,94,161,253,223,200,143,16,162,175,93,211,88,243,61,118,144,204,158,163,68,183,243,85,64,42,52,155,32,39,213,93,165,239,188,8,152,93,228,136,71,213,103,158,57,252,54,203,34,230,180,127,56,46,22,5,220,190,103,131,16,64,135,114,68,112,125,205,54,108,113,157,5,31,108,20,138,80,149,170,6,114,65,223,21,159,246,115,158,118,220,203,106,20,66,204,213,59,225,109,136,122,206,137,104,126,66,24,195,83,223,112,36,241,154,219,254,255,248,77,142,202,95,86,171,11,42,188,7,245,217,138,49,224,34,61,121,28,57,25,3,70,9,40,108,107,108,211,160,206,154,77,59,153,161,172,200,23,84,154,131,94,122,115,145,19,13,234,127,86,154,80,149,41,50,98,186,251,36,10,53,159,223,103,104,248,67,154,136,228,46,83,243,36,33,221,157,116,83,109,54,89,171,46,252,120,86,50,220,23,252,185,68,192,125,37,223,233,232,110,16,135,71,175,199,37,75,162,17,48,41,32,39,131,59,145,161,20,26,149,216,99,1,188,240,87,189,8,24,224,227,175,207,156,151,37,76,105,62,202,86,172,9,208,0,186,72,213,78,103,254,132,192,92,113,242,42,224,245,111,181,206,107,130,182,212,63,185,27,28,41,112,220,209,148,172,7,140,225,168,124,67,203,73,76,139,41,226,87,30,125,197,216,76,36,160,168,194,202,181,254,134,0,148,187,242,94,239,72,9,21,148,168,92,66,161,144,73,37,106,39,176,127,116,44,183,89,77,47,138,171,10,169,117,147,107,92,29,184,69,82,220,13,130,34,214,197,214,6,152,46,180,228,77,211,162,47,149,169,145,56,196,174,84,97,93,246,216,30,34,211,137,93,8,161,64,73,106,220,60,107,201,86,86,124,51,9,66,244,168,8,22,125,147,200,68,23,23,247,75,139,87,52,54,5,53,175,14,218,127,126,196,104,220,88,75,122,52,99,226,111,88,137,95,199,196,6,2,87,182,200,67,133,205,210,73,174,53,64,12,134,84,182,73,199,7,65,88,7,24,83,187,31,81,35,236,229,37,177,78,42,143,233,94,241,133,195,255,185,7,218,41,43,231,129,3,23,175,147,37,26,188,70,161,146,126,24,12,38,104,96,209,143,227,254,9,198,24,192,4,227,59,174,32,240,251,5,34,127,186,184,83,193,62,41,187,33,39,239,28,16,118,164,36,171,230,136,212,122,52,86,39,165,85,61,117,145,179,83,209,229,95,227,85,170,136,187,59,115,217,179,60,48,21,67,116,58,14,145,89,89,35,229,5,152,217,138,26,10,189,186,35,83,210,174,165,179,87,168,247,177,43,213,204,247,37,109,164,15,182,108,253,170,140,83,214,151,0,211,81,132,64,43,30,248,18,149,11,44,248,98,107,216,117,38,96,167,82,124,152,140,191,51,40,145,207,31,45,189,144,120,151,236,172,94,196,233,80,172,227,217,187,197,174,24,108,153,189,212,51,44,156,203,149,74,222,95,240,202,168,235,255,91,215,29,201,254,8,156,120,134,162,218,172,153,51,254,189,4,238,93,65,227,158,247,6,74,254,126,91,58,204,84,167,188,223,91,180,79,147,62,150,135,231,158,186,185,126,91,13,115,56,108,78,17,205,175,102,47,20,157,73,175,89,225,242,141,119,215,191,236,127,186,252,109,87,164,233,22,213,98,137,134,97,78,12,13,150,30,160,164,149,154,108,167,156,104,67,228,187,152,143,135,114,154,47,7,21,89,131,179,34,253,135,40,109,220,0,127,213,82,85,64,161,1,113,242,240,66,56,78,225,32,59,26,177,12,19,79,6,212,120,217,177,7,187,76,85,122,133,9,219,81,118,109,201,21,119,47,122,30,190,208,241,78,63,16,91,45,44,253,13,228,18,228,187,96,222,132,166,77,100,226,124,234,61,59,174,40,117,26,163,5,65,107,1,95,18,170,126,100,95,216,113,98,15,186,246,133,3,205,221,228,159,206,212,201,240,175,113,198,72,187,233,28,104,253,239,168,246,139,120,149,143,34,146,39,220,145,216,114,243,109,219,151,117,75,33,162,197,181,62,19,128,118,215,96,101,54,68,109,7,171,133,54,145,1,15,56,224,58,123,172,196,221,3,133,158,85,120,21,246,153,166,1,17,66,48,223,247,230,95,15,223,253,250,109,197,6,190,76,117,7,245,185,143,129,188,191,215,198,20,90,194,172,250,78,233,102,182,120,92,116,208,65,80,84,235,77,57,207,221,127,16,225,96,218,22,104,216,138,195,220,101,236,3,109,87,42,198,95,96,164,202,48,107,45,17,107,246,2,243,229,149,152,83,101,228,91,80,183,254,119,138,201,64,197,135,212,15,171,151,44,69,249,208,188,57,253,250,157,63,153,226,131,155,3,224,56,103,144,28,200,229,192,71,131,21,129,219,235,31,205,144,191,146,253,77,67,78,216,241,242,228,244,174,123,254,65,212,26,35,218,100,1,28,145,247,37,254,116,206,212,40,200,241,209,30,238,181,165,198,211,144,87,158,142,226,70,232,172,134,42,41,121,222,108,17,68,45,47,16,56,26,77,188,99,188,115,118,252,245,11,51,25,44,27,128,31,32,221,54,158,109,102,53,155,4,245,73,26,234,174,198,111,64,52,171,213,56,173,114,145,152,204,191,140,179,22,93,211,35,243,221,136,103,201,155,0,41,110,183,62,30,176,252,190,108,47,23,203,166,160,173,17,124,11,189,244,44,4,13,133,74,224,19,240,200,254,27,57,180,193,89,67,10,147,117,127,169,109,96,98,8,10,21,26,37,181,81,247,202,60,172,58,139,237,116,143,140,46,52,176,49,71,231,243,80,161,14,219,152,25,62,178,232,150,162,47,124,122,155,221,61,212,160,224,158,136,39,24,24,159,93,108,6,145,49,245,189,95,22,153,45,100,83,225,12,97,201,53,242,6,2,23,210,62,108,106,189,178,189,42,64,247,93,171,233,157,196,159,103,239,240,111,60,164,43,151,83,198,183,204,37,185,207,113,120,130,103,10,4,90,144,149,54,51,128,82,233,108,119,172,85,82,79,203,25,184,22,113,202,100,46,34,121,95,234,102,43,243,242,211,223,171,133,152,188,18,134,67,47,2,94,11,17,249,254,0,115,150,132,37,136,76,84,42,91,153,219,138,4,233,91,164,1,243,162,12,134,75,244,55,138,40,252,182,74,245,239,39,45,157,106,56,118,130,15,190,210,138,155,237,239,57,182,77,69,190,113,237,27,178,173,214,149,95,133,12,106,208,89,63,129,174,51,58,43,142,103,103,138,109,123,39,101,45,171,1,233,54,34,208,63,121,151,241,39,0,207,133,172,100,150,134,5,196,133,184,171,253,201,139,186,75,242,123,53,174,38,249,95,72,254,64,108,209,147,37,177,166,69,3,178,95,255,47,41,195,232,6,73,119,89,203,225,150,80,125,183,56,28,82,112,89,167,237,204,73,139,208,233,7,168,90,35,244,133,50,216,254,240,80,227,187,102,135,27,213,192,201,21,175,236,199,100,103,36,247,192,4,133,40,125,16,111,25,177,101,37,180,170,49,230,106,169,123,73,58,231,60,106,230,145,116,211,215,134,199,90,18,243,210,29,225,79,224,248,108,204,147,215,73,244,75,154,145,95,137,151,193,154,146,43,242,175,5,62,42,113,9,57,70,59,133,75,165,250,154,186,143,167,22,47,252,137,102,87,181,104,147,207,195,205,88,18,48,209,126,182,35,179,10,30,175,25,163,6,202,85,185,99,52,208,20,19,242,169,14,253,227,198,85,129,68,11,99,112,59,79,142,105,188,254,123,148,88,153,70,89,84,106,236,34,181,241,51,194,138,62,14,134,245,151,117,235,135,10,139,140,204,146,196,96,242,114,217,131,102,142,129,65,132,108,64,29,42,233,238,33,19,249,17,222,195,125,158,124,202,110,18,183,150,111,199,70,127,8,180,135,203,33,143,230,228,90,44,43,118,241,57,168,162,89,150,106,102,32,60,250,93,143,196,239,12,214,171,73,180,196,199,210,115,112,192,13,9,123,222,213,148,91,19,101,236,101,30,146,43,164,10,156,101,112,151,65,89,151,245,154,56,37,194,99,153,35,80,3,93,62,246,6,68,42,34,155,207,230,215,121,37,213,153,36,165,136,123,181,144,31,215,138,161,118,151,196,108,131,138,93,13,158,182,138,197,184,0,44,139,70,0,204,15,179,245,235,111,229,61,119,1,248,135,70,169,50,116,69,16,223,77,223,248,176,81,63,205,104,150,100,178,216,215,7,243,251,58,16,117,59,213,117,122,156,183,0,72,126,132,100,86,92,240,106,174,220,88,51,75,166,111,176,139,229,215,30,173,166,246,249,201,187,24,250,69,150,214,224,9,17,218,53,173,213,254,11,60,19,32,202,124,40,131,51,99,223,226,217,190,252,29,14,39,73,199,37,180,254,114,46,169,46,109,205,172,86,62,198,113,209,186,149,211,122,42,239,238,71,133,33,39,217,86,131,68,199,243,26,0,143,97,215,140,217,34,11,55,192,118,66,69,203,200,128,171,40,250,94,127,204,76,168,232,153,226,37,150,4,8,22,177,75,64,204,39,19,45,127,173,174,14,222,159,184,66,88,61,250,133,231,114,166,164,33,157,77,203,31,222,189,111,131,178,107,117,10,165,203,18,211,117,188,134,254,238,158,123,143,231,245,189,89,21,88,66,169,241,24,26,210,108,105,249,56,37,196,36,26,110,237,31,34,198,114,72,218,133,14,40,38,0,26,218,130,56,146,228,86,253,43,36,112,162,58,232,178,162,105,114,186,74,187,229,215,195,101,241,14,24,95,246,248,101,255,68,164,79,41,18,245,65,11,228,167,132,169,52,170,196,91,52,224,204,230,105,193,231,254,49,143,85,42,221,140,233,18,131,116,86,127,103,136,113,15,23,95,39,90,226,59,168,56,73,43,227,171,60,251,5,66,24,207,129,225,168,127,243,190,108,173,215,76,110,107,75,120,242,147,252,217,57,234,116,1,133,221,90,162,174,126,61,236,200,53,105,71,155,217,56,85,6,214,13,60,119,234,225,200,186,152,215,237,225,105,85,252,240,252,38,75,220,200,6,243,144,34,127,161,14,197,107,63,75,235,195,72,44,27,244,129,243,201,59,241,45,173,62,200,145,232,76,142,208,183,15,77,119,157,26,157,170,159,104,206,13,248,132,68,229,234,196,252,168,229,154,203,44,177,54,200,235,132,93,52,10,196,60,152,226,220,27,98,85,215,82,144,161,12,76,202,47,71,231,225,223,105,35,201,195,174,188,10,168,199,141,255,108,74,166,226,33,4,203,54,202,178,27,127,250,86,181,225,246,70,219,65,173,49,214,202,71,22,67,184,54,90,182,251,202,40,14,235,63,201,190,75,65,15,33,62,81,56,157,55,187,67,3,223,5,188,105,211,72,202,95,229,207,20,1,219,121,116,56,5,116,227,97,48,200,192,252,86,238,56,125,89,89,89,100,76,5,180,81,31,33,111,202,211,182,51,25,81,28,239,153,125,85,67,149,136,118,157,65,84,65,43,74,86,81,238,45,7,227,222,145,234,95,152,157,225,22,53,47,59,189,252,16,40,26,171,155,247,98,73,206,206,218,9,241,152,213,3,15,107,123,100,86,78,2,200,194,8,78,101,235,150,113,69,232,13,102,131,200,41,240,126,186,238,184,20,62,218,235,221,116,53,44,20,219,104,254,112,139,81,119,100,253,105,53,62,247,159,166,75,128,64,51,7,193,108,154,115,34,146,127,75,102,17,112,81,35,33,255,104,228,11,97,24,252,219,214,122,235,2,28,34,128,252,220,126,248,87,48,200,149,102,191,135,59,48,111,142,210,22,87,41,25,209,90,114,67,98,234,128,53,45,198,155,116,161,66,14,216,226,63,200,18,7,20,213,60,221,77,128,48,20,142,208,197,61,210,161,90,77,80,146,220,80,168,29,93,171,234,195,182,134,136,225,120,206,94,147,141,52,199,5,155,74,143,12,252,50,79,254,135,78,145,222,143,150,128,28,137,206,79,88,83,195,0,213,182,223,225,201,191,235,235,39,175,202,211,139,11,109,8,255,251,237,232,33,37,250,169,184,42,115,205,55,220,211,160,190,225,201,208,87,227,181,15,92,123,111,172,104,71,23,236,206,214,177,119,77,128,149,238,102,224,147,48,143,82,158,83,179,110,112,12,75,86,190,48,208,14,156,92,140,55,64,14,23,106,204,140,48,97,72,62,247,14,217,121,31,224,171,233,69,177,129,185,71,17,87,96,138,78,19,178,198,229,37,235,51,51,208,149,100,111,39,54,197,126,215,245,125,0,18,64,157,246,4,183,62,21,82,209,182,193,74,163,255,99,143,38,119,30,171,116,62,129,241,64,167,205,128,48,19,141,208,126,96,231,17,94,11,123,106,132,252,127,95,4,217,84,100,231,9,56,144,178,55,92,107,154,194,164,113,19,93,117,152,188,49,241,135,95,131,177,63,10,247,179,86,47,153,63,125,70,239,205,3,48,196,135,152,123,146,5,229,21,112,255,72,4,180,42,148,238,234,211,163,111,223,49,176,36,101,182,121,145,65,242,151,27,181,100,235,212,127,238,78,165,2,36,188,117,89,217,137,39,32,249,156,72,106,48,65,177,35,119,166,109,125,93,15,74,133,194,177,8,208,79,4,23,216,37,3,20,67,12,40,52,11,160,213,96,177,234,40,240,251,19,126,81,186,153,249,204,11,91,78,70,238,38,31,243,13,156,49,165,95,148,218,155,179,139,30,216,15,153,27,164,59,189,173,159,141,146,16,21,167,183,161,203,82,140,66,150,182,16,73,40,176,102,55,118,132,173,249,137,117,137,145,90,53,86,164,24,152,171,14,64,192,181,253,238,22,204,59,115,228,173,155,232,15,108,250,14,135,190,177,25,54,114,152,83,38,132,125,185,243,134,112,168,170,99,100,155,125,107,46,165,146,10,12,243,170,39,155,195,220,140,129,9,27,178,166,144,112,200,134,3,146,228,27,60,217,251,147,93,72,56,196,158,217,177,53,113,146,111,93,172,7,71,165,196,105,120,164,255,79,158,235,183,45,61,139,128,87,87,24,202,89,236,50,129,135,90,217,225,115,211,102,32,22,124,87,167,76,209,47,193,179,5,176,1,172,115,53,235,4,198,69,17,146,1,156,60,169,171,3,154,137,1,8,160,180,39,33,145,194,221,167,74,225,147,22,226,175,161,190,155,99,104,36,234,28,206,255,153,106,146,140,248,208,160,159,129,189,81,79,151,34,57,191,19,60,238,132,173,126,112,102,40,167,236,248,169,15,165,62,167,248,117,241,242,52,190,179,82,62,174,253,135,166,242,116,101,164,25,44,212,205,199,182,51,26,85,54,11,16,243,103,183,145,84,222,115,193,84,191,14,243,49,214,76,187,20,39,29,243,173,156,181,219,109,64,24,75,52,179,28,160,231,99,85,33,44,165,96,91,1,116,151,203,247,43,74,128,179,172,198,31,77,89,11,160,120,13,159,140,72,217,110,79,78,206,233,178,98,50,152,74,216,73,133,249,217,70,75,56,129,241,107,234,100,37,103,60,16,188,2,190,11,70,104,226,153,93,247,153,143,161,19,20,220,168,207,59,231,145,117,83,136,104,18,107,25,84,26,105,116,169,98,24,122,32,236,228,193,206,223,235,29,238,49,143,225,2,196,58,61,127,140,102,14,140,100,86,158,130,245,106,213,21,195,130,77,170,38,87,189,28,239,43,9,141,221,172,71,101,23,117,196,97,176,152,245,228,11,197,252,84,206,70,36,202,196,205,27,80,137,39,25,75,180,73,162,224,150,97,44,115,24,151,153,239,190,250,64,81,124,193,49,199,158,225,239,216,251,150,194,11,43,136,66,171,93,122,163,101,50,248,76,30,251,201,114,80,75,69,109,212,155,11,141,217,118,95,15,127,174,149,147,216,251,178,89,253,92,51,157,16,128,60,144,26,219,47,131,125,182,76,241,164,209,6,26,7,92,85,220,173,245,230,208,98,209,124,70,173,192,190,132,55,211,201,186,183,60,108,73,202,134,11,25,98,22,219,173,173,140,39,222,243,91,17,177,81,168,144,244,94,105,34,211,227,16,134,9,254,20,51,4,182,243,203,82,63,238,89,246,230,147,185,200,52,129,113,141,167,177,99,18,247,119,52,84,13,203,187,89,98,35,178,30,13,149,205,77,136,197,164,183,202,225,132,158,34,253,166,180,170,81,56,53,16,116,34,149,120,212,66,17,226,5,193,175,148,81,251,230,23,177,141,43,79,103,153,84,172,51,44,242,34,237,188,74,225,118,144,129,40,56,96,157,254,134,231,14,209,110,23,26,41,253,29,33,247,80,149,196,100,34,23,183,198,124,246,191,174,56,254,31,119,127,229,154,236,190,38,98,101,91,126,182,201,156,27,210,62,101,17,18,95,17,62,112,173,218,95,8,203,29,169,3,23,137,111,219,234,54,156,50,148,31,227,60,56,205,74,105,149,45,57,162,39,83,232,38,150,169,204,161,15,212,82,220,124,196,127,1,123,135,186,208,13,210,224,127,223,143,131,107,123,201,10,21,58,99,135,64,212,81,242,174,16,20,198,65,72,42,58,79,59,206,26,52,133,57,223,232,6,119,87,13,47,214,82,42,153,242,77,203,163,205,22,188,0,129,78,179,114,86,63,119,183,248,180,74,200,49,174,239,118,170,130,129,69,61,251,182,192,219,239,214,192,255,58,247,26,49,105,232,74,79,103,145,214,114,231,134,233,230,182,242,244,118,246,117,136,107,207,19,107,184,247,251,123,157,189,96,101,189,162,223,179,99,10,86,165,128,163,231,16,244,57,68,233,20,250,104,28,166,38,49,110,177,66,17,127,187,199,42,122,137,238,193,107,95,247,227,189,113,10,75,176,213,70,136,141,144,164,87,37,42,23,127,141,164,183,78,139,218,128,235,216,244,18,237,172,200,24,113,21,112,117,16,59,41,136,9,155,210,169,170,75,221,91,65,24,147,102,178,110,106,220,193,124,222,37,240,191,119,132,54,85,182,115,221,35,234,48,168,174,45,235,227,126,189,190,94,228,240,101,211,112,91,127,57,151,48,255,55,129,17,139,254,252,80,114,75,182,22,51,188,91,109,69,192,230,36,179,138,232,162,3,131,1,137,52,56,241,139,77,224,236,177,175,210,192,80,187,135,105,224,116,81,229,132,151,223,232,67,207,191,76,55,255,26,58,42,239,48,161,0,251,40,166,214,231,173,40,122,99,165,8,170,84,14,152,38,0,60,172,198,70,127,95,75,16,127,6,6,164,64,141,172,238,59,222,131,224,43,38,141,127,96,100,62,2,30,34,180,54,230,3,150,5,231,193,31,96,61,201,7,121,144,136,49,68,114,1,180,193,165,67,117,98,92,230,45,153,167,120,227,39,220,201,40,218,176,242,79,255,176,197,84,44,219,188,24,123,109,252,180,10,54,56,205,152,158,23,34,226,122,114,118,86,190,135,145,210,139,53,111,80,254,12,33,99,114,50,69,174,102,63,40,134,203,163,241,201,210,132,197,30,194,21,41,67,111,169,59,137,176,140,87,223,35,219,148,41,17,47,87,132,177,195,184,155,62,44,57,51,61,166,176,0,78,17,239,248,132,24,90,111,0,114,11,243,116,156,217,62,172,237,169,184,102,49,203,132,170,173,228,19,92,247,110,129,213,51,246,166,189,117,14,122,133,32,168,49,250,110,109,130,233,47,207,247,73,245,53,4,163,18,37,68,143,96,159,144,46,41,170,94,167,114,150,192,69,209,251,219,13,111,213,186,98,240,94,100,151,249,137,215,40,31,202,233,102,233,87,154,45,180,231,125,239,156,180,218,112,223,97,62,42,141,65,252,126,67,80,247,250,233,208,232,35,192,160,163,194,226,126,10,45,236,6,185,108,216,204,37,163,11,79,111,48,215,146,155,158,134,141,203,55,89,61,222,33,78,82,125,74,58,124,11,39,39,25,125,19,251,109,165,69,192,6,62,4,243,172,60,180,97,171,114,245,37,98,216,173,83,172,42,223,203,123,98,129,233,163,55,50,102,117,207,223,131,8,155,151,246,17,163,194,153,249,69,72,100,93,139,51,97,70,143,174,24,21,44,73,67,97,203,26,232,224,113,226,185,74,242,203,51,164,179,209,188,168,1,102,93,74,120,214,135,191,193,209,7,112,218,199,145,10,92,23,239,226,242,205,187,159,126,171,125,35,158,53,118,74,19,183,224,31,116,118,13,32,211,205,92,131,123,48,181,32,124,7,233,247,254,24,251,109,189,0,184,187,80,73,194,94,100,239,81,170,145,20,235,132,230,56,141,90,22,151,198,88,153,66,134,20,94,237,62,58,110,218,255,50,111,198,109,211,202,21,39,7,30,238,147,85,35,154,58,236,112,221,70,102,211,120,115,74,109,188,70,229,214,191,122,134,120,195,231,217,122,35,113,9,110,154,50,82,32,35,111,159,191,205,52,223,124,250,77,32,228,68,131,215,255,245,107,10,80,105,104,31,4,173,207,219,31,219,171,182,182,254,211,181,183,202,185,238,165,167,38,248,72,193,90,249,154,165,80,64,209,68,160,49,226,93,135,143,48,97,211,47,187,29,120,160,203,115,39,87,245,227,220,244,5,60,57,251,126,42,117,244,81,69,98,77,242,210,249,188,19,130,253,198,56,95,174,249,187,185,215,132,16,226,25,29,180,25,54,143,69,121,134,79,117,180,218,210,211,236,58,207,231,69,104,95,149,166,212,59,105,131,68,83,21,233,177,143,135,83,237,99,3,20,58,123,234,249,128,199,117,238,163,124,52,215,100,124,76,146,61,253,192,135,196,87,201,115,149,98,141,214,85,252,207,188,13,34,208,166,93,132,22,39,44,115,121,203,93,78,137,69,196,253,197,120,148,36,21,208,5,95,43,5,122,145,41,160,12,117,201,143,36,62,133,73,185,73,185,155,194,182,166,248,96,33,9,112,7,42,39,42,203,253,23,196,161,187,66,234,58,217,44,48,7,139,47,158,58,153,179,83,189,27,100,164,156,234,199,98,117,100,38,11,24,163,169,221,244,159,173,191,177,229,194,60,25,229,142,239,38,104,95,145,238,47,214,188,90,21,66,126,66,111,210,228,101,36,242,172,130,97,234,90,20,62,166,38,11,198,159,44,245,249,131,27,135,234,87,83,2,62,185,253,129,60,125,165,26,164,138,148,193,87,246,201,45,72,3,33,31,191,29,45,33,15,238,109,8,39,100,38,195,128,83,7,133,205,161,144,113,161,194,75,111,13,7,188,92,227,251,80,96,18,64,26,145,25,40,183,204,243,127,122,119,214,146,16,231,175,187,101,92,23,25,172,45,195,139,252,212,135,73,86,24,33,203,30,64,143,202,39,238,180,143,39,141,32,30,65,76,186,57,211,14,143,45,98,183,16,106,103,221,249,6,53,137,24,139,142,183,198,247,95,139,222,54,254,33,32,110,206,70,243,213,3,192,199,172,149,164,83,182,93,148,177,50,21,141,173,13,238,107,195,127,67,110,37,112,43,142,183,230,190,209,160,162,156,23,27,134,24,34,52,140,72,249,61,178,169,148,8,130,66,147,91,31,208,121,252,240,86,4,49,94,172,145,170,231,175,155,91,81,34,65,35,19,119,54,89,16,204,192,75,121,73,147,188,144,117,13,228,38,41,170,216,212,138,219,190,30,66,160,168,25,44,46,139,91,239,138,252,75,214,254,70,38,167,102,27,83,199,3,87,193,132,173,198,46,20,126,199,149,77,169,28,80,101,104,137,62,96,184,186,195,156,232,54,165,152,181,234,109,221,187,146,210,235,81,120,213,202,4,54,76,73,143,91,58,186,245,234,169,42,230,22,18,250,90,107,166,223,111,105,64,154,164,4,224,90,136,137,59,115,161,111,33,203,195,109,85,228,153,230,42,60,71,72,5,2,62,18,247,95,210,226,191,18,86,215,250,188,187,220,235,252,237,222,248,38,43,49,68,167,200,78,234,221,147,5,179,21,224,63,87,13,134,86,163,63,36,111,99,183,191,107,252,17,109,125,244,237,227,124,248,96,249,123,151,124,55,89,15,60,83,228,51,167,78,178,149,160,185,115,84,80,74,205,223,140,130,90,11,7,178,123,40,235,140,10,228,159,27,22,21,27,35,97,198,101,3,45,152,101,159,133,198,240,50,167,96,88,76,87,206,44,39,249,11,105,101,233,91,94,0,117,182,228,62,63,40,7,175,93,108,94,109,10,13,105,155,235,242,84,115,42,225,207,146,64,214,155,15,160,204,116,101,205,129,106,90,130,161,1,205,66,106,134,110,197,2,121,251,255,76,57,17,131,177,22,249,53,191,239,3,209,175,23,202,194,236,120,82,27,150,175,201,140,218,92,66,6,242,27,242,72,21,153,249,76,147,161,201,108,133,37,82,63,157,26,16,157,157,53,227,144,45,33,251,159,166,102,14,146,8,130,61,71,232,239,55,149,154,94,62,201,196,46,66,64,182,197,173,177,174,129,184,239,93,144,26,35,78,229,198,0,35,11,0,24,58,31,116,17,14,148,173,217,199,57,30,154,70,63,65,205,96,139,15,161,221,167,15,248,53,144,210,247,198,28,89,183,77,185,161,137,46,60,33,250,124,201,6,162,14,149,173,139,246,183,196,97,174,62,140,41,85,124,32,241,157,180,188,116,43,88,101,206,143,162,87,136,175,53,8,137,29,26,223,233,139,150,187,232,66,160,175,236,60,249,74,124,88,0,169,71,249,158,190,158,10,136,161,14,192,129,205,123,206,139,139,194,116,10,232,178,229,135,29,133,175,175,159,206,251,200,116,49,111,179,231,204,59,114,82,198,44,18,188,92,104,214,214,0,99,131,131,20,13,139,95,163,166,89,240,125,147,162,92,27,236,208,194,108,76,213,90,135,100,0,183,53,71,191,95,49,61,227,177,149,62,19,73,102,79,254,208,162,75,217,114,173,130,116,114,179,103,102,51,151,84,216,208,210,52,137,180,99,72,124,128,249,247,136,183,36,28,249,242,125,70,239,231,22,75,183,222,194,216,180,98,166,182,159,27,186,214,74,253,234,220,112,80,103,58,215,113,70,28,68,149,92,181,110,119,67,179,179,9,96,140,249,194,72,173,244,144,58,9,141,246,68,237,118,179,124,164,96,125,30,196,126,104,19,176,107,25,7,162,89,236,206,184,139,167,166,16,55,67,7,93,251,90,252,86,252,171,140,238,114,28,106,253,2,64,26,18,192,199,145,70,224,41,158,81,211,254,47,235,74,231,215,176,97,187,165,209,79,109,189,21,14,209,97,193,29,254,42,24,157,72,5,143,9,214,54,90,86,243,143,140,12,163,2,158,213,69,48,232,80,165,123,73,197,247,8,241,232,198,127,142,153,236,153,145,20,27,64,72,56,14,13,147,102,116,211,20,44,176,108,13,229,36,230,81,206,9,197,5,42,177,137,125,239,52,138,145,92,76,16,223,134,138,221,234,177,91,177,210,67,1,151,117,176,201,125,211,227,144,217,180,31,53,97,31,147,33,222,114,225,63,236,245,62,68,54,30,147,134,96,110,84,124,209,201,141,3,62,115,79,24,228,194,3,74,218,184,3,66,224,170,40,123,37,121,61,129,54,53,103,197,43,89,135,6,26,104,193,193,136,152,56,142,183,224,128,35,138,123,231,218,184,64,116,133,134,79,71,93,163,18,65,127,217,137,72,42,147,44,193,117,255,58,201,221,139,83,224,169,171,21,200,243,196,43,229,12,27,96,110,87,50,136,174,144,220,236,35,210,9,136,71,10,14,95,205,206,230,46,210,240,140,197,31,1,18,188,0,238,15,228,67,49,220,86,132,126,70,124,204,88,118,84,251,214,36,171,200,70,160,93,190,20,193,149,122,208,201,60,231,13,227,143,217,98,120,101,241,47,166,37,0,246,166,53,179,69,210,170,111,102,237,39,29,58,140,90,17,30,66,50,240,135,134,156,130,216,158,96,227,238,43,173,150,62,156,252,12,213,121,200,99,178,38,253,248,51,29,232,51,139,88,26,160,174,235,4,96,47,68,39,65,224,118,4,246,129,110,151,23,33,196,101,107,18,57,33,181,138,239,175,105,157,49,247,51,175,4,49,223,166,210,239,121,16,164,212,230,198,33,63,150,165,9,54,147,43,215,241,224,55,27,106,204,89,39,184,161,80,49,4,115,240,147,14,244,80,211,157,188,47,240,27,232,175,82,215,194,147,55,86,12,143,240,196,252,206,171,147,238,96,167,220,204,222,124,57,43,217,33,94,205,196,224,116,99,78,12,233,159,227,1,76,43,79,235,217,146,66,161,211,175,94,65,74,199,243,183,6,81,84,203,242,106,233,76,173,158,214,45,43,108,174,250,106,136,126,230,63,14,251,213,18,71,87,50,64,255,236,85,183,102,109,45,1,174,202,9,149,185,253,197,58,210,45,138,136,51,85,221,138,73,184,106,127,134,253,72,58,18,180,62,151,29,82,139,220,202,116,64,248,20,81,96,109,47,138,242,186,193,36,58,228,83,194,172,38,0,252,218,244,10,112,115,142,57,210,57,11,64,200,229,159,61,193,101,132,118,218,80,148,208,24,56,50,42,216,65,221,198,222,42,94,40,195,189,60,175,28,71,25,114,164,42,45,8,67,46,142,204,238,25,167,37,150,221,46,11,216,39,161,104,150,116,113,1,94,67,6,9,155,180,85,217,5,244,160,99,51,203,177,93,136,13,60,29,150,143,141,45,240,202,86,52,252,208,169,251,4,6,159,54,129,123,18,109,207,1,191,79,38,187,105,43,96,244,160,246,58,53,1,126,98,82,106,12,250,65,44,103,65,155,146,190,0,201,249,32,20,57,171,220,149,156,114,51,66,148,220,137,156,113,120,32,169,126,124,13,130,177,138,31,55,46,148,240,128,29,71,141,116,145,112,8,66,189,190,216,123,114,164,94,213,103,242,213,46,100,240,150,169,179,251,110,47,164,50,174,245,163,245,59,14,243,8,35,82,74,151,19,130,70,32,129,139,54,14,190,35,131,230,71,44,133,253,187,52,219,118,239,235,58,76,31,196,252,32,242,187,197,157,187,55,29,121,51,214,250,24,234,46,96,133,232,102,63,43,191,186,226,113,189,64,205,186,249,119,43,113,194,61,250,58,221,69,191,75,14,152,187,167,243,108,156,124,46,5,218,175,243,118,7,240,85,167,144,192,213,61,210,252,162,165,162,46,86,124,240,63,149,35,88,159,198,71,207,56,140,25,144,133,248,190,191,241,252,13,124,234,108,165,9,106,44,119,178,102,193,221,168,140,143,125,102,211,106,41,163,241,103,12,131,227,10,78,64,224,131,209,128,108,224,131,81,196,188,208,57,0,65,7,171,245,92,68,97,155,26,19,0,220,173,153,62,182,16,55,19,229,89,135,80,157,145,162,168,60,3,54,77,8,252,62,78,45,97,13,187,5,95,233,221,143,244,218,237,9,191,191,111,230,19,235,185,24,229,133,236,211,127,22,70,243,186,237,63,6,52,140,155,111,172,124,143,130,20,198,240,17,48,164,10,74,221,17,240,102,82,73,186,66,214,132,28,226,189,253,197,216,71,13,102,76,54,192,250,157,250,97,33,169,125,119,76,18,127,148,89,55,79,41,27,171,173,241,40,25,242,210,152,51,104,129,66,79,162,178,205,127,78,159,148,90,244,237,62,200,220,157,71,215,30,45,95,17,166,151,2,107,156,25,214,202,113,205,64,70,182,24,9,62,176,176,190,16,176,188,96,117,242,77,22,88,50,108,118,138,246,209,82,199,143,160,77,201,121,197,140,194,143,8,181,195,45,95,221,40,139,214,14,153,166,70,195,180,165,102,177,227,237,193,79,231,55,66,91,102,116,212,200,47,182,152,106,44,255,140,122,66,158,160,250,117,112,5,28,227,9,101,161,115,43,75,216,160,129,201,85,4,155,212,168,94,163,160,204,9,102,25,233,102,160,184,227,106,238,100,129,31,84,122,126,254,145,223,210,150,80,172,229,177,248,245,3,169,238,5,16,2,78,51,54,207,82,72,227,99,136,26,105,129,53,22,17,45,214,181,195,68,36,56,169,195,242,5,8,191,67,154,4,98,246,26,112,153,140,77,237,240,2,154,115,169,245,170,100,202,110,18,149,98,123,104,24,71,192,232,157,222,215,83,47,36,18,129,246,103,237,227,185,218,144,30,199,136,151,160,138,100,74,32,166,208,86,67,75,237,132,120,166,153,52,64,10,225,171,2,81,131,86,59,191,48,93,62,184,125,186,164,181,232,91,66,146,242,21,173,53,43,188,74,248,215,108,185,224,167,76,81,71,206,93,12,235,166,22,241,224,190,133,235,131,111,103,60,230,112,49,52,171,86,194,94,59,123,115,191,87,69,241,194,32,229,82,37,247,66,83,202,39,30,54,213,89,3,78,249,44,22,248,167,57,0,84,189,32,168,147,103,6,140,148,202,187,193,37,38,180,46,29,166,57,72,223,230,106,44,108,111,251,141,251,89,7,111,191,116,203,52,57,144,49,241,196,170,155,145,94,130,81,6,8,48,239,173,230,55,130,69,187,163,225,66,214,151,106,237,182,124,152,252,164,152,71,188,138,18,156,234,158,96,75,48,112,107,71,163,19,180,198,24,225,112,151,114,89,6,217,49,26,232,78,138,51,90,69,91,193,126,130,54,20,217,158,121,249,61,85,203,2,97,83,109,237,170,254,0,91,197,122,244,126,45,233,234,109,127,179,19,219,93,31,65,76,94,19,176,192,62,20,225,161,144,181,212,117,211,254,177,20,119,165,4,191,21,105,172,116,103,36,198,101,166,240,111,212,21,87,239,249,26,153,242,52,76,142,34,251,237,81,66,187,57,122,29,236,37,110,21,148,230,218,247,104,63,1,234,5,69,199,73,134,157,172,42,231,147,224,75,141,129,211,82,4,89,195,246,70,171,181,93,183,55,108,159,166,33,84,4,185,111,204,210,203,121,247,47,11,38,196,128,175,73,224,158,13,7,251,219,162,20,164,80,64,199,241,117,6,96,69,101,173,208,37,165,211,107,165,193,43,31,159,138,214,247,2,33,12,191,208,158,105,240,17,229,141,41,237,45,38,45,115,88,232,28,191,188,150,228,13,47,17,235,94,149,41,105,96,203,124,26,222,106,9,189,50,92,15,120,136,57,57,255,99,51,112,155,217,186,209,181,137,48,198,43,39,230,86,230,26,217,240,223,93,238,195,80,220,79,238,160,255,161,52,146,25,191,179,0,106,203,39,179,207,46,133,153,151,239,88,57,122,189,135,89,178,115,230,216,10,114,143,251,93,168,61,169,202,150,202,196,237,75,49,182,183,125,110,19,34,1,136,14,89,81,155,227,118,201,69,250,152,109,216,132,250,88,147,48,2,191,100,195,211,13,126,162,119,72,133,229,123,207,22,23,212,210,63,155,150,227,57,166,222,129,67,70,42,85,154,245,247,41,193,230,95,156,113,40,103,226,86,19,6,181,49,124,103,224,189,223,33,119,236,24,20,229,68,141,154,5,89,177,163,212,125,152,33,38,48,226,24,141,151,158,51,86,207,22,139,80,172,113,125,82,37,229,71,24,29,22,151,195,95,177,29,49,74,158,121,217,68,52,92,168,158,88,196,251,22,3,155,79,122,252,156,221,200,181,70,100,216,71,156,175,156,86,2,231,130,108,43,211,119,75,181,114,163,95,222,24,246,255,186,183,186,101,37,137,223,53,194,47,117,58,55,235,209,179,14,167,242,26,134,221,36,193,38,118,184,207,96,67,32,145,250,154,128,94,25,66,185,48,57,213,130,222,58,197,173,252,78,101,199,141,206,155,94,81,157,155,216,239,200,168,141,203,59,210,55,17,55,170,5,110,70,51,20,19,17,219,187,198,121,220,48,135,101,52,185,215,244,4,37,229,220,138,211,126,144,244,210,14,194,134,9,176,26,52,128,5,94,173,63,199,171,196,37,142,16,185,13,98,224,38,105,153,24,182,124,179,35,177,69,226,224,127,75,236,2,98,7,44,185,3,14,107,156,129,152,51,36,29,203,211,203,108,162,74,162,216,89,12,128,9,112,14,157,147,3,227,248,177,51,228,239,231,213,231,254,82,42,244,137,106,99,170,156,192,66,71,139,213,5,156,125,195,124,229,130,190,205,89,225,241,254,176,95,30,219,40,248,129,218,116,222,75,183,241,249,60,88,178,52,92,157,156,113,232,162,36,107,47,55,17,155,162,70,224,125,82,84,211,203,26,49,246,193,94,207,161,122,216,126,138,16,206,87,28,38,45,30,196,186,30,68,206,95,156,208,218,236,93,107,125,217,121,46,223,4,69,183,46,238,206,71,72,167,159,167,48,118,25,0,159,147,140,99,166,172,4,113,21,161,52,102,54,219,194,90,106,50,6,156,202,21,86,112,33,45,53,6,124,162,83,226,178,246,1,165,167,177,190,237,128,219,79,114,30,187,31,146,10,157,251,80,124,108,191,233,91,104,68,35,156,13,54,123,191,37,77,245,82,222,206,8,246,133,27,217,87,116,7,145,65,128,81,142,250,19,137,207,10,217,88,150,119,183,30,231,123,9,189,145,113,150,247,204,148,101,142,228,144,127,101,122,157,153,221,45,112,44,139,13,223,94,18,221,245,14,185,252,132,117,15,173,122,121,1,251,109,2,107,25,97,29,180,199,11,124,161,138,37,92,119,254,245,118,34,128,28,100,200,80,5,114,99,208,232,126,215,247,226,193,129,111,229,166,12,107,30,67,118,84,156,100,158,204,44,28,118,134,227,10,22,153,126,77,13,134,137,18,167,115,62,98,60,182,179,66,109,93,146,39,135,247,137,193,45,175,156,83,87,217,63,250,57,154,128,151,152,45,35,43,126,198,229,219,126,200,145,4,236,251,153,196,162,89,73,134,96,119,107,128,190,147,228,64,73,220,100,124,73,203,91,213,77,92,68,50,107,69,237,110,138,228,193,175,162,213,78,39,118,105,39,11,196,157,25,195,35,53,250,121,123,219,197,179,143,206,30,210,251,106,231,243,37,84,55,23,7,30,84,11,121,92,53,9,191,28,49,57,237,112,78,183,12,215,243,99,159,238,14,246,197,136,207,69,0,120,99,89,37,184,54,94,128,204,224,174,118,50,226,59,151,162,115,167,144,223,213,199,4,87,55,193,10,212,169,238,242,254,70,213,252,87,32,245,18,157,79,122,232,143,103,31,93,140,93,243,91,156,91,223,136,12,68,98,200,179,170,185,195,112,27,104,3,205,165,28,186,174,118,57,189,119,144,158,95,158,164,143,139,58,87,217,43,22,68,43,126,240,70,94,163,225,233,248,227,168,70,198,16,51,205,239,192,4,124,244,190,80,130,188,253,65,63,201,98,243,142,139,238,115,52,164,188,234,11,203,33,66,111,40,174,113,78,139,135,102,209,122,166,53,10,2,10,140,215,139,223,100,11,23,208,126,65,214,52,37,98,93,37,250,159,75,209,155,248,86,107,5,114,199,254,105,179,240,132,18,228,65,136,188,180,168,141,149,43,234,13,114,25,92,32,8,212,172,186,194,234,241,77,20,142,76,140,225,110,176,248,93,52,69,8,47,143,25,99,166,56,37,228,218,183,234,205,236,237,168,228,136,179,145,123,254,230,182,37,220,223,96,199,45,24,147,73,86,254,47,90,124,89,129,192,199,167,216,217,62,148,163,46,107,74,67,155,206,30,163,44,42,238,69,77,5,86,126,151,131,136,59,134,63,72,23,50,35,228,75,48,172,147,4,200,35,217,142,56,51,159,145,237,51,218,27,192,43,193,90,63,194,218,149,77,69,58,68,24,177,235,144,245,52,41,241,21,63,202,204,123,60,245,245,147,59,230,53,58,179,177,6,108,72,142,101,202,171,147,1,238,27,183,145,157,7,29,13,111,137,129,183,185,196,139,126,204,48,220,237,170,227,65,153,226,170,245,241,69,250,74,235,39,129,115,94,113,165,212,140,219,239,255,30,2,150,71,167,222,250,123,230,253,102,110,67,175,23,73,166,0,144,47,148,163,151,221,23,81,24,247,230,191,244,11,1,206,112,51,40,182,33,40,163,61,107,169,167,6,202,202,72,255,23,102,172,225,38,148,226,88,109,43,255,21,145,157,184,0,241,95,26,253,89,42,53,13,149,184,8,74,173,119,80,63,39,122,131,186,46,224,96,135,125,146,230,186,215,105,91,230,163,169,125,167,150,59,214,137,125,94,22,30,51,110,143,175,201,170,44,185,136,253,28,105,89,77,41,65,135,12,60,237,170,191,75,127,88,149,34,205,123,6,139,121,217,249,166,254,165,197,104,144,84,48,58,172,21,122,128,85,199,148,36,114,91,239,123,1,206,8,169,49,206,39,142,97,137,189,224,169,198,119,13,171,201,140,49,157,103,118,88,94,210,27,126,242,245,68,55,25,204,114,244,247,64,29,145,137,154,56,172,22,62,19,227,79,143,90,5,12,201,194,154,224,71,103,79,31,119,20,146,114,219,19,44,92,21,211,69,49,20,95,47,183,25,195,60,209,50,238,182,244,59,9,94,112,27,36,210,214,7,152,57,84,87,219,76,117,252,173,214,2,188,162,120,141,43,194,108,127,121,25,148,205,129,10,46,39,41,144,243,52,218,147,187,37,188,247,50,228,177,63,51,214,17,10,240,24,244,129,34,87,146,124,5,230,163,171,120,234,22,101,103,156,68,245,144,114,132,132,244,163,47,127,235,219,88,243,187,140,196,153,78,126,139,116,152,107,147,27,119,0,2,213,231,59,70,73,214,67,31,130,51,71,155,189,211,225,165,140,83,24,36,56,202,105,50,33,140,155,216,216,209,252,54,156,254,20,81,120,206,235,241,53,194,44,177,128,30,239,26,95,124,88,90,21,132,123,188,158,141,127,241,223,95,178,108,21,221,145,222,26,192,180,84,129,78,175,117,146,57,215,116,10,13,53,12,252,227,64,32,115,213,68,143,238,155,225,101,184,132,28,92,127,89,232,1,139,160,185,99,115,92,29,188,211,254,180,85,121,47,205,53,199,122,73,153,119,188,74,163,229,129,90,48,50,178,91,189,168,116,38,32,114,55,89,132,116,208,124,128,113,113,16,206,199,26,163,212,71,1,250,155,96,53,100,44,246,31,136,208,243,220,60,176,23,103,88,245,48,51,59,225,235,226,76,182,53,49,135,126,117,23,4,0,51,62,11,237,65,252,21,246,193,84,14,85,217,111,240,108,226,134,59,194,210,198,214,9,245,99,101,81,3,89,134,225,173,80,61,204,115,250,25,191,22,137,42,177,155,159,237,248,200,39,189,1,66,189,88,8,198,57,47,194,59,150,74,50,244,192,145,124,139,137,9,88,183,226,179,162,219,55,201,222,186,109,36,242,146,104,134,170,9,120,67,123,240,251,118,184,113,206,203,242,204,29,95,103,160,139,24,229,246,174,44,232,1,92,51,119,121,192,74,200,193,169,150,115,168,56,37,31,105,175,166,10,183,252,135,115,233,34,0,229,124,183,246,177,143,42,237,125,2,142,154,240,49,228,213,15,77,123,202,79,84,0,147,189,200,161,106,243,41,87,86,158,216,240,246,100,112,9,91,213,220,206,108,190,57,220,218,99,189,47,194,120,28,127,254,169,178,91,243,109,75,134,210,210,244,242,159,54,217,20,133,68,233,153,234,101,91,233,30,96,171,224,92,91,176,236,182,188,20,131,21,122,84,104,171,14,236,252,249,75,212,235,191,95,11,62,141,94,241,165,26,219,173,197,153,214,168,223,240,94,213,113,148,95,22,212,203,134,117,232,60,147,51,11,201,54,4,81,122,170,58,150,209,147,128,196,78,68,78,148,160,114,198,127,162,120,180,68,133,22,76,101,119,11,93,246,9,232,183,127,140,173,92,221,236,51,178,45,217,246,70,118,91,129,102,24,199,252,7,6,116,81,43,240,49,115,77,164,134,23,10,184,92,26,223,238,174,254,108,5,221,29,205,3,38,30,51,143,196,202,21,102,228,51,105,45,191,54,175,140,175,135,132,56,183,9,116,20,68,132,18,220,233,176,239,82,87,160,87,75,33,255,121,193,156,78,230,23,79,64,52,198,99,148,130,106,107,8,203,26,34,248,194,178,123,242,238,250,69,219,168,219,185,118,64,221,220,7,62,58,172,34,161,85,252,155,52,152,60,87,103,183,167,226,234,225,170,247,90,38,143,81,89,210,156,20,60,194,148,113,179,171,5,77,184,78,26,208,131,200,86,18,46,116,74,134,61,119,29,194,3,117,40,80,168,90,103,191,42,184,95,218,91,28,155,54,146,65,95,188,105,77,14,205,75,249,117,46,221,98,224,169,93,190,83,43,182,146,208,7,135,154,99,250,12,2,189,246,105,220,172,175,69,1,167,218,186,57,136,247,112,149,221,32,11,202,229,160,52,60,200,208,193,198,75,246,250,53,55,150,176,139,93,85,222,206,205,111,9,73,162,186,211,69,140,188,136,164,203,223,18,225,119,181,234,138,60,23,112,75,105,15,203,7,125,177,246,31,45,74,151,48,22,139,175,136,183,250,161,111,94,119,158,113,175,140,79,29,122,65,55,233,80,125,200,31,209,18,35,82,3,116,190,125,208,46,253,125,100,73,160,238,5,244,38,184,200,7,167,119,122,165,28,250,26,52,110,188,151,63,208,63,248,94,165,164,111,163,146,32,37,5,60,85,192,27,61,24,60,161,222,0,4,254,155,189,84,196,0,157,35,12,162,103,138,192,135,38,45,40,41,69,63,30,177,222,41,253,200,54,63,230,237,20,103,172,23,99,192,215,2,181,198,52,12,1,157,162,169,147,206,27,237,188,158,40,214,164,233,240,100,201,245,24,178,38,205,66,140,166,43,132,117,143,233,22,167,190,202,18,188,127,240,184,49,182,87,84,214,121,140,169,20,29,122,133,69,18,168,61,132,146,108,35,131,109,86,101,183,150,34,77,90,194,24,46,232,28,48,183,206,47,100,61,163,165,74,17,92,27,210,106,16,222,186,117,41,103,197,144,3,27,9,248,132,189,88,83,122,219,49,116,2,50,30,40,205,76,130,35,126,83,228,228,138,171,171,135,39,196,227,87,106,235,241,239,86,179,253,11,23,99,7,66,41,158,178,157,76,234,6,5,214,254,184,155,181,84,197,165,122,251,119,249,236,166,219,144,14,253,20,200,71,185,128,249,58,15,196,101,206,51,124,190,50,159,255,10,172,123,168,253,230,89,10,236,71,194,62,129,71,92,165,85,0,198,135,157,141,191,50,13,140,37,124,110,249,46,46,25,251,68,145,8,18,120,51,137,142,119,244,148,246,141,26,132,163,135,241,35,159,49,77,209,163,230,111,6,242,146,195,49,170,2,124,194,17,165,42,155,254,34,50,37,48,67,234,117,90,102,69,129,61,195,172,78,87,34,46,79,146,168,210,166,122,231,226,222,204,251,20,75,223,196,242,130,34,225,110,75,207,175,78,24,239,45,171,104,198,59,0,19,49,11,243,112,43,250,158,62,80,155,237,46,52,188,185,245,171,68,197,202,251,110,93,211,94,67,191,87,157,87,233,13,61,47,52,206,80,194,167,66,67,198,170,244,247,174,171,50,79,255,184,161,14,254,202,162,162,254,221,148,221,251,90,102,154,71,98,61,150,1,32,250,227,57,240,168,21,174,152,107,235,75,2,198,35,117,161,148,210,231,214,184,87,241,102,16,184,144,221,165,158,108,17,177,46,228,156,159,149,123,171,239,250,40,10,62,189,159,144,124,7,64,76,122,161,214,158,46,206,191,99,142,189,68,40,168,172,65,88,130,102,169,121,107,188,201,117,35,139,212,14,176,77,110,172,197,14,238,254,189,108,234,224,228,68,226,121,230,183,185,224,25,14,142,86,3,2,21,133,116,109,24,125,214,126,192,236,107,42,30,208,247,43,102,62,205,11,213,177,80,163,92,245,82,101,244,192,151,191,169,102,204,190,167,232,66,226,12,115,238,131,188,181,235,30,55,68,17,186,125,64,121,44,39,147,240,53,20,40,101,224,109,239,226,32,115,253,200,113,202,118,207,81,168,138,146,224,129,38,168,181,120,87,225,170,24,6,223,254,59,48,103,66,191,112,18,100,232,149,121,191,132,39,231,12,223,111,202,150,238,150,76,143,41,37,183,222,8,16,24,33,99,101,144,218,10,68,70,133,97,95,109,42,67,13,102,0,93,189,206,41,149,160,206,101,195,209,76,22,231,109,76,142,113,78,222,63,202,227,65,140,154,29,47,96,41,58,77,137,107,249,152,7,126,53,105,31,221,134,107,150,14,18,108,110,152,91,57,88,146,199,220,12,79,116,220,134,180,176,224,71,97,52,154,76,94,230,58,14,196,154,89,27,162,219,96,227,91,143,175,92,36,179,222,30,59,163,32,250,146,96,163,83,134,33,18,27,99,127,113,171,35,52,143,96,219,71,71,254,216,30,244,75,88,241,242,50,213,1,83,56,154,152,153,219,130,166,175,82,10,125,111,96,137,38,46,205,11,85,195,29,184,117,250,218,58,49,10,40,30,139,211,81,157,249,51,33,100,201,34,96,197,189,206,48,180,50,2,111,154,109,10,90,116,189,224,85,45,153,10,96,210,142,179,131,174,213,131,9,90,194,235,113,201,152,223,253,134,198,136,215,196,121,114,145,127,197,63,226,22,10,124,149,177,37,12,217,218,113,9,235,142,49,103,237,98,82,140,8,127,97,56,61,78,76,142,106,216,56,78,153,139,60,223,243,28,34,38,199,137,132,50,118,151,58,141,192,20,249,138,53,114,177,45,146,78,147,234,123,244,61,157,119,7,88,41,82,17,102,213,59,93,79,45,40,157,139,219,81,12,134,18,77,1,101,45,228,155,66,227,243,242,202,71,136,205,94,102,239,237,253,62,207,30,222,178,58,135,219,74,150,232,27,209,251,37,198,33,83,209,39,249,183,21,38,213,39,143,198,149,91,161,250,193,43,45,233,70,234,118,173,231,180,151,157,138,7,167,198,81,194,51,164,200,83,56,176,121,167,225,108,50,245,125,137,148,215,111,59,19,64,109,5,114,176,218,137,186,235,94,254,156,96,194,168,34,159,84,171,68,70,215,155,148,244,240,11,54,128,75,56,161,201,231,65,137,194,113,32,89,201,13,141,169,131,94,198,168,132,135,101,50,165,181,8,159,184,15,19,74,16,105,43,25,168,214,106,76,164,64,91,12,74,22,16,124,27,121,145,188,125,255,96,131,33,245,145,180,29,62,194,137,30,62,243,129,77,13,158,163,117,162,206,61,236,135,244,220,166,174,217,73,139,0,254,201,26,125,241,33,68,187,155,235,119,25,72,196,151,8,255,8,84,250,43,102,204,134,121,186,123,144,48,2,235,7,229,41,190,150,181,169,203,226,194,118,180,182,162,220,222,14,52,114,197,229,86,207,201,148,241,246,69,68,231,8,57,6,21,171,44,83,134,151,83,25,48,142,91,248,21,21,213,9,104,208,21,12,133,100,100,144,124,237,193,56,180,34,39,246,232,53,212,121,61,127,221,103,74,114,150,223,11,229,210,6,76,40,95,192,199,167,100,100,64,117,44,73,13,187,42,241,47,212,35,164,55,64,85,88,41,102,68,165,110,72,100,66,38,33,14,166,233,157,80,35,137,1,69,63,111,169,42,19,65,190,106,104,216,90,154,147,190,183,207,177,145,142,190,213,148,10,228,251,99,58,72,148,192,227,20,1,79,110,181,47,89,218,133,7,75,111,229,49,60,97,179,158,28,51,110,139,80,56,147,33,182,227,153,92,32,1,241,44,181,143,24,16,252,26,129,134,63,65,186,1,160,90,254,21,88,43,220,101,222,156,214,211,98,172,42,254,193,103,147,61,229,181,85,228,223,127,163,201,157,106,97,82,251,201,89,32,245,234,92,103,151,70,111,44,210,74,166,88,95,204,82,185,9,218,72,146,27,181,139,97,122,22,228,206,84,237,87,140,101,100,110,216,186,226,110,186,109,140,162,59,52,3,26,96,176,41,84,66,47,216,100,110,106,2,55,106,165,232,43,156,42,193,122,42,74,224,96,101,41,240,141,4,88,29,113,31,121,80,196,152,15,234,154,70,129,228,97,137,99,89,108,64,143,32,111,199,220,209,192,20,24,80,192,202,191,169,156,133,210,36,179,17,149,67,213,52,180,176,134,253,181,179,174,87,217,236,254,162,137,201,192,88,23,89,195,231,73,182,226,224,149,99,172,221,135,5,241,132,86,236,118,69,50,108,27,103,65,17,127,75,11,160,71,85,227,148,153,62,103,83,250,192,254,215,123,252,157,8,112,132,210,193,21,244,168,131,44,69,226,190,243,10,225,163,84,190,118,32,19,193,234,220,32,188,74,90,197,143,70,191,99,113,186,143,49,131,109,253,62,234,221,183,103,238,89,65,67,11,230,9,222,24,95,129,14,228,125,126,166,49,29,239,36,39,124,130,203,200,105,29,231,182,43,1,179,193,103,230,251,205,22,182,65,191,137,110,165,113,180,60,209,87,212,7,69,241,130,157,125,59,225,89,244,120,134,142,170,92,19,65,251,87,163,83,32,185,163,202,187,191,34,192,183,186,236,30,222,225,180,237,142,162,77,93,190,100,248,70,134,164,253,105,255,142,189,83,50,161,225,223,241,240,252,170,90,122,221,22,108,187,81,31,252,76,218,238,217,175,90,110,37,190,8,65,147,181,160,202,39,24,230,218,92,233,102,123,98,72,215,163,152,111,198,25,215,60,213,1,254,4,168,45,13,40,238,142,158,60,70,241,144,183,215,236,146,149,13,234,215,133,3,112,135,7,8,40,195,214,105,244,172,246,200,198,238,153,112,100,59,137,18,122,9,204,17,41,181,111,41,61,21,160,16,170,194,218,178,62,88,92,199,233,200,24,70,246,142,224,164,200,210,237,216,75,100,45,115,160,117,92,38,226,170,215,156,203,215,210,248,231,199,216,248,161,125,167,132,103,180,186,9,249,4,154,16,237,107,80,28,27,235,150,39,210,201,153,66,17,97,165,29,15,167,130,23,77,17,106,160,90,248,47,219,164,20,127,81,248,1,36,254,22,50,208,65,145,45,220,160,93,16,45,62,229,177,187,144,167,142,26,248,232,6,191,77,59,136,49,2,33,116,66,65,146,218,44,111,73,2,222,99,111,24,180,41,67,103,39,216,168,240,207,142,34,241,86,17,173,37,58,64,186,213,98,181,151,159,141,26,22,31,45,92,64,9,10,26,76,181,236,145,18,8,30,219,158,183,71,138,134,56,65,70,34,140,141,13,54,245,29,155,227,200,183,113,40,113,203,86,214,2,162,90,237,5,247,2,186,149,205,73,75,106,255,178,8,39,126,21,96,43,117,216,10,81,98,244,208,25,252,177,189,21,50,204,13,115,42,29,115,2,10,234,207,168,29,131,228,241,82,183,158,85,177,161,142,249,81,208,74,7,73,61,160,142,153,121,63,78,230,152,77,38,100,58,119,15,102,23,145,201,189,165,77,147,230,208,2,84,68,22,86,13,32,68,58,88,73,8,48,139,117,27,222,40,32,182,33,168,89,188,113,162,162,146,225,102,118,158,53,22,82,149,184,240,92,212,243,40,50,170,149,147,223,104,185,45,162,20,59,162,173,157,5,224,233,8,159,219,28,215,102,178,59,121,254,199,162,199,99,2,69,53,6,16,218,9,6,241,44,220,188,45,208,250,244,235,250,209,70,110,222,198,183,219,47,135,143,170,11,226,178,201,194,8,0,115,63,105,158,9,227,172,16,176,218,211,18,70,236,5,109,35,119,143,218,145,213,190,153,247,240,232,191,61,9,58,130,175,235,45,122,195,207,43,194,102,133,91,46,230,18,78,212,122,114,168,4,94,120,96,72,18,12,142,191,141,105,202,78,241,114,85,34,238,84,11,10,254,50,188,122,76,216,117,121,110,3,95,91,62,253,60,174,139,195,120,183,220,61,229,75,22,220,190,134,216,68,90,111,184,152,40,130,43,39,76,144,94,215,83,252,62,127,27,6,175,158,50,87,41,85,95,32,24,14,193,22,92,54,156,254,77,61,50,7,243,25,48,156,89,56,17,33,107,135,110,160,52,80,216,55,217,98,40,102,1,34,70,233,200,205,172,234,156,17,180,123,113,143,67,81,224,51,149,12,213,251,3,2,63,30,249,181,254,120,160,155,133,96,137,181,35,5,182,121,214,39,128,129,237,203,19,137,24,93,101,255,228,209,34,58,241,253,187,131,60,8,241,178,36,11,26,109,21,150,214,31,242,19,60,118,147,158,111,23,164,168,73,67,92,231,211,6,86,222,242,248,107,142,231,119,143,1,168,27,187,91,70,38,230,162,216,232,152,83,71,41,183,182,189,94,221,128,7,217,182,42,49,232,20,23,3,87,95,213,181,137,117,14,161,52,243,122,183,193,90,134,182,58,222,179,72,150,241,129,197,216,227,156,20,75,90,202,71,128,15,137,242,183,117,188,168,252,39,243,76,167,222,12,190,250,197,206,164,145,191,47,206,24,20,40,253,36,4,220,72,143,199,19,105,30,48,219,215,196,37,15,182,38,220,134,239,35,187,29,230,68,215,139,220,215,90,25,184,246,196,149,239,249,142,248,63,141,205,161,28,87,142,170,237,214,67,142,251,97,163,163,242,208,139,28,201,5,249,160,111,232,64,231,207,201,197,196,206,92,127,71,17,57,48,200,25,226,176,113,210,162,108,233,45,224,15,40,196,161,187,228,55,88,74,235,30,68,12,209,70,87,243,159,85,208,70,192,75,111,14,15,239,6,234,134,248,30,113,51,255,128,43,104,82,6,158,241,74,19,174,199,229,132,238,6,70,145,96,242,208,185,17,12,251,210,13,113,233,186,188,29,9,195,244,71,62,26,195,82,44,209,10,230,93,188,92,234,241,145,115,67,77,67,44,210,249,228,5,84,43,160,77,103,214,59,87,195,200,20,129,254,173,229,229,37,115,254,49,72,119,145,188,255,12,95,191,110,239,124,12,213,234,217,4,211,133,39,184,242,103,223,13,5,50,56,74,214,135,66,130,62,223,167,91,175,30,40,134,82,42,167,175,169,33,40,205,88,123,104,96,189,142,226,130,73,0,60,121,128,225,203,146,1,170,4,93,235,72,243,97,77,129,92,246,173,53,161,138,204,83,70,234,80,223,20,176,62,149,150,127,141,182,196,163,80,117,13,31,248,64,166,35,112,96,44,221,70,128,124,229,74,60,65,83,15,20,135,165,184,82,153,163,153,145,137,168,21,68,140,120,76,239,1,57,32,133,38,158,157,114,92,79,139,129,100,233,109,73,206,6,164,101,18,250,41,214,14,185,87,241,153,142,116,3,55,77,138,149,123,112,38,59,191,132,156,136,205,108,175,236,117,66,107,36,241,192,147,149,227,116,253,26,209,34,134,94,214,68,212,25,142,117,207,151,32,13,101,187,154,38,54,165,162,58,254,142,54,86,89,13,232,46,36,31,67,169,250,183,168,205,55,163,165,77,37,211,28,12,51,80,99,47,117,190,69,215,83,246,24,48,152,252,50,167,183,242,94,21,63,211,171,23,199,4,160,172,57,57,92,128,50,52,174,87,77,255,17,221,149,165,195,162,43,38,226,27,221,101,124,188,82,226,222,49,132,246,31,27,81,255,205,69,176,163,195,253,83,47,80,99,157,132,223,160,92,39,120,73,149,51,171,255,67,218,107,160,220,58,236,28,119,180,1,82,24,146,160,44,200,70,141,109,254,12,126,229,95,99,96,3,216,221,136,205,113,142,122,186,243,183,255,22,253,97,176,39,222,179,209,180,233,133,72,37,54,158,28,65,95,13,1,59,153,193,87,230,128,104,160,201,205,2,196,6,125,232,155,188,65,83,240,126,145,178,63,143,0,240,193,78,184,2,226,82,240,49,22,50,167,206,196,168,121,68,212,156,249,154,95,24,93,83,113,168,33,14,246,208,135,139,78,122,101,123,8,177,97,182,122,128,106,140,8,192,100,143,88,196,50,29,207,215,143,65,120,133,133,118,94,128,12,106,130,195,165,203,112,192,173,166,222,59,23,34,6,82,131,16,84,214,205,87,208,140,201,182,166,221,131,122,181,85,150,65,139,133,103,23,179,159,231,7,175,204,95,130,131,126,45,155,135,76,69,145,54,197,251,173,9,206,46,189,122,101,178,24,17,52,231,121,151,60,255,66,47,5,0,134,235,185,232,129,137,35,158,3,110,230,211,73,61,209,224,71,153,55,248,61,100,233,170,140,66,27,177,253,40,208,209,143,4,27,108,105,166,136,60,8,218,119,168,182,107,8,119,5,118,31,219,43,94,70,182,91,68,254,135,245,212,250,26,105,156,109,180,133,177,249,140,89,130,79,55,31,123,18,154,42,191,139,9,240,237,151,107,173,188,134,243,132,118,79,249,197,52,29,174,60,127,48,203,213,101,118,178,117,92,200,49,217,119,172,213,150,231,103,134,168,200,159,174,105,85,8,72,53,243,196,179,102,171,173,207,190,134,186,250,180,231,155,193,203,81,248,175,8,196,145,73,186,178,63,177,60,238,12,42,169,79,173,245,76,171,131,19,102,237,156,201,116,42,209,167,158,198,227,114,197,227,182,212,229,151,110,140,149,239,82,124,137,145,167,26,54,159,102,237,132,139,121,181,115,78,145,179,231,40,243,114,107,190,126,230,152,86,21,43,130,126,87,172,107,120,215,174,119,95,238,138,107,162,109,30,0,156,48,191,59,137,171,39,151,249,219,16,202,29,186,7,225,198,202,213,119,26,30,46,66,61,154,127,212,160,121,30,139,137,77,16,197,1,225,23,181,190,52,124,88,224,250,45,111,131,115,99,26,188,227,244,207,13,101,230,130,96,187,90,109,141,203,246,150,213,238,2,180,162,199,113,129,255,97,7,65,101,37,145,166,70,193,39,68,86,45,6,162,80,189,182,147,237,204,108,173,114,12,139,6,79,110,178,50,39,17,113,41,178,217,61,88,132,240,93,181,152,170,7,71,170,146,115,177,209,87,215,16,157,38,76,45,46,220,16,103,58,125,32,153,241,187,154,232,13,56,84,165,56,94,8,6,118,36,14,96,65,93,68,50,208,97,85,185,103,1,161,83,67,194,38,128,76,181,204,102,151,40,72,219,119,58,243,206,0,99,50,157,241,110,31,75,39,89,181,28,80,34,47,54,40,145,0,60,100,212,148,16,35,19,189,130,103,237,1,19,109,241,72,134,148,103,72,23,209,106,186,211,41,196,18,76,23,75,122,68,251,50,11,252,232,52,72,57,5,52,226,217,252,184,71,71,112,106,214,93,60,250,235,235,115,148,64,183,222,82,158,135,135,145,153,54,138,126,116,216,66,235,51,100,7,1,111,11,231,57,153,174,195,76,173,195,2,137,227,217,61,109,233,31,68,5,179,235,72,80,16,191,118,37,76,119,131,246,39,251,58,127,172,229,32,135,167,216,216,39,54,7,180,45,236,44,47,186,218,5,45,145,201,222,24,126,214,198,237,218,245,74,159,119,201,233,27,224,213,175,46,43,252,104,209,254,53,126,25,166,190,157,66,64,23,226,4,74,69,28,42,238,195,233,33,1,64,116,16,110,32,81,97,57,242,250,108,13,200,31,184,115,30,190,65,111,225,197,90,215,174,221,193,216,165,11,16,3,153,141,181,161,223,213,141,64,243,41,33,65,208,245,48,203,171,242,234,120,183,57,60,85,83,188,148,249,94,62,178,164,119,223,137,180,49,184,166,120,134,127,76,230,216,208,161,5,42,237,196,235,114,222,23,134,110,242,244,163,1,42,228,3,251,93,156,48,46,154,200,19,163,205,213,250,142,212,14,156,210,48,20,148,235,204,232,128,21,3,100,38,184,230,249,138,117,207,253,60,79,102,174,115,184,21,102,194,116,47,69,98,110,200,73,248,186,30,220,75,239,155,228,138,141,255,84,179,127,17,124,167,107,102,248,93,59,11,170,167,110,129,228,140,41,111,215,131,169,31,210,192,131,220,50,29,241,34,235,141,60,96,178,83,126,109,14,186,209,248,63,130,108,186,180,105,95,192,234,29,87,8,197,153,103,55,13,10,116,247,40,153,54,84,199,120,69,98,185,228,4,234,107,80,168,240,218,9,114,58,196,150,245,120,244,210,164,160,201,55,20,40,135,138,179,149,228,199,157,192,174,190,79,35,154,208,104,215,44,229,241,125,186,156,42,60,224,60,98,79,40,64,126,207,165,212,10,115,54,25,33,126,58,236,50,194,209,149,85,111,178,89,79,15,60,227,54,174,229,243,135,42,102,50,171,254,95,21,247,31,125,0,215,95,9,254,115,158,204,23,106,103,28,139,202,110,125,119,242,110,213,56,152,116,42,49,235,231,28,252,0,141,119,191,200,51,122,183,74,56,200,99,174,153,239,174,227,16,247,241,53,17,43,147,201,28,236,24,172,158,183,250,239,232,109,178,138,191,154,85,92,101,93,173,175,120,149,115,204,109,250,109,193,172,203,85,254,72,122,109,173,97,223,35,161,59,23,39,177,164,124,186,70,76,36,143,143,79,179,160,167,125,30,112,233,209,141,126,247,37,119,77,159,6,86,22,186,250,64,148,109,116,69,157,161,219,213,126,74,234,55,4,74,150,191,164,59,229,208,73,147,153,74,155,93,93,177,111,177,180,36,107,46,26,222,118,125,41,31,110,95,84,199,96,81,223,99,229,230,111,208,187,44,207,189,197,162,155,118,66,246,102,5,157,180,61,121,27,171,235,38,194,219,47,109,32,238,247,114,130,158,184,151,243,155,87,210,50,16,172,39,124,229,145,237,44,49,206,229,30,118,171,255,129,65,10,175,28,62,65,30,217,20,113,253,179,149,240,28,118,112,140,20,237,39,7,159,242,230,64,144,209,53,33,213,116,176,141,135,111,225,244,248,107,202,235,131,88,130,60,113,17,151,144,193,21,155,78,5,33,221,177,64,101,141,166,1,217,83,16,24,8,33,203,8,73,180,252,201,36,37,193,112,158,81,36,62,12,87,125,150,121,19,39,92,191,173,210,244,36,77,195,88,140,26,156,4,231,27,111,89,251,35,188,185,246,75,176,127,162,75,144,137,255,124,36,161,108,144,154,177,88,19,197,21,51,61,242,175,177,115,118,58,158,40,174,196,158,97,198,184,209,36,126,232,71,189,204,186,7,102,36,124,234,204,89,172,220,192,86,101,51,175,40,9,191,17,115,155,117,200,237,22,138,77,48,250,240,160,224,117,133,170,182,144,213,211,213,2,243,145,65,254,0,2,248,48,33,249,80,119,29,108,76,228,213,3,143,250,23,23,131,183,155,60,55,214,27,114,225,198,150,10,35,148,123,109,118,26,2,65,205,51,165,231,113,146,183,118,99,110,128,192,107,84,128,130,68,16,88,195,165,35,170,219,153,195,92,132,226,34,20,77,81,240,139,150,107,214,77,155,204,106,79,19,168,44,71,198,240,87,142,60,44,60,246,5,116,90,243,72,82,123,206,123,164,157,159,113,100,46,227,97,151,247,172,49,26,253,214,112,110,75,191,20,199,178,121,153,73,146,167,80,165,179,249,104,118,42,76,8,126,200,69,25,1,35,35,219,85,218,235,253,164,63,211,195,178,60,208,120,222,151,167,79,238,35,131,109,53,18,149,50,40,14,206,218,230,111,82,234,124,19,223,6,18,94,196,199,189,219,79,203,3,86,63,184,11,70,220,145,70,39,204,13,70,25,105,99,18,2,0,24,161,197,244,35,162,11,157,34,54,196,92,138,255,30,83,77,170,69,196,207,11,28,60,155,7,88,6,248,72,159,21,242,123,4,244,230,249,74,32,130,186,174,143,2,140,24,130,73,170,186,195,129,0,221,95,213,21,27,147,128,194,103,91,111,210,249,82,200,180,140,107,187,79,132,95,135,105,220,39,219,47,101,130,232,19,153,84,96,21,214,227,184,212,26,88,77,22,173,250,215,51,120,214,55,206,86,220,178,39,170,15,114,12,97,98,239,4,124,47,250,230,133,149,196,82,209,165,151,0,207,30,106,133,62,251,241,196,196,47,179,145,179,2,155,15,5,165,22,67,52,207,39,246,123,134,219,252,174,231,168,82,8,7,192,229,168,45,215,86,100,235,111,169,107,12,249,89,109,86,160,142,181,238,237,223,92,168,130,150,236,224,116,222,45,18,13,13,164,73,38,27,208,24,138,45,80,4,148,58,149,54,128,230,244,22,230,218,179,87,51,104,223,178,9,209,228,14,206,192,249,41,82,34,115,235,125,150,192,196,1,165,252,62,83,243,157,37,218,134,192,149,232,139,145,253,205,51,17,97,192,121,157,60,181,170,126,156,5,44,196,235,223,123,170,2,118,228,255,243,8,132,196,221,30,242,92,159,112,180,131,51,25,126,253,184,7,4,110,34,217,37,185,91,186,44,77,80,104,181,58,171,9,210,180,17,119,8,141,229,247,64,62,232,121,118,112,133,52,173,5,202,94,170,37,212,28,222,193,97,51,164,107,197,181,220,102,52,58,47,147,194,179,174,14,89,19,221,145,39,174,86,249,64,89,192,101,143,207,156,186,210,1,137,143,225,13,38,98,59,92,137,53,31,64,212,100,157,144,100,131,3,65,115,94,185,87,13,25,176,45,184,207,19,250,197,231,86,217,51,191,125,60,11,95,125,105,236,148,166,54,6,42,0,150,180,138,38,30,235,72,106,14,217,69,184,242,46,197,173,38,89,234,41,197,213,165,79,86,118,231,142,207,69,207,108,20,53,179,160,231,84,99,156,253,80,13,15,65,18,73,160,149,31,76,124,141,4,48,207,86,81,87,66,32,121,213,115,116,230,240,201,247,195,159,66,154,244,180,174,14,101,84,3,66,175,40,177,65,194,101,162,234,26,55,222,21,72,164,219,243,129,30,172,104,212,50,6,152,90,233,235,35,221,207,165,225,44,109,74,127,123,173,56,87,209,84,211,48,214,123,5,105,101,78,188,169,175,36,172,214,19,232,125,217,130,252,99,237,244,61,173,193,82,209,216,57,13,12,202,82,193,78,70,69,206,74,240,191,91,25,179,254,242,177,68,23,139,165,101,32,52,246,25,212,240,38,237,147,60,156,190,36,3,56,163,125,228,107,228,6,235,44,250,90,92,77,158,36,217,168,161,77,26,49,125,99,103,191,115,41,120,16,231,243,69,108,169,115,81,127,195,48,164,132,75,173,147,62,148,220,3,189,186,165,200,86,60,18,172,193,207,129,196,167,69,181,134,232,130,109,48,76,133,202,38,184,207,153,39,149,26,4,242,77,59,193,254,102,222,99,68,91,147,245,252,14,111,57,224,121,244,233,148,97,66,37,162,181,44,60,144,184,181,187,204,143,33,120,225,243,226,97,190,168,25,134,240,146,145,251,166,104,183,243,126,93,104,93,84,55,148,49,84,30,71,204,203,236,226,179,113,247,64,213,92,207,126,35,130,231,86,232,149,34,79,127,8,155,120,228,29,247,142,10,151,52,57,180,40,56,93,99,171,253,160,143,201,101,183,204,59,240,23,208,83,198,151,231,231,147,28,110,4,156,102,57,157,18,249,18,50,20,130,56,53,156,41,45,170,41,117,136,179,222,121,239,18,168,166,237,2,237,98,107,148,236,81,60,2,33,181,218,46,71,254,197,234,84,204,80,27,160,118,123,153,37,55,238,240,199,98,227,116,197,126,232,21,255,98,226,206,152,34,211,121,85,69,183,195,225,202,232,188,79,208,206,156,187,96,21,189,252,76,203,227,241,70,211,61,52,217,12,33,243,41,50,152,77,47,82,19,140,197,235,100,59,65,70,115,52,246,95,80,145,224,57,224,221,213,78,145,49,47,117,102,248,205,92,84,18,215,150,191,135,145,62,36,193,200,52,133,187,34,96,149,139,1,97,248,25,51,64,247,58,93,111,15,225,212,223,114,61,92,11,95,154,153,245,208,78,148,39,150,34,40,110,50,154,11,54,4,145,21,134,166,233,0,193,39,105,2,102,29,28,168,238,231,117,248,142,40,50,56,142,240,142,165,151,16,85,30,155,98,225,239,177,187,143,215,228,29,118,98,85,69,167,21,45,116,143,40,42,152,1,87,158,139,169,81,137,18,54,65,178,145,44,82,225,241,84,208,111,202,139,17,95,107,130,255,148,105,65,106,172,230,171,55,197,239,133,168,4,152,247,235,19,138,175,168,216,216,171,23,160,83,71,40,126,234,228,1,76,145,9,132,135,166,202,190,232,233,218,105,184,138,161,252,19,33,132,61,159,183,129,62,37,37,194,79,104,59,218,204,215,82,166,4,190,36,224,43,97,59,71,51,188,214,175,54,18,10,15,153,110,203,218,59,225,113,185,123,75,111,206,104,24,163,254,170,85,40,105,9,229,41,218,37,240,211,103,89,253,97,34,77,188,114,220,132,215,129,26,109,149,186,128,119,108,19,20,122,172,175,10,20,169,9,104,195,150,51,8,159,140,86,232,226,177,7,196,200,167,207,106,126,27,140,222,219,198,149,46,0,13,93,255,121,205,23,206,245,185,247,15,231,173,156,59,156,16,48,118,254,93,148,203,237,189,158,180,101,52,62,155,57,8,175,171,215,67,69,104,60,72,232,226,185,20,206,65,59,42,125,90,124,100,202,134,141,239,191,110,203,164,223,50,232,219,4,222,205,22,70,62,180,75,143,174,228,44,62,245,202,39,117,215,33,145,80,106,131,177,244,66,46,89,167,198,251,80,38,72,190,90,118,85,34,158,83,17,61,132,124,53,24,63,24,90,249,68,131,245,198,183,117,13,157,137,70,189,73,23,75,77,13,25,88,126,217,87,108,92,8,133,154,15,158,112,113,94,186,162,177,9,232,181,162,55,24,38,161,79,176,4,233,11,158,170,242,240,168,77,25,3,223,158,186,182,26,129,84,106,135,108,205,79,254,175,227,1,238,248,79,5,72,169,217,128,158,1,139,110,157,12,39,55,95,3,2,113,179,81,229,38,144,253,35,77,155,97,157,9,47,133,35,238,97,246,176,156,164,3,236,181,42,140,173,1,46,164,218,168,228,127,219,160,224,59,249,247,7,155,98,77,199,215,146,55,151,221,185,163,241,26,122,137,164,190,205,207,4,237,134,165,74,238,223,226,15,248,242,139,107,210,187,234,4,145,23,231,180,229,53,254,166,201,220,10,14,58,33,230,72,92,230,207,170,109,188,229,137,28,147,22,41,192,213,40,215,216,127,14,228,9,13,85,247,106,247,1,155,206,136,4,23,190,148,170,106,194,155,170,96,227,85,168,247,195,20,113,172,17,34,38,123,79,167,110,206,207,53,66,173,162,178,166,84,120,160,160,218,186,227,34,87,100,212,219,28,84,255,59,138,26,28,227,102,205,94,75,152,55,216,163,46,225,96,152,57,32,57,159,27,251,178,201,231,5,139,31,163,136,69,71,125,19,213,46,252,84,88,215,163,249,153,181,25,227,174,4,105,93,98,251,60,164,4,222,26,165,85,83,87,45,206,132,134,6,108,89,96,76,139,144,143,144,116,59,72,48,184,248,230,195,135,167,29,166,42,207,49,87,221,159,42,168,96,157,181,125,152,96,130,72,48,100,105,145,96,98,200,116,7,131,166,69,99,117,55,141,40,125,106,249,33,118,191,121,159,138,79,27,90,132,13,52,0,61,44,246,212,77,127,107,26,124,234,104,26,14,238,68,79,124,247,99,81,60,135,27,62,83,231,104,214,53,69,104,188,95,120,30,105,222,150,218,223,80,221,209,86,113,125,226,123,36,1,136,94,206,253,124,34,218,2,77,208,172,39,238,148,151,111,237,3,135,99,41,22,142,129,39,56,105,255,31,62,12,171,5,206,94,114,13,174,185,89,199,225,131,239,187,92,132,102,86,138,156,36,55,112,65,191,209,70,60,75,110,59,216,180,148,36,118,238,139,97,222,17,236,209,68,163,76,177,206,58,196,113,2,166,47,131,113,199,180,134,23,174,24,119,20,124,144,29,221,9,90,224,188,131,232,13,244,94,200,129,51,27,11,124,24,154,5,91,171,150,238,212,117,175,71,155,110,168,3,236,162,196,193,74,101,6,238,157,132,151,181,88,122,26,84,194,170,253,198,124,142,133,185,66,4,105,5,152,87,209,178,134,243,242,197,214,209,103,53,218,128,193,9,83,231,55,111,29,235,133,45,107,115,71,203,15,1,69,200,105,216,1,163,183,18,222,54,6,56,48,104,228,237,119,166,90,242,184,97,160,218,194,255,151,131,120,180,104,202,167,157,179,147,77,161,34,65,201,171,236,177,175,0,92,134,255,40,217,133,61,187,44,165,109,184,127,37,189,61,62,60,232,182,210,78,123,118,207,185,156,158,77,117,67,26,37,222,174,87,192,241,152,180,170,218,35,86,86,91,87,98,97,192,129,140,194,233,36,79,152,203,136,73,223,63,26,117,190,88,188,60,42,9,45,54,223,198,207,196,237,26,244,60,233,67,132,223,113,147,253,16,126,10,119,41,159,99,237,109,167,23,248,146,7,166,214,75,0,234,202,90,254,26,71,82,240,116,216,96,236,109,46,104,255,134,115,253,155,36,36,129,188,183,140,151,14,153,244,139,244,252,214,160,8,249,226,35,58,185,116,255,126,128,120,235,190,225,169,185,175,255,64,176,56,247,249,7,18,39,92,249,142,98,47,116,247,126,6,66,208,245,253,217,123,160,123,49,99,18,90,47,9,80,207,212,123,18,61,155,193,44,242,205,146,4,96,210,222,194,220,47,172,241,165,29,155,45,163,105,121,174,115,233,211,216,182,136,24,90,234,77,214,70,94,160,35,59,16,39,71,24,186,43,251,99,53,11,47,60,159,24,144,250,41,114,90,26,97,209,154,96,63,178,67,28,211,107,179,90,253,127,165,163,26,175,163,165,60,47,25,151,210,245,25,91,122,31,176,184,179,128,161,75,71,166,119,40,19,58,101,115,237,145,211,239,250,235,224,4,46,64,94,118,213,191,21,42,27,169,75,217,193,182,121,215,57,216,234,245,160,135,78,21,125,113,51,250,39,177,32,227,61,57,182,118,16,212,181,130,153,240,62,148,127,188,127,160,37,3,231,33,68,181,179,95,116,179,14,247,145,214,104,222,71,140,17,161,171,218,105,81,195,25,20,202,235,110,70,90,42,47,194,109,74,85,60,77,65,92,205,106,16,171,147,0,227,16,251,48,224,101,8,46,29,94,50,36,213,78,254,13,7,254,227,219,219,18,45,213,145,136,25,210,42,32,47,62,61,139,31,140,17,210,249,37,178,80,160,59,139,26,250,178,179,208,129,81,82,239,54,209,224,20,156,174,251,26,130,136,28,68,243,28,42,28,17,51,90,6,39,125,11,249,223,165,193,243,148,129,17,210,146,186,89,202,253,59,205,5,52,237,17,181,104,92,54,142,214,177,178,59,214,195,73,72,186,175,17,1,0,220,146,69,144,120,89,133,146,152,239,230,141,237,0,78,250,117,54,179,45,38,167,90,149,136,233,115,8,227,210,205,255,208,177,5,45,173,12,189,122,109,122,136,191,40,176,51,234,201,4,208,42,147,44,56,120,17,43,69,93,97,143,103,130,166,129,101,7,40,85,92,157,218,212,230,114,139,2,233,64,93,127,49,140,232,168,194,0,74,215,40,158,61,12,247,57,151,103,148,42,210,155,139,211,87,19,0,208,70,224,199,34,241,199,70,169,161,135,61,105,233,172,62,114,0,96,15,45,231,45,55,172,39,55,41,225,133,190,138,162,53,142,120,95,183,32,192,36,208,155,102,233,86,61,53,30,206,83,199,125,72,101,207,29,247,104,10,148,18,184,234,165,202,151,116,193,119,185,112,23,192,20,152,65,174,8,254,94,56,95,112,30,175,131,75,160,36,26,226,61,55,97,225,40,77,212,181,0,239,155,198,208,128,240,202,248,190,135,42,46,22,94,11,61,30,199,55,16,98,142,1,63,173,36,147,172,74,152,45,239,201,204,46,115,27,81,227,120,112,155,184,99,79,214,130,147,122,64,139,9,147,208,82,76,15,123,98,5,74,218,198,40,175,162,34,226,243,95,227,126,94,45,242,141,118,9,49,66,13,62,135,201,56,200,96,255,212,204,11,3,243,18,242,108,74,227,62,173,115,180,224,226,248,249,141,136,245,6,158,110,65,8,248,189,225,236,226,84,45,8,72,133,12,176,12,140,172,135,245,88,80,88,0,185,175,79,207,75,134,219,100,194,29,255,125,135,114,8,126,63,172,235,145,65,229,120,37,197,36,66,254,60,122,61,197,192,6,79,197,152,198,219,179,231,14,155,211,69,154,175,209,49,59,91,6,25,138,1,144,199,28,148,67,149,19,37,147,101,173,173,206,196,37,179,47,184,185,251,43,182,74,221,246,66,82,220,131,113,87,197,241,66,226,95,156,93,186,196,250,229,244,248,189,22,207,27,43,104,3,210,183,207,145,95,190,74,251,145,107,71,36,138,225,83,79,207,145,78,210,137,175,90,23,239,94,181,98,41,136,109,211,114,150,87,255,49,149,169,69,132,65,211,140,205,214,29,22,127,210,12,110,19,72,139,152,200,229,246,220,110,222,227,189,5,36,90,254,53,6,237,122,57,142,108,23,90,140,146,218,237,207,124,148,18,43,1,231,98,177,83,35,133,156,57,105,201,222,84,80,168,12,176,33,62,83,81,72,91,127,176,136,94,105,255,254,90,145,155,68,132,45,203,4,81,16,2,218,66,189,227,170,31,12,196,122,121,143,12,99,122,129,195,234,210,79,14,55,209,162,72,6,182,66,57,203,144,165,124,104,28,239,250,145,78,30,73,201,115,103,29,184,58,64,70,85,21,63,220,48,82,120,182,147,193,160,57,159,29,228,110,185,119,116,208,106,226,116,121,81,43,222,244,81,208,45,54,252,92,150,203,97,118,228,145,19,251,135,68,118,217,134,205,225,179,191,233,152,12,91,197,183,100,112,245,155,90,49,164,31,226,11,161,97,101,12,52,104,87,67,185,88,236,186,244,207,7,33,67,86,181,69,233,84,8,132,228,204,119,32,165,140,91,72,140,72,59,85,160,243,119,182,101,202,174,103,225,103,157,66,245,6,239,65,118,228,82,220,95,37,111,101,138,161,191,68,163,207,254,132,5,33,34,56,45,15,145,79,100,40,250,236,235,36,175,245,20,209,154,13,198,149,155,0,80,11,84,80,172,105,217,187,232,7,132,48,231,150,103,105,189,165,83,77,153,247,75,244,46,186,175,219,208,150,199,180,28,58,132,148,105,13,207,113,32,133,101,252,13,167,207,239,200,38,246,25,126,101,156,150,20,134,155,28,193,203,237,91,8,31,34,172,248,160,57,105,219,239,42,133,226,116,81,43,132,235,167,30,68,43,231,221,164,52,182,249,179,61,153,161,159,137,151,189,73,236,246,163,36,98,19,85,248,126,173,105,179,75,212,179,6,192,100,128,153,211,199,108,66,203,86,207,169,95,199,34,119,154,244,10,13,220,112,98,175,183,40,113,55,27,57,116,86,1,170,179,54,173,252,94,178,69,116,19,143,251,130,194,112,136,117,223,38,229,127,85,195,14,156,30,223,71,155,223,129,124,152,171,136,110,120,95,180,53,100,168,25,3,216,42,54,85,46,69,119,107,155,145,251,64,53,185,193,15,13,139,6,167,11,60,47,89,97,48,152,126,89,204,146,71,95,57,111,150,78,240,251,102,115,113,11,147,15,192,253,231,25,248,245,109,134,153,56,58,101,46,144,2,253,31,2,83,198,61,64,121,63,76,80,67,29,12,66,28,147,254,92,69,68,35,212,156,221,161,237,249,146,56,121,137,145,156,246,183,247,139,124,62,163,212,103,229,186,93,174,69,23,160,26,196,181,43,175,176,60,110,211,55,131,146,61,179,46,79,154,194,63,7,77,202,244,150,202,18,92,217,129,241,239,222,111,51,135,13,231,255,23,171,205,2,165,228,225,46,247,213,245,181,190,140,154,241,182,186,251,24,83,159,137,53,64,138,170,164,60,147,27,90,82,193,36,201,173,182,188,108,188,229,45,193,211,18,253,200,185,25,95,180,93,30,219,69,195,239,222,97,161,110,214,36,114,96,168,76,77,164,53,131,226,197,100,0,42,106,159,84,214,55,249,124,216,170,102,155,118,134,77,181,65,115,14,167,123,89,46,212,228,181,29,222,148,86,228,253,74,236,231,197,148,188,137,167,27,127,12,253,186,84,67,146,211,91,131,122,218,230,239,254,175,168,1,213,249,121,7,221,136,146,201,36,166,47,73,221,190,128,205,126,206,89,121,78,233,57,64,136,20,67,198,178,249,191,17,131,33,149,197,130,104,170,130,142,237,246,170,147,192,156,248,187,123,25,225,139,220,171,61,24,24,114,110,77,3,160,244,82,56,94,113,16,27,118,228,217,56,29,253,10,75,145,97,193,150,89,210,52,60,146,17,127,187,216,5,195,108,15,251,39,157,158,86,49,193,199,155,106,6,73,80,247,203,61,88,81,56,93,158,179,40,245,81,68,136,69,32,237,101,122,112,165,100,55,9,127,59,26,9,41,16,102,92,246,179,125,108,231,225,63,120,88,135,69,195,239,197,51,245,72,72,59,15,231,42,3,184,123,64,176,64,2,15,246,220,67,193,252,8,159,56,20,44,137,45,172,109,183,204,159,101,6,17,221,228,44,160,69,242,153,202,128,203,12,4,126,92,35,50,234,50,118,36,235,41,31,25,142,113,24,62,9,95,20,19,50,125,158,204,53,186,86,53,189,102,153,228,219,22,2,99,14,143,147,221,199,23,113,107,196,224,225,104,121,99,34,19,112,121,28,191,160,245,10,17,84,184,88,225,151,167,54,240,195,72,254,120,18,22,155,131,146,29,227,234,30,101,250,135,69,125,243,191,220,108,252,27,73,15,229,136,53,207,18,173,204,19,205,199,182,167,225,33,249,143,99,91,17,55,149,227,252,128,238,114,212,169,242,145,36,176,68,219,87,139,157,11,63,61,59,211,206,153,189,127,223,109,58,97,39,141,146,29,253,92,94,80,25,18,106,154,118,230,19,134,225,160,83,60,150,40,14,114,137,33,215,197,110,48,190,240,56,91,138,248,129,37,247,39,83,175,2,103,194,229,110,102,216,12,120,6,3,226,163,55,78,249,252,111,226,91,6,137,148,130,47,48,247,229,23,243,182,71,150,137,124,20,124,66,139,32,193,148,161,185,236,79,174,99,200,112,53,55,117,29,34,237,204,153,30,100,212,1,178,63,101,108,21,60,226,164,189,178,191,164,14,130,253,211,82,162,209,199,23,248,243,208,248,249,158,141,215,199,86,0,246,74,146,131,115,160,41,65,31,203,224,248,194,77,33,67,47,171,200,140,46,76,21,188,172,177,183,243,246,224,185,32,56,122,180,233,201,25,233,15,85,45,133,25,16,136,35,136,145,142,15,86,80,133,48,119,224,178,65,40,193,213,90,108,89,160,56,151,217,217,57,103,175,63,242,81,89,154,80,29,72,39,62,162,124,64,207,184,236,170,24,70,121,44,61,235,14,3,108,68,201,57,178,69,188,58,91,211,235,251,154,69,34,123,86,213,66,253,253,216,176,67,99,197,91,185,250,198,244,215,134,106,130,27,155,101,61,23,181,173,83,247,184,185,24,221,87,94,129,150,24,83,250,180,99,14,23,157,95,133,189,98,219,252,120,118,181,213,41,131,138,220,245,32,75,155,209,55,31,197,21,188,175,14,108,96,144,219,70,87,169,105,80,215,39,54,253,164,135,220,113,179,11,26,86,90,17,173,82,168,51,234,219,159,197,190,211,12,96,163,96,156,21,216,237,81,71,8,238,177,222,65,238,18,207,224,198,6,78,77,58,229,128,113,49,80,53,64,60,188,235,183,243,253,19,186,159,48,179,25,11,199,176,100,249,48,94,85,170,164,215,111,157,248,47,235,115,199,148,241,90,5,156,158,194,36,48,2,128,54,251,107,121,73,162,149,9,148,65,58,167,164,203,170,52,197,196,44,120,167,22,204,41,135,101,200,149,248,38,73,57,71,205,69,158,255,72,185,219,30,199,49,162,53,242,190,45,142,206,11,94,30,40,120,221,10,171,209,31,64,30,69,102,138,222,180,169,4,28,97,34,15,174,50,15,217,31,255,141,56,24,233,173,156,216,252,142,255,94,59,43,223,147,253,34,44,189,10,93,55,252,67,27,40,123,12,243,5,33,140,234,16,240,115,171,26,131,179,201,114,216,135,196,14,204,11,226,91,159,139,238,182,65,152,10,212,173,146,189,31,16,197,251,214,140,176,101,41,217,127,19,65,118,112,116,119,159,28,52,102,175,254,92,132,73,106,70,124,121,229,34,136,208,230,102,14,165,73,4,170,233,83,76,138,148,54,152,21,227,68,40,188,180,162,79,72,48,228,26,205,64,66,33,171,221,163,170,114,114,184,172,219,201,168,200,24,77,52,12,80,226,95,105,205,101,189,221,3,5,202,38,226,148,208,76,126,116,245,120,125,186,56,187,96,82,46,133,211,10,66,86,187,156,137,23,160,98,171,226,232,11,114,200,18,250,211,87,122,21,93,163,90,104,194,160,53,194,74,207,94,195,91,24,76,184,136,174,136,22,245,12,54,167,76,106,249,48,251,40,188,97,95,223,30,22,142,194,231,189,143,57,151,51,105,150,197,223,211,167,34,90,118,91,128,229,236,240,185,96,234,208,26,179,111,122,244,232,80,12,38,10,75,30,38,189,236,165,19,26,106,197,252,71,235,185,204,73,177,213,143,142,148,0,198,150,67,125,250,112,233,80,164,49,60,6,157,40,93,68,163,97,177,11,138,69,11,80,35,151,37,226,112,83,104,68,199,208,112,120,18,122,5,174,225,120,249,246,187,239,139,207,193,43,156,214,226,0,98,218,49,189,224,164,249,146,98,223,125,50,17,156,249,81,199,227,5,93,233,167,93,238,114,241,192,104,44,145,2,60,79,168,0,112,62,78,120,31,150,105,225,33,243,194,10,247,239,80,186,67,248,147,112,190,206,149,49,185,35,4,129,193,254,128,152,100,164,105,79,44,168,54,203,1,129,230,43,92,174,4,56,200,148,20,82,211,212,136,193,83,214,240,81,138,39,11,132,114,55,99,194,4,143,40,233,177,238,255,46,166,183,5,115,190,182,171,253,136,6,248,32,219,26,252,55,109,189,224,176,219,6,131,136,170,148,101,102,58,242,121,97,120,125,146,126,232,251,70,200,193,191,199,169,112,172,43,218,147,205,17,215,99,9,141,194,206,149,104,71,115,45,250,190,121,28,115,88,81,131,250,172,238,160,98,146,119,165,113,166,10,172,34,174,43,44,119,114,32,110,169,188,210,22,181,71,3,8,218,196,202,103,105,234,72,209,168,202,3,206,120,58,52,91,169,202,207,73,67,52,223,246,40,85,129,186,17,147,193,231,46,110,139,178,74,210,186,252,20,42,212,66,107,31,239,184,60,105,247,138,212,29,59,35,147,239,109,123,57,144,11,149,66,71,134,57,20,223,47,197,51,83,184,140,102,217,213,245,43,232,173,139,129,135,141,23,147,64,170,6,101,154,52,47,242,34,140,3,101,199,41,95,122,146,104,251,210,114,60,120,85,93,235,23,132,185,200,46,225,58,185,30,23,139,234,67,231,176,36,70,216,129,111,57,23,74,254,117,89,199,41,209,178,61,214,211,184,105,167,86,249,49,90,42,123,168,58,104,222,200,67,41,108,0,17,167,116,177,110,201,116,233,182,36,97,100,6,194,14,109,98,123,229,192,135,60,139,212,178,229,24,178,75,57,129,64,124,38,73,23,182,0,233,69,40,62,242,69,133,151,96,88,46,115,166,144,227,171,12,67,150,150,224,205,128,11,68,98,7,65,199,98,217,18,163,103,246,75,237,111,191,192,188,237,204,240,118,109,98,193,54,170,132,185,37,96,110,213,152,18,190,35,50,82,137,93,149,215,225,221,42,90,5,238,158,171,51,61,216,167,102,11,175,66,32,95,200,136,58,38,185,31,31,7,154,137,77,199,135,129,68,11,138,218,56,51,63,138,232,178,118,35,168,128,222,75,254,4,133,240,20,138,225,42,242,179,147,238,252,236,171,207,216,158,161,187,121,28,211,191,97,168,90,83,211,109,149,65,124,180,9,172,11,247,233,144,178,35,236,201,59,110,14,121,70,14,224,61,254,78,212,28,174,65,117,240,197,140,63,81,231,180,236,142,119,35,45,55,146,227,92,243,89,103,227,113,113,7,241,196,218,216,222,133,210,176,201,227,29,129,190,164,242,224,9,230,82,122,179,114,75,246,39,15,229,149,39,223,54,20,209,236,251,52,201,186,78,73,37,151,126,3,228,78,186,96,42,131,8,164,251,31,66,192,181,12,97,55,186,77,32,219,199,151,33,3,42,85,29,142,29,6,107,115,68,114,214,114,140,199,143,20,245,129,9,78,83,246,169,65,41,122,99,69,204,115,173,8,254,95,66,163,162,48,175,244,113,209,100,147,112,188,220,233,113,5,212,201,138,91,38,191,72,7,99,178,116,234,92,48,244,0,211,154,27,247,206,232,89,85,99,233,132,72,85,200,139,238,153,179,24,123,99,134,246,142,188,239,9,157,112,162,234,185,118,245,59,130,224,204,31,163,171,38,159,221,225,99,216,177,58,35,104,109,10,125,89,23,53,56,37,68,165,189,60,83,249,63,161,240,70,141,1,210,143,125,157,56,227,11,24,55,38,168,16,119,213,155,223,143,131,175,37,234,125,238,16,194,101,201,158,4,110,18,210,221,84,87,14,13,169,250,241,240,1,12,205,98,246,198,75,250,239,249,104,97,127,57,19,15,104,126,28,59,196,119,32,32,82,17,212,81,175,226,118,175,241,105,177,135,71,82,187,16,240,159,71,37,41,230,115,64,156,184,169,24,234,219,0,246,117,253,167,73,143,69,3,130,245,116,43,177,166,154,119,212,153,47,46,26,192,155,252,200,241,110,201,195,252,231,181,147,45,221,62,85,89,150,72,79,230,174,245,52,49,209,202,184,143,160,9,190,63,249,33,193,163,53,123,237,31,46,225,42,225,49,158,14,120,71,133,247,37,52,27,195,168,0,173,254,175,48,203,127,136,142,20,140,58,102,224,52,13,72,195,143,146,84,91,160,228,92,126,63,39,81,150,207,232,13,28,22,22,113,169,45,140,23,5,46,155,127,197,116,25,54,226,104,89,169,95,100,83,211,41,119,115,107,60,190,170,12,213,173,189,220,228,10,211,105,116,245,166,208,229,181,165,201,68,170,57,36,97,78,110,76,75,65,230,77,138,17,146,196,148,196,16,237,121,105,24,158,75,121,236,185,205,129,31,100,68,181,179,248,183,65,29,74,96,126,223,176,27,19,62,148,147,12,48,70,173,22,7,123,162,216,137,16,123,171,81,196,100,84,138,92,119,3,209,28,49,46,184,35,78,201,26,213,233,176,139,204,161,161,100,134,151,46,27,220,236,243,154,104,171,179,29,24,244,219,213,4,109,217,17,167,110,219,11,225,255,47,80,164,122,91,85,104,133,179,78,39,122,132,12,176,53,220,175,184,93,42,5,93,129,217,176,225,1,179,77,53,121,239,203,231,143,218,94,107,129,31,11,195,254,148,78,105,60,149,153,223,20,120,153,7,211,141,71,154,236,170,254,85,202,104,196,108,18,145,215,252,129,244,163,252,137,151,112,146,157,1,59,187,240,13,15,2,216,118,65,35,126,38,27,221,174,235,245,160,106,120,196,95,105,214,48,54,136,226,74,65,88,37,3,224,245,60,140,2,150,249,134,212,251,59,123,169,14,76,79,118,67,227,62,202,182,40,50,114,7,24,44,54,254,33,251,230,193,198,191,167,178,228,71,214,100,187,93,9,99,58,230,102,178,170,160,39,178,130,14,57,7,70,171,249,174,14,35,35,120,237,233,152,182,162,97,118,134,142,150,24,7,159,154,144,20,178,175,155,125,114,58,253,140,118,189,3,236,201,17,137,170,158,6,138,214,209,52,137,203,102,157,11,99,113,92,97,55,117,153,111,20,219,251,13,105,77,46,143,89,53,195,147,116,53,124,195,182,95,154,49,226,94,206,124,56,128,210,109,131,196,167,229,110,5,138,241,184,84,170,48,209,20,77,49,194,144,208,224,23,8,82,52,152,83,235,136,168,48,59,7,125,42,229,139,89,170,227,83,9,67,233,174,188,101,17,74,229,208,35,149,23,105,183,73,116,1,80,193,46,164,25,242,129,1,17,88,87,87,94,55,96,126,151,60,35,202,219,9,3,222,161,131,34,149,198,202,198,131,167,91,75,106,85,22,230,193,8,201,156,81,226,164,111,44,147,161,162,209,240,123,26,148,30,161,104,16,29,236,170,204,149,74,126,34,109,24,139,125,1,32,228,137,89,30,201,147,146,189,177,123,185,72,228,107,91,49,121,163,27,243,72,155,29,183,58,67,212,196,210,201,58,31,102,67,158,141,70,175,80,213,3,99,198,124,34,110,94,209,77,20,85,45,162,82,18,61,189,203,199,56,131,228,230,7,53,226,247,217,35,66,115,37,68,130,210,200,156,186,44,33,11,229,31,84,159,92,194,52,14,158,187,179,106,80,194,179,80,226,202,110,147,204,167,44,63,158,49,55,80,115,164,46,156,244,58,137,134,55,253,220,75,9,103,136,249,242,3,215,220,53,123,17,75,112,40,131,105,76,0,16,17,245,242,195,47,165,106,200,206,26,130,189,65,203,2,99,181,5,143,191,100,128,52,249,154,169,127,159,85,163,175,105,201,79,170,124,33,172,15,229,166,146,194,104,108,129,91,132,33,195,224,4,116,61,113,89,52,79,251,121,2,32,71,98,121,115,214,245,87,160,16,97,250,177,149,55,39,223,212,203,76,231,248,127,176,129,187,75,9,209,101,237,148,65,111,200,193,164,44,66,237,159,220,85,84,91,89,208,128,237,151,180,31,151,237,151,16,114,221,155,43,42,4,83,34,238,79,149,66,231,157,222,132,11,145,104,170,56,236,84,248,183,36,85,4,10,143,170,141,177,87,7,163,114,225,72,248,238,122,146,203,203,157,4,155,198,245,193,60,218,180,175,34,89,80,195,35,71,85,234,238,86,77,49,244,128,157,230,211,30,114,38,88,35,242,190,254,27,132,194,18,236,121,228,133,95,97,44,236,154,28,64,235,14,62,141,6,104,2,239,196,0,239,190,200,189,55,225,88,118,166,28,3,155,39,73,135,166,250,86,28,103,243,78,21,135,177,206,135,183,141,13,148,181,253,155,176,98,53,113,191,110,156,23,111,210,0,12,145,6,255,146,80,247,0,74,171,33,213,96,90,118,193,89,208,79,47,247,61,246,11,199,235,65,231,27,63,41,110,254,129,80,132,0,167,84,59,171,175,164,131,185,207,179,36,207,187,236,180,205,188,150,112,119,170,82,180,155,78,6,33,163,196,74,97,85,204,95,48,248,81,22,74,219,228,3,163,28,111,155,134,69,37,9,187,242,25,75,186,8,17,151,196,130,59,118,14,82,207,194,129,82,65,199,147,72,96,117,243,22,125,145,219,206,184,153,41,144,219,98,96,155,34,94,181,44,163,237,168,33,89,151,218,192,247,57,198,126,236,197,141,63,109,159,157,29,83,185,46,181,8,73,42,95,252,161,116,224,219,172,169,119,219,52,46,170,69,178,172,93,174,0,45,81,139,114,181,102,240,100,159,66,137,156,200,175,244,173,51,117,206,244,24,77,6,23,82,12,37,118,160,225,85,183,69,79,100,126,129,93,155,18,95,145,39,32,118,241,90,236,152,14,20,126,31,234,84,34,120,172,90,243,50,162,34,238,83,91,24,255,99,225,240,27,114,166,100,243,207,98,170,111,107,224,19,79,177,203,231,135,126,205,13,231,108,153,215,16,143,6,18,244,71,18,188,143,224,169,189,54,129,185,202,121,10,142,246,219,251,81,92,184,115,207,55,223,23,9,172,6,80,2,236,96,4,51,62,54,135,46,10,0,229,235,188,235,218,127,115,177,136,157,40,2,71,146,32,245,200,137,190,179,220,117,208,242,197,14,183,79,124,35,171,203,89,139,208,30,50,32,249,148,242,236,98,48,88,255,143,25,1,235,159,210,127,229,219,6,20,19,41,23,220,116,32,214,217,7,197,244,101,247,93,18,117,151,140,84,68,104,42,232,36,226,57,55,57,181,128,52,6,203,130,54,199,103,197,158,184,138,127,61,223,65,111,57,25,181,72,139,155,65,139,48,15,128,95,194,241,163,12,246,39,191,53,212,114,194,90,65,109,13,121,48,171,160,68,35,192,251,149,193,182,207,178,158,107,32,192,59,214,166,145,205,76,194,17,236,248,105,195,184,201,91,214,106,71,163,206,253,189,15,166,160,158,55,182,108,213,82,244,47,221,194,227,48,139,93,104,165,186,46,214,47,63,142,36,158,192,116,253,133,77,50,45,85,208,33,203,120,156,6,55,217,53,210,131,30,194,170,65,32,80,32,81,218,104,125,77,236,131,42,23,51,41,208,230,40,175,127,201,126,254,209,89,221,187,181,101,185,235,139,217,248,49,187,232,192,124,28,52,88,70,236,155,38,60,43,157,178,180,45,203,113,4,9,67,86,60,136,52,5,61,152,126,254,205,152,68,61,64,58,226,75,218,19,204,177,16,138,148,243,180,234,110,6,134,194,139,167,50,151,95,62,160,137,209,208,255,81,199,177,240,114,1,163,160,235,235,172,203,57,245,240,94,121,56,11,132,16,23,152,180,38,90,26,107,103,77,223,70,133,160,220,55,161,159,238,135,127,195,39,208,86,53,94,195,241,255,207,90,238,9,252,64,51,154,107,238,114,42,193,58,242,19,108,172,209,86,71,42,197,80,100,152,114,254,57,174,37,64,50,36,160,251,173,106,84,18,16,170,209,101,166,151,240,142,96,134,97,50,207,93,244,231,22,49,72,181,188,188,85,53,41,160,158,84,157,23,30,169,226,115,33,73,115,107,143,0,226,138,147,191,74,190,144,231,29,158,45,154,232,182,228,53,105,112,118,75,176,179,123,111,233,14,139,90,157,138,223,14,191,88,106,91,191,149,119,119,125,12,238,211,244,188,43,214,146,153,165,147,172,221,81,131,160,19,124,234,236,188,144,176,73,96,127,208,169,247,17,186,160,163,61,186,59,233,72,217,58,90,43,43,23,250,105,188,236,66,19,98,125,250,90,130,162,167,174,46,218,37,184,26,92,237,34,0,26,104,74,167,221,23,105,113,9,187,125,231,185,93,92,121,93,23,185,54,19,90,235,249,3,121,58,43,88,53,140,51,45,206,210,228,223,67,147,216,82,11,167,178,164,218,132,152,116,134,84,112,15,165,106,15,116,46,222,118,186,76,133,157,255,99,27,35,96,230,14,223,36,164,244,30,234,71,169,225,124,239,103,239,185,44,71,223,241,177,16,211,173,64,220,127,244,65,244,249,195,214,90,121,43,248,177,241,128,96,74,224,104,16,53,79,225,14,219,175,78,129,103,35,184,131,156,66,49,75,196,237,145,109,124,157,74,188,157,84,32,153,170,210,235,165,6,155,60,118,114,50,169,40,37,1,220,122,220,107,20,39,19,238,244,128,227,140,103,0,179,250,11,140,38,165,57,63,111,193,84,165,175,223,21,24,232,153,190,211,114,99,96,103,146,32,24,107,66,117,93,27,243,49,114,246,219,30,34,20,17,69,183,243,131,101,22,123,146,89,58,14,130,29,141,36,211,54,162,164,189,208,207,2,157,64,29,178,133,166,206,71,226,123,104,195,207,127,14,140,247,187,212,124,199,222,83,46,134,206,111,75,190,63,73,82,47,139,200,197,11,130,44,168,239,104,124,162,31,115,106,15,77,72,8,188,215,102,185,145,177,146,105,215,243,128,236,120,202,35,200,18,3,56,41,51,228,233,136,75,253,209,15,226,133,173,67,184,30,89,158,18,91,156,153,18,111,152,178,1,79,85,158,151,216,76,58,134,155,146,49,89,17,51,188,208,128,156,11,43,131,131,106,12,149,63,166,121,16,63,219,137,51,65,222,5,172,189,253,110,113,53,167,226,44,245,31,50,38,174,100,68,22,13,112,212,36,155,239,195,60,53,18,123,223,198,86,22,195,153,183,238,240,84,186,32,5,221,42,82,204,140,146,40,142,221,64,66,150,70,55,47,30,39,14,91,230,39,190,250,204,44,92,192,48,150,46,192,2,42,75,126,145,237,31,191,38,153,131,36,227,179,79,231,201,9,204,104,33,64,247,81,36,153,134,244,72,253,218,167,247,131,248,178,75,238,207,226,79,244,209,92,176,76,70,26,233,159,72,80,240,245,86,236,211,60,129,147,52,202,224,10,121,136,140,72,97,73,10,133,96,120,170,207,50,34,150,192,32,223,232,196,218,17,88,13,218,31,177,119,20,156,206,58,133,152,213,248,174,186,249,107,70,175,113,37,10,115,145,51,107,100,20,219,82,204,77,140,219,219,169,215,58,48,94,235,31,79,145,66,12,48,214,3,229,197,44,184,188,88,27,187,162,100,106,211,186,207,12,7,55,129,174,102,0,79,203,232,178,166,41,96,67,20,205,236,10,17,185,214,114,166,94,180,205,186,114,55,253,184,106,217,46,50,15,196,129,214,56,81,178,117,165,228,136,107,226,194,252,239,232,52,189,121,119,33,227,225,214,234,74,40,173,225,105,36,9,32,65,235,127,209,218,119,230,246,90,85,92,208,117,25,145,241,125,158,150,196,130,194,200,251,49,170,85,124,87,213,239,96,184,96,197,63,244,187,217,215,49,3,224,114,164,10,22,251,65,108,238,13,29,254,18,139,129,219,58,169,151,73,96,64,221,26,16,12,14,12,78,9,203,11,80,73,221,118,103,173,1,169,193,215,109,126,166,137,12,12,135,17,81,209,32,12,131,60,0,153,66,201,121,182,155,39,109,173,1,186,45,253,219,88,63,179,91,22,106,108,66,107,17,105,97,59,6,133,136,82,129,125,190,184,234,131,23,198,146,94,243,204,25,190,50,160,81,176,220,38,215,41,120,112,38,74,163,171,24,106,116,214,231,194,77,99,71,195,47,141,134,111,103,119,122,241,34,5,170,123,150,232,85,63,156,112,76,202,78,176,136,79,161,164,245,223,119,235,27,8,99,121,57,0,225,90,143,129,173,209,102,133,158,64,233,181,113,212,237,35,132,15,88,36,85,226,152,217,11,16,251,213,25,7,85,125,48,155,221,141,133,205,66,237,6,5,241,72,247,133,199,177,78,236,71,27,110,205,207,241,40,22,141,156,101,179,172,227,30,248,161,147,84,177,176,26,32,103,36,110,30,67,137,223,121,255,110,247,94,76,30,149,83,111,96,72,165,93,200,58,207,176,213,13,29,75,187,45,112,179,43,234,213,242,216,43,249,33,207,40,167,96,46,219,167,44,111,57,183,96,243,201,5,215,73,106,130,134,7,142,153,17,97,126,88,35,57,154,246,15,16,48,120,187,131,106,242,11,250,99,54,230,135,88,172,62,208,30,127,145,236,44,247,246,202,229,174,206,139,144,172,167,141,73,106,163,33,202,57,80,76,67,219,18,99,153,119,22,223,8,132,90,173,119,88,241,34,158,228,149,129,248,73,110,153,176,170,26,33,117,151,227,204,107,181,26,21,245,164,236,219,77,199,199,35,205,68,49,148,238,100,242,214,99,155,100,23,181,56,99,13,119,225,107,153,143,182,246,225,208,95,196,75,114,87,98,134,84,115,210,91,16,159,38,83,255,6,141,147,176,178,28,7,98,154,157,117,22,186,222,203,229,195,97,78,111,21,1,209,7,216,220,49,206,103,113,12,92,248,125,213,205,208,125,25,23,255,131,122,18,244,102,110,19,246,57,97,29,160,122,12,249,191,178,249,218,202,196,118,95,227,2,202,72,253,166,224,126,142,247,255,235,17,182,40,239,72,49,69,198,190,146,45,197,143,72,232,60,106,114,24,207,64,199,21,148,63,154,255,94,65,161,221,130,35,137,115,115,180,84,241,144,61,126,156,106,22,242,150,187,185,206,193,114,109,233,188,162,195,80,84,37,148,76,38,233,82,107,55,196,65,244,142,66,169,247,79,119,3,176,143,31,254,163,250,36,254,95,244,199,37,243,80,12,199,218,35,41,133,113,33,14,19,65,68,109,255,12,46,255,36,190,184,245,158,28,243,54,230,255,252,10,28,140,185,137,52,36,177,174,246,253,228,33,46,4,171,48,142,104,247,44,43,68,29,108,218,170,183,172,241,193,73,207,219,37,138,1,150,130,219,251,45,165,77,163,56,41,211,48,28,136,245,232,57,137,129,92,21,128,45,154,238,208,32,231,214,120,74,179,72,201,37,186,206,84,50,7,123,49,12,239,253,65,164,149,178,102,109,53,34,240,96,200,137,6,135,145,49,172,151,73,182,67,200,127,30,211,36,85,185,165,56,97,54,221,209,90,70,22,143,152,129,15,204,59,5,143,171,180,132,244,145,20,44,11,142,181,72,223,151,147,26,241,164,157,222,7,97,79,43,35,103,66,163,25,155,118,174,109,181,98,111,56,136,55,63,81,51,89,250,61,148,153,110,132,172,218,99,18,104,242,83,175,53,197,209,126,182,44,53,73,229,104,21,252,214,227,27,176,170,31,200,156,251,40,253,90,104,145,10,1,175,235,135,77,56,137,11,51,99,233,59,250,122,62,196,2,245,142,86,59,143,192,123,130,214,245,182,157,134,228,82,199,243,29,167,83,105,75,4,236,116,174,50,18,89,242,200,87,109,23,221,184,42,3,82,80,103,135,218,190,7,129,98,180,64,149,196,181,217,136,28,58,56,53,14,16,248,30,82,197,85,149,53,2,112,81,243,53,131,126,174,187,3,237,209,3,20,9,246,22,3,194,201,118,169,89,116,66,199,66,16,175,193,47,238,65,137,126,87,148,144,167,191,216,137,23,120,162,24,80,68,168,161,148,167,6,137,56,1,160,59,75,181,56,92,175,90,233,7,212,173,52,242,167,91,64,194,196,220,18,71,186,221,224,84,47,76,156,55,190,180,102,18,21,27,55,125,249,219,154,48,54,210,58,72,73,154,78,48,73,105,233,200,178,230,208,130,172,18,160,79,130,20,166,83,203,232,203,108,136,211,228,152,192,103,222,8,46,245,50,29,25,234,254,228,47,202,93,242,41,33,139,115,212,186,141,90,222,177,4}; diff --git a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_16spp.cpp b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_16spp.cpp index bf828c52..4ecb1f3b 100644 --- a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_16spp.cpp +++ b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_16spp.cpp @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // An Owen-scrambled Sobol sequence of 256 samples of 256 dimensions static const int sobol_256spp_256d[256*256] = {32,226,72,70,57,171,246,75,112,81,109,239,120,101,230,103,103,41,249,86,253,99,132,184,214,147,128,248,17,149,163,17,60,40,169,196,77,79,102,23,250,77,75,151,95,123,234,198,25,26,184,114,230,188,105,18,231,233,175,151,19,174,202,71,84,229,247,148,182,127,92,14,41,112,162,253,35,101,137,30,111,134,95,122,28,2,41,254,181,91,101,188,145,31,166,38,53,193,1,122,99,86,178,36,198,169,113,255,97,221,227,231,29,100,30,141,250,254,16,157,2,220,187,95,181,125,207,187,105,119,156,41,16,194,93,216,227,124,138,90,227,1,88,153,233,69,120,36,19,189,120,4,185,220,185,109,184,96,247,173,210,227,54,3,18,9,139,213,156,57,61,101,37,247,21,201,10,143,11,38,146,18,118,129,95,191,75,207,12,252,238,104,47,39,190,229,31,56,20,127,42,178,100,141,93,222,192,247,186,7,224,161,72,100,87,69,218,44,25,195,185,118,179,123,231,170,96,225,204,52,117,60,3,86,25,143,230,18,11,165,72,188,158,3,66,105,50,200,226,145,227,45,183,62,82,176,191,36,248,191,189,122,96,185,146,166,203,78,144,189,67,174,154,182,86,169,90,236,101,40,71,107,81,93,159,82,75,230,157,191,34,35,235,139,150,193,10,142,217,77,154,249,74,13,196,248,56,154,27,6,242,226,105,94,66,67,145,112,31,145,133,68,21,0,44,212,254,153,183,238,98,102,145,199,100,213,196,52,131,141,216,209,236,122,58,249,188,108,8,206,62,199,207,103,160,247,207,255,101,185,1,113,223,126,182,0,50,93,250,174,194,18,65,111,206,104,156,3,48,195,122,212,10,101,235,200,13,183,173,7,192,3,101,228,84,168,121,241,205,122,115,132,155,242,215,22,236,242,69,35,48,245,3,175,68,57,4,15,226,155,222,140,54,48,80,200,194,149,213,68,225,14,182,122,147,195,69,166,191,17,176,58,222,58,190,70,66,153,196,215,121,123,176,190,161,145,203,121,255,27,207,28,113,22,44,232,46,84,181,131,245,220,27,202,161,38,94,208,39,143,52,5,154,85,121,139,226,223,159,246,170,56,94,209,188,71,205,76,16,233,168,172,200,37,19,123,120,202,28,175,232,88,120,107,157,198,111,253,18,24,36,35,43,169,199,197,137,194,12,238,138,232,17,17,58,115,39,234,4,164,225,215,14,185,232,76,215,171,142,206,206,132,90,31,130,24,0,165,34,91,126,113,64,202,144,114,132,125,58,184,234,211,246,238,168,7,1,172,169,218,67,29,185,66,73,49,222,167,243,189,36,116,23,223,219,200,84,67,94,53,79,26,202,204,91,180,221,166,106,18,207,17,128,137,246,235,162,13,129,130,49,76,104,189,138,55,174,71,152,49,116,204,207,103,198,147,225,142,79,8,172,59,234,225,192,168,181,144,185,6,233,243,61,123,46,55,44,16,228,79,156,235,190,115,61,162,115,182,122,230,138,204,140,86,173,80,99,207,211,181,23,141,152,17,180,35,121,168,67,205,107,74,55,229,234,210,6,94,48,186,210,189,2,200,190,181,227,128,211,225,215,228,74,7,188,195,36,82,10,131,96,99,138,63,1,210,39,134,153,112,72,163,196,55,126,37,125,107,234,166,129,80,61,97,121,20,123,222,3,155,219,62,49,207,87,182,26,214,167,142,89,38,36,112,87,100,56,245,240,152,23,7,237,11,185,206,233,203,131,42,53,35,60,40,211,114,9,13,189,130,196,210,173,39,208,56,110,34,240,65,75,234,76,73,34,39,2,118,174,237,52,194,197,28,155,161,135,180,200,3,89,210,26,154,145,45,57,54,85,26,118,207,212,58,101,69,202,184,36,234,219,155,41,29,80,22,193,175,145,100,50,29,149,166,168,162,213,130,36,25,234,78,84,97,191,139,95,156,9,12,41,97,110,222,8,16,250,161,130,45,111,195,83,213,16,141,154,48,124,175,89,25,27,9,172,242,51,167,76,109,69,107,23,80,23,166,12,16,180,156,182,238,148,249,59,130,75,122,59,134,240,69,220,21,230,47,1,124,66,180,77,247,147,103,66,98,211,96,105,213,127,178,144,102,213,33,247,141,232,67,62,86,230,222,146,68,122,27,147,7,85,69,31,22,67,67,78,13,149,221,57,121,176,133,161,84,201,146,119,196,217,19,132,52,76,135,247,107,29,131,248,220,156,248,29,41,36,202,174,136,253,191,226,91,179,96,69,213,172,0,206,75,192,54,69,120,138,218,171,185,232,211,139,8,31,11,50,119,28,197,83,158,170,229,244,195,190,23,213,87,70,17,102,197,39,59,88,152,234,95,106,29,195,236,114,136,6,159,105,101,2,119,184,47,212,218,188,165,163,138,174,114,71,54,127,64,183,39,51,42,209,202,106,96,215,154,56,33,102,25,62,111,9,49,4,98,142,198,128,138,13,74,95,229,42,164,19,175,179,111,138,19,157,125,94,34,221,103,246,144,141,176,129,201,55,100,23,12,139,33,227,91,223,224,69,120,83,245,50,57,190,21,54,86,245,95,250,34,71,249,100,201,144,16,221,0,40,74,133,38,145,48,217,119,132,34,138,67,161,62,221,126,108,207,140,42,156,13,224,198,142,19,55,85,254,155,140,168,250,58,118,137,42,78,8,48,89,195,167,91,243,246,88,23,22,206,17,190,56,125,171,116,245,129,121,57,144,228,159,197,243,217,239,86,188,152,88,239,112,120,245,119,147,189,25,128,240,72,208,29,162,23,152,24,143,226,136,174,171,58,178,10,5,250,209,239,88,62,34,251,156,163,231,247,102,112,46,48,61,233,24,71,54,73,12,81,195,243,115,138,145,194,164,135,148,51,201,104,74,24,78,107,65,246,118,159,165,130,206,34,157,177,180,10,126,163,167,129,75,0,149,115,172,21,242,139,162,170,92,238,35,46,24,108,101,62,26,147,180,210,227,166,103,149,188,192,92,115,141,161,120,90,231,250,181,130,208,232,151,157,141,208,27,81,82,42,162,244,186,62,163,6,254,94,107,138,123,144,14,216,138,235,104,135,98,77,82,57,47,77,171,213,192,134,69,226,93,197,9,63,181,197,169,22,248,190,55,178,250,167,76,157,101,170,138,94,156,44,12,155,102,133,133,149,43,224,51,130,44,138,3,195,25,161,29,216,1,188,160,73,4,196,125,240,92,88,50,192,176,234,39,109,96,39,60,165,226,80,248,179,232,244,141,102,81,131,110,19,206,225,222,115,198,63,195,251,19,155,77,51,194,251,124,13,77,69,106,112,114,187,126,67,222,81,227,163,80,172,25,70,205,111,48,160,111,165,112,243,47,236,107,81,15,83,95,132,80,133,178,116,87,10,195,139,151,122,44,82,111,24,234,156,187,202,250,20,233,186,204,184,154,149,117,78,205,119,71,166,192,239,88,148,154,229,200,139,163,129,12,155,167,252,50,198,46,106,221,91,235,75,2,14,240,122,62,178,218,42,223,213,6,17,212,242,32,190,96,163,121,63,228,65,111,229,63,70,140,232,221,248,216,80,5,145,12,27,33,195,86,111,42,125,70,44,232,82,209,40,234,168,224,215,215,133,247,128,76,248,178,34,253,61,204,193,105,44,227,66,45,238,159,16,241,67,99,178,235,181,68,204,234,144,58,40,132,125,203,25,204,148,151,253,195,198,81,8,54,248,148,248,58,54,235,82,71,67,181,212,241,43,111,111,202,69,166,200,66,87,245,207,70,112,64,26,240,149,82,86,28,104,17,59,72,154,106,1,173,59,21,204,184,231,15,224,161,253,174,78,249,25,217,35,144,180,57,102,174,57,138,227,125,141,246,16,35,201,173,170,31,107,205,169,59,19,52,209,226,49,136,168,13,238,63,53,78,203,68,18,146,228,165,245,244,84,215,78,230,167,83,239,15,210,34,99,90,184,143,187,50,98,95,182,121,47,53,112,15,53,239,130,105,66,142,11,185,224,203,20,44,156,28,197,195,65,118,36,206,88,55,37,18,112,9,20,231,73,6,11,225,79,180,145,124,204,29,245,148,198,53,210,171,103,53,215,106,111,154,237,107,2,249,79,145,126,255,255,53,222,196,57,237,131,6,63,45,70,68,190,191,12,210,247,162,41,135,184,234,206,153,176,115,255,114,178,110,24,25,66,114,55,29,79,253,67,124,245,37,236,13,88,232,186,18,143,178,59,5,237,10,249,253,37,88,46,134,71,53,74,172,186,69,137,11,154,60,68,120,125,100,91,182,239,177,38,28,125,208,165,38,150,207,244,41,88,127,241,251,168,84,195,111,37,211,165,113,3,212,184,180,207,48,52,204,171,213,128,154,138,218,69,214,154,99,201,203,109,93,71,190,5,99,1,72,173,15,149,49,253,51,82,171,179,114,131,68,114,133,15,104,227,141,109,39,68,225,130,50,51,133,154,148,48,28,230,9,43,157,50,133,203,239,37,160,233,120,54,20,116,57,174,116,158,45,8,196,14,200,80,203,212,233,1,0,88,172,214,196,22,192,224,142,138,146,230,105,100,153,155,112,241,124,26,71,253,143,4,191,50,49,88,226,25,142,141,13,12,50,159,122,211,42,168,23,217,253,218,151,135,3,152,114,102,191,76,186,42,124,70,19,56,25,85,234,58,57,225,230,253,56,194,107,134,142,201,213,43,14,33,242,16,141,205,196,99,143,100,115,5,99,128,100,221,174,110,191,83,165,164,78,60,124,209,199,63,185,120,175,43,3,24,40,153,1,83,147,223,112,72,242,148,166,115,36,138,42,13,63,1,45,173,225,83,121,19,23,208,171,146,240,108,150,3,213,83,210,238,72,120,80,197,2,4,159,197,138,216,19,178,24,173,212,237,169,129,129,102,51,63,203,142,11,134,180,207,105,98,133,253,20,224,6,126,194,167,33,132,90,101,179,113,216,222,132,30,88,23,229,210,85,6,154,226,252,17,39,174,208,255,8,11,252,159,110,195,86,250,59,161,218,31,140,167,41,33,201,143,250,68,82,205,44,4,77,43,214,212,60,82,214,41,44,125,236,152,34,64,133,184,58,145,227,65,70,73,166,49,21,158,242,114,42,75,209,36,72,188,192,146,223,138,76,27,235,115,153,105,169,96,209,231,4,33,105,226,175,187,91,218,12,73,168,214,254,98,208,113,214,116,177,49,34,94,22,127,175,12,155,193,56,187,115,187,240,136,234,206,189,250,115,219,154,17,52,62,198,63,225,81,77,90,127,246,219,192,106,223,78,102,88,142,46,208,156,230,196,67,182,18,112,210,126,198,59,15,234,166,243,77,61,149,24,223,70,245,142,178,199,101,195,190,109,78,244,224,12,84,52,158,184,88,212,155,159,128,187,54,48,209,190,202,157,70,122,109,33,221,124,227,1,196,124,121,163,138,238,25,129,134,83,111,124,60,142,46,143,48,85,63,5,77,46,251,193,209,81,108,149,108,1,47,137,175,85,106,148,27,204,145,104,3,152,84,228,215,113,141,6,117,115,151,206,248,61,43,182,198,76,88,12,222,132,75,73,8,205,190,32,12,159,70,205,4,158,0,107,220,104,90,223,181,80,7,111,166,130,16,168,145,218,242,101,35,165,172,12,217,239,157,76,37,238,176,63,124,243,45,101,181,191,200,64,186,170,42,104,154,191,224,67,145,240,72,82,103,93,108,220,251,36,178,110,145,98,136,83,2,171,177,220,23,98,221,2,160,216,219,237,90,105,255,48,157,136,55,102,122,181,7,225,55,229,254,215,169,94,22,44,65,136,50,190,151,198,54,132,81,245,106,71,91,141,176,162,15,210,33,14,140,108,81,17,135,249,17,44,15,121,28,16,114,178,210,7,129,250,11,239,18,86,203,161,124,2,185,178,83,110,168,3,81,125,80,149,8,67,30,212,0,129,8,77,255,114,243,68,8,119,210,232,104,244,127,165,159,26,176,206,160,228,34,116,10,3,91,65,149,163,43,43,44,171,113,113,223,206,17,63,64,215,216,94,118,5,139,66,201,213,30,120,149,18,236,99,41,81,175,245,1,7,171,209,151,134,28,32,122,201,13,18,46,236,215,113,188,192,221,39,69,117,121,255,119,26,59,142,121,126,238,179,163,183,245,98,199,32,46,39,137,236,232,52,138,4,60,86,83,12,100,44,195,49,107,228,105,56,183,18,177,222,50,189,188,97,197,148,94,99,1,198,221,121,206,54,31,212,145,62,73,77,213,189,38,66,13,139,69,173,57,26,11,176,245,141,166,141,203,10,48,45,201,17,131,241,115,13,165,235,28,129,88,72,36,124,169,128,6,145,10,109,219,198,187,90,149,67,215,68,116,33,56,204,217,236,231,0,205,84,97,113,175,30,185,95,187,166,164,123,103,0,218,18,150,180,103,151,153,146,97,15,161,171,246,252,131,198,186,58,55,210,93,58,157,3,142,220,98,50,202,151,2,115,205,200,3,236,146,210,233,71,222,129,198,18,131,29,157,152,63,201,45,197,253,170,121,124,232,64,197,112,22,208,106,99,54,41,247,146,135,234,142,177,3,38,157,234,222,46,189,233,76,41,150,255,135,82,99,244,246,187,81,215,16,76,188,188,104,156,21,239,255,206,97,35,217,194,13,70,106,106,238,171,232,93,223,145,190,50,39,144,48,13,113,146,151,178,156,18,131,231,168,108,178,224,7,44,122,98,87,166,65,220,174,138,98,95,93,188,127,246,195,136,215,160,201,137,35,217,167,126,219,175,109,180,111,127,222,93,69,133,2,58,198,186,238,108,57,157,101,174,249,26,46,210,254,251,76,43,197,209,161,52,197,28,246,173,229,35,43,13,81,122,34,245,212,223,50,135,69,70,192,171,78,9,135,189,54,168,232,131,250,208,59,227,252,247,231,40,235,203,254,51,25,198,223,165,81,140,141,67,194,180,31,194,172,47,195,56,153,118,221,30,217,17,85,154,184,122,15,130,179,86,8,37,33,200,95,144,73,175,68,185,197,128,182,154,171,147,182,86,172,23,236,20,92,194,110,253,124,133,82,127,206,92,34,108,69,170,47,61,41,87,108,218,3,244,7,124,51,153,83,186,164,116,154,85,123,43,135,177,107,28,189,81,241,214,189,235,233,142,6,109,183,130,75,79,107,99,67,31,164,248,227,114,159,230,115,116,115,252,33,75,4,171,191,217,88,245,156,203,48,239,140,253,211,46,184,136,34,21,248,161,128,156,16,88,64,71,34,174,125,70,164,125,92,205,214,79,157,199,223,143,214,138,213,150,169,17,16,181,95,200,208,91,91,55,125,7,1,39,91,6,103,252,246,22,71,110,149,236,73,1,247,51,2,168,88,124,234,86,100,6,94,1,17,215,157,34,238,126,194,222,109,67,175,96,45,252,99,58,3,34,192,251,95,240,36,188,243,191,229,74,164,55,171,108,239,73,208,140,114,46,244,36,30,33,56,14,209,94,86,28,9,153,30,23,102,165,252,98,77,72,233,22,126,152,98,40,246,35,93,137,114,191,114,200,54,214,8,238,145,43,119,180,186,55,74,170,232,166,247,56,233,9,162,16,241,95,47,5,109,72,125,67,35,130,55,138,75,157,246,85,244,3,230,60,226,159,12,234,155,160,180,119,243,253,179,202,194,53,218,65,208,230,212,71,228,29,49,220,31,146,244,249,84,46,237,203,93,171,73,33,115,46,109,10,163,137,73,18,133,213,236,174,230,216,119,127,80,199,18,100,180,236,191,127,152,158,226,45,72,70,181,106,90,21,229,46,41,109,55,237,81,0,158,169,63,40,22,85,246,181,235,161,180,28,175,136,87,132,184,54,121,185,69,89,58,20,54,81,101,87,37,251,152,4,162,108,113,248,178,219,151,240,144,158,242,185,138,4,34,148,255,250,66,75,144,141,25,248,244,89,180,203,97,141,149,179,129,213,186,64,101,242,119,130,121,108,230,198,74,228,155,96,237,140,201,158,44,127,161,120,219,94,11,95,27,145,80,184,107,215,88,252,32,89,59,97,159,249,183,75,131,180,65,184,179,85,80,88,74,128,53,126,191,54,169,0,133,100,248,196,158,91,121,110,12,248,130,87,248,186,85,136,101,181,0,90,45,34,227,84,17,40,96,221,187,167,131,112,48,70,62,240,138,78,245,248,226,203,255,32,242,246,141,200,17,167,32,151,12,72,159,221,190,56,115,237,233,226,113,71,228,167,60,113,127,28,174,27,176,227,160,77,221,157,64,14,166,82,60,78,7,91,16,214,169,78,222,97,33,229,210,4,255,104,234,42,181,7,177,190,23,40,135,53,67,63,28,151,60,167,81,21,190,110,214,160,222,51,228,87,83,113,220,46,182,163,193,79,214,249,120,197,244,197,169,252,20,33,253,246,46,198,16,208,35,110,5,37,236,172,149,234,155,32,36,8,249,70,224,226,40,16,146,131,224,173,250,111,102,227,160,196,255,167,81,196,62,24,6,39,4,245,139,98,158,201,247,5,6,2,61,92,5,65,70,24,206,135,30,246,146,155,22,29,247,25,112,186,5,208,134,240,95,137,29,48,148,222,92,36,165,248,10,244,222,158,131,46,156,217,243,219,101,123,98,209,124,89,178,16,48,173,142,241,134,127,160,217,64,134,35,244,28,253,59,26,10,212,162,143,252,94,0,198,0,16,156,116,145,64,255,206,234,251,104,250,213,247,171,89,86,125,48,237,216,196,160,45,90,227,12,33,58,31,88,200,117,101,36,105,135,49,134,64,181,233,40,63,100,189,192,13,48,58,159,183,105,34,162,170,166,132,83,141,116,29,39,216,84,29,224,211,54,145,251,248,148,150,203,26,51,179,47,134,175,80,66,223,24,221,52,170,59,241,37,95,232,183,15,162,203,144,221,60,248,8,211,255,78,249,55,59,23,131,11,165,152,182,82,168,71,89,48,249,78,107,182,117,73,21,79,42,128,232,89,103,207,13,224,32,236,175,138,201,54,26,98,122,91,253,144,222,108,171,101,120,208,168,40,29,46,64,23,171,248,115,40,80,28,107,143,65,188,142,205,155,234,86,121,157,124,23,44,177,188,201,222,229,244,169,241,155,62,102,187,15,28,49,168,157,29,135,202,9,160,102,125,112,184,31,209,162,114,13,130,215,93,15,255,110,50,54,19,144,98,47,46,170,252,210,5,161,176,69,185,97,187,253,94,124,215,85,69,73,136,150,68,137,217,52,113,151,241,70,44,102,126,10,143,167,133,81,239,233,109,73,171,141,93,133,112,185,133,103,206,49,208,130,79,127,234,48,173,231,82,200,74,68,194,188,185,26,56,199,134,122,3,153,227,174,245,23,34,49,20,68,184,202,1,232,252,31,171,45,85,7,114,187,66,203,169,98,117,144,15,165,104,143,111,174,100,197,60,7,53,248,238,100,12,162,96,40,189,247,101,64,57,57,14,195,114,229,155,228,32,111,37,141,8,8,163,2,223,6,96,54,144,175,85,141,51,77,41,60,192,113,15,103,101,44,30,102,189,100,251,227,71,37,62,123,4,63,119,25,116,47,205,191,156,1,106,136,248,37,151,162,72,226,41,208,133,69,146,114,137,43,245,90,115,117,90,122,134,180,218,136,10,36,210,53,138,90,139,213,130,56,173,119,174,71,72,213,138,87,171,101,156,110,0,164,38,191,156,215,148,220,106,138,50,237,54,37,49,215,127,45,81,226,61,181,195,147,154,208,170,94,34,8,228,121,71,182,239,63,56,65,244,0,70,162,73,198,63,16,134,216,58,187,203,234,115,44,209,105,127,183,130,74,82,203,219,128,128,162,13,47,106,252,31,56,155,184,119,56,139,70,241,3,104,153,43,183,28,68,241,224,25,154,52,51,131,108,142,150,13,106,43,251,166,76,47,218,150,11,125,109,109,179,145,213,217,241,16,32,208,48,33,217,59,171,245,248,174,34,191,77,111,183,221,49,141,59,221,76,224,103,190,107,171,215,232,44,84,133,236,88,227,175,24,57,144,252,229,182,140,36,219,42,92,101,187,212,188,34,205,167,99,168,91,224,154,187,112,52,190,62,212,191,250,250,68,229,248,142,143,161,185,243,117,222,69,61,162,247,179,140,133,135,164,217,144,222,8,114,20,240,161,44,27,187,82,122,237,53,167,43,2,215,122,219,61,163,54,181,154,176,222,239,12,13,63,88,213,167,98,162,94,254,89,113,112,242,88,158,65,229,215,16,126,234,96,129,34,233,231,85,152,90,16,97,32,90,134,18,131,114,130,148,249,76,135,186,171,103,192,83,45,100,96,36,88,217,197,165,86,194,168,112,149,125,108,133,112,117,199,26,221,35,245,88,233,9,113,47,138,31,61,114,47,51,32,197,55,17,175,164,93,204,223,215,203,221,224,147,103,78,214,230,214,71,214,220,169,117,39,0,147,198,108,242,153,155,144,235,250,162,35,53,61,45,156,227,244,108,123,32,227,129,77,252,146,213,168,197,237,147,123,38,228,75,144,165,144,102,113,198,22,145,14,101,195,177,43,62,151,113,96,81,189,204,180,207,197,24,72,76,135,127,181,246,81,18,167,113,85,184,62,190,140,86,209,148,134,111,32,60,108,33,233,115,99,216,239,112,146,92,217,236,252,213,215,98,122,215,64,175,155,179,121,195,7,207,252,163,51,58,143,187,255,188,122,6,199,73,36,149,218,141,142,43,108,99,2,232,187,65,216,24,169,125,102,148,113,59,233,176,194,207,77,204,245,20,43,145,104,88,88,212,187,237,152,64,18,141,254,53,255,111,53,61,62,49,143,145,197,10,207,36,198,166,88,7,199,42,201,145,219,135,53,239,108,162,82,202,181,4,255,82,23,38,141,213,120,0,218,105,2,141,120,255,138,20,27,255,97,202,151,0,166,227,16,196,48,139,91,164,4,170,177,243,27,154,220,212,167,205,179,84,245,205,50,51,155,45,39,99,124,70,27,48,182,173,3,26,38,214,1,26,23,216,248,214,89,78,142,7,44,2,118,103,73,72,202,187,222,242,74,37,84,166,251,191,67,11,231,116,61,33,17,96,93,116,165,173,88,153,105,123,125,159,243,89,143,66,211,213,23,47,204,192,2,231,229,224,32,30,45,9,31,149,216,137,119,152,34,22,131,206,47,216,201,89,197,58,66,204,67,92,0,150,199,161,213,185,96,252,164,78,46,247,41,134,48,118,14,77,30,250,176,12,138,96,58,51,142,9,249,103,99,29,247,189,31,126,29,86,211,201,108,216,195,90,32,119,124,219,207,128,192,119,91,217,60,215,24,182,244,100,241,153,24,3,99,115,167,33,25,239,186,42,198,202,179,57,117,112,11,208,212,50,26,170,22,148,206,252,232,159,56,64,37,184,40,232,109,62,164,199,64,198,112,56,71,12,215,108,220,20,211,118,70,182,19,212,219,182,104,5,188,255,61,162,241,25,176,78,25,176,239,21,205,246,214,246,86,45,101,158,9,252,149,38,59,72,225,119,121,209,20,85,6,84,253,24,182,126,20,150,105,176,238,54,59,96,46,28,214,21,80,112,19,118,125,115,134,244,30,35,230,238,255,199,220,32,200,9,142,2,182,14,101,191,176,143,96,217,200,124,194,43,105,61,93,143,135,53,12,228,233,30,150,173,228,73,179,184,84,21,117,63,245,231,49,129,29,249,46,23,172,195,94,36,76,227,246,71,159,188,8,88,119,49,177,156,203,88,101,195,170,151,183,106,100,9,246,64,254,1,90,4,9,163,154,231,88,68,182,99,67,75,171,107,142,196,79,237,114,70,178,128,33,83,168,67,129,82,214,135,38,206,41,152,140,168,52,239,28,171,28,29,180,246,185,183,243,85,129,112,168,63,139,133,0,162,86,166,48,132,244,159,151,235,175,64,110,168,85,97,233,11,62,25,177,16,57,124,63,250,59,218,136,209,136,192,23,168,160,206,65,84,30,73,213,235,181,104,66,27,98,126,183,219,93,200,115,84,141,57,55,20,131,91,14,228,85,181,19,4,110,176,90,101,40,91,107,155,7,70,21,114,154,141,146,125,246,64,1,216,213,232,23,143,224,115,244,247,144,186,71,134,69,183,141,25,186,91,29,145,163,250,202,181,57,216,172,131,228,242,181,187,52,94,218,252,4,118,44,52,124,160,37,176,17,218,121,140,191,107,102,91,222,49,91,229,106,179,221,170,200,88,38,138,167,10,48,157,47,99,57,137,88,76,206,141,214,208,48,80,226,18,227,6,175,180,63,107,247,251,197,59,51,247,13,109,209,162,206,192,125,112,94,235,247,26,88,14,126,241,225,249,81,162,7,157,238,150,138,24,69,121,155,219,17,169,180,218,93,230,99,92,139,53,179,145,30,14,205,171,75,247,49,194,3,14,177,24,222,122,30,75,174,121,243,104,233,244,81,4,47,70,43,206,113,229,119,231,49,72,144,78,214,29,193,41,75,14,97,19,84,148,246,3,250,243,7,246,233,153,48,135,226,204,199,93,210,3,97,11,106,117,170,122,92,97,150,179,177,220,46,59,17,151,242,160,233,237,81,78,255,87,243,237,113,135,216,131,97,197,224,41,142,85,234,243,135,58,152,220,191,227,149,78,77,30,82,167,63,217,43,227,106,173,223,128,161,49,70,29,184,169,178,179,124,224,2,243,210,229,112,103,15,29,78,229,91,9,68,198,94,135,241,207,69,183,229,46,78,63,189,93,163,10,91,172,13,205,180,217,216,102,237,239,3,217,247,218,0,147,130,158,175,242,39,94,23,238,221,229,211,72,140,103,207,7,73,10,200,247,155,254,35,165,152,2,137,237,154,128,235,215,210,1,132,104,143,128,91,191,225,241,171,220,16,165,209,59,10,1,128,151,229,116,17,20,188,108,57,196,105,197,5,64,216,75,255,49,10,35,243,39,238,142,201,1,32,8,28,116,21,216,226,89,90,231,210,128,81,149,93,249,111,150,128,11,228,231,236,178,74,34,174,187,230,84,78,197,136,17,197,25,242,154,123,24,78,245,178,254,76,70,182,72,15,115,54,62,10,89,172,129,113,97,148,204,240,100,172,169,122,13,95,182,26,184,25,191,255,250,250,137,18,19,72,145,135,112,125,227,63,65,26,54,228,181,30,158,27,191,9,236,168,115,248,144,187,132,253,45,84,154,196,103,30,149,123,53,42,206,172,146,175,44,203,69,239,45,147,0,121,103,125,132,136,192,38,62,79,29,241,17,151,110,28,38,221,234,230,228,182,64,241,144,165,124,145,120,49,50,129,18,33,242,212,143,68,167,109,134,179,113,176,85,93,87,105,133,15,66,249,8,43,9,147,72,30,6,2,85,185,204,160,20,76,70,119,163,67,200,121,228,185,204,22,48,31,122,177,123,93,159,108,114,65,90,91,67,95,139,6,187,3,78,142,38,96,61,68,23,146,93,32,245,153,131,61,126,1,194,201,158,51,161,172,0,176,76,143,229,81,201,36,157,210,139,109,215,12,9,41,152,243,188,240,144,194,27,114,193,162,39,43,9,203,46,137,76,217,93,125,215,74,43,75,0,153,246,95,88,44,134,248,43,87,166,46,133,1,77,197,205,206,31,50,102,178,248,22,226,192,156,203,195,155,193,32,35,158,173,76,75,79,240,112,7,161,130,162,85,225,67,223,15,127,53,24,49,231,201,248,16,114,146,228,17,178,247,166,162,2,32,180,41,188,9,197,103,77,246,35,30,71,112,6,222,168,64,60,248,242,61,201,130,219,58,182,38,143,103,45,104,219,7,121,119,138,183,148,149,107,216,169,2,89,111,185,120,49,74,173,174,35,38,194,214,86,32,216,229,123,41,64,108,178,152,13,174,71,86,192,147,84,112,246,98,151,238,63,210,134,112,5,28,254,154,125,236,82,78,22,114,230,212,88,97,54,211,70,203,48,159,59,21,36,55,56,141,194,247,133,160,138,224,66,180,74,137,37,94,5,120,135,170,119,209,147,221,28,19,215,139,29,199,87,234,102,225,111,74,180,27,169,131,129,29,44,138,81,235,206,181,229,133,192,201,163,110,48,203,245,95,200,183,29,29,31,255,74,216,148,92,109,191,130,29,236,248,204,126,228,208,76,200,13,128,197,198,255,211,23,197,132,124,133,71,155,21,132,233,191,189,212,255,108,47,94,109,53,232,234,95,174,83,223,18,188,255,239,215,139,141,51,127,243,199,103,111,117,45,101,67,184,104,196,20,34,25,184,251,144,47,226,217,214,217,125,47,52,41,242,113,104,13,56,74,44,166,36,63,154,133,145,18,80,160,124,59,47,48,219,63,43,134,67,115,238,189,252,67,6,164,83,181,123,230,213,252,7,222,130,221,30,79,68,34,162,2,61,134,162,207,49,146,161,216,82,98,181,190,57,57,164,128,97,121,148,131,128,152,66,106,247,15,154,148,82,42,174,142,17,249,123,23,138,78,106,245,159,202,19,26,160,50,138,153,136,182,101,89,247,195,169,69,220,50,155,45,140,251,248,183,139,84,17,44,98,83,13,102,234,106,135,22,255,212,246,163,28,11,251,123,18,5,150,221,6,2,137,17,176,56,215,12,166,187,52,149,11,97,119,140,245,13,201,20,98,80,27,26,125,126,58,232,231,83,52,195,75,116,248,147,230,123,171,77,81,168,163,120,39,158,18,54,60,212,117,67,148,122,151,78,51,30,88,27,152,83,92,191,105,162,106,233,12,27,116,4,53,100,189,242,253,169,182,10,105,196,84,229,122,141,80,15,0,38,26,50,176,229,18,32,169,241,202,190,190,225,100,193,44,196,209,193,83,89,43,228,8,127,48,9,221,186,199,251,97,138,218,190,131,202,206,62,148,128,44,48,107,164,177,57,149,171,214,244,57,198,194,87,179,232,10,17,65,243,255,109,19,208,42,55,68,178,164,84,21,57,206,5,27,252,203,144,108,90,231,137,198,221,204,164,204,56,73,223,129,127,246,244,144,140,13,229,195,199,39,42,93,103,202,8,45,68,203,17,186,154,9,154,228,59,255,134,120,125,170,90,18,141,31,17,116,10,189,48,63,147,112,188,11,184,92,95,253,180,92,80,106,57,112,187,229,228,69,3,1,47,47,72,146,48,135,37,111,82,27,20,77,157,222,115,123,120,119,159,196,99,7,116,57,222,119,79,79,212,213,215,145,225,154,187,25,22,126,89,170,169,123,159,94,29,177,63,137,207,167,192,97,134,193,17,236,199,8,35,214,220,156,72,183,180,8,63,200,171,93,216,103,110,145,159,209,158,236,233,50,228,220,144,113,159,214,222,157,156,27,133,183,240,127,191,28,41,222,148,155,247,32,97,96,128,237,98,236,159,107,157,192,176,19,81,248,145,219,183,179,73,178,81,38,137,81,108,189,148,180,164,63,244,107,140,13,253,2,84,88,16,121,200,120,77,203,104,24,207,202,194,62,253,155,102,96,168,116,28,237,163,138,91,149,34,82,230,211,109,230,176,130,28,82,186,233,159,99,238,249,81,38,106,243,246,4,63,80,43,104,47,1,253,236,84,79,158,5,81,26,18,242,70,42,11,229,216,154,236,16,203,159,227,7,207,120,26,197,81,87,177,4,32,197,147,111,255,229,91,211,194,195,230,35,169,151,31,196,33,181,120,192,254,71,84,152,228,208,209,129,98,55,39,210,144,146,192,231,249,121,170,81,218,202,197,150,149,234,93,90,178,167,209,244,86,25,140,141,156,206,14,247,240,217,14,39,99,82,121,16,119,157,210,169,220,50,58,255,48,130,189,120,154,59,60,85,94,135,23,15,171,6,31,212,224,89,73,100,179,91,61,170,128,28,33,227,9,149,128,12,110,120,44,9,52,192,4,24,65,221,114,24,77,109,0,237,94,4,42,232,84,150,134,32,50,33,84,234,130,136,89,117,253,79,60,135,69,29,50,128,196,38,41,43,37,78,168,73,163,249,45,207,177,76,38,115,76,143,118,145,106,166,6,142,230,193,147,145,87,195,222,73,219,219,89,33,68,237,118,120,146,164,74,130,237,16,47,79,228,9,153,184,5,127,80,182,81,105,196,51,244,192,237,160,118,200,191,94,235,152,191,202,161,231,171,19,116,102,94,206,253,175,4,193,18,70,53,214,98,123,181,137,167,190,84,96,169,2,204,232,54,221,169,175,186,172,137,170,75,32,249,57,119,86,19,52,123,234,142,11,108,19,58,84,98,250,242,114,170,31,205,195,117,12,243,41,93,222,0,101,219,102,129,196,192,91,8,186,233,243,37,194,183,162,121,59,93,71,52,178,114,96,72,252,185,254,109,31,107,112,168,64,226,160,216,43,49,74,50,139,112,148,135,148,88,184,35,26,29,171,245,47,96,61,39,146,159,194,252,57,202,244,245,218,216,18,29,71,237,39,25,197,164,184,67,97,53,45,16,218,207,244,97,249,96,167,93,62,103,162,164,67,186,159,2,26,136,32,184,9,167,169,183,210,72,43,253,167,72,211,171,205,117,92,82,32,5,197,107,8,68,106,237,8,142,148,101,227,90,210,67,13,252,233,3,242,79,95,172,175,195,246,251,254,247,71,7,224,252,37,255,4,158,178,131,23,77,77,22,178,114,155,151,162,207,53,98,63,132,143,232,73,194,185,91,243,57,47,83,36,154,42,31,150,56,15,33,40,14,111,70,137,225,158,138,108,119,114,255,48,176,231,182,51,219,163,86,122,80,104,197,169,107,181,97,55,228,63,47,73,106,27,23,65,207,177,34,218,221,147,192,237,165,74,89,152,255,181,169,250,226,99,10,232,6,181,45,3,222,174,26,248,155,12,199,237,65,205,85,22,125,164,146,124,17,73,140,71,36,57,173,173,157,157,161,35,164,157,190,71,67,29,142,133,206,231,64,185,95,111,65,166,220,233,245,73,242,25,16,29,223,124,142,199,177,13,24,198,245,218,190,115,38,32,45,236,12,96,101,63,17,230,151,217,117,234,153,112,111,91,162,196,247,185,166,60,2,8,145,56,160,48,175,226,250,67,51,132,106,42,213,138,119,167,9,240,25,8,56,22,165,218,9,62,218,121,29,43,177,130,210,166,150,15,220,225,225,152,34,255,104,115,223,108,131,55,250,255,49,92,130,20,179,218,73,38,116,122,102,17,118,237,183,109,65,232,122,235,4,68,3,245,160,150,224,73,183,115,6,100,124,166,210,201,82,249,142,15,23,20,60,118,137,170,181,229,205,108,201,240,169,87,195,99,76,138,15,228,158,47,216,146,8,248,175,110,207,39,94,180,173,250,47,24,2,201,150,241,233,238,16,120,75,140,84,49,212,106,98,213,162,86,181,76,170,35,124,116,48,164,197,74,131,117,229,28,19,139,154,0,123,202,110,178,10,79,113,166,22,172,117,191,54,48,27,183,59,223,105,57,148,54,241,188,72,118,58,255,33,235,238,206,33,254,197,162,45,154,226,221,57,145,225,19,36,11,164,245,79,188,132,50,190,248,255,75,183,214,242,69,109,232,147,130,166,70,86,58,124,161,96,88,92,166,32,184,117,117,232,148,14,163,81,163,242,0,239,41,82,240,105,189,74,68,200,164,195,85,62,74,56,226,196,41,2,105,154,95,205,207,232,106,98,226,99,112,210,188,162,203,188,28,65,78,18,252,134,93,120,74,188,64,154,12,133,146,228,14,25,9,13,157,22,83,145,169,201,189,221,137,49,232,138,179,182,165,146,2,109,172,21,172,40,157,230,199,70,170,17,231,133,250,192,45,75,214,33,111,3,120,209,54,12,206,159,226,150,136,96,94,25,66,56,178,106,7,73,214,104,156,236,28,249,93,15,229,9,0,132,16,69,155,125,179,207,94,14,13,244,207,241,54,32,52,63,98,162,154,191,75,209,229,33,193,255,57,31,229,86,153,43,207,166,165,245,54,40,212,29,222,70,136,130,40,74,185,218,104,130,108,129,245,188,86,215,76,131,33,190,168,234,99,175,11,251,216,73,187,108,44,255,201,238,119,247,44,86,81,235,45,3,57,216,75,34,73,180,36,35,240,164,214,36,117,135,41,119,211,38,76,81,196,8,21,97,136,235,119,71,123,36,176,199,227,228,108,128,149,137,5,164,77,148,159,81,47,176,108,234,54,46,235,56,167,178,84,254,105,129,190,49,65,57,236,213,149,152,10,85,206,195,221,92,221,54,74,114,134,198,83,208,132,62,75,99,76,23,147,221,170,238,47,2,231,238,159,31,157,21,230,120,116,37,205,171,183,193,105,172,143,117,1,93,76,23,54,218,89,41,8,34,70,14,172,247,13,165,93,149,104,106,13,209,88,202,31,127,1,56,213,196,57,128,219,160,128,36,102,11,50,241,144,120,109,249,181,6,101,158,193,159,198,121,72,53,117,201,226,238,36,19,89,190,170,97,242,166,133,255,187,116,117,149,110,240,34,46,115,10,173,23,253,193,26,88,218,204,250,37,212,109,250,201,191,194,118,95,136,247,161,207,241,204,135,2,78,149,74,112,131,147,47,174,61,6,17,165,170,245,205,230,27,4,219,42,253,132,224,5,105,216,149,164,189,139,111,218,70,124,62,36,131,167,58,160,166,166,15,182,6,55,43,51,18,46,56,174,90,10,0,14,29,74,85,33,208,147,69,176,90,198,106,36,37,30,25,35,124,178,130,4,84,25,198,20,229,53,83,27,191,7,155,221,115,87,5,220,83,80,84,102,251,48,221,102,199,149,98,72,199,4,97,43,61,78,97,140,141,115,8,36,76,209,170,73,151,35,27,50,135,70,240,173,0,121,54,23,163,78,109,212,129,93,171,216,134,28,83,113,141,233,192,101,187,144,201,55,84,241,226,162,50,111,152,243,114,9,111,93,4,89,234,55,65,28,241,78,143,188,189,252,70,80,238,69,204,212,181,122,171,109,189,186,144,136,240,116,95,234,155,53,70,170,203,113,36,46,45,134,195,163,140,104,104,25,181,136,167,116,55,237,25,77,120,91,44,239,159,52,190,41,227,220,175,171,101,213,127,105,222,163,58,68,40,210,118,247,1,76,42,20,189,248,76,43,113,25,81,37,26,154,234,25,226,251,39,69,143,3,138,235,220,47,9,31,25,63,195,193,72,173,92,80,43,152,143,80,74,126,49,33,238,113,228,171,168,241,82,49,174,116,73,94,130,72,230,253,161,187,183,237,195,41,153,143,130,252,152,169,147,185,106,2,207,13,134,90,175,141,157,242,255,161,154,42,107,178,145,195,16,211,119,181,175,211,84,142,39,77,187,239,159,12,177,186,243,150,95,140,58,167,52,103,146,158,98,247,173,141,219,214,180,87,55,184,155,216,203,67,81,243,45,171,219,220,110,144,106,5,138,225,212,232,110,202,220,68,84,250,115,120,118,200,167,154,108,73,90,190,72,34,47,249,229,114,4,80,142,144,22,68,254,128,128,196,171,194,100,131,176,168,30,203,107,42,65,59,156,176,21,156,53,86,125,203,58,216,87,127,233,238,153,162,195,175,35,133,212,69,25,61,96,246,99,19,132,120,219,58,140,93,223,248,9,43,246,147,166,10,33,40,237,26,6,87,228,81,182,159,34,234,48,74,27,30,186,36,136,63,92,110,3,131,130,27,239,155,0,156,219,146,232,148,189,133,204,227,35,102,6,13,242,251,69,127,251,171,127,248,242,116,126,174,84,115,6,193,135,29,128,225,230,162,23,222,79,106,4,26,156,61,251,88,57,81,76,237,7,19,107,37,95,147,230,99,193,76,98,87,252,124,217,105,200,201,204,245,189,226,154,95,54,19,34,64,85,66,163,243,6,203,46,201,0,174,183,154,181,226,46,152,199,255,75,54,243,29,83,133,231,240,6,21,38,68,184,253,109,54,23,224,31,102,11,112,103,43,17,38,125,238,71,104,161,159,219,136,215,196,141,170,10,56,156,93,207,152,188,114,22,157,0,165,25,138,205,58,248,67,193,58,28,147,32,38,229,221,175,114,14,42,161,2,223,231,204,164,6,92,49,52,64,37,164,223,252,197,118,55,243,108,10,158,239,219,175,244,102,22,194,134,212,9,249,244,43,86,97,41,53,9,224,110,61,250,140,202,187,95,171,204,21,221,58,141,24,176,120,96,194,232,84,28,125,246,218,142,73,131,254,249,22,179,71,110,208,97,247,139,162,171,64,251,79,190,180,190,186,29,110,165,88,119,225,30,58,64,49,68,45,83,93,122,136,199,146,158,106,5,211,222,64,64,160,74,72,185,138,112,186,135,133,95,31,236,77,86,54,59,235,32,245,245,133,152,27,233,115,154,253,233,222,36,218,216,218,211,137,127,103,199,95,165,151,234,33,228,72,167,103,13,43,119,38,71,23,218,227,177,230,222,214,149,81,102,246,94,251,84,233,90,116,77,26,118,194,122,55,75,208,137,52,159,238,73,8,33,157,218,178,213,108,45,131,207,210,31,144,133,204,239,144,183,230,251,195,57,195,154,39,61,36,39,117,126,121,69,224,198,15,198,98,59,82,181,202,28,149,49,219,53,48,163,19,164,57,251,219,61,159,235,12,121,100,151,160,191,93,194,90,22,119,28,191,219,210,170,234,145,2,111,53,86,140,171,46,232,231,111,18,43,83,2,142,131,38,36,99,174,3,26,169,105,31,214,250,212,191,8,1,141,69,73,158,180,248,93,117,146,242,10,188,63,7,61,149,69,118,161,141,117,25,193,18,187,220,194,82,13,30,5,225,194,158,252,56,159,129,5,240,0,213,85,67,54,209,242,151,41,141,172,187,12,215,255,6,5,126,185,11,225,35,202,5,182,98,154,26,217,237,193,140,136,38,71,118,166,44,17,223,179,101,97,16,153,33,21,204,15,219,189,120,219,24,117,23,4,153,22,143,40,174,238,185,27,159,69,251,1,227,108,218,69,111,198,184,236,14,216,136,208,115,154,211,47,149,116,98,114,40,90,83,116,92,109,38,134,140,104,157,197,116,57,122,111,5,224,4,175,201,244,62,210,203,188,216,230,131,214,184,164,54,48,242,179,251,201,77,16,77,13,77,23,34,66,146,24,12,187,238,151,92,139,64,114,217,125,244,175,10,155,138,118,58,245,52,121,17,241,62,231,105,214,169,120,184,4,155,16,20,12,215,206,40,237,161,186,68,63,141,166,178,6,127,126,151,70,195,245,163,96,91,23,138,173,211,99,103,164,14,51,246,20,75,76,135,150,74,215,220,71,15,76,77,215,250,38,227,176,76,17,15,179,232,18,19,165,54,194,146,187,110,158,216,55,66,145,232,119,152,61,63,121,155,194,202,244,22,81,66,36,140,38,108,209,21,139,25,159,255,185,60,117,9,245,95,46,99,220,27,61,151,235,253,38,161,64,188,88,189,117,249,42,176,56,54,107,62,80,240,135,153,86,180,137,121,111,177,208,196,3,194,236,106,173,82,40,195,1,146,180,204,141,11,192,120,252,52,4,116,199,14,254,104,216,4,219,7,221,233,33,47,34,247,94,0,104,240,54,18,128,85,240,255,179,195,197,161,240,178,242,197,103,68,166,60,95,131,245,148,198,163,124,209,39,120,42,206,15,106,91,118,113,89,19,66,66,241,200,64,65,37,82,169,139,136,203,234,192,172,175,27,160,244,10,91,4,183,109,177,183,93,233,92,26,227,67,87,232,184,97,234,202,240,80,213,42,133,15,68,206,0,206,110,170,227,223,113,90,208,60,11,93,245,151,50,51,86,152,199,229,35,248,13,119,64,238,165,152,108,70,48,149,157,110,249,189,25,187,246,251,124,64,0,176,165,128,174,39,200,94,100,193,34,233,19,192,83,39,177,228,74,234,195,128,251,203,238,192,16,66,200,223,179,30,106,195,189,26,217,157,142,161,132,38,20,179,217,79,34,97,189,231,106,19,144,223,172,39,206,91,192,115,254,111,141,170,103,121,61,72,101,60,110,173,73,193,25,89,206,122,137,151,213,60,169,7,42,226,224,249,190,43,17,190,187,240,163,77,26,192,162,70,170,154,216,20,183,212,229,81,56,157,247,123,219,168,91,21,53,107,174,135,98,32,176,146,78,98,190,30,232,190,171,107,188,254,223,5,25,58,134,150,36,28,218,134,107,40,253,245,199,11,1,191,26,173,238,5,142,204,170,161,157,127,172,254,27,185,235,87,15,3,74,170,36,195,132,163,3,126,33,178,173,141,106,23,111,96,111,124,164,68,230,2,210,18,190,148,45,70,148,194,38,160,67,130,166,172,81,5,91,142,239,190,58,3,102,81,212,68,68,73,134,6,117,116,100,47,57,100,207,232,224,125,32,30,193,162,117,36,57,8,27,203,56,199,110,251,56,35,162,240,157,224,0,42,206,199,201,33,95,5,127,132,29,178,152,101,166,1,242,99,155,248,47,71,180,75,84,99,65,91,32,31,136,206,52,48,74,184,208,83,85,179,51,105,125,87,66,145,207,127,71,239,255,157,126,120,139,232,35,64,70,128,118,191,41,217,7,185,86,117,216,187,163,194,206,174,218,56,214,58,160,248,111,154,70,17,108,212,91,199,245,32,108,125,43,198,192,38,68,101,100,147,129,87,52,240,50,91,92,218,108,127,101,155,228,123,77,147,41,86,207,159,139,140,93,22,169,163,63,89,236,154,98,131,93,39,55,237,122,107,6,174,184,202,126,27,199,141,16,52,167,250,44,52,64,134,244,66,235,39,127,190,88,127,61,105,107,157,35,59,146,10,14,155,241,227,170,104,180,47,95,20,235,236,196,100,29,66,255,252,236,249,128,214,5,234,40,241,34,234,45,47,166,217,121,36,243,35,251,23,126,3,133,136,164,113,22,69,236,180,239,139,48,255,146,161,48,135,129,150,245,193,181,210,85,120,4,249,147,174,66,17,136,154,208,148,214,82,198,29,171,4,223,212,84,104,93,95,153,151,59,52,212,150,113,85,179,189,60,151,118,28,93,220,49,114,124,228,164,99,165,40,1,5,200,121,138,132,77,15,5,21,162,216,252,37,141,224,202,125,209,225,242,62,177,195,93,254,238,77,226,148,168,119,167,195,151,180,25,60,215,48,166,94,44,45,114,159,78,24,155,132,119,38,31,231,227,51,37,35,33,239,40,171,12,250,68,190,248,231,228,59,213,61,15,65,53,179,92,176,23,172,176,32,72,135,37,241,24,107,242,184,186,57,99,239,241,14,0,114,211,202,79,176,88,52,130,56,18,75,55,22,208,79,100,1,57,105,53,174,100,13,234,232,158,118,211,9,144,128,160,76,177,166,10,90,95,110,144,254,243,190,208,135,184,198,226,200,27,9,38,241,0,208,210,237,180,2,22,149,157,19,155,249,21,3,55,195,149,105,206,24,110,148,19,249,58,78,186,176,25,100,216,4,198,194,104,71,150,103,193,54,223,28,146,80,51,157,194,14,178,180,189,161,192,44,225,168,111,47,225,151,43,100,26,191,125,146,222,221,199,216,186,126,173,89,90,229,77,60,34,228,75,219,182,85,232,170,22,24,130,197,101,20,253,116,141,176,241,34,223,208,190,53,49,201,93,144,151,241,108,236,120,86,232,128,234,238,83,111,80,172,96,67,34,128,6,29,10,136,122,7,204,83,50,186,1,23,79,169,21,92,114,15,132,236,51,188,123,139,240,236,199,67,208,132,52,13,194,187,174,29,120,140,151,198,252,88,147,102,219,35,162,73,126,98,77,213,8,169,217,193,210,100,239,19,153,49,43,252,194,75,228,65,143,184,39,77,42,202,171,40,113,137,164,157,33,120,131,63,197,218,5,250,238,192,175,128,92,206,161,173,254,238,133,100,158,136,16,101,127,238,52,208,92,82,3,217,66,93,246,228,193,254,74,72,78,122,33,105,54,8,66,93,246,194,222,27,194,33,125,31,125,186,243,13,92,218,44,36,132,226,180,89,124,205,104,135,159,122,252,15,162,223,62,10,250,171,0,131,127,85,178,231,79,207,40,253,46,196,118,242,128,72,35,191,117,82,21,59,50,253,123,77,220,143,104,20,203,224,176,13,252,32,28,67,43,91,75,244,94,186,135,19,180,199,223,127,142,98,37,239,28,103,87,65,235,18,238,103,120,238,30,86,59,98,172,2,220,161,99,43,3,209,122,161,55,146,255,1,36,249,99,184,3,3,168,72,232,46,73,223,106,79,159,210,38,156,147,51,126,50,165,108,52,49,96,42,238,80,99,70,146,206,224,54,97,97,16,213,14,248,251,126,49,66,87,134,179,227,232,143,91,185,125,0,158,183,5,242,48,7,152,160,171,198,163,34,181,199,170,68,125,93,97,109,136,230,150,33,113,56,104,7,226,175,49,100,51,84,213,22,135,7,237,200,148,72,116,142,163,153,122,86,4,164,15,210,118,24,67,210,223,220,137,144,48,144,180,185,234,2,241,154,213,43,109,156,143,172,26,128,135,231,119,24,217,131,61,148,77,141,150,92,115,120,2,154,217,75,86,241,208,171,108,103,82,89,209,129,238,172,132,255,207,27,146,164,74,184,68,92,141,13,124,214,138,185,244,149,236,189,182,103,67,87,10,32,216,220,143,80,210,206,245,104,149,139,20,55,5,113,172,207,125,29,89,249,19,112,108,14,88,182,201,165,18,10,245,121,6,178,148,34,12,59,196,61,173,239,178,241,33,155,25,242,134,32,227,233,188,135,113,163,52,64,251,178,224,118,246,79,167,5,63,212,177,112,180,80,242,169,49,210,21,134,141,17,157,190,91,64,227,91,38,133,159,225,105,247,226,195,200,172,31,220,215,170,68,107,20,234,183,178,143,56,158,107,86,223,172,215,193,84,10,65,89,99,158,61,203,224,96,108,213,54,164,149,13,125,118,120,95,189,114,57,41,211,241,237,209,190,6,62,79,184,242,245,149,195,91,85,198,131,178,227,71,202,112,154,51,82,29,130,223,121,113,6,199,251,129,30,201,68,187,181,197,35,52,79,104,12,235,40,127,72,62,197,101,25,50,235,135,22,61,18,204,9,17,58,139,193,112,118,161,34,157,65,113,190,135,176,140,117,20,216,176,111,50,116,217,162,214,180,80,45,31,21,53,93,2,228,123,100,207,17,230,207,97,240,183,85,31,41,46,45,3,43,72,155,187,165,203,128,67,28,120,236,54,20,65,238,109,110,179,222,136,198,17,77,149,130,251,103,177,204,150,184,189,37,5,55,241,217,14,130,255,116,126,175,235,144,116,140,66,14,51,205,67,99,220,51,208,79,206,154,127,22,85,71,77,215,145,255,44,243,64,209,227,67,73,110,151,218,87,197,55,237,118,245,39,169,244,170,245,203,108,245,142,50,189,176,80,21,202,93,146,1,53,148,177,158,56,213,31,235,149,163,76,7,160,96,185,175,209,247,27,135,158,217,147,16,10,240,197,137,20,206,239,82,56,27,22,220,198,2,89,79,127,31,142,1,6,55,182,200,142,137,107,201,174,111,181,210,207,62,30,104,243,208,79,121,233,86,23,51,192,246,38,237,63,185,68,166,75,123,229,116,251,234,207,59,122,231,68,113,211,62,70,25,143,151,209,232,208,160,147,131,216,54,242,90,239,63,40,144,174,63,16,36,202,26,114,183,89,217,89,136,230,91,48,252,125,202,164,150,89,145,56,123,247,12,54,155,187,186,61,40,196,208,28,136,119,101,36,210,226,52,175,235,200,109,39,72,109,208,243,138,191,212,112,241,255,140,84,135,41,149,18,74,71,117,169,225,47,36,251,47,104,143,61,234,88,50,148,255,119,218,157,33,205,193,198,233,229,11,62,162,92,119,220,137,255,123,184,226,35,157,8,174,39,63,216,248,137,225,131,8,2,82,204,80,214,39,91,209,189,161,6,81,144,36,198,76,197,109,194,10,4,72,54,53,184,115,91,225,10,11,168,200,46,218,124,246,135,15,89,53,166,8,241,71,83,123,154,209,50,174,37,55,123,83,140,20,54,44,56,182,163,26,6,6,190,38,53,147,232,222,149,68,107,255,157,252,151,137,92,252,145,148,33,103,9,72,231,13,116,195,38,2,23,236,159,143,19,6,218,213,124,179,244,182,30,110,173,19,168,90,131,57,252,205,106,250,34,115,21,156,227,2,178,233,51,164,166,165,72,112,14,41,93,38,111,111,37,191,106,207,33,185,185,90,72,233,134,236,98,171,160,112,169,40,190,94,93,171,234,98,137,93,127,65,248,80,186,131,116,191,197,63,31,50,255,195,58,34,142,54,220,246,198,63,55,183,44,126,0,217,209,232,158,8,7,110,86,107,240,61,28,52,138,97,149,20,247,180,192,143,33,83,155,177,22,187,216,48,139,83,169,139,99,123,154,74,125,236,38,59,46,27,30,157,211,15,232,203,47,94,136,56,194,51,139,205,174,21,161,217,7,160,227,59,236,156,91,143,154,27,42,117,22,168,18,246,201,35,37,107,157,58,5,158,76,100,112,62,84,117,50,22,6,96,111,120,207,116,151,161,13,67,239,116,206,98,64,136,103,8,201,197,9,81,239,18,226,93,190,46,81,229,232,167,200,193,215,90,182,212,93,78,67,26,105,97,197,49,164,150,52,143,248,121,13,95,217,227,206,14,80,200,179,171,10,146,200,142,90,137,125,253,146,71,131,33,45,48,69,241,119,153,254,188,241,25,222,97,30,63,46,136,159,57,134,89,0,129,234,189,184,64,200,208,245,48,167,116,134,99,230,3,164,217,19,159,106,99,97,202,22,164,70,66,13,97,32,58,239,114,37,9,60,59,67,157,37,172,251,50,177,13,116,63,7,119,74,90,248,108,175,187,95,134,112,101,157,132,160,143,70,245,232,144,69,184,106,150,9,184,122,224,32,162,162,167,166,203,10,237,99,78,75,217,159,250,237,184,75,97,163,68,55,215,93,14,236,225,12,141,49,8,40,126,117,77,135,80,77,205,97,75,21,26,145,221,123,172,2,182,77,86,93,204,86,114,144,92,13,141,25,97,222,15,100,182,160,159,142,35,220,49,107,187,208,137,105,153,135,0,174,222,172,239,170,133,207,178,208,164,230,211,2,139,92,32,192,133,89,232,32,239,245,110,166,136,37,21,196,131,79,242,98,209,25,180,252,102,119,100,85,102,115,189,106,122,226,157,178,221,143,154,92,187,57,68,241,18,33,225,250,134,114,116,72,134,250,27,40,97,219,30,86,74,184,102,193,26,66,181,24,165,153,255,190,75,185,18,121,114,85,220,59,224,145,174,176,36,67,144,74,196,161,88,9,48,79,220,4,67,25,232,105,176,32,242,28,201,66,116,178,36,164,218,208,31,240,68,239,166,138,242,198,226,27,136,232,255,174,210,152,60,200,61,15,238,2,218,231,198,130,236,180,235,65,221,66,82,162,92,235,251,20,38,65,92,156,106,85,0,144,25,182,28,226,88,153,34,253,19,27,116,90,101,248,35,202,216,184,19,35,2,94,8,209,254,66,212,135,68,219,185,32,107,225,25,227,136,211,138,181,174,112,128,190,66,165,251,135,185,108,40,159,222,177,26,58,26,148,218,89,13,15,27,236,24,118,78,33,185,174,168,219,230,119,230,179,169,161,57,118,97,227,203,9,125,55,136,197,112,94,138,136,230,112,204,245,136,116,59,13,75,68,121,43,122,9,22,252,149,172,182,118,113,61,53,171,44,42,118,178,166,69,222,44,157,34,128,126,179,24,154,159,106,149,17,227,58,143,176,241,222,56,42,62,181,26,208,33,24,30,33,112,83,127,84,65,41,251,206,115,178,2,222,106,153,209,238,98,208,200,210,177,133,86,65,23,104,110,177,161,96,79,57,142,162,15,207,173,153,56,254,250,73,76,74,43,36,200,57,145,60,95,227,21,147,221,41,171,192,107,234,251,74,126,3,247,128,122,243,153,128,202,238,189,17,198,179,70,97,245,190,200,231,176,186,98,217,254,45,230,228,185,78,204,155,64,247,183,255,152,161,26,12,21,183,209,199,194,177,1,221,95,77,76,253,203,104,7,192,167,209,180,50,138,227,189,182,231,239,238,168,59,221,119,154,107,247,102,200,51,40,120,192,133,47,249,238,189,123,233,117,188,210,82,68,72,178,111,103,77,144,205,181,97,1,172,166,152,242,0,187,181,174,188,39,82,5,75,21,213,113,66,102,62,173,169,132,21,120,138,226,211,39,44,143,160,126,74,108,191,13,117,58,148,234,239,194,161,161,156,231,240,170,77,120,106,63,168,175,231,243,60,192,181,236,20,52,239,78,141,78,130,59,219,80,208,24,37,165,109,209,49,251,9,62,80,50,249,181,232,42,228,47,166,191,144,176,206,148,242,148,153,182,121,24,128,65,137,42,161,119,66,94,240,11,55,102,122,7,205,142,144,144,180,47,60,218,192,149,85,15,213,83,8,79,215,104,8,209,172,222,200,242,28,255,51,185,167,33,226,26,65,147,100,114,222,54,27,170,212,207,83,56,170,37,126,121,14,18,40,231,4,14,164,248,6,110,118,48,51,83,228,76,3,131,87,77,86,163,48,72,194,109,53,105,118,111,198,140,133,34,20,119,56,35,236,7,170,176,164,95,86,183,232,105,108,7,25,169,127,50,26,86,83,94,101,58,219,72,205,46,231,78,158,94,221,190,147,92,96,224,0,30,65,191,21,237,118,106,224,247,161,116,33,41,10,92,81,248,232,191,41,72,116,171,89,110,208,62,230,196,11,67,172,81,188,8,212,62,255,199,22,201,68,20,120,21,90,72,70,211,251,61,232,5,238,147,16,91,225,65,103,178,238,63,246,157,100,192,170,206,249,101,28,25,120,125,225,94,105,146,218,75,10,178,103,244,73,77,174,18,113,205,198,233,5,88,129,66,64,72,137,118,81,217,130,206,156,174,224,223,115,249,164,10,160,47,237,255,135,146,236,13,99,71,63,62,20,134,132,135,155,27,21,239,159,60,195,224,248,123,205,45,147,225,233,72,95,151,236,249,144,43,148,51,197,175,100,140,185,170,200,234,37,87,113,85,41,197,41,164,33,181,64,228,58,125,41,220,43,111,47,37,139,69,75,126,166,210,12,7,175,6,63,122,236,237,156,149,142,254,174,11,37,215,82,200,54,62,74,43,2,249,172,218,115,203,91,14,165,110,103,178,200,5,226,141,45,42,68,130,198,173,253,230,217,122,113,39,163,182,160,231,100,179,40,207,8,27,212,22,174,85,58,27,55,118,83,118,244,201,68,167,205,50,31,36,17,250,228,187,200,203,159,109,44,83,197,240,214,82,128,207,62,237,127,108,238,226,36,190,44,152,27,248,90,79,254,43,191,182,206,138,179,239,133,27,56,192,25,166,40,83,172,241,62,178,172,53,58,205,73,6,139,66,50,24,22,193,232,205,173,161,67,139,236,13,114,239,156,46,253,12,218,238,6,255,169,98,117,8,215,156,102,178,212,208,18,175,147,108,96,73,71,115,87,75,254,77,61,212,49,252,42,72,23,95,49,206,208,189,203,240,139,4,56,101,109,139,204,117,23,213,104,47,1,254,115,179,25,96,58,221,157,53,112,19,110,172,118,168,11,21,171,109,123,100,79,124,202,172,155,236,144,86,224,44,183,119,167,51,180,139,191,76,201,173,212,215,120,148,255,149,110,69,229,152,112,197,133,178,122,15,23,55,103,67,13,152,239,59,168,53,175,130,232,143,236,0,96,95,206,91,141,167,127,199,149,82,51,222,51,43,148,225,183,56,32,68,76,97,35,154,233,207,47,2,29,114,143,36,159,81,168,169,22,163,74,208,233,149,204,129,138,138,13,48,180,42,41,155,141,156,228,19,71,135,137,63,119,146,67,61,236,133,52,209,164,39,67,110,28,5,36,100,159,52,79,220,118,89,126,230,63,180,117,243,165,179,147,209,255,162,97,177,43,45,86,56,48,223,195,122,39,130,118,8,183,36,55,42,221,83,72,74,95,130,91,23,121,226,221,206,241,204,44,105,177,188,105,190,84,106,225,244,183,44,76,188,169,150,98,155,208,244,161,94,75,232,173,64,126,153,184,124,75,229,87,31,209,154,93,125,64,53,167,155,250,167,122,169,184,231,14,34,61,208,47,179,182,194,37,87,240,10,125,2,26,125,232,189,207,199,3,153,204,157,148,33,93,160,134,67,238,203,126,198,203,210,112,25,199,23,136,192,135,207,227,224,213,125,17,93,230,177,178,164,152,162,80,107,50,52,221,42,20,128,143,202,168,22,91,223,159,118,214,249,29,184,124,24,124,1,183,54,43,61,91,155,116,241,94,157,187,60,100,244,97,97,177,9,57,90,72,245,38,31,86,172,41,102,15,35,39,4,233,141,9,165,41,137,229,44,122,16,181,99,178,84,124,207,34,140,41,145,250,172,186,100,100,156,162,5,126,187,160,57,183,240,17,46,181,44,120,144,141,151,142,129,195,192,11,203,241,78,134,142,214,106,198,94,141,84,62,51,127,110,9,65,150,68,221,157,131,236,130,114,10,128,197,13,157,252,8,165,223,138,108,179,156,231,156,82,132,196,202,13,64,69,92,110,180,238,15,125,240,30,231,134,56,66,31,193,191,100,72,106,233,11,113,8,121,238,178,117,107,157,215,58,43,212,236,53,215,214,1,16,192,173,175,231,62,113,26,94,248,47,30,36,232,160,227,75,161,127,33,5,192,210,69,155,249,190,217,224,42,17,77,54,231,20,45,5,116,154,154,80,74,148,126,85,137,13,59,123,226,167,20,148,24,19,123,17,78,46,126,232,255,147,20,83,85,103,16,86,141,246,211,162,58,245,162,77,31,51,40,174,164,117,38,201,18,8,240,124,226,180,213,190,92,223,249,184,227,8,168,86,142,19,66,247,142,54,135,218,13,197,216,225,152,61,155,156,171,88,150,158,129,132,144,138,13,21,166,17,156,62,40,147,131,134,66,228,77,177,184,53,207,92,208,3,16,2,45,215,154,73,196,92,47,104,0,94,23,103,132,206,81,105,63,84,231,7,205,95,148,128,250,142,158,42,49,223,26,22,72,27,211,39,245,201,245,4,127,48,221,21,121,201,223,108,209,6,93,31,85,112,207,74,123,201,78,249,139,38,60,134,47,225,21,74,31,177,146,41,144,16,100,28,219,207,21,104,154,200,135,169,238,147,227,243,217,211,187,109,182,74,223,148,201,132,46,26,159,121,196,145,148,161,153,126,127,103,44,44,215,135,248,8,157,23,184,220,82,173,81,229,136,173,243,230,69,68,158,137,156,73,166,209,116,155,166,231,141,186,187,84,175,227,63,227,13,18,245,222,185,2,9,97,179,58,174,246,67,94,255,153,44,100,138,172,19,5,67,221,82,20,224,61,104,222,44,53,106,82,147,130,225,31,218,140,64,109,45,5,216,165,119,100,159,228,18,213,150,192,59,85,135,249,36,228,230,57,28,67,206,105,230,148,212,28,106,92,97,2,31,152,107,208,11,10,205,238,102,126,66,83,190,233,77,232,77,96,85,249,251,119,192,179,5,0,198,67,127,22,157,78,146,64,204,6,39,200,12,229,227,234,242,193,195,141,125,107,248,143,210,251,18,220,67,240,110,48,114,110,15,160,241,14,133,152,132,225,44,134,92,88,11,167,164,225,12,234,164,92,9,175,74,190,164,193,157,232,4,137,216,80,165,124,20,254,221,2,198,63,217,156,135,119,4,178,58,153,215,139,67,52,172,206,47,40,75,33,86,67,63,41,10,20,37,237,37,156,4,13,25,23,201,228,9,237,67,16,22,116,17,184,162,203,188,227,13,110,65,231,79,200,61,118,207,68,161,90,71,47,113,31,224,165,90,23,21,239,63,80,176,54,103,99,60,125,72,207,90,110,231,121,225,205,35,28,16,137,252,136,94,179,14,97,157,227,66,82,219,137,26,78,157,181,147,28,161,251,43,196,201,53,245,149,152,194,86,91,70,203,91,114,199,241,212,180,125,44,131,135,116,26,132,69,27,84,222,132,88,96,163,119,62,129,249,230,33,147,28,124,23,172,231,132,144,182,235,125,193,70,233,206,77,27,210,203,223,213,95,105,230,117,205,214,164,126,23,240,10,34,237,211,43,162,138,230,118,192,86,247,125,167,215,62,26,113,209,175,19,231,246,167,150,22,44,69,31,236,205,198,210,214,123,93,60,9,175,131,96,145,71,92,190,209,201,225,103,43,204,242,98,253,129,95,56,223,107,29,87,165,180,44,49,28,37,42,83,215,122,91,126,77,38,243,71,213,191,223,14,76,247,97,110,190,120,147,167,234,237,10,98,148,45,218,3,23,117,15,148,142,173,118,236,90,31,27,85,54,188,202,253,43,102,109,130,17,8,239,241,89,212,14,29,172,179,90,8,104,5,203,117,188,43,184,167,54,8,100,136,17,55,201,102,193,221,245,173,86,65,162,176,40,92,214,101,18,82,59,131,63,156,187,219,65,190,115,172,242,52,181,80,109,165,136,98,148,149,152,234,86,143,132,100,239,159,119,163,250,30,130,119,190,45,58,208,104,161,144,10,202,200,31,177,215,242,236,78,3,151,34,8,16,172,231,112,71,159,168,32,208,230,50,84,234,214,40,92,65,60,148,117,76,216,111,91,121,177,66,86,123,55,54,126,46,118,241,103,105,245,89,242,0,0,166,87,7,145,164,227,90,30,10,4,88,64,114,70,127,14,161,218,198,16,35,230,115,54,65,108,190,175,186,252,79,33,24,82,118,130,249,181,253,61,28,154,77,227,209,111,63,61,68,223,162,41,90,176,37,114,169,199,77,160,219,199,22,79,240,212,158,243,217,226,74,158,215,193,166,204,82,135,0,106,12,155,150,113,241,197,33,205,6,16,19,118,164,194,115,243,112,162,251,134,203,122,124,61,242,68,140,200,131,168,172,123,48,70,132,227,199,3,196,130,48,55,231,64,216,195,86,36,160,233,137,145,108,224,93,218,61,107,191,138,171,13,215,212,65,223,117,85,120,109,207,141,12,23,221,175,68,130,129,185,138,67,225,85,127,85,215,75,146,79,69,133,10,129,210,51,71,147,116,11,104,76,194,87,78,137,12,108,185,53,10,210,35,135,33,203,224,96,175,47,98,138,83,60,163,16,100,51,21,186,245,7,153,128,164,73,27,189,195,13,61,255,96,12,174,169,37,39,235,177,224,137,71,128,240,63,137,238,255,68,185,212,135,190,156,240,184,158,113,210,241,119,224,63,177,236,63,172,135,117,74,27,187,227,253,246,222,134,197,251,197,243,107,188,160,85,252,111,4,141,195,243,91,73,226,144,131,109,136,10,172,209,186,95,172,96,107,43,22,44,176,226,122,100,50,28,65,163,62,235,88,16,254,97,48,250,64,155,101,21,83,64,255,189,98,142,60,20,184,3,54,87,20,50,178,254,138,105,53,169,141,5,88,57,244,207,138,191,208,185,54,87,134,70,182,197,77,248,201,118,133,148,231,106,241,215,91,61,184,61,250,9,140,91,66,203,141,93,171,166,65,183,29,234,196,85,230,194,177,148,240,126,71,14,92,212,2,120,179,141,11,42,166,15,45,196,187,30,249,247,104,244,5,25,126,208,252,253,157,224,36,138,145,222,221,213,15,204,112,217,50,193,215,194,2,248,214,48,43,229,7,204,79,218,223,82,137,114,228,41,220,68,157,35,245,242,213,255,141,189,192,243,63,72,119,222,107,252,230,192,211,47,186,209,144,213,221,185,22,152,208,54,130,76,100,242,54,210,211,40,29,189,40,7,183,252,209,130,240,76,107,14,110,35,151,57,0,187,180,78,210,153,198,18,212,33,205,72,211,89,150,175,136,7,138,13,18,93,226,93,52,171,126,188,165,113,29,15,231,234,11,67,54,164,115,158,58,48,20,202,65,198,247,224,202,190,45,10,153,146,148,150,218,67,157,27,190,197,15,182,135,56,130,43,203,209,174,134,100,81,179,58,182,229,1,155,224,135,148,214,99,38,92,212,220,49,17,170,248,161,123,88,92,5,119,19,210,149,12,254,121,21,140,38,10,247,25,4,22,186,68,1,211,221,109,182,103,137,4,242,129,66,67,138,61,50,131,83,208,81,53,132,36,86,63,33,62,142,250,210,195,68,246,210,84,77,150,182,48,140,129,1,24,195,122,107,160,22,129,227,250,27,102,21,127,52,229,47,19,58,21,47,132,85,233,11,183,119,3,54,223,94,30,168,153,3,202,62,170,29,46,235,105,186,122,192,71,128,73,149,47,98,46,122,34,64,101,76,177,160,154,47,174,96,118,108,73,203,121,15,19,101,72,99,177,70,118,219,124,182,128,41,154,76,22,204,166,120,224,174,35,27,29,63,8,248,217,183,247,192,11,141,178,28,4,184,73,111,64,221,65,220,21,145,34,163,79,94,28,225,40,146,182,182,2,244,18,250,136,64,65,3,121,52,149,19,150,105,221,244,244,247,77,249,155,100,216,128,178,170,122,153,140,221,2,88,211,227,255,108,191,91,6,185,100,148,31,75,245,179,229,46,107,30,214,20,93,198,142,86,108,83,131,235,38,107,38,203,229,248,160,22,216,41,215,22,55,59,211,156,38,76,79,202,176,49,88,161,162,206,46,81,83,200,99,138,117,40,110,2,84,142,165,212,63,185,183,35,165,96,218,110,177,40,36,21,19,181,76,171,145,175,144,249,115,42,97,99,152,49,128,122,54,8,136,236,196,46,137,181,211,218,83,112,177,64,193,136,89,220,176,221,204,172,174,154,77,96,166,191,132,59,141,90,169,6,46,45,84,193,160,209,49,6,199,255,3,129,73,146,92,31,226,30,164,12,7,148,241,217,3,113,226,199,81,146,95,141,45,176,205,253,233,128,78,74,123,244,138,154,234,99,11,241,18,251,174,123,196,122,254,82,210,2,90,216,87,97,38,253,160,197,255,134,152,168,162,17,72,133,41,122,235,85,154,133,172,162,240,103,107,149,216,192,182,55,27,163,94,52,129,61,154,61,11,135,223,222,154,217,53,135,124,181,120,2,41,107,239,28,32,232,45,27,51,86,176,14,7,40,249,170,100,67,101,131,23,151,200,74,151,82,184,146,40,7,64,240,146,253,80,218,150,108,16,186,224,225,98,8,166,177,252,0,35,95,107,137,80,130,116,129,161,149,37,52,149,240,167,11,50,129,134,80,126,16,233,201,206,97,186,68,205,245,254,241,139,20,5,89,162,39,98,188,107,186,119,233,101,250,245,150,241,120,191,39,29,12,121,31,198,242,252,230,85,160,112,172,171,128,29,103,65,246,39,126,74,92,140,142,56,181,82,101,195,59,71,4,8,9,42,98,180,136,41,26,56,252,4,230,102,239,251,161,183,106,22,54,238,250,59,61,243,9,189,77,195,254,119,234,124,186,211,5,26,88,176,159,87,101,242,100,179,102,218,39,85,82,118,109,146,144,225,73,28,78,77,189,135,29,192,12,95,153,113,248,50,171,113,241,189,121,194,155,247,109,70,124,72,61,27,79,56,185,218,51,155,130,98,183,1,100,60,85,55,160,158,110,41,58,63,216,176,49,228,195,87,118,254,105,223,41,138,84,41,78,214,111,49,206,175,91,190,57,25,68,120,22,127,85,81,202,226,197,123,156,169,249,12,182,148,31,115,211,146,41,208,248,249,197,188,103,47,138,8,117,43,130,28,28,102,44,149,38,221,176,211,11,76,148,186,176,252,87,62,69,3,88,80,123,168,196,245,128,224,186,224,99,220,46,237,181,88,159,161,175,204,237,160,154,13,131,12,99,88,171,231,111,242,238,194,193,15,3,254,152,148,114,131,215,216,106,245,73,197,176,147,149,25,185,200,252,52,225,236,86,240,34,22,76,102,243,132,148,11,204,125,58,185,37,184,188,4,169,89,249,104,232,254,3,96,102,68,177,242,8,251,188,177,100,48,1,248,177,185,181,108,161,130,117,35,229,28,94,131,105,31,242,158,200,167,63,124,21,55,142,139,10,202,5,82,209,8,37,48,22,47,237,174,182,254,11,32,46,255,142,78,113,207,192,187,172,174,16,156,90,26,138,142,57,129,2,59,148,175,197,194,242,205,81,57,214,199,206,60,204,225,254,113,28,148,222,242,209,101,104,98,108,237,223,49,114,212,129,78,146,78,208,40,162,230,188,127,198,195,47,15,146,82,173,159,186,217,133,148,237,194,5,33,102,245,90,65,8,165,35,12,231,205,62,97,232,36,7,127,30,119,233,149,99,221,178,173,102,226,168,250,196,60,181,5,125,126,243,158,64,110,37,30,195,162,229,136,241,198,229,105,88,85,49,14,96,84,216,55,253,53,92,172,24,38,54,35,37,50,118,149,84,244,199,203,56,87,218,44,100,7,25,135,147,55,101,115,200,99,37,8,239,72,221,30,76,8,86,146,55,44,91,241,31,111,230,90,185,168,144,245,50,43,46,238,33,229,223,34,244,14,118,219,103,141,110,249,21,49,255,202,251,214,126,66,144,34,95,94,195,240,131,109,100,123,73,158,69,82,217,206,59,169,190,31,185,211,83,88,73,74,185,229,228,147,57,21,198,39,234,143,84,167,170,144,247,206,56,43,55,104,193,157,220,89,125,173,151,17,4,10,18,124,244,41,133,194,59,11,202,98,174,212,26,19,95,71,26,82,242,133,85,125,4,131,36,108,37,250,255,99,63,15,53,173,129,255,175,83,105,132,142,35,4,243,133,67,237,220,88,25,169,219,83,229,33,83,46,251,0,111,226,87,41,226,98,245,208,93,251,94,207,210,41,146,56,119,137,32,0,61,212,6,161,219,144,112,202,88,124,132,83,197,240,185,196,152,34,202,136,59,198,165,5,136,11,246,158,60,3,176,105,203,207,70,162,187,45,160,39,60,82,115,113,239,37,166,188,235,215,222,227,65,73,188,70,178,98,215,247,7,12,10,4,216,139,202,178,125,231,103,79,61,127,58,10,202,75,42,107,139,214,172,4,14,3,23,73,247,52,158,78,61,218,235,79,191,182,70,127,157,34,208,242,177,248,153,110,42,50,168,186,212,159,202,174,245,161,60,197,47,221,200,111,195,231,35,136,145,196,62,119,52,247,41,50,41,64,94,231,136,149,213,174,127,157,61,143,47,166,152,59,245,186,16,70,32,201,49,239,157,90,225,122,138,88,158,93,59,121,246,69,151,25,182,189,199,100,74,131,123,99,103,185,138,240,169,255,83,8,240,13,159,156,5,223,181,247,243,244,179,90,207,159,36,69,34,174,29,39,12,198,108,220,130,2,10,203,188,206,67,116,209,27,67,170,198,93,113,250,14,198,254,196,37,146,198,0,245,162,19,196,105,30,136,94,211,48,61,213,53,160,236,102,140,240,236,1,246,124,73,73,184,88,243,157,125,154,77,39,104,111,1,205,78,22,233,44,37,253,92,198,51,8,211,150,43,192,106,122,208,21,123,140,14,148,222,144,217,194,15,242,120,80,45,66,71,74,147,132,37,185,45,165,41,76,166,143,130,134,3,4,15,104,214,102,179,162,238,195,200,235,20,223,172,249,110,37,43,216,136,128,232,235,48,215,2,250,173,82,109,146,30,125,217,231,73,206,65,2,40,45,35,163,248,230,102,19,67,102,0,76,64,7,130,23,167,105,28,152,26,73,234,15,36,35,231,146,205,50,217,164,199,154,192,15,19,80,26,30,181,14,197,12,131,88,61,140,86,85,233,182,210,78,143,77,63,177,30,176,10,224,14,137,130,162,84,191,108,227,75,85,115,237,159,119,222,168,131,18,13,22,92,110,176,134,71,180,31,116,154,111,4,116,74,59,2,191,75,114,181,184,238,106,236,202,251,63,247,48,35,155,172,61,122,174,26,38,3,176,42,15,71,195,153,55,66,191,33,169,177,220,36,95,177,66,86,173,31,180,219,166,178,139,120,139,67,88,25,238,233,169,169,111,163,217,54,29,44,34,138,236,199,35,50,82,214,30,125,91,25,222,65,137,125,96,232,78,167,209,68,71,70,1,22,163,34,202,200,71,113,235,157,41,14,32,110,171,235,197,174,10,51,158,251,44,98,199,201,196,168,50,201,99,205,245,153,75,169,17,143,154,52,222,138,28,173,86,92,134,115,136,220,131,85,171,122,218,117,190,117,143,79,26,121,10,50,45,80,241,33,4,253,140,1,159,201,105,123,35,133,81,59,236,16,238,109,215,10,124,211,64,112,180,147,203,106,142,69,97,205,162,177,217,151,174,189,239,69,50,30,166,238,219,120,79,225,197,121,127,91,215,89,102,17,39,158,213,94,164,254,49,125,216,191,222,90,38,224,214,242,60,2,38,241,139,218,34,185,186,30,206,33,43,38,242,81,191,12,1,200,96,167,125,197,194,127,129,244,184,30,74,74,196,174,229,224,226,124,52,137,122,146,108,187,169,127,72,111,131,243,79,149,236,134,103,137,212,161,44,61,183,188,103,150,96,95,88,187,167,31,213,185,63,128,70,10,58,47,69,155,112,231,242,129,19,78,116,74,152,85,44,128,199,241,148,56,48,27,194,180,191,35,170,227,179,166,110,172,88,208,185,53,153,120,109,155,216,205,172,159,59,191,94,49,209,213,90,125,246,132,153,163,89,50,28,91,141,185,11,4,229,210,18,79,36,117,191,90,231,97,92,89,193,98,201,7,9,252,3,100,157,87,134,164,29,218,54,7,117,232,97,226,74,185,43,135,78,199,151,206,137,157,244,201,49,137,164,23,115,134,121,92,128,224,192,100,154,252,124,146,17,129,44,130,237,65,159,194,35,88,56,132,29,163,200,91,112,118,35,100,76,112,87,180,233,171,69,124,62,161,232,54,66,129,248,193,47,232,197,143,236,112,36,132,61,97,179,231,60,124,4,220,161,114,16,84,196,143,200,58,98,2,255,8,3,222,42,146,204,234,68,199,78,202,173,32,215,30,242,64,32,250,49,111,31,174,191,209,40,51,55,101,12,137,212,116,140,72,132,52,104,204,245,218,122,29,236,175,188,112,137,112,129,225,22,84,118,55,75,104,13,207,51,243,102,148,120,49,86,192,53,173,30,143,161,0,187,160,141,185,32,104,37,221,242,44,29,27,162,135,12,4,205,239,98,8,217,237,81,207,29,240,169,209,6,80,56,120,99,193,90,244,235,14,45,162,130,224,62,152,96,147,9,238,188,49,82,151,207,8,240,126,39,228,192,121,199,227,52,238,238,69,130,134,174,90,34,126,176,133,63,234,79,219,126,186,224,106,183,242,244,90,180,161,17,110,155,66,109,222,205,83,121,103,49,85,234,220,198,98,67,0,50,194,21,182,193,118,19,220,4,173,96,221,203,40,186,232,98,162,37,12,169,225,26,229,12,71,121,194,162,100,159,139,30,0,151,86,14,131,219,129,154,212,170,79,126,26,171,90,92,239,0,106,79,97,213,183,128,12,238,216,30,67,114,73,64,191,22,179,225,12,252,220,234,87,55,51,145,66,34,63,168,252,148,87,47,176,54,228,85,152,226,61,198,41,76,94,182,131,134,142,127,97,14,232,78,147,107,91,23,55,184,220,0,132,128,230,214,41,253,146,45,59,69,244,78,228,127,47,234,235,212,197,152,203,251,16,167,93,153,46,245,207,238,82,246,96,131,4,123,250,67,9,15,63,198,214,205,18,51,223,238,190,104,69,185,188,1,61,168,132,22,21,224,86,237,119,49,15,228,241,216,161,180,19,252,22,109,144,133,49,21,97,145,73,250,32,160,0,103,179,235,69,26,206,44,140,184,97,110,167,21,84,228,112,18,154,24,41,60,232,190,168,43,72,248,82,221,13,138,79,89,140,122,61,117,232,17,75,243,217,88,218,235,50,96,182,174,230,168,249,99,90,3,240,143,171,128,49,247,62,32,242,216,73,239,88,172,30,77,172,78,40,138,46,152,178,103,92,139,57,224,167,208,14,63,245,78,69,235,225,103,133,134,96,22,32,104,77,117,153,192,206,38,183,221,117,253,207,240,211,16,89,105,251,119,74,144,222,156,150,154,58,135,38,58,165,24,125,4,181,205,243,117,226,156,243,80,70,66,176,146,37,197,55,215,99,87,148,92,191,170,198,29,60,48,57,132,232,226,100,191,28,143,184,235,205,69,47,243,18,71,89,96,148,5,68,98,120,4,46,222,166,248,156,123,31,13,147,244,29,153,133,248,130,207,112,2,139,131,49,115,58,120,121,244,170,19,97,201,192,75,161,137,127,83,157,78,253,58,222,224,220,83,182,11,236,101,153,140,34,113,36,254,143,112,151,78,23,46,155,32,170,178,239,64,77,243,128,127,240,27,82,213,68,205,87,27,42,124,75,156,9,234,4,161,210,181,7,140,130,78,31,105,100,208,169,223,62,105,229,132,50,56,128,226,5,184,254,213,116,54,2,93,233,67,132,34,39,179,133,27,209,227,163,127,21,38,10,175,140,28,114,70,190,173,123,166,31,176,23,83,27,2,64,147,250,217,95,1,100,211,238,42,151,65,188,182,234,61,134,64,31,245,14,173,167,214,244,223,242,182,230,208,180,241,228,142,135,251,1,188,189,100,175,18,181,117,35,14,102,136,20,208,168,235,41,228,102,112,204,114,197,137,63,144,1,174,122,8,52,194,119,247,169,229,16,103,124,105,126,128,30,165,102,132,107,24,55,253,220,212,101,202,129,150,144,2,88,195,9,152,160,243,97,168,80,228,18,168,79,186,193,151,206,197,164,32,6,58,126,128,178,154,122,20,188,81,123,96,6,46,214,149,107,24,177,129,255,208,247,29,66,228,212,126,81,168,1,76,131,174,108,141,122,248,24,107,113,170,68,235,117,129,83,56,163,148,130,79,104,185,22,138,198,242,77,180,102,47,117,225,233,90,16,225,8,163,241,112,173,15,227,176,197,136,139,114,202,96,151,63,60,96,154,107,17,147,224,206,248,93,53,106,235,229,60,87,165,173,67,60,192,40,25,38,154,183,128,195,41,187,21,254,166,61,76,158,20,29,63,194,131,191,180,111,32,193,245,193,122,94,224,84,142,94,172,150,192,219,151,49,107,61,164,252,204,72,119,227,21,253,120,84,60,176,113,224,172,24,196,92,64,19,6,114,3,127,121,48,40,3,60,52,74,110,225,56,14,140,23,179,58,129,206,230,166,25,190,123,31,5,201,50,253,204,94,174,116,91,166,97,216,90,145,201,152,88,164,18,19,17,202,204,251,146,159,61,233,43,209,63,240,241,168,94,78,86,211,0,62,97,12,204,199,62,218,65,64,9,170,91,210,0,191,56,249,81,51,140,84,246,229,192,59,27,87,104,195,108,174,216,168,188,98,234,57,57,162,193,13,190,155,45,124,40,58,32,99,14,179,68,39,112,92,159,159,36,201,2,226,129,171,120,102,185,148,114,152,162,196,181,56,69,182,37,197,98,228,38,41,142,10,57,84,197,160,183,210,236,9,42,214,224,63,62,31,118,26,251,177,236,185,210,104,244,19,251,195,113,141,34,50,255,204,42,56,117,66,203,139,249,119,14,28,203,175,32,42,245,180,104,11,154,25,127,248,60,200,28,180,91,39,244,161,108,240,140,189,72,32,119,76,235,30,100,46,74,250,110,234,232,192,243,51,124,39,251,186,123,64,23,149,105,161,56,180,49,163,245,34,42,187,145,64,13,82,135,95,186,146,44,214,135,104,194,94,110,93,178,242,130,21,226,63,156,184,127,204,241,167,193,180,9,237,106,90,105,165,19,198,246,140,189,35,66,77,27,170,145,237,170,99,161,189,234,238,51,219,82,212,214,32,43,128,193,45,163,2,216,44,192,84,104,92,99,93,116,94,163,255,90,174,176,184,147,127,46,68,22,63,23,62,151,173,125,237,52,101,54,144,205,184,145,103,197,86,53,11,127,158,118,175,217,13,86,251,47,11,230,181,185,174,212,134,254,17,229,174,154,246,87,107,230,55,252,104,84,104,251,201,66,110,183,24,71,54,10,178,175,12,182,18,163,73,203,244,85,216,175,129,81,60,17,112,71,155,136,34,122,134,137,245,172,152,64,127,55,97,0,148,116,138,88,45,172,16,250,169,10,55,168,155,249,246,117,74,112,183,220,144,84,127,245,255,79,75,162,219,9,150,235,53,199,122,194,58,198,192,83,66,183,114,7,36,198,143,179,218,40,178,248,218,185,108,140,103,50,91,31,235,191,230,109,62,140,189,224,31,241,31,255,48,167,106,18,242,164,95,24,208,232,159,107,188,95,66,187,61,92,245,43,201,191,135,1,41,19,255,103,156,115,9,219,112,48,74,62,113,152,120,196,200,133,105,206,67,75,26,102,159,159,237,244,74,119,46,70,217,24,102,5,82,212,11,224,67,44,241,148,125,122,140,30,141,56,185,122,202,228,228,152,203,143,221,92,116,168,69,113,89,106,187,215,201,255,151,132,143,105,97,52,138,102,179,146,194,72,5,11,142,16,31,119,218,54,11,45,117,143,78,191,169,116,115,101,231,67,196,81,203,175,126,36,74,3,153,52,15,176,118,87,2,10,235,166,166,25,217,24,97,56,174,121,208,62,83,81,159,25,1,81,67,213,89,71,34,140,83,221,7,159,118,96,172,176,235,249,185,28,97,166,17,64,245,165,23,63,251,128,105,12,76,148,92,91,188,236,238,25,184,58,203,60,22,171,192,183,224,144,158,173,39,61,188,92,76,155,181,102,5,187,207,150,94,58,3,250,36,236,210,151,254,24,164,165,111,28,108,229,47,22,146,124,12,137,148,24,184,174,127,13,247,114,83,177,100,178,209,116,247,77,184,99,249,116,52,90,208,48,242,239,23,251,172,248,54,133,62,24,240,90,110,209,64,19,65,231,127,36,40,74,61,89,232,108,40,133,183,241,255,164,20,180,249,37,233,11,144,123,198,10,134,56,30,115,232,181,188,113,167,11,26,133,132,207,13,144,114,236,85,141,70,151,42,10,176,211,160,243,33,210,57,247,197,33,32,215,207,152,153,82,222,95,87,217,232,251,9,157,52,92,92,186,221,244,36,132,244,171,126,222,212,178,213,118,239,52,68,215,228,157,37,229,77,151,40,95,205,177,209,250,59,223,193,65,135,147,161,220,60,30,20,221,12,251,251,237,115,218,76,211,222,227,113,244,133,150,144,25,141,230,202,17,219,118,142,8,254,249,111,8,74,66,92,214,206,5,252,176,47,65,208,174,127,25,182,208,254,125,215,136,104,95,122,148,47,160,24,171,217,115,108,36,46,111,121,54,209,200,78,201,242,47,82,146,153,116,84,30,151,175,199,2,189,89,106,30,113,219,11,101,233,191,165,1,168,238,15,156,187,76,114,205,125,10,232,251,59,152,234,16,241,125,111,195,40,170,83,198,62,219,137,128,20,195,25,33,235,77,95,39,151,116,175,239,44,250,171,84,173,154,211,23,212,157,160,162,208,164,16,244,147,14,14,17,6,104,150,53,108,250,78,227,27,137,22,252,98,238,175,243,37,70,13,183,79,164,152,113,101,78,244,30,197,103,210,103,214,38,156,171,0,17,21,28,178,30,168,20,31,200,208,51,52,113,15,151,103,235,237,40,10,81,34,216,193,173,182,231,138,223,70,74,110,140,135,128,67,193,157,182,109,142,223,157,163,206,148,192,228,100,183,148,130,219,246,217,18,184,83,27,227,178,40,188,85,136,45,33,244,69,87,159,128,40,97,108,157,0,46,148,60,23,222,235,38,205,188,53,18,244,187,182,168,183,237,144,27,24,195,130,65,220,216,15,20,137,249,27,41,218,232,246,197,92,106,119,80,113,188,192,30,233,34,219,39,146,187,114,27,18,165,104,236,249,38,44,105,166,205,230,49,128,243,36,251,113,40,38,25,215,224,120,27,235,159,12,92,34,87,109,158,74,60,6,136,178,187,38,91,137,86,88,121,201,214,195,151,83,64,228,135,143,158,147,97,176,188,111,251,247,113,197,192,23,113,9,177,188,15,65,193,111,153,189,107,45,251,63,75,15,75,144,12,21,147,41,0,174,131,76,50,32,230,156,172,12,21,217,99,174,122,176,90,142,255,218,205,218,102,252,254,211,225,2,68,190,66,50,226,64,173,14,103,174,112,42,47,226,144,59,125,110,69,123,255,9,156,24,136,238,168,115,76,198,25,170,142,181,178,27,82,125,25,38,98,50,248,232,139,82,51,79,162,74,26,73,204,26,40,13,40,2,73,96,105,177,92,99,35,99,110,56,185,105,177,205,31,100,153,114,150,60,150,252,43,129,210,116,71,159,252,129,54,152,242,65,180,226,15,50,224,127,124,175,143,91,38,46,62,8,22,59,186,178,38,77,246,103,48,216,212,109,56,156,174,127,24,51,123,161,249,178,142,219,27,68,158,78,254,94,242,73,34,240,204,200,93,216,7,25,228,165,205,3,19,2,181,77,104,175,11,217,230,194,135,111,69,253,161,56,50,214,192,155,137,146,17,189,167,202,57,121,74,241,142,45,201,161,154,57,125,92,44,130,241,88,74,115,124,14,144,36,13,187,40,11,139,4,59,158,157,206,13,92,151,135,1,219,94,61,152,173,99,202,240,172,225,103,253,248,69,184,171,34,33,169,218,245,125,15,58,199,178,40,202,80,134,75,170,110,92,65,6,58,200,15,51,116,102,229,188,24,164,185,80,221,62,235,227,1,238,159,158,44,47,211,248,136,211,153,57,241,104,231,90,19,39,187,253,118,187,69,91,208,213,90,157,249,110,157,246,186,4,46,212,11,235,27,55,22,236,16,139,224,123,76,76,174,18,156,21,2,25,59,83,147,157,186,202,18,243,139,77,192,205,43,11,67,231,130,169,53,171,6,241,244,138,2,96,125,93,209,194,120,187,162,104,129,237,118,242,149,94,212,207,222,141,202,202,204,103,231,34,132,92,157,95,239,176,202,195,185,87,154,63,219,10,215,8,146,73,190,222,17,110,27,90,35,66,27,93,191,17,12,120,158,138,224,58,68,152,169,243,48,157,252,163,132,148,157,222,184,145,161,202,141,123,93,61,82,14,213,82,53,66,165,100,215,10,77,207,216,139,35,208,176,63,63,80,219,7,147,222,36,12,252,16,92,225,56,96,70,218,129,99,205,25,99,208,253,109,43,104,153,0,224,39,192,163,67,138,85,157,8,128,148,197,89,194,87,99,206,81,141,47,214,217,156,211,187,184,220,33,32,20,31,143,48,136,147,54,141,147,129,53,91,215,115,208,74,187,36,225,92,30,238,23,79,195,80,124,161,28,40,129,212,156,128,13,94,16,64,122,47,166,181,116,236,218,16,106,162,20,12,250,106,59,75,168,173,41,229,75,239,230,135,79,240,61,106,144,243,222,80,207,8,155,238,226,204,246,25,2,83,116,227,42,121,189,61,88,237,200,221,66,111,84,209,44,204,5,74,21,249,236,194,187,52,103,164,109,114,191,27,0,240,99,60,253,103,92,69,90,87,109,109,138,61,171,55,129,98,152,62,65,82,93,47,130,95,171,12,145,48,243,4,220,47,118,144,188,144,153,224,242,141,144,94,218,128,144,77,106,98,182,215,118,91,73,238,22,122,110,3,109,89,91,34,0,57,72,86,228,158,153,209,235,58,200,213,223,68,254,49,210,128,11,87,0,207,25,93,183,141,193,9,142,11,15,213,209,90,220,249,117,222,163,188,42,116,162,111,235,175,70,29,243,205,184,46,214,112,219,68,27,190,37,228,13,196,98,127,58,220,90,248,241,41,128,82,170,102,78,72,99,103,47,49,238,210,203,217,40,130,83,98,143,81,119,52,173,166,24,234,61,253,11,147,118,189,128,69,161,207,122,161,251,67,139,246,0,44,109,95,241,166,224,177,225,201,10,38,201,24,44,192,55,22,191,109,159,167,39,67,213,33,100,6,197,183,223,105,223,51,37,21,232,53,7,12,64,243,13,77,22,76,175,156,127,201,50,147,144,135,179,71,59,88,161,195,29,23,213,184,66,77,202,54,134,198,21,205,74,59,68,197,2,150,28,192,219,164,192,158,231,193,240,26,176,33,136,97,129,95,91,76,114,79,86,97,220,135,80,233,39,150,150,27,223,206,160,84,151,120,226,45,231,200,167,121,200,46,1,132,39,112,88,96,85,173,249,29,67,46,208,224,131,84,81,64,218,16,15,12,243,215,86,157,212,204,147,221,26,11,10,114,75,9,240,8,16,58,152,196,219,149,51,8,94,225,203,7,157,156,249,220,220,207,80,128,47,103,189,58,38,83,183,122,51,230,254,146,160,37,235,226,233,55,164,177,33,246,224,67,54,25,126,27,216,100,83,102,46,231,99,215,206,57,243,30,174,54,153,209,116,17,156,121,215,104,69,33,59,37,187,95,75,158,233,68,148,64,236,174,32,201,143,189,99,126,50,216,65,155,184,98,84,102,243,47,178,99,59,227,198,213,53,206,39,35,180,9,162,212,58,190,48,80,234,176,124,165,130,234,100,117,5,245,122,210,159,134,31,165,144,196,154,81,131,130,236,180,4,23,225,45,144,92,99,117,71,130,142,141,103,81,168,211,2,123,203,171,59,133,24,46,169,116,160,216,233,44,215,66,201,119,51,58,75,50,68,116,127,170,113,129,55,193,109,155,237,246,191,189,150,135,24,5,204,65,201,86,15,202,87,40,122,227,52,245,82,182,54,65,104,165,101,190,208,117,246,203,163,168,171,35,67,186,170,221,100,63,0,206,157,229,28,237,147,132,88,91,215,64,64,22,48,88,246,232,140,146,211,199,110,230,207,238,78,66,78,104,253,244,227,114,94,210,30,6,33,43,1,110,176,2,156,178,126,202,213,183,124,213,218,56,96,100,54,192,53,69,60,180,73,48,142,15,85,251,191,216,147,246,47,251,203,203,138,14,174,9,73,186,102,220,0,200,22,56,137,234,117,155,105,229,151,192,129,193,93,234,222,103,57,195,107,240,92,18,180,41,23,23,255,255,135,26,222,109,47,129,205,129,52,192,82,153,195,24,72,58,156,127,159,210,114,67,196,173,239,17,84,216,115,57,151,70,218,133,179,61,149,175,160,128,222,103,91,202,239,92,198,173,251,58,186,236,105,215,23,167,254,58,4,21,22,17,213,211,230,47,195,183,154,245,187,224,165,236,107,184,195,149,49,79,138,158,97,201,64,138,145,249,37,253,56,175,148,83,197,74,69,186,47,38,63,14,241,224,30,52,152,74,163,144,190,253,92,176,164,109,217,165,118,19,56,214,162,10,193,213,18,95,72,55,150,22,199,50,196,111,155,204,32,122,25,68,234,156,43,178,92,160,204,83,138,2,184,248,7,132,201,144,69,176,216,12,49,175,55,89,163,91,23,159,27,226,183,111,153,13,35,140,237,237,170,126,119,171,55,105,81,53,55,142,131,46,39,136,83,145,158,216,192,73,71,22,117,124,243,85,81,130,52,28,216,143,226,153,141,3,162,141,249,125,8,119,27,65,133,135,123,117,71,161,45,130,255,194,160,178,21,123,106,105,199,3,146,205,115,157,18,61,181,226,101,151,234,244,10,17,216,104,186,3,215,32,157,200,151,190,41,62,181,74,5,160,213,185,70,97,253,164,115,81,108,228,207,4,144,210,54,224,36,93,21,210,109,58,54,121,127,235,182,110,122,161,24,48,114,193,83,31,221,109,136,70,83,212,203,195,232,231,69,5,55,157,106,77,101,19,58,55,127,91,240,85,64,11,229,155,10,93,177,2,144,20,75,121,186,81,171,50,1,196,62,217,231,16,206,250,186,173,24,60,218,230,99,216,36,3,103,61,237,73,61,170,38,35,224,158,166,103,119,128,4,5,152,194,141,234,113,149,54,196,25,235,18,81,227,137,137,138,115,20,204,38,189,115,69,224,31,135,6,32,171,72,87,42,144,71,72,255,171,79,132,159,83,151,209,62,152,25,79,133,19,172,154,90,84,80,101,131,150,37,245,195,199,210,235,98,122,229,215,7,164,79,63,62,80,142,144,161,189,235,24,212,200,109,145,185,104,122,29,112,81,147,15,4,108,147,244,184,155,249,18,80,201,174,227,93,226,109,63,7,17,14,209,141,194,160,30,170,18,60,144,32,224,177,0,106,248,126,107,84,185,179,106,146,13,238,80,251,18,50,96,122,216,217,112,187,148,102,111,47,244,158,22,39,76,59,150,43,22,117,202,253,88,26,166,126,243,142,239,81,69,185,255,93,56,20,32,232,185,22,217,19,198,221,159,42,176,105,127,180,90,189,136,213,241,120,92,0,77,136,165,142,142,126,142,164,219,231,41,237,134,253,191,235,254,252,57,52,25,89,120,215,145,142,87,152,149,107,177,79,86,176,4,105,59,150,254,14,74,110,116,206,16,0,218,98,156,66,18,10,16,202,136,15,80,236,236,233,75,132,186,168,174,233,16,240,124,0,189,243,98,252,33,121,215,44,173,199,127,71,233,97,165,227,102,12,62,59,225,180,119,55,117,95,159,229,177,99,143,111,247,182,37,180,23,219,51,67,250,113,124,122,213,160,93,82,156,170,252,0,1,76,22,11,250,91,147,112,1,233,251,21,112,60,137,25,215,114,231,83,28,55,129,94,198,200,247,80,156,163,198,211,214,235,239,111,210,160,137,128,181,114,163,61,8,94,83,46,49,30,181,239,140,222,109,66,167,226,89,159,32,73,145,21,222,213,65,62,66,94,137,206,128,169,236,73,167,141,150,232,238,36,44,136,68,28,4,21,153,225,253,254,31,210,190,138,17,5,228,142,90,163,91,64,60,208,230,70,88,201,198,140,171,37,112,143,83,251,39,36,63,189,48,135,196,100,189,76,124,37,117,179,153,183,236,97,94,72,5,144,76,23,71,22,137,91,101,17,51,31,37,37,248,167,248,202,225,125,28,24,192,51,67,242,20,243,183,110,138,211,210,110,39,221,189,226,241,100,225,217,111,128,6,152,234,156,179,79,2,139,150,103,51,47,252,21,104,71,84,83,243,17,144,151,52,96,128,26,163,179,77,162,97,109,136,128,106,219,50,111,229,203,148,252,102,19,181,220,239,169,7,60,6,173,111,160,55,24,162,69,223,39,186,222,104,184,206,203,0,68,178,244,108,51,107,230,205,176,248,207,12,225,122,184,184,1,99,226,173,135,71,136,45,243,127,168,160,134,31,180,45,53,1,213,36,43,83,51,59,61,115,223,67,123,54,86,38,128,71,198,210,179,241,150,253,253,1,26,104,127,234,182,86,121,188,19,134,211,19,249,75,96,210,137,255,175,48,38,23,82,107,180,73,87,97,17,31,217,160,77,243,143,164,224,77,154,152,148,205,66,240,48,168,156,21,103,19,214,154,17,173,156,16,31,18,63,134,224,211,145,46,114,33,113,105,125,72,78,202,25,183,28,255,45,63,169,16,225,2,237,156,45,254,223,125,195,250,99,49,156,250,188,216,169,104,171,157,188,114,72,110,29,153,187,99,254,51,237,255,23,98,131,248,193,121,59,142,7,176,78,52,182,134,170,136,125,40,234,245,225,74,212,208,176,105,253,8,32,143,69,180,249,246,10,31,176,129,144,255,199,193,59,12,181,231,207,169,241,243,19,253,220,49,45,195,42,147,102,239,117,186,240,63,156,184,43,225,119,87,44,38,11,106,231,241,208,145,167,222,147,22,240,37,62,139,30,249,0,209,78,164,84,131,254,178,126,91,170,226,29,73,170,154,101,221,202,18,92,146,134,178,38,195,106,88,228,86,86,172,34,113,89,4,85,139,78,39,3,161,49,94,245,107,21,206,162,64,240,35,201,126,89,226,156,229,141,165,29,4,22,197,202,125,44,200,64,176,137,55,95,167,234,104,86,244,217,45,234,206,4,6,171,85,146,235,237,168,81,103,77,204,104,16,110,90,132,100,240,72,96,188,201,254,56,43,229,76,8,144,250,190,182,102,89,64,104,238,222,184,173,138,130,235,233,91,226,30,237,38,236,194,116,180,36,198,97,37,242,32,60,224,15,13,203,190,121,127,41,1,108,205,117,79,104,173,232,164,128,0,31,193,82,164,115,1,175,199,50,22,0,215,136,87,212,105,174,240,47,27,51,93,165,183,61,96,31,150,125,70,38,192,85,215,191,65,159,42,123,59,211,210,39,96,64,53,80,103,134,214,75,89,23,40,114,4,148,61,56,175,176,119,180,61,162,119,184,21,110,204,103,52,202,109,151,202,204,240,215,165,116,96,52,113,64,112,42,171,54,172,169,69,253,44,153,24,232,19,141,73,3,80,141,143,57,23,209,218,79,5,176,20,117,197,223,97,0,0,216,103,205,251,42,189,173,104,182,224,240,187,184,90,150,165,151,54,237,248,21,195,252,26,86,186,43,130,85,173,165,88,77,47,61,60,251,197,177,40,114,201,153,72,161,39,61,136,217,22,39,227,180,112,20,184,0,22,255,248,87,132,120,113,8,6,226,212,166,57,112,185,75,15,83,79,196,106,136,205,5,59,250,63,35,80,140,176,236,196,248,3,221,98,250,104,32,99,152,165,109,139,192,40,49,68,14,50,89,102,202,12,64,120,114,49,227,205,144,18,43,180,65,47,167,89,67,145,180,44,241,173,23,232,86,141,103,210,72,240,225,180,133,221,238,4,125,161,121,44,204,5,162,64,34,84,167,152,247,154,190,162,116,71,83,180,181,174,3,151,227,180,162,28,198,133,1,195,199,54,251,220,4,182,126,209,15,24,207,187,240,50,11,120,250,158,87,125,246,74,64,175,190,21,150,255,202,170,125,38,228,16,24,166,186,7,113,0,133,182,112,138,188,2,24,120,236,10,76,154,89,48,23,228,159,219,144,219,209,76,59,25,100,202,46,203,178,117,252,97,240,97,42,143,205,52,199,220,7,0,109,217,139,126,170,178,227,213,192,16,171,133,173,237,240,186,6,14,155,94,157,194,99,123,174,181,74,164,126,56,178,0,172,77,163,74,172,53,5,161,130,161,162,149,232,150,69,170,172,59,70,142,112,87,58,16,192,67,8,250,29,140,221,17,117,167,133,43,180,141,157,214,18,131,114,105,147,206,25,138,207,188,30,41,9,97,113,247,123,251,56,165,182,239,95,79,152,45,113,160,213,230,249,227,167,149,52,172,156,182,242,134,61,19,90,144,248,100,252,168,76,213,246,126,123,175,8,114,218,41,247,90,229,94,238,86,73,43,35,42,116,168,217,75,167,166,122,230,82,130,255,164,51,9,86,79,111,49,152,198,132,96,62,12,131,23,66,96,51,213,29,13,144,20,26,228,66,41,228,68,254,126,173,192,51,62,41,184,136,182,93,102,144,250,65,236,200,19,121,182,87,125,72,97,132,164,29,130,211,26,115,217,177,199,35,54,132,98,87,138,188,229,34,130,240,81,186,231,130,41,17,74,64,27,41,169,251,229,192,38,247,81,85,224,10,181,80,164,164,112,73,150,53,119,166,144,157,52,98,187,48,28,64,77,33,237,100,1,46,123,40,27,232,128,105,190,126,27,132,205,16,107,184,30,187,240,29,128,81,177,9,175,37,159,188,53,109,59,15,33,102,39,182,31,73,163,176,14,150,178,216,231,41,152,253,100,240,46,106,181,137,111,240,101,204,74,57,134,179,49,230,134,124,152,70,64,166,43,65,203,80,53,157,166,39,138,142,243,74,145,217,9,194,93,128,67,93,129,161,161,254,211,189,239,205,32,171,253,118,141,204,240,183,222,146,198,220,187,58,201,238,218,179,206,89,183,40,198,33,53,38,40,144,216,247,161,189,216,173,9,22,72,148,174,45,3,127,35,125,111,140,15,207,119,246,38,244,195,69,85,106,121,28,241,125,124,103,116,108,152,84,133,165,68,92,5,189,160,223,125,159,69,84,91,214,24,52,36,207,180,152,8,156,70,209,194,220,165,138,212,192,246,132,124,186,64,218,179,23,131,210,117,7,15,197,250,249,187,104,74,19,195,232,168,66,171,125,133,252,89,123,236,67,152,150,187,82,161,241,29,160,206,15,254,101,201,34,79,182,6,88,237,204,67,3,24,199,64,58,22,71,118,31,80,235,148,111,111,74,248,229,15,0,160,215,0,121,227,15,243,58,122,251,203,236,223,102,217,235,105,113,239,209,206,227,198,166,116,250,85,48,71,14,78,216,2,167,129,129,240,167,56,89,118,161,125,49,228,56,221,13,219,207,36,68,253,27,45,219,117,151,229,111,247,206,97,173,132,8,74,182,16,125,54,238,31,46,244,50,250,3,216,182,42,120,67,61,39,106,101,23,248,21,80,151,115,41,105,95,47,32,90,53,3,164,31,12,113,105,26,135,101,186,43,191,173,143,177,4,75,109,96,7,121,5,231,218,250,45,96,254,193,146,225,251,238,21,240,27,207,43,187,7,61,254,195,234,210,152,46,241,186,188,216,234,82,179,109,61,190,139,211,58,36,74,149,107,249,150,196,71,226,167,232,40,42,19,152,17,194,16,94,5,11,57,37,43,99,98,248,81,211,60,69,192,80,94,225,241,197,53,76,100,1,166,253,132,17,3,72,232,72,214,60,18,151,159,15,167,78,27,76,142,22,21,129,121,10,185,35,246,49,165,218,73,182,236,65,1,175,236,230,71,209,189,163,164,179,194,209,86,6,180,219,147,94,15,212,246,83,21,183,250,40,230,78,222,159,74,94,13,20,247,51,90,218,253,125,50,81,72,93,1,200,50,199,223,192,197,223,38,208,98,122,118,7,82,178,154,193,50,199,199,7,184,231,120,39,2,232,41,182,32,75,56,236,176,5,0,113,190,13,109,1,175,212,249,89,21,130,204,162,228,119,244,190,87,252,151,13,40,209,103,93,95,199,103,141,133,122,94,189,161,222,26,229,214,114,137,110,97,84,81,251,213,80,122,215,144,113,154,105,12,130,191,24,0,226,159,46,86,119,142,104,231,72,118,224,91,195,94,179,212,168,32,243,2,25,219,4,197,34,167,252,198,18,155,87,88,62,165,118,253,176,96,152,186,128,214,140,226,59,11,113,104,102,96,136,126,9,13,140,165,46,116,134,52,249,105,131,168,226,83,93,216,194,247,236,251,159,42,118,243,93,85,175,120,106,134,75,146,217,187,183,49,138,190,5,189,3,203,106,166,110,104,108,70,111,165,41,203,34,212,254,32,10,2,238,30,243,126,47,119,175,63,107,73,75,131,105,17,54,253,158,128,179,196,198,64,151,178,55,47,159,191,106,78,234,208,198,108,42,131,2,33,44,121,43,48,137,107,252,205,15,84,242,200,169,148,239,199,117,248,6,151,51,83,45,149,57,75,160,202,27,122,235,14,50,90,135,90,94,140,171,241,123,236,90,200,243,190,6,111,165,246,139,34,141,151,172,38,34,66,201,218,83,110,52,12,146,6,26,248,102,120,174,193,25,147,171,152,87,174,79,55,208,166,73,111,90,214,25,117,239,102,226,213,182,128,93,49,129,174,3,2,180,9,250,166,8,32,141,187,26,55,157,229,144,64,195,91,154,133,56,176,6,198,60,119,115,232,70,213,143,59,250,97,136,50,75,125,198,19,151,141,168,48,163,47,67,211,114,119,103,69,9,119,244,236,196,164,248,228,69,215,205,245,16,57,177,244,43,224,109,172,45,14,5,161,195,63,81,38,117,19,125,248,179,103,199,168,84,151,192,55,216,72,96,43,117,199,103,51,202,42,177,40,169,84,157,153,173,244,141,108,142,38,188,53,35,151,221,147,12,148,111,151,129,212,37,253,142,191,152,21,241,153,150,30,71,95,49,124,83,150,47,109,169,199,96,70,141,167,74,79,11,152,159,93,215,159,185,141,249,140,114,217,75,87,133,177,114,114,27,32,86,10,246,20,157,127,160,164,227,79,194,177,107,49,142,179,84,144,135,178,81,30,7,228,120,116,11,103,210,83,15,94,77,40,116,144,27,125,81,192,231,217,112,4,184,78,6,144,65,184,221,84,114,52,150,241,217,130,114,219,252,15,34,244,209,76,178,193,231,229,38,137,147,0,147,242,150,26,33,32,28,132,60,63,134,221,9,214,135,97,120,217,109,78,130,199,253,153,215,234,19,186,201,199,169,20,132,151,74,179,54,65,25,171,126,126,88,23,247,222,39,52,65,85,45,245,229,214,38,98,14,0,10,216,42,17,230,34,91,84,144,209,31,186,211,140,175,188,80,202,99,174,124,88,40,32,214,235,133,253,145,179,186,102,42,135,61,67,235,163,133,41,35,25,168,87,141,24,186,210,233,150,19,220,120,81,123,169,245,18,197,27,207,176,15,197,115,139,69,152,82,211,148,77,184,232,173,29,253,46,123,173,245,217,54,231,135,218,236,101,196,45,109,136,189,206,68,215,214,77,251,43,39,224,144,62,135,50,114,247,67,110,247,38,143,220,5,1,173,142,88,7,149,152,225,194,10,114,152,121,105,239,242,249,117,29,172,2,39,98,218,33,31,69,93,11,210,222,132,40,251,162,173,144,13,165,165,242,181,202,215,89,196,228,253,39,70,73,153,144,63,184,211,2,204,107,51,166,197,173,14,15,96,66,141,11,12,244,148,50,16,214,9,8,52,6,165,105,91,184,10,10,62,135,250,200,159,69,227,229,86,98,229,73,27,200,217,108,233,211,81,90,93,45,50,50,149,19,35,23,116,202,113,21,211,33,217,140,128,86,228,185,130,140,104,87,180,174,131,213,254,48,90,67,239,159,204,139,229,42,236,142,82,151,187,165,11,12,150,53,56,10,76,97,213,117,217,51,242,133,135,229,78,117,95,26,31,69,32,138,147,70,226,136,42,0,8,199,224,233,35,206,48,207,61,99,52,101,204,118,143,245,236,120,33,226,57,223,53,32,255,6,236,127,223,89,137,99,84,204,80,106,20,237,64,149,193,65,7,41,202,120,56,115,112,137,35,254,243,28,47,4,229,33,115,177,48,219,231,48,63,139,95,214,209,6,170,197,116,222,104,88,254,141,16,48,222,226,9,47,121,65,188,142,38,129,229,60,122,25,131,229,78,249,211,139,93,199,181,248,231,247,38,161,131,223,146,216,88,123,189,77,186,220,2,185,53,173,226,101,153,213,103,171,140,207,44,51,120,168,36,182,213,176,87,166,170,61,250,49,139,249,215,135,168,170,59,95,118,142,249,166,177,121,94,175,159,219,228,219,117,28,222,43,180,225,108,140,7,25,5,94,45,171,5,65,137,255,40,123,190,89,181,94,76,172,91,161,197,240,85,79,172,28,47,57,205,233,102,137,143,28,155,20,20,157,41,148,175,43,167,5,82,171,148,109,247,237,236,176,176,124,1,158,189,93,168,51,115,231,208,228,55,164,123,212,27,25,190,38,1,120,25,153,91,236,95,116,67,210,173,224,156,220,91,207,120,91,114,212,191,71,198,205,146,136,65,91,33,204,192,154,155,243,71,11,55,239,100,89,204,247,199,59,120,22,68,109,137,194,203,81,61,247,11,226,242,210,155,195,209,1,193,108,163,178,20,22,170,30,148,214,80,229,153,91,103,246,237,10,245,110,211,150,205,98,239,92,94,71,206,91,253,204,90,157,216,152,35,148,167,8,201,167,24,239,191,158,102,23,131,159,64,99,81,159,58,193,185,68,1,28,24,38,198,132,80,191,19,122,235,99,129,100,49,253,29,52,194,32,108,106,166,243,179,53,189,96,59,73,241,61,32,223,84,218,118,59,32,64,9,98,239,207,219,101,38,106,54,148,148,25,5,50,107,106,152,242,117,192,102,56,184,19,232,133,157,243,182,52,144,217,94,101,153,221,88,157,52,224,159,93,159,71,2,115,200,230,116,202,177,236,75,20,176,16,39,147,24,150,195,21,251,77,57,185,113,216,168,48,127,164,56,104,92,23,85,141,159,93,53,192,103,163,130,24,85,85,160,61,246,23,185,196,18,158,228,129,148,126,206,52,198,191,182,12,98,112,31,56,160,62,208,196,234,1,56,249,23,61,115,25,164,254,151,45,11,124,107,53,151,131,221,52,249,185,90,5,4,129,177,134,168,239,37,50,111,225,178,53,251,9,5,87,32,111,75,239,38,160,33,50,128,211,5,250,31,61,177,31,115,182,221,118,33,225,75,165,5,43,89,152,62,217,185,246,122,194,98,47,193,42,74,46,144,111,16,231,76,88,151,7,93,68,144,237,82,117,206,167,239,6,137,55,125,14,88,92,201,143,148,62,216,55,224,150,178,38,77,42,167,163,233,124,131,220,55,50,219,117,225,244,220,233,124,27,133,246,213,86,54,152,29,92,98,226,98,54,110,144,186,41,161,225,72,199,30,105,121,160,56,141,23,100,40,88,208,169,32,196,122,95,231,57,244,199,120,13,232,165,250,170,24,34,231,23,205,33,18,214,128,56,165,14,48,104,223,133,183,73,58,100,111,112,115,239,70,81,81,38,94,88,232,164,212,242,0,59,114,36,133,89,252,41,204,37,193,144,244,255,242,124,20,131,112,126,131,187,205,71,229,86,90,197,199,245,45,120,190,56,223,164,63,177,75,188,238,180,176,137,182,95,221,29,158,104,4,224,38,183,94,172,67,44,62,168,237,218,85,159,58,25,168,173,108,204,228,81,18,145,207,176,19,10,212,78,133,108,169,178,117,11,19,155,152,200,117,243,99,143,126,93,75,167,4,103,249,245,27,30,184,78,162,35,174,200,4,59,119,138,195,58,130,59,179,147,48,207,134,201,207,31,90,145,168,212,195,79,220,16,253,80,24,42,159,61,178,241,81,140,246,198,225,166,94,74,63,254,3,218,93,2,74,194,239,192,68,55,75,132,51,79,200,162,72,133,34,87,86,7,157,235,37,94,78,191,150,81,213,162,147,20,232,243,173,36,1,244,91,3,192,10,224,194,229,74,147,19,192,165,168,153,5,127,230,113,185,206,127,146,80,114,246,179,16,31,90,0,242,254,82,189,36,246,211,7,118,168,33,154,220,184,107,101,40,150,196,194,242,253,216,72,132,210,147,230,224,198,34,75,25,74,233,205,159,168,6,197,50,217,127,251,94,27,0,89,55,171,138,10,197,251,46,127,84,139,97,212,131,44,89,5,181,154,11,223,2,106,249,29,222,72,44,89,57,56,8,138,102,140,86,159,219,77,239,32,203,126,142,214,192,72,16,119,161,71,155,250,58,115,189,112,51,213,249,25,85,78,170,171,102,164,103,133,109,37,229,130,167,116,64,21,234,76,246,89,206,141,235,89,223,141,56,47,168,166,97,190,26,197,70,97,133,200,148,53,45,183,39,129,38,122,174,116,58,75,115,221,204,101,52,24,94,177,14,237,2,172,234,210,8,208,25,77,235,113,24,108,216,242,184,180,255,173,101,240,51,246,200,240,13,156,209,93,60,66,170,252,82,230,13,215,146,117,255,210,7,34,122,10,106,156,176,21,68,222,248,33,83,152,206,191,60,18,158,149,114,74,41,60,203,244,210,249,189,212,25,25,75,131,95,76,207,254,188,23,124,249,162,255,170,137,0,81,97,181,221,127,2,120,240,234,80,28,115,105,158,136,89,77,135,103,255,251,8,186,242,63,176,164,122,8,11,128,19,58,243,8,212,252,204,84,170,108,158,179,247,0,254,32,87,139,213,136,45,180,92,145,67,92,246,247,205,97,103,87,101,163,137,0,61,23,230,147,218,153,102,235,104,17,24,246,70,190,79,179,238,178,41,56,128,115,241,148,114,229,173,144,63,54,151,123,191,45,145,222,89,230,29,59,34,163,123,120,56,34,137,149,161,32,221,255,87,39,50,57,112,84,159,209,51,170,143,167,190,117,145,202,12,127,248,132,142,52,118,154,247,22,242,179,161,240,146,155,7,176,79,18,1,228,242,227,81,34,121,92,236,105,176,207,233,51,86,159,119,70,173,14,42,103,31,241,149,157,98,49,61,96,106,94,142,12,146,88,63,16,173,84,14,216,170,188,7,119,188,94,156,24,78,218,117,39,252,216,201,136,241,118,24,231,164,15,9,211,193,68,14,9,140,214,99,95,235,172,219,136,83,12,95,75,88,48,152,236,153,95,137,236,38,125,35,176,220,87,52,101,106,40,172,224,140,105,118,201,227,143,43,59,162,152,247,197,72,70,232,183,21,160,2,64,169,41,69,166,102,52,189,217,130,19,196,230,34,133,35,31,17,193,45,252,112,79,79,223,99,168,154,14,19,74,179,41,246,27,199,128,101,54,80,252,173,165,241,80,26,204,142,255,57,94,25,56,246,22,133,229,144,110,212,118,251,36,49,81,254,183,116,222,99,70,181,22,74,96,199,161,124,176,7,199,9,56,128,64,200,185,222,37,225,144,156,152,22,99,76,208,43,99,207,169,146,220,182,136,30,96,166,118,49,125,40,132,106,49,212,158,91,55,84,208,213,75,63,190,113,71,83,98,109,21,176,11,204,253,157,79,106,111,232,239,253,187,98,141,32,52,39,209,183,100,176,183,32,232,137,209,189,13,67,230,44,99,233,235,31,211,62,149,120,185,114,79,123,8,153,151,112,255,65,154,228,16,226,177,21,18,10,146,172,134,181,123,4,253,122,188,229,98,89,112,147,19,145,108,246,176,210,201,128,231,96,230,39,140,7,175,246,144,253,114,34,223,14,48,134,160,78,112,135,138,197,142,208,213,221,156,197,198,131,42,169,203,191,140,36,205,131,59,11,239,147,205,235,193,132,59,199,198,42,204,244,120,24,172,221,253,85,141,118,110,76,153,91,146,222,142,200,251,52,172,145,250,47,123,86,49,253,220,27,77,170,51,36,179,148,26,32,251,162,197,246,163,248,65,123,233,68,194,166,153,206,118,238,22,134,49,13,218,176,11,183,124,197,148,169,251,224,80,11,209,166,233,229,19,220,114,244,144,246,17,131,119,108,78,6,26,238,121,82,13,57,179,139,149,164,255,235,181,20,240,76,155,71,61,89,192,100,16,244,93,71,199,139,70,203,107,44,233,154,66,40,255,1,15,20,206,89,244,23,68,123,164,177,175,187,170,150,195,150,44,96,99,142,169,220,220,197,235,124,72,198,60,112,180,196,35,190,154,107,29,177,10,243,111,210,61,157,156,223,255,101,5,210,27,224,15,23,138,119,65,201,139,134,84,70,122,22,204,153,5,193,108,54,149,173,173,37,200,81,229,93,72,7,45,14,51,177,85,166,96,189,55,43,70,88,172,251,17,221,163,81,62,196,216,14,31,82,46,38,65,125,42,32,4,9,145,100,31,102,106,231,86,31,167,246,39,11,28,118,34,92,179,80,65,191,115,43,247,211,118,115,124,156,122,145,222,177,73,161,7,117,51,20,29,178,100,26,127,202,208,177,209,121,101,140,194,20,229,139,123,55,186,209,31,33,39,115,64,97,128,152,60,147,70,35,97,4,156,87,181,58,244,132,109,115,229,91,215,10,28,25,21,57,163,234,21,101,81,18,220,78,130,105,85,41,164,78,228,156,201,182,234,93,221,241,194,212,66,84,4,11,81,116,94,234,37,200,8,214,228,253,58,205,250,62,168,189,1,46,223,0,158,154,29,127,247,188,25,193,165,228,117,234,121,149,167,254,11,3,15,12,91,42,46,11,240,230,134,120,108,46,58,63,23,230,140,113,173,206,94,55,63,20,187,32,255,142,32,192,135,161,231,95,115,204,50,125,129,245,15,153,89,124,35,87,200,91,78,68,126,100,158,103,224,232,192,132,174,34,19,19,48,139,182,247,255,70,88,227,139,253,31,10,222,62,188,140,85,169,143,143,14,29,108,159,46,98,211,30,129,63,149,77,230,246,61,181,103,153,124,242,214,63,70,78,193,78,208,159,94,20,59,30,81,88,112,124,123,183,101,239,217,86,232,137,59,250,5,110,107,71,27,31,15,33,62,200,161,218,153,82,134,5,7,141,180,7,152,169,23,182,33,150,252,223,90,209,54,177,15,50,19,8,253,37,226,84,143,33,164,230,38,215,102,42,156,198,36,35,149,175,75,79,102,252,69,215,7,165,103,252,189,221,18,204,32,86,110,22,47,74,38,247,11,126,5,145,242,247,20,9,190,177,121,79,16,110,73,41,45,141,3,247,35,3,252,191,45,7,156,127,115,198,74,194,5,25,124,110,61,109,115,151,84,72,182,140,170,23,217,123,133,98,143,18,53,128,55,78,61,89,152,214,253,63,133,196,183,215,107,107,158,245,129,15,153,169,246,158,65,172,8,47,226,30,126,10,64,163,175,108,218,130,19,89,235,34,206,150,176,199,6,140,234,201,165,130,107,208,64,112,36,44,115,250,199,236,204,60,127,43,124,225,163,49,76,103,210,254,126,180,82,44,230,68,93,12,246,201,186,72,190,172,76,128,42,173,0,221,120,14,150,19,197,121,163,71,111,214,183,143,24,187,70,13,255,228,250,134,173,209,183,166,208,21,225,94,109,145,98,70,255,76,151,190,150,183,152,248,238,224,187,111,4,2,111,236,73,135,133,67,34,193,94,52,159,42,187,59,38,75,152,72,134,112,236,191,233,150,43,156,14,167,70,226,7,114,200,31,140,164,33,84,232,169,15,96,172,175,192,57,229,71,227,101,139,17,90,45,154,32,255,204,159,141,200,159,147,45,152,135,128,51,11,78,181,154,83,92,144,157,134,244,234,140,201,95,218,104,165,146,35,28,223,139,111,128,149,30,162,119,191,217,136,196,219,138,212,22,168,182,19,118,34,168,68,234,104,231,59,166,128,52,254,212,215,218,117,66,31,249,88,61,78,33,130,242,94,66,17,169,102,100,130,251,1,125,169,71,110,165,239,246,162,251,220,185,184,20,76,133,171,122,57,219,218,181,169,220,38,166,27,206,53,166,180,135,172,64,7,187,131,182,110,67,34,191,25,145,197,184,217,30,140,72,15,212,194,123,34,239,194,64,110,117,35,199,82,17,157,252,230,226,228,44,151,158,81,101,191,59,18,175,143,139,235,12,185,50,15,106,29,143,82,247,211,52,208,35,153,64,11,50,37,13,38,232,128,45,104,62,240,201,122,137,83,140,250,178,64,142,202,168,54,119,221,215,71,166,35,108,71,223,239,99,153,12,8,134,64,200,182,235,107,96,111,231,153,200,254,189,247,49,93,127,4,200,77,43,160,120,224,252,243,224,46,190,166,143,82,46,207,86,235,116,203,190,88,18,55,121,70,227,215,107,69,58,245,221,133,33,73,230,34,36,254,49,127,129,180,253,175,209,180,54,94,124,96,104,97,243,225,38,248,166,230,189,233,78,38,61,122,43,51,76,9,219,127,1,239,79,151,48,213,26,208,118,80,108,178,180,167,38,224,5,87,106,12,73,252,109,195,190,244,1,237,106,212,236,116,74,192,255,121,219,152,67,18,77,38,21,51,27,121,200,196,0,84,219,179,46,124,54,85,12,179,49,241,46,197,14,33,28,79,227,246,94,112,66,187,209,230,116,161,40,15,78,57,156,110,138,178,73,41,255,178,62,43,236,180,171,248,21,243,240,13,110,71,67,79,176,57,76,207,194,20,219,223,36,60,83,50,200,87,245,137,235,132,89,144,67,4,174,55,221,14,212,138,175,187,209,186,54,80,178,238,243,36,9,199,108,128,111,120,61,208,105,53,44,233,236,78,63,226,71,197,238,242,101,100,227,70,160,209,41,198,56,65,115,138,237,132,126,95,23,46,122,98,177,164,159,251,98,212,145,111,203,95,36,21,53,163,88,57,51,139,255,60,181,38,187,107,75,128,165,215,232,130,56,103,173,192,192,119,72,104,142,246,79,232,200,17,207,225,61,55,106,74,61,126,180,229,233,187,223,190,82,11,232,15,84,52,13,98,154,199,134,191,227,132,219,235,17,230,249,92,249,34,165,54,132,101,234,209,220,66,6,69,181,50,132,160,155,246,171,5,167,56,49,27,175,90,222,36,13,217,116,128,9,151,3,203,43,43,40,205,132,14,248,28,88,180,107,146,95,19,175,0,109,41,170,148,148,54,179,0,71,101,59,99,221,143,205,42,59,156,112,136,31,59,18,231,136,191,41,46,122,77,101,152,172,123,108,116,111,53,229,4,163,218,156,39,171,198,100,223,236,90,205,126,143,72,67,138,159,241,118,154,239,154,219,34,182,123,33,163,113,46,15,249,238,36,50,215,132,241,226,207,196,181,96,162,212,88,224,190,81,179,12,136,146,122,238,83,129,26,72,105,125,20,146,253,67,112,232,12,188,96,52,161,160,121,241,50,77,49,218,20,78,169,246,196,95,213,12,11,243,170,71,1,244,78,233,115,143,34,201,250,23,100,9,97,17,4,211,193,128,42,106,170,138,9,75,28,208,247,157,32,4,210,106,87,15,97,167,209,22,160,123,52,183,148,194,21,14,53,212,119,43,76,147,154,56,43,175,79,109,103,68,93,115,95,230,242,89,230,162,136,47,37,79,109,220,24,217,83,40,241,45,113,250,138,133,115,120,72,115,222,65,36,226,44,1,172,128,192,152,113,44,162,139,24,194,114,139,90,162,31,228,198,129,96,97,224,87,232,183,43,193,104,251,129,67,148,240,227,100,4,27,202,89,241,226,221,189,142,102,74,1,234,197,88,247,95,217,142,161,58,118,124,174,252,162,242,248,126,19,199,138,191,202,209,59,204,127,100,65,187,50,108,197,107,107,205,55,228,48,246,168,68,28,74,186,102,54,116,29,188,57,221,206,122,202,240,151,15,23,162,146,91,12,88,51,69,3,110,205,52,5,186,49,46,171,126,221,23,30,236,45,162,17,198,211,238,177,147,106,5,203,206,78,143,1,167,153,96,15,225,28,219,223,209,68,221,218,102,32,19,138,90,130,254,63,73,240,165,99,150,83,198,65,210,22,92,216,204,186,182,213,249,35,2,80,190,138,101,47,225,210,232,29,85,90,174,228,82,244,173,189,193,47,20,238,93,189,172,27,25,87,244,243,224,87,201,186,153,42,69,160,195,77,180,136,128,231,197,161,163,94,0,191,87,57,125,254,155,170,223,110,165,95,181,188,82,153,240,68,118,58,137,253,184,248,35,170,207,20,197,246,93,21,36,48,195,147,75,92,94,166,34,77,198,225,189,122,91,111,136,32,138,146,132,33,113,35,32,184,97,10,255,132,98,61,203,100,65,30,160,150,30,85,22,8,32,101,187,142,240,176,3,67,219,207,113,202,242,213,177,61,155,141,225,69,7,10,3,184,65,132,69,241,149,214,97,91,168,150,187,136,18,190,15,66,134,232,239,202,169,247,10,160,246,157,238,77,41,185,221,165,157,108,94,145,231,229,169,101,1,167,15,161,20,158,211,139,204,107,228,206,211,185,65,246,158,167,12,107,190,45,182,28,192,44,106,148,62,159,222,82,10,227,237,251,3,151,152,139,76,162,183,169,202,107,181,200,129,195,124,71,208,135,234,26,203,154,53,208,137,99,150,100,142,114,50,153,183,126,133,1,253,9,202,235,65,46,106,126,8,5,105,93,53,17,35,209,62,117,114,152,57,29,66,71,127,2,130,103,158,7,17,86,195,64,229,219,75,195,212,33,209,50,154,59,27,177,135,24,163,107,219,137,197,220,7,153,96,131,0,65,187,83,25,18,15,100,245,27,6,174,119,25,182,124,115,158,7,84,182,105,34,75,231,222,190,48,233,221,49,119,79,153,174,200,28,223,87,37,72,254,237,189,199,23,239,255,69,27,152,251,104,233,142,231,80,48,149,197,234,170,200,149,73,120,9,20,212,128,69,99,144,23,22,83,89,207,47,19,17,198,156,214,226,55,130,85,146,54,5,58,224,214,6,27,36,31,164,126,182,225,53,4,52,100,11,28,220,125,41,101,102,215,188,97,6,55,113,252,140,78,81,115,58,203,129,115,132,109,206,21,68,78,20,128,95,62,34,72,211,75,41,78,234,223,115,175,57,229,107,227,179,9,162,15,86,211,207,126,44,120,162,65,99,15,187,57,91,18,41,138,119,15,37,90,138,187,40,13,121,164,30,26,160,7,116,143,9,149,10,228,215,85,75,134,113,241,72,248,12,116,160,177,187,166,188,208,252,178,182,169,220,121,139,203,135,116,198,224,193,215,214,189,110,168,68,129,130,192,8,226,15,122,181,16,37,227,17,156,38,246,249,4,89,193,12,237,32,109,66,52,139,50,235,10,231,210,19,204,191,161,192,238,27,142,203,62,146,194,119,135,132,70,245,214,127,209,179,254,19,43,72,110,124,118,71,34,142,134,163,182,130,140,131,160,56,194,13,10,6,8,136,131,171,206,237,108,163,127,8,17,208,116,17,165,125,236,166,45,180,115,123,110,117,255,84,33,201,176,66,60,220,2,92,128,59,50,147,27,232,7,251,48,118,128,215,225,182,113,163,1,165,184,212,132,246,28,57,13,84,140,97,222,230,172,120,254,160,216,70,239,215,0,111,160,68,51,0,31,109,79,49,38,221,94,95,37,226,200,239,75,160,227,1,122,27,49,244,122,133,67,125,60,12,216,60,89,219,92,146,252,169,205,31,71,112,119,174,142,76,205,10,173,28,31,26,119,222,159,151,151,214,150,124,197,51,174,17,3,58,240,120,130,175,51,87,155,106,76,197,143,86,226,95,45,72,196,34,230,99,248,121,236,163,207,67,132,152,165,42,252,107,111,171,10,114,221,71,94,190,87,197,251,236,116,86,60,82,253,64,166,236,178,150,126,252,230,179,186,45,52,123,29,16,175,237,157,13,213,215,69,153,217,233,51,38,227,186,80,200,188,65,110,196,78,3,202,66,175,161,253,111,249,120,23,44,176,170,211,138,243,128,128,115,108,85,27,23,107,91,1,212,31,154,136,228,166,30,96,59,92,34,162,61,242,225,232,47,195,154,45,144,74,125,246,69,128,166,229,187,39,196,152,5,66,133,189,18,245,235,31,214,153,14,205,11,130,1,238,167,83,107,14,41,235,8,139,62,37,74,87,110,189,142,226,150,1,219,52,58,115,150,62,55,66,239,30,11,157,138,57,159,200,148,184,237,250,169,248,88,159,137,188,98,30,50,189,59,15,225,149,129,184,102,146,114,254,181,178,143,54,171,186,63,219,29,83,52,76,222,208,189,242,11,81,188,87,249,54,213,162,246,147,7,72,54,22,48,119,146,108,131,16,194,137,175,45,132,109,33,243,243,40,190,135,54,116,177,29,228,193,151,91,207,114,183,37,198,58,44,53,196,42,118,27,144,95,155,137,80,255,233,76,228,204,81,135,24,99,82,230,130,134,134,90,185,64,21,78,113,200,124,44,66,8,202,250,219,158,245,90,117,100,130,99,79,193,113,76,66,140,147,91,76,194,35,42,183,235,58,162,251,48,190,103,86,96,173,72,202,179,222,118,203,182,225,42,46,211,245,250,204,238,192,46,2,210,178,141,212,84,160,233,228,60,100,58,151,244,252,138,108,189,119,187,104,222,9,36,11,182,33,204,41,164,233,176,152,233,86,233,50,206,99,64,128,110,66,233,201,123,179,225,189,88,55,210,152,178,238,149,204,213,200,212,190,228,170,205,255,165,46,209,51,91,74,229,36,181,120,52,6,82,169,229,225,218,231,110,222,218,6,179,193,106,30,34,243,244,157,149,112,198,254,119,89,250,217,97,62,28,209,188,203,80,211,129,242,222,66,129,254,133,112,29,113,174,62,6,239,237,224,23,116,214,189,215,75,239,171,17,204,68,178,19,31,37,201,108,153,71,126,166,217,28,201,87,186,193,62,200,110,44,41,74,172,66,60,174,120,134,18,85,137,113,240,138,170,198,225,97,115,26,202,243,51,96,31,18,185,179,52,52,98,63,170,11,216,247,18,9,35,203,107,220,12,6,21,178,236,232,102,112,57,211,73,9,28,24,100,146,157,25,199,182,169,71,71,6,60,175,82,210,8,190,110,18,136,70,15,43,13,60,52,12,43,123,111,248,2,36,45,160,215,73,52,54,36,80,105,210,238,113,115,116,84,251,91,72,109,192,195,188,108,51,89,2,189,86,142,28,210,69,246,138,253,85,224,49,223,6,47,125,40,72,173,56,214,70,132,134,51,244,168,101,112,151,126,77,102,143,239,4,13,116,106,10,103,119,126,65,6,31,18,107,68,76,241,127,130,133,186,61,250,68,253,189,150,134,117,83,51,83,25,187,118,78,134,35,123,184,148,245,53,68,14,88,131,0,68,159,141,48,76,196,130,198,34,56,19,203,64,75,87,26,133,28,73,19,242,167,183,2,251,172,114,9,7,155,151,79,86,68,141,54,101,212,74,210,65,219,237,175,83,252,71,245,207,108,46,196,105,180,46,85,217,5,128,221,226,157,62,176,224,25,140,26,228,142,51,187,96,116,42,92,18,197,211,133,4,0,207,161,141,187,60,8,215,220,174,187,41,153,27,83,242,133,205,30,135,7,207,178,168,111,3,85,173,149,137,68,187,204,184,237,209,59,41,154,36,35,7,212,199,183,241,25,178,86,195,41,137,201,81,164,246,218,251,180,218,161,189,193,147,17,147,15,78,69,23,170,86,93,28,58,170,81,208,143,20,240,63,182,158,203,197,94,135,254,11,135,124,183,89,193,71,88,184,98,208,164,134,197,140,75,234,159,83,20,177,109,123,195,118,229,245,116,207,220,6,11,187,253,37,198,220,195,29,176,38,46,67,200,232,90,245,23,105,165,133,57,29,208,185,232,69,180,3,5,19,111,91,226,98,197,90,102,20,243,203,137,88,156,217,18,24,141,253,17,194,150,75,120,212,232,5,187,191,80,176,71,27,94,71,149,230,108,103,17,129,248,166,186,196,171,152,249,136,146,130,38,204,223,106,175,46,105,241,113,125,212,159,243,233,110,229,177,187,141,186,157,99,212,232,218,25,58,4,212,122,110,11,236,187,184,12,168,127,135,212,37,81,184,79,102,171,143,151,189,158,113,56,80,94,110,58,223,118,37,73,53,158,134,151,251,250,216,143,88,233,8,206,211,238,115,195,53,186,238,140,128,150,50,225,14,236,49,195,224,75,85,229,24,20,244,72,136,144,15,96,152,6,156,158,133,144,200,229,50,186,234,205,77,101,31,5,147,136,55,31,158,100,141,179,213,225,15,161,176,225,156,40,169,60,57,227,45,170,44,97,107,83,178,31,102,192,84,212,43,159,32,188,252,47,248,53,6,68,8,126,187,27,46,133,214,4,199,153,29,177,123,35,170,100,66,253,178,46,37,206,97,62,17,208,98,178,195,223,64,76,251,94,132,241,102,36,130,182,53,98,94,253,122,211,197,204,144,195,101,203,40,158,215,192,102,44,87,233,61,81,147,158,79,117,222,27,26,219,168,15,59,142,65,113,172,49,253,190,191,188,12,59,244,226,238,7,59,116,34,120,56,20,118,83,59,78,142,79,43,150,41,207,228,35,234,182,14,86,50,120,254,31,74,82,5,29,39,173,104,87,10,249,237,158,29,211,250,239,50,64,90,200,107,209,100,26,135,182,38,139,177,27,64,6,87,21,235,204,230,235,222,248,48,156,212,204,138,22,36,123,3,40,93,25,200,55,162,51,116,3,140,58,246,81,78,59,89,103,138,23,220,89,171,48,48,203,181,80,163,171,109,173,17,34,188,238,42,205,32,106,18,122,80,8,247,127,26,32,148,141,138,226,57,27,129,234,74,40,235,202,6,106,127,1,11,117,117,236,240,123,227,139,185,241,205,42,57,186,237,83,21,90,3,25,88,42,109,224,140,238,11,177,108,46,111,28,229,139,95,217,72,101,173,235,131,28,2,85,51,19,52,105,218,235,176,84,57,140,165,80,238,93,92,6,47,138,188,132,100,36,219,223,236,201,112,201,190,0,20,146,68,95,16,147,1,52,108,54,185,188,154,104,247,173,127,160,214,230,207,56,112,98,105,62,42,66,97,101,47,220,193,114,23,202,61,21,118,64,16,191,112,119,123,20,117,173,202,70,39,239,112,202,66,142,163,211,106,89,2,97,150,55,78,226,111,190,170,144,53,195,72,96,89,229,178,153,130,164,161,86,154,154,21,95,120,12,31,122,50,142,245,189,124,17,218,35,201,75,20,203,234,97,11,70,151,3,185,169,71,243,91,56,248,117,103,8,162,90,14,193,33,124,194,169,48,150,40,80,127,37,151,74,195,221,99,145,74,172,228,150,120,147,204,160,67,110,187,30,236,197,101,7,127,128,115,7,243,235,20,66,101,40,114,136,254,206,220,67,96,231,89,65,202,234,82,8,131,187,238,220,213,142,223,77,25,167,69,68,87,110,101,200,142,51,26,234,143,164,214,134,215,222,141,23,42,75,147,88,211,199,154,201,24,72,202,13,136,234,25,52,120,254,136,185,193,163,187,133,84,93,81,133,177,73,126,136,46,251,136,144,180,33,34,18,230,128,47,79,79,106,150,8,58,160,248,106,132,183,215,17,146,173,177,243,32,65,1,175,14,45,235,55,127,69,29,175,177,184,199,168,231,173,143,212,218,44,28,243,157,87,243,247,193,142,155,49,191,221,140,235,246,53,125,204,139,60,232,18,220,63,106,61,252,172,154,140,47,208,189,55,163,20,44,108,250,50,252,255,204,45,52,2,76,66,64,241,107,21,163,134,187,242,247,136,203,1,7,118,226,244,67,198,15,238,194,74,9,230,186,185,49,162,49,71,168,31,130,160,103,223,244,225,108,133,142,123,181,164,114,112,172,100,229,165,150,250,57,212,15,63,204,70,163,4,98,111,152,45,37,45,245,228,45,244,111,124,250,163,197,120,243,232,117,56,154,191,145,196,141,125,8,55,90,132,216,85,224,174,60,253,201,63,198,114,202,235,236,103,174,176,192,65,93,161,74,226,65,222,241,126,119,113,174,16,71,68,19,253,160,250,79,117,231,129,159,61,132,104,164,251,78,110,48,246,12,36,172,100,111,152,87,36,40,95,115,60,227,74,123,204,149,244,119,65,162,114,102,121,19,155,249,117,248,51,151,33,42,115,199,237,144,43,180,51,121,129,23,83,127,226,56,9,32,222,44,201,44,21,7,249,122,183,224,239,85,204,10,181,91,19,103,103,133,205,12,229,38,97,31,108,141,82,255,186,32,185,59,95,66,45,15,41,179,36,56,178,53,39,230,128,252,12,104,165,98,132,4,223,238,44,36,222,188,218,52,250,146,212,148,237,85,68,175,72,79,155,38,36,230,62,122,67,208,138,241,5,49,158,119,106,100,178,247,61,154,161,134,111,198,28,192,44,150,189,7,205,154,142,45,190,172,69,107,176,36,105,64,30,153,120,233,138,210,10,19,201,37,119,182,152,85,43,37,56,68,199,14,82,214,220,245,249,231,141,77,20,190,252,61,102,166,209,230,24,109,225,229,78,195,145,93,109,32,127,163,49,126,248,87,165,80,47,35,155,3,51,50,146,244,105,171,122,226,62,82,242,157,209,37,222,157,224,156,21,73,10,238,198,123,110,60,209,122,158,82,5,221,166,227,119,183,251,80,175,245,112,156,150,175,183,247,162,53,159,213,33,71,40,168,227,104,244,244,210,154,12,114,234,6,153,36,147,203,170,108,85,64,250,110,225,137,2,143,243,163,40,173,220,191,63,210,108,131,154,142,83,175,46,56,41,236,83,221,81,161,144,135,172,99,88,139,115,229,148,143,162,9,203,12,44,238,102,165,234,230,179,179,242,16,227,158,20,196,203,126,102,121,194,246,105,131,73,192,81,122,192,229,32,52,68,139,60,16,102,94,4,190,236,77,238,222,73,240,221,6,252,179,240,56,85,108,237,167,95,168,223,161,49,28,186,57,93,43,203,125,223,42,221,67,47,174,96,56,99,204,115,41,252,252,106,153,180,228,242,100,155,42,105,108,181,215,47,150,176,81,36,192,211,244,135,162,127,189,201,80,62,117,91,125,58,245,215,9,16,165,134,52,42,43,225,155,28,21,189,76,85,226,216,155,133,105,120,60,145,152,6,52,150,149,2,255,255,126,255,45,36,58,37,21,112,25,5,210,187,69,74,195,46,226,170,12,90,154,7,142,228,89,148,22,211,1,150,132,252,99,19,215,135,242,15,150,0,17,251,192,38,133,71,164,62,161,144,240,178,62,63,254,50,137,26,207,233,156,52,145,94,86,239,132,26,146,181,46,165,248,100,14,76,252,16,214,130,195,166,67,120,113,30,255,126,197,11,57,108,130,66,163,177,70,30,223,117,244,53,44,13,86,39,70,58,213,212,230,152,164,76,152,10,227,3,6,230,216,73,88,108,91,245,126,137,58,224,132,168,129,199,254,247,134,142,56,81,168,160,119,44,222,123,230,189,204,92,245,18,227,172,58,240,174,149,68,71,210,183,169,241,146,73,86,210,216,156,250,239,161,219,212,210,69,48,33,137,81,185,192,218,197,2,122,26,76,13,121,61,31,44,239,37,158,126,254,241,131,26,167,224,67,133,125,52,204,195,141,119,131,208,214,151,86,54,137,139,144,178,173,220,170,156,70,125,66,38,125,127,135,146,246,160,95,230,1,248,184,55,65,56,225,139,169,106,17,246,153,98,119,248,67,85,148,28,157,200,233,186,149,138,180,147,37,42,212,190,28,189,109,117,242,168,56,133,17,29,241,89,218,5,242,81,50,61,166,175,124,106,47,237,20,201,235,69,95,202,35,243,79,223,34,85,47,100,252,168,29,171,20,189,109,65,14,156,71,195,246,94,104,211,21,29,195,84,33,131,207,221,120,139,57,78,126,88,195,191,172,133,96,242,110,140,236,227,76,154,55,32,134,193,20,204,21,192,232,157,224,147,175,193,96,9,127,18,107,239,96,240,98,139,149,104,92,151,196,170,198,104,185,117,179,26,20,72,48,36,47,32,86,42,189,173,80,71,219,151,79,181,88,45,26,191,38,133,45,54,131,31,109,115,161,163,34,38,89,40,49,173,198,48,17,40,39,121,77,90,70,42,251,130,168,125,184,76,60,95,94,136,227,248,145,210,226,191,137,247,72,210,17,141,52,5,102,220,23,111,146,114,218,208,22,105,9,130,97,83,57,25,228,137,6,99,12,24,29,89,25,101,217,133,196,253,246,158,114,75,8,90,142,28,147,19,22,164,240,205,1,21,145,19,225,61,98,21,22,215,32,158,9,44,97,148,104,201,219,76,43,45,162,73,151,252,188,155,192,134,113,103,109,255,54,42,206,24,76,87,154,98,187,78,193,50,86,191,222,86,162,165,38,191,118,117,72,31,6,174,147,231,105,158,70,133,79,138,223,55,73,210,90,194,194,112,167,14,253,133,160,197,234,193,24,75,239,106,47,115,70,102,75,122,123,87,158,185,162,180,84,210,222,141,172,125,211,117,181,155,250,182,51,247,178,100,123,8,8,173,224,246,222,40,35,31,171,203,195,36,34,6,53,171,105,219,106,216,77,18,130,182,37,225,3,235,196,203,114,168,7,2,10,14,230,118,6,134,118,20,184,145,213,218,127,110,182,193,145,91,202,110,11,96,118,1,8,96,103,167,236,180,15,141,151,253,100,7,112,25,70,89,121,233,178,158,234,47,68,162,185,146,146,7,74,2,17,238,108,171,91,64,92,173,85,82,121,240,175,136,132,26,123,225,64,169,132,53,192,187,113,8,165,133,192,249,61,166,108,170,2,175,11,243,183,162,93,109,51,151,40,206,39,150,0,84,130,215,29,211,96,200,244,193,206,63,137,9,225,205,195,93,147,70,125,177,146,164,76,247,0,61,118,12,73,75,151,145,218,82,180,207,112,233,175,169,104,180,29,149,4,129,248,70,10,159,34,67,208,4,235,146,205,128,223,104,17,16,189,72,150,29,148,21,85,152,237,97,200,84,57,234,9,165,16,73,40,118,10,18,222,171,43,231,169,211,149,179,250,145,227,129,66,53,2,35,228,99,7,1,101,161,122,247,98,103,47,32,194,21,66,228,215,171,211,95,93,47,71,164,197,154,72,46,73,190,186,131,152,104,252,1,237,94,154,240,6,67,188,57,183,3,28,30,181,14,142,247,193,242,88,231,188,86,198,130,125,97,9,115,137,196,6,38,94,170,51,157,253,197,152,195,181,150,253,125,49,6,217,29,102,120,252,248,217,191,232,176,151,7,118,12,126,164,219,67,123,72,16,146,223,203,183,0,196,87,186,185,173,67,246,204,171,20,21,86,98,182,253,7,186,6,120,189,118,3,229,237,60,53,90,120,139,87,229,79,153,85,139,16,81,100,189,150,202,125,164,42,132,10,163,190,85,177,69,169,181,85,186,64,77,182,99,209,185,183,19,5,1,24,167,247,211,71,7,154,124,136,40,199,61,196,217,202,170,170,93,64,20,178,234,247,41,59,124,192,158,211,128,28,144,37,95,61,108,113,150,27,161,102,97,250,86,162,10,193,27,201,55,193,56,84,164,176,59,172,180,2,117,209,83,226,255,156,104,115,80,9,171,177,196,38,252,19,138,252,29,242,231,74,93,205,161,41,158,79,204,211,0,30,248,42,125,237,167,151,3,163,35,219,102,225,38,80,160,246,91,202,15,81,5,104,108,210,239,193,131,146,27,150,17,171,71,221,84,112,204,146,94,186,237,255,206,118,141,107,20,169,226,15,43,75,224,52,120,186,0,134,235,166,30,237,98,31,139,146,29,104,64,56,3,249,66,92,147,217,211,9,31,96,178,69,148,227,230,101,236,243,45,246,172,39,229,59,69,106,63,147,212,148,179,217,10,220,19,61,36,147,54,173,248,250,238,79,181,163,211,105,11,79,136,249,56,91,202,219,147,180,212,42,140,52,110,222,216,92,215,61,213,55,188,33,239,190,201,255,96,1,215,85,244,86,49,152,17,180,172,68,196,115,71,107,182,243,219,136,48,23,116,210,242,8,233,123,235,101,169,61,55,63,1,51,205,161,189,96,59,52,218,197,250,26,88,73,52,217,104,199,216,234,189,209,12,232,29,210,128,20,244,127,219,15,204,123,222,84,167,249,54,43,174,28,118,186,210,116,176,58,78,38,166,130,144,219,92,43,91,180,1,195,20,39,139,0,25,240,204,75,61,178,95,199,10,3,136,139,50,249,155,86,95,70,214,41,166,76,132,6,166,146,35,118,145,100,203,149,154,211,215,94,104,5,44,83,183,45,251,89,212,57,197,144,82,87,170,120,45,105,80,129,100,131,159,10,127,221,163,246,63,192,154,53,205,6,127,117,223,24,147,216,93,28,239,163,214,221,158,12,149,255,83,88,41,136,165,138,1,254,6,44,25,143,22,104,150,94,24,196,25,238,193,216,170,71,103,76,33,52,211,45,205,235,134,41,248,86,65,9,32,255,32,95,30,250,243,251,43,119,170,184,85,107,38,21,98,231,54,218,226,16,72,174,6,221,38,211,120,221,119,117,120,67,209,251,33,84,155,163,163,47,53,96,15,51,76,204,87,153,85,170,54,66,113,12,174,34,104,136,90,62,76,103,210,150,82,37,200,148,44,89,113,229,33,173,240,114,61,21,131,193,157,216,181,193,207,219,29,42,99,21,186,158,11,145,155,4,216,22,244,162,245,120,63,128,57,117,241,213,60,251,251,149,87,153,99,63,22,75,81,103,103,239,199,225,110,110,88,38,125,240,116,161,226,53,38,183,2,223,68,221,87,205,73,201,187,129,82,39,35,166,109,116,96,250,15,15,242,104,227,86,21,140,48,172,188,54,214,185,33,4,199,217,220,218,185,44,244,170,133,64,135,231,135,80,159,130,65,112,36,250,209,241,226,74,174,130,199,202,217,218,87,161,162,130,254,242,150,34,63,117,178,224,76,211,80,201,111,72,69,137,93,62,24,23,249,115,80,83,95,17,166,84,223,132,120,6,53,34,199,208,205,80,109,133,213,92,49,18,214,230,123,245,73,80,228,94,106,241,165,216,84,255,96,177,178,90,92,5,219,185,153,238,208,136,79,150,15,232,139,179,52,146,235,158,62,239,136,154,45,92,190,176,19,91,40,214,152,149,209,222,247,97,175,74,250,98,231,204,211,233,2,168,136,18,202,254,144,196,95,80,187,220,123,31,164,176,207,23,248,81,3,174,138,206,65,83,36,29,70,32,71,21,227,157,254,228,2,4,215,71,27,252,9,219,49,49,23,248,163,43,170,192,126,75,198,97,91,38,182,93,204,141,250,187,145,128,158,103,88,73,178,191,233,253,231,3,169,38,117,163,181,44,217,91,138,15,239,82,140,19,78,13,168,212,227,46,202,225,130,28,150,211,105,239,25,243,208,76,174,52,37,170,87,125,141,221,90,95,41,51,53,205,112,75,54,129,102,51,87,222,28,117,188,154,174,103,66,55,95,247,97,127,31,107,22,117,195,115,97,108,19,52,70,179,212,190,15,8,213,49,139,119,170,201,169,8,199,203,166,183,90,134,185,169,133,135,9,251,66,104,187,220,182,164,82,21,125,132,197,116,14,169,241,211,104,107,169,17,246,140,46,235,236,23,84,93,180,72,214,10,39,185,197,170,73,30,43,35,75,114,202,126,143,2,127,114,206,107,25,116,183,11,43,3,146,183,121,214,79,26,240,70,203,45,88,74,11,137,245,21,38,44,66,143,61,168,69,76,204,92,186,121,203,15,46,213,237,131,23,220,68,52,188,111,185,48,81,35,208,159,218,44,76,71,236,152,61,103,92,247,136,123,88,196,109,213,91,97,190,88,164,237,171,59,217,231,230,51,149,191,114,162,41,91,249,249,25,109,183,231,25,48,30,35,44,156,199,26,146,144,26,85,40,82,54,83,253,102,88,29,52,114,160,176,0,95,4,217,205,123,143,97,62,149,15,178,195,166,156,183,183,170,183,54,232,197,211,241,7,215,241,86,159,151,161,98,116,91,139,14,111,22,41,155,5,43,72,245,246,20,196,27,62,112,149,21,253,42,111,173,148,25,42,199,41,53,84,169,17,246,92,25,211,161,41,159,252,62,243,4,19,121,43,66,199,74,28,208,193,205,33,126,84,173,30,16,26,179,244,95,188,90,6,16,178,251,191,203,121,130,161,12,52,170,24,14,141,2,163,190,6,52,205,187,57,245,252,9,53,65,132,246,126,90,3,26,54,238,222,74,237,35,163,214,83,43,254,139,112,244,74,15,241,20,255,217,117,129,81,233,181,187,160,29,30,245,145,199,163,29,171,87,228,222,50,229,60,139,23,152,179,33,23,124,180,100,223,209,21,191,93,240,166,209,66,67,28,158,237,190,62,80,188,131,151,72,22,159,212,121,139,49,254,184,106,134,122,77,103,165,81,70,69,174,0,7,179,26,152,234,23,37,155,212,120,59,223,226,216,189,170,9,42,206,10,123,140,130,214,229,149,218,74,215,152,151,235,170,53,33,209,190,193,105,61,182,108,226,176,32,213,78,117,106,23,56,121,61,82,213,107,121,107,114,185,20,99,151,57,44,105,153,238,174,24,192,241,254,251,80,193,143,221,0,58,227,109,190,129,185,22,131,37,221,129,34,101,144,152,33,250,198,183,73,236,69,174,215,68,64,181,94,33,132,40,149,248,252,133,191,99,245,130,21,43,49,211,224,204,33,169,240,230,120,107,228,46,140,168,241,32,17,95,48,147,101,16,176,251,83,160,253,105,171,56,79,198,139,36,48,144,120,99,236,171,235,56,117,196,171,178,244,170,61,79,183,32,202,66,50,130,211,99,78,199,73,255,242,30,138,199,156,129,107,187,182,255,144,201,230,138,199,111,154,10,126,232,144,99,117,187,160,97,221,177,191,5,239,139,181,240,32,249,247,61,216,207,154,217,224,246,49,118,3,194,107,197,233,3,242,99,182,58,45,151,176,238,101,118,57,44,123,195,112,61,129,140,199,98,25,86,104,2,141,220,161,128,109,32,8,89,147,249,11,246,14,255,195,81,233,46,89,37,122,225,211,69,132,120,138,169,254,0,72,208,116,247,244,60,55,28,135,15,11,28,174,65,40,253,148,181,6,57,220,134,224,205,255,225,22,228,49,200,228,182,179,141,237,217,9,47,114,203,57,24,173,236,15,100,174,120,178,73,84,236,141,45,188,142,252,66,85,56,248,161,247,21,240,209,145,198,24,158,227,106,158,18,248,204,21,1,99,35,91,187,157,228,98,106,35,231,158,103,53,119,135,62,168,207,48,5,118,236,117,255,204,65,60,49,102,180,55,82,149,17,205,214,182,198,223,77,55,234,99,156,29,161,90,22,138,7,126,240,213,226,110,63,214,97,71,161,203,216,10,31,25,62,71,223,163,238,97,14,115,144,121,112,103,4,186,16,66,51,105,110,65,111,32,206,82,213,231,74,107,199,255,85,48,249,19,123,45,142,3,104,77,86,181,99,8,158,50,3,108,43,23,113,246,189,180,107,134,24,9,137,36,178,9,176,197,63,33,63,164,220,217,243,175,16,197,210,28,16,109,192,143,193,240,252,44,124,8,108,179,168,171,135,107,32,216,49,136,123,109,133,33,176,167,185,189,30,120,210,5,211,14,127,118,199,147,121,246,58,33,239,172,251,87,223,152,144,13,169,216,65,87,59,132,210,118,116,30,68,72,68,155,103,230,81,33,26,21,82,14,73,251,183,147,86,222,194,97,44,169,244,82,155,95,253,205,116,91,165,44,64,31,163,242,253,93,23,26,209,14,33,97,62,148,115,63,247,111,137,13,9,163,215,243,223,218,10,114,82,195,219,233,24,117,167,173,231,13,156,77,46,231,130,200,122,169,91,49,229,215,250,140,73,229,240,44,212,41,117,112,31,126,218,196,58,241,101,147,26,195,148,98,153,198,104,87,90,149,128,60,239,177,50,49,11,242,239,230,196,182,89,101,80,215,168,143,70,48,53,53,215,22,99,194,129,245,128,163,40,102,25,14,99,189,152,35,135,13,16,105,137,188,32,226,246,176,38,30,36,65,146,145,240,83,103,2,107,133,21,172,41,239,28,250,134,170,228,80,43,122,211,87,111,228,168,29,171,79,69,62,152,18,69,203,96,169,144,83,50,37,65,208,1,113,46,2,67,73,221,2,181,73,185,209,20,163,237,141,222,221,69,220,155,12,177,239,150,84,234,58,111,225,3,31,187,110,139,78,139,234,186,202,73,72,34,125,59,43,206,220,68,6,49,123,14,147,144,206,60,95,31,173,236,244,239,64,11,119,89,226,7,117,175,218,115,104,165,195,209,202,140,132,15,6,115,213,209,69,238,7,89,37,249,156,158,67,124,208,100,194,232,148,52,214,125,166,99,224,152,46,109,187,234,230,51,60,189,191,120,28,13,67,152,105,230,40,147,153,215,16,149,231,51,170,159,88,97,228,216,161,34,87,65,129,153,213,186,140,150,104,113,164,25,120,246,58,78,221,124,33,179,135,7,220,233,68,9,15,123,101,187,131,139,95,177,234,29,215,24,57,107,53,194,252,161,247,70,224,245,22,104,10,41,39,213,190,186,249,159,32,28,196,55,153,225,205,18,72,227,70,120,101,199,237,132,225,10,124,88,154,151,215,153,67,177,100,244,99,169,37,127,97,122,188,216,217,79,187,227,87,69,243,42,139,151,228,79,141,154,88,240,7,29,255,165,129,150,70,173,212,207,194,245,243,54,210,111,168,77,71,140,61,28,64,106,8,196,60,68,154,18,110,22,252,63,172,163,34,138,138,105,145,101,244,110,11,75,95,244,220,224,140,191,243,85,79,137,128,246,173,146,28,1,68,146,131,190,104,107,105,10,183,141,149,204,59,176,190,91,3,180,254,33,47,24,58,4,53,177,211,193,103,6,161,57,156,191,177,108,76,83,185,133,20,167,103,26,75,148,54,239,124,182,71,95,160,157,60,112,22,149,136,53,82,150,241,250,192,35,199,124,207,79,66,84,131,7,63,140,114,16,166,158,30,0,73,131,202,144,116,46,50,92,60,23,147,147,14,236,195,64,128,205,63,248,146,1,49,182,30,96,166,149,196,243,131,88,93,119,167,118,22,137,56,179,169,223,194,48,235,4,196,19,7,210,55,75,235,92,247,15,83,174,53,132,172,34,214,91,205,147,70,34,195,103,132,175,68,245,7,227,205,122,160,7,72,137,123,51,243,8,7,82,113,179,53,171,249,151,156,75,82,204,101,194,53,247,2,201,39,125,151,8,4,189,190,40,95,41,72,181,116,99,58,100,136,118,164,13,191,107,164,69,39,229,204,2,248,254,87,112,64,247,106,105,66,193,73,104,67,75,181,248,105,39,227,153,139,164,41,215,76,244,118,95,99,56,13,94,20,67,33,205,238,108,249,81,105,60,177,18,155,229,73,173,205,78,164,144,180,161,191,210,203,150,190,16,55,228,110,203,212,118,15,103,25,67,152,199,2,36,17,117,201,129,88,197,112,153,188,44,58,196,160,131,198,150,19,223,209,224,90,127,231,71,1,40,82,195,12,242,223,233,211,68,210,32,176,1,106,119,179,211,33,221,107,210,194,227,213,88,3,122,19,130,145,199,16,66,179,41,215,40,18,133,40,191,25,49,31,101,27,16,11,60,119,20,186,217,168,204,250,28,173,159,38,166,106,2,35,49,133,30,16,174,41,134,5,154,247,72,247,171,23,225,89,228,141,14,221,122,56,188,54,252,90,121,252,169,8,168,27,59,138,8,245,70,122,230,65,165,140,117,136,206,11,169,209,146,240,8,234,87,27,21,119,136,227,84,138,65,172,42,227,109,202,167,67,219,148,125,32,179,242,176,224,42,235,163,145,195,63,145,122,135,21,164,85,133,249,38,87,145,90,3,151,203,189,99,172,189,248,86,207,193,226,138,44,42,179,190,99,83,127,92,185,32,159,58,246,239,241,246,235,227,205,219,169,42,77,149,0,212,210,172,47,174,68,122,133,7,78,152,86,30,65,58,84,65,40,113,125,213,150,112,146,1,46,218,175,242,206,243,3,22,233,246,135,129,96,57,130,15,151,104,91,220,169,42,107,34,44,14,229,23,97,55,219,134,96,213,252,133,227,120,195,1,46,17,86,212,120,130,91,248,166,233,51,66,254,106,183,117,42,44,36,169,196,204,173,91,96,109,228,171,28,189,45,250,183,121,167,12,164,164,245,225,177,164,170,138,139,161,93,90,83,85,26,198,104,106,203,108,131,144,196,153,22,188,229,99,101,228,68,84,115,35,112,19,129,18,184,189,228,220,191,206,106,106,126,188,176,42,150,208,166,249,215,76,49,78,167,49,137,16,206,210,203,31,206,130,158,233,143,12,168,123,152,246,181,110,5,9,143,33,8,20,72,188,117,52,80,18,200,90,101,236,228,207,56,241,5,217,53,40,86,180,67,214,216,113,227,232,42,4,123,161,29,225,131,69,60,164,193,158,200,54,177,14,32,137,153,25,110,144,200,246,156,194,61,16,88,79,24,113,181,5,133,88,82,165,176,38,251,156,45,231,111,141,37,120,107,195,254,51,23,243,143,18,30,92,222,216,31,27,168,49,204,158,75,50,29,108,173,189,227,162,147,5,233,159,187,189,71,11,14,221,15,68,223,60,234,186,227,182,193,229,131,242,98,115,34,126,30,59,20,56,101,249,9,38,148,110,79,181,179,181,29,240,61,110,204,161,242,160,184,30,38,49,180,136,78,22,156,1,249,192,217,132,67,3,250,243,132,141,231,10,84,231,97,122,73,28,88,116,105,213,193,202,47,183,216,19,80,71,55,14,123,32,194,193,121,208,234,113,73,234,146,93,189,196,164,129,140,201,122,187,60,67,10,121,125,17,246,192,134,16,58,220,3,66,88,63,127,197,206,164,85,151,11,143,43,109,35,215,25,113,90,99,90,205,22,209,122,41,112,244,206,253,59,161,241,168,251,89,190,186,151,193,3,142,219,1,102,68,147,87,145,74,157,223,203,18,248,51,21,219,92,9,251,196,149,82,153,103,27,151,252,54,21,4,47,205,56,172,183,3,29,202,225,83,16,70,15,21,227,219,225,178,248,157,53,135,57,185,163,37,123,167,126,80,187,41,181,17,191,207,228,71,37,158,205,118,62,248,250,194,59,71,214,167,103,233,25,73,205,178,231,128,78,53,113,28,73,140,86,87,88,87,238,196,137,77,234,138,39,195,39,117,89,71,3,123,115,108,182,175,148,180,142,193,159,155,141,71,168,172,98,136,187,112,36,25,146,98,217,160,17,34,77,55,98,189,208,173,74,117,181,200,124,182,123,12,56,62,149,214,75,112,112,107,126,242,224,85,234,235,172,131,250,233,229,99,14,92,194,36,21,156,167,172,215,243,141,214,57,79,177,104,94,207,160,8,3,102,237,50,84,126,223,147,92,211,221,196,52,130,24,176,159,132,65,156,131,71,126,4,33,143,91,104,28,50,153,209,95,181,28,75,113,70,67,27,109,192,39,174,135,252,172,218,211,94,160,62,199,154,79,251,16,22,195,15,22,140,253,36,242,85,72,147,22,121,33,25,195,83,123,67,179,160,66,85,146,45,114,228,93,116,57,55,217,212,216,31,50,167,229,242,19,107,240,57,124,255,142,191,249,148,74,39,163,43,156,151,201,207,220,46,185,27,203,141,137,15,92,5,101,198,159,181,2,84,128,42,9,10,185,221,175,55,128,247,131,98,98,146,152,8,240,110,121,15,67,233,2,21,145,83,105,182,127,239,100,153,185,165,225,124,59,119,26,175,192,81,4,98,42,93,184,200,34,68,13,134,123,5,43,164,167,218,32,67,79,70,4,196,254,131,50,201,157,133,80,79,208,242,155,224,237,252,110,27,249,238,45,235,77,229,182,93,205,123,32,5,3,78,154,69,213,117,216,130,198,46,105,47,78,76,255,250,230,254,99,106,218,110,21,186,185,71,173,236,91,67,119,59,38,141,202,223,39,183,153,239,2,113,168,121,123,54,217,55,237,94,11,1,190,38,16,170,216,147,239,88,254,229,245,220,108,102,247,55,229,237,173,167,179,231,185,82,226,109,53,81,87,15,55,217,69,204,109,3,164,126,143,193,42,141,227,90,36,226,83,128,215,12,177,216,190,140,85,129,225,224,25,74,141,225,41,192,131,60,180,130,169,191,124,58,1,135,224,63,27,9,138,244,124,167,199,35,2,120,62,25,218,238,78,254,29,125,60,19,72,168,31,194,52,28,70,137,193,242,203,2,91,43,138,248,5,135,204,165,116,67,10,198,121,98,100,238,143,43,94,209,39,162,232,129,176,41,254,158,40,195,167,51,206,48,151,123,55,64,65,233,220,176,238,73,3,129,139,129,242,194,88,95,199,147,187,75,237,229,171,30,89,115,154,239,165,169,235,59,98,63,177,91,115,84,142,203,97,103,79,66,2,91,157,207,14,45,246,75,211,46,69,228,42,158,158,132,228,178,36,163,98,194,69,11,37,186,217,155,206,244,54,125,9,122,128,237,37,159,232,91,68,159,92,116,153,244,199,136,214,88,171,186,117,98,60,171,163,232,45,147,151,123,170,237,130,250,83,244,253,125,237,248,178,237,111,15,63,154,122,147,51,15,60,204,111,139,245,231,228,185,51,36,176,237,79,48,4,150,130,163,59,120,29,126,54,40,104,116,142,238,121,237,189,107,191,35,8,119,113,131,109,108,173,24,9,142,108,8,49,51,202,146,192,173,17,1,241,218,187,124,164,246,139,220,70,143,192,138,152,227,175,189,77,209,86,106,63,119,2,159,194,2,163,89,30,119,83,127,152,98,60,123,145,96,155,67,36,124,94,20,93,243,98,219,253,143,238,124,45,39,226,10,242,116,227,184,129,242,21,192,51,94,97,231,64,148,237,211,59,177,198,10,216,238,62,4,109,230,168,9,132,240,215,0,86,29,251,174,78,233,243,27,50,92,197,253,214,2,123,146,246,222,140,146,148,108,237,15,4,222,247,156,154,132,10,40,151,8,10,70,114,132,181,145,136,176,233,7,169,57,111,204,90,220,67,215,132,40,150,216,152,69,54,80,43,171,67,46,100,140,33,185,115,58,154,35,242,247,6,43,31,174,39,80,101,216,73,40,132,227,201,14,85,37,194,50,3,146,118,78,76,36,211,88,24,220,98,14,33,120,148,222,160,20,160,118,195,167,167,92,128,37,5,53,38,72,206,146,123,57,213,135,200,109,71,35,239,160,169,225,222,136,217,153,92,67,165,51,105,189,47,203,155,237,217,9,216,232,29,225,177,49,205,230,232,177,124,66,19,114,207,198,114,64,45,161,124,66,110,85,157,81,102,32,22,83,53,111,196,27,133,196,169,162,223,120,126,235,105,163,132,221,206,150,110,214,226,227,26,172,30,160,193,251,235,130,209,125,165,77,58,39,115,187,196,165,24,148,33,237,15,73,76,51,191,88,212,165,137,89,220,47,35,108,174,114,48,214,113,39,163,180,185,63,88,233,112,0,120,241,137,168,24,63,138,54,82,207,177,179,66,101,46,177,222,3,52,49,103,68,5,246,78,182,234,55,35,29,9,19,192,144,78,132,224,162,148,96,89,62,61,109,6,178,98,241,196,88,167,22,196,56,11,139,35,94,112,213,134,206,158,24,179,145,144,24,250,44,149,253,67,210,8,0,244,166,243,0,180,234,155,46,191,122,41,93,142,70,154,56,201,66,159,207,162,193,63,26,46,204,221,206,29,100,232,161,225,87,106,130,47,154,66,253,50,33,4,103,71,134,239,65,137,220,222,90,200,221,145,253,16,73,125,66,213,113,239,82,209,96,85,98,196,87,143,30,250,24,217,92,120,23,123,71,64,51,243,204,192,239,147,75,30,170,32,161,187,95,176,78,235,9,173,103,112,9,93,39,55,89,66,223,135,55,158,58,28,249,4,53,46,175,138,48,65,135,70,136,1,162,20,77,236,103,41,150,88,60,162,162,221,75,62,108,114,118,100,40,120,101,241,122,160,0,109,225,54,161,239,188,6,149,136,139,198,177,179,32,43,126,52,149,57,217,226,136,215,201,55,32,213,229,87,28,109,36,223,42,151,98,71,107,140,255,230,206,183,84,127,109,108,57,226,37,11,140,188,250,216,82,32,241,186,122,68,173,128,81,29,57,2,23,81,10,233,198,238,113,91,11,7,17,184,180,159,230,116,147,143,120,21,24,1,220,118,49,16,80,204,12,78,41,111,117,193,98,56,148,193,219,160,156,230,56,126,1,172,183,95,204,229,202,75,218,108,245,33,254,8,58,127,98,209,197,176,100,60,110,139,133,80,43,42,133,200,12,216,121,186,89,171,171,252,220,132,121,46,180,75,79,8,157,91,112,112,34,247,193,147,132,119,236,30,223,101,129,132,197,45,134,84,202,92,249,70,208,211,158,206,209,216,202,106,106,96,1,80,249,182,103,247,124,85,169,42,212,67,245,112,214,156,147,143,216,186,202,197,119,5,230,23,226,199,79,150,253,252,85,1,193,145,96,212,15,165,73,246,244,50,249,165,95,254,252,112,62,100,237,167,234,181,238,164,135,224,175,19,225,82,153,135,122,209,81,59,123,165,21,127,99,54,56,18,153,226,205,161,95,202,7,79,126,124,92,208,244,46,5,176,227,206,200,16,140,97,250,131,187,54,34,117,52,52,206,150,201,200,182,45,201,225,80,46,100,113,199,193,12,116,224,253,59,85,244,248,161,239,199,164,208,63,114,103,163,167,185,246,203,19,33,102,53,236,108,3,205,170,155,230,73,204,142,178,233,7,187,171,191,137,254,60,149,218,98,40,42,87,10,3,146,207,162,67,113,25,173,141,27,217,143,225,97,164,2,208,116,57,181,180,112,233,183,114,62,110,197,29,79,155,213,7,115,94,60,229,43,83,79,119,171,196,20,78,239,233,51,87,6,32,5,59,166,121,176,193,0,2,145,150,183,130,7,36,179,159,57,212,66,179,111,151,174,27,202,58,35,12,121,174,29,17,69,244,46,87,1,173,238,194,40,107,180,147,157,209,184,241,104,251,123,242,164,42,31,93,118,82,79,189,47,105,102,158,30,210,164,16,47,140,226,212,235,70,176,78,30,247,193,162,137,19,102,181,9,248,156,29,149,41,73,2,34,88,183,198,106,254,34,124,19,150,32,99,71,253,14,190,121,107,200,168,38,114,205,153,112,139,204,16,149,101,168,127,70,40,156,157,78,179,113,220,4,46,194,124,96,187,139,83,36,28,169,50,209,88,176,134,217,219,55,18,186,165,170,11,175,60,216,24,132,95,218,101,75,194,66,64,184,1,56,29,86,92,86,243,122,204,124,185,21,219,37,111,68,82,178,41,69,127,186,121,223,219,84,41,169,105,54,165,5,128,102,12,67,130,217,46,97,233,254,216,57,121,145,39,46,34,136,82,175,114,153,215,16,119,138,116,45,137,136,230,59,132,221,97,0,150,250,153,211,18,141,254,212,157,9,45,217,191,16,24,133,130,194,151,189,230,92,187,55,12,247,187,8,115,13,29,222,207,59,92,230,24,146,39,165,2,54,188,107,162,190,178,185,22,188,187,172,42,164,239,225,92,55,26,237,230,59,0,75,13,33,47,250,12,161,72,4,185,159,244,163,208,129,102,176,239,178,99,211,97,92,241,234,19,85,70,42,189,55,130,151,119,38,50,126,239,231,40,153,124,51,220,63,234,208,163,211,170,63,37,231,40,152,183,204,90,227,246,208,8,196,85,209,243,92,102,174,199,27,110,145,27,1,158,35,176,107,152,163,227,75,21,184,120,238,57,155,201,3,194,165,57,117,211,136,236,17,128,98,177,93,111,46,94,137,155,5,70,101,212,42,190,79,218,62,143,123,151,171,59,185,175,9,185,245,254,235,130,177,69,252,61,157,29,229,105,128,229,192,180,37,158,214,254,13,129,64,53,209,247,56,140,241,97,250,119,174,250,204,68,97,184,208,29,20,117,25,12,105,234,224,76,223,115,197,177,7,235,247,19,42,20,85,78,15,81,181,192,153,4,160,176,82,106,67,212,194,132,240,190,45,126,79,192,122,42,28,239,165,14,139,14,152,62,129,78,48,66,45,207,97,240,165,178,129,234,169,234,59,12,218,46,249,54,76,20,225,254,11,128,237,242,61,101,16,36,207,202,13,244,205,77,104,204,51,50,1,5,95,211,151,110,251,255,185,191,151,167,102,140,98,163,129,27,38,60,101,197,176,252,212,232,136,208,157,118,51,83,111,209,188,223,78,130,47,24,91,236,170,159,121,55,3,202,0,155,212,180,173,74,37,161,201,91,108,166,174,27,239,60,20,65,158,225,185,85,89,127,76,244,27,86,150,160,201,13,106,79,143,68,200,236,55,107,243,76,149,215,188,118,183,198,159,26,140,136,153,211,173,159,16,57,139,31,93,149,70,6,141,53,112,164,6,184,239,106,159,222,67,158,26,121,136,223,39,46,140,67,170,202,95,88,179,214,186,212,140,8,12,94,34,77,226,17,17,162,210,225,20,151,177,74,9,100,126,170,73,142,33,144,154,131,151,205,235,28,118,190,6,137,98,50,237,7,94,230,246,133,250,179,160,199,89,103,9,203,111,37,216,185,171,40,117,6,107,87,133,165,172,22,140,220,186,41,97,187,57,196,102,220,15,169,194,254,170,33,237,69,78,127,4,30,119,51,251,153,50,179,106,153,232,131,96,100,243,32,78,78,223,191,150,158,39,30,201,43,12,220,233,103,223,247,156,210,213,52,75,203,102,114,46,35,81,55,175,89,207,53,66,198,247,164,132,51,64,124,120,125,108,35,3,184,185,202,162,122,93,58,198,11,176,146,221,62,6,92,250,135,230,38,135,125,76,89,22,140,243,110,14,212,252,94,85,234,86,142,168,158,28,94,124,183,180,213,174,80,170,142,88,83,48,201,169,249,109,156,83,4,161,186,46,235,85,83,86,244,7,52,58,188,19,124,117,35,105,13,185,191,47,252,142,77,194,147,27,235,193,126,138,65,32,134,118,24,227,33,219,142,48,59,235,147,8,183,94,74,184,233,4,78,44,55,20,167,190,216,145,187,105,253,135,93,68,15,204,76,81,176,255,140,229,106,248,29,154,109,79,247,240,181,62,181,2,28,187,26,136,254,180,92,158,140,81,194,11,245,237,48,28,57,112,87,48,233,185,13,251,113,29,199,152,222,226,254,232,119,199,120,251,113,224,226,89,162,215,74,115,227,118,145,197,176,156,161,226,233,79,170,203,163,113,106,144,108,25,85,163,91,129,143,75,216,56,51,156,13,106,116,79,121,79,152,139,128,156,169,174,94,228,172,49,115,235,134,42,145,67,107,214,122,8,49,156,210,218,178,151,67,247,169,0,56,164,44,222,132,125,193,90,153,10,15,29,69,159,229,98,193,181,138,65,215,14,65,89,116,209,247,174,22,72,27,141,214,94,36,169,203,34,123,25,192,248,196,238,148,225,225,253,59,44,43,96,2,26,21,96,123,202,184,253,55,162,172,81,29,95,172,11,133,235,129,224,183,94,71,85,29,23,65,246,242,222,224,109,136,62,63,145,107,248,167,160,195,242,204,135,237,253,107,53,91,77,34,207,186,102,102,84,28,14,44,194,39,232,156,245,132,232,76,102,63,206,240,49,132,118,211,1,70,75,30,42,3,149,207,174,223,160,227,64,221,207,62,64,74,186,97,163,201,85,231,33,84,76,132,47,66,189,73,137,21,77,184,234,168,231,171,247,76,32,229,1,138,186,116,5,60,65,8,57,133,57,165,125,190,51,105,242,89,1,141,234,53,168,34,89,88,55,63,52,10,226,116,30,115,175,214,74,234,133,248,48,242,17,47,155,75,131,130,124,207,192,199,156,142,142,119,122,3,15,49,119,155,82,80,171,180,19,29,133,31,247,222,9,245,206,244,22,69,12,85,112,250,23,97,212,191,32,152,5,115,206,31,197,19,250,138,219,130,3,84,216,78,11,80,213,13,161,199,128,136,64,7,53,223,221,247,108,10,139,128,47,36,225,149,145,94,106,22,86,14,62,13,43,181,226,188,243,228,218,231,144,137,51,46,13,237,21,72,193,233,132,28,220,20,8,4,122,72,237,253,246,222,239,176,0,105,79,66,248,100,211,232,18,217,109,127,11,57,83,34,123,20,60,137,153,193,152,195,96,127,130,205,193,250,201,146,44,174,91,40,108,105,104,231,248,136,114,61,136,124,241,31,128,186,165,230,218,248,76,54,35,51,13,80,241,46,59,34,214,111,253,168,149,252,124,4,81,171,131,110,58,165,172,223,166,5,45,240,154,11,195,26,117,137,238,192,41,98,219,74,113,235,25,234,46,9,144,57,228,196,138,122,230,73,229,42,31,24,18,166,217,131,24,95,177,251,18,240,249,10,235,122,112,16,73,162,6,70,8,231,108,54,87,216,194,174,60,128,244,234,190,212,213,146,128,244,187,133,74,29,128,195,60,234,120,57,168,116,97,234,156,164,173,42,225,70,177,38,184,43,121,148,186,19,207,224,19,253,214,102,184,227,77,205,223,63,242,184,142,75,134,48,96,96,243,151,83,50,87,123,186,147,177,176,62,113,237,99,50,108,201,126,185,218,219,219,241,171,55,44,28,194,49,254,72,63,140,63,178,112,216,15,3,183,189,172,230,154,116,254,246,200,73,82,76,41,15,168,132,147,25,115,46,90,151,15,180,193,60,237,178,105,74,47,191,86,59,221,105,248,98,26,140,49,149,76,146,83,229,173,71,134,78,113,171,186,136,69,240,102,228,167,251,86,198,107,167,79,180,215,210,44,58,98,143,79,188,44,133,107,54,248,165,231,104,149,127,120,62,61,159,252,239,41,101,177,140,108,77,90,49,230,151,125,115,153,80,213,191,17,98,59,202,149,108,239,233,23,177,26,245,216,97,198,111,31,75,248,67,177,55,207,157,212,233,20,69,111,167,232,80,21,144,9,32,199,43,200,181,141,195,9,143,237,154,121,175,158,247,124,39,117,184,48,30,51,103,4,19,16,28,84,98,72,251,204,19,32,194,90,236,170,52,202,181,96,92,120,59,184,47,169,66,177,66,217,150,2,50,182,17,7,131,32,76,227,116,70,174,42,90,163,89,35,33,148,41,240,228,253,31,107,201,210,198,152,13,86,70,112,248,225,121,155,252,134,99,239,2,8,98,108,44,76,227,160,213,104,141,16,130,205,118,253,123,220,48,200,187,80,35,114,62,45,188,107,29,79,220,169,244,147,158,70,102,122,231,232,149,243,55,230,115,28,185,83,39,179,237,221,41,170,240,44,143,39,216,163,87,213,39,157,118,225,99,80,190,57,171,200,20,2,7,166,112,211,127,0,69,167,84,159,62,190,37,46,1,194,192,152,94,188,50,203,38,220,128,2,108,156,32,255,174,254,89,135,44,97,26,237,37,203,70,32,238,3,218,163,213,145,32,244,50,67,233,217,30,131,135,205,0,46,29,143,192,99,180,144,34,96,7,74,212,164,44,215,190,88,252,138,84,97,50,251,203,44,252,175,247,178,155,79,180,28,8,80,184,205,211,9,119,150,32,91,150,4,102,212,89,217,117,71,241,163,146,90,113,142,34,228,139,182,236,101,97,47,152,88,91,161,47,37,246,4,92,89,174,210,15,82,44,118,249,82,198,192,155,172,220,91,168,190,233,35,204,84,24,113,139,102,112,42,108,124,19,27,148,60,159,78,38,239,90,234,5,193,172,28,58,20,182,11,43,162,123,82,184,178,167,19,172,101,106,3,69,146,204,136,46,70,35,133,166,103,74,245,222,246,76,109,232,173,160,36,50,39,140,112,227,59,10,18,127,30,232,161,113,146,233,102,248,171,205,245,154,98,101,53,109,65,36,82,31,241,200,111,216,27,255,10,48,237,213,82,221,17,250,248,215,19,150,56,175,233,19,230,30,233,199,3,100,121,176,189,175,63,20,231,105,113,121,51,88,188,231,109,177,58,34,9,199,121,226,157,183,76,219,41,224,204,61,144,124,88,115,7,214,74,179,178,42,119,144,76,98,58,171,185,134,98,123,177,87,100,213,183,165,147,22,29,151,19,74,146,102,107,158,201,189,0,79,185,36,105,84,104,73,152,103,132,228,196,39,102,113,158,255,56,212,198,37,172,139,31,238,98,184,182,42,69,108,194,245,23,205,45,21,76,115,162,181,174,59,213,233,59,240,184,32,212,226,199,126,11,205,232,217,187,51,197,98,94,117,94,105,152,41,48,22,181,8,146,134,207,30,237,255,240,248,183,191,187,67,210,16,185,191,54,193,2,218,22,99,176,191,233,78,247,165,4,231,131,62,37,109,244,76,194,155,129,212,66,0,101,223,162,211,13,80,169,217,16,68,4,155,216,61,35,76,162,144,217,34,209,73,249,250,253,186,140,124,41,237,124,22,168,97,40,95,47,38,188,204,216,150,184,229,185,174,113,3,154,126,238,50,165,170,12,27,209,53,157,76,118,81,252,10,140,31,103,160,43,171,6,65,205,225,154,85,121,76,216,228,29,241,184,200,160,225,86,4,199,137,80,222,199,30,9,163,177,222,131,91,24,3,147,148,250,20,157,246,166,73,41,246,240,159,85,53,172,227,255,239,211,188,78,85,210,198,63,175,149,47,251,126,139,167,245,143,5,212,41,111,52,133,173,37,114,122,63,214,212,6,98,213,169,140,241,226,233,95,47,169,91,89,117,116,228,30,78,123,163,137,11,19,142,70,121,166,215,141,20,57,100,202,75,131,150,222,136,204,79,199,205,220,46,9,129,92,116,55,148,224,138,82,32,255,250,251,59,239,99,130,13,77,106,233,191,37,70,164,141,160,195,95,192,54,39,178,189,46,17,135,160,255,198,62,249,69,57,5,74,22,165,134,209,143,179,8,28,219,212,141,148,242,233,231,171,234,72,186,111,252,84,120,130,253,206,225,145,123,88,19,194,150,24,168,247,191,92,162,203,56,94,55,72,199,142,76,50,37,253,13,142,159,201,100,153,149,243,217,240,192,204,254,66,239,13,23,161,166,210,210,120,35,7,141,179,109,83,57,146,163,16,195,195,129,214,39,34,155,158,29,244,128,143,18,233,121,150,87,80,227,145,22,207,133,15,10,172,79,48,176,209,68,66,116,22,167,251,162,90,108,98,148,98,84,46,164,185,106,48,68,247,163,112,24,15,78,105,58,173,251,63,10,252,91,83,158,57,178,63,21,40,113,231,82,251,191,134,27,71,131,203,150,222,121,48,211,181,0,62,91,119,123,77,252,183,63,204,142,239,211,87,244,129,213,2,81,221,210,104,182,252,35,116,91,198,172,132,76,148,89,3,74,8,96,232,19,70,18,232,128,18,145,133,229,23,13,93,175,174,68,105,55,192,81,168,1,142,132,193,37,99,188,243,51,14,26,6,195,29,149,159,115,77,169,235,22,66,101,37,224,43,146,152,141,191,222,67,12,74,51,124,129,141,11,37,97,10,50,79,112,123,54,180,89,156,10,237,145,90,99,35,116,84,163,249,196,70,103,144,16,14,13,233,42,5,213,163,203,205,92,6,212,210,195,46,141,24,15,1,215,71,30,31,0,4,24,15,93,217,35,228,173,104,78,117,69,140,243,168,119,62,223,200,171,123,57,184,88,64,53,21,153,201,0,115,146,22,119,84,228,16,189,124,213,148,92,15,178,58,83,69,87,213,137,150,254,92,197,211,157,193,255,150,115,3,222,48,64,41,28,208,245,211,29,135,30,54,205,250,93,94,57,155,196,37,151,90,109,165,11,249,203,106,37,64,103,100,206,108,40,181,36,238,104,208,241,13,26,75,32,133,101,47,132,226,199,174,3,139,186,102,206,19,21,6,166,44,184,63,7,255,61,155,90,233,60,161,86,176,23,97,194,237,176,234,251,116,25,226,11,145,130,13,179,158,222,252,26,235,132,202,117,229,195,232,158,52,183,96,47,219,235,210,51,146,103,15,241,22,194,84,73,169,183,142,81,87,203,6,251,105,254,2,56,164,156,137,219,71,205,59,144,217,70,38,73,57,73,70,131,114,20,249,181,50,184,200,127,251,28,30,92,166,20,252,156,141,128,223,214,176,136,154,210,238,245,131,123,1,114,106,160,197,74,57,4,101,162,185,66,93,219,192,225,68,181,231,74,140,180,121,162,114,142,129,187,73,66,192,218,128,28,39,134,251,0,243,48,55,112,205,204,80,144,149,109,100,247,179,224,228,198,89,225,7,131,170,203,32,130,21,23,249,122,134,208,160,239,23,10,91,107,175,27,56,59,104,18,71,209,245,4,165,227,203,178,69,1,114,130,119,193,171,64,18,182,174,155,16,84,193,55,150,153,90,251,6,94,161,253,223,200,143,16,162,175,93,211,88,243,61,118,144,204,158,163,68,183,243,85,64,42,52,155,32,39,213,93,165,239,188,8,152,93,228,136,71,213,103,158,57,252,54,203,34,230,180,127,56,46,22,5,220,190,103,131,16,64,135,114,68,112,125,205,54,108,113,157,5,31,108,20,138,80,149,170,6,114,65,223,21,159,246,115,158,118,220,203,106,20,66,204,213,59,225,109,136,122,206,137,104,126,66,24,195,83,223,112,36,241,154,219,254,255,248,77,142,202,95,86,171,11,42,188,7,245,217,138,49,224,34,61,121,28,57,25,3,70,9,40,108,107,108,211,160,206,154,77,59,153,161,172,200,23,84,154,131,94,122,115,145,19,13,234,127,86,154,80,149,41,50,98,186,251,36,10,53,159,223,103,104,248,67,154,136,228,46,83,243,36,33,221,157,116,83,109,54,89,171,46,252,120,86,50,220,23,252,185,68,192,125,37,223,233,232,110,16,135,71,175,199,37,75,162,17,48,41,32,39,131,59,145,161,20,26,149,216,99,1,188,240,87,189,8,24,224,227,175,207,156,151,37,76,105,62,202,86,172,9,208,0,186,72,213,78,103,254,132,192,92,113,242,42,224,245,111,181,206,107,130,182,212,63,185,27,28,41,112,220,209,148,172,7,140,225,168,124,67,203,73,76,139,41,226,87,30,125,197,216,76,36,160,168,194,202,181,254,134,0,148,187,242,94,239,72,9,21,148,168,92,66,161,144,73,37,106,39,176,127,116,44,183,89,77,47,138,171,10,169,117,147,107,92,29,184,69,82,220,13,130,34,214,197,214,6,152,46,180,228,77,211,162,47,149,169,145,56,196,174,84,97,93,246,216,30,34,211,137,93,8,161,64,73,106,220,60,107,201,86,86,124,51,9,66,244,168,8,22,125,147,200,68,23,23,247,75,139,87,52,54,5,53,175,14,218,127,126,196,104,220,88,75,122,52,99,226,111,88,137,95,199,196,6,2,87,182,200,67,133,205,210,73,174,53,64,12,134,84,182,73,199,7,65,88,7,24,83,187,31,81,35,236,229,37,177,78,42,143,233,94,241,133,195,255,185,7,218,41,43,231,129,3,23,175,147,37,26,188,70,161,146,126,24,12,38,104,96,209,143,227,254,9,198,24,192,4,227,59,174,32,240,251,5,34,127,186,184,83,193,62,41,187,33,39,239,28,16,118,164,36,171,230,136,212,122,52,86,39,165,85,61,117,145,179,83,209,229,95,227,85,170,136,187,59,115,217,179,60,48,21,67,116,58,14,145,89,89,35,229,5,152,217,138,26,10,189,186,35,83,210,174,165,179,87,168,247,177,43,213,204,247,37,109,164,15,182,108,253,170,140,83,214,151,0,211,81,132,64,43,30,248,18,149,11,44,248,98,107,216,117,38,96,167,82,124,152,140,191,51,40,145,207,31,45,189,144,120,151,236,172,94,196,233,80,172,227,217,187,197,174,24,108,153,189,212,51,44,156,203,149,74,222,95,240,202,168,235,255,91,215,29,201,254,8,156,120,134,162,218,172,153,51,254,189,4,238,93,65,227,158,247,6,74,254,126,91,58,204,84,167,188,223,91,180,79,147,62,150,135,231,158,186,185,126,91,13,115,56,108,78,17,205,175,102,47,20,157,73,175,89,225,242,141,119,215,191,236,127,186,252,109,87,164,233,22,213,98,137,134,97,78,12,13,150,30,160,164,149,154,108,167,156,104,67,228,187,152,143,135,114,154,47,7,21,89,131,179,34,253,135,40,109,220,0,127,213,82,85,64,161,1,113,242,240,66,56,78,225,32,59,26,177,12,19,79,6,212,120,217,177,7,187,76,85,122,133,9,219,81,118,109,201,21,119,47,122,30,190,208,241,78,63,16,91,45,44,253,13,228,18,228,187,96,222,132,166,77,100,226,124,234,61,59,174,40,117,26,163,5,65,107,1,95,18,170,126,100,95,216,113,98,15,186,246,133,3,205,221,228,159,206,212,201,240,175,113,198,72,187,233,28,104,253,239,168,246,139,120,149,143,34,146,39,220,145,216,114,243,109,219,151,117,75,33,162,197,181,62,19,128,118,215,96,101,54,68,109,7,171,133,54,145,1,15,56,224,58,123,172,196,221,3,133,158,85,120,21,246,153,166,1,17,66,48,223,247,230,95,15,223,253,250,109,197,6,190,76,117,7,245,185,143,129,188,191,215,198,20,90,194,172,250,78,233,102,182,120,92,116,208,65,80,84,235,77,57,207,221,127,16,225,96,218,22,104,216,138,195,220,101,236,3,109,87,42,198,95,96,164,202,48,107,45,17,107,246,2,243,229,149,152,83,101,228,91,80,183,254,119,138,201,64,197,135,212,15,171,151,44,69,249,208,188,57,253,250,157,63,153,226,131,155,3,224,56,103,144,28,200,229,192,71,131,21,129,219,235,31,205,144,191,146,253,77,67,78,216,241,242,228,244,174,123,254,65,212,26,35,218,100,1,28,145,247,37,254,116,206,212,40,200,241,209,30,238,181,165,198,211,144,87,158,142,226,70,232,172,134,42,41,121,222,108,17,68,45,47,16,56,26,77,188,99,188,115,118,252,245,11,51,25,44,27,128,31,32,221,54,158,109,102,53,155,4,245,73,26,234,174,198,111,64,52,171,213,56,173,114,145,152,204,191,140,179,22,93,211,35,243,221,136,103,201,155,0,41,110,183,62,30,176,252,190,108,47,23,203,166,160,173,17,124,11,189,244,44,4,13,133,74,224,19,240,200,254,27,57,180,193,89,67,10,147,117,127,169,109,96,98,8,10,21,26,37,181,81,247,202,60,172,58,139,237,116,143,140,46,52,176,49,71,231,243,80,161,14,219,152,25,62,178,232,150,162,47,124,122,155,221,61,212,160,224,158,136,39,24,24,159,93,108,6,145,49,245,189,95,22,153,45,100,83,225,12,97,201,53,242,6,2,23,210,62,108,106,189,178,189,42,64,247,93,171,233,157,196,159,103,239,240,111,60,164,43,151,83,198,183,204,37,185,207,113,120,130,103,10,4,90,144,149,54,51,128,82,233,108,119,172,85,82,79,203,25,184,22,113,202,100,46,34,121,95,234,102,43,243,242,211,223,171,133,152,188,18,134,67,47,2,94,11,17,249,254,0,115,150,132,37,136,76,84,42,91,153,219,138,4,233,91,164,1,243,162,12,134,75,244,55,138,40,252,182,74,245,239,39,45,157,106,56,118,130,15,190,210,138,155,237,239,57,182,77,69,190,113,237,27,178,173,214,149,95,133,12,106,208,89,63,129,174,51,58,43,142,103,103,138,109,123,39,101,45,171,1,233,54,34,208,63,121,151,241,39,0,207,133,172,100,150,134,5,196,133,184,171,253,201,139,186,75,242,123,53,174,38,249,95,72,254,64,108,209,147,37,177,166,69,3,178,95,255,47,41,195,232,6,73,119,89,203,225,150,80,125,183,56,28,82,112,89,167,237,204,73,139,208,233,7,168,90,35,244,133,50,216,254,240,80,227,187,102,135,27,213,192,201,21,175,236,199,100,103,36,247,192,4,133,40,125,16,111,25,177,101,37,180,170,49,230,106,169,123,73,58,231,60,106,230,145,116,211,215,134,199,90,18,243,210,29,225,79,224,248,108,204,147,215,73,244,75,154,145,95,137,151,193,154,146,43,242,175,5,62,42,113,9,57,70,59,133,75,165,250,154,186,143,167,22,47,252,137,102,87,181,104,147,207,195,205,88,18,48,209,126,182,35,179,10,30,175,25,163,6,202,85,185,99,52,208,20,19,242,169,14,253,227,198,85,129,68,11,99,112,59,79,142,105,188,254,123,148,88,153,70,89,84,106,236,34,181,241,51,194,138,62,14,134,245,151,117,235,135,10,139,140,204,146,196,96,242,114,217,131,102,142,129,65,132,108,64,29,42,233,238,33,19,249,17,222,195,125,158,124,202,110,18,183,150,111,199,70,127,8,180,135,203,33,143,230,228,90,44,43,118,241,57,168,162,89,150,106,102,32,60,250,93,143,196,239,12,214,171,73,180,196,199,210,115,112,192,13,9,123,222,213,148,91,19,101,236,101,30,146,43,164,10,156,101,112,151,65,89,151,245,154,56,37,194,99,153,35,80,3,93,62,246,6,68,42,34,155,207,230,215,121,37,213,153,36,165,136,123,181,144,31,215,138,161,118,151,196,108,131,138,93,13,158,182,138,197,184,0,44,139,70,0,204,15,179,245,235,111,229,61,119,1,248,135,70,169,50,116,69,16,223,77,223,248,176,81,63,205,104,150,100,178,216,215,7,243,251,58,16,117,59,213,117,122,156,183,0,72,126,132,100,86,92,240,106,174,220,88,51,75,166,111,176,139,229,215,30,173,166,246,249,201,187,24,250,69,150,214,224,9,17,218,53,173,213,254,11,60,19,32,202,124,40,131,51,99,223,226,217,190,252,29,14,39,73,199,37,180,254,114,46,169,46,109,205,172,86,62,198,113,209,186,149,211,122,42,239,238,71,133,33,39,217,86,131,68,199,243,26,0,143,97,215,140,217,34,11,55,192,118,66,69,203,200,128,171,40,250,94,127,204,76,168,232,153,226,37,150,4,8,22,177,75,64,204,39,19,45,127,173,174,14,222,159,184,66,88,61,250,133,231,114,166,164,33,157,77,203,31,222,189,111,131,178,107,117,10,165,203,18,211,117,188,134,254,238,158,123,143,231,245,189,89,21,88,66,169,241,24,26,210,108,105,249,56,37,196,36,26,110,237,31,34,198,114,72,218,133,14,40,38,0,26,218,130,56,146,228,86,253,43,36,112,162,58,232,178,162,105,114,186,74,187,229,215,195,101,241,14,24,95,246,248,101,255,68,164,79,41,18,245,65,11,228,167,132,169,52,170,196,91,52,224,204,230,105,193,231,254,49,143,85,42,221,140,233,18,131,116,86,127,103,136,113,15,23,95,39,90,226,59,168,56,73,43,227,171,60,251,5,66,24,207,129,225,168,127,243,190,108,173,215,76,110,107,75,120,242,147,252,217,57,234,116,1,133,221,90,162,174,126,61,236,200,53,105,71,155,217,56,85,6,214,13,60,119,234,225,200,186,152,215,237,225,105,85,252,240,252,38,75,220,200,6,243,144,34,127,161,14,197,107,63,75,235,195,72,44,27,244,129,243,201,59,241,45,173,62,200,145,232,76,142,208,183,15,77,119,157,26,157,170,159,104,206,13,248,132,68,229,234,196,252,168,229,154,203,44,177,54,200,235,132,93,52,10,196,60,152,226,220,27,98,85,215,82,144,161,12,76,202,47,71,231,225,223,105,35,201,195,174,188,10,168,199,141,255,108,74,166,226,33,4,203,54,202,178,27,127,250,86,181,225,246,70,219,65,173,49,214,202,71,22,67,184,54,90,182,251,202,40,14,235,63,201,190,75,65,15,33,62,81,56,157,55,187,67,3,223,5,188,105,211,72,202,95,229,207,20,1,219,121,116,56,5,116,227,97,48,200,192,252,86,238,56,125,89,89,89,100,76,5,180,81,31,33,111,202,211,182,51,25,81,28,239,153,125,85,67,149,136,118,157,65,84,65,43,74,86,81,238,45,7,227,222,145,234,95,152,157,225,22,53,47,59,189,252,16,40,26,171,155,247,98,73,206,206,218,9,241,152,213,3,15,107,123,100,86,78,2,200,194,8,78,101,235,150,113,69,232,13,102,131,200,41,240,126,186,238,184,20,62,218,235,221,116,53,44,20,219,104,254,112,139,81,119,100,253,105,53,62,247,159,166,75,128,64,51,7,193,108,154,115,34,146,127,75,102,17,112,81,35,33,255,104,228,11,97,24,252,219,214,122,235,2,28,34,128,252,220,126,248,87,48,200,149,102,191,135,59,48,111,142,210,22,87,41,25,209,90,114,67,98,234,128,53,45,198,155,116,161,66,14,216,226,63,200,18,7,20,213,60,221,77,128,48,20,142,208,197,61,210,161,90,77,80,146,220,80,168,29,93,171,234,195,182,134,136,225,120,206,94,147,141,52,199,5,155,74,143,12,252,50,79,254,135,78,145,222,143,150,128,28,137,206,79,88,83,195,0,213,182,223,225,201,191,235,235,39,175,202,211,139,11,109,8,255,251,237,232,33,37,250,169,184,42,115,205,55,220,211,160,190,225,201,208,87,227,181,15,92,123,111,172,104,71,23,236,206,214,177,119,77,128,149,238,102,224,147,48,143,82,158,83,179,110,112,12,75,86,190,48,208,14,156,92,140,55,64,14,23,106,204,140,48,97,72,62,247,14,217,121,31,224,171,233,69,177,129,185,71,17,87,96,138,78,19,178,198,229,37,235,51,51,208,149,100,111,39,54,197,126,215,245,125,0,18,64,157,246,4,183,62,21,82,209,182,193,74,163,255,99,143,38,119,30,171,116,62,129,241,64,167,205,128,48,19,141,208,126,96,231,17,94,11,123,106,132,252,127,95,4,217,84,100,231,9,56,144,178,55,92,107,154,194,164,113,19,93,117,152,188,49,241,135,95,131,177,63,10,247,179,86,47,153,63,125,70,239,205,3,48,196,135,152,123,146,5,229,21,112,255,72,4,180,42,148,238,234,211,163,111,223,49,176,36,101,182,121,145,65,242,151,27,181,100,235,212,127,238,78,165,2,36,188,117,89,217,137,39,32,249,156,72,106,48,65,177,35,119,166,109,125,93,15,74,133,194,177,8,208,79,4,23,216,37,3,20,67,12,40,52,11,160,213,96,177,234,40,240,251,19,126,81,186,153,249,204,11,91,78,70,238,38,31,243,13,156,49,165,95,148,218,155,179,139,30,216,15,153,27,164,59,189,173,159,141,146,16,21,167,183,161,203,82,140,66,150,182,16,73,40,176,102,55,118,132,173,249,137,117,137,145,90,53,86,164,24,152,171,14,64,192,181,253,238,22,204,59,115,228,173,155,232,15,108,250,14,135,190,177,25,54,114,152,83,38,132,125,185,243,134,112,168,170,99,100,155,125,107,46,165,146,10,12,243,170,39,155,195,220,140,129,9,27,178,166,144,112,200,134,3,146,228,27,60,217,251,147,93,72,56,196,158,217,177,53,113,146,111,93,172,7,71,165,196,105,120,164,255,79,158,235,183,45,61,139,128,87,87,24,202,89,236,50,129,135,90,217,225,115,211,102,32,22,124,87,167,76,209,47,193,179,5,176,1,172,115,53,235,4,198,69,17,146,1,156,60,169,171,3,154,137,1,8,160,180,39,33,145,194,221,167,74,225,147,22,226,175,161,190,155,99,104,36,234,28,206,255,153,106,146,140,248,208,160,159,129,189,81,79,151,34,57,191,19,60,238,132,173,126,112,102,40,167,236,248,169,15,165,62,167,248,117,241,242,52,190,179,82,62,174,253,135,166,242,116,101,164,25,44,212,205,199,182,51,26,85,54,11,16,243,103,183,145,84,222,115,193,84,191,14,243,49,214,76,187,20,39,29,243,173,156,181,219,109,64,24,75,52,179,28,160,231,99,85,33,44,165,96,91,1,116,151,203,247,43,74,128,179,172,198,31,77,89,11,160,120,13,159,140,72,217,110,79,78,206,233,178,98,50,152,74,216,73,133,249,217,70,75,56,129,241,107,234,100,37,103,60,16,188,2,190,11,70,104,226,153,93,247,153,143,161,19,20,220,168,207,59,231,145,117,83,136,104,18,107,25,84,26,105,116,169,98,24,122,32,236,228,193,206,223,235,29,238,49,143,225,2,196,58,61,127,140,102,14,140,100,86,158,130,245,106,213,21,195,130,77,170,38,87,189,28,239,43,9,141,221,172,71,101,23,117,196,97,176,152,245,228,11,197,252,84,206,70,36,202,196,205,27,80,137,39,25,75,180,73,162,224,150,97,44,115,24,151,153,239,190,250,64,81,124,193,49,199,158,225,239,216,251,150,194,11,43,136,66,171,93,122,163,101,50,248,76,30,251,201,114,80,75,69,109,212,155,11,141,217,118,95,15,127,174,149,147,216,251,178,89,253,92,51,157,16,128,60,144,26,219,47,131,125,182,76,241,164,209,6,26,7,92,85,220,173,245,230,208,98,209,124,70,173,192,190,132,55,211,201,186,183,60,108,73,202,134,11,25,98,22,219,173,173,140,39,222,243,91,17,177,81,168,144,244,94,105,34,211,227,16,134,9,254,20,51,4,182,243,203,82,63,238,89,246,230,147,185,200,52,129,113,141,167,177,99,18,247,119,52,84,13,203,187,89,98,35,178,30,13,149,205,77,136,197,164,183,202,225,132,158,34,253,166,180,170,81,56,53,16,116,34,149,120,212,66,17,226,5,193,175,148,81,251,230,23,177,141,43,79,103,153,84,172,51,44,242,34,237,188,74,225,118,144,129,40,56,96,157,254,134,231,14,209,110,23,26,41,253,29,33,247,80,149,196,100,34,23,183,198,124,246,191,174,56,254,31,119,127,229,154,236,190,38,98,101,91,126,182,201,156,27,210,62,101,17,18,95,17,62,112,173,218,95,8,203,29,169,3,23,137,111,219,234,54,156,50,148,31,227,60,56,205,74,105,149,45,57,162,39,83,232,38,150,169,204,161,15,212,82,220,124,196,127,1,123,135,186,208,13,210,224,127,223,143,131,107,123,201,10,21,58,99,135,64,212,81,242,174,16,20,198,65,72,42,58,79,59,206,26,52,133,57,223,232,6,119,87,13,47,214,82,42,153,242,77,203,163,205,22,188,0,129,78,179,114,86,63,119,183,248,180,74,200,49,174,239,118,170,130,129,69,61,251,182,192,219,239,214,192,255,58,247,26,49,105,232,74,79,103,145,214,114,231,134,233,230,182,242,244,118,246,117,136,107,207,19,107,184,247,251,123,157,189,96,101,189,162,223,179,99,10,86,165,128,163,231,16,244,57,68,233,20,250,104,28,166,38,49,110,177,66,17,127,187,199,42,122,137,238,193,107,95,247,227,189,113,10,75,176,213,70,136,141,144,164,87,37,42,23,127,141,164,183,78,139,218,128,235,216,244,18,237,172,200,24,113,21,112,117,16,59,41,136,9,155,210,169,170,75,221,91,65,24,147,102,178,110,106,220,193,124,222,37,240,191,119,132,54,85,182,115,221,35,234,48,168,174,45,235,227,126,189,190,94,228,240,101,211,112,91,127,57,151,48,255,55,129,17,139,254,252,80,114,75,182,22,51,188,91,109,69,192,230,36,179,138,232,162,3,131,1,137,52,56,241,139,77,224,236,177,175,210,192,80,187,135,105,224,116,81,229,132,151,223,232,67,207,191,76,55,255,26,58,42,239,48,161,0,251,40,166,214,231,173,40,122,99,165,8,170,84,14,152,38,0,60,172,198,70,127,95,75,16,127,6,6,164,64,141,172,238,59,222,131,224,43,38,141,127,96,100,62,2,30,34,180,54,230,3,150,5,231,193,31,96,61,201,7,121,144,136,49,68,114,1,180,193,165,67,117,98,92,230,45,153,167,120,227,39,220,201,40,218,176,242,79,255,176,197,84,44,219,188,24,123,109,252,180,10,54,56,205,152,158,23,34,226,122,114,118,86,190,135,145,210,139,53,111,80,254,12,33,99,114,50,69,174,102,63,40,134,203,163,241,201,210,132,197,30,194,21,41,67,111,169,59,137,176,140,87,223,35,219,148,41,17,47,87,132,177,195,184,155,62,44,57,51,61,166,176,0,78,17,239,248,132,24,90,111,0,114,11,243,116,156,217,62,172,237,169,184,102,49,203,132,170,173,228,19,92,247,110,129,213,51,246,166,189,117,14,122,133,32,168,49,250,110,109,130,233,47,207,247,73,245,53,4,163,18,37,68,143,96,159,144,46,41,170,94,167,114,150,192,69,209,251,219,13,111,213,186,98,240,94,100,151,249,137,215,40,31,202,233,102,233,87,154,45,180,231,125,239,156,180,218,112,223,97,62,42,141,65,252,126,67,80,247,250,233,208,232,35,192,160,163,194,226,126,10,45,236,6,185,108,216,204,37,163,11,79,111,48,215,146,155,158,134,141,203,55,89,61,222,33,78,82,125,74,58,124,11,39,39,25,125,19,251,109,165,69,192,6,62,4,243,172,60,180,97,171,114,245,37,98,216,173,83,172,42,223,203,123,98,129,233,163,55,50,102,117,207,223,131,8,155,151,246,17,163,194,153,249,69,72,100,93,139,51,97,70,143,174,24,21,44,73,67,97,203,26,232,224,113,226,185,74,242,203,51,164,179,209,188,168,1,102,93,74,120,214,135,191,193,209,7,112,218,199,145,10,92,23,239,226,242,205,187,159,126,171,125,35,158,53,118,74,19,183,224,31,116,118,13,32,211,205,92,131,123,48,181,32,124,7,233,247,254,24,251,109,189,0,184,187,80,73,194,94,100,239,81,170,145,20,235,132,230,56,141,90,22,151,198,88,153,66,134,20,94,237,62,58,110,218,255,50,111,198,109,211,202,21,39,7,30,238,147,85,35,154,58,236,112,221,70,102,211,120,115,74,109,188,70,229,214,191,122,134,120,195,231,217,122,35,113,9,110,154,50,82,32,35,111,159,191,205,52,223,124,250,77,32,228,68,131,215,255,245,107,10,80,105,104,31,4,173,207,219,31,219,171,182,182,254,211,181,183,202,185,238,165,167,38,248,72,193,90,249,154,165,80,64,209,68,160,49,226,93,135,143,48,97,211,47,187,29,120,160,203,115,39,87,245,227,220,244,5,60,57,251,126,42,117,244,81,69,98,77,242,210,249,188,19,130,253,198,56,95,174,249,187,185,215,132,16,226,25,29,180,25,54,143,69,121,134,79,117,180,218,210,211,236,58,207,231,69,104,95,149,166,212,59,105,131,68,83,21,233,177,143,135,83,237,99,3,20,58,123,234,249,128,199,117,238,163,124,52,215,100,124,76,146,61,253,192,135,196,87,201,115,149,98,141,214,85,252,207,188,13,34,208,166,93,132,22,39,44,115,121,203,93,78,137,69,196,253,197,120,148,36,21,208,5,95,43,5,122,145,41,160,12,117,201,143,36,62,133,73,185,73,185,155,194,182,166,248,96,33,9,112,7,42,39,42,203,253,23,196,161,187,66,234,58,217,44,48,7,139,47,158,58,153,179,83,189,27,100,164,156,234,199,98,117,100,38,11,24,163,169,221,244,159,173,191,177,229,194,60,25,229,142,239,38,104,95,145,238,47,214,188,90,21,66,126,66,111,210,228,101,36,242,172,130,97,234,90,20,62,166,38,11,198,159,44,245,249,131,27,135,234,87,83,2,62,185,253,129,60,125,165,26,164,138,148,193,87,246,201,45,72,3,33,31,191,29,45,33,15,238,109,8,39,100,38,195,128,83,7,133,205,161,144,113,161,194,75,111,13,7,188,92,227,251,80,96,18,64,26,145,25,40,183,204,243,127,122,119,214,146,16,231,175,187,101,92,23,25,172,45,195,139,252,212,135,73,86,24,33,203,30,64,143,202,39,238,180,143,39,141,32,30,65,76,186,57,211,14,143,45,98,183,16,106,103,221,249,6,53,137,24,139,142,183,198,247,95,139,222,54,254,33,32,110,206,70,243,213,3,192,199,172,149,164,83,182,93,148,177,50,21,141,173,13,238,107,195,127,67,110,37,112,43,142,183,230,190,209,160,162,156,23,27,134,24,34,52,140,72,249,61,178,169,148,8,130,66,147,91,31,208,121,252,240,86,4,49,94,172,145,170,231,175,155,91,81,34,65,35,19,119,54,89,16,204,192,75,121,73,147,188,144,117,13,228,38,41,170,216,212,138,219,190,30,66,160,168,25,44,46,139,91,239,138,252,75,214,254,70,38,167,102,27,83,199,3,87,193,132,173,198,46,20,126,199,149,77,169,28,80,101,104,137,62,96,184,186,195,156,232,54,165,152,181,234,109,221,187,146,210,235,81,120,213,202,4,54,76,73,143,91,58,186,245,234,169,42,230,22,18,250,90,107,166,223,111,105,64,154,164,4,224,90,136,137,59,115,161,111,33,203,195,109,85,228,153,230,42,60,71,72,5,2,62,18,247,95,210,226,191,18,86,215,250,188,187,220,235,252,237,222,248,38,43,49,68,167,200,78,234,221,147,5,179,21,224,63,87,13,134,86,163,63,36,111,99,183,191,107,252,17,109,125,244,237,227,124,248,96,249,123,151,124,55,89,15,60,83,228,51,167,78,178,149,160,185,115,84,80,74,205,223,140,130,90,11,7,178,123,40,235,140,10,228,159,27,22,21,27,35,97,198,101,3,45,152,101,159,133,198,240,50,167,96,88,76,87,206,44,39,249,11,105,101,233,91,94,0,117,182,228,62,63,40,7,175,93,108,94,109,10,13,105,155,235,242,84,115,42,225,207,146,64,214,155,15,160,204,116,101,205,129,106,90,130,161,1,205,66,106,134,110,197,2,121,251,255,76,57,17,131,177,22,249,53,191,239,3,209,175,23,202,194,236,120,82,27,150,175,201,140,218,92,66,6,242,27,242,72,21,153,249,76,147,161,201,108,133,37,82,63,157,26,16,157,157,53,227,144,45,33,251,159,166,102,14,146,8,130,61,71,232,239,55,149,154,94,62,201,196,46,66,64,182,197,173,177,174,129,184,239,93,144,26,35,78,229,198,0,35,11,0,24,58,31,116,17,14,148,173,217,199,57,30,154,70,63,65,205,96,139,15,161,221,167,15,248,53,144,210,247,198,28,89,183,77,185,161,137,46,60,33,250,124,201,6,162,14,149,173,139,246,183,196,97,174,62,140,41,85,124,32,241,157,180,188,116,43,88,101,206,143,162,87,136,175,53,8,137,29,26,223,233,139,150,187,232,66,160,175,236,60,249,74,124,88,0,169,71,249,158,190,158,10,136,161,14,192,129,205,123,206,139,139,194,116,10,232,178,229,135,29,133,175,175,159,206,251,200,116,49,111,179,231,204,59,114,82,198,44,18,188,92,104,214,214,0,99,131,131,20,13,139,95,163,166,89,240,125,147,162,92,27,236,208,194,108,76,213,90,135,100,0,183,53,71,191,95,49,61,227,177,149,62,19,73,102,79,254,208,162,75,217,114,173,130,116,114,179,103,102,51,151,84,216,208,210,52,137,180,99,72,124,128,249,247,136,183,36,28,249,242,125,70,239,231,22,75,183,222,194,216,180,98,166,182,159,27,186,214,74,253,234,220,112,80,103,58,215,113,70,28,68,149,92,181,110,119,67,179,179,9,96,140,249,194,72,173,244,144,58,9,141,246,68,237,118,179,124,164,96,125,30,196,126,104,19,176,107,25,7,162,89,236,206,184,139,167,166,16,55,67,7,93,251,90,252,86,252,171,140,238,114,28,106,253,2,64,26,18,192,199,145,70,224,41,158,81,211,254,47,235,74,231,215,176,97,187,165,209,79,109,189,21,14,209,97,193,29,254,42,24,157,72,5,143,9,214,54,90,86,243,143,140,12,163,2,158,213,69,48,232,80,165,123,73,197,247,8,241,232,198,127,142,153,236,153,145,20,27,64,72,56,14,13,147,102,116,211,20,44,176,108,13,229,36,230,81,206,9,197,5,42,177,137,125,239,52,138,145,92,76,16,223,134,138,221,234,177,91,177,210,67,1,151,117,176,201,125,211,227,144,217,180,31,53,97,31,147,33,222,114,225,63,236,245,62,68,54,30,147,134,96,110,84,124,209,201,141,3,62,115,79,24,228,194,3,74,218,184,3,66,224,170,40,123,37,121,61,129,54,53,103,197,43,89,135,6,26,104,193,193,136,152,56,142,183,224,128,35,138,123,231,218,184,64,116,133,134,79,71,93,163,18,65,127,217,137,72,42,147,44,193,117,255,58,201,221,139,83,224,169,171,21,200,243,196,43,229,12,27,96,110,87,50,136,174,144,220,236,35,210,9,136,71,10,14,95,205,206,230,46,210,240,140,197,31,1,18,188,0,238,15,228,67,49,220,86,132,126,70,124,204,88,118,84,251,214,36,171,200,70,160,93,190,20,193,149,122,208,201,60,231,13,227,143,217,98,120,101,241,47,166,37,0,246,166,53,179,69,210,170,111,102,237,39,29,58,140,90,17,30,66,50,240,135,134,156,130,216,158,96,227,238,43,173,150,62,156,252,12,213,121,200,99,178,38,253,248,51,29,232,51,139,88,26,160,174,235,4,96,47,68,39,65,224,118,4,246,129,110,151,23,33,196,101,107,18,57,33,181,138,239,175,105,157,49,247,51,175,4,49,223,166,210,239,121,16,164,212,230,198,33,63,150,165,9,54,147,43,215,241,224,55,27,106,204,89,39,184,161,80,49,4,115,240,147,14,244,80,211,157,188,47,240,27,232,175,82,215,194,147,55,86,12,143,240,196,252,206,171,147,238,96,167,220,204,222,124,57,43,217,33,94,205,196,224,116,99,78,12,233,159,227,1,76,43,79,235,217,146,66,161,211,175,94,65,74,199,243,183,6,81,84,203,242,106,233,76,173,158,214,45,43,108,174,250,106,136,126,230,63,14,251,213,18,71,87,50,64,255,236,85,183,102,109,45,1,174,202,9,149,185,253,197,58,210,45,138,136,51,85,221,138,73,184,106,127,134,253,72,58,18,180,62,151,29,82,139,220,202,116,64,248,20,81,96,109,47,138,242,186,193,36,58,228,83,194,172,38,0,252,218,244,10,112,115,142,57,210,57,11,64,200,229,159,61,193,101,132,118,218,80,148,208,24,56,50,42,216,65,221,198,222,42,94,40,195,189,60,175,28,71,25,114,164,42,45,8,67,46,142,204,238,25,167,37,150,221,46,11,216,39,161,104,150,116,113,1,94,67,6,9,155,180,85,217,5,244,160,99,51,203,177,93,136,13,60,29,150,143,141,45,240,202,86,52,252,208,169,251,4,6,159,54,129,123,18,109,207,1,191,79,38,187,105,43,96,244,160,246,58,53,1,126,98,82,106,12,250,65,44,103,65,155,146,190,0,201,249,32,20,57,171,220,149,156,114,51,66,148,220,137,156,113,120,32,169,126,124,13,130,177,138,31,55,46,148,240,128,29,71,141,116,145,112,8,66,189,190,216,123,114,164,94,213,103,242,213,46,100,240,150,169,179,251,110,47,164,50,174,245,163,245,59,14,243,8,35,82,74,151,19,130,70,32,129,139,54,14,190,35,131,230,71,44,133,253,187,52,219,118,239,235,58,76,31,196,252,32,242,187,197,157,187,55,29,121,51,214,250,24,234,46,96,133,232,102,63,43,191,186,226,113,189,64,205,186,249,119,43,113,194,61,250,58,221,69,191,75,14,152,187,167,243,108,156,124,46,5,218,175,243,118,7,240,85,167,144,192,213,61,210,252,162,165,162,46,86,124,240,63,149,35,88,159,198,71,207,56,140,25,144,133,248,190,191,241,252,13,124,234,108,165,9,106,44,119,178,102,193,221,168,140,143,125,102,211,106,41,163,241,103,12,131,227,10,78,64,224,131,209,128,108,224,131,81,196,188,208,57,0,65,7,171,245,92,68,97,155,26,19,0,220,173,153,62,182,16,55,19,229,89,135,80,157,145,162,168,60,3,54,77,8,252,62,78,45,97,13,187,5,95,233,221,143,244,218,237,9,191,191,111,230,19,235,185,24,229,133,236,211,127,22,70,243,186,237,63,6,52,140,155,111,172,124,143,130,20,198,240,17,48,164,10,74,221,17,240,102,82,73,186,66,214,132,28,226,189,253,197,216,71,13,102,76,54,192,250,157,250,97,33,169,125,119,76,18,127,148,89,55,79,41,27,171,173,241,40,25,242,210,152,51,104,129,66,79,162,178,205,127,78,159,148,90,244,237,62,200,220,157,71,215,30,45,95,17,166,151,2,107,156,25,214,202,113,205,64,70,182,24,9,62,176,176,190,16,176,188,96,117,242,77,22,88,50,108,118,138,246,209,82,199,143,160,77,201,121,197,140,194,143,8,181,195,45,95,221,40,139,214,14,153,166,70,195,180,165,102,177,227,237,193,79,231,55,66,91,102,116,212,200,47,182,152,106,44,255,140,122,66,158,160,250,117,112,5,28,227,9,101,161,115,43,75,216,160,129,201,85,4,155,212,168,94,163,160,204,9,102,25,233,102,160,184,227,106,238,100,129,31,84,122,126,254,145,223,210,150,80,172,229,177,248,245,3,169,238,5,16,2,78,51,54,207,82,72,227,99,136,26,105,129,53,22,17,45,214,181,195,68,36,56,169,195,242,5,8,191,67,154,4,98,246,26,112,153,140,77,237,240,2,154,115,169,245,170,100,202,110,18,149,98,123,104,24,71,192,232,157,222,215,83,47,36,18,129,246,103,237,227,185,218,144,30,199,136,151,160,138,100,74,32,166,208,86,67,75,237,132,120,166,153,52,64,10,225,171,2,81,131,86,59,191,48,93,62,184,125,186,164,181,232,91,66,146,242,21,173,53,43,188,74,248,215,108,185,224,167,76,81,71,206,93,12,235,166,22,241,224,190,133,235,131,111,103,60,230,112,49,52,171,86,194,94,59,123,115,191,87,69,241,194,32,229,82,37,247,66,83,202,39,30,54,213,89,3,78,249,44,22,248,167,57,0,84,189,32,168,147,103,6,140,148,202,187,193,37,38,180,46,29,166,57,72,223,230,106,44,108,111,251,141,251,89,7,111,191,116,203,52,57,144,49,241,196,170,155,145,94,130,81,6,8,48,239,173,230,55,130,69,187,163,225,66,214,151,106,237,182,124,152,252,164,152,71,188,138,18,156,234,158,96,75,48,112,107,71,163,19,180,198,24,225,112,151,114,89,6,217,49,26,232,78,138,51,90,69,91,193,126,130,54,20,217,158,121,249,61,85,203,2,97,83,109,237,170,254,0,91,197,122,244,126,45,233,234,109,127,179,19,219,93,31,65,76,94,19,176,192,62,20,225,161,144,181,212,117,211,254,177,20,119,165,4,191,21,105,172,116,103,36,198,101,166,240,111,212,21,87,239,249,26,153,242,52,76,142,34,251,237,81,66,187,57,122,29,236,37,110,21,148,230,218,247,104,63,1,234,5,69,199,73,134,157,172,42,231,147,224,75,141,129,211,82,4,89,195,246,70,171,181,93,183,55,108,159,166,33,84,4,185,111,204,210,203,121,247,47,11,38,196,128,175,73,224,158,13,7,251,219,162,20,164,80,64,199,241,117,6,96,69,101,173,208,37,165,211,107,165,193,43,31,159,138,214,247,2,33,12,191,208,158,105,240,17,229,141,41,237,45,38,45,115,88,232,28,191,188,150,228,13,47,17,235,94,149,41,105,96,203,124,26,222,106,9,189,50,92,15,120,136,57,57,255,99,51,112,155,217,186,209,181,137,48,198,43,39,230,86,230,26,217,240,223,93,238,195,80,220,79,238,160,255,161,52,146,25,191,179,0,106,203,39,179,207,46,133,153,151,239,88,57,122,189,135,89,178,115,230,216,10,114,143,251,93,168,61,169,202,150,202,196,237,75,49,182,183,125,110,19,34,1,136,14,89,81,155,227,118,201,69,250,152,109,216,132,250,88,147,48,2,191,100,195,211,13,126,162,119,72,133,229,123,207,22,23,212,210,63,155,150,227,57,166,222,129,67,70,42,85,154,245,247,41,193,230,95,156,113,40,103,226,86,19,6,181,49,124,103,224,189,223,33,119,236,24,20,229,68,141,154,5,89,177,163,212,125,152,33,38,48,226,24,141,151,158,51,86,207,22,139,80,172,113,125,82,37,229,71,24,29,22,151,195,95,177,29,49,74,158,121,217,68,52,92,168,158,88,196,251,22,3,155,79,122,252,156,221,200,181,70,100,216,71,156,175,156,86,2,231,130,108,43,211,119,75,181,114,163,95,222,24,246,255,186,183,186,101,37,137,223,53,194,47,117,58,55,235,209,179,14,167,242,26,134,221,36,193,38,118,184,207,96,67,32,145,250,154,128,94,25,66,185,48,57,213,130,222,58,197,173,252,78,101,199,141,206,155,94,81,157,155,216,239,200,168,141,203,59,210,55,17,55,170,5,110,70,51,20,19,17,219,187,198,121,220,48,135,101,52,185,215,244,4,37,229,220,138,211,126,144,244,210,14,194,134,9,176,26,52,128,5,94,173,63,199,171,196,37,142,16,185,13,98,224,38,105,153,24,182,124,179,35,177,69,226,224,127,75,236,2,98,7,44,185,3,14,107,156,129,152,51,36,29,203,211,203,108,162,74,162,216,89,12,128,9,112,14,157,147,3,227,248,177,51,228,239,231,213,231,254,82,42,244,137,106,99,170,156,192,66,71,139,213,5,156,125,195,124,229,130,190,205,89,225,241,254,176,95,30,219,40,248,129,218,116,222,75,183,241,249,60,88,178,52,92,157,156,113,232,162,36,107,47,55,17,155,162,70,224,125,82,84,211,203,26,49,246,193,94,207,161,122,216,126,138,16,206,87,28,38,45,30,196,186,30,68,206,95,156,208,218,236,93,107,125,217,121,46,223,4,69,183,46,238,206,71,72,167,159,167,48,118,25,0,159,147,140,99,166,172,4,113,21,161,52,102,54,219,194,90,106,50,6,156,202,21,86,112,33,45,53,6,124,162,83,226,178,246,1,165,167,177,190,237,128,219,79,114,30,187,31,146,10,157,251,80,124,108,191,233,91,104,68,35,156,13,54,123,191,37,77,245,82,222,206,8,246,133,27,217,87,116,7,145,65,128,81,142,250,19,137,207,10,217,88,150,119,183,30,231,123,9,189,145,113,150,247,204,148,101,142,228,144,127,101,122,157,153,221,45,112,44,139,13,223,94,18,221,245,14,185,252,132,117,15,173,122,121,1,251,109,2,107,25,97,29,180,199,11,124,161,138,37,92,119,254,245,118,34,128,28,100,200,80,5,114,99,208,232,126,215,247,226,193,129,111,229,166,12,107,30,67,118,84,156,100,158,204,44,28,118,134,227,10,22,153,126,77,13,134,137,18,167,115,62,98,60,182,179,66,109,93,146,39,135,247,137,193,45,175,156,83,87,217,63,250,57,154,128,151,152,45,35,43,126,198,229,219,126,200,145,4,236,251,153,196,162,89,73,134,96,119,107,128,190,147,228,64,73,220,100,124,73,203,91,213,77,92,68,50,107,69,237,110,138,228,193,175,162,213,78,39,118,105,39,11,196,157,25,195,35,53,250,121,123,219,197,179,143,206,30,210,251,106,231,243,37,84,55,23,7,30,84,11,121,92,53,9,191,28,49,57,237,112,78,183,12,215,243,99,159,238,14,246,197,136,207,69,0,120,99,89,37,184,54,94,128,204,224,174,118,50,226,59,151,162,115,167,144,223,213,199,4,87,55,193,10,212,169,238,242,254,70,213,252,87,32,245,18,157,79,122,232,143,103,31,93,140,93,243,91,156,91,223,136,12,68,98,200,179,170,185,195,112,27,104,3,205,165,28,186,174,118,57,189,119,144,158,95,158,164,143,139,58,87,217,43,22,68,43,126,240,70,94,163,225,233,248,227,168,70,198,16,51,205,239,192,4,124,244,190,80,130,188,253,65,63,201,98,243,142,139,238,115,52,164,188,234,11,203,33,66,111,40,174,113,78,139,135,102,209,122,166,53,10,2,10,140,215,139,223,100,11,23,208,126,65,214,52,37,98,93,37,250,159,75,209,155,248,86,107,5,114,199,254,105,179,240,132,18,228,65,136,188,180,168,141,149,43,234,13,114,25,92,32,8,212,172,186,194,234,241,77,20,142,76,140,225,110,176,248,93,52,69,8,47,143,25,99,166,56,37,228,218,183,234,205,236,237,168,228,136,179,145,123,254,230,182,37,220,223,96,199,45,24,147,73,86,254,47,90,124,89,129,192,199,167,216,217,62,148,163,46,107,74,67,155,206,30,163,44,42,238,69,77,5,86,126,151,131,136,59,134,63,72,23,50,35,228,75,48,172,147,4,200,35,217,142,56,51,159,145,237,51,218,27,192,43,193,90,63,194,218,149,77,69,58,68,24,177,235,144,245,52,41,241,21,63,202,204,123,60,245,245,147,59,230,53,58,179,177,6,108,72,142,101,202,171,147,1,238,27,183,145,157,7,29,13,111,137,129,183,185,196,139,126,204,48,220,237,170,227,65,153,226,170,245,241,69,250,74,235,39,129,115,94,113,165,212,140,219,239,255,30,2,150,71,167,222,250,123,230,253,102,110,67,175,23,73,166,0,144,47,148,163,151,221,23,81,24,247,230,191,244,11,1,206,112,51,40,182,33,40,163,61,107,169,167,6,202,202,72,255,23,102,172,225,38,148,226,88,109,43,255,21,145,157,184,0,241,95,26,253,89,42,53,13,149,184,8,74,173,119,80,63,39,122,131,186,46,224,96,135,125,146,230,186,215,105,91,230,163,169,125,167,150,59,214,137,125,94,22,30,51,110,143,175,201,170,44,185,136,253,28,105,89,77,41,65,135,12,60,237,170,191,75,127,88,149,34,205,123,6,139,121,217,249,166,254,165,197,104,144,84,48,58,172,21,122,128,85,199,148,36,114,91,239,123,1,206,8,169,49,206,39,142,97,137,189,224,169,198,119,13,171,201,140,49,157,103,118,88,94,210,27,126,242,245,68,55,25,204,114,244,247,64,29,145,137,154,56,172,22,62,19,227,79,143,90,5,12,201,194,154,224,71,103,79,31,119,20,146,114,219,19,44,92,21,211,69,49,20,95,47,183,25,195,60,209,50,238,182,244,59,9,94,112,27,36,210,214,7,152,57,84,87,219,76,117,252,173,214,2,188,162,120,141,43,194,108,127,121,25,148,205,129,10,46,39,41,144,243,52,218,147,187,37,188,247,50,228,177,63,51,214,17,10,240,24,244,129,34,87,146,124,5,230,163,171,120,234,22,101,103,156,68,245,144,114,132,132,244,163,47,127,235,219,88,243,187,140,196,153,78,126,139,116,152,107,147,27,119,0,2,213,231,59,70,73,214,67,31,130,51,71,155,189,211,225,165,140,83,24,36,56,202,105,50,33,140,155,216,216,209,252,54,156,254,20,81,120,206,235,241,53,194,44,177,128,30,239,26,95,124,88,90,21,132,123,188,158,141,127,241,223,95,178,108,21,221,145,222,26,192,180,84,129,78,175,117,146,57,215,116,10,13,53,12,252,227,64,32,115,213,68,143,238,155,225,101,184,132,28,92,127,89,232,1,139,160,185,99,115,92,29,188,211,254,180,85,121,47,205,53,199,122,73,153,119,188,74,163,229,129,90,48,50,178,91,189,168,116,38,32,114,55,89,132,116,208,124,128,113,113,16,206,199,26,163,212,71,1,250,155,96,53,100,44,246,31,136,208,243,220,60,176,23,103,88,245,48,51,59,225,235,226,76,182,53,49,135,126,117,23,4,0,51,62,11,237,65,252,21,246,193,84,14,85,217,111,240,108,226,134,59,194,210,198,214,9,245,99,101,81,3,89,134,225,173,80,61,204,115,250,25,191,22,137,42,177,155,159,237,248,200,39,189,1,66,189,88,8,198,57,47,194,59,150,74,50,244,192,145,124,139,137,9,88,183,226,179,162,219,55,201,222,186,109,36,242,146,104,134,170,9,120,67,123,240,251,118,184,113,206,203,242,204,29,95,103,160,139,24,229,246,174,44,232,1,92,51,119,121,192,74,200,193,169,150,115,168,56,37,31,105,175,166,10,183,252,135,115,233,34,0,229,124,183,246,177,143,42,237,125,2,142,154,240,49,228,213,15,77,123,202,79,84,0,147,189,200,161,106,243,41,87,86,158,216,240,246,100,112,9,91,213,220,206,108,190,57,220,218,99,189,47,194,120,28,127,254,169,178,91,243,109,75,134,210,210,244,242,159,54,217,20,133,68,233,153,234,101,91,233,30,96,171,224,92,91,176,236,182,188,20,131,21,122,84,104,171,14,236,252,249,75,212,235,191,95,11,62,141,94,241,165,26,219,173,197,153,214,168,223,240,94,213,113,148,95,22,212,203,134,117,232,60,147,51,11,201,54,4,81,122,170,58,150,209,147,128,196,78,68,78,148,160,114,198,127,162,120,180,68,133,22,76,101,119,11,93,246,9,232,183,127,140,173,92,221,236,51,178,45,217,246,70,118,91,129,102,24,199,252,7,6,116,81,43,240,49,115,77,164,134,23,10,184,92,26,223,238,174,254,108,5,221,29,205,3,38,30,51,143,196,202,21,102,228,51,105,45,191,54,175,140,175,135,132,56,183,9,116,20,68,132,18,220,233,176,239,82,87,160,87,75,33,255,121,193,156,78,230,23,79,64,52,198,99,148,130,106,107,8,203,26,34,248,194,178,123,242,238,250,69,219,168,219,185,118,64,221,220,7,62,58,172,34,161,85,252,155,52,152,60,87,103,183,167,226,234,225,170,247,90,38,143,81,89,210,156,20,60,194,148,113,179,171,5,77,184,78,26,208,131,200,86,18,46,116,74,134,61,119,29,194,3,117,40,80,168,90,103,191,42,184,95,218,91,28,155,54,146,65,95,188,105,77,14,205,75,249,117,46,221,98,224,169,93,190,83,43,182,146,208,7,135,154,99,250,12,2,189,246,105,220,172,175,69,1,167,218,186,57,136,247,112,149,221,32,11,202,229,160,52,60,200,208,193,198,75,246,250,53,55,150,176,139,93,85,222,206,205,111,9,73,162,186,211,69,140,188,136,164,203,223,18,225,119,181,234,138,60,23,112,75,105,15,203,7,125,177,246,31,45,74,151,48,22,139,175,136,183,250,161,111,94,119,158,113,175,140,79,29,122,65,55,233,80,125,200,31,209,18,35,82,3,116,190,125,208,46,253,125,100,73,160,238,5,244,38,184,200,7,167,119,122,165,28,250,26,52,110,188,151,63,208,63,248,94,165,164,111,163,146,32,37,5,60,85,192,27,61,24,60,161,222,0,4,254,155,189,84,196,0,157,35,12,162,103,138,192,135,38,45,40,41,69,63,30,177,222,41,253,200,54,63,230,237,20,103,172,23,99,192,215,2,181,198,52,12,1,157,162,169,147,206,27,237,188,158,40,214,164,233,240,100,201,245,24,178,38,205,66,140,166,43,132,117,143,233,22,167,190,202,18,188,127,240,184,49,182,87,84,214,121,140,169,20,29,122,133,69,18,168,61,132,146,108,35,131,109,86,101,183,150,34,77,90,194,24,46,232,28,48,183,206,47,100,61,163,165,74,17,92,27,210,106,16,222,186,117,41,103,197,144,3,27,9,248,132,189,88,83,122,219,49,116,2,50,30,40,205,76,130,35,126,83,228,228,138,171,171,135,39,196,227,87,106,235,241,239,86,179,253,11,23,99,7,66,41,158,178,157,76,234,6,5,214,254,184,155,181,84,197,165,122,251,119,249,236,166,219,144,14,253,20,200,71,185,128,249,58,15,196,101,206,51,124,190,50,159,255,10,172,123,168,253,230,89,10,236,71,194,62,129,71,92,165,85,0,198,135,157,141,191,50,13,140,37,124,110,249,46,46,25,251,68,145,8,18,120,51,137,142,119,244,148,246,141,26,132,163,135,241,35,159,49,77,209,163,230,111,6,242,146,195,49,170,2,124,194,17,165,42,155,254,34,50,37,48,67,234,117,90,102,69,129,61,195,172,78,87,34,46,79,146,168,210,166,122,231,226,222,204,251,20,75,223,196,242,130,34,225,110,75,207,175,78,24,239,45,171,104,198,59,0,19,49,11,243,112,43,250,158,62,80,155,237,46,52,188,185,245,171,68,197,202,251,110,93,211,94,67,191,87,157,87,233,13,61,47,52,206,80,194,167,66,67,198,170,244,247,174,171,50,79,255,184,161,14,254,202,162,162,254,221,148,221,251,90,102,154,71,98,61,150,1,32,250,227,57,240,168,21,174,152,107,235,75,2,198,35,117,161,148,210,231,214,184,87,241,102,16,184,144,221,165,158,108,17,177,46,228,156,159,149,123,171,239,250,40,10,62,189,159,144,124,7,64,76,122,161,214,158,46,206,191,99,142,189,68,40,168,172,65,88,130,102,169,121,107,188,201,117,35,139,212,14,176,77,110,172,197,14,238,254,189,108,234,224,228,68,226,121,230,183,185,224,25,14,142,86,3,2,21,133,116,109,24,125,214,126,192,236,107,42,30,208,247,43,102,62,205,11,213,177,80,163,92,245,82,101,244,192,151,191,169,102,204,190,167,232,66,226,12,115,238,131,188,181,235,30,55,68,17,186,125,64,121,44,39,147,240,53,20,40,101,224,109,239,226,32,115,253,200,113,202,118,207,81,168,138,146,224,129,38,168,181,120,87,225,170,24,6,223,254,59,48,103,66,191,112,18,100,232,149,121,191,132,39,231,12,223,111,202,150,238,150,76,143,41,37,183,222,8,16,24,33,99,101,144,218,10,68,70,133,97,95,109,42,67,13,102,0,93,189,206,41,149,160,206,101,195,209,76,22,231,109,76,142,113,78,222,63,202,227,65,140,154,29,47,96,41,58,77,137,107,249,152,7,126,53,105,31,221,134,107,150,14,18,108,110,152,91,57,88,146,199,220,12,79,116,220,134,180,176,224,71,97,52,154,76,94,230,58,14,196,154,89,27,162,219,96,227,91,143,175,92,36,179,222,30,59,163,32,250,146,96,163,83,134,33,18,27,99,127,113,171,35,52,143,96,219,71,71,254,216,30,244,75,88,241,242,50,213,1,83,56,154,152,153,219,130,166,175,82,10,125,111,96,137,38,46,205,11,85,195,29,184,117,250,218,58,49,10,40,30,139,211,81,157,249,51,33,100,201,34,96,197,189,206,48,180,50,2,111,154,109,10,90,116,189,224,85,45,153,10,96,210,142,179,131,174,213,131,9,90,194,235,113,201,152,223,253,134,198,136,215,196,121,114,145,127,197,63,226,22,10,124,149,177,37,12,217,218,113,9,235,142,49,103,237,98,82,140,8,127,97,56,61,78,76,142,106,216,56,78,153,139,60,223,243,28,34,38,199,137,132,50,118,151,58,141,192,20,249,138,53,114,177,45,146,78,147,234,123,244,61,157,119,7,88,41,82,17,102,213,59,93,79,45,40,157,139,219,81,12,134,18,77,1,101,45,228,155,66,227,243,242,202,71,136,205,94,102,239,237,253,62,207,30,222,178,58,135,219,74,150,232,27,209,251,37,198,33,83,209,39,249,183,21,38,213,39,143,198,149,91,161,250,193,43,45,233,70,234,118,173,231,180,151,157,138,7,167,198,81,194,51,164,200,83,56,176,121,167,225,108,50,245,125,137,148,215,111,59,19,64,109,5,114,176,218,137,186,235,94,254,156,96,194,168,34,159,84,171,68,70,215,155,148,244,240,11,54,128,75,56,161,201,231,65,137,194,113,32,89,201,13,141,169,131,94,198,168,132,135,101,50,165,181,8,159,184,15,19,74,16,105,43,25,168,214,106,76,164,64,91,12,74,22,16,124,27,121,145,188,125,255,96,131,33,245,145,180,29,62,194,137,30,62,243,129,77,13,158,163,117,162,206,61,236,135,244,220,166,174,217,73,139,0,254,201,26,125,241,33,68,187,155,235,119,25,72,196,151,8,255,8,84,250,43,102,204,134,121,186,123,144,48,2,235,7,229,41,190,150,181,169,203,226,194,118,180,182,162,220,222,14,52,114,197,229,86,207,201,148,241,246,69,68,231,8,57,6,21,171,44,83,134,151,83,25,48,142,91,248,21,21,213,9,104,208,21,12,133,100,100,144,124,237,193,56,180,34,39,246,232,53,212,121,61,127,221,103,74,114,150,223,11,229,210,6,76,40,95,192,199,167,100,100,64,117,44,73,13,187,42,241,47,212,35,164,55,64,85,88,41,102,68,165,110,72,100,66,38,33,14,166,233,157,80,35,137,1,69,63,111,169,42,19,65,190,106,104,216,90,154,147,190,183,207,177,145,142,190,213,148,10,228,251,99,58,72,148,192,227,20,1,79,110,181,47,89,218,133,7,75,111,229,49,60,97,179,158,28,51,110,139,80,56,147,33,182,227,153,92,32,1,241,44,181,143,24,16,252,26,129,134,63,65,186,1,160,90,254,21,88,43,220,101,222,156,214,211,98,172,42,254,193,103,147,61,229,181,85,228,223,127,163,201,157,106,97,82,251,201,89,32,245,234,92,103,151,70,111,44,210,74,166,88,95,204,82,185,9,218,72,146,27,181,139,97,122,22,228,206,84,237,87,140,101,100,110,216,186,226,110,186,109,140,162,59,52,3,26,96,176,41,84,66,47,216,100,110,106,2,55,106,165,232,43,156,42,193,122,42,74,224,96,101,41,240,141,4,88,29,113,31,121,80,196,152,15,234,154,70,129,228,97,137,99,89,108,64,143,32,111,199,220,209,192,20,24,80,192,202,191,169,156,133,210,36,179,17,149,67,213,52,180,176,134,253,181,179,174,87,217,236,254,162,137,201,192,88,23,89,195,231,73,182,226,224,149,99,172,221,135,5,241,132,86,236,118,69,50,108,27,103,65,17,127,75,11,160,71,85,227,148,153,62,103,83,250,192,254,215,123,252,157,8,112,132,210,193,21,244,168,131,44,69,226,190,243,10,225,163,84,190,118,32,19,193,234,220,32,188,74,90,197,143,70,191,99,113,186,143,49,131,109,253,62,234,221,183,103,238,89,65,67,11,230,9,222,24,95,129,14,228,125,126,166,49,29,239,36,39,124,130,203,200,105,29,231,182,43,1,179,193,103,230,251,205,22,182,65,191,137,110,165,113,180,60,209,87,212,7,69,241,130,157,125,59,225,89,244,120,134,142,170,92,19,65,251,87,163,83,32,185,163,202,187,191,34,192,183,186,236,30,222,225,180,237,142,162,77,93,190,100,248,70,134,164,253,105,255,142,189,83,50,161,225,223,241,240,252,170,90,122,221,22,108,187,81,31,252,76,218,238,217,175,90,110,37,190,8,65,147,181,160,202,39,24,230,218,92,233,102,123,98,72,215,163,152,111,198,25,215,60,213,1,254,4,168,45,13,40,238,142,158,60,70,241,144,183,215,236,146,149,13,234,215,133,3,112,135,7,8,40,195,214,105,244,172,246,200,198,238,153,112,100,59,137,18,122,9,204,17,41,181,111,41,61,21,160,16,170,194,218,178,62,88,92,199,233,200,24,70,246,142,224,164,200,210,237,216,75,100,45,115,160,117,92,38,226,170,215,156,203,215,210,248,231,199,216,248,161,125,167,132,103,180,186,9,249,4,154,16,237,107,80,28,27,235,150,39,210,201,153,66,17,97,165,29,15,167,130,23,77,17,106,160,90,248,47,219,164,20,127,81,248,1,36,254,22,50,208,65,145,45,220,160,93,16,45,62,229,177,187,144,167,142,26,248,232,6,191,77,59,136,49,2,33,116,66,65,146,218,44,111,73,2,222,99,111,24,180,41,67,103,39,216,168,240,207,142,34,241,86,17,173,37,58,64,186,213,98,181,151,159,141,26,22,31,45,92,64,9,10,26,76,181,236,145,18,8,30,219,158,183,71,138,134,56,65,70,34,140,141,13,54,245,29,155,227,200,183,113,40,113,203,86,214,2,162,90,237,5,247,2,186,149,205,73,75,106,255,178,8,39,126,21,96,43,117,216,10,81,98,244,208,25,252,177,189,21,50,204,13,115,42,29,115,2,10,234,207,168,29,131,228,241,82,183,158,85,177,161,142,249,81,208,74,7,73,61,160,142,153,121,63,78,230,152,77,38,100,58,119,15,102,23,145,201,189,165,77,147,230,208,2,84,68,22,86,13,32,68,58,88,73,8,48,139,117,27,222,40,32,182,33,168,89,188,113,162,162,146,225,102,118,158,53,22,82,149,184,240,92,212,243,40,50,170,149,147,223,104,185,45,162,20,59,162,173,157,5,224,233,8,159,219,28,215,102,178,59,121,254,199,162,199,99,2,69,53,6,16,218,9,6,241,44,220,188,45,208,250,244,235,250,209,70,110,222,198,183,219,47,135,143,170,11,226,178,201,194,8,0,115,63,105,158,9,227,172,16,176,218,211,18,70,236,5,109,35,119,143,218,145,213,190,153,247,240,232,191,61,9,58,130,175,235,45,122,195,207,43,194,102,133,91,46,230,18,78,212,122,114,168,4,94,120,96,72,18,12,142,191,141,105,202,78,241,114,85,34,238,84,11,10,254,50,188,122,76,216,117,121,110,3,95,91,62,253,60,174,139,195,120,183,220,61,229,75,22,220,190,134,216,68,90,111,184,152,40,130,43,39,76,144,94,215,83,252,62,127,27,6,175,158,50,87,41,85,95,32,24,14,193,22,92,54,156,254,77,61,50,7,243,25,48,156,89,56,17,33,107,135,110,160,52,80,216,55,217,98,40,102,1,34,70,233,200,205,172,234,156,17,180,123,113,143,67,81,224,51,149,12,213,251,3,2,63,30,249,181,254,120,160,155,133,96,137,181,35,5,182,121,214,39,128,129,237,203,19,137,24,93,101,255,228,209,34,58,241,253,187,131,60,8,241,178,36,11,26,109,21,150,214,31,242,19,60,118,147,158,111,23,164,168,73,67,92,231,211,6,86,222,242,248,107,142,231,119,143,1,168,27,187,91,70,38,230,162,216,232,152,83,71,41,183,182,189,94,221,128,7,217,182,42,49,232,20,23,3,87,95,213,181,137,117,14,161,52,243,122,183,193,90,134,182,58,222,179,72,150,241,129,197,216,227,156,20,75,90,202,71,128,15,137,242,183,117,188,168,252,39,243,76,167,222,12,190,250,197,206,164,145,191,47,206,24,20,40,253,36,4,220,72,143,199,19,105,30,48,219,215,196,37,15,182,38,220,134,239,35,187,29,230,68,215,139,220,215,90,25,184,246,196,149,239,249,142,248,63,141,205,161,28,87,142,170,237,214,67,142,251,97,163,163,242,208,139,28,201,5,249,160,111,232,64,231,207,201,197,196,206,92,127,71,17,57,48,200,25,226,176,113,210,162,108,233,45,224,15,40,196,161,187,228,55,88,74,235,30,68,12,209,70,87,243,159,85,208,70,192,75,111,14,15,239,6,234,134,248,30,113,51,255,128,43,104,82,6,158,241,74,19,174,199,229,132,238,6,70,145,96,242,208,185,17,12,251,210,13,113,233,186,188,29,9,195,244,71,62,26,195,82,44,209,10,230,93,188,92,234,241,145,115,67,77,67,44,210,249,228,5,84,43,160,77,103,214,59,87,195,200,20,129,254,173,229,229,37,115,254,49,72,119,145,188,255,12,95,191,110,239,124,12,213,234,217,4,211,133,39,184,242,103,223,13,5,50,56,74,214,135,66,130,62,223,167,91,175,30,40,134,82,42,167,175,169,33,40,205,88,123,104,96,189,142,226,130,73,0,60,121,128,225,203,146,1,170,4,93,235,72,243,97,77,129,92,246,173,53,161,138,204,83,70,234,80,223,20,176,62,149,150,127,141,182,196,163,80,117,13,31,248,64,166,35,112,96,44,221,70,128,124,229,74,60,65,83,15,20,135,165,184,82,153,163,153,145,137,168,21,68,140,120,76,239,1,57,32,133,38,158,157,114,92,79,139,129,100,233,109,73,206,6,164,101,18,250,41,214,14,185,87,241,153,142,116,3,55,77,138,149,123,112,38,59,191,132,156,136,205,108,175,236,117,66,107,36,241,192,147,149,227,116,253,26,209,34,134,94,214,68,212,25,142,117,207,151,32,13,101,187,154,38,54,165,162,58,254,142,54,86,89,13,232,46,36,31,67,169,250,183,168,205,55,163,165,77,37,211,28,12,51,80,99,47,117,190,69,215,83,246,24,48,152,252,50,167,183,242,94,21,63,211,171,23,199,4,160,172,57,57,92,128,50,52,174,87,77,255,17,221,149,165,195,162,43,38,226,27,221,101,124,188,82,226,222,49,132,246,31,27,81,255,205,69,176,163,195,253,83,47,80,99,157,132,223,160,92,39,120,73,149,51,171,255,67,218,107,160,220,58,236,28,119,180,1,82,24,146,160,44,200,70,141,109,254,12,126,229,95,99,96,3,216,221,136,205,113,142,122,186,243,183,255,22,253,97,176,39,222,179,209,180,233,133,72,37,54,158,28,65,95,13,1,59,153,193,87,230,128,104,160,201,205,2,196,6,125,232,155,188,65,83,240,126,145,178,63,143,0,240,193,78,184,2,226,82,240,49,22,50,167,206,196,168,121,68,212,156,249,154,95,24,93,83,113,168,33,14,246,208,135,139,78,122,101,123,8,177,97,182,122,128,106,140,8,192,100,143,88,196,50,29,207,215,143,65,120,133,133,118,94,128,12,106,130,195,165,203,112,192,173,166,222,59,23,34,6,82,131,16,84,214,205,87,208,140,201,182,166,221,131,122,181,85,150,65,139,133,103,23,179,159,231,7,175,204,95,130,131,126,45,155,135,76,69,145,54,197,251,173,9,206,46,189,122,101,178,24,17,52,231,121,151,60,255,66,47,5,0,134,235,185,232,129,137,35,158,3,110,230,211,73,61,209,224,71,153,55,248,61,100,233,170,140,66,27,177,253,40,208,209,143,4,27,108,105,166,136,60,8,218,119,168,182,107,8,119,5,118,31,219,43,94,70,182,91,68,254,135,245,212,250,26,105,156,109,180,133,177,249,140,89,130,79,55,31,123,18,154,42,191,139,9,240,237,151,107,173,188,134,243,132,118,79,249,197,52,29,174,60,127,48,203,213,101,118,178,117,92,200,49,217,119,172,213,150,231,103,134,168,200,159,174,105,85,8,72,53,243,196,179,102,171,173,207,190,134,186,250,180,231,155,193,203,81,248,175,8,196,145,73,186,178,63,177,60,238,12,42,169,79,173,245,76,171,131,19,102,237,156,201,116,42,209,167,158,198,227,114,197,227,182,212,229,151,110,140,149,239,82,124,137,145,167,26,54,159,102,237,132,139,121,181,115,78,145,179,231,40,243,114,107,190,126,230,152,86,21,43,130,126,87,172,107,120,215,174,119,95,238,138,107,162,109,30,0,156,48,191,59,137,171,39,151,249,219,16,202,29,186,7,225,198,202,213,119,26,30,46,66,61,154,127,212,160,121,30,139,137,77,16,197,1,225,23,181,190,52,124,88,224,250,45,111,131,115,99,26,188,227,244,207,13,101,230,130,96,187,90,109,141,203,246,150,213,238,2,180,162,199,113,129,255,97,7,65,101,37,145,166,70,193,39,68,86,45,6,162,80,189,182,147,237,204,108,173,114,12,139,6,79,110,178,50,39,17,113,41,178,217,61,88,132,240,93,181,152,170,7,71,170,146,115,177,209,87,215,16,157,38,76,45,46,220,16,103,58,125,32,153,241,187,154,232,13,56,84,165,56,94,8,6,118,36,14,96,65,93,68,50,208,97,85,185,103,1,161,83,67,194,38,128,76,181,204,102,151,40,72,219,119,58,243,206,0,99,50,157,241,110,31,75,39,89,181,28,80,34,47,54,40,145,0,60,100,212,148,16,35,19,189,130,103,237,1,19,109,241,72,134,148,103,72,23,209,106,186,211,41,196,18,76,23,75,122,68,251,50,11,252,232,52,72,57,5,52,226,217,252,184,71,71,112,106,214,93,60,250,235,235,115,148,64,183,222,82,158,135,135,145,153,54,138,126,116,216,66,235,51,100,7,1,111,11,231,57,153,174,195,76,173,195,2,137,227,217,61,109,233,31,68,5,179,235,72,80,16,191,118,37,76,119,131,246,39,251,58,127,172,229,32,135,167,216,216,39,54,7,180,45,236,44,47,186,218,5,45,145,201,222,24,126,214,198,237,218,245,74,159,119,201,233,27,224,213,175,46,43,252,104,209,254,53,126,25,166,190,157,66,64,23,226,4,74,69,28,42,238,195,233,33,1,64,116,16,110,32,81,97,57,242,250,108,13,200,31,184,115,30,190,65,111,225,197,90,215,174,221,193,216,165,11,16,3,153,141,181,161,223,213,141,64,243,41,33,65,208,245,48,203,171,242,234,120,183,57,60,85,83,188,148,249,94,62,178,164,119,223,137,180,49,184,166,120,134,127,76,230,216,208,161,5,42,237,196,235,114,222,23,134,110,242,244,163,1,42,228,3,251,93,156,48,46,154,200,19,163,205,213,250,142,212,14,156,210,48,20,148,235,204,232,128,21,3,100,38,184,230,249,138,117,207,253,60,79,102,174,115,184,21,102,194,116,47,69,98,110,200,73,248,186,30,220,75,239,155,228,138,141,255,84,179,127,17,124,167,107,102,248,93,59,11,170,167,110,129,228,140,41,111,215,131,169,31,210,192,131,220,50,29,241,34,235,141,60,96,178,83,126,109,14,186,209,248,63,130,108,186,180,105,95,192,234,29,87,8,197,153,103,55,13,10,116,247,40,153,54,84,199,120,69,98,185,228,4,234,107,80,168,240,218,9,114,58,196,150,245,120,244,210,164,160,201,55,20,40,135,138,179,149,228,199,157,192,174,190,79,35,154,208,104,215,44,229,241,125,186,156,42,60,224,60,98,79,40,64,126,207,165,212,10,115,54,25,33,126,58,236,50,194,209,149,85,111,178,89,79,15,60,227,54,174,229,243,135,42,102,50,171,254,95,21,247,31,125,0,215,95,9,254,115,158,204,23,106,103,28,139,202,110,125,119,242,110,213,56,152,116,42,49,235,231,28,252,0,141,119,191,200,51,122,183,74,56,200,99,174,153,239,174,227,16,247,241,53,17,43,147,201,28,236,24,172,158,183,250,239,232,109,178,138,191,154,85,92,101,93,173,175,120,149,115,204,109,250,109,193,172,203,85,254,72,122,109,173,97,223,35,161,59,23,39,177,164,124,186,70,76,36,143,143,79,179,160,167,125,30,112,233,209,141,126,247,37,119,77,159,6,86,22,186,250,64,148,109,116,69,157,161,219,213,126,74,234,55,4,74,150,191,164,59,229,208,73,147,153,74,155,93,93,177,111,177,180,36,107,46,26,222,118,125,41,31,110,95,84,199,96,81,223,99,229,230,111,208,187,44,207,189,197,162,155,118,66,246,102,5,157,180,61,121,27,171,235,38,194,219,47,109,32,238,247,114,130,158,184,151,243,155,87,210,50,16,172,39,124,229,145,237,44,49,206,229,30,118,171,255,129,65,10,175,28,62,65,30,217,20,113,253,179,149,240,28,118,112,140,20,237,39,7,159,242,230,64,144,209,53,33,213,116,176,141,135,111,225,244,248,107,202,235,131,88,130,60,113,17,151,144,193,21,155,78,5,33,221,177,64,101,141,166,1,217,83,16,24,8,33,203,8,73,180,252,201,36,37,193,112,158,81,36,62,12,87,125,150,121,19,39,92,191,173,210,244,36,77,195,88,140,26,156,4,231,27,111,89,251,35,188,185,246,75,176,127,162,75,144,137,255,124,36,161,108,144,154,177,88,19,197,21,51,61,242,175,177,115,118,58,158,40,174,196,158,97,198,184,209,36,126,232,71,189,204,186,7,102,36,124,234,204,89,172,220,192,86,101,51,175,40,9,191,17,115,155,117,200,237,22,138,77,48,250,240,160,224,117,133,170,182,144,213,211,213,2,243,145,65,254,0,2,248,48,33,249,80,119,29,108,76,228,213,3,143,250,23,23,131,183,155,60,55,214,27,114,225,198,150,10,35,148,123,109,118,26,2,65,205,51,165,231,113,146,183,118,99,110,128,192,107,84,128,130,68,16,88,195,165,35,170,219,153,195,92,132,226,34,20,77,81,240,139,150,107,214,77,155,204,106,79,19,168,44,71,198,240,87,142,60,44,60,246,5,116,90,243,72,82,123,206,123,164,157,159,113,100,46,227,97,151,247,172,49,26,253,214,112,110,75,191,20,199,178,121,153,73,146,167,80,165,179,249,104,118,42,76,8,126,200,69,25,1,35,35,219,85,218,235,253,164,63,211,195,178,60,208,120,222,151,167,79,238,35,131,109,53,18,149,50,40,14,206,218,230,111,82,234,124,19,223,6,18,94,196,199,189,219,79,203,3,86,63,184,11,70,220,145,70,39,204,13,70,25,105,99,18,2,0,24,161,197,244,35,162,11,157,34,54,196,92,138,255,30,83,77,170,69,196,207,11,28,60,155,7,88,6,248,72,159,21,242,123,4,244,230,249,74,32,130,186,174,143,2,140,24,130,73,170,186,195,129,0,221,95,213,21,27,147,128,194,103,91,111,210,249,82,200,180,140,107,187,79,132,95,135,105,220,39,219,47,101,130,232,19,153,84,96,21,214,227,184,212,26,88,77,22,173,250,215,51,120,214,55,206,86,220,178,39,170,15,114,12,97,98,239,4,124,47,250,230,133,149,196,82,209,165,151,0,207,30,106,133,62,251,241,196,196,47,179,145,179,2,155,15,5,165,22,67,52,207,39,246,123,134,219,252,174,231,168,82,8,7,192,229,168,45,215,86,100,235,111,169,107,12,249,89,109,86,160,142,181,238,237,223,92,168,130,150,236,224,116,222,45,18,13,13,164,73,38,27,208,24,138,45,80,4,148,58,149,54,128,230,244,22,230,218,179,87,51,104,223,178,9,209,228,14,206,192,249,41,82,34,115,235,125,150,192,196,1,165,252,62,83,243,157,37,218,134,192,149,232,139,145,253,205,51,17,97,192,121,157,60,181,170,126,156,5,44,196,235,223,123,170,2,118,228,255,243,8,132,196,221,30,242,92,159,112,180,131,51,25,126,253,184,7,4,110,34,217,37,185,91,186,44,77,80,104,181,58,171,9,210,180,17,119,8,141,229,247,64,62,232,121,118,112,133,52,173,5,202,94,170,37,212,28,222,193,97,51,164,107,197,181,220,102,52,58,47,147,194,179,174,14,89,19,221,145,39,174,86,249,64,89,192,101,143,207,156,186,210,1,137,143,225,13,38,98,59,92,137,53,31,64,212,100,157,144,100,131,3,65,115,94,185,87,13,25,176,45,184,207,19,250,197,231,86,217,51,191,125,60,11,95,125,105,236,148,166,54,6,42,0,150,180,138,38,30,235,72,106,14,217,69,184,242,46,197,173,38,89,234,41,197,213,165,79,86,118,231,142,207,69,207,108,20,53,179,160,231,84,99,156,253,80,13,15,65,18,73,160,149,31,76,124,141,4,48,207,86,81,87,66,32,121,213,115,116,230,240,201,247,195,159,66,154,244,180,174,14,101,84,3,66,175,40,177,65,194,101,162,234,26,55,222,21,72,164,219,243,129,30,172,104,212,50,6,152,90,233,235,35,221,207,165,225,44,109,74,127,123,173,56,87,209,84,211,48,214,123,5,105,101,78,188,169,175,36,172,214,19,232,125,217,130,252,99,237,244,61,173,193,82,209,216,57,13,12,202,82,193,78,70,69,206,74,240,191,91,25,179,254,242,177,68,23,139,165,101,32,52,246,25,212,240,38,237,147,60,156,190,36,3,56,163,125,228,107,228,6,235,44,250,90,92,77,158,36,217,168,161,77,26,49,125,99,103,191,115,41,120,16,231,243,69,108,169,115,81,127,195,48,164,132,75,173,147,62,148,220,3,189,186,165,200,86,60,18,172,193,207,129,196,167,69,181,134,232,130,109,48,76,133,202,38,184,207,153,39,149,26,4,242,77,59,193,254,102,222,99,68,91,147,245,252,14,111,57,224,121,244,233,148,97,66,37,162,181,44,60,144,184,181,187,204,143,33,120,225,243,226,97,190,168,25,134,240,146,145,251,166,104,183,243,126,93,104,93,84,55,148,49,84,30,71,204,203,236,226,179,113,247,64,213,92,207,126,35,130,231,86,232,149,34,79,127,8,155,120,228,29,247,142,10,151,52,57,180,40,56,93,99,171,253,160,143,201,101,183,204,59,240,23,208,83,198,151,231,231,147,28,110,4,156,102,57,157,18,249,18,50,20,130,56,53,156,41,45,170,41,117,136,179,222,121,239,18,168,166,237,2,237,98,107,148,236,81,60,2,33,181,218,46,71,254,197,234,84,204,80,27,160,118,123,153,37,55,238,240,199,98,227,116,197,126,232,21,255,98,226,206,152,34,211,121,85,69,183,195,225,202,232,188,79,208,206,156,187,96,21,189,252,76,203,227,241,70,211,61,52,217,12,33,243,41,50,152,77,47,82,19,140,197,235,100,59,65,70,115,52,246,95,80,145,224,57,224,221,213,78,145,49,47,117,102,248,205,92,84,18,215,150,191,135,145,62,36,193,200,52,133,187,34,96,149,139,1,97,248,25,51,64,247,58,93,111,15,225,212,223,114,61,92,11,95,154,153,245,208,78,148,39,150,34,40,110,50,154,11,54,4,145,21,134,166,233,0,193,39,105,2,102,29,28,168,238,231,117,248,142,40,50,56,142,240,142,165,151,16,85,30,155,98,225,239,177,187,143,215,228,29,118,98,85,69,167,21,45,116,143,40,42,152,1,87,158,139,169,81,137,18,54,65,178,145,44,82,225,241,84,208,111,202,139,17,95,107,130,255,148,105,65,106,172,230,171,55,197,239,133,168,4,152,247,235,19,138,175,168,216,216,171,23,160,83,71,40,126,234,228,1,76,145,9,132,135,166,202,190,232,233,218,105,184,138,161,252,19,33,132,61,159,183,129,62,37,37,194,79,104,59,218,204,215,82,166,4,190,36,224,43,97,59,71,51,188,214,175,54,18,10,15,153,110,203,218,59,225,113,185,123,75,111,206,104,24,163,254,170,85,40,105,9,229,41,218,37,240,211,103,89,253,97,34,77,188,114,220,132,215,129,26,109,149,186,128,119,108,19,20,122,172,175,10,20,169,9,104,195,150,51,8,159,140,86,232,226,177,7,196,200,167,207,106,126,27,140,222,219,198,149,46,0,13,93,255,121,205,23,206,245,185,247,15,231,173,156,59,156,16,48,118,254,93,148,203,237,189,158,180,101,52,62,155,57,8,175,171,215,67,69,104,60,72,232,226,185,20,206,65,59,42,125,90,124,100,202,134,141,239,191,110,203,164,223,50,232,219,4,222,205,22,70,62,180,75,143,174,228,44,62,245,202,39,117,215,33,145,80,106,131,177,244,66,46,89,167,198,251,80,38,72,190,90,118,85,34,158,83,17,61,132,124,53,24,63,24,90,249,68,131,245,198,183,117,13,157,137,70,189,73,23,75,77,13,25,88,126,217,87,108,92,8,133,154,15,158,112,113,94,186,162,177,9,232,181,162,55,24,38,161,79,176,4,233,11,158,170,242,240,168,77,25,3,223,158,186,182,26,129,84,106,135,108,205,79,254,175,227,1,238,248,79,5,72,169,217,128,158,1,139,110,157,12,39,55,95,3,2,113,179,81,229,38,144,253,35,77,155,97,157,9,47,133,35,238,97,246,176,156,164,3,236,181,42,140,173,1,46,164,218,168,228,127,219,160,224,59,249,247,7,155,98,77,199,215,146,55,151,221,185,163,241,26,122,137,164,190,205,207,4,237,134,165,74,238,223,226,15,248,242,139,107,210,187,234,4,145,23,231,180,229,53,254,166,201,220,10,14,58,33,230,72,92,230,207,170,109,188,229,137,28,147,22,41,192,213,40,215,216,127,14,228,9,13,85,247,106,247,1,155,206,136,4,23,190,148,170,106,194,155,170,96,227,85,168,247,195,20,113,172,17,34,38,123,79,167,110,206,207,53,66,173,162,178,166,84,120,160,160,218,186,227,34,87,100,212,219,28,84,255,59,138,26,28,227,102,205,94,75,152,55,216,163,46,225,96,152,57,32,57,159,27,251,178,201,231,5,139,31,163,136,69,71,125,19,213,46,252,84,88,215,163,249,153,181,25,227,174,4,105,93,98,251,60,164,4,222,26,165,85,83,87,45,206,132,134,6,108,89,96,76,139,144,143,144,116,59,72,48,184,248,230,195,135,167,29,166,42,207,49,87,221,159,42,168,96,157,181,125,152,96,130,72,48,100,105,145,96,98,200,116,7,131,166,69,99,117,55,141,40,125,106,249,33,118,191,121,159,138,79,27,90,132,13,52,0,61,44,246,212,77,127,107,26,124,234,104,26,14,238,68,79,124,247,99,81,60,135,27,62,83,231,104,214,53,69,104,188,95,120,30,105,222,150,218,223,80,221,209,86,113,125,226,123,36,1,136,94,206,253,124,34,218,2,77,208,172,39,238,148,151,111,237,3,135,99,41,22,142,129,39,56,105,255,31,62,12,171,5,206,94,114,13,174,185,89,199,225,131,239,187,92,132,102,86,138,156,36,55,112,65,191,209,70,60,75,110,59,216,180,148,36,118,238,139,97,222,17,236,209,68,163,76,177,206,58,196,113,2,166,47,131,113,199,180,134,23,174,24,119,20,124,144,29,221,9,90,224,188,131,232,13,244,94,200,129,51,27,11,124,24,154,5,91,171,150,238,212,117,175,71,155,110,168,3,236,162,196,193,74,101,6,238,157,132,151,181,88,122,26,84,194,170,253,198,124,142,133,185,66,4,105,5,152,87,209,178,134,243,242,197,214,209,103,53,218,128,193,9,83,231,55,111,29,235,133,45,107,115,71,203,15,1,69,200,105,216,1,163,183,18,222,54,6,56,48,104,228,237,119,166,90,242,184,97,160,218,194,255,151,131,120,180,104,202,167,157,179,147,77,161,34,65,201,171,236,177,175,0,92,134,255,40,217,133,61,187,44,165,109,184,127,37,189,61,62,60,232,182,210,78,123,118,207,185,156,158,77,117,67,26,37,222,174,87,192,241,152,180,170,218,35,86,86,91,87,98,97,192,129,140,194,233,36,79,152,203,136,73,223,63,26,117,190,88,188,60,42,9,45,54,223,198,207,196,237,26,244,60,233,67,132,223,113,147,253,16,126,10,119,41,159,99,237,109,167,23,248,146,7,166,214,75,0,234,202,90,254,26,71,82,240,116,216,96,236,109,46,104,255,134,115,253,155,36,36,129,188,183,140,151,14,153,244,139,244,252,214,160,8,249,226,35,58,185,116,255,126,128,120,235,190,225,169,185,175,255,64,176,56,247,249,7,18,39,92,249,142,98,47,116,247,126,6,66,208,245,253,217,123,160,123,49,99,18,90,47,9,80,207,212,123,18,61,155,193,44,242,205,146,4,96,210,222,194,220,47,172,241,165,29,155,45,163,105,121,174,115,233,211,216,182,136,24,90,234,77,214,70,94,160,35,59,16,39,71,24,186,43,251,99,53,11,47,60,159,24,144,250,41,114,90,26,97,209,154,96,63,178,67,28,211,107,179,90,253,127,165,163,26,175,163,165,60,47,25,151,210,245,25,91,122,31,176,184,179,128,161,75,71,166,119,40,19,58,101,115,237,145,211,239,250,235,224,4,46,64,94,118,213,191,21,42,27,169,75,217,193,182,121,215,57,216,234,245,160,135,78,21,125,113,51,250,39,177,32,227,61,57,182,118,16,212,181,130,153,240,62,148,127,188,127,160,37,3,231,33,68,181,179,95,116,179,14,247,145,214,104,222,71,140,17,161,171,218,105,81,195,25,20,202,235,110,70,90,42,47,194,109,74,85,60,77,65,92,205,106,16,171,147,0,227,16,251,48,224,101,8,46,29,94,50,36,213,78,254,13,7,254,227,219,219,18,45,213,145,136,25,210,42,32,47,62,61,139,31,140,17,210,249,37,178,80,160,59,139,26,250,178,179,208,129,81,82,239,54,209,224,20,156,174,251,26,130,136,28,68,243,28,42,28,17,51,90,6,39,125,11,249,223,165,193,243,148,129,17,210,146,186,89,202,253,59,205,5,52,237,17,181,104,92,54,142,214,177,178,59,214,195,73,72,186,175,17,1,0,220,146,69,144,120,89,133,146,152,239,230,141,237,0,78,250,117,54,179,45,38,167,90,149,136,233,115,8,227,210,205,255,208,177,5,45,173,12,189,122,109,122,136,191,40,176,51,234,201,4,208,42,147,44,56,120,17,43,69,93,97,143,103,130,166,129,101,7,40,85,92,157,218,212,230,114,139,2,233,64,93,127,49,140,232,168,194,0,74,215,40,158,61,12,247,57,151,103,148,42,210,155,139,211,87,19,0,208,70,224,199,34,241,199,70,169,161,135,61,105,233,172,62,114,0,96,15,45,231,45,55,172,39,55,41,225,133,190,138,162,53,142,120,95,183,32,192,36,208,155,102,233,86,61,53,30,206,83,199,125,72,101,207,29,247,104,10,148,18,184,234,165,202,151,116,193,119,185,112,23,192,20,152,65,174,8,254,94,56,95,112,30,175,131,75,160,36,26,226,61,55,97,225,40,77,212,181,0,239,155,198,208,128,240,202,248,190,135,42,46,22,94,11,61,30,199,55,16,98,142,1,63,173,36,147,172,74,152,45,239,201,204,46,115,27,81,227,120,112,155,184,99,79,214,130,147,122,64,139,9,147,208,82,76,15,123,98,5,74,218,198,40,175,162,34,226,243,95,227,126,94,45,242,141,118,9,49,66,13,62,135,201,56,200,96,255,212,204,11,3,243,18,242,108,74,227,62,173,115,180,224,226,248,249,141,136,245,6,158,110,65,8,248,189,225,236,226,84,45,8,72,133,12,176,12,140,172,135,245,88,80,88,0,185,175,79,207,75,134,219,100,194,29,255,125,135,114,8,126,63,172,235,145,65,229,120,37,197,36,66,254,60,122,61,197,192,6,79,197,152,198,219,179,231,14,155,211,69,154,175,209,49,59,91,6,25,138,1,144,199,28,148,67,149,19,37,147,101,173,173,206,196,37,179,47,184,185,251,43,182,74,221,246,66,82,220,131,113,87,197,241,66,226,95,156,93,186,196,250,229,244,248,189,22,207,27,43,104,3,210,183,207,145,95,190,74,251,145,107,71,36,138,225,83,79,207,145,78,210,137,175,90,23,239,94,181,98,41,136,109,211,114,150,87,255,49,149,169,69,132,65,211,140,205,214,29,22,127,210,12,110,19,72,139,152,200,229,246,220,110,222,227,189,5,36,90,254,53,6,237,122,57,142,108,23,90,140,146,218,237,207,124,148,18,43,1,231,98,177,83,35,133,156,57,105,201,222,84,80,168,12,176,33,62,83,81,72,91,127,176,136,94,105,255,254,90,145,155,68,132,45,203,4,81,16,2,218,66,189,227,170,31,12,196,122,121,143,12,99,122,129,195,234,210,79,14,55,209,162,72,6,182,66,57,203,144,165,124,104,28,239,250,145,78,30,73,201,115,103,29,184,58,64,70,85,21,63,220,48,82,120,182,147,193,160,57,159,29,228,110,185,119,116,208,106,226,116,121,81,43,222,244,81,208,45,54,252,92,150,203,97,118,228,145,19,251,135,68,118,217,134,205,225,179,191,233,152,12,91,197,183,100,112,245,155,90,49,164,31,226,11,161,97,101,12,52,104,87,67,185,88,236,186,244,207,7,33,67,86,181,69,233,84,8,132,228,204,119,32,165,140,91,72,140,72,59,85,160,243,119,182,101,202,174,103,225,103,157,66,245,6,239,65,118,228,82,220,95,37,111,101,138,161,191,68,163,207,254,132,5,33,34,56,45,15,145,79,100,40,250,236,235,36,175,245,20,209,154,13,198,149,155,0,80,11,84,80,172,105,217,187,232,7,132,48,231,150,103,105,189,165,83,77,153,247,75,244,46,186,175,219,208,150,199,180,28,58,132,148,105,13,207,113,32,133,101,252,13,167,207,239,200,38,246,25,126,101,156,150,20,134,155,28,193,203,237,91,8,31,34,172,248,160,57,105,219,239,42,133,226,116,81,43,132,235,167,30,68,43,231,221,164,52,182,249,179,61,153,161,159,137,151,189,73,236,246,163,36,98,19,85,248,126,173,105,179,75,212,179,6,192,100,128,153,211,199,108,66,203,86,207,169,95,199,34,119,154,244,10,13,220,112,98,175,183,40,113,55,27,57,116,86,1,170,179,54,173,252,94,178,69,116,19,143,251,130,194,112,136,117,223,38,229,127,85,195,14,156,30,223,71,155,223,129,124,152,171,136,110,120,95,180,53,100,168,25,3,216,42,54,85,46,69,119,107,155,145,251,64,53,185,193,15,13,139,6,167,11,60,47,89,97,48,152,126,89,204,146,71,95,57,111,150,78,240,251,102,115,113,11,147,15,192,253,231,25,248,245,109,134,153,56,58,101,46,144,2,253,31,2,83,198,61,64,121,63,76,80,67,29,12,66,28,147,254,92,69,68,35,212,156,221,161,237,249,146,56,121,137,145,156,246,183,247,139,124,62,163,212,103,229,186,93,174,69,23,160,26,196,181,43,175,176,60,110,211,55,131,146,61,179,46,79,154,194,63,7,77,202,244,150,202,18,92,217,129,241,239,222,111,51,135,13,231,255,23,171,205,2,165,228,225,46,247,213,245,181,190,140,154,241,182,186,251,24,83,159,137,53,64,138,170,164,60,147,27,90,82,193,36,201,173,182,188,108,188,229,45,193,211,18,253,200,185,25,95,180,93,30,219,69,195,239,222,97,161,110,214,36,114,96,168,76,77,164,53,131,226,197,100,0,42,106,159,84,214,55,249,124,216,170,102,155,118,134,77,181,65,115,14,167,123,89,46,212,228,181,29,222,148,86,228,253,74,236,231,197,148,188,137,167,27,127,12,253,186,84,67,146,211,91,131,122,218,230,239,254,175,168,1,213,249,121,7,221,136,146,201,36,166,47,73,221,190,128,205,126,206,89,121,78,233,57,64,136,20,67,198,178,249,191,17,131,33,149,197,130,104,170,130,142,237,246,170,147,192,156,248,187,123,25,225,139,220,171,61,24,24,114,110,77,3,160,244,82,56,94,113,16,27,118,228,217,56,29,253,10,75,145,97,193,150,89,210,52,60,146,17,127,187,216,5,195,108,15,251,39,157,158,86,49,193,199,155,106,6,73,80,247,203,61,88,81,56,93,158,179,40,245,81,68,136,69,32,237,101,122,112,165,100,55,9,127,59,26,9,41,16,102,92,246,179,125,108,231,225,63,120,88,135,69,195,239,197,51,245,72,72,59,15,231,42,3,184,123,64,176,64,2,15,246,220,67,193,252,8,159,56,20,44,137,45,172,109,183,204,159,101,6,17,221,228,44,160,69,242,153,202,128,203,12,4,126,92,35,50,234,50,118,36,235,41,31,25,142,113,24,62,9,95,20,19,50,125,158,204,53,186,86,53,189,102,153,228,219,22,2,99,14,143,147,221,199,23,113,107,196,224,225,104,121,99,34,19,112,121,28,191,160,245,10,17,84,184,88,225,151,167,54,240,195,72,254,120,18,22,155,131,146,29,227,234,30,101,250,135,69,125,243,191,220,108,252,27,73,15,229,136,53,207,18,173,204,19,205,199,182,167,225,33,249,143,99,91,17,55,149,227,252,128,238,114,212,169,242,145,36,176,68,219,87,139,157,11,63,61,59,211,206,153,189,127,223,109,58,97,39,141,146,29,253,92,94,80,25,18,106,154,118,230,19,134,225,160,83,60,150,40,14,114,137,33,215,197,110,48,190,240,56,91,138,248,129,37,247,39,83,175,2,103,194,229,110,102,216,12,120,6,3,226,163,55,78,249,252,111,226,91,6,137,148,130,47,48,247,229,23,243,182,71,150,137,124,20,124,66,139,32,193,148,161,185,236,79,174,99,200,112,53,55,117,29,34,237,204,153,30,100,212,1,178,63,101,108,21,60,226,164,189,178,191,164,14,130,253,211,82,162,209,199,23,248,243,208,248,249,158,141,215,199,86,0,246,74,146,131,115,160,41,65,31,203,224,248,194,77,33,67,47,171,200,140,46,76,21,188,172,177,183,243,246,224,185,32,56,122,180,233,201,25,233,15,85,45,133,25,16,136,35,136,145,142,15,86,80,133,48,119,224,178,65,40,193,213,90,108,89,160,56,151,217,217,57,103,175,63,242,81,89,154,80,29,72,39,62,162,124,64,207,184,236,170,24,70,121,44,61,235,14,3,108,68,201,57,178,69,188,58,91,211,235,251,154,69,34,123,86,213,66,253,253,216,176,67,99,197,91,185,250,198,244,215,134,106,130,27,155,101,61,23,181,173,83,247,184,185,24,221,87,94,129,150,24,83,250,180,99,14,23,157,95,133,189,98,219,252,120,118,181,213,41,131,138,220,245,32,75,155,209,55,31,197,21,188,175,14,108,96,144,219,70,87,169,105,80,215,39,54,253,164,135,220,113,179,11,26,86,90,17,173,82,168,51,234,219,159,197,190,211,12,96,163,96,156,21,216,237,81,71,8,238,177,222,65,238,18,207,224,198,6,78,77,58,229,128,113,49,80,53,64,60,188,235,183,243,253,19,186,159,48,179,25,11,199,176,100,249,48,94,85,170,164,215,111,157,248,47,235,115,199,148,241,90,5,156,158,194,36,48,2,128,54,251,107,121,73,162,149,9,148,65,58,167,164,203,170,52,197,196,44,120,167,22,204,41,135,101,200,149,248,38,73,57,71,205,69,158,255,72,185,219,30,199,49,162,53,242,190,45,142,206,11,94,30,40,120,221,10,171,209,31,64,30,69,102,138,222,180,169,4,28,97,34,15,174,50,15,217,31,255,141,56,24,233,173,156,216,252,142,255,94,59,43,223,147,253,34,44,189,10,93,55,252,67,27,40,123,12,243,5,33,140,234,16,240,115,171,26,131,179,201,114,216,135,196,14,204,11,226,91,159,139,238,182,65,152,10,212,173,146,189,31,16,197,251,214,140,176,101,41,217,127,19,65,118,112,116,119,159,28,52,102,175,254,92,132,73,106,70,124,121,229,34,136,208,230,102,14,165,73,4,170,233,83,76,138,148,54,152,21,227,68,40,188,180,162,79,72,48,228,26,205,64,66,33,171,221,163,170,114,114,184,172,219,201,168,200,24,77,52,12,80,226,95,105,205,101,189,221,3,5,202,38,226,148,208,76,126,116,245,120,125,186,56,187,96,82,46,133,211,10,66,86,187,156,137,23,160,98,171,226,232,11,114,200,18,250,211,87,122,21,93,163,90,104,194,160,53,194,74,207,94,195,91,24,76,184,136,174,136,22,245,12,54,167,76,106,249,48,251,40,188,97,95,223,30,22,142,194,231,189,143,57,151,51,105,150,197,223,211,167,34,90,118,91,128,229,236,240,185,96,234,208,26,179,111,122,244,232,80,12,38,10,75,30,38,189,236,165,19,26,106,197,252,71,235,185,204,73,177,213,143,142,148,0,198,150,67,125,250,112,233,80,164,49,60,6,157,40,93,68,163,97,177,11,138,69,11,80,35,151,37,226,112,83,104,68,199,208,112,120,18,122,5,174,225,120,249,246,187,239,139,207,193,43,156,214,226,0,98,218,49,189,224,164,249,146,98,223,125,50,17,156,249,81,199,227,5,93,233,167,93,238,114,241,192,104,44,145,2,60,79,168,0,112,62,78,120,31,150,105,225,33,243,194,10,247,239,80,186,67,248,147,112,190,206,149,49,185,35,4,129,193,254,128,152,100,164,105,79,44,168,54,203,1,129,230,43,92,174,4,56,200,148,20,82,211,212,136,193,83,214,240,81,138,39,11,132,114,55,99,194,4,143,40,233,177,238,255,46,166,183,5,115,190,182,171,253,136,6,248,32,219,26,252,55,109,189,224,176,219,6,131,136,170,148,101,102,58,242,121,97,120,125,146,126,232,251,70,200,193,191,199,169,112,172,43,218,147,205,17,215,99,9,141,194,206,149,104,71,115,45,250,190,121,28,115,88,81,131,250,172,238,160,98,146,119,165,113,166,10,172,34,174,43,44,119,114,32,110,169,188,210,22,181,71,3,8,218,196,202,103,105,234,72,209,168,202,3,206,120,58,52,91,169,202,207,73,67,52,223,246,40,85,129,186,17,147,193,231,46,110,139,178,74,210,186,252,20,42,212,66,107,31,239,184,60,105,247,138,212,29,59,35,147,239,109,123,57,144,11,149,66,71,134,57,20,223,47,197,51,83,184,140,102,217,213,245,43,232,173,139,129,135,141,23,147,64,170,6,101,154,52,47,242,34,140,3,101,199,41,95,122,146,104,251,210,114,60,120,85,93,235,23,132,185,200,46,225,58,185,30,23,139,234,67,231,176,36,70,216,129,111,57,23,74,254,117,89,199,41,209,178,61,214,211,184,105,167,86,249,49,90,42,123,168,58,104,222,200,67,41,108,0,17,167,116,177,110,201,116,233,182,36,97,100,6,194,14,109,98,123,229,192,135,60,139,212,178,229,24,178,75,57,129,64,124,38,73,23,182,0,233,69,40,62,242,69,133,151,96,88,46,115,166,144,227,171,12,67,150,150,224,205,128,11,68,98,7,65,199,98,217,18,163,103,246,75,237,111,191,192,188,237,204,240,118,109,98,193,54,170,132,185,37,96,110,213,152,18,190,35,50,82,137,93,149,215,225,221,42,90,5,238,158,171,51,61,216,167,102,11,175,66,32,95,200,136,58,38,185,31,31,7,154,137,77,199,135,129,68,11,138,218,56,51,63,138,232,178,118,35,168,128,222,75,254,4,133,240,20,138,225,42,242,179,147,238,252,236,171,207,216,158,161,187,121,28,211,191,97,168,90,83,211,109,149,65,124,180,9,172,11,247,233,144,178,35,236,201,59,110,14,121,70,14,224,61,254,78,212,28,174,65,117,240,197,140,63,81,231,180,236,142,119,35,45,55,146,227,92,243,89,103,227,113,113,7,241,196,218,216,222,133,210,176,201,227,29,129,190,164,242,224,9,230,82,122,179,114,75,246,39,15,229,149,39,223,54,20,209,236,251,52,201,186,78,73,37,151,126,3,228,78,186,96,42,131,8,164,251,31,66,192,181,12,97,55,186,77,32,219,199,151,33,3,42,85,29,142,29,6,107,115,68,114,214,114,140,199,143,20,245,129,9,78,83,246,169,65,41,122,99,69,204,115,173,8,254,95,66,163,162,48,175,244,113,209,100,147,112,188,220,233,113,5,212,201,138,91,38,191,72,7,99,178,116,234,92,48,244,0,211,154,27,247,206,232,89,85,99,233,132,72,85,200,139,238,153,179,24,123,99,134,246,142,188,239,9,157,112,162,234,185,118,245,59,130,224,204,31,163,171,38,159,221,225,99,216,177,58,35,104,109,10,125,89,23,53,56,37,68,165,189,60,83,249,63,161,240,70,141,1,210,143,125,157,56,227,11,24,55,38,168,16,119,213,155,223,143,131,175,37,234,125,238,16,194,101,201,158,4,110,18,210,221,84,87,14,13,169,250,241,240,1,12,205,98,246,198,75,250,239,249,104,97,127,57,19,15,104,126,28,59,196,119,32,32,82,17,212,81,175,226,118,175,241,105,177,135,71,82,187,16,240,159,71,37,41,230,115,64,156,184,169,24,234,219,0,246,117,253,167,73,143,69,3,130,245,116,43,177,166,154,119,212,153,47,46,26,192,155,252,200,241,110,201,195,252,231,181,147,45,221,62,85,89,150,72,79,230,174,245,52,49,209,202,184,143,160,9,190,63,249,33,193,163,53,123,237,31,46,225,42,225,49,158,14,120,71,133,247,37,52,27,195,168,0,173,254,175,48,203,127,136,142,20,140,58,102,224,52,13,72,195,143,146,84,91,160,228,92,126,63,39,81,150,207,232,13,28,22,22,113,169,45,140,23,5,46,155,127,197,116,25,54,226,104,89,169,95,100,83,211,41,119,115,107,60,190,170,12,213,173,189,220,228,10,211,105,116,245,166,208,229,181,165,201,68,170,57,36,97,78,110,76,75,65,230,77,138,17,146,196,148,196,16,237,121,105,24,158,75,121,236,185,205,129,31,100,68,181,179,248,183,65,29,74,96,126,223,176,27,19,62,148,147,12,48,70,173,22,7,123,162,216,137,16,123,171,81,196,100,84,138,92,119,3,209,28,49,46,184,35,78,201,26,213,233,176,139,204,161,161,100,134,151,46,27,220,236,243,154,104,171,179,29,24,244,219,213,4,109,217,17,167,110,219,11,225,255,47,80,164,122,91,85,104,133,179,78,39,122,132,12,176,53,220,175,184,93,42,5,93,129,217,176,225,1,179,77,53,121,239,203,231,143,218,94,107,129,31,11,195,254,148,78,105,60,149,153,223,20,120,153,7,211,141,71,154,236,170,254,85,202,104,196,108,18,145,215,252,129,244,163,252,137,151,112,146,157,1,59,187,240,13,15,2,216,118,65,35,126,38,27,221,174,235,245,160,106,120,196,95,105,214,48,54,136,226,74,65,88,37,3,224,245,60,140,2,150,249,134,212,251,59,123,169,14,76,79,118,67,227,62,202,182,40,50,114,7,24,44,54,254,33,251,230,193,198,191,167,178,228,71,214,100,187,93,9,99,58,230,102,178,170,160,39,178,130,14,57,7,70,171,249,174,14,35,35,120,237,233,152,182,162,97,118,134,142,150,24,7,159,154,144,20,178,175,155,125,114,58,253,140,118,189,3,236,201,17,137,170,158,6,138,214,209,52,137,203,102,157,11,99,113,92,97,55,117,153,111,20,219,251,13,105,77,46,143,89,53,195,147,116,53,124,195,182,95,154,49,226,94,206,124,56,128,210,109,131,196,167,229,110,5,138,241,184,84,170,48,209,20,77,49,194,144,208,224,23,8,82,52,152,83,235,136,168,48,59,7,125,42,229,139,89,170,227,83,9,67,233,174,188,101,17,74,229,208,35,149,23,105,183,73,116,1,80,193,46,164,25,242,129,1,17,88,87,87,94,55,96,126,151,60,35,202,219,9,3,222,161,131,34,149,198,202,198,131,167,91,75,106,85,22,230,193,8,201,156,81,226,164,111,44,147,161,162,209,240,123,26,148,30,161,104,16,29,236,170,204,149,74,126,34,109,24,139,125,1,32,228,137,89,30,201,147,146,189,177,123,185,72,228,107,91,49,121,163,27,243,72,155,29,183,58,67,212,196,210,201,58,31,102,67,158,141,70,175,80,213,3,99,198,124,34,110,94,209,77,20,85,45,162,82,18,61,189,203,199,56,131,228,230,7,53,226,247,217,35,66,115,37,68,130,210,200,156,186,44,33,11,229,31,84,159,92,194,52,14,158,187,179,106,80,194,179,80,226,202,110,147,204,167,44,63,158,49,55,80,115,164,46,156,244,58,137,134,55,253,220,75,9,103,136,249,242,3,215,220,53,123,17,75,112,40,131,105,76,0,16,17,245,242,195,47,165,106,200,206,26,130,189,65,203,2,99,181,5,143,191,100,128,52,249,154,169,127,159,85,163,175,105,201,79,170,124,33,172,15,229,166,146,194,104,108,129,91,132,33,195,224,4,116,61,113,89,52,79,251,121,2,32,71,98,121,115,214,245,87,160,16,97,250,177,149,55,39,223,212,203,76,231,248,127,176,129,187,75,9,209,101,237,148,65,111,200,193,164,44,66,237,159,220,85,84,91,89,208,128,237,151,180,31,151,237,151,16,114,221,155,43,42,4,83,34,238,79,149,66,231,157,222,132,11,145,104,170,56,236,84,248,183,36,85,4,10,143,170,141,177,87,7,163,114,225,72,248,238,122,146,203,203,157,4,155,198,245,193,60,218,180,175,34,89,80,195,35,71,85,234,238,86,77,49,244,128,157,230,211,30,114,38,88,35,242,190,254,27,132,194,18,236,121,228,133,95,97,44,236,154,28,64,235,14,62,141,6,104,2,239,196,0,239,190,200,189,55,225,88,118,166,28,3,155,39,73,135,166,250,86,28,103,243,78,21,135,177,206,135,183,141,13,148,181,253,155,176,98,53,113,191,110,156,23,111,210,0,12,145,6,255,146,80,247,0,74,171,33,213,96,90,118,193,89,208,79,47,247,61,246,11,199,235,65,231,27,63,41,110,254,129,80,132,0,167,84,59,171,175,164,131,185,207,179,36,207,187,236,180,205,188,150,112,119,170,82,180,155,78,6,33,163,196,74,97,85,204,95,48,248,81,22,74,219,228,3,163,28,111,155,134,69,37,9,187,242,25,75,186,8,17,151,196,130,59,118,14,82,207,194,129,82,65,199,147,72,96,117,243,22,125,145,219,206,184,153,41,144,219,98,96,155,34,94,181,44,163,237,168,33,89,151,218,192,247,57,198,126,236,197,141,63,109,159,157,29,83,185,46,181,8,73,42,95,252,161,116,224,219,172,169,119,219,52,46,170,69,178,172,93,174,0,45,81,139,114,181,102,240,100,159,66,137,156,200,175,244,173,51,117,206,244,24,77,6,23,82,12,37,118,160,225,85,183,69,79,100,126,129,93,155,18,95,145,39,32,118,241,90,236,152,14,20,126,31,234,84,34,120,172,90,243,50,162,34,238,83,91,24,255,99,225,240,27,114,166,100,243,207,98,170,111,107,224,19,79,177,203,231,135,126,205,13,231,108,153,215,16,143,6,18,244,71,18,188,143,224,169,189,54,129,185,202,121,10,142,246,219,251,81,92,184,115,207,55,223,23,9,172,6,80,2,236,96,4,51,62,54,135,46,10,0,229,235,188,235,218,127,115,177,136,157,40,2,71,146,32,245,200,137,190,179,220,117,208,242,197,14,183,79,124,35,171,203,89,139,208,30,50,32,249,148,242,236,98,48,88,255,143,25,1,235,159,210,127,229,219,6,20,19,41,23,220,116,32,214,217,7,197,244,101,247,93,18,117,151,140,84,68,104,42,232,36,226,57,55,57,181,128,52,6,203,130,54,199,103,197,158,184,138,127,61,223,65,111,57,25,181,72,139,155,65,139,48,15,128,95,194,241,163,12,246,39,191,53,212,114,194,90,65,109,13,121,48,171,160,68,35,192,251,149,193,182,207,178,158,107,32,192,59,214,166,145,205,76,194,17,236,248,105,195,184,201,91,214,106,71,163,206,253,189,15,166,160,158,55,182,108,213,82,244,47,221,194,227,48,139,93,104,165,186,46,214,47,63,142,36,158,192,116,253,133,77,50,45,85,208,33,203,120,156,6,55,217,53,210,131,30,194,170,65,32,80,32,81,218,104,125,77,236,131,42,23,51,41,208,230,40,175,127,201,126,254,209,89,221,187,181,101,185,235,139,217,248,49,187,232,192,124,28,52,88,70,236,155,38,60,43,157,178,180,45,203,113,4,9,67,86,60,136,52,5,61,152,126,254,205,152,68,61,64,58,226,75,218,19,204,177,16,138,148,243,180,234,110,6,134,194,139,167,50,151,95,62,160,137,209,208,255,81,199,177,240,114,1,163,160,235,235,172,203,57,245,240,94,121,56,11,132,16,23,152,180,38,90,26,107,103,77,223,70,133,160,220,55,161,159,238,135,127,195,39,208,86,53,94,195,241,255,207,90,238,9,252,64,51,154,107,238,114,42,193,58,242,19,108,172,209,86,71,42,197,80,100,152,114,254,57,174,37,64,50,36,160,251,173,106,84,18,16,170,209,101,166,151,240,142,96,134,97,50,207,93,244,231,22,49,72,181,188,188,85,53,41,160,158,84,157,23,30,169,226,115,33,73,115,107,143,0,226,138,147,191,74,190,144,231,29,158,45,154,232,182,228,53,105,112,118,75,176,179,123,111,233,14,139,90,157,138,223,14,191,88,106,91,191,149,119,119,125,12,238,211,244,188,43,214,146,153,165,147,172,221,81,131,160,19,124,234,236,188,144,176,73,96,127,208,169,247,17,186,160,163,61,186,59,233,72,217,58,90,43,43,23,250,105,188,236,66,19,98,125,250,90,130,162,167,174,46,218,37,184,26,92,237,34,0,26,104,74,167,221,23,105,113,9,187,125,231,185,93,92,121,93,23,185,54,19,90,235,249,3,121,58,43,88,53,140,51,45,206,210,228,223,67,147,216,82,11,167,178,164,218,132,152,116,134,84,112,15,165,106,15,116,46,222,118,186,76,133,157,255,99,27,35,96,230,14,223,36,164,244,30,234,71,169,225,124,239,103,239,185,44,71,223,241,177,16,211,173,64,220,127,244,65,244,249,195,214,90,121,43,248,177,241,128,96,74,224,104,16,53,79,225,14,219,175,78,129,103,35,184,131,156,66,49,75,196,237,145,109,124,157,74,188,157,84,32,153,170,210,235,165,6,155,60,118,114,50,169,40,37,1,220,122,220,107,20,39,19,238,244,128,227,140,103,0,179,250,11,140,38,165,57,63,111,193,84,165,175,223,21,24,232,153,190,211,114,99,96,103,146,32,24,107,66,117,93,27,243,49,114,246,219,30,34,20,17,69,183,243,131,101,22,123,146,89,58,14,130,29,141,36,211,54,162,164,189,208,207,2,157,64,29,178,133,166,206,71,226,123,104,195,207,127,14,140,247,187,212,124,199,222,83,46,134,206,111,75,190,63,73,82,47,139,200,197,11,130,44,168,239,104,124,162,31,115,106,15,77,72,8,188,215,102,185,145,177,146,105,215,243,128,236,120,202,35,200,18,3,56,41,51,228,233,136,75,253,209,15,226,133,173,67,184,30,89,158,18,91,156,153,18,111,152,178,1,79,85,158,151,216,76,58,134,155,146,49,89,17,51,188,208,128,156,11,43,131,131,106,12,149,63,166,121,16,63,219,137,51,65,222,5,172,189,253,110,113,53,167,226,44,245,31,50,38,174,100,68,22,13,112,212,36,155,239,195,60,53,18,123,223,198,86,22,195,153,183,238,240,84,186,32,5,221,42,82,204,140,146,40,142,221,64,66,150,70,55,47,30,39,14,91,230,39,190,250,204,44,92,192,48,150,46,192,2,42,75,126,145,237,31,191,38,153,131,36,227,179,79,231,201,9,204,104,33,64,247,81,36,153,134,244,72,253,218,167,247,131,248,178,75,238,207,226,79,244,209,92,176,76,70,26,233,159,72,80,240,245,86,236,211,60,129,147,52,202,224,10,121,136,140,72,97,73,10,133,96,120,170,207,50,34,150,192,32,223,232,196,218,17,88,13,218,31,177,119,20,156,206,58,133,152,213,248,174,186,249,107,70,175,113,37,10,115,145,51,107,100,20,219,82,204,77,140,219,219,169,215,58,48,94,235,31,79,145,66,12,48,214,3,229,197,44,184,188,88,27,187,162,100,106,211,186,207,12,7,55,129,174,102,0,79,203,232,178,166,41,96,67,20,205,236,10,17,185,214,114,166,94,180,205,186,114,55,253,184,106,217,46,50,15,196,129,214,56,81,178,117,165,228,136,107,226,194,252,239,232,52,189,121,119,33,227,225,214,234,74,40,173,225,105,36,9,32,65,235,127,209,218,119,230,246,90,85,92,208,117,25,145,241,125,158,150,196,130,194,200,251,49,170,85,124,87,213,239,96,184,96,197,63,244,187,217,215,49,3,224,114,164,10,22,251,65,108,238,13,29,254,18,139,129,219,58,169,151,73,96,64,221,26,16,12,14,12,78,9,203,11,80,73,221,118,103,173,1,169,193,215,109,126,166,137,12,12,135,17,81,209,32,12,131,60,0,153,66,201,121,182,155,39,109,173,1,186,45,253,219,88,63,179,91,22,106,108,66,107,17,105,97,59,6,133,136,82,129,125,190,184,234,131,23,198,146,94,243,204,25,190,50,160,81,176,220,38,215,41,120,112,38,74,163,171,24,106,116,214,231,194,77,99,71,195,47,141,134,111,103,119,122,241,34,5,170,123,150,232,85,63,156,112,76,202,78,176,136,79,161,164,245,223,119,235,27,8,99,121,57,0,225,90,143,129,173,209,102,133,158,64,233,181,113,212,237,35,132,15,88,36,85,226,152,217,11,16,251,213,25,7,85,125,48,155,221,141,133,205,66,237,6,5,241,72,247,133,199,177,78,236,71,27,110,205,207,241,40,22,141,156,101,179,172,227,30,248,161,147,84,177,176,26,32,103,36,110,30,67,137,223,121,255,110,247,94,76,30,149,83,111,96,72,165,93,200,58,207,176,213,13,29,75,187,45,112,179,43,234,213,242,216,43,249,33,207,40,167,96,46,219,167,44,111,57,183,96,243,201,5,215,73,106,130,134,7,142,153,17,97,126,88,35,57,154,246,15,16,48,120,187,131,106,242,11,250,99,54,230,135,88,172,62,208,30,127,145,236,44,247,246,202,229,174,206,139,144,172,167,141,73,106,163,33,202,57,80,76,67,219,18,99,153,119,22,223,8,132,90,173,119,88,241,34,158,228,149,129,248,73,110,153,176,170,26,33,117,151,227,204,107,181,26,21,245,164,236,219,77,199,199,35,205,68,49,148,238,100,242,214,99,155,100,23,181,56,99,13,119,225,107,153,143,182,246,225,208,95,196,75,114,87,98,134,84,115,210,91,16,159,38,83,255,6,141,147,176,178,28,7,98,154,157,117,22,186,222,203,229,195,97,78,111,21,1,209,7,216,220,49,206,103,113,12,92,248,125,213,205,208,125,25,23,255,131,122,18,244,102,110,19,246,57,97,29,160,122,12,249,191,178,249,218,202,196,118,95,227,2,202,72,253,166,224,126,142,247,255,235,17,182,40,239,72,49,69,198,190,146,45,197,143,72,232,60,106,114,24,207,64,199,21,148,63,154,255,94,65,161,221,130,35,137,115,115,180,84,241,144,61,126,156,106,22,242,150,187,185,206,193,114,109,233,188,162,195,80,84,37,148,76,38,233,82,107,55,196,65,244,142,66,169,247,79,119,3,176,143,31,254,163,250,36,254,95,244,199,37,243,80,12,199,218,35,41,133,113,33,14,19,65,68,109,255,12,46,255,36,190,184,245,158,28,243,54,230,255,252,10,28,140,185,137,52,36,177,174,246,253,228,33,46,4,171,48,142,104,247,44,43,68,29,108,218,170,183,172,241,193,73,207,219,37,138,1,150,130,219,251,45,165,77,163,56,41,211,48,28,136,245,232,57,137,129,92,21,128,45,154,238,208,32,231,214,120,74,179,72,201,37,186,206,84,50,7,123,49,12,239,253,65,164,149,178,102,109,53,34,240,96,200,137,6,135,145,49,172,151,73,182,67,200,127,30,211,36,85,185,165,56,97,54,221,209,90,70,22,143,152,129,15,204,59,5,143,171,180,132,244,145,20,44,11,142,181,72,223,151,147,26,241,164,157,222,7,97,79,43,35,103,66,163,25,155,118,174,109,181,98,111,56,136,55,63,81,51,89,250,61,148,153,110,132,172,218,99,18,104,242,83,175,53,197,209,126,182,44,53,73,229,104,21,252,214,227,27,176,170,31,200,156,251,40,253,90,104,145,10,1,175,235,135,77,56,137,11,51,99,233,59,250,122,62,196,2,245,142,86,59,143,192,123,130,214,245,182,157,134,228,82,199,243,29,167,83,105,75,4,236,116,174,50,18,89,242,200,87,109,23,221,184,42,3,82,80,103,135,218,190,7,129,98,180,64,149,196,181,217,136,28,58,56,53,14,16,248,30,82,197,85,149,53,2,112,81,243,53,131,126,174,187,3,237,209,3,20,9,246,22,3,194,201,118,169,89,116,66,199,66,16,175,193,47,238,65,137,126,87,148,144,167,191,216,137,23,120,162,24,80,68,168,161,148,167,6,137,56,1,160,59,75,181,56,92,175,90,233,7,212,173,52,242,167,91,64,194,196,220,18,71,186,221,224,84,47,76,156,55,190,180,102,18,21,27,55,125,249,219,154,48,54,210,58,72,73,154,78,48,73,105,233,200,178,230,208,130,172,18,160,79,130,20,166,83,203,232,203,108,136,211,228,152,192,103,222,8,46,245,50,29,25,234,254,228,47,202,93,242,41,33,139,115,212,186,141,90,222,177,4}; diff --git a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_1spp.cpp b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_1spp.cpp index 303a9a2a..e7799ac2 100644 --- a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_1spp.cpp +++ b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_1spp.cpp @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // An Owen-scrambled Sobol sequence of 256 samples of 256 dimensions static const int sobol_256spp_256d[256*256] = {32,226,72,70,57,171,246,75,112,81,109,239,120,101,230,103,103,41,249,86,253,99,132,184,214,147,128,248,17,149,163,17,60,40,169,196,77,79,102,23,250,77,75,151,95,123,234,198,25,26,184,114,230,188,105,18,231,233,175,151,19,174,202,71,84,229,247,148,182,127,92,14,41,112,162,253,35,101,137,30,111,134,95,122,28,2,41,254,181,91,101,188,145,31,166,38,53,193,1,122,99,86,178,36,198,169,113,255,97,221,227,231,29,100,30,141,250,254,16,157,2,220,187,95,181,125,207,187,105,119,156,41,16,194,93,216,227,124,138,90,227,1,88,153,233,69,120,36,19,189,120,4,185,220,185,109,184,96,247,173,210,227,54,3,18,9,139,213,156,57,61,101,37,247,21,201,10,143,11,38,146,18,118,129,95,191,75,207,12,252,238,104,47,39,190,229,31,56,20,127,42,178,100,141,93,222,192,247,186,7,224,161,72,100,87,69,218,44,25,195,185,118,179,123,231,170,96,225,204,52,117,60,3,86,25,143,230,18,11,165,72,188,158,3,66,105,50,200,226,145,227,45,183,62,82,176,191,36,248,191,189,122,96,185,146,166,203,78,144,189,67,174,154,182,86,169,90,236,101,40,71,107,81,93,159,82,75,230,157,191,34,35,235,139,150,193,10,142,217,77,154,249,74,13,196,248,56,154,27,6,242,226,105,94,66,67,145,112,31,145,133,68,21,0,44,212,254,153,183,238,98,102,145,199,100,213,196,52,131,141,216,209,236,122,58,249,188,108,8,206,62,199,207,103,160,247,207,255,101,185,1,113,223,126,182,0,50,93,250,174,194,18,65,111,206,104,156,3,48,195,122,212,10,101,235,200,13,183,173,7,192,3,101,228,84,168,121,241,205,122,115,132,155,242,215,22,236,242,69,35,48,245,3,175,68,57,4,15,226,155,222,140,54,48,80,200,194,149,213,68,225,14,182,122,147,195,69,166,191,17,176,58,222,58,190,70,66,153,196,215,121,123,176,190,161,145,203,121,255,27,207,28,113,22,44,232,46,84,181,131,245,220,27,202,161,38,94,208,39,143,52,5,154,85,121,139,226,223,159,246,170,56,94,209,188,71,205,76,16,233,168,172,200,37,19,123,120,202,28,175,232,88,120,107,157,198,111,253,18,24,36,35,43,169,199,197,137,194,12,238,138,232,17,17,58,115,39,234,4,164,225,215,14,185,232,76,215,171,142,206,206,132,90,31,130,24,0,165,34,91,126,113,64,202,144,114,132,125,58,184,234,211,246,238,168,7,1,172,169,218,67,29,185,66,73,49,222,167,243,189,36,116,23,223,219,200,84,67,94,53,79,26,202,204,91,180,221,166,106,18,207,17,128,137,246,235,162,13,129,130,49,76,104,189,138,55,174,71,152,49,116,204,207,103,198,147,225,142,79,8,172,59,234,225,192,168,181,144,185,6,233,243,61,123,46,55,44,16,228,79,156,235,190,115,61,162,115,182,122,230,138,204,140,86,173,80,99,207,211,181,23,141,152,17,180,35,121,168,67,205,107,74,55,229,234,210,6,94,48,186,210,189,2,200,190,181,227,128,211,225,215,228,74,7,188,195,36,82,10,131,96,99,138,63,1,210,39,134,153,112,72,163,196,55,126,37,125,107,234,166,129,80,61,97,121,20,123,222,3,155,219,62,49,207,87,182,26,214,167,142,89,38,36,112,87,100,56,245,240,152,23,7,237,11,185,206,233,203,131,42,53,35,60,40,211,114,9,13,189,130,196,210,173,39,208,56,110,34,240,65,75,234,76,73,34,39,2,118,174,237,52,194,197,28,155,161,135,180,200,3,89,210,26,154,145,45,57,54,85,26,118,207,212,58,101,69,202,184,36,234,219,155,41,29,80,22,193,175,145,100,50,29,149,166,168,162,213,130,36,25,234,78,84,97,191,139,95,156,9,12,41,97,110,222,8,16,250,161,130,45,111,195,83,213,16,141,154,48,124,175,89,25,27,9,172,242,51,167,76,109,69,107,23,80,23,166,12,16,180,156,182,238,148,249,59,130,75,122,59,134,240,69,220,21,230,47,1,124,66,180,77,247,147,103,66,98,211,96,105,213,127,178,144,102,213,33,247,141,232,67,62,86,230,222,146,68,122,27,147,7,85,69,31,22,67,67,78,13,149,221,57,121,176,133,161,84,201,146,119,196,217,19,132,52,76,135,247,107,29,131,248,220,156,248,29,41,36,202,174,136,253,191,226,91,179,96,69,213,172,0,206,75,192,54,69,120,138,218,171,185,232,211,139,8,31,11,50,119,28,197,83,158,170,229,244,195,190,23,213,87,70,17,102,197,39,59,88,152,234,95,106,29,195,236,114,136,6,159,105,101,2,119,184,47,212,218,188,165,163,138,174,114,71,54,127,64,183,39,51,42,209,202,106,96,215,154,56,33,102,25,62,111,9,49,4,98,142,198,128,138,13,74,95,229,42,164,19,175,179,111,138,19,157,125,94,34,221,103,246,144,141,176,129,201,55,100,23,12,139,33,227,91,223,224,69,120,83,245,50,57,190,21,54,86,245,95,250,34,71,249,100,201,144,16,221,0,40,74,133,38,145,48,217,119,132,34,138,67,161,62,221,126,108,207,140,42,156,13,224,198,142,19,55,85,254,155,140,168,250,58,118,137,42,78,8,48,89,195,167,91,243,246,88,23,22,206,17,190,56,125,171,116,245,129,121,57,144,228,159,197,243,217,239,86,188,152,88,239,112,120,245,119,147,189,25,128,240,72,208,29,162,23,152,24,143,226,136,174,171,58,178,10,5,250,209,239,88,62,34,251,156,163,231,247,102,112,46,48,61,233,24,71,54,73,12,81,195,243,115,138,145,194,164,135,148,51,201,104,74,24,78,107,65,246,118,159,165,130,206,34,157,177,180,10,126,163,167,129,75,0,149,115,172,21,242,139,162,170,92,238,35,46,24,108,101,62,26,147,180,210,227,166,103,149,188,192,92,115,141,161,120,90,231,250,181,130,208,232,151,157,141,208,27,81,82,42,162,244,186,62,163,6,254,94,107,138,123,144,14,216,138,235,104,135,98,77,82,57,47,77,171,213,192,134,69,226,93,197,9,63,181,197,169,22,248,190,55,178,250,167,76,157,101,170,138,94,156,44,12,155,102,133,133,149,43,224,51,130,44,138,3,195,25,161,29,216,1,188,160,73,4,196,125,240,92,88,50,192,176,234,39,109,96,39,60,165,226,80,248,179,232,244,141,102,81,131,110,19,206,225,222,115,198,63,195,251,19,155,77,51,194,251,124,13,77,69,106,112,114,187,126,67,222,81,227,163,80,172,25,70,205,111,48,160,111,165,112,243,47,236,107,81,15,83,95,132,80,133,178,116,87,10,195,139,151,122,44,82,111,24,234,156,187,202,250,20,233,186,204,184,154,149,117,78,205,119,71,166,192,239,88,148,154,229,200,139,163,129,12,155,167,252,50,198,46,106,221,91,235,75,2,14,240,122,62,178,218,42,223,213,6,17,212,242,32,190,96,163,121,63,228,65,111,229,63,70,140,232,221,248,216,80,5,145,12,27,33,195,86,111,42,125,70,44,232,82,209,40,234,168,224,215,215,133,247,128,76,248,178,34,253,61,204,193,105,44,227,66,45,238,159,16,241,67,99,178,235,181,68,204,234,144,58,40,132,125,203,25,204,148,151,253,195,198,81,8,54,248,148,248,58,54,235,82,71,67,181,212,241,43,111,111,202,69,166,200,66,87,245,207,70,112,64,26,240,149,82,86,28,104,17,59,72,154,106,1,173,59,21,204,184,231,15,224,161,253,174,78,249,25,217,35,144,180,57,102,174,57,138,227,125,141,246,16,35,201,173,170,31,107,205,169,59,19,52,209,226,49,136,168,13,238,63,53,78,203,68,18,146,228,165,245,244,84,215,78,230,167,83,239,15,210,34,99,90,184,143,187,50,98,95,182,121,47,53,112,15,53,239,130,105,66,142,11,185,224,203,20,44,156,28,197,195,65,118,36,206,88,55,37,18,112,9,20,231,73,6,11,225,79,180,145,124,204,29,245,148,198,53,210,171,103,53,215,106,111,154,237,107,2,249,79,145,126,255,255,53,222,196,57,237,131,6,63,45,70,68,190,191,12,210,247,162,41,135,184,234,206,153,176,115,255,114,178,110,24,25,66,114,55,29,79,253,67,124,245,37,236,13,88,232,186,18,143,178,59,5,237,10,249,253,37,88,46,134,71,53,74,172,186,69,137,11,154,60,68,120,125,100,91,182,239,177,38,28,125,208,165,38,150,207,244,41,88,127,241,251,168,84,195,111,37,211,165,113,3,212,184,180,207,48,52,204,171,213,128,154,138,218,69,214,154,99,201,203,109,93,71,190,5,99,1,72,173,15,149,49,253,51,82,171,179,114,131,68,114,133,15,104,227,141,109,39,68,225,130,50,51,133,154,148,48,28,230,9,43,157,50,133,203,239,37,160,233,120,54,20,116,57,174,116,158,45,8,196,14,200,80,203,212,233,1,0,88,172,214,196,22,192,224,142,138,146,230,105,100,153,155,112,241,124,26,71,253,143,4,191,50,49,88,226,25,142,141,13,12,50,159,122,211,42,168,23,217,253,218,151,135,3,152,114,102,191,76,186,42,124,70,19,56,25,85,234,58,57,225,230,253,56,194,107,134,142,201,213,43,14,33,242,16,141,205,196,99,143,100,115,5,99,128,100,221,174,110,191,83,165,164,78,60,124,209,199,63,185,120,175,43,3,24,40,153,1,83,147,223,112,72,242,148,166,115,36,138,42,13,63,1,45,173,225,83,121,19,23,208,171,146,240,108,150,3,213,83,210,238,72,120,80,197,2,4,159,197,138,216,19,178,24,173,212,237,169,129,129,102,51,63,203,142,11,134,180,207,105,98,133,253,20,224,6,126,194,167,33,132,90,101,179,113,216,222,132,30,88,23,229,210,85,6,154,226,252,17,39,174,208,255,8,11,252,159,110,195,86,250,59,161,218,31,140,167,41,33,201,143,250,68,82,205,44,4,77,43,214,212,60,82,214,41,44,125,236,152,34,64,133,184,58,145,227,65,70,73,166,49,21,158,242,114,42,75,209,36,72,188,192,146,223,138,76,27,235,115,153,105,169,96,209,231,4,33,105,226,175,187,91,218,12,73,168,214,254,98,208,113,214,116,177,49,34,94,22,127,175,12,155,193,56,187,115,187,240,136,234,206,189,250,115,219,154,17,52,62,198,63,225,81,77,90,127,246,219,192,106,223,78,102,88,142,46,208,156,230,196,67,182,18,112,210,126,198,59,15,234,166,243,77,61,149,24,223,70,245,142,178,199,101,195,190,109,78,244,224,12,84,52,158,184,88,212,155,159,128,187,54,48,209,190,202,157,70,122,109,33,221,124,227,1,196,124,121,163,138,238,25,129,134,83,111,124,60,142,46,143,48,85,63,5,77,46,251,193,209,81,108,149,108,1,47,137,175,85,106,148,27,204,145,104,3,152,84,228,215,113,141,6,117,115,151,206,248,61,43,182,198,76,88,12,222,132,75,73,8,205,190,32,12,159,70,205,4,158,0,107,220,104,90,223,181,80,7,111,166,130,16,168,145,218,242,101,35,165,172,12,217,239,157,76,37,238,176,63,124,243,45,101,181,191,200,64,186,170,42,104,154,191,224,67,145,240,72,82,103,93,108,220,251,36,178,110,145,98,136,83,2,171,177,220,23,98,221,2,160,216,219,237,90,105,255,48,157,136,55,102,122,181,7,225,55,229,254,215,169,94,22,44,65,136,50,190,151,198,54,132,81,245,106,71,91,141,176,162,15,210,33,14,140,108,81,17,135,249,17,44,15,121,28,16,114,178,210,7,129,250,11,239,18,86,203,161,124,2,185,178,83,110,168,3,81,125,80,149,8,67,30,212,0,129,8,77,255,114,243,68,8,119,210,232,104,244,127,165,159,26,176,206,160,228,34,116,10,3,91,65,149,163,43,43,44,171,113,113,223,206,17,63,64,215,216,94,118,5,139,66,201,213,30,120,149,18,236,99,41,81,175,245,1,7,171,209,151,134,28,32,122,201,13,18,46,236,215,113,188,192,221,39,69,117,121,255,119,26,59,142,121,126,238,179,163,183,245,98,199,32,46,39,137,236,232,52,138,4,60,86,83,12,100,44,195,49,107,228,105,56,183,18,177,222,50,189,188,97,197,148,94,99,1,198,221,121,206,54,31,212,145,62,73,77,213,189,38,66,13,139,69,173,57,26,11,176,245,141,166,141,203,10,48,45,201,17,131,241,115,13,165,235,28,129,88,72,36,124,169,128,6,145,10,109,219,198,187,90,149,67,215,68,116,33,56,204,217,236,231,0,205,84,97,113,175,30,185,95,187,166,164,123,103,0,218,18,150,180,103,151,153,146,97,15,161,171,246,252,131,198,186,58,55,210,93,58,157,3,142,220,98,50,202,151,2,115,205,200,3,236,146,210,233,71,222,129,198,18,131,29,157,152,63,201,45,197,253,170,121,124,232,64,197,112,22,208,106,99,54,41,247,146,135,234,142,177,3,38,157,234,222,46,189,233,76,41,150,255,135,82,99,244,246,187,81,215,16,76,188,188,104,156,21,239,255,206,97,35,217,194,13,70,106,106,238,171,232,93,223,145,190,50,39,144,48,13,113,146,151,178,156,18,131,231,168,108,178,224,7,44,122,98,87,166,65,220,174,138,98,95,93,188,127,246,195,136,215,160,201,137,35,217,167,126,219,175,109,180,111,127,222,93,69,133,2,58,198,186,238,108,57,157,101,174,249,26,46,210,254,251,76,43,197,209,161,52,197,28,246,173,229,35,43,13,81,122,34,245,212,223,50,135,69,70,192,171,78,9,135,189,54,168,232,131,250,208,59,227,252,247,231,40,235,203,254,51,25,198,223,165,81,140,141,67,194,180,31,194,172,47,195,56,153,118,221,30,217,17,85,154,184,122,15,130,179,86,8,37,33,200,95,144,73,175,68,185,197,128,182,154,171,147,182,86,172,23,236,20,92,194,110,253,124,133,82,127,206,92,34,108,69,170,47,61,41,87,108,218,3,244,7,124,51,153,83,186,164,116,154,85,123,43,135,177,107,28,189,81,241,214,189,235,233,142,6,109,183,130,75,79,107,99,67,31,164,248,227,114,159,230,115,116,115,252,33,75,4,171,191,217,88,245,156,203,48,239,140,253,211,46,184,136,34,21,248,161,128,156,16,88,64,71,34,174,125,70,164,125,92,205,214,79,157,199,223,143,214,138,213,150,169,17,16,181,95,200,208,91,91,55,125,7,1,39,91,6,103,252,246,22,71,110,149,236,73,1,247,51,2,168,88,124,234,86,100,6,94,1,17,215,157,34,238,126,194,222,109,67,175,96,45,252,99,58,3,34,192,251,95,240,36,188,243,191,229,74,164,55,171,108,239,73,208,140,114,46,244,36,30,33,56,14,209,94,86,28,9,153,30,23,102,165,252,98,77,72,233,22,126,152,98,40,246,35,93,137,114,191,114,200,54,214,8,238,145,43,119,180,186,55,74,170,232,166,247,56,233,9,162,16,241,95,47,5,109,72,125,67,35,130,55,138,75,157,246,85,244,3,230,60,226,159,12,234,155,160,180,119,243,253,179,202,194,53,218,65,208,230,212,71,228,29,49,220,31,146,244,249,84,46,237,203,93,171,73,33,115,46,109,10,163,137,73,18,133,213,236,174,230,216,119,127,80,199,18,100,180,236,191,127,152,158,226,45,72,70,181,106,90,21,229,46,41,109,55,237,81,0,158,169,63,40,22,85,246,181,235,161,180,28,175,136,87,132,184,54,121,185,69,89,58,20,54,81,101,87,37,251,152,4,162,108,113,248,178,219,151,240,144,158,242,185,138,4,34,148,255,250,66,75,144,141,25,248,244,89,180,203,97,141,149,179,129,213,186,64,101,242,119,130,121,108,230,198,74,228,155,96,237,140,201,158,44,127,161,120,219,94,11,95,27,145,80,184,107,215,88,252,32,89,59,97,159,249,183,75,131,180,65,184,179,85,80,88,74,128,53,126,191,54,169,0,133,100,248,196,158,91,121,110,12,248,130,87,248,186,85,136,101,181,0,90,45,34,227,84,17,40,96,221,187,167,131,112,48,70,62,240,138,78,245,248,226,203,255,32,242,246,141,200,17,167,32,151,12,72,159,221,190,56,115,237,233,226,113,71,228,167,60,113,127,28,174,27,176,227,160,77,221,157,64,14,166,82,60,78,7,91,16,214,169,78,222,97,33,229,210,4,255,104,234,42,181,7,177,190,23,40,135,53,67,63,28,151,60,167,81,21,190,110,214,160,222,51,228,87,83,113,220,46,182,163,193,79,214,249,120,197,244,197,169,252,20,33,253,246,46,198,16,208,35,110,5,37,236,172,149,234,155,32,36,8,249,70,224,226,40,16,146,131,224,173,250,111,102,227,160,196,255,167,81,196,62,24,6,39,4,245,139,98,158,201,247,5,6,2,61,92,5,65,70,24,206,135,30,246,146,155,22,29,247,25,112,186,5,208,134,240,95,137,29,48,148,222,92,36,165,248,10,244,222,158,131,46,156,217,243,219,101,123,98,209,124,89,178,16,48,173,142,241,134,127,160,217,64,134,35,244,28,253,59,26,10,212,162,143,252,94,0,198,0,16,156,116,145,64,255,206,234,251,104,250,213,247,171,89,86,125,48,237,216,196,160,45,90,227,12,33,58,31,88,200,117,101,36,105,135,49,134,64,181,233,40,63,100,189,192,13,48,58,159,183,105,34,162,170,166,132,83,141,116,29,39,216,84,29,224,211,54,145,251,248,148,150,203,26,51,179,47,134,175,80,66,223,24,221,52,170,59,241,37,95,232,183,15,162,203,144,221,60,248,8,211,255,78,249,55,59,23,131,11,165,152,182,82,168,71,89,48,249,78,107,182,117,73,21,79,42,128,232,89,103,207,13,224,32,236,175,138,201,54,26,98,122,91,253,144,222,108,171,101,120,208,168,40,29,46,64,23,171,248,115,40,80,28,107,143,65,188,142,205,155,234,86,121,157,124,23,44,177,188,201,222,229,244,169,241,155,62,102,187,15,28,49,168,157,29,135,202,9,160,102,125,112,184,31,209,162,114,13,130,215,93,15,255,110,50,54,19,144,98,47,46,170,252,210,5,161,176,69,185,97,187,253,94,124,215,85,69,73,136,150,68,137,217,52,113,151,241,70,44,102,126,10,143,167,133,81,239,233,109,73,171,141,93,133,112,185,133,103,206,49,208,130,79,127,234,48,173,231,82,200,74,68,194,188,185,26,56,199,134,122,3,153,227,174,245,23,34,49,20,68,184,202,1,232,252,31,171,45,85,7,114,187,66,203,169,98,117,144,15,165,104,143,111,174,100,197,60,7,53,248,238,100,12,162,96,40,189,247,101,64,57,57,14,195,114,229,155,228,32,111,37,141,8,8,163,2,223,6,96,54,144,175,85,141,51,77,41,60,192,113,15,103,101,44,30,102,189,100,251,227,71,37,62,123,4,63,119,25,116,47,205,191,156,1,106,136,248,37,151,162,72,226,41,208,133,69,146,114,137,43,245,90,115,117,90,122,134,180,218,136,10,36,210,53,138,90,139,213,130,56,173,119,174,71,72,213,138,87,171,101,156,110,0,164,38,191,156,215,148,220,106,138,50,237,54,37,49,215,127,45,81,226,61,181,195,147,154,208,170,94,34,8,228,121,71,182,239,63,56,65,244,0,70,162,73,198,63,16,134,216,58,187,203,234,115,44,209,105,127,183,130,74,82,203,219,128,128,162,13,47,106,252,31,56,155,184,119,56,139,70,241,3,104,153,43,183,28,68,241,224,25,154,52,51,131,108,142,150,13,106,43,251,166,76,47,218,150,11,125,109,109,179,145,213,217,241,16,32,208,48,33,217,59,171,245,248,174,34,191,77,111,183,221,49,141,59,221,76,224,103,190,107,171,215,232,44,84,133,236,88,227,175,24,57,144,252,229,182,140,36,219,42,92,101,187,212,188,34,205,167,99,168,91,224,154,187,112,52,190,62,212,191,250,250,68,229,248,142,143,161,185,243,117,222,69,61,162,247,179,140,133,135,164,217,144,222,8,114,20,240,161,44,27,187,82,122,237,53,167,43,2,215,122,219,61,163,54,181,154,176,222,239,12,13,63,88,213,167,98,162,94,254,89,113,112,242,88,158,65,229,215,16,126,234,96,129,34,233,231,85,152,90,16,97,32,90,134,18,131,114,130,148,249,76,135,186,171,103,192,83,45,100,96,36,88,217,197,165,86,194,168,112,149,125,108,133,112,117,199,26,221,35,245,88,233,9,113,47,138,31,61,114,47,51,32,197,55,17,175,164,93,204,223,215,203,221,224,147,103,78,214,230,214,71,214,220,169,117,39,0,147,198,108,242,153,155,144,235,250,162,35,53,61,45,156,227,244,108,123,32,227,129,77,252,146,213,168,197,237,147,123,38,228,75,144,165,144,102,113,198,22,145,14,101,195,177,43,62,151,113,96,81,189,204,180,207,197,24,72,76,135,127,181,246,81,18,167,113,85,184,62,190,140,86,209,148,134,111,32,60,108,33,233,115,99,216,239,112,146,92,217,236,252,213,215,98,122,215,64,175,155,179,121,195,7,207,252,163,51,58,143,187,255,188,122,6,199,73,36,149,218,141,142,43,108,99,2,232,187,65,216,24,169,125,102,148,113,59,233,176,194,207,77,204,245,20,43,145,104,88,88,212,187,237,152,64,18,141,254,53,255,111,53,61,62,49,143,145,197,10,207,36,198,166,88,7,199,42,201,145,219,135,53,239,108,162,82,202,181,4,255,82,23,38,141,213,120,0,218,105,2,141,120,255,138,20,27,255,97,202,151,0,166,227,16,196,48,139,91,164,4,170,177,243,27,154,220,212,167,205,179,84,245,205,50,51,155,45,39,99,124,70,27,48,182,173,3,26,38,214,1,26,23,216,248,214,89,78,142,7,44,2,118,103,73,72,202,187,222,242,74,37,84,166,251,191,67,11,231,116,61,33,17,96,93,116,165,173,88,153,105,123,125,159,243,89,143,66,211,213,23,47,204,192,2,231,229,224,32,30,45,9,31,149,216,137,119,152,34,22,131,206,47,216,201,89,197,58,66,204,67,92,0,150,199,161,213,185,96,252,164,78,46,247,41,134,48,118,14,77,30,250,176,12,138,96,58,51,142,9,249,103,99,29,247,189,31,126,29,86,211,201,108,216,195,90,32,119,124,219,207,128,192,119,91,217,60,215,24,182,244,100,241,153,24,3,99,115,167,33,25,239,186,42,198,202,179,57,117,112,11,208,212,50,26,170,22,148,206,252,232,159,56,64,37,184,40,232,109,62,164,199,64,198,112,56,71,12,215,108,220,20,211,118,70,182,19,212,219,182,104,5,188,255,61,162,241,25,176,78,25,176,239,21,205,246,214,246,86,45,101,158,9,252,149,38,59,72,225,119,121,209,20,85,6,84,253,24,182,126,20,150,105,176,238,54,59,96,46,28,214,21,80,112,19,118,125,115,134,244,30,35,230,238,255,199,220,32,200,9,142,2,182,14,101,191,176,143,96,217,200,124,194,43,105,61,93,143,135,53,12,228,233,30,150,173,228,73,179,184,84,21,117,63,245,231,49,129,29,249,46,23,172,195,94,36,76,227,246,71,159,188,8,88,119,49,177,156,203,88,101,195,170,151,183,106,100,9,246,64,254,1,90,4,9,163,154,231,88,68,182,99,67,75,171,107,142,196,79,237,114,70,178,128,33,83,168,67,129,82,214,135,38,206,41,152,140,168,52,239,28,171,28,29,180,246,185,183,243,85,129,112,168,63,139,133,0,162,86,166,48,132,244,159,151,235,175,64,110,168,85,97,233,11,62,25,177,16,57,124,63,250,59,218,136,209,136,192,23,168,160,206,65,84,30,73,213,235,181,104,66,27,98,126,183,219,93,200,115,84,141,57,55,20,131,91,14,228,85,181,19,4,110,176,90,101,40,91,107,155,7,70,21,114,154,141,146,125,246,64,1,216,213,232,23,143,224,115,244,247,144,186,71,134,69,183,141,25,186,91,29,145,163,250,202,181,57,216,172,131,228,242,181,187,52,94,218,252,4,118,44,52,124,160,37,176,17,218,121,140,191,107,102,91,222,49,91,229,106,179,221,170,200,88,38,138,167,10,48,157,47,99,57,137,88,76,206,141,214,208,48,80,226,18,227,6,175,180,63,107,247,251,197,59,51,247,13,109,209,162,206,192,125,112,94,235,247,26,88,14,126,241,225,249,81,162,7,157,238,150,138,24,69,121,155,219,17,169,180,218,93,230,99,92,139,53,179,145,30,14,205,171,75,247,49,194,3,14,177,24,222,122,30,75,174,121,243,104,233,244,81,4,47,70,43,206,113,229,119,231,49,72,144,78,214,29,193,41,75,14,97,19,84,148,246,3,250,243,7,246,233,153,48,135,226,204,199,93,210,3,97,11,106,117,170,122,92,97,150,179,177,220,46,59,17,151,242,160,233,237,81,78,255,87,243,237,113,135,216,131,97,197,224,41,142,85,234,243,135,58,152,220,191,227,149,78,77,30,82,167,63,217,43,227,106,173,223,128,161,49,70,29,184,169,178,179,124,224,2,243,210,229,112,103,15,29,78,229,91,9,68,198,94,135,241,207,69,183,229,46,78,63,189,93,163,10,91,172,13,205,180,217,216,102,237,239,3,217,247,218,0,147,130,158,175,242,39,94,23,238,221,229,211,72,140,103,207,7,73,10,200,247,155,254,35,165,152,2,137,237,154,128,235,215,210,1,132,104,143,128,91,191,225,241,171,220,16,165,209,59,10,1,128,151,229,116,17,20,188,108,57,196,105,197,5,64,216,75,255,49,10,35,243,39,238,142,201,1,32,8,28,116,21,216,226,89,90,231,210,128,81,149,93,249,111,150,128,11,228,231,236,178,74,34,174,187,230,84,78,197,136,17,197,25,242,154,123,24,78,245,178,254,76,70,182,72,15,115,54,62,10,89,172,129,113,97,148,204,240,100,172,169,122,13,95,182,26,184,25,191,255,250,250,137,18,19,72,145,135,112,125,227,63,65,26,54,228,181,30,158,27,191,9,236,168,115,248,144,187,132,253,45,84,154,196,103,30,149,123,53,42,206,172,146,175,44,203,69,239,45,147,0,121,103,125,132,136,192,38,62,79,29,241,17,151,110,28,38,221,234,230,228,182,64,241,144,165,124,145,120,49,50,129,18,33,242,212,143,68,167,109,134,179,113,176,85,93,87,105,133,15,66,249,8,43,9,147,72,30,6,2,85,185,204,160,20,76,70,119,163,67,200,121,228,185,204,22,48,31,122,177,123,93,159,108,114,65,90,91,67,95,139,6,187,3,78,142,38,96,61,68,23,146,93,32,245,153,131,61,126,1,194,201,158,51,161,172,0,176,76,143,229,81,201,36,157,210,139,109,215,12,9,41,152,243,188,240,144,194,27,114,193,162,39,43,9,203,46,137,76,217,93,125,215,74,43,75,0,153,246,95,88,44,134,248,43,87,166,46,133,1,77,197,205,206,31,50,102,178,248,22,226,192,156,203,195,155,193,32,35,158,173,76,75,79,240,112,7,161,130,162,85,225,67,223,15,127,53,24,49,231,201,248,16,114,146,228,17,178,247,166,162,2,32,180,41,188,9,197,103,77,246,35,30,71,112,6,222,168,64,60,248,242,61,201,130,219,58,182,38,143,103,45,104,219,7,121,119,138,183,148,149,107,216,169,2,89,111,185,120,49,74,173,174,35,38,194,214,86,32,216,229,123,41,64,108,178,152,13,174,71,86,192,147,84,112,246,98,151,238,63,210,134,112,5,28,254,154,125,236,82,78,22,114,230,212,88,97,54,211,70,203,48,159,59,21,36,55,56,141,194,247,133,160,138,224,66,180,74,137,37,94,5,120,135,170,119,209,147,221,28,19,215,139,29,199,87,234,102,225,111,74,180,27,169,131,129,29,44,138,81,235,206,181,229,133,192,201,163,110,48,203,245,95,200,183,29,29,31,255,74,216,148,92,109,191,130,29,236,248,204,126,228,208,76,200,13,128,197,198,255,211,23,197,132,124,133,71,155,21,132,233,191,189,212,255,108,47,94,109,53,232,234,95,174,83,223,18,188,255,239,215,139,141,51,127,243,199,103,111,117,45,101,67,184,104,196,20,34,25,184,251,144,47,226,217,214,217,125,47,52,41,242,113,104,13,56,74,44,166,36,63,154,133,145,18,80,160,124,59,47,48,219,63,43,134,67,115,238,189,252,67,6,164,83,181,123,230,213,252,7,222,130,221,30,79,68,34,162,2,61,134,162,207,49,146,161,216,82,98,181,190,57,57,164,128,97,121,148,131,128,152,66,106,247,15,154,148,82,42,174,142,17,249,123,23,138,78,106,245,159,202,19,26,160,50,138,153,136,182,101,89,247,195,169,69,220,50,155,45,140,251,248,183,139,84,17,44,98,83,13,102,234,106,135,22,255,212,246,163,28,11,251,123,18,5,150,221,6,2,137,17,176,56,215,12,166,187,52,149,11,97,119,140,245,13,201,20,98,80,27,26,125,126,58,232,231,83,52,195,75,116,248,147,230,123,171,77,81,168,163,120,39,158,18,54,60,212,117,67,148,122,151,78,51,30,88,27,152,83,92,191,105,162,106,233,12,27,116,4,53,100,189,242,253,169,182,10,105,196,84,229,122,141,80,15,0,38,26,50,176,229,18,32,169,241,202,190,190,225,100,193,44,196,209,193,83,89,43,228,8,127,48,9,221,186,199,251,97,138,218,190,131,202,206,62,148,128,44,48,107,164,177,57,149,171,214,244,57,198,194,87,179,232,10,17,65,243,255,109,19,208,42,55,68,178,164,84,21,57,206,5,27,252,203,144,108,90,231,137,198,221,204,164,204,56,73,223,129,127,246,244,144,140,13,229,195,199,39,42,93,103,202,8,45,68,203,17,186,154,9,154,228,59,255,134,120,125,170,90,18,141,31,17,116,10,189,48,63,147,112,188,11,184,92,95,253,180,92,80,106,57,112,187,229,228,69,3,1,47,47,72,146,48,135,37,111,82,27,20,77,157,222,115,123,120,119,159,196,99,7,116,57,222,119,79,79,212,213,215,145,225,154,187,25,22,126,89,170,169,123,159,94,29,177,63,137,207,167,192,97,134,193,17,236,199,8,35,214,220,156,72,183,180,8,63,200,171,93,216,103,110,145,159,209,158,236,233,50,228,220,144,113,159,214,222,157,156,27,133,183,240,127,191,28,41,222,148,155,247,32,97,96,128,237,98,236,159,107,157,192,176,19,81,248,145,219,183,179,73,178,81,38,137,81,108,189,148,180,164,63,244,107,140,13,253,2,84,88,16,121,200,120,77,203,104,24,207,202,194,62,253,155,102,96,168,116,28,237,163,138,91,149,34,82,230,211,109,230,176,130,28,82,186,233,159,99,238,249,81,38,106,243,246,4,63,80,43,104,47,1,253,236,84,79,158,5,81,26,18,242,70,42,11,229,216,154,236,16,203,159,227,7,207,120,26,197,81,87,177,4,32,197,147,111,255,229,91,211,194,195,230,35,169,151,31,196,33,181,120,192,254,71,84,152,228,208,209,129,98,55,39,210,144,146,192,231,249,121,170,81,218,202,197,150,149,234,93,90,178,167,209,244,86,25,140,141,156,206,14,247,240,217,14,39,99,82,121,16,119,157,210,169,220,50,58,255,48,130,189,120,154,59,60,85,94,135,23,15,171,6,31,212,224,89,73,100,179,91,61,170,128,28,33,227,9,149,128,12,110,120,44,9,52,192,4,24,65,221,114,24,77,109,0,237,94,4,42,232,84,150,134,32,50,33,84,234,130,136,89,117,253,79,60,135,69,29,50,128,196,38,41,43,37,78,168,73,163,249,45,207,177,76,38,115,76,143,118,145,106,166,6,142,230,193,147,145,87,195,222,73,219,219,89,33,68,237,118,120,146,164,74,130,237,16,47,79,228,9,153,184,5,127,80,182,81,105,196,51,244,192,237,160,118,200,191,94,235,152,191,202,161,231,171,19,116,102,94,206,253,175,4,193,18,70,53,214,98,123,181,137,167,190,84,96,169,2,204,232,54,221,169,175,186,172,137,170,75,32,249,57,119,86,19,52,123,234,142,11,108,19,58,84,98,250,242,114,170,31,205,195,117,12,243,41,93,222,0,101,219,102,129,196,192,91,8,186,233,243,37,194,183,162,121,59,93,71,52,178,114,96,72,252,185,254,109,31,107,112,168,64,226,160,216,43,49,74,50,139,112,148,135,148,88,184,35,26,29,171,245,47,96,61,39,146,159,194,252,57,202,244,245,218,216,18,29,71,237,39,25,197,164,184,67,97,53,45,16,218,207,244,97,249,96,167,93,62,103,162,164,67,186,159,2,26,136,32,184,9,167,169,183,210,72,43,253,167,72,211,171,205,117,92,82,32,5,197,107,8,68,106,237,8,142,148,101,227,90,210,67,13,252,233,3,242,79,95,172,175,195,246,251,254,247,71,7,224,252,37,255,4,158,178,131,23,77,77,22,178,114,155,151,162,207,53,98,63,132,143,232,73,194,185,91,243,57,47,83,36,154,42,31,150,56,15,33,40,14,111,70,137,225,158,138,108,119,114,255,48,176,231,182,51,219,163,86,122,80,104,197,169,107,181,97,55,228,63,47,73,106,27,23,65,207,177,34,218,221,147,192,237,165,74,89,152,255,181,169,250,226,99,10,232,6,181,45,3,222,174,26,248,155,12,199,237,65,205,85,22,125,164,146,124,17,73,140,71,36,57,173,173,157,157,161,35,164,157,190,71,67,29,142,133,206,231,64,185,95,111,65,166,220,233,245,73,242,25,16,29,223,124,142,199,177,13,24,198,245,218,190,115,38,32,45,236,12,96,101,63,17,230,151,217,117,234,153,112,111,91,162,196,247,185,166,60,2,8,145,56,160,48,175,226,250,67,51,132,106,42,213,138,119,167,9,240,25,8,56,22,165,218,9,62,218,121,29,43,177,130,210,166,150,15,220,225,225,152,34,255,104,115,223,108,131,55,250,255,49,92,130,20,179,218,73,38,116,122,102,17,118,237,183,109,65,232,122,235,4,68,3,245,160,150,224,73,183,115,6,100,124,166,210,201,82,249,142,15,23,20,60,118,137,170,181,229,205,108,201,240,169,87,195,99,76,138,15,228,158,47,216,146,8,248,175,110,207,39,94,180,173,250,47,24,2,201,150,241,233,238,16,120,75,140,84,49,212,106,98,213,162,86,181,76,170,35,124,116,48,164,197,74,131,117,229,28,19,139,154,0,123,202,110,178,10,79,113,166,22,172,117,191,54,48,27,183,59,223,105,57,148,54,241,188,72,118,58,255,33,235,238,206,33,254,197,162,45,154,226,221,57,145,225,19,36,11,164,245,79,188,132,50,190,248,255,75,183,214,242,69,109,232,147,130,166,70,86,58,124,161,96,88,92,166,32,184,117,117,232,148,14,163,81,163,242,0,239,41,82,240,105,189,74,68,200,164,195,85,62,74,56,226,196,41,2,105,154,95,205,207,232,106,98,226,99,112,210,188,162,203,188,28,65,78,18,252,134,93,120,74,188,64,154,12,133,146,228,14,25,9,13,157,22,83,145,169,201,189,221,137,49,232,138,179,182,165,146,2,109,172,21,172,40,157,230,199,70,170,17,231,133,250,192,45,75,214,33,111,3,120,209,54,12,206,159,226,150,136,96,94,25,66,56,178,106,7,73,214,104,156,236,28,249,93,15,229,9,0,132,16,69,155,125,179,207,94,14,13,244,207,241,54,32,52,63,98,162,154,191,75,209,229,33,193,255,57,31,229,86,153,43,207,166,165,245,54,40,212,29,222,70,136,130,40,74,185,218,104,130,108,129,245,188,86,215,76,131,33,190,168,234,99,175,11,251,216,73,187,108,44,255,201,238,119,247,44,86,81,235,45,3,57,216,75,34,73,180,36,35,240,164,214,36,117,135,41,119,211,38,76,81,196,8,21,97,136,235,119,71,123,36,176,199,227,228,108,128,149,137,5,164,77,148,159,81,47,176,108,234,54,46,235,56,167,178,84,254,105,129,190,49,65,57,236,213,149,152,10,85,206,195,221,92,221,54,74,114,134,198,83,208,132,62,75,99,76,23,147,221,170,238,47,2,231,238,159,31,157,21,230,120,116,37,205,171,183,193,105,172,143,117,1,93,76,23,54,218,89,41,8,34,70,14,172,247,13,165,93,149,104,106,13,209,88,202,31,127,1,56,213,196,57,128,219,160,128,36,102,11,50,241,144,120,109,249,181,6,101,158,193,159,198,121,72,53,117,201,226,238,36,19,89,190,170,97,242,166,133,255,187,116,117,149,110,240,34,46,115,10,173,23,253,193,26,88,218,204,250,37,212,109,250,201,191,194,118,95,136,247,161,207,241,204,135,2,78,149,74,112,131,147,47,174,61,6,17,165,170,245,205,230,27,4,219,42,253,132,224,5,105,216,149,164,189,139,111,218,70,124,62,36,131,167,58,160,166,166,15,182,6,55,43,51,18,46,56,174,90,10,0,14,29,74,85,33,208,147,69,176,90,198,106,36,37,30,25,35,124,178,130,4,84,25,198,20,229,53,83,27,191,7,155,221,115,87,5,220,83,80,84,102,251,48,221,102,199,149,98,72,199,4,97,43,61,78,97,140,141,115,8,36,76,209,170,73,151,35,27,50,135,70,240,173,0,121,54,23,163,78,109,212,129,93,171,216,134,28,83,113,141,233,192,101,187,144,201,55,84,241,226,162,50,111,152,243,114,9,111,93,4,89,234,55,65,28,241,78,143,188,189,252,70,80,238,69,204,212,181,122,171,109,189,186,144,136,240,116,95,234,155,53,70,170,203,113,36,46,45,134,195,163,140,104,104,25,181,136,167,116,55,237,25,77,120,91,44,239,159,52,190,41,227,220,175,171,101,213,127,105,222,163,58,68,40,210,118,247,1,76,42,20,189,248,76,43,113,25,81,37,26,154,234,25,226,251,39,69,143,3,138,235,220,47,9,31,25,63,195,193,72,173,92,80,43,152,143,80,74,126,49,33,238,113,228,171,168,241,82,49,174,116,73,94,130,72,230,253,161,187,183,237,195,41,153,143,130,252,152,169,147,185,106,2,207,13,134,90,175,141,157,242,255,161,154,42,107,178,145,195,16,211,119,181,175,211,84,142,39,77,187,239,159,12,177,186,243,150,95,140,58,167,52,103,146,158,98,247,173,141,219,214,180,87,55,184,155,216,203,67,81,243,45,171,219,220,110,144,106,5,138,225,212,232,110,202,220,68,84,250,115,120,118,200,167,154,108,73,90,190,72,34,47,249,229,114,4,80,142,144,22,68,254,128,128,196,171,194,100,131,176,168,30,203,107,42,65,59,156,176,21,156,53,86,125,203,58,216,87,127,233,238,153,162,195,175,35,133,212,69,25,61,96,246,99,19,132,120,219,58,140,93,223,248,9,43,246,147,166,10,33,40,237,26,6,87,228,81,182,159,34,234,48,74,27,30,186,36,136,63,92,110,3,131,130,27,239,155,0,156,219,146,232,148,189,133,204,227,35,102,6,13,242,251,69,127,251,171,127,248,242,116,126,174,84,115,6,193,135,29,128,225,230,162,23,222,79,106,4,26,156,61,251,88,57,81,76,237,7,19,107,37,95,147,230,99,193,76,98,87,252,124,217,105,200,201,204,245,189,226,154,95,54,19,34,64,85,66,163,243,6,203,46,201,0,174,183,154,181,226,46,152,199,255,75,54,243,29,83,133,231,240,6,21,38,68,184,253,109,54,23,224,31,102,11,112,103,43,17,38,125,238,71,104,161,159,219,136,215,196,141,170,10,56,156,93,207,152,188,114,22,157,0,165,25,138,205,58,248,67,193,58,28,147,32,38,229,221,175,114,14,42,161,2,223,231,204,164,6,92,49,52,64,37,164,223,252,197,118,55,243,108,10,158,239,219,175,244,102,22,194,134,212,9,249,244,43,86,97,41,53,9,224,110,61,250,140,202,187,95,171,204,21,221,58,141,24,176,120,96,194,232,84,28,125,246,218,142,73,131,254,249,22,179,71,110,208,97,247,139,162,171,64,251,79,190,180,190,186,29,110,165,88,119,225,30,58,64,49,68,45,83,93,122,136,199,146,158,106,5,211,222,64,64,160,74,72,185,138,112,186,135,133,95,31,236,77,86,54,59,235,32,245,245,133,152,27,233,115,154,253,233,222,36,218,216,218,211,137,127,103,199,95,165,151,234,33,228,72,167,103,13,43,119,38,71,23,218,227,177,230,222,214,149,81,102,246,94,251,84,233,90,116,77,26,118,194,122,55,75,208,137,52,159,238,73,8,33,157,218,178,213,108,45,131,207,210,31,144,133,204,239,144,183,230,251,195,57,195,154,39,61,36,39,117,126,121,69,224,198,15,198,98,59,82,181,202,28,149,49,219,53,48,163,19,164,57,251,219,61,159,235,12,121,100,151,160,191,93,194,90,22,119,28,191,219,210,170,234,145,2,111,53,86,140,171,46,232,231,111,18,43,83,2,142,131,38,36,99,174,3,26,169,105,31,214,250,212,191,8,1,141,69,73,158,180,248,93,117,146,242,10,188,63,7,61,149,69,118,161,141,117,25,193,18,187,220,194,82,13,30,5,225,194,158,252,56,159,129,5,240,0,213,85,67,54,209,242,151,41,141,172,187,12,215,255,6,5,126,185,11,225,35,202,5,182,98,154,26,217,237,193,140,136,38,71,118,166,44,17,223,179,101,97,16,153,33,21,204,15,219,189,120,219,24,117,23,4,153,22,143,40,174,238,185,27,159,69,251,1,227,108,218,69,111,198,184,236,14,216,136,208,115,154,211,47,149,116,98,114,40,90,83,116,92,109,38,134,140,104,157,197,116,57,122,111,5,224,4,175,201,244,62,210,203,188,216,230,131,214,184,164,54,48,242,179,251,201,77,16,77,13,77,23,34,66,146,24,12,187,238,151,92,139,64,114,217,125,244,175,10,155,138,118,58,245,52,121,17,241,62,231,105,214,169,120,184,4,155,16,20,12,215,206,40,237,161,186,68,63,141,166,178,6,127,126,151,70,195,245,163,96,91,23,138,173,211,99,103,164,14,51,246,20,75,76,135,150,74,215,220,71,15,76,77,215,250,38,227,176,76,17,15,179,232,18,19,165,54,194,146,187,110,158,216,55,66,145,232,119,152,61,63,121,155,194,202,244,22,81,66,36,140,38,108,209,21,139,25,159,255,185,60,117,9,245,95,46,99,220,27,61,151,235,253,38,161,64,188,88,189,117,249,42,176,56,54,107,62,80,240,135,153,86,180,137,121,111,177,208,196,3,194,236,106,173,82,40,195,1,146,180,204,141,11,192,120,252,52,4,116,199,14,254,104,216,4,219,7,221,233,33,47,34,247,94,0,104,240,54,18,128,85,240,255,179,195,197,161,240,178,242,197,103,68,166,60,95,131,245,148,198,163,124,209,39,120,42,206,15,106,91,118,113,89,19,66,66,241,200,64,65,37,82,169,139,136,203,234,192,172,175,27,160,244,10,91,4,183,109,177,183,93,233,92,26,227,67,87,232,184,97,234,202,240,80,213,42,133,15,68,206,0,206,110,170,227,223,113,90,208,60,11,93,245,151,50,51,86,152,199,229,35,248,13,119,64,238,165,152,108,70,48,149,157,110,249,189,25,187,246,251,124,64,0,176,165,128,174,39,200,94,100,193,34,233,19,192,83,39,177,228,74,234,195,128,251,203,238,192,16,66,200,223,179,30,106,195,189,26,217,157,142,161,132,38,20,179,217,79,34,97,189,231,106,19,144,223,172,39,206,91,192,115,254,111,141,170,103,121,61,72,101,60,110,173,73,193,25,89,206,122,137,151,213,60,169,7,42,226,224,249,190,43,17,190,187,240,163,77,26,192,162,70,170,154,216,20,183,212,229,81,56,157,247,123,219,168,91,21,53,107,174,135,98,32,176,146,78,98,190,30,232,190,171,107,188,254,223,5,25,58,134,150,36,28,218,134,107,40,253,245,199,11,1,191,26,173,238,5,142,204,170,161,157,127,172,254,27,185,235,87,15,3,74,170,36,195,132,163,3,126,33,178,173,141,106,23,111,96,111,124,164,68,230,2,210,18,190,148,45,70,148,194,38,160,67,130,166,172,81,5,91,142,239,190,58,3,102,81,212,68,68,73,134,6,117,116,100,47,57,100,207,232,224,125,32,30,193,162,117,36,57,8,27,203,56,199,110,251,56,35,162,240,157,224,0,42,206,199,201,33,95,5,127,132,29,178,152,101,166,1,242,99,155,248,47,71,180,75,84,99,65,91,32,31,136,206,52,48,74,184,208,83,85,179,51,105,125,87,66,145,207,127,71,239,255,157,126,120,139,232,35,64,70,128,118,191,41,217,7,185,86,117,216,187,163,194,206,174,218,56,214,58,160,248,111,154,70,17,108,212,91,199,245,32,108,125,43,198,192,38,68,101,100,147,129,87,52,240,50,91,92,218,108,127,101,155,228,123,77,147,41,86,207,159,139,140,93,22,169,163,63,89,236,154,98,131,93,39,55,237,122,107,6,174,184,202,126,27,199,141,16,52,167,250,44,52,64,134,244,66,235,39,127,190,88,127,61,105,107,157,35,59,146,10,14,155,241,227,170,104,180,47,95,20,235,236,196,100,29,66,255,252,236,249,128,214,5,234,40,241,34,234,45,47,166,217,121,36,243,35,251,23,126,3,133,136,164,113,22,69,236,180,239,139,48,255,146,161,48,135,129,150,245,193,181,210,85,120,4,249,147,174,66,17,136,154,208,148,214,82,198,29,171,4,223,212,84,104,93,95,153,151,59,52,212,150,113,85,179,189,60,151,118,28,93,220,49,114,124,228,164,99,165,40,1,5,200,121,138,132,77,15,5,21,162,216,252,37,141,224,202,125,209,225,242,62,177,195,93,254,238,77,226,148,168,119,167,195,151,180,25,60,215,48,166,94,44,45,114,159,78,24,155,132,119,38,31,231,227,51,37,35,33,239,40,171,12,250,68,190,248,231,228,59,213,61,15,65,53,179,92,176,23,172,176,32,72,135,37,241,24,107,242,184,186,57,99,239,241,14,0,114,211,202,79,176,88,52,130,56,18,75,55,22,208,79,100,1,57,105,53,174,100,13,234,232,158,118,211,9,144,128,160,76,177,166,10,90,95,110,144,254,243,190,208,135,184,198,226,200,27,9,38,241,0,208,210,237,180,2,22,149,157,19,155,249,21,3,55,195,149,105,206,24,110,148,19,249,58,78,186,176,25,100,216,4,198,194,104,71,150,103,193,54,223,28,146,80,51,157,194,14,178,180,189,161,192,44,225,168,111,47,225,151,43,100,26,191,125,146,222,221,199,216,186,126,173,89,90,229,77,60,34,228,75,219,182,85,232,170,22,24,130,197,101,20,253,116,141,176,241,34,223,208,190,53,49,201,93,144,151,241,108,236,120,86,232,128,234,238,83,111,80,172,96,67,34,128,6,29,10,136,122,7,204,83,50,186,1,23,79,169,21,92,114,15,132,236,51,188,123,139,240,236,199,67,208,132,52,13,194,187,174,29,120,140,151,198,252,88,147,102,219,35,162,73,126,98,77,213,8,169,217,193,210,100,239,19,153,49,43,252,194,75,228,65,143,184,39,77,42,202,171,40,113,137,164,157,33,120,131,63,197,218,5,250,238,192,175,128,92,206,161,173,254,238,133,100,158,136,16,101,127,238,52,208,92,82,3,217,66,93,246,228,193,254,74,72,78,122,33,105,54,8,66,93,246,194,222,27,194,33,125,31,125,186,243,13,92,218,44,36,132,226,180,89,124,205,104,135,159,122,252,15,162,223,62,10,250,171,0,131,127,85,178,231,79,207,40,253,46,196,118,242,128,72,35,191,117,82,21,59,50,253,123,77,220,143,104,20,203,224,176,13,252,32,28,67,43,91,75,244,94,186,135,19,180,199,223,127,142,98,37,239,28,103,87,65,235,18,238,103,120,238,30,86,59,98,172,2,220,161,99,43,3,209,122,161,55,146,255,1,36,249,99,184,3,3,168,72,232,46,73,223,106,79,159,210,38,156,147,51,126,50,165,108,52,49,96,42,238,80,99,70,146,206,224,54,97,97,16,213,14,248,251,126,49,66,87,134,179,227,232,143,91,185,125,0,158,183,5,242,48,7,152,160,171,198,163,34,181,199,170,68,125,93,97,109,136,230,150,33,113,56,104,7,226,175,49,100,51,84,213,22,135,7,237,200,148,72,116,142,163,153,122,86,4,164,15,210,118,24,67,210,223,220,137,144,48,144,180,185,234,2,241,154,213,43,109,156,143,172,26,128,135,231,119,24,217,131,61,148,77,141,150,92,115,120,2,154,217,75,86,241,208,171,108,103,82,89,209,129,238,172,132,255,207,27,146,164,74,184,68,92,141,13,124,214,138,185,244,149,236,189,182,103,67,87,10,32,216,220,143,80,210,206,245,104,149,139,20,55,5,113,172,207,125,29,89,249,19,112,108,14,88,182,201,165,18,10,245,121,6,178,148,34,12,59,196,61,173,239,178,241,33,155,25,242,134,32,227,233,188,135,113,163,52,64,251,178,224,118,246,79,167,5,63,212,177,112,180,80,242,169,49,210,21,134,141,17,157,190,91,64,227,91,38,133,159,225,105,247,226,195,200,172,31,220,215,170,68,107,20,234,183,178,143,56,158,107,86,223,172,215,193,84,10,65,89,99,158,61,203,224,96,108,213,54,164,149,13,125,118,120,95,189,114,57,41,211,241,237,209,190,6,62,79,184,242,245,149,195,91,85,198,131,178,227,71,202,112,154,51,82,29,130,223,121,113,6,199,251,129,30,201,68,187,181,197,35,52,79,104,12,235,40,127,72,62,197,101,25,50,235,135,22,61,18,204,9,17,58,139,193,112,118,161,34,157,65,113,190,135,176,140,117,20,216,176,111,50,116,217,162,214,180,80,45,31,21,53,93,2,228,123,100,207,17,230,207,97,240,183,85,31,41,46,45,3,43,72,155,187,165,203,128,67,28,120,236,54,20,65,238,109,110,179,222,136,198,17,77,149,130,251,103,177,204,150,184,189,37,5,55,241,217,14,130,255,116,126,175,235,144,116,140,66,14,51,205,67,99,220,51,208,79,206,154,127,22,85,71,77,215,145,255,44,243,64,209,227,67,73,110,151,218,87,197,55,237,118,245,39,169,244,170,245,203,108,245,142,50,189,176,80,21,202,93,146,1,53,148,177,158,56,213,31,235,149,163,76,7,160,96,185,175,209,247,27,135,158,217,147,16,10,240,197,137,20,206,239,82,56,27,22,220,198,2,89,79,127,31,142,1,6,55,182,200,142,137,107,201,174,111,181,210,207,62,30,104,243,208,79,121,233,86,23,51,192,246,38,237,63,185,68,166,75,123,229,116,251,234,207,59,122,231,68,113,211,62,70,25,143,151,209,232,208,160,147,131,216,54,242,90,239,63,40,144,174,63,16,36,202,26,114,183,89,217,89,136,230,91,48,252,125,202,164,150,89,145,56,123,247,12,54,155,187,186,61,40,196,208,28,136,119,101,36,210,226,52,175,235,200,109,39,72,109,208,243,138,191,212,112,241,255,140,84,135,41,149,18,74,71,117,169,225,47,36,251,47,104,143,61,234,88,50,148,255,119,218,157,33,205,193,198,233,229,11,62,162,92,119,220,137,255,123,184,226,35,157,8,174,39,63,216,248,137,225,131,8,2,82,204,80,214,39,91,209,189,161,6,81,144,36,198,76,197,109,194,10,4,72,54,53,184,115,91,225,10,11,168,200,46,218,124,246,135,15,89,53,166,8,241,71,83,123,154,209,50,174,37,55,123,83,140,20,54,44,56,182,163,26,6,6,190,38,53,147,232,222,149,68,107,255,157,252,151,137,92,252,145,148,33,103,9,72,231,13,116,195,38,2,23,236,159,143,19,6,218,213,124,179,244,182,30,110,173,19,168,90,131,57,252,205,106,250,34,115,21,156,227,2,178,233,51,164,166,165,72,112,14,41,93,38,111,111,37,191,106,207,33,185,185,90,72,233,134,236,98,171,160,112,169,40,190,94,93,171,234,98,137,93,127,65,248,80,186,131,116,191,197,63,31,50,255,195,58,34,142,54,220,246,198,63,55,183,44,126,0,217,209,232,158,8,7,110,86,107,240,61,28,52,138,97,149,20,247,180,192,143,33,83,155,177,22,187,216,48,139,83,169,139,99,123,154,74,125,236,38,59,46,27,30,157,211,15,232,203,47,94,136,56,194,51,139,205,174,21,161,217,7,160,227,59,236,156,91,143,154,27,42,117,22,168,18,246,201,35,37,107,157,58,5,158,76,100,112,62,84,117,50,22,6,96,111,120,207,116,151,161,13,67,239,116,206,98,64,136,103,8,201,197,9,81,239,18,226,93,190,46,81,229,232,167,200,193,215,90,182,212,93,78,67,26,105,97,197,49,164,150,52,143,248,121,13,95,217,227,206,14,80,200,179,171,10,146,200,142,90,137,125,253,146,71,131,33,45,48,69,241,119,153,254,188,241,25,222,97,30,63,46,136,159,57,134,89,0,129,234,189,184,64,200,208,245,48,167,116,134,99,230,3,164,217,19,159,106,99,97,202,22,164,70,66,13,97,32,58,239,114,37,9,60,59,67,157,37,172,251,50,177,13,116,63,7,119,74,90,248,108,175,187,95,134,112,101,157,132,160,143,70,245,232,144,69,184,106,150,9,184,122,224,32,162,162,167,166,203,10,237,99,78,75,217,159,250,237,184,75,97,163,68,55,215,93,14,236,225,12,141,49,8,40,126,117,77,135,80,77,205,97,75,21,26,145,221,123,172,2,182,77,86,93,204,86,114,144,92,13,141,25,97,222,15,100,182,160,159,142,35,220,49,107,187,208,137,105,153,135,0,174,222,172,239,170,133,207,178,208,164,230,211,2,139,92,32,192,133,89,232,32,239,245,110,166,136,37,21,196,131,79,242,98,209,25,180,252,102,119,100,85,102,115,189,106,122,226,157,178,221,143,154,92,187,57,68,241,18,33,225,250,134,114,116,72,134,250,27,40,97,219,30,86,74,184,102,193,26,66,181,24,165,153,255,190,75,185,18,121,114,85,220,59,224,145,174,176,36,67,144,74,196,161,88,9,48,79,220,4,67,25,232,105,176,32,242,28,201,66,116,178,36,164,218,208,31,240,68,239,166,138,242,198,226,27,136,232,255,174,210,152,60,200,61,15,238,2,218,231,198,130,236,180,235,65,221,66,82,162,92,235,251,20,38,65,92,156,106,85,0,144,25,182,28,226,88,153,34,253,19,27,116,90,101,248,35,202,216,184,19,35,2,94,8,209,254,66,212,135,68,219,185,32,107,225,25,227,136,211,138,181,174,112,128,190,66,165,251,135,185,108,40,159,222,177,26,58,26,148,218,89,13,15,27,236,24,118,78,33,185,174,168,219,230,119,230,179,169,161,57,118,97,227,203,9,125,55,136,197,112,94,138,136,230,112,204,245,136,116,59,13,75,68,121,43,122,9,22,252,149,172,182,118,113,61,53,171,44,42,118,178,166,69,222,44,157,34,128,126,179,24,154,159,106,149,17,227,58,143,176,241,222,56,42,62,181,26,208,33,24,30,33,112,83,127,84,65,41,251,206,115,178,2,222,106,153,209,238,98,208,200,210,177,133,86,65,23,104,110,177,161,96,79,57,142,162,15,207,173,153,56,254,250,73,76,74,43,36,200,57,145,60,95,227,21,147,221,41,171,192,107,234,251,74,126,3,247,128,122,243,153,128,202,238,189,17,198,179,70,97,245,190,200,231,176,186,98,217,254,45,230,228,185,78,204,155,64,247,183,255,152,161,26,12,21,183,209,199,194,177,1,221,95,77,76,253,203,104,7,192,167,209,180,50,138,227,189,182,231,239,238,168,59,221,119,154,107,247,102,200,51,40,120,192,133,47,249,238,189,123,233,117,188,210,82,68,72,178,111,103,77,144,205,181,97,1,172,166,152,242,0,187,181,174,188,39,82,5,75,21,213,113,66,102,62,173,169,132,21,120,138,226,211,39,44,143,160,126,74,108,191,13,117,58,148,234,239,194,161,161,156,231,240,170,77,120,106,63,168,175,231,243,60,192,181,236,20,52,239,78,141,78,130,59,219,80,208,24,37,165,109,209,49,251,9,62,80,50,249,181,232,42,228,47,166,191,144,176,206,148,242,148,153,182,121,24,128,65,137,42,161,119,66,94,240,11,55,102,122,7,205,142,144,144,180,47,60,218,192,149,85,15,213,83,8,79,215,104,8,209,172,222,200,242,28,255,51,185,167,33,226,26,65,147,100,114,222,54,27,170,212,207,83,56,170,37,126,121,14,18,40,231,4,14,164,248,6,110,118,48,51,83,228,76,3,131,87,77,86,163,48,72,194,109,53,105,118,111,198,140,133,34,20,119,56,35,236,7,170,176,164,95,86,183,232,105,108,7,25,169,127,50,26,86,83,94,101,58,219,72,205,46,231,78,158,94,221,190,147,92,96,224,0,30,65,191,21,237,118,106,224,247,161,116,33,41,10,92,81,248,232,191,41,72,116,171,89,110,208,62,230,196,11,67,172,81,188,8,212,62,255,199,22,201,68,20,120,21,90,72,70,211,251,61,232,5,238,147,16,91,225,65,103,178,238,63,246,157,100,192,170,206,249,101,28,25,120,125,225,94,105,146,218,75,10,178,103,244,73,77,174,18,113,205,198,233,5,88,129,66,64,72,137,118,81,217,130,206,156,174,224,223,115,249,164,10,160,47,237,255,135,146,236,13,99,71,63,62,20,134,132,135,155,27,21,239,159,60,195,224,248,123,205,45,147,225,233,72,95,151,236,249,144,43,148,51,197,175,100,140,185,170,200,234,37,87,113,85,41,197,41,164,33,181,64,228,58,125,41,220,43,111,47,37,139,69,75,126,166,210,12,7,175,6,63,122,236,237,156,149,142,254,174,11,37,215,82,200,54,62,74,43,2,249,172,218,115,203,91,14,165,110,103,178,200,5,226,141,45,42,68,130,198,173,253,230,217,122,113,39,163,182,160,231,100,179,40,207,8,27,212,22,174,85,58,27,55,118,83,118,244,201,68,167,205,50,31,36,17,250,228,187,200,203,159,109,44,83,197,240,214,82,128,207,62,237,127,108,238,226,36,190,44,152,27,248,90,79,254,43,191,182,206,138,179,239,133,27,56,192,25,166,40,83,172,241,62,178,172,53,58,205,73,6,139,66,50,24,22,193,232,205,173,161,67,139,236,13,114,239,156,46,253,12,218,238,6,255,169,98,117,8,215,156,102,178,212,208,18,175,147,108,96,73,71,115,87,75,254,77,61,212,49,252,42,72,23,95,49,206,208,189,203,240,139,4,56,101,109,139,204,117,23,213,104,47,1,254,115,179,25,96,58,221,157,53,112,19,110,172,118,168,11,21,171,109,123,100,79,124,202,172,155,236,144,86,224,44,183,119,167,51,180,139,191,76,201,173,212,215,120,148,255,149,110,69,229,152,112,197,133,178,122,15,23,55,103,67,13,152,239,59,168,53,175,130,232,143,236,0,96,95,206,91,141,167,127,199,149,82,51,222,51,43,148,225,183,56,32,68,76,97,35,154,233,207,47,2,29,114,143,36,159,81,168,169,22,163,74,208,233,149,204,129,138,138,13,48,180,42,41,155,141,156,228,19,71,135,137,63,119,146,67,61,236,133,52,209,164,39,67,110,28,5,36,100,159,52,79,220,118,89,126,230,63,180,117,243,165,179,147,209,255,162,97,177,43,45,86,56,48,223,195,122,39,130,118,8,183,36,55,42,221,83,72,74,95,130,91,23,121,226,221,206,241,204,44,105,177,188,105,190,84,106,225,244,183,44,76,188,169,150,98,155,208,244,161,94,75,232,173,64,126,153,184,124,75,229,87,31,209,154,93,125,64,53,167,155,250,167,122,169,184,231,14,34,61,208,47,179,182,194,37,87,240,10,125,2,26,125,232,189,207,199,3,153,204,157,148,33,93,160,134,67,238,203,126,198,203,210,112,25,199,23,136,192,135,207,227,224,213,125,17,93,230,177,178,164,152,162,80,107,50,52,221,42,20,128,143,202,168,22,91,223,159,118,214,249,29,184,124,24,124,1,183,54,43,61,91,155,116,241,94,157,187,60,100,244,97,97,177,9,57,90,72,245,38,31,86,172,41,102,15,35,39,4,233,141,9,165,41,137,229,44,122,16,181,99,178,84,124,207,34,140,41,145,250,172,186,100,100,156,162,5,126,187,160,57,183,240,17,46,181,44,120,144,141,151,142,129,195,192,11,203,241,78,134,142,214,106,198,94,141,84,62,51,127,110,9,65,150,68,221,157,131,236,130,114,10,128,197,13,157,252,8,165,223,138,108,179,156,231,156,82,132,196,202,13,64,69,92,110,180,238,15,125,240,30,231,134,56,66,31,193,191,100,72,106,233,11,113,8,121,238,178,117,107,157,215,58,43,212,236,53,215,214,1,16,192,173,175,231,62,113,26,94,248,47,30,36,232,160,227,75,161,127,33,5,192,210,69,155,249,190,217,224,42,17,77,54,231,20,45,5,116,154,154,80,74,148,126,85,137,13,59,123,226,167,20,148,24,19,123,17,78,46,126,232,255,147,20,83,85,103,16,86,141,246,211,162,58,245,162,77,31,51,40,174,164,117,38,201,18,8,240,124,226,180,213,190,92,223,249,184,227,8,168,86,142,19,66,247,142,54,135,218,13,197,216,225,152,61,155,156,171,88,150,158,129,132,144,138,13,21,166,17,156,62,40,147,131,134,66,228,77,177,184,53,207,92,208,3,16,2,45,215,154,73,196,92,47,104,0,94,23,103,132,206,81,105,63,84,231,7,205,95,148,128,250,142,158,42,49,223,26,22,72,27,211,39,245,201,245,4,127,48,221,21,121,201,223,108,209,6,93,31,85,112,207,74,123,201,78,249,139,38,60,134,47,225,21,74,31,177,146,41,144,16,100,28,219,207,21,104,154,200,135,169,238,147,227,243,217,211,187,109,182,74,223,148,201,132,46,26,159,121,196,145,148,161,153,126,127,103,44,44,215,135,248,8,157,23,184,220,82,173,81,229,136,173,243,230,69,68,158,137,156,73,166,209,116,155,166,231,141,186,187,84,175,227,63,227,13,18,245,222,185,2,9,97,179,58,174,246,67,94,255,153,44,100,138,172,19,5,67,221,82,20,224,61,104,222,44,53,106,82,147,130,225,31,218,140,64,109,45,5,216,165,119,100,159,228,18,213,150,192,59,85,135,249,36,228,230,57,28,67,206,105,230,148,212,28,106,92,97,2,31,152,107,208,11,10,205,238,102,126,66,83,190,233,77,232,77,96,85,249,251,119,192,179,5,0,198,67,127,22,157,78,146,64,204,6,39,200,12,229,227,234,242,193,195,141,125,107,248,143,210,251,18,220,67,240,110,48,114,110,15,160,241,14,133,152,132,225,44,134,92,88,11,167,164,225,12,234,164,92,9,175,74,190,164,193,157,232,4,137,216,80,165,124,20,254,221,2,198,63,217,156,135,119,4,178,58,153,215,139,67,52,172,206,47,40,75,33,86,67,63,41,10,20,37,237,37,156,4,13,25,23,201,228,9,237,67,16,22,116,17,184,162,203,188,227,13,110,65,231,79,200,61,118,207,68,161,90,71,47,113,31,224,165,90,23,21,239,63,80,176,54,103,99,60,125,72,207,90,110,231,121,225,205,35,28,16,137,252,136,94,179,14,97,157,227,66,82,219,137,26,78,157,181,147,28,161,251,43,196,201,53,245,149,152,194,86,91,70,203,91,114,199,241,212,180,125,44,131,135,116,26,132,69,27,84,222,132,88,96,163,119,62,129,249,230,33,147,28,124,23,172,231,132,144,182,235,125,193,70,233,206,77,27,210,203,223,213,95,105,230,117,205,214,164,126,23,240,10,34,237,211,43,162,138,230,118,192,86,247,125,167,215,62,26,113,209,175,19,231,246,167,150,22,44,69,31,236,205,198,210,214,123,93,60,9,175,131,96,145,71,92,190,209,201,225,103,43,204,242,98,253,129,95,56,223,107,29,87,165,180,44,49,28,37,42,83,215,122,91,126,77,38,243,71,213,191,223,14,76,247,97,110,190,120,147,167,234,237,10,98,148,45,218,3,23,117,15,148,142,173,118,236,90,31,27,85,54,188,202,253,43,102,109,130,17,8,239,241,89,212,14,29,172,179,90,8,104,5,203,117,188,43,184,167,54,8,100,136,17,55,201,102,193,221,245,173,86,65,162,176,40,92,214,101,18,82,59,131,63,156,187,219,65,190,115,172,242,52,181,80,109,165,136,98,148,149,152,234,86,143,132,100,239,159,119,163,250,30,130,119,190,45,58,208,104,161,144,10,202,200,31,177,215,242,236,78,3,151,34,8,16,172,231,112,71,159,168,32,208,230,50,84,234,214,40,92,65,60,148,117,76,216,111,91,121,177,66,86,123,55,54,126,46,118,241,103,105,245,89,242,0,0,166,87,7,145,164,227,90,30,10,4,88,64,114,70,127,14,161,218,198,16,35,230,115,54,65,108,190,175,186,252,79,33,24,82,118,130,249,181,253,61,28,154,77,227,209,111,63,61,68,223,162,41,90,176,37,114,169,199,77,160,219,199,22,79,240,212,158,243,217,226,74,158,215,193,166,204,82,135,0,106,12,155,150,113,241,197,33,205,6,16,19,118,164,194,115,243,112,162,251,134,203,122,124,61,242,68,140,200,131,168,172,123,48,70,132,227,199,3,196,130,48,55,231,64,216,195,86,36,160,233,137,145,108,224,93,218,61,107,191,138,171,13,215,212,65,223,117,85,120,109,207,141,12,23,221,175,68,130,129,185,138,67,225,85,127,85,215,75,146,79,69,133,10,129,210,51,71,147,116,11,104,76,194,87,78,137,12,108,185,53,10,210,35,135,33,203,224,96,175,47,98,138,83,60,163,16,100,51,21,186,245,7,153,128,164,73,27,189,195,13,61,255,96,12,174,169,37,39,235,177,224,137,71,128,240,63,137,238,255,68,185,212,135,190,156,240,184,158,113,210,241,119,224,63,177,236,63,172,135,117,74,27,187,227,253,246,222,134,197,251,197,243,107,188,160,85,252,111,4,141,195,243,91,73,226,144,131,109,136,10,172,209,186,95,172,96,107,43,22,44,176,226,122,100,50,28,65,163,62,235,88,16,254,97,48,250,64,155,101,21,83,64,255,189,98,142,60,20,184,3,54,87,20,50,178,254,138,105,53,169,141,5,88,57,244,207,138,191,208,185,54,87,134,70,182,197,77,248,201,118,133,148,231,106,241,215,91,61,184,61,250,9,140,91,66,203,141,93,171,166,65,183,29,234,196,85,230,194,177,148,240,126,71,14,92,212,2,120,179,141,11,42,166,15,45,196,187,30,249,247,104,244,5,25,126,208,252,253,157,224,36,138,145,222,221,213,15,204,112,217,50,193,215,194,2,248,214,48,43,229,7,204,79,218,223,82,137,114,228,41,220,68,157,35,245,242,213,255,141,189,192,243,63,72,119,222,107,252,230,192,211,47,186,209,144,213,221,185,22,152,208,54,130,76,100,242,54,210,211,40,29,189,40,7,183,252,209,130,240,76,107,14,110,35,151,57,0,187,180,78,210,153,198,18,212,33,205,72,211,89,150,175,136,7,138,13,18,93,226,93,52,171,126,188,165,113,29,15,231,234,11,67,54,164,115,158,58,48,20,202,65,198,247,224,202,190,45,10,153,146,148,150,218,67,157,27,190,197,15,182,135,56,130,43,203,209,174,134,100,81,179,58,182,229,1,155,224,135,148,214,99,38,92,212,220,49,17,170,248,161,123,88,92,5,119,19,210,149,12,254,121,21,140,38,10,247,25,4,22,186,68,1,211,221,109,182,103,137,4,242,129,66,67,138,61,50,131,83,208,81,53,132,36,86,63,33,62,142,250,210,195,68,246,210,84,77,150,182,48,140,129,1,24,195,122,107,160,22,129,227,250,27,102,21,127,52,229,47,19,58,21,47,132,85,233,11,183,119,3,54,223,94,30,168,153,3,202,62,170,29,46,235,105,186,122,192,71,128,73,149,47,98,46,122,34,64,101,76,177,160,154,47,174,96,118,108,73,203,121,15,19,101,72,99,177,70,118,219,124,182,128,41,154,76,22,204,166,120,224,174,35,27,29,63,8,248,217,183,247,192,11,141,178,28,4,184,73,111,64,221,65,220,21,145,34,163,79,94,28,225,40,146,182,182,2,244,18,250,136,64,65,3,121,52,149,19,150,105,221,244,244,247,77,249,155,100,216,128,178,170,122,153,140,221,2,88,211,227,255,108,191,91,6,185,100,148,31,75,245,179,229,46,107,30,214,20,93,198,142,86,108,83,131,235,38,107,38,203,229,248,160,22,216,41,215,22,55,59,211,156,38,76,79,202,176,49,88,161,162,206,46,81,83,200,99,138,117,40,110,2,84,142,165,212,63,185,183,35,165,96,218,110,177,40,36,21,19,181,76,171,145,175,144,249,115,42,97,99,152,49,128,122,54,8,136,236,196,46,137,181,211,218,83,112,177,64,193,136,89,220,176,221,204,172,174,154,77,96,166,191,132,59,141,90,169,6,46,45,84,193,160,209,49,6,199,255,3,129,73,146,92,31,226,30,164,12,7,148,241,217,3,113,226,199,81,146,95,141,45,176,205,253,233,128,78,74,123,244,138,154,234,99,11,241,18,251,174,123,196,122,254,82,210,2,90,216,87,97,38,253,160,197,255,134,152,168,162,17,72,133,41,122,235,85,154,133,172,162,240,103,107,149,216,192,182,55,27,163,94,52,129,61,154,61,11,135,223,222,154,217,53,135,124,181,120,2,41,107,239,28,32,232,45,27,51,86,176,14,7,40,249,170,100,67,101,131,23,151,200,74,151,82,184,146,40,7,64,240,146,253,80,218,150,108,16,186,224,225,98,8,166,177,252,0,35,95,107,137,80,130,116,129,161,149,37,52,149,240,167,11,50,129,134,80,126,16,233,201,206,97,186,68,205,245,254,241,139,20,5,89,162,39,98,188,107,186,119,233,101,250,245,150,241,120,191,39,29,12,121,31,198,242,252,230,85,160,112,172,171,128,29,103,65,246,39,126,74,92,140,142,56,181,82,101,195,59,71,4,8,9,42,98,180,136,41,26,56,252,4,230,102,239,251,161,183,106,22,54,238,250,59,61,243,9,189,77,195,254,119,234,124,186,211,5,26,88,176,159,87,101,242,100,179,102,218,39,85,82,118,109,146,144,225,73,28,78,77,189,135,29,192,12,95,153,113,248,50,171,113,241,189,121,194,155,247,109,70,124,72,61,27,79,56,185,218,51,155,130,98,183,1,100,60,85,55,160,158,110,41,58,63,216,176,49,228,195,87,118,254,105,223,41,138,84,41,78,214,111,49,206,175,91,190,57,25,68,120,22,127,85,81,202,226,197,123,156,169,249,12,182,148,31,115,211,146,41,208,248,249,197,188,103,47,138,8,117,43,130,28,28,102,44,149,38,221,176,211,11,76,148,186,176,252,87,62,69,3,88,80,123,168,196,245,128,224,186,224,99,220,46,237,181,88,159,161,175,204,237,160,154,13,131,12,99,88,171,231,111,242,238,194,193,15,3,254,152,148,114,131,215,216,106,245,73,197,176,147,149,25,185,200,252,52,225,236,86,240,34,22,76,102,243,132,148,11,204,125,58,185,37,184,188,4,169,89,249,104,232,254,3,96,102,68,177,242,8,251,188,177,100,48,1,248,177,185,181,108,161,130,117,35,229,28,94,131,105,31,242,158,200,167,63,124,21,55,142,139,10,202,5,82,209,8,37,48,22,47,237,174,182,254,11,32,46,255,142,78,113,207,192,187,172,174,16,156,90,26,138,142,57,129,2,59,148,175,197,194,242,205,81,57,214,199,206,60,204,225,254,113,28,148,222,242,209,101,104,98,108,237,223,49,114,212,129,78,146,78,208,40,162,230,188,127,198,195,47,15,146,82,173,159,186,217,133,148,237,194,5,33,102,245,90,65,8,165,35,12,231,205,62,97,232,36,7,127,30,119,233,149,99,221,178,173,102,226,168,250,196,60,181,5,125,126,243,158,64,110,37,30,195,162,229,136,241,198,229,105,88,85,49,14,96,84,216,55,253,53,92,172,24,38,54,35,37,50,118,149,84,244,199,203,56,87,218,44,100,7,25,135,147,55,101,115,200,99,37,8,239,72,221,30,76,8,86,146,55,44,91,241,31,111,230,90,185,168,144,245,50,43,46,238,33,229,223,34,244,14,118,219,103,141,110,249,21,49,255,202,251,214,126,66,144,34,95,94,195,240,131,109,100,123,73,158,69,82,217,206,59,169,190,31,185,211,83,88,73,74,185,229,228,147,57,21,198,39,234,143,84,167,170,144,247,206,56,43,55,104,193,157,220,89,125,173,151,17,4,10,18,124,244,41,133,194,59,11,202,98,174,212,26,19,95,71,26,82,242,133,85,125,4,131,36,108,37,250,255,99,63,15,53,173,129,255,175,83,105,132,142,35,4,243,133,67,237,220,88,25,169,219,83,229,33,83,46,251,0,111,226,87,41,226,98,245,208,93,251,94,207,210,41,146,56,119,137,32,0,61,212,6,161,219,144,112,202,88,124,132,83,197,240,185,196,152,34,202,136,59,198,165,5,136,11,246,158,60,3,176,105,203,207,70,162,187,45,160,39,60,82,115,113,239,37,166,188,235,215,222,227,65,73,188,70,178,98,215,247,7,12,10,4,216,139,202,178,125,231,103,79,61,127,58,10,202,75,42,107,139,214,172,4,14,3,23,73,247,52,158,78,61,218,235,79,191,182,70,127,157,34,208,242,177,248,153,110,42,50,168,186,212,159,202,174,245,161,60,197,47,221,200,111,195,231,35,136,145,196,62,119,52,247,41,50,41,64,94,231,136,149,213,174,127,157,61,143,47,166,152,59,245,186,16,70,32,201,49,239,157,90,225,122,138,88,158,93,59,121,246,69,151,25,182,189,199,100,74,131,123,99,103,185,138,240,169,255,83,8,240,13,159,156,5,223,181,247,243,244,179,90,207,159,36,69,34,174,29,39,12,198,108,220,130,2,10,203,188,206,67,116,209,27,67,170,198,93,113,250,14,198,254,196,37,146,198,0,245,162,19,196,105,30,136,94,211,48,61,213,53,160,236,102,140,240,236,1,246,124,73,73,184,88,243,157,125,154,77,39,104,111,1,205,78,22,233,44,37,253,92,198,51,8,211,150,43,192,106,122,208,21,123,140,14,148,222,144,217,194,15,242,120,80,45,66,71,74,147,132,37,185,45,165,41,76,166,143,130,134,3,4,15,104,214,102,179,162,238,195,200,235,20,223,172,249,110,37,43,216,136,128,232,235,48,215,2,250,173,82,109,146,30,125,217,231,73,206,65,2,40,45,35,163,248,230,102,19,67,102,0,76,64,7,130,23,167,105,28,152,26,73,234,15,36,35,231,146,205,50,217,164,199,154,192,15,19,80,26,30,181,14,197,12,131,88,61,140,86,85,233,182,210,78,143,77,63,177,30,176,10,224,14,137,130,162,84,191,108,227,75,85,115,237,159,119,222,168,131,18,13,22,92,110,176,134,71,180,31,116,154,111,4,116,74,59,2,191,75,114,181,184,238,106,236,202,251,63,247,48,35,155,172,61,122,174,26,38,3,176,42,15,71,195,153,55,66,191,33,169,177,220,36,95,177,66,86,173,31,180,219,166,178,139,120,139,67,88,25,238,233,169,169,111,163,217,54,29,44,34,138,236,199,35,50,82,214,30,125,91,25,222,65,137,125,96,232,78,167,209,68,71,70,1,22,163,34,202,200,71,113,235,157,41,14,32,110,171,235,197,174,10,51,158,251,44,98,199,201,196,168,50,201,99,205,245,153,75,169,17,143,154,52,222,138,28,173,86,92,134,115,136,220,131,85,171,122,218,117,190,117,143,79,26,121,10,50,45,80,241,33,4,253,140,1,159,201,105,123,35,133,81,59,236,16,238,109,215,10,124,211,64,112,180,147,203,106,142,69,97,205,162,177,217,151,174,189,239,69,50,30,166,238,219,120,79,225,197,121,127,91,215,89,102,17,39,158,213,94,164,254,49,125,216,191,222,90,38,224,214,242,60,2,38,241,139,218,34,185,186,30,206,33,43,38,242,81,191,12,1,200,96,167,125,197,194,127,129,244,184,30,74,74,196,174,229,224,226,124,52,137,122,146,108,187,169,127,72,111,131,243,79,149,236,134,103,137,212,161,44,61,183,188,103,150,96,95,88,187,167,31,213,185,63,128,70,10,58,47,69,155,112,231,242,129,19,78,116,74,152,85,44,128,199,241,148,56,48,27,194,180,191,35,170,227,179,166,110,172,88,208,185,53,153,120,109,155,216,205,172,159,59,191,94,49,209,213,90,125,246,132,153,163,89,50,28,91,141,185,11,4,229,210,18,79,36,117,191,90,231,97,92,89,193,98,201,7,9,252,3,100,157,87,134,164,29,218,54,7,117,232,97,226,74,185,43,135,78,199,151,206,137,157,244,201,49,137,164,23,115,134,121,92,128,224,192,100,154,252,124,146,17,129,44,130,237,65,159,194,35,88,56,132,29,163,200,91,112,118,35,100,76,112,87,180,233,171,69,124,62,161,232,54,66,129,248,193,47,232,197,143,236,112,36,132,61,97,179,231,60,124,4,220,161,114,16,84,196,143,200,58,98,2,255,8,3,222,42,146,204,234,68,199,78,202,173,32,215,30,242,64,32,250,49,111,31,174,191,209,40,51,55,101,12,137,212,116,140,72,132,52,104,204,245,218,122,29,236,175,188,112,137,112,129,225,22,84,118,55,75,104,13,207,51,243,102,148,120,49,86,192,53,173,30,143,161,0,187,160,141,185,32,104,37,221,242,44,29,27,162,135,12,4,205,239,98,8,217,237,81,207,29,240,169,209,6,80,56,120,99,193,90,244,235,14,45,162,130,224,62,152,96,147,9,238,188,49,82,151,207,8,240,126,39,228,192,121,199,227,52,238,238,69,130,134,174,90,34,126,176,133,63,234,79,219,126,186,224,106,183,242,244,90,180,161,17,110,155,66,109,222,205,83,121,103,49,85,234,220,198,98,67,0,50,194,21,182,193,118,19,220,4,173,96,221,203,40,186,232,98,162,37,12,169,225,26,229,12,71,121,194,162,100,159,139,30,0,151,86,14,131,219,129,154,212,170,79,126,26,171,90,92,239,0,106,79,97,213,183,128,12,238,216,30,67,114,73,64,191,22,179,225,12,252,220,234,87,55,51,145,66,34,63,168,252,148,87,47,176,54,228,85,152,226,61,198,41,76,94,182,131,134,142,127,97,14,232,78,147,107,91,23,55,184,220,0,132,128,230,214,41,253,146,45,59,69,244,78,228,127,47,234,235,212,197,152,203,251,16,167,93,153,46,245,207,238,82,246,96,131,4,123,250,67,9,15,63,198,214,205,18,51,223,238,190,104,69,185,188,1,61,168,132,22,21,224,86,237,119,49,15,228,241,216,161,180,19,252,22,109,144,133,49,21,97,145,73,250,32,160,0,103,179,235,69,26,206,44,140,184,97,110,167,21,84,228,112,18,154,24,41,60,232,190,168,43,72,248,82,221,13,138,79,89,140,122,61,117,232,17,75,243,217,88,218,235,50,96,182,174,230,168,249,99,90,3,240,143,171,128,49,247,62,32,242,216,73,239,88,172,30,77,172,78,40,138,46,152,178,103,92,139,57,224,167,208,14,63,245,78,69,235,225,103,133,134,96,22,32,104,77,117,153,192,206,38,183,221,117,253,207,240,211,16,89,105,251,119,74,144,222,156,150,154,58,135,38,58,165,24,125,4,181,205,243,117,226,156,243,80,70,66,176,146,37,197,55,215,99,87,148,92,191,170,198,29,60,48,57,132,232,226,100,191,28,143,184,235,205,69,47,243,18,71,89,96,148,5,68,98,120,4,46,222,166,248,156,123,31,13,147,244,29,153,133,248,130,207,112,2,139,131,49,115,58,120,121,244,170,19,97,201,192,75,161,137,127,83,157,78,253,58,222,224,220,83,182,11,236,101,153,140,34,113,36,254,143,112,151,78,23,46,155,32,170,178,239,64,77,243,128,127,240,27,82,213,68,205,87,27,42,124,75,156,9,234,4,161,210,181,7,140,130,78,31,105,100,208,169,223,62,105,229,132,50,56,128,226,5,184,254,213,116,54,2,93,233,67,132,34,39,179,133,27,209,227,163,127,21,38,10,175,140,28,114,70,190,173,123,166,31,176,23,83,27,2,64,147,250,217,95,1,100,211,238,42,151,65,188,182,234,61,134,64,31,245,14,173,167,214,244,223,242,182,230,208,180,241,228,142,135,251,1,188,189,100,175,18,181,117,35,14,102,136,20,208,168,235,41,228,102,112,204,114,197,137,63,144,1,174,122,8,52,194,119,247,169,229,16,103,124,105,126,128,30,165,102,132,107,24,55,253,220,212,101,202,129,150,144,2,88,195,9,152,160,243,97,168,80,228,18,168,79,186,193,151,206,197,164,32,6,58,126,128,178,154,122,20,188,81,123,96,6,46,214,149,107,24,177,129,255,208,247,29,66,228,212,126,81,168,1,76,131,174,108,141,122,248,24,107,113,170,68,235,117,129,83,56,163,148,130,79,104,185,22,138,198,242,77,180,102,47,117,225,233,90,16,225,8,163,241,112,173,15,227,176,197,136,139,114,202,96,151,63,60,96,154,107,17,147,224,206,248,93,53,106,235,229,60,87,165,173,67,60,192,40,25,38,154,183,128,195,41,187,21,254,166,61,76,158,20,29,63,194,131,191,180,111,32,193,245,193,122,94,224,84,142,94,172,150,192,219,151,49,107,61,164,252,204,72,119,227,21,253,120,84,60,176,113,224,172,24,196,92,64,19,6,114,3,127,121,48,40,3,60,52,74,110,225,56,14,140,23,179,58,129,206,230,166,25,190,123,31,5,201,50,253,204,94,174,116,91,166,97,216,90,145,201,152,88,164,18,19,17,202,204,251,146,159,61,233,43,209,63,240,241,168,94,78,86,211,0,62,97,12,204,199,62,218,65,64,9,170,91,210,0,191,56,249,81,51,140,84,246,229,192,59,27,87,104,195,108,174,216,168,188,98,234,57,57,162,193,13,190,155,45,124,40,58,32,99,14,179,68,39,112,92,159,159,36,201,2,226,129,171,120,102,185,148,114,152,162,196,181,56,69,182,37,197,98,228,38,41,142,10,57,84,197,160,183,210,236,9,42,214,224,63,62,31,118,26,251,177,236,185,210,104,244,19,251,195,113,141,34,50,255,204,42,56,117,66,203,139,249,119,14,28,203,175,32,42,245,180,104,11,154,25,127,248,60,200,28,180,91,39,244,161,108,240,140,189,72,32,119,76,235,30,100,46,74,250,110,234,232,192,243,51,124,39,251,186,123,64,23,149,105,161,56,180,49,163,245,34,42,187,145,64,13,82,135,95,186,146,44,214,135,104,194,94,110,93,178,242,130,21,226,63,156,184,127,204,241,167,193,180,9,237,106,90,105,165,19,198,246,140,189,35,66,77,27,170,145,237,170,99,161,189,234,238,51,219,82,212,214,32,43,128,193,45,163,2,216,44,192,84,104,92,99,93,116,94,163,255,90,174,176,184,147,127,46,68,22,63,23,62,151,173,125,237,52,101,54,144,205,184,145,103,197,86,53,11,127,158,118,175,217,13,86,251,47,11,230,181,185,174,212,134,254,17,229,174,154,246,87,107,230,55,252,104,84,104,251,201,66,110,183,24,71,54,10,178,175,12,182,18,163,73,203,244,85,216,175,129,81,60,17,112,71,155,136,34,122,134,137,245,172,152,64,127,55,97,0,148,116,138,88,45,172,16,250,169,10,55,168,155,249,246,117,74,112,183,220,144,84,127,245,255,79,75,162,219,9,150,235,53,199,122,194,58,198,192,83,66,183,114,7,36,198,143,179,218,40,178,248,218,185,108,140,103,50,91,31,235,191,230,109,62,140,189,224,31,241,31,255,48,167,106,18,242,164,95,24,208,232,159,107,188,95,66,187,61,92,245,43,201,191,135,1,41,19,255,103,156,115,9,219,112,48,74,62,113,152,120,196,200,133,105,206,67,75,26,102,159,159,237,244,74,119,46,70,217,24,102,5,82,212,11,224,67,44,241,148,125,122,140,30,141,56,185,122,202,228,228,152,203,143,221,92,116,168,69,113,89,106,187,215,201,255,151,132,143,105,97,52,138,102,179,146,194,72,5,11,142,16,31,119,218,54,11,45,117,143,78,191,169,116,115,101,231,67,196,81,203,175,126,36,74,3,153,52,15,176,118,87,2,10,235,166,166,25,217,24,97,56,174,121,208,62,83,81,159,25,1,81,67,213,89,71,34,140,83,221,7,159,118,96,172,176,235,249,185,28,97,166,17,64,245,165,23,63,251,128,105,12,76,148,92,91,188,236,238,25,184,58,203,60,22,171,192,183,224,144,158,173,39,61,188,92,76,155,181,102,5,187,207,150,94,58,3,250,36,236,210,151,254,24,164,165,111,28,108,229,47,22,146,124,12,137,148,24,184,174,127,13,247,114,83,177,100,178,209,116,247,77,184,99,249,116,52,90,208,48,242,239,23,251,172,248,54,133,62,24,240,90,110,209,64,19,65,231,127,36,40,74,61,89,232,108,40,133,183,241,255,164,20,180,249,37,233,11,144,123,198,10,134,56,30,115,232,181,188,113,167,11,26,133,132,207,13,144,114,236,85,141,70,151,42,10,176,211,160,243,33,210,57,247,197,33,32,215,207,152,153,82,222,95,87,217,232,251,9,157,52,92,92,186,221,244,36,132,244,171,126,222,212,178,213,118,239,52,68,215,228,157,37,229,77,151,40,95,205,177,209,250,59,223,193,65,135,147,161,220,60,30,20,221,12,251,251,237,115,218,76,211,222,227,113,244,133,150,144,25,141,230,202,17,219,118,142,8,254,249,111,8,74,66,92,214,206,5,252,176,47,65,208,174,127,25,182,208,254,125,215,136,104,95,122,148,47,160,24,171,217,115,108,36,46,111,121,54,209,200,78,201,242,47,82,146,153,116,84,30,151,175,199,2,189,89,106,30,113,219,11,101,233,191,165,1,168,238,15,156,187,76,114,205,125,10,232,251,59,152,234,16,241,125,111,195,40,170,83,198,62,219,137,128,20,195,25,33,235,77,95,39,151,116,175,239,44,250,171,84,173,154,211,23,212,157,160,162,208,164,16,244,147,14,14,17,6,104,150,53,108,250,78,227,27,137,22,252,98,238,175,243,37,70,13,183,79,164,152,113,101,78,244,30,197,103,210,103,214,38,156,171,0,17,21,28,178,30,168,20,31,200,208,51,52,113,15,151,103,235,237,40,10,81,34,216,193,173,182,231,138,223,70,74,110,140,135,128,67,193,157,182,109,142,223,157,163,206,148,192,228,100,183,148,130,219,246,217,18,184,83,27,227,178,40,188,85,136,45,33,244,69,87,159,128,40,97,108,157,0,46,148,60,23,222,235,38,205,188,53,18,244,187,182,168,183,237,144,27,24,195,130,65,220,216,15,20,137,249,27,41,218,232,246,197,92,106,119,80,113,188,192,30,233,34,219,39,146,187,114,27,18,165,104,236,249,38,44,105,166,205,230,49,128,243,36,251,113,40,38,25,215,224,120,27,235,159,12,92,34,87,109,158,74,60,6,136,178,187,38,91,137,86,88,121,201,214,195,151,83,64,228,135,143,158,147,97,176,188,111,251,247,113,197,192,23,113,9,177,188,15,65,193,111,153,189,107,45,251,63,75,15,75,144,12,21,147,41,0,174,131,76,50,32,230,156,172,12,21,217,99,174,122,176,90,142,255,218,205,218,102,252,254,211,225,2,68,190,66,50,226,64,173,14,103,174,112,42,47,226,144,59,125,110,69,123,255,9,156,24,136,238,168,115,76,198,25,170,142,181,178,27,82,125,25,38,98,50,248,232,139,82,51,79,162,74,26,73,204,26,40,13,40,2,73,96,105,177,92,99,35,99,110,56,185,105,177,205,31,100,153,114,150,60,150,252,43,129,210,116,71,159,252,129,54,152,242,65,180,226,15,50,224,127,124,175,143,91,38,46,62,8,22,59,186,178,38,77,246,103,48,216,212,109,56,156,174,127,24,51,123,161,249,178,142,219,27,68,158,78,254,94,242,73,34,240,204,200,93,216,7,25,228,165,205,3,19,2,181,77,104,175,11,217,230,194,135,111,69,253,161,56,50,214,192,155,137,146,17,189,167,202,57,121,74,241,142,45,201,161,154,57,125,92,44,130,241,88,74,115,124,14,144,36,13,187,40,11,139,4,59,158,157,206,13,92,151,135,1,219,94,61,152,173,99,202,240,172,225,103,253,248,69,184,171,34,33,169,218,245,125,15,58,199,178,40,202,80,134,75,170,110,92,65,6,58,200,15,51,116,102,229,188,24,164,185,80,221,62,235,227,1,238,159,158,44,47,211,248,136,211,153,57,241,104,231,90,19,39,187,253,118,187,69,91,208,213,90,157,249,110,157,246,186,4,46,212,11,235,27,55,22,236,16,139,224,123,76,76,174,18,156,21,2,25,59,83,147,157,186,202,18,243,139,77,192,205,43,11,67,231,130,169,53,171,6,241,244,138,2,96,125,93,209,194,120,187,162,104,129,237,118,242,149,94,212,207,222,141,202,202,204,103,231,34,132,92,157,95,239,176,202,195,185,87,154,63,219,10,215,8,146,73,190,222,17,110,27,90,35,66,27,93,191,17,12,120,158,138,224,58,68,152,169,243,48,157,252,163,132,148,157,222,184,145,161,202,141,123,93,61,82,14,213,82,53,66,165,100,215,10,77,207,216,139,35,208,176,63,63,80,219,7,147,222,36,12,252,16,92,225,56,96,70,218,129,99,205,25,99,208,253,109,43,104,153,0,224,39,192,163,67,138,85,157,8,128,148,197,89,194,87,99,206,81,141,47,214,217,156,211,187,184,220,33,32,20,31,143,48,136,147,54,141,147,129,53,91,215,115,208,74,187,36,225,92,30,238,23,79,195,80,124,161,28,40,129,212,156,128,13,94,16,64,122,47,166,181,116,236,218,16,106,162,20,12,250,106,59,75,168,173,41,229,75,239,230,135,79,240,61,106,144,243,222,80,207,8,155,238,226,204,246,25,2,83,116,227,42,121,189,61,88,237,200,221,66,111,84,209,44,204,5,74,21,249,236,194,187,52,103,164,109,114,191,27,0,240,99,60,253,103,92,69,90,87,109,109,138,61,171,55,129,98,152,62,65,82,93,47,130,95,171,12,145,48,243,4,220,47,118,144,188,144,153,224,242,141,144,94,218,128,144,77,106,98,182,215,118,91,73,238,22,122,110,3,109,89,91,34,0,57,72,86,228,158,153,209,235,58,200,213,223,68,254,49,210,128,11,87,0,207,25,93,183,141,193,9,142,11,15,213,209,90,220,249,117,222,163,188,42,116,162,111,235,175,70,29,243,205,184,46,214,112,219,68,27,190,37,228,13,196,98,127,58,220,90,248,241,41,128,82,170,102,78,72,99,103,47,49,238,210,203,217,40,130,83,98,143,81,119,52,173,166,24,234,61,253,11,147,118,189,128,69,161,207,122,161,251,67,139,246,0,44,109,95,241,166,224,177,225,201,10,38,201,24,44,192,55,22,191,109,159,167,39,67,213,33,100,6,197,183,223,105,223,51,37,21,232,53,7,12,64,243,13,77,22,76,175,156,127,201,50,147,144,135,179,71,59,88,161,195,29,23,213,184,66,77,202,54,134,198,21,205,74,59,68,197,2,150,28,192,219,164,192,158,231,193,240,26,176,33,136,97,129,95,91,76,114,79,86,97,220,135,80,233,39,150,150,27,223,206,160,84,151,120,226,45,231,200,167,121,200,46,1,132,39,112,88,96,85,173,249,29,67,46,208,224,131,84,81,64,218,16,15,12,243,215,86,157,212,204,147,221,26,11,10,114,75,9,240,8,16,58,152,196,219,149,51,8,94,225,203,7,157,156,249,220,220,207,80,128,47,103,189,58,38,83,183,122,51,230,254,146,160,37,235,226,233,55,164,177,33,246,224,67,54,25,126,27,216,100,83,102,46,231,99,215,206,57,243,30,174,54,153,209,116,17,156,121,215,104,69,33,59,37,187,95,75,158,233,68,148,64,236,174,32,201,143,189,99,126,50,216,65,155,184,98,84,102,243,47,178,99,59,227,198,213,53,206,39,35,180,9,162,212,58,190,48,80,234,176,124,165,130,234,100,117,5,245,122,210,159,134,31,165,144,196,154,81,131,130,236,180,4,23,225,45,144,92,99,117,71,130,142,141,103,81,168,211,2,123,203,171,59,133,24,46,169,116,160,216,233,44,215,66,201,119,51,58,75,50,68,116,127,170,113,129,55,193,109,155,237,246,191,189,150,135,24,5,204,65,201,86,15,202,87,40,122,227,52,245,82,182,54,65,104,165,101,190,208,117,246,203,163,168,171,35,67,186,170,221,100,63,0,206,157,229,28,237,147,132,88,91,215,64,64,22,48,88,246,232,140,146,211,199,110,230,207,238,78,66,78,104,253,244,227,114,94,210,30,6,33,43,1,110,176,2,156,178,126,202,213,183,124,213,218,56,96,100,54,192,53,69,60,180,73,48,142,15,85,251,191,216,147,246,47,251,203,203,138,14,174,9,73,186,102,220,0,200,22,56,137,234,117,155,105,229,151,192,129,193,93,234,222,103,57,195,107,240,92,18,180,41,23,23,255,255,135,26,222,109,47,129,205,129,52,192,82,153,195,24,72,58,156,127,159,210,114,67,196,173,239,17,84,216,115,57,151,70,218,133,179,61,149,175,160,128,222,103,91,202,239,92,198,173,251,58,186,236,105,215,23,167,254,58,4,21,22,17,213,211,230,47,195,183,154,245,187,224,165,236,107,184,195,149,49,79,138,158,97,201,64,138,145,249,37,253,56,175,148,83,197,74,69,186,47,38,63,14,241,224,30,52,152,74,163,144,190,253,92,176,164,109,217,165,118,19,56,214,162,10,193,213,18,95,72,55,150,22,199,50,196,111,155,204,32,122,25,68,234,156,43,178,92,160,204,83,138,2,184,248,7,132,201,144,69,176,216,12,49,175,55,89,163,91,23,159,27,226,183,111,153,13,35,140,237,237,170,126,119,171,55,105,81,53,55,142,131,46,39,136,83,145,158,216,192,73,71,22,117,124,243,85,81,130,52,28,216,143,226,153,141,3,162,141,249,125,8,119,27,65,133,135,123,117,71,161,45,130,255,194,160,178,21,123,106,105,199,3,146,205,115,157,18,61,181,226,101,151,234,244,10,17,216,104,186,3,215,32,157,200,151,190,41,62,181,74,5,160,213,185,70,97,253,164,115,81,108,228,207,4,144,210,54,224,36,93,21,210,109,58,54,121,127,235,182,110,122,161,24,48,114,193,83,31,221,109,136,70,83,212,203,195,232,231,69,5,55,157,106,77,101,19,58,55,127,91,240,85,64,11,229,155,10,93,177,2,144,20,75,121,186,81,171,50,1,196,62,217,231,16,206,250,186,173,24,60,218,230,99,216,36,3,103,61,237,73,61,170,38,35,224,158,166,103,119,128,4,5,152,194,141,234,113,149,54,196,25,235,18,81,227,137,137,138,115,20,204,38,189,115,69,224,31,135,6,32,171,72,87,42,144,71,72,255,171,79,132,159,83,151,209,62,152,25,79,133,19,172,154,90,84,80,101,131,150,37,245,195,199,210,235,98,122,229,215,7,164,79,63,62,80,142,144,161,189,235,24,212,200,109,145,185,104,122,29,112,81,147,15,4,108,147,244,184,155,249,18,80,201,174,227,93,226,109,63,7,17,14,209,141,194,160,30,170,18,60,144,32,224,177,0,106,248,126,107,84,185,179,106,146,13,238,80,251,18,50,96,122,216,217,112,187,148,102,111,47,244,158,22,39,76,59,150,43,22,117,202,253,88,26,166,126,243,142,239,81,69,185,255,93,56,20,32,232,185,22,217,19,198,221,159,42,176,105,127,180,90,189,136,213,241,120,92,0,77,136,165,142,142,126,142,164,219,231,41,237,134,253,191,235,254,252,57,52,25,89,120,215,145,142,87,152,149,107,177,79,86,176,4,105,59,150,254,14,74,110,116,206,16,0,218,98,156,66,18,10,16,202,136,15,80,236,236,233,75,132,186,168,174,233,16,240,124,0,189,243,98,252,33,121,215,44,173,199,127,71,233,97,165,227,102,12,62,59,225,180,119,55,117,95,159,229,177,99,143,111,247,182,37,180,23,219,51,67,250,113,124,122,213,160,93,82,156,170,252,0,1,76,22,11,250,91,147,112,1,233,251,21,112,60,137,25,215,114,231,83,28,55,129,94,198,200,247,80,156,163,198,211,214,235,239,111,210,160,137,128,181,114,163,61,8,94,83,46,49,30,181,239,140,222,109,66,167,226,89,159,32,73,145,21,222,213,65,62,66,94,137,206,128,169,236,73,167,141,150,232,238,36,44,136,68,28,4,21,153,225,253,254,31,210,190,138,17,5,228,142,90,163,91,64,60,208,230,70,88,201,198,140,171,37,112,143,83,251,39,36,63,189,48,135,196,100,189,76,124,37,117,179,153,183,236,97,94,72,5,144,76,23,71,22,137,91,101,17,51,31,37,37,248,167,248,202,225,125,28,24,192,51,67,242,20,243,183,110,138,211,210,110,39,221,189,226,241,100,225,217,111,128,6,152,234,156,179,79,2,139,150,103,51,47,252,21,104,71,84,83,243,17,144,151,52,96,128,26,163,179,77,162,97,109,136,128,106,219,50,111,229,203,148,252,102,19,181,220,239,169,7,60,6,173,111,160,55,24,162,69,223,39,186,222,104,184,206,203,0,68,178,244,108,51,107,230,205,176,248,207,12,225,122,184,184,1,99,226,173,135,71,136,45,243,127,168,160,134,31,180,45,53,1,213,36,43,83,51,59,61,115,223,67,123,54,86,38,128,71,198,210,179,241,150,253,253,1,26,104,127,234,182,86,121,188,19,134,211,19,249,75,96,210,137,255,175,48,38,23,82,107,180,73,87,97,17,31,217,160,77,243,143,164,224,77,154,152,148,205,66,240,48,168,156,21,103,19,214,154,17,173,156,16,31,18,63,134,224,211,145,46,114,33,113,105,125,72,78,202,25,183,28,255,45,63,169,16,225,2,237,156,45,254,223,125,195,250,99,49,156,250,188,216,169,104,171,157,188,114,72,110,29,153,187,99,254,51,237,255,23,98,131,248,193,121,59,142,7,176,78,52,182,134,170,136,125,40,234,245,225,74,212,208,176,105,253,8,32,143,69,180,249,246,10,31,176,129,144,255,199,193,59,12,181,231,207,169,241,243,19,253,220,49,45,195,42,147,102,239,117,186,240,63,156,184,43,225,119,87,44,38,11,106,231,241,208,145,167,222,147,22,240,37,62,139,30,249,0,209,78,164,84,131,254,178,126,91,170,226,29,73,170,154,101,221,202,18,92,146,134,178,38,195,106,88,228,86,86,172,34,113,89,4,85,139,78,39,3,161,49,94,245,107,21,206,162,64,240,35,201,126,89,226,156,229,141,165,29,4,22,197,202,125,44,200,64,176,137,55,95,167,234,104,86,244,217,45,234,206,4,6,171,85,146,235,237,168,81,103,77,204,104,16,110,90,132,100,240,72,96,188,201,254,56,43,229,76,8,144,250,190,182,102,89,64,104,238,222,184,173,138,130,235,233,91,226,30,237,38,236,194,116,180,36,198,97,37,242,32,60,224,15,13,203,190,121,127,41,1,108,205,117,79,104,173,232,164,128,0,31,193,82,164,115,1,175,199,50,22,0,215,136,87,212,105,174,240,47,27,51,93,165,183,61,96,31,150,125,70,38,192,85,215,191,65,159,42,123,59,211,210,39,96,64,53,80,103,134,214,75,89,23,40,114,4,148,61,56,175,176,119,180,61,162,119,184,21,110,204,103,52,202,109,151,202,204,240,215,165,116,96,52,113,64,112,42,171,54,172,169,69,253,44,153,24,232,19,141,73,3,80,141,143,57,23,209,218,79,5,176,20,117,197,223,97,0,0,216,103,205,251,42,189,173,104,182,224,240,187,184,90,150,165,151,54,237,248,21,195,252,26,86,186,43,130,85,173,165,88,77,47,61,60,251,197,177,40,114,201,153,72,161,39,61,136,217,22,39,227,180,112,20,184,0,22,255,248,87,132,120,113,8,6,226,212,166,57,112,185,75,15,83,79,196,106,136,205,5,59,250,63,35,80,140,176,236,196,248,3,221,98,250,104,32,99,152,165,109,139,192,40,49,68,14,50,89,102,202,12,64,120,114,49,227,205,144,18,43,180,65,47,167,89,67,145,180,44,241,173,23,232,86,141,103,210,72,240,225,180,133,221,238,4,125,161,121,44,204,5,162,64,34,84,167,152,247,154,190,162,116,71,83,180,181,174,3,151,227,180,162,28,198,133,1,195,199,54,251,220,4,182,126,209,15,24,207,187,240,50,11,120,250,158,87,125,246,74,64,175,190,21,150,255,202,170,125,38,228,16,24,166,186,7,113,0,133,182,112,138,188,2,24,120,236,10,76,154,89,48,23,228,159,219,144,219,209,76,59,25,100,202,46,203,178,117,252,97,240,97,42,143,205,52,199,220,7,0,109,217,139,126,170,178,227,213,192,16,171,133,173,237,240,186,6,14,155,94,157,194,99,123,174,181,74,164,126,56,178,0,172,77,163,74,172,53,5,161,130,161,162,149,232,150,69,170,172,59,70,142,112,87,58,16,192,67,8,250,29,140,221,17,117,167,133,43,180,141,157,214,18,131,114,105,147,206,25,138,207,188,30,41,9,97,113,247,123,251,56,165,182,239,95,79,152,45,113,160,213,230,249,227,167,149,52,172,156,182,242,134,61,19,90,144,248,100,252,168,76,213,246,126,123,175,8,114,218,41,247,90,229,94,238,86,73,43,35,42,116,168,217,75,167,166,122,230,82,130,255,164,51,9,86,79,111,49,152,198,132,96,62,12,131,23,66,96,51,213,29,13,144,20,26,228,66,41,228,68,254,126,173,192,51,62,41,184,136,182,93,102,144,250,65,236,200,19,121,182,87,125,72,97,132,164,29,130,211,26,115,217,177,199,35,54,132,98,87,138,188,229,34,130,240,81,186,231,130,41,17,74,64,27,41,169,251,229,192,38,247,81,85,224,10,181,80,164,164,112,73,150,53,119,166,144,157,52,98,187,48,28,64,77,33,237,100,1,46,123,40,27,232,128,105,190,126,27,132,205,16,107,184,30,187,240,29,128,81,177,9,175,37,159,188,53,109,59,15,33,102,39,182,31,73,163,176,14,150,178,216,231,41,152,253,100,240,46,106,181,137,111,240,101,204,74,57,134,179,49,230,134,124,152,70,64,166,43,65,203,80,53,157,166,39,138,142,243,74,145,217,9,194,93,128,67,93,129,161,161,254,211,189,239,205,32,171,253,118,141,204,240,183,222,146,198,220,187,58,201,238,218,179,206,89,183,40,198,33,53,38,40,144,216,247,161,189,216,173,9,22,72,148,174,45,3,127,35,125,111,140,15,207,119,246,38,244,195,69,85,106,121,28,241,125,124,103,116,108,152,84,133,165,68,92,5,189,160,223,125,159,69,84,91,214,24,52,36,207,180,152,8,156,70,209,194,220,165,138,212,192,246,132,124,186,64,218,179,23,131,210,117,7,15,197,250,249,187,104,74,19,195,232,168,66,171,125,133,252,89,123,236,67,152,150,187,82,161,241,29,160,206,15,254,101,201,34,79,182,6,88,237,204,67,3,24,199,64,58,22,71,118,31,80,235,148,111,111,74,248,229,15,0,160,215,0,121,227,15,243,58,122,251,203,236,223,102,217,235,105,113,239,209,206,227,198,166,116,250,85,48,71,14,78,216,2,167,129,129,240,167,56,89,118,161,125,49,228,56,221,13,219,207,36,68,253,27,45,219,117,151,229,111,247,206,97,173,132,8,74,182,16,125,54,238,31,46,244,50,250,3,216,182,42,120,67,61,39,106,101,23,248,21,80,151,115,41,105,95,47,32,90,53,3,164,31,12,113,105,26,135,101,186,43,191,173,143,177,4,75,109,96,7,121,5,231,218,250,45,96,254,193,146,225,251,238,21,240,27,207,43,187,7,61,254,195,234,210,152,46,241,186,188,216,234,82,179,109,61,190,139,211,58,36,74,149,107,249,150,196,71,226,167,232,40,42,19,152,17,194,16,94,5,11,57,37,43,99,98,248,81,211,60,69,192,80,94,225,241,197,53,76,100,1,166,253,132,17,3,72,232,72,214,60,18,151,159,15,167,78,27,76,142,22,21,129,121,10,185,35,246,49,165,218,73,182,236,65,1,175,236,230,71,209,189,163,164,179,194,209,86,6,180,219,147,94,15,212,246,83,21,183,250,40,230,78,222,159,74,94,13,20,247,51,90,218,253,125,50,81,72,93,1,200,50,199,223,192,197,223,38,208,98,122,118,7,82,178,154,193,50,199,199,7,184,231,120,39,2,232,41,182,32,75,56,236,176,5,0,113,190,13,109,1,175,212,249,89,21,130,204,162,228,119,244,190,87,252,151,13,40,209,103,93,95,199,103,141,133,122,94,189,161,222,26,229,214,114,137,110,97,84,81,251,213,80,122,215,144,113,154,105,12,130,191,24,0,226,159,46,86,119,142,104,231,72,118,224,91,195,94,179,212,168,32,243,2,25,219,4,197,34,167,252,198,18,155,87,88,62,165,118,253,176,96,152,186,128,214,140,226,59,11,113,104,102,96,136,126,9,13,140,165,46,116,134,52,249,105,131,168,226,83,93,216,194,247,236,251,159,42,118,243,93,85,175,120,106,134,75,146,217,187,183,49,138,190,5,189,3,203,106,166,110,104,108,70,111,165,41,203,34,212,254,32,10,2,238,30,243,126,47,119,175,63,107,73,75,131,105,17,54,253,158,128,179,196,198,64,151,178,55,47,159,191,106,78,234,208,198,108,42,131,2,33,44,121,43,48,137,107,252,205,15,84,242,200,169,148,239,199,117,248,6,151,51,83,45,149,57,75,160,202,27,122,235,14,50,90,135,90,94,140,171,241,123,236,90,200,243,190,6,111,165,246,139,34,141,151,172,38,34,66,201,218,83,110,52,12,146,6,26,248,102,120,174,193,25,147,171,152,87,174,79,55,208,166,73,111,90,214,25,117,239,102,226,213,182,128,93,49,129,174,3,2,180,9,250,166,8,32,141,187,26,55,157,229,144,64,195,91,154,133,56,176,6,198,60,119,115,232,70,213,143,59,250,97,136,50,75,125,198,19,151,141,168,48,163,47,67,211,114,119,103,69,9,119,244,236,196,164,248,228,69,215,205,245,16,57,177,244,43,224,109,172,45,14,5,161,195,63,81,38,117,19,125,248,179,103,199,168,84,151,192,55,216,72,96,43,117,199,103,51,202,42,177,40,169,84,157,153,173,244,141,108,142,38,188,53,35,151,221,147,12,148,111,151,129,212,37,253,142,191,152,21,241,153,150,30,71,95,49,124,83,150,47,109,169,199,96,70,141,167,74,79,11,152,159,93,215,159,185,141,249,140,114,217,75,87,133,177,114,114,27,32,86,10,246,20,157,127,160,164,227,79,194,177,107,49,142,179,84,144,135,178,81,30,7,228,120,116,11,103,210,83,15,94,77,40,116,144,27,125,81,192,231,217,112,4,184,78,6,144,65,184,221,84,114,52,150,241,217,130,114,219,252,15,34,244,209,76,178,193,231,229,38,137,147,0,147,242,150,26,33,32,28,132,60,63,134,221,9,214,135,97,120,217,109,78,130,199,253,153,215,234,19,186,201,199,169,20,132,151,74,179,54,65,25,171,126,126,88,23,247,222,39,52,65,85,45,245,229,214,38,98,14,0,10,216,42,17,230,34,91,84,144,209,31,186,211,140,175,188,80,202,99,174,124,88,40,32,214,235,133,253,145,179,186,102,42,135,61,67,235,163,133,41,35,25,168,87,141,24,186,210,233,150,19,220,120,81,123,169,245,18,197,27,207,176,15,197,115,139,69,152,82,211,148,77,184,232,173,29,253,46,123,173,245,217,54,231,135,218,236,101,196,45,109,136,189,206,68,215,214,77,251,43,39,224,144,62,135,50,114,247,67,110,247,38,143,220,5,1,173,142,88,7,149,152,225,194,10,114,152,121,105,239,242,249,117,29,172,2,39,98,218,33,31,69,93,11,210,222,132,40,251,162,173,144,13,165,165,242,181,202,215,89,196,228,253,39,70,73,153,144,63,184,211,2,204,107,51,166,197,173,14,15,96,66,141,11,12,244,148,50,16,214,9,8,52,6,165,105,91,184,10,10,62,135,250,200,159,69,227,229,86,98,229,73,27,200,217,108,233,211,81,90,93,45,50,50,149,19,35,23,116,202,113,21,211,33,217,140,128,86,228,185,130,140,104,87,180,174,131,213,254,48,90,67,239,159,204,139,229,42,236,142,82,151,187,165,11,12,150,53,56,10,76,97,213,117,217,51,242,133,135,229,78,117,95,26,31,69,32,138,147,70,226,136,42,0,8,199,224,233,35,206,48,207,61,99,52,101,204,118,143,245,236,120,33,226,57,223,53,32,255,6,236,127,223,89,137,99,84,204,80,106,20,237,64,149,193,65,7,41,202,120,56,115,112,137,35,254,243,28,47,4,229,33,115,177,48,219,231,48,63,139,95,214,209,6,170,197,116,222,104,88,254,141,16,48,222,226,9,47,121,65,188,142,38,129,229,60,122,25,131,229,78,249,211,139,93,199,181,248,231,247,38,161,131,223,146,216,88,123,189,77,186,220,2,185,53,173,226,101,153,213,103,171,140,207,44,51,120,168,36,182,213,176,87,166,170,61,250,49,139,249,215,135,168,170,59,95,118,142,249,166,177,121,94,175,159,219,228,219,117,28,222,43,180,225,108,140,7,25,5,94,45,171,5,65,137,255,40,123,190,89,181,94,76,172,91,161,197,240,85,79,172,28,47,57,205,233,102,137,143,28,155,20,20,157,41,148,175,43,167,5,82,171,148,109,247,237,236,176,176,124,1,158,189,93,168,51,115,231,208,228,55,164,123,212,27,25,190,38,1,120,25,153,91,236,95,116,67,210,173,224,156,220,91,207,120,91,114,212,191,71,198,205,146,136,65,91,33,204,192,154,155,243,71,11,55,239,100,89,204,247,199,59,120,22,68,109,137,194,203,81,61,247,11,226,242,210,155,195,209,1,193,108,163,178,20,22,170,30,148,214,80,229,153,91,103,246,237,10,245,110,211,150,205,98,239,92,94,71,206,91,253,204,90,157,216,152,35,148,167,8,201,167,24,239,191,158,102,23,131,159,64,99,81,159,58,193,185,68,1,28,24,38,198,132,80,191,19,122,235,99,129,100,49,253,29,52,194,32,108,106,166,243,179,53,189,96,59,73,241,61,32,223,84,218,118,59,32,64,9,98,239,207,219,101,38,106,54,148,148,25,5,50,107,106,152,242,117,192,102,56,184,19,232,133,157,243,182,52,144,217,94,101,153,221,88,157,52,224,159,93,159,71,2,115,200,230,116,202,177,236,75,20,176,16,39,147,24,150,195,21,251,77,57,185,113,216,168,48,127,164,56,104,92,23,85,141,159,93,53,192,103,163,130,24,85,85,160,61,246,23,185,196,18,158,228,129,148,126,206,52,198,191,182,12,98,112,31,56,160,62,208,196,234,1,56,249,23,61,115,25,164,254,151,45,11,124,107,53,151,131,221,52,249,185,90,5,4,129,177,134,168,239,37,50,111,225,178,53,251,9,5,87,32,111,75,239,38,160,33,50,128,211,5,250,31,61,177,31,115,182,221,118,33,225,75,165,5,43,89,152,62,217,185,246,122,194,98,47,193,42,74,46,144,111,16,231,76,88,151,7,93,68,144,237,82,117,206,167,239,6,137,55,125,14,88,92,201,143,148,62,216,55,224,150,178,38,77,42,167,163,233,124,131,220,55,50,219,117,225,244,220,233,124,27,133,246,213,86,54,152,29,92,98,226,98,54,110,144,186,41,161,225,72,199,30,105,121,160,56,141,23,100,40,88,208,169,32,196,122,95,231,57,244,199,120,13,232,165,250,170,24,34,231,23,205,33,18,214,128,56,165,14,48,104,223,133,183,73,58,100,111,112,115,239,70,81,81,38,94,88,232,164,212,242,0,59,114,36,133,89,252,41,204,37,193,144,244,255,242,124,20,131,112,126,131,187,205,71,229,86,90,197,199,245,45,120,190,56,223,164,63,177,75,188,238,180,176,137,182,95,221,29,158,104,4,224,38,183,94,172,67,44,62,168,237,218,85,159,58,25,168,173,108,204,228,81,18,145,207,176,19,10,212,78,133,108,169,178,117,11,19,155,152,200,117,243,99,143,126,93,75,167,4,103,249,245,27,30,184,78,162,35,174,200,4,59,119,138,195,58,130,59,179,147,48,207,134,201,207,31,90,145,168,212,195,79,220,16,253,80,24,42,159,61,178,241,81,140,246,198,225,166,94,74,63,254,3,218,93,2,74,194,239,192,68,55,75,132,51,79,200,162,72,133,34,87,86,7,157,235,37,94,78,191,150,81,213,162,147,20,232,243,173,36,1,244,91,3,192,10,224,194,229,74,147,19,192,165,168,153,5,127,230,113,185,206,127,146,80,114,246,179,16,31,90,0,242,254,82,189,36,246,211,7,118,168,33,154,220,184,107,101,40,150,196,194,242,253,216,72,132,210,147,230,224,198,34,75,25,74,233,205,159,168,6,197,50,217,127,251,94,27,0,89,55,171,138,10,197,251,46,127,84,139,97,212,131,44,89,5,181,154,11,223,2,106,249,29,222,72,44,89,57,56,8,138,102,140,86,159,219,77,239,32,203,126,142,214,192,72,16,119,161,71,155,250,58,115,189,112,51,213,249,25,85,78,170,171,102,164,103,133,109,37,229,130,167,116,64,21,234,76,246,89,206,141,235,89,223,141,56,47,168,166,97,190,26,197,70,97,133,200,148,53,45,183,39,129,38,122,174,116,58,75,115,221,204,101,52,24,94,177,14,237,2,172,234,210,8,208,25,77,235,113,24,108,216,242,184,180,255,173,101,240,51,246,200,240,13,156,209,93,60,66,170,252,82,230,13,215,146,117,255,210,7,34,122,10,106,156,176,21,68,222,248,33,83,152,206,191,60,18,158,149,114,74,41,60,203,244,210,249,189,212,25,25,75,131,95,76,207,254,188,23,124,249,162,255,170,137,0,81,97,181,221,127,2,120,240,234,80,28,115,105,158,136,89,77,135,103,255,251,8,186,242,63,176,164,122,8,11,128,19,58,243,8,212,252,204,84,170,108,158,179,247,0,254,32,87,139,213,136,45,180,92,145,67,92,246,247,205,97,103,87,101,163,137,0,61,23,230,147,218,153,102,235,104,17,24,246,70,190,79,179,238,178,41,56,128,115,241,148,114,229,173,144,63,54,151,123,191,45,145,222,89,230,29,59,34,163,123,120,56,34,137,149,161,32,221,255,87,39,50,57,112,84,159,209,51,170,143,167,190,117,145,202,12,127,248,132,142,52,118,154,247,22,242,179,161,240,146,155,7,176,79,18,1,228,242,227,81,34,121,92,236,105,176,207,233,51,86,159,119,70,173,14,42,103,31,241,149,157,98,49,61,96,106,94,142,12,146,88,63,16,173,84,14,216,170,188,7,119,188,94,156,24,78,218,117,39,252,216,201,136,241,118,24,231,164,15,9,211,193,68,14,9,140,214,99,95,235,172,219,136,83,12,95,75,88,48,152,236,153,95,137,236,38,125,35,176,220,87,52,101,106,40,172,224,140,105,118,201,227,143,43,59,162,152,247,197,72,70,232,183,21,160,2,64,169,41,69,166,102,52,189,217,130,19,196,230,34,133,35,31,17,193,45,252,112,79,79,223,99,168,154,14,19,74,179,41,246,27,199,128,101,54,80,252,173,165,241,80,26,204,142,255,57,94,25,56,246,22,133,229,144,110,212,118,251,36,49,81,254,183,116,222,99,70,181,22,74,96,199,161,124,176,7,199,9,56,128,64,200,185,222,37,225,144,156,152,22,99,76,208,43,99,207,169,146,220,182,136,30,96,166,118,49,125,40,132,106,49,212,158,91,55,84,208,213,75,63,190,113,71,83,98,109,21,176,11,204,253,157,79,106,111,232,239,253,187,98,141,32,52,39,209,183,100,176,183,32,232,137,209,189,13,67,230,44,99,233,235,31,211,62,149,120,185,114,79,123,8,153,151,112,255,65,154,228,16,226,177,21,18,10,146,172,134,181,123,4,253,122,188,229,98,89,112,147,19,145,108,246,176,210,201,128,231,96,230,39,140,7,175,246,144,253,114,34,223,14,48,134,160,78,112,135,138,197,142,208,213,221,156,197,198,131,42,169,203,191,140,36,205,131,59,11,239,147,205,235,193,132,59,199,198,42,204,244,120,24,172,221,253,85,141,118,110,76,153,91,146,222,142,200,251,52,172,145,250,47,123,86,49,253,220,27,77,170,51,36,179,148,26,32,251,162,197,246,163,248,65,123,233,68,194,166,153,206,118,238,22,134,49,13,218,176,11,183,124,197,148,169,251,224,80,11,209,166,233,229,19,220,114,244,144,246,17,131,119,108,78,6,26,238,121,82,13,57,179,139,149,164,255,235,181,20,240,76,155,71,61,89,192,100,16,244,93,71,199,139,70,203,107,44,233,154,66,40,255,1,15,20,206,89,244,23,68,123,164,177,175,187,170,150,195,150,44,96,99,142,169,220,220,197,235,124,72,198,60,112,180,196,35,190,154,107,29,177,10,243,111,210,61,157,156,223,255,101,5,210,27,224,15,23,138,119,65,201,139,134,84,70,122,22,204,153,5,193,108,54,149,173,173,37,200,81,229,93,72,7,45,14,51,177,85,166,96,189,55,43,70,88,172,251,17,221,163,81,62,196,216,14,31,82,46,38,65,125,42,32,4,9,145,100,31,102,106,231,86,31,167,246,39,11,28,118,34,92,179,80,65,191,115,43,247,211,118,115,124,156,122,145,222,177,73,161,7,117,51,20,29,178,100,26,127,202,208,177,209,121,101,140,194,20,229,139,123,55,186,209,31,33,39,115,64,97,128,152,60,147,70,35,97,4,156,87,181,58,244,132,109,115,229,91,215,10,28,25,21,57,163,234,21,101,81,18,220,78,130,105,85,41,164,78,228,156,201,182,234,93,221,241,194,212,66,84,4,11,81,116,94,234,37,200,8,214,228,253,58,205,250,62,168,189,1,46,223,0,158,154,29,127,247,188,25,193,165,228,117,234,121,149,167,254,11,3,15,12,91,42,46,11,240,230,134,120,108,46,58,63,23,230,140,113,173,206,94,55,63,20,187,32,255,142,32,192,135,161,231,95,115,204,50,125,129,245,15,153,89,124,35,87,200,91,78,68,126,100,158,103,224,232,192,132,174,34,19,19,48,139,182,247,255,70,88,227,139,253,31,10,222,62,188,140,85,169,143,143,14,29,108,159,46,98,211,30,129,63,149,77,230,246,61,181,103,153,124,242,214,63,70,78,193,78,208,159,94,20,59,30,81,88,112,124,123,183,101,239,217,86,232,137,59,250,5,110,107,71,27,31,15,33,62,200,161,218,153,82,134,5,7,141,180,7,152,169,23,182,33,150,252,223,90,209,54,177,15,50,19,8,253,37,226,84,143,33,164,230,38,215,102,42,156,198,36,35,149,175,75,79,102,252,69,215,7,165,103,252,189,221,18,204,32,86,110,22,47,74,38,247,11,126,5,145,242,247,20,9,190,177,121,79,16,110,73,41,45,141,3,247,35,3,252,191,45,7,156,127,115,198,74,194,5,25,124,110,61,109,115,151,84,72,182,140,170,23,217,123,133,98,143,18,53,128,55,78,61,89,152,214,253,63,133,196,183,215,107,107,158,245,129,15,153,169,246,158,65,172,8,47,226,30,126,10,64,163,175,108,218,130,19,89,235,34,206,150,176,199,6,140,234,201,165,130,107,208,64,112,36,44,115,250,199,236,204,60,127,43,124,225,163,49,76,103,210,254,126,180,82,44,230,68,93,12,246,201,186,72,190,172,76,128,42,173,0,221,120,14,150,19,197,121,163,71,111,214,183,143,24,187,70,13,255,228,250,134,173,209,183,166,208,21,225,94,109,145,98,70,255,76,151,190,150,183,152,248,238,224,187,111,4,2,111,236,73,135,133,67,34,193,94,52,159,42,187,59,38,75,152,72,134,112,236,191,233,150,43,156,14,167,70,226,7,114,200,31,140,164,33,84,232,169,15,96,172,175,192,57,229,71,227,101,139,17,90,45,154,32,255,204,159,141,200,159,147,45,152,135,128,51,11,78,181,154,83,92,144,157,134,244,234,140,201,95,218,104,165,146,35,28,223,139,111,128,149,30,162,119,191,217,136,196,219,138,212,22,168,182,19,118,34,168,68,234,104,231,59,166,128,52,254,212,215,218,117,66,31,249,88,61,78,33,130,242,94,66,17,169,102,100,130,251,1,125,169,71,110,165,239,246,162,251,220,185,184,20,76,133,171,122,57,219,218,181,169,220,38,166,27,206,53,166,180,135,172,64,7,187,131,182,110,67,34,191,25,145,197,184,217,30,140,72,15,212,194,123,34,239,194,64,110,117,35,199,82,17,157,252,230,226,228,44,151,158,81,101,191,59,18,175,143,139,235,12,185,50,15,106,29,143,82,247,211,52,208,35,153,64,11,50,37,13,38,232,128,45,104,62,240,201,122,137,83,140,250,178,64,142,202,168,54,119,221,215,71,166,35,108,71,223,239,99,153,12,8,134,64,200,182,235,107,96,111,231,153,200,254,189,247,49,93,127,4,200,77,43,160,120,224,252,243,224,46,190,166,143,82,46,207,86,235,116,203,190,88,18,55,121,70,227,215,107,69,58,245,221,133,33,73,230,34,36,254,49,127,129,180,253,175,209,180,54,94,124,96,104,97,243,225,38,248,166,230,189,233,78,38,61,122,43,51,76,9,219,127,1,239,79,151,48,213,26,208,118,80,108,178,180,167,38,224,5,87,106,12,73,252,109,195,190,244,1,237,106,212,236,116,74,192,255,121,219,152,67,18,77,38,21,51,27,121,200,196,0,84,219,179,46,124,54,85,12,179,49,241,46,197,14,33,28,79,227,246,94,112,66,187,209,230,116,161,40,15,78,57,156,110,138,178,73,41,255,178,62,43,236,180,171,248,21,243,240,13,110,71,67,79,176,57,76,207,194,20,219,223,36,60,83,50,200,87,245,137,235,132,89,144,67,4,174,55,221,14,212,138,175,187,209,186,54,80,178,238,243,36,9,199,108,128,111,120,61,208,105,53,44,233,236,78,63,226,71,197,238,242,101,100,227,70,160,209,41,198,56,65,115,138,237,132,126,95,23,46,122,98,177,164,159,251,98,212,145,111,203,95,36,21,53,163,88,57,51,139,255,60,181,38,187,107,75,128,165,215,232,130,56,103,173,192,192,119,72,104,142,246,79,232,200,17,207,225,61,55,106,74,61,126,180,229,233,187,223,190,82,11,232,15,84,52,13,98,154,199,134,191,227,132,219,235,17,230,249,92,249,34,165,54,132,101,234,209,220,66,6,69,181,50,132,160,155,246,171,5,167,56,49,27,175,90,222,36,13,217,116,128,9,151,3,203,43,43,40,205,132,14,248,28,88,180,107,146,95,19,175,0,109,41,170,148,148,54,179,0,71,101,59,99,221,143,205,42,59,156,112,136,31,59,18,231,136,191,41,46,122,77,101,152,172,123,108,116,111,53,229,4,163,218,156,39,171,198,100,223,236,90,205,126,143,72,67,138,159,241,118,154,239,154,219,34,182,123,33,163,113,46,15,249,238,36,50,215,132,241,226,207,196,181,96,162,212,88,224,190,81,179,12,136,146,122,238,83,129,26,72,105,125,20,146,253,67,112,232,12,188,96,52,161,160,121,241,50,77,49,218,20,78,169,246,196,95,213,12,11,243,170,71,1,244,78,233,115,143,34,201,250,23,100,9,97,17,4,211,193,128,42,106,170,138,9,75,28,208,247,157,32,4,210,106,87,15,97,167,209,22,160,123,52,183,148,194,21,14,53,212,119,43,76,147,154,56,43,175,79,109,103,68,93,115,95,230,242,89,230,162,136,47,37,79,109,220,24,217,83,40,241,45,113,250,138,133,115,120,72,115,222,65,36,226,44,1,172,128,192,152,113,44,162,139,24,194,114,139,90,162,31,228,198,129,96,97,224,87,232,183,43,193,104,251,129,67,148,240,227,100,4,27,202,89,241,226,221,189,142,102,74,1,234,197,88,247,95,217,142,161,58,118,124,174,252,162,242,248,126,19,199,138,191,202,209,59,204,127,100,65,187,50,108,197,107,107,205,55,228,48,246,168,68,28,74,186,102,54,116,29,188,57,221,206,122,202,240,151,15,23,162,146,91,12,88,51,69,3,110,205,52,5,186,49,46,171,126,221,23,30,236,45,162,17,198,211,238,177,147,106,5,203,206,78,143,1,167,153,96,15,225,28,219,223,209,68,221,218,102,32,19,138,90,130,254,63,73,240,165,99,150,83,198,65,210,22,92,216,204,186,182,213,249,35,2,80,190,138,101,47,225,210,232,29,85,90,174,228,82,244,173,189,193,47,20,238,93,189,172,27,25,87,244,243,224,87,201,186,153,42,69,160,195,77,180,136,128,231,197,161,163,94,0,191,87,57,125,254,155,170,223,110,165,95,181,188,82,153,240,68,118,58,137,253,184,248,35,170,207,20,197,246,93,21,36,48,195,147,75,92,94,166,34,77,198,225,189,122,91,111,136,32,138,146,132,33,113,35,32,184,97,10,255,132,98,61,203,100,65,30,160,150,30,85,22,8,32,101,187,142,240,176,3,67,219,207,113,202,242,213,177,61,155,141,225,69,7,10,3,184,65,132,69,241,149,214,97,91,168,150,187,136,18,190,15,66,134,232,239,202,169,247,10,160,246,157,238,77,41,185,221,165,157,108,94,145,231,229,169,101,1,167,15,161,20,158,211,139,204,107,228,206,211,185,65,246,158,167,12,107,190,45,182,28,192,44,106,148,62,159,222,82,10,227,237,251,3,151,152,139,76,162,183,169,202,107,181,200,129,195,124,71,208,135,234,26,203,154,53,208,137,99,150,100,142,114,50,153,183,126,133,1,253,9,202,235,65,46,106,126,8,5,105,93,53,17,35,209,62,117,114,152,57,29,66,71,127,2,130,103,158,7,17,86,195,64,229,219,75,195,212,33,209,50,154,59,27,177,135,24,163,107,219,137,197,220,7,153,96,131,0,65,187,83,25,18,15,100,245,27,6,174,119,25,182,124,115,158,7,84,182,105,34,75,231,222,190,48,233,221,49,119,79,153,174,200,28,223,87,37,72,254,237,189,199,23,239,255,69,27,152,251,104,233,142,231,80,48,149,197,234,170,200,149,73,120,9,20,212,128,69,99,144,23,22,83,89,207,47,19,17,198,156,214,226,55,130,85,146,54,5,58,224,214,6,27,36,31,164,126,182,225,53,4,52,100,11,28,220,125,41,101,102,215,188,97,6,55,113,252,140,78,81,115,58,203,129,115,132,109,206,21,68,78,20,128,95,62,34,72,211,75,41,78,234,223,115,175,57,229,107,227,179,9,162,15,86,211,207,126,44,120,162,65,99,15,187,57,91,18,41,138,119,15,37,90,138,187,40,13,121,164,30,26,160,7,116,143,9,149,10,228,215,85,75,134,113,241,72,248,12,116,160,177,187,166,188,208,252,178,182,169,220,121,139,203,135,116,198,224,193,215,214,189,110,168,68,129,130,192,8,226,15,122,181,16,37,227,17,156,38,246,249,4,89,193,12,237,32,109,66,52,139,50,235,10,231,210,19,204,191,161,192,238,27,142,203,62,146,194,119,135,132,70,245,214,127,209,179,254,19,43,72,110,124,118,71,34,142,134,163,182,130,140,131,160,56,194,13,10,6,8,136,131,171,206,237,108,163,127,8,17,208,116,17,165,125,236,166,45,180,115,123,110,117,255,84,33,201,176,66,60,220,2,92,128,59,50,147,27,232,7,251,48,118,128,215,225,182,113,163,1,165,184,212,132,246,28,57,13,84,140,97,222,230,172,120,254,160,216,70,239,215,0,111,160,68,51,0,31,109,79,49,38,221,94,95,37,226,200,239,75,160,227,1,122,27,49,244,122,133,67,125,60,12,216,60,89,219,92,146,252,169,205,31,71,112,119,174,142,76,205,10,173,28,31,26,119,222,159,151,151,214,150,124,197,51,174,17,3,58,240,120,130,175,51,87,155,106,76,197,143,86,226,95,45,72,196,34,230,99,248,121,236,163,207,67,132,152,165,42,252,107,111,171,10,114,221,71,94,190,87,197,251,236,116,86,60,82,253,64,166,236,178,150,126,252,230,179,186,45,52,123,29,16,175,237,157,13,213,215,69,153,217,233,51,38,227,186,80,200,188,65,110,196,78,3,202,66,175,161,253,111,249,120,23,44,176,170,211,138,243,128,128,115,108,85,27,23,107,91,1,212,31,154,136,228,166,30,96,59,92,34,162,61,242,225,232,47,195,154,45,144,74,125,246,69,128,166,229,187,39,196,152,5,66,133,189,18,245,235,31,214,153,14,205,11,130,1,238,167,83,107,14,41,235,8,139,62,37,74,87,110,189,142,226,150,1,219,52,58,115,150,62,55,66,239,30,11,157,138,57,159,200,148,184,237,250,169,248,88,159,137,188,98,30,50,189,59,15,225,149,129,184,102,146,114,254,181,178,143,54,171,186,63,219,29,83,52,76,222,208,189,242,11,81,188,87,249,54,213,162,246,147,7,72,54,22,48,119,146,108,131,16,194,137,175,45,132,109,33,243,243,40,190,135,54,116,177,29,228,193,151,91,207,114,183,37,198,58,44,53,196,42,118,27,144,95,155,137,80,255,233,76,228,204,81,135,24,99,82,230,130,134,134,90,185,64,21,78,113,200,124,44,66,8,202,250,219,158,245,90,117,100,130,99,79,193,113,76,66,140,147,91,76,194,35,42,183,235,58,162,251,48,190,103,86,96,173,72,202,179,222,118,203,182,225,42,46,211,245,250,204,238,192,46,2,210,178,141,212,84,160,233,228,60,100,58,151,244,252,138,108,189,119,187,104,222,9,36,11,182,33,204,41,164,233,176,152,233,86,233,50,206,99,64,128,110,66,233,201,123,179,225,189,88,55,210,152,178,238,149,204,213,200,212,190,228,170,205,255,165,46,209,51,91,74,229,36,181,120,52,6,82,169,229,225,218,231,110,222,218,6,179,193,106,30,34,243,244,157,149,112,198,254,119,89,250,217,97,62,28,209,188,203,80,211,129,242,222,66,129,254,133,112,29,113,174,62,6,239,237,224,23,116,214,189,215,75,239,171,17,204,68,178,19,31,37,201,108,153,71,126,166,217,28,201,87,186,193,62,200,110,44,41,74,172,66,60,174,120,134,18,85,137,113,240,138,170,198,225,97,115,26,202,243,51,96,31,18,185,179,52,52,98,63,170,11,216,247,18,9,35,203,107,220,12,6,21,178,236,232,102,112,57,211,73,9,28,24,100,146,157,25,199,182,169,71,71,6,60,175,82,210,8,190,110,18,136,70,15,43,13,60,52,12,43,123,111,248,2,36,45,160,215,73,52,54,36,80,105,210,238,113,115,116,84,251,91,72,109,192,195,188,108,51,89,2,189,86,142,28,210,69,246,138,253,85,224,49,223,6,47,125,40,72,173,56,214,70,132,134,51,244,168,101,112,151,126,77,102,143,239,4,13,116,106,10,103,119,126,65,6,31,18,107,68,76,241,127,130,133,186,61,250,68,253,189,150,134,117,83,51,83,25,187,118,78,134,35,123,184,148,245,53,68,14,88,131,0,68,159,141,48,76,196,130,198,34,56,19,203,64,75,87,26,133,28,73,19,242,167,183,2,251,172,114,9,7,155,151,79,86,68,141,54,101,212,74,210,65,219,237,175,83,252,71,245,207,108,46,196,105,180,46,85,217,5,128,221,226,157,62,176,224,25,140,26,228,142,51,187,96,116,42,92,18,197,211,133,4,0,207,161,141,187,60,8,215,220,174,187,41,153,27,83,242,133,205,30,135,7,207,178,168,111,3,85,173,149,137,68,187,204,184,237,209,59,41,154,36,35,7,212,199,183,241,25,178,86,195,41,137,201,81,164,246,218,251,180,218,161,189,193,147,17,147,15,78,69,23,170,86,93,28,58,170,81,208,143,20,240,63,182,158,203,197,94,135,254,11,135,124,183,89,193,71,88,184,98,208,164,134,197,140,75,234,159,83,20,177,109,123,195,118,229,245,116,207,220,6,11,187,253,37,198,220,195,29,176,38,46,67,200,232,90,245,23,105,165,133,57,29,208,185,232,69,180,3,5,19,111,91,226,98,197,90,102,20,243,203,137,88,156,217,18,24,141,253,17,194,150,75,120,212,232,5,187,191,80,176,71,27,94,71,149,230,108,103,17,129,248,166,186,196,171,152,249,136,146,130,38,204,223,106,175,46,105,241,113,125,212,159,243,233,110,229,177,187,141,186,157,99,212,232,218,25,58,4,212,122,110,11,236,187,184,12,168,127,135,212,37,81,184,79,102,171,143,151,189,158,113,56,80,94,110,58,223,118,37,73,53,158,134,151,251,250,216,143,88,233,8,206,211,238,115,195,53,186,238,140,128,150,50,225,14,236,49,195,224,75,85,229,24,20,244,72,136,144,15,96,152,6,156,158,133,144,200,229,50,186,234,205,77,101,31,5,147,136,55,31,158,100,141,179,213,225,15,161,176,225,156,40,169,60,57,227,45,170,44,97,107,83,178,31,102,192,84,212,43,159,32,188,252,47,248,53,6,68,8,126,187,27,46,133,214,4,199,153,29,177,123,35,170,100,66,253,178,46,37,206,97,62,17,208,98,178,195,223,64,76,251,94,132,241,102,36,130,182,53,98,94,253,122,211,197,204,144,195,101,203,40,158,215,192,102,44,87,233,61,81,147,158,79,117,222,27,26,219,168,15,59,142,65,113,172,49,253,190,191,188,12,59,244,226,238,7,59,116,34,120,56,20,118,83,59,78,142,79,43,150,41,207,228,35,234,182,14,86,50,120,254,31,74,82,5,29,39,173,104,87,10,249,237,158,29,211,250,239,50,64,90,200,107,209,100,26,135,182,38,139,177,27,64,6,87,21,235,204,230,235,222,248,48,156,212,204,138,22,36,123,3,40,93,25,200,55,162,51,116,3,140,58,246,81,78,59,89,103,138,23,220,89,171,48,48,203,181,80,163,171,109,173,17,34,188,238,42,205,32,106,18,122,80,8,247,127,26,32,148,141,138,226,57,27,129,234,74,40,235,202,6,106,127,1,11,117,117,236,240,123,227,139,185,241,205,42,57,186,237,83,21,90,3,25,88,42,109,224,140,238,11,177,108,46,111,28,229,139,95,217,72,101,173,235,131,28,2,85,51,19,52,105,218,235,176,84,57,140,165,80,238,93,92,6,47,138,188,132,100,36,219,223,236,201,112,201,190,0,20,146,68,95,16,147,1,52,108,54,185,188,154,104,247,173,127,160,214,230,207,56,112,98,105,62,42,66,97,101,47,220,193,114,23,202,61,21,118,64,16,191,112,119,123,20,117,173,202,70,39,239,112,202,66,142,163,211,106,89,2,97,150,55,78,226,111,190,170,144,53,195,72,96,89,229,178,153,130,164,161,86,154,154,21,95,120,12,31,122,50,142,245,189,124,17,218,35,201,75,20,203,234,97,11,70,151,3,185,169,71,243,91,56,248,117,103,8,162,90,14,193,33,124,194,169,48,150,40,80,127,37,151,74,195,221,99,145,74,172,228,150,120,147,204,160,67,110,187,30,236,197,101,7,127,128,115,7,243,235,20,66,101,40,114,136,254,206,220,67,96,231,89,65,202,234,82,8,131,187,238,220,213,142,223,77,25,167,69,68,87,110,101,200,142,51,26,234,143,164,214,134,215,222,141,23,42,75,147,88,211,199,154,201,24,72,202,13,136,234,25,52,120,254,136,185,193,163,187,133,84,93,81,133,177,73,126,136,46,251,136,144,180,33,34,18,230,128,47,79,79,106,150,8,58,160,248,106,132,183,215,17,146,173,177,243,32,65,1,175,14,45,235,55,127,69,29,175,177,184,199,168,231,173,143,212,218,44,28,243,157,87,243,247,193,142,155,49,191,221,140,235,246,53,125,204,139,60,232,18,220,63,106,61,252,172,154,140,47,208,189,55,163,20,44,108,250,50,252,255,204,45,52,2,76,66,64,241,107,21,163,134,187,242,247,136,203,1,7,118,226,244,67,198,15,238,194,74,9,230,186,185,49,162,49,71,168,31,130,160,103,223,244,225,108,133,142,123,181,164,114,112,172,100,229,165,150,250,57,212,15,63,204,70,163,4,98,111,152,45,37,45,245,228,45,244,111,124,250,163,197,120,243,232,117,56,154,191,145,196,141,125,8,55,90,132,216,85,224,174,60,253,201,63,198,114,202,235,236,103,174,176,192,65,93,161,74,226,65,222,241,126,119,113,174,16,71,68,19,253,160,250,79,117,231,129,159,61,132,104,164,251,78,110,48,246,12,36,172,100,111,152,87,36,40,95,115,60,227,74,123,204,149,244,119,65,162,114,102,121,19,155,249,117,248,51,151,33,42,115,199,237,144,43,180,51,121,129,23,83,127,226,56,9,32,222,44,201,44,21,7,249,122,183,224,239,85,204,10,181,91,19,103,103,133,205,12,229,38,97,31,108,141,82,255,186,32,185,59,95,66,45,15,41,179,36,56,178,53,39,230,128,252,12,104,165,98,132,4,223,238,44,36,222,188,218,52,250,146,212,148,237,85,68,175,72,79,155,38,36,230,62,122,67,208,138,241,5,49,158,119,106,100,178,247,61,154,161,134,111,198,28,192,44,150,189,7,205,154,142,45,190,172,69,107,176,36,105,64,30,153,120,233,138,210,10,19,201,37,119,182,152,85,43,37,56,68,199,14,82,214,220,245,249,231,141,77,20,190,252,61,102,166,209,230,24,109,225,229,78,195,145,93,109,32,127,163,49,126,248,87,165,80,47,35,155,3,51,50,146,244,105,171,122,226,62,82,242,157,209,37,222,157,224,156,21,73,10,238,198,123,110,60,209,122,158,82,5,221,166,227,119,183,251,80,175,245,112,156,150,175,183,247,162,53,159,213,33,71,40,168,227,104,244,244,210,154,12,114,234,6,153,36,147,203,170,108,85,64,250,110,225,137,2,143,243,163,40,173,220,191,63,210,108,131,154,142,83,175,46,56,41,236,83,221,81,161,144,135,172,99,88,139,115,229,148,143,162,9,203,12,44,238,102,165,234,230,179,179,242,16,227,158,20,196,203,126,102,121,194,246,105,131,73,192,81,122,192,229,32,52,68,139,60,16,102,94,4,190,236,77,238,222,73,240,221,6,252,179,240,56,85,108,237,167,95,168,223,161,49,28,186,57,93,43,203,125,223,42,221,67,47,174,96,56,99,204,115,41,252,252,106,153,180,228,242,100,155,42,105,108,181,215,47,150,176,81,36,192,211,244,135,162,127,189,201,80,62,117,91,125,58,245,215,9,16,165,134,52,42,43,225,155,28,21,189,76,85,226,216,155,133,105,120,60,145,152,6,52,150,149,2,255,255,126,255,45,36,58,37,21,112,25,5,210,187,69,74,195,46,226,170,12,90,154,7,142,228,89,148,22,211,1,150,132,252,99,19,215,135,242,15,150,0,17,251,192,38,133,71,164,62,161,144,240,178,62,63,254,50,137,26,207,233,156,52,145,94,86,239,132,26,146,181,46,165,248,100,14,76,252,16,214,130,195,166,67,120,113,30,255,126,197,11,57,108,130,66,163,177,70,30,223,117,244,53,44,13,86,39,70,58,213,212,230,152,164,76,152,10,227,3,6,230,216,73,88,108,91,245,126,137,58,224,132,168,129,199,254,247,134,142,56,81,168,160,119,44,222,123,230,189,204,92,245,18,227,172,58,240,174,149,68,71,210,183,169,241,146,73,86,210,216,156,250,239,161,219,212,210,69,48,33,137,81,185,192,218,197,2,122,26,76,13,121,61,31,44,239,37,158,126,254,241,131,26,167,224,67,133,125,52,204,195,141,119,131,208,214,151,86,54,137,139,144,178,173,220,170,156,70,125,66,38,125,127,135,146,246,160,95,230,1,248,184,55,65,56,225,139,169,106,17,246,153,98,119,248,67,85,148,28,157,200,233,186,149,138,180,147,37,42,212,190,28,189,109,117,242,168,56,133,17,29,241,89,218,5,242,81,50,61,166,175,124,106,47,237,20,201,235,69,95,202,35,243,79,223,34,85,47,100,252,168,29,171,20,189,109,65,14,156,71,195,246,94,104,211,21,29,195,84,33,131,207,221,120,139,57,78,126,88,195,191,172,133,96,242,110,140,236,227,76,154,55,32,134,193,20,204,21,192,232,157,224,147,175,193,96,9,127,18,107,239,96,240,98,139,149,104,92,151,196,170,198,104,185,117,179,26,20,72,48,36,47,32,86,42,189,173,80,71,219,151,79,181,88,45,26,191,38,133,45,54,131,31,109,115,161,163,34,38,89,40,49,173,198,48,17,40,39,121,77,90,70,42,251,130,168,125,184,76,60,95,94,136,227,248,145,210,226,191,137,247,72,210,17,141,52,5,102,220,23,111,146,114,218,208,22,105,9,130,97,83,57,25,228,137,6,99,12,24,29,89,25,101,217,133,196,253,246,158,114,75,8,90,142,28,147,19,22,164,240,205,1,21,145,19,225,61,98,21,22,215,32,158,9,44,97,148,104,201,219,76,43,45,162,73,151,252,188,155,192,134,113,103,109,255,54,42,206,24,76,87,154,98,187,78,193,50,86,191,222,86,162,165,38,191,118,117,72,31,6,174,147,231,105,158,70,133,79,138,223,55,73,210,90,194,194,112,167,14,253,133,160,197,234,193,24,75,239,106,47,115,70,102,75,122,123,87,158,185,162,180,84,210,222,141,172,125,211,117,181,155,250,182,51,247,178,100,123,8,8,173,224,246,222,40,35,31,171,203,195,36,34,6,53,171,105,219,106,216,77,18,130,182,37,225,3,235,196,203,114,168,7,2,10,14,230,118,6,134,118,20,184,145,213,218,127,110,182,193,145,91,202,110,11,96,118,1,8,96,103,167,236,180,15,141,151,253,100,7,112,25,70,89,121,233,178,158,234,47,68,162,185,146,146,7,74,2,17,238,108,171,91,64,92,173,85,82,121,240,175,136,132,26,123,225,64,169,132,53,192,187,113,8,165,133,192,249,61,166,108,170,2,175,11,243,183,162,93,109,51,151,40,206,39,150,0,84,130,215,29,211,96,200,244,193,206,63,137,9,225,205,195,93,147,70,125,177,146,164,76,247,0,61,118,12,73,75,151,145,218,82,180,207,112,233,175,169,104,180,29,149,4,129,248,70,10,159,34,67,208,4,235,146,205,128,223,104,17,16,189,72,150,29,148,21,85,152,237,97,200,84,57,234,9,165,16,73,40,118,10,18,222,171,43,231,169,211,149,179,250,145,227,129,66,53,2,35,228,99,7,1,101,161,122,247,98,103,47,32,194,21,66,228,215,171,211,95,93,47,71,164,197,154,72,46,73,190,186,131,152,104,252,1,237,94,154,240,6,67,188,57,183,3,28,30,181,14,142,247,193,242,88,231,188,86,198,130,125,97,9,115,137,196,6,38,94,170,51,157,253,197,152,195,181,150,253,125,49,6,217,29,102,120,252,248,217,191,232,176,151,7,118,12,126,164,219,67,123,72,16,146,223,203,183,0,196,87,186,185,173,67,246,204,171,20,21,86,98,182,253,7,186,6,120,189,118,3,229,237,60,53,90,120,139,87,229,79,153,85,139,16,81,100,189,150,202,125,164,42,132,10,163,190,85,177,69,169,181,85,186,64,77,182,99,209,185,183,19,5,1,24,167,247,211,71,7,154,124,136,40,199,61,196,217,202,170,170,93,64,20,178,234,247,41,59,124,192,158,211,128,28,144,37,95,61,108,113,150,27,161,102,97,250,86,162,10,193,27,201,55,193,56,84,164,176,59,172,180,2,117,209,83,226,255,156,104,115,80,9,171,177,196,38,252,19,138,252,29,242,231,74,93,205,161,41,158,79,204,211,0,30,248,42,125,237,167,151,3,163,35,219,102,225,38,80,160,246,91,202,15,81,5,104,108,210,239,193,131,146,27,150,17,171,71,221,84,112,204,146,94,186,237,255,206,118,141,107,20,169,226,15,43,75,224,52,120,186,0,134,235,166,30,237,98,31,139,146,29,104,64,56,3,249,66,92,147,217,211,9,31,96,178,69,148,227,230,101,236,243,45,246,172,39,229,59,69,106,63,147,212,148,179,217,10,220,19,61,36,147,54,173,248,250,238,79,181,163,211,105,11,79,136,249,56,91,202,219,147,180,212,42,140,52,110,222,216,92,215,61,213,55,188,33,239,190,201,255,96,1,215,85,244,86,49,152,17,180,172,68,196,115,71,107,182,243,219,136,48,23,116,210,242,8,233,123,235,101,169,61,55,63,1,51,205,161,189,96,59,52,218,197,250,26,88,73,52,217,104,199,216,234,189,209,12,232,29,210,128,20,244,127,219,15,204,123,222,84,167,249,54,43,174,28,118,186,210,116,176,58,78,38,166,130,144,219,92,43,91,180,1,195,20,39,139,0,25,240,204,75,61,178,95,199,10,3,136,139,50,249,155,86,95,70,214,41,166,76,132,6,166,146,35,118,145,100,203,149,154,211,215,94,104,5,44,83,183,45,251,89,212,57,197,144,82,87,170,120,45,105,80,129,100,131,159,10,127,221,163,246,63,192,154,53,205,6,127,117,223,24,147,216,93,28,239,163,214,221,158,12,149,255,83,88,41,136,165,138,1,254,6,44,25,143,22,104,150,94,24,196,25,238,193,216,170,71,103,76,33,52,211,45,205,235,134,41,248,86,65,9,32,255,32,95,30,250,243,251,43,119,170,184,85,107,38,21,98,231,54,218,226,16,72,174,6,221,38,211,120,221,119,117,120,67,209,251,33,84,155,163,163,47,53,96,15,51,76,204,87,153,85,170,54,66,113,12,174,34,104,136,90,62,76,103,210,150,82,37,200,148,44,89,113,229,33,173,240,114,61,21,131,193,157,216,181,193,207,219,29,42,99,21,186,158,11,145,155,4,216,22,244,162,245,120,63,128,57,117,241,213,60,251,251,149,87,153,99,63,22,75,81,103,103,239,199,225,110,110,88,38,125,240,116,161,226,53,38,183,2,223,68,221,87,205,73,201,187,129,82,39,35,166,109,116,96,250,15,15,242,104,227,86,21,140,48,172,188,54,214,185,33,4,199,217,220,218,185,44,244,170,133,64,135,231,135,80,159,130,65,112,36,250,209,241,226,74,174,130,199,202,217,218,87,161,162,130,254,242,150,34,63,117,178,224,76,211,80,201,111,72,69,137,93,62,24,23,249,115,80,83,95,17,166,84,223,132,120,6,53,34,199,208,205,80,109,133,213,92,49,18,214,230,123,245,73,80,228,94,106,241,165,216,84,255,96,177,178,90,92,5,219,185,153,238,208,136,79,150,15,232,139,179,52,146,235,158,62,239,136,154,45,92,190,176,19,91,40,214,152,149,209,222,247,97,175,74,250,98,231,204,211,233,2,168,136,18,202,254,144,196,95,80,187,220,123,31,164,176,207,23,248,81,3,174,138,206,65,83,36,29,70,32,71,21,227,157,254,228,2,4,215,71,27,252,9,219,49,49,23,248,163,43,170,192,126,75,198,97,91,38,182,93,204,141,250,187,145,128,158,103,88,73,178,191,233,253,231,3,169,38,117,163,181,44,217,91,138,15,239,82,140,19,78,13,168,212,227,46,202,225,130,28,150,211,105,239,25,243,208,76,174,52,37,170,87,125,141,221,90,95,41,51,53,205,112,75,54,129,102,51,87,222,28,117,188,154,174,103,66,55,95,247,97,127,31,107,22,117,195,115,97,108,19,52,70,179,212,190,15,8,213,49,139,119,170,201,169,8,199,203,166,183,90,134,185,169,133,135,9,251,66,104,187,220,182,164,82,21,125,132,197,116,14,169,241,211,104,107,169,17,246,140,46,235,236,23,84,93,180,72,214,10,39,185,197,170,73,30,43,35,75,114,202,126,143,2,127,114,206,107,25,116,183,11,43,3,146,183,121,214,79,26,240,70,203,45,88,74,11,137,245,21,38,44,66,143,61,168,69,76,204,92,186,121,203,15,46,213,237,131,23,220,68,52,188,111,185,48,81,35,208,159,218,44,76,71,236,152,61,103,92,247,136,123,88,196,109,213,91,97,190,88,164,237,171,59,217,231,230,51,149,191,114,162,41,91,249,249,25,109,183,231,25,48,30,35,44,156,199,26,146,144,26,85,40,82,54,83,253,102,88,29,52,114,160,176,0,95,4,217,205,123,143,97,62,149,15,178,195,166,156,183,183,170,183,54,232,197,211,241,7,215,241,86,159,151,161,98,116,91,139,14,111,22,41,155,5,43,72,245,246,20,196,27,62,112,149,21,253,42,111,173,148,25,42,199,41,53,84,169,17,246,92,25,211,161,41,159,252,62,243,4,19,121,43,66,199,74,28,208,193,205,33,126,84,173,30,16,26,179,244,95,188,90,6,16,178,251,191,203,121,130,161,12,52,170,24,14,141,2,163,190,6,52,205,187,57,245,252,9,53,65,132,246,126,90,3,26,54,238,222,74,237,35,163,214,83,43,254,139,112,244,74,15,241,20,255,217,117,129,81,233,181,187,160,29,30,245,145,199,163,29,171,87,228,222,50,229,60,139,23,152,179,33,23,124,180,100,223,209,21,191,93,240,166,209,66,67,28,158,237,190,62,80,188,131,151,72,22,159,212,121,139,49,254,184,106,134,122,77,103,165,81,70,69,174,0,7,179,26,152,234,23,37,155,212,120,59,223,226,216,189,170,9,42,206,10,123,140,130,214,229,149,218,74,215,152,151,235,170,53,33,209,190,193,105,61,182,108,226,176,32,213,78,117,106,23,56,121,61,82,213,107,121,107,114,185,20,99,151,57,44,105,153,238,174,24,192,241,254,251,80,193,143,221,0,58,227,109,190,129,185,22,131,37,221,129,34,101,144,152,33,250,198,183,73,236,69,174,215,68,64,181,94,33,132,40,149,248,252,133,191,99,245,130,21,43,49,211,224,204,33,169,240,230,120,107,228,46,140,168,241,32,17,95,48,147,101,16,176,251,83,160,253,105,171,56,79,198,139,36,48,144,120,99,236,171,235,56,117,196,171,178,244,170,61,79,183,32,202,66,50,130,211,99,78,199,73,255,242,30,138,199,156,129,107,187,182,255,144,201,230,138,199,111,154,10,126,232,144,99,117,187,160,97,221,177,191,5,239,139,181,240,32,249,247,61,216,207,154,217,224,246,49,118,3,194,107,197,233,3,242,99,182,58,45,151,176,238,101,118,57,44,123,195,112,61,129,140,199,98,25,86,104,2,141,220,161,128,109,32,8,89,147,249,11,246,14,255,195,81,233,46,89,37,122,225,211,69,132,120,138,169,254,0,72,208,116,247,244,60,55,28,135,15,11,28,174,65,40,253,148,181,6,57,220,134,224,205,255,225,22,228,49,200,228,182,179,141,237,217,9,47,114,203,57,24,173,236,15,100,174,120,178,73,84,236,141,45,188,142,252,66,85,56,248,161,247,21,240,209,145,198,24,158,227,106,158,18,248,204,21,1,99,35,91,187,157,228,98,106,35,231,158,103,53,119,135,62,168,207,48,5,118,236,117,255,204,65,60,49,102,180,55,82,149,17,205,214,182,198,223,77,55,234,99,156,29,161,90,22,138,7,126,240,213,226,110,63,214,97,71,161,203,216,10,31,25,62,71,223,163,238,97,14,115,144,121,112,103,4,186,16,66,51,105,110,65,111,32,206,82,213,231,74,107,199,255,85,48,249,19,123,45,142,3,104,77,86,181,99,8,158,50,3,108,43,23,113,246,189,180,107,134,24,9,137,36,178,9,176,197,63,33,63,164,220,217,243,175,16,197,210,28,16,109,192,143,193,240,252,44,124,8,108,179,168,171,135,107,32,216,49,136,123,109,133,33,176,167,185,189,30,120,210,5,211,14,127,118,199,147,121,246,58,33,239,172,251,87,223,152,144,13,169,216,65,87,59,132,210,118,116,30,68,72,68,155,103,230,81,33,26,21,82,14,73,251,183,147,86,222,194,97,44,169,244,82,155,95,253,205,116,91,165,44,64,31,163,242,253,93,23,26,209,14,33,97,62,148,115,63,247,111,137,13,9,163,215,243,223,218,10,114,82,195,219,233,24,117,167,173,231,13,156,77,46,231,130,200,122,169,91,49,229,215,250,140,73,229,240,44,212,41,117,112,31,126,218,196,58,241,101,147,26,195,148,98,153,198,104,87,90,149,128,60,239,177,50,49,11,242,239,230,196,182,89,101,80,215,168,143,70,48,53,53,215,22,99,194,129,245,128,163,40,102,25,14,99,189,152,35,135,13,16,105,137,188,32,226,246,176,38,30,36,65,146,145,240,83,103,2,107,133,21,172,41,239,28,250,134,170,228,80,43,122,211,87,111,228,168,29,171,79,69,62,152,18,69,203,96,169,144,83,50,37,65,208,1,113,46,2,67,73,221,2,181,73,185,209,20,163,237,141,222,221,69,220,155,12,177,239,150,84,234,58,111,225,3,31,187,110,139,78,139,234,186,202,73,72,34,125,59,43,206,220,68,6,49,123,14,147,144,206,60,95,31,173,236,244,239,64,11,119,89,226,7,117,175,218,115,104,165,195,209,202,140,132,15,6,115,213,209,69,238,7,89,37,249,156,158,67,124,208,100,194,232,148,52,214,125,166,99,224,152,46,109,187,234,230,51,60,189,191,120,28,13,67,152,105,230,40,147,153,215,16,149,231,51,170,159,88,97,228,216,161,34,87,65,129,153,213,186,140,150,104,113,164,25,120,246,58,78,221,124,33,179,135,7,220,233,68,9,15,123,101,187,131,139,95,177,234,29,215,24,57,107,53,194,252,161,247,70,224,245,22,104,10,41,39,213,190,186,249,159,32,28,196,55,153,225,205,18,72,227,70,120,101,199,237,132,225,10,124,88,154,151,215,153,67,177,100,244,99,169,37,127,97,122,188,216,217,79,187,227,87,69,243,42,139,151,228,79,141,154,88,240,7,29,255,165,129,150,70,173,212,207,194,245,243,54,210,111,168,77,71,140,61,28,64,106,8,196,60,68,154,18,110,22,252,63,172,163,34,138,138,105,145,101,244,110,11,75,95,244,220,224,140,191,243,85,79,137,128,246,173,146,28,1,68,146,131,190,104,107,105,10,183,141,149,204,59,176,190,91,3,180,254,33,47,24,58,4,53,177,211,193,103,6,161,57,156,191,177,108,76,83,185,133,20,167,103,26,75,148,54,239,124,182,71,95,160,157,60,112,22,149,136,53,82,150,241,250,192,35,199,124,207,79,66,84,131,7,63,140,114,16,166,158,30,0,73,131,202,144,116,46,50,92,60,23,147,147,14,236,195,64,128,205,63,248,146,1,49,182,30,96,166,149,196,243,131,88,93,119,167,118,22,137,56,179,169,223,194,48,235,4,196,19,7,210,55,75,235,92,247,15,83,174,53,132,172,34,214,91,205,147,70,34,195,103,132,175,68,245,7,227,205,122,160,7,72,137,123,51,243,8,7,82,113,179,53,171,249,151,156,75,82,204,101,194,53,247,2,201,39,125,151,8,4,189,190,40,95,41,72,181,116,99,58,100,136,118,164,13,191,107,164,69,39,229,204,2,248,254,87,112,64,247,106,105,66,193,73,104,67,75,181,248,105,39,227,153,139,164,41,215,76,244,118,95,99,56,13,94,20,67,33,205,238,108,249,81,105,60,177,18,155,229,73,173,205,78,164,144,180,161,191,210,203,150,190,16,55,228,110,203,212,118,15,103,25,67,152,199,2,36,17,117,201,129,88,197,112,153,188,44,58,196,160,131,198,150,19,223,209,224,90,127,231,71,1,40,82,195,12,242,223,233,211,68,210,32,176,1,106,119,179,211,33,221,107,210,194,227,213,88,3,122,19,130,145,199,16,66,179,41,215,40,18,133,40,191,25,49,31,101,27,16,11,60,119,20,186,217,168,204,250,28,173,159,38,166,106,2,35,49,133,30,16,174,41,134,5,154,247,72,247,171,23,225,89,228,141,14,221,122,56,188,54,252,90,121,252,169,8,168,27,59,138,8,245,70,122,230,65,165,140,117,136,206,11,169,209,146,240,8,234,87,27,21,119,136,227,84,138,65,172,42,227,109,202,167,67,219,148,125,32,179,242,176,224,42,235,163,145,195,63,145,122,135,21,164,85,133,249,38,87,145,90,3,151,203,189,99,172,189,248,86,207,193,226,138,44,42,179,190,99,83,127,92,185,32,159,58,246,239,241,246,235,227,205,219,169,42,77,149,0,212,210,172,47,174,68,122,133,7,78,152,86,30,65,58,84,65,40,113,125,213,150,112,146,1,46,218,175,242,206,243,3,22,233,246,135,129,96,57,130,15,151,104,91,220,169,42,107,34,44,14,229,23,97,55,219,134,96,213,252,133,227,120,195,1,46,17,86,212,120,130,91,248,166,233,51,66,254,106,183,117,42,44,36,169,196,204,173,91,96,109,228,171,28,189,45,250,183,121,167,12,164,164,245,225,177,164,170,138,139,161,93,90,83,85,26,198,104,106,203,108,131,144,196,153,22,188,229,99,101,228,68,84,115,35,112,19,129,18,184,189,228,220,191,206,106,106,126,188,176,42,150,208,166,249,215,76,49,78,167,49,137,16,206,210,203,31,206,130,158,233,143,12,168,123,152,246,181,110,5,9,143,33,8,20,72,188,117,52,80,18,200,90,101,236,228,207,56,241,5,217,53,40,86,180,67,214,216,113,227,232,42,4,123,161,29,225,131,69,60,164,193,158,200,54,177,14,32,137,153,25,110,144,200,246,156,194,61,16,88,79,24,113,181,5,133,88,82,165,176,38,251,156,45,231,111,141,37,120,107,195,254,51,23,243,143,18,30,92,222,216,31,27,168,49,204,158,75,50,29,108,173,189,227,162,147,5,233,159,187,189,71,11,14,221,15,68,223,60,234,186,227,182,193,229,131,242,98,115,34,126,30,59,20,56,101,249,9,38,148,110,79,181,179,181,29,240,61,110,204,161,242,160,184,30,38,49,180,136,78,22,156,1,249,192,217,132,67,3,250,243,132,141,231,10,84,231,97,122,73,28,88,116,105,213,193,202,47,183,216,19,80,71,55,14,123,32,194,193,121,208,234,113,73,234,146,93,189,196,164,129,140,201,122,187,60,67,10,121,125,17,246,192,134,16,58,220,3,66,88,63,127,197,206,164,85,151,11,143,43,109,35,215,25,113,90,99,90,205,22,209,122,41,112,244,206,253,59,161,241,168,251,89,190,186,151,193,3,142,219,1,102,68,147,87,145,74,157,223,203,18,248,51,21,219,92,9,251,196,149,82,153,103,27,151,252,54,21,4,47,205,56,172,183,3,29,202,225,83,16,70,15,21,227,219,225,178,248,157,53,135,57,185,163,37,123,167,126,80,187,41,181,17,191,207,228,71,37,158,205,118,62,248,250,194,59,71,214,167,103,233,25,73,205,178,231,128,78,53,113,28,73,140,86,87,88,87,238,196,137,77,234,138,39,195,39,117,89,71,3,123,115,108,182,175,148,180,142,193,159,155,141,71,168,172,98,136,187,112,36,25,146,98,217,160,17,34,77,55,98,189,208,173,74,117,181,200,124,182,123,12,56,62,149,214,75,112,112,107,126,242,224,85,234,235,172,131,250,233,229,99,14,92,194,36,21,156,167,172,215,243,141,214,57,79,177,104,94,207,160,8,3,102,237,50,84,126,223,147,92,211,221,196,52,130,24,176,159,132,65,156,131,71,126,4,33,143,91,104,28,50,153,209,95,181,28,75,113,70,67,27,109,192,39,174,135,252,172,218,211,94,160,62,199,154,79,251,16,22,195,15,22,140,253,36,242,85,72,147,22,121,33,25,195,83,123,67,179,160,66,85,146,45,114,228,93,116,57,55,217,212,216,31,50,167,229,242,19,107,240,57,124,255,142,191,249,148,74,39,163,43,156,151,201,207,220,46,185,27,203,141,137,15,92,5,101,198,159,181,2,84,128,42,9,10,185,221,175,55,128,247,131,98,98,146,152,8,240,110,121,15,67,233,2,21,145,83,105,182,127,239,100,153,185,165,225,124,59,119,26,175,192,81,4,98,42,93,184,200,34,68,13,134,123,5,43,164,167,218,32,67,79,70,4,196,254,131,50,201,157,133,80,79,208,242,155,224,237,252,110,27,249,238,45,235,77,229,182,93,205,123,32,5,3,78,154,69,213,117,216,130,198,46,105,47,78,76,255,250,230,254,99,106,218,110,21,186,185,71,173,236,91,67,119,59,38,141,202,223,39,183,153,239,2,113,168,121,123,54,217,55,237,94,11,1,190,38,16,170,216,147,239,88,254,229,245,220,108,102,247,55,229,237,173,167,179,231,185,82,226,109,53,81,87,15,55,217,69,204,109,3,164,126,143,193,42,141,227,90,36,226,83,128,215,12,177,216,190,140,85,129,225,224,25,74,141,225,41,192,131,60,180,130,169,191,124,58,1,135,224,63,27,9,138,244,124,167,199,35,2,120,62,25,218,238,78,254,29,125,60,19,72,168,31,194,52,28,70,137,193,242,203,2,91,43,138,248,5,135,204,165,116,67,10,198,121,98,100,238,143,43,94,209,39,162,232,129,176,41,254,158,40,195,167,51,206,48,151,123,55,64,65,233,220,176,238,73,3,129,139,129,242,194,88,95,199,147,187,75,237,229,171,30,89,115,154,239,165,169,235,59,98,63,177,91,115,84,142,203,97,103,79,66,2,91,157,207,14,45,246,75,211,46,69,228,42,158,158,132,228,178,36,163,98,194,69,11,37,186,217,155,206,244,54,125,9,122,128,237,37,159,232,91,68,159,92,116,153,244,199,136,214,88,171,186,117,98,60,171,163,232,45,147,151,123,170,237,130,250,83,244,253,125,237,248,178,237,111,15,63,154,122,147,51,15,60,204,111,139,245,231,228,185,51,36,176,237,79,48,4,150,130,163,59,120,29,126,54,40,104,116,142,238,121,237,189,107,191,35,8,119,113,131,109,108,173,24,9,142,108,8,49,51,202,146,192,173,17,1,241,218,187,124,164,246,139,220,70,143,192,138,152,227,175,189,77,209,86,106,63,119,2,159,194,2,163,89,30,119,83,127,152,98,60,123,145,96,155,67,36,124,94,20,93,243,98,219,253,143,238,124,45,39,226,10,242,116,227,184,129,242,21,192,51,94,97,231,64,148,237,211,59,177,198,10,216,238,62,4,109,230,168,9,132,240,215,0,86,29,251,174,78,233,243,27,50,92,197,253,214,2,123,146,246,222,140,146,148,108,237,15,4,222,247,156,154,132,10,40,151,8,10,70,114,132,181,145,136,176,233,7,169,57,111,204,90,220,67,215,132,40,150,216,152,69,54,80,43,171,67,46,100,140,33,185,115,58,154,35,242,247,6,43,31,174,39,80,101,216,73,40,132,227,201,14,85,37,194,50,3,146,118,78,76,36,211,88,24,220,98,14,33,120,148,222,160,20,160,118,195,167,167,92,128,37,5,53,38,72,206,146,123,57,213,135,200,109,71,35,239,160,169,225,222,136,217,153,92,67,165,51,105,189,47,203,155,237,217,9,216,232,29,225,177,49,205,230,232,177,124,66,19,114,207,198,114,64,45,161,124,66,110,85,157,81,102,32,22,83,53,111,196,27,133,196,169,162,223,120,126,235,105,163,132,221,206,150,110,214,226,227,26,172,30,160,193,251,235,130,209,125,165,77,58,39,115,187,196,165,24,148,33,237,15,73,76,51,191,88,212,165,137,89,220,47,35,108,174,114,48,214,113,39,163,180,185,63,88,233,112,0,120,241,137,168,24,63,138,54,82,207,177,179,66,101,46,177,222,3,52,49,103,68,5,246,78,182,234,55,35,29,9,19,192,144,78,132,224,162,148,96,89,62,61,109,6,178,98,241,196,88,167,22,196,56,11,139,35,94,112,213,134,206,158,24,179,145,144,24,250,44,149,253,67,210,8,0,244,166,243,0,180,234,155,46,191,122,41,93,142,70,154,56,201,66,159,207,162,193,63,26,46,204,221,206,29,100,232,161,225,87,106,130,47,154,66,253,50,33,4,103,71,134,239,65,137,220,222,90,200,221,145,253,16,73,125,66,213,113,239,82,209,96,85,98,196,87,143,30,250,24,217,92,120,23,123,71,64,51,243,204,192,239,147,75,30,170,32,161,187,95,176,78,235,9,173,103,112,9,93,39,55,89,66,223,135,55,158,58,28,249,4,53,46,175,138,48,65,135,70,136,1,162,20,77,236,103,41,150,88,60,162,162,221,75,62,108,114,118,100,40,120,101,241,122,160,0,109,225,54,161,239,188,6,149,136,139,198,177,179,32,43,126,52,149,57,217,226,136,215,201,55,32,213,229,87,28,109,36,223,42,151,98,71,107,140,255,230,206,183,84,127,109,108,57,226,37,11,140,188,250,216,82,32,241,186,122,68,173,128,81,29,57,2,23,81,10,233,198,238,113,91,11,7,17,184,180,159,230,116,147,143,120,21,24,1,220,118,49,16,80,204,12,78,41,111,117,193,98,56,148,193,219,160,156,230,56,126,1,172,183,95,204,229,202,75,218,108,245,33,254,8,58,127,98,209,197,176,100,60,110,139,133,80,43,42,133,200,12,216,121,186,89,171,171,252,220,132,121,46,180,75,79,8,157,91,112,112,34,247,193,147,132,119,236,30,223,101,129,132,197,45,134,84,202,92,249,70,208,211,158,206,209,216,202,106,106,96,1,80,249,182,103,247,124,85,169,42,212,67,245,112,214,156,147,143,216,186,202,197,119,5,230,23,226,199,79,150,253,252,85,1,193,145,96,212,15,165,73,246,244,50,249,165,95,254,252,112,62,100,237,167,234,181,238,164,135,224,175,19,225,82,153,135,122,209,81,59,123,165,21,127,99,54,56,18,153,226,205,161,95,202,7,79,126,124,92,208,244,46,5,176,227,206,200,16,140,97,250,131,187,54,34,117,52,52,206,150,201,200,182,45,201,225,80,46,100,113,199,193,12,116,224,253,59,85,244,248,161,239,199,164,208,63,114,103,163,167,185,246,203,19,33,102,53,236,108,3,205,170,155,230,73,204,142,178,233,7,187,171,191,137,254,60,149,218,98,40,42,87,10,3,146,207,162,67,113,25,173,141,27,217,143,225,97,164,2,208,116,57,181,180,112,233,183,114,62,110,197,29,79,155,213,7,115,94,60,229,43,83,79,119,171,196,20,78,239,233,51,87,6,32,5,59,166,121,176,193,0,2,145,150,183,130,7,36,179,159,57,212,66,179,111,151,174,27,202,58,35,12,121,174,29,17,69,244,46,87,1,173,238,194,40,107,180,147,157,209,184,241,104,251,123,242,164,42,31,93,118,82,79,189,47,105,102,158,30,210,164,16,47,140,226,212,235,70,176,78,30,247,193,162,137,19,102,181,9,248,156,29,149,41,73,2,34,88,183,198,106,254,34,124,19,150,32,99,71,253,14,190,121,107,200,168,38,114,205,153,112,139,204,16,149,101,168,127,70,40,156,157,78,179,113,220,4,46,194,124,96,187,139,83,36,28,169,50,209,88,176,134,217,219,55,18,186,165,170,11,175,60,216,24,132,95,218,101,75,194,66,64,184,1,56,29,86,92,86,243,122,204,124,185,21,219,37,111,68,82,178,41,69,127,186,121,223,219,84,41,169,105,54,165,5,128,102,12,67,130,217,46,97,233,254,216,57,121,145,39,46,34,136,82,175,114,153,215,16,119,138,116,45,137,136,230,59,132,221,97,0,150,250,153,211,18,141,254,212,157,9,45,217,191,16,24,133,130,194,151,189,230,92,187,55,12,247,187,8,115,13,29,222,207,59,92,230,24,146,39,165,2,54,188,107,162,190,178,185,22,188,187,172,42,164,239,225,92,55,26,237,230,59,0,75,13,33,47,250,12,161,72,4,185,159,244,163,208,129,102,176,239,178,99,211,97,92,241,234,19,85,70,42,189,55,130,151,119,38,50,126,239,231,40,153,124,51,220,63,234,208,163,211,170,63,37,231,40,152,183,204,90,227,246,208,8,196,85,209,243,92,102,174,199,27,110,145,27,1,158,35,176,107,152,163,227,75,21,184,120,238,57,155,201,3,194,165,57,117,211,136,236,17,128,98,177,93,111,46,94,137,155,5,70,101,212,42,190,79,218,62,143,123,151,171,59,185,175,9,185,245,254,235,130,177,69,252,61,157,29,229,105,128,229,192,180,37,158,214,254,13,129,64,53,209,247,56,140,241,97,250,119,174,250,204,68,97,184,208,29,20,117,25,12,105,234,224,76,223,115,197,177,7,235,247,19,42,20,85,78,15,81,181,192,153,4,160,176,82,106,67,212,194,132,240,190,45,126,79,192,122,42,28,239,165,14,139,14,152,62,129,78,48,66,45,207,97,240,165,178,129,234,169,234,59,12,218,46,249,54,76,20,225,254,11,128,237,242,61,101,16,36,207,202,13,244,205,77,104,204,51,50,1,5,95,211,151,110,251,255,185,191,151,167,102,140,98,163,129,27,38,60,101,197,176,252,212,232,136,208,157,118,51,83,111,209,188,223,78,130,47,24,91,236,170,159,121,55,3,202,0,155,212,180,173,74,37,161,201,91,108,166,174,27,239,60,20,65,158,225,185,85,89,127,76,244,27,86,150,160,201,13,106,79,143,68,200,236,55,107,243,76,149,215,188,118,183,198,159,26,140,136,153,211,173,159,16,57,139,31,93,149,70,6,141,53,112,164,6,184,239,106,159,222,67,158,26,121,136,223,39,46,140,67,170,202,95,88,179,214,186,212,140,8,12,94,34,77,226,17,17,162,210,225,20,151,177,74,9,100,126,170,73,142,33,144,154,131,151,205,235,28,118,190,6,137,98,50,237,7,94,230,246,133,250,179,160,199,89,103,9,203,111,37,216,185,171,40,117,6,107,87,133,165,172,22,140,220,186,41,97,187,57,196,102,220,15,169,194,254,170,33,237,69,78,127,4,30,119,51,251,153,50,179,106,153,232,131,96,100,243,32,78,78,223,191,150,158,39,30,201,43,12,220,233,103,223,247,156,210,213,52,75,203,102,114,46,35,81,55,175,89,207,53,66,198,247,164,132,51,64,124,120,125,108,35,3,184,185,202,162,122,93,58,198,11,176,146,221,62,6,92,250,135,230,38,135,125,76,89,22,140,243,110,14,212,252,94,85,234,86,142,168,158,28,94,124,183,180,213,174,80,170,142,88,83,48,201,169,249,109,156,83,4,161,186,46,235,85,83,86,244,7,52,58,188,19,124,117,35,105,13,185,191,47,252,142,77,194,147,27,235,193,126,138,65,32,134,118,24,227,33,219,142,48,59,235,147,8,183,94,74,184,233,4,78,44,55,20,167,190,216,145,187,105,253,135,93,68,15,204,76,81,176,255,140,229,106,248,29,154,109,79,247,240,181,62,181,2,28,187,26,136,254,180,92,158,140,81,194,11,245,237,48,28,57,112,87,48,233,185,13,251,113,29,199,152,222,226,254,232,119,199,120,251,113,224,226,89,162,215,74,115,227,118,145,197,176,156,161,226,233,79,170,203,163,113,106,144,108,25,85,163,91,129,143,75,216,56,51,156,13,106,116,79,121,79,152,139,128,156,169,174,94,228,172,49,115,235,134,42,145,67,107,214,122,8,49,156,210,218,178,151,67,247,169,0,56,164,44,222,132,125,193,90,153,10,15,29,69,159,229,98,193,181,138,65,215,14,65,89,116,209,247,174,22,72,27,141,214,94,36,169,203,34,123,25,192,248,196,238,148,225,225,253,59,44,43,96,2,26,21,96,123,202,184,253,55,162,172,81,29,95,172,11,133,235,129,224,183,94,71,85,29,23,65,246,242,222,224,109,136,62,63,145,107,248,167,160,195,242,204,135,237,253,107,53,91,77,34,207,186,102,102,84,28,14,44,194,39,232,156,245,132,232,76,102,63,206,240,49,132,118,211,1,70,75,30,42,3,149,207,174,223,160,227,64,221,207,62,64,74,186,97,163,201,85,231,33,84,76,132,47,66,189,73,137,21,77,184,234,168,231,171,247,76,32,229,1,138,186,116,5,60,65,8,57,133,57,165,125,190,51,105,242,89,1,141,234,53,168,34,89,88,55,63,52,10,226,116,30,115,175,214,74,234,133,248,48,242,17,47,155,75,131,130,124,207,192,199,156,142,142,119,122,3,15,49,119,155,82,80,171,180,19,29,133,31,247,222,9,245,206,244,22,69,12,85,112,250,23,97,212,191,32,152,5,115,206,31,197,19,250,138,219,130,3,84,216,78,11,80,213,13,161,199,128,136,64,7,53,223,221,247,108,10,139,128,47,36,225,149,145,94,106,22,86,14,62,13,43,181,226,188,243,228,218,231,144,137,51,46,13,237,21,72,193,233,132,28,220,20,8,4,122,72,237,253,246,222,239,176,0,105,79,66,248,100,211,232,18,217,109,127,11,57,83,34,123,20,60,137,153,193,152,195,96,127,130,205,193,250,201,146,44,174,91,40,108,105,104,231,248,136,114,61,136,124,241,31,128,186,165,230,218,248,76,54,35,51,13,80,241,46,59,34,214,111,253,168,149,252,124,4,81,171,131,110,58,165,172,223,166,5,45,240,154,11,195,26,117,137,238,192,41,98,219,74,113,235,25,234,46,9,144,57,228,196,138,122,230,73,229,42,31,24,18,166,217,131,24,95,177,251,18,240,249,10,235,122,112,16,73,162,6,70,8,231,108,54,87,216,194,174,60,128,244,234,190,212,213,146,128,244,187,133,74,29,128,195,60,234,120,57,168,116,97,234,156,164,173,42,225,70,177,38,184,43,121,148,186,19,207,224,19,253,214,102,184,227,77,205,223,63,242,184,142,75,134,48,96,96,243,151,83,50,87,123,186,147,177,176,62,113,237,99,50,108,201,126,185,218,219,219,241,171,55,44,28,194,49,254,72,63,140,63,178,112,216,15,3,183,189,172,230,154,116,254,246,200,73,82,76,41,15,168,132,147,25,115,46,90,151,15,180,193,60,237,178,105,74,47,191,86,59,221,105,248,98,26,140,49,149,76,146,83,229,173,71,134,78,113,171,186,136,69,240,102,228,167,251,86,198,107,167,79,180,215,210,44,58,98,143,79,188,44,133,107,54,248,165,231,104,149,127,120,62,61,159,252,239,41,101,177,140,108,77,90,49,230,151,125,115,153,80,213,191,17,98,59,202,149,108,239,233,23,177,26,245,216,97,198,111,31,75,248,67,177,55,207,157,212,233,20,69,111,167,232,80,21,144,9,32,199,43,200,181,141,195,9,143,237,154,121,175,158,247,124,39,117,184,48,30,51,103,4,19,16,28,84,98,72,251,204,19,32,194,90,236,170,52,202,181,96,92,120,59,184,47,169,66,177,66,217,150,2,50,182,17,7,131,32,76,227,116,70,174,42,90,163,89,35,33,148,41,240,228,253,31,107,201,210,198,152,13,86,70,112,248,225,121,155,252,134,99,239,2,8,98,108,44,76,227,160,213,104,141,16,130,205,118,253,123,220,48,200,187,80,35,114,62,45,188,107,29,79,220,169,244,147,158,70,102,122,231,232,149,243,55,230,115,28,185,83,39,179,237,221,41,170,240,44,143,39,216,163,87,213,39,157,118,225,99,80,190,57,171,200,20,2,7,166,112,211,127,0,69,167,84,159,62,190,37,46,1,194,192,152,94,188,50,203,38,220,128,2,108,156,32,255,174,254,89,135,44,97,26,237,37,203,70,32,238,3,218,163,213,145,32,244,50,67,233,217,30,131,135,205,0,46,29,143,192,99,180,144,34,96,7,74,212,164,44,215,190,88,252,138,84,97,50,251,203,44,252,175,247,178,155,79,180,28,8,80,184,205,211,9,119,150,32,91,150,4,102,212,89,217,117,71,241,163,146,90,113,142,34,228,139,182,236,101,97,47,152,88,91,161,47,37,246,4,92,89,174,210,15,82,44,118,249,82,198,192,155,172,220,91,168,190,233,35,204,84,24,113,139,102,112,42,108,124,19,27,148,60,159,78,38,239,90,234,5,193,172,28,58,20,182,11,43,162,123,82,184,178,167,19,172,101,106,3,69,146,204,136,46,70,35,133,166,103,74,245,222,246,76,109,232,173,160,36,50,39,140,112,227,59,10,18,127,30,232,161,113,146,233,102,248,171,205,245,154,98,101,53,109,65,36,82,31,241,200,111,216,27,255,10,48,237,213,82,221,17,250,248,215,19,150,56,175,233,19,230,30,233,199,3,100,121,176,189,175,63,20,231,105,113,121,51,88,188,231,109,177,58,34,9,199,121,226,157,183,76,219,41,224,204,61,144,124,88,115,7,214,74,179,178,42,119,144,76,98,58,171,185,134,98,123,177,87,100,213,183,165,147,22,29,151,19,74,146,102,107,158,201,189,0,79,185,36,105,84,104,73,152,103,132,228,196,39,102,113,158,255,56,212,198,37,172,139,31,238,98,184,182,42,69,108,194,245,23,205,45,21,76,115,162,181,174,59,213,233,59,240,184,32,212,226,199,126,11,205,232,217,187,51,197,98,94,117,94,105,152,41,48,22,181,8,146,134,207,30,237,255,240,248,183,191,187,67,210,16,185,191,54,193,2,218,22,99,176,191,233,78,247,165,4,231,131,62,37,109,244,76,194,155,129,212,66,0,101,223,162,211,13,80,169,217,16,68,4,155,216,61,35,76,162,144,217,34,209,73,249,250,253,186,140,124,41,237,124,22,168,97,40,95,47,38,188,204,216,150,184,229,185,174,113,3,154,126,238,50,165,170,12,27,209,53,157,76,118,81,252,10,140,31,103,160,43,171,6,65,205,225,154,85,121,76,216,228,29,241,184,200,160,225,86,4,199,137,80,222,199,30,9,163,177,222,131,91,24,3,147,148,250,20,157,246,166,73,41,246,240,159,85,53,172,227,255,239,211,188,78,85,210,198,63,175,149,47,251,126,139,167,245,143,5,212,41,111,52,133,173,37,114,122,63,214,212,6,98,213,169,140,241,226,233,95,47,169,91,89,117,116,228,30,78,123,163,137,11,19,142,70,121,166,215,141,20,57,100,202,75,131,150,222,136,204,79,199,205,220,46,9,129,92,116,55,148,224,138,82,32,255,250,251,59,239,99,130,13,77,106,233,191,37,70,164,141,160,195,95,192,54,39,178,189,46,17,135,160,255,198,62,249,69,57,5,74,22,165,134,209,143,179,8,28,219,212,141,148,242,233,231,171,234,72,186,111,252,84,120,130,253,206,225,145,123,88,19,194,150,24,168,247,191,92,162,203,56,94,55,72,199,142,76,50,37,253,13,142,159,201,100,153,149,243,217,240,192,204,254,66,239,13,23,161,166,210,210,120,35,7,141,179,109,83,57,146,163,16,195,195,129,214,39,34,155,158,29,244,128,143,18,233,121,150,87,80,227,145,22,207,133,15,10,172,79,48,176,209,68,66,116,22,167,251,162,90,108,98,148,98,84,46,164,185,106,48,68,247,163,112,24,15,78,105,58,173,251,63,10,252,91,83,158,57,178,63,21,40,113,231,82,251,191,134,27,71,131,203,150,222,121,48,211,181,0,62,91,119,123,77,252,183,63,204,142,239,211,87,244,129,213,2,81,221,210,104,182,252,35,116,91,198,172,132,76,148,89,3,74,8,96,232,19,70,18,232,128,18,145,133,229,23,13,93,175,174,68,105,55,192,81,168,1,142,132,193,37,99,188,243,51,14,26,6,195,29,149,159,115,77,169,235,22,66,101,37,224,43,146,152,141,191,222,67,12,74,51,124,129,141,11,37,97,10,50,79,112,123,54,180,89,156,10,237,145,90,99,35,116,84,163,249,196,70,103,144,16,14,13,233,42,5,213,163,203,205,92,6,212,210,195,46,141,24,15,1,215,71,30,31,0,4,24,15,93,217,35,228,173,104,78,117,69,140,243,168,119,62,223,200,171,123,57,184,88,64,53,21,153,201,0,115,146,22,119,84,228,16,189,124,213,148,92,15,178,58,83,69,87,213,137,150,254,92,197,211,157,193,255,150,115,3,222,48,64,41,28,208,245,211,29,135,30,54,205,250,93,94,57,155,196,37,151,90,109,165,11,249,203,106,37,64,103,100,206,108,40,181,36,238,104,208,241,13,26,75,32,133,101,47,132,226,199,174,3,139,186,102,206,19,21,6,166,44,184,63,7,255,61,155,90,233,60,161,86,176,23,97,194,237,176,234,251,116,25,226,11,145,130,13,179,158,222,252,26,235,132,202,117,229,195,232,158,52,183,96,47,219,235,210,51,146,103,15,241,22,194,84,73,169,183,142,81,87,203,6,251,105,254,2,56,164,156,137,219,71,205,59,144,217,70,38,73,57,73,70,131,114,20,249,181,50,184,200,127,251,28,30,92,166,20,252,156,141,128,223,214,176,136,154,210,238,245,131,123,1,114,106,160,197,74,57,4,101,162,185,66,93,219,192,225,68,181,231,74,140,180,121,162,114,142,129,187,73,66,192,218,128,28,39,134,251,0,243,48,55,112,205,204,80,144,149,109,100,247,179,224,228,198,89,225,7,131,170,203,32,130,21,23,249,122,134,208,160,239,23,10,91,107,175,27,56,59,104,18,71,209,245,4,165,227,203,178,69,1,114,130,119,193,171,64,18,182,174,155,16,84,193,55,150,153,90,251,6,94,161,253,223,200,143,16,162,175,93,211,88,243,61,118,144,204,158,163,68,183,243,85,64,42,52,155,32,39,213,93,165,239,188,8,152,93,228,136,71,213,103,158,57,252,54,203,34,230,180,127,56,46,22,5,220,190,103,131,16,64,135,114,68,112,125,205,54,108,113,157,5,31,108,20,138,80,149,170,6,114,65,223,21,159,246,115,158,118,220,203,106,20,66,204,213,59,225,109,136,122,206,137,104,126,66,24,195,83,223,112,36,241,154,219,254,255,248,77,142,202,95,86,171,11,42,188,7,245,217,138,49,224,34,61,121,28,57,25,3,70,9,40,108,107,108,211,160,206,154,77,59,153,161,172,200,23,84,154,131,94,122,115,145,19,13,234,127,86,154,80,149,41,50,98,186,251,36,10,53,159,223,103,104,248,67,154,136,228,46,83,243,36,33,221,157,116,83,109,54,89,171,46,252,120,86,50,220,23,252,185,68,192,125,37,223,233,232,110,16,135,71,175,199,37,75,162,17,48,41,32,39,131,59,145,161,20,26,149,216,99,1,188,240,87,189,8,24,224,227,175,207,156,151,37,76,105,62,202,86,172,9,208,0,186,72,213,78,103,254,132,192,92,113,242,42,224,245,111,181,206,107,130,182,212,63,185,27,28,41,112,220,209,148,172,7,140,225,168,124,67,203,73,76,139,41,226,87,30,125,197,216,76,36,160,168,194,202,181,254,134,0,148,187,242,94,239,72,9,21,148,168,92,66,161,144,73,37,106,39,176,127,116,44,183,89,77,47,138,171,10,169,117,147,107,92,29,184,69,82,220,13,130,34,214,197,214,6,152,46,180,228,77,211,162,47,149,169,145,56,196,174,84,97,93,246,216,30,34,211,137,93,8,161,64,73,106,220,60,107,201,86,86,124,51,9,66,244,168,8,22,125,147,200,68,23,23,247,75,139,87,52,54,5,53,175,14,218,127,126,196,104,220,88,75,122,52,99,226,111,88,137,95,199,196,6,2,87,182,200,67,133,205,210,73,174,53,64,12,134,84,182,73,199,7,65,88,7,24,83,187,31,81,35,236,229,37,177,78,42,143,233,94,241,133,195,255,185,7,218,41,43,231,129,3,23,175,147,37,26,188,70,161,146,126,24,12,38,104,96,209,143,227,254,9,198,24,192,4,227,59,174,32,240,251,5,34,127,186,184,83,193,62,41,187,33,39,239,28,16,118,164,36,171,230,136,212,122,52,86,39,165,85,61,117,145,179,83,209,229,95,227,85,170,136,187,59,115,217,179,60,48,21,67,116,58,14,145,89,89,35,229,5,152,217,138,26,10,189,186,35,83,210,174,165,179,87,168,247,177,43,213,204,247,37,109,164,15,182,108,253,170,140,83,214,151,0,211,81,132,64,43,30,248,18,149,11,44,248,98,107,216,117,38,96,167,82,124,152,140,191,51,40,145,207,31,45,189,144,120,151,236,172,94,196,233,80,172,227,217,187,197,174,24,108,153,189,212,51,44,156,203,149,74,222,95,240,202,168,235,255,91,215,29,201,254,8,156,120,134,162,218,172,153,51,254,189,4,238,93,65,227,158,247,6,74,254,126,91,58,204,84,167,188,223,91,180,79,147,62,150,135,231,158,186,185,126,91,13,115,56,108,78,17,205,175,102,47,20,157,73,175,89,225,242,141,119,215,191,236,127,186,252,109,87,164,233,22,213,98,137,134,97,78,12,13,150,30,160,164,149,154,108,167,156,104,67,228,187,152,143,135,114,154,47,7,21,89,131,179,34,253,135,40,109,220,0,127,213,82,85,64,161,1,113,242,240,66,56,78,225,32,59,26,177,12,19,79,6,212,120,217,177,7,187,76,85,122,133,9,219,81,118,109,201,21,119,47,122,30,190,208,241,78,63,16,91,45,44,253,13,228,18,228,187,96,222,132,166,77,100,226,124,234,61,59,174,40,117,26,163,5,65,107,1,95,18,170,126,100,95,216,113,98,15,186,246,133,3,205,221,228,159,206,212,201,240,175,113,198,72,187,233,28,104,253,239,168,246,139,120,149,143,34,146,39,220,145,216,114,243,109,219,151,117,75,33,162,197,181,62,19,128,118,215,96,101,54,68,109,7,171,133,54,145,1,15,56,224,58,123,172,196,221,3,133,158,85,120,21,246,153,166,1,17,66,48,223,247,230,95,15,223,253,250,109,197,6,190,76,117,7,245,185,143,129,188,191,215,198,20,90,194,172,250,78,233,102,182,120,92,116,208,65,80,84,235,77,57,207,221,127,16,225,96,218,22,104,216,138,195,220,101,236,3,109,87,42,198,95,96,164,202,48,107,45,17,107,246,2,243,229,149,152,83,101,228,91,80,183,254,119,138,201,64,197,135,212,15,171,151,44,69,249,208,188,57,253,250,157,63,153,226,131,155,3,224,56,103,144,28,200,229,192,71,131,21,129,219,235,31,205,144,191,146,253,77,67,78,216,241,242,228,244,174,123,254,65,212,26,35,218,100,1,28,145,247,37,254,116,206,212,40,200,241,209,30,238,181,165,198,211,144,87,158,142,226,70,232,172,134,42,41,121,222,108,17,68,45,47,16,56,26,77,188,99,188,115,118,252,245,11,51,25,44,27,128,31,32,221,54,158,109,102,53,155,4,245,73,26,234,174,198,111,64,52,171,213,56,173,114,145,152,204,191,140,179,22,93,211,35,243,221,136,103,201,155,0,41,110,183,62,30,176,252,190,108,47,23,203,166,160,173,17,124,11,189,244,44,4,13,133,74,224,19,240,200,254,27,57,180,193,89,67,10,147,117,127,169,109,96,98,8,10,21,26,37,181,81,247,202,60,172,58,139,237,116,143,140,46,52,176,49,71,231,243,80,161,14,219,152,25,62,178,232,150,162,47,124,122,155,221,61,212,160,224,158,136,39,24,24,159,93,108,6,145,49,245,189,95,22,153,45,100,83,225,12,97,201,53,242,6,2,23,210,62,108,106,189,178,189,42,64,247,93,171,233,157,196,159,103,239,240,111,60,164,43,151,83,198,183,204,37,185,207,113,120,130,103,10,4,90,144,149,54,51,128,82,233,108,119,172,85,82,79,203,25,184,22,113,202,100,46,34,121,95,234,102,43,243,242,211,223,171,133,152,188,18,134,67,47,2,94,11,17,249,254,0,115,150,132,37,136,76,84,42,91,153,219,138,4,233,91,164,1,243,162,12,134,75,244,55,138,40,252,182,74,245,239,39,45,157,106,56,118,130,15,190,210,138,155,237,239,57,182,77,69,190,113,237,27,178,173,214,149,95,133,12,106,208,89,63,129,174,51,58,43,142,103,103,138,109,123,39,101,45,171,1,233,54,34,208,63,121,151,241,39,0,207,133,172,100,150,134,5,196,133,184,171,253,201,139,186,75,242,123,53,174,38,249,95,72,254,64,108,209,147,37,177,166,69,3,178,95,255,47,41,195,232,6,73,119,89,203,225,150,80,125,183,56,28,82,112,89,167,237,204,73,139,208,233,7,168,90,35,244,133,50,216,254,240,80,227,187,102,135,27,213,192,201,21,175,236,199,100,103,36,247,192,4,133,40,125,16,111,25,177,101,37,180,170,49,230,106,169,123,73,58,231,60,106,230,145,116,211,215,134,199,90,18,243,210,29,225,79,224,248,108,204,147,215,73,244,75,154,145,95,137,151,193,154,146,43,242,175,5,62,42,113,9,57,70,59,133,75,165,250,154,186,143,167,22,47,252,137,102,87,181,104,147,207,195,205,88,18,48,209,126,182,35,179,10,30,175,25,163,6,202,85,185,99,52,208,20,19,242,169,14,253,227,198,85,129,68,11,99,112,59,79,142,105,188,254,123,148,88,153,70,89,84,106,236,34,181,241,51,194,138,62,14,134,245,151,117,235,135,10,139,140,204,146,196,96,242,114,217,131,102,142,129,65,132,108,64,29,42,233,238,33,19,249,17,222,195,125,158,124,202,110,18,183,150,111,199,70,127,8,180,135,203,33,143,230,228,90,44,43,118,241,57,168,162,89,150,106,102,32,60,250,93,143,196,239,12,214,171,73,180,196,199,210,115,112,192,13,9,123,222,213,148,91,19,101,236,101,30,146,43,164,10,156,101,112,151,65,89,151,245,154,56,37,194,99,153,35,80,3,93,62,246,6,68,42,34,155,207,230,215,121,37,213,153,36,165,136,123,181,144,31,215,138,161,118,151,196,108,131,138,93,13,158,182,138,197,184,0,44,139,70,0,204,15,179,245,235,111,229,61,119,1,248,135,70,169,50,116,69,16,223,77,223,248,176,81,63,205,104,150,100,178,216,215,7,243,251,58,16,117,59,213,117,122,156,183,0,72,126,132,100,86,92,240,106,174,220,88,51,75,166,111,176,139,229,215,30,173,166,246,249,201,187,24,250,69,150,214,224,9,17,218,53,173,213,254,11,60,19,32,202,124,40,131,51,99,223,226,217,190,252,29,14,39,73,199,37,180,254,114,46,169,46,109,205,172,86,62,198,113,209,186,149,211,122,42,239,238,71,133,33,39,217,86,131,68,199,243,26,0,143,97,215,140,217,34,11,55,192,118,66,69,203,200,128,171,40,250,94,127,204,76,168,232,153,226,37,150,4,8,22,177,75,64,204,39,19,45,127,173,174,14,222,159,184,66,88,61,250,133,231,114,166,164,33,157,77,203,31,222,189,111,131,178,107,117,10,165,203,18,211,117,188,134,254,238,158,123,143,231,245,189,89,21,88,66,169,241,24,26,210,108,105,249,56,37,196,36,26,110,237,31,34,198,114,72,218,133,14,40,38,0,26,218,130,56,146,228,86,253,43,36,112,162,58,232,178,162,105,114,186,74,187,229,215,195,101,241,14,24,95,246,248,101,255,68,164,79,41,18,245,65,11,228,167,132,169,52,170,196,91,52,224,204,230,105,193,231,254,49,143,85,42,221,140,233,18,131,116,86,127,103,136,113,15,23,95,39,90,226,59,168,56,73,43,227,171,60,251,5,66,24,207,129,225,168,127,243,190,108,173,215,76,110,107,75,120,242,147,252,217,57,234,116,1,133,221,90,162,174,126,61,236,200,53,105,71,155,217,56,85,6,214,13,60,119,234,225,200,186,152,215,237,225,105,85,252,240,252,38,75,220,200,6,243,144,34,127,161,14,197,107,63,75,235,195,72,44,27,244,129,243,201,59,241,45,173,62,200,145,232,76,142,208,183,15,77,119,157,26,157,170,159,104,206,13,248,132,68,229,234,196,252,168,229,154,203,44,177,54,200,235,132,93,52,10,196,60,152,226,220,27,98,85,215,82,144,161,12,76,202,47,71,231,225,223,105,35,201,195,174,188,10,168,199,141,255,108,74,166,226,33,4,203,54,202,178,27,127,250,86,181,225,246,70,219,65,173,49,214,202,71,22,67,184,54,90,182,251,202,40,14,235,63,201,190,75,65,15,33,62,81,56,157,55,187,67,3,223,5,188,105,211,72,202,95,229,207,20,1,219,121,116,56,5,116,227,97,48,200,192,252,86,238,56,125,89,89,89,100,76,5,180,81,31,33,111,202,211,182,51,25,81,28,239,153,125,85,67,149,136,118,157,65,84,65,43,74,86,81,238,45,7,227,222,145,234,95,152,157,225,22,53,47,59,189,252,16,40,26,171,155,247,98,73,206,206,218,9,241,152,213,3,15,107,123,100,86,78,2,200,194,8,78,101,235,150,113,69,232,13,102,131,200,41,240,126,186,238,184,20,62,218,235,221,116,53,44,20,219,104,254,112,139,81,119,100,253,105,53,62,247,159,166,75,128,64,51,7,193,108,154,115,34,146,127,75,102,17,112,81,35,33,255,104,228,11,97,24,252,219,214,122,235,2,28,34,128,252,220,126,248,87,48,200,149,102,191,135,59,48,111,142,210,22,87,41,25,209,90,114,67,98,234,128,53,45,198,155,116,161,66,14,216,226,63,200,18,7,20,213,60,221,77,128,48,20,142,208,197,61,210,161,90,77,80,146,220,80,168,29,93,171,234,195,182,134,136,225,120,206,94,147,141,52,199,5,155,74,143,12,252,50,79,254,135,78,145,222,143,150,128,28,137,206,79,88,83,195,0,213,182,223,225,201,191,235,235,39,175,202,211,139,11,109,8,255,251,237,232,33,37,250,169,184,42,115,205,55,220,211,160,190,225,201,208,87,227,181,15,92,123,111,172,104,71,23,236,206,214,177,119,77,128,149,238,102,224,147,48,143,82,158,83,179,110,112,12,75,86,190,48,208,14,156,92,140,55,64,14,23,106,204,140,48,97,72,62,247,14,217,121,31,224,171,233,69,177,129,185,71,17,87,96,138,78,19,178,198,229,37,235,51,51,208,149,100,111,39,54,197,126,215,245,125,0,18,64,157,246,4,183,62,21,82,209,182,193,74,163,255,99,143,38,119,30,171,116,62,129,241,64,167,205,128,48,19,141,208,126,96,231,17,94,11,123,106,132,252,127,95,4,217,84,100,231,9,56,144,178,55,92,107,154,194,164,113,19,93,117,152,188,49,241,135,95,131,177,63,10,247,179,86,47,153,63,125,70,239,205,3,48,196,135,152,123,146,5,229,21,112,255,72,4,180,42,148,238,234,211,163,111,223,49,176,36,101,182,121,145,65,242,151,27,181,100,235,212,127,238,78,165,2,36,188,117,89,217,137,39,32,249,156,72,106,48,65,177,35,119,166,109,125,93,15,74,133,194,177,8,208,79,4,23,216,37,3,20,67,12,40,52,11,160,213,96,177,234,40,240,251,19,126,81,186,153,249,204,11,91,78,70,238,38,31,243,13,156,49,165,95,148,218,155,179,139,30,216,15,153,27,164,59,189,173,159,141,146,16,21,167,183,161,203,82,140,66,150,182,16,73,40,176,102,55,118,132,173,249,137,117,137,145,90,53,86,164,24,152,171,14,64,192,181,253,238,22,204,59,115,228,173,155,232,15,108,250,14,135,190,177,25,54,114,152,83,38,132,125,185,243,134,112,168,170,99,100,155,125,107,46,165,146,10,12,243,170,39,155,195,220,140,129,9,27,178,166,144,112,200,134,3,146,228,27,60,217,251,147,93,72,56,196,158,217,177,53,113,146,111,93,172,7,71,165,196,105,120,164,255,79,158,235,183,45,61,139,128,87,87,24,202,89,236,50,129,135,90,217,225,115,211,102,32,22,124,87,167,76,209,47,193,179,5,176,1,172,115,53,235,4,198,69,17,146,1,156,60,169,171,3,154,137,1,8,160,180,39,33,145,194,221,167,74,225,147,22,226,175,161,190,155,99,104,36,234,28,206,255,153,106,146,140,248,208,160,159,129,189,81,79,151,34,57,191,19,60,238,132,173,126,112,102,40,167,236,248,169,15,165,62,167,248,117,241,242,52,190,179,82,62,174,253,135,166,242,116,101,164,25,44,212,205,199,182,51,26,85,54,11,16,243,103,183,145,84,222,115,193,84,191,14,243,49,214,76,187,20,39,29,243,173,156,181,219,109,64,24,75,52,179,28,160,231,99,85,33,44,165,96,91,1,116,151,203,247,43,74,128,179,172,198,31,77,89,11,160,120,13,159,140,72,217,110,79,78,206,233,178,98,50,152,74,216,73,133,249,217,70,75,56,129,241,107,234,100,37,103,60,16,188,2,190,11,70,104,226,153,93,247,153,143,161,19,20,220,168,207,59,231,145,117,83,136,104,18,107,25,84,26,105,116,169,98,24,122,32,236,228,193,206,223,235,29,238,49,143,225,2,196,58,61,127,140,102,14,140,100,86,158,130,245,106,213,21,195,130,77,170,38,87,189,28,239,43,9,141,221,172,71,101,23,117,196,97,176,152,245,228,11,197,252,84,206,70,36,202,196,205,27,80,137,39,25,75,180,73,162,224,150,97,44,115,24,151,153,239,190,250,64,81,124,193,49,199,158,225,239,216,251,150,194,11,43,136,66,171,93,122,163,101,50,248,76,30,251,201,114,80,75,69,109,212,155,11,141,217,118,95,15,127,174,149,147,216,251,178,89,253,92,51,157,16,128,60,144,26,219,47,131,125,182,76,241,164,209,6,26,7,92,85,220,173,245,230,208,98,209,124,70,173,192,190,132,55,211,201,186,183,60,108,73,202,134,11,25,98,22,219,173,173,140,39,222,243,91,17,177,81,168,144,244,94,105,34,211,227,16,134,9,254,20,51,4,182,243,203,82,63,238,89,246,230,147,185,200,52,129,113,141,167,177,99,18,247,119,52,84,13,203,187,89,98,35,178,30,13,149,205,77,136,197,164,183,202,225,132,158,34,253,166,180,170,81,56,53,16,116,34,149,120,212,66,17,226,5,193,175,148,81,251,230,23,177,141,43,79,103,153,84,172,51,44,242,34,237,188,74,225,118,144,129,40,56,96,157,254,134,231,14,209,110,23,26,41,253,29,33,247,80,149,196,100,34,23,183,198,124,246,191,174,56,254,31,119,127,229,154,236,190,38,98,101,91,126,182,201,156,27,210,62,101,17,18,95,17,62,112,173,218,95,8,203,29,169,3,23,137,111,219,234,54,156,50,148,31,227,60,56,205,74,105,149,45,57,162,39,83,232,38,150,169,204,161,15,212,82,220,124,196,127,1,123,135,186,208,13,210,224,127,223,143,131,107,123,201,10,21,58,99,135,64,212,81,242,174,16,20,198,65,72,42,58,79,59,206,26,52,133,57,223,232,6,119,87,13,47,214,82,42,153,242,77,203,163,205,22,188,0,129,78,179,114,86,63,119,183,248,180,74,200,49,174,239,118,170,130,129,69,61,251,182,192,219,239,214,192,255,58,247,26,49,105,232,74,79,103,145,214,114,231,134,233,230,182,242,244,118,246,117,136,107,207,19,107,184,247,251,123,157,189,96,101,189,162,223,179,99,10,86,165,128,163,231,16,244,57,68,233,20,250,104,28,166,38,49,110,177,66,17,127,187,199,42,122,137,238,193,107,95,247,227,189,113,10,75,176,213,70,136,141,144,164,87,37,42,23,127,141,164,183,78,139,218,128,235,216,244,18,237,172,200,24,113,21,112,117,16,59,41,136,9,155,210,169,170,75,221,91,65,24,147,102,178,110,106,220,193,124,222,37,240,191,119,132,54,85,182,115,221,35,234,48,168,174,45,235,227,126,189,190,94,228,240,101,211,112,91,127,57,151,48,255,55,129,17,139,254,252,80,114,75,182,22,51,188,91,109,69,192,230,36,179,138,232,162,3,131,1,137,52,56,241,139,77,224,236,177,175,210,192,80,187,135,105,224,116,81,229,132,151,223,232,67,207,191,76,55,255,26,58,42,239,48,161,0,251,40,166,214,231,173,40,122,99,165,8,170,84,14,152,38,0,60,172,198,70,127,95,75,16,127,6,6,164,64,141,172,238,59,222,131,224,43,38,141,127,96,100,62,2,30,34,180,54,230,3,150,5,231,193,31,96,61,201,7,121,144,136,49,68,114,1,180,193,165,67,117,98,92,230,45,153,167,120,227,39,220,201,40,218,176,242,79,255,176,197,84,44,219,188,24,123,109,252,180,10,54,56,205,152,158,23,34,226,122,114,118,86,190,135,145,210,139,53,111,80,254,12,33,99,114,50,69,174,102,63,40,134,203,163,241,201,210,132,197,30,194,21,41,67,111,169,59,137,176,140,87,223,35,219,148,41,17,47,87,132,177,195,184,155,62,44,57,51,61,166,176,0,78,17,239,248,132,24,90,111,0,114,11,243,116,156,217,62,172,237,169,184,102,49,203,132,170,173,228,19,92,247,110,129,213,51,246,166,189,117,14,122,133,32,168,49,250,110,109,130,233,47,207,247,73,245,53,4,163,18,37,68,143,96,159,144,46,41,170,94,167,114,150,192,69,209,251,219,13,111,213,186,98,240,94,100,151,249,137,215,40,31,202,233,102,233,87,154,45,180,231,125,239,156,180,218,112,223,97,62,42,141,65,252,126,67,80,247,250,233,208,232,35,192,160,163,194,226,126,10,45,236,6,185,108,216,204,37,163,11,79,111,48,215,146,155,158,134,141,203,55,89,61,222,33,78,82,125,74,58,124,11,39,39,25,125,19,251,109,165,69,192,6,62,4,243,172,60,180,97,171,114,245,37,98,216,173,83,172,42,223,203,123,98,129,233,163,55,50,102,117,207,223,131,8,155,151,246,17,163,194,153,249,69,72,100,93,139,51,97,70,143,174,24,21,44,73,67,97,203,26,232,224,113,226,185,74,242,203,51,164,179,209,188,168,1,102,93,74,120,214,135,191,193,209,7,112,218,199,145,10,92,23,239,226,242,205,187,159,126,171,125,35,158,53,118,74,19,183,224,31,116,118,13,32,211,205,92,131,123,48,181,32,124,7,233,247,254,24,251,109,189,0,184,187,80,73,194,94,100,239,81,170,145,20,235,132,230,56,141,90,22,151,198,88,153,66,134,20,94,237,62,58,110,218,255,50,111,198,109,211,202,21,39,7,30,238,147,85,35,154,58,236,112,221,70,102,211,120,115,74,109,188,70,229,214,191,122,134,120,195,231,217,122,35,113,9,110,154,50,82,32,35,111,159,191,205,52,223,124,250,77,32,228,68,131,215,255,245,107,10,80,105,104,31,4,173,207,219,31,219,171,182,182,254,211,181,183,202,185,238,165,167,38,248,72,193,90,249,154,165,80,64,209,68,160,49,226,93,135,143,48,97,211,47,187,29,120,160,203,115,39,87,245,227,220,244,5,60,57,251,126,42,117,244,81,69,98,77,242,210,249,188,19,130,253,198,56,95,174,249,187,185,215,132,16,226,25,29,180,25,54,143,69,121,134,79,117,180,218,210,211,236,58,207,231,69,104,95,149,166,212,59,105,131,68,83,21,233,177,143,135,83,237,99,3,20,58,123,234,249,128,199,117,238,163,124,52,215,100,124,76,146,61,253,192,135,196,87,201,115,149,98,141,214,85,252,207,188,13,34,208,166,93,132,22,39,44,115,121,203,93,78,137,69,196,253,197,120,148,36,21,208,5,95,43,5,122,145,41,160,12,117,201,143,36,62,133,73,185,73,185,155,194,182,166,248,96,33,9,112,7,42,39,42,203,253,23,196,161,187,66,234,58,217,44,48,7,139,47,158,58,153,179,83,189,27,100,164,156,234,199,98,117,100,38,11,24,163,169,221,244,159,173,191,177,229,194,60,25,229,142,239,38,104,95,145,238,47,214,188,90,21,66,126,66,111,210,228,101,36,242,172,130,97,234,90,20,62,166,38,11,198,159,44,245,249,131,27,135,234,87,83,2,62,185,253,129,60,125,165,26,164,138,148,193,87,246,201,45,72,3,33,31,191,29,45,33,15,238,109,8,39,100,38,195,128,83,7,133,205,161,144,113,161,194,75,111,13,7,188,92,227,251,80,96,18,64,26,145,25,40,183,204,243,127,122,119,214,146,16,231,175,187,101,92,23,25,172,45,195,139,252,212,135,73,86,24,33,203,30,64,143,202,39,238,180,143,39,141,32,30,65,76,186,57,211,14,143,45,98,183,16,106,103,221,249,6,53,137,24,139,142,183,198,247,95,139,222,54,254,33,32,110,206,70,243,213,3,192,199,172,149,164,83,182,93,148,177,50,21,141,173,13,238,107,195,127,67,110,37,112,43,142,183,230,190,209,160,162,156,23,27,134,24,34,52,140,72,249,61,178,169,148,8,130,66,147,91,31,208,121,252,240,86,4,49,94,172,145,170,231,175,155,91,81,34,65,35,19,119,54,89,16,204,192,75,121,73,147,188,144,117,13,228,38,41,170,216,212,138,219,190,30,66,160,168,25,44,46,139,91,239,138,252,75,214,254,70,38,167,102,27,83,199,3,87,193,132,173,198,46,20,126,199,149,77,169,28,80,101,104,137,62,96,184,186,195,156,232,54,165,152,181,234,109,221,187,146,210,235,81,120,213,202,4,54,76,73,143,91,58,186,245,234,169,42,230,22,18,250,90,107,166,223,111,105,64,154,164,4,224,90,136,137,59,115,161,111,33,203,195,109,85,228,153,230,42,60,71,72,5,2,62,18,247,95,210,226,191,18,86,215,250,188,187,220,235,252,237,222,248,38,43,49,68,167,200,78,234,221,147,5,179,21,224,63,87,13,134,86,163,63,36,111,99,183,191,107,252,17,109,125,244,237,227,124,248,96,249,123,151,124,55,89,15,60,83,228,51,167,78,178,149,160,185,115,84,80,74,205,223,140,130,90,11,7,178,123,40,235,140,10,228,159,27,22,21,27,35,97,198,101,3,45,152,101,159,133,198,240,50,167,96,88,76,87,206,44,39,249,11,105,101,233,91,94,0,117,182,228,62,63,40,7,175,93,108,94,109,10,13,105,155,235,242,84,115,42,225,207,146,64,214,155,15,160,204,116,101,205,129,106,90,130,161,1,205,66,106,134,110,197,2,121,251,255,76,57,17,131,177,22,249,53,191,239,3,209,175,23,202,194,236,120,82,27,150,175,201,140,218,92,66,6,242,27,242,72,21,153,249,76,147,161,201,108,133,37,82,63,157,26,16,157,157,53,227,144,45,33,251,159,166,102,14,146,8,130,61,71,232,239,55,149,154,94,62,201,196,46,66,64,182,197,173,177,174,129,184,239,93,144,26,35,78,229,198,0,35,11,0,24,58,31,116,17,14,148,173,217,199,57,30,154,70,63,65,205,96,139,15,161,221,167,15,248,53,144,210,247,198,28,89,183,77,185,161,137,46,60,33,250,124,201,6,162,14,149,173,139,246,183,196,97,174,62,140,41,85,124,32,241,157,180,188,116,43,88,101,206,143,162,87,136,175,53,8,137,29,26,223,233,139,150,187,232,66,160,175,236,60,249,74,124,88,0,169,71,249,158,190,158,10,136,161,14,192,129,205,123,206,139,139,194,116,10,232,178,229,135,29,133,175,175,159,206,251,200,116,49,111,179,231,204,59,114,82,198,44,18,188,92,104,214,214,0,99,131,131,20,13,139,95,163,166,89,240,125,147,162,92,27,236,208,194,108,76,213,90,135,100,0,183,53,71,191,95,49,61,227,177,149,62,19,73,102,79,254,208,162,75,217,114,173,130,116,114,179,103,102,51,151,84,216,208,210,52,137,180,99,72,124,128,249,247,136,183,36,28,249,242,125,70,239,231,22,75,183,222,194,216,180,98,166,182,159,27,186,214,74,253,234,220,112,80,103,58,215,113,70,28,68,149,92,181,110,119,67,179,179,9,96,140,249,194,72,173,244,144,58,9,141,246,68,237,118,179,124,164,96,125,30,196,126,104,19,176,107,25,7,162,89,236,206,184,139,167,166,16,55,67,7,93,251,90,252,86,252,171,140,238,114,28,106,253,2,64,26,18,192,199,145,70,224,41,158,81,211,254,47,235,74,231,215,176,97,187,165,209,79,109,189,21,14,209,97,193,29,254,42,24,157,72,5,143,9,214,54,90,86,243,143,140,12,163,2,158,213,69,48,232,80,165,123,73,197,247,8,241,232,198,127,142,153,236,153,145,20,27,64,72,56,14,13,147,102,116,211,20,44,176,108,13,229,36,230,81,206,9,197,5,42,177,137,125,239,52,138,145,92,76,16,223,134,138,221,234,177,91,177,210,67,1,151,117,176,201,125,211,227,144,217,180,31,53,97,31,147,33,222,114,225,63,236,245,62,68,54,30,147,134,96,110,84,124,209,201,141,3,62,115,79,24,228,194,3,74,218,184,3,66,224,170,40,123,37,121,61,129,54,53,103,197,43,89,135,6,26,104,193,193,136,152,56,142,183,224,128,35,138,123,231,218,184,64,116,133,134,79,71,93,163,18,65,127,217,137,72,42,147,44,193,117,255,58,201,221,139,83,224,169,171,21,200,243,196,43,229,12,27,96,110,87,50,136,174,144,220,236,35,210,9,136,71,10,14,95,205,206,230,46,210,240,140,197,31,1,18,188,0,238,15,228,67,49,220,86,132,126,70,124,204,88,118,84,251,214,36,171,200,70,160,93,190,20,193,149,122,208,201,60,231,13,227,143,217,98,120,101,241,47,166,37,0,246,166,53,179,69,210,170,111,102,237,39,29,58,140,90,17,30,66,50,240,135,134,156,130,216,158,96,227,238,43,173,150,62,156,252,12,213,121,200,99,178,38,253,248,51,29,232,51,139,88,26,160,174,235,4,96,47,68,39,65,224,118,4,246,129,110,151,23,33,196,101,107,18,57,33,181,138,239,175,105,157,49,247,51,175,4,49,223,166,210,239,121,16,164,212,230,198,33,63,150,165,9,54,147,43,215,241,224,55,27,106,204,89,39,184,161,80,49,4,115,240,147,14,244,80,211,157,188,47,240,27,232,175,82,215,194,147,55,86,12,143,240,196,252,206,171,147,238,96,167,220,204,222,124,57,43,217,33,94,205,196,224,116,99,78,12,233,159,227,1,76,43,79,235,217,146,66,161,211,175,94,65,74,199,243,183,6,81,84,203,242,106,233,76,173,158,214,45,43,108,174,250,106,136,126,230,63,14,251,213,18,71,87,50,64,255,236,85,183,102,109,45,1,174,202,9,149,185,253,197,58,210,45,138,136,51,85,221,138,73,184,106,127,134,253,72,58,18,180,62,151,29,82,139,220,202,116,64,248,20,81,96,109,47,138,242,186,193,36,58,228,83,194,172,38,0,252,218,244,10,112,115,142,57,210,57,11,64,200,229,159,61,193,101,132,118,218,80,148,208,24,56,50,42,216,65,221,198,222,42,94,40,195,189,60,175,28,71,25,114,164,42,45,8,67,46,142,204,238,25,167,37,150,221,46,11,216,39,161,104,150,116,113,1,94,67,6,9,155,180,85,217,5,244,160,99,51,203,177,93,136,13,60,29,150,143,141,45,240,202,86,52,252,208,169,251,4,6,159,54,129,123,18,109,207,1,191,79,38,187,105,43,96,244,160,246,58,53,1,126,98,82,106,12,250,65,44,103,65,155,146,190,0,201,249,32,20,57,171,220,149,156,114,51,66,148,220,137,156,113,120,32,169,126,124,13,130,177,138,31,55,46,148,240,128,29,71,141,116,145,112,8,66,189,190,216,123,114,164,94,213,103,242,213,46,100,240,150,169,179,251,110,47,164,50,174,245,163,245,59,14,243,8,35,82,74,151,19,130,70,32,129,139,54,14,190,35,131,230,71,44,133,253,187,52,219,118,239,235,58,76,31,196,252,32,242,187,197,157,187,55,29,121,51,214,250,24,234,46,96,133,232,102,63,43,191,186,226,113,189,64,205,186,249,119,43,113,194,61,250,58,221,69,191,75,14,152,187,167,243,108,156,124,46,5,218,175,243,118,7,240,85,167,144,192,213,61,210,252,162,165,162,46,86,124,240,63,149,35,88,159,198,71,207,56,140,25,144,133,248,190,191,241,252,13,124,234,108,165,9,106,44,119,178,102,193,221,168,140,143,125,102,211,106,41,163,241,103,12,131,227,10,78,64,224,131,209,128,108,224,131,81,196,188,208,57,0,65,7,171,245,92,68,97,155,26,19,0,220,173,153,62,182,16,55,19,229,89,135,80,157,145,162,168,60,3,54,77,8,252,62,78,45,97,13,187,5,95,233,221,143,244,218,237,9,191,191,111,230,19,235,185,24,229,133,236,211,127,22,70,243,186,237,63,6,52,140,155,111,172,124,143,130,20,198,240,17,48,164,10,74,221,17,240,102,82,73,186,66,214,132,28,226,189,253,197,216,71,13,102,76,54,192,250,157,250,97,33,169,125,119,76,18,127,148,89,55,79,41,27,171,173,241,40,25,242,210,152,51,104,129,66,79,162,178,205,127,78,159,148,90,244,237,62,200,220,157,71,215,30,45,95,17,166,151,2,107,156,25,214,202,113,205,64,70,182,24,9,62,176,176,190,16,176,188,96,117,242,77,22,88,50,108,118,138,246,209,82,199,143,160,77,201,121,197,140,194,143,8,181,195,45,95,221,40,139,214,14,153,166,70,195,180,165,102,177,227,237,193,79,231,55,66,91,102,116,212,200,47,182,152,106,44,255,140,122,66,158,160,250,117,112,5,28,227,9,101,161,115,43,75,216,160,129,201,85,4,155,212,168,94,163,160,204,9,102,25,233,102,160,184,227,106,238,100,129,31,84,122,126,254,145,223,210,150,80,172,229,177,248,245,3,169,238,5,16,2,78,51,54,207,82,72,227,99,136,26,105,129,53,22,17,45,214,181,195,68,36,56,169,195,242,5,8,191,67,154,4,98,246,26,112,153,140,77,237,240,2,154,115,169,245,170,100,202,110,18,149,98,123,104,24,71,192,232,157,222,215,83,47,36,18,129,246,103,237,227,185,218,144,30,199,136,151,160,138,100,74,32,166,208,86,67,75,237,132,120,166,153,52,64,10,225,171,2,81,131,86,59,191,48,93,62,184,125,186,164,181,232,91,66,146,242,21,173,53,43,188,74,248,215,108,185,224,167,76,81,71,206,93,12,235,166,22,241,224,190,133,235,131,111,103,60,230,112,49,52,171,86,194,94,59,123,115,191,87,69,241,194,32,229,82,37,247,66,83,202,39,30,54,213,89,3,78,249,44,22,248,167,57,0,84,189,32,168,147,103,6,140,148,202,187,193,37,38,180,46,29,166,57,72,223,230,106,44,108,111,251,141,251,89,7,111,191,116,203,52,57,144,49,241,196,170,155,145,94,130,81,6,8,48,239,173,230,55,130,69,187,163,225,66,214,151,106,237,182,124,152,252,164,152,71,188,138,18,156,234,158,96,75,48,112,107,71,163,19,180,198,24,225,112,151,114,89,6,217,49,26,232,78,138,51,90,69,91,193,126,130,54,20,217,158,121,249,61,85,203,2,97,83,109,237,170,254,0,91,197,122,244,126,45,233,234,109,127,179,19,219,93,31,65,76,94,19,176,192,62,20,225,161,144,181,212,117,211,254,177,20,119,165,4,191,21,105,172,116,103,36,198,101,166,240,111,212,21,87,239,249,26,153,242,52,76,142,34,251,237,81,66,187,57,122,29,236,37,110,21,148,230,218,247,104,63,1,234,5,69,199,73,134,157,172,42,231,147,224,75,141,129,211,82,4,89,195,246,70,171,181,93,183,55,108,159,166,33,84,4,185,111,204,210,203,121,247,47,11,38,196,128,175,73,224,158,13,7,251,219,162,20,164,80,64,199,241,117,6,96,69,101,173,208,37,165,211,107,165,193,43,31,159,138,214,247,2,33,12,191,208,158,105,240,17,229,141,41,237,45,38,45,115,88,232,28,191,188,150,228,13,47,17,235,94,149,41,105,96,203,124,26,222,106,9,189,50,92,15,120,136,57,57,255,99,51,112,155,217,186,209,181,137,48,198,43,39,230,86,230,26,217,240,223,93,238,195,80,220,79,238,160,255,161,52,146,25,191,179,0,106,203,39,179,207,46,133,153,151,239,88,57,122,189,135,89,178,115,230,216,10,114,143,251,93,168,61,169,202,150,202,196,237,75,49,182,183,125,110,19,34,1,136,14,89,81,155,227,118,201,69,250,152,109,216,132,250,88,147,48,2,191,100,195,211,13,126,162,119,72,133,229,123,207,22,23,212,210,63,155,150,227,57,166,222,129,67,70,42,85,154,245,247,41,193,230,95,156,113,40,103,226,86,19,6,181,49,124,103,224,189,223,33,119,236,24,20,229,68,141,154,5,89,177,163,212,125,152,33,38,48,226,24,141,151,158,51,86,207,22,139,80,172,113,125,82,37,229,71,24,29,22,151,195,95,177,29,49,74,158,121,217,68,52,92,168,158,88,196,251,22,3,155,79,122,252,156,221,200,181,70,100,216,71,156,175,156,86,2,231,130,108,43,211,119,75,181,114,163,95,222,24,246,255,186,183,186,101,37,137,223,53,194,47,117,58,55,235,209,179,14,167,242,26,134,221,36,193,38,118,184,207,96,67,32,145,250,154,128,94,25,66,185,48,57,213,130,222,58,197,173,252,78,101,199,141,206,155,94,81,157,155,216,239,200,168,141,203,59,210,55,17,55,170,5,110,70,51,20,19,17,219,187,198,121,220,48,135,101,52,185,215,244,4,37,229,220,138,211,126,144,244,210,14,194,134,9,176,26,52,128,5,94,173,63,199,171,196,37,142,16,185,13,98,224,38,105,153,24,182,124,179,35,177,69,226,224,127,75,236,2,98,7,44,185,3,14,107,156,129,152,51,36,29,203,211,203,108,162,74,162,216,89,12,128,9,112,14,157,147,3,227,248,177,51,228,239,231,213,231,254,82,42,244,137,106,99,170,156,192,66,71,139,213,5,156,125,195,124,229,130,190,205,89,225,241,254,176,95,30,219,40,248,129,218,116,222,75,183,241,249,60,88,178,52,92,157,156,113,232,162,36,107,47,55,17,155,162,70,224,125,82,84,211,203,26,49,246,193,94,207,161,122,216,126,138,16,206,87,28,38,45,30,196,186,30,68,206,95,156,208,218,236,93,107,125,217,121,46,223,4,69,183,46,238,206,71,72,167,159,167,48,118,25,0,159,147,140,99,166,172,4,113,21,161,52,102,54,219,194,90,106,50,6,156,202,21,86,112,33,45,53,6,124,162,83,226,178,246,1,165,167,177,190,237,128,219,79,114,30,187,31,146,10,157,251,80,124,108,191,233,91,104,68,35,156,13,54,123,191,37,77,245,82,222,206,8,246,133,27,217,87,116,7,145,65,128,81,142,250,19,137,207,10,217,88,150,119,183,30,231,123,9,189,145,113,150,247,204,148,101,142,228,144,127,101,122,157,153,221,45,112,44,139,13,223,94,18,221,245,14,185,252,132,117,15,173,122,121,1,251,109,2,107,25,97,29,180,199,11,124,161,138,37,92,119,254,245,118,34,128,28,100,200,80,5,114,99,208,232,126,215,247,226,193,129,111,229,166,12,107,30,67,118,84,156,100,158,204,44,28,118,134,227,10,22,153,126,77,13,134,137,18,167,115,62,98,60,182,179,66,109,93,146,39,135,247,137,193,45,175,156,83,87,217,63,250,57,154,128,151,152,45,35,43,126,198,229,219,126,200,145,4,236,251,153,196,162,89,73,134,96,119,107,128,190,147,228,64,73,220,100,124,73,203,91,213,77,92,68,50,107,69,237,110,138,228,193,175,162,213,78,39,118,105,39,11,196,157,25,195,35,53,250,121,123,219,197,179,143,206,30,210,251,106,231,243,37,84,55,23,7,30,84,11,121,92,53,9,191,28,49,57,237,112,78,183,12,215,243,99,159,238,14,246,197,136,207,69,0,120,99,89,37,184,54,94,128,204,224,174,118,50,226,59,151,162,115,167,144,223,213,199,4,87,55,193,10,212,169,238,242,254,70,213,252,87,32,245,18,157,79,122,232,143,103,31,93,140,93,243,91,156,91,223,136,12,68,98,200,179,170,185,195,112,27,104,3,205,165,28,186,174,118,57,189,119,144,158,95,158,164,143,139,58,87,217,43,22,68,43,126,240,70,94,163,225,233,248,227,168,70,198,16,51,205,239,192,4,124,244,190,80,130,188,253,65,63,201,98,243,142,139,238,115,52,164,188,234,11,203,33,66,111,40,174,113,78,139,135,102,209,122,166,53,10,2,10,140,215,139,223,100,11,23,208,126,65,214,52,37,98,93,37,250,159,75,209,155,248,86,107,5,114,199,254,105,179,240,132,18,228,65,136,188,180,168,141,149,43,234,13,114,25,92,32,8,212,172,186,194,234,241,77,20,142,76,140,225,110,176,248,93,52,69,8,47,143,25,99,166,56,37,228,218,183,234,205,236,237,168,228,136,179,145,123,254,230,182,37,220,223,96,199,45,24,147,73,86,254,47,90,124,89,129,192,199,167,216,217,62,148,163,46,107,74,67,155,206,30,163,44,42,238,69,77,5,86,126,151,131,136,59,134,63,72,23,50,35,228,75,48,172,147,4,200,35,217,142,56,51,159,145,237,51,218,27,192,43,193,90,63,194,218,149,77,69,58,68,24,177,235,144,245,52,41,241,21,63,202,204,123,60,245,245,147,59,230,53,58,179,177,6,108,72,142,101,202,171,147,1,238,27,183,145,157,7,29,13,111,137,129,183,185,196,139,126,204,48,220,237,170,227,65,153,226,170,245,241,69,250,74,235,39,129,115,94,113,165,212,140,219,239,255,30,2,150,71,167,222,250,123,230,253,102,110,67,175,23,73,166,0,144,47,148,163,151,221,23,81,24,247,230,191,244,11,1,206,112,51,40,182,33,40,163,61,107,169,167,6,202,202,72,255,23,102,172,225,38,148,226,88,109,43,255,21,145,157,184,0,241,95,26,253,89,42,53,13,149,184,8,74,173,119,80,63,39,122,131,186,46,224,96,135,125,146,230,186,215,105,91,230,163,169,125,167,150,59,214,137,125,94,22,30,51,110,143,175,201,170,44,185,136,253,28,105,89,77,41,65,135,12,60,237,170,191,75,127,88,149,34,205,123,6,139,121,217,249,166,254,165,197,104,144,84,48,58,172,21,122,128,85,199,148,36,114,91,239,123,1,206,8,169,49,206,39,142,97,137,189,224,169,198,119,13,171,201,140,49,157,103,118,88,94,210,27,126,242,245,68,55,25,204,114,244,247,64,29,145,137,154,56,172,22,62,19,227,79,143,90,5,12,201,194,154,224,71,103,79,31,119,20,146,114,219,19,44,92,21,211,69,49,20,95,47,183,25,195,60,209,50,238,182,244,59,9,94,112,27,36,210,214,7,152,57,84,87,219,76,117,252,173,214,2,188,162,120,141,43,194,108,127,121,25,148,205,129,10,46,39,41,144,243,52,218,147,187,37,188,247,50,228,177,63,51,214,17,10,240,24,244,129,34,87,146,124,5,230,163,171,120,234,22,101,103,156,68,245,144,114,132,132,244,163,47,127,235,219,88,243,187,140,196,153,78,126,139,116,152,107,147,27,119,0,2,213,231,59,70,73,214,67,31,130,51,71,155,189,211,225,165,140,83,24,36,56,202,105,50,33,140,155,216,216,209,252,54,156,254,20,81,120,206,235,241,53,194,44,177,128,30,239,26,95,124,88,90,21,132,123,188,158,141,127,241,223,95,178,108,21,221,145,222,26,192,180,84,129,78,175,117,146,57,215,116,10,13,53,12,252,227,64,32,115,213,68,143,238,155,225,101,184,132,28,92,127,89,232,1,139,160,185,99,115,92,29,188,211,254,180,85,121,47,205,53,199,122,73,153,119,188,74,163,229,129,90,48,50,178,91,189,168,116,38,32,114,55,89,132,116,208,124,128,113,113,16,206,199,26,163,212,71,1,250,155,96,53,100,44,246,31,136,208,243,220,60,176,23,103,88,245,48,51,59,225,235,226,76,182,53,49,135,126,117,23,4,0,51,62,11,237,65,252,21,246,193,84,14,85,217,111,240,108,226,134,59,194,210,198,214,9,245,99,101,81,3,89,134,225,173,80,61,204,115,250,25,191,22,137,42,177,155,159,237,248,200,39,189,1,66,189,88,8,198,57,47,194,59,150,74,50,244,192,145,124,139,137,9,88,183,226,179,162,219,55,201,222,186,109,36,242,146,104,134,170,9,120,67,123,240,251,118,184,113,206,203,242,204,29,95,103,160,139,24,229,246,174,44,232,1,92,51,119,121,192,74,200,193,169,150,115,168,56,37,31,105,175,166,10,183,252,135,115,233,34,0,229,124,183,246,177,143,42,237,125,2,142,154,240,49,228,213,15,77,123,202,79,84,0,147,189,200,161,106,243,41,87,86,158,216,240,246,100,112,9,91,213,220,206,108,190,57,220,218,99,189,47,194,120,28,127,254,169,178,91,243,109,75,134,210,210,244,242,159,54,217,20,133,68,233,153,234,101,91,233,30,96,171,224,92,91,176,236,182,188,20,131,21,122,84,104,171,14,236,252,249,75,212,235,191,95,11,62,141,94,241,165,26,219,173,197,153,214,168,223,240,94,213,113,148,95,22,212,203,134,117,232,60,147,51,11,201,54,4,81,122,170,58,150,209,147,128,196,78,68,78,148,160,114,198,127,162,120,180,68,133,22,76,101,119,11,93,246,9,232,183,127,140,173,92,221,236,51,178,45,217,246,70,118,91,129,102,24,199,252,7,6,116,81,43,240,49,115,77,164,134,23,10,184,92,26,223,238,174,254,108,5,221,29,205,3,38,30,51,143,196,202,21,102,228,51,105,45,191,54,175,140,175,135,132,56,183,9,116,20,68,132,18,220,233,176,239,82,87,160,87,75,33,255,121,193,156,78,230,23,79,64,52,198,99,148,130,106,107,8,203,26,34,248,194,178,123,242,238,250,69,219,168,219,185,118,64,221,220,7,62,58,172,34,161,85,252,155,52,152,60,87,103,183,167,226,234,225,170,247,90,38,143,81,89,210,156,20,60,194,148,113,179,171,5,77,184,78,26,208,131,200,86,18,46,116,74,134,61,119,29,194,3,117,40,80,168,90,103,191,42,184,95,218,91,28,155,54,146,65,95,188,105,77,14,205,75,249,117,46,221,98,224,169,93,190,83,43,182,146,208,7,135,154,99,250,12,2,189,246,105,220,172,175,69,1,167,218,186,57,136,247,112,149,221,32,11,202,229,160,52,60,200,208,193,198,75,246,250,53,55,150,176,139,93,85,222,206,205,111,9,73,162,186,211,69,140,188,136,164,203,223,18,225,119,181,234,138,60,23,112,75,105,15,203,7,125,177,246,31,45,74,151,48,22,139,175,136,183,250,161,111,94,119,158,113,175,140,79,29,122,65,55,233,80,125,200,31,209,18,35,82,3,116,190,125,208,46,253,125,100,73,160,238,5,244,38,184,200,7,167,119,122,165,28,250,26,52,110,188,151,63,208,63,248,94,165,164,111,163,146,32,37,5,60,85,192,27,61,24,60,161,222,0,4,254,155,189,84,196,0,157,35,12,162,103,138,192,135,38,45,40,41,69,63,30,177,222,41,253,200,54,63,230,237,20,103,172,23,99,192,215,2,181,198,52,12,1,157,162,169,147,206,27,237,188,158,40,214,164,233,240,100,201,245,24,178,38,205,66,140,166,43,132,117,143,233,22,167,190,202,18,188,127,240,184,49,182,87,84,214,121,140,169,20,29,122,133,69,18,168,61,132,146,108,35,131,109,86,101,183,150,34,77,90,194,24,46,232,28,48,183,206,47,100,61,163,165,74,17,92,27,210,106,16,222,186,117,41,103,197,144,3,27,9,248,132,189,88,83,122,219,49,116,2,50,30,40,205,76,130,35,126,83,228,228,138,171,171,135,39,196,227,87,106,235,241,239,86,179,253,11,23,99,7,66,41,158,178,157,76,234,6,5,214,254,184,155,181,84,197,165,122,251,119,249,236,166,219,144,14,253,20,200,71,185,128,249,58,15,196,101,206,51,124,190,50,159,255,10,172,123,168,253,230,89,10,236,71,194,62,129,71,92,165,85,0,198,135,157,141,191,50,13,140,37,124,110,249,46,46,25,251,68,145,8,18,120,51,137,142,119,244,148,246,141,26,132,163,135,241,35,159,49,77,209,163,230,111,6,242,146,195,49,170,2,124,194,17,165,42,155,254,34,50,37,48,67,234,117,90,102,69,129,61,195,172,78,87,34,46,79,146,168,210,166,122,231,226,222,204,251,20,75,223,196,242,130,34,225,110,75,207,175,78,24,239,45,171,104,198,59,0,19,49,11,243,112,43,250,158,62,80,155,237,46,52,188,185,245,171,68,197,202,251,110,93,211,94,67,191,87,157,87,233,13,61,47,52,206,80,194,167,66,67,198,170,244,247,174,171,50,79,255,184,161,14,254,202,162,162,254,221,148,221,251,90,102,154,71,98,61,150,1,32,250,227,57,240,168,21,174,152,107,235,75,2,198,35,117,161,148,210,231,214,184,87,241,102,16,184,144,221,165,158,108,17,177,46,228,156,159,149,123,171,239,250,40,10,62,189,159,144,124,7,64,76,122,161,214,158,46,206,191,99,142,189,68,40,168,172,65,88,130,102,169,121,107,188,201,117,35,139,212,14,176,77,110,172,197,14,238,254,189,108,234,224,228,68,226,121,230,183,185,224,25,14,142,86,3,2,21,133,116,109,24,125,214,126,192,236,107,42,30,208,247,43,102,62,205,11,213,177,80,163,92,245,82,101,244,192,151,191,169,102,204,190,167,232,66,226,12,115,238,131,188,181,235,30,55,68,17,186,125,64,121,44,39,147,240,53,20,40,101,224,109,239,226,32,115,253,200,113,202,118,207,81,168,138,146,224,129,38,168,181,120,87,225,170,24,6,223,254,59,48,103,66,191,112,18,100,232,149,121,191,132,39,231,12,223,111,202,150,238,150,76,143,41,37,183,222,8,16,24,33,99,101,144,218,10,68,70,133,97,95,109,42,67,13,102,0,93,189,206,41,149,160,206,101,195,209,76,22,231,109,76,142,113,78,222,63,202,227,65,140,154,29,47,96,41,58,77,137,107,249,152,7,126,53,105,31,221,134,107,150,14,18,108,110,152,91,57,88,146,199,220,12,79,116,220,134,180,176,224,71,97,52,154,76,94,230,58,14,196,154,89,27,162,219,96,227,91,143,175,92,36,179,222,30,59,163,32,250,146,96,163,83,134,33,18,27,99,127,113,171,35,52,143,96,219,71,71,254,216,30,244,75,88,241,242,50,213,1,83,56,154,152,153,219,130,166,175,82,10,125,111,96,137,38,46,205,11,85,195,29,184,117,250,218,58,49,10,40,30,139,211,81,157,249,51,33,100,201,34,96,197,189,206,48,180,50,2,111,154,109,10,90,116,189,224,85,45,153,10,96,210,142,179,131,174,213,131,9,90,194,235,113,201,152,223,253,134,198,136,215,196,121,114,145,127,197,63,226,22,10,124,149,177,37,12,217,218,113,9,235,142,49,103,237,98,82,140,8,127,97,56,61,78,76,142,106,216,56,78,153,139,60,223,243,28,34,38,199,137,132,50,118,151,58,141,192,20,249,138,53,114,177,45,146,78,147,234,123,244,61,157,119,7,88,41,82,17,102,213,59,93,79,45,40,157,139,219,81,12,134,18,77,1,101,45,228,155,66,227,243,242,202,71,136,205,94,102,239,237,253,62,207,30,222,178,58,135,219,74,150,232,27,209,251,37,198,33,83,209,39,249,183,21,38,213,39,143,198,149,91,161,250,193,43,45,233,70,234,118,173,231,180,151,157,138,7,167,198,81,194,51,164,200,83,56,176,121,167,225,108,50,245,125,137,148,215,111,59,19,64,109,5,114,176,218,137,186,235,94,254,156,96,194,168,34,159,84,171,68,70,215,155,148,244,240,11,54,128,75,56,161,201,231,65,137,194,113,32,89,201,13,141,169,131,94,198,168,132,135,101,50,165,181,8,159,184,15,19,74,16,105,43,25,168,214,106,76,164,64,91,12,74,22,16,124,27,121,145,188,125,255,96,131,33,245,145,180,29,62,194,137,30,62,243,129,77,13,158,163,117,162,206,61,236,135,244,220,166,174,217,73,139,0,254,201,26,125,241,33,68,187,155,235,119,25,72,196,151,8,255,8,84,250,43,102,204,134,121,186,123,144,48,2,235,7,229,41,190,150,181,169,203,226,194,118,180,182,162,220,222,14,52,114,197,229,86,207,201,148,241,246,69,68,231,8,57,6,21,171,44,83,134,151,83,25,48,142,91,248,21,21,213,9,104,208,21,12,133,100,100,144,124,237,193,56,180,34,39,246,232,53,212,121,61,127,221,103,74,114,150,223,11,229,210,6,76,40,95,192,199,167,100,100,64,117,44,73,13,187,42,241,47,212,35,164,55,64,85,88,41,102,68,165,110,72,100,66,38,33,14,166,233,157,80,35,137,1,69,63,111,169,42,19,65,190,106,104,216,90,154,147,190,183,207,177,145,142,190,213,148,10,228,251,99,58,72,148,192,227,20,1,79,110,181,47,89,218,133,7,75,111,229,49,60,97,179,158,28,51,110,139,80,56,147,33,182,227,153,92,32,1,241,44,181,143,24,16,252,26,129,134,63,65,186,1,160,90,254,21,88,43,220,101,222,156,214,211,98,172,42,254,193,103,147,61,229,181,85,228,223,127,163,201,157,106,97,82,251,201,89,32,245,234,92,103,151,70,111,44,210,74,166,88,95,204,82,185,9,218,72,146,27,181,139,97,122,22,228,206,84,237,87,140,101,100,110,216,186,226,110,186,109,140,162,59,52,3,26,96,176,41,84,66,47,216,100,110,106,2,55,106,165,232,43,156,42,193,122,42,74,224,96,101,41,240,141,4,88,29,113,31,121,80,196,152,15,234,154,70,129,228,97,137,99,89,108,64,143,32,111,199,220,209,192,20,24,80,192,202,191,169,156,133,210,36,179,17,149,67,213,52,180,176,134,253,181,179,174,87,217,236,254,162,137,201,192,88,23,89,195,231,73,182,226,224,149,99,172,221,135,5,241,132,86,236,118,69,50,108,27,103,65,17,127,75,11,160,71,85,227,148,153,62,103,83,250,192,254,215,123,252,157,8,112,132,210,193,21,244,168,131,44,69,226,190,243,10,225,163,84,190,118,32,19,193,234,220,32,188,74,90,197,143,70,191,99,113,186,143,49,131,109,253,62,234,221,183,103,238,89,65,67,11,230,9,222,24,95,129,14,228,125,126,166,49,29,239,36,39,124,130,203,200,105,29,231,182,43,1,179,193,103,230,251,205,22,182,65,191,137,110,165,113,180,60,209,87,212,7,69,241,130,157,125,59,225,89,244,120,134,142,170,92,19,65,251,87,163,83,32,185,163,202,187,191,34,192,183,186,236,30,222,225,180,237,142,162,77,93,190,100,248,70,134,164,253,105,255,142,189,83,50,161,225,223,241,240,252,170,90,122,221,22,108,187,81,31,252,76,218,238,217,175,90,110,37,190,8,65,147,181,160,202,39,24,230,218,92,233,102,123,98,72,215,163,152,111,198,25,215,60,213,1,254,4,168,45,13,40,238,142,158,60,70,241,144,183,215,236,146,149,13,234,215,133,3,112,135,7,8,40,195,214,105,244,172,246,200,198,238,153,112,100,59,137,18,122,9,204,17,41,181,111,41,61,21,160,16,170,194,218,178,62,88,92,199,233,200,24,70,246,142,224,164,200,210,237,216,75,100,45,115,160,117,92,38,226,170,215,156,203,215,210,248,231,199,216,248,161,125,167,132,103,180,186,9,249,4,154,16,237,107,80,28,27,235,150,39,210,201,153,66,17,97,165,29,15,167,130,23,77,17,106,160,90,248,47,219,164,20,127,81,248,1,36,254,22,50,208,65,145,45,220,160,93,16,45,62,229,177,187,144,167,142,26,248,232,6,191,77,59,136,49,2,33,116,66,65,146,218,44,111,73,2,222,99,111,24,180,41,67,103,39,216,168,240,207,142,34,241,86,17,173,37,58,64,186,213,98,181,151,159,141,26,22,31,45,92,64,9,10,26,76,181,236,145,18,8,30,219,158,183,71,138,134,56,65,70,34,140,141,13,54,245,29,155,227,200,183,113,40,113,203,86,214,2,162,90,237,5,247,2,186,149,205,73,75,106,255,178,8,39,126,21,96,43,117,216,10,81,98,244,208,25,252,177,189,21,50,204,13,115,42,29,115,2,10,234,207,168,29,131,228,241,82,183,158,85,177,161,142,249,81,208,74,7,73,61,160,142,153,121,63,78,230,152,77,38,100,58,119,15,102,23,145,201,189,165,77,147,230,208,2,84,68,22,86,13,32,68,58,88,73,8,48,139,117,27,222,40,32,182,33,168,89,188,113,162,162,146,225,102,118,158,53,22,82,149,184,240,92,212,243,40,50,170,149,147,223,104,185,45,162,20,59,162,173,157,5,224,233,8,159,219,28,215,102,178,59,121,254,199,162,199,99,2,69,53,6,16,218,9,6,241,44,220,188,45,208,250,244,235,250,209,70,110,222,198,183,219,47,135,143,170,11,226,178,201,194,8,0,115,63,105,158,9,227,172,16,176,218,211,18,70,236,5,109,35,119,143,218,145,213,190,153,247,240,232,191,61,9,58,130,175,235,45,122,195,207,43,194,102,133,91,46,230,18,78,212,122,114,168,4,94,120,96,72,18,12,142,191,141,105,202,78,241,114,85,34,238,84,11,10,254,50,188,122,76,216,117,121,110,3,95,91,62,253,60,174,139,195,120,183,220,61,229,75,22,220,190,134,216,68,90,111,184,152,40,130,43,39,76,144,94,215,83,252,62,127,27,6,175,158,50,87,41,85,95,32,24,14,193,22,92,54,156,254,77,61,50,7,243,25,48,156,89,56,17,33,107,135,110,160,52,80,216,55,217,98,40,102,1,34,70,233,200,205,172,234,156,17,180,123,113,143,67,81,224,51,149,12,213,251,3,2,63,30,249,181,254,120,160,155,133,96,137,181,35,5,182,121,214,39,128,129,237,203,19,137,24,93,101,255,228,209,34,58,241,253,187,131,60,8,241,178,36,11,26,109,21,150,214,31,242,19,60,118,147,158,111,23,164,168,73,67,92,231,211,6,86,222,242,248,107,142,231,119,143,1,168,27,187,91,70,38,230,162,216,232,152,83,71,41,183,182,189,94,221,128,7,217,182,42,49,232,20,23,3,87,95,213,181,137,117,14,161,52,243,122,183,193,90,134,182,58,222,179,72,150,241,129,197,216,227,156,20,75,90,202,71,128,15,137,242,183,117,188,168,252,39,243,76,167,222,12,190,250,197,206,164,145,191,47,206,24,20,40,253,36,4,220,72,143,199,19,105,30,48,219,215,196,37,15,182,38,220,134,239,35,187,29,230,68,215,139,220,215,90,25,184,246,196,149,239,249,142,248,63,141,205,161,28,87,142,170,237,214,67,142,251,97,163,163,242,208,139,28,201,5,249,160,111,232,64,231,207,201,197,196,206,92,127,71,17,57,48,200,25,226,176,113,210,162,108,233,45,224,15,40,196,161,187,228,55,88,74,235,30,68,12,209,70,87,243,159,85,208,70,192,75,111,14,15,239,6,234,134,248,30,113,51,255,128,43,104,82,6,158,241,74,19,174,199,229,132,238,6,70,145,96,242,208,185,17,12,251,210,13,113,233,186,188,29,9,195,244,71,62,26,195,82,44,209,10,230,93,188,92,234,241,145,115,67,77,67,44,210,249,228,5,84,43,160,77,103,214,59,87,195,200,20,129,254,173,229,229,37,115,254,49,72,119,145,188,255,12,95,191,110,239,124,12,213,234,217,4,211,133,39,184,242,103,223,13,5,50,56,74,214,135,66,130,62,223,167,91,175,30,40,134,82,42,167,175,169,33,40,205,88,123,104,96,189,142,226,130,73,0,60,121,128,225,203,146,1,170,4,93,235,72,243,97,77,129,92,246,173,53,161,138,204,83,70,234,80,223,20,176,62,149,150,127,141,182,196,163,80,117,13,31,248,64,166,35,112,96,44,221,70,128,124,229,74,60,65,83,15,20,135,165,184,82,153,163,153,145,137,168,21,68,140,120,76,239,1,57,32,133,38,158,157,114,92,79,139,129,100,233,109,73,206,6,164,101,18,250,41,214,14,185,87,241,153,142,116,3,55,77,138,149,123,112,38,59,191,132,156,136,205,108,175,236,117,66,107,36,241,192,147,149,227,116,253,26,209,34,134,94,214,68,212,25,142,117,207,151,32,13,101,187,154,38,54,165,162,58,254,142,54,86,89,13,232,46,36,31,67,169,250,183,168,205,55,163,165,77,37,211,28,12,51,80,99,47,117,190,69,215,83,246,24,48,152,252,50,167,183,242,94,21,63,211,171,23,199,4,160,172,57,57,92,128,50,52,174,87,77,255,17,221,149,165,195,162,43,38,226,27,221,101,124,188,82,226,222,49,132,246,31,27,81,255,205,69,176,163,195,253,83,47,80,99,157,132,223,160,92,39,120,73,149,51,171,255,67,218,107,160,220,58,236,28,119,180,1,82,24,146,160,44,200,70,141,109,254,12,126,229,95,99,96,3,216,221,136,205,113,142,122,186,243,183,255,22,253,97,176,39,222,179,209,180,233,133,72,37,54,158,28,65,95,13,1,59,153,193,87,230,128,104,160,201,205,2,196,6,125,232,155,188,65,83,240,126,145,178,63,143,0,240,193,78,184,2,226,82,240,49,22,50,167,206,196,168,121,68,212,156,249,154,95,24,93,83,113,168,33,14,246,208,135,139,78,122,101,123,8,177,97,182,122,128,106,140,8,192,100,143,88,196,50,29,207,215,143,65,120,133,133,118,94,128,12,106,130,195,165,203,112,192,173,166,222,59,23,34,6,82,131,16,84,214,205,87,208,140,201,182,166,221,131,122,181,85,150,65,139,133,103,23,179,159,231,7,175,204,95,130,131,126,45,155,135,76,69,145,54,197,251,173,9,206,46,189,122,101,178,24,17,52,231,121,151,60,255,66,47,5,0,134,235,185,232,129,137,35,158,3,110,230,211,73,61,209,224,71,153,55,248,61,100,233,170,140,66,27,177,253,40,208,209,143,4,27,108,105,166,136,60,8,218,119,168,182,107,8,119,5,118,31,219,43,94,70,182,91,68,254,135,245,212,250,26,105,156,109,180,133,177,249,140,89,130,79,55,31,123,18,154,42,191,139,9,240,237,151,107,173,188,134,243,132,118,79,249,197,52,29,174,60,127,48,203,213,101,118,178,117,92,200,49,217,119,172,213,150,231,103,134,168,200,159,174,105,85,8,72,53,243,196,179,102,171,173,207,190,134,186,250,180,231,155,193,203,81,248,175,8,196,145,73,186,178,63,177,60,238,12,42,169,79,173,245,76,171,131,19,102,237,156,201,116,42,209,167,158,198,227,114,197,227,182,212,229,151,110,140,149,239,82,124,137,145,167,26,54,159,102,237,132,139,121,181,115,78,145,179,231,40,243,114,107,190,126,230,152,86,21,43,130,126,87,172,107,120,215,174,119,95,238,138,107,162,109,30,0,156,48,191,59,137,171,39,151,249,219,16,202,29,186,7,225,198,202,213,119,26,30,46,66,61,154,127,212,160,121,30,139,137,77,16,197,1,225,23,181,190,52,124,88,224,250,45,111,131,115,99,26,188,227,244,207,13,101,230,130,96,187,90,109,141,203,246,150,213,238,2,180,162,199,113,129,255,97,7,65,101,37,145,166,70,193,39,68,86,45,6,162,80,189,182,147,237,204,108,173,114,12,139,6,79,110,178,50,39,17,113,41,178,217,61,88,132,240,93,181,152,170,7,71,170,146,115,177,209,87,215,16,157,38,76,45,46,220,16,103,58,125,32,153,241,187,154,232,13,56,84,165,56,94,8,6,118,36,14,96,65,93,68,50,208,97,85,185,103,1,161,83,67,194,38,128,76,181,204,102,151,40,72,219,119,58,243,206,0,99,50,157,241,110,31,75,39,89,181,28,80,34,47,54,40,145,0,60,100,212,148,16,35,19,189,130,103,237,1,19,109,241,72,134,148,103,72,23,209,106,186,211,41,196,18,76,23,75,122,68,251,50,11,252,232,52,72,57,5,52,226,217,252,184,71,71,112,106,214,93,60,250,235,235,115,148,64,183,222,82,158,135,135,145,153,54,138,126,116,216,66,235,51,100,7,1,111,11,231,57,153,174,195,76,173,195,2,137,227,217,61,109,233,31,68,5,179,235,72,80,16,191,118,37,76,119,131,246,39,251,58,127,172,229,32,135,167,216,216,39,54,7,180,45,236,44,47,186,218,5,45,145,201,222,24,126,214,198,237,218,245,74,159,119,201,233,27,224,213,175,46,43,252,104,209,254,53,126,25,166,190,157,66,64,23,226,4,74,69,28,42,238,195,233,33,1,64,116,16,110,32,81,97,57,242,250,108,13,200,31,184,115,30,190,65,111,225,197,90,215,174,221,193,216,165,11,16,3,153,141,181,161,223,213,141,64,243,41,33,65,208,245,48,203,171,242,234,120,183,57,60,85,83,188,148,249,94,62,178,164,119,223,137,180,49,184,166,120,134,127,76,230,216,208,161,5,42,237,196,235,114,222,23,134,110,242,244,163,1,42,228,3,251,93,156,48,46,154,200,19,163,205,213,250,142,212,14,156,210,48,20,148,235,204,232,128,21,3,100,38,184,230,249,138,117,207,253,60,79,102,174,115,184,21,102,194,116,47,69,98,110,200,73,248,186,30,220,75,239,155,228,138,141,255,84,179,127,17,124,167,107,102,248,93,59,11,170,167,110,129,228,140,41,111,215,131,169,31,210,192,131,220,50,29,241,34,235,141,60,96,178,83,126,109,14,186,209,248,63,130,108,186,180,105,95,192,234,29,87,8,197,153,103,55,13,10,116,247,40,153,54,84,199,120,69,98,185,228,4,234,107,80,168,240,218,9,114,58,196,150,245,120,244,210,164,160,201,55,20,40,135,138,179,149,228,199,157,192,174,190,79,35,154,208,104,215,44,229,241,125,186,156,42,60,224,60,98,79,40,64,126,207,165,212,10,115,54,25,33,126,58,236,50,194,209,149,85,111,178,89,79,15,60,227,54,174,229,243,135,42,102,50,171,254,95,21,247,31,125,0,215,95,9,254,115,158,204,23,106,103,28,139,202,110,125,119,242,110,213,56,152,116,42,49,235,231,28,252,0,141,119,191,200,51,122,183,74,56,200,99,174,153,239,174,227,16,247,241,53,17,43,147,201,28,236,24,172,158,183,250,239,232,109,178,138,191,154,85,92,101,93,173,175,120,149,115,204,109,250,109,193,172,203,85,254,72,122,109,173,97,223,35,161,59,23,39,177,164,124,186,70,76,36,143,143,79,179,160,167,125,30,112,233,209,141,126,247,37,119,77,159,6,86,22,186,250,64,148,109,116,69,157,161,219,213,126,74,234,55,4,74,150,191,164,59,229,208,73,147,153,74,155,93,93,177,111,177,180,36,107,46,26,222,118,125,41,31,110,95,84,199,96,81,223,99,229,230,111,208,187,44,207,189,197,162,155,118,66,246,102,5,157,180,61,121,27,171,235,38,194,219,47,109,32,238,247,114,130,158,184,151,243,155,87,210,50,16,172,39,124,229,145,237,44,49,206,229,30,118,171,255,129,65,10,175,28,62,65,30,217,20,113,253,179,149,240,28,118,112,140,20,237,39,7,159,242,230,64,144,209,53,33,213,116,176,141,135,111,225,244,248,107,202,235,131,88,130,60,113,17,151,144,193,21,155,78,5,33,221,177,64,101,141,166,1,217,83,16,24,8,33,203,8,73,180,252,201,36,37,193,112,158,81,36,62,12,87,125,150,121,19,39,92,191,173,210,244,36,77,195,88,140,26,156,4,231,27,111,89,251,35,188,185,246,75,176,127,162,75,144,137,255,124,36,161,108,144,154,177,88,19,197,21,51,61,242,175,177,115,118,58,158,40,174,196,158,97,198,184,209,36,126,232,71,189,204,186,7,102,36,124,234,204,89,172,220,192,86,101,51,175,40,9,191,17,115,155,117,200,237,22,138,77,48,250,240,160,224,117,133,170,182,144,213,211,213,2,243,145,65,254,0,2,248,48,33,249,80,119,29,108,76,228,213,3,143,250,23,23,131,183,155,60,55,214,27,114,225,198,150,10,35,148,123,109,118,26,2,65,205,51,165,231,113,146,183,118,99,110,128,192,107,84,128,130,68,16,88,195,165,35,170,219,153,195,92,132,226,34,20,77,81,240,139,150,107,214,77,155,204,106,79,19,168,44,71,198,240,87,142,60,44,60,246,5,116,90,243,72,82,123,206,123,164,157,159,113,100,46,227,97,151,247,172,49,26,253,214,112,110,75,191,20,199,178,121,153,73,146,167,80,165,179,249,104,118,42,76,8,126,200,69,25,1,35,35,219,85,218,235,253,164,63,211,195,178,60,208,120,222,151,167,79,238,35,131,109,53,18,149,50,40,14,206,218,230,111,82,234,124,19,223,6,18,94,196,199,189,219,79,203,3,86,63,184,11,70,220,145,70,39,204,13,70,25,105,99,18,2,0,24,161,197,244,35,162,11,157,34,54,196,92,138,255,30,83,77,170,69,196,207,11,28,60,155,7,88,6,248,72,159,21,242,123,4,244,230,249,74,32,130,186,174,143,2,140,24,130,73,170,186,195,129,0,221,95,213,21,27,147,128,194,103,91,111,210,249,82,200,180,140,107,187,79,132,95,135,105,220,39,219,47,101,130,232,19,153,84,96,21,214,227,184,212,26,88,77,22,173,250,215,51,120,214,55,206,86,220,178,39,170,15,114,12,97,98,239,4,124,47,250,230,133,149,196,82,209,165,151,0,207,30,106,133,62,251,241,196,196,47,179,145,179,2,155,15,5,165,22,67,52,207,39,246,123,134,219,252,174,231,168,82,8,7,192,229,168,45,215,86,100,235,111,169,107,12,249,89,109,86,160,142,181,238,237,223,92,168,130,150,236,224,116,222,45,18,13,13,164,73,38,27,208,24,138,45,80,4,148,58,149,54,128,230,244,22,230,218,179,87,51,104,223,178,9,209,228,14,206,192,249,41,82,34,115,235,125,150,192,196,1,165,252,62,83,243,157,37,218,134,192,149,232,139,145,253,205,51,17,97,192,121,157,60,181,170,126,156,5,44,196,235,223,123,170,2,118,228,255,243,8,132,196,221,30,242,92,159,112,180,131,51,25,126,253,184,7,4,110,34,217,37,185,91,186,44,77,80,104,181,58,171,9,210,180,17,119,8,141,229,247,64,62,232,121,118,112,133,52,173,5,202,94,170,37,212,28,222,193,97,51,164,107,197,181,220,102,52,58,47,147,194,179,174,14,89,19,221,145,39,174,86,249,64,89,192,101,143,207,156,186,210,1,137,143,225,13,38,98,59,92,137,53,31,64,212,100,157,144,100,131,3,65,115,94,185,87,13,25,176,45,184,207,19,250,197,231,86,217,51,191,125,60,11,95,125,105,236,148,166,54,6,42,0,150,180,138,38,30,235,72,106,14,217,69,184,242,46,197,173,38,89,234,41,197,213,165,79,86,118,231,142,207,69,207,108,20,53,179,160,231,84,99,156,253,80,13,15,65,18,73,160,149,31,76,124,141,4,48,207,86,81,87,66,32,121,213,115,116,230,240,201,247,195,159,66,154,244,180,174,14,101,84,3,66,175,40,177,65,194,101,162,234,26,55,222,21,72,164,219,243,129,30,172,104,212,50,6,152,90,233,235,35,221,207,165,225,44,109,74,127,123,173,56,87,209,84,211,48,214,123,5,105,101,78,188,169,175,36,172,214,19,232,125,217,130,252,99,237,244,61,173,193,82,209,216,57,13,12,202,82,193,78,70,69,206,74,240,191,91,25,179,254,242,177,68,23,139,165,101,32,52,246,25,212,240,38,237,147,60,156,190,36,3,56,163,125,228,107,228,6,235,44,250,90,92,77,158,36,217,168,161,77,26,49,125,99,103,191,115,41,120,16,231,243,69,108,169,115,81,127,195,48,164,132,75,173,147,62,148,220,3,189,186,165,200,86,60,18,172,193,207,129,196,167,69,181,134,232,130,109,48,76,133,202,38,184,207,153,39,149,26,4,242,77,59,193,254,102,222,99,68,91,147,245,252,14,111,57,224,121,244,233,148,97,66,37,162,181,44,60,144,184,181,187,204,143,33,120,225,243,226,97,190,168,25,134,240,146,145,251,166,104,183,243,126,93,104,93,84,55,148,49,84,30,71,204,203,236,226,179,113,247,64,213,92,207,126,35,130,231,86,232,149,34,79,127,8,155,120,228,29,247,142,10,151,52,57,180,40,56,93,99,171,253,160,143,201,101,183,204,59,240,23,208,83,198,151,231,231,147,28,110,4,156,102,57,157,18,249,18,50,20,130,56,53,156,41,45,170,41,117,136,179,222,121,239,18,168,166,237,2,237,98,107,148,236,81,60,2,33,181,218,46,71,254,197,234,84,204,80,27,160,118,123,153,37,55,238,240,199,98,227,116,197,126,232,21,255,98,226,206,152,34,211,121,85,69,183,195,225,202,232,188,79,208,206,156,187,96,21,189,252,76,203,227,241,70,211,61,52,217,12,33,243,41,50,152,77,47,82,19,140,197,235,100,59,65,70,115,52,246,95,80,145,224,57,224,221,213,78,145,49,47,117,102,248,205,92,84,18,215,150,191,135,145,62,36,193,200,52,133,187,34,96,149,139,1,97,248,25,51,64,247,58,93,111,15,225,212,223,114,61,92,11,95,154,153,245,208,78,148,39,150,34,40,110,50,154,11,54,4,145,21,134,166,233,0,193,39,105,2,102,29,28,168,238,231,117,248,142,40,50,56,142,240,142,165,151,16,85,30,155,98,225,239,177,187,143,215,228,29,118,98,85,69,167,21,45,116,143,40,42,152,1,87,158,139,169,81,137,18,54,65,178,145,44,82,225,241,84,208,111,202,139,17,95,107,130,255,148,105,65,106,172,230,171,55,197,239,133,168,4,152,247,235,19,138,175,168,216,216,171,23,160,83,71,40,126,234,228,1,76,145,9,132,135,166,202,190,232,233,218,105,184,138,161,252,19,33,132,61,159,183,129,62,37,37,194,79,104,59,218,204,215,82,166,4,190,36,224,43,97,59,71,51,188,214,175,54,18,10,15,153,110,203,218,59,225,113,185,123,75,111,206,104,24,163,254,170,85,40,105,9,229,41,218,37,240,211,103,89,253,97,34,77,188,114,220,132,215,129,26,109,149,186,128,119,108,19,20,122,172,175,10,20,169,9,104,195,150,51,8,159,140,86,232,226,177,7,196,200,167,207,106,126,27,140,222,219,198,149,46,0,13,93,255,121,205,23,206,245,185,247,15,231,173,156,59,156,16,48,118,254,93,148,203,237,189,158,180,101,52,62,155,57,8,175,171,215,67,69,104,60,72,232,226,185,20,206,65,59,42,125,90,124,100,202,134,141,239,191,110,203,164,223,50,232,219,4,222,205,22,70,62,180,75,143,174,228,44,62,245,202,39,117,215,33,145,80,106,131,177,244,66,46,89,167,198,251,80,38,72,190,90,118,85,34,158,83,17,61,132,124,53,24,63,24,90,249,68,131,245,198,183,117,13,157,137,70,189,73,23,75,77,13,25,88,126,217,87,108,92,8,133,154,15,158,112,113,94,186,162,177,9,232,181,162,55,24,38,161,79,176,4,233,11,158,170,242,240,168,77,25,3,223,158,186,182,26,129,84,106,135,108,205,79,254,175,227,1,238,248,79,5,72,169,217,128,158,1,139,110,157,12,39,55,95,3,2,113,179,81,229,38,144,253,35,77,155,97,157,9,47,133,35,238,97,246,176,156,164,3,236,181,42,140,173,1,46,164,218,168,228,127,219,160,224,59,249,247,7,155,98,77,199,215,146,55,151,221,185,163,241,26,122,137,164,190,205,207,4,237,134,165,74,238,223,226,15,248,242,139,107,210,187,234,4,145,23,231,180,229,53,254,166,201,220,10,14,58,33,230,72,92,230,207,170,109,188,229,137,28,147,22,41,192,213,40,215,216,127,14,228,9,13,85,247,106,247,1,155,206,136,4,23,190,148,170,106,194,155,170,96,227,85,168,247,195,20,113,172,17,34,38,123,79,167,110,206,207,53,66,173,162,178,166,84,120,160,160,218,186,227,34,87,100,212,219,28,84,255,59,138,26,28,227,102,205,94,75,152,55,216,163,46,225,96,152,57,32,57,159,27,251,178,201,231,5,139,31,163,136,69,71,125,19,213,46,252,84,88,215,163,249,153,181,25,227,174,4,105,93,98,251,60,164,4,222,26,165,85,83,87,45,206,132,134,6,108,89,96,76,139,144,143,144,116,59,72,48,184,248,230,195,135,167,29,166,42,207,49,87,221,159,42,168,96,157,181,125,152,96,130,72,48,100,105,145,96,98,200,116,7,131,166,69,99,117,55,141,40,125,106,249,33,118,191,121,159,138,79,27,90,132,13,52,0,61,44,246,212,77,127,107,26,124,234,104,26,14,238,68,79,124,247,99,81,60,135,27,62,83,231,104,214,53,69,104,188,95,120,30,105,222,150,218,223,80,221,209,86,113,125,226,123,36,1,136,94,206,253,124,34,218,2,77,208,172,39,238,148,151,111,237,3,135,99,41,22,142,129,39,56,105,255,31,62,12,171,5,206,94,114,13,174,185,89,199,225,131,239,187,92,132,102,86,138,156,36,55,112,65,191,209,70,60,75,110,59,216,180,148,36,118,238,139,97,222,17,236,209,68,163,76,177,206,58,196,113,2,166,47,131,113,199,180,134,23,174,24,119,20,124,144,29,221,9,90,224,188,131,232,13,244,94,200,129,51,27,11,124,24,154,5,91,171,150,238,212,117,175,71,155,110,168,3,236,162,196,193,74,101,6,238,157,132,151,181,88,122,26,84,194,170,253,198,124,142,133,185,66,4,105,5,152,87,209,178,134,243,242,197,214,209,103,53,218,128,193,9,83,231,55,111,29,235,133,45,107,115,71,203,15,1,69,200,105,216,1,163,183,18,222,54,6,56,48,104,228,237,119,166,90,242,184,97,160,218,194,255,151,131,120,180,104,202,167,157,179,147,77,161,34,65,201,171,236,177,175,0,92,134,255,40,217,133,61,187,44,165,109,184,127,37,189,61,62,60,232,182,210,78,123,118,207,185,156,158,77,117,67,26,37,222,174,87,192,241,152,180,170,218,35,86,86,91,87,98,97,192,129,140,194,233,36,79,152,203,136,73,223,63,26,117,190,88,188,60,42,9,45,54,223,198,207,196,237,26,244,60,233,67,132,223,113,147,253,16,126,10,119,41,159,99,237,109,167,23,248,146,7,166,214,75,0,234,202,90,254,26,71,82,240,116,216,96,236,109,46,104,255,134,115,253,155,36,36,129,188,183,140,151,14,153,244,139,244,252,214,160,8,249,226,35,58,185,116,255,126,128,120,235,190,225,169,185,175,255,64,176,56,247,249,7,18,39,92,249,142,98,47,116,247,126,6,66,208,245,253,217,123,160,123,49,99,18,90,47,9,80,207,212,123,18,61,155,193,44,242,205,146,4,96,210,222,194,220,47,172,241,165,29,155,45,163,105,121,174,115,233,211,216,182,136,24,90,234,77,214,70,94,160,35,59,16,39,71,24,186,43,251,99,53,11,47,60,159,24,144,250,41,114,90,26,97,209,154,96,63,178,67,28,211,107,179,90,253,127,165,163,26,175,163,165,60,47,25,151,210,245,25,91,122,31,176,184,179,128,161,75,71,166,119,40,19,58,101,115,237,145,211,239,250,235,224,4,46,64,94,118,213,191,21,42,27,169,75,217,193,182,121,215,57,216,234,245,160,135,78,21,125,113,51,250,39,177,32,227,61,57,182,118,16,212,181,130,153,240,62,148,127,188,127,160,37,3,231,33,68,181,179,95,116,179,14,247,145,214,104,222,71,140,17,161,171,218,105,81,195,25,20,202,235,110,70,90,42,47,194,109,74,85,60,77,65,92,205,106,16,171,147,0,227,16,251,48,224,101,8,46,29,94,50,36,213,78,254,13,7,254,227,219,219,18,45,213,145,136,25,210,42,32,47,62,61,139,31,140,17,210,249,37,178,80,160,59,139,26,250,178,179,208,129,81,82,239,54,209,224,20,156,174,251,26,130,136,28,68,243,28,42,28,17,51,90,6,39,125,11,249,223,165,193,243,148,129,17,210,146,186,89,202,253,59,205,5,52,237,17,181,104,92,54,142,214,177,178,59,214,195,73,72,186,175,17,1,0,220,146,69,144,120,89,133,146,152,239,230,141,237,0,78,250,117,54,179,45,38,167,90,149,136,233,115,8,227,210,205,255,208,177,5,45,173,12,189,122,109,122,136,191,40,176,51,234,201,4,208,42,147,44,56,120,17,43,69,93,97,143,103,130,166,129,101,7,40,85,92,157,218,212,230,114,139,2,233,64,93,127,49,140,232,168,194,0,74,215,40,158,61,12,247,57,151,103,148,42,210,155,139,211,87,19,0,208,70,224,199,34,241,199,70,169,161,135,61,105,233,172,62,114,0,96,15,45,231,45,55,172,39,55,41,225,133,190,138,162,53,142,120,95,183,32,192,36,208,155,102,233,86,61,53,30,206,83,199,125,72,101,207,29,247,104,10,148,18,184,234,165,202,151,116,193,119,185,112,23,192,20,152,65,174,8,254,94,56,95,112,30,175,131,75,160,36,26,226,61,55,97,225,40,77,212,181,0,239,155,198,208,128,240,202,248,190,135,42,46,22,94,11,61,30,199,55,16,98,142,1,63,173,36,147,172,74,152,45,239,201,204,46,115,27,81,227,120,112,155,184,99,79,214,130,147,122,64,139,9,147,208,82,76,15,123,98,5,74,218,198,40,175,162,34,226,243,95,227,126,94,45,242,141,118,9,49,66,13,62,135,201,56,200,96,255,212,204,11,3,243,18,242,108,74,227,62,173,115,180,224,226,248,249,141,136,245,6,158,110,65,8,248,189,225,236,226,84,45,8,72,133,12,176,12,140,172,135,245,88,80,88,0,185,175,79,207,75,134,219,100,194,29,255,125,135,114,8,126,63,172,235,145,65,229,120,37,197,36,66,254,60,122,61,197,192,6,79,197,152,198,219,179,231,14,155,211,69,154,175,209,49,59,91,6,25,138,1,144,199,28,148,67,149,19,37,147,101,173,173,206,196,37,179,47,184,185,251,43,182,74,221,246,66,82,220,131,113,87,197,241,66,226,95,156,93,186,196,250,229,244,248,189,22,207,27,43,104,3,210,183,207,145,95,190,74,251,145,107,71,36,138,225,83,79,207,145,78,210,137,175,90,23,239,94,181,98,41,136,109,211,114,150,87,255,49,149,169,69,132,65,211,140,205,214,29,22,127,210,12,110,19,72,139,152,200,229,246,220,110,222,227,189,5,36,90,254,53,6,237,122,57,142,108,23,90,140,146,218,237,207,124,148,18,43,1,231,98,177,83,35,133,156,57,105,201,222,84,80,168,12,176,33,62,83,81,72,91,127,176,136,94,105,255,254,90,145,155,68,132,45,203,4,81,16,2,218,66,189,227,170,31,12,196,122,121,143,12,99,122,129,195,234,210,79,14,55,209,162,72,6,182,66,57,203,144,165,124,104,28,239,250,145,78,30,73,201,115,103,29,184,58,64,70,85,21,63,220,48,82,120,182,147,193,160,57,159,29,228,110,185,119,116,208,106,226,116,121,81,43,222,244,81,208,45,54,252,92,150,203,97,118,228,145,19,251,135,68,118,217,134,205,225,179,191,233,152,12,91,197,183,100,112,245,155,90,49,164,31,226,11,161,97,101,12,52,104,87,67,185,88,236,186,244,207,7,33,67,86,181,69,233,84,8,132,228,204,119,32,165,140,91,72,140,72,59,85,160,243,119,182,101,202,174,103,225,103,157,66,245,6,239,65,118,228,82,220,95,37,111,101,138,161,191,68,163,207,254,132,5,33,34,56,45,15,145,79,100,40,250,236,235,36,175,245,20,209,154,13,198,149,155,0,80,11,84,80,172,105,217,187,232,7,132,48,231,150,103,105,189,165,83,77,153,247,75,244,46,186,175,219,208,150,199,180,28,58,132,148,105,13,207,113,32,133,101,252,13,167,207,239,200,38,246,25,126,101,156,150,20,134,155,28,193,203,237,91,8,31,34,172,248,160,57,105,219,239,42,133,226,116,81,43,132,235,167,30,68,43,231,221,164,52,182,249,179,61,153,161,159,137,151,189,73,236,246,163,36,98,19,85,248,126,173,105,179,75,212,179,6,192,100,128,153,211,199,108,66,203,86,207,169,95,199,34,119,154,244,10,13,220,112,98,175,183,40,113,55,27,57,116,86,1,170,179,54,173,252,94,178,69,116,19,143,251,130,194,112,136,117,223,38,229,127,85,195,14,156,30,223,71,155,223,129,124,152,171,136,110,120,95,180,53,100,168,25,3,216,42,54,85,46,69,119,107,155,145,251,64,53,185,193,15,13,139,6,167,11,60,47,89,97,48,152,126,89,204,146,71,95,57,111,150,78,240,251,102,115,113,11,147,15,192,253,231,25,248,245,109,134,153,56,58,101,46,144,2,253,31,2,83,198,61,64,121,63,76,80,67,29,12,66,28,147,254,92,69,68,35,212,156,221,161,237,249,146,56,121,137,145,156,246,183,247,139,124,62,163,212,103,229,186,93,174,69,23,160,26,196,181,43,175,176,60,110,211,55,131,146,61,179,46,79,154,194,63,7,77,202,244,150,202,18,92,217,129,241,239,222,111,51,135,13,231,255,23,171,205,2,165,228,225,46,247,213,245,181,190,140,154,241,182,186,251,24,83,159,137,53,64,138,170,164,60,147,27,90,82,193,36,201,173,182,188,108,188,229,45,193,211,18,253,200,185,25,95,180,93,30,219,69,195,239,222,97,161,110,214,36,114,96,168,76,77,164,53,131,226,197,100,0,42,106,159,84,214,55,249,124,216,170,102,155,118,134,77,181,65,115,14,167,123,89,46,212,228,181,29,222,148,86,228,253,74,236,231,197,148,188,137,167,27,127,12,253,186,84,67,146,211,91,131,122,218,230,239,254,175,168,1,213,249,121,7,221,136,146,201,36,166,47,73,221,190,128,205,126,206,89,121,78,233,57,64,136,20,67,198,178,249,191,17,131,33,149,197,130,104,170,130,142,237,246,170,147,192,156,248,187,123,25,225,139,220,171,61,24,24,114,110,77,3,160,244,82,56,94,113,16,27,118,228,217,56,29,253,10,75,145,97,193,150,89,210,52,60,146,17,127,187,216,5,195,108,15,251,39,157,158,86,49,193,199,155,106,6,73,80,247,203,61,88,81,56,93,158,179,40,245,81,68,136,69,32,237,101,122,112,165,100,55,9,127,59,26,9,41,16,102,92,246,179,125,108,231,225,63,120,88,135,69,195,239,197,51,245,72,72,59,15,231,42,3,184,123,64,176,64,2,15,246,220,67,193,252,8,159,56,20,44,137,45,172,109,183,204,159,101,6,17,221,228,44,160,69,242,153,202,128,203,12,4,126,92,35,50,234,50,118,36,235,41,31,25,142,113,24,62,9,95,20,19,50,125,158,204,53,186,86,53,189,102,153,228,219,22,2,99,14,143,147,221,199,23,113,107,196,224,225,104,121,99,34,19,112,121,28,191,160,245,10,17,84,184,88,225,151,167,54,240,195,72,254,120,18,22,155,131,146,29,227,234,30,101,250,135,69,125,243,191,220,108,252,27,73,15,229,136,53,207,18,173,204,19,205,199,182,167,225,33,249,143,99,91,17,55,149,227,252,128,238,114,212,169,242,145,36,176,68,219,87,139,157,11,63,61,59,211,206,153,189,127,223,109,58,97,39,141,146,29,253,92,94,80,25,18,106,154,118,230,19,134,225,160,83,60,150,40,14,114,137,33,215,197,110,48,190,240,56,91,138,248,129,37,247,39,83,175,2,103,194,229,110,102,216,12,120,6,3,226,163,55,78,249,252,111,226,91,6,137,148,130,47,48,247,229,23,243,182,71,150,137,124,20,124,66,139,32,193,148,161,185,236,79,174,99,200,112,53,55,117,29,34,237,204,153,30,100,212,1,178,63,101,108,21,60,226,164,189,178,191,164,14,130,253,211,82,162,209,199,23,248,243,208,248,249,158,141,215,199,86,0,246,74,146,131,115,160,41,65,31,203,224,248,194,77,33,67,47,171,200,140,46,76,21,188,172,177,183,243,246,224,185,32,56,122,180,233,201,25,233,15,85,45,133,25,16,136,35,136,145,142,15,86,80,133,48,119,224,178,65,40,193,213,90,108,89,160,56,151,217,217,57,103,175,63,242,81,89,154,80,29,72,39,62,162,124,64,207,184,236,170,24,70,121,44,61,235,14,3,108,68,201,57,178,69,188,58,91,211,235,251,154,69,34,123,86,213,66,253,253,216,176,67,99,197,91,185,250,198,244,215,134,106,130,27,155,101,61,23,181,173,83,247,184,185,24,221,87,94,129,150,24,83,250,180,99,14,23,157,95,133,189,98,219,252,120,118,181,213,41,131,138,220,245,32,75,155,209,55,31,197,21,188,175,14,108,96,144,219,70,87,169,105,80,215,39,54,253,164,135,220,113,179,11,26,86,90,17,173,82,168,51,234,219,159,197,190,211,12,96,163,96,156,21,216,237,81,71,8,238,177,222,65,238,18,207,224,198,6,78,77,58,229,128,113,49,80,53,64,60,188,235,183,243,253,19,186,159,48,179,25,11,199,176,100,249,48,94,85,170,164,215,111,157,248,47,235,115,199,148,241,90,5,156,158,194,36,48,2,128,54,251,107,121,73,162,149,9,148,65,58,167,164,203,170,52,197,196,44,120,167,22,204,41,135,101,200,149,248,38,73,57,71,205,69,158,255,72,185,219,30,199,49,162,53,242,190,45,142,206,11,94,30,40,120,221,10,171,209,31,64,30,69,102,138,222,180,169,4,28,97,34,15,174,50,15,217,31,255,141,56,24,233,173,156,216,252,142,255,94,59,43,223,147,253,34,44,189,10,93,55,252,67,27,40,123,12,243,5,33,140,234,16,240,115,171,26,131,179,201,114,216,135,196,14,204,11,226,91,159,139,238,182,65,152,10,212,173,146,189,31,16,197,251,214,140,176,101,41,217,127,19,65,118,112,116,119,159,28,52,102,175,254,92,132,73,106,70,124,121,229,34,136,208,230,102,14,165,73,4,170,233,83,76,138,148,54,152,21,227,68,40,188,180,162,79,72,48,228,26,205,64,66,33,171,221,163,170,114,114,184,172,219,201,168,200,24,77,52,12,80,226,95,105,205,101,189,221,3,5,202,38,226,148,208,76,126,116,245,120,125,186,56,187,96,82,46,133,211,10,66,86,187,156,137,23,160,98,171,226,232,11,114,200,18,250,211,87,122,21,93,163,90,104,194,160,53,194,74,207,94,195,91,24,76,184,136,174,136,22,245,12,54,167,76,106,249,48,251,40,188,97,95,223,30,22,142,194,231,189,143,57,151,51,105,150,197,223,211,167,34,90,118,91,128,229,236,240,185,96,234,208,26,179,111,122,244,232,80,12,38,10,75,30,38,189,236,165,19,26,106,197,252,71,235,185,204,73,177,213,143,142,148,0,198,150,67,125,250,112,233,80,164,49,60,6,157,40,93,68,163,97,177,11,138,69,11,80,35,151,37,226,112,83,104,68,199,208,112,120,18,122,5,174,225,120,249,246,187,239,139,207,193,43,156,214,226,0,98,218,49,189,224,164,249,146,98,223,125,50,17,156,249,81,199,227,5,93,233,167,93,238,114,241,192,104,44,145,2,60,79,168,0,112,62,78,120,31,150,105,225,33,243,194,10,247,239,80,186,67,248,147,112,190,206,149,49,185,35,4,129,193,254,128,152,100,164,105,79,44,168,54,203,1,129,230,43,92,174,4,56,200,148,20,82,211,212,136,193,83,214,240,81,138,39,11,132,114,55,99,194,4,143,40,233,177,238,255,46,166,183,5,115,190,182,171,253,136,6,248,32,219,26,252,55,109,189,224,176,219,6,131,136,170,148,101,102,58,242,121,97,120,125,146,126,232,251,70,200,193,191,199,169,112,172,43,218,147,205,17,215,99,9,141,194,206,149,104,71,115,45,250,190,121,28,115,88,81,131,250,172,238,160,98,146,119,165,113,166,10,172,34,174,43,44,119,114,32,110,169,188,210,22,181,71,3,8,218,196,202,103,105,234,72,209,168,202,3,206,120,58,52,91,169,202,207,73,67,52,223,246,40,85,129,186,17,147,193,231,46,110,139,178,74,210,186,252,20,42,212,66,107,31,239,184,60,105,247,138,212,29,59,35,147,239,109,123,57,144,11,149,66,71,134,57,20,223,47,197,51,83,184,140,102,217,213,245,43,232,173,139,129,135,141,23,147,64,170,6,101,154,52,47,242,34,140,3,101,199,41,95,122,146,104,251,210,114,60,120,85,93,235,23,132,185,200,46,225,58,185,30,23,139,234,67,231,176,36,70,216,129,111,57,23,74,254,117,89,199,41,209,178,61,214,211,184,105,167,86,249,49,90,42,123,168,58,104,222,200,67,41,108,0,17,167,116,177,110,201,116,233,182,36,97,100,6,194,14,109,98,123,229,192,135,60,139,212,178,229,24,178,75,57,129,64,124,38,73,23,182,0,233,69,40,62,242,69,133,151,96,88,46,115,166,144,227,171,12,67,150,150,224,205,128,11,68,98,7,65,199,98,217,18,163,103,246,75,237,111,191,192,188,237,204,240,118,109,98,193,54,170,132,185,37,96,110,213,152,18,190,35,50,82,137,93,149,215,225,221,42,90,5,238,158,171,51,61,216,167,102,11,175,66,32,95,200,136,58,38,185,31,31,7,154,137,77,199,135,129,68,11,138,218,56,51,63,138,232,178,118,35,168,128,222,75,254,4,133,240,20,138,225,42,242,179,147,238,252,236,171,207,216,158,161,187,121,28,211,191,97,168,90,83,211,109,149,65,124,180,9,172,11,247,233,144,178,35,236,201,59,110,14,121,70,14,224,61,254,78,212,28,174,65,117,240,197,140,63,81,231,180,236,142,119,35,45,55,146,227,92,243,89,103,227,113,113,7,241,196,218,216,222,133,210,176,201,227,29,129,190,164,242,224,9,230,82,122,179,114,75,246,39,15,229,149,39,223,54,20,209,236,251,52,201,186,78,73,37,151,126,3,228,78,186,96,42,131,8,164,251,31,66,192,181,12,97,55,186,77,32,219,199,151,33,3,42,85,29,142,29,6,107,115,68,114,214,114,140,199,143,20,245,129,9,78,83,246,169,65,41,122,99,69,204,115,173,8,254,95,66,163,162,48,175,244,113,209,100,147,112,188,220,233,113,5,212,201,138,91,38,191,72,7,99,178,116,234,92,48,244,0,211,154,27,247,206,232,89,85,99,233,132,72,85,200,139,238,153,179,24,123,99,134,246,142,188,239,9,157,112,162,234,185,118,245,59,130,224,204,31,163,171,38,159,221,225,99,216,177,58,35,104,109,10,125,89,23,53,56,37,68,165,189,60,83,249,63,161,240,70,141,1,210,143,125,157,56,227,11,24,55,38,168,16,119,213,155,223,143,131,175,37,234,125,238,16,194,101,201,158,4,110,18,210,221,84,87,14,13,169,250,241,240,1,12,205,98,246,198,75,250,239,249,104,97,127,57,19,15,104,126,28,59,196,119,32,32,82,17,212,81,175,226,118,175,241,105,177,135,71,82,187,16,240,159,71,37,41,230,115,64,156,184,169,24,234,219,0,246,117,253,167,73,143,69,3,130,245,116,43,177,166,154,119,212,153,47,46,26,192,155,252,200,241,110,201,195,252,231,181,147,45,221,62,85,89,150,72,79,230,174,245,52,49,209,202,184,143,160,9,190,63,249,33,193,163,53,123,237,31,46,225,42,225,49,158,14,120,71,133,247,37,52,27,195,168,0,173,254,175,48,203,127,136,142,20,140,58,102,224,52,13,72,195,143,146,84,91,160,228,92,126,63,39,81,150,207,232,13,28,22,22,113,169,45,140,23,5,46,155,127,197,116,25,54,226,104,89,169,95,100,83,211,41,119,115,107,60,190,170,12,213,173,189,220,228,10,211,105,116,245,166,208,229,181,165,201,68,170,57,36,97,78,110,76,75,65,230,77,138,17,146,196,148,196,16,237,121,105,24,158,75,121,236,185,205,129,31,100,68,181,179,248,183,65,29,74,96,126,223,176,27,19,62,148,147,12,48,70,173,22,7,123,162,216,137,16,123,171,81,196,100,84,138,92,119,3,209,28,49,46,184,35,78,201,26,213,233,176,139,204,161,161,100,134,151,46,27,220,236,243,154,104,171,179,29,24,244,219,213,4,109,217,17,167,110,219,11,225,255,47,80,164,122,91,85,104,133,179,78,39,122,132,12,176,53,220,175,184,93,42,5,93,129,217,176,225,1,179,77,53,121,239,203,231,143,218,94,107,129,31,11,195,254,148,78,105,60,149,153,223,20,120,153,7,211,141,71,154,236,170,254,85,202,104,196,108,18,145,215,252,129,244,163,252,137,151,112,146,157,1,59,187,240,13,15,2,216,118,65,35,126,38,27,221,174,235,245,160,106,120,196,95,105,214,48,54,136,226,74,65,88,37,3,224,245,60,140,2,150,249,134,212,251,59,123,169,14,76,79,118,67,227,62,202,182,40,50,114,7,24,44,54,254,33,251,230,193,198,191,167,178,228,71,214,100,187,93,9,99,58,230,102,178,170,160,39,178,130,14,57,7,70,171,249,174,14,35,35,120,237,233,152,182,162,97,118,134,142,150,24,7,159,154,144,20,178,175,155,125,114,58,253,140,118,189,3,236,201,17,137,170,158,6,138,214,209,52,137,203,102,157,11,99,113,92,97,55,117,153,111,20,219,251,13,105,77,46,143,89,53,195,147,116,53,124,195,182,95,154,49,226,94,206,124,56,128,210,109,131,196,167,229,110,5,138,241,184,84,170,48,209,20,77,49,194,144,208,224,23,8,82,52,152,83,235,136,168,48,59,7,125,42,229,139,89,170,227,83,9,67,233,174,188,101,17,74,229,208,35,149,23,105,183,73,116,1,80,193,46,164,25,242,129,1,17,88,87,87,94,55,96,126,151,60,35,202,219,9,3,222,161,131,34,149,198,202,198,131,167,91,75,106,85,22,230,193,8,201,156,81,226,164,111,44,147,161,162,209,240,123,26,148,30,161,104,16,29,236,170,204,149,74,126,34,109,24,139,125,1,32,228,137,89,30,201,147,146,189,177,123,185,72,228,107,91,49,121,163,27,243,72,155,29,183,58,67,212,196,210,201,58,31,102,67,158,141,70,175,80,213,3,99,198,124,34,110,94,209,77,20,85,45,162,82,18,61,189,203,199,56,131,228,230,7,53,226,247,217,35,66,115,37,68,130,210,200,156,186,44,33,11,229,31,84,159,92,194,52,14,158,187,179,106,80,194,179,80,226,202,110,147,204,167,44,63,158,49,55,80,115,164,46,156,244,58,137,134,55,253,220,75,9,103,136,249,242,3,215,220,53,123,17,75,112,40,131,105,76,0,16,17,245,242,195,47,165,106,200,206,26,130,189,65,203,2,99,181,5,143,191,100,128,52,249,154,169,127,159,85,163,175,105,201,79,170,124,33,172,15,229,166,146,194,104,108,129,91,132,33,195,224,4,116,61,113,89,52,79,251,121,2,32,71,98,121,115,214,245,87,160,16,97,250,177,149,55,39,223,212,203,76,231,248,127,176,129,187,75,9,209,101,237,148,65,111,200,193,164,44,66,237,159,220,85,84,91,89,208,128,237,151,180,31,151,237,151,16,114,221,155,43,42,4,83,34,238,79,149,66,231,157,222,132,11,145,104,170,56,236,84,248,183,36,85,4,10,143,170,141,177,87,7,163,114,225,72,248,238,122,146,203,203,157,4,155,198,245,193,60,218,180,175,34,89,80,195,35,71,85,234,238,86,77,49,244,128,157,230,211,30,114,38,88,35,242,190,254,27,132,194,18,236,121,228,133,95,97,44,236,154,28,64,235,14,62,141,6,104,2,239,196,0,239,190,200,189,55,225,88,118,166,28,3,155,39,73,135,166,250,86,28,103,243,78,21,135,177,206,135,183,141,13,148,181,253,155,176,98,53,113,191,110,156,23,111,210,0,12,145,6,255,146,80,247,0,74,171,33,213,96,90,118,193,89,208,79,47,247,61,246,11,199,235,65,231,27,63,41,110,254,129,80,132,0,167,84,59,171,175,164,131,185,207,179,36,207,187,236,180,205,188,150,112,119,170,82,180,155,78,6,33,163,196,74,97,85,204,95,48,248,81,22,74,219,228,3,163,28,111,155,134,69,37,9,187,242,25,75,186,8,17,151,196,130,59,118,14,82,207,194,129,82,65,199,147,72,96,117,243,22,125,145,219,206,184,153,41,144,219,98,96,155,34,94,181,44,163,237,168,33,89,151,218,192,247,57,198,126,236,197,141,63,109,159,157,29,83,185,46,181,8,73,42,95,252,161,116,224,219,172,169,119,219,52,46,170,69,178,172,93,174,0,45,81,139,114,181,102,240,100,159,66,137,156,200,175,244,173,51,117,206,244,24,77,6,23,82,12,37,118,160,225,85,183,69,79,100,126,129,93,155,18,95,145,39,32,118,241,90,236,152,14,20,126,31,234,84,34,120,172,90,243,50,162,34,238,83,91,24,255,99,225,240,27,114,166,100,243,207,98,170,111,107,224,19,79,177,203,231,135,126,205,13,231,108,153,215,16,143,6,18,244,71,18,188,143,224,169,189,54,129,185,202,121,10,142,246,219,251,81,92,184,115,207,55,223,23,9,172,6,80,2,236,96,4,51,62,54,135,46,10,0,229,235,188,235,218,127,115,177,136,157,40,2,71,146,32,245,200,137,190,179,220,117,208,242,197,14,183,79,124,35,171,203,89,139,208,30,50,32,249,148,242,236,98,48,88,255,143,25,1,235,159,210,127,229,219,6,20,19,41,23,220,116,32,214,217,7,197,244,101,247,93,18,117,151,140,84,68,104,42,232,36,226,57,55,57,181,128,52,6,203,130,54,199,103,197,158,184,138,127,61,223,65,111,57,25,181,72,139,155,65,139,48,15,128,95,194,241,163,12,246,39,191,53,212,114,194,90,65,109,13,121,48,171,160,68,35,192,251,149,193,182,207,178,158,107,32,192,59,214,166,145,205,76,194,17,236,248,105,195,184,201,91,214,106,71,163,206,253,189,15,166,160,158,55,182,108,213,82,244,47,221,194,227,48,139,93,104,165,186,46,214,47,63,142,36,158,192,116,253,133,77,50,45,85,208,33,203,120,156,6,55,217,53,210,131,30,194,170,65,32,80,32,81,218,104,125,77,236,131,42,23,51,41,208,230,40,175,127,201,126,254,209,89,221,187,181,101,185,235,139,217,248,49,187,232,192,124,28,52,88,70,236,155,38,60,43,157,178,180,45,203,113,4,9,67,86,60,136,52,5,61,152,126,254,205,152,68,61,64,58,226,75,218,19,204,177,16,138,148,243,180,234,110,6,134,194,139,167,50,151,95,62,160,137,209,208,255,81,199,177,240,114,1,163,160,235,235,172,203,57,245,240,94,121,56,11,132,16,23,152,180,38,90,26,107,103,77,223,70,133,160,220,55,161,159,238,135,127,195,39,208,86,53,94,195,241,255,207,90,238,9,252,64,51,154,107,238,114,42,193,58,242,19,108,172,209,86,71,42,197,80,100,152,114,254,57,174,37,64,50,36,160,251,173,106,84,18,16,170,209,101,166,151,240,142,96,134,97,50,207,93,244,231,22,49,72,181,188,188,85,53,41,160,158,84,157,23,30,169,226,115,33,73,115,107,143,0,226,138,147,191,74,190,144,231,29,158,45,154,232,182,228,53,105,112,118,75,176,179,123,111,233,14,139,90,157,138,223,14,191,88,106,91,191,149,119,119,125,12,238,211,244,188,43,214,146,153,165,147,172,221,81,131,160,19,124,234,236,188,144,176,73,96,127,208,169,247,17,186,160,163,61,186,59,233,72,217,58,90,43,43,23,250,105,188,236,66,19,98,125,250,90,130,162,167,174,46,218,37,184,26,92,237,34,0,26,104,74,167,221,23,105,113,9,187,125,231,185,93,92,121,93,23,185,54,19,90,235,249,3,121,58,43,88,53,140,51,45,206,210,228,223,67,147,216,82,11,167,178,164,218,132,152,116,134,84,112,15,165,106,15,116,46,222,118,186,76,133,157,255,99,27,35,96,230,14,223,36,164,244,30,234,71,169,225,124,239,103,239,185,44,71,223,241,177,16,211,173,64,220,127,244,65,244,249,195,214,90,121,43,248,177,241,128,96,74,224,104,16,53,79,225,14,219,175,78,129,103,35,184,131,156,66,49,75,196,237,145,109,124,157,74,188,157,84,32,153,170,210,235,165,6,155,60,118,114,50,169,40,37,1,220,122,220,107,20,39,19,238,244,128,227,140,103,0,179,250,11,140,38,165,57,63,111,193,84,165,175,223,21,24,232,153,190,211,114,99,96,103,146,32,24,107,66,117,93,27,243,49,114,246,219,30,34,20,17,69,183,243,131,101,22,123,146,89,58,14,130,29,141,36,211,54,162,164,189,208,207,2,157,64,29,178,133,166,206,71,226,123,104,195,207,127,14,140,247,187,212,124,199,222,83,46,134,206,111,75,190,63,73,82,47,139,200,197,11,130,44,168,239,104,124,162,31,115,106,15,77,72,8,188,215,102,185,145,177,146,105,215,243,128,236,120,202,35,200,18,3,56,41,51,228,233,136,75,253,209,15,226,133,173,67,184,30,89,158,18,91,156,153,18,111,152,178,1,79,85,158,151,216,76,58,134,155,146,49,89,17,51,188,208,128,156,11,43,131,131,106,12,149,63,166,121,16,63,219,137,51,65,222,5,172,189,253,110,113,53,167,226,44,245,31,50,38,174,100,68,22,13,112,212,36,155,239,195,60,53,18,123,223,198,86,22,195,153,183,238,240,84,186,32,5,221,42,82,204,140,146,40,142,221,64,66,150,70,55,47,30,39,14,91,230,39,190,250,204,44,92,192,48,150,46,192,2,42,75,126,145,237,31,191,38,153,131,36,227,179,79,231,201,9,204,104,33,64,247,81,36,153,134,244,72,253,218,167,247,131,248,178,75,238,207,226,79,244,209,92,176,76,70,26,233,159,72,80,240,245,86,236,211,60,129,147,52,202,224,10,121,136,140,72,97,73,10,133,96,120,170,207,50,34,150,192,32,223,232,196,218,17,88,13,218,31,177,119,20,156,206,58,133,152,213,248,174,186,249,107,70,175,113,37,10,115,145,51,107,100,20,219,82,204,77,140,219,219,169,215,58,48,94,235,31,79,145,66,12,48,214,3,229,197,44,184,188,88,27,187,162,100,106,211,186,207,12,7,55,129,174,102,0,79,203,232,178,166,41,96,67,20,205,236,10,17,185,214,114,166,94,180,205,186,114,55,253,184,106,217,46,50,15,196,129,214,56,81,178,117,165,228,136,107,226,194,252,239,232,52,189,121,119,33,227,225,214,234,74,40,173,225,105,36,9,32,65,235,127,209,218,119,230,246,90,85,92,208,117,25,145,241,125,158,150,196,130,194,200,251,49,170,85,124,87,213,239,96,184,96,197,63,244,187,217,215,49,3,224,114,164,10,22,251,65,108,238,13,29,254,18,139,129,219,58,169,151,73,96,64,221,26,16,12,14,12,78,9,203,11,80,73,221,118,103,173,1,169,193,215,109,126,166,137,12,12,135,17,81,209,32,12,131,60,0,153,66,201,121,182,155,39,109,173,1,186,45,253,219,88,63,179,91,22,106,108,66,107,17,105,97,59,6,133,136,82,129,125,190,184,234,131,23,198,146,94,243,204,25,190,50,160,81,176,220,38,215,41,120,112,38,74,163,171,24,106,116,214,231,194,77,99,71,195,47,141,134,111,103,119,122,241,34,5,170,123,150,232,85,63,156,112,76,202,78,176,136,79,161,164,245,223,119,235,27,8,99,121,57,0,225,90,143,129,173,209,102,133,158,64,233,181,113,212,237,35,132,15,88,36,85,226,152,217,11,16,251,213,25,7,85,125,48,155,221,141,133,205,66,237,6,5,241,72,247,133,199,177,78,236,71,27,110,205,207,241,40,22,141,156,101,179,172,227,30,248,161,147,84,177,176,26,32,103,36,110,30,67,137,223,121,255,110,247,94,76,30,149,83,111,96,72,165,93,200,58,207,176,213,13,29,75,187,45,112,179,43,234,213,242,216,43,249,33,207,40,167,96,46,219,167,44,111,57,183,96,243,201,5,215,73,106,130,134,7,142,153,17,97,126,88,35,57,154,246,15,16,48,120,187,131,106,242,11,250,99,54,230,135,88,172,62,208,30,127,145,236,44,247,246,202,229,174,206,139,144,172,167,141,73,106,163,33,202,57,80,76,67,219,18,99,153,119,22,223,8,132,90,173,119,88,241,34,158,228,149,129,248,73,110,153,176,170,26,33,117,151,227,204,107,181,26,21,245,164,236,219,77,199,199,35,205,68,49,148,238,100,242,214,99,155,100,23,181,56,99,13,119,225,107,153,143,182,246,225,208,95,196,75,114,87,98,134,84,115,210,91,16,159,38,83,255,6,141,147,176,178,28,7,98,154,157,117,22,186,222,203,229,195,97,78,111,21,1,209,7,216,220,49,206,103,113,12,92,248,125,213,205,208,125,25,23,255,131,122,18,244,102,110,19,246,57,97,29,160,122,12,249,191,178,249,218,202,196,118,95,227,2,202,72,253,166,224,126,142,247,255,235,17,182,40,239,72,49,69,198,190,146,45,197,143,72,232,60,106,114,24,207,64,199,21,148,63,154,255,94,65,161,221,130,35,137,115,115,180,84,241,144,61,126,156,106,22,242,150,187,185,206,193,114,109,233,188,162,195,80,84,37,148,76,38,233,82,107,55,196,65,244,142,66,169,247,79,119,3,176,143,31,254,163,250,36,254,95,244,199,37,243,80,12,199,218,35,41,133,113,33,14,19,65,68,109,255,12,46,255,36,190,184,245,158,28,243,54,230,255,252,10,28,140,185,137,52,36,177,174,246,253,228,33,46,4,171,48,142,104,247,44,43,68,29,108,218,170,183,172,241,193,73,207,219,37,138,1,150,130,219,251,45,165,77,163,56,41,211,48,28,136,245,232,57,137,129,92,21,128,45,154,238,208,32,231,214,120,74,179,72,201,37,186,206,84,50,7,123,49,12,239,253,65,164,149,178,102,109,53,34,240,96,200,137,6,135,145,49,172,151,73,182,67,200,127,30,211,36,85,185,165,56,97,54,221,209,90,70,22,143,152,129,15,204,59,5,143,171,180,132,244,145,20,44,11,142,181,72,223,151,147,26,241,164,157,222,7,97,79,43,35,103,66,163,25,155,118,174,109,181,98,111,56,136,55,63,81,51,89,250,61,148,153,110,132,172,218,99,18,104,242,83,175,53,197,209,126,182,44,53,73,229,104,21,252,214,227,27,176,170,31,200,156,251,40,253,90,104,145,10,1,175,235,135,77,56,137,11,51,99,233,59,250,122,62,196,2,245,142,86,59,143,192,123,130,214,245,182,157,134,228,82,199,243,29,167,83,105,75,4,236,116,174,50,18,89,242,200,87,109,23,221,184,42,3,82,80,103,135,218,190,7,129,98,180,64,149,196,181,217,136,28,58,56,53,14,16,248,30,82,197,85,149,53,2,112,81,243,53,131,126,174,187,3,237,209,3,20,9,246,22,3,194,201,118,169,89,116,66,199,66,16,175,193,47,238,65,137,126,87,148,144,167,191,216,137,23,120,162,24,80,68,168,161,148,167,6,137,56,1,160,59,75,181,56,92,175,90,233,7,212,173,52,242,167,91,64,194,196,220,18,71,186,221,224,84,47,76,156,55,190,180,102,18,21,27,55,125,249,219,154,48,54,210,58,72,73,154,78,48,73,105,233,200,178,230,208,130,172,18,160,79,130,20,166,83,203,232,203,108,136,211,228,152,192,103,222,8,46,245,50,29,25,234,254,228,47,202,93,242,41,33,139,115,212,186,141,90,222,177,4}; diff --git a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_256spp.cpp b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_256spp.cpp index da6a163b..e48d3ca9 100644 --- a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_256spp.cpp +++ b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_256spp.cpp @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // An Owen-scrambled Sobol sequence of 256 samples of 256 dimensions static const int sobol_256spp_256d[256*256] = {32,226,72,70,57,171,246,75,112,81,109,239,120,101,230,103,103,41,249,86,253,99,132,184,214,147,128,248,17,149,163,17,60,40,169,196,77,79,102,23,250,77,75,151,95,123,234,198,25,26,184,114,230,188,105,18,231,233,175,151,19,174,202,71,84,229,247,148,182,127,92,14,41,112,162,253,35,101,137,30,111,134,95,122,28,2,41,254,181,91,101,188,145,31,166,38,53,193,1,122,99,86,178,36,198,169,113,255,97,221,227,231,29,100,30,141,250,254,16,157,2,220,187,95,181,125,207,187,105,119,156,41,16,194,93,216,227,124,138,90,227,1,88,153,233,69,120,36,19,189,120,4,185,220,185,109,184,96,247,173,210,227,54,3,18,9,139,213,156,57,61,101,37,247,21,201,10,143,11,38,146,18,118,129,95,191,75,207,12,252,238,104,47,39,190,229,31,56,20,127,42,178,100,141,93,222,192,247,186,7,224,161,72,100,87,69,218,44,25,195,185,118,179,123,231,170,96,225,204,52,117,60,3,86,25,143,230,18,11,165,72,188,158,3,66,105,50,200,226,145,227,45,183,62,82,176,191,36,248,191,189,122,96,185,146,166,203,78,144,189,67,174,154,182,86,169,90,236,101,40,71,107,81,93,159,82,75,230,157,191,34,35,235,139,150,193,10,142,217,77,154,249,74,13,196,248,56,154,27,6,242,226,105,94,66,67,145,112,31,145,133,68,21,0,44,212,254,153,183,238,98,102,145,199,100,213,196,52,131,141,216,209,236,122,58,249,188,108,8,206,62,199,207,103,160,247,207,255,101,185,1,113,223,126,182,0,50,93,250,174,194,18,65,111,206,104,156,3,48,195,122,212,10,101,235,200,13,183,173,7,192,3,101,228,84,168,121,241,205,122,115,132,155,242,215,22,236,242,69,35,48,245,3,175,68,57,4,15,226,155,222,140,54,48,80,200,194,149,213,68,225,14,182,122,147,195,69,166,191,17,176,58,222,58,190,70,66,153,196,215,121,123,176,190,161,145,203,121,255,27,207,28,113,22,44,232,46,84,181,131,245,220,27,202,161,38,94,208,39,143,52,5,154,85,121,139,226,223,159,246,170,56,94,209,188,71,205,76,16,233,168,172,200,37,19,123,120,202,28,175,232,88,120,107,157,198,111,253,18,24,36,35,43,169,199,197,137,194,12,238,138,232,17,17,58,115,39,234,4,164,225,215,14,185,232,76,215,171,142,206,206,132,90,31,130,24,0,165,34,91,126,113,64,202,144,114,132,125,58,184,234,211,246,238,168,7,1,172,169,218,67,29,185,66,73,49,222,167,243,189,36,116,23,223,219,200,84,67,94,53,79,26,202,204,91,180,221,166,106,18,207,17,128,137,246,235,162,13,129,130,49,76,104,189,138,55,174,71,152,49,116,204,207,103,198,147,225,142,79,8,172,59,234,225,192,168,181,144,185,6,233,243,61,123,46,55,44,16,228,79,156,235,190,115,61,162,115,182,122,230,138,204,140,86,173,80,99,207,211,181,23,141,152,17,180,35,121,168,67,205,107,74,55,229,234,210,6,94,48,186,210,189,2,200,190,181,227,128,211,225,215,228,74,7,188,195,36,82,10,131,96,99,138,63,1,210,39,134,153,112,72,163,196,55,126,37,125,107,234,166,129,80,61,97,121,20,123,222,3,155,219,62,49,207,87,182,26,214,167,142,89,38,36,112,87,100,56,245,240,152,23,7,237,11,185,206,233,203,131,42,53,35,60,40,211,114,9,13,189,130,196,210,173,39,208,56,110,34,240,65,75,234,76,73,34,39,2,118,174,237,52,194,197,28,155,161,135,180,200,3,89,210,26,154,145,45,57,54,85,26,118,207,212,58,101,69,202,184,36,234,219,155,41,29,80,22,193,175,145,100,50,29,149,166,168,162,213,130,36,25,234,78,84,97,191,139,95,156,9,12,41,97,110,222,8,16,250,161,130,45,111,195,83,213,16,141,154,48,124,175,89,25,27,9,172,242,51,167,76,109,69,107,23,80,23,166,12,16,180,156,182,238,148,249,59,130,75,122,59,134,240,69,220,21,230,47,1,124,66,180,77,247,147,103,66,98,211,96,105,213,127,178,144,102,213,33,247,141,232,67,62,86,230,222,146,68,122,27,147,7,85,69,31,22,67,67,78,13,149,221,57,121,176,133,161,84,201,146,119,196,217,19,132,52,76,135,247,107,29,131,248,220,156,248,29,41,36,202,174,136,253,191,226,91,179,96,69,213,172,0,206,75,192,54,69,120,138,218,171,185,232,211,139,8,31,11,50,119,28,197,83,158,170,229,244,195,190,23,213,87,70,17,102,197,39,59,88,152,234,95,106,29,195,236,114,136,6,159,105,101,2,119,184,47,212,218,188,165,163,138,174,114,71,54,127,64,183,39,51,42,209,202,106,96,215,154,56,33,102,25,62,111,9,49,4,98,142,198,128,138,13,74,95,229,42,164,19,175,179,111,138,19,157,125,94,34,221,103,246,144,141,176,129,201,55,100,23,12,139,33,227,91,223,224,69,120,83,245,50,57,190,21,54,86,245,95,250,34,71,249,100,201,144,16,221,0,40,74,133,38,145,48,217,119,132,34,138,67,161,62,221,126,108,207,140,42,156,13,224,198,142,19,55,85,254,155,140,168,250,58,118,137,42,78,8,48,89,195,167,91,243,246,88,23,22,206,17,190,56,125,171,116,245,129,121,57,144,228,159,197,243,217,239,86,188,152,88,239,112,120,245,119,147,189,25,128,240,72,208,29,162,23,152,24,143,226,136,174,171,58,178,10,5,250,209,239,88,62,34,251,156,163,231,247,102,112,46,48,61,233,24,71,54,73,12,81,195,243,115,138,145,194,164,135,148,51,201,104,74,24,78,107,65,246,118,159,165,130,206,34,157,177,180,10,126,163,167,129,75,0,149,115,172,21,242,139,162,170,92,238,35,46,24,108,101,62,26,147,180,210,227,166,103,149,188,192,92,115,141,161,120,90,231,250,181,130,208,232,151,157,141,208,27,81,82,42,162,244,186,62,163,6,254,94,107,138,123,144,14,216,138,235,104,135,98,77,82,57,47,77,171,213,192,134,69,226,93,197,9,63,181,197,169,22,248,190,55,178,250,167,76,157,101,170,138,94,156,44,12,155,102,133,133,149,43,224,51,130,44,138,3,195,25,161,29,216,1,188,160,73,4,196,125,240,92,88,50,192,176,234,39,109,96,39,60,165,226,80,248,179,232,244,141,102,81,131,110,19,206,225,222,115,198,63,195,251,19,155,77,51,194,251,124,13,77,69,106,112,114,187,126,67,222,81,227,163,80,172,25,70,205,111,48,160,111,165,112,243,47,236,107,81,15,83,95,132,80,133,178,116,87,10,195,139,151,122,44,82,111,24,234,156,187,202,250,20,233,186,204,184,154,149,117,78,205,119,71,166,192,239,88,148,154,229,200,139,163,129,12,155,167,252,50,198,46,106,221,91,235,75,2,14,240,122,62,178,218,42,223,213,6,17,212,242,32,190,96,163,121,63,228,65,111,229,63,70,140,232,221,248,216,80,5,145,12,27,33,195,86,111,42,125,70,44,232,82,209,40,234,168,224,215,215,133,247,128,76,248,178,34,253,61,204,193,105,44,227,66,45,238,159,16,241,67,99,178,235,181,68,204,234,144,58,40,132,125,203,25,204,148,151,253,195,198,81,8,54,248,148,248,58,54,235,82,71,67,181,212,241,43,111,111,202,69,166,200,66,87,245,207,70,112,64,26,240,149,82,86,28,104,17,59,72,154,106,1,173,59,21,204,184,231,15,224,161,253,174,78,249,25,217,35,144,180,57,102,174,57,138,227,125,141,246,16,35,201,173,170,31,107,205,169,59,19,52,209,226,49,136,168,13,238,63,53,78,203,68,18,146,228,165,245,244,84,215,78,230,167,83,239,15,210,34,99,90,184,143,187,50,98,95,182,121,47,53,112,15,53,239,130,105,66,142,11,185,224,203,20,44,156,28,197,195,65,118,36,206,88,55,37,18,112,9,20,231,73,6,11,225,79,180,145,124,204,29,245,148,198,53,210,171,103,53,215,106,111,154,237,107,2,249,79,145,126,255,255,53,222,196,57,237,131,6,63,45,70,68,190,191,12,210,247,162,41,135,184,234,206,153,176,115,255,114,178,110,24,25,66,114,55,29,79,253,67,124,245,37,236,13,88,232,186,18,143,178,59,5,237,10,249,253,37,88,46,134,71,53,74,172,186,69,137,11,154,60,68,120,125,100,91,182,239,177,38,28,125,208,165,38,150,207,244,41,88,127,241,251,168,84,195,111,37,211,165,113,3,212,184,180,207,48,52,204,171,213,128,154,138,218,69,214,154,99,201,203,109,93,71,190,5,99,1,72,173,15,149,49,253,51,82,171,179,114,131,68,114,133,15,104,227,141,109,39,68,225,130,50,51,133,154,148,48,28,230,9,43,157,50,133,203,239,37,160,233,120,54,20,116,57,174,116,158,45,8,196,14,200,80,203,212,233,1,0,88,172,214,196,22,192,224,142,138,146,230,105,100,153,155,112,241,124,26,71,253,143,4,191,50,49,88,226,25,142,141,13,12,50,159,122,211,42,168,23,217,253,218,151,135,3,152,114,102,191,76,186,42,124,70,19,56,25,85,234,58,57,225,230,253,56,194,107,134,142,201,213,43,14,33,242,16,141,205,196,99,143,100,115,5,99,128,100,221,174,110,191,83,165,164,78,60,124,209,199,63,185,120,175,43,3,24,40,153,1,83,147,223,112,72,242,148,166,115,36,138,42,13,63,1,45,173,225,83,121,19,23,208,171,146,240,108,150,3,213,83,210,238,72,120,80,197,2,4,159,197,138,216,19,178,24,173,212,237,169,129,129,102,51,63,203,142,11,134,180,207,105,98,133,253,20,224,6,126,194,167,33,132,90,101,179,113,216,222,132,30,88,23,229,210,85,6,154,226,252,17,39,174,208,255,8,11,252,159,110,195,86,250,59,161,218,31,140,167,41,33,201,143,250,68,82,205,44,4,77,43,214,212,60,82,214,41,44,125,236,152,34,64,133,184,58,145,227,65,70,73,166,49,21,158,242,114,42,75,209,36,72,188,192,146,223,138,76,27,235,115,153,105,169,96,209,231,4,33,105,226,175,187,91,218,12,73,168,214,254,98,208,113,214,116,177,49,34,94,22,127,175,12,155,193,56,187,115,187,240,136,234,206,189,250,115,219,154,17,52,62,198,63,225,81,77,90,127,246,219,192,106,223,78,102,88,142,46,208,156,230,196,67,182,18,112,210,126,198,59,15,234,166,243,77,61,149,24,223,70,245,142,178,199,101,195,190,109,78,244,224,12,84,52,158,184,88,212,155,159,128,187,54,48,209,190,202,157,70,122,109,33,221,124,227,1,196,124,121,163,138,238,25,129,134,83,111,124,60,142,46,143,48,85,63,5,77,46,251,193,209,81,108,149,108,1,47,137,175,85,106,148,27,204,145,104,3,152,84,228,215,113,141,6,117,115,151,206,248,61,43,182,198,76,88,12,222,132,75,73,8,205,190,32,12,159,70,205,4,158,0,107,220,104,90,223,181,80,7,111,166,130,16,168,145,218,242,101,35,165,172,12,217,239,157,76,37,238,176,63,124,243,45,101,181,191,200,64,186,170,42,104,154,191,224,67,145,240,72,82,103,93,108,220,251,36,178,110,145,98,136,83,2,171,177,220,23,98,221,2,160,216,219,237,90,105,255,48,157,136,55,102,122,181,7,225,55,229,254,215,169,94,22,44,65,136,50,190,151,198,54,132,81,245,106,71,91,141,176,162,15,210,33,14,140,108,81,17,135,249,17,44,15,121,28,16,114,178,210,7,129,250,11,239,18,86,203,161,124,2,185,178,83,110,168,3,81,125,80,149,8,67,30,212,0,129,8,77,255,114,243,68,8,119,210,232,104,244,127,165,159,26,176,206,160,228,34,116,10,3,91,65,149,163,43,43,44,171,113,113,223,206,17,63,64,215,216,94,118,5,139,66,201,213,30,120,149,18,236,99,41,81,175,245,1,7,171,209,151,134,28,32,122,201,13,18,46,236,215,113,188,192,221,39,69,117,121,255,119,26,59,142,121,126,238,179,163,183,245,98,199,32,46,39,137,236,232,52,138,4,60,86,83,12,100,44,195,49,107,228,105,56,183,18,177,222,50,189,188,97,197,148,94,99,1,198,221,121,206,54,31,212,145,62,73,77,213,189,38,66,13,139,69,173,57,26,11,176,245,141,166,141,203,10,48,45,201,17,131,241,115,13,165,235,28,129,88,72,36,124,169,128,6,145,10,109,219,198,187,90,149,67,215,68,116,33,56,204,217,236,231,0,205,84,97,113,175,30,185,95,187,166,164,123,103,0,218,18,150,180,103,151,153,146,97,15,161,171,246,252,131,198,186,58,55,210,93,58,157,3,142,220,98,50,202,151,2,115,205,200,3,236,146,210,233,71,222,129,198,18,131,29,157,152,63,201,45,197,253,170,121,124,232,64,197,112,22,208,106,99,54,41,247,146,135,234,142,177,3,38,157,234,222,46,189,233,76,41,150,255,135,82,99,244,246,187,81,215,16,76,188,188,104,156,21,239,255,206,97,35,217,194,13,70,106,106,238,171,232,93,223,145,190,50,39,144,48,13,113,146,151,178,156,18,131,231,168,108,178,224,7,44,122,98,87,166,65,220,174,138,98,95,93,188,127,246,195,136,215,160,201,137,35,217,167,126,219,175,109,180,111,127,222,93,69,133,2,58,198,186,238,108,57,157,101,174,249,26,46,210,254,251,76,43,197,209,161,52,197,28,246,173,229,35,43,13,81,122,34,245,212,223,50,135,69,70,192,171,78,9,135,189,54,168,232,131,250,208,59,227,252,247,231,40,235,203,254,51,25,198,223,165,81,140,141,67,194,180,31,194,172,47,195,56,153,118,221,30,217,17,85,154,184,122,15,130,179,86,8,37,33,200,95,144,73,175,68,185,197,128,182,154,171,147,182,86,172,23,236,20,92,194,110,253,124,133,82,127,206,92,34,108,69,170,47,61,41,87,108,218,3,244,7,124,51,153,83,186,164,116,154,85,123,43,135,177,107,28,189,81,241,214,189,235,233,142,6,109,183,130,75,79,107,99,67,31,164,248,227,114,159,230,115,116,115,252,33,75,4,171,191,217,88,245,156,203,48,239,140,253,211,46,184,136,34,21,248,161,128,156,16,88,64,71,34,174,125,70,164,125,92,205,214,79,157,199,223,143,214,138,213,150,169,17,16,181,95,200,208,91,91,55,125,7,1,39,91,6,103,252,246,22,71,110,149,236,73,1,247,51,2,168,88,124,234,86,100,6,94,1,17,215,157,34,238,126,194,222,109,67,175,96,45,252,99,58,3,34,192,251,95,240,36,188,243,191,229,74,164,55,171,108,239,73,208,140,114,46,244,36,30,33,56,14,209,94,86,28,9,153,30,23,102,165,252,98,77,72,233,22,126,152,98,40,246,35,93,137,114,191,114,200,54,214,8,238,145,43,119,180,186,55,74,170,232,166,247,56,233,9,162,16,241,95,47,5,109,72,125,67,35,130,55,138,75,157,246,85,244,3,230,60,226,159,12,234,155,160,180,119,243,253,179,202,194,53,218,65,208,230,212,71,228,29,49,220,31,146,244,249,84,46,237,203,93,171,73,33,115,46,109,10,163,137,73,18,133,213,236,174,230,216,119,127,80,199,18,100,180,236,191,127,152,158,226,45,72,70,181,106,90,21,229,46,41,109,55,237,81,0,158,169,63,40,22,85,246,181,235,161,180,28,175,136,87,132,184,54,121,185,69,89,58,20,54,81,101,87,37,251,152,4,162,108,113,248,178,219,151,240,144,158,242,185,138,4,34,148,255,250,66,75,144,141,25,248,244,89,180,203,97,141,149,179,129,213,186,64,101,242,119,130,121,108,230,198,74,228,155,96,237,140,201,158,44,127,161,120,219,94,11,95,27,145,80,184,107,215,88,252,32,89,59,97,159,249,183,75,131,180,65,184,179,85,80,88,74,128,53,126,191,54,169,0,133,100,248,196,158,91,121,110,12,248,130,87,248,186,85,136,101,181,0,90,45,34,227,84,17,40,96,221,187,167,131,112,48,70,62,240,138,78,245,248,226,203,255,32,242,246,141,200,17,167,32,151,12,72,159,221,190,56,115,237,233,226,113,71,228,167,60,113,127,28,174,27,176,227,160,77,221,157,64,14,166,82,60,78,7,91,16,214,169,78,222,97,33,229,210,4,255,104,234,42,181,7,177,190,23,40,135,53,67,63,28,151,60,167,81,21,190,110,214,160,222,51,228,87,83,113,220,46,182,163,193,79,214,249,120,197,244,197,169,252,20,33,253,246,46,198,16,208,35,110,5,37,236,172,149,234,155,32,36,8,249,70,224,226,40,16,146,131,224,173,250,111,102,227,160,196,255,167,81,196,62,24,6,39,4,245,139,98,158,201,247,5,6,2,61,92,5,65,70,24,206,135,30,246,146,155,22,29,247,25,112,186,5,208,134,240,95,137,29,48,148,222,92,36,165,248,10,244,222,158,131,46,156,217,243,219,101,123,98,209,124,89,178,16,48,173,142,241,134,127,160,217,64,134,35,244,28,253,59,26,10,212,162,143,252,94,0,198,0,16,156,116,145,64,255,206,234,251,104,250,213,247,171,89,86,125,48,237,216,196,160,45,90,227,12,33,58,31,88,200,117,101,36,105,135,49,134,64,181,233,40,63,100,189,192,13,48,58,159,183,105,34,162,170,166,132,83,141,116,29,39,216,84,29,224,211,54,145,251,248,148,150,203,26,51,179,47,134,175,80,66,223,24,221,52,170,59,241,37,95,232,183,15,162,203,144,221,60,248,8,211,255,78,249,55,59,23,131,11,165,152,182,82,168,71,89,48,249,78,107,182,117,73,21,79,42,128,232,89,103,207,13,224,32,236,175,138,201,54,26,98,122,91,253,144,222,108,171,101,120,208,168,40,29,46,64,23,171,248,115,40,80,28,107,143,65,188,142,205,155,234,86,121,157,124,23,44,177,188,201,222,229,244,169,241,155,62,102,187,15,28,49,168,157,29,135,202,9,160,102,125,112,184,31,209,162,114,13,130,215,93,15,255,110,50,54,19,144,98,47,46,170,252,210,5,161,176,69,185,97,187,253,94,124,215,85,69,73,136,150,68,137,217,52,113,151,241,70,44,102,126,10,143,167,133,81,239,233,109,73,171,141,93,133,112,185,133,103,206,49,208,130,79,127,234,48,173,231,82,200,74,68,194,188,185,26,56,199,134,122,3,153,227,174,245,23,34,49,20,68,184,202,1,232,252,31,171,45,85,7,114,187,66,203,169,98,117,144,15,165,104,143,111,174,100,197,60,7,53,248,238,100,12,162,96,40,189,247,101,64,57,57,14,195,114,229,155,228,32,111,37,141,8,8,163,2,223,6,96,54,144,175,85,141,51,77,41,60,192,113,15,103,101,44,30,102,189,100,251,227,71,37,62,123,4,63,119,25,116,47,205,191,156,1,106,136,248,37,151,162,72,226,41,208,133,69,146,114,137,43,245,90,115,117,90,122,134,180,218,136,10,36,210,53,138,90,139,213,130,56,173,119,174,71,72,213,138,87,171,101,156,110,0,164,38,191,156,215,148,220,106,138,50,237,54,37,49,215,127,45,81,226,61,181,195,147,154,208,170,94,34,8,228,121,71,182,239,63,56,65,244,0,70,162,73,198,63,16,134,216,58,187,203,234,115,44,209,105,127,183,130,74,82,203,219,128,128,162,13,47,106,252,31,56,155,184,119,56,139,70,241,3,104,153,43,183,28,68,241,224,25,154,52,51,131,108,142,150,13,106,43,251,166,76,47,218,150,11,125,109,109,179,145,213,217,241,16,32,208,48,33,217,59,171,245,248,174,34,191,77,111,183,221,49,141,59,221,76,224,103,190,107,171,215,232,44,84,133,236,88,227,175,24,57,144,252,229,182,140,36,219,42,92,101,187,212,188,34,205,167,99,168,91,224,154,187,112,52,190,62,212,191,250,250,68,229,248,142,143,161,185,243,117,222,69,61,162,247,179,140,133,135,164,217,144,222,8,114,20,240,161,44,27,187,82,122,237,53,167,43,2,215,122,219,61,163,54,181,154,176,222,239,12,13,63,88,213,167,98,162,94,254,89,113,112,242,88,158,65,229,215,16,126,234,96,129,34,233,231,85,152,90,16,97,32,90,134,18,131,114,130,148,249,76,135,186,171,103,192,83,45,100,96,36,88,217,197,165,86,194,168,112,149,125,108,133,112,117,199,26,221,35,245,88,233,9,113,47,138,31,61,114,47,51,32,197,55,17,175,164,93,204,223,215,203,221,224,147,103,78,214,230,214,71,214,220,169,117,39,0,147,198,108,242,153,155,144,235,250,162,35,53,61,45,156,227,244,108,123,32,227,129,77,252,146,213,168,197,237,147,123,38,228,75,144,165,144,102,113,198,22,145,14,101,195,177,43,62,151,113,96,81,189,204,180,207,197,24,72,76,135,127,181,246,81,18,167,113,85,184,62,190,140,86,209,148,134,111,32,60,108,33,233,115,99,216,239,112,146,92,217,236,252,213,215,98,122,215,64,175,155,179,121,195,7,207,252,163,51,58,143,187,255,188,122,6,199,73,36,149,218,141,142,43,108,99,2,232,187,65,216,24,169,125,102,148,113,59,233,176,194,207,77,204,245,20,43,145,104,88,88,212,187,237,152,64,18,141,254,53,255,111,53,61,62,49,143,145,197,10,207,36,198,166,88,7,199,42,201,145,219,135,53,239,108,162,82,202,181,4,255,82,23,38,141,213,120,0,218,105,2,141,120,255,138,20,27,255,97,202,151,0,166,227,16,196,48,139,91,164,4,170,177,243,27,154,220,212,167,205,179,84,245,205,50,51,155,45,39,99,124,70,27,48,182,173,3,26,38,214,1,26,23,216,248,214,89,78,142,7,44,2,118,103,73,72,202,187,222,242,74,37,84,166,251,191,67,11,231,116,61,33,17,96,93,116,165,173,88,153,105,123,125,159,243,89,143,66,211,213,23,47,204,192,2,231,229,224,32,30,45,9,31,149,216,137,119,152,34,22,131,206,47,216,201,89,197,58,66,204,67,92,0,150,199,161,213,185,96,252,164,78,46,247,41,134,48,118,14,77,30,250,176,12,138,96,58,51,142,9,249,103,99,29,247,189,31,126,29,86,211,201,108,216,195,90,32,119,124,219,207,128,192,119,91,217,60,215,24,182,244,100,241,153,24,3,99,115,167,33,25,239,186,42,198,202,179,57,117,112,11,208,212,50,26,170,22,148,206,252,232,159,56,64,37,184,40,232,109,62,164,199,64,198,112,56,71,12,215,108,220,20,211,118,70,182,19,212,219,182,104,5,188,255,61,162,241,25,176,78,25,176,239,21,205,246,214,246,86,45,101,158,9,252,149,38,59,72,225,119,121,209,20,85,6,84,253,24,182,126,20,150,105,176,238,54,59,96,46,28,214,21,80,112,19,118,125,115,134,244,30,35,230,238,255,199,220,32,200,9,142,2,182,14,101,191,176,143,96,217,200,124,194,43,105,61,93,143,135,53,12,228,233,30,150,173,228,73,179,184,84,21,117,63,245,231,49,129,29,249,46,23,172,195,94,36,76,227,246,71,159,188,8,88,119,49,177,156,203,88,101,195,170,151,183,106,100,9,246,64,254,1,90,4,9,163,154,231,88,68,182,99,67,75,171,107,142,196,79,237,114,70,178,128,33,83,168,67,129,82,214,135,38,206,41,152,140,168,52,239,28,171,28,29,180,246,185,183,243,85,129,112,168,63,139,133,0,162,86,166,48,132,244,159,151,235,175,64,110,168,85,97,233,11,62,25,177,16,57,124,63,250,59,218,136,209,136,192,23,168,160,206,65,84,30,73,213,235,181,104,66,27,98,126,183,219,93,200,115,84,141,57,55,20,131,91,14,228,85,181,19,4,110,176,90,101,40,91,107,155,7,70,21,114,154,141,146,125,246,64,1,216,213,232,23,143,224,115,244,247,144,186,71,134,69,183,141,25,186,91,29,145,163,250,202,181,57,216,172,131,228,242,181,187,52,94,218,252,4,118,44,52,124,160,37,176,17,218,121,140,191,107,102,91,222,49,91,229,106,179,221,170,200,88,38,138,167,10,48,157,47,99,57,137,88,76,206,141,214,208,48,80,226,18,227,6,175,180,63,107,247,251,197,59,51,247,13,109,209,162,206,192,125,112,94,235,247,26,88,14,126,241,225,249,81,162,7,157,238,150,138,24,69,121,155,219,17,169,180,218,93,230,99,92,139,53,179,145,30,14,205,171,75,247,49,194,3,14,177,24,222,122,30,75,174,121,243,104,233,244,81,4,47,70,43,206,113,229,119,231,49,72,144,78,214,29,193,41,75,14,97,19,84,148,246,3,250,243,7,246,233,153,48,135,226,204,199,93,210,3,97,11,106,117,170,122,92,97,150,179,177,220,46,59,17,151,242,160,233,237,81,78,255,87,243,237,113,135,216,131,97,197,224,41,142,85,234,243,135,58,152,220,191,227,149,78,77,30,82,167,63,217,43,227,106,173,223,128,161,49,70,29,184,169,178,179,124,224,2,243,210,229,112,103,15,29,78,229,91,9,68,198,94,135,241,207,69,183,229,46,78,63,189,93,163,10,91,172,13,205,180,217,216,102,237,239,3,217,247,218,0,147,130,158,175,242,39,94,23,238,221,229,211,72,140,103,207,7,73,10,200,247,155,254,35,165,152,2,137,237,154,128,235,215,210,1,132,104,143,128,91,191,225,241,171,220,16,165,209,59,10,1,128,151,229,116,17,20,188,108,57,196,105,197,5,64,216,75,255,49,10,35,243,39,238,142,201,1,32,8,28,116,21,216,226,89,90,231,210,128,81,149,93,249,111,150,128,11,228,231,236,178,74,34,174,187,230,84,78,197,136,17,197,25,242,154,123,24,78,245,178,254,76,70,182,72,15,115,54,62,10,89,172,129,113,97,148,204,240,100,172,169,122,13,95,182,26,184,25,191,255,250,250,137,18,19,72,145,135,112,125,227,63,65,26,54,228,181,30,158,27,191,9,236,168,115,248,144,187,132,253,45,84,154,196,103,30,149,123,53,42,206,172,146,175,44,203,69,239,45,147,0,121,103,125,132,136,192,38,62,79,29,241,17,151,110,28,38,221,234,230,228,182,64,241,144,165,124,145,120,49,50,129,18,33,242,212,143,68,167,109,134,179,113,176,85,93,87,105,133,15,66,249,8,43,9,147,72,30,6,2,85,185,204,160,20,76,70,119,163,67,200,121,228,185,204,22,48,31,122,177,123,93,159,108,114,65,90,91,67,95,139,6,187,3,78,142,38,96,61,68,23,146,93,32,245,153,131,61,126,1,194,201,158,51,161,172,0,176,76,143,229,81,201,36,157,210,139,109,215,12,9,41,152,243,188,240,144,194,27,114,193,162,39,43,9,203,46,137,76,217,93,125,215,74,43,75,0,153,246,95,88,44,134,248,43,87,166,46,133,1,77,197,205,206,31,50,102,178,248,22,226,192,156,203,195,155,193,32,35,158,173,76,75,79,240,112,7,161,130,162,85,225,67,223,15,127,53,24,49,231,201,248,16,114,146,228,17,178,247,166,162,2,32,180,41,188,9,197,103,77,246,35,30,71,112,6,222,168,64,60,248,242,61,201,130,219,58,182,38,143,103,45,104,219,7,121,119,138,183,148,149,107,216,169,2,89,111,185,120,49,74,173,174,35,38,194,214,86,32,216,229,123,41,64,108,178,152,13,174,71,86,192,147,84,112,246,98,151,238,63,210,134,112,5,28,254,154,125,236,82,78,22,114,230,212,88,97,54,211,70,203,48,159,59,21,36,55,56,141,194,247,133,160,138,224,66,180,74,137,37,94,5,120,135,170,119,209,147,221,28,19,215,139,29,199,87,234,102,225,111,74,180,27,169,131,129,29,44,138,81,235,206,181,229,133,192,201,163,110,48,203,245,95,200,183,29,29,31,255,74,216,148,92,109,191,130,29,236,248,204,126,228,208,76,200,13,128,197,198,255,211,23,197,132,124,133,71,155,21,132,233,191,189,212,255,108,47,94,109,53,232,234,95,174,83,223,18,188,255,239,215,139,141,51,127,243,199,103,111,117,45,101,67,184,104,196,20,34,25,184,251,144,47,226,217,214,217,125,47,52,41,242,113,104,13,56,74,44,166,36,63,154,133,145,18,80,160,124,59,47,48,219,63,43,134,67,115,238,189,252,67,6,164,83,181,123,230,213,252,7,222,130,221,30,79,68,34,162,2,61,134,162,207,49,146,161,216,82,98,181,190,57,57,164,128,97,121,148,131,128,152,66,106,247,15,154,148,82,42,174,142,17,249,123,23,138,78,106,245,159,202,19,26,160,50,138,153,136,182,101,89,247,195,169,69,220,50,155,45,140,251,248,183,139,84,17,44,98,83,13,102,234,106,135,22,255,212,246,163,28,11,251,123,18,5,150,221,6,2,137,17,176,56,215,12,166,187,52,149,11,97,119,140,245,13,201,20,98,80,27,26,125,126,58,232,231,83,52,195,75,116,248,147,230,123,171,77,81,168,163,120,39,158,18,54,60,212,117,67,148,122,151,78,51,30,88,27,152,83,92,191,105,162,106,233,12,27,116,4,53,100,189,242,253,169,182,10,105,196,84,229,122,141,80,15,0,38,26,50,176,229,18,32,169,241,202,190,190,225,100,193,44,196,209,193,83,89,43,228,8,127,48,9,221,186,199,251,97,138,218,190,131,202,206,62,148,128,44,48,107,164,177,57,149,171,214,244,57,198,194,87,179,232,10,17,65,243,255,109,19,208,42,55,68,178,164,84,21,57,206,5,27,252,203,144,108,90,231,137,198,221,204,164,204,56,73,223,129,127,246,244,144,140,13,229,195,199,39,42,93,103,202,8,45,68,203,17,186,154,9,154,228,59,255,134,120,125,170,90,18,141,31,17,116,10,189,48,63,147,112,188,11,184,92,95,253,180,92,80,106,57,112,187,229,228,69,3,1,47,47,72,146,48,135,37,111,82,27,20,77,157,222,115,123,120,119,159,196,99,7,116,57,222,119,79,79,212,213,215,145,225,154,187,25,22,126,89,170,169,123,159,94,29,177,63,137,207,167,192,97,134,193,17,236,199,8,35,214,220,156,72,183,180,8,63,200,171,93,216,103,110,145,159,209,158,236,233,50,228,220,144,113,159,214,222,157,156,27,133,183,240,127,191,28,41,222,148,155,247,32,97,96,128,237,98,236,159,107,157,192,176,19,81,248,145,219,183,179,73,178,81,38,137,81,108,189,148,180,164,63,244,107,140,13,253,2,84,88,16,121,200,120,77,203,104,24,207,202,194,62,253,155,102,96,168,116,28,237,163,138,91,149,34,82,230,211,109,230,176,130,28,82,186,233,159,99,238,249,81,38,106,243,246,4,63,80,43,104,47,1,253,236,84,79,158,5,81,26,18,242,70,42,11,229,216,154,236,16,203,159,227,7,207,120,26,197,81,87,177,4,32,197,147,111,255,229,91,211,194,195,230,35,169,151,31,196,33,181,120,192,254,71,84,152,228,208,209,129,98,55,39,210,144,146,192,231,249,121,170,81,218,202,197,150,149,234,93,90,178,167,209,244,86,25,140,141,156,206,14,247,240,217,14,39,99,82,121,16,119,157,210,169,220,50,58,255,48,130,189,120,154,59,60,85,94,135,23,15,171,6,31,212,224,89,73,100,179,91,61,170,128,28,33,227,9,149,128,12,110,120,44,9,52,192,4,24,65,221,114,24,77,109,0,237,94,4,42,232,84,150,134,32,50,33,84,234,130,136,89,117,253,79,60,135,69,29,50,128,196,38,41,43,37,78,168,73,163,249,45,207,177,76,38,115,76,143,118,145,106,166,6,142,230,193,147,145,87,195,222,73,219,219,89,33,68,237,118,120,146,164,74,130,237,16,47,79,228,9,153,184,5,127,80,182,81,105,196,51,244,192,237,160,118,200,191,94,235,152,191,202,161,231,171,19,116,102,94,206,253,175,4,193,18,70,53,214,98,123,181,137,167,190,84,96,169,2,204,232,54,221,169,175,186,172,137,170,75,32,249,57,119,86,19,52,123,234,142,11,108,19,58,84,98,250,242,114,170,31,205,195,117,12,243,41,93,222,0,101,219,102,129,196,192,91,8,186,233,243,37,194,183,162,121,59,93,71,52,178,114,96,72,252,185,254,109,31,107,112,168,64,226,160,216,43,49,74,50,139,112,148,135,148,88,184,35,26,29,171,245,47,96,61,39,146,159,194,252,57,202,244,245,218,216,18,29,71,237,39,25,197,164,184,67,97,53,45,16,218,207,244,97,249,96,167,93,62,103,162,164,67,186,159,2,26,136,32,184,9,167,169,183,210,72,43,253,167,72,211,171,205,117,92,82,32,5,197,107,8,68,106,237,8,142,148,101,227,90,210,67,13,252,233,3,242,79,95,172,175,195,246,251,254,247,71,7,224,252,37,255,4,158,178,131,23,77,77,22,178,114,155,151,162,207,53,98,63,132,143,232,73,194,185,91,243,57,47,83,36,154,42,31,150,56,15,33,40,14,111,70,137,225,158,138,108,119,114,255,48,176,231,182,51,219,163,86,122,80,104,197,169,107,181,97,55,228,63,47,73,106,27,23,65,207,177,34,218,221,147,192,237,165,74,89,152,255,181,169,250,226,99,10,232,6,181,45,3,222,174,26,248,155,12,199,237,65,205,85,22,125,164,146,124,17,73,140,71,36,57,173,173,157,157,161,35,164,157,190,71,67,29,142,133,206,231,64,185,95,111,65,166,220,233,245,73,242,25,16,29,223,124,142,199,177,13,24,198,245,218,190,115,38,32,45,236,12,96,101,63,17,230,151,217,117,234,153,112,111,91,162,196,247,185,166,60,2,8,145,56,160,48,175,226,250,67,51,132,106,42,213,138,119,167,9,240,25,8,56,22,165,218,9,62,218,121,29,43,177,130,210,166,150,15,220,225,225,152,34,255,104,115,223,108,131,55,250,255,49,92,130,20,179,218,73,38,116,122,102,17,118,237,183,109,65,232,122,235,4,68,3,245,160,150,224,73,183,115,6,100,124,166,210,201,82,249,142,15,23,20,60,118,137,170,181,229,205,108,201,240,169,87,195,99,76,138,15,228,158,47,216,146,8,248,175,110,207,39,94,180,173,250,47,24,2,201,150,241,233,238,16,120,75,140,84,49,212,106,98,213,162,86,181,76,170,35,124,116,48,164,197,74,131,117,229,28,19,139,154,0,123,202,110,178,10,79,113,166,22,172,117,191,54,48,27,183,59,223,105,57,148,54,241,188,72,118,58,255,33,235,238,206,33,254,197,162,45,154,226,221,57,145,225,19,36,11,164,245,79,188,132,50,190,248,255,75,183,214,242,69,109,232,147,130,166,70,86,58,124,161,96,88,92,166,32,184,117,117,232,148,14,163,81,163,242,0,239,41,82,240,105,189,74,68,200,164,195,85,62,74,56,226,196,41,2,105,154,95,205,207,232,106,98,226,99,112,210,188,162,203,188,28,65,78,18,252,134,93,120,74,188,64,154,12,133,146,228,14,25,9,13,157,22,83,145,169,201,189,221,137,49,232,138,179,182,165,146,2,109,172,21,172,40,157,230,199,70,170,17,231,133,250,192,45,75,214,33,111,3,120,209,54,12,206,159,226,150,136,96,94,25,66,56,178,106,7,73,214,104,156,236,28,249,93,15,229,9,0,132,16,69,155,125,179,207,94,14,13,244,207,241,54,32,52,63,98,162,154,191,75,209,229,33,193,255,57,31,229,86,153,43,207,166,165,245,54,40,212,29,222,70,136,130,40,74,185,218,104,130,108,129,245,188,86,215,76,131,33,190,168,234,99,175,11,251,216,73,187,108,44,255,201,238,119,247,44,86,81,235,45,3,57,216,75,34,73,180,36,35,240,164,214,36,117,135,41,119,211,38,76,81,196,8,21,97,136,235,119,71,123,36,176,199,227,228,108,128,149,137,5,164,77,148,159,81,47,176,108,234,54,46,235,56,167,178,84,254,105,129,190,49,65,57,236,213,149,152,10,85,206,195,221,92,221,54,74,114,134,198,83,208,132,62,75,99,76,23,147,221,170,238,47,2,231,238,159,31,157,21,230,120,116,37,205,171,183,193,105,172,143,117,1,93,76,23,54,218,89,41,8,34,70,14,172,247,13,165,93,149,104,106,13,209,88,202,31,127,1,56,213,196,57,128,219,160,128,36,102,11,50,241,144,120,109,249,181,6,101,158,193,159,198,121,72,53,117,201,226,238,36,19,89,190,170,97,242,166,133,255,187,116,117,149,110,240,34,46,115,10,173,23,253,193,26,88,218,204,250,37,212,109,250,201,191,194,118,95,136,247,161,207,241,204,135,2,78,149,74,112,131,147,47,174,61,6,17,165,170,245,205,230,27,4,219,42,253,132,224,5,105,216,149,164,189,139,111,218,70,124,62,36,131,167,58,160,166,166,15,182,6,55,43,51,18,46,56,174,90,10,0,14,29,74,85,33,208,147,69,176,90,198,106,36,37,30,25,35,124,178,130,4,84,25,198,20,229,53,83,27,191,7,155,221,115,87,5,220,83,80,84,102,251,48,221,102,199,149,98,72,199,4,97,43,61,78,97,140,141,115,8,36,76,209,170,73,151,35,27,50,135,70,240,173,0,121,54,23,163,78,109,212,129,93,171,216,134,28,83,113,141,233,192,101,187,144,201,55,84,241,226,162,50,111,152,243,114,9,111,93,4,89,234,55,65,28,241,78,143,188,189,252,70,80,238,69,204,212,181,122,171,109,189,186,144,136,240,116,95,234,155,53,70,170,203,113,36,46,45,134,195,163,140,104,104,25,181,136,167,116,55,237,25,77,120,91,44,239,159,52,190,41,227,220,175,171,101,213,127,105,222,163,58,68,40,210,118,247,1,76,42,20,189,248,76,43,113,25,81,37,26,154,234,25,226,251,39,69,143,3,138,235,220,47,9,31,25,63,195,193,72,173,92,80,43,152,143,80,74,126,49,33,238,113,228,171,168,241,82,49,174,116,73,94,130,72,230,253,161,187,183,237,195,41,153,143,130,252,152,169,147,185,106,2,207,13,134,90,175,141,157,242,255,161,154,42,107,178,145,195,16,211,119,181,175,211,84,142,39,77,187,239,159,12,177,186,243,150,95,140,58,167,52,103,146,158,98,247,173,141,219,214,180,87,55,184,155,216,203,67,81,243,45,171,219,220,110,144,106,5,138,225,212,232,110,202,220,68,84,250,115,120,118,200,167,154,108,73,90,190,72,34,47,249,229,114,4,80,142,144,22,68,254,128,128,196,171,194,100,131,176,168,30,203,107,42,65,59,156,176,21,156,53,86,125,203,58,216,87,127,233,238,153,162,195,175,35,133,212,69,25,61,96,246,99,19,132,120,219,58,140,93,223,248,9,43,246,147,166,10,33,40,237,26,6,87,228,81,182,159,34,234,48,74,27,30,186,36,136,63,92,110,3,131,130,27,239,155,0,156,219,146,232,148,189,133,204,227,35,102,6,13,242,251,69,127,251,171,127,248,242,116,126,174,84,115,6,193,135,29,128,225,230,162,23,222,79,106,4,26,156,61,251,88,57,81,76,237,7,19,107,37,95,147,230,99,193,76,98,87,252,124,217,105,200,201,204,245,189,226,154,95,54,19,34,64,85,66,163,243,6,203,46,201,0,174,183,154,181,226,46,152,199,255,75,54,243,29,83,133,231,240,6,21,38,68,184,253,109,54,23,224,31,102,11,112,103,43,17,38,125,238,71,104,161,159,219,136,215,196,141,170,10,56,156,93,207,152,188,114,22,157,0,165,25,138,205,58,248,67,193,58,28,147,32,38,229,221,175,114,14,42,161,2,223,231,204,164,6,92,49,52,64,37,164,223,252,197,118,55,243,108,10,158,239,219,175,244,102,22,194,134,212,9,249,244,43,86,97,41,53,9,224,110,61,250,140,202,187,95,171,204,21,221,58,141,24,176,120,96,194,232,84,28,125,246,218,142,73,131,254,249,22,179,71,110,208,97,247,139,162,171,64,251,79,190,180,190,186,29,110,165,88,119,225,30,58,64,49,68,45,83,93,122,136,199,146,158,106,5,211,222,64,64,160,74,72,185,138,112,186,135,133,95,31,236,77,86,54,59,235,32,245,245,133,152,27,233,115,154,253,233,222,36,218,216,218,211,137,127,103,199,95,165,151,234,33,228,72,167,103,13,43,119,38,71,23,218,227,177,230,222,214,149,81,102,246,94,251,84,233,90,116,77,26,118,194,122,55,75,208,137,52,159,238,73,8,33,157,218,178,213,108,45,131,207,210,31,144,133,204,239,144,183,230,251,195,57,195,154,39,61,36,39,117,126,121,69,224,198,15,198,98,59,82,181,202,28,149,49,219,53,48,163,19,164,57,251,219,61,159,235,12,121,100,151,160,191,93,194,90,22,119,28,191,219,210,170,234,145,2,111,53,86,140,171,46,232,231,111,18,43,83,2,142,131,38,36,99,174,3,26,169,105,31,214,250,212,191,8,1,141,69,73,158,180,248,93,117,146,242,10,188,63,7,61,149,69,118,161,141,117,25,193,18,187,220,194,82,13,30,5,225,194,158,252,56,159,129,5,240,0,213,85,67,54,209,242,151,41,141,172,187,12,215,255,6,5,126,185,11,225,35,202,5,182,98,154,26,217,237,193,140,136,38,71,118,166,44,17,223,179,101,97,16,153,33,21,204,15,219,189,120,219,24,117,23,4,153,22,143,40,174,238,185,27,159,69,251,1,227,108,218,69,111,198,184,236,14,216,136,208,115,154,211,47,149,116,98,114,40,90,83,116,92,109,38,134,140,104,157,197,116,57,122,111,5,224,4,175,201,244,62,210,203,188,216,230,131,214,184,164,54,48,242,179,251,201,77,16,77,13,77,23,34,66,146,24,12,187,238,151,92,139,64,114,217,125,244,175,10,155,138,118,58,245,52,121,17,241,62,231,105,214,169,120,184,4,155,16,20,12,215,206,40,237,161,186,68,63,141,166,178,6,127,126,151,70,195,245,163,96,91,23,138,173,211,99,103,164,14,51,246,20,75,76,135,150,74,215,220,71,15,76,77,215,250,38,227,176,76,17,15,179,232,18,19,165,54,194,146,187,110,158,216,55,66,145,232,119,152,61,63,121,155,194,202,244,22,81,66,36,140,38,108,209,21,139,25,159,255,185,60,117,9,245,95,46,99,220,27,61,151,235,253,38,161,64,188,88,189,117,249,42,176,56,54,107,62,80,240,135,153,86,180,137,121,111,177,208,196,3,194,236,106,173,82,40,195,1,146,180,204,141,11,192,120,252,52,4,116,199,14,254,104,216,4,219,7,221,233,33,47,34,247,94,0,104,240,54,18,128,85,240,255,179,195,197,161,240,178,242,197,103,68,166,60,95,131,245,148,198,163,124,209,39,120,42,206,15,106,91,118,113,89,19,66,66,241,200,64,65,37,82,169,139,136,203,234,192,172,175,27,160,244,10,91,4,183,109,177,183,93,233,92,26,227,67,87,232,184,97,234,202,240,80,213,42,133,15,68,206,0,206,110,170,227,223,113,90,208,60,11,93,245,151,50,51,86,152,199,229,35,248,13,119,64,238,165,152,108,70,48,149,157,110,249,189,25,187,246,251,124,64,0,176,165,128,174,39,200,94,100,193,34,233,19,192,83,39,177,228,74,234,195,128,251,203,238,192,16,66,200,223,179,30,106,195,189,26,217,157,142,161,132,38,20,179,217,79,34,97,189,231,106,19,144,223,172,39,206,91,192,115,254,111,141,170,103,121,61,72,101,60,110,173,73,193,25,89,206,122,137,151,213,60,169,7,42,226,224,249,190,43,17,190,187,240,163,77,26,192,162,70,170,154,216,20,183,212,229,81,56,157,247,123,219,168,91,21,53,107,174,135,98,32,176,146,78,98,190,30,232,190,171,107,188,254,223,5,25,58,134,150,36,28,218,134,107,40,253,245,199,11,1,191,26,173,238,5,142,204,170,161,157,127,172,254,27,185,235,87,15,3,74,170,36,195,132,163,3,126,33,178,173,141,106,23,111,96,111,124,164,68,230,2,210,18,190,148,45,70,148,194,38,160,67,130,166,172,81,5,91,142,239,190,58,3,102,81,212,68,68,73,134,6,117,116,100,47,57,100,207,232,224,125,32,30,193,162,117,36,57,8,27,203,56,199,110,251,56,35,162,240,157,224,0,42,206,199,201,33,95,5,127,132,29,178,152,101,166,1,242,99,155,248,47,71,180,75,84,99,65,91,32,31,136,206,52,48,74,184,208,83,85,179,51,105,125,87,66,145,207,127,71,239,255,157,126,120,139,232,35,64,70,128,118,191,41,217,7,185,86,117,216,187,163,194,206,174,218,56,214,58,160,248,111,154,70,17,108,212,91,199,245,32,108,125,43,198,192,38,68,101,100,147,129,87,52,240,50,91,92,218,108,127,101,155,228,123,77,147,41,86,207,159,139,140,93,22,169,163,63,89,236,154,98,131,93,39,55,237,122,107,6,174,184,202,126,27,199,141,16,52,167,250,44,52,64,134,244,66,235,39,127,190,88,127,61,105,107,157,35,59,146,10,14,155,241,227,170,104,180,47,95,20,235,236,196,100,29,66,255,252,236,249,128,214,5,234,40,241,34,234,45,47,166,217,121,36,243,35,251,23,126,3,133,136,164,113,22,69,236,180,239,139,48,255,146,161,48,135,129,150,245,193,181,210,85,120,4,249,147,174,66,17,136,154,208,148,214,82,198,29,171,4,223,212,84,104,93,95,153,151,59,52,212,150,113,85,179,189,60,151,118,28,93,220,49,114,124,228,164,99,165,40,1,5,200,121,138,132,77,15,5,21,162,216,252,37,141,224,202,125,209,225,242,62,177,195,93,254,238,77,226,148,168,119,167,195,151,180,25,60,215,48,166,94,44,45,114,159,78,24,155,132,119,38,31,231,227,51,37,35,33,239,40,171,12,250,68,190,248,231,228,59,213,61,15,65,53,179,92,176,23,172,176,32,72,135,37,241,24,107,242,184,186,57,99,239,241,14,0,114,211,202,79,176,88,52,130,56,18,75,55,22,208,79,100,1,57,105,53,174,100,13,234,232,158,118,211,9,144,128,160,76,177,166,10,90,95,110,144,254,243,190,208,135,184,198,226,200,27,9,38,241,0,208,210,237,180,2,22,149,157,19,155,249,21,3,55,195,149,105,206,24,110,148,19,249,58,78,186,176,25,100,216,4,198,194,104,71,150,103,193,54,223,28,146,80,51,157,194,14,178,180,189,161,192,44,225,168,111,47,225,151,43,100,26,191,125,146,222,221,199,216,186,126,173,89,90,229,77,60,34,228,75,219,182,85,232,170,22,24,130,197,101,20,253,116,141,176,241,34,223,208,190,53,49,201,93,144,151,241,108,236,120,86,232,128,234,238,83,111,80,172,96,67,34,128,6,29,10,136,122,7,204,83,50,186,1,23,79,169,21,92,114,15,132,236,51,188,123,139,240,236,199,67,208,132,52,13,194,187,174,29,120,140,151,198,252,88,147,102,219,35,162,73,126,98,77,213,8,169,217,193,210,100,239,19,153,49,43,252,194,75,228,65,143,184,39,77,42,202,171,40,113,137,164,157,33,120,131,63,197,218,5,250,238,192,175,128,92,206,161,173,254,238,133,100,158,136,16,101,127,238,52,208,92,82,3,217,66,93,246,228,193,254,74,72,78,122,33,105,54,8,66,93,246,194,222,27,194,33,125,31,125,186,243,13,92,218,44,36,132,226,180,89,124,205,104,135,159,122,252,15,162,223,62,10,250,171,0,131,127,85,178,231,79,207,40,253,46,196,118,242,128,72,35,191,117,82,21,59,50,253,123,77,220,143,104,20,203,224,176,13,252,32,28,67,43,91,75,244,94,186,135,19,180,199,223,127,142,98,37,239,28,103,87,65,235,18,238,103,120,238,30,86,59,98,172,2,220,161,99,43,3,209,122,161,55,146,255,1,36,249,99,184,3,3,168,72,232,46,73,223,106,79,159,210,38,156,147,51,126,50,165,108,52,49,96,42,238,80,99,70,146,206,224,54,97,97,16,213,14,248,251,126,49,66,87,134,179,227,232,143,91,185,125,0,158,183,5,242,48,7,152,160,171,198,163,34,181,199,170,68,125,93,97,109,136,230,150,33,113,56,104,7,226,175,49,100,51,84,213,22,135,7,237,200,148,72,116,142,163,153,122,86,4,164,15,210,118,24,67,210,223,220,137,144,48,144,180,185,234,2,241,154,213,43,109,156,143,172,26,128,135,231,119,24,217,131,61,148,77,141,150,92,115,120,2,154,217,75,86,241,208,171,108,103,82,89,209,129,238,172,132,255,207,27,146,164,74,184,68,92,141,13,124,214,138,185,244,149,236,189,182,103,67,87,10,32,216,220,143,80,210,206,245,104,149,139,20,55,5,113,172,207,125,29,89,249,19,112,108,14,88,182,201,165,18,10,245,121,6,178,148,34,12,59,196,61,173,239,178,241,33,155,25,242,134,32,227,233,188,135,113,163,52,64,251,178,224,118,246,79,167,5,63,212,177,112,180,80,242,169,49,210,21,134,141,17,157,190,91,64,227,91,38,133,159,225,105,247,226,195,200,172,31,220,215,170,68,107,20,234,183,178,143,56,158,107,86,223,172,215,193,84,10,65,89,99,158,61,203,224,96,108,213,54,164,149,13,125,118,120,95,189,114,57,41,211,241,237,209,190,6,62,79,184,242,245,149,195,91,85,198,131,178,227,71,202,112,154,51,82,29,130,223,121,113,6,199,251,129,30,201,68,187,181,197,35,52,79,104,12,235,40,127,72,62,197,101,25,50,235,135,22,61,18,204,9,17,58,139,193,112,118,161,34,157,65,113,190,135,176,140,117,20,216,176,111,50,116,217,162,214,180,80,45,31,21,53,93,2,228,123,100,207,17,230,207,97,240,183,85,31,41,46,45,3,43,72,155,187,165,203,128,67,28,120,236,54,20,65,238,109,110,179,222,136,198,17,77,149,130,251,103,177,204,150,184,189,37,5,55,241,217,14,130,255,116,126,175,235,144,116,140,66,14,51,205,67,99,220,51,208,79,206,154,127,22,85,71,77,215,145,255,44,243,64,209,227,67,73,110,151,218,87,197,55,237,118,245,39,169,244,170,245,203,108,245,142,50,189,176,80,21,202,93,146,1,53,148,177,158,56,213,31,235,149,163,76,7,160,96,185,175,209,247,27,135,158,217,147,16,10,240,197,137,20,206,239,82,56,27,22,220,198,2,89,79,127,31,142,1,6,55,182,200,142,137,107,201,174,111,181,210,207,62,30,104,243,208,79,121,233,86,23,51,192,246,38,237,63,185,68,166,75,123,229,116,251,234,207,59,122,231,68,113,211,62,70,25,143,151,209,232,208,160,147,131,216,54,242,90,239,63,40,144,174,63,16,36,202,26,114,183,89,217,89,136,230,91,48,252,125,202,164,150,89,145,56,123,247,12,54,155,187,186,61,40,196,208,28,136,119,101,36,210,226,52,175,235,200,109,39,72,109,208,243,138,191,212,112,241,255,140,84,135,41,149,18,74,71,117,169,225,47,36,251,47,104,143,61,234,88,50,148,255,119,218,157,33,205,193,198,233,229,11,62,162,92,119,220,137,255,123,184,226,35,157,8,174,39,63,216,248,137,225,131,8,2,82,204,80,214,39,91,209,189,161,6,81,144,36,198,76,197,109,194,10,4,72,54,53,184,115,91,225,10,11,168,200,46,218,124,246,135,15,89,53,166,8,241,71,83,123,154,209,50,174,37,55,123,83,140,20,54,44,56,182,163,26,6,6,190,38,53,147,232,222,149,68,107,255,157,252,151,137,92,252,145,148,33,103,9,72,231,13,116,195,38,2,23,236,159,143,19,6,218,213,124,179,244,182,30,110,173,19,168,90,131,57,252,205,106,250,34,115,21,156,227,2,178,233,51,164,166,165,72,112,14,41,93,38,111,111,37,191,106,207,33,185,185,90,72,233,134,236,98,171,160,112,169,40,190,94,93,171,234,98,137,93,127,65,248,80,186,131,116,191,197,63,31,50,255,195,58,34,142,54,220,246,198,63,55,183,44,126,0,217,209,232,158,8,7,110,86,107,240,61,28,52,138,97,149,20,247,180,192,143,33,83,155,177,22,187,216,48,139,83,169,139,99,123,154,74,125,236,38,59,46,27,30,157,211,15,232,203,47,94,136,56,194,51,139,205,174,21,161,217,7,160,227,59,236,156,91,143,154,27,42,117,22,168,18,246,201,35,37,107,157,58,5,158,76,100,112,62,84,117,50,22,6,96,111,120,207,116,151,161,13,67,239,116,206,98,64,136,103,8,201,197,9,81,239,18,226,93,190,46,81,229,232,167,200,193,215,90,182,212,93,78,67,26,105,97,197,49,164,150,52,143,248,121,13,95,217,227,206,14,80,200,179,171,10,146,200,142,90,137,125,253,146,71,131,33,45,48,69,241,119,153,254,188,241,25,222,97,30,63,46,136,159,57,134,89,0,129,234,189,184,64,200,208,245,48,167,116,134,99,230,3,164,217,19,159,106,99,97,202,22,164,70,66,13,97,32,58,239,114,37,9,60,59,67,157,37,172,251,50,177,13,116,63,7,119,74,90,248,108,175,187,95,134,112,101,157,132,160,143,70,245,232,144,69,184,106,150,9,184,122,224,32,162,162,167,166,203,10,237,99,78,75,217,159,250,237,184,75,97,163,68,55,215,93,14,236,225,12,141,49,8,40,126,117,77,135,80,77,205,97,75,21,26,145,221,123,172,2,182,77,86,93,204,86,114,144,92,13,141,25,97,222,15,100,182,160,159,142,35,220,49,107,187,208,137,105,153,135,0,174,222,172,239,170,133,207,178,208,164,230,211,2,139,92,32,192,133,89,232,32,239,245,110,166,136,37,21,196,131,79,242,98,209,25,180,252,102,119,100,85,102,115,189,106,122,226,157,178,221,143,154,92,187,57,68,241,18,33,225,250,134,114,116,72,134,250,27,40,97,219,30,86,74,184,102,193,26,66,181,24,165,153,255,190,75,185,18,121,114,85,220,59,224,145,174,176,36,67,144,74,196,161,88,9,48,79,220,4,67,25,232,105,176,32,242,28,201,66,116,178,36,164,218,208,31,240,68,239,166,138,242,198,226,27,136,232,255,174,210,152,60,200,61,15,238,2,218,231,198,130,236,180,235,65,221,66,82,162,92,235,251,20,38,65,92,156,106,85,0,144,25,182,28,226,88,153,34,253,19,27,116,90,101,248,35,202,216,184,19,35,2,94,8,209,254,66,212,135,68,219,185,32,107,225,25,227,136,211,138,181,174,112,128,190,66,165,251,135,185,108,40,159,222,177,26,58,26,148,218,89,13,15,27,236,24,118,78,33,185,174,168,219,230,119,230,179,169,161,57,118,97,227,203,9,125,55,136,197,112,94,138,136,230,112,204,245,136,116,59,13,75,68,121,43,122,9,22,252,149,172,182,118,113,61,53,171,44,42,118,178,166,69,222,44,157,34,128,126,179,24,154,159,106,149,17,227,58,143,176,241,222,56,42,62,181,26,208,33,24,30,33,112,83,127,84,65,41,251,206,115,178,2,222,106,153,209,238,98,208,200,210,177,133,86,65,23,104,110,177,161,96,79,57,142,162,15,207,173,153,56,254,250,73,76,74,43,36,200,57,145,60,95,227,21,147,221,41,171,192,107,234,251,74,126,3,247,128,122,243,153,128,202,238,189,17,198,179,70,97,245,190,200,231,176,186,98,217,254,45,230,228,185,78,204,155,64,247,183,255,152,161,26,12,21,183,209,199,194,177,1,221,95,77,76,253,203,104,7,192,167,209,180,50,138,227,189,182,231,239,238,168,59,221,119,154,107,247,102,200,51,40,120,192,133,47,249,238,189,123,233,117,188,210,82,68,72,178,111,103,77,144,205,181,97,1,172,166,152,242,0,187,181,174,188,39,82,5,75,21,213,113,66,102,62,173,169,132,21,120,138,226,211,39,44,143,160,126,74,108,191,13,117,58,148,234,239,194,161,161,156,231,240,170,77,120,106,63,168,175,231,243,60,192,181,236,20,52,239,78,141,78,130,59,219,80,208,24,37,165,109,209,49,251,9,62,80,50,249,181,232,42,228,47,166,191,144,176,206,148,242,148,153,182,121,24,128,65,137,42,161,119,66,94,240,11,55,102,122,7,205,142,144,144,180,47,60,218,192,149,85,15,213,83,8,79,215,104,8,209,172,222,200,242,28,255,51,185,167,33,226,26,65,147,100,114,222,54,27,170,212,207,83,56,170,37,126,121,14,18,40,231,4,14,164,248,6,110,118,48,51,83,228,76,3,131,87,77,86,163,48,72,194,109,53,105,118,111,198,140,133,34,20,119,56,35,236,7,170,176,164,95,86,183,232,105,108,7,25,169,127,50,26,86,83,94,101,58,219,72,205,46,231,78,158,94,221,190,147,92,96,224,0,30,65,191,21,237,118,106,224,247,161,116,33,41,10,92,81,248,232,191,41,72,116,171,89,110,208,62,230,196,11,67,172,81,188,8,212,62,255,199,22,201,68,20,120,21,90,72,70,211,251,61,232,5,238,147,16,91,225,65,103,178,238,63,246,157,100,192,170,206,249,101,28,25,120,125,225,94,105,146,218,75,10,178,103,244,73,77,174,18,113,205,198,233,5,88,129,66,64,72,137,118,81,217,130,206,156,174,224,223,115,249,164,10,160,47,237,255,135,146,236,13,99,71,63,62,20,134,132,135,155,27,21,239,159,60,195,224,248,123,205,45,147,225,233,72,95,151,236,249,144,43,148,51,197,175,100,140,185,170,200,234,37,87,113,85,41,197,41,164,33,181,64,228,58,125,41,220,43,111,47,37,139,69,75,126,166,210,12,7,175,6,63,122,236,237,156,149,142,254,174,11,37,215,82,200,54,62,74,43,2,249,172,218,115,203,91,14,165,110,103,178,200,5,226,141,45,42,68,130,198,173,253,230,217,122,113,39,163,182,160,231,100,179,40,207,8,27,212,22,174,85,58,27,55,118,83,118,244,201,68,167,205,50,31,36,17,250,228,187,200,203,159,109,44,83,197,240,214,82,128,207,62,237,127,108,238,226,36,190,44,152,27,248,90,79,254,43,191,182,206,138,179,239,133,27,56,192,25,166,40,83,172,241,62,178,172,53,58,205,73,6,139,66,50,24,22,193,232,205,173,161,67,139,236,13,114,239,156,46,253,12,218,238,6,255,169,98,117,8,215,156,102,178,212,208,18,175,147,108,96,73,71,115,87,75,254,77,61,212,49,252,42,72,23,95,49,206,208,189,203,240,139,4,56,101,109,139,204,117,23,213,104,47,1,254,115,179,25,96,58,221,157,53,112,19,110,172,118,168,11,21,171,109,123,100,79,124,202,172,155,236,144,86,224,44,183,119,167,51,180,139,191,76,201,173,212,215,120,148,255,149,110,69,229,152,112,197,133,178,122,15,23,55,103,67,13,152,239,59,168,53,175,130,232,143,236,0,96,95,206,91,141,167,127,199,149,82,51,222,51,43,148,225,183,56,32,68,76,97,35,154,233,207,47,2,29,114,143,36,159,81,168,169,22,163,74,208,233,149,204,129,138,138,13,48,180,42,41,155,141,156,228,19,71,135,137,63,119,146,67,61,236,133,52,209,164,39,67,110,28,5,36,100,159,52,79,220,118,89,126,230,63,180,117,243,165,179,147,209,255,162,97,177,43,45,86,56,48,223,195,122,39,130,118,8,183,36,55,42,221,83,72,74,95,130,91,23,121,226,221,206,241,204,44,105,177,188,105,190,84,106,225,244,183,44,76,188,169,150,98,155,208,244,161,94,75,232,173,64,126,153,184,124,75,229,87,31,209,154,93,125,64,53,167,155,250,167,122,169,184,231,14,34,61,208,47,179,182,194,37,87,240,10,125,2,26,125,232,189,207,199,3,153,204,157,148,33,93,160,134,67,238,203,126,198,203,210,112,25,199,23,136,192,135,207,227,224,213,125,17,93,230,177,178,164,152,162,80,107,50,52,221,42,20,128,143,202,168,22,91,223,159,118,214,249,29,184,124,24,124,1,183,54,43,61,91,155,116,241,94,157,187,60,100,244,97,97,177,9,57,90,72,245,38,31,86,172,41,102,15,35,39,4,233,141,9,165,41,137,229,44,122,16,181,99,178,84,124,207,34,140,41,145,250,172,186,100,100,156,162,5,126,187,160,57,183,240,17,46,181,44,120,144,141,151,142,129,195,192,11,203,241,78,134,142,214,106,198,94,141,84,62,51,127,110,9,65,150,68,221,157,131,236,130,114,10,128,197,13,157,252,8,165,223,138,108,179,156,231,156,82,132,196,202,13,64,69,92,110,180,238,15,125,240,30,231,134,56,66,31,193,191,100,72,106,233,11,113,8,121,238,178,117,107,157,215,58,43,212,236,53,215,214,1,16,192,173,175,231,62,113,26,94,248,47,30,36,232,160,227,75,161,127,33,5,192,210,69,155,249,190,217,224,42,17,77,54,231,20,45,5,116,154,154,80,74,148,126,85,137,13,59,123,226,167,20,148,24,19,123,17,78,46,126,232,255,147,20,83,85,103,16,86,141,246,211,162,58,245,162,77,31,51,40,174,164,117,38,201,18,8,240,124,226,180,213,190,92,223,249,184,227,8,168,86,142,19,66,247,142,54,135,218,13,197,216,225,152,61,155,156,171,88,150,158,129,132,144,138,13,21,166,17,156,62,40,147,131,134,66,228,77,177,184,53,207,92,208,3,16,2,45,215,154,73,196,92,47,104,0,94,23,103,132,206,81,105,63,84,231,7,205,95,148,128,250,142,158,42,49,223,26,22,72,27,211,39,245,201,245,4,127,48,221,21,121,201,223,108,209,6,93,31,85,112,207,74,123,201,78,249,139,38,60,134,47,225,21,74,31,177,146,41,144,16,100,28,219,207,21,104,154,200,135,169,238,147,227,243,217,211,187,109,182,74,223,148,201,132,46,26,159,121,196,145,148,161,153,126,127,103,44,44,215,135,248,8,157,23,184,220,82,173,81,229,136,173,243,230,69,68,158,137,156,73,166,209,116,155,166,231,141,186,187,84,175,227,63,227,13,18,245,222,185,2,9,97,179,58,174,246,67,94,255,153,44,100,138,172,19,5,67,221,82,20,224,61,104,222,44,53,106,82,147,130,225,31,218,140,64,109,45,5,216,165,119,100,159,228,18,213,150,192,59,85,135,249,36,228,230,57,28,67,206,105,230,148,212,28,106,92,97,2,31,152,107,208,11,10,205,238,102,126,66,83,190,233,77,232,77,96,85,249,251,119,192,179,5,0,198,67,127,22,157,78,146,64,204,6,39,200,12,229,227,234,242,193,195,141,125,107,248,143,210,251,18,220,67,240,110,48,114,110,15,160,241,14,133,152,132,225,44,134,92,88,11,167,164,225,12,234,164,92,9,175,74,190,164,193,157,232,4,137,216,80,165,124,20,254,221,2,198,63,217,156,135,119,4,178,58,153,215,139,67,52,172,206,47,40,75,33,86,67,63,41,10,20,37,237,37,156,4,13,25,23,201,228,9,237,67,16,22,116,17,184,162,203,188,227,13,110,65,231,79,200,61,118,207,68,161,90,71,47,113,31,224,165,90,23,21,239,63,80,176,54,103,99,60,125,72,207,90,110,231,121,225,205,35,28,16,137,252,136,94,179,14,97,157,227,66,82,219,137,26,78,157,181,147,28,161,251,43,196,201,53,245,149,152,194,86,91,70,203,91,114,199,241,212,180,125,44,131,135,116,26,132,69,27,84,222,132,88,96,163,119,62,129,249,230,33,147,28,124,23,172,231,132,144,182,235,125,193,70,233,206,77,27,210,203,223,213,95,105,230,117,205,214,164,126,23,240,10,34,237,211,43,162,138,230,118,192,86,247,125,167,215,62,26,113,209,175,19,231,246,167,150,22,44,69,31,236,205,198,210,214,123,93,60,9,175,131,96,145,71,92,190,209,201,225,103,43,204,242,98,253,129,95,56,223,107,29,87,165,180,44,49,28,37,42,83,215,122,91,126,77,38,243,71,213,191,223,14,76,247,97,110,190,120,147,167,234,237,10,98,148,45,218,3,23,117,15,148,142,173,118,236,90,31,27,85,54,188,202,253,43,102,109,130,17,8,239,241,89,212,14,29,172,179,90,8,104,5,203,117,188,43,184,167,54,8,100,136,17,55,201,102,193,221,245,173,86,65,162,176,40,92,214,101,18,82,59,131,63,156,187,219,65,190,115,172,242,52,181,80,109,165,136,98,148,149,152,234,86,143,132,100,239,159,119,163,250,30,130,119,190,45,58,208,104,161,144,10,202,200,31,177,215,242,236,78,3,151,34,8,16,172,231,112,71,159,168,32,208,230,50,84,234,214,40,92,65,60,148,117,76,216,111,91,121,177,66,86,123,55,54,126,46,118,241,103,105,245,89,242,0,0,166,87,7,145,164,227,90,30,10,4,88,64,114,70,127,14,161,218,198,16,35,230,115,54,65,108,190,175,186,252,79,33,24,82,118,130,249,181,253,61,28,154,77,227,209,111,63,61,68,223,162,41,90,176,37,114,169,199,77,160,219,199,22,79,240,212,158,243,217,226,74,158,215,193,166,204,82,135,0,106,12,155,150,113,241,197,33,205,6,16,19,118,164,194,115,243,112,162,251,134,203,122,124,61,242,68,140,200,131,168,172,123,48,70,132,227,199,3,196,130,48,55,231,64,216,195,86,36,160,233,137,145,108,224,93,218,61,107,191,138,171,13,215,212,65,223,117,85,120,109,207,141,12,23,221,175,68,130,129,185,138,67,225,85,127,85,215,75,146,79,69,133,10,129,210,51,71,147,116,11,104,76,194,87,78,137,12,108,185,53,10,210,35,135,33,203,224,96,175,47,98,138,83,60,163,16,100,51,21,186,245,7,153,128,164,73,27,189,195,13,61,255,96,12,174,169,37,39,235,177,224,137,71,128,240,63,137,238,255,68,185,212,135,190,156,240,184,158,113,210,241,119,224,63,177,236,63,172,135,117,74,27,187,227,253,246,222,134,197,251,197,243,107,188,160,85,252,111,4,141,195,243,91,73,226,144,131,109,136,10,172,209,186,95,172,96,107,43,22,44,176,226,122,100,50,28,65,163,62,235,88,16,254,97,48,250,64,155,101,21,83,64,255,189,98,142,60,20,184,3,54,87,20,50,178,254,138,105,53,169,141,5,88,57,244,207,138,191,208,185,54,87,134,70,182,197,77,248,201,118,133,148,231,106,241,215,91,61,184,61,250,9,140,91,66,203,141,93,171,166,65,183,29,234,196,85,230,194,177,148,240,126,71,14,92,212,2,120,179,141,11,42,166,15,45,196,187,30,249,247,104,244,5,25,126,208,252,253,157,224,36,138,145,222,221,213,15,204,112,217,50,193,215,194,2,248,214,48,43,229,7,204,79,218,223,82,137,114,228,41,220,68,157,35,245,242,213,255,141,189,192,243,63,72,119,222,107,252,230,192,211,47,186,209,144,213,221,185,22,152,208,54,130,76,100,242,54,210,211,40,29,189,40,7,183,252,209,130,240,76,107,14,110,35,151,57,0,187,180,78,210,153,198,18,212,33,205,72,211,89,150,175,136,7,138,13,18,93,226,93,52,171,126,188,165,113,29,15,231,234,11,67,54,164,115,158,58,48,20,202,65,198,247,224,202,190,45,10,153,146,148,150,218,67,157,27,190,197,15,182,135,56,130,43,203,209,174,134,100,81,179,58,182,229,1,155,224,135,148,214,99,38,92,212,220,49,17,170,248,161,123,88,92,5,119,19,210,149,12,254,121,21,140,38,10,247,25,4,22,186,68,1,211,221,109,182,103,137,4,242,129,66,67,138,61,50,131,83,208,81,53,132,36,86,63,33,62,142,250,210,195,68,246,210,84,77,150,182,48,140,129,1,24,195,122,107,160,22,129,227,250,27,102,21,127,52,229,47,19,58,21,47,132,85,233,11,183,119,3,54,223,94,30,168,153,3,202,62,170,29,46,235,105,186,122,192,71,128,73,149,47,98,46,122,34,64,101,76,177,160,154,47,174,96,118,108,73,203,121,15,19,101,72,99,177,70,118,219,124,182,128,41,154,76,22,204,166,120,224,174,35,27,29,63,8,248,217,183,247,192,11,141,178,28,4,184,73,111,64,221,65,220,21,145,34,163,79,94,28,225,40,146,182,182,2,244,18,250,136,64,65,3,121,52,149,19,150,105,221,244,244,247,77,249,155,100,216,128,178,170,122,153,140,221,2,88,211,227,255,108,191,91,6,185,100,148,31,75,245,179,229,46,107,30,214,20,93,198,142,86,108,83,131,235,38,107,38,203,229,248,160,22,216,41,215,22,55,59,211,156,38,76,79,202,176,49,88,161,162,206,46,81,83,200,99,138,117,40,110,2,84,142,165,212,63,185,183,35,165,96,218,110,177,40,36,21,19,181,76,171,145,175,144,249,115,42,97,99,152,49,128,122,54,8,136,236,196,46,137,181,211,218,83,112,177,64,193,136,89,220,176,221,204,172,174,154,77,96,166,191,132,59,141,90,169,6,46,45,84,193,160,209,49,6,199,255,3,129,73,146,92,31,226,30,164,12,7,148,241,217,3,113,226,199,81,146,95,141,45,176,205,253,233,128,78,74,123,244,138,154,234,99,11,241,18,251,174,123,196,122,254,82,210,2,90,216,87,97,38,253,160,197,255,134,152,168,162,17,72,133,41,122,235,85,154,133,172,162,240,103,107,149,216,192,182,55,27,163,94,52,129,61,154,61,11,135,223,222,154,217,53,135,124,181,120,2,41,107,239,28,32,232,45,27,51,86,176,14,7,40,249,170,100,67,101,131,23,151,200,74,151,82,184,146,40,7,64,240,146,253,80,218,150,108,16,186,224,225,98,8,166,177,252,0,35,95,107,137,80,130,116,129,161,149,37,52,149,240,167,11,50,129,134,80,126,16,233,201,206,97,186,68,205,245,254,241,139,20,5,89,162,39,98,188,107,186,119,233,101,250,245,150,241,120,191,39,29,12,121,31,198,242,252,230,85,160,112,172,171,128,29,103,65,246,39,126,74,92,140,142,56,181,82,101,195,59,71,4,8,9,42,98,180,136,41,26,56,252,4,230,102,239,251,161,183,106,22,54,238,250,59,61,243,9,189,77,195,254,119,234,124,186,211,5,26,88,176,159,87,101,242,100,179,102,218,39,85,82,118,109,146,144,225,73,28,78,77,189,135,29,192,12,95,153,113,248,50,171,113,241,189,121,194,155,247,109,70,124,72,61,27,79,56,185,218,51,155,130,98,183,1,100,60,85,55,160,158,110,41,58,63,216,176,49,228,195,87,118,254,105,223,41,138,84,41,78,214,111,49,206,175,91,190,57,25,68,120,22,127,85,81,202,226,197,123,156,169,249,12,182,148,31,115,211,146,41,208,248,249,197,188,103,47,138,8,117,43,130,28,28,102,44,149,38,221,176,211,11,76,148,186,176,252,87,62,69,3,88,80,123,168,196,245,128,224,186,224,99,220,46,237,181,88,159,161,175,204,237,160,154,13,131,12,99,88,171,231,111,242,238,194,193,15,3,254,152,148,114,131,215,216,106,245,73,197,176,147,149,25,185,200,252,52,225,236,86,240,34,22,76,102,243,132,148,11,204,125,58,185,37,184,188,4,169,89,249,104,232,254,3,96,102,68,177,242,8,251,188,177,100,48,1,248,177,185,181,108,161,130,117,35,229,28,94,131,105,31,242,158,200,167,63,124,21,55,142,139,10,202,5,82,209,8,37,48,22,47,237,174,182,254,11,32,46,255,142,78,113,207,192,187,172,174,16,156,90,26,138,142,57,129,2,59,148,175,197,194,242,205,81,57,214,199,206,60,204,225,254,113,28,148,222,242,209,101,104,98,108,237,223,49,114,212,129,78,146,78,208,40,162,230,188,127,198,195,47,15,146,82,173,159,186,217,133,148,237,194,5,33,102,245,90,65,8,165,35,12,231,205,62,97,232,36,7,127,30,119,233,149,99,221,178,173,102,226,168,250,196,60,181,5,125,126,243,158,64,110,37,30,195,162,229,136,241,198,229,105,88,85,49,14,96,84,216,55,253,53,92,172,24,38,54,35,37,50,118,149,84,244,199,203,56,87,218,44,100,7,25,135,147,55,101,115,200,99,37,8,239,72,221,30,76,8,86,146,55,44,91,241,31,111,230,90,185,168,144,245,50,43,46,238,33,229,223,34,244,14,118,219,103,141,110,249,21,49,255,202,251,214,126,66,144,34,95,94,195,240,131,109,100,123,73,158,69,82,217,206,59,169,190,31,185,211,83,88,73,74,185,229,228,147,57,21,198,39,234,143,84,167,170,144,247,206,56,43,55,104,193,157,220,89,125,173,151,17,4,10,18,124,244,41,133,194,59,11,202,98,174,212,26,19,95,71,26,82,242,133,85,125,4,131,36,108,37,250,255,99,63,15,53,173,129,255,175,83,105,132,142,35,4,243,133,67,237,220,88,25,169,219,83,229,33,83,46,251,0,111,226,87,41,226,98,245,208,93,251,94,207,210,41,146,56,119,137,32,0,61,212,6,161,219,144,112,202,88,124,132,83,197,240,185,196,152,34,202,136,59,198,165,5,136,11,246,158,60,3,176,105,203,207,70,162,187,45,160,39,60,82,115,113,239,37,166,188,235,215,222,227,65,73,188,70,178,98,215,247,7,12,10,4,216,139,202,178,125,231,103,79,61,127,58,10,202,75,42,107,139,214,172,4,14,3,23,73,247,52,158,78,61,218,235,79,191,182,70,127,157,34,208,242,177,248,153,110,42,50,168,186,212,159,202,174,245,161,60,197,47,221,200,111,195,231,35,136,145,196,62,119,52,247,41,50,41,64,94,231,136,149,213,174,127,157,61,143,47,166,152,59,245,186,16,70,32,201,49,239,157,90,225,122,138,88,158,93,59,121,246,69,151,25,182,189,199,100,74,131,123,99,103,185,138,240,169,255,83,8,240,13,159,156,5,223,181,247,243,244,179,90,207,159,36,69,34,174,29,39,12,198,108,220,130,2,10,203,188,206,67,116,209,27,67,170,198,93,113,250,14,198,254,196,37,146,198,0,245,162,19,196,105,30,136,94,211,48,61,213,53,160,236,102,140,240,236,1,246,124,73,73,184,88,243,157,125,154,77,39,104,111,1,205,78,22,233,44,37,253,92,198,51,8,211,150,43,192,106,122,208,21,123,140,14,148,222,144,217,194,15,242,120,80,45,66,71,74,147,132,37,185,45,165,41,76,166,143,130,134,3,4,15,104,214,102,179,162,238,195,200,235,20,223,172,249,110,37,43,216,136,128,232,235,48,215,2,250,173,82,109,146,30,125,217,231,73,206,65,2,40,45,35,163,248,230,102,19,67,102,0,76,64,7,130,23,167,105,28,152,26,73,234,15,36,35,231,146,205,50,217,164,199,154,192,15,19,80,26,30,181,14,197,12,131,88,61,140,86,85,233,182,210,78,143,77,63,177,30,176,10,224,14,137,130,162,84,191,108,227,75,85,115,237,159,119,222,168,131,18,13,22,92,110,176,134,71,180,31,116,154,111,4,116,74,59,2,191,75,114,181,184,238,106,236,202,251,63,247,48,35,155,172,61,122,174,26,38,3,176,42,15,71,195,153,55,66,191,33,169,177,220,36,95,177,66,86,173,31,180,219,166,178,139,120,139,67,88,25,238,233,169,169,111,163,217,54,29,44,34,138,236,199,35,50,82,214,30,125,91,25,222,65,137,125,96,232,78,167,209,68,71,70,1,22,163,34,202,200,71,113,235,157,41,14,32,110,171,235,197,174,10,51,158,251,44,98,199,201,196,168,50,201,99,205,245,153,75,169,17,143,154,52,222,138,28,173,86,92,134,115,136,220,131,85,171,122,218,117,190,117,143,79,26,121,10,50,45,80,241,33,4,253,140,1,159,201,105,123,35,133,81,59,236,16,238,109,215,10,124,211,64,112,180,147,203,106,142,69,97,205,162,177,217,151,174,189,239,69,50,30,166,238,219,120,79,225,197,121,127,91,215,89,102,17,39,158,213,94,164,254,49,125,216,191,222,90,38,224,214,242,60,2,38,241,139,218,34,185,186,30,206,33,43,38,242,81,191,12,1,200,96,167,125,197,194,127,129,244,184,30,74,74,196,174,229,224,226,124,52,137,122,146,108,187,169,127,72,111,131,243,79,149,236,134,103,137,212,161,44,61,183,188,103,150,96,95,88,187,167,31,213,185,63,128,70,10,58,47,69,155,112,231,242,129,19,78,116,74,152,85,44,128,199,241,148,56,48,27,194,180,191,35,170,227,179,166,110,172,88,208,185,53,153,120,109,155,216,205,172,159,59,191,94,49,209,213,90,125,246,132,153,163,89,50,28,91,141,185,11,4,229,210,18,79,36,117,191,90,231,97,92,89,193,98,201,7,9,252,3,100,157,87,134,164,29,218,54,7,117,232,97,226,74,185,43,135,78,199,151,206,137,157,244,201,49,137,164,23,115,134,121,92,128,224,192,100,154,252,124,146,17,129,44,130,237,65,159,194,35,88,56,132,29,163,200,91,112,118,35,100,76,112,87,180,233,171,69,124,62,161,232,54,66,129,248,193,47,232,197,143,236,112,36,132,61,97,179,231,60,124,4,220,161,114,16,84,196,143,200,58,98,2,255,8,3,222,42,146,204,234,68,199,78,202,173,32,215,30,242,64,32,250,49,111,31,174,191,209,40,51,55,101,12,137,212,116,140,72,132,52,104,204,245,218,122,29,236,175,188,112,137,112,129,225,22,84,118,55,75,104,13,207,51,243,102,148,120,49,86,192,53,173,30,143,161,0,187,160,141,185,32,104,37,221,242,44,29,27,162,135,12,4,205,239,98,8,217,237,81,207,29,240,169,209,6,80,56,120,99,193,90,244,235,14,45,162,130,224,62,152,96,147,9,238,188,49,82,151,207,8,240,126,39,228,192,121,199,227,52,238,238,69,130,134,174,90,34,126,176,133,63,234,79,219,126,186,224,106,183,242,244,90,180,161,17,110,155,66,109,222,205,83,121,103,49,85,234,220,198,98,67,0,50,194,21,182,193,118,19,220,4,173,96,221,203,40,186,232,98,162,37,12,169,225,26,229,12,71,121,194,162,100,159,139,30,0,151,86,14,131,219,129,154,212,170,79,126,26,171,90,92,239,0,106,79,97,213,183,128,12,238,216,30,67,114,73,64,191,22,179,225,12,252,220,234,87,55,51,145,66,34,63,168,252,148,87,47,176,54,228,85,152,226,61,198,41,76,94,182,131,134,142,127,97,14,232,78,147,107,91,23,55,184,220,0,132,128,230,214,41,253,146,45,59,69,244,78,228,127,47,234,235,212,197,152,203,251,16,167,93,153,46,245,207,238,82,246,96,131,4,123,250,67,9,15,63,198,214,205,18,51,223,238,190,104,69,185,188,1,61,168,132,22,21,224,86,237,119,49,15,228,241,216,161,180,19,252,22,109,144,133,49,21,97,145,73,250,32,160,0,103,179,235,69,26,206,44,140,184,97,110,167,21,84,228,112,18,154,24,41,60,232,190,168,43,72,248,82,221,13,138,79,89,140,122,61,117,232,17,75,243,217,88,218,235,50,96,182,174,230,168,249,99,90,3,240,143,171,128,49,247,62,32,242,216,73,239,88,172,30,77,172,78,40,138,46,152,178,103,92,139,57,224,167,208,14,63,245,78,69,235,225,103,133,134,96,22,32,104,77,117,153,192,206,38,183,221,117,253,207,240,211,16,89,105,251,119,74,144,222,156,150,154,58,135,38,58,165,24,125,4,181,205,243,117,226,156,243,80,70,66,176,146,37,197,55,215,99,87,148,92,191,170,198,29,60,48,57,132,232,226,100,191,28,143,184,235,205,69,47,243,18,71,89,96,148,5,68,98,120,4,46,222,166,248,156,123,31,13,147,244,29,153,133,248,130,207,112,2,139,131,49,115,58,120,121,244,170,19,97,201,192,75,161,137,127,83,157,78,253,58,222,224,220,83,182,11,236,101,153,140,34,113,36,254,143,112,151,78,23,46,155,32,170,178,239,64,77,243,128,127,240,27,82,213,68,205,87,27,42,124,75,156,9,234,4,161,210,181,7,140,130,78,31,105,100,208,169,223,62,105,229,132,50,56,128,226,5,184,254,213,116,54,2,93,233,67,132,34,39,179,133,27,209,227,163,127,21,38,10,175,140,28,114,70,190,173,123,166,31,176,23,83,27,2,64,147,250,217,95,1,100,211,238,42,151,65,188,182,234,61,134,64,31,245,14,173,167,214,244,223,242,182,230,208,180,241,228,142,135,251,1,188,189,100,175,18,181,117,35,14,102,136,20,208,168,235,41,228,102,112,204,114,197,137,63,144,1,174,122,8,52,194,119,247,169,229,16,103,124,105,126,128,30,165,102,132,107,24,55,253,220,212,101,202,129,150,144,2,88,195,9,152,160,243,97,168,80,228,18,168,79,186,193,151,206,197,164,32,6,58,126,128,178,154,122,20,188,81,123,96,6,46,214,149,107,24,177,129,255,208,247,29,66,228,212,126,81,168,1,76,131,174,108,141,122,248,24,107,113,170,68,235,117,129,83,56,163,148,130,79,104,185,22,138,198,242,77,180,102,47,117,225,233,90,16,225,8,163,241,112,173,15,227,176,197,136,139,114,202,96,151,63,60,96,154,107,17,147,224,206,248,93,53,106,235,229,60,87,165,173,67,60,192,40,25,38,154,183,128,195,41,187,21,254,166,61,76,158,20,29,63,194,131,191,180,111,32,193,245,193,122,94,224,84,142,94,172,150,192,219,151,49,107,61,164,252,204,72,119,227,21,253,120,84,60,176,113,224,172,24,196,92,64,19,6,114,3,127,121,48,40,3,60,52,74,110,225,56,14,140,23,179,58,129,206,230,166,25,190,123,31,5,201,50,253,204,94,174,116,91,166,97,216,90,145,201,152,88,164,18,19,17,202,204,251,146,159,61,233,43,209,63,240,241,168,94,78,86,211,0,62,97,12,204,199,62,218,65,64,9,170,91,210,0,191,56,249,81,51,140,84,246,229,192,59,27,87,104,195,108,174,216,168,188,98,234,57,57,162,193,13,190,155,45,124,40,58,32,99,14,179,68,39,112,92,159,159,36,201,2,226,129,171,120,102,185,148,114,152,162,196,181,56,69,182,37,197,98,228,38,41,142,10,57,84,197,160,183,210,236,9,42,214,224,63,62,31,118,26,251,177,236,185,210,104,244,19,251,195,113,141,34,50,255,204,42,56,117,66,203,139,249,119,14,28,203,175,32,42,245,180,104,11,154,25,127,248,60,200,28,180,91,39,244,161,108,240,140,189,72,32,119,76,235,30,100,46,74,250,110,234,232,192,243,51,124,39,251,186,123,64,23,149,105,161,56,180,49,163,245,34,42,187,145,64,13,82,135,95,186,146,44,214,135,104,194,94,110,93,178,242,130,21,226,63,156,184,127,204,241,167,193,180,9,237,106,90,105,165,19,198,246,140,189,35,66,77,27,170,145,237,170,99,161,189,234,238,51,219,82,212,214,32,43,128,193,45,163,2,216,44,192,84,104,92,99,93,116,94,163,255,90,174,176,184,147,127,46,68,22,63,23,62,151,173,125,237,52,101,54,144,205,184,145,103,197,86,53,11,127,158,118,175,217,13,86,251,47,11,230,181,185,174,212,134,254,17,229,174,154,246,87,107,230,55,252,104,84,104,251,201,66,110,183,24,71,54,10,178,175,12,182,18,163,73,203,244,85,216,175,129,81,60,17,112,71,155,136,34,122,134,137,245,172,152,64,127,55,97,0,148,116,138,88,45,172,16,250,169,10,55,168,155,249,246,117,74,112,183,220,144,84,127,245,255,79,75,162,219,9,150,235,53,199,122,194,58,198,192,83,66,183,114,7,36,198,143,179,218,40,178,248,218,185,108,140,103,50,91,31,235,191,230,109,62,140,189,224,31,241,31,255,48,167,106,18,242,164,95,24,208,232,159,107,188,95,66,187,61,92,245,43,201,191,135,1,41,19,255,103,156,115,9,219,112,48,74,62,113,152,120,196,200,133,105,206,67,75,26,102,159,159,237,244,74,119,46,70,217,24,102,5,82,212,11,224,67,44,241,148,125,122,140,30,141,56,185,122,202,228,228,152,203,143,221,92,116,168,69,113,89,106,187,215,201,255,151,132,143,105,97,52,138,102,179,146,194,72,5,11,142,16,31,119,218,54,11,45,117,143,78,191,169,116,115,101,231,67,196,81,203,175,126,36,74,3,153,52,15,176,118,87,2,10,235,166,166,25,217,24,97,56,174,121,208,62,83,81,159,25,1,81,67,213,89,71,34,140,83,221,7,159,118,96,172,176,235,249,185,28,97,166,17,64,245,165,23,63,251,128,105,12,76,148,92,91,188,236,238,25,184,58,203,60,22,171,192,183,224,144,158,173,39,61,188,92,76,155,181,102,5,187,207,150,94,58,3,250,36,236,210,151,254,24,164,165,111,28,108,229,47,22,146,124,12,137,148,24,184,174,127,13,247,114,83,177,100,178,209,116,247,77,184,99,249,116,52,90,208,48,242,239,23,251,172,248,54,133,62,24,240,90,110,209,64,19,65,231,127,36,40,74,61,89,232,108,40,133,183,241,255,164,20,180,249,37,233,11,144,123,198,10,134,56,30,115,232,181,188,113,167,11,26,133,132,207,13,144,114,236,85,141,70,151,42,10,176,211,160,243,33,210,57,247,197,33,32,215,207,152,153,82,222,95,87,217,232,251,9,157,52,92,92,186,221,244,36,132,244,171,126,222,212,178,213,118,239,52,68,215,228,157,37,229,77,151,40,95,205,177,209,250,59,223,193,65,135,147,161,220,60,30,20,221,12,251,251,237,115,218,76,211,222,227,113,244,133,150,144,25,141,230,202,17,219,118,142,8,254,249,111,8,74,66,92,214,206,5,252,176,47,65,208,174,127,25,182,208,254,125,215,136,104,95,122,148,47,160,24,171,217,115,108,36,46,111,121,54,209,200,78,201,242,47,82,146,153,116,84,30,151,175,199,2,189,89,106,30,113,219,11,101,233,191,165,1,168,238,15,156,187,76,114,205,125,10,232,251,59,152,234,16,241,125,111,195,40,170,83,198,62,219,137,128,20,195,25,33,235,77,95,39,151,116,175,239,44,250,171,84,173,154,211,23,212,157,160,162,208,164,16,244,147,14,14,17,6,104,150,53,108,250,78,227,27,137,22,252,98,238,175,243,37,70,13,183,79,164,152,113,101,78,244,30,197,103,210,103,214,38,156,171,0,17,21,28,178,30,168,20,31,200,208,51,52,113,15,151,103,235,237,40,10,81,34,216,193,173,182,231,138,223,70,74,110,140,135,128,67,193,157,182,109,142,223,157,163,206,148,192,228,100,183,148,130,219,246,217,18,184,83,27,227,178,40,188,85,136,45,33,244,69,87,159,128,40,97,108,157,0,46,148,60,23,222,235,38,205,188,53,18,244,187,182,168,183,237,144,27,24,195,130,65,220,216,15,20,137,249,27,41,218,232,246,197,92,106,119,80,113,188,192,30,233,34,219,39,146,187,114,27,18,165,104,236,249,38,44,105,166,205,230,49,128,243,36,251,113,40,38,25,215,224,120,27,235,159,12,92,34,87,109,158,74,60,6,136,178,187,38,91,137,86,88,121,201,214,195,151,83,64,228,135,143,158,147,97,176,188,111,251,247,113,197,192,23,113,9,177,188,15,65,193,111,153,189,107,45,251,63,75,15,75,144,12,21,147,41,0,174,131,76,50,32,230,156,172,12,21,217,99,174,122,176,90,142,255,218,205,218,102,252,254,211,225,2,68,190,66,50,226,64,173,14,103,174,112,42,47,226,144,59,125,110,69,123,255,9,156,24,136,238,168,115,76,198,25,170,142,181,178,27,82,125,25,38,98,50,248,232,139,82,51,79,162,74,26,73,204,26,40,13,40,2,73,96,105,177,92,99,35,99,110,56,185,105,177,205,31,100,153,114,150,60,150,252,43,129,210,116,71,159,252,129,54,152,242,65,180,226,15,50,224,127,124,175,143,91,38,46,62,8,22,59,186,178,38,77,246,103,48,216,212,109,56,156,174,127,24,51,123,161,249,178,142,219,27,68,158,78,254,94,242,73,34,240,204,200,93,216,7,25,228,165,205,3,19,2,181,77,104,175,11,217,230,194,135,111,69,253,161,56,50,214,192,155,137,146,17,189,167,202,57,121,74,241,142,45,201,161,154,57,125,92,44,130,241,88,74,115,124,14,144,36,13,187,40,11,139,4,59,158,157,206,13,92,151,135,1,219,94,61,152,173,99,202,240,172,225,103,253,248,69,184,171,34,33,169,218,245,125,15,58,199,178,40,202,80,134,75,170,110,92,65,6,58,200,15,51,116,102,229,188,24,164,185,80,221,62,235,227,1,238,159,158,44,47,211,248,136,211,153,57,241,104,231,90,19,39,187,253,118,187,69,91,208,213,90,157,249,110,157,246,186,4,46,212,11,235,27,55,22,236,16,139,224,123,76,76,174,18,156,21,2,25,59,83,147,157,186,202,18,243,139,77,192,205,43,11,67,231,130,169,53,171,6,241,244,138,2,96,125,93,209,194,120,187,162,104,129,237,118,242,149,94,212,207,222,141,202,202,204,103,231,34,132,92,157,95,239,176,202,195,185,87,154,63,219,10,215,8,146,73,190,222,17,110,27,90,35,66,27,93,191,17,12,120,158,138,224,58,68,152,169,243,48,157,252,163,132,148,157,222,184,145,161,202,141,123,93,61,82,14,213,82,53,66,165,100,215,10,77,207,216,139,35,208,176,63,63,80,219,7,147,222,36,12,252,16,92,225,56,96,70,218,129,99,205,25,99,208,253,109,43,104,153,0,224,39,192,163,67,138,85,157,8,128,148,197,89,194,87,99,206,81,141,47,214,217,156,211,187,184,220,33,32,20,31,143,48,136,147,54,141,147,129,53,91,215,115,208,74,187,36,225,92,30,238,23,79,195,80,124,161,28,40,129,212,156,128,13,94,16,64,122,47,166,181,116,236,218,16,106,162,20,12,250,106,59,75,168,173,41,229,75,239,230,135,79,240,61,106,144,243,222,80,207,8,155,238,226,204,246,25,2,83,116,227,42,121,189,61,88,237,200,221,66,111,84,209,44,204,5,74,21,249,236,194,187,52,103,164,109,114,191,27,0,240,99,60,253,103,92,69,90,87,109,109,138,61,171,55,129,98,152,62,65,82,93,47,130,95,171,12,145,48,243,4,220,47,118,144,188,144,153,224,242,141,144,94,218,128,144,77,106,98,182,215,118,91,73,238,22,122,110,3,109,89,91,34,0,57,72,86,228,158,153,209,235,58,200,213,223,68,254,49,210,128,11,87,0,207,25,93,183,141,193,9,142,11,15,213,209,90,220,249,117,222,163,188,42,116,162,111,235,175,70,29,243,205,184,46,214,112,219,68,27,190,37,228,13,196,98,127,58,220,90,248,241,41,128,82,170,102,78,72,99,103,47,49,238,210,203,217,40,130,83,98,143,81,119,52,173,166,24,234,61,253,11,147,118,189,128,69,161,207,122,161,251,67,139,246,0,44,109,95,241,166,224,177,225,201,10,38,201,24,44,192,55,22,191,109,159,167,39,67,213,33,100,6,197,183,223,105,223,51,37,21,232,53,7,12,64,243,13,77,22,76,175,156,127,201,50,147,144,135,179,71,59,88,161,195,29,23,213,184,66,77,202,54,134,198,21,205,74,59,68,197,2,150,28,192,219,164,192,158,231,193,240,26,176,33,136,97,129,95,91,76,114,79,86,97,220,135,80,233,39,150,150,27,223,206,160,84,151,120,226,45,231,200,167,121,200,46,1,132,39,112,88,96,85,173,249,29,67,46,208,224,131,84,81,64,218,16,15,12,243,215,86,157,212,204,147,221,26,11,10,114,75,9,240,8,16,58,152,196,219,149,51,8,94,225,203,7,157,156,249,220,220,207,80,128,47,103,189,58,38,83,183,122,51,230,254,146,160,37,235,226,233,55,164,177,33,246,224,67,54,25,126,27,216,100,83,102,46,231,99,215,206,57,243,30,174,54,153,209,116,17,156,121,215,104,69,33,59,37,187,95,75,158,233,68,148,64,236,174,32,201,143,189,99,126,50,216,65,155,184,98,84,102,243,47,178,99,59,227,198,213,53,206,39,35,180,9,162,212,58,190,48,80,234,176,124,165,130,234,100,117,5,245,122,210,159,134,31,165,144,196,154,81,131,130,236,180,4,23,225,45,144,92,99,117,71,130,142,141,103,81,168,211,2,123,203,171,59,133,24,46,169,116,160,216,233,44,215,66,201,119,51,58,75,50,68,116,127,170,113,129,55,193,109,155,237,246,191,189,150,135,24,5,204,65,201,86,15,202,87,40,122,227,52,245,82,182,54,65,104,165,101,190,208,117,246,203,163,168,171,35,67,186,170,221,100,63,0,206,157,229,28,237,147,132,88,91,215,64,64,22,48,88,246,232,140,146,211,199,110,230,207,238,78,66,78,104,253,244,227,114,94,210,30,6,33,43,1,110,176,2,156,178,126,202,213,183,124,213,218,56,96,100,54,192,53,69,60,180,73,48,142,15,85,251,191,216,147,246,47,251,203,203,138,14,174,9,73,186,102,220,0,200,22,56,137,234,117,155,105,229,151,192,129,193,93,234,222,103,57,195,107,240,92,18,180,41,23,23,255,255,135,26,222,109,47,129,205,129,52,192,82,153,195,24,72,58,156,127,159,210,114,67,196,173,239,17,84,216,115,57,151,70,218,133,179,61,149,175,160,128,222,103,91,202,239,92,198,173,251,58,186,236,105,215,23,167,254,58,4,21,22,17,213,211,230,47,195,183,154,245,187,224,165,236,107,184,195,149,49,79,138,158,97,201,64,138,145,249,37,253,56,175,148,83,197,74,69,186,47,38,63,14,241,224,30,52,152,74,163,144,190,253,92,176,164,109,217,165,118,19,56,214,162,10,193,213,18,95,72,55,150,22,199,50,196,111,155,204,32,122,25,68,234,156,43,178,92,160,204,83,138,2,184,248,7,132,201,144,69,176,216,12,49,175,55,89,163,91,23,159,27,226,183,111,153,13,35,140,237,237,170,126,119,171,55,105,81,53,55,142,131,46,39,136,83,145,158,216,192,73,71,22,117,124,243,85,81,130,52,28,216,143,226,153,141,3,162,141,249,125,8,119,27,65,133,135,123,117,71,161,45,130,255,194,160,178,21,123,106,105,199,3,146,205,115,157,18,61,181,226,101,151,234,244,10,17,216,104,186,3,215,32,157,200,151,190,41,62,181,74,5,160,213,185,70,97,253,164,115,81,108,228,207,4,144,210,54,224,36,93,21,210,109,58,54,121,127,235,182,110,122,161,24,48,114,193,83,31,221,109,136,70,83,212,203,195,232,231,69,5,55,157,106,77,101,19,58,55,127,91,240,85,64,11,229,155,10,93,177,2,144,20,75,121,186,81,171,50,1,196,62,217,231,16,206,250,186,173,24,60,218,230,99,216,36,3,103,61,237,73,61,170,38,35,224,158,166,103,119,128,4,5,152,194,141,234,113,149,54,196,25,235,18,81,227,137,137,138,115,20,204,38,189,115,69,224,31,135,6,32,171,72,87,42,144,71,72,255,171,79,132,159,83,151,209,62,152,25,79,133,19,172,154,90,84,80,101,131,150,37,245,195,199,210,235,98,122,229,215,7,164,79,63,62,80,142,144,161,189,235,24,212,200,109,145,185,104,122,29,112,81,147,15,4,108,147,244,184,155,249,18,80,201,174,227,93,226,109,63,7,17,14,209,141,194,160,30,170,18,60,144,32,224,177,0,106,248,126,107,84,185,179,106,146,13,238,80,251,18,50,96,122,216,217,112,187,148,102,111,47,244,158,22,39,76,59,150,43,22,117,202,253,88,26,166,126,243,142,239,81,69,185,255,93,56,20,32,232,185,22,217,19,198,221,159,42,176,105,127,180,90,189,136,213,241,120,92,0,77,136,165,142,142,126,142,164,219,231,41,237,134,253,191,235,254,252,57,52,25,89,120,215,145,142,87,152,149,107,177,79,86,176,4,105,59,150,254,14,74,110,116,206,16,0,218,98,156,66,18,10,16,202,136,15,80,236,236,233,75,132,186,168,174,233,16,240,124,0,189,243,98,252,33,121,215,44,173,199,127,71,233,97,165,227,102,12,62,59,225,180,119,55,117,95,159,229,177,99,143,111,247,182,37,180,23,219,51,67,250,113,124,122,213,160,93,82,156,170,252,0,1,76,22,11,250,91,147,112,1,233,251,21,112,60,137,25,215,114,231,83,28,55,129,94,198,200,247,80,156,163,198,211,214,235,239,111,210,160,137,128,181,114,163,61,8,94,83,46,49,30,181,239,140,222,109,66,167,226,89,159,32,73,145,21,222,213,65,62,66,94,137,206,128,169,236,73,167,141,150,232,238,36,44,136,68,28,4,21,153,225,253,254,31,210,190,138,17,5,228,142,90,163,91,64,60,208,230,70,88,201,198,140,171,37,112,143,83,251,39,36,63,189,48,135,196,100,189,76,124,37,117,179,153,183,236,97,94,72,5,144,76,23,71,22,137,91,101,17,51,31,37,37,248,167,248,202,225,125,28,24,192,51,67,242,20,243,183,110,138,211,210,110,39,221,189,226,241,100,225,217,111,128,6,152,234,156,179,79,2,139,150,103,51,47,252,21,104,71,84,83,243,17,144,151,52,96,128,26,163,179,77,162,97,109,136,128,106,219,50,111,229,203,148,252,102,19,181,220,239,169,7,60,6,173,111,160,55,24,162,69,223,39,186,222,104,184,206,203,0,68,178,244,108,51,107,230,205,176,248,207,12,225,122,184,184,1,99,226,173,135,71,136,45,243,127,168,160,134,31,180,45,53,1,213,36,43,83,51,59,61,115,223,67,123,54,86,38,128,71,198,210,179,241,150,253,253,1,26,104,127,234,182,86,121,188,19,134,211,19,249,75,96,210,137,255,175,48,38,23,82,107,180,73,87,97,17,31,217,160,77,243,143,164,224,77,154,152,148,205,66,240,48,168,156,21,103,19,214,154,17,173,156,16,31,18,63,134,224,211,145,46,114,33,113,105,125,72,78,202,25,183,28,255,45,63,169,16,225,2,237,156,45,254,223,125,195,250,99,49,156,250,188,216,169,104,171,157,188,114,72,110,29,153,187,99,254,51,237,255,23,98,131,248,193,121,59,142,7,176,78,52,182,134,170,136,125,40,234,245,225,74,212,208,176,105,253,8,32,143,69,180,249,246,10,31,176,129,144,255,199,193,59,12,181,231,207,169,241,243,19,253,220,49,45,195,42,147,102,239,117,186,240,63,156,184,43,225,119,87,44,38,11,106,231,241,208,145,167,222,147,22,240,37,62,139,30,249,0,209,78,164,84,131,254,178,126,91,170,226,29,73,170,154,101,221,202,18,92,146,134,178,38,195,106,88,228,86,86,172,34,113,89,4,85,139,78,39,3,161,49,94,245,107,21,206,162,64,240,35,201,126,89,226,156,229,141,165,29,4,22,197,202,125,44,200,64,176,137,55,95,167,234,104,86,244,217,45,234,206,4,6,171,85,146,235,237,168,81,103,77,204,104,16,110,90,132,100,240,72,96,188,201,254,56,43,229,76,8,144,250,190,182,102,89,64,104,238,222,184,173,138,130,235,233,91,226,30,237,38,236,194,116,180,36,198,97,37,242,32,60,224,15,13,203,190,121,127,41,1,108,205,117,79,104,173,232,164,128,0,31,193,82,164,115,1,175,199,50,22,0,215,136,87,212,105,174,240,47,27,51,93,165,183,61,96,31,150,125,70,38,192,85,215,191,65,159,42,123,59,211,210,39,96,64,53,80,103,134,214,75,89,23,40,114,4,148,61,56,175,176,119,180,61,162,119,184,21,110,204,103,52,202,109,151,202,204,240,215,165,116,96,52,113,64,112,42,171,54,172,169,69,253,44,153,24,232,19,141,73,3,80,141,143,57,23,209,218,79,5,176,20,117,197,223,97,0,0,216,103,205,251,42,189,173,104,182,224,240,187,184,90,150,165,151,54,237,248,21,195,252,26,86,186,43,130,85,173,165,88,77,47,61,60,251,197,177,40,114,201,153,72,161,39,61,136,217,22,39,227,180,112,20,184,0,22,255,248,87,132,120,113,8,6,226,212,166,57,112,185,75,15,83,79,196,106,136,205,5,59,250,63,35,80,140,176,236,196,248,3,221,98,250,104,32,99,152,165,109,139,192,40,49,68,14,50,89,102,202,12,64,120,114,49,227,205,144,18,43,180,65,47,167,89,67,145,180,44,241,173,23,232,86,141,103,210,72,240,225,180,133,221,238,4,125,161,121,44,204,5,162,64,34,84,167,152,247,154,190,162,116,71,83,180,181,174,3,151,227,180,162,28,198,133,1,195,199,54,251,220,4,182,126,209,15,24,207,187,240,50,11,120,250,158,87,125,246,74,64,175,190,21,150,255,202,170,125,38,228,16,24,166,186,7,113,0,133,182,112,138,188,2,24,120,236,10,76,154,89,48,23,228,159,219,144,219,209,76,59,25,100,202,46,203,178,117,252,97,240,97,42,143,205,52,199,220,7,0,109,217,139,126,170,178,227,213,192,16,171,133,173,237,240,186,6,14,155,94,157,194,99,123,174,181,74,164,126,56,178,0,172,77,163,74,172,53,5,161,130,161,162,149,232,150,69,170,172,59,70,142,112,87,58,16,192,67,8,250,29,140,221,17,117,167,133,43,180,141,157,214,18,131,114,105,147,206,25,138,207,188,30,41,9,97,113,247,123,251,56,165,182,239,95,79,152,45,113,160,213,230,249,227,167,149,52,172,156,182,242,134,61,19,90,144,248,100,252,168,76,213,246,126,123,175,8,114,218,41,247,90,229,94,238,86,73,43,35,42,116,168,217,75,167,166,122,230,82,130,255,164,51,9,86,79,111,49,152,198,132,96,62,12,131,23,66,96,51,213,29,13,144,20,26,228,66,41,228,68,254,126,173,192,51,62,41,184,136,182,93,102,144,250,65,236,200,19,121,182,87,125,72,97,132,164,29,130,211,26,115,217,177,199,35,54,132,98,87,138,188,229,34,130,240,81,186,231,130,41,17,74,64,27,41,169,251,229,192,38,247,81,85,224,10,181,80,164,164,112,73,150,53,119,166,144,157,52,98,187,48,28,64,77,33,237,100,1,46,123,40,27,232,128,105,190,126,27,132,205,16,107,184,30,187,240,29,128,81,177,9,175,37,159,188,53,109,59,15,33,102,39,182,31,73,163,176,14,150,178,216,231,41,152,253,100,240,46,106,181,137,111,240,101,204,74,57,134,179,49,230,134,124,152,70,64,166,43,65,203,80,53,157,166,39,138,142,243,74,145,217,9,194,93,128,67,93,129,161,161,254,211,189,239,205,32,171,253,118,141,204,240,183,222,146,198,220,187,58,201,238,218,179,206,89,183,40,198,33,53,38,40,144,216,247,161,189,216,173,9,22,72,148,174,45,3,127,35,125,111,140,15,207,119,246,38,244,195,69,85,106,121,28,241,125,124,103,116,108,152,84,133,165,68,92,5,189,160,223,125,159,69,84,91,214,24,52,36,207,180,152,8,156,70,209,194,220,165,138,212,192,246,132,124,186,64,218,179,23,131,210,117,7,15,197,250,249,187,104,74,19,195,232,168,66,171,125,133,252,89,123,236,67,152,150,187,82,161,241,29,160,206,15,254,101,201,34,79,182,6,88,237,204,67,3,24,199,64,58,22,71,118,31,80,235,148,111,111,74,248,229,15,0,160,215,0,121,227,15,243,58,122,251,203,236,223,102,217,235,105,113,239,209,206,227,198,166,116,250,85,48,71,14,78,216,2,167,129,129,240,167,56,89,118,161,125,49,228,56,221,13,219,207,36,68,253,27,45,219,117,151,229,111,247,206,97,173,132,8,74,182,16,125,54,238,31,46,244,50,250,3,216,182,42,120,67,61,39,106,101,23,248,21,80,151,115,41,105,95,47,32,90,53,3,164,31,12,113,105,26,135,101,186,43,191,173,143,177,4,75,109,96,7,121,5,231,218,250,45,96,254,193,146,225,251,238,21,240,27,207,43,187,7,61,254,195,234,210,152,46,241,186,188,216,234,82,179,109,61,190,139,211,58,36,74,149,107,249,150,196,71,226,167,232,40,42,19,152,17,194,16,94,5,11,57,37,43,99,98,248,81,211,60,69,192,80,94,225,241,197,53,76,100,1,166,253,132,17,3,72,232,72,214,60,18,151,159,15,167,78,27,76,142,22,21,129,121,10,185,35,246,49,165,218,73,182,236,65,1,175,236,230,71,209,189,163,164,179,194,209,86,6,180,219,147,94,15,212,246,83,21,183,250,40,230,78,222,159,74,94,13,20,247,51,90,218,253,125,50,81,72,93,1,200,50,199,223,192,197,223,38,208,98,122,118,7,82,178,154,193,50,199,199,7,184,231,120,39,2,232,41,182,32,75,56,236,176,5,0,113,190,13,109,1,175,212,249,89,21,130,204,162,228,119,244,190,87,252,151,13,40,209,103,93,95,199,103,141,133,122,94,189,161,222,26,229,214,114,137,110,97,84,81,251,213,80,122,215,144,113,154,105,12,130,191,24,0,226,159,46,86,119,142,104,231,72,118,224,91,195,94,179,212,168,32,243,2,25,219,4,197,34,167,252,198,18,155,87,88,62,165,118,253,176,96,152,186,128,214,140,226,59,11,113,104,102,96,136,126,9,13,140,165,46,116,134,52,249,105,131,168,226,83,93,216,194,247,236,251,159,42,118,243,93,85,175,120,106,134,75,146,217,187,183,49,138,190,5,189,3,203,106,166,110,104,108,70,111,165,41,203,34,212,254,32,10,2,238,30,243,126,47,119,175,63,107,73,75,131,105,17,54,253,158,128,179,196,198,64,151,178,55,47,159,191,106,78,234,208,198,108,42,131,2,33,44,121,43,48,137,107,252,205,15,84,242,200,169,148,239,199,117,248,6,151,51,83,45,149,57,75,160,202,27,122,235,14,50,90,135,90,94,140,171,241,123,236,90,200,243,190,6,111,165,246,139,34,141,151,172,38,34,66,201,218,83,110,52,12,146,6,26,248,102,120,174,193,25,147,171,152,87,174,79,55,208,166,73,111,90,214,25,117,239,102,226,213,182,128,93,49,129,174,3,2,180,9,250,166,8,32,141,187,26,55,157,229,144,64,195,91,154,133,56,176,6,198,60,119,115,232,70,213,143,59,250,97,136,50,75,125,198,19,151,141,168,48,163,47,67,211,114,119,103,69,9,119,244,236,196,164,248,228,69,215,205,245,16,57,177,244,43,224,109,172,45,14,5,161,195,63,81,38,117,19,125,248,179,103,199,168,84,151,192,55,216,72,96,43,117,199,103,51,202,42,177,40,169,84,157,153,173,244,141,108,142,38,188,53,35,151,221,147,12,148,111,151,129,212,37,253,142,191,152,21,241,153,150,30,71,95,49,124,83,150,47,109,169,199,96,70,141,167,74,79,11,152,159,93,215,159,185,141,249,140,114,217,75,87,133,177,114,114,27,32,86,10,246,20,157,127,160,164,227,79,194,177,107,49,142,179,84,144,135,178,81,30,7,228,120,116,11,103,210,83,15,94,77,40,116,144,27,125,81,192,231,217,112,4,184,78,6,144,65,184,221,84,114,52,150,241,217,130,114,219,252,15,34,244,209,76,178,193,231,229,38,137,147,0,147,242,150,26,33,32,28,132,60,63,134,221,9,214,135,97,120,217,109,78,130,199,253,153,215,234,19,186,201,199,169,20,132,151,74,179,54,65,25,171,126,126,88,23,247,222,39,52,65,85,45,245,229,214,38,98,14,0,10,216,42,17,230,34,91,84,144,209,31,186,211,140,175,188,80,202,99,174,124,88,40,32,214,235,133,253,145,179,186,102,42,135,61,67,235,163,133,41,35,25,168,87,141,24,186,210,233,150,19,220,120,81,123,169,245,18,197,27,207,176,15,197,115,139,69,152,82,211,148,77,184,232,173,29,253,46,123,173,245,217,54,231,135,218,236,101,196,45,109,136,189,206,68,215,214,77,251,43,39,224,144,62,135,50,114,247,67,110,247,38,143,220,5,1,173,142,88,7,149,152,225,194,10,114,152,121,105,239,242,249,117,29,172,2,39,98,218,33,31,69,93,11,210,222,132,40,251,162,173,144,13,165,165,242,181,202,215,89,196,228,253,39,70,73,153,144,63,184,211,2,204,107,51,166,197,173,14,15,96,66,141,11,12,244,148,50,16,214,9,8,52,6,165,105,91,184,10,10,62,135,250,200,159,69,227,229,86,98,229,73,27,200,217,108,233,211,81,90,93,45,50,50,149,19,35,23,116,202,113,21,211,33,217,140,128,86,228,185,130,140,104,87,180,174,131,213,254,48,90,67,239,159,204,139,229,42,236,142,82,151,187,165,11,12,150,53,56,10,76,97,213,117,217,51,242,133,135,229,78,117,95,26,31,69,32,138,147,70,226,136,42,0,8,199,224,233,35,206,48,207,61,99,52,101,204,118,143,245,236,120,33,226,57,223,53,32,255,6,236,127,223,89,137,99,84,204,80,106,20,237,64,149,193,65,7,41,202,120,56,115,112,137,35,254,243,28,47,4,229,33,115,177,48,219,231,48,63,139,95,214,209,6,170,197,116,222,104,88,254,141,16,48,222,226,9,47,121,65,188,142,38,129,229,60,122,25,131,229,78,249,211,139,93,199,181,248,231,247,38,161,131,223,146,216,88,123,189,77,186,220,2,185,53,173,226,101,153,213,103,171,140,207,44,51,120,168,36,182,213,176,87,166,170,61,250,49,139,249,215,135,168,170,59,95,118,142,249,166,177,121,94,175,159,219,228,219,117,28,222,43,180,225,108,140,7,25,5,94,45,171,5,65,137,255,40,123,190,89,181,94,76,172,91,161,197,240,85,79,172,28,47,57,205,233,102,137,143,28,155,20,20,157,41,148,175,43,167,5,82,171,148,109,247,237,236,176,176,124,1,158,189,93,168,51,115,231,208,228,55,164,123,212,27,25,190,38,1,120,25,153,91,236,95,116,67,210,173,224,156,220,91,207,120,91,114,212,191,71,198,205,146,136,65,91,33,204,192,154,155,243,71,11,55,239,100,89,204,247,199,59,120,22,68,109,137,194,203,81,61,247,11,226,242,210,155,195,209,1,193,108,163,178,20,22,170,30,148,214,80,229,153,91,103,246,237,10,245,110,211,150,205,98,239,92,94,71,206,91,253,204,90,157,216,152,35,148,167,8,201,167,24,239,191,158,102,23,131,159,64,99,81,159,58,193,185,68,1,28,24,38,198,132,80,191,19,122,235,99,129,100,49,253,29,52,194,32,108,106,166,243,179,53,189,96,59,73,241,61,32,223,84,218,118,59,32,64,9,98,239,207,219,101,38,106,54,148,148,25,5,50,107,106,152,242,117,192,102,56,184,19,232,133,157,243,182,52,144,217,94,101,153,221,88,157,52,224,159,93,159,71,2,115,200,230,116,202,177,236,75,20,176,16,39,147,24,150,195,21,251,77,57,185,113,216,168,48,127,164,56,104,92,23,85,141,159,93,53,192,103,163,130,24,85,85,160,61,246,23,185,196,18,158,228,129,148,126,206,52,198,191,182,12,98,112,31,56,160,62,208,196,234,1,56,249,23,61,115,25,164,254,151,45,11,124,107,53,151,131,221,52,249,185,90,5,4,129,177,134,168,239,37,50,111,225,178,53,251,9,5,87,32,111,75,239,38,160,33,50,128,211,5,250,31,61,177,31,115,182,221,118,33,225,75,165,5,43,89,152,62,217,185,246,122,194,98,47,193,42,74,46,144,111,16,231,76,88,151,7,93,68,144,237,82,117,206,167,239,6,137,55,125,14,88,92,201,143,148,62,216,55,224,150,178,38,77,42,167,163,233,124,131,220,55,50,219,117,225,244,220,233,124,27,133,246,213,86,54,152,29,92,98,226,98,54,110,144,186,41,161,225,72,199,30,105,121,160,56,141,23,100,40,88,208,169,32,196,122,95,231,57,244,199,120,13,232,165,250,170,24,34,231,23,205,33,18,214,128,56,165,14,48,104,223,133,183,73,58,100,111,112,115,239,70,81,81,38,94,88,232,164,212,242,0,59,114,36,133,89,252,41,204,37,193,144,244,255,242,124,20,131,112,126,131,187,205,71,229,86,90,197,199,245,45,120,190,56,223,164,63,177,75,188,238,180,176,137,182,95,221,29,158,104,4,224,38,183,94,172,67,44,62,168,237,218,85,159,58,25,168,173,108,204,228,81,18,145,207,176,19,10,212,78,133,108,169,178,117,11,19,155,152,200,117,243,99,143,126,93,75,167,4,103,249,245,27,30,184,78,162,35,174,200,4,59,119,138,195,58,130,59,179,147,48,207,134,201,207,31,90,145,168,212,195,79,220,16,253,80,24,42,159,61,178,241,81,140,246,198,225,166,94,74,63,254,3,218,93,2,74,194,239,192,68,55,75,132,51,79,200,162,72,133,34,87,86,7,157,235,37,94,78,191,150,81,213,162,147,20,232,243,173,36,1,244,91,3,192,10,224,194,229,74,147,19,192,165,168,153,5,127,230,113,185,206,127,146,80,114,246,179,16,31,90,0,242,254,82,189,36,246,211,7,118,168,33,154,220,184,107,101,40,150,196,194,242,253,216,72,132,210,147,230,224,198,34,75,25,74,233,205,159,168,6,197,50,217,127,251,94,27,0,89,55,171,138,10,197,251,46,127,84,139,97,212,131,44,89,5,181,154,11,223,2,106,249,29,222,72,44,89,57,56,8,138,102,140,86,159,219,77,239,32,203,126,142,214,192,72,16,119,161,71,155,250,58,115,189,112,51,213,249,25,85,78,170,171,102,164,103,133,109,37,229,130,167,116,64,21,234,76,246,89,206,141,235,89,223,141,56,47,168,166,97,190,26,197,70,97,133,200,148,53,45,183,39,129,38,122,174,116,58,75,115,221,204,101,52,24,94,177,14,237,2,172,234,210,8,208,25,77,235,113,24,108,216,242,184,180,255,173,101,240,51,246,200,240,13,156,209,93,60,66,170,252,82,230,13,215,146,117,255,210,7,34,122,10,106,156,176,21,68,222,248,33,83,152,206,191,60,18,158,149,114,74,41,60,203,244,210,249,189,212,25,25,75,131,95,76,207,254,188,23,124,249,162,255,170,137,0,81,97,181,221,127,2,120,240,234,80,28,115,105,158,136,89,77,135,103,255,251,8,186,242,63,176,164,122,8,11,128,19,58,243,8,212,252,204,84,170,108,158,179,247,0,254,32,87,139,213,136,45,180,92,145,67,92,246,247,205,97,103,87,101,163,137,0,61,23,230,147,218,153,102,235,104,17,24,246,70,190,79,179,238,178,41,56,128,115,241,148,114,229,173,144,63,54,151,123,191,45,145,222,89,230,29,59,34,163,123,120,56,34,137,149,161,32,221,255,87,39,50,57,112,84,159,209,51,170,143,167,190,117,145,202,12,127,248,132,142,52,118,154,247,22,242,179,161,240,146,155,7,176,79,18,1,228,242,227,81,34,121,92,236,105,176,207,233,51,86,159,119,70,173,14,42,103,31,241,149,157,98,49,61,96,106,94,142,12,146,88,63,16,173,84,14,216,170,188,7,119,188,94,156,24,78,218,117,39,252,216,201,136,241,118,24,231,164,15,9,211,193,68,14,9,140,214,99,95,235,172,219,136,83,12,95,75,88,48,152,236,153,95,137,236,38,125,35,176,220,87,52,101,106,40,172,224,140,105,118,201,227,143,43,59,162,152,247,197,72,70,232,183,21,160,2,64,169,41,69,166,102,52,189,217,130,19,196,230,34,133,35,31,17,193,45,252,112,79,79,223,99,168,154,14,19,74,179,41,246,27,199,128,101,54,80,252,173,165,241,80,26,204,142,255,57,94,25,56,246,22,133,229,144,110,212,118,251,36,49,81,254,183,116,222,99,70,181,22,74,96,199,161,124,176,7,199,9,56,128,64,200,185,222,37,225,144,156,152,22,99,76,208,43,99,207,169,146,220,182,136,30,96,166,118,49,125,40,132,106,49,212,158,91,55,84,208,213,75,63,190,113,71,83,98,109,21,176,11,204,253,157,79,106,111,232,239,253,187,98,141,32,52,39,209,183,100,176,183,32,232,137,209,189,13,67,230,44,99,233,235,31,211,62,149,120,185,114,79,123,8,153,151,112,255,65,154,228,16,226,177,21,18,10,146,172,134,181,123,4,253,122,188,229,98,89,112,147,19,145,108,246,176,210,201,128,231,96,230,39,140,7,175,246,144,253,114,34,223,14,48,134,160,78,112,135,138,197,142,208,213,221,156,197,198,131,42,169,203,191,140,36,205,131,59,11,239,147,205,235,193,132,59,199,198,42,204,244,120,24,172,221,253,85,141,118,110,76,153,91,146,222,142,200,251,52,172,145,250,47,123,86,49,253,220,27,77,170,51,36,179,148,26,32,251,162,197,246,163,248,65,123,233,68,194,166,153,206,118,238,22,134,49,13,218,176,11,183,124,197,148,169,251,224,80,11,209,166,233,229,19,220,114,244,144,246,17,131,119,108,78,6,26,238,121,82,13,57,179,139,149,164,255,235,181,20,240,76,155,71,61,89,192,100,16,244,93,71,199,139,70,203,107,44,233,154,66,40,255,1,15,20,206,89,244,23,68,123,164,177,175,187,170,150,195,150,44,96,99,142,169,220,220,197,235,124,72,198,60,112,180,196,35,190,154,107,29,177,10,243,111,210,61,157,156,223,255,101,5,210,27,224,15,23,138,119,65,201,139,134,84,70,122,22,204,153,5,193,108,54,149,173,173,37,200,81,229,93,72,7,45,14,51,177,85,166,96,189,55,43,70,88,172,251,17,221,163,81,62,196,216,14,31,82,46,38,65,125,42,32,4,9,145,100,31,102,106,231,86,31,167,246,39,11,28,118,34,92,179,80,65,191,115,43,247,211,118,115,124,156,122,145,222,177,73,161,7,117,51,20,29,178,100,26,127,202,208,177,209,121,101,140,194,20,229,139,123,55,186,209,31,33,39,115,64,97,128,152,60,147,70,35,97,4,156,87,181,58,244,132,109,115,229,91,215,10,28,25,21,57,163,234,21,101,81,18,220,78,130,105,85,41,164,78,228,156,201,182,234,93,221,241,194,212,66,84,4,11,81,116,94,234,37,200,8,214,228,253,58,205,250,62,168,189,1,46,223,0,158,154,29,127,247,188,25,193,165,228,117,234,121,149,167,254,11,3,15,12,91,42,46,11,240,230,134,120,108,46,58,63,23,230,140,113,173,206,94,55,63,20,187,32,255,142,32,192,135,161,231,95,115,204,50,125,129,245,15,153,89,124,35,87,200,91,78,68,126,100,158,103,224,232,192,132,174,34,19,19,48,139,182,247,255,70,88,227,139,253,31,10,222,62,188,140,85,169,143,143,14,29,108,159,46,98,211,30,129,63,149,77,230,246,61,181,103,153,124,242,214,63,70,78,193,78,208,159,94,20,59,30,81,88,112,124,123,183,101,239,217,86,232,137,59,250,5,110,107,71,27,31,15,33,62,200,161,218,153,82,134,5,7,141,180,7,152,169,23,182,33,150,252,223,90,209,54,177,15,50,19,8,253,37,226,84,143,33,164,230,38,215,102,42,156,198,36,35,149,175,75,79,102,252,69,215,7,165,103,252,189,221,18,204,32,86,110,22,47,74,38,247,11,126,5,145,242,247,20,9,190,177,121,79,16,110,73,41,45,141,3,247,35,3,252,191,45,7,156,127,115,198,74,194,5,25,124,110,61,109,115,151,84,72,182,140,170,23,217,123,133,98,143,18,53,128,55,78,61,89,152,214,253,63,133,196,183,215,107,107,158,245,129,15,153,169,246,158,65,172,8,47,226,30,126,10,64,163,175,108,218,130,19,89,235,34,206,150,176,199,6,140,234,201,165,130,107,208,64,112,36,44,115,250,199,236,204,60,127,43,124,225,163,49,76,103,210,254,126,180,82,44,230,68,93,12,246,201,186,72,190,172,76,128,42,173,0,221,120,14,150,19,197,121,163,71,111,214,183,143,24,187,70,13,255,228,250,134,173,209,183,166,208,21,225,94,109,145,98,70,255,76,151,190,150,183,152,248,238,224,187,111,4,2,111,236,73,135,133,67,34,193,94,52,159,42,187,59,38,75,152,72,134,112,236,191,233,150,43,156,14,167,70,226,7,114,200,31,140,164,33,84,232,169,15,96,172,175,192,57,229,71,227,101,139,17,90,45,154,32,255,204,159,141,200,159,147,45,152,135,128,51,11,78,181,154,83,92,144,157,134,244,234,140,201,95,218,104,165,146,35,28,223,139,111,128,149,30,162,119,191,217,136,196,219,138,212,22,168,182,19,118,34,168,68,234,104,231,59,166,128,52,254,212,215,218,117,66,31,249,88,61,78,33,130,242,94,66,17,169,102,100,130,251,1,125,169,71,110,165,239,246,162,251,220,185,184,20,76,133,171,122,57,219,218,181,169,220,38,166,27,206,53,166,180,135,172,64,7,187,131,182,110,67,34,191,25,145,197,184,217,30,140,72,15,212,194,123,34,239,194,64,110,117,35,199,82,17,157,252,230,226,228,44,151,158,81,101,191,59,18,175,143,139,235,12,185,50,15,106,29,143,82,247,211,52,208,35,153,64,11,50,37,13,38,232,128,45,104,62,240,201,122,137,83,140,250,178,64,142,202,168,54,119,221,215,71,166,35,108,71,223,239,99,153,12,8,134,64,200,182,235,107,96,111,231,153,200,254,189,247,49,93,127,4,200,77,43,160,120,224,252,243,224,46,190,166,143,82,46,207,86,235,116,203,190,88,18,55,121,70,227,215,107,69,58,245,221,133,33,73,230,34,36,254,49,127,129,180,253,175,209,180,54,94,124,96,104,97,243,225,38,248,166,230,189,233,78,38,61,122,43,51,76,9,219,127,1,239,79,151,48,213,26,208,118,80,108,178,180,167,38,224,5,87,106,12,73,252,109,195,190,244,1,237,106,212,236,116,74,192,255,121,219,152,67,18,77,38,21,51,27,121,200,196,0,84,219,179,46,124,54,85,12,179,49,241,46,197,14,33,28,79,227,246,94,112,66,187,209,230,116,161,40,15,78,57,156,110,138,178,73,41,255,178,62,43,236,180,171,248,21,243,240,13,110,71,67,79,176,57,76,207,194,20,219,223,36,60,83,50,200,87,245,137,235,132,89,144,67,4,174,55,221,14,212,138,175,187,209,186,54,80,178,238,243,36,9,199,108,128,111,120,61,208,105,53,44,233,236,78,63,226,71,197,238,242,101,100,227,70,160,209,41,198,56,65,115,138,237,132,126,95,23,46,122,98,177,164,159,251,98,212,145,111,203,95,36,21,53,163,88,57,51,139,255,60,181,38,187,107,75,128,165,215,232,130,56,103,173,192,192,119,72,104,142,246,79,232,200,17,207,225,61,55,106,74,61,126,180,229,233,187,223,190,82,11,232,15,84,52,13,98,154,199,134,191,227,132,219,235,17,230,249,92,249,34,165,54,132,101,234,209,220,66,6,69,181,50,132,160,155,246,171,5,167,56,49,27,175,90,222,36,13,217,116,128,9,151,3,203,43,43,40,205,132,14,248,28,88,180,107,146,95,19,175,0,109,41,170,148,148,54,179,0,71,101,59,99,221,143,205,42,59,156,112,136,31,59,18,231,136,191,41,46,122,77,101,152,172,123,108,116,111,53,229,4,163,218,156,39,171,198,100,223,236,90,205,126,143,72,67,138,159,241,118,154,239,154,219,34,182,123,33,163,113,46,15,249,238,36,50,215,132,241,226,207,196,181,96,162,212,88,224,190,81,179,12,136,146,122,238,83,129,26,72,105,125,20,146,253,67,112,232,12,188,96,52,161,160,121,241,50,77,49,218,20,78,169,246,196,95,213,12,11,243,170,71,1,244,78,233,115,143,34,201,250,23,100,9,97,17,4,211,193,128,42,106,170,138,9,75,28,208,247,157,32,4,210,106,87,15,97,167,209,22,160,123,52,183,148,194,21,14,53,212,119,43,76,147,154,56,43,175,79,109,103,68,93,115,95,230,242,89,230,162,136,47,37,79,109,220,24,217,83,40,241,45,113,250,138,133,115,120,72,115,222,65,36,226,44,1,172,128,192,152,113,44,162,139,24,194,114,139,90,162,31,228,198,129,96,97,224,87,232,183,43,193,104,251,129,67,148,240,227,100,4,27,202,89,241,226,221,189,142,102,74,1,234,197,88,247,95,217,142,161,58,118,124,174,252,162,242,248,126,19,199,138,191,202,209,59,204,127,100,65,187,50,108,197,107,107,205,55,228,48,246,168,68,28,74,186,102,54,116,29,188,57,221,206,122,202,240,151,15,23,162,146,91,12,88,51,69,3,110,205,52,5,186,49,46,171,126,221,23,30,236,45,162,17,198,211,238,177,147,106,5,203,206,78,143,1,167,153,96,15,225,28,219,223,209,68,221,218,102,32,19,138,90,130,254,63,73,240,165,99,150,83,198,65,210,22,92,216,204,186,182,213,249,35,2,80,190,138,101,47,225,210,232,29,85,90,174,228,82,244,173,189,193,47,20,238,93,189,172,27,25,87,244,243,224,87,201,186,153,42,69,160,195,77,180,136,128,231,197,161,163,94,0,191,87,57,125,254,155,170,223,110,165,95,181,188,82,153,240,68,118,58,137,253,184,248,35,170,207,20,197,246,93,21,36,48,195,147,75,92,94,166,34,77,198,225,189,122,91,111,136,32,138,146,132,33,113,35,32,184,97,10,255,132,98,61,203,100,65,30,160,150,30,85,22,8,32,101,187,142,240,176,3,67,219,207,113,202,242,213,177,61,155,141,225,69,7,10,3,184,65,132,69,241,149,214,97,91,168,150,187,136,18,190,15,66,134,232,239,202,169,247,10,160,246,157,238,77,41,185,221,165,157,108,94,145,231,229,169,101,1,167,15,161,20,158,211,139,204,107,228,206,211,185,65,246,158,167,12,107,190,45,182,28,192,44,106,148,62,159,222,82,10,227,237,251,3,151,152,139,76,162,183,169,202,107,181,200,129,195,124,71,208,135,234,26,203,154,53,208,137,99,150,100,142,114,50,153,183,126,133,1,253,9,202,235,65,46,106,126,8,5,105,93,53,17,35,209,62,117,114,152,57,29,66,71,127,2,130,103,158,7,17,86,195,64,229,219,75,195,212,33,209,50,154,59,27,177,135,24,163,107,219,137,197,220,7,153,96,131,0,65,187,83,25,18,15,100,245,27,6,174,119,25,182,124,115,158,7,84,182,105,34,75,231,222,190,48,233,221,49,119,79,153,174,200,28,223,87,37,72,254,237,189,199,23,239,255,69,27,152,251,104,233,142,231,80,48,149,197,234,170,200,149,73,120,9,20,212,128,69,99,144,23,22,83,89,207,47,19,17,198,156,214,226,55,130,85,146,54,5,58,224,214,6,27,36,31,164,126,182,225,53,4,52,100,11,28,220,125,41,101,102,215,188,97,6,55,113,252,140,78,81,115,58,203,129,115,132,109,206,21,68,78,20,128,95,62,34,72,211,75,41,78,234,223,115,175,57,229,107,227,179,9,162,15,86,211,207,126,44,120,162,65,99,15,187,57,91,18,41,138,119,15,37,90,138,187,40,13,121,164,30,26,160,7,116,143,9,149,10,228,215,85,75,134,113,241,72,248,12,116,160,177,187,166,188,208,252,178,182,169,220,121,139,203,135,116,198,224,193,215,214,189,110,168,68,129,130,192,8,226,15,122,181,16,37,227,17,156,38,246,249,4,89,193,12,237,32,109,66,52,139,50,235,10,231,210,19,204,191,161,192,238,27,142,203,62,146,194,119,135,132,70,245,214,127,209,179,254,19,43,72,110,124,118,71,34,142,134,163,182,130,140,131,160,56,194,13,10,6,8,136,131,171,206,237,108,163,127,8,17,208,116,17,165,125,236,166,45,180,115,123,110,117,255,84,33,201,176,66,60,220,2,92,128,59,50,147,27,232,7,251,48,118,128,215,225,182,113,163,1,165,184,212,132,246,28,57,13,84,140,97,222,230,172,120,254,160,216,70,239,215,0,111,160,68,51,0,31,109,79,49,38,221,94,95,37,226,200,239,75,160,227,1,122,27,49,244,122,133,67,125,60,12,216,60,89,219,92,146,252,169,205,31,71,112,119,174,142,76,205,10,173,28,31,26,119,222,159,151,151,214,150,124,197,51,174,17,3,58,240,120,130,175,51,87,155,106,76,197,143,86,226,95,45,72,196,34,230,99,248,121,236,163,207,67,132,152,165,42,252,107,111,171,10,114,221,71,94,190,87,197,251,236,116,86,60,82,253,64,166,236,178,150,126,252,230,179,186,45,52,123,29,16,175,237,157,13,213,215,69,153,217,233,51,38,227,186,80,200,188,65,110,196,78,3,202,66,175,161,253,111,249,120,23,44,176,170,211,138,243,128,128,115,108,85,27,23,107,91,1,212,31,154,136,228,166,30,96,59,92,34,162,61,242,225,232,47,195,154,45,144,74,125,246,69,128,166,229,187,39,196,152,5,66,133,189,18,245,235,31,214,153,14,205,11,130,1,238,167,83,107,14,41,235,8,139,62,37,74,87,110,189,142,226,150,1,219,52,58,115,150,62,55,66,239,30,11,157,138,57,159,200,148,184,237,250,169,248,88,159,137,188,98,30,50,189,59,15,225,149,129,184,102,146,114,254,181,178,143,54,171,186,63,219,29,83,52,76,222,208,189,242,11,81,188,87,249,54,213,162,246,147,7,72,54,22,48,119,146,108,131,16,194,137,175,45,132,109,33,243,243,40,190,135,54,116,177,29,228,193,151,91,207,114,183,37,198,58,44,53,196,42,118,27,144,95,155,137,80,255,233,76,228,204,81,135,24,99,82,230,130,134,134,90,185,64,21,78,113,200,124,44,66,8,202,250,219,158,245,90,117,100,130,99,79,193,113,76,66,140,147,91,76,194,35,42,183,235,58,162,251,48,190,103,86,96,173,72,202,179,222,118,203,182,225,42,46,211,245,250,204,238,192,46,2,210,178,141,212,84,160,233,228,60,100,58,151,244,252,138,108,189,119,187,104,222,9,36,11,182,33,204,41,164,233,176,152,233,86,233,50,206,99,64,128,110,66,233,201,123,179,225,189,88,55,210,152,178,238,149,204,213,200,212,190,228,170,205,255,165,46,209,51,91,74,229,36,181,120,52,6,82,169,229,225,218,231,110,222,218,6,179,193,106,30,34,243,244,157,149,112,198,254,119,89,250,217,97,62,28,209,188,203,80,211,129,242,222,66,129,254,133,112,29,113,174,62,6,239,237,224,23,116,214,189,215,75,239,171,17,204,68,178,19,31,37,201,108,153,71,126,166,217,28,201,87,186,193,62,200,110,44,41,74,172,66,60,174,120,134,18,85,137,113,240,138,170,198,225,97,115,26,202,243,51,96,31,18,185,179,52,52,98,63,170,11,216,247,18,9,35,203,107,220,12,6,21,178,236,232,102,112,57,211,73,9,28,24,100,146,157,25,199,182,169,71,71,6,60,175,82,210,8,190,110,18,136,70,15,43,13,60,52,12,43,123,111,248,2,36,45,160,215,73,52,54,36,80,105,210,238,113,115,116,84,251,91,72,109,192,195,188,108,51,89,2,189,86,142,28,210,69,246,138,253,85,224,49,223,6,47,125,40,72,173,56,214,70,132,134,51,244,168,101,112,151,126,77,102,143,239,4,13,116,106,10,103,119,126,65,6,31,18,107,68,76,241,127,130,133,186,61,250,68,253,189,150,134,117,83,51,83,25,187,118,78,134,35,123,184,148,245,53,68,14,88,131,0,68,159,141,48,76,196,130,198,34,56,19,203,64,75,87,26,133,28,73,19,242,167,183,2,251,172,114,9,7,155,151,79,86,68,141,54,101,212,74,210,65,219,237,175,83,252,71,245,207,108,46,196,105,180,46,85,217,5,128,221,226,157,62,176,224,25,140,26,228,142,51,187,96,116,42,92,18,197,211,133,4,0,207,161,141,187,60,8,215,220,174,187,41,153,27,83,242,133,205,30,135,7,207,178,168,111,3,85,173,149,137,68,187,204,184,237,209,59,41,154,36,35,7,212,199,183,241,25,178,86,195,41,137,201,81,164,246,218,251,180,218,161,189,193,147,17,147,15,78,69,23,170,86,93,28,58,170,81,208,143,20,240,63,182,158,203,197,94,135,254,11,135,124,183,89,193,71,88,184,98,208,164,134,197,140,75,234,159,83,20,177,109,123,195,118,229,245,116,207,220,6,11,187,253,37,198,220,195,29,176,38,46,67,200,232,90,245,23,105,165,133,57,29,208,185,232,69,180,3,5,19,111,91,226,98,197,90,102,20,243,203,137,88,156,217,18,24,141,253,17,194,150,75,120,212,232,5,187,191,80,176,71,27,94,71,149,230,108,103,17,129,248,166,186,196,171,152,249,136,146,130,38,204,223,106,175,46,105,241,113,125,212,159,243,233,110,229,177,187,141,186,157,99,212,232,218,25,58,4,212,122,110,11,236,187,184,12,168,127,135,212,37,81,184,79,102,171,143,151,189,158,113,56,80,94,110,58,223,118,37,73,53,158,134,151,251,250,216,143,88,233,8,206,211,238,115,195,53,186,238,140,128,150,50,225,14,236,49,195,224,75,85,229,24,20,244,72,136,144,15,96,152,6,156,158,133,144,200,229,50,186,234,205,77,101,31,5,147,136,55,31,158,100,141,179,213,225,15,161,176,225,156,40,169,60,57,227,45,170,44,97,107,83,178,31,102,192,84,212,43,159,32,188,252,47,248,53,6,68,8,126,187,27,46,133,214,4,199,153,29,177,123,35,170,100,66,253,178,46,37,206,97,62,17,208,98,178,195,223,64,76,251,94,132,241,102,36,130,182,53,98,94,253,122,211,197,204,144,195,101,203,40,158,215,192,102,44,87,233,61,81,147,158,79,117,222,27,26,219,168,15,59,142,65,113,172,49,253,190,191,188,12,59,244,226,238,7,59,116,34,120,56,20,118,83,59,78,142,79,43,150,41,207,228,35,234,182,14,86,50,120,254,31,74,82,5,29,39,173,104,87,10,249,237,158,29,211,250,239,50,64,90,200,107,209,100,26,135,182,38,139,177,27,64,6,87,21,235,204,230,235,222,248,48,156,212,204,138,22,36,123,3,40,93,25,200,55,162,51,116,3,140,58,246,81,78,59,89,103,138,23,220,89,171,48,48,203,181,80,163,171,109,173,17,34,188,238,42,205,32,106,18,122,80,8,247,127,26,32,148,141,138,226,57,27,129,234,74,40,235,202,6,106,127,1,11,117,117,236,240,123,227,139,185,241,205,42,57,186,237,83,21,90,3,25,88,42,109,224,140,238,11,177,108,46,111,28,229,139,95,217,72,101,173,235,131,28,2,85,51,19,52,105,218,235,176,84,57,140,165,80,238,93,92,6,47,138,188,132,100,36,219,223,236,201,112,201,190,0,20,146,68,95,16,147,1,52,108,54,185,188,154,104,247,173,127,160,214,230,207,56,112,98,105,62,42,66,97,101,47,220,193,114,23,202,61,21,118,64,16,191,112,119,123,20,117,173,202,70,39,239,112,202,66,142,163,211,106,89,2,97,150,55,78,226,111,190,170,144,53,195,72,96,89,229,178,153,130,164,161,86,154,154,21,95,120,12,31,122,50,142,245,189,124,17,218,35,201,75,20,203,234,97,11,70,151,3,185,169,71,243,91,56,248,117,103,8,162,90,14,193,33,124,194,169,48,150,40,80,127,37,151,74,195,221,99,145,74,172,228,150,120,147,204,160,67,110,187,30,236,197,101,7,127,128,115,7,243,235,20,66,101,40,114,136,254,206,220,67,96,231,89,65,202,234,82,8,131,187,238,220,213,142,223,77,25,167,69,68,87,110,101,200,142,51,26,234,143,164,214,134,215,222,141,23,42,75,147,88,211,199,154,201,24,72,202,13,136,234,25,52,120,254,136,185,193,163,187,133,84,93,81,133,177,73,126,136,46,251,136,144,180,33,34,18,230,128,47,79,79,106,150,8,58,160,248,106,132,183,215,17,146,173,177,243,32,65,1,175,14,45,235,55,127,69,29,175,177,184,199,168,231,173,143,212,218,44,28,243,157,87,243,247,193,142,155,49,191,221,140,235,246,53,125,204,139,60,232,18,220,63,106,61,252,172,154,140,47,208,189,55,163,20,44,108,250,50,252,255,204,45,52,2,76,66,64,241,107,21,163,134,187,242,247,136,203,1,7,118,226,244,67,198,15,238,194,74,9,230,186,185,49,162,49,71,168,31,130,160,103,223,244,225,108,133,142,123,181,164,114,112,172,100,229,165,150,250,57,212,15,63,204,70,163,4,98,111,152,45,37,45,245,228,45,244,111,124,250,163,197,120,243,232,117,56,154,191,145,196,141,125,8,55,90,132,216,85,224,174,60,253,201,63,198,114,202,235,236,103,174,176,192,65,93,161,74,226,65,222,241,126,119,113,174,16,71,68,19,253,160,250,79,117,231,129,159,61,132,104,164,251,78,110,48,246,12,36,172,100,111,152,87,36,40,95,115,60,227,74,123,204,149,244,119,65,162,114,102,121,19,155,249,117,248,51,151,33,42,115,199,237,144,43,180,51,121,129,23,83,127,226,56,9,32,222,44,201,44,21,7,249,122,183,224,239,85,204,10,181,91,19,103,103,133,205,12,229,38,97,31,108,141,82,255,186,32,185,59,95,66,45,15,41,179,36,56,178,53,39,230,128,252,12,104,165,98,132,4,223,238,44,36,222,188,218,52,250,146,212,148,237,85,68,175,72,79,155,38,36,230,62,122,67,208,138,241,5,49,158,119,106,100,178,247,61,154,161,134,111,198,28,192,44,150,189,7,205,154,142,45,190,172,69,107,176,36,105,64,30,153,120,233,138,210,10,19,201,37,119,182,152,85,43,37,56,68,199,14,82,214,220,245,249,231,141,77,20,190,252,61,102,166,209,230,24,109,225,229,78,195,145,93,109,32,127,163,49,126,248,87,165,80,47,35,155,3,51,50,146,244,105,171,122,226,62,82,242,157,209,37,222,157,224,156,21,73,10,238,198,123,110,60,209,122,158,82,5,221,166,227,119,183,251,80,175,245,112,156,150,175,183,247,162,53,159,213,33,71,40,168,227,104,244,244,210,154,12,114,234,6,153,36,147,203,170,108,85,64,250,110,225,137,2,143,243,163,40,173,220,191,63,210,108,131,154,142,83,175,46,56,41,236,83,221,81,161,144,135,172,99,88,139,115,229,148,143,162,9,203,12,44,238,102,165,234,230,179,179,242,16,227,158,20,196,203,126,102,121,194,246,105,131,73,192,81,122,192,229,32,52,68,139,60,16,102,94,4,190,236,77,238,222,73,240,221,6,252,179,240,56,85,108,237,167,95,168,223,161,49,28,186,57,93,43,203,125,223,42,221,67,47,174,96,56,99,204,115,41,252,252,106,153,180,228,242,100,155,42,105,108,181,215,47,150,176,81,36,192,211,244,135,162,127,189,201,80,62,117,91,125,58,245,215,9,16,165,134,52,42,43,225,155,28,21,189,76,85,226,216,155,133,105,120,60,145,152,6,52,150,149,2,255,255,126,255,45,36,58,37,21,112,25,5,210,187,69,74,195,46,226,170,12,90,154,7,142,228,89,148,22,211,1,150,132,252,99,19,215,135,242,15,150,0,17,251,192,38,133,71,164,62,161,144,240,178,62,63,254,50,137,26,207,233,156,52,145,94,86,239,132,26,146,181,46,165,248,100,14,76,252,16,214,130,195,166,67,120,113,30,255,126,197,11,57,108,130,66,163,177,70,30,223,117,244,53,44,13,86,39,70,58,213,212,230,152,164,76,152,10,227,3,6,230,216,73,88,108,91,245,126,137,58,224,132,168,129,199,254,247,134,142,56,81,168,160,119,44,222,123,230,189,204,92,245,18,227,172,58,240,174,149,68,71,210,183,169,241,146,73,86,210,216,156,250,239,161,219,212,210,69,48,33,137,81,185,192,218,197,2,122,26,76,13,121,61,31,44,239,37,158,126,254,241,131,26,167,224,67,133,125,52,204,195,141,119,131,208,214,151,86,54,137,139,144,178,173,220,170,156,70,125,66,38,125,127,135,146,246,160,95,230,1,248,184,55,65,56,225,139,169,106,17,246,153,98,119,248,67,85,148,28,157,200,233,186,149,138,180,147,37,42,212,190,28,189,109,117,242,168,56,133,17,29,241,89,218,5,242,81,50,61,166,175,124,106,47,237,20,201,235,69,95,202,35,243,79,223,34,85,47,100,252,168,29,171,20,189,109,65,14,156,71,195,246,94,104,211,21,29,195,84,33,131,207,221,120,139,57,78,126,88,195,191,172,133,96,242,110,140,236,227,76,154,55,32,134,193,20,204,21,192,232,157,224,147,175,193,96,9,127,18,107,239,96,240,98,139,149,104,92,151,196,170,198,104,185,117,179,26,20,72,48,36,47,32,86,42,189,173,80,71,219,151,79,181,88,45,26,191,38,133,45,54,131,31,109,115,161,163,34,38,89,40,49,173,198,48,17,40,39,121,77,90,70,42,251,130,168,125,184,76,60,95,94,136,227,248,145,210,226,191,137,247,72,210,17,141,52,5,102,220,23,111,146,114,218,208,22,105,9,130,97,83,57,25,228,137,6,99,12,24,29,89,25,101,217,133,196,253,246,158,114,75,8,90,142,28,147,19,22,164,240,205,1,21,145,19,225,61,98,21,22,215,32,158,9,44,97,148,104,201,219,76,43,45,162,73,151,252,188,155,192,134,113,103,109,255,54,42,206,24,76,87,154,98,187,78,193,50,86,191,222,86,162,165,38,191,118,117,72,31,6,174,147,231,105,158,70,133,79,138,223,55,73,210,90,194,194,112,167,14,253,133,160,197,234,193,24,75,239,106,47,115,70,102,75,122,123,87,158,185,162,180,84,210,222,141,172,125,211,117,181,155,250,182,51,247,178,100,123,8,8,173,224,246,222,40,35,31,171,203,195,36,34,6,53,171,105,219,106,216,77,18,130,182,37,225,3,235,196,203,114,168,7,2,10,14,230,118,6,134,118,20,184,145,213,218,127,110,182,193,145,91,202,110,11,96,118,1,8,96,103,167,236,180,15,141,151,253,100,7,112,25,70,89,121,233,178,158,234,47,68,162,185,146,146,7,74,2,17,238,108,171,91,64,92,173,85,82,121,240,175,136,132,26,123,225,64,169,132,53,192,187,113,8,165,133,192,249,61,166,108,170,2,175,11,243,183,162,93,109,51,151,40,206,39,150,0,84,130,215,29,211,96,200,244,193,206,63,137,9,225,205,195,93,147,70,125,177,146,164,76,247,0,61,118,12,73,75,151,145,218,82,180,207,112,233,175,169,104,180,29,149,4,129,248,70,10,159,34,67,208,4,235,146,205,128,223,104,17,16,189,72,150,29,148,21,85,152,237,97,200,84,57,234,9,165,16,73,40,118,10,18,222,171,43,231,169,211,149,179,250,145,227,129,66,53,2,35,228,99,7,1,101,161,122,247,98,103,47,32,194,21,66,228,215,171,211,95,93,47,71,164,197,154,72,46,73,190,186,131,152,104,252,1,237,94,154,240,6,67,188,57,183,3,28,30,181,14,142,247,193,242,88,231,188,86,198,130,125,97,9,115,137,196,6,38,94,170,51,157,253,197,152,195,181,150,253,125,49,6,217,29,102,120,252,248,217,191,232,176,151,7,118,12,126,164,219,67,123,72,16,146,223,203,183,0,196,87,186,185,173,67,246,204,171,20,21,86,98,182,253,7,186,6,120,189,118,3,229,237,60,53,90,120,139,87,229,79,153,85,139,16,81,100,189,150,202,125,164,42,132,10,163,190,85,177,69,169,181,85,186,64,77,182,99,209,185,183,19,5,1,24,167,247,211,71,7,154,124,136,40,199,61,196,217,202,170,170,93,64,20,178,234,247,41,59,124,192,158,211,128,28,144,37,95,61,108,113,150,27,161,102,97,250,86,162,10,193,27,201,55,193,56,84,164,176,59,172,180,2,117,209,83,226,255,156,104,115,80,9,171,177,196,38,252,19,138,252,29,242,231,74,93,205,161,41,158,79,204,211,0,30,248,42,125,237,167,151,3,163,35,219,102,225,38,80,160,246,91,202,15,81,5,104,108,210,239,193,131,146,27,150,17,171,71,221,84,112,204,146,94,186,237,255,206,118,141,107,20,169,226,15,43,75,224,52,120,186,0,134,235,166,30,237,98,31,139,146,29,104,64,56,3,249,66,92,147,217,211,9,31,96,178,69,148,227,230,101,236,243,45,246,172,39,229,59,69,106,63,147,212,148,179,217,10,220,19,61,36,147,54,173,248,250,238,79,181,163,211,105,11,79,136,249,56,91,202,219,147,180,212,42,140,52,110,222,216,92,215,61,213,55,188,33,239,190,201,255,96,1,215,85,244,86,49,152,17,180,172,68,196,115,71,107,182,243,219,136,48,23,116,210,242,8,233,123,235,101,169,61,55,63,1,51,205,161,189,96,59,52,218,197,250,26,88,73,52,217,104,199,216,234,189,209,12,232,29,210,128,20,244,127,219,15,204,123,222,84,167,249,54,43,174,28,118,186,210,116,176,58,78,38,166,130,144,219,92,43,91,180,1,195,20,39,139,0,25,240,204,75,61,178,95,199,10,3,136,139,50,249,155,86,95,70,214,41,166,76,132,6,166,146,35,118,145,100,203,149,154,211,215,94,104,5,44,83,183,45,251,89,212,57,197,144,82,87,170,120,45,105,80,129,100,131,159,10,127,221,163,246,63,192,154,53,205,6,127,117,223,24,147,216,93,28,239,163,214,221,158,12,149,255,83,88,41,136,165,138,1,254,6,44,25,143,22,104,150,94,24,196,25,238,193,216,170,71,103,76,33,52,211,45,205,235,134,41,248,86,65,9,32,255,32,95,30,250,243,251,43,119,170,184,85,107,38,21,98,231,54,218,226,16,72,174,6,221,38,211,120,221,119,117,120,67,209,251,33,84,155,163,163,47,53,96,15,51,76,204,87,153,85,170,54,66,113,12,174,34,104,136,90,62,76,103,210,150,82,37,200,148,44,89,113,229,33,173,240,114,61,21,131,193,157,216,181,193,207,219,29,42,99,21,186,158,11,145,155,4,216,22,244,162,245,120,63,128,57,117,241,213,60,251,251,149,87,153,99,63,22,75,81,103,103,239,199,225,110,110,88,38,125,240,116,161,226,53,38,183,2,223,68,221,87,205,73,201,187,129,82,39,35,166,109,116,96,250,15,15,242,104,227,86,21,140,48,172,188,54,214,185,33,4,199,217,220,218,185,44,244,170,133,64,135,231,135,80,159,130,65,112,36,250,209,241,226,74,174,130,199,202,217,218,87,161,162,130,254,242,150,34,63,117,178,224,76,211,80,201,111,72,69,137,93,62,24,23,249,115,80,83,95,17,166,84,223,132,120,6,53,34,199,208,205,80,109,133,213,92,49,18,214,230,123,245,73,80,228,94,106,241,165,216,84,255,96,177,178,90,92,5,219,185,153,238,208,136,79,150,15,232,139,179,52,146,235,158,62,239,136,154,45,92,190,176,19,91,40,214,152,149,209,222,247,97,175,74,250,98,231,204,211,233,2,168,136,18,202,254,144,196,95,80,187,220,123,31,164,176,207,23,248,81,3,174,138,206,65,83,36,29,70,32,71,21,227,157,254,228,2,4,215,71,27,252,9,219,49,49,23,248,163,43,170,192,126,75,198,97,91,38,182,93,204,141,250,187,145,128,158,103,88,73,178,191,233,253,231,3,169,38,117,163,181,44,217,91,138,15,239,82,140,19,78,13,168,212,227,46,202,225,130,28,150,211,105,239,25,243,208,76,174,52,37,170,87,125,141,221,90,95,41,51,53,205,112,75,54,129,102,51,87,222,28,117,188,154,174,103,66,55,95,247,97,127,31,107,22,117,195,115,97,108,19,52,70,179,212,190,15,8,213,49,139,119,170,201,169,8,199,203,166,183,90,134,185,169,133,135,9,251,66,104,187,220,182,164,82,21,125,132,197,116,14,169,241,211,104,107,169,17,246,140,46,235,236,23,84,93,180,72,214,10,39,185,197,170,73,30,43,35,75,114,202,126,143,2,127,114,206,107,25,116,183,11,43,3,146,183,121,214,79,26,240,70,203,45,88,74,11,137,245,21,38,44,66,143,61,168,69,76,204,92,186,121,203,15,46,213,237,131,23,220,68,52,188,111,185,48,81,35,208,159,218,44,76,71,236,152,61,103,92,247,136,123,88,196,109,213,91,97,190,88,164,237,171,59,217,231,230,51,149,191,114,162,41,91,249,249,25,109,183,231,25,48,30,35,44,156,199,26,146,144,26,85,40,82,54,83,253,102,88,29,52,114,160,176,0,95,4,217,205,123,143,97,62,149,15,178,195,166,156,183,183,170,183,54,232,197,211,241,7,215,241,86,159,151,161,98,116,91,139,14,111,22,41,155,5,43,72,245,246,20,196,27,62,112,149,21,253,42,111,173,148,25,42,199,41,53,84,169,17,246,92,25,211,161,41,159,252,62,243,4,19,121,43,66,199,74,28,208,193,205,33,126,84,173,30,16,26,179,244,95,188,90,6,16,178,251,191,203,121,130,161,12,52,170,24,14,141,2,163,190,6,52,205,187,57,245,252,9,53,65,132,246,126,90,3,26,54,238,222,74,237,35,163,214,83,43,254,139,112,244,74,15,241,20,255,217,117,129,81,233,181,187,160,29,30,245,145,199,163,29,171,87,228,222,50,229,60,139,23,152,179,33,23,124,180,100,223,209,21,191,93,240,166,209,66,67,28,158,237,190,62,80,188,131,151,72,22,159,212,121,139,49,254,184,106,134,122,77,103,165,81,70,69,174,0,7,179,26,152,234,23,37,155,212,120,59,223,226,216,189,170,9,42,206,10,123,140,130,214,229,149,218,74,215,152,151,235,170,53,33,209,190,193,105,61,182,108,226,176,32,213,78,117,106,23,56,121,61,82,213,107,121,107,114,185,20,99,151,57,44,105,153,238,174,24,192,241,254,251,80,193,143,221,0,58,227,109,190,129,185,22,131,37,221,129,34,101,144,152,33,250,198,183,73,236,69,174,215,68,64,181,94,33,132,40,149,248,252,133,191,99,245,130,21,43,49,211,224,204,33,169,240,230,120,107,228,46,140,168,241,32,17,95,48,147,101,16,176,251,83,160,253,105,171,56,79,198,139,36,48,144,120,99,236,171,235,56,117,196,171,178,244,170,61,79,183,32,202,66,50,130,211,99,78,199,73,255,242,30,138,199,156,129,107,187,182,255,144,201,230,138,199,111,154,10,126,232,144,99,117,187,160,97,221,177,191,5,239,139,181,240,32,249,247,61,216,207,154,217,224,246,49,118,3,194,107,197,233,3,242,99,182,58,45,151,176,238,101,118,57,44,123,195,112,61,129,140,199,98,25,86,104,2,141,220,161,128,109,32,8,89,147,249,11,246,14,255,195,81,233,46,89,37,122,225,211,69,132,120,138,169,254,0,72,208,116,247,244,60,55,28,135,15,11,28,174,65,40,253,148,181,6,57,220,134,224,205,255,225,22,228,49,200,228,182,179,141,237,217,9,47,114,203,57,24,173,236,15,100,174,120,178,73,84,236,141,45,188,142,252,66,85,56,248,161,247,21,240,209,145,198,24,158,227,106,158,18,248,204,21,1,99,35,91,187,157,228,98,106,35,231,158,103,53,119,135,62,168,207,48,5,118,236,117,255,204,65,60,49,102,180,55,82,149,17,205,214,182,198,223,77,55,234,99,156,29,161,90,22,138,7,126,240,213,226,110,63,214,97,71,161,203,216,10,31,25,62,71,223,163,238,97,14,115,144,121,112,103,4,186,16,66,51,105,110,65,111,32,206,82,213,231,74,107,199,255,85,48,249,19,123,45,142,3,104,77,86,181,99,8,158,50,3,108,43,23,113,246,189,180,107,134,24,9,137,36,178,9,176,197,63,33,63,164,220,217,243,175,16,197,210,28,16,109,192,143,193,240,252,44,124,8,108,179,168,171,135,107,32,216,49,136,123,109,133,33,176,167,185,189,30,120,210,5,211,14,127,118,199,147,121,246,58,33,239,172,251,87,223,152,144,13,169,216,65,87,59,132,210,118,116,30,68,72,68,155,103,230,81,33,26,21,82,14,73,251,183,147,86,222,194,97,44,169,244,82,155,95,253,205,116,91,165,44,64,31,163,242,253,93,23,26,209,14,33,97,62,148,115,63,247,111,137,13,9,163,215,243,223,218,10,114,82,195,219,233,24,117,167,173,231,13,156,77,46,231,130,200,122,169,91,49,229,215,250,140,73,229,240,44,212,41,117,112,31,126,218,196,58,241,101,147,26,195,148,98,153,198,104,87,90,149,128,60,239,177,50,49,11,242,239,230,196,182,89,101,80,215,168,143,70,48,53,53,215,22,99,194,129,245,128,163,40,102,25,14,99,189,152,35,135,13,16,105,137,188,32,226,246,176,38,30,36,65,146,145,240,83,103,2,107,133,21,172,41,239,28,250,134,170,228,80,43,122,211,87,111,228,168,29,171,79,69,62,152,18,69,203,96,169,144,83,50,37,65,208,1,113,46,2,67,73,221,2,181,73,185,209,20,163,237,141,222,221,69,220,155,12,177,239,150,84,234,58,111,225,3,31,187,110,139,78,139,234,186,202,73,72,34,125,59,43,206,220,68,6,49,123,14,147,144,206,60,95,31,173,236,244,239,64,11,119,89,226,7,117,175,218,115,104,165,195,209,202,140,132,15,6,115,213,209,69,238,7,89,37,249,156,158,67,124,208,100,194,232,148,52,214,125,166,99,224,152,46,109,187,234,230,51,60,189,191,120,28,13,67,152,105,230,40,147,153,215,16,149,231,51,170,159,88,97,228,216,161,34,87,65,129,153,213,186,140,150,104,113,164,25,120,246,58,78,221,124,33,179,135,7,220,233,68,9,15,123,101,187,131,139,95,177,234,29,215,24,57,107,53,194,252,161,247,70,224,245,22,104,10,41,39,213,190,186,249,159,32,28,196,55,153,225,205,18,72,227,70,120,101,199,237,132,225,10,124,88,154,151,215,153,67,177,100,244,99,169,37,127,97,122,188,216,217,79,187,227,87,69,243,42,139,151,228,79,141,154,88,240,7,29,255,165,129,150,70,173,212,207,194,245,243,54,210,111,168,77,71,140,61,28,64,106,8,196,60,68,154,18,110,22,252,63,172,163,34,138,138,105,145,101,244,110,11,75,95,244,220,224,140,191,243,85,79,137,128,246,173,146,28,1,68,146,131,190,104,107,105,10,183,141,149,204,59,176,190,91,3,180,254,33,47,24,58,4,53,177,211,193,103,6,161,57,156,191,177,108,76,83,185,133,20,167,103,26,75,148,54,239,124,182,71,95,160,157,60,112,22,149,136,53,82,150,241,250,192,35,199,124,207,79,66,84,131,7,63,140,114,16,166,158,30,0,73,131,202,144,116,46,50,92,60,23,147,147,14,236,195,64,128,205,63,248,146,1,49,182,30,96,166,149,196,243,131,88,93,119,167,118,22,137,56,179,169,223,194,48,235,4,196,19,7,210,55,75,235,92,247,15,83,174,53,132,172,34,214,91,205,147,70,34,195,103,132,175,68,245,7,227,205,122,160,7,72,137,123,51,243,8,7,82,113,179,53,171,249,151,156,75,82,204,101,194,53,247,2,201,39,125,151,8,4,189,190,40,95,41,72,181,116,99,58,100,136,118,164,13,191,107,164,69,39,229,204,2,248,254,87,112,64,247,106,105,66,193,73,104,67,75,181,248,105,39,227,153,139,164,41,215,76,244,118,95,99,56,13,94,20,67,33,205,238,108,249,81,105,60,177,18,155,229,73,173,205,78,164,144,180,161,191,210,203,150,190,16,55,228,110,203,212,118,15,103,25,67,152,199,2,36,17,117,201,129,88,197,112,153,188,44,58,196,160,131,198,150,19,223,209,224,90,127,231,71,1,40,82,195,12,242,223,233,211,68,210,32,176,1,106,119,179,211,33,221,107,210,194,227,213,88,3,122,19,130,145,199,16,66,179,41,215,40,18,133,40,191,25,49,31,101,27,16,11,60,119,20,186,217,168,204,250,28,173,159,38,166,106,2,35,49,133,30,16,174,41,134,5,154,247,72,247,171,23,225,89,228,141,14,221,122,56,188,54,252,90,121,252,169,8,168,27,59,138,8,245,70,122,230,65,165,140,117,136,206,11,169,209,146,240,8,234,87,27,21,119,136,227,84,138,65,172,42,227,109,202,167,67,219,148,125,32,179,242,176,224,42,235,163,145,195,63,145,122,135,21,164,85,133,249,38,87,145,90,3,151,203,189,99,172,189,248,86,207,193,226,138,44,42,179,190,99,83,127,92,185,32,159,58,246,239,241,246,235,227,205,219,169,42,77,149,0,212,210,172,47,174,68,122,133,7,78,152,86,30,65,58,84,65,40,113,125,213,150,112,146,1,46,218,175,242,206,243,3,22,233,246,135,129,96,57,130,15,151,104,91,220,169,42,107,34,44,14,229,23,97,55,219,134,96,213,252,133,227,120,195,1,46,17,86,212,120,130,91,248,166,233,51,66,254,106,183,117,42,44,36,169,196,204,173,91,96,109,228,171,28,189,45,250,183,121,167,12,164,164,245,225,177,164,170,138,139,161,93,90,83,85,26,198,104,106,203,108,131,144,196,153,22,188,229,99,101,228,68,84,115,35,112,19,129,18,184,189,228,220,191,206,106,106,126,188,176,42,150,208,166,249,215,76,49,78,167,49,137,16,206,210,203,31,206,130,158,233,143,12,168,123,152,246,181,110,5,9,143,33,8,20,72,188,117,52,80,18,200,90,101,236,228,207,56,241,5,217,53,40,86,180,67,214,216,113,227,232,42,4,123,161,29,225,131,69,60,164,193,158,200,54,177,14,32,137,153,25,110,144,200,246,156,194,61,16,88,79,24,113,181,5,133,88,82,165,176,38,251,156,45,231,111,141,37,120,107,195,254,51,23,243,143,18,30,92,222,216,31,27,168,49,204,158,75,50,29,108,173,189,227,162,147,5,233,159,187,189,71,11,14,221,15,68,223,60,234,186,227,182,193,229,131,242,98,115,34,126,30,59,20,56,101,249,9,38,148,110,79,181,179,181,29,240,61,110,204,161,242,160,184,30,38,49,180,136,78,22,156,1,249,192,217,132,67,3,250,243,132,141,231,10,84,231,97,122,73,28,88,116,105,213,193,202,47,183,216,19,80,71,55,14,123,32,194,193,121,208,234,113,73,234,146,93,189,196,164,129,140,201,122,187,60,67,10,121,125,17,246,192,134,16,58,220,3,66,88,63,127,197,206,164,85,151,11,143,43,109,35,215,25,113,90,99,90,205,22,209,122,41,112,244,206,253,59,161,241,168,251,89,190,186,151,193,3,142,219,1,102,68,147,87,145,74,157,223,203,18,248,51,21,219,92,9,251,196,149,82,153,103,27,151,252,54,21,4,47,205,56,172,183,3,29,202,225,83,16,70,15,21,227,219,225,178,248,157,53,135,57,185,163,37,123,167,126,80,187,41,181,17,191,207,228,71,37,158,205,118,62,248,250,194,59,71,214,167,103,233,25,73,205,178,231,128,78,53,113,28,73,140,86,87,88,87,238,196,137,77,234,138,39,195,39,117,89,71,3,123,115,108,182,175,148,180,142,193,159,155,141,71,168,172,98,136,187,112,36,25,146,98,217,160,17,34,77,55,98,189,208,173,74,117,181,200,124,182,123,12,56,62,149,214,75,112,112,107,126,242,224,85,234,235,172,131,250,233,229,99,14,92,194,36,21,156,167,172,215,243,141,214,57,79,177,104,94,207,160,8,3,102,237,50,84,126,223,147,92,211,221,196,52,130,24,176,159,132,65,156,131,71,126,4,33,143,91,104,28,50,153,209,95,181,28,75,113,70,67,27,109,192,39,174,135,252,172,218,211,94,160,62,199,154,79,251,16,22,195,15,22,140,253,36,242,85,72,147,22,121,33,25,195,83,123,67,179,160,66,85,146,45,114,228,93,116,57,55,217,212,216,31,50,167,229,242,19,107,240,57,124,255,142,191,249,148,74,39,163,43,156,151,201,207,220,46,185,27,203,141,137,15,92,5,101,198,159,181,2,84,128,42,9,10,185,221,175,55,128,247,131,98,98,146,152,8,240,110,121,15,67,233,2,21,145,83,105,182,127,239,100,153,185,165,225,124,59,119,26,175,192,81,4,98,42,93,184,200,34,68,13,134,123,5,43,164,167,218,32,67,79,70,4,196,254,131,50,201,157,133,80,79,208,242,155,224,237,252,110,27,249,238,45,235,77,229,182,93,205,123,32,5,3,78,154,69,213,117,216,130,198,46,105,47,78,76,255,250,230,254,99,106,218,110,21,186,185,71,173,236,91,67,119,59,38,141,202,223,39,183,153,239,2,113,168,121,123,54,217,55,237,94,11,1,190,38,16,170,216,147,239,88,254,229,245,220,108,102,247,55,229,237,173,167,179,231,185,82,226,109,53,81,87,15,55,217,69,204,109,3,164,126,143,193,42,141,227,90,36,226,83,128,215,12,177,216,190,140,85,129,225,224,25,74,141,225,41,192,131,60,180,130,169,191,124,58,1,135,224,63,27,9,138,244,124,167,199,35,2,120,62,25,218,238,78,254,29,125,60,19,72,168,31,194,52,28,70,137,193,242,203,2,91,43,138,248,5,135,204,165,116,67,10,198,121,98,100,238,143,43,94,209,39,162,232,129,176,41,254,158,40,195,167,51,206,48,151,123,55,64,65,233,220,176,238,73,3,129,139,129,242,194,88,95,199,147,187,75,237,229,171,30,89,115,154,239,165,169,235,59,98,63,177,91,115,84,142,203,97,103,79,66,2,91,157,207,14,45,246,75,211,46,69,228,42,158,158,132,228,178,36,163,98,194,69,11,37,186,217,155,206,244,54,125,9,122,128,237,37,159,232,91,68,159,92,116,153,244,199,136,214,88,171,186,117,98,60,171,163,232,45,147,151,123,170,237,130,250,83,244,253,125,237,248,178,237,111,15,63,154,122,147,51,15,60,204,111,139,245,231,228,185,51,36,176,237,79,48,4,150,130,163,59,120,29,126,54,40,104,116,142,238,121,237,189,107,191,35,8,119,113,131,109,108,173,24,9,142,108,8,49,51,202,146,192,173,17,1,241,218,187,124,164,246,139,220,70,143,192,138,152,227,175,189,77,209,86,106,63,119,2,159,194,2,163,89,30,119,83,127,152,98,60,123,145,96,155,67,36,124,94,20,93,243,98,219,253,143,238,124,45,39,226,10,242,116,227,184,129,242,21,192,51,94,97,231,64,148,237,211,59,177,198,10,216,238,62,4,109,230,168,9,132,240,215,0,86,29,251,174,78,233,243,27,50,92,197,253,214,2,123,146,246,222,140,146,148,108,237,15,4,222,247,156,154,132,10,40,151,8,10,70,114,132,181,145,136,176,233,7,169,57,111,204,90,220,67,215,132,40,150,216,152,69,54,80,43,171,67,46,100,140,33,185,115,58,154,35,242,247,6,43,31,174,39,80,101,216,73,40,132,227,201,14,85,37,194,50,3,146,118,78,76,36,211,88,24,220,98,14,33,120,148,222,160,20,160,118,195,167,167,92,128,37,5,53,38,72,206,146,123,57,213,135,200,109,71,35,239,160,169,225,222,136,217,153,92,67,165,51,105,189,47,203,155,237,217,9,216,232,29,225,177,49,205,230,232,177,124,66,19,114,207,198,114,64,45,161,124,66,110,85,157,81,102,32,22,83,53,111,196,27,133,196,169,162,223,120,126,235,105,163,132,221,206,150,110,214,226,227,26,172,30,160,193,251,235,130,209,125,165,77,58,39,115,187,196,165,24,148,33,237,15,73,76,51,191,88,212,165,137,89,220,47,35,108,174,114,48,214,113,39,163,180,185,63,88,233,112,0,120,241,137,168,24,63,138,54,82,207,177,179,66,101,46,177,222,3,52,49,103,68,5,246,78,182,234,55,35,29,9,19,192,144,78,132,224,162,148,96,89,62,61,109,6,178,98,241,196,88,167,22,196,56,11,139,35,94,112,213,134,206,158,24,179,145,144,24,250,44,149,253,67,210,8,0,244,166,243,0,180,234,155,46,191,122,41,93,142,70,154,56,201,66,159,207,162,193,63,26,46,204,221,206,29,100,232,161,225,87,106,130,47,154,66,253,50,33,4,103,71,134,239,65,137,220,222,90,200,221,145,253,16,73,125,66,213,113,239,82,209,96,85,98,196,87,143,30,250,24,217,92,120,23,123,71,64,51,243,204,192,239,147,75,30,170,32,161,187,95,176,78,235,9,173,103,112,9,93,39,55,89,66,223,135,55,158,58,28,249,4,53,46,175,138,48,65,135,70,136,1,162,20,77,236,103,41,150,88,60,162,162,221,75,62,108,114,118,100,40,120,101,241,122,160,0,109,225,54,161,239,188,6,149,136,139,198,177,179,32,43,126,52,149,57,217,226,136,215,201,55,32,213,229,87,28,109,36,223,42,151,98,71,107,140,255,230,206,183,84,127,109,108,57,226,37,11,140,188,250,216,82,32,241,186,122,68,173,128,81,29,57,2,23,81,10,233,198,238,113,91,11,7,17,184,180,159,230,116,147,143,120,21,24,1,220,118,49,16,80,204,12,78,41,111,117,193,98,56,148,193,219,160,156,230,56,126,1,172,183,95,204,229,202,75,218,108,245,33,254,8,58,127,98,209,197,176,100,60,110,139,133,80,43,42,133,200,12,216,121,186,89,171,171,252,220,132,121,46,180,75,79,8,157,91,112,112,34,247,193,147,132,119,236,30,223,101,129,132,197,45,134,84,202,92,249,70,208,211,158,206,209,216,202,106,106,96,1,80,249,182,103,247,124,85,169,42,212,67,245,112,214,156,147,143,216,186,202,197,119,5,230,23,226,199,79,150,253,252,85,1,193,145,96,212,15,165,73,246,244,50,249,165,95,254,252,112,62,100,237,167,234,181,238,164,135,224,175,19,225,82,153,135,122,209,81,59,123,165,21,127,99,54,56,18,153,226,205,161,95,202,7,79,126,124,92,208,244,46,5,176,227,206,200,16,140,97,250,131,187,54,34,117,52,52,206,150,201,200,182,45,201,225,80,46,100,113,199,193,12,116,224,253,59,85,244,248,161,239,199,164,208,63,114,103,163,167,185,246,203,19,33,102,53,236,108,3,205,170,155,230,73,204,142,178,233,7,187,171,191,137,254,60,149,218,98,40,42,87,10,3,146,207,162,67,113,25,173,141,27,217,143,225,97,164,2,208,116,57,181,180,112,233,183,114,62,110,197,29,79,155,213,7,115,94,60,229,43,83,79,119,171,196,20,78,239,233,51,87,6,32,5,59,166,121,176,193,0,2,145,150,183,130,7,36,179,159,57,212,66,179,111,151,174,27,202,58,35,12,121,174,29,17,69,244,46,87,1,173,238,194,40,107,180,147,157,209,184,241,104,251,123,242,164,42,31,93,118,82,79,189,47,105,102,158,30,210,164,16,47,140,226,212,235,70,176,78,30,247,193,162,137,19,102,181,9,248,156,29,149,41,73,2,34,88,183,198,106,254,34,124,19,150,32,99,71,253,14,190,121,107,200,168,38,114,205,153,112,139,204,16,149,101,168,127,70,40,156,157,78,179,113,220,4,46,194,124,96,187,139,83,36,28,169,50,209,88,176,134,217,219,55,18,186,165,170,11,175,60,216,24,132,95,218,101,75,194,66,64,184,1,56,29,86,92,86,243,122,204,124,185,21,219,37,111,68,82,178,41,69,127,186,121,223,219,84,41,169,105,54,165,5,128,102,12,67,130,217,46,97,233,254,216,57,121,145,39,46,34,136,82,175,114,153,215,16,119,138,116,45,137,136,230,59,132,221,97,0,150,250,153,211,18,141,254,212,157,9,45,217,191,16,24,133,130,194,151,189,230,92,187,55,12,247,187,8,115,13,29,222,207,59,92,230,24,146,39,165,2,54,188,107,162,190,178,185,22,188,187,172,42,164,239,225,92,55,26,237,230,59,0,75,13,33,47,250,12,161,72,4,185,159,244,163,208,129,102,176,239,178,99,211,97,92,241,234,19,85,70,42,189,55,130,151,119,38,50,126,239,231,40,153,124,51,220,63,234,208,163,211,170,63,37,231,40,152,183,204,90,227,246,208,8,196,85,209,243,92,102,174,199,27,110,145,27,1,158,35,176,107,152,163,227,75,21,184,120,238,57,155,201,3,194,165,57,117,211,136,236,17,128,98,177,93,111,46,94,137,155,5,70,101,212,42,190,79,218,62,143,123,151,171,59,185,175,9,185,245,254,235,130,177,69,252,61,157,29,229,105,128,229,192,180,37,158,214,254,13,129,64,53,209,247,56,140,241,97,250,119,174,250,204,68,97,184,208,29,20,117,25,12,105,234,224,76,223,115,197,177,7,235,247,19,42,20,85,78,15,81,181,192,153,4,160,176,82,106,67,212,194,132,240,190,45,126,79,192,122,42,28,239,165,14,139,14,152,62,129,78,48,66,45,207,97,240,165,178,129,234,169,234,59,12,218,46,249,54,76,20,225,254,11,128,237,242,61,101,16,36,207,202,13,244,205,77,104,204,51,50,1,5,95,211,151,110,251,255,185,191,151,167,102,140,98,163,129,27,38,60,101,197,176,252,212,232,136,208,157,118,51,83,111,209,188,223,78,130,47,24,91,236,170,159,121,55,3,202,0,155,212,180,173,74,37,161,201,91,108,166,174,27,239,60,20,65,158,225,185,85,89,127,76,244,27,86,150,160,201,13,106,79,143,68,200,236,55,107,243,76,149,215,188,118,183,198,159,26,140,136,153,211,173,159,16,57,139,31,93,149,70,6,141,53,112,164,6,184,239,106,159,222,67,158,26,121,136,223,39,46,140,67,170,202,95,88,179,214,186,212,140,8,12,94,34,77,226,17,17,162,210,225,20,151,177,74,9,100,126,170,73,142,33,144,154,131,151,205,235,28,118,190,6,137,98,50,237,7,94,230,246,133,250,179,160,199,89,103,9,203,111,37,216,185,171,40,117,6,107,87,133,165,172,22,140,220,186,41,97,187,57,196,102,220,15,169,194,254,170,33,237,69,78,127,4,30,119,51,251,153,50,179,106,153,232,131,96,100,243,32,78,78,223,191,150,158,39,30,201,43,12,220,233,103,223,247,156,210,213,52,75,203,102,114,46,35,81,55,175,89,207,53,66,198,247,164,132,51,64,124,120,125,108,35,3,184,185,202,162,122,93,58,198,11,176,146,221,62,6,92,250,135,230,38,135,125,76,89,22,140,243,110,14,212,252,94,85,234,86,142,168,158,28,94,124,183,180,213,174,80,170,142,88,83,48,201,169,249,109,156,83,4,161,186,46,235,85,83,86,244,7,52,58,188,19,124,117,35,105,13,185,191,47,252,142,77,194,147,27,235,193,126,138,65,32,134,118,24,227,33,219,142,48,59,235,147,8,183,94,74,184,233,4,78,44,55,20,167,190,216,145,187,105,253,135,93,68,15,204,76,81,176,255,140,229,106,248,29,154,109,79,247,240,181,62,181,2,28,187,26,136,254,180,92,158,140,81,194,11,245,237,48,28,57,112,87,48,233,185,13,251,113,29,199,152,222,226,254,232,119,199,120,251,113,224,226,89,162,215,74,115,227,118,145,197,176,156,161,226,233,79,170,203,163,113,106,144,108,25,85,163,91,129,143,75,216,56,51,156,13,106,116,79,121,79,152,139,128,156,169,174,94,228,172,49,115,235,134,42,145,67,107,214,122,8,49,156,210,218,178,151,67,247,169,0,56,164,44,222,132,125,193,90,153,10,15,29,69,159,229,98,193,181,138,65,215,14,65,89,116,209,247,174,22,72,27,141,214,94,36,169,203,34,123,25,192,248,196,238,148,225,225,253,59,44,43,96,2,26,21,96,123,202,184,253,55,162,172,81,29,95,172,11,133,235,129,224,183,94,71,85,29,23,65,246,242,222,224,109,136,62,63,145,107,248,167,160,195,242,204,135,237,253,107,53,91,77,34,207,186,102,102,84,28,14,44,194,39,232,156,245,132,232,76,102,63,206,240,49,132,118,211,1,70,75,30,42,3,149,207,174,223,160,227,64,221,207,62,64,74,186,97,163,201,85,231,33,84,76,132,47,66,189,73,137,21,77,184,234,168,231,171,247,76,32,229,1,138,186,116,5,60,65,8,57,133,57,165,125,190,51,105,242,89,1,141,234,53,168,34,89,88,55,63,52,10,226,116,30,115,175,214,74,234,133,248,48,242,17,47,155,75,131,130,124,207,192,199,156,142,142,119,122,3,15,49,119,155,82,80,171,180,19,29,133,31,247,222,9,245,206,244,22,69,12,85,112,250,23,97,212,191,32,152,5,115,206,31,197,19,250,138,219,130,3,84,216,78,11,80,213,13,161,199,128,136,64,7,53,223,221,247,108,10,139,128,47,36,225,149,145,94,106,22,86,14,62,13,43,181,226,188,243,228,218,231,144,137,51,46,13,237,21,72,193,233,132,28,220,20,8,4,122,72,237,253,246,222,239,176,0,105,79,66,248,100,211,232,18,217,109,127,11,57,83,34,123,20,60,137,153,193,152,195,96,127,130,205,193,250,201,146,44,174,91,40,108,105,104,231,248,136,114,61,136,124,241,31,128,186,165,230,218,248,76,54,35,51,13,80,241,46,59,34,214,111,253,168,149,252,124,4,81,171,131,110,58,165,172,223,166,5,45,240,154,11,195,26,117,137,238,192,41,98,219,74,113,235,25,234,46,9,144,57,228,196,138,122,230,73,229,42,31,24,18,166,217,131,24,95,177,251,18,240,249,10,235,122,112,16,73,162,6,70,8,231,108,54,87,216,194,174,60,128,244,234,190,212,213,146,128,244,187,133,74,29,128,195,60,234,120,57,168,116,97,234,156,164,173,42,225,70,177,38,184,43,121,148,186,19,207,224,19,253,214,102,184,227,77,205,223,63,242,184,142,75,134,48,96,96,243,151,83,50,87,123,186,147,177,176,62,113,237,99,50,108,201,126,185,218,219,219,241,171,55,44,28,194,49,254,72,63,140,63,178,112,216,15,3,183,189,172,230,154,116,254,246,200,73,82,76,41,15,168,132,147,25,115,46,90,151,15,180,193,60,237,178,105,74,47,191,86,59,221,105,248,98,26,140,49,149,76,146,83,229,173,71,134,78,113,171,186,136,69,240,102,228,167,251,86,198,107,167,79,180,215,210,44,58,98,143,79,188,44,133,107,54,248,165,231,104,149,127,120,62,61,159,252,239,41,101,177,140,108,77,90,49,230,151,125,115,153,80,213,191,17,98,59,202,149,108,239,233,23,177,26,245,216,97,198,111,31,75,248,67,177,55,207,157,212,233,20,69,111,167,232,80,21,144,9,32,199,43,200,181,141,195,9,143,237,154,121,175,158,247,124,39,117,184,48,30,51,103,4,19,16,28,84,98,72,251,204,19,32,194,90,236,170,52,202,181,96,92,120,59,184,47,169,66,177,66,217,150,2,50,182,17,7,131,32,76,227,116,70,174,42,90,163,89,35,33,148,41,240,228,253,31,107,201,210,198,152,13,86,70,112,248,225,121,155,252,134,99,239,2,8,98,108,44,76,227,160,213,104,141,16,130,205,118,253,123,220,48,200,187,80,35,114,62,45,188,107,29,79,220,169,244,147,158,70,102,122,231,232,149,243,55,230,115,28,185,83,39,179,237,221,41,170,240,44,143,39,216,163,87,213,39,157,118,225,99,80,190,57,171,200,20,2,7,166,112,211,127,0,69,167,84,159,62,190,37,46,1,194,192,152,94,188,50,203,38,220,128,2,108,156,32,255,174,254,89,135,44,97,26,237,37,203,70,32,238,3,218,163,213,145,32,244,50,67,233,217,30,131,135,205,0,46,29,143,192,99,180,144,34,96,7,74,212,164,44,215,190,88,252,138,84,97,50,251,203,44,252,175,247,178,155,79,180,28,8,80,184,205,211,9,119,150,32,91,150,4,102,212,89,217,117,71,241,163,146,90,113,142,34,228,139,182,236,101,97,47,152,88,91,161,47,37,246,4,92,89,174,210,15,82,44,118,249,82,198,192,155,172,220,91,168,190,233,35,204,84,24,113,139,102,112,42,108,124,19,27,148,60,159,78,38,239,90,234,5,193,172,28,58,20,182,11,43,162,123,82,184,178,167,19,172,101,106,3,69,146,204,136,46,70,35,133,166,103,74,245,222,246,76,109,232,173,160,36,50,39,140,112,227,59,10,18,127,30,232,161,113,146,233,102,248,171,205,245,154,98,101,53,109,65,36,82,31,241,200,111,216,27,255,10,48,237,213,82,221,17,250,248,215,19,150,56,175,233,19,230,30,233,199,3,100,121,176,189,175,63,20,231,105,113,121,51,88,188,231,109,177,58,34,9,199,121,226,157,183,76,219,41,224,204,61,144,124,88,115,7,214,74,179,178,42,119,144,76,98,58,171,185,134,98,123,177,87,100,213,183,165,147,22,29,151,19,74,146,102,107,158,201,189,0,79,185,36,105,84,104,73,152,103,132,228,196,39,102,113,158,255,56,212,198,37,172,139,31,238,98,184,182,42,69,108,194,245,23,205,45,21,76,115,162,181,174,59,213,233,59,240,184,32,212,226,199,126,11,205,232,217,187,51,197,98,94,117,94,105,152,41,48,22,181,8,146,134,207,30,237,255,240,248,183,191,187,67,210,16,185,191,54,193,2,218,22,99,176,191,233,78,247,165,4,231,131,62,37,109,244,76,194,155,129,212,66,0,101,223,162,211,13,80,169,217,16,68,4,155,216,61,35,76,162,144,217,34,209,73,249,250,253,186,140,124,41,237,124,22,168,97,40,95,47,38,188,204,216,150,184,229,185,174,113,3,154,126,238,50,165,170,12,27,209,53,157,76,118,81,252,10,140,31,103,160,43,171,6,65,205,225,154,85,121,76,216,228,29,241,184,200,160,225,86,4,199,137,80,222,199,30,9,163,177,222,131,91,24,3,147,148,250,20,157,246,166,73,41,246,240,159,85,53,172,227,255,239,211,188,78,85,210,198,63,175,149,47,251,126,139,167,245,143,5,212,41,111,52,133,173,37,114,122,63,214,212,6,98,213,169,140,241,226,233,95,47,169,91,89,117,116,228,30,78,123,163,137,11,19,142,70,121,166,215,141,20,57,100,202,75,131,150,222,136,204,79,199,205,220,46,9,129,92,116,55,148,224,138,82,32,255,250,251,59,239,99,130,13,77,106,233,191,37,70,164,141,160,195,95,192,54,39,178,189,46,17,135,160,255,198,62,249,69,57,5,74,22,165,134,209,143,179,8,28,219,212,141,148,242,233,231,171,234,72,186,111,252,84,120,130,253,206,225,145,123,88,19,194,150,24,168,247,191,92,162,203,56,94,55,72,199,142,76,50,37,253,13,142,159,201,100,153,149,243,217,240,192,204,254,66,239,13,23,161,166,210,210,120,35,7,141,179,109,83,57,146,163,16,195,195,129,214,39,34,155,158,29,244,128,143,18,233,121,150,87,80,227,145,22,207,133,15,10,172,79,48,176,209,68,66,116,22,167,251,162,90,108,98,148,98,84,46,164,185,106,48,68,247,163,112,24,15,78,105,58,173,251,63,10,252,91,83,158,57,178,63,21,40,113,231,82,251,191,134,27,71,131,203,150,222,121,48,211,181,0,62,91,119,123,77,252,183,63,204,142,239,211,87,244,129,213,2,81,221,210,104,182,252,35,116,91,198,172,132,76,148,89,3,74,8,96,232,19,70,18,232,128,18,145,133,229,23,13,93,175,174,68,105,55,192,81,168,1,142,132,193,37,99,188,243,51,14,26,6,195,29,149,159,115,77,169,235,22,66,101,37,224,43,146,152,141,191,222,67,12,74,51,124,129,141,11,37,97,10,50,79,112,123,54,180,89,156,10,237,145,90,99,35,116,84,163,249,196,70,103,144,16,14,13,233,42,5,213,163,203,205,92,6,212,210,195,46,141,24,15,1,215,71,30,31,0,4,24,15,93,217,35,228,173,104,78,117,69,140,243,168,119,62,223,200,171,123,57,184,88,64,53,21,153,201,0,115,146,22,119,84,228,16,189,124,213,148,92,15,178,58,83,69,87,213,137,150,254,92,197,211,157,193,255,150,115,3,222,48,64,41,28,208,245,211,29,135,30,54,205,250,93,94,57,155,196,37,151,90,109,165,11,249,203,106,37,64,103,100,206,108,40,181,36,238,104,208,241,13,26,75,32,133,101,47,132,226,199,174,3,139,186,102,206,19,21,6,166,44,184,63,7,255,61,155,90,233,60,161,86,176,23,97,194,237,176,234,251,116,25,226,11,145,130,13,179,158,222,252,26,235,132,202,117,229,195,232,158,52,183,96,47,219,235,210,51,146,103,15,241,22,194,84,73,169,183,142,81,87,203,6,251,105,254,2,56,164,156,137,219,71,205,59,144,217,70,38,73,57,73,70,131,114,20,249,181,50,184,200,127,251,28,30,92,166,20,252,156,141,128,223,214,176,136,154,210,238,245,131,123,1,114,106,160,197,74,57,4,101,162,185,66,93,219,192,225,68,181,231,74,140,180,121,162,114,142,129,187,73,66,192,218,128,28,39,134,251,0,243,48,55,112,205,204,80,144,149,109,100,247,179,224,228,198,89,225,7,131,170,203,32,130,21,23,249,122,134,208,160,239,23,10,91,107,175,27,56,59,104,18,71,209,245,4,165,227,203,178,69,1,114,130,119,193,171,64,18,182,174,155,16,84,193,55,150,153,90,251,6,94,161,253,223,200,143,16,162,175,93,211,88,243,61,118,144,204,158,163,68,183,243,85,64,42,52,155,32,39,213,93,165,239,188,8,152,93,228,136,71,213,103,158,57,252,54,203,34,230,180,127,56,46,22,5,220,190,103,131,16,64,135,114,68,112,125,205,54,108,113,157,5,31,108,20,138,80,149,170,6,114,65,223,21,159,246,115,158,118,220,203,106,20,66,204,213,59,225,109,136,122,206,137,104,126,66,24,195,83,223,112,36,241,154,219,254,255,248,77,142,202,95,86,171,11,42,188,7,245,217,138,49,224,34,61,121,28,57,25,3,70,9,40,108,107,108,211,160,206,154,77,59,153,161,172,200,23,84,154,131,94,122,115,145,19,13,234,127,86,154,80,149,41,50,98,186,251,36,10,53,159,223,103,104,248,67,154,136,228,46,83,243,36,33,221,157,116,83,109,54,89,171,46,252,120,86,50,220,23,252,185,68,192,125,37,223,233,232,110,16,135,71,175,199,37,75,162,17,48,41,32,39,131,59,145,161,20,26,149,216,99,1,188,240,87,189,8,24,224,227,175,207,156,151,37,76,105,62,202,86,172,9,208,0,186,72,213,78,103,254,132,192,92,113,242,42,224,245,111,181,206,107,130,182,212,63,185,27,28,41,112,220,209,148,172,7,140,225,168,124,67,203,73,76,139,41,226,87,30,125,197,216,76,36,160,168,194,202,181,254,134,0,148,187,242,94,239,72,9,21,148,168,92,66,161,144,73,37,106,39,176,127,116,44,183,89,77,47,138,171,10,169,117,147,107,92,29,184,69,82,220,13,130,34,214,197,214,6,152,46,180,228,77,211,162,47,149,169,145,56,196,174,84,97,93,246,216,30,34,211,137,93,8,161,64,73,106,220,60,107,201,86,86,124,51,9,66,244,168,8,22,125,147,200,68,23,23,247,75,139,87,52,54,5,53,175,14,218,127,126,196,104,220,88,75,122,52,99,226,111,88,137,95,199,196,6,2,87,182,200,67,133,205,210,73,174,53,64,12,134,84,182,73,199,7,65,88,7,24,83,187,31,81,35,236,229,37,177,78,42,143,233,94,241,133,195,255,185,7,218,41,43,231,129,3,23,175,147,37,26,188,70,161,146,126,24,12,38,104,96,209,143,227,254,9,198,24,192,4,227,59,174,32,240,251,5,34,127,186,184,83,193,62,41,187,33,39,239,28,16,118,164,36,171,230,136,212,122,52,86,39,165,85,61,117,145,179,83,209,229,95,227,85,170,136,187,59,115,217,179,60,48,21,67,116,58,14,145,89,89,35,229,5,152,217,138,26,10,189,186,35,83,210,174,165,179,87,168,247,177,43,213,204,247,37,109,164,15,182,108,253,170,140,83,214,151,0,211,81,132,64,43,30,248,18,149,11,44,248,98,107,216,117,38,96,167,82,124,152,140,191,51,40,145,207,31,45,189,144,120,151,236,172,94,196,233,80,172,227,217,187,197,174,24,108,153,189,212,51,44,156,203,149,74,222,95,240,202,168,235,255,91,215,29,201,254,8,156,120,134,162,218,172,153,51,254,189,4,238,93,65,227,158,247,6,74,254,126,91,58,204,84,167,188,223,91,180,79,147,62,150,135,231,158,186,185,126,91,13,115,56,108,78,17,205,175,102,47,20,157,73,175,89,225,242,141,119,215,191,236,127,186,252,109,87,164,233,22,213,98,137,134,97,78,12,13,150,30,160,164,149,154,108,167,156,104,67,228,187,152,143,135,114,154,47,7,21,89,131,179,34,253,135,40,109,220,0,127,213,82,85,64,161,1,113,242,240,66,56,78,225,32,59,26,177,12,19,79,6,212,120,217,177,7,187,76,85,122,133,9,219,81,118,109,201,21,119,47,122,30,190,208,241,78,63,16,91,45,44,253,13,228,18,228,187,96,222,132,166,77,100,226,124,234,61,59,174,40,117,26,163,5,65,107,1,95,18,170,126,100,95,216,113,98,15,186,246,133,3,205,221,228,159,206,212,201,240,175,113,198,72,187,233,28,104,253,239,168,246,139,120,149,143,34,146,39,220,145,216,114,243,109,219,151,117,75,33,162,197,181,62,19,128,118,215,96,101,54,68,109,7,171,133,54,145,1,15,56,224,58,123,172,196,221,3,133,158,85,120,21,246,153,166,1,17,66,48,223,247,230,95,15,223,253,250,109,197,6,190,76,117,7,245,185,143,129,188,191,215,198,20,90,194,172,250,78,233,102,182,120,92,116,208,65,80,84,235,77,57,207,221,127,16,225,96,218,22,104,216,138,195,220,101,236,3,109,87,42,198,95,96,164,202,48,107,45,17,107,246,2,243,229,149,152,83,101,228,91,80,183,254,119,138,201,64,197,135,212,15,171,151,44,69,249,208,188,57,253,250,157,63,153,226,131,155,3,224,56,103,144,28,200,229,192,71,131,21,129,219,235,31,205,144,191,146,253,77,67,78,216,241,242,228,244,174,123,254,65,212,26,35,218,100,1,28,145,247,37,254,116,206,212,40,200,241,209,30,238,181,165,198,211,144,87,158,142,226,70,232,172,134,42,41,121,222,108,17,68,45,47,16,56,26,77,188,99,188,115,118,252,245,11,51,25,44,27,128,31,32,221,54,158,109,102,53,155,4,245,73,26,234,174,198,111,64,52,171,213,56,173,114,145,152,204,191,140,179,22,93,211,35,243,221,136,103,201,155,0,41,110,183,62,30,176,252,190,108,47,23,203,166,160,173,17,124,11,189,244,44,4,13,133,74,224,19,240,200,254,27,57,180,193,89,67,10,147,117,127,169,109,96,98,8,10,21,26,37,181,81,247,202,60,172,58,139,237,116,143,140,46,52,176,49,71,231,243,80,161,14,219,152,25,62,178,232,150,162,47,124,122,155,221,61,212,160,224,158,136,39,24,24,159,93,108,6,145,49,245,189,95,22,153,45,100,83,225,12,97,201,53,242,6,2,23,210,62,108,106,189,178,189,42,64,247,93,171,233,157,196,159,103,239,240,111,60,164,43,151,83,198,183,204,37,185,207,113,120,130,103,10,4,90,144,149,54,51,128,82,233,108,119,172,85,82,79,203,25,184,22,113,202,100,46,34,121,95,234,102,43,243,242,211,223,171,133,152,188,18,134,67,47,2,94,11,17,249,254,0,115,150,132,37,136,76,84,42,91,153,219,138,4,233,91,164,1,243,162,12,134,75,244,55,138,40,252,182,74,245,239,39,45,157,106,56,118,130,15,190,210,138,155,237,239,57,182,77,69,190,113,237,27,178,173,214,149,95,133,12,106,208,89,63,129,174,51,58,43,142,103,103,138,109,123,39,101,45,171,1,233,54,34,208,63,121,151,241,39,0,207,133,172,100,150,134,5,196,133,184,171,253,201,139,186,75,242,123,53,174,38,249,95,72,254,64,108,209,147,37,177,166,69,3,178,95,255,47,41,195,232,6,73,119,89,203,225,150,80,125,183,56,28,82,112,89,167,237,204,73,139,208,233,7,168,90,35,244,133,50,216,254,240,80,227,187,102,135,27,213,192,201,21,175,236,199,100,103,36,247,192,4,133,40,125,16,111,25,177,101,37,180,170,49,230,106,169,123,73,58,231,60,106,230,145,116,211,215,134,199,90,18,243,210,29,225,79,224,248,108,204,147,215,73,244,75,154,145,95,137,151,193,154,146,43,242,175,5,62,42,113,9,57,70,59,133,75,165,250,154,186,143,167,22,47,252,137,102,87,181,104,147,207,195,205,88,18,48,209,126,182,35,179,10,30,175,25,163,6,202,85,185,99,52,208,20,19,242,169,14,253,227,198,85,129,68,11,99,112,59,79,142,105,188,254,123,148,88,153,70,89,84,106,236,34,181,241,51,194,138,62,14,134,245,151,117,235,135,10,139,140,204,146,196,96,242,114,217,131,102,142,129,65,132,108,64,29,42,233,238,33,19,249,17,222,195,125,158,124,202,110,18,183,150,111,199,70,127,8,180,135,203,33,143,230,228,90,44,43,118,241,57,168,162,89,150,106,102,32,60,250,93,143,196,239,12,214,171,73,180,196,199,210,115,112,192,13,9,123,222,213,148,91,19,101,236,101,30,146,43,164,10,156,101,112,151,65,89,151,245,154,56,37,194,99,153,35,80,3,93,62,246,6,68,42,34,155,207,230,215,121,37,213,153,36,165,136,123,181,144,31,215,138,161,118,151,196,108,131,138,93,13,158,182,138,197,184,0,44,139,70,0,204,15,179,245,235,111,229,61,119,1,248,135,70,169,50,116,69,16,223,77,223,248,176,81,63,205,104,150,100,178,216,215,7,243,251,58,16,117,59,213,117,122,156,183,0,72,126,132,100,86,92,240,106,174,220,88,51,75,166,111,176,139,229,215,30,173,166,246,249,201,187,24,250,69,150,214,224,9,17,218,53,173,213,254,11,60,19,32,202,124,40,131,51,99,223,226,217,190,252,29,14,39,73,199,37,180,254,114,46,169,46,109,205,172,86,62,198,113,209,186,149,211,122,42,239,238,71,133,33,39,217,86,131,68,199,243,26,0,143,97,215,140,217,34,11,55,192,118,66,69,203,200,128,171,40,250,94,127,204,76,168,232,153,226,37,150,4,8,22,177,75,64,204,39,19,45,127,173,174,14,222,159,184,66,88,61,250,133,231,114,166,164,33,157,77,203,31,222,189,111,131,178,107,117,10,165,203,18,211,117,188,134,254,238,158,123,143,231,245,189,89,21,88,66,169,241,24,26,210,108,105,249,56,37,196,36,26,110,237,31,34,198,114,72,218,133,14,40,38,0,26,218,130,56,146,228,86,253,43,36,112,162,58,232,178,162,105,114,186,74,187,229,215,195,101,241,14,24,95,246,248,101,255,68,164,79,41,18,245,65,11,228,167,132,169,52,170,196,91,52,224,204,230,105,193,231,254,49,143,85,42,221,140,233,18,131,116,86,127,103,136,113,15,23,95,39,90,226,59,168,56,73,43,227,171,60,251,5,66,24,207,129,225,168,127,243,190,108,173,215,76,110,107,75,120,242,147,252,217,57,234,116,1,133,221,90,162,174,126,61,236,200,53,105,71,155,217,56,85,6,214,13,60,119,234,225,200,186,152,215,237,225,105,85,252,240,252,38,75,220,200,6,243,144,34,127,161,14,197,107,63,75,235,195,72,44,27,244,129,243,201,59,241,45,173,62,200,145,232,76,142,208,183,15,77,119,157,26,157,170,159,104,206,13,248,132,68,229,234,196,252,168,229,154,203,44,177,54,200,235,132,93,52,10,196,60,152,226,220,27,98,85,215,82,144,161,12,76,202,47,71,231,225,223,105,35,201,195,174,188,10,168,199,141,255,108,74,166,226,33,4,203,54,202,178,27,127,250,86,181,225,246,70,219,65,173,49,214,202,71,22,67,184,54,90,182,251,202,40,14,235,63,201,190,75,65,15,33,62,81,56,157,55,187,67,3,223,5,188,105,211,72,202,95,229,207,20,1,219,121,116,56,5,116,227,97,48,200,192,252,86,238,56,125,89,89,89,100,76,5,180,81,31,33,111,202,211,182,51,25,81,28,239,153,125,85,67,149,136,118,157,65,84,65,43,74,86,81,238,45,7,227,222,145,234,95,152,157,225,22,53,47,59,189,252,16,40,26,171,155,247,98,73,206,206,218,9,241,152,213,3,15,107,123,100,86,78,2,200,194,8,78,101,235,150,113,69,232,13,102,131,200,41,240,126,186,238,184,20,62,218,235,221,116,53,44,20,219,104,254,112,139,81,119,100,253,105,53,62,247,159,166,75,128,64,51,7,193,108,154,115,34,146,127,75,102,17,112,81,35,33,255,104,228,11,97,24,252,219,214,122,235,2,28,34,128,252,220,126,248,87,48,200,149,102,191,135,59,48,111,142,210,22,87,41,25,209,90,114,67,98,234,128,53,45,198,155,116,161,66,14,216,226,63,200,18,7,20,213,60,221,77,128,48,20,142,208,197,61,210,161,90,77,80,146,220,80,168,29,93,171,234,195,182,134,136,225,120,206,94,147,141,52,199,5,155,74,143,12,252,50,79,254,135,78,145,222,143,150,128,28,137,206,79,88,83,195,0,213,182,223,225,201,191,235,235,39,175,202,211,139,11,109,8,255,251,237,232,33,37,250,169,184,42,115,205,55,220,211,160,190,225,201,208,87,227,181,15,92,123,111,172,104,71,23,236,206,214,177,119,77,128,149,238,102,224,147,48,143,82,158,83,179,110,112,12,75,86,190,48,208,14,156,92,140,55,64,14,23,106,204,140,48,97,72,62,247,14,217,121,31,224,171,233,69,177,129,185,71,17,87,96,138,78,19,178,198,229,37,235,51,51,208,149,100,111,39,54,197,126,215,245,125,0,18,64,157,246,4,183,62,21,82,209,182,193,74,163,255,99,143,38,119,30,171,116,62,129,241,64,167,205,128,48,19,141,208,126,96,231,17,94,11,123,106,132,252,127,95,4,217,84,100,231,9,56,144,178,55,92,107,154,194,164,113,19,93,117,152,188,49,241,135,95,131,177,63,10,247,179,86,47,153,63,125,70,239,205,3,48,196,135,152,123,146,5,229,21,112,255,72,4,180,42,148,238,234,211,163,111,223,49,176,36,101,182,121,145,65,242,151,27,181,100,235,212,127,238,78,165,2,36,188,117,89,217,137,39,32,249,156,72,106,48,65,177,35,119,166,109,125,93,15,74,133,194,177,8,208,79,4,23,216,37,3,20,67,12,40,52,11,160,213,96,177,234,40,240,251,19,126,81,186,153,249,204,11,91,78,70,238,38,31,243,13,156,49,165,95,148,218,155,179,139,30,216,15,153,27,164,59,189,173,159,141,146,16,21,167,183,161,203,82,140,66,150,182,16,73,40,176,102,55,118,132,173,249,137,117,137,145,90,53,86,164,24,152,171,14,64,192,181,253,238,22,204,59,115,228,173,155,232,15,108,250,14,135,190,177,25,54,114,152,83,38,132,125,185,243,134,112,168,170,99,100,155,125,107,46,165,146,10,12,243,170,39,155,195,220,140,129,9,27,178,166,144,112,200,134,3,146,228,27,60,217,251,147,93,72,56,196,158,217,177,53,113,146,111,93,172,7,71,165,196,105,120,164,255,79,158,235,183,45,61,139,128,87,87,24,202,89,236,50,129,135,90,217,225,115,211,102,32,22,124,87,167,76,209,47,193,179,5,176,1,172,115,53,235,4,198,69,17,146,1,156,60,169,171,3,154,137,1,8,160,180,39,33,145,194,221,167,74,225,147,22,226,175,161,190,155,99,104,36,234,28,206,255,153,106,146,140,248,208,160,159,129,189,81,79,151,34,57,191,19,60,238,132,173,126,112,102,40,167,236,248,169,15,165,62,167,248,117,241,242,52,190,179,82,62,174,253,135,166,242,116,101,164,25,44,212,205,199,182,51,26,85,54,11,16,243,103,183,145,84,222,115,193,84,191,14,243,49,214,76,187,20,39,29,243,173,156,181,219,109,64,24,75,52,179,28,160,231,99,85,33,44,165,96,91,1,116,151,203,247,43,74,128,179,172,198,31,77,89,11,160,120,13,159,140,72,217,110,79,78,206,233,178,98,50,152,74,216,73,133,249,217,70,75,56,129,241,107,234,100,37,103,60,16,188,2,190,11,70,104,226,153,93,247,153,143,161,19,20,220,168,207,59,231,145,117,83,136,104,18,107,25,84,26,105,116,169,98,24,122,32,236,228,193,206,223,235,29,238,49,143,225,2,196,58,61,127,140,102,14,140,100,86,158,130,245,106,213,21,195,130,77,170,38,87,189,28,239,43,9,141,221,172,71,101,23,117,196,97,176,152,245,228,11,197,252,84,206,70,36,202,196,205,27,80,137,39,25,75,180,73,162,224,150,97,44,115,24,151,153,239,190,250,64,81,124,193,49,199,158,225,239,216,251,150,194,11,43,136,66,171,93,122,163,101,50,248,76,30,251,201,114,80,75,69,109,212,155,11,141,217,118,95,15,127,174,149,147,216,251,178,89,253,92,51,157,16,128,60,144,26,219,47,131,125,182,76,241,164,209,6,26,7,92,85,220,173,245,230,208,98,209,124,70,173,192,190,132,55,211,201,186,183,60,108,73,202,134,11,25,98,22,219,173,173,140,39,222,243,91,17,177,81,168,144,244,94,105,34,211,227,16,134,9,254,20,51,4,182,243,203,82,63,238,89,246,230,147,185,200,52,129,113,141,167,177,99,18,247,119,52,84,13,203,187,89,98,35,178,30,13,149,205,77,136,197,164,183,202,225,132,158,34,253,166,180,170,81,56,53,16,116,34,149,120,212,66,17,226,5,193,175,148,81,251,230,23,177,141,43,79,103,153,84,172,51,44,242,34,237,188,74,225,118,144,129,40,56,96,157,254,134,231,14,209,110,23,26,41,253,29,33,247,80,149,196,100,34,23,183,198,124,246,191,174,56,254,31,119,127,229,154,236,190,38,98,101,91,126,182,201,156,27,210,62,101,17,18,95,17,62,112,173,218,95,8,203,29,169,3,23,137,111,219,234,54,156,50,148,31,227,60,56,205,74,105,149,45,57,162,39,83,232,38,150,169,204,161,15,212,82,220,124,196,127,1,123,135,186,208,13,210,224,127,223,143,131,107,123,201,10,21,58,99,135,64,212,81,242,174,16,20,198,65,72,42,58,79,59,206,26,52,133,57,223,232,6,119,87,13,47,214,82,42,153,242,77,203,163,205,22,188,0,129,78,179,114,86,63,119,183,248,180,74,200,49,174,239,118,170,130,129,69,61,251,182,192,219,239,214,192,255,58,247,26,49,105,232,74,79,103,145,214,114,231,134,233,230,182,242,244,118,246,117,136,107,207,19,107,184,247,251,123,157,189,96,101,189,162,223,179,99,10,86,165,128,163,231,16,244,57,68,233,20,250,104,28,166,38,49,110,177,66,17,127,187,199,42,122,137,238,193,107,95,247,227,189,113,10,75,176,213,70,136,141,144,164,87,37,42,23,127,141,164,183,78,139,218,128,235,216,244,18,237,172,200,24,113,21,112,117,16,59,41,136,9,155,210,169,170,75,221,91,65,24,147,102,178,110,106,220,193,124,222,37,240,191,119,132,54,85,182,115,221,35,234,48,168,174,45,235,227,126,189,190,94,228,240,101,211,112,91,127,57,151,48,255,55,129,17,139,254,252,80,114,75,182,22,51,188,91,109,69,192,230,36,179,138,232,162,3,131,1,137,52,56,241,139,77,224,236,177,175,210,192,80,187,135,105,224,116,81,229,132,151,223,232,67,207,191,76,55,255,26,58,42,239,48,161,0,251,40,166,214,231,173,40,122,99,165,8,170,84,14,152,38,0,60,172,198,70,127,95,75,16,127,6,6,164,64,141,172,238,59,222,131,224,43,38,141,127,96,100,62,2,30,34,180,54,230,3,150,5,231,193,31,96,61,201,7,121,144,136,49,68,114,1,180,193,165,67,117,98,92,230,45,153,167,120,227,39,220,201,40,218,176,242,79,255,176,197,84,44,219,188,24,123,109,252,180,10,54,56,205,152,158,23,34,226,122,114,118,86,190,135,145,210,139,53,111,80,254,12,33,99,114,50,69,174,102,63,40,134,203,163,241,201,210,132,197,30,194,21,41,67,111,169,59,137,176,140,87,223,35,219,148,41,17,47,87,132,177,195,184,155,62,44,57,51,61,166,176,0,78,17,239,248,132,24,90,111,0,114,11,243,116,156,217,62,172,237,169,184,102,49,203,132,170,173,228,19,92,247,110,129,213,51,246,166,189,117,14,122,133,32,168,49,250,110,109,130,233,47,207,247,73,245,53,4,163,18,37,68,143,96,159,144,46,41,170,94,167,114,150,192,69,209,251,219,13,111,213,186,98,240,94,100,151,249,137,215,40,31,202,233,102,233,87,154,45,180,231,125,239,156,180,218,112,223,97,62,42,141,65,252,126,67,80,247,250,233,208,232,35,192,160,163,194,226,126,10,45,236,6,185,108,216,204,37,163,11,79,111,48,215,146,155,158,134,141,203,55,89,61,222,33,78,82,125,74,58,124,11,39,39,25,125,19,251,109,165,69,192,6,62,4,243,172,60,180,97,171,114,245,37,98,216,173,83,172,42,223,203,123,98,129,233,163,55,50,102,117,207,223,131,8,155,151,246,17,163,194,153,249,69,72,100,93,139,51,97,70,143,174,24,21,44,73,67,97,203,26,232,224,113,226,185,74,242,203,51,164,179,209,188,168,1,102,93,74,120,214,135,191,193,209,7,112,218,199,145,10,92,23,239,226,242,205,187,159,126,171,125,35,158,53,118,74,19,183,224,31,116,118,13,32,211,205,92,131,123,48,181,32,124,7,233,247,254,24,251,109,189,0,184,187,80,73,194,94,100,239,81,170,145,20,235,132,230,56,141,90,22,151,198,88,153,66,134,20,94,237,62,58,110,218,255,50,111,198,109,211,202,21,39,7,30,238,147,85,35,154,58,236,112,221,70,102,211,120,115,74,109,188,70,229,214,191,122,134,120,195,231,217,122,35,113,9,110,154,50,82,32,35,111,159,191,205,52,223,124,250,77,32,228,68,131,215,255,245,107,10,80,105,104,31,4,173,207,219,31,219,171,182,182,254,211,181,183,202,185,238,165,167,38,248,72,193,90,249,154,165,80,64,209,68,160,49,226,93,135,143,48,97,211,47,187,29,120,160,203,115,39,87,245,227,220,244,5,60,57,251,126,42,117,244,81,69,98,77,242,210,249,188,19,130,253,198,56,95,174,249,187,185,215,132,16,226,25,29,180,25,54,143,69,121,134,79,117,180,218,210,211,236,58,207,231,69,104,95,149,166,212,59,105,131,68,83,21,233,177,143,135,83,237,99,3,20,58,123,234,249,128,199,117,238,163,124,52,215,100,124,76,146,61,253,192,135,196,87,201,115,149,98,141,214,85,252,207,188,13,34,208,166,93,132,22,39,44,115,121,203,93,78,137,69,196,253,197,120,148,36,21,208,5,95,43,5,122,145,41,160,12,117,201,143,36,62,133,73,185,73,185,155,194,182,166,248,96,33,9,112,7,42,39,42,203,253,23,196,161,187,66,234,58,217,44,48,7,139,47,158,58,153,179,83,189,27,100,164,156,234,199,98,117,100,38,11,24,163,169,221,244,159,173,191,177,229,194,60,25,229,142,239,38,104,95,145,238,47,214,188,90,21,66,126,66,111,210,228,101,36,242,172,130,97,234,90,20,62,166,38,11,198,159,44,245,249,131,27,135,234,87,83,2,62,185,253,129,60,125,165,26,164,138,148,193,87,246,201,45,72,3,33,31,191,29,45,33,15,238,109,8,39,100,38,195,128,83,7,133,205,161,144,113,161,194,75,111,13,7,188,92,227,251,80,96,18,64,26,145,25,40,183,204,243,127,122,119,214,146,16,231,175,187,101,92,23,25,172,45,195,139,252,212,135,73,86,24,33,203,30,64,143,202,39,238,180,143,39,141,32,30,65,76,186,57,211,14,143,45,98,183,16,106,103,221,249,6,53,137,24,139,142,183,198,247,95,139,222,54,254,33,32,110,206,70,243,213,3,192,199,172,149,164,83,182,93,148,177,50,21,141,173,13,238,107,195,127,67,110,37,112,43,142,183,230,190,209,160,162,156,23,27,134,24,34,52,140,72,249,61,178,169,148,8,130,66,147,91,31,208,121,252,240,86,4,49,94,172,145,170,231,175,155,91,81,34,65,35,19,119,54,89,16,204,192,75,121,73,147,188,144,117,13,228,38,41,170,216,212,138,219,190,30,66,160,168,25,44,46,139,91,239,138,252,75,214,254,70,38,167,102,27,83,199,3,87,193,132,173,198,46,20,126,199,149,77,169,28,80,101,104,137,62,96,184,186,195,156,232,54,165,152,181,234,109,221,187,146,210,235,81,120,213,202,4,54,76,73,143,91,58,186,245,234,169,42,230,22,18,250,90,107,166,223,111,105,64,154,164,4,224,90,136,137,59,115,161,111,33,203,195,109,85,228,153,230,42,60,71,72,5,2,62,18,247,95,210,226,191,18,86,215,250,188,187,220,235,252,237,222,248,38,43,49,68,167,200,78,234,221,147,5,179,21,224,63,87,13,134,86,163,63,36,111,99,183,191,107,252,17,109,125,244,237,227,124,248,96,249,123,151,124,55,89,15,60,83,228,51,167,78,178,149,160,185,115,84,80,74,205,223,140,130,90,11,7,178,123,40,235,140,10,228,159,27,22,21,27,35,97,198,101,3,45,152,101,159,133,198,240,50,167,96,88,76,87,206,44,39,249,11,105,101,233,91,94,0,117,182,228,62,63,40,7,175,93,108,94,109,10,13,105,155,235,242,84,115,42,225,207,146,64,214,155,15,160,204,116,101,205,129,106,90,130,161,1,205,66,106,134,110,197,2,121,251,255,76,57,17,131,177,22,249,53,191,239,3,209,175,23,202,194,236,120,82,27,150,175,201,140,218,92,66,6,242,27,242,72,21,153,249,76,147,161,201,108,133,37,82,63,157,26,16,157,157,53,227,144,45,33,251,159,166,102,14,146,8,130,61,71,232,239,55,149,154,94,62,201,196,46,66,64,182,197,173,177,174,129,184,239,93,144,26,35,78,229,198,0,35,11,0,24,58,31,116,17,14,148,173,217,199,57,30,154,70,63,65,205,96,139,15,161,221,167,15,248,53,144,210,247,198,28,89,183,77,185,161,137,46,60,33,250,124,201,6,162,14,149,173,139,246,183,196,97,174,62,140,41,85,124,32,241,157,180,188,116,43,88,101,206,143,162,87,136,175,53,8,137,29,26,223,233,139,150,187,232,66,160,175,236,60,249,74,124,88,0,169,71,249,158,190,158,10,136,161,14,192,129,205,123,206,139,139,194,116,10,232,178,229,135,29,133,175,175,159,206,251,200,116,49,111,179,231,204,59,114,82,198,44,18,188,92,104,214,214,0,99,131,131,20,13,139,95,163,166,89,240,125,147,162,92,27,236,208,194,108,76,213,90,135,100,0,183,53,71,191,95,49,61,227,177,149,62,19,73,102,79,254,208,162,75,217,114,173,130,116,114,179,103,102,51,151,84,216,208,210,52,137,180,99,72,124,128,249,247,136,183,36,28,249,242,125,70,239,231,22,75,183,222,194,216,180,98,166,182,159,27,186,214,74,253,234,220,112,80,103,58,215,113,70,28,68,149,92,181,110,119,67,179,179,9,96,140,249,194,72,173,244,144,58,9,141,246,68,237,118,179,124,164,96,125,30,196,126,104,19,176,107,25,7,162,89,236,206,184,139,167,166,16,55,67,7,93,251,90,252,86,252,171,140,238,114,28,106,253,2,64,26,18,192,199,145,70,224,41,158,81,211,254,47,235,74,231,215,176,97,187,165,209,79,109,189,21,14,209,97,193,29,254,42,24,157,72,5,143,9,214,54,90,86,243,143,140,12,163,2,158,213,69,48,232,80,165,123,73,197,247,8,241,232,198,127,142,153,236,153,145,20,27,64,72,56,14,13,147,102,116,211,20,44,176,108,13,229,36,230,81,206,9,197,5,42,177,137,125,239,52,138,145,92,76,16,223,134,138,221,234,177,91,177,210,67,1,151,117,176,201,125,211,227,144,217,180,31,53,97,31,147,33,222,114,225,63,236,245,62,68,54,30,147,134,96,110,84,124,209,201,141,3,62,115,79,24,228,194,3,74,218,184,3,66,224,170,40,123,37,121,61,129,54,53,103,197,43,89,135,6,26,104,193,193,136,152,56,142,183,224,128,35,138,123,231,218,184,64,116,133,134,79,71,93,163,18,65,127,217,137,72,42,147,44,193,117,255,58,201,221,139,83,224,169,171,21,200,243,196,43,229,12,27,96,110,87,50,136,174,144,220,236,35,210,9,136,71,10,14,95,205,206,230,46,210,240,140,197,31,1,18,188,0,238,15,228,67,49,220,86,132,126,70,124,204,88,118,84,251,214,36,171,200,70,160,93,190,20,193,149,122,208,201,60,231,13,227,143,217,98,120,101,241,47,166,37,0,246,166,53,179,69,210,170,111,102,237,39,29,58,140,90,17,30,66,50,240,135,134,156,130,216,158,96,227,238,43,173,150,62,156,252,12,213,121,200,99,178,38,253,248,51,29,232,51,139,88,26,160,174,235,4,96,47,68,39,65,224,118,4,246,129,110,151,23,33,196,101,107,18,57,33,181,138,239,175,105,157,49,247,51,175,4,49,223,166,210,239,121,16,164,212,230,198,33,63,150,165,9,54,147,43,215,241,224,55,27,106,204,89,39,184,161,80,49,4,115,240,147,14,244,80,211,157,188,47,240,27,232,175,82,215,194,147,55,86,12,143,240,196,252,206,171,147,238,96,167,220,204,222,124,57,43,217,33,94,205,196,224,116,99,78,12,233,159,227,1,76,43,79,235,217,146,66,161,211,175,94,65,74,199,243,183,6,81,84,203,242,106,233,76,173,158,214,45,43,108,174,250,106,136,126,230,63,14,251,213,18,71,87,50,64,255,236,85,183,102,109,45,1,174,202,9,149,185,253,197,58,210,45,138,136,51,85,221,138,73,184,106,127,134,253,72,58,18,180,62,151,29,82,139,220,202,116,64,248,20,81,96,109,47,138,242,186,193,36,58,228,83,194,172,38,0,252,218,244,10,112,115,142,57,210,57,11,64,200,229,159,61,193,101,132,118,218,80,148,208,24,56,50,42,216,65,221,198,222,42,94,40,195,189,60,175,28,71,25,114,164,42,45,8,67,46,142,204,238,25,167,37,150,221,46,11,216,39,161,104,150,116,113,1,94,67,6,9,155,180,85,217,5,244,160,99,51,203,177,93,136,13,60,29,150,143,141,45,240,202,86,52,252,208,169,251,4,6,159,54,129,123,18,109,207,1,191,79,38,187,105,43,96,244,160,246,58,53,1,126,98,82,106,12,250,65,44,103,65,155,146,190,0,201,249,32,20,57,171,220,149,156,114,51,66,148,220,137,156,113,120,32,169,126,124,13,130,177,138,31,55,46,148,240,128,29,71,141,116,145,112,8,66,189,190,216,123,114,164,94,213,103,242,213,46,100,240,150,169,179,251,110,47,164,50,174,245,163,245,59,14,243,8,35,82,74,151,19,130,70,32,129,139,54,14,190,35,131,230,71,44,133,253,187,52,219,118,239,235,58,76,31,196,252,32,242,187,197,157,187,55,29,121,51,214,250,24,234,46,96,133,232,102,63,43,191,186,226,113,189,64,205,186,249,119,43,113,194,61,250,58,221,69,191,75,14,152,187,167,243,108,156,124,46,5,218,175,243,118,7,240,85,167,144,192,213,61,210,252,162,165,162,46,86,124,240,63,149,35,88,159,198,71,207,56,140,25,144,133,248,190,191,241,252,13,124,234,108,165,9,106,44,119,178,102,193,221,168,140,143,125,102,211,106,41,163,241,103,12,131,227,10,78,64,224,131,209,128,108,224,131,81,196,188,208,57,0,65,7,171,245,92,68,97,155,26,19,0,220,173,153,62,182,16,55,19,229,89,135,80,157,145,162,168,60,3,54,77,8,252,62,78,45,97,13,187,5,95,233,221,143,244,218,237,9,191,191,111,230,19,235,185,24,229,133,236,211,127,22,70,243,186,237,63,6,52,140,155,111,172,124,143,130,20,198,240,17,48,164,10,74,221,17,240,102,82,73,186,66,214,132,28,226,189,253,197,216,71,13,102,76,54,192,250,157,250,97,33,169,125,119,76,18,127,148,89,55,79,41,27,171,173,241,40,25,242,210,152,51,104,129,66,79,162,178,205,127,78,159,148,90,244,237,62,200,220,157,71,215,30,45,95,17,166,151,2,107,156,25,214,202,113,205,64,70,182,24,9,62,176,176,190,16,176,188,96,117,242,77,22,88,50,108,118,138,246,209,82,199,143,160,77,201,121,197,140,194,143,8,181,195,45,95,221,40,139,214,14,153,166,70,195,180,165,102,177,227,237,193,79,231,55,66,91,102,116,212,200,47,182,152,106,44,255,140,122,66,158,160,250,117,112,5,28,227,9,101,161,115,43,75,216,160,129,201,85,4,155,212,168,94,163,160,204,9,102,25,233,102,160,184,227,106,238,100,129,31,84,122,126,254,145,223,210,150,80,172,229,177,248,245,3,169,238,5,16,2,78,51,54,207,82,72,227,99,136,26,105,129,53,22,17,45,214,181,195,68,36,56,169,195,242,5,8,191,67,154,4,98,246,26,112,153,140,77,237,240,2,154,115,169,245,170,100,202,110,18,149,98,123,104,24,71,192,232,157,222,215,83,47,36,18,129,246,103,237,227,185,218,144,30,199,136,151,160,138,100,74,32,166,208,86,67,75,237,132,120,166,153,52,64,10,225,171,2,81,131,86,59,191,48,93,62,184,125,186,164,181,232,91,66,146,242,21,173,53,43,188,74,248,215,108,185,224,167,76,81,71,206,93,12,235,166,22,241,224,190,133,235,131,111,103,60,230,112,49,52,171,86,194,94,59,123,115,191,87,69,241,194,32,229,82,37,247,66,83,202,39,30,54,213,89,3,78,249,44,22,248,167,57,0,84,189,32,168,147,103,6,140,148,202,187,193,37,38,180,46,29,166,57,72,223,230,106,44,108,111,251,141,251,89,7,111,191,116,203,52,57,144,49,241,196,170,155,145,94,130,81,6,8,48,239,173,230,55,130,69,187,163,225,66,214,151,106,237,182,124,152,252,164,152,71,188,138,18,156,234,158,96,75,48,112,107,71,163,19,180,198,24,225,112,151,114,89,6,217,49,26,232,78,138,51,90,69,91,193,126,130,54,20,217,158,121,249,61,85,203,2,97,83,109,237,170,254,0,91,197,122,244,126,45,233,234,109,127,179,19,219,93,31,65,76,94,19,176,192,62,20,225,161,144,181,212,117,211,254,177,20,119,165,4,191,21,105,172,116,103,36,198,101,166,240,111,212,21,87,239,249,26,153,242,52,76,142,34,251,237,81,66,187,57,122,29,236,37,110,21,148,230,218,247,104,63,1,234,5,69,199,73,134,157,172,42,231,147,224,75,141,129,211,82,4,89,195,246,70,171,181,93,183,55,108,159,166,33,84,4,185,111,204,210,203,121,247,47,11,38,196,128,175,73,224,158,13,7,251,219,162,20,164,80,64,199,241,117,6,96,69,101,173,208,37,165,211,107,165,193,43,31,159,138,214,247,2,33,12,191,208,158,105,240,17,229,141,41,237,45,38,45,115,88,232,28,191,188,150,228,13,47,17,235,94,149,41,105,96,203,124,26,222,106,9,189,50,92,15,120,136,57,57,255,99,51,112,155,217,186,209,181,137,48,198,43,39,230,86,230,26,217,240,223,93,238,195,80,220,79,238,160,255,161,52,146,25,191,179,0,106,203,39,179,207,46,133,153,151,239,88,57,122,189,135,89,178,115,230,216,10,114,143,251,93,168,61,169,202,150,202,196,237,75,49,182,183,125,110,19,34,1,136,14,89,81,155,227,118,201,69,250,152,109,216,132,250,88,147,48,2,191,100,195,211,13,126,162,119,72,133,229,123,207,22,23,212,210,63,155,150,227,57,166,222,129,67,70,42,85,154,245,247,41,193,230,95,156,113,40,103,226,86,19,6,181,49,124,103,224,189,223,33,119,236,24,20,229,68,141,154,5,89,177,163,212,125,152,33,38,48,226,24,141,151,158,51,86,207,22,139,80,172,113,125,82,37,229,71,24,29,22,151,195,95,177,29,49,74,158,121,217,68,52,92,168,158,88,196,251,22,3,155,79,122,252,156,221,200,181,70,100,216,71,156,175,156,86,2,231,130,108,43,211,119,75,181,114,163,95,222,24,246,255,186,183,186,101,37,137,223,53,194,47,117,58,55,235,209,179,14,167,242,26,134,221,36,193,38,118,184,207,96,67,32,145,250,154,128,94,25,66,185,48,57,213,130,222,58,197,173,252,78,101,199,141,206,155,94,81,157,155,216,239,200,168,141,203,59,210,55,17,55,170,5,110,70,51,20,19,17,219,187,198,121,220,48,135,101,52,185,215,244,4,37,229,220,138,211,126,144,244,210,14,194,134,9,176,26,52,128,5,94,173,63,199,171,196,37,142,16,185,13,98,224,38,105,153,24,182,124,179,35,177,69,226,224,127,75,236,2,98,7,44,185,3,14,107,156,129,152,51,36,29,203,211,203,108,162,74,162,216,89,12,128,9,112,14,157,147,3,227,248,177,51,228,239,231,213,231,254,82,42,244,137,106,99,170,156,192,66,71,139,213,5,156,125,195,124,229,130,190,205,89,225,241,254,176,95,30,219,40,248,129,218,116,222,75,183,241,249,60,88,178,52,92,157,156,113,232,162,36,107,47,55,17,155,162,70,224,125,82,84,211,203,26,49,246,193,94,207,161,122,216,126,138,16,206,87,28,38,45,30,196,186,30,68,206,95,156,208,218,236,93,107,125,217,121,46,223,4,69,183,46,238,206,71,72,167,159,167,48,118,25,0,159,147,140,99,166,172,4,113,21,161,52,102,54,219,194,90,106,50,6,156,202,21,86,112,33,45,53,6,124,162,83,226,178,246,1,165,167,177,190,237,128,219,79,114,30,187,31,146,10,157,251,80,124,108,191,233,91,104,68,35,156,13,54,123,191,37,77,245,82,222,206,8,246,133,27,217,87,116,7,145,65,128,81,142,250,19,137,207,10,217,88,150,119,183,30,231,123,9,189,145,113,150,247,204,148,101,142,228,144,127,101,122,157,153,221,45,112,44,139,13,223,94,18,221,245,14,185,252,132,117,15,173,122,121,1,251,109,2,107,25,97,29,180,199,11,124,161,138,37,92,119,254,245,118,34,128,28,100,200,80,5,114,99,208,232,126,215,247,226,193,129,111,229,166,12,107,30,67,118,84,156,100,158,204,44,28,118,134,227,10,22,153,126,77,13,134,137,18,167,115,62,98,60,182,179,66,109,93,146,39,135,247,137,193,45,175,156,83,87,217,63,250,57,154,128,151,152,45,35,43,126,198,229,219,126,200,145,4,236,251,153,196,162,89,73,134,96,119,107,128,190,147,228,64,73,220,100,124,73,203,91,213,77,92,68,50,107,69,237,110,138,228,193,175,162,213,78,39,118,105,39,11,196,157,25,195,35,53,250,121,123,219,197,179,143,206,30,210,251,106,231,243,37,84,55,23,7,30,84,11,121,92,53,9,191,28,49,57,237,112,78,183,12,215,243,99,159,238,14,246,197,136,207,69,0,120,99,89,37,184,54,94,128,204,224,174,118,50,226,59,151,162,115,167,144,223,213,199,4,87,55,193,10,212,169,238,242,254,70,213,252,87,32,245,18,157,79,122,232,143,103,31,93,140,93,243,91,156,91,223,136,12,68,98,200,179,170,185,195,112,27,104,3,205,165,28,186,174,118,57,189,119,144,158,95,158,164,143,139,58,87,217,43,22,68,43,126,240,70,94,163,225,233,248,227,168,70,198,16,51,205,239,192,4,124,244,190,80,130,188,253,65,63,201,98,243,142,139,238,115,52,164,188,234,11,203,33,66,111,40,174,113,78,139,135,102,209,122,166,53,10,2,10,140,215,139,223,100,11,23,208,126,65,214,52,37,98,93,37,250,159,75,209,155,248,86,107,5,114,199,254,105,179,240,132,18,228,65,136,188,180,168,141,149,43,234,13,114,25,92,32,8,212,172,186,194,234,241,77,20,142,76,140,225,110,176,248,93,52,69,8,47,143,25,99,166,56,37,228,218,183,234,205,236,237,168,228,136,179,145,123,254,230,182,37,220,223,96,199,45,24,147,73,86,254,47,90,124,89,129,192,199,167,216,217,62,148,163,46,107,74,67,155,206,30,163,44,42,238,69,77,5,86,126,151,131,136,59,134,63,72,23,50,35,228,75,48,172,147,4,200,35,217,142,56,51,159,145,237,51,218,27,192,43,193,90,63,194,218,149,77,69,58,68,24,177,235,144,245,52,41,241,21,63,202,204,123,60,245,245,147,59,230,53,58,179,177,6,108,72,142,101,202,171,147,1,238,27,183,145,157,7,29,13,111,137,129,183,185,196,139,126,204,48,220,237,170,227,65,153,226,170,245,241,69,250,74,235,39,129,115,94,113,165,212,140,219,239,255,30,2,150,71,167,222,250,123,230,253,102,110,67,175,23,73,166,0,144,47,148,163,151,221,23,81,24,247,230,191,244,11,1,206,112,51,40,182,33,40,163,61,107,169,167,6,202,202,72,255,23,102,172,225,38,148,226,88,109,43,255,21,145,157,184,0,241,95,26,253,89,42,53,13,149,184,8,74,173,119,80,63,39,122,131,186,46,224,96,135,125,146,230,186,215,105,91,230,163,169,125,167,150,59,214,137,125,94,22,30,51,110,143,175,201,170,44,185,136,253,28,105,89,77,41,65,135,12,60,237,170,191,75,127,88,149,34,205,123,6,139,121,217,249,166,254,165,197,104,144,84,48,58,172,21,122,128,85,199,148,36,114,91,239,123,1,206,8,169,49,206,39,142,97,137,189,224,169,198,119,13,171,201,140,49,157,103,118,88,94,210,27,126,242,245,68,55,25,204,114,244,247,64,29,145,137,154,56,172,22,62,19,227,79,143,90,5,12,201,194,154,224,71,103,79,31,119,20,146,114,219,19,44,92,21,211,69,49,20,95,47,183,25,195,60,209,50,238,182,244,59,9,94,112,27,36,210,214,7,152,57,84,87,219,76,117,252,173,214,2,188,162,120,141,43,194,108,127,121,25,148,205,129,10,46,39,41,144,243,52,218,147,187,37,188,247,50,228,177,63,51,214,17,10,240,24,244,129,34,87,146,124,5,230,163,171,120,234,22,101,103,156,68,245,144,114,132,132,244,163,47,127,235,219,88,243,187,140,196,153,78,126,139,116,152,107,147,27,119,0,2,213,231,59,70,73,214,67,31,130,51,71,155,189,211,225,165,140,83,24,36,56,202,105,50,33,140,155,216,216,209,252,54,156,254,20,81,120,206,235,241,53,194,44,177,128,30,239,26,95,124,88,90,21,132,123,188,158,141,127,241,223,95,178,108,21,221,145,222,26,192,180,84,129,78,175,117,146,57,215,116,10,13,53,12,252,227,64,32,115,213,68,143,238,155,225,101,184,132,28,92,127,89,232,1,139,160,185,99,115,92,29,188,211,254,180,85,121,47,205,53,199,122,73,153,119,188,74,163,229,129,90,48,50,178,91,189,168,116,38,32,114,55,89,132,116,208,124,128,113,113,16,206,199,26,163,212,71,1,250,155,96,53,100,44,246,31,136,208,243,220,60,176,23,103,88,245,48,51,59,225,235,226,76,182,53,49,135,126,117,23,4,0,51,62,11,237,65,252,21,246,193,84,14,85,217,111,240,108,226,134,59,194,210,198,214,9,245,99,101,81,3,89,134,225,173,80,61,204,115,250,25,191,22,137,42,177,155,159,237,248,200,39,189,1,66,189,88,8,198,57,47,194,59,150,74,50,244,192,145,124,139,137,9,88,183,226,179,162,219,55,201,222,186,109,36,242,146,104,134,170,9,120,67,123,240,251,118,184,113,206,203,242,204,29,95,103,160,139,24,229,246,174,44,232,1,92,51,119,121,192,74,200,193,169,150,115,168,56,37,31,105,175,166,10,183,252,135,115,233,34,0,229,124,183,246,177,143,42,237,125,2,142,154,240,49,228,213,15,77,123,202,79,84,0,147,189,200,161,106,243,41,87,86,158,216,240,246,100,112,9,91,213,220,206,108,190,57,220,218,99,189,47,194,120,28,127,254,169,178,91,243,109,75,134,210,210,244,242,159,54,217,20,133,68,233,153,234,101,91,233,30,96,171,224,92,91,176,236,182,188,20,131,21,122,84,104,171,14,236,252,249,75,212,235,191,95,11,62,141,94,241,165,26,219,173,197,153,214,168,223,240,94,213,113,148,95,22,212,203,134,117,232,60,147,51,11,201,54,4,81,122,170,58,150,209,147,128,196,78,68,78,148,160,114,198,127,162,120,180,68,133,22,76,101,119,11,93,246,9,232,183,127,140,173,92,221,236,51,178,45,217,246,70,118,91,129,102,24,199,252,7,6,116,81,43,240,49,115,77,164,134,23,10,184,92,26,223,238,174,254,108,5,221,29,205,3,38,30,51,143,196,202,21,102,228,51,105,45,191,54,175,140,175,135,132,56,183,9,116,20,68,132,18,220,233,176,239,82,87,160,87,75,33,255,121,193,156,78,230,23,79,64,52,198,99,148,130,106,107,8,203,26,34,248,194,178,123,242,238,250,69,219,168,219,185,118,64,221,220,7,62,58,172,34,161,85,252,155,52,152,60,87,103,183,167,226,234,225,170,247,90,38,143,81,89,210,156,20,60,194,148,113,179,171,5,77,184,78,26,208,131,200,86,18,46,116,74,134,61,119,29,194,3,117,40,80,168,90,103,191,42,184,95,218,91,28,155,54,146,65,95,188,105,77,14,205,75,249,117,46,221,98,224,169,93,190,83,43,182,146,208,7,135,154,99,250,12,2,189,246,105,220,172,175,69,1,167,218,186,57,136,247,112,149,221,32,11,202,229,160,52,60,200,208,193,198,75,246,250,53,55,150,176,139,93,85,222,206,205,111,9,73,162,186,211,69,140,188,136,164,203,223,18,225,119,181,234,138,60,23,112,75,105,15,203,7,125,177,246,31,45,74,151,48,22,139,175,136,183,250,161,111,94,119,158,113,175,140,79,29,122,65,55,233,80,125,200,31,209,18,35,82,3,116,190,125,208,46,253,125,100,73,160,238,5,244,38,184,200,7,167,119,122,165,28,250,26,52,110,188,151,63,208,63,248,94,165,164,111,163,146,32,37,5,60,85,192,27,61,24,60,161,222,0,4,254,155,189,84,196,0,157,35,12,162,103,138,192,135,38,45,40,41,69,63,30,177,222,41,253,200,54,63,230,237,20,103,172,23,99,192,215,2,181,198,52,12,1,157,162,169,147,206,27,237,188,158,40,214,164,233,240,100,201,245,24,178,38,205,66,140,166,43,132,117,143,233,22,167,190,202,18,188,127,240,184,49,182,87,84,214,121,140,169,20,29,122,133,69,18,168,61,132,146,108,35,131,109,86,101,183,150,34,77,90,194,24,46,232,28,48,183,206,47,100,61,163,165,74,17,92,27,210,106,16,222,186,117,41,103,197,144,3,27,9,248,132,189,88,83,122,219,49,116,2,50,30,40,205,76,130,35,126,83,228,228,138,171,171,135,39,196,227,87,106,235,241,239,86,179,253,11,23,99,7,66,41,158,178,157,76,234,6,5,214,254,184,155,181,84,197,165,122,251,119,249,236,166,219,144,14,253,20,200,71,185,128,249,58,15,196,101,206,51,124,190,50,159,255,10,172,123,168,253,230,89,10,236,71,194,62,129,71,92,165,85,0,198,135,157,141,191,50,13,140,37,124,110,249,46,46,25,251,68,145,8,18,120,51,137,142,119,244,148,246,141,26,132,163,135,241,35,159,49,77,209,163,230,111,6,242,146,195,49,170,2,124,194,17,165,42,155,254,34,50,37,48,67,234,117,90,102,69,129,61,195,172,78,87,34,46,79,146,168,210,166,122,231,226,222,204,251,20,75,223,196,242,130,34,225,110,75,207,175,78,24,239,45,171,104,198,59,0,19,49,11,243,112,43,250,158,62,80,155,237,46,52,188,185,245,171,68,197,202,251,110,93,211,94,67,191,87,157,87,233,13,61,47,52,206,80,194,167,66,67,198,170,244,247,174,171,50,79,255,184,161,14,254,202,162,162,254,221,148,221,251,90,102,154,71,98,61,150,1,32,250,227,57,240,168,21,174,152,107,235,75,2,198,35,117,161,148,210,231,214,184,87,241,102,16,184,144,221,165,158,108,17,177,46,228,156,159,149,123,171,239,250,40,10,62,189,159,144,124,7,64,76,122,161,214,158,46,206,191,99,142,189,68,40,168,172,65,88,130,102,169,121,107,188,201,117,35,139,212,14,176,77,110,172,197,14,238,254,189,108,234,224,228,68,226,121,230,183,185,224,25,14,142,86,3,2,21,133,116,109,24,125,214,126,192,236,107,42,30,208,247,43,102,62,205,11,213,177,80,163,92,245,82,101,244,192,151,191,169,102,204,190,167,232,66,226,12,115,238,131,188,181,235,30,55,68,17,186,125,64,121,44,39,147,240,53,20,40,101,224,109,239,226,32,115,253,200,113,202,118,207,81,168,138,146,224,129,38,168,181,120,87,225,170,24,6,223,254,59,48,103,66,191,112,18,100,232,149,121,191,132,39,231,12,223,111,202,150,238,150,76,143,41,37,183,222,8,16,24,33,99,101,144,218,10,68,70,133,97,95,109,42,67,13,102,0,93,189,206,41,149,160,206,101,195,209,76,22,231,109,76,142,113,78,222,63,202,227,65,140,154,29,47,96,41,58,77,137,107,249,152,7,126,53,105,31,221,134,107,150,14,18,108,110,152,91,57,88,146,199,220,12,79,116,220,134,180,176,224,71,97,52,154,76,94,230,58,14,196,154,89,27,162,219,96,227,91,143,175,92,36,179,222,30,59,163,32,250,146,96,163,83,134,33,18,27,99,127,113,171,35,52,143,96,219,71,71,254,216,30,244,75,88,241,242,50,213,1,83,56,154,152,153,219,130,166,175,82,10,125,111,96,137,38,46,205,11,85,195,29,184,117,250,218,58,49,10,40,30,139,211,81,157,249,51,33,100,201,34,96,197,189,206,48,180,50,2,111,154,109,10,90,116,189,224,85,45,153,10,96,210,142,179,131,174,213,131,9,90,194,235,113,201,152,223,253,134,198,136,215,196,121,114,145,127,197,63,226,22,10,124,149,177,37,12,217,218,113,9,235,142,49,103,237,98,82,140,8,127,97,56,61,78,76,142,106,216,56,78,153,139,60,223,243,28,34,38,199,137,132,50,118,151,58,141,192,20,249,138,53,114,177,45,146,78,147,234,123,244,61,157,119,7,88,41,82,17,102,213,59,93,79,45,40,157,139,219,81,12,134,18,77,1,101,45,228,155,66,227,243,242,202,71,136,205,94,102,239,237,253,62,207,30,222,178,58,135,219,74,150,232,27,209,251,37,198,33,83,209,39,249,183,21,38,213,39,143,198,149,91,161,250,193,43,45,233,70,234,118,173,231,180,151,157,138,7,167,198,81,194,51,164,200,83,56,176,121,167,225,108,50,245,125,137,148,215,111,59,19,64,109,5,114,176,218,137,186,235,94,254,156,96,194,168,34,159,84,171,68,70,215,155,148,244,240,11,54,128,75,56,161,201,231,65,137,194,113,32,89,201,13,141,169,131,94,198,168,132,135,101,50,165,181,8,159,184,15,19,74,16,105,43,25,168,214,106,76,164,64,91,12,74,22,16,124,27,121,145,188,125,255,96,131,33,245,145,180,29,62,194,137,30,62,243,129,77,13,158,163,117,162,206,61,236,135,244,220,166,174,217,73,139,0,254,201,26,125,241,33,68,187,155,235,119,25,72,196,151,8,255,8,84,250,43,102,204,134,121,186,123,144,48,2,235,7,229,41,190,150,181,169,203,226,194,118,180,182,162,220,222,14,52,114,197,229,86,207,201,148,241,246,69,68,231,8,57,6,21,171,44,83,134,151,83,25,48,142,91,248,21,21,213,9,104,208,21,12,133,100,100,144,124,237,193,56,180,34,39,246,232,53,212,121,61,127,221,103,74,114,150,223,11,229,210,6,76,40,95,192,199,167,100,100,64,117,44,73,13,187,42,241,47,212,35,164,55,64,85,88,41,102,68,165,110,72,100,66,38,33,14,166,233,157,80,35,137,1,69,63,111,169,42,19,65,190,106,104,216,90,154,147,190,183,207,177,145,142,190,213,148,10,228,251,99,58,72,148,192,227,20,1,79,110,181,47,89,218,133,7,75,111,229,49,60,97,179,158,28,51,110,139,80,56,147,33,182,227,153,92,32,1,241,44,181,143,24,16,252,26,129,134,63,65,186,1,160,90,254,21,88,43,220,101,222,156,214,211,98,172,42,254,193,103,147,61,229,181,85,228,223,127,163,201,157,106,97,82,251,201,89,32,245,234,92,103,151,70,111,44,210,74,166,88,95,204,82,185,9,218,72,146,27,181,139,97,122,22,228,206,84,237,87,140,101,100,110,216,186,226,110,186,109,140,162,59,52,3,26,96,176,41,84,66,47,216,100,110,106,2,55,106,165,232,43,156,42,193,122,42,74,224,96,101,41,240,141,4,88,29,113,31,121,80,196,152,15,234,154,70,129,228,97,137,99,89,108,64,143,32,111,199,220,209,192,20,24,80,192,202,191,169,156,133,210,36,179,17,149,67,213,52,180,176,134,253,181,179,174,87,217,236,254,162,137,201,192,88,23,89,195,231,73,182,226,224,149,99,172,221,135,5,241,132,86,236,118,69,50,108,27,103,65,17,127,75,11,160,71,85,227,148,153,62,103,83,250,192,254,215,123,252,157,8,112,132,210,193,21,244,168,131,44,69,226,190,243,10,225,163,84,190,118,32,19,193,234,220,32,188,74,90,197,143,70,191,99,113,186,143,49,131,109,253,62,234,221,183,103,238,89,65,67,11,230,9,222,24,95,129,14,228,125,126,166,49,29,239,36,39,124,130,203,200,105,29,231,182,43,1,179,193,103,230,251,205,22,182,65,191,137,110,165,113,180,60,209,87,212,7,69,241,130,157,125,59,225,89,244,120,134,142,170,92,19,65,251,87,163,83,32,185,163,202,187,191,34,192,183,186,236,30,222,225,180,237,142,162,77,93,190,100,248,70,134,164,253,105,255,142,189,83,50,161,225,223,241,240,252,170,90,122,221,22,108,187,81,31,252,76,218,238,217,175,90,110,37,190,8,65,147,181,160,202,39,24,230,218,92,233,102,123,98,72,215,163,152,111,198,25,215,60,213,1,254,4,168,45,13,40,238,142,158,60,70,241,144,183,215,236,146,149,13,234,215,133,3,112,135,7,8,40,195,214,105,244,172,246,200,198,238,153,112,100,59,137,18,122,9,204,17,41,181,111,41,61,21,160,16,170,194,218,178,62,88,92,199,233,200,24,70,246,142,224,164,200,210,237,216,75,100,45,115,160,117,92,38,226,170,215,156,203,215,210,248,231,199,216,248,161,125,167,132,103,180,186,9,249,4,154,16,237,107,80,28,27,235,150,39,210,201,153,66,17,97,165,29,15,167,130,23,77,17,106,160,90,248,47,219,164,20,127,81,248,1,36,254,22,50,208,65,145,45,220,160,93,16,45,62,229,177,187,144,167,142,26,248,232,6,191,77,59,136,49,2,33,116,66,65,146,218,44,111,73,2,222,99,111,24,180,41,67,103,39,216,168,240,207,142,34,241,86,17,173,37,58,64,186,213,98,181,151,159,141,26,22,31,45,92,64,9,10,26,76,181,236,145,18,8,30,219,158,183,71,138,134,56,65,70,34,140,141,13,54,245,29,155,227,200,183,113,40,113,203,86,214,2,162,90,237,5,247,2,186,149,205,73,75,106,255,178,8,39,126,21,96,43,117,216,10,81,98,244,208,25,252,177,189,21,50,204,13,115,42,29,115,2,10,234,207,168,29,131,228,241,82,183,158,85,177,161,142,249,81,208,74,7,73,61,160,142,153,121,63,78,230,152,77,38,100,58,119,15,102,23,145,201,189,165,77,147,230,208,2,84,68,22,86,13,32,68,58,88,73,8,48,139,117,27,222,40,32,182,33,168,89,188,113,162,162,146,225,102,118,158,53,22,82,149,184,240,92,212,243,40,50,170,149,147,223,104,185,45,162,20,59,162,173,157,5,224,233,8,159,219,28,215,102,178,59,121,254,199,162,199,99,2,69,53,6,16,218,9,6,241,44,220,188,45,208,250,244,235,250,209,70,110,222,198,183,219,47,135,143,170,11,226,178,201,194,8,0,115,63,105,158,9,227,172,16,176,218,211,18,70,236,5,109,35,119,143,218,145,213,190,153,247,240,232,191,61,9,58,130,175,235,45,122,195,207,43,194,102,133,91,46,230,18,78,212,122,114,168,4,94,120,96,72,18,12,142,191,141,105,202,78,241,114,85,34,238,84,11,10,254,50,188,122,76,216,117,121,110,3,95,91,62,253,60,174,139,195,120,183,220,61,229,75,22,220,190,134,216,68,90,111,184,152,40,130,43,39,76,144,94,215,83,252,62,127,27,6,175,158,50,87,41,85,95,32,24,14,193,22,92,54,156,254,77,61,50,7,243,25,48,156,89,56,17,33,107,135,110,160,52,80,216,55,217,98,40,102,1,34,70,233,200,205,172,234,156,17,180,123,113,143,67,81,224,51,149,12,213,251,3,2,63,30,249,181,254,120,160,155,133,96,137,181,35,5,182,121,214,39,128,129,237,203,19,137,24,93,101,255,228,209,34,58,241,253,187,131,60,8,241,178,36,11,26,109,21,150,214,31,242,19,60,118,147,158,111,23,164,168,73,67,92,231,211,6,86,222,242,248,107,142,231,119,143,1,168,27,187,91,70,38,230,162,216,232,152,83,71,41,183,182,189,94,221,128,7,217,182,42,49,232,20,23,3,87,95,213,181,137,117,14,161,52,243,122,183,193,90,134,182,58,222,179,72,150,241,129,197,216,227,156,20,75,90,202,71,128,15,137,242,183,117,188,168,252,39,243,76,167,222,12,190,250,197,206,164,145,191,47,206,24,20,40,253,36,4,220,72,143,199,19,105,30,48,219,215,196,37,15,182,38,220,134,239,35,187,29,230,68,215,139,220,215,90,25,184,246,196,149,239,249,142,248,63,141,205,161,28,87,142,170,237,214,67,142,251,97,163,163,242,208,139,28,201,5,249,160,111,232,64,231,207,201,197,196,206,92,127,71,17,57,48,200,25,226,176,113,210,162,108,233,45,224,15,40,196,161,187,228,55,88,74,235,30,68,12,209,70,87,243,159,85,208,70,192,75,111,14,15,239,6,234,134,248,30,113,51,255,128,43,104,82,6,158,241,74,19,174,199,229,132,238,6,70,145,96,242,208,185,17,12,251,210,13,113,233,186,188,29,9,195,244,71,62,26,195,82,44,209,10,230,93,188,92,234,241,145,115,67,77,67,44,210,249,228,5,84,43,160,77,103,214,59,87,195,200,20,129,254,173,229,229,37,115,254,49,72,119,145,188,255,12,95,191,110,239,124,12,213,234,217,4,211,133,39,184,242,103,223,13,5,50,56,74,214,135,66,130,62,223,167,91,175,30,40,134,82,42,167,175,169,33,40,205,88,123,104,96,189,142,226,130,73,0,60,121,128,225,203,146,1,170,4,93,235,72,243,97,77,129,92,246,173,53,161,138,204,83,70,234,80,223,20,176,62,149,150,127,141,182,196,163,80,117,13,31,248,64,166,35,112,96,44,221,70,128,124,229,74,60,65,83,15,20,135,165,184,82,153,163,153,145,137,168,21,68,140,120,76,239,1,57,32,133,38,158,157,114,92,79,139,129,100,233,109,73,206,6,164,101,18,250,41,214,14,185,87,241,153,142,116,3,55,77,138,149,123,112,38,59,191,132,156,136,205,108,175,236,117,66,107,36,241,192,147,149,227,116,253,26,209,34,134,94,214,68,212,25,142,117,207,151,32,13,101,187,154,38,54,165,162,58,254,142,54,86,89,13,232,46,36,31,67,169,250,183,168,205,55,163,165,77,37,211,28,12,51,80,99,47,117,190,69,215,83,246,24,48,152,252,50,167,183,242,94,21,63,211,171,23,199,4,160,172,57,57,92,128,50,52,174,87,77,255,17,221,149,165,195,162,43,38,226,27,221,101,124,188,82,226,222,49,132,246,31,27,81,255,205,69,176,163,195,253,83,47,80,99,157,132,223,160,92,39,120,73,149,51,171,255,67,218,107,160,220,58,236,28,119,180,1,82,24,146,160,44,200,70,141,109,254,12,126,229,95,99,96,3,216,221,136,205,113,142,122,186,243,183,255,22,253,97,176,39,222,179,209,180,233,133,72,37,54,158,28,65,95,13,1,59,153,193,87,230,128,104,160,201,205,2,196,6,125,232,155,188,65,83,240,126,145,178,63,143,0,240,193,78,184,2,226,82,240,49,22,50,167,206,196,168,121,68,212,156,249,154,95,24,93,83,113,168,33,14,246,208,135,139,78,122,101,123,8,177,97,182,122,128,106,140,8,192,100,143,88,196,50,29,207,215,143,65,120,133,133,118,94,128,12,106,130,195,165,203,112,192,173,166,222,59,23,34,6,82,131,16,84,214,205,87,208,140,201,182,166,221,131,122,181,85,150,65,139,133,103,23,179,159,231,7,175,204,95,130,131,126,45,155,135,76,69,145,54,197,251,173,9,206,46,189,122,101,178,24,17,52,231,121,151,60,255,66,47,5,0,134,235,185,232,129,137,35,158,3,110,230,211,73,61,209,224,71,153,55,248,61,100,233,170,140,66,27,177,253,40,208,209,143,4,27,108,105,166,136,60,8,218,119,168,182,107,8,119,5,118,31,219,43,94,70,182,91,68,254,135,245,212,250,26,105,156,109,180,133,177,249,140,89,130,79,55,31,123,18,154,42,191,139,9,240,237,151,107,173,188,134,243,132,118,79,249,197,52,29,174,60,127,48,203,213,101,118,178,117,92,200,49,217,119,172,213,150,231,103,134,168,200,159,174,105,85,8,72,53,243,196,179,102,171,173,207,190,134,186,250,180,231,155,193,203,81,248,175,8,196,145,73,186,178,63,177,60,238,12,42,169,79,173,245,76,171,131,19,102,237,156,201,116,42,209,167,158,198,227,114,197,227,182,212,229,151,110,140,149,239,82,124,137,145,167,26,54,159,102,237,132,139,121,181,115,78,145,179,231,40,243,114,107,190,126,230,152,86,21,43,130,126,87,172,107,120,215,174,119,95,238,138,107,162,109,30,0,156,48,191,59,137,171,39,151,249,219,16,202,29,186,7,225,198,202,213,119,26,30,46,66,61,154,127,212,160,121,30,139,137,77,16,197,1,225,23,181,190,52,124,88,224,250,45,111,131,115,99,26,188,227,244,207,13,101,230,130,96,187,90,109,141,203,246,150,213,238,2,180,162,199,113,129,255,97,7,65,101,37,145,166,70,193,39,68,86,45,6,162,80,189,182,147,237,204,108,173,114,12,139,6,79,110,178,50,39,17,113,41,178,217,61,88,132,240,93,181,152,170,7,71,170,146,115,177,209,87,215,16,157,38,76,45,46,220,16,103,58,125,32,153,241,187,154,232,13,56,84,165,56,94,8,6,118,36,14,96,65,93,68,50,208,97,85,185,103,1,161,83,67,194,38,128,76,181,204,102,151,40,72,219,119,58,243,206,0,99,50,157,241,110,31,75,39,89,181,28,80,34,47,54,40,145,0,60,100,212,148,16,35,19,189,130,103,237,1,19,109,241,72,134,148,103,72,23,209,106,186,211,41,196,18,76,23,75,122,68,251,50,11,252,232,52,72,57,5,52,226,217,252,184,71,71,112,106,214,93,60,250,235,235,115,148,64,183,222,82,158,135,135,145,153,54,138,126,116,216,66,235,51,100,7,1,111,11,231,57,153,174,195,76,173,195,2,137,227,217,61,109,233,31,68,5,179,235,72,80,16,191,118,37,76,119,131,246,39,251,58,127,172,229,32,135,167,216,216,39,54,7,180,45,236,44,47,186,218,5,45,145,201,222,24,126,214,198,237,218,245,74,159,119,201,233,27,224,213,175,46,43,252,104,209,254,53,126,25,166,190,157,66,64,23,226,4,74,69,28,42,238,195,233,33,1,64,116,16,110,32,81,97,57,242,250,108,13,200,31,184,115,30,190,65,111,225,197,90,215,174,221,193,216,165,11,16,3,153,141,181,161,223,213,141,64,243,41,33,65,208,245,48,203,171,242,234,120,183,57,60,85,83,188,148,249,94,62,178,164,119,223,137,180,49,184,166,120,134,127,76,230,216,208,161,5,42,237,196,235,114,222,23,134,110,242,244,163,1,42,228,3,251,93,156,48,46,154,200,19,163,205,213,250,142,212,14,156,210,48,20,148,235,204,232,128,21,3,100,38,184,230,249,138,117,207,253,60,79,102,174,115,184,21,102,194,116,47,69,98,110,200,73,248,186,30,220,75,239,155,228,138,141,255,84,179,127,17,124,167,107,102,248,93,59,11,170,167,110,129,228,140,41,111,215,131,169,31,210,192,131,220,50,29,241,34,235,141,60,96,178,83,126,109,14,186,209,248,63,130,108,186,180,105,95,192,234,29,87,8,197,153,103,55,13,10,116,247,40,153,54,84,199,120,69,98,185,228,4,234,107,80,168,240,218,9,114,58,196,150,245,120,244,210,164,160,201,55,20,40,135,138,179,149,228,199,157,192,174,190,79,35,154,208,104,215,44,229,241,125,186,156,42,60,224,60,98,79,40,64,126,207,165,212,10,115,54,25,33,126,58,236,50,194,209,149,85,111,178,89,79,15,60,227,54,174,229,243,135,42,102,50,171,254,95,21,247,31,125,0,215,95,9,254,115,158,204,23,106,103,28,139,202,110,125,119,242,110,213,56,152,116,42,49,235,231,28,252,0,141,119,191,200,51,122,183,74,56,200,99,174,153,239,174,227,16,247,241,53,17,43,147,201,28,236,24,172,158,183,250,239,232,109,178,138,191,154,85,92,101,93,173,175,120,149,115,204,109,250,109,193,172,203,85,254,72,122,109,173,97,223,35,161,59,23,39,177,164,124,186,70,76,36,143,143,79,179,160,167,125,30,112,233,209,141,126,247,37,119,77,159,6,86,22,186,250,64,148,109,116,69,157,161,219,213,126,74,234,55,4,74,150,191,164,59,229,208,73,147,153,74,155,93,93,177,111,177,180,36,107,46,26,222,118,125,41,31,110,95,84,199,96,81,223,99,229,230,111,208,187,44,207,189,197,162,155,118,66,246,102,5,157,180,61,121,27,171,235,38,194,219,47,109,32,238,247,114,130,158,184,151,243,155,87,210,50,16,172,39,124,229,145,237,44,49,206,229,30,118,171,255,129,65,10,175,28,62,65,30,217,20,113,253,179,149,240,28,118,112,140,20,237,39,7,159,242,230,64,144,209,53,33,213,116,176,141,135,111,225,244,248,107,202,235,131,88,130,60,113,17,151,144,193,21,155,78,5,33,221,177,64,101,141,166,1,217,83,16,24,8,33,203,8,73,180,252,201,36,37,193,112,158,81,36,62,12,87,125,150,121,19,39,92,191,173,210,244,36,77,195,88,140,26,156,4,231,27,111,89,251,35,188,185,246,75,176,127,162,75,144,137,255,124,36,161,108,144,154,177,88,19,197,21,51,61,242,175,177,115,118,58,158,40,174,196,158,97,198,184,209,36,126,232,71,189,204,186,7,102,36,124,234,204,89,172,220,192,86,101,51,175,40,9,191,17,115,155,117,200,237,22,138,77,48,250,240,160,224,117,133,170,182,144,213,211,213,2,243,145,65,254,0,2,248,48,33,249,80,119,29,108,76,228,213,3,143,250,23,23,131,183,155,60,55,214,27,114,225,198,150,10,35,148,123,109,118,26,2,65,205,51,165,231,113,146,183,118,99,110,128,192,107,84,128,130,68,16,88,195,165,35,170,219,153,195,92,132,226,34,20,77,81,240,139,150,107,214,77,155,204,106,79,19,168,44,71,198,240,87,142,60,44,60,246,5,116,90,243,72,82,123,206,123,164,157,159,113,100,46,227,97,151,247,172,49,26,253,214,112,110,75,191,20,199,178,121,153,73,146,167,80,165,179,249,104,118,42,76,8,126,200,69,25,1,35,35,219,85,218,235,253,164,63,211,195,178,60,208,120,222,151,167,79,238,35,131,109,53,18,149,50,40,14,206,218,230,111,82,234,124,19,223,6,18,94,196,199,189,219,79,203,3,86,63,184,11,70,220,145,70,39,204,13,70,25,105,99,18,2,0,24,161,197,244,35,162,11,157,34,54,196,92,138,255,30,83,77,170,69,196,207,11,28,60,155,7,88,6,248,72,159,21,242,123,4,244,230,249,74,32,130,186,174,143,2,140,24,130,73,170,186,195,129,0,221,95,213,21,27,147,128,194,103,91,111,210,249,82,200,180,140,107,187,79,132,95,135,105,220,39,219,47,101,130,232,19,153,84,96,21,214,227,184,212,26,88,77,22,173,250,215,51,120,214,55,206,86,220,178,39,170,15,114,12,97,98,239,4,124,47,250,230,133,149,196,82,209,165,151,0,207,30,106,133,62,251,241,196,196,47,179,145,179,2,155,15,5,165,22,67,52,207,39,246,123,134,219,252,174,231,168,82,8,7,192,229,168,45,215,86,100,235,111,169,107,12,249,89,109,86,160,142,181,238,237,223,92,168,130,150,236,224,116,222,45,18,13,13,164,73,38,27,208,24,138,45,80,4,148,58,149,54,128,230,244,22,230,218,179,87,51,104,223,178,9,209,228,14,206,192,249,41,82,34,115,235,125,150,192,196,1,165,252,62,83,243,157,37,218,134,192,149,232,139,145,253,205,51,17,97,192,121,157,60,181,170,126,156,5,44,196,235,223,123,170,2,118,228,255,243,8,132,196,221,30,242,92,159,112,180,131,51,25,126,253,184,7,4,110,34,217,37,185,91,186,44,77,80,104,181,58,171,9,210,180,17,119,8,141,229,247,64,62,232,121,118,112,133,52,173,5,202,94,170,37,212,28,222,193,97,51,164,107,197,181,220,102,52,58,47,147,194,179,174,14,89,19,221,145,39,174,86,249,64,89,192,101,143,207,156,186,210,1,137,143,225,13,38,98,59,92,137,53,31,64,212,100,157,144,100,131,3,65,115,94,185,87,13,25,176,45,184,207,19,250,197,231,86,217,51,191,125,60,11,95,125,105,236,148,166,54,6,42,0,150,180,138,38,30,235,72,106,14,217,69,184,242,46,197,173,38,89,234,41,197,213,165,79,86,118,231,142,207,69,207,108,20,53,179,160,231,84,99,156,253,80,13,15,65,18,73,160,149,31,76,124,141,4,48,207,86,81,87,66,32,121,213,115,116,230,240,201,247,195,159,66,154,244,180,174,14,101,84,3,66,175,40,177,65,194,101,162,234,26,55,222,21,72,164,219,243,129,30,172,104,212,50,6,152,90,233,235,35,221,207,165,225,44,109,74,127,123,173,56,87,209,84,211,48,214,123,5,105,101,78,188,169,175,36,172,214,19,232,125,217,130,252,99,237,244,61,173,193,82,209,216,57,13,12,202,82,193,78,70,69,206,74,240,191,91,25,179,254,242,177,68,23,139,165,101,32,52,246,25,212,240,38,237,147,60,156,190,36,3,56,163,125,228,107,228,6,235,44,250,90,92,77,158,36,217,168,161,77,26,49,125,99,103,191,115,41,120,16,231,243,69,108,169,115,81,127,195,48,164,132,75,173,147,62,148,220,3,189,186,165,200,86,60,18,172,193,207,129,196,167,69,181,134,232,130,109,48,76,133,202,38,184,207,153,39,149,26,4,242,77,59,193,254,102,222,99,68,91,147,245,252,14,111,57,224,121,244,233,148,97,66,37,162,181,44,60,144,184,181,187,204,143,33,120,225,243,226,97,190,168,25,134,240,146,145,251,166,104,183,243,126,93,104,93,84,55,148,49,84,30,71,204,203,236,226,179,113,247,64,213,92,207,126,35,130,231,86,232,149,34,79,127,8,155,120,228,29,247,142,10,151,52,57,180,40,56,93,99,171,253,160,143,201,101,183,204,59,240,23,208,83,198,151,231,231,147,28,110,4,156,102,57,157,18,249,18,50,20,130,56,53,156,41,45,170,41,117,136,179,222,121,239,18,168,166,237,2,237,98,107,148,236,81,60,2,33,181,218,46,71,254,197,234,84,204,80,27,160,118,123,153,37,55,238,240,199,98,227,116,197,126,232,21,255,98,226,206,152,34,211,121,85,69,183,195,225,202,232,188,79,208,206,156,187,96,21,189,252,76,203,227,241,70,211,61,52,217,12,33,243,41,50,152,77,47,82,19,140,197,235,100,59,65,70,115,52,246,95,80,145,224,57,224,221,213,78,145,49,47,117,102,248,205,92,84,18,215,150,191,135,145,62,36,193,200,52,133,187,34,96,149,139,1,97,248,25,51,64,247,58,93,111,15,225,212,223,114,61,92,11,95,154,153,245,208,78,148,39,150,34,40,110,50,154,11,54,4,145,21,134,166,233,0,193,39,105,2,102,29,28,168,238,231,117,248,142,40,50,56,142,240,142,165,151,16,85,30,155,98,225,239,177,187,143,215,228,29,118,98,85,69,167,21,45,116,143,40,42,152,1,87,158,139,169,81,137,18,54,65,178,145,44,82,225,241,84,208,111,202,139,17,95,107,130,255,148,105,65,106,172,230,171,55,197,239,133,168,4,152,247,235,19,138,175,168,216,216,171,23,160,83,71,40,126,234,228,1,76,145,9,132,135,166,202,190,232,233,218,105,184,138,161,252,19,33,132,61,159,183,129,62,37,37,194,79,104,59,218,204,215,82,166,4,190,36,224,43,97,59,71,51,188,214,175,54,18,10,15,153,110,203,218,59,225,113,185,123,75,111,206,104,24,163,254,170,85,40,105,9,229,41,218,37,240,211,103,89,253,97,34,77,188,114,220,132,215,129,26,109,149,186,128,119,108,19,20,122,172,175,10,20,169,9,104,195,150,51,8,159,140,86,232,226,177,7,196,200,167,207,106,126,27,140,222,219,198,149,46,0,13,93,255,121,205,23,206,245,185,247,15,231,173,156,59,156,16,48,118,254,93,148,203,237,189,158,180,101,52,62,155,57,8,175,171,215,67,69,104,60,72,232,226,185,20,206,65,59,42,125,90,124,100,202,134,141,239,191,110,203,164,223,50,232,219,4,222,205,22,70,62,180,75,143,174,228,44,62,245,202,39,117,215,33,145,80,106,131,177,244,66,46,89,167,198,251,80,38,72,190,90,118,85,34,158,83,17,61,132,124,53,24,63,24,90,249,68,131,245,198,183,117,13,157,137,70,189,73,23,75,77,13,25,88,126,217,87,108,92,8,133,154,15,158,112,113,94,186,162,177,9,232,181,162,55,24,38,161,79,176,4,233,11,158,170,242,240,168,77,25,3,223,158,186,182,26,129,84,106,135,108,205,79,254,175,227,1,238,248,79,5,72,169,217,128,158,1,139,110,157,12,39,55,95,3,2,113,179,81,229,38,144,253,35,77,155,97,157,9,47,133,35,238,97,246,176,156,164,3,236,181,42,140,173,1,46,164,218,168,228,127,219,160,224,59,249,247,7,155,98,77,199,215,146,55,151,221,185,163,241,26,122,137,164,190,205,207,4,237,134,165,74,238,223,226,15,248,242,139,107,210,187,234,4,145,23,231,180,229,53,254,166,201,220,10,14,58,33,230,72,92,230,207,170,109,188,229,137,28,147,22,41,192,213,40,215,216,127,14,228,9,13,85,247,106,247,1,155,206,136,4,23,190,148,170,106,194,155,170,96,227,85,168,247,195,20,113,172,17,34,38,123,79,167,110,206,207,53,66,173,162,178,166,84,120,160,160,218,186,227,34,87,100,212,219,28,84,255,59,138,26,28,227,102,205,94,75,152,55,216,163,46,225,96,152,57,32,57,159,27,251,178,201,231,5,139,31,163,136,69,71,125,19,213,46,252,84,88,215,163,249,153,181,25,227,174,4,105,93,98,251,60,164,4,222,26,165,85,83,87,45,206,132,134,6,108,89,96,76,139,144,143,144,116,59,72,48,184,248,230,195,135,167,29,166,42,207,49,87,221,159,42,168,96,157,181,125,152,96,130,72,48,100,105,145,96,98,200,116,7,131,166,69,99,117,55,141,40,125,106,249,33,118,191,121,159,138,79,27,90,132,13,52,0,61,44,246,212,77,127,107,26,124,234,104,26,14,238,68,79,124,247,99,81,60,135,27,62,83,231,104,214,53,69,104,188,95,120,30,105,222,150,218,223,80,221,209,86,113,125,226,123,36,1,136,94,206,253,124,34,218,2,77,208,172,39,238,148,151,111,237,3,135,99,41,22,142,129,39,56,105,255,31,62,12,171,5,206,94,114,13,174,185,89,199,225,131,239,187,92,132,102,86,138,156,36,55,112,65,191,209,70,60,75,110,59,216,180,148,36,118,238,139,97,222,17,236,209,68,163,76,177,206,58,196,113,2,166,47,131,113,199,180,134,23,174,24,119,20,124,144,29,221,9,90,224,188,131,232,13,244,94,200,129,51,27,11,124,24,154,5,91,171,150,238,212,117,175,71,155,110,168,3,236,162,196,193,74,101,6,238,157,132,151,181,88,122,26,84,194,170,253,198,124,142,133,185,66,4,105,5,152,87,209,178,134,243,242,197,214,209,103,53,218,128,193,9,83,231,55,111,29,235,133,45,107,115,71,203,15,1,69,200,105,216,1,163,183,18,222,54,6,56,48,104,228,237,119,166,90,242,184,97,160,218,194,255,151,131,120,180,104,202,167,157,179,147,77,161,34,65,201,171,236,177,175,0,92,134,255,40,217,133,61,187,44,165,109,184,127,37,189,61,62,60,232,182,210,78,123,118,207,185,156,158,77,117,67,26,37,222,174,87,192,241,152,180,170,218,35,86,86,91,87,98,97,192,129,140,194,233,36,79,152,203,136,73,223,63,26,117,190,88,188,60,42,9,45,54,223,198,207,196,237,26,244,60,233,67,132,223,113,147,253,16,126,10,119,41,159,99,237,109,167,23,248,146,7,166,214,75,0,234,202,90,254,26,71,82,240,116,216,96,236,109,46,104,255,134,115,253,155,36,36,129,188,183,140,151,14,153,244,139,244,252,214,160,8,249,226,35,58,185,116,255,126,128,120,235,190,225,169,185,175,255,64,176,56,247,249,7,18,39,92,249,142,98,47,116,247,126,6,66,208,245,253,217,123,160,123,49,99,18,90,47,9,80,207,212,123,18,61,155,193,44,242,205,146,4,96,210,222,194,220,47,172,241,165,29,155,45,163,105,121,174,115,233,211,216,182,136,24,90,234,77,214,70,94,160,35,59,16,39,71,24,186,43,251,99,53,11,47,60,159,24,144,250,41,114,90,26,97,209,154,96,63,178,67,28,211,107,179,90,253,127,165,163,26,175,163,165,60,47,25,151,210,245,25,91,122,31,176,184,179,128,161,75,71,166,119,40,19,58,101,115,237,145,211,239,250,235,224,4,46,64,94,118,213,191,21,42,27,169,75,217,193,182,121,215,57,216,234,245,160,135,78,21,125,113,51,250,39,177,32,227,61,57,182,118,16,212,181,130,153,240,62,148,127,188,127,160,37,3,231,33,68,181,179,95,116,179,14,247,145,214,104,222,71,140,17,161,171,218,105,81,195,25,20,202,235,110,70,90,42,47,194,109,74,85,60,77,65,92,205,106,16,171,147,0,227,16,251,48,224,101,8,46,29,94,50,36,213,78,254,13,7,254,227,219,219,18,45,213,145,136,25,210,42,32,47,62,61,139,31,140,17,210,249,37,178,80,160,59,139,26,250,178,179,208,129,81,82,239,54,209,224,20,156,174,251,26,130,136,28,68,243,28,42,28,17,51,90,6,39,125,11,249,223,165,193,243,148,129,17,210,146,186,89,202,253,59,205,5,52,237,17,181,104,92,54,142,214,177,178,59,214,195,73,72,186,175,17,1,0,220,146,69,144,120,89,133,146,152,239,230,141,237,0,78,250,117,54,179,45,38,167,90,149,136,233,115,8,227,210,205,255,208,177,5,45,173,12,189,122,109,122,136,191,40,176,51,234,201,4,208,42,147,44,56,120,17,43,69,93,97,143,103,130,166,129,101,7,40,85,92,157,218,212,230,114,139,2,233,64,93,127,49,140,232,168,194,0,74,215,40,158,61,12,247,57,151,103,148,42,210,155,139,211,87,19,0,208,70,224,199,34,241,199,70,169,161,135,61,105,233,172,62,114,0,96,15,45,231,45,55,172,39,55,41,225,133,190,138,162,53,142,120,95,183,32,192,36,208,155,102,233,86,61,53,30,206,83,199,125,72,101,207,29,247,104,10,148,18,184,234,165,202,151,116,193,119,185,112,23,192,20,152,65,174,8,254,94,56,95,112,30,175,131,75,160,36,26,226,61,55,97,225,40,77,212,181,0,239,155,198,208,128,240,202,248,190,135,42,46,22,94,11,61,30,199,55,16,98,142,1,63,173,36,147,172,74,152,45,239,201,204,46,115,27,81,227,120,112,155,184,99,79,214,130,147,122,64,139,9,147,208,82,76,15,123,98,5,74,218,198,40,175,162,34,226,243,95,227,126,94,45,242,141,118,9,49,66,13,62,135,201,56,200,96,255,212,204,11,3,243,18,242,108,74,227,62,173,115,180,224,226,248,249,141,136,245,6,158,110,65,8,248,189,225,236,226,84,45,8,72,133,12,176,12,140,172,135,245,88,80,88,0,185,175,79,207,75,134,219,100,194,29,255,125,135,114,8,126,63,172,235,145,65,229,120,37,197,36,66,254,60,122,61,197,192,6,79,197,152,198,219,179,231,14,155,211,69,154,175,209,49,59,91,6,25,138,1,144,199,28,148,67,149,19,37,147,101,173,173,206,196,37,179,47,184,185,251,43,182,74,221,246,66,82,220,131,113,87,197,241,66,226,95,156,93,186,196,250,229,244,248,189,22,207,27,43,104,3,210,183,207,145,95,190,74,251,145,107,71,36,138,225,83,79,207,145,78,210,137,175,90,23,239,94,181,98,41,136,109,211,114,150,87,255,49,149,169,69,132,65,211,140,205,214,29,22,127,210,12,110,19,72,139,152,200,229,246,220,110,222,227,189,5,36,90,254,53,6,237,122,57,142,108,23,90,140,146,218,237,207,124,148,18,43,1,231,98,177,83,35,133,156,57,105,201,222,84,80,168,12,176,33,62,83,81,72,91,127,176,136,94,105,255,254,90,145,155,68,132,45,203,4,81,16,2,218,66,189,227,170,31,12,196,122,121,143,12,99,122,129,195,234,210,79,14,55,209,162,72,6,182,66,57,203,144,165,124,104,28,239,250,145,78,30,73,201,115,103,29,184,58,64,70,85,21,63,220,48,82,120,182,147,193,160,57,159,29,228,110,185,119,116,208,106,226,116,121,81,43,222,244,81,208,45,54,252,92,150,203,97,118,228,145,19,251,135,68,118,217,134,205,225,179,191,233,152,12,91,197,183,100,112,245,155,90,49,164,31,226,11,161,97,101,12,52,104,87,67,185,88,236,186,244,207,7,33,67,86,181,69,233,84,8,132,228,204,119,32,165,140,91,72,140,72,59,85,160,243,119,182,101,202,174,103,225,103,157,66,245,6,239,65,118,228,82,220,95,37,111,101,138,161,191,68,163,207,254,132,5,33,34,56,45,15,145,79,100,40,250,236,235,36,175,245,20,209,154,13,198,149,155,0,80,11,84,80,172,105,217,187,232,7,132,48,231,150,103,105,189,165,83,77,153,247,75,244,46,186,175,219,208,150,199,180,28,58,132,148,105,13,207,113,32,133,101,252,13,167,207,239,200,38,246,25,126,101,156,150,20,134,155,28,193,203,237,91,8,31,34,172,248,160,57,105,219,239,42,133,226,116,81,43,132,235,167,30,68,43,231,221,164,52,182,249,179,61,153,161,159,137,151,189,73,236,246,163,36,98,19,85,248,126,173,105,179,75,212,179,6,192,100,128,153,211,199,108,66,203,86,207,169,95,199,34,119,154,244,10,13,220,112,98,175,183,40,113,55,27,57,116,86,1,170,179,54,173,252,94,178,69,116,19,143,251,130,194,112,136,117,223,38,229,127,85,195,14,156,30,223,71,155,223,129,124,152,171,136,110,120,95,180,53,100,168,25,3,216,42,54,85,46,69,119,107,155,145,251,64,53,185,193,15,13,139,6,167,11,60,47,89,97,48,152,126,89,204,146,71,95,57,111,150,78,240,251,102,115,113,11,147,15,192,253,231,25,248,245,109,134,153,56,58,101,46,144,2,253,31,2,83,198,61,64,121,63,76,80,67,29,12,66,28,147,254,92,69,68,35,212,156,221,161,237,249,146,56,121,137,145,156,246,183,247,139,124,62,163,212,103,229,186,93,174,69,23,160,26,196,181,43,175,176,60,110,211,55,131,146,61,179,46,79,154,194,63,7,77,202,244,150,202,18,92,217,129,241,239,222,111,51,135,13,231,255,23,171,205,2,165,228,225,46,247,213,245,181,190,140,154,241,182,186,251,24,83,159,137,53,64,138,170,164,60,147,27,90,82,193,36,201,173,182,188,108,188,229,45,193,211,18,253,200,185,25,95,180,93,30,219,69,195,239,222,97,161,110,214,36,114,96,168,76,77,164,53,131,226,197,100,0,42,106,159,84,214,55,249,124,216,170,102,155,118,134,77,181,65,115,14,167,123,89,46,212,228,181,29,222,148,86,228,253,74,236,231,197,148,188,137,167,27,127,12,253,186,84,67,146,211,91,131,122,218,230,239,254,175,168,1,213,249,121,7,221,136,146,201,36,166,47,73,221,190,128,205,126,206,89,121,78,233,57,64,136,20,67,198,178,249,191,17,131,33,149,197,130,104,170,130,142,237,246,170,147,192,156,248,187,123,25,225,139,220,171,61,24,24,114,110,77,3,160,244,82,56,94,113,16,27,118,228,217,56,29,253,10,75,145,97,193,150,89,210,52,60,146,17,127,187,216,5,195,108,15,251,39,157,158,86,49,193,199,155,106,6,73,80,247,203,61,88,81,56,93,158,179,40,245,81,68,136,69,32,237,101,122,112,165,100,55,9,127,59,26,9,41,16,102,92,246,179,125,108,231,225,63,120,88,135,69,195,239,197,51,245,72,72,59,15,231,42,3,184,123,64,176,64,2,15,246,220,67,193,252,8,159,56,20,44,137,45,172,109,183,204,159,101,6,17,221,228,44,160,69,242,153,202,128,203,12,4,126,92,35,50,234,50,118,36,235,41,31,25,142,113,24,62,9,95,20,19,50,125,158,204,53,186,86,53,189,102,153,228,219,22,2,99,14,143,147,221,199,23,113,107,196,224,225,104,121,99,34,19,112,121,28,191,160,245,10,17,84,184,88,225,151,167,54,240,195,72,254,120,18,22,155,131,146,29,227,234,30,101,250,135,69,125,243,191,220,108,252,27,73,15,229,136,53,207,18,173,204,19,205,199,182,167,225,33,249,143,99,91,17,55,149,227,252,128,238,114,212,169,242,145,36,176,68,219,87,139,157,11,63,61,59,211,206,153,189,127,223,109,58,97,39,141,146,29,253,92,94,80,25,18,106,154,118,230,19,134,225,160,83,60,150,40,14,114,137,33,215,197,110,48,190,240,56,91,138,248,129,37,247,39,83,175,2,103,194,229,110,102,216,12,120,6,3,226,163,55,78,249,252,111,226,91,6,137,148,130,47,48,247,229,23,243,182,71,150,137,124,20,124,66,139,32,193,148,161,185,236,79,174,99,200,112,53,55,117,29,34,237,204,153,30,100,212,1,178,63,101,108,21,60,226,164,189,178,191,164,14,130,253,211,82,162,209,199,23,248,243,208,248,249,158,141,215,199,86,0,246,74,146,131,115,160,41,65,31,203,224,248,194,77,33,67,47,171,200,140,46,76,21,188,172,177,183,243,246,224,185,32,56,122,180,233,201,25,233,15,85,45,133,25,16,136,35,136,145,142,15,86,80,133,48,119,224,178,65,40,193,213,90,108,89,160,56,151,217,217,57,103,175,63,242,81,89,154,80,29,72,39,62,162,124,64,207,184,236,170,24,70,121,44,61,235,14,3,108,68,201,57,178,69,188,58,91,211,235,251,154,69,34,123,86,213,66,253,253,216,176,67,99,197,91,185,250,198,244,215,134,106,130,27,155,101,61,23,181,173,83,247,184,185,24,221,87,94,129,150,24,83,250,180,99,14,23,157,95,133,189,98,219,252,120,118,181,213,41,131,138,220,245,32,75,155,209,55,31,197,21,188,175,14,108,96,144,219,70,87,169,105,80,215,39,54,253,164,135,220,113,179,11,26,86,90,17,173,82,168,51,234,219,159,197,190,211,12,96,163,96,156,21,216,237,81,71,8,238,177,222,65,238,18,207,224,198,6,78,77,58,229,128,113,49,80,53,64,60,188,235,183,243,253,19,186,159,48,179,25,11,199,176,100,249,48,94,85,170,164,215,111,157,248,47,235,115,199,148,241,90,5,156,158,194,36,48,2,128,54,251,107,121,73,162,149,9,148,65,58,167,164,203,170,52,197,196,44,120,167,22,204,41,135,101,200,149,248,38,73,57,71,205,69,158,255,72,185,219,30,199,49,162,53,242,190,45,142,206,11,94,30,40,120,221,10,171,209,31,64,30,69,102,138,222,180,169,4,28,97,34,15,174,50,15,217,31,255,141,56,24,233,173,156,216,252,142,255,94,59,43,223,147,253,34,44,189,10,93,55,252,67,27,40,123,12,243,5,33,140,234,16,240,115,171,26,131,179,201,114,216,135,196,14,204,11,226,91,159,139,238,182,65,152,10,212,173,146,189,31,16,197,251,214,140,176,101,41,217,127,19,65,118,112,116,119,159,28,52,102,175,254,92,132,73,106,70,124,121,229,34,136,208,230,102,14,165,73,4,170,233,83,76,138,148,54,152,21,227,68,40,188,180,162,79,72,48,228,26,205,64,66,33,171,221,163,170,114,114,184,172,219,201,168,200,24,77,52,12,80,226,95,105,205,101,189,221,3,5,202,38,226,148,208,76,126,116,245,120,125,186,56,187,96,82,46,133,211,10,66,86,187,156,137,23,160,98,171,226,232,11,114,200,18,250,211,87,122,21,93,163,90,104,194,160,53,194,74,207,94,195,91,24,76,184,136,174,136,22,245,12,54,167,76,106,249,48,251,40,188,97,95,223,30,22,142,194,231,189,143,57,151,51,105,150,197,223,211,167,34,90,118,91,128,229,236,240,185,96,234,208,26,179,111,122,244,232,80,12,38,10,75,30,38,189,236,165,19,26,106,197,252,71,235,185,204,73,177,213,143,142,148,0,198,150,67,125,250,112,233,80,164,49,60,6,157,40,93,68,163,97,177,11,138,69,11,80,35,151,37,226,112,83,104,68,199,208,112,120,18,122,5,174,225,120,249,246,187,239,139,207,193,43,156,214,226,0,98,218,49,189,224,164,249,146,98,223,125,50,17,156,249,81,199,227,5,93,233,167,93,238,114,241,192,104,44,145,2,60,79,168,0,112,62,78,120,31,150,105,225,33,243,194,10,247,239,80,186,67,248,147,112,190,206,149,49,185,35,4,129,193,254,128,152,100,164,105,79,44,168,54,203,1,129,230,43,92,174,4,56,200,148,20,82,211,212,136,193,83,214,240,81,138,39,11,132,114,55,99,194,4,143,40,233,177,238,255,46,166,183,5,115,190,182,171,253,136,6,248,32,219,26,252,55,109,189,224,176,219,6,131,136,170,148,101,102,58,242,121,97,120,125,146,126,232,251,70,200,193,191,199,169,112,172,43,218,147,205,17,215,99,9,141,194,206,149,104,71,115,45,250,190,121,28,115,88,81,131,250,172,238,160,98,146,119,165,113,166,10,172,34,174,43,44,119,114,32,110,169,188,210,22,181,71,3,8,218,196,202,103,105,234,72,209,168,202,3,206,120,58,52,91,169,202,207,73,67,52,223,246,40,85,129,186,17,147,193,231,46,110,139,178,74,210,186,252,20,42,212,66,107,31,239,184,60,105,247,138,212,29,59,35,147,239,109,123,57,144,11,149,66,71,134,57,20,223,47,197,51,83,184,140,102,217,213,245,43,232,173,139,129,135,141,23,147,64,170,6,101,154,52,47,242,34,140,3,101,199,41,95,122,146,104,251,210,114,60,120,85,93,235,23,132,185,200,46,225,58,185,30,23,139,234,67,231,176,36,70,216,129,111,57,23,74,254,117,89,199,41,209,178,61,214,211,184,105,167,86,249,49,90,42,123,168,58,104,222,200,67,41,108,0,17,167,116,177,110,201,116,233,182,36,97,100,6,194,14,109,98,123,229,192,135,60,139,212,178,229,24,178,75,57,129,64,124,38,73,23,182,0,233,69,40,62,242,69,133,151,96,88,46,115,166,144,227,171,12,67,150,150,224,205,128,11,68,98,7,65,199,98,217,18,163,103,246,75,237,111,191,192,188,237,204,240,118,109,98,193,54,170,132,185,37,96,110,213,152,18,190,35,50,82,137,93,149,215,225,221,42,90,5,238,158,171,51,61,216,167,102,11,175,66,32,95,200,136,58,38,185,31,31,7,154,137,77,199,135,129,68,11,138,218,56,51,63,138,232,178,118,35,168,128,222,75,254,4,133,240,20,138,225,42,242,179,147,238,252,236,171,207,216,158,161,187,121,28,211,191,97,168,90,83,211,109,149,65,124,180,9,172,11,247,233,144,178,35,236,201,59,110,14,121,70,14,224,61,254,78,212,28,174,65,117,240,197,140,63,81,231,180,236,142,119,35,45,55,146,227,92,243,89,103,227,113,113,7,241,196,218,216,222,133,210,176,201,227,29,129,190,164,242,224,9,230,82,122,179,114,75,246,39,15,229,149,39,223,54,20,209,236,251,52,201,186,78,73,37,151,126,3,228,78,186,96,42,131,8,164,251,31,66,192,181,12,97,55,186,77,32,219,199,151,33,3,42,85,29,142,29,6,107,115,68,114,214,114,140,199,143,20,245,129,9,78,83,246,169,65,41,122,99,69,204,115,173,8,254,95,66,163,162,48,175,244,113,209,100,147,112,188,220,233,113,5,212,201,138,91,38,191,72,7,99,178,116,234,92,48,244,0,211,154,27,247,206,232,89,85,99,233,132,72,85,200,139,238,153,179,24,123,99,134,246,142,188,239,9,157,112,162,234,185,118,245,59,130,224,204,31,163,171,38,159,221,225,99,216,177,58,35,104,109,10,125,89,23,53,56,37,68,165,189,60,83,249,63,161,240,70,141,1,210,143,125,157,56,227,11,24,55,38,168,16,119,213,155,223,143,131,175,37,234,125,238,16,194,101,201,158,4,110,18,210,221,84,87,14,13,169,250,241,240,1,12,205,98,246,198,75,250,239,249,104,97,127,57,19,15,104,126,28,59,196,119,32,32,82,17,212,81,175,226,118,175,241,105,177,135,71,82,187,16,240,159,71,37,41,230,115,64,156,184,169,24,234,219,0,246,117,253,167,73,143,69,3,130,245,116,43,177,166,154,119,212,153,47,46,26,192,155,252,200,241,110,201,195,252,231,181,147,45,221,62,85,89,150,72,79,230,174,245,52,49,209,202,184,143,160,9,190,63,249,33,193,163,53,123,237,31,46,225,42,225,49,158,14,120,71,133,247,37,52,27,195,168,0,173,254,175,48,203,127,136,142,20,140,58,102,224,52,13,72,195,143,146,84,91,160,228,92,126,63,39,81,150,207,232,13,28,22,22,113,169,45,140,23,5,46,155,127,197,116,25,54,226,104,89,169,95,100,83,211,41,119,115,107,60,190,170,12,213,173,189,220,228,10,211,105,116,245,166,208,229,181,165,201,68,170,57,36,97,78,110,76,75,65,230,77,138,17,146,196,148,196,16,237,121,105,24,158,75,121,236,185,205,129,31,100,68,181,179,248,183,65,29,74,96,126,223,176,27,19,62,148,147,12,48,70,173,22,7,123,162,216,137,16,123,171,81,196,100,84,138,92,119,3,209,28,49,46,184,35,78,201,26,213,233,176,139,204,161,161,100,134,151,46,27,220,236,243,154,104,171,179,29,24,244,219,213,4,109,217,17,167,110,219,11,225,255,47,80,164,122,91,85,104,133,179,78,39,122,132,12,176,53,220,175,184,93,42,5,93,129,217,176,225,1,179,77,53,121,239,203,231,143,218,94,107,129,31,11,195,254,148,78,105,60,149,153,223,20,120,153,7,211,141,71,154,236,170,254,85,202,104,196,108,18,145,215,252,129,244,163,252,137,151,112,146,157,1,59,187,240,13,15,2,216,118,65,35,126,38,27,221,174,235,245,160,106,120,196,95,105,214,48,54,136,226,74,65,88,37,3,224,245,60,140,2,150,249,134,212,251,59,123,169,14,76,79,118,67,227,62,202,182,40,50,114,7,24,44,54,254,33,251,230,193,198,191,167,178,228,71,214,100,187,93,9,99,58,230,102,178,170,160,39,178,130,14,57,7,70,171,249,174,14,35,35,120,237,233,152,182,162,97,118,134,142,150,24,7,159,154,144,20,178,175,155,125,114,58,253,140,118,189,3,236,201,17,137,170,158,6,138,214,209,52,137,203,102,157,11,99,113,92,97,55,117,153,111,20,219,251,13,105,77,46,143,89,53,195,147,116,53,124,195,182,95,154,49,226,94,206,124,56,128,210,109,131,196,167,229,110,5,138,241,184,84,170,48,209,20,77,49,194,144,208,224,23,8,82,52,152,83,235,136,168,48,59,7,125,42,229,139,89,170,227,83,9,67,233,174,188,101,17,74,229,208,35,149,23,105,183,73,116,1,80,193,46,164,25,242,129,1,17,88,87,87,94,55,96,126,151,60,35,202,219,9,3,222,161,131,34,149,198,202,198,131,167,91,75,106,85,22,230,193,8,201,156,81,226,164,111,44,147,161,162,209,240,123,26,148,30,161,104,16,29,236,170,204,149,74,126,34,109,24,139,125,1,32,228,137,89,30,201,147,146,189,177,123,185,72,228,107,91,49,121,163,27,243,72,155,29,183,58,67,212,196,210,201,58,31,102,67,158,141,70,175,80,213,3,99,198,124,34,110,94,209,77,20,85,45,162,82,18,61,189,203,199,56,131,228,230,7,53,226,247,217,35,66,115,37,68,130,210,200,156,186,44,33,11,229,31,84,159,92,194,52,14,158,187,179,106,80,194,179,80,226,202,110,147,204,167,44,63,158,49,55,80,115,164,46,156,244,58,137,134,55,253,220,75,9,103,136,249,242,3,215,220,53,123,17,75,112,40,131,105,76,0,16,17,245,242,195,47,165,106,200,206,26,130,189,65,203,2,99,181,5,143,191,100,128,52,249,154,169,127,159,85,163,175,105,201,79,170,124,33,172,15,229,166,146,194,104,108,129,91,132,33,195,224,4,116,61,113,89,52,79,251,121,2,32,71,98,121,115,214,245,87,160,16,97,250,177,149,55,39,223,212,203,76,231,248,127,176,129,187,75,9,209,101,237,148,65,111,200,193,164,44,66,237,159,220,85,84,91,89,208,128,237,151,180,31,151,237,151,16,114,221,155,43,42,4,83,34,238,79,149,66,231,157,222,132,11,145,104,170,56,236,84,248,183,36,85,4,10,143,170,141,177,87,7,163,114,225,72,248,238,122,146,203,203,157,4,155,198,245,193,60,218,180,175,34,89,80,195,35,71,85,234,238,86,77,49,244,128,157,230,211,30,114,38,88,35,242,190,254,27,132,194,18,236,121,228,133,95,97,44,236,154,28,64,235,14,62,141,6,104,2,239,196,0,239,190,200,189,55,225,88,118,166,28,3,155,39,73,135,166,250,86,28,103,243,78,21,135,177,206,135,183,141,13,148,181,253,155,176,98,53,113,191,110,156,23,111,210,0,12,145,6,255,146,80,247,0,74,171,33,213,96,90,118,193,89,208,79,47,247,61,246,11,199,235,65,231,27,63,41,110,254,129,80,132,0,167,84,59,171,175,164,131,185,207,179,36,207,187,236,180,205,188,150,112,119,170,82,180,155,78,6,33,163,196,74,97,85,204,95,48,248,81,22,74,219,228,3,163,28,111,155,134,69,37,9,187,242,25,75,186,8,17,151,196,130,59,118,14,82,207,194,129,82,65,199,147,72,96,117,243,22,125,145,219,206,184,153,41,144,219,98,96,155,34,94,181,44,163,237,168,33,89,151,218,192,247,57,198,126,236,197,141,63,109,159,157,29,83,185,46,181,8,73,42,95,252,161,116,224,219,172,169,119,219,52,46,170,69,178,172,93,174,0,45,81,139,114,181,102,240,100,159,66,137,156,200,175,244,173,51,117,206,244,24,77,6,23,82,12,37,118,160,225,85,183,69,79,100,126,129,93,155,18,95,145,39,32,118,241,90,236,152,14,20,126,31,234,84,34,120,172,90,243,50,162,34,238,83,91,24,255,99,225,240,27,114,166,100,243,207,98,170,111,107,224,19,79,177,203,231,135,126,205,13,231,108,153,215,16,143,6,18,244,71,18,188,143,224,169,189,54,129,185,202,121,10,142,246,219,251,81,92,184,115,207,55,223,23,9,172,6,80,2,236,96,4,51,62,54,135,46,10,0,229,235,188,235,218,127,115,177,136,157,40,2,71,146,32,245,200,137,190,179,220,117,208,242,197,14,183,79,124,35,171,203,89,139,208,30,50,32,249,148,242,236,98,48,88,255,143,25,1,235,159,210,127,229,219,6,20,19,41,23,220,116,32,214,217,7,197,244,101,247,93,18,117,151,140,84,68,104,42,232,36,226,57,55,57,181,128,52,6,203,130,54,199,103,197,158,184,138,127,61,223,65,111,57,25,181,72,139,155,65,139,48,15,128,95,194,241,163,12,246,39,191,53,212,114,194,90,65,109,13,121,48,171,160,68,35,192,251,149,193,182,207,178,158,107,32,192,59,214,166,145,205,76,194,17,236,248,105,195,184,201,91,214,106,71,163,206,253,189,15,166,160,158,55,182,108,213,82,244,47,221,194,227,48,139,93,104,165,186,46,214,47,63,142,36,158,192,116,253,133,77,50,45,85,208,33,203,120,156,6,55,217,53,210,131,30,194,170,65,32,80,32,81,218,104,125,77,236,131,42,23,51,41,208,230,40,175,127,201,126,254,209,89,221,187,181,101,185,235,139,217,248,49,187,232,192,124,28,52,88,70,236,155,38,60,43,157,178,180,45,203,113,4,9,67,86,60,136,52,5,61,152,126,254,205,152,68,61,64,58,226,75,218,19,204,177,16,138,148,243,180,234,110,6,134,194,139,167,50,151,95,62,160,137,209,208,255,81,199,177,240,114,1,163,160,235,235,172,203,57,245,240,94,121,56,11,132,16,23,152,180,38,90,26,107,103,77,223,70,133,160,220,55,161,159,238,135,127,195,39,208,86,53,94,195,241,255,207,90,238,9,252,64,51,154,107,238,114,42,193,58,242,19,108,172,209,86,71,42,197,80,100,152,114,254,57,174,37,64,50,36,160,251,173,106,84,18,16,170,209,101,166,151,240,142,96,134,97,50,207,93,244,231,22,49,72,181,188,188,85,53,41,160,158,84,157,23,30,169,226,115,33,73,115,107,143,0,226,138,147,191,74,190,144,231,29,158,45,154,232,182,228,53,105,112,118,75,176,179,123,111,233,14,139,90,157,138,223,14,191,88,106,91,191,149,119,119,125,12,238,211,244,188,43,214,146,153,165,147,172,221,81,131,160,19,124,234,236,188,144,176,73,96,127,208,169,247,17,186,160,163,61,186,59,233,72,217,58,90,43,43,23,250,105,188,236,66,19,98,125,250,90,130,162,167,174,46,218,37,184,26,92,237,34,0,26,104,74,167,221,23,105,113,9,187,125,231,185,93,92,121,93,23,185,54,19,90,235,249,3,121,58,43,88,53,140,51,45,206,210,228,223,67,147,216,82,11,167,178,164,218,132,152,116,134,84,112,15,165,106,15,116,46,222,118,186,76,133,157,255,99,27,35,96,230,14,223,36,164,244,30,234,71,169,225,124,239,103,239,185,44,71,223,241,177,16,211,173,64,220,127,244,65,244,249,195,214,90,121,43,248,177,241,128,96,74,224,104,16,53,79,225,14,219,175,78,129,103,35,184,131,156,66,49,75,196,237,145,109,124,157,74,188,157,84,32,153,170,210,235,165,6,155,60,118,114,50,169,40,37,1,220,122,220,107,20,39,19,238,244,128,227,140,103,0,179,250,11,140,38,165,57,63,111,193,84,165,175,223,21,24,232,153,190,211,114,99,96,103,146,32,24,107,66,117,93,27,243,49,114,246,219,30,34,20,17,69,183,243,131,101,22,123,146,89,58,14,130,29,141,36,211,54,162,164,189,208,207,2,157,64,29,178,133,166,206,71,226,123,104,195,207,127,14,140,247,187,212,124,199,222,83,46,134,206,111,75,190,63,73,82,47,139,200,197,11,130,44,168,239,104,124,162,31,115,106,15,77,72,8,188,215,102,185,145,177,146,105,215,243,128,236,120,202,35,200,18,3,56,41,51,228,233,136,75,253,209,15,226,133,173,67,184,30,89,158,18,91,156,153,18,111,152,178,1,79,85,158,151,216,76,58,134,155,146,49,89,17,51,188,208,128,156,11,43,131,131,106,12,149,63,166,121,16,63,219,137,51,65,222,5,172,189,253,110,113,53,167,226,44,245,31,50,38,174,100,68,22,13,112,212,36,155,239,195,60,53,18,123,223,198,86,22,195,153,183,238,240,84,186,32,5,221,42,82,204,140,146,40,142,221,64,66,150,70,55,47,30,39,14,91,230,39,190,250,204,44,92,192,48,150,46,192,2,42,75,126,145,237,31,191,38,153,131,36,227,179,79,231,201,9,204,104,33,64,247,81,36,153,134,244,72,253,218,167,247,131,248,178,75,238,207,226,79,244,209,92,176,76,70,26,233,159,72,80,240,245,86,236,211,60,129,147,52,202,224,10,121,136,140,72,97,73,10,133,96,120,170,207,50,34,150,192,32,223,232,196,218,17,88,13,218,31,177,119,20,156,206,58,133,152,213,248,174,186,249,107,70,175,113,37,10,115,145,51,107,100,20,219,82,204,77,140,219,219,169,215,58,48,94,235,31,79,145,66,12,48,214,3,229,197,44,184,188,88,27,187,162,100,106,211,186,207,12,7,55,129,174,102,0,79,203,232,178,166,41,96,67,20,205,236,10,17,185,214,114,166,94,180,205,186,114,55,253,184,106,217,46,50,15,196,129,214,56,81,178,117,165,228,136,107,226,194,252,239,232,52,189,121,119,33,227,225,214,234,74,40,173,225,105,36,9,32,65,235,127,209,218,119,230,246,90,85,92,208,117,25,145,241,125,158,150,196,130,194,200,251,49,170,85,124,87,213,239,96,184,96,197,63,244,187,217,215,49,3,224,114,164,10,22,251,65,108,238,13,29,254,18,139,129,219,58,169,151,73,96,64,221,26,16,12,14,12,78,9,203,11,80,73,221,118,103,173,1,169,193,215,109,126,166,137,12,12,135,17,81,209,32,12,131,60,0,153,66,201,121,182,155,39,109,173,1,186,45,253,219,88,63,179,91,22,106,108,66,107,17,105,97,59,6,133,136,82,129,125,190,184,234,131,23,198,146,94,243,204,25,190,50,160,81,176,220,38,215,41,120,112,38,74,163,171,24,106,116,214,231,194,77,99,71,195,47,141,134,111,103,119,122,241,34,5,170,123,150,232,85,63,156,112,76,202,78,176,136,79,161,164,245,223,119,235,27,8,99,121,57,0,225,90,143,129,173,209,102,133,158,64,233,181,113,212,237,35,132,15,88,36,85,226,152,217,11,16,251,213,25,7,85,125,48,155,221,141,133,205,66,237,6,5,241,72,247,133,199,177,78,236,71,27,110,205,207,241,40,22,141,156,101,179,172,227,30,248,161,147,84,177,176,26,32,103,36,110,30,67,137,223,121,255,110,247,94,76,30,149,83,111,96,72,165,93,200,58,207,176,213,13,29,75,187,45,112,179,43,234,213,242,216,43,249,33,207,40,167,96,46,219,167,44,111,57,183,96,243,201,5,215,73,106,130,134,7,142,153,17,97,126,88,35,57,154,246,15,16,48,120,187,131,106,242,11,250,99,54,230,135,88,172,62,208,30,127,145,236,44,247,246,202,229,174,206,139,144,172,167,141,73,106,163,33,202,57,80,76,67,219,18,99,153,119,22,223,8,132,90,173,119,88,241,34,158,228,149,129,248,73,110,153,176,170,26,33,117,151,227,204,107,181,26,21,245,164,236,219,77,199,199,35,205,68,49,148,238,100,242,214,99,155,100,23,181,56,99,13,119,225,107,153,143,182,246,225,208,95,196,75,114,87,98,134,84,115,210,91,16,159,38,83,255,6,141,147,176,178,28,7,98,154,157,117,22,186,222,203,229,195,97,78,111,21,1,209,7,216,220,49,206,103,113,12,92,248,125,213,205,208,125,25,23,255,131,122,18,244,102,110,19,246,57,97,29,160,122,12,249,191,178,249,218,202,196,118,95,227,2,202,72,253,166,224,126,142,247,255,235,17,182,40,239,72,49,69,198,190,146,45,197,143,72,232,60,106,114,24,207,64,199,21,148,63,154,255,94,65,161,221,130,35,137,115,115,180,84,241,144,61,126,156,106,22,242,150,187,185,206,193,114,109,233,188,162,195,80,84,37,148,76,38,233,82,107,55,196,65,244,142,66,169,247,79,119,3,176,143,31,254,163,250,36,254,95,244,199,37,243,80,12,199,218,35,41,133,113,33,14,19,65,68,109,255,12,46,255,36,190,184,245,158,28,243,54,230,255,252,10,28,140,185,137,52,36,177,174,246,253,228,33,46,4,171,48,142,104,247,44,43,68,29,108,218,170,183,172,241,193,73,207,219,37,138,1,150,130,219,251,45,165,77,163,56,41,211,48,28,136,245,232,57,137,129,92,21,128,45,154,238,208,32,231,214,120,74,179,72,201,37,186,206,84,50,7,123,49,12,239,253,65,164,149,178,102,109,53,34,240,96,200,137,6,135,145,49,172,151,73,182,67,200,127,30,211,36,85,185,165,56,97,54,221,209,90,70,22,143,152,129,15,204,59,5,143,171,180,132,244,145,20,44,11,142,181,72,223,151,147,26,241,164,157,222,7,97,79,43,35,103,66,163,25,155,118,174,109,181,98,111,56,136,55,63,81,51,89,250,61,148,153,110,132,172,218,99,18,104,242,83,175,53,197,209,126,182,44,53,73,229,104,21,252,214,227,27,176,170,31,200,156,251,40,253,90,104,145,10,1,175,235,135,77,56,137,11,51,99,233,59,250,122,62,196,2,245,142,86,59,143,192,123,130,214,245,182,157,134,228,82,199,243,29,167,83,105,75,4,236,116,174,50,18,89,242,200,87,109,23,221,184,42,3,82,80,103,135,218,190,7,129,98,180,64,149,196,181,217,136,28,58,56,53,14,16,248,30,82,197,85,149,53,2,112,81,243,53,131,126,174,187,3,237,209,3,20,9,246,22,3,194,201,118,169,89,116,66,199,66,16,175,193,47,238,65,137,126,87,148,144,167,191,216,137,23,120,162,24,80,68,168,161,148,167,6,137,56,1,160,59,75,181,56,92,175,90,233,7,212,173,52,242,167,91,64,194,196,220,18,71,186,221,224,84,47,76,156,55,190,180,102,18,21,27,55,125,249,219,154,48,54,210,58,72,73,154,78,48,73,105,233,200,178,230,208,130,172,18,160,79,130,20,166,83,203,232,203,108,136,211,228,152,192,103,222,8,46,245,50,29,25,234,254,228,47,202,93,242,41,33,139,115,212,186,141,90,222,177,4}; diff --git a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_2spp.cpp b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_2spp.cpp index 8fac420a..56817e5d 100644 --- a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_2spp.cpp +++ b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_2spp.cpp @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // An Owen-scrambled Sobol sequence of 256 samples of 256 dimensions static const int sobol_256spp_256d[256*256] = {32,226,72,70,57,171,246,75,112,81,109,239,120,101,230,103,103,41,249,86,253,99,132,184,214,147,128,248,17,149,163,17,60,40,169,196,77,79,102,23,250,77,75,151,95,123,234,198,25,26,184,114,230,188,105,18,231,233,175,151,19,174,202,71,84,229,247,148,182,127,92,14,41,112,162,253,35,101,137,30,111,134,95,122,28,2,41,254,181,91,101,188,145,31,166,38,53,193,1,122,99,86,178,36,198,169,113,255,97,221,227,231,29,100,30,141,250,254,16,157,2,220,187,95,181,125,207,187,105,119,156,41,16,194,93,216,227,124,138,90,227,1,88,153,233,69,120,36,19,189,120,4,185,220,185,109,184,96,247,173,210,227,54,3,18,9,139,213,156,57,61,101,37,247,21,201,10,143,11,38,146,18,118,129,95,191,75,207,12,252,238,104,47,39,190,229,31,56,20,127,42,178,100,141,93,222,192,247,186,7,224,161,72,100,87,69,218,44,25,195,185,118,179,123,231,170,96,225,204,52,117,60,3,86,25,143,230,18,11,165,72,188,158,3,66,105,50,200,226,145,227,45,183,62,82,176,191,36,248,191,189,122,96,185,146,166,203,78,144,189,67,174,154,182,86,169,90,236,101,40,71,107,81,93,159,82,75,230,157,191,34,35,235,139,150,193,10,142,217,77,154,249,74,13,196,248,56,154,27,6,242,226,105,94,66,67,145,112,31,145,133,68,21,0,44,212,254,153,183,238,98,102,145,199,100,213,196,52,131,141,216,209,236,122,58,249,188,108,8,206,62,199,207,103,160,247,207,255,101,185,1,113,223,126,182,0,50,93,250,174,194,18,65,111,206,104,156,3,48,195,122,212,10,101,235,200,13,183,173,7,192,3,101,228,84,168,121,241,205,122,115,132,155,242,215,22,236,242,69,35,48,245,3,175,68,57,4,15,226,155,222,140,54,48,80,200,194,149,213,68,225,14,182,122,147,195,69,166,191,17,176,58,222,58,190,70,66,153,196,215,121,123,176,190,161,145,203,121,255,27,207,28,113,22,44,232,46,84,181,131,245,220,27,202,161,38,94,208,39,143,52,5,154,85,121,139,226,223,159,246,170,56,94,209,188,71,205,76,16,233,168,172,200,37,19,123,120,202,28,175,232,88,120,107,157,198,111,253,18,24,36,35,43,169,199,197,137,194,12,238,138,232,17,17,58,115,39,234,4,164,225,215,14,185,232,76,215,171,142,206,206,132,90,31,130,24,0,165,34,91,126,113,64,202,144,114,132,125,58,184,234,211,246,238,168,7,1,172,169,218,67,29,185,66,73,49,222,167,243,189,36,116,23,223,219,200,84,67,94,53,79,26,202,204,91,180,221,166,106,18,207,17,128,137,246,235,162,13,129,130,49,76,104,189,138,55,174,71,152,49,116,204,207,103,198,147,225,142,79,8,172,59,234,225,192,168,181,144,185,6,233,243,61,123,46,55,44,16,228,79,156,235,190,115,61,162,115,182,122,230,138,204,140,86,173,80,99,207,211,181,23,141,152,17,180,35,121,168,67,205,107,74,55,229,234,210,6,94,48,186,210,189,2,200,190,181,227,128,211,225,215,228,74,7,188,195,36,82,10,131,96,99,138,63,1,210,39,134,153,112,72,163,196,55,126,37,125,107,234,166,129,80,61,97,121,20,123,222,3,155,219,62,49,207,87,182,26,214,167,142,89,38,36,112,87,100,56,245,240,152,23,7,237,11,185,206,233,203,131,42,53,35,60,40,211,114,9,13,189,130,196,210,173,39,208,56,110,34,240,65,75,234,76,73,34,39,2,118,174,237,52,194,197,28,155,161,135,180,200,3,89,210,26,154,145,45,57,54,85,26,118,207,212,58,101,69,202,184,36,234,219,155,41,29,80,22,193,175,145,100,50,29,149,166,168,162,213,130,36,25,234,78,84,97,191,139,95,156,9,12,41,97,110,222,8,16,250,161,130,45,111,195,83,213,16,141,154,48,124,175,89,25,27,9,172,242,51,167,76,109,69,107,23,80,23,166,12,16,180,156,182,238,148,249,59,130,75,122,59,134,240,69,220,21,230,47,1,124,66,180,77,247,147,103,66,98,211,96,105,213,127,178,144,102,213,33,247,141,232,67,62,86,230,222,146,68,122,27,147,7,85,69,31,22,67,67,78,13,149,221,57,121,176,133,161,84,201,146,119,196,217,19,132,52,76,135,247,107,29,131,248,220,156,248,29,41,36,202,174,136,253,191,226,91,179,96,69,213,172,0,206,75,192,54,69,120,138,218,171,185,232,211,139,8,31,11,50,119,28,197,83,158,170,229,244,195,190,23,213,87,70,17,102,197,39,59,88,152,234,95,106,29,195,236,114,136,6,159,105,101,2,119,184,47,212,218,188,165,163,138,174,114,71,54,127,64,183,39,51,42,209,202,106,96,215,154,56,33,102,25,62,111,9,49,4,98,142,198,128,138,13,74,95,229,42,164,19,175,179,111,138,19,157,125,94,34,221,103,246,144,141,176,129,201,55,100,23,12,139,33,227,91,223,224,69,120,83,245,50,57,190,21,54,86,245,95,250,34,71,249,100,201,144,16,221,0,40,74,133,38,145,48,217,119,132,34,138,67,161,62,221,126,108,207,140,42,156,13,224,198,142,19,55,85,254,155,140,168,250,58,118,137,42,78,8,48,89,195,167,91,243,246,88,23,22,206,17,190,56,125,171,116,245,129,121,57,144,228,159,197,243,217,239,86,188,152,88,239,112,120,245,119,147,189,25,128,240,72,208,29,162,23,152,24,143,226,136,174,171,58,178,10,5,250,209,239,88,62,34,251,156,163,231,247,102,112,46,48,61,233,24,71,54,73,12,81,195,243,115,138,145,194,164,135,148,51,201,104,74,24,78,107,65,246,118,159,165,130,206,34,157,177,180,10,126,163,167,129,75,0,149,115,172,21,242,139,162,170,92,238,35,46,24,108,101,62,26,147,180,210,227,166,103,149,188,192,92,115,141,161,120,90,231,250,181,130,208,232,151,157,141,208,27,81,82,42,162,244,186,62,163,6,254,94,107,138,123,144,14,216,138,235,104,135,98,77,82,57,47,77,171,213,192,134,69,226,93,197,9,63,181,197,169,22,248,190,55,178,250,167,76,157,101,170,138,94,156,44,12,155,102,133,133,149,43,224,51,130,44,138,3,195,25,161,29,216,1,188,160,73,4,196,125,240,92,88,50,192,176,234,39,109,96,39,60,165,226,80,248,179,232,244,141,102,81,131,110,19,206,225,222,115,198,63,195,251,19,155,77,51,194,251,124,13,77,69,106,112,114,187,126,67,222,81,227,163,80,172,25,70,205,111,48,160,111,165,112,243,47,236,107,81,15,83,95,132,80,133,178,116,87,10,195,139,151,122,44,82,111,24,234,156,187,202,250,20,233,186,204,184,154,149,117,78,205,119,71,166,192,239,88,148,154,229,200,139,163,129,12,155,167,252,50,198,46,106,221,91,235,75,2,14,240,122,62,178,218,42,223,213,6,17,212,242,32,190,96,163,121,63,228,65,111,229,63,70,140,232,221,248,216,80,5,145,12,27,33,195,86,111,42,125,70,44,232,82,209,40,234,168,224,215,215,133,247,128,76,248,178,34,253,61,204,193,105,44,227,66,45,238,159,16,241,67,99,178,235,181,68,204,234,144,58,40,132,125,203,25,204,148,151,253,195,198,81,8,54,248,148,248,58,54,235,82,71,67,181,212,241,43,111,111,202,69,166,200,66,87,245,207,70,112,64,26,240,149,82,86,28,104,17,59,72,154,106,1,173,59,21,204,184,231,15,224,161,253,174,78,249,25,217,35,144,180,57,102,174,57,138,227,125,141,246,16,35,201,173,170,31,107,205,169,59,19,52,209,226,49,136,168,13,238,63,53,78,203,68,18,146,228,165,245,244,84,215,78,230,167,83,239,15,210,34,99,90,184,143,187,50,98,95,182,121,47,53,112,15,53,239,130,105,66,142,11,185,224,203,20,44,156,28,197,195,65,118,36,206,88,55,37,18,112,9,20,231,73,6,11,225,79,180,145,124,204,29,245,148,198,53,210,171,103,53,215,106,111,154,237,107,2,249,79,145,126,255,255,53,222,196,57,237,131,6,63,45,70,68,190,191,12,210,247,162,41,135,184,234,206,153,176,115,255,114,178,110,24,25,66,114,55,29,79,253,67,124,245,37,236,13,88,232,186,18,143,178,59,5,237,10,249,253,37,88,46,134,71,53,74,172,186,69,137,11,154,60,68,120,125,100,91,182,239,177,38,28,125,208,165,38,150,207,244,41,88,127,241,251,168,84,195,111,37,211,165,113,3,212,184,180,207,48,52,204,171,213,128,154,138,218,69,214,154,99,201,203,109,93,71,190,5,99,1,72,173,15,149,49,253,51,82,171,179,114,131,68,114,133,15,104,227,141,109,39,68,225,130,50,51,133,154,148,48,28,230,9,43,157,50,133,203,239,37,160,233,120,54,20,116,57,174,116,158,45,8,196,14,200,80,203,212,233,1,0,88,172,214,196,22,192,224,142,138,146,230,105,100,153,155,112,241,124,26,71,253,143,4,191,50,49,88,226,25,142,141,13,12,50,159,122,211,42,168,23,217,253,218,151,135,3,152,114,102,191,76,186,42,124,70,19,56,25,85,234,58,57,225,230,253,56,194,107,134,142,201,213,43,14,33,242,16,141,205,196,99,143,100,115,5,99,128,100,221,174,110,191,83,165,164,78,60,124,209,199,63,185,120,175,43,3,24,40,153,1,83,147,223,112,72,242,148,166,115,36,138,42,13,63,1,45,173,225,83,121,19,23,208,171,146,240,108,150,3,213,83,210,238,72,120,80,197,2,4,159,197,138,216,19,178,24,173,212,237,169,129,129,102,51,63,203,142,11,134,180,207,105,98,133,253,20,224,6,126,194,167,33,132,90,101,179,113,216,222,132,30,88,23,229,210,85,6,154,226,252,17,39,174,208,255,8,11,252,159,110,195,86,250,59,161,218,31,140,167,41,33,201,143,250,68,82,205,44,4,77,43,214,212,60,82,214,41,44,125,236,152,34,64,133,184,58,145,227,65,70,73,166,49,21,158,242,114,42,75,209,36,72,188,192,146,223,138,76,27,235,115,153,105,169,96,209,231,4,33,105,226,175,187,91,218,12,73,168,214,254,98,208,113,214,116,177,49,34,94,22,127,175,12,155,193,56,187,115,187,240,136,234,206,189,250,115,219,154,17,52,62,198,63,225,81,77,90,127,246,219,192,106,223,78,102,88,142,46,208,156,230,196,67,182,18,112,210,126,198,59,15,234,166,243,77,61,149,24,223,70,245,142,178,199,101,195,190,109,78,244,224,12,84,52,158,184,88,212,155,159,128,187,54,48,209,190,202,157,70,122,109,33,221,124,227,1,196,124,121,163,138,238,25,129,134,83,111,124,60,142,46,143,48,85,63,5,77,46,251,193,209,81,108,149,108,1,47,137,175,85,106,148,27,204,145,104,3,152,84,228,215,113,141,6,117,115,151,206,248,61,43,182,198,76,88,12,222,132,75,73,8,205,190,32,12,159,70,205,4,158,0,107,220,104,90,223,181,80,7,111,166,130,16,168,145,218,242,101,35,165,172,12,217,239,157,76,37,238,176,63,124,243,45,101,181,191,200,64,186,170,42,104,154,191,224,67,145,240,72,82,103,93,108,220,251,36,178,110,145,98,136,83,2,171,177,220,23,98,221,2,160,216,219,237,90,105,255,48,157,136,55,102,122,181,7,225,55,229,254,215,169,94,22,44,65,136,50,190,151,198,54,132,81,245,106,71,91,141,176,162,15,210,33,14,140,108,81,17,135,249,17,44,15,121,28,16,114,178,210,7,129,250,11,239,18,86,203,161,124,2,185,178,83,110,168,3,81,125,80,149,8,67,30,212,0,129,8,77,255,114,243,68,8,119,210,232,104,244,127,165,159,26,176,206,160,228,34,116,10,3,91,65,149,163,43,43,44,171,113,113,223,206,17,63,64,215,216,94,118,5,139,66,201,213,30,120,149,18,236,99,41,81,175,245,1,7,171,209,151,134,28,32,122,201,13,18,46,236,215,113,188,192,221,39,69,117,121,255,119,26,59,142,121,126,238,179,163,183,245,98,199,32,46,39,137,236,232,52,138,4,60,86,83,12,100,44,195,49,107,228,105,56,183,18,177,222,50,189,188,97,197,148,94,99,1,198,221,121,206,54,31,212,145,62,73,77,213,189,38,66,13,139,69,173,57,26,11,176,245,141,166,141,203,10,48,45,201,17,131,241,115,13,165,235,28,129,88,72,36,124,169,128,6,145,10,109,219,198,187,90,149,67,215,68,116,33,56,204,217,236,231,0,205,84,97,113,175,30,185,95,187,166,164,123,103,0,218,18,150,180,103,151,153,146,97,15,161,171,246,252,131,198,186,58,55,210,93,58,157,3,142,220,98,50,202,151,2,115,205,200,3,236,146,210,233,71,222,129,198,18,131,29,157,152,63,201,45,197,253,170,121,124,232,64,197,112,22,208,106,99,54,41,247,146,135,234,142,177,3,38,157,234,222,46,189,233,76,41,150,255,135,82,99,244,246,187,81,215,16,76,188,188,104,156,21,239,255,206,97,35,217,194,13,70,106,106,238,171,232,93,223,145,190,50,39,144,48,13,113,146,151,178,156,18,131,231,168,108,178,224,7,44,122,98,87,166,65,220,174,138,98,95,93,188,127,246,195,136,215,160,201,137,35,217,167,126,219,175,109,180,111,127,222,93,69,133,2,58,198,186,238,108,57,157,101,174,249,26,46,210,254,251,76,43,197,209,161,52,197,28,246,173,229,35,43,13,81,122,34,245,212,223,50,135,69,70,192,171,78,9,135,189,54,168,232,131,250,208,59,227,252,247,231,40,235,203,254,51,25,198,223,165,81,140,141,67,194,180,31,194,172,47,195,56,153,118,221,30,217,17,85,154,184,122,15,130,179,86,8,37,33,200,95,144,73,175,68,185,197,128,182,154,171,147,182,86,172,23,236,20,92,194,110,253,124,133,82,127,206,92,34,108,69,170,47,61,41,87,108,218,3,244,7,124,51,153,83,186,164,116,154,85,123,43,135,177,107,28,189,81,241,214,189,235,233,142,6,109,183,130,75,79,107,99,67,31,164,248,227,114,159,230,115,116,115,252,33,75,4,171,191,217,88,245,156,203,48,239,140,253,211,46,184,136,34,21,248,161,128,156,16,88,64,71,34,174,125,70,164,125,92,205,214,79,157,199,223,143,214,138,213,150,169,17,16,181,95,200,208,91,91,55,125,7,1,39,91,6,103,252,246,22,71,110,149,236,73,1,247,51,2,168,88,124,234,86,100,6,94,1,17,215,157,34,238,126,194,222,109,67,175,96,45,252,99,58,3,34,192,251,95,240,36,188,243,191,229,74,164,55,171,108,239,73,208,140,114,46,244,36,30,33,56,14,209,94,86,28,9,153,30,23,102,165,252,98,77,72,233,22,126,152,98,40,246,35,93,137,114,191,114,200,54,214,8,238,145,43,119,180,186,55,74,170,232,166,247,56,233,9,162,16,241,95,47,5,109,72,125,67,35,130,55,138,75,157,246,85,244,3,230,60,226,159,12,234,155,160,180,119,243,253,179,202,194,53,218,65,208,230,212,71,228,29,49,220,31,146,244,249,84,46,237,203,93,171,73,33,115,46,109,10,163,137,73,18,133,213,236,174,230,216,119,127,80,199,18,100,180,236,191,127,152,158,226,45,72,70,181,106,90,21,229,46,41,109,55,237,81,0,158,169,63,40,22,85,246,181,235,161,180,28,175,136,87,132,184,54,121,185,69,89,58,20,54,81,101,87,37,251,152,4,162,108,113,248,178,219,151,240,144,158,242,185,138,4,34,148,255,250,66,75,144,141,25,248,244,89,180,203,97,141,149,179,129,213,186,64,101,242,119,130,121,108,230,198,74,228,155,96,237,140,201,158,44,127,161,120,219,94,11,95,27,145,80,184,107,215,88,252,32,89,59,97,159,249,183,75,131,180,65,184,179,85,80,88,74,128,53,126,191,54,169,0,133,100,248,196,158,91,121,110,12,248,130,87,248,186,85,136,101,181,0,90,45,34,227,84,17,40,96,221,187,167,131,112,48,70,62,240,138,78,245,248,226,203,255,32,242,246,141,200,17,167,32,151,12,72,159,221,190,56,115,237,233,226,113,71,228,167,60,113,127,28,174,27,176,227,160,77,221,157,64,14,166,82,60,78,7,91,16,214,169,78,222,97,33,229,210,4,255,104,234,42,181,7,177,190,23,40,135,53,67,63,28,151,60,167,81,21,190,110,214,160,222,51,228,87,83,113,220,46,182,163,193,79,214,249,120,197,244,197,169,252,20,33,253,246,46,198,16,208,35,110,5,37,236,172,149,234,155,32,36,8,249,70,224,226,40,16,146,131,224,173,250,111,102,227,160,196,255,167,81,196,62,24,6,39,4,245,139,98,158,201,247,5,6,2,61,92,5,65,70,24,206,135,30,246,146,155,22,29,247,25,112,186,5,208,134,240,95,137,29,48,148,222,92,36,165,248,10,244,222,158,131,46,156,217,243,219,101,123,98,209,124,89,178,16,48,173,142,241,134,127,160,217,64,134,35,244,28,253,59,26,10,212,162,143,252,94,0,198,0,16,156,116,145,64,255,206,234,251,104,250,213,247,171,89,86,125,48,237,216,196,160,45,90,227,12,33,58,31,88,200,117,101,36,105,135,49,134,64,181,233,40,63,100,189,192,13,48,58,159,183,105,34,162,170,166,132,83,141,116,29,39,216,84,29,224,211,54,145,251,248,148,150,203,26,51,179,47,134,175,80,66,223,24,221,52,170,59,241,37,95,232,183,15,162,203,144,221,60,248,8,211,255,78,249,55,59,23,131,11,165,152,182,82,168,71,89,48,249,78,107,182,117,73,21,79,42,128,232,89,103,207,13,224,32,236,175,138,201,54,26,98,122,91,253,144,222,108,171,101,120,208,168,40,29,46,64,23,171,248,115,40,80,28,107,143,65,188,142,205,155,234,86,121,157,124,23,44,177,188,201,222,229,244,169,241,155,62,102,187,15,28,49,168,157,29,135,202,9,160,102,125,112,184,31,209,162,114,13,130,215,93,15,255,110,50,54,19,144,98,47,46,170,252,210,5,161,176,69,185,97,187,253,94,124,215,85,69,73,136,150,68,137,217,52,113,151,241,70,44,102,126,10,143,167,133,81,239,233,109,73,171,141,93,133,112,185,133,103,206,49,208,130,79,127,234,48,173,231,82,200,74,68,194,188,185,26,56,199,134,122,3,153,227,174,245,23,34,49,20,68,184,202,1,232,252,31,171,45,85,7,114,187,66,203,169,98,117,144,15,165,104,143,111,174,100,197,60,7,53,248,238,100,12,162,96,40,189,247,101,64,57,57,14,195,114,229,155,228,32,111,37,141,8,8,163,2,223,6,96,54,144,175,85,141,51,77,41,60,192,113,15,103,101,44,30,102,189,100,251,227,71,37,62,123,4,63,119,25,116,47,205,191,156,1,106,136,248,37,151,162,72,226,41,208,133,69,146,114,137,43,245,90,115,117,90,122,134,180,218,136,10,36,210,53,138,90,139,213,130,56,173,119,174,71,72,213,138,87,171,101,156,110,0,164,38,191,156,215,148,220,106,138,50,237,54,37,49,215,127,45,81,226,61,181,195,147,154,208,170,94,34,8,228,121,71,182,239,63,56,65,244,0,70,162,73,198,63,16,134,216,58,187,203,234,115,44,209,105,127,183,130,74,82,203,219,128,128,162,13,47,106,252,31,56,155,184,119,56,139,70,241,3,104,153,43,183,28,68,241,224,25,154,52,51,131,108,142,150,13,106,43,251,166,76,47,218,150,11,125,109,109,179,145,213,217,241,16,32,208,48,33,217,59,171,245,248,174,34,191,77,111,183,221,49,141,59,221,76,224,103,190,107,171,215,232,44,84,133,236,88,227,175,24,57,144,252,229,182,140,36,219,42,92,101,187,212,188,34,205,167,99,168,91,224,154,187,112,52,190,62,212,191,250,250,68,229,248,142,143,161,185,243,117,222,69,61,162,247,179,140,133,135,164,217,144,222,8,114,20,240,161,44,27,187,82,122,237,53,167,43,2,215,122,219,61,163,54,181,154,176,222,239,12,13,63,88,213,167,98,162,94,254,89,113,112,242,88,158,65,229,215,16,126,234,96,129,34,233,231,85,152,90,16,97,32,90,134,18,131,114,130,148,249,76,135,186,171,103,192,83,45,100,96,36,88,217,197,165,86,194,168,112,149,125,108,133,112,117,199,26,221,35,245,88,233,9,113,47,138,31,61,114,47,51,32,197,55,17,175,164,93,204,223,215,203,221,224,147,103,78,214,230,214,71,214,220,169,117,39,0,147,198,108,242,153,155,144,235,250,162,35,53,61,45,156,227,244,108,123,32,227,129,77,252,146,213,168,197,237,147,123,38,228,75,144,165,144,102,113,198,22,145,14,101,195,177,43,62,151,113,96,81,189,204,180,207,197,24,72,76,135,127,181,246,81,18,167,113,85,184,62,190,140,86,209,148,134,111,32,60,108,33,233,115,99,216,239,112,146,92,217,236,252,213,215,98,122,215,64,175,155,179,121,195,7,207,252,163,51,58,143,187,255,188,122,6,199,73,36,149,218,141,142,43,108,99,2,232,187,65,216,24,169,125,102,148,113,59,233,176,194,207,77,204,245,20,43,145,104,88,88,212,187,237,152,64,18,141,254,53,255,111,53,61,62,49,143,145,197,10,207,36,198,166,88,7,199,42,201,145,219,135,53,239,108,162,82,202,181,4,255,82,23,38,141,213,120,0,218,105,2,141,120,255,138,20,27,255,97,202,151,0,166,227,16,196,48,139,91,164,4,170,177,243,27,154,220,212,167,205,179,84,245,205,50,51,155,45,39,99,124,70,27,48,182,173,3,26,38,214,1,26,23,216,248,214,89,78,142,7,44,2,118,103,73,72,202,187,222,242,74,37,84,166,251,191,67,11,231,116,61,33,17,96,93,116,165,173,88,153,105,123,125,159,243,89,143,66,211,213,23,47,204,192,2,231,229,224,32,30,45,9,31,149,216,137,119,152,34,22,131,206,47,216,201,89,197,58,66,204,67,92,0,150,199,161,213,185,96,252,164,78,46,247,41,134,48,118,14,77,30,250,176,12,138,96,58,51,142,9,249,103,99,29,247,189,31,126,29,86,211,201,108,216,195,90,32,119,124,219,207,128,192,119,91,217,60,215,24,182,244,100,241,153,24,3,99,115,167,33,25,239,186,42,198,202,179,57,117,112,11,208,212,50,26,170,22,148,206,252,232,159,56,64,37,184,40,232,109,62,164,199,64,198,112,56,71,12,215,108,220,20,211,118,70,182,19,212,219,182,104,5,188,255,61,162,241,25,176,78,25,176,239,21,205,246,214,246,86,45,101,158,9,252,149,38,59,72,225,119,121,209,20,85,6,84,253,24,182,126,20,150,105,176,238,54,59,96,46,28,214,21,80,112,19,118,125,115,134,244,30,35,230,238,255,199,220,32,200,9,142,2,182,14,101,191,176,143,96,217,200,124,194,43,105,61,93,143,135,53,12,228,233,30,150,173,228,73,179,184,84,21,117,63,245,231,49,129,29,249,46,23,172,195,94,36,76,227,246,71,159,188,8,88,119,49,177,156,203,88,101,195,170,151,183,106,100,9,246,64,254,1,90,4,9,163,154,231,88,68,182,99,67,75,171,107,142,196,79,237,114,70,178,128,33,83,168,67,129,82,214,135,38,206,41,152,140,168,52,239,28,171,28,29,180,246,185,183,243,85,129,112,168,63,139,133,0,162,86,166,48,132,244,159,151,235,175,64,110,168,85,97,233,11,62,25,177,16,57,124,63,250,59,218,136,209,136,192,23,168,160,206,65,84,30,73,213,235,181,104,66,27,98,126,183,219,93,200,115,84,141,57,55,20,131,91,14,228,85,181,19,4,110,176,90,101,40,91,107,155,7,70,21,114,154,141,146,125,246,64,1,216,213,232,23,143,224,115,244,247,144,186,71,134,69,183,141,25,186,91,29,145,163,250,202,181,57,216,172,131,228,242,181,187,52,94,218,252,4,118,44,52,124,160,37,176,17,218,121,140,191,107,102,91,222,49,91,229,106,179,221,170,200,88,38,138,167,10,48,157,47,99,57,137,88,76,206,141,214,208,48,80,226,18,227,6,175,180,63,107,247,251,197,59,51,247,13,109,209,162,206,192,125,112,94,235,247,26,88,14,126,241,225,249,81,162,7,157,238,150,138,24,69,121,155,219,17,169,180,218,93,230,99,92,139,53,179,145,30,14,205,171,75,247,49,194,3,14,177,24,222,122,30,75,174,121,243,104,233,244,81,4,47,70,43,206,113,229,119,231,49,72,144,78,214,29,193,41,75,14,97,19,84,148,246,3,250,243,7,246,233,153,48,135,226,204,199,93,210,3,97,11,106,117,170,122,92,97,150,179,177,220,46,59,17,151,242,160,233,237,81,78,255,87,243,237,113,135,216,131,97,197,224,41,142,85,234,243,135,58,152,220,191,227,149,78,77,30,82,167,63,217,43,227,106,173,223,128,161,49,70,29,184,169,178,179,124,224,2,243,210,229,112,103,15,29,78,229,91,9,68,198,94,135,241,207,69,183,229,46,78,63,189,93,163,10,91,172,13,205,180,217,216,102,237,239,3,217,247,218,0,147,130,158,175,242,39,94,23,238,221,229,211,72,140,103,207,7,73,10,200,247,155,254,35,165,152,2,137,237,154,128,235,215,210,1,132,104,143,128,91,191,225,241,171,220,16,165,209,59,10,1,128,151,229,116,17,20,188,108,57,196,105,197,5,64,216,75,255,49,10,35,243,39,238,142,201,1,32,8,28,116,21,216,226,89,90,231,210,128,81,149,93,249,111,150,128,11,228,231,236,178,74,34,174,187,230,84,78,197,136,17,197,25,242,154,123,24,78,245,178,254,76,70,182,72,15,115,54,62,10,89,172,129,113,97,148,204,240,100,172,169,122,13,95,182,26,184,25,191,255,250,250,137,18,19,72,145,135,112,125,227,63,65,26,54,228,181,30,158,27,191,9,236,168,115,248,144,187,132,253,45,84,154,196,103,30,149,123,53,42,206,172,146,175,44,203,69,239,45,147,0,121,103,125,132,136,192,38,62,79,29,241,17,151,110,28,38,221,234,230,228,182,64,241,144,165,124,145,120,49,50,129,18,33,242,212,143,68,167,109,134,179,113,176,85,93,87,105,133,15,66,249,8,43,9,147,72,30,6,2,85,185,204,160,20,76,70,119,163,67,200,121,228,185,204,22,48,31,122,177,123,93,159,108,114,65,90,91,67,95,139,6,187,3,78,142,38,96,61,68,23,146,93,32,245,153,131,61,126,1,194,201,158,51,161,172,0,176,76,143,229,81,201,36,157,210,139,109,215,12,9,41,152,243,188,240,144,194,27,114,193,162,39,43,9,203,46,137,76,217,93,125,215,74,43,75,0,153,246,95,88,44,134,248,43,87,166,46,133,1,77,197,205,206,31,50,102,178,248,22,226,192,156,203,195,155,193,32,35,158,173,76,75,79,240,112,7,161,130,162,85,225,67,223,15,127,53,24,49,231,201,248,16,114,146,228,17,178,247,166,162,2,32,180,41,188,9,197,103,77,246,35,30,71,112,6,222,168,64,60,248,242,61,201,130,219,58,182,38,143,103,45,104,219,7,121,119,138,183,148,149,107,216,169,2,89,111,185,120,49,74,173,174,35,38,194,214,86,32,216,229,123,41,64,108,178,152,13,174,71,86,192,147,84,112,246,98,151,238,63,210,134,112,5,28,254,154,125,236,82,78,22,114,230,212,88,97,54,211,70,203,48,159,59,21,36,55,56,141,194,247,133,160,138,224,66,180,74,137,37,94,5,120,135,170,119,209,147,221,28,19,215,139,29,199,87,234,102,225,111,74,180,27,169,131,129,29,44,138,81,235,206,181,229,133,192,201,163,110,48,203,245,95,200,183,29,29,31,255,74,216,148,92,109,191,130,29,236,248,204,126,228,208,76,200,13,128,197,198,255,211,23,197,132,124,133,71,155,21,132,233,191,189,212,255,108,47,94,109,53,232,234,95,174,83,223,18,188,255,239,215,139,141,51,127,243,199,103,111,117,45,101,67,184,104,196,20,34,25,184,251,144,47,226,217,214,217,125,47,52,41,242,113,104,13,56,74,44,166,36,63,154,133,145,18,80,160,124,59,47,48,219,63,43,134,67,115,238,189,252,67,6,164,83,181,123,230,213,252,7,222,130,221,30,79,68,34,162,2,61,134,162,207,49,146,161,216,82,98,181,190,57,57,164,128,97,121,148,131,128,152,66,106,247,15,154,148,82,42,174,142,17,249,123,23,138,78,106,245,159,202,19,26,160,50,138,153,136,182,101,89,247,195,169,69,220,50,155,45,140,251,248,183,139,84,17,44,98,83,13,102,234,106,135,22,255,212,246,163,28,11,251,123,18,5,150,221,6,2,137,17,176,56,215,12,166,187,52,149,11,97,119,140,245,13,201,20,98,80,27,26,125,126,58,232,231,83,52,195,75,116,248,147,230,123,171,77,81,168,163,120,39,158,18,54,60,212,117,67,148,122,151,78,51,30,88,27,152,83,92,191,105,162,106,233,12,27,116,4,53,100,189,242,253,169,182,10,105,196,84,229,122,141,80,15,0,38,26,50,176,229,18,32,169,241,202,190,190,225,100,193,44,196,209,193,83,89,43,228,8,127,48,9,221,186,199,251,97,138,218,190,131,202,206,62,148,128,44,48,107,164,177,57,149,171,214,244,57,198,194,87,179,232,10,17,65,243,255,109,19,208,42,55,68,178,164,84,21,57,206,5,27,252,203,144,108,90,231,137,198,221,204,164,204,56,73,223,129,127,246,244,144,140,13,229,195,199,39,42,93,103,202,8,45,68,203,17,186,154,9,154,228,59,255,134,120,125,170,90,18,141,31,17,116,10,189,48,63,147,112,188,11,184,92,95,253,180,92,80,106,57,112,187,229,228,69,3,1,47,47,72,146,48,135,37,111,82,27,20,77,157,222,115,123,120,119,159,196,99,7,116,57,222,119,79,79,212,213,215,145,225,154,187,25,22,126,89,170,169,123,159,94,29,177,63,137,207,167,192,97,134,193,17,236,199,8,35,214,220,156,72,183,180,8,63,200,171,93,216,103,110,145,159,209,158,236,233,50,228,220,144,113,159,214,222,157,156,27,133,183,240,127,191,28,41,222,148,155,247,32,97,96,128,237,98,236,159,107,157,192,176,19,81,248,145,219,183,179,73,178,81,38,137,81,108,189,148,180,164,63,244,107,140,13,253,2,84,88,16,121,200,120,77,203,104,24,207,202,194,62,253,155,102,96,168,116,28,237,163,138,91,149,34,82,230,211,109,230,176,130,28,82,186,233,159,99,238,249,81,38,106,243,246,4,63,80,43,104,47,1,253,236,84,79,158,5,81,26,18,242,70,42,11,229,216,154,236,16,203,159,227,7,207,120,26,197,81,87,177,4,32,197,147,111,255,229,91,211,194,195,230,35,169,151,31,196,33,181,120,192,254,71,84,152,228,208,209,129,98,55,39,210,144,146,192,231,249,121,170,81,218,202,197,150,149,234,93,90,178,167,209,244,86,25,140,141,156,206,14,247,240,217,14,39,99,82,121,16,119,157,210,169,220,50,58,255,48,130,189,120,154,59,60,85,94,135,23,15,171,6,31,212,224,89,73,100,179,91,61,170,128,28,33,227,9,149,128,12,110,120,44,9,52,192,4,24,65,221,114,24,77,109,0,237,94,4,42,232,84,150,134,32,50,33,84,234,130,136,89,117,253,79,60,135,69,29,50,128,196,38,41,43,37,78,168,73,163,249,45,207,177,76,38,115,76,143,118,145,106,166,6,142,230,193,147,145,87,195,222,73,219,219,89,33,68,237,118,120,146,164,74,130,237,16,47,79,228,9,153,184,5,127,80,182,81,105,196,51,244,192,237,160,118,200,191,94,235,152,191,202,161,231,171,19,116,102,94,206,253,175,4,193,18,70,53,214,98,123,181,137,167,190,84,96,169,2,204,232,54,221,169,175,186,172,137,170,75,32,249,57,119,86,19,52,123,234,142,11,108,19,58,84,98,250,242,114,170,31,205,195,117,12,243,41,93,222,0,101,219,102,129,196,192,91,8,186,233,243,37,194,183,162,121,59,93,71,52,178,114,96,72,252,185,254,109,31,107,112,168,64,226,160,216,43,49,74,50,139,112,148,135,148,88,184,35,26,29,171,245,47,96,61,39,146,159,194,252,57,202,244,245,218,216,18,29,71,237,39,25,197,164,184,67,97,53,45,16,218,207,244,97,249,96,167,93,62,103,162,164,67,186,159,2,26,136,32,184,9,167,169,183,210,72,43,253,167,72,211,171,205,117,92,82,32,5,197,107,8,68,106,237,8,142,148,101,227,90,210,67,13,252,233,3,242,79,95,172,175,195,246,251,254,247,71,7,224,252,37,255,4,158,178,131,23,77,77,22,178,114,155,151,162,207,53,98,63,132,143,232,73,194,185,91,243,57,47,83,36,154,42,31,150,56,15,33,40,14,111,70,137,225,158,138,108,119,114,255,48,176,231,182,51,219,163,86,122,80,104,197,169,107,181,97,55,228,63,47,73,106,27,23,65,207,177,34,218,221,147,192,237,165,74,89,152,255,181,169,250,226,99,10,232,6,181,45,3,222,174,26,248,155,12,199,237,65,205,85,22,125,164,146,124,17,73,140,71,36,57,173,173,157,157,161,35,164,157,190,71,67,29,142,133,206,231,64,185,95,111,65,166,220,233,245,73,242,25,16,29,223,124,142,199,177,13,24,198,245,218,190,115,38,32,45,236,12,96,101,63,17,230,151,217,117,234,153,112,111,91,162,196,247,185,166,60,2,8,145,56,160,48,175,226,250,67,51,132,106,42,213,138,119,167,9,240,25,8,56,22,165,218,9,62,218,121,29,43,177,130,210,166,150,15,220,225,225,152,34,255,104,115,223,108,131,55,250,255,49,92,130,20,179,218,73,38,116,122,102,17,118,237,183,109,65,232,122,235,4,68,3,245,160,150,224,73,183,115,6,100,124,166,210,201,82,249,142,15,23,20,60,118,137,170,181,229,205,108,201,240,169,87,195,99,76,138,15,228,158,47,216,146,8,248,175,110,207,39,94,180,173,250,47,24,2,201,150,241,233,238,16,120,75,140,84,49,212,106,98,213,162,86,181,76,170,35,124,116,48,164,197,74,131,117,229,28,19,139,154,0,123,202,110,178,10,79,113,166,22,172,117,191,54,48,27,183,59,223,105,57,148,54,241,188,72,118,58,255,33,235,238,206,33,254,197,162,45,154,226,221,57,145,225,19,36,11,164,245,79,188,132,50,190,248,255,75,183,214,242,69,109,232,147,130,166,70,86,58,124,161,96,88,92,166,32,184,117,117,232,148,14,163,81,163,242,0,239,41,82,240,105,189,74,68,200,164,195,85,62,74,56,226,196,41,2,105,154,95,205,207,232,106,98,226,99,112,210,188,162,203,188,28,65,78,18,252,134,93,120,74,188,64,154,12,133,146,228,14,25,9,13,157,22,83,145,169,201,189,221,137,49,232,138,179,182,165,146,2,109,172,21,172,40,157,230,199,70,170,17,231,133,250,192,45,75,214,33,111,3,120,209,54,12,206,159,226,150,136,96,94,25,66,56,178,106,7,73,214,104,156,236,28,249,93,15,229,9,0,132,16,69,155,125,179,207,94,14,13,244,207,241,54,32,52,63,98,162,154,191,75,209,229,33,193,255,57,31,229,86,153,43,207,166,165,245,54,40,212,29,222,70,136,130,40,74,185,218,104,130,108,129,245,188,86,215,76,131,33,190,168,234,99,175,11,251,216,73,187,108,44,255,201,238,119,247,44,86,81,235,45,3,57,216,75,34,73,180,36,35,240,164,214,36,117,135,41,119,211,38,76,81,196,8,21,97,136,235,119,71,123,36,176,199,227,228,108,128,149,137,5,164,77,148,159,81,47,176,108,234,54,46,235,56,167,178,84,254,105,129,190,49,65,57,236,213,149,152,10,85,206,195,221,92,221,54,74,114,134,198,83,208,132,62,75,99,76,23,147,221,170,238,47,2,231,238,159,31,157,21,230,120,116,37,205,171,183,193,105,172,143,117,1,93,76,23,54,218,89,41,8,34,70,14,172,247,13,165,93,149,104,106,13,209,88,202,31,127,1,56,213,196,57,128,219,160,128,36,102,11,50,241,144,120,109,249,181,6,101,158,193,159,198,121,72,53,117,201,226,238,36,19,89,190,170,97,242,166,133,255,187,116,117,149,110,240,34,46,115,10,173,23,253,193,26,88,218,204,250,37,212,109,250,201,191,194,118,95,136,247,161,207,241,204,135,2,78,149,74,112,131,147,47,174,61,6,17,165,170,245,205,230,27,4,219,42,253,132,224,5,105,216,149,164,189,139,111,218,70,124,62,36,131,167,58,160,166,166,15,182,6,55,43,51,18,46,56,174,90,10,0,14,29,74,85,33,208,147,69,176,90,198,106,36,37,30,25,35,124,178,130,4,84,25,198,20,229,53,83,27,191,7,155,221,115,87,5,220,83,80,84,102,251,48,221,102,199,149,98,72,199,4,97,43,61,78,97,140,141,115,8,36,76,209,170,73,151,35,27,50,135,70,240,173,0,121,54,23,163,78,109,212,129,93,171,216,134,28,83,113,141,233,192,101,187,144,201,55,84,241,226,162,50,111,152,243,114,9,111,93,4,89,234,55,65,28,241,78,143,188,189,252,70,80,238,69,204,212,181,122,171,109,189,186,144,136,240,116,95,234,155,53,70,170,203,113,36,46,45,134,195,163,140,104,104,25,181,136,167,116,55,237,25,77,120,91,44,239,159,52,190,41,227,220,175,171,101,213,127,105,222,163,58,68,40,210,118,247,1,76,42,20,189,248,76,43,113,25,81,37,26,154,234,25,226,251,39,69,143,3,138,235,220,47,9,31,25,63,195,193,72,173,92,80,43,152,143,80,74,126,49,33,238,113,228,171,168,241,82,49,174,116,73,94,130,72,230,253,161,187,183,237,195,41,153,143,130,252,152,169,147,185,106,2,207,13,134,90,175,141,157,242,255,161,154,42,107,178,145,195,16,211,119,181,175,211,84,142,39,77,187,239,159,12,177,186,243,150,95,140,58,167,52,103,146,158,98,247,173,141,219,214,180,87,55,184,155,216,203,67,81,243,45,171,219,220,110,144,106,5,138,225,212,232,110,202,220,68,84,250,115,120,118,200,167,154,108,73,90,190,72,34,47,249,229,114,4,80,142,144,22,68,254,128,128,196,171,194,100,131,176,168,30,203,107,42,65,59,156,176,21,156,53,86,125,203,58,216,87,127,233,238,153,162,195,175,35,133,212,69,25,61,96,246,99,19,132,120,219,58,140,93,223,248,9,43,246,147,166,10,33,40,237,26,6,87,228,81,182,159,34,234,48,74,27,30,186,36,136,63,92,110,3,131,130,27,239,155,0,156,219,146,232,148,189,133,204,227,35,102,6,13,242,251,69,127,251,171,127,248,242,116,126,174,84,115,6,193,135,29,128,225,230,162,23,222,79,106,4,26,156,61,251,88,57,81,76,237,7,19,107,37,95,147,230,99,193,76,98,87,252,124,217,105,200,201,204,245,189,226,154,95,54,19,34,64,85,66,163,243,6,203,46,201,0,174,183,154,181,226,46,152,199,255,75,54,243,29,83,133,231,240,6,21,38,68,184,253,109,54,23,224,31,102,11,112,103,43,17,38,125,238,71,104,161,159,219,136,215,196,141,170,10,56,156,93,207,152,188,114,22,157,0,165,25,138,205,58,248,67,193,58,28,147,32,38,229,221,175,114,14,42,161,2,223,231,204,164,6,92,49,52,64,37,164,223,252,197,118,55,243,108,10,158,239,219,175,244,102,22,194,134,212,9,249,244,43,86,97,41,53,9,224,110,61,250,140,202,187,95,171,204,21,221,58,141,24,176,120,96,194,232,84,28,125,246,218,142,73,131,254,249,22,179,71,110,208,97,247,139,162,171,64,251,79,190,180,190,186,29,110,165,88,119,225,30,58,64,49,68,45,83,93,122,136,199,146,158,106,5,211,222,64,64,160,74,72,185,138,112,186,135,133,95,31,236,77,86,54,59,235,32,245,245,133,152,27,233,115,154,253,233,222,36,218,216,218,211,137,127,103,199,95,165,151,234,33,228,72,167,103,13,43,119,38,71,23,218,227,177,230,222,214,149,81,102,246,94,251,84,233,90,116,77,26,118,194,122,55,75,208,137,52,159,238,73,8,33,157,218,178,213,108,45,131,207,210,31,144,133,204,239,144,183,230,251,195,57,195,154,39,61,36,39,117,126,121,69,224,198,15,198,98,59,82,181,202,28,149,49,219,53,48,163,19,164,57,251,219,61,159,235,12,121,100,151,160,191,93,194,90,22,119,28,191,219,210,170,234,145,2,111,53,86,140,171,46,232,231,111,18,43,83,2,142,131,38,36,99,174,3,26,169,105,31,214,250,212,191,8,1,141,69,73,158,180,248,93,117,146,242,10,188,63,7,61,149,69,118,161,141,117,25,193,18,187,220,194,82,13,30,5,225,194,158,252,56,159,129,5,240,0,213,85,67,54,209,242,151,41,141,172,187,12,215,255,6,5,126,185,11,225,35,202,5,182,98,154,26,217,237,193,140,136,38,71,118,166,44,17,223,179,101,97,16,153,33,21,204,15,219,189,120,219,24,117,23,4,153,22,143,40,174,238,185,27,159,69,251,1,227,108,218,69,111,198,184,236,14,216,136,208,115,154,211,47,149,116,98,114,40,90,83,116,92,109,38,134,140,104,157,197,116,57,122,111,5,224,4,175,201,244,62,210,203,188,216,230,131,214,184,164,54,48,242,179,251,201,77,16,77,13,77,23,34,66,146,24,12,187,238,151,92,139,64,114,217,125,244,175,10,155,138,118,58,245,52,121,17,241,62,231,105,214,169,120,184,4,155,16,20,12,215,206,40,237,161,186,68,63,141,166,178,6,127,126,151,70,195,245,163,96,91,23,138,173,211,99,103,164,14,51,246,20,75,76,135,150,74,215,220,71,15,76,77,215,250,38,227,176,76,17,15,179,232,18,19,165,54,194,146,187,110,158,216,55,66,145,232,119,152,61,63,121,155,194,202,244,22,81,66,36,140,38,108,209,21,139,25,159,255,185,60,117,9,245,95,46,99,220,27,61,151,235,253,38,161,64,188,88,189,117,249,42,176,56,54,107,62,80,240,135,153,86,180,137,121,111,177,208,196,3,194,236,106,173,82,40,195,1,146,180,204,141,11,192,120,252,52,4,116,199,14,254,104,216,4,219,7,221,233,33,47,34,247,94,0,104,240,54,18,128,85,240,255,179,195,197,161,240,178,242,197,103,68,166,60,95,131,245,148,198,163,124,209,39,120,42,206,15,106,91,118,113,89,19,66,66,241,200,64,65,37,82,169,139,136,203,234,192,172,175,27,160,244,10,91,4,183,109,177,183,93,233,92,26,227,67,87,232,184,97,234,202,240,80,213,42,133,15,68,206,0,206,110,170,227,223,113,90,208,60,11,93,245,151,50,51,86,152,199,229,35,248,13,119,64,238,165,152,108,70,48,149,157,110,249,189,25,187,246,251,124,64,0,176,165,128,174,39,200,94,100,193,34,233,19,192,83,39,177,228,74,234,195,128,251,203,238,192,16,66,200,223,179,30,106,195,189,26,217,157,142,161,132,38,20,179,217,79,34,97,189,231,106,19,144,223,172,39,206,91,192,115,254,111,141,170,103,121,61,72,101,60,110,173,73,193,25,89,206,122,137,151,213,60,169,7,42,226,224,249,190,43,17,190,187,240,163,77,26,192,162,70,170,154,216,20,183,212,229,81,56,157,247,123,219,168,91,21,53,107,174,135,98,32,176,146,78,98,190,30,232,190,171,107,188,254,223,5,25,58,134,150,36,28,218,134,107,40,253,245,199,11,1,191,26,173,238,5,142,204,170,161,157,127,172,254,27,185,235,87,15,3,74,170,36,195,132,163,3,126,33,178,173,141,106,23,111,96,111,124,164,68,230,2,210,18,190,148,45,70,148,194,38,160,67,130,166,172,81,5,91,142,239,190,58,3,102,81,212,68,68,73,134,6,117,116,100,47,57,100,207,232,224,125,32,30,193,162,117,36,57,8,27,203,56,199,110,251,56,35,162,240,157,224,0,42,206,199,201,33,95,5,127,132,29,178,152,101,166,1,242,99,155,248,47,71,180,75,84,99,65,91,32,31,136,206,52,48,74,184,208,83,85,179,51,105,125,87,66,145,207,127,71,239,255,157,126,120,139,232,35,64,70,128,118,191,41,217,7,185,86,117,216,187,163,194,206,174,218,56,214,58,160,248,111,154,70,17,108,212,91,199,245,32,108,125,43,198,192,38,68,101,100,147,129,87,52,240,50,91,92,218,108,127,101,155,228,123,77,147,41,86,207,159,139,140,93,22,169,163,63,89,236,154,98,131,93,39,55,237,122,107,6,174,184,202,126,27,199,141,16,52,167,250,44,52,64,134,244,66,235,39,127,190,88,127,61,105,107,157,35,59,146,10,14,155,241,227,170,104,180,47,95,20,235,236,196,100,29,66,255,252,236,249,128,214,5,234,40,241,34,234,45,47,166,217,121,36,243,35,251,23,126,3,133,136,164,113,22,69,236,180,239,139,48,255,146,161,48,135,129,150,245,193,181,210,85,120,4,249,147,174,66,17,136,154,208,148,214,82,198,29,171,4,223,212,84,104,93,95,153,151,59,52,212,150,113,85,179,189,60,151,118,28,93,220,49,114,124,228,164,99,165,40,1,5,200,121,138,132,77,15,5,21,162,216,252,37,141,224,202,125,209,225,242,62,177,195,93,254,238,77,226,148,168,119,167,195,151,180,25,60,215,48,166,94,44,45,114,159,78,24,155,132,119,38,31,231,227,51,37,35,33,239,40,171,12,250,68,190,248,231,228,59,213,61,15,65,53,179,92,176,23,172,176,32,72,135,37,241,24,107,242,184,186,57,99,239,241,14,0,114,211,202,79,176,88,52,130,56,18,75,55,22,208,79,100,1,57,105,53,174,100,13,234,232,158,118,211,9,144,128,160,76,177,166,10,90,95,110,144,254,243,190,208,135,184,198,226,200,27,9,38,241,0,208,210,237,180,2,22,149,157,19,155,249,21,3,55,195,149,105,206,24,110,148,19,249,58,78,186,176,25,100,216,4,198,194,104,71,150,103,193,54,223,28,146,80,51,157,194,14,178,180,189,161,192,44,225,168,111,47,225,151,43,100,26,191,125,146,222,221,199,216,186,126,173,89,90,229,77,60,34,228,75,219,182,85,232,170,22,24,130,197,101,20,253,116,141,176,241,34,223,208,190,53,49,201,93,144,151,241,108,236,120,86,232,128,234,238,83,111,80,172,96,67,34,128,6,29,10,136,122,7,204,83,50,186,1,23,79,169,21,92,114,15,132,236,51,188,123,139,240,236,199,67,208,132,52,13,194,187,174,29,120,140,151,198,252,88,147,102,219,35,162,73,126,98,77,213,8,169,217,193,210,100,239,19,153,49,43,252,194,75,228,65,143,184,39,77,42,202,171,40,113,137,164,157,33,120,131,63,197,218,5,250,238,192,175,128,92,206,161,173,254,238,133,100,158,136,16,101,127,238,52,208,92,82,3,217,66,93,246,228,193,254,74,72,78,122,33,105,54,8,66,93,246,194,222,27,194,33,125,31,125,186,243,13,92,218,44,36,132,226,180,89,124,205,104,135,159,122,252,15,162,223,62,10,250,171,0,131,127,85,178,231,79,207,40,253,46,196,118,242,128,72,35,191,117,82,21,59,50,253,123,77,220,143,104,20,203,224,176,13,252,32,28,67,43,91,75,244,94,186,135,19,180,199,223,127,142,98,37,239,28,103,87,65,235,18,238,103,120,238,30,86,59,98,172,2,220,161,99,43,3,209,122,161,55,146,255,1,36,249,99,184,3,3,168,72,232,46,73,223,106,79,159,210,38,156,147,51,126,50,165,108,52,49,96,42,238,80,99,70,146,206,224,54,97,97,16,213,14,248,251,126,49,66,87,134,179,227,232,143,91,185,125,0,158,183,5,242,48,7,152,160,171,198,163,34,181,199,170,68,125,93,97,109,136,230,150,33,113,56,104,7,226,175,49,100,51,84,213,22,135,7,237,200,148,72,116,142,163,153,122,86,4,164,15,210,118,24,67,210,223,220,137,144,48,144,180,185,234,2,241,154,213,43,109,156,143,172,26,128,135,231,119,24,217,131,61,148,77,141,150,92,115,120,2,154,217,75,86,241,208,171,108,103,82,89,209,129,238,172,132,255,207,27,146,164,74,184,68,92,141,13,124,214,138,185,244,149,236,189,182,103,67,87,10,32,216,220,143,80,210,206,245,104,149,139,20,55,5,113,172,207,125,29,89,249,19,112,108,14,88,182,201,165,18,10,245,121,6,178,148,34,12,59,196,61,173,239,178,241,33,155,25,242,134,32,227,233,188,135,113,163,52,64,251,178,224,118,246,79,167,5,63,212,177,112,180,80,242,169,49,210,21,134,141,17,157,190,91,64,227,91,38,133,159,225,105,247,226,195,200,172,31,220,215,170,68,107,20,234,183,178,143,56,158,107,86,223,172,215,193,84,10,65,89,99,158,61,203,224,96,108,213,54,164,149,13,125,118,120,95,189,114,57,41,211,241,237,209,190,6,62,79,184,242,245,149,195,91,85,198,131,178,227,71,202,112,154,51,82,29,130,223,121,113,6,199,251,129,30,201,68,187,181,197,35,52,79,104,12,235,40,127,72,62,197,101,25,50,235,135,22,61,18,204,9,17,58,139,193,112,118,161,34,157,65,113,190,135,176,140,117,20,216,176,111,50,116,217,162,214,180,80,45,31,21,53,93,2,228,123,100,207,17,230,207,97,240,183,85,31,41,46,45,3,43,72,155,187,165,203,128,67,28,120,236,54,20,65,238,109,110,179,222,136,198,17,77,149,130,251,103,177,204,150,184,189,37,5,55,241,217,14,130,255,116,126,175,235,144,116,140,66,14,51,205,67,99,220,51,208,79,206,154,127,22,85,71,77,215,145,255,44,243,64,209,227,67,73,110,151,218,87,197,55,237,118,245,39,169,244,170,245,203,108,245,142,50,189,176,80,21,202,93,146,1,53,148,177,158,56,213,31,235,149,163,76,7,160,96,185,175,209,247,27,135,158,217,147,16,10,240,197,137,20,206,239,82,56,27,22,220,198,2,89,79,127,31,142,1,6,55,182,200,142,137,107,201,174,111,181,210,207,62,30,104,243,208,79,121,233,86,23,51,192,246,38,237,63,185,68,166,75,123,229,116,251,234,207,59,122,231,68,113,211,62,70,25,143,151,209,232,208,160,147,131,216,54,242,90,239,63,40,144,174,63,16,36,202,26,114,183,89,217,89,136,230,91,48,252,125,202,164,150,89,145,56,123,247,12,54,155,187,186,61,40,196,208,28,136,119,101,36,210,226,52,175,235,200,109,39,72,109,208,243,138,191,212,112,241,255,140,84,135,41,149,18,74,71,117,169,225,47,36,251,47,104,143,61,234,88,50,148,255,119,218,157,33,205,193,198,233,229,11,62,162,92,119,220,137,255,123,184,226,35,157,8,174,39,63,216,248,137,225,131,8,2,82,204,80,214,39,91,209,189,161,6,81,144,36,198,76,197,109,194,10,4,72,54,53,184,115,91,225,10,11,168,200,46,218,124,246,135,15,89,53,166,8,241,71,83,123,154,209,50,174,37,55,123,83,140,20,54,44,56,182,163,26,6,6,190,38,53,147,232,222,149,68,107,255,157,252,151,137,92,252,145,148,33,103,9,72,231,13,116,195,38,2,23,236,159,143,19,6,218,213,124,179,244,182,30,110,173,19,168,90,131,57,252,205,106,250,34,115,21,156,227,2,178,233,51,164,166,165,72,112,14,41,93,38,111,111,37,191,106,207,33,185,185,90,72,233,134,236,98,171,160,112,169,40,190,94,93,171,234,98,137,93,127,65,248,80,186,131,116,191,197,63,31,50,255,195,58,34,142,54,220,246,198,63,55,183,44,126,0,217,209,232,158,8,7,110,86,107,240,61,28,52,138,97,149,20,247,180,192,143,33,83,155,177,22,187,216,48,139,83,169,139,99,123,154,74,125,236,38,59,46,27,30,157,211,15,232,203,47,94,136,56,194,51,139,205,174,21,161,217,7,160,227,59,236,156,91,143,154,27,42,117,22,168,18,246,201,35,37,107,157,58,5,158,76,100,112,62,84,117,50,22,6,96,111,120,207,116,151,161,13,67,239,116,206,98,64,136,103,8,201,197,9,81,239,18,226,93,190,46,81,229,232,167,200,193,215,90,182,212,93,78,67,26,105,97,197,49,164,150,52,143,248,121,13,95,217,227,206,14,80,200,179,171,10,146,200,142,90,137,125,253,146,71,131,33,45,48,69,241,119,153,254,188,241,25,222,97,30,63,46,136,159,57,134,89,0,129,234,189,184,64,200,208,245,48,167,116,134,99,230,3,164,217,19,159,106,99,97,202,22,164,70,66,13,97,32,58,239,114,37,9,60,59,67,157,37,172,251,50,177,13,116,63,7,119,74,90,248,108,175,187,95,134,112,101,157,132,160,143,70,245,232,144,69,184,106,150,9,184,122,224,32,162,162,167,166,203,10,237,99,78,75,217,159,250,237,184,75,97,163,68,55,215,93,14,236,225,12,141,49,8,40,126,117,77,135,80,77,205,97,75,21,26,145,221,123,172,2,182,77,86,93,204,86,114,144,92,13,141,25,97,222,15,100,182,160,159,142,35,220,49,107,187,208,137,105,153,135,0,174,222,172,239,170,133,207,178,208,164,230,211,2,139,92,32,192,133,89,232,32,239,245,110,166,136,37,21,196,131,79,242,98,209,25,180,252,102,119,100,85,102,115,189,106,122,226,157,178,221,143,154,92,187,57,68,241,18,33,225,250,134,114,116,72,134,250,27,40,97,219,30,86,74,184,102,193,26,66,181,24,165,153,255,190,75,185,18,121,114,85,220,59,224,145,174,176,36,67,144,74,196,161,88,9,48,79,220,4,67,25,232,105,176,32,242,28,201,66,116,178,36,164,218,208,31,240,68,239,166,138,242,198,226,27,136,232,255,174,210,152,60,200,61,15,238,2,218,231,198,130,236,180,235,65,221,66,82,162,92,235,251,20,38,65,92,156,106,85,0,144,25,182,28,226,88,153,34,253,19,27,116,90,101,248,35,202,216,184,19,35,2,94,8,209,254,66,212,135,68,219,185,32,107,225,25,227,136,211,138,181,174,112,128,190,66,165,251,135,185,108,40,159,222,177,26,58,26,148,218,89,13,15,27,236,24,118,78,33,185,174,168,219,230,119,230,179,169,161,57,118,97,227,203,9,125,55,136,197,112,94,138,136,230,112,204,245,136,116,59,13,75,68,121,43,122,9,22,252,149,172,182,118,113,61,53,171,44,42,118,178,166,69,222,44,157,34,128,126,179,24,154,159,106,149,17,227,58,143,176,241,222,56,42,62,181,26,208,33,24,30,33,112,83,127,84,65,41,251,206,115,178,2,222,106,153,209,238,98,208,200,210,177,133,86,65,23,104,110,177,161,96,79,57,142,162,15,207,173,153,56,254,250,73,76,74,43,36,200,57,145,60,95,227,21,147,221,41,171,192,107,234,251,74,126,3,247,128,122,243,153,128,202,238,189,17,198,179,70,97,245,190,200,231,176,186,98,217,254,45,230,228,185,78,204,155,64,247,183,255,152,161,26,12,21,183,209,199,194,177,1,221,95,77,76,253,203,104,7,192,167,209,180,50,138,227,189,182,231,239,238,168,59,221,119,154,107,247,102,200,51,40,120,192,133,47,249,238,189,123,233,117,188,210,82,68,72,178,111,103,77,144,205,181,97,1,172,166,152,242,0,187,181,174,188,39,82,5,75,21,213,113,66,102,62,173,169,132,21,120,138,226,211,39,44,143,160,126,74,108,191,13,117,58,148,234,239,194,161,161,156,231,240,170,77,120,106,63,168,175,231,243,60,192,181,236,20,52,239,78,141,78,130,59,219,80,208,24,37,165,109,209,49,251,9,62,80,50,249,181,232,42,228,47,166,191,144,176,206,148,242,148,153,182,121,24,128,65,137,42,161,119,66,94,240,11,55,102,122,7,205,142,144,144,180,47,60,218,192,149,85,15,213,83,8,79,215,104,8,209,172,222,200,242,28,255,51,185,167,33,226,26,65,147,100,114,222,54,27,170,212,207,83,56,170,37,126,121,14,18,40,231,4,14,164,248,6,110,118,48,51,83,228,76,3,131,87,77,86,163,48,72,194,109,53,105,118,111,198,140,133,34,20,119,56,35,236,7,170,176,164,95,86,183,232,105,108,7,25,169,127,50,26,86,83,94,101,58,219,72,205,46,231,78,158,94,221,190,147,92,96,224,0,30,65,191,21,237,118,106,224,247,161,116,33,41,10,92,81,248,232,191,41,72,116,171,89,110,208,62,230,196,11,67,172,81,188,8,212,62,255,199,22,201,68,20,120,21,90,72,70,211,251,61,232,5,238,147,16,91,225,65,103,178,238,63,246,157,100,192,170,206,249,101,28,25,120,125,225,94,105,146,218,75,10,178,103,244,73,77,174,18,113,205,198,233,5,88,129,66,64,72,137,118,81,217,130,206,156,174,224,223,115,249,164,10,160,47,237,255,135,146,236,13,99,71,63,62,20,134,132,135,155,27,21,239,159,60,195,224,248,123,205,45,147,225,233,72,95,151,236,249,144,43,148,51,197,175,100,140,185,170,200,234,37,87,113,85,41,197,41,164,33,181,64,228,58,125,41,220,43,111,47,37,139,69,75,126,166,210,12,7,175,6,63,122,236,237,156,149,142,254,174,11,37,215,82,200,54,62,74,43,2,249,172,218,115,203,91,14,165,110,103,178,200,5,226,141,45,42,68,130,198,173,253,230,217,122,113,39,163,182,160,231,100,179,40,207,8,27,212,22,174,85,58,27,55,118,83,118,244,201,68,167,205,50,31,36,17,250,228,187,200,203,159,109,44,83,197,240,214,82,128,207,62,237,127,108,238,226,36,190,44,152,27,248,90,79,254,43,191,182,206,138,179,239,133,27,56,192,25,166,40,83,172,241,62,178,172,53,58,205,73,6,139,66,50,24,22,193,232,205,173,161,67,139,236,13,114,239,156,46,253,12,218,238,6,255,169,98,117,8,215,156,102,178,212,208,18,175,147,108,96,73,71,115,87,75,254,77,61,212,49,252,42,72,23,95,49,206,208,189,203,240,139,4,56,101,109,139,204,117,23,213,104,47,1,254,115,179,25,96,58,221,157,53,112,19,110,172,118,168,11,21,171,109,123,100,79,124,202,172,155,236,144,86,224,44,183,119,167,51,180,139,191,76,201,173,212,215,120,148,255,149,110,69,229,152,112,197,133,178,122,15,23,55,103,67,13,152,239,59,168,53,175,130,232,143,236,0,96,95,206,91,141,167,127,199,149,82,51,222,51,43,148,225,183,56,32,68,76,97,35,154,233,207,47,2,29,114,143,36,159,81,168,169,22,163,74,208,233,149,204,129,138,138,13,48,180,42,41,155,141,156,228,19,71,135,137,63,119,146,67,61,236,133,52,209,164,39,67,110,28,5,36,100,159,52,79,220,118,89,126,230,63,180,117,243,165,179,147,209,255,162,97,177,43,45,86,56,48,223,195,122,39,130,118,8,183,36,55,42,221,83,72,74,95,130,91,23,121,226,221,206,241,204,44,105,177,188,105,190,84,106,225,244,183,44,76,188,169,150,98,155,208,244,161,94,75,232,173,64,126,153,184,124,75,229,87,31,209,154,93,125,64,53,167,155,250,167,122,169,184,231,14,34,61,208,47,179,182,194,37,87,240,10,125,2,26,125,232,189,207,199,3,153,204,157,148,33,93,160,134,67,238,203,126,198,203,210,112,25,199,23,136,192,135,207,227,224,213,125,17,93,230,177,178,164,152,162,80,107,50,52,221,42,20,128,143,202,168,22,91,223,159,118,214,249,29,184,124,24,124,1,183,54,43,61,91,155,116,241,94,157,187,60,100,244,97,97,177,9,57,90,72,245,38,31,86,172,41,102,15,35,39,4,233,141,9,165,41,137,229,44,122,16,181,99,178,84,124,207,34,140,41,145,250,172,186,100,100,156,162,5,126,187,160,57,183,240,17,46,181,44,120,144,141,151,142,129,195,192,11,203,241,78,134,142,214,106,198,94,141,84,62,51,127,110,9,65,150,68,221,157,131,236,130,114,10,128,197,13,157,252,8,165,223,138,108,179,156,231,156,82,132,196,202,13,64,69,92,110,180,238,15,125,240,30,231,134,56,66,31,193,191,100,72,106,233,11,113,8,121,238,178,117,107,157,215,58,43,212,236,53,215,214,1,16,192,173,175,231,62,113,26,94,248,47,30,36,232,160,227,75,161,127,33,5,192,210,69,155,249,190,217,224,42,17,77,54,231,20,45,5,116,154,154,80,74,148,126,85,137,13,59,123,226,167,20,148,24,19,123,17,78,46,126,232,255,147,20,83,85,103,16,86,141,246,211,162,58,245,162,77,31,51,40,174,164,117,38,201,18,8,240,124,226,180,213,190,92,223,249,184,227,8,168,86,142,19,66,247,142,54,135,218,13,197,216,225,152,61,155,156,171,88,150,158,129,132,144,138,13,21,166,17,156,62,40,147,131,134,66,228,77,177,184,53,207,92,208,3,16,2,45,215,154,73,196,92,47,104,0,94,23,103,132,206,81,105,63,84,231,7,205,95,148,128,250,142,158,42,49,223,26,22,72,27,211,39,245,201,245,4,127,48,221,21,121,201,223,108,209,6,93,31,85,112,207,74,123,201,78,249,139,38,60,134,47,225,21,74,31,177,146,41,144,16,100,28,219,207,21,104,154,200,135,169,238,147,227,243,217,211,187,109,182,74,223,148,201,132,46,26,159,121,196,145,148,161,153,126,127,103,44,44,215,135,248,8,157,23,184,220,82,173,81,229,136,173,243,230,69,68,158,137,156,73,166,209,116,155,166,231,141,186,187,84,175,227,63,227,13,18,245,222,185,2,9,97,179,58,174,246,67,94,255,153,44,100,138,172,19,5,67,221,82,20,224,61,104,222,44,53,106,82,147,130,225,31,218,140,64,109,45,5,216,165,119,100,159,228,18,213,150,192,59,85,135,249,36,228,230,57,28,67,206,105,230,148,212,28,106,92,97,2,31,152,107,208,11,10,205,238,102,126,66,83,190,233,77,232,77,96,85,249,251,119,192,179,5,0,198,67,127,22,157,78,146,64,204,6,39,200,12,229,227,234,242,193,195,141,125,107,248,143,210,251,18,220,67,240,110,48,114,110,15,160,241,14,133,152,132,225,44,134,92,88,11,167,164,225,12,234,164,92,9,175,74,190,164,193,157,232,4,137,216,80,165,124,20,254,221,2,198,63,217,156,135,119,4,178,58,153,215,139,67,52,172,206,47,40,75,33,86,67,63,41,10,20,37,237,37,156,4,13,25,23,201,228,9,237,67,16,22,116,17,184,162,203,188,227,13,110,65,231,79,200,61,118,207,68,161,90,71,47,113,31,224,165,90,23,21,239,63,80,176,54,103,99,60,125,72,207,90,110,231,121,225,205,35,28,16,137,252,136,94,179,14,97,157,227,66,82,219,137,26,78,157,181,147,28,161,251,43,196,201,53,245,149,152,194,86,91,70,203,91,114,199,241,212,180,125,44,131,135,116,26,132,69,27,84,222,132,88,96,163,119,62,129,249,230,33,147,28,124,23,172,231,132,144,182,235,125,193,70,233,206,77,27,210,203,223,213,95,105,230,117,205,214,164,126,23,240,10,34,237,211,43,162,138,230,118,192,86,247,125,167,215,62,26,113,209,175,19,231,246,167,150,22,44,69,31,236,205,198,210,214,123,93,60,9,175,131,96,145,71,92,190,209,201,225,103,43,204,242,98,253,129,95,56,223,107,29,87,165,180,44,49,28,37,42,83,215,122,91,126,77,38,243,71,213,191,223,14,76,247,97,110,190,120,147,167,234,237,10,98,148,45,218,3,23,117,15,148,142,173,118,236,90,31,27,85,54,188,202,253,43,102,109,130,17,8,239,241,89,212,14,29,172,179,90,8,104,5,203,117,188,43,184,167,54,8,100,136,17,55,201,102,193,221,245,173,86,65,162,176,40,92,214,101,18,82,59,131,63,156,187,219,65,190,115,172,242,52,181,80,109,165,136,98,148,149,152,234,86,143,132,100,239,159,119,163,250,30,130,119,190,45,58,208,104,161,144,10,202,200,31,177,215,242,236,78,3,151,34,8,16,172,231,112,71,159,168,32,208,230,50,84,234,214,40,92,65,60,148,117,76,216,111,91,121,177,66,86,123,55,54,126,46,118,241,103,105,245,89,242,0,0,166,87,7,145,164,227,90,30,10,4,88,64,114,70,127,14,161,218,198,16,35,230,115,54,65,108,190,175,186,252,79,33,24,82,118,130,249,181,253,61,28,154,77,227,209,111,63,61,68,223,162,41,90,176,37,114,169,199,77,160,219,199,22,79,240,212,158,243,217,226,74,158,215,193,166,204,82,135,0,106,12,155,150,113,241,197,33,205,6,16,19,118,164,194,115,243,112,162,251,134,203,122,124,61,242,68,140,200,131,168,172,123,48,70,132,227,199,3,196,130,48,55,231,64,216,195,86,36,160,233,137,145,108,224,93,218,61,107,191,138,171,13,215,212,65,223,117,85,120,109,207,141,12,23,221,175,68,130,129,185,138,67,225,85,127,85,215,75,146,79,69,133,10,129,210,51,71,147,116,11,104,76,194,87,78,137,12,108,185,53,10,210,35,135,33,203,224,96,175,47,98,138,83,60,163,16,100,51,21,186,245,7,153,128,164,73,27,189,195,13,61,255,96,12,174,169,37,39,235,177,224,137,71,128,240,63,137,238,255,68,185,212,135,190,156,240,184,158,113,210,241,119,224,63,177,236,63,172,135,117,74,27,187,227,253,246,222,134,197,251,197,243,107,188,160,85,252,111,4,141,195,243,91,73,226,144,131,109,136,10,172,209,186,95,172,96,107,43,22,44,176,226,122,100,50,28,65,163,62,235,88,16,254,97,48,250,64,155,101,21,83,64,255,189,98,142,60,20,184,3,54,87,20,50,178,254,138,105,53,169,141,5,88,57,244,207,138,191,208,185,54,87,134,70,182,197,77,248,201,118,133,148,231,106,241,215,91,61,184,61,250,9,140,91,66,203,141,93,171,166,65,183,29,234,196,85,230,194,177,148,240,126,71,14,92,212,2,120,179,141,11,42,166,15,45,196,187,30,249,247,104,244,5,25,126,208,252,253,157,224,36,138,145,222,221,213,15,204,112,217,50,193,215,194,2,248,214,48,43,229,7,204,79,218,223,82,137,114,228,41,220,68,157,35,245,242,213,255,141,189,192,243,63,72,119,222,107,252,230,192,211,47,186,209,144,213,221,185,22,152,208,54,130,76,100,242,54,210,211,40,29,189,40,7,183,252,209,130,240,76,107,14,110,35,151,57,0,187,180,78,210,153,198,18,212,33,205,72,211,89,150,175,136,7,138,13,18,93,226,93,52,171,126,188,165,113,29,15,231,234,11,67,54,164,115,158,58,48,20,202,65,198,247,224,202,190,45,10,153,146,148,150,218,67,157,27,190,197,15,182,135,56,130,43,203,209,174,134,100,81,179,58,182,229,1,155,224,135,148,214,99,38,92,212,220,49,17,170,248,161,123,88,92,5,119,19,210,149,12,254,121,21,140,38,10,247,25,4,22,186,68,1,211,221,109,182,103,137,4,242,129,66,67,138,61,50,131,83,208,81,53,132,36,86,63,33,62,142,250,210,195,68,246,210,84,77,150,182,48,140,129,1,24,195,122,107,160,22,129,227,250,27,102,21,127,52,229,47,19,58,21,47,132,85,233,11,183,119,3,54,223,94,30,168,153,3,202,62,170,29,46,235,105,186,122,192,71,128,73,149,47,98,46,122,34,64,101,76,177,160,154,47,174,96,118,108,73,203,121,15,19,101,72,99,177,70,118,219,124,182,128,41,154,76,22,204,166,120,224,174,35,27,29,63,8,248,217,183,247,192,11,141,178,28,4,184,73,111,64,221,65,220,21,145,34,163,79,94,28,225,40,146,182,182,2,244,18,250,136,64,65,3,121,52,149,19,150,105,221,244,244,247,77,249,155,100,216,128,178,170,122,153,140,221,2,88,211,227,255,108,191,91,6,185,100,148,31,75,245,179,229,46,107,30,214,20,93,198,142,86,108,83,131,235,38,107,38,203,229,248,160,22,216,41,215,22,55,59,211,156,38,76,79,202,176,49,88,161,162,206,46,81,83,200,99,138,117,40,110,2,84,142,165,212,63,185,183,35,165,96,218,110,177,40,36,21,19,181,76,171,145,175,144,249,115,42,97,99,152,49,128,122,54,8,136,236,196,46,137,181,211,218,83,112,177,64,193,136,89,220,176,221,204,172,174,154,77,96,166,191,132,59,141,90,169,6,46,45,84,193,160,209,49,6,199,255,3,129,73,146,92,31,226,30,164,12,7,148,241,217,3,113,226,199,81,146,95,141,45,176,205,253,233,128,78,74,123,244,138,154,234,99,11,241,18,251,174,123,196,122,254,82,210,2,90,216,87,97,38,253,160,197,255,134,152,168,162,17,72,133,41,122,235,85,154,133,172,162,240,103,107,149,216,192,182,55,27,163,94,52,129,61,154,61,11,135,223,222,154,217,53,135,124,181,120,2,41,107,239,28,32,232,45,27,51,86,176,14,7,40,249,170,100,67,101,131,23,151,200,74,151,82,184,146,40,7,64,240,146,253,80,218,150,108,16,186,224,225,98,8,166,177,252,0,35,95,107,137,80,130,116,129,161,149,37,52,149,240,167,11,50,129,134,80,126,16,233,201,206,97,186,68,205,245,254,241,139,20,5,89,162,39,98,188,107,186,119,233,101,250,245,150,241,120,191,39,29,12,121,31,198,242,252,230,85,160,112,172,171,128,29,103,65,246,39,126,74,92,140,142,56,181,82,101,195,59,71,4,8,9,42,98,180,136,41,26,56,252,4,230,102,239,251,161,183,106,22,54,238,250,59,61,243,9,189,77,195,254,119,234,124,186,211,5,26,88,176,159,87,101,242,100,179,102,218,39,85,82,118,109,146,144,225,73,28,78,77,189,135,29,192,12,95,153,113,248,50,171,113,241,189,121,194,155,247,109,70,124,72,61,27,79,56,185,218,51,155,130,98,183,1,100,60,85,55,160,158,110,41,58,63,216,176,49,228,195,87,118,254,105,223,41,138,84,41,78,214,111,49,206,175,91,190,57,25,68,120,22,127,85,81,202,226,197,123,156,169,249,12,182,148,31,115,211,146,41,208,248,249,197,188,103,47,138,8,117,43,130,28,28,102,44,149,38,221,176,211,11,76,148,186,176,252,87,62,69,3,88,80,123,168,196,245,128,224,186,224,99,220,46,237,181,88,159,161,175,204,237,160,154,13,131,12,99,88,171,231,111,242,238,194,193,15,3,254,152,148,114,131,215,216,106,245,73,197,176,147,149,25,185,200,252,52,225,236,86,240,34,22,76,102,243,132,148,11,204,125,58,185,37,184,188,4,169,89,249,104,232,254,3,96,102,68,177,242,8,251,188,177,100,48,1,248,177,185,181,108,161,130,117,35,229,28,94,131,105,31,242,158,200,167,63,124,21,55,142,139,10,202,5,82,209,8,37,48,22,47,237,174,182,254,11,32,46,255,142,78,113,207,192,187,172,174,16,156,90,26,138,142,57,129,2,59,148,175,197,194,242,205,81,57,214,199,206,60,204,225,254,113,28,148,222,242,209,101,104,98,108,237,223,49,114,212,129,78,146,78,208,40,162,230,188,127,198,195,47,15,146,82,173,159,186,217,133,148,237,194,5,33,102,245,90,65,8,165,35,12,231,205,62,97,232,36,7,127,30,119,233,149,99,221,178,173,102,226,168,250,196,60,181,5,125,126,243,158,64,110,37,30,195,162,229,136,241,198,229,105,88,85,49,14,96,84,216,55,253,53,92,172,24,38,54,35,37,50,118,149,84,244,199,203,56,87,218,44,100,7,25,135,147,55,101,115,200,99,37,8,239,72,221,30,76,8,86,146,55,44,91,241,31,111,230,90,185,168,144,245,50,43,46,238,33,229,223,34,244,14,118,219,103,141,110,249,21,49,255,202,251,214,126,66,144,34,95,94,195,240,131,109,100,123,73,158,69,82,217,206,59,169,190,31,185,211,83,88,73,74,185,229,228,147,57,21,198,39,234,143,84,167,170,144,247,206,56,43,55,104,193,157,220,89,125,173,151,17,4,10,18,124,244,41,133,194,59,11,202,98,174,212,26,19,95,71,26,82,242,133,85,125,4,131,36,108,37,250,255,99,63,15,53,173,129,255,175,83,105,132,142,35,4,243,133,67,237,220,88,25,169,219,83,229,33,83,46,251,0,111,226,87,41,226,98,245,208,93,251,94,207,210,41,146,56,119,137,32,0,61,212,6,161,219,144,112,202,88,124,132,83,197,240,185,196,152,34,202,136,59,198,165,5,136,11,246,158,60,3,176,105,203,207,70,162,187,45,160,39,60,82,115,113,239,37,166,188,235,215,222,227,65,73,188,70,178,98,215,247,7,12,10,4,216,139,202,178,125,231,103,79,61,127,58,10,202,75,42,107,139,214,172,4,14,3,23,73,247,52,158,78,61,218,235,79,191,182,70,127,157,34,208,242,177,248,153,110,42,50,168,186,212,159,202,174,245,161,60,197,47,221,200,111,195,231,35,136,145,196,62,119,52,247,41,50,41,64,94,231,136,149,213,174,127,157,61,143,47,166,152,59,245,186,16,70,32,201,49,239,157,90,225,122,138,88,158,93,59,121,246,69,151,25,182,189,199,100,74,131,123,99,103,185,138,240,169,255,83,8,240,13,159,156,5,223,181,247,243,244,179,90,207,159,36,69,34,174,29,39,12,198,108,220,130,2,10,203,188,206,67,116,209,27,67,170,198,93,113,250,14,198,254,196,37,146,198,0,245,162,19,196,105,30,136,94,211,48,61,213,53,160,236,102,140,240,236,1,246,124,73,73,184,88,243,157,125,154,77,39,104,111,1,205,78,22,233,44,37,253,92,198,51,8,211,150,43,192,106,122,208,21,123,140,14,148,222,144,217,194,15,242,120,80,45,66,71,74,147,132,37,185,45,165,41,76,166,143,130,134,3,4,15,104,214,102,179,162,238,195,200,235,20,223,172,249,110,37,43,216,136,128,232,235,48,215,2,250,173,82,109,146,30,125,217,231,73,206,65,2,40,45,35,163,248,230,102,19,67,102,0,76,64,7,130,23,167,105,28,152,26,73,234,15,36,35,231,146,205,50,217,164,199,154,192,15,19,80,26,30,181,14,197,12,131,88,61,140,86,85,233,182,210,78,143,77,63,177,30,176,10,224,14,137,130,162,84,191,108,227,75,85,115,237,159,119,222,168,131,18,13,22,92,110,176,134,71,180,31,116,154,111,4,116,74,59,2,191,75,114,181,184,238,106,236,202,251,63,247,48,35,155,172,61,122,174,26,38,3,176,42,15,71,195,153,55,66,191,33,169,177,220,36,95,177,66,86,173,31,180,219,166,178,139,120,139,67,88,25,238,233,169,169,111,163,217,54,29,44,34,138,236,199,35,50,82,214,30,125,91,25,222,65,137,125,96,232,78,167,209,68,71,70,1,22,163,34,202,200,71,113,235,157,41,14,32,110,171,235,197,174,10,51,158,251,44,98,199,201,196,168,50,201,99,205,245,153,75,169,17,143,154,52,222,138,28,173,86,92,134,115,136,220,131,85,171,122,218,117,190,117,143,79,26,121,10,50,45,80,241,33,4,253,140,1,159,201,105,123,35,133,81,59,236,16,238,109,215,10,124,211,64,112,180,147,203,106,142,69,97,205,162,177,217,151,174,189,239,69,50,30,166,238,219,120,79,225,197,121,127,91,215,89,102,17,39,158,213,94,164,254,49,125,216,191,222,90,38,224,214,242,60,2,38,241,139,218,34,185,186,30,206,33,43,38,242,81,191,12,1,200,96,167,125,197,194,127,129,244,184,30,74,74,196,174,229,224,226,124,52,137,122,146,108,187,169,127,72,111,131,243,79,149,236,134,103,137,212,161,44,61,183,188,103,150,96,95,88,187,167,31,213,185,63,128,70,10,58,47,69,155,112,231,242,129,19,78,116,74,152,85,44,128,199,241,148,56,48,27,194,180,191,35,170,227,179,166,110,172,88,208,185,53,153,120,109,155,216,205,172,159,59,191,94,49,209,213,90,125,246,132,153,163,89,50,28,91,141,185,11,4,229,210,18,79,36,117,191,90,231,97,92,89,193,98,201,7,9,252,3,100,157,87,134,164,29,218,54,7,117,232,97,226,74,185,43,135,78,199,151,206,137,157,244,201,49,137,164,23,115,134,121,92,128,224,192,100,154,252,124,146,17,129,44,130,237,65,159,194,35,88,56,132,29,163,200,91,112,118,35,100,76,112,87,180,233,171,69,124,62,161,232,54,66,129,248,193,47,232,197,143,236,112,36,132,61,97,179,231,60,124,4,220,161,114,16,84,196,143,200,58,98,2,255,8,3,222,42,146,204,234,68,199,78,202,173,32,215,30,242,64,32,250,49,111,31,174,191,209,40,51,55,101,12,137,212,116,140,72,132,52,104,204,245,218,122,29,236,175,188,112,137,112,129,225,22,84,118,55,75,104,13,207,51,243,102,148,120,49,86,192,53,173,30,143,161,0,187,160,141,185,32,104,37,221,242,44,29,27,162,135,12,4,205,239,98,8,217,237,81,207,29,240,169,209,6,80,56,120,99,193,90,244,235,14,45,162,130,224,62,152,96,147,9,238,188,49,82,151,207,8,240,126,39,228,192,121,199,227,52,238,238,69,130,134,174,90,34,126,176,133,63,234,79,219,126,186,224,106,183,242,244,90,180,161,17,110,155,66,109,222,205,83,121,103,49,85,234,220,198,98,67,0,50,194,21,182,193,118,19,220,4,173,96,221,203,40,186,232,98,162,37,12,169,225,26,229,12,71,121,194,162,100,159,139,30,0,151,86,14,131,219,129,154,212,170,79,126,26,171,90,92,239,0,106,79,97,213,183,128,12,238,216,30,67,114,73,64,191,22,179,225,12,252,220,234,87,55,51,145,66,34,63,168,252,148,87,47,176,54,228,85,152,226,61,198,41,76,94,182,131,134,142,127,97,14,232,78,147,107,91,23,55,184,220,0,132,128,230,214,41,253,146,45,59,69,244,78,228,127,47,234,235,212,197,152,203,251,16,167,93,153,46,245,207,238,82,246,96,131,4,123,250,67,9,15,63,198,214,205,18,51,223,238,190,104,69,185,188,1,61,168,132,22,21,224,86,237,119,49,15,228,241,216,161,180,19,252,22,109,144,133,49,21,97,145,73,250,32,160,0,103,179,235,69,26,206,44,140,184,97,110,167,21,84,228,112,18,154,24,41,60,232,190,168,43,72,248,82,221,13,138,79,89,140,122,61,117,232,17,75,243,217,88,218,235,50,96,182,174,230,168,249,99,90,3,240,143,171,128,49,247,62,32,242,216,73,239,88,172,30,77,172,78,40,138,46,152,178,103,92,139,57,224,167,208,14,63,245,78,69,235,225,103,133,134,96,22,32,104,77,117,153,192,206,38,183,221,117,253,207,240,211,16,89,105,251,119,74,144,222,156,150,154,58,135,38,58,165,24,125,4,181,205,243,117,226,156,243,80,70,66,176,146,37,197,55,215,99,87,148,92,191,170,198,29,60,48,57,132,232,226,100,191,28,143,184,235,205,69,47,243,18,71,89,96,148,5,68,98,120,4,46,222,166,248,156,123,31,13,147,244,29,153,133,248,130,207,112,2,139,131,49,115,58,120,121,244,170,19,97,201,192,75,161,137,127,83,157,78,253,58,222,224,220,83,182,11,236,101,153,140,34,113,36,254,143,112,151,78,23,46,155,32,170,178,239,64,77,243,128,127,240,27,82,213,68,205,87,27,42,124,75,156,9,234,4,161,210,181,7,140,130,78,31,105,100,208,169,223,62,105,229,132,50,56,128,226,5,184,254,213,116,54,2,93,233,67,132,34,39,179,133,27,209,227,163,127,21,38,10,175,140,28,114,70,190,173,123,166,31,176,23,83,27,2,64,147,250,217,95,1,100,211,238,42,151,65,188,182,234,61,134,64,31,245,14,173,167,214,244,223,242,182,230,208,180,241,228,142,135,251,1,188,189,100,175,18,181,117,35,14,102,136,20,208,168,235,41,228,102,112,204,114,197,137,63,144,1,174,122,8,52,194,119,247,169,229,16,103,124,105,126,128,30,165,102,132,107,24,55,253,220,212,101,202,129,150,144,2,88,195,9,152,160,243,97,168,80,228,18,168,79,186,193,151,206,197,164,32,6,58,126,128,178,154,122,20,188,81,123,96,6,46,214,149,107,24,177,129,255,208,247,29,66,228,212,126,81,168,1,76,131,174,108,141,122,248,24,107,113,170,68,235,117,129,83,56,163,148,130,79,104,185,22,138,198,242,77,180,102,47,117,225,233,90,16,225,8,163,241,112,173,15,227,176,197,136,139,114,202,96,151,63,60,96,154,107,17,147,224,206,248,93,53,106,235,229,60,87,165,173,67,60,192,40,25,38,154,183,128,195,41,187,21,254,166,61,76,158,20,29,63,194,131,191,180,111,32,193,245,193,122,94,224,84,142,94,172,150,192,219,151,49,107,61,164,252,204,72,119,227,21,253,120,84,60,176,113,224,172,24,196,92,64,19,6,114,3,127,121,48,40,3,60,52,74,110,225,56,14,140,23,179,58,129,206,230,166,25,190,123,31,5,201,50,253,204,94,174,116,91,166,97,216,90,145,201,152,88,164,18,19,17,202,204,251,146,159,61,233,43,209,63,240,241,168,94,78,86,211,0,62,97,12,204,199,62,218,65,64,9,170,91,210,0,191,56,249,81,51,140,84,246,229,192,59,27,87,104,195,108,174,216,168,188,98,234,57,57,162,193,13,190,155,45,124,40,58,32,99,14,179,68,39,112,92,159,159,36,201,2,226,129,171,120,102,185,148,114,152,162,196,181,56,69,182,37,197,98,228,38,41,142,10,57,84,197,160,183,210,236,9,42,214,224,63,62,31,118,26,251,177,236,185,210,104,244,19,251,195,113,141,34,50,255,204,42,56,117,66,203,139,249,119,14,28,203,175,32,42,245,180,104,11,154,25,127,248,60,200,28,180,91,39,244,161,108,240,140,189,72,32,119,76,235,30,100,46,74,250,110,234,232,192,243,51,124,39,251,186,123,64,23,149,105,161,56,180,49,163,245,34,42,187,145,64,13,82,135,95,186,146,44,214,135,104,194,94,110,93,178,242,130,21,226,63,156,184,127,204,241,167,193,180,9,237,106,90,105,165,19,198,246,140,189,35,66,77,27,170,145,237,170,99,161,189,234,238,51,219,82,212,214,32,43,128,193,45,163,2,216,44,192,84,104,92,99,93,116,94,163,255,90,174,176,184,147,127,46,68,22,63,23,62,151,173,125,237,52,101,54,144,205,184,145,103,197,86,53,11,127,158,118,175,217,13,86,251,47,11,230,181,185,174,212,134,254,17,229,174,154,246,87,107,230,55,252,104,84,104,251,201,66,110,183,24,71,54,10,178,175,12,182,18,163,73,203,244,85,216,175,129,81,60,17,112,71,155,136,34,122,134,137,245,172,152,64,127,55,97,0,148,116,138,88,45,172,16,250,169,10,55,168,155,249,246,117,74,112,183,220,144,84,127,245,255,79,75,162,219,9,150,235,53,199,122,194,58,198,192,83,66,183,114,7,36,198,143,179,218,40,178,248,218,185,108,140,103,50,91,31,235,191,230,109,62,140,189,224,31,241,31,255,48,167,106,18,242,164,95,24,208,232,159,107,188,95,66,187,61,92,245,43,201,191,135,1,41,19,255,103,156,115,9,219,112,48,74,62,113,152,120,196,200,133,105,206,67,75,26,102,159,159,237,244,74,119,46,70,217,24,102,5,82,212,11,224,67,44,241,148,125,122,140,30,141,56,185,122,202,228,228,152,203,143,221,92,116,168,69,113,89,106,187,215,201,255,151,132,143,105,97,52,138,102,179,146,194,72,5,11,142,16,31,119,218,54,11,45,117,143,78,191,169,116,115,101,231,67,196,81,203,175,126,36,74,3,153,52,15,176,118,87,2,10,235,166,166,25,217,24,97,56,174,121,208,62,83,81,159,25,1,81,67,213,89,71,34,140,83,221,7,159,118,96,172,176,235,249,185,28,97,166,17,64,245,165,23,63,251,128,105,12,76,148,92,91,188,236,238,25,184,58,203,60,22,171,192,183,224,144,158,173,39,61,188,92,76,155,181,102,5,187,207,150,94,58,3,250,36,236,210,151,254,24,164,165,111,28,108,229,47,22,146,124,12,137,148,24,184,174,127,13,247,114,83,177,100,178,209,116,247,77,184,99,249,116,52,90,208,48,242,239,23,251,172,248,54,133,62,24,240,90,110,209,64,19,65,231,127,36,40,74,61,89,232,108,40,133,183,241,255,164,20,180,249,37,233,11,144,123,198,10,134,56,30,115,232,181,188,113,167,11,26,133,132,207,13,144,114,236,85,141,70,151,42,10,176,211,160,243,33,210,57,247,197,33,32,215,207,152,153,82,222,95,87,217,232,251,9,157,52,92,92,186,221,244,36,132,244,171,126,222,212,178,213,118,239,52,68,215,228,157,37,229,77,151,40,95,205,177,209,250,59,223,193,65,135,147,161,220,60,30,20,221,12,251,251,237,115,218,76,211,222,227,113,244,133,150,144,25,141,230,202,17,219,118,142,8,254,249,111,8,74,66,92,214,206,5,252,176,47,65,208,174,127,25,182,208,254,125,215,136,104,95,122,148,47,160,24,171,217,115,108,36,46,111,121,54,209,200,78,201,242,47,82,146,153,116,84,30,151,175,199,2,189,89,106,30,113,219,11,101,233,191,165,1,168,238,15,156,187,76,114,205,125,10,232,251,59,152,234,16,241,125,111,195,40,170,83,198,62,219,137,128,20,195,25,33,235,77,95,39,151,116,175,239,44,250,171,84,173,154,211,23,212,157,160,162,208,164,16,244,147,14,14,17,6,104,150,53,108,250,78,227,27,137,22,252,98,238,175,243,37,70,13,183,79,164,152,113,101,78,244,30,197,103,210,103,214,38,156,171,0,17,21,28,178,30,168,20,31,200,208,51,52,113,15,151,103,235,237,40,10,81,34,216,193,173,182,231,138,223,70,74,110,140,135,128,67,193,157,182,109,142,223,157,163,206,148,192,228,100,183,148,130,219,246,217,18,184,83,27,227,178,40,188,85,136,45,33,244,69,87,159,128,40,97,108,157,0,46,148,60,23,222,235,38,205,188,53,18,244,187,182,168,183,237,144,27,24,195,130,65,220,216,15,20,137,249,27,41,218,232,246,197,92,106,119,80,113,188,192,30,233,34,219,39,146,187,114,27,18,165,104,236,249,38,44,105,166,205,230,49,128,243,36,251,113,40,38,25,215,224,120,27,235,159,12,92,34,87,109,158,74,60,6,136,178,187,38,91,137,86,88,121,201,214,195,151,83,64,228,135,143,158,147,97,176,188,111,251,247,113,197,192,23,113,9,177,188,15,65,193,111,153,189,107,45,251,63,75,15,75,144,12,21,147,41,0,174,131,76,50,32,230,156,172,12,21,217,99,174,122,176,90,142,255,218,205,218,102,252,254,211,225,2,68,190,66,50,226,64,173,14,103,174,112,42,47,226,144,59,125,110,69,123,255,9,156,24,136,238,168,115,76,198,25,170,142,181,178,27,82,125,25,38,98,50,248,232,139,82,51,79,162,74,26,73,204,26,40,13,40,2,73,96,105,177,92,99,35,99,110,56,185,105,177,205,31,100,153,114,150,60,150,252,43,129,210,116,71,159,252,129,54,152,242,65,180,226,15,50,224,127,124,175,143,91,38,46,62,8,22,59,186,178,38,77,246,103,48,216,212,109,56,156,174,127,24,51,123,161,249,178,142,219,27,68,158,78,254,94,242,73,34,240,204,200,93,216,7,25,228,165,205,3,19,2,181,77,104,175,11,217,230,194,135,111,69,253,161,56,50,214,192,155,137,146,17,189,167,202,57,121,74,241,142,45,201,161,154,57,125,92,44,130,241,88,74,115,124,14,144,36,13,187,40,11,139,4,59,158,157,206,13,92,151,135,1,219,94,61,152,173,99,202,240,172,225,103,253,248,69,184,171,34,33,169,218,245,125,15,58,199,178,40,202,80,134,75,170,110,92,65,6,58,200,15,51,116,102,229,188,24,164,185,80,221,62,235,227,1,238,159,158,44,47,211,248,136,211,153,57,241,104,231,90,19,39,187,253,118,187,69,91,208,213,90,157,249,110,157,246,186,4,46,212,11,235,27,55,22,236,16,139,224,123,76,76,174,18,156,21,2,25,59,83,147,157,186,202,18,243,139,77,192,205,43,11,67,231,130,169,53,171,6,241,244,138,2,96,125,93,209,194,120,187,162,104,129,237,118,242,149,94,212,207,222,141,202,202,204,103,231,34,132,92,157,95,239,176,202,195,185,87,154,63,219,10,215,8,146,73,190,222,17,110,27,90,35,66,27,93,191,17,12,120,158,138,224,58,68,152,169,243,48,157,252,163,132,148,157,222,184,145,161,202,141,123,93,61,82,14,213,82,53,66,165,100,215,10,77,207,216,139,35,208,176,63,63,80,219,7,147,222,36,12,252,16,92,225,56,96,70,218,129,99,205,25,99,208,253,109,43,104,153,0,224,39,192,163,67,138,85,157,8,128,148,197,89,194,87,99,206,81,141,47,214,217,156,211,187,184,220,33,32,20,31,143,48,136,147,54,141,147,129,53,91,215,115,208,74,187,36,225,92,30,238,23,79,195,80,124,161,28,40,129,212,156,128,13,94,16,64,122,47,166,181,116,236,218,16,106,162,20,12,250,106,59,75,168,173,41,229,75,239,230,135,79,240,61,106,144,243,222,80,207,8,155,238,226,204,246,25,2,83,116,227,42,121,189,61,88,237,200,221,66,111,84,209,44,204,5,74,21,249,236,194,187,52,103,164,109,114,191,27,0,240,99,60,253,103,92,69,90,87,109,109,138,61,171,55,129,98,152,62,65,82,93,47,130,95,171,12,145,48,243,4,220,47,118,144,188,144,153,224,242,141,144,94,218,128,144,77,106,98,182,215,118,91,73,238,22,122,110,3,109,89,91,34,0,57,72,86,228,158,153,209,235,58,200,213,223,68,254,49,210,128,11,87,0,207,25,93,183,141,193,9,142,11,15,213,209,90,220,249,117,222,163,188,42,116,162,111,235,175,70,29,243,205,184,46,214,112,219,68,27,190,37,228,13,196,98,127,58,220,90,248,241,41,128,82,170,102,78,72,99,103,47,49,238,210,203,217,40,130,83,98,143,81,119,52,173,166,24,234,61,253,11,147,118,189,128,69,161,207,122,161,251,67,139,246,0,44,109,95,241,166,224,177,225,201,10,38,201,24,44,192,55,22,191,109,159,167,39,67,213,33,100,6,197,183,223,105,223,51,37,21,232,53,7,12,64,243,13,77,22,76,175,156,127,201,50,147,144,135,179,71,59,88,161,195,29,23,213,184,66,77,202,54,134,198,21,205,74,59,68,197,2,150,28,192,219,164,192,158,231,193,240,26,176,33,136,97,129,95,91,76,114,79,86,97,220,135,80,233,39,150,150,27,223,206,160,84,151,120,226,45,231,200,167,121,200,46,1,132,39,112,88,96,85,173,249,29,67,46,208,224,131,84,81,64,218,16,15,12,243,215,86,157,212,204,147,221,26,11,10,114,75,9,240,8,16,58,152,196,219,149,51,8,94,225,203,7,157,156,249,220,220,207,80,128,47,103,189,58,38,83,183,122,51,230,254,146,160,37,235,226,233,55,164,177,33,246,224,67,54,25,126,27,216,100,83,102,46,231,99,215,206,57,243,30,174,54,153,209,116,17,156,121,215,104,69,33,59,37,187,95,75,158,233,68,148,64,236,174,32,201,143,189,99,126,50,216,65,155,184,98,84,102,243,47,178,99,59,227,198,213,53,206,39,35,180,9,162,212,58,190,48,80,234,176,124,165,130,234,100,117,5,245,122,210,159,134,31,165,144,196,154,81,131,130,236,180,4,23,225,45,144,92,99,117,71,130,142,141,103,81,168,211,2,123,203,171,59,133,24,46,169,116,160,216,233,44,215,66,201,119,51,58,75,50,68,116,127,170,113,129,55,193,109,155,237,246,191,189,150,135,24,5,204,65,201,86,15,202,87,40,122,227,52,245,82,182,54,65,104,165,101,190,208,117,246,203,163,168,171,35,67,186,170,221,100,63,0,206,157,229,28,237,147,132,88,91,215,64,64,22,48,88,246,232,140,146,211,199,110,230,207,238,78,66,78,104,253,244,227,114,94,210,30,6,33,43,1,110,176,2,156,178,126,202,213,183,124,213,218,56,96,100,54,192,53,69,60,180,73,48,142,15,85,251,191,216,147,246,47,251,203,203,138,14,174,9,73,186,102,220,0,200,22,56,137,234,117,155,105,229,151,192,129,193,93,234,222,103,57,195,107,240,92,18,180,41,23,23,255,255,135,26,222,109,47,129,205,129,52,192,82,153,195,24,72,58,156,127,159,210,114,67,196,173,239,17,84,216,115,57,151,70,218,133,179,61,149,175,160,128,222,103,91,202,239,92,198,173,251,58,186,236,105,215,23,167,254,58,4,21,22,17,213,211,230,47,195,183,154,245,187,224,165,236,107,184,195,149,49,79,138,158,97,201,64,138,145,249,37,253,56,175,148,83,197,74,69,186,47,38,63,14,241,224,30,52,152,74,163,144,190,253,92,176,164,109,217,165,118,19,56,214,162,10,193,213,18,95,72,55,150,22,199,50,196,111,155,204,32,122,25,68,234,156,43,178,92,160,204,83,138,2,184,248,7,132,201,144,69,176,216,12,49,175,55,89,163,91,23,159,27,226,183,111,153,13,35,140,237,237,170,126,119,171,55,105,81,53,55,142,131,46,39,136,83,145,158,216,192,73,71,22,117,124,243,85,81,130,52,28,216,143,226,153,141,3,162,141,249,125,8,119,27,65,133,135,123,117,71,161,45,130,255,194,160,178,21,123,106,105,199,3,146,205,115,157,18,61,181,226,101,151,234,244,10,17,216,104,186,3,215,32,157,200,151,190,41,62,181,74,5,160,213,185,70,97,253,164,115,81,108,228,207,4,144,210,54,224,36,93,21,210,109,58,54,121,127,235,182,110,122,161,24,48,114,193,83,31,221,109,136,70,83,212,203,195,232,231,69,5,55,157,106,77,101,19,58,55,127,91,240,85,64,11,229,155,10,93,177,2,144,20,75,121,186,81,171,50,1,196,62,217,231,16,206,250,186,173,24,60,218,230,99,216,36,3,103,61,237,73,61,170,38,35,224,158,166,103,119,128,4,5,152,194,141,234,113,149,54,196,25,235,18,81,227,137,137,138,115,20,204,38,189,115,69,224,31,135,6,32,171,72,87,42,144,71,72,255,171,79,132,159,83,151,209,62,152,25,79,133,19,172,154,90,84,80,101,131,150,37,245,195,199,210,235,98,122,229,215,7,164,79,63,62,80,142,144,161,189,235,24,212,200,109,145,185,104,122,29,112,81,147,15,4,108,147,244,184,155,249,18,80,201,174,227,93,226,109,63,7,17,14,209,141,194,160,30,170,18,60,144,32,224,177,0,106,248,126,107,84,185,179,106,146,13,238,80,251,18,50,96,122,216,217,112,187,148,102,111,47,244,158,22,39,76,59,150,43,22,117,202,253,88,26,166,126,243,142,239,81,69,185,255,93,56,20,32,232,185,22,217,19,198,221,159,42,176,105,127,180,90,189,136,213,241,120,92,0,77,136,165,142,142,126,142,164,219,231,41,237,134,253,191,235,254,252,57,52,25,89,120,215,145,142,87,152,149,107,177,79,86,176,4,105,59,150,254,14,74,110,116,206,16,0,218,98,156,66,18,10,16,202,136,15,80,236,236,233,75,132,186,168,174,233,16,240,124,0,189,243,98,252,33,121,215,44,173,199,127,71,233,97,165,227,102,12,62,59,225,180,119,55,117,95,159,229,177,99,143,111,247,182,37,180,23,219,51,67,250,113,124,122,213,160,93,82,156,170,252,0,1,76,22,11,250,91,147,112,1,233,251,21,112,60,137,25,215,114,231,83,28,55,129,94,198,200,247,80,156,163,198,211,214,235,239,111,210,160,137,128,181,114,163,61,8,94,83,46,49,30,181,239,140,222,109,66,167,226,89,159,32,73,145,21,222,213,65,62,66,94,137,206,128,169,236,73,167,141,150,232,238,36,44,136,68,28,4,21,153,225,253,254,31,210,190,138,17,5,228,142,90,163,91,64,60,208,230,70,88,201,198,140,171,37,112,143,83,251,39,36,63,189,48,135,196,100,189,76,124,37,117,179,153,183,236,97,94,72,5,144,76,23,71,22,137,91,101,17,51,31,37,37,248,167,248,202,225,125,28,24,192,51,67,242,20,243,183,110,138,211,210,110,39,221,189,226,241,100,225,217,111,128,6,152,234,156,179,79,2,139,150,103,51,47,252,21,104,71,84,83,243,17,144,151,52,96,128,26,163,179,77,162,97,109,136,128,106,219,50,111,229,203,148,252,102,19,181,220,239,169,7,60,6,173,111,160,55,24,162,69,223,39,186,222,104,184,206,203,0,68,178,244,108,51,107,230,205,176,248,207,12,225,122,184,184,1,99,226,173,135,71,136,45,243,127,168,160,134,31,180,45,53,1,213,36,43,83,51,59,61,115,223,67,123,54,86,38,128,71,198,210,179,241,150,253,253,1,26,104,127,234,182,86,121,188,19,134,211,19,249,75,96,210,137,255,175,48,38,23,82,107,180,73,87,97,17,31,217,160,77,243,143,164,224,77,154,152,148,205,66,240,48,168,156,21,103,19,214,154,17,173,156,16,31,18,63,134,224,211,145,46,114,33,113,105,125,72,78,202,25,183,28,255,45,63,169,16,225,2,237,156,45,254,223,125,195,250,99,49,156,250,188,216,169,104,171,157,188,114,72,110,29,153,187,99,254,51,237,255,23,98,131,248,193,121,59,142,7,176,78,52,182,134,170,136,125,40,234,245,225,74,212,208,176,105,253,8,32,143,69,180,249,246,10,31,176,129,144,255,199,193,59,12,181,231,207,169,241,243,19,253,220,49,45,195,42,147,102,239,117,186,240,63,156,184,43,225,119,87,44,38,11,106,231,241,208,145,167,222,147,22,240,37,62,139,30,249,0,209,78,164,84,131,254,178,126,91,170,226,29,73,170,154,101,221,202,18,92,146,134,178,38,195,106,88,228,86,86,172,34,113,89,4,85,139,78,39,3,161,49,94,245,107,21,206,162,64,240,35,201,126,89,226,156,229,141,165,29,4,22,197,202,125,44,200,64,176,137,55,95,167,234,104,86,244,217,45,234,206,4,6,171,85,146,235,237,168,81,103,77,204,104,16,110,90,132,100,240,72,96,188,201,254,56,43,229,76,8,144,250,190,182,102,89,64,104,238,222,184,173,138,130,235,233,91,226,30,237,38,236,194,116,180,36,198,97,37,242,32,60,224,15,13,203,190,121,127,41,1,108,205,117,79,104,173,232,164,128,0,31,193,82,164,115,1,175,199,50,22,0,215,136,87,212,105,174,240,47,27,51,93,165,183,61,96,31,150,125,70,38,192,85,215,191,65,159,42,123,59,211,210,39,96,64,53,80,103,134,214,75,89,23,40,114,4,148,61,56,175,176,119,180,61,162,119,184,21,110,204,103,52,202,109,151,202,204,240,215,165,116,96,52,113,64,112,42,171,54,172,169,69,253,44,153,24,232,19,141,73,3,80,141,143,57,23,209,218,79,5,176,20,117,197,223,97,0,0,216,103,205,251,42,189,173,104,182,224,240,187,184,90,150,165,151,54,237,248,21,195,252,26,86,186,43,130,85,173,165,88,77,47,61,60,251,197,177,40,114,201,153,72,161,39,61,136,217,22,39,227,180,112,20,184,0,22,255,248,87,132,120,113,8,6,226,212,166,57,112,185,75,15,83,79,196,106,136,205,5,59,250,63,35,80,140,176,236,196,248,3,221,98,250,104,32,99,152,165,109,139,192,40,49,68,14,50,89,102,202,12,64,120,114,49,227,205,144,18,43,180,65,47,167,89,67,145,180,44,241,173,23,232,86,141,103,210,72,240,225,180,133,221,238,4,125,161,121,44,204,5,162,64,34,84,167,152,247,154,190,162,116,71,83,180,181,174,3,151,227,180,162,28,198,133,1,195,199,54,251,220,4,182,126,209,15,24,207,187,240,50,11,120,250,158,87,125,246,74,64,175,190,21,150,255,202,170,125,38,228,16,24,166,186,7,113,0,133,182,112,138,188,2,24,120,236,10,76,154,89,48,23,228,159,219,144,219,209,76,59,25,100,202,46,203,178,117,252,97,240,97,42,143,205,52,199,220,7,0,109,217,139,126,170,178,227,213,192,16,171,133,173,237,240,186,6,14,155,94,157,194,99,123,174,181,74,164,126,56,178,0,172,77,163,74,172,53,5,161,130,161,162,149,232,150,69,170,172,59,70,142,112,87,58,16,192,67,8,250,29,140,221,17,117,167,133,43,180,141,157,214,18,131,114,105,147,206,25,138,207,188,30,41,9,97,113,247,123,251,56,165,182,239,95,79,152,45,113,160,213,230,249,227,167,149,52,172,156,182,242,134,61,19,90,144,248,100,252,168,76,213,246,126,123,175,8,114,218,41,247,90,229,94,238,86,73,43,35,42,116,168,217,75,167,166,122,230,82,130,255,164,51,9,86,79,111,49,152,198,132,96,62,12,131,23,66,96,51,213,29,13,144,20,26,228,66,41,228,68,254,126,173,192,51,62,41,184,136,182,93,102,144,250,65,236,200,19,121,182,87,125,72,97,132,164,29,130,211,26,115,217,177,199,35,54,132,98,87,138,188,229,34,130,240,81,186,231,130,41,17,74,64,27,41,169,251,229,192,38,247,81,85,224,10,181,80,164,164,112,73,150,53,119,166,144,157,52,98,187,48,28,64,77,33,237,100,1,46,123,40,27,232,128,105,190,126,27,132,205,16,107,184,30,187,240,29,128,81,177,9,175,37,159,188,53,109,59,15,33,102,39,182,31,73,163,176,14,150,178,216,231,41,152,253,100,240,46,106,181,137,111,240,101,204,74,57,134,179,49,230,134,124,152,70,64,166,43,65,203,80,53,157,166,39,138,142,243,74,145,217,9,194,93,128,67,93,129,161,161,254,211,189,239,205,32,171,253,118,141,204,240,183,222,146,198,220,187,58,201,238,218,179,206,89,183,40,198,33,53,38,40,144,216,247,161,189,216,173,9,22,72,148,174,45,3,127,35,125,111,140,15,207,119,246,38,244,195,69,85,106,121,28,241,125,124,103,116,108,152,84,133,165,68,92,5,189,160,223,125,159,69,84,91,214,24,52,36,207,180,152,8,156,70,209,194,220,165,138,212,192,246,132,124,186,64,218,179,23,131,210,117,7,15,197,250,249,187,104,74,19,195,232,168,66,171,125,133,252,89,123,236,67,152,150,187,82,161,241,29,160,206,15,254,101,201,34,79,182,6,88,237,204,67,3,24,199,64,58,22,71,118,31,80,235,148,111,111,74,248,229,15,0,160,215,0,121,227,15,243,58,122,251,203,236,223,102,217,235,105,113,239,209,206,227,198,166,116,250,85,48,71,14,78,216,2,167,129,129,240,167,56,89,118,161,125,49,228,56,221,13,219,207,36,68,253,27,45,219,117,151,229,111,247,206,97,173,132,8,74,182,16,125,54,238,31,46,244,50,250,3,216,182,42,120,67,61,39,106,101,23,248,21,80,151,115,41,105,95,47,32,90,53,3,164,31,12,113,105,26,135,101,186,43,191,173,143,177,4,75,109,96,7,121,5,231,218,250,45,96,254,193,146,225,251,238,21,240,27,207,43,187,7,61,254,195,234,210,152,46,241,186,188,216,234,82,179,109,61,190,139,211,58,36,74,149,107,249,150,196,71,226,167,232,40,42,19,152,17,194,16,94,5,11,57,37,43,99,98,248,81,211,60,69,192,80,94,225,241,197,53,76,100,1,166,253,132,17,3,72,232,72,214,60,18,151,159,15,167,78,27,76,142,22,21,129,121,10,185,35,246,49,165,218,73,182,236,65,1,175,236,230,71,209,189,163,164,179,194,209,86,6,180,219,147,94,15,212,246,83,21,183,250,40,230,78,222,159,74,94,13,20,247,51,90,218,253,125,50,81,72,93,1,200,50,199,223,192,197,223,38,208,98,122,118,7,82,178,154,193,50,199,199,7,184,231,120,39,2,232,41,182,32,75,56,236,176,5,0,113,190,13,109,1,175,212,249,89,21,130,204,162,228,119,244,190,87,252,151,13,40,209,103,93,95,199,103,141,133,122,94,189,161,222,26,229,214,114,137,110,97,84,81,251,213,80,122,215,144,113,154,105,12,130,191,24,0,226,159,46,86,119,142,104,231,72,118,224,91,195,94,179,212,168,32,243,2,25,219,4,197,34,167,252,198,18,155,87,88,62,165,118,253,176,96,152,186,128,214,140,226,59,11,113,104,102,96,136,126,9,13,140,165,46,116,134,52,249,105,131,168,226,83,93,216,194,247,236,251,159,42,118,243,93,85,175,120,106,134,75,146,217,187,183,49,138,190,5,189,3,203,106,166,110,104,108,70,111,165,41,203,34,212,254,32,10,2,238,30,243,126,47,119,175,63,107,73,75,131,105,17,54,253,158,128,179,196,198,64,151,178,55,47,159,191,106,78,234,208,198,108,42,131,2,33,44,121,43,48,137,107,252,205,15,84,242,200,169,148,239,199,117,248,6,151,51,83,45,149,57,75,160,202,27,122,235,14,50,90,135,90,94,140,171,241,123,236,90,200,243,190,6,111,165,246,139,34,141,151,172,38,34,66,201,218,83,110,52,12,146,6,26,248,102,120,174,193,25,147,171,152,87,174,79,55,208,166,73,111,90,214,25,117,239,102,226,213,182,128,93,49,129,174,3,2,180,9,250,166,8,32,141,187,26,55,157,229,144,64,195,91,154,133,56,176,6,198,60,119,115,232,70,213,143,59,250,97,136,50,75,125,198,19,151,141,168,48,163,47,67,211,114,119,103,69,9,119,244,236,196,164,248,228,69,215,205,245,16,57,177,244,43,224,109,172,45,14,5,161,195,63,81,38,117,19,125,248,179,103,199,168,84,151,192,55,216,72,96,43,117,199,103,51,202,42,177,40,169,84,157,153,173,244,141,108,142,38,188,53,35,151,221,147,12,148,111,151,129,212,37,253,142,191,152,21,241,153,150,30,71,95,49,124,83,150,47,109,169,199,96,70,141,167,74,79,11,152,159,93,215,159,185,141,249,140,114,217,75,87,133,177,114,114,27,32,86,10,246,20,157,127,160,164,227,79,194,177,107,49,142,179,84,144,135,178,81,30,7,228,120,116,11,103,210,83,15,94,77,40,116,144,27,125,81,192,231,217,112,4,184,78,6,144,65,184,221,84,114,52,150,241,217,130,114,219,252,15,34,244,209,76,178,193,231,229,38,137,147,0,147,242,150,26,33,32,28,132,60,63,134,221,9,214,135,97,120,217,109,78,130,199,253,153,215,234,19,186,201,199,169,20,132,151,74,179,54,65,25,171,126,126,88,23,247,222,39,52,65,85,45,245,229,214,38,98,14,0,10,216,42,17,230,34,91,84,144,209,31,186,211,140,175,188,80,202,99,174,124,88,40,32,214,235,133,253,145,179,186,102,42,135,61,67,235,163,133,41,35,25,168,87,141,24,186,210,233,150,19,220,120,81,123,169,245,18,197,27,207,176,15,197,115,139,69,152,82,211,148,77,184,232,173,29,253,46,123,173,245,217,54,231,135,218,236,101,196,45,109,136,189,206,68,215,214,77,251,43,39,224,144,62,135,50,114,247,67,110,247,38,143,220,5,1,173,142,88,7,149,152,225,194,10,114,152,121,105,239,242,249,117,29,172,2,39,98,218,33,31,69,93,11,210,222,132,40,251,162,173,144,13,165,165,242,181,202,215,89,196,228,253,39,70,73,153,144,63,184,211,2,204,107,51,166,197,173,14,15,96,66,141,11,12,244,148,50,16,214,9,8,52,6,165,105,91,184,10,10,62,135,250,200,159,69,227,229,86,98,229,73,27,200,217,108,233,211,81,90,93,45,50,50,149,19,35,23,116,202,113,21,211,33,217,140,128,86,228,185,130,140,104,87,180,174,131,213,254,48,90,67,239,159,204,139,229,42,236,142,82,151,187,165,11,12,150,53,56,10,76,97,213,117,217,51,242,133,135,229,78,117,95,26,31,69,32,138,147,70,226,136,42,0,8,199,224,233,35,206,48,207,61,99,52,101,204,118,143,245,236,120,33,226,57,223,53,32,255,6,236,127,223,89,137,99,84,204,80,106,20,237,64,149,193,65,7,41,202,120,56,115,112,137,35,254,243,28,47,4,229,33,115,177,48,219,231,48,63,139,95,214,209,6,170,197,116,222,104,88,254,141,16,48,222,226,9,47,121,65,188,142,38,129,229,60,122,25,131,229,78,249,211,139,93,199,181,248,231,247,38,161,131,223,146,216,88,123,189,77,186,220,2,185,53,173,226,101,153,213,103,171,140,207,44,51,120,168,36,182,213,176,87,166,170,61,250,49,139,249,215,135,168,170,59,95,118,142,249,166,177,121,94,175,159,219,228,219,117,28,222,43,180,225,108,140,7,25,5,94,45,171,5,65,137,255,40,123,190,89,181,94,76,172,91,161,197,240,85,79,172,28,47,57,205,233,102,137,143,28,155,20,20,157,41,148,175,43,167,5,82,171,148,109,247,237,236,176,176,124,1,158,189,93,168,51,115,231,208,228,55,164,123,212,27,25,190,38,1,120,25,153,91,236,95,116,67,210,173,224,156,220,91,207,120,91,114,212,191,71,198,205,146,136,65,91,33,204,192,154,155,243,71,11,55,239,100,89,204,247,199,59,120,22,68,109,137,194,203,81,61,247,11,226,242,210,155,195,209,1,193,108,163,178,20,22,170,30,148,214,80,229,153,91,103,246,237,10,245,110,211,150,205,98,239,92,94,71,206,91,253,204,90,157,216,152,35,148,167,8,201,167,24,239,191,158,102,23,131,159,64,99,81,159,58,193,185,68,1,28,24,38,198,132,80,191,19,122,235,99,129,100,49,253,29,52,194,32,108,106,166,243,179,53,189,96,59,73,241,61,32,223,84,218,118,59,32,64,9,98,239,207,219,101,38,106,54,148,148,25,5,50,107,106,152,242,117,192,102,56,184,19,232,133,157,243,182,52,144,217,94,101,153,221,88,157,52,224,159,93,159,71,2,115,200,230,116,202,177,236,75,20,176,16,39,147,24,150,195,21,251,77,57,185,113,216,168,48,127,164,56,104,92,23,85,141,159,93,53,192,103,163,130,24,85,85,160,61,246,23,185,196,18,158,228,129,148,126,206,52,198,191,182,12,98,112,31,56,160,62,208,196,234,1,56,249,23,61,115,25,164,254,151,45,11,124,107,53,151,131,221,52,249,185,90,5,4,129,177,134,168,239,37,50,111,225,178,53,251,9,5,87,32,111,75,239,38,160,33,50,128,211,5,250,31,61,177,31,115,182,221,118,33,225,75,165,5,43,89,152,62,217,185,246,122,194,98,47,193,42,74,46,144,111,16,231,76,88,151,7,93,68,144,237,82,117,206,167,239,6,137,55,125,14,88,92,201,143,148,62,216,55,224,150,178,38,77,42,167,163,233,124,131,220,55,50,219,117,225,244,220,233,124,27,133,246,213,86,54,152,29,92,98,226,98,54,110,144,186,41,161,225,72,199,30,105,121,160,56,141,23,100,40,88,208,169,32,196,122,95,231,57,244,199,120,13,232,165,250,170,24,34,231,23,205,33,18,214,128,56,165,14,48,104,223,133,183,73,58,100,111,112,115,239,70,81,81,38,94,88,232,164,212,242,0,59,114,36,133,89,252,41,204,37,193,144,244,255,242,124,20,131,112,126,131,187,205,71,229,86,90,197,199,245,45,120,190,56,223,164,63,177,75,188,238,180,176,137,182,95,221,29,158,104,4,224,38,183,94,172,67,44,62,168,237,218,85,159,58,25,168,173,108,204,228,81,18,145,207,176,19,10,212,78,133,108,169,178,117,11,19,155,152,200,117,243,99,143,126,93,75,167,4,103,249,245,27,30,184,78,162,35,174,200,4,59,119,138,195,58,130,59,179,147,48,207,134,201,207,31,90,145,168,212,195,79,220,16,253,80,24,42,159,61,178,241,81,140,246,198,225,166,94,74,63,254,3,218,93,2,74,194,239,192,68,55,75,132,51,79,200,162,72,133,34,87,86,7,157,235,37,94,78,191,150,81,213,162,147,20,232,243,173,36,1,244,91,3,192,10,224,194,229,74,147,19,192,165,168,153,5,127,230,113,185,206,127,146,80,114,246,179,16,31,90,0,242,254,82,189,36,246,211,7,118,168,33,154,220,184,107,101,40,150,196,194,242,253,216,72,132,210,147,230,224,198,34,75,25,74,233,205,159,168,6,197,50,217,127,251,94,27,0,89,55,171,138,10,197,251,46,127,84,139,97,212,131,44,89,5,181,154,11,223,2,106,249,29,222,72,44,89,57,56,8,138,102,140,86,159,219,77,239,32,203,126,142,214,192,72,16,119,161,71,155,250,58,115,189,112,51,213,249,25,85,78,170,171,102,164,103,133,109,37,229,130,167,116,64,21,234,76,246,89,206,141,235,89,223,141,56,47,168,166,97,190,26,197,70,97,133,200,148,53,45,183,39,129,38,122,174,116,58,75,115,221,204,101,52,24,94,177,14,237,2,172,234,210,8,208,25,77,235,113,24,108,216,242,184,180,255,173,101,240,51,246,200,240,13,156,209,93,60,66,170,252,82,230,13,215,146,117,255,210,7,34,122,10,106,156,176,21,68,222,248,33,83,152,206,191,60,18,158,149,114,74,41,60,203,244,210,249,189,212,25,25,75,131,95,76,207,254,188,23,124,249,162,255,170,137,0,81,97,181,221,127,2,120,240,234,80,28,115,105,158,136,89,77,135,103,255,251,8,186,242,63,176,164,122,8,11,128,19,58,243,8,212,252,204,84,170,108,158,179,247,0,254,32,87,139,213,136,45,180,92,145,67,92,246,247,205,97,103,87,101,163,137,0,61,23,230,147,218,153,102,235,104,17,24,246,70,190,79,179,238,178,41,56,128,115,241,148,114,229,173,144,63,54,151,123,191,45,145,222,89,230,29,59,34,163,123,120,56,34,137,149,161,32,221,255,87,39,50,57,112,84,159,209,51,170,143,167,190,117,145,202,12,127,248,132,142,52,118,154,247,22,242,179,161,240,146,155,7,176,79,18,1,228,242,227,81,34,121,92,236,105,176,207,233,51,86,159,119,70,173,14,42,103,31,241,149,157,98,49,61,96,106,94,142,12,146,88,63,16,173,84,14,216,170,188,7,119,188,94,156,24,78,218,117,39,252,216,201,136,241,118,24,231,164,15,9,211,193,68,14,9,140,214,99,95,235,172,219,136,83,12,95,75,88,48,152,236,153,95,137,236,38,125,35,176,220,87,52,101,106,40,172,224,140,105,118,201,227,143,43,59,162,152,247,197,72,70,232,183,21,160,2,64,169,41,69,166,102,52,189,217,130,19,196,230,34,133,35,31,17,193,45,252,112,79,79,223,99,168,154,14,19,74,179,41,246,27,199,128,101,54,80,252,173,165,241,80,26,204,142,255,57,94,25,56,246,22,133,229,144,110,212,118,251,36,49,81,254,183,116,222,99,70,181,22,74,96,199,161,124,176,7,199,9,56,128,64,200,185,222,37,225,144,156,152,22,99,76,208,43,99,207,169,146,220,182,136,30,96,166,118,49,125,40,132,106,49,212,158,91,55,84,208,213,75,63,190,113,71,83,98,109,21,176,11,204,253,157,79,106,111,232,239,253,187,98,141,32,52,39,209,183,100,176,183,32,232,137,209,189,13,67,230,44,99,233,235,31,211,62,149,120,185,114,79,123,8,153,151,112,255,65,154,228,16,226,177,21,18,10,146,172,134,181,123,4,253,122,188,229,98,89,112,147,19,145,108,246,176,210,201,128,231,96,230,39,140,7,175,246,144,253,114,34,223,14,48,134,160,78,112,135,138,197,142,208,213,221,156,197,198,131,42,169,203,191,140,36,205,131,59,11,239,147,205,235,193,132,59,199,198,42,204,244,120,24,172,221,253,85,141,118,110,76,153,91,146,222,142,200,251,52,172,145,250,47,123,86,49,253,220,27,77,170,51,36,179,148,26,32,251,162,197,246,163,248,65,123,233,68,194,166,153,206,118,238,22,134,49,13,218,176,11,183,124,197,148,169,251,224,80,11,209,166,233,229,19,220,114,244,144,246,17,131,119,108,78,6,26,238,121,82,13,57,179,139,149,164,255,235,181,20,240,76,155,71,61,89,192,100,16,244,93,71,199,139,70,203,107,44,233,154,66,40,255,1,15,20,206,89,244,23,68,123,164,177,175,187,170,150,195,150,44,96,99,142,169,220,220,197,235,124,72,198,60,112,180,196,35,190,154,107,29,177,10,243,111,210,61,157,156,223,255,101,5,210,27,224,15,23,138,119,65,201,139,134,84,70,122,22,204,153,5,193,108,54,149,173,173,37,200,81,229,93,72,7,45,14,51,177,85,166,96,189,55,43,70,88,172,251,17,221,163,81,62,196,216,14,31,82,46,38,65,125,42,32,4,9,145,100,31,102,106,231,86,31,167,246,39,11,28,118,34,92,179,80,65,191,115,43,247,211,118,115,124,156,122,145,222,177,73,161,7,117,51,20,29,178,100,26,127,202,208,177,209,121,101,140,194,20,229,139,123,55,186,209,31,33,39,115,64,97,128,152,60,147,70,35,97,4,156,87,181,58,244,132,109,115,229,91,215,10,28,25,21,57,163,234,21,101,81,18,220,78,130,105,85,41,164,78,228,156,201,182,234,93,221,241,194,212,66,84,4,11,81,116,94,234,37,200,8,214,228,253,58,205,250,62,168,189,1,46,223,0,158,154,29,127,247,188,25,193,165,228,117,234,121,149,167,254,11,3,15,12,91,42,46,11,240,230,134,120,108,46,58,63,23,230,140,113,173,206,94,55,63,20,187,32,255,142,32,192,135,161,231,95,115,204,50,125,129,245,15,153,89,124,35,87,200,91,78,68,126,100,158,103,224,232,192,132,174,34,19,19,48,139,182,247,255,70,88,227,139,253,31,10,222,62,188,140,85,169,143,143,14,29,108,159,46,98,211,30,129,63,149,77,230,246,61,181,103,153,124,242,214,63,70,78,193,78,208,159,94,20,59,30,81,88,112,124,123,183,101,239,217,86,232,137,59,250,5,110,107,71,27,31,15,33,62,200,161,218,153,82,134,5,7,141,180,7,152,169,23,182,33,150,252,223,90,209,54,177,15,50,19,8,253,37,226,84,143,33,164,230,38,215,102,42,156,198,36,35,149,175,75,79,102,252,69,215,7,165,103,252,189,221,18,204,32,86,110,22,47,74,38,247,11,126,5,145,242,247,20,9,190,177,121,79,16,110,73,41,45,141,3,247,35,3,252,191,45,7,156,127,115,198,74,194,5,25,124,110,61,109,115,151,84,72,182,140,170,23,217,123,133,98,143,18,53,128,55,78,61,89,152,214,253,63,133,196,183,215,107,107,158,245,129,15,153,169,246,158,65,172,8,47,226,30,126,10,64,163,175,108,218,130,19,89,235,34,206,150,176,199,6,140,234,201,165,130,107,208,64,112,36,44,115,250,199,236,204,60,127,43,124,225,163,49,76,103,210,254,126,180,82,44,230,68,93,12,246,201,186,72,190,172,76,128,42,173,0,221,120,14,150,19,197,121,163,71,111,214,183,143,24,187,70,13,255,228,250,134,173,209,183,166,208,21,225,94,109,145,98,70,255,76,151,190,150,183,152,248,238,224,187,111,4,2,111,236,73,135,133,67,34,193,94,52,159,42,187,59,38,75,152,72,134,112,236,191,233,150,43,156,14,167,70,226,7,114,200,31,140,164,33,84,232,169,15,96,172,175,192,57,229,71,227,101,139,17,90,45,154,32,255,204,159,141,200,159,147,45,152,135,128,51,11,78,181,154,83,92,144,157,134,244,234,140,201,95,218,104,165,146,35,28,223,139,111,128,149,30,162,119,191,217,136,196,219,138,212,22,168,182,19,118,34,168,68,234,104,231,59,166,128,52,254,212,215,218,117,66,31,249,88,61,78,33,130,242,94,66,17,169,102,100,130,251,1,125,169,71,110,165,239,246,162,251,220,185,184,20,76,133,171,122,57,219,218,181,169,220,38,166,27,206,53,166,180,135,172,64,7,187,131,182,110,67,34,191,25,145,197,184,217,30,140,72,15,212,194,123,34,239,194,64,110,117,35,199,82,17,157,252,230,226,228,44,151,158,81,101,191,59,18,175,143,139,235,12,185,50,15,106,29,143,82,247,211,52,208,35,153,64,11,50,37,13,38,232,128,45,104,62,240,201,122,137,83,140,250,178,64,142,202,168,54,119,221,215,71,166,35,108,71,223,239,99,153,12,8,134,64,200,182,235,107,96,111,231,153,200,254,189,247,49,93,127,4,200,77,43,160,120,224,252,243,224,46,190,166,143,82,46,207,86,235,116,203,190,88,18,55,121,70,227,215,107,69,58,245,221,133,33,73,230,34,36,254,49,127,129,180,253,175,209,180,54,94,124,96,104,97,243,225,38,248,166,230,189,233,78,38,61,122,43,51,76,9,219,127,1,239,79,151,48,213,26,208,118,80,108,178,180,167,38,224,5,87,106,12,73,252,109,195,190,244,1,237,106,212,236,116,74,192,255,121,219,152,67,18,77,38,21,51,27,121,200,196,0,84,219,179,46,124,54,85,12,179,49,241,46,197,14,33,28,79,227,246,94,112,66,187,209,230,116,161,40,15,78,57,156,110,138,178,73,41,255,178,62,43,236,180,171,248,21,243,240,13,110,71,67,79,176,57,76,207,194,20,219,223,36,60,83,50,200,87,245,137,235,132,89,144,67,4,174,55,221,14,212,138,175,187,209,186,54,80,178,238,243,36,9,199,108,128,111,120,61,208,105,53,44,233,236,78,63,226,71,197,238,242,101,100,227,70,160,209,41,198,56,65,115,138,237,132,126,95,23,46,122,98,177,164,159,251,98,212,145,111,203,95,36,21,53,163,88,57,51,139,255,60,181,38,187,107,75,128,165,215,232,130,56,103,173,192,192,119,72,104,142,246,79,232,200,17,207,225,61,55,106,74,61,126,180,229,233,187,223,190,82,11,232,15,84,52,13,98,154,199,134,191,227,132,219,235,17,230,249,92,249,34,165,54,132,101,234,209,220,66,6,69,181,50,132,160,155,246,171,5,167,56,49,27,175,90,222,36,13,217,116,128,9,151,3,203,43,43,40,205,132,14,248,28,88,180,107,146,95,19,175,0,109,41,170,148,148,54,179,0,71,101,59,99,221,143,205,42,59,156,112,136,31,59,18,231,136,191,41,46,122,77,101,152,172,123,108,116,111,53,229,4,163,218,156,39,171,198,100,223,236,90,205,126,143,72,67,138,159,241,118,154,239,154,219,34,182,123,33,163,113,46,15,249,238,36,50,215,132,241,226,207,196,181,96,162,212,88,224,190,81,179,12,136,146,122,238,83,129,26,72,105,125,20,146,253,67,112,232,12,188,96,52,161,160,121,241,50,77,49,218,20,78,169,246,196,95,213,12,11,243,170,71,1,244,78,233,115,143,34,201,250,23,100,9,97,17,4,211,193,128,42,106,170,138,9,75,28,208,247,157,32,4,210,106,87,15,97,167,209,22,160,123,52,183,148,194,21,14,53,212,119,43,76,147,154,56,43,175,79,109,103,68,93,115,95,230,242,89,230,162,136,47,37,79,109,220,24,217,83,40,241,45,113,250,138,133,115,120,72,115,222,65,36,226,44,1,172,128,192,152,113,44,162,139,24,194,114,139,90,162,31,228,198,129,96,97,224,87,232,183,43,193,104,251,129,67,148,240,227,100,4,27,202,89,241,226,221,189,142,102,74,1,234,197,88,247,95,217,142,161,58,118,124,174,252,162,242,248,126,19,199,138,191,202,209,59,204,127,100,65,187,50,108,197,107,107,205,55,228,48,246,168,68,28,74,186,102,54,116,29,188,57,221,206,122,202,240,151,15,23,162,146,91,12,88,51,69,3,110,205,52,5,186,49,46,171,126,221,23,30,236,45,162,17,198,211,238,177,147,106,5,203,206,78,143,1,167,153,96,15,225,28,219,223,209,68,221,218,102,32,19,138,90,130,254,63,73,240,165,99,150,83,198,65,210,22,92,216,204,186,182,213,249,35,2,80,190,138,101,47,225,210,232,29,85,90,174,228,82,244,173,189,193,47,20,238,93,189,172,27,25,87,244,243,224,87,201,186,153,42,69,160,195,77,180,136,128,231,197,161,163,94,0,191,87,57,125,254,155,170,223,110,165,95,181,188,82,153,240,68,118,58,137,253,184,248,35,170,207,20,197,246,93,21,36,48,195,147,75,92,94,166,34,77,198,225,189,122,91,111,136,32,138,146,132,33,113,35,32,184,97,10,255,132,98,61,203,100,65,30,160,150,30,85,22,8,32,101,187,142,240,176,3,67,219,207,113,202,242,213,177,61,155,141,225,69,7,10,3,184,65,132,69,241,149,214,97,91,168,150,187,136,18,190,15,66,134,232,239,202,169,247,10,160,246,157,238,77,41,185,221,165,157,108,94,145,231,229,169,101,1,167,15,161,20,158,211,139,204,107,228,206,211,185,65,246,158,167,12,107,190,45,182,28,192,44,106,148,62,159,222,82,10,227,237,251,3,151,152,139,76,162,183,169,202,107,181,200,129,195,124,71,208,135,234,26,203,154,53,208,137,99,150,100,142,114,50,153,183,126,133,1,253,9,202,235,65,46,106,126,8,5,105,93,53,17,35,209,62,117,114,152,57,29,66,71,127,2,130,103,158,7,17,86,195,64,229,219,75,195,212,33,209,50,154,59,27,177,135,24,163,107,219,137,197,220,7,153,96,131,0,65,187,83,25,18,15,100,245,27,6,174,119,25,182,124,115,158,7,84,182,105,34,75,231,222,190,48,233,221,49,119,79,153,174,200,28,223,87,37,72,254,237,189,199,23,239,255,69,27,152,251,104,233,142,231,80,48,149,197,234,170,200,149,73,120,9,20,212,128,69,99,144,23,22,83,89,207,47,19,17,198,156,214,226,55,130,85,146,54,5,58,224,214,6,27,36,31,164,126,182,225,53,4,52,100,11,28,220,125,41,101,102,215,188,97,6,55,113,252,140,78,81,115,58,203,129,115,132,109,206,21,68,78,20,128,95,62,34,72,211,75,41,78,234,223,115,175,57,229,107,227,179,9,162,15,86,211,207,126,44,120,162,65,99,15,187,57,91,18,41,138,119,15,37,90,138,187,40,13,121,164,30,26,160,7,116,143,9,149,10,228,215,85,75,134,113,241,72,248,12,116,160,177,187,166,188,208,252,178,182,169,220,121,139,203,135,116,198,224,193,215,214,189,110,168,68,129,130,192,8,226,15,122,181,16,37,227,17,156,38,246,249,4,89,193,12,237,32,109,66,52,139,50,235,10,231,210,19,204,191,161,192,238,27,142,203,62,146,194,119,135,132,70,245,214,127,209,179,254,19,43,72,110,124,118,71,34,142,134,163,182,130,140,131,160,56,194,13,10,6,8,136,131,171,206,237,108,163,127,8,17,208,116,17,165,125,236,166,45,180,115,123,110,117,255,84,33,201,176,66,60,220,2,92,128,59,50,147,27,232,7,251,48,118,128,215,225,182,113,163,1,165,184,212,132,246,28,57,13,84,140,97,222,230,172,120,254,160,216,70,239,215,0,111,160,68,51,0,31,109,79,49,38,221,94,95,37,226,200,239,75,160,227,1,122,27,49,244,122,133,67,125,60,12,216,60,89,219,92,146,252,169,205,31,71,112,119,174,142,76,205,10,173,28,31,26,119,222,159,151,151,214,150,124,197,51,174,17,3,58,240,120,130,175,51,87,155,106,76,197,143,86,226,95,45,72,196,34,230,99,248,121,236,163,207,67,132,152,165,42,252,107,111,171,10,114,221,71,94,190,87,197,251,236,116,86,60,82,253,64,166,236,178,150,126,252,230,179,186,45,52,123,29,16,175,237,157,13,213,215,69,153,217,233,51,38,227,186,80,200,188,65,110,196,78,3,202,66,175,161,253,111,249,120,23,44,176,170,211,138,243,128,128,115,108,85,27,23,107,91,1,212,31,154,136,228,166,30,96,59,92,34,162,61,242,225,232,47,195,154,45,144,74,125,246,69,128,166,229,187,39,196,152,5,66,133,189,18,245,235,31,214,153,14,205,11,130,1,238,167,83,107,14,41,235,8,139,62,37,74,87,110,189,142,226,150,1,219,52,58,115,150,62,55,66,239,30,11,157,138,57,159,200,148,184,237,250,169,248,88,159,137,188,98,30,50,189,59,15,225,149,129,184,102,146,114,254,181,178,143,54,171,186,63,219,29,83,52,76,222,208,189,242,11,81,188,87,249,54,213,162,246,147,7,72,54,22,48,119,146,108,131,16,194,137,175,45,132,109,33,243,243,40,190,135,54,116,177,29,228,193,151,91,207,114,183,37,198,58,44,53,196,42,118,27,144,95,155,137,80,255,233,76,228,204,81,135,24,99,82,230,130,134,134,90,185,64,21,78,113,200,124,44,66,8,202,250,219,158,245,90,117,100,130,99,79,193,113,76,66,140,147,91,76,194,35,42,183,235,58,162,251,48,190,103,86,96,173,72,202,179,222,118,203,182,225,42,46,211,245,250,204,238,192,46,2,210,178,141,212,84,160,233,228,60,100,58,151,244,252,138,108,189,119,187,104,222,9,36,11,182,33,204,41,164,233,176,152,233,86,233,50,206,99,64,128,110,66,233,201,123,179,225,189,88,55,210,152,178,238,149,204,213,200,212,190,228,170,205,255,165,46,209,51,91,74,229,36,181,120,52,6,82,169,229,225,218,231,110,222,218,6,179,193,106,30,34,243,244,157,149,112,198,254,119,89,250,217,97,62,28,209,188,203,80,211,129,242,222,66,129,254,133,112,29,113,174,62,6,239,237,224,23,116,214,189,215,75,239,171,17,204,68,178,19,31,37,201,108,153,71,126,166,217,28,201,87,186,193,62,200,110,44,41,74,172,66,60,174,120,134,18,85,137,113,240,138,170,198,225,97,115,26,202,243,51,96,31,18,185,179,52,52,98,63,170,11,216,247,18,9,35,203,107,220,12,6,21,178,236,232,102,112,57,211,73,9,28,24,100,146,157,25,199,182,169,71,71,6,60,175,82,210,8,190,110,18,136,70,15,43,13,60,52,12,43,123,111,248,2,36,45,160,215,73,52,54,36,80,105,210,238,113,115,116,84,251,91,72,109,192,195,188,108,51,89,2,189,86,142,28,210,69,246,138,253,85,224,49,223,6,47,125,40,72,173,56,214,70,132,134,51,244,168,101,112,151,126,77,102,143,239,4,13,116,106,10,103,119,126,65,6,31,18,107,68,76,241,127,130,133,186,61,250,68,253,189,150,134,117,83,51,83,25,187,118,78,134,35,123,184,148,245,53,68,14,88,131,0,68,159,141,48,76,196,130,198,34,56,19,203,64,75,87,26,133,28,73,19,242,167,183,2,251,172,114,9,7,155,151,79,86,68,141,54,101,212,74,210,65,219,237,175,83,252,71,245,207,108,46,196,105,180,46,85,217,5,128,221,226,157,62,176,224,25,140,26,228,142,51,187,96,116,42,92,18,197,211,133,4,0,207,161,141,187,60,8,215,220,174,187,41,153,27,83,242,133,205,30,135,7,207,178,168,111,3,85,173,149,137,68,187,204,184,237,209,59,41,154,36,35,7,212,199,183,241,25,178,86,195,41,137,201,81,164,246,218,251,180,218,161,189,193,147,17,147,15,78,69,23,170,86,93,28,58,170,81,208,143,20,240,63,182,158,203,197,94,135,254,11,135,124,183,89,193,71,88,184,98,208,164,134,197,140,75,234,159,83,20,177,109,123,195,118,229,245,116,207,220,6,11,187,253,37,198,220,195,29,176,38,46,67,200,232,90,245,23,105,165,133,57,29,208,185,232,69,180,3,5,19,111,91,226,98,197,90,102,20,243,203,137,88,156,217,18,24,141,253,17,194,150,75,120,212,232,5,187,191,80,176,71,27,94,71,149,230,108,103,17,129,248,166,186,196,171,152,249,136,146,130,38,204,223,106,175,46,105,241,113,125,212,159,243,233,110,229,177,187,141,186,157,99,212,232,218,25,58,4,212,122,110,11,236,187,184,12,168,127,135,212,37,81,184,79,102,171,143,151,189,158,113,56,80,94,110,58,223,118,37,73,53,158,134,151,251,250,216,143,88,233,8,206,211,238,115,195,53,186,238,140,128,150,50,225,14,236,49,195,224,75,85,229,24,20,244,72,136,144,15,96,152,6,156,158,133,144,200,229,50,186,234,205,77,101,31,5,147,136,55,31,158,100,141,179,213,225,15,161,176,225,156,40,169,60,57,227,45,170,44,97,107,83,178,31,102,192,84,212,43,159,32,188,252,47,248,53,6,68,8,126,187,27,46,133,214,4,199,153,29,177,123,35,170,100,66,253,178,46,37,206,97,62,17,208,98,178,195,223,64,76,251,94,132,241,102,36,130,182,53,98,94,253,122,211,197,204,144,195,101,203,40,158,215,192,102,44,87,233,61,81,147,158,79,117,222,27,26,219,168,15,59,142,65,113,172,49,253,190,191,188,12,59,244,226,238,7,59,116,34,120,56,20,118,83,59,78,142,79,43,150,41,207,228,35,234,182,14,86,50,120,254,31,74,82,5,29,39,173,104,87,10,249,237,158,29,211,250,239,50,64,90,200,107,209,100,26,135,182,38,139,177,27,64,6,87,21,235,204,230,235,222,248,48,156,212,204,138,22,36,123,3,40,93,25,200,55,162,51,116,3,140,58,246,81,78,59,89,103,138,23,220,89,171,48,48,203,181,80,163,171,109,173,17,34,188,238,42,205,32,106,18,122,80,8,247,127,26,32,148,141,138,226,57,27,129,234,74,40,235,202,6,106,127,1,11,117,117,236,240,123,227,139,185,241,205,42,57,186,237,83,21,90,3,25,88,42,109,224,140,238,11,177,108,46,111,28,229,139,95,217,72,101,173,235,131,28,2,85,51,19,52,105,218,235,176,84,57,140,165,80,238,93,92,6,47,138,188,132,100,36,219,223,236,201,112,201,190,0,20,146,68,95,16,147,1,52,108,54,185,188,154,104,247,173,127,160,214,230,207,56,112,98,105,62,42,66,97,101,47,220,193,114,23,202,61,21,118,64,16,191,112,119,123,20,117,173,202,70,39,239,112,202,66,142,163,211,106,89,2,97,150,55,78,226,111,190,170,144,53,195,72,96,89,229,178,153,130,164,161,86,154,154,21,95,120,12,31,122,50,142,245,189,124,17,218,35,201,75,20,203,234,97,11,70,151,3,185,169,71,243,91,56,248,117,103,8,162,90,14,193,33,124,194,169,48,150,40,80,127,37,151,74,195,221,99,145,74,172,228,150,120,147,204,160,67,110,187,30,236,197,101,7,127,128,115,7,243,235,20,66,101,40,114,136,254,206,220,67,96,231,89,65,202,234,82,8,131,187,238,220,213,142,223,77,25,167,69,68,87,110,101,200,142,51,26,234,143,164,214,134,215,222,141,23,42,75,147,88,211,199,154,201,24,72,202,13,136,234,25,52,120,254,136,185,193,163,187,133,84,93,81,133,177,73,126,136,46,251,136,144,180,33,34,18,230,128,47,79,79,106,150,8,58,160,248,106,132,183,215,17,146,173,177,243,32,65,1,175,14,45,235,55,127,69,29,175,177,184,199,168,231,173,143,212,218,44,28,243,157,87,243,247,193,142,155,49,191,221,140,235,246,53,125,204,139,60,232,18,220,63,106,61,252,172,154,140,47,208,189,55,163,20,44,108,250,50,252,255,204,45,52,2,76,66,64,241,107,21,163,134,187,242,247,136,203,1,7,118,226,244,67,198,15,238,194,74,9,230,186,185,49,162,49,71,168,31,130,160,103,223,244,225,108,133,142,123,181,164,114,112,172,100,229,165,150,250,57,212,15,63,204,70,163,4,98,111,152,45,37,45,245,228,45,244,111,124,250,163,197,120,243,232,117,56,154,191,145,196,141,125,8,55,90,132,216,85,224,174,60,253,201,63,198,114,202,235,236,103,174,176,192,65,93,161,74,226,65,222,241,126,119,113,174,16,71,68,19,253,160,250,79,117,231,129,159,61,132,104,164,251,78,110,48,246,12,36,172,100,111,152,87,36,40,95,115,60,227,74,123,204,149,244,119,65,162,114,102,121,19,155,249,117,248,51,151,33,42,115,199,237,144,43,180,51,121,129,23,83,127,226,56,9,32,222,44,201,44,21,7,249,122,183,224,239,85,204,10,181,91,19,103,103,133,205,12,229,38,97,31,108,141,82,255,186,32,185,59,95,66,45,15,41,179,36,56,178,53,39,230,128,252,12,104,165,98,132,4,223,238,44,36,222,188,218,52,250,146,212,148,237,85,68,175,72,79,155,38,36,230,62,122,67,208,138,241,5,49,158,119,106,100,178,247,61,154,161,134,111,198,28,192,44,150,189,7,205,154,142,45,190,172,69,107,176,36,105,64,30,153,120,233,138,210,10,19,201,37,119,182,152,85,43,37,56,68,199,14,82,214,220,245,249,231,141,77,20,190,252,61,102,166,209,230,24,109,225,229,78,195,145,93,109,32,127,163,49,126,248,87,165,80,47,35,155,3,51,50,146,244,105,171,122,226,62,82,242,157,209,37,222,157,224,156,21,73,10,238,198,123,110,60,209,122,158,82,5,221,166,227,119,183,251,80,175,245,112,156,150,175,183,247,162,53,159,213,33,71,40,168,227,104,244,244,210,154,12,114,234,6,153,36,147,203,170,108,85,64,250,110,225,137,2,143,243,163,40,173,220,191,63,210,108,131,154,142,83,175,46,56,41,236,83,221,81,161,144,135,172,99,88,139,115,229,148,143,162,9,203,12,44,238,102,165,234,230,179,179,242,16,227,158,20,196,203,126,102,121,194,246,105,131,73,192,81,122,192,229,32,52,68,139,60,16,102,94,4,190,236,77,238,222,73,240,221,6,252,179,240,56,85,108,237,167,95,168,223,161,49,28,186,57,93,43,203,125,223,42,221,67,47,174,96,56,99,204,115,41,252,252,106,153,180,228,242,100,155,42,105,108,181,215,47,150,176,81,36,192,211,244,135,162,127,189,201,80,62,117,91,125,58,245,215,9,16,165,134,52,42,43,225,155,28,21,189,76,85,226,216,155,133,105,120,60,145,152,6,52,150,149,2,255,255,126,255,45,36,58,37,21,112,25,5,210,187,69,74,195,46,226,170,12,90,154,7,142,228,89,148,22,211,1,150,132,252,99,19,215,135,242,15,150,0,17,251,192,38,133,71,164,62,161,144,240,178,62,63,254,50,137,26,207,233,156,52,145,94,86,239,132,26,146,181,46,165,248,100,14,76,252,16,214,130,195,166,67,120,113,30,255,126,197,11,57,108,130,66,163,177,70,30,223,117,244,53,44,13,86,39,70,58,213,212,230,152,164,76,152,10,227,3,6,230,216,73,88,108,91,245,126,137,58,224,132,168,129,199,254,247,134,142,56,81,168,160,119,44,222,123,230,189,204,92,245,18,227,172,58,240,174,149,68,71,210,183,169,241,146,73,86,210,216,156,250,239,161,219,212,210,69,48,33,137,81,185,192,218,197,2,122,26,76,13,121,61,31,44,239,37,158,126,254,241,131,26,167,224,67,133,125,52,204,195,141,119,131,208,214,151,86,54,137,139,144,178,173,220,170,156,70,125,66,38,125,127,135,146,246,160,95,230,1,248,184,55,65,56,225,139,169,106,17,246,153,98,119,248,67,85,148,28,157,200,233,186,149,138,180,147,37,42,212,190,28,189,109,117,242,168,56,133,17,29,241,89,218,5,242,81,50,61,166,175,124,106,47,237,20,201,235,69,95,202,35,243,79,223,34,85,47,100,252,168,29,171,20,189,109,65,14,156,71,195,246,94,104,211,21,29,195,84,33,131,207,221,120,139,57,78,126,88,195,191,172,133,96,242,110,140,236,227,76,154,55,32,134,193,20,204,21,192,232,157,224,147,175,193,96,9,127,18,107,239,96,240,98,139,149,104,92,151,196,170,198,104,185,117,179,26,20,72,48,36,47,32,86,42,189,173,80,71,219,151,79,181,88,45,26,191,38,133,45,54,131,31,109,115,161,163,34,38,89,40,49,173,198,48,17,40,39,121,77,90,70,42,251,130,168,125,184,76,60,95,94,136,227,248,145,210,226,191,137,247,72,210,17,141,52,5,102,220,23,111,146,114,218,208,22,105,9,130,97,83,57,25,228,137,6,99,12,24,29,89,25,101,217,133,196,253,246,158,114,75,8,90,142,28,147,19,22,164,240,205,1,21,145,19,225,61,98,21,22,215,32,158,9,44,97,148,104,201,219,76,43,45,162,73,151,252,188,155,192,134,113,103,109,255,54,42,206,24,76,87,154,98,187,78,193,50,86,191,222,86,162,165,38,191,118,117,72,31,6,174,147,231,105,158,70,133,79,138,223,55,73,210,90,194,194,112,167,14,253,133,160,197,234,193,24,75,239,106,47,115,70,102,75,122,123,87,158,185,162,180,84,210,222,141,172,125,211,117,181,155,250,182,51,247,178,100,123,8,8,173,224,246,222,40,35,31,171,203,195,36,34,6,53,171,105,219,106,216,77,18,130,182,37,225,3,235,196,203,114,168,7,2,10,14,230,118,6,134,118,20,184,145,213,218,127,110,182,193,145,91,202,110,11,96,118,1,8,96,103,167,236,180,15,141,151,253,100,7,112,25,70,89,121,233,178,158,234,47,68,162,185,146,146,7,74,2,17,238,108,171,91,64,92,173,85,82,121,240,175,136,132,26,123,225,64,169,132,53,192,187,113,8,165,133,192,249,61,166,108,170,2,175,11,243,183,162,93,109,51,151,40,206,39,150,0,84,130,215,29,211,96,200,244,193,206,63,137,9,225,205,195,93,147,70,125,177,146,164,76,247,0,61,118,12,73,75,151,145,218,82,180,207,112,233,175,169,104,180,29,149,4,129,248,70,10,159,34,67,208,4,235,146,205,128,223,104,17,16,189,72,150,29,148,21,85,152,237,97,200,84,57,234,9,165,16,73,40,118,10,18,222,171,43,231,169,211,149,179,250,145,227,129,66,53,2,35,228,99,7,1,101,161,122,247,98,103,47,32,194,21,66,228,215,171,211,95,93,47,71,164,197,154,72,46,73,190,186,131,152,104,252,1,237,94,154,240,6,67,188,57,183,3,28,30,181,14,142,247,193,242,88,231,188,86,198,130,125,97,9,115,137,196,6,38,94,170,51,157,253,197,152,195,181,150,253,125,49,6,217,29,102,120,252,248,217,191,232,176,151,7,118,12,126,164,219,67,123,72,16,146,223,203,183,0,196,87,186,185,173,67,246,204,171,20,21,86,98,182,253,7,186,6,120,189,118,3,229,237,60,53,90,120,139,87,229,79,153,85,139,16,81,100,189,150,202,125,164,42,132,10,163,190,85,177,69,169,181,85,186,64,77,182,99,209,185,183,19,5,1,24,167,247,211,71,7,154,124,136,40,199,61,196,217,202,170,170,93,64,20,178,234,247,41,59,124,192,158,211,128,28,144,37,95,61,108,113,150,27,161,102,97,250,86,162,10,193,27,201,55,193,56,84,164,176,59,172,180,2,117,209,83,226,255,156,104,115,80,9,171,177,196,38,252,19,138,252,29,242,231,74,93,205,161,41,158,79,204,211,0,30,248,42,125,237,167,151,3,163,35,219,102,225,38,80,160,246,91,202,15,81,5,104,108,210,239,193,131,146,27,150,17,171,71,221,84,112,204,146,94,186,237,255,206,118,141,107,20,169,226,15,43,75,224,52,120,186,0,134,235,166,30,237,98,31,139,146,29,104,64,56,3,249,66,92,147,217,211,9,31,96,178,69,148,227,230,101,236,243,45,246,172,39,229,59,69,106,63,147,212,148,179,217,10,220,19,61,36,147,54,173,248,250,238,79,181,163,211,105,11,79,136,249,56,91,202,219,147,180,212,42,140,52,110,222,216,92,215,61,213,55,188,33,239,190,201,255,96,1,215,85,244,86,49,152,17,180,172,68,196,115,71,107,182,243,219,136,48,23,116,210,242,8,233,123,235,101,169,61,55,63,1,51,205,161,189,96,59,52,218,197,250,26,88,73,52,217,104,199,216,234,189,209,12,232,29,210,128,20,244,127,219,15,204,123,222,84,167,249,54,43,174,28,118,186,210,116,176,58,78,38,166,130,144,219,92,43,91,180,1,195,20,39,139,0,25,240,204,75,61,178,95,199,10,3,136,139,50,249,155,86,95,70,214,41,166,76,132,6,166,146,35,118,145,100,203,149,154,211,215,94,104,5,44,83,183,45,251,89,212,57,197,144,82,87,170,120,45,105,80,129,100,131,159,10,127,221,163,246,63,192,154,53,205,6,127,117,223,24,147,216,93,28,239,163,214,221,158,12,149,255,83,88,41,136,165,138,1,254,6,44,25,143,22,104,150,94,24,196,25,238,193,216,170,71,103,76,33,52,211,45,205,235,134,41,248,86,65,9,32,255,32,95,30,250,243,251,43,119,170,184,85,107,38,21,98,231,54,218,226,16,72,174,6,221,38,211,120,221,119,117,120,67,209,251,33,84,155,163,163,47,53,96,15,51,76,204,87,153,85,170,54,66,113,12,174,34,104,136,90,62,76,103,210,150,82,37,200,148,44,89,113,229,33,173,240,114,61,21,131,193,157,216,181,193,207,219,29,42,99,21,186,158,11,145,155,4,216,22,244,162,245,120,63,128,57,117,241,213,60,251,251,149,87,153,99,63,22,75,81,103,103,239,199,225,110,110,88,38,125,240,116,161,226,53,38,183,2,223,68,221,87,205,73,201,187,129,82,39,35,166,109,116,96,250,15,15,242,104,227,86,21,140,48,172,188,54,214,185,33,4,199,217,220,218,185,44,244,170,133,64,135,231,135,80,159,130,65,112,36,250,209,241,226,74,174,130,199,202,217,218,87,161,162,130,254,242,150,34,63,117,178,224,76,211,80,201,111,72,69,137,93,62,24,23,249,115,80,83,95,17,166,84,223,132,120,6,53,34,199,208,205,80,109,133,213,92,49,18,214,230,123,245,73,80,228,94,106,241,165,216,84,255,96,177,178,90,92,5,219,185,153,238,208,136,79,150,15,232,139,179,52,146,235,158,62,239,136,154,45,92,190,176,19,91,40,214,152,149,209,222,247,97,175,74,250,98,231,204,211,233,2,168,136,18,202,254,144,196,95,80,187,220,123,31,164,176,207,23,248,81,3,174,138,206,65,83,36,29,70,32,71,21,227,157,254,228,2,4,215,71,27,252,9,219,49,49,23,248,163,43,170,192,126,75,198,97,91,38,182,93,204,141,250,187,145,128,158,103,88,73,178,191,233,253,231,3,169,38,117,163,181,44,217,91,138,15,239,82,140,19,78,13,168,212,227,46,202,225,130,28,150,211,105,239,25,243,208,76,174,52,37,170,87,125,141,221,90,95,41,51,53,205,112,75,54,129,102,51,87,222,28,117,188,154,174,103,66,55,95,247,97,127,31,107,22,117,195,115,97,108,19,52,70,179,212,190,15,8,213,49,139,119,170,201,169,8,199,203,166,183,90,134,185,169,133,135,9,251,66,104,187,220,182,164,82,21,125,132,197,116,14,169,241,211,104,107,169,17,246,140,46,235,236,23,84,93,180,72,214,10,39,185,197,170,73,30,43,35,75,114,202,126,143,2,127,114,206,107,25,116,183,11,43,3,146,183,121,214,79,26,240,70,203,45,88,74,11,137,245,21,38,44,66,143,61,168,69,76,204,92,186,121,203,15,46,213,237,131,23,220,68,52,188,111,185,48,81,35,208,159,218,44,76,71,236,152,61,103,92,247,136,123,88,196,109,213,91,97,190,88,164,237,171,59,217,231,230,51,149,191,114,162,41,91,249,249,25,109,183,231,25,48,30,35,44,156,199,26,146,144,26,85,40,82,54,83,253,102,88,29,52,114,160,176,0,95,4,217,205,123,143,97,62,149,15,178,195,166,156,183,183,170,183,54,232,197,211,241,7,215,241,86,159,151,161,98,116,91,139,14,111,22,41,155,5,43,72,245,246,20,196,27,62,112,149,21,253,42,111,173,148,25,42,199,41,53,84,169,17,246,92,25,211,161,41,159,252,62,243,4,19,121,43,66,199,74,28,208,193,205,33,126,84,173,30,16,26,179,244,95,188,90,6,16,178,251,191,203,121,130,161,12,52,170,24,14,141,2,163,190,6,52,205,187,57,245,252,9,53,65,132,246,126,90,3,26,54,238,222,74,237,35,163,214,83,43,254,139,112,244,74,15,241,20,255,217,117,129,81,233,181,187,160,29,30,245,145,199,163,29,171,87,228,222,50,229,60,139,23,152,179,33,23,124,180,100,223,209,21,191,93,240,166,209,66,67,28,158,237,190,62,80,188,131,151,72,22,159,212,121,139,49,254,184,106,134,122,77,103,165,81,70,69,174,0,7,179,26,152,234,23,37,155,212,120,59,223,226,216,189,170,9,42,206,10,123,140,130,214,229,149,218,74,215,152,151,235,170,53,33,209,190,193,105,61,182,108,226,176,32,213,78,117,106,23,56,121,61,82,213,107,121,107,114,185,20,99,151,57,44,105,153,238,174,24,192,241,254,251,80,193,143,221,0,58,227,109,190,129,185,22,131,37,221,129,34,101,144,152,33,250,198,183,73,236,69,174,215,68,64,181,94,33,132,40,149,248,252,133,191,99,245,130,21,43,49,211,224,204,33,169,240,230,120,107,228,46,140,168,241,32,17,95,48,147,101,16,176,251,83,160,253,105,171,56,79,198,139,36,48,144,120,99,236,171,235,56,117,196,171,178,244,170,61,79,183,32,202,66,50,130,211,99,78,199,73,255,242,30,138,199,156,129,107,187,182,255,144,201,230,138,199,111,154,10,126,232,144,99,117,187,160,97,221,177,191,5,239,139,181,240,32,249,247,61,216,207,154,217,224,246,49,118,3,194,107,197,233,3,242,99,182,58,45,151,176,238,101,118,57,44,123,195,112,61,129,140,199,98,25,86,104,2,141,220,161,128,109,32,8,89,147,249,11,246,14,255,195,81,233,46,89,37,122,225,211,69,132,120,138,169,254,0,72,208,116,247,244,60,55,28,135,15,11,28,174,65,40,253,148,181,6,57,220,134,224,205,255,225,22,228,49,200,228,182,179,141,237,217,9,47,114,203,57,24,173,236,15,100,174,120,178,73,84,236,141,45,188,142,252,66,85,56,248,161,247,21,240,209,145,198,24,158,227,106,158,18,248,204,21,1,99,35,91,187,157,228,98,106,35,231,158,103,53,119,135,62,168,207,48,5,118,236,117,255,204,65,60,49,102,180,55,82,149,17,205,214,182,198,223,77,55,234,99,156,29,161,90,22,138,7,126,240,213,226,110,63,214,97,71,161,203,216,10,31,25,62,71,223,163,238,97,14,115,144,121,112,103,4,186,16,66,51,105,110,65,111,32,206,82,213,231,74,107,199,255,85,48,249,19,123,45,142,3,104,77,86,181,99,8,158,50,3,108,43,23,113,246,189,180,107,134,24,9,137,36,178,9,176,197,63,33,63,164,220,217,243,175,16,197,210,28,16,109,192,143,193,240,252,44,124,8,108,179,168,171,135,107,32,216,49,136,123,109,133,33,176,167,185,189,30,120,210,5,211,14,127,118,199,147,121,246,58,33,239,172,251,87,223,152,144,13,169,216,65,87,59,132,210,118,116,30,68,72,68,155,103,230,81,33,26,21,82,14,73,251,183,147,86,222,194,97,44,169,244,82,155,95,253,205,116,91,165,44,64,31,163,242,253,93,23,26,209,14,33,97,62,148,115,63,247,111,137,13,9,163,215,243,223,218,10,114,82,195,219,233,24,117,167,173,231,13,156,77,46,231,130,200,122,169,91,49,229,215,250,140,73,229,240,44,212,41,117,112,31,126,218,196,58,241,101,147,26,195,148,98,153,198,104,87,90,149,128,60,239,177,50,49,11,242,239,230,196,182,89,101,80,215,168,143,70,48,53,53,215,22,99,194,129,245,128,163,40,102,25,14,99,189,152,35,135,13,16,105,137,188,32,226,246,176,38,30,36,65,146,145,240,83,103,2,107,133,21,172,41,239,28,250,134,170,228,80,43,122,211,87,111,228,168,29,171,79,69,62,152,18,69,203,96,169,144,83,50,37,65,208,1,113,46,2,67,73,221,2,181,73,185,209,20,163,237,141,222,221,69,220,155,12,177,239,150,84,234,58,111,225,3,31,187,110,139,78,139,234,186,202,73,72,34,125,59,43,206,220,68,6,49,123,14,147,144,206,60,95,31,173,236,244,239,64,11,119,89,226,7,117,175,218,115,104,165,195,209,202,140,132,15,6,115,213,209,69,238,7,89,37,249,156,158,67,124,208,100,194,232,148,52,214,125,166,99,224,152,46,109,187,234,230,51,60,189,191,120,28,13,67,152,105,230,40,147,153,215,16,149,231,51,170,159,88,97,228,216,161,34,87,65,129,153,213,186,140,150,104,113,164,25,120,246,58,78,221,124,33,179,135,7,220,233,68,9,15,123,101,187,131,139,95,177,234,29,215,24,57,107,53,194,252,161,247,70,224,245,22,104,10,41,39,213,190,186,249,159,32,28,196,55,153,225,205,18,72,227,70,120,101,199,237,132,225,10,124,88,154,151,215,153,67,177,100,244,99,169,37,127,97,122,188,216,217,79,187,227,87,69,243,42,139,151,228,79,141,154,88,240,7,29,255,165,129,150,70,173,212,207,194,245,243,54,210,111,168,77,71,140,61,28,64,106,8,196,60,68,154,18,110,22,252,63,172,163,34,138,138,105,145,101,244,110,11,75,95,244,220,224,140,191,243,85,79,137,128,246,173,146,28,1,68,146,131,190,104,107,105,10,183,141,149,204,59,176,190,91,3,180,254,33,47,24,58,4,53,177,211,193,103,6,161,57,156,191,177,108,76,83,185,133,20,167,103,26,75,148,54,239,124,182,71,95,160,157,60,112,22,149,136,53,82,150,241,250,192,35,199,124,207,79,66,84,131,7,63,140,114,16,166,158,30,0,73,131,202,144,116,46,50,92,60,23,147,147,14,236,195,64,128,205,63,248,146,1,49,182,30,96,166,149,196,243,131,88,93,119,167,118,22,137,56,179,169,223,194,48,235,4,196,19,7,210,55,75,235,92,247,15,83,174,53,132,172,34,214,91,205,147,70,34,195,103,132,175,68,245,7,227,205,122,160,7,72,137,123,51,243,8,7,82,113,179,53,171,249,151,156,75,82,204,101,194,53,247,2,201,39,125,151,8,4,189,190,40,95,41,72,181,116,99,58,100,136,118,164,13,191,107,164,69,39,229,204,2,248,254,87,112,64,247,106,105,66,193,73,104,67,75,181,248,105,39,227,153,139,164,41,215,76,244,118,95,99,56,13,94,20,67,33,205,238,108,249,81,105,60,177,18,155,229,73,173,205,78,164,144,180,161,191,210,203,150,190,16,55,228,110,203,212,118,15,103,25,67,152,199,2,36,17,117,201,129,88,197,112,153,188,44,58,196,160,131,198,150,19,223,209,224,90,127,231,71,1,40,82,195,12,242,223,233,211,68,210,32,176,1,106,119,179,211,33,221,107,210,194,227,213,88,3,122,19,130,145,199,16,66,179,41,215,40,18,133,40,191,25,49,31,101,27,16,11,60,119,20,186,217,168,204,250,28,173,159,38,166,106,2,35,49,133,30,16,174,41,134,5,154,247,72,247,171,23,225,89,228,141,14,221,122,56,188,54,252,90,121,252,169,8,168,27,59,138,8,245,70,122,230,65,165,140,117,136,206,11,169,209,146,240,8,234,87,27,21,119,136,227,84,138,65,172,42,227,109,202,167,67,219,148,125,32,179,242,176,224,42,235,163,145,195,63,145,122,135,21,164,85,133,249,38,87,145,90,3,151,203,189,99,172,189,248,86,207,193,226,138,44,42,179,190,99,83,127,92,185,32,159,58,246,239,241,246,235,227,205,219,169,42,77,149,0,212,210,172,47,174,68,122,133,7,78,152,86,30,65,58,84,65,40,113,125,213,150,112,146,1,46,218,175,242,206,243,3,22,233,246,135,129,96,57,130,15,151,104,91,220,169,42,107,34,44,14,229,23,97,55,219,134,96,213,252,133,227,120,195,1,46,17,86,212,120,130,91,248,166,233,51,66,254,106,183,117,42,44,36,169,196,204,173,91,96,109,228,171,28,189,45,250,183,121,167,12,164,164,245,225,177,164,170,138,139,161,93,90,83,85,26,198,104,106,203,108,131,144,196,153,22,188,229,99,101,228,68,84,115,35,112,19,129,18,184,189,228,220,191,206,106,106,126,188,176,42,150,208,166,249,215,76,49,78,167,49,137,16,206,210,203,31,206,130,158,233,143,12,168,123,152,246,181,110,5,9,143,33,8,20,72,188,117,52,80,18,200,90,101,236,228,207,56,241,5,217,53,40,86,180,67,214,216,113,227,232,42,4,123,161,29,225,131,69,60,164,193,158,200,54,177,14,32,137,153,25,110,144,200,246,156,194,61,16,88,79,24,113,181,5,133,88,82,165,176,38,251,156,45,231,111,141,37,120,107,195,254,51,23,243,143,18,30,92,222,216,31,27,168,49,204,158,75,50,29,108,173,189,227,162,147,5,233,159,187,189,71,11,14,221,15,68,223,60,234,186,227,182,193,229,131,242,98,115,34,126,30,59,20,56,101,249,9,38,148,110,79,181,179,181,29,240,61,110,204,161,242,160,184,30,38,49,180,136,78,22,156,1,249,192,217,132,67,3,250,243,132,141,231,10,84,231,97,122,73,28,88,116,105,213,193,202,47,183,216,19,80,71,55,14,123,32,194,193,121,208,234,113,73,234,146,93,189,196,164,129,140,201,122,187,60,67,10,121,125,17,246,192,134,16,58,220,3,66,88,63,127,197,206,164,85,151,11,143,43,109,35,215,25,113,90,99,90,205,22,209,122,41,112,244,206,253,59,161,241,168,251,89,190,186,151,193,3,142,219,1,102,68,147,87,145,74,157,223,203,18,248,51,21,219,92,9,251,196,149,82,153,103,27,151,252,54,21,4,47,205,56,172,183,3,29,202,225,83,16,70,15,21,227,219,225,178,248,157,53,135,57,185,163,37,123,167,126,80,187,41,181,17,191,207,228,71,37,158,205,118,62,248,250,194,59,71,214,167,103,233,25,73,205,178,231,128,78,53,113,28,73,140,86,87,88,87,238,196,137,77,234,138,39,195,39,117,89,71,3,123,115,108,182,175,148,180,142,193,159,155,141,71,168,172,98,136,187,112,36,25,146,98,217,160,17,34,77,55,98,189,208,173,74,117,181,200,124,182,123,12,56,62,149,214,75,112,112,107,126,242,224,85,234,235,172,131,250,233,229,99,14,92,194,36,21,156,167,172,215,243,141,214,57,79,177,104,94,207,160,8,3,102,237,50,84,126,223,147,92,211,221,196,52,130,24,176,159,132,65,156,131,71,126,4,33,143,91,104,28,50,153,209,95,181,28,75,113,70,67,27,109,192,39,174,135,252,172,218,211,94,160,62,199,154,79,251,16,22,195,15,22,140,253,36,242,85,72,147,22,121,33,25,195,83,123,67,179,160,66,85,146,45,114,228,93,116,57,55,217,212,216,31,50,167,229,242,19,107,240,57,124,255,142,191,249,148,74,39,163,43,156,151,201,207,220,46,185,27,203,141,137,15,92,5,101,198,159,181,2,84,128,42,9,10,185,221,175,55,128,247,131,98,98,146,152,8,240,110,121,15,67,233,2,21,145,83,105,182,127,239,100,153,185,165,225,124,59,119,26,175,192,81,4,98,42,93,184,200,34,68,13,134,123,5,43,164,167,218,32,67,79,70,4,196,254,131,50,201,157,133,80,79,208,242,155,224,237,252,110,27,249,238,45,235,77,229,182,93,205,123,32,5,3,78,154,69,213,117,216,130,198,46,105,47,78,76,255,250,230,254,99,106,218,110,21,186,185,71,173,236,91,67,119,59,38,141,202,223,39,183,153,239,2,113,168,121,123,54,217,55,237,94,11,1,190,38,16,170,216,147,239,88,254,229,245,220,108,102,247,55,229,237,173,167,179,231,185,82,226,109,53,81,87,15,55,217,69,204,109,3,164,126,143,193,42,141,227,90,36,226,83,128,215,12,177,216,190,140,85,129,225,224,25,74,141,225,41,192,131,60,180,130,169,191,124,58,1,135,224,63,27,9,138,244,124,167,199,35,2,120,62,25,218,238,78,254,29,125,60,19,72,168,31,194,52,28,70,137,193,242,203,2,91,43,138,248,5,135,204,165,116,67,10,198,121,98,100,238,143,43,94,209,39,162,232,129,176,41,254,158,40,195,167,51,206,48,151,123,55,64,65,233,220,176,238,73,3,129,139,129,242,194,88,95,199,147,187,75,237,229,171,30,89,115,154,239,165,169,235,59,98,63,177,91,115,84,142,203,97,103,79,66,2,91,157,207,14,45,246,75,211,46,69,228,42,158,158,132,228,178,36,163,98,194,69,11,37,186,217,155,206,244,54,125,9,122,128,237,37,159,232,91,68,159,92,116,153,244,199,136,214,88,171,186,117,98,60,171,163,232,45,147,151,123,170,237,130,250,83,244,253,125,237,248,178,237,111,15,63,154,122,147,51,15,60,204,111,139,245,231,228,185,51,36,176,237,79,48,4,150,130,163,59,120,29,126,54,40,104,116,142,238,121,237,189,107,191,35,8,119,113,131,109,108,173,24,9,142,108,8,49,51,202,146,192,173,17,1,241,218,187,124,164,246,139,220,70,143,192,138,152,227,175,189,77,209,86,106,63,119,2,159,194,2,163,89,30,119,83,127,152,98,60,123,145,96,155,67,36,124,94,20,93,243,98,219,253,143,238,124,45,39,226,10,242,116,227,184,129,242,21,192,51,94,97,231,64,148,237,211,59,177,198,10,216,238,62,4,109,230,168,9,132,240,215,0,86,29,251,174,78,233,243,27,50,92,197,253,214,2,123,146,246,222,140,146,148,108,237,15,4,222,247,156,154,132,10,40,151,8,10,70,114,132,181,145,136,176,233,7,169,57,111,204,90,220,67,215,132,40,150,216,152,69,54,80,43,171,67,46,100,140,33,185,115,58,154,35,242,247,6,43,31,174,39,80,101,216,73,40,132,227,201,14,85,37,194,50,3,146,118,78,76,36,211,88,24,220,98,14,33,120,148,222,160,20,160,118,195,167,167,92,128,37,5,53,38,72,206,146,123,57,213,135,200,109,71,35,239,160,169,225,222,136,217,153,92,67,165,51,105,189,47,203,155,237,217,9,216,232,29,225,177,49,205,230,232,177,124,66,19,114,207,198,114,64,45,161,124,66,110,85,157,81,102,32,22,83,53,111,196,27,133,196,169,162,223,120,126,235,105,163,132,221,206,150,110,214,226,227,26,172,30,160,193,251,235,130,209,125,165,77,58,39,115,187,196,165,24,148,33,237,15,73,76,51,191,88,212,165,137,89,220,47,35,108,174,114,48,214,113,39,163,180,185,63,88,233,112,0,120,241,137,168,24,63,138,54,82,207,177,179,66,101,46,177,222,3,52,49,103,68,5,246,78,182,234,55,35,29,9,19,192,144,78,132,224,162,148,96,89,62,61,109,6,178,98,241,196,88,167,22,196,56,11,139,35,94,112,213,134,206,158,24,179,145,144,24,250,44,149,253,67,210,8,0,244,166,243,0,180,234,155,46,191,122,41,93,142,70,154,56,201,66,159,207,162,193,63,26,46,204,221,206,29,100,232,161,225,87,106,130,47,154,66,253,50,33,4,103,71,134,239,65,137,220,222,90,200,221,145,253,16,73,125,66,213,113,239,82,209,96,85,98,196,87,143,30,250,24,217,92,120,23,123,71,64,51,243,204,192,239,147,75,30,170,32,161,187,95,176,78,235,9,173,103,112,9,93,39,55,89,66,223,135,55,158,58,28,249,4,53,46,175,138,48,65,135,70,136,1,162,20,77,236,103,41,150,88,60,162,162,221,75,62,108,114,118,100,40,120,101,241,122,160,0,109,225,54,161,239,188,6,149,136,139,198,177,179,32,43,126,52,149,57,217,226,136,215,201,55,32,213,229,87,28,109,36,223,42,151,98,71,107,140,255,230,206,183,84,127,109,108,57,226,37,11,140,188,250,216,82,32,241,186,122,68,173,128,81,29,57,2,23,81,10,233,198,238,113,91,11,7,17,184,180,159,230,116,147,143,120,21,24,1,220,118,49,16,80,204,12,78,41,111,117,193,98,56,148,193,219,160,156,230,56,126,1,172,183,95,204,229,202,75,218,108,245,33,254,8,58,127,98,209,197,176,100,60,110,139,133,80,43,42,133,200,12,216,121,186,89,171,171,252,220,132,121,46,180,75,79,8,157,91,112,112,34,247,193,147,132,119,236,30,223,101,129,132,197,45,134,84,202,92,249,70,208,211,158,206,209,216,202,106,106,96,1,80,249,182,103,247,124,85,169,42,212,67,245,112,214,156,147,143,216,186,202,197,119,5,230,23,226,199,79,150,253,252,85,1,193,145,96,212,15,165,73,246,244,50,249,165,95,254,252,112,62,100,237,167,234,181,238,164,135,224,175,19,225,82,153,135,122,209,81,59,123,165,21,127,99,54,56,18,153,226,205,161,95,202,7,79,126,124,92,208,244,46,5,176,227,206,200,16,140,97,250,131,187,54,34,117,52,52,206,150,201,200,182,45,201,225,80,46,100,113,199,193,12,116,224,253,59,85,244,248,161,239,199,164,208,63,114,103,163,167,185,246,203,19,33,102,53,236,108,3,205,170,155,230,73,204,142,178,233,7,187,171,191,137,254,60,149,218,98,40,42,87,10,3,146,207,162,67,113,25,173,141,27,217,143,225,97,164,2,208,116,57,181,180,112,233,183,114,62,110,197,29,79,155,213,7,115,94,60,229,43,83,79,119,171,196,20,78,239,233,51,87,6,32,5,59,166,121,176,193,0,2,145,150,183,130,7,36,179,159,57,212,66,179,111,151,174,27,202,58,35,12,121,174,29,17,69,244,46,87,1,173,238,194,40,107,180,147,157,209,184,241,104,251,123,242,164,42,31,93,118,82,79,189,47,105,102,158,30,210,164,16,47,140,226,212,235,70,176,78,30,247,193,162,137,19,102,181,9,248,156,29,149,41,73,2,34,88,183,198,106,254,34,124,19,150,32,99,71,253,14,190,121,107,200,168,38,114,205,153,112,139,204,16,149,101,168,127,70,40,156,157,78,179,113,220,4,46,194,124,96,187,139,83,36,28,169,50,209,88,176,134,217,219,55,18,186,165,170,11,175,60,216,24,132,95,218,101,75,194,66,64,184,1,56,29,86,92,86,243,122,204,124,185,21,219,37,111,68,82,178,41,69,127,186,121,223,219,84,41,169,105,54,165,5,128,102,12,67,130,217,46,97,233,254,216,57,121,145,39,46,34,136,82,175,114,153,215,16,119,138,116,45,137,136,230,59,132,221,97,0,150,250,153,211,18,141,254,212,157,9,45,217,191,16,24,133,130,194,151,189,230,92,187,55,12,247,187,8,115,13,29,222,207,59,92,230,24,146,39,165,2,54,188,107,162,190,178,185,22,188,187,172,42,164,239,225,92,55,26,237,230,59,0,75,13,33,47,250,12,161,72,4,185,159,244,163,208,129,102,176,239,178,99,211,97,92,241,234,19,85,70,42,189,55,130,151,119,38,50,126,239,231,40,153,124,51,220,63,234,208,163,211,170,63,37,231,40,152,183,204,90,227,246,208,8,196,85,209,243,92,102,174,199,27,110,145,27,1,158,35,176,107,152,163,227,75,21,184,120,238,57,155,201,3,194,165,57,117,211,136,236,17,128,98,177,93,111,46,94,137,155,5,70,101,212,42,190,79,218,62,143,123,151,171,59,185,175,9,185,245,254,235,130,177,69,252,61,157,29,229,105,128,229,192,180,37,158,214,254,13,129,64,53,209,247,56,140,241,97,250,119,174,250,204,68,97,184,208,29,20,117,25,12,105,234,224,76,223,115,197,177,7,235,247,19,42,20,85,78,15,81,181,192,153,4,160,176,82,106,67,212,194,132,240,190,45,126,79,192,122,42,28,239,165,14,139,14,152,62,129,78,48,66,45,207,97,240,165,178,129,234,169,234,59,12,218,46,249,54,76,20,225,254,11,128,237,242,61,101,16,36,207,202,13,244,205,77,104,204,51,50,1,5,95,211,151,110,251,255,185,191,151,167,102,140,98,163,129,27,38,60,101,197,176,252,212,232,136,208,157,118,51,83,111,209,188,223,78,130,47,24,91,236,170,159,121,55,3,202,0,155,212,180,173,74,37,161,201,91,108,166,174,27,239,60,20,65,158,225,185,85,89,127,76,244,27,86,150,160,201,13,106,79,143,68,200,236,55,107,243,76,149,215,188,118,183,198,159,26,140,136,153,211,173,159,16,57,139,31,93,149,70,6,141,53,112,164,6,184,239,106,159,222,67,158,26,121,136,223,39,46,140,67,170,202,95,88,179,214,186,212,140,8,12,94,34,77,226,17,17,162,210,225,20,151,177,74,9,100,126,170,73,142,33,144,154,131,151,205,235,28,118,190,6,137,98,50,237,7,94,230,246,133,250,179,160,199,89,103,9,203,111,37,216,185,171,40,117,6,107,87,133,165,172,22,140,220,186,41,97,187,57,196,102,220,15,169,194,254,170,33,237,69,78,127,4,30,119,51,251,153,50,179,106,153,232,131,96,100,243,32,78,78,223,191,150,158,39,30,201,43,12,220,233,103,223,247,156,210,213,52,75,203,102,114,46,35,81,55,175,89,207,53,66,198,247,164,132,51,64,124,120,125,108,35,3,184,185,202,162,122,93,58,198,11,176,146,221,62,6,92,250,135,230,38,135,125,76,89,22,140,243,110,14,212,252,94,85,234,86,142,168,158,28,94,124,183,180,213,174,80,170,142,88,83,48,201,169,249,109,156,83,4,161,186,46,235,85,83,86,244,7,52,58,188,19,124,117,35,105,13,185,191,47,252,142,77,194,147,27,235,193,126,138,65,32,134,118,24,227,33,219,142,48,59,235,147,8,183,94,74,184,233,4,78,44,55,20,167,190,216,145,187,105,253,135,93,68,15,204,76,81,176,255,140,229,106,248,29,154,109,79,247,240,181,62,181,2,28,187,26,136,254,180,92,158,140,81,194,11,245,237,48,28,57,112,87,48,233,185,13,251,113,29,199,152,222,226,254,232,119,199,120,251,113,224,226,89,162,215,74,115,227,118,145,197,176,156,161,226,233,79,170,203,163,113,106,144,108,25,85,163,91,129,143,75,216,56,51,156,13,106,116,79,121,79,152,139,128,156,169,174,94,228,172,49,115,235,134,42,145,67,107,214,122,8,49,156,210,218,178,151,67,247,169,0,56,164,44,222,132,125,193,90,153,10,15,29,69,159,229,98,193,181,138,65,215,14,65,89,116,209,247,174,22,72,27,141,214,94,36,169,203,34,123,25,192,248,196,238,148,225,225,253,59,44,43,96,2,26,21,96,123,202,184,253,55,162,172,81,29,95,172,11,133,235,129,224,183,94,71,85,29,23,65,246,242,222,224,109,136,62,63,145,107,248,167,160,195,242,204,135,237,253,107,53,91,77,34,207,186,102,102,84,28,14,44,194,39,232,156,245,132,232,76,102,63,206,240,49,132,118,211,1,70,75,30,42,3,149,207,174,223,160,227,64,221,207,62,64,74,186,97,163,201,85,231,33,84,76,132,47,66,189,73,137,21,77,184,234,168,231,171,247,76,32,229,1,138,186,116,5,60,65,8,57,133,57,165,125,190,51,105,242,89,1,141,234,53,168,34,89,88,55,63,52,10,226,116,30,115,175,214,74,234,133,248,48,242,17,47,155,75,131,130,124,207,192,199,156,142,142,119,122,3,15,49,119,155,82,80,171,180,19,29,133,31,247,222,9,245,206,244,22,69,12,85,112,250,23,97,212,191,32,152,5,115,206,31,197,19,250,138,219,130,3,84,216,78,11,80,213,13,161,199,128,136,64,7,53,223,221,247,108,10,139,128,47,36,225,149,145,94,106,22,86,14,62,13,43,181,226,188,243,228,218,231,144,137,51,46,13,237,21,72,193,233,132,28,220,20,8,4,122,72,237,253,246,222,239,176,0,105,79,66,248,100,211,232,18,217,109,127,11,57,83,34,123,20,60,137,153,193,152,195,96,127,130,205,193,250,201,146,44,174,91,40,108,105,104,231,248,136,114,61,136,124,241,31,128,186,165,230,218,248,76,54,35,51,13,80,241,46,59,34,214,111,253,168,149,252,124,4,81,171,131,110,58,165,172,223,166,5,45,240,154,11,195,26,117,137,238,192,41,98,219,74,113,235,25,234,46,9,144,57,228,196,138,122,230,73,229,42,31,24,18,166,217,131,24,95,177,251,18,240,249,10,235,122,112,16,73,162,6,70,8,231,108,54,87,216,194,174,60,128,244,234,190,212,213,146,128,244,187,133,74,29,128,195,60,234,120,57,168,116,97,234,156,164,173,42,225,70,177,38,184,43,121,148,186,19,207,224,19,253,214,102,184,227,77,205,223,63,242,184,142,75,134,48,96,96,243,151,83,50,87,123,186,147,177,176,62,113,237,99,50,108,201,126,185,218,219,219,241,171,55,44,28,194,49,254,72,63,140,63,178,112,216,15,3,183,189,172,230,154,116,254,246,200,73,82,76,41,15,168,132,147,25,115,46,90,151,15,180,193,60,237,178,105,74,47,191,86,59,221,105,248,98,26,140,49,149,76,146,83,229,173,71,134,78,113,171,186,136,69,240,102,228,167,251,86,198,107,167,79,180,215,210,44,58,98,143,79,188,44,133,107,54,248,165,231,104,149,127,120,62,61,159,252,239,41,101,177,140,108,77,90,49,230,151,125,115,153,80,213,191,17,98,59,202,149,108,239,233,23,177,26,245,216,97,198,111,31,75,248,67,177,55,207,157,212,233,20,69,111,167,232,80,21,144,9,32,199,43,200,181,141,195,9,143,237,154,121,175,158,247,124,39,117,184,48,30,51,103,4,19,16,28,84,98,72,251,204,19,32,194,90,236,170,52,202,181,96,92,120,59,184,47,169,66,177,66,217,150,2,50,182,17,7,131,32,76,227,116,70,174,42,90,163,89,35,33,148,41,240,228,253,31,107,201,210,198,152,13,86,70,112,248,225,121,155,252,134,99,239,2,8,98,108,44,76,227,160,213,104,141,16,130,205,118,253,123,220,48,200,187,80,35,114,62,45,188,107,29,79,220,169,244,147,158,70,102,122,231,232,149,243,55,230,115,28,185,83,39,179,237,221,41,170,240,44,143,39,216,163,87,213,39,157,118,225,99,80,190,57,171,200,20,2,7,166,112,211,127,0,69,167,84,159,62,190,37,46,1,194,192,152,94,188,50,203,38,220,128,2,108,156,32,255,174,254,89,135,44,97,26,237,37,203,70,32,238,3,218,163,213,145,32,244,50,67,233,217,30,131,135,205,0,46,29,143,192,99,180,144,34,96,7,74,212,164,44,215,190,88,252,138,84,97,50,251,203,44,252,175,247,178,155,79,180,28,8,80,184,205,211,9,119,150,32,91,150,4,102,212,89,217,117,71,241,163,146,90,113,142,34,228,139,182,236,101,97,47,152,88,91,161,47,37,246,4,92,89,174,210,15,82,44,118,249,82,198,192,155,172,220,91,168,190,233,35,204,84,24,113,139,102,112,42,108,124,19,27,148,60,159,78,38,239,90,234,5,193,172,28,58,20,182,11,43,162,123,82,184,178,167,19,172,101,106,3,69,146,204,136,46,70,35,133,166,103,74,245,222,246,76,109,232,173,160,36,50,39,140,112,227,59,10,18,127,30,232,161,113,146,233,102,248,171,205,245,154,98,101,53,109,65,36,82,31,241,200,111,216,27,255,10,48,237,213,82,221,17,250,248,215,19,150,56,175,233,19,230,30,233,199,3,100,121,176,189,175,63,20,231,105,113,121,51,88,188,231,109,177,58,34,9,199,121,226,157,183,76,219,41,224,204,61,144,124,88,115,7,214,74,179,178,42,119,144,76,98,58,171,185,134,98,123,177,87,100,213,183,165,147,22,29,151,19,74,146,102,107,158,201,189,0,79,185,36,105,84,104,73,152,103,132,228,196,39,102,113,158,255,56,212,198,37,172,139,31,238,98,184,182,42,69,108,194,245,23,205,45,21,76,115,162,181,174,59,213,233,59,240,184,32,212,226,199,126,11,205,232,217,187,51,197,98,94,117,94,105,152,41,48,22,181,8,146,134,207,30,237,255,240,248,183,191,187,67,210,16,185,191,54,193,2,218,22,99,176,191,233,78,247,165,4,231,131,62,37,109,244,76,194,155,129,212,66,0,101,223,162,211,13,80,169,217,16,68,4,155,216,61,35,76,162,144,217,34,209,73,249,250,253,186,140,124,41,237,124,22,168,97,40,95,47,38,188,204,216,150,184,229,185,174,113,3,154,126,238,50,165,170,12,27,209,53,157,76,118,81,252,10,140,31,103,160,43,171,6,65,205,225,154,85,121,76,216,228,29,241,184,200,160,225,86,4,199,137,80,222,199,30,9,163,177,222,131,91,24,3,147,148,250,20,157,246,166,73,41,246,240,159,85,53,172,227,255,239,211,188,78,85,210,198,63,175,149,47,251,126,139,167,245,143,5,212,41,111,52,133,173,37,114,122,63,214,212,6,98,213,169,140,241,226,233,95,47,169,91,89,117,116,228,30,78,123,163,137,11,19,142,70,121,166,215,141,20,57,100,202,75,131,150,222,136,204,79,199,205,220,46,9,129,92,116,55,148,224,138,82,32,255,250,251,59,239,99,130,13,77,106,233,191,37,70,164,141,160,195,95,192,54,39,178,189,46,17,135,160,255,198,62,249,69,57,5,74,22,165,134,209,143,179,8,28,219,212,141,148,242,233,231,171,234,72,186,111,252,84,120,130,253,206,225,145,123,88,19,194,150,24,168,247,191,92,162,203,56,94,55,72,199,142,76,50,37,253,13,142,159,201,100,153,149,243,217,240,192,204,254,66,239,13,23,161,166,210,210,120,35,7,141,179,109,83,57,146,163,16,195,195,129,214,39,34,155,158,29,244,128,143,18,233,121,150,87,80,227,145,22,207,133,15,10,172,79,48,176,209,68,66,116,22,167,251,162,90,108,98,148,98,84,46,164,185,106,48,68,247,163,112,24,15,78,105,58,173,251,63,10,252,91,83,158,57,178,63,21,40,113,231,82,251,191,134,27,71,131,203,150,222,121,48,211,181,0,62,91,119,123,77,252,183,63,204,142,239,211,87,244,129,213,2,81,221,210,104,182,252,35,116,91,198,172,132,76,148,89,3,74,8,96,232,19,70,18,232,128,18,145,133,229,23,13,93,175,174,68,105,55,192,81,168,1,142,132,193,37,99,188,243,51,14,26,6,195,29,149,159,115,77,169,235,22,66,101,37,224,43,146,152,141,191,222,67,12,74,51,124,129,141,11,37,97,10,50,79,112,123,54,180,89,156,10,237,145,90,99,35,116,84,163,249,196,70,103,144,16,14,13,233,42,5,213,163,203,205,92,6,212,210,195,46,141,24,15,1,215,71,30,31,0,4,24,15,93,217,35,228,173,104,78,117,69,140,243,168,119,62,223,200,171,123,57,184,88,64,53,21,153,201,0,115,146,22,119,84,228,16,189,124,213,148,92,15,178,58,83,69,87,213,137,150,254,92,197,211,157,193,255,150,115,3,222,48,64,41,28,208,245,211,29,135,30,54,205,250,93,94,57,155,196,37,151,90,109,165,11,249,203,106,37,64,103,100,206,108,40,181,36,238,104,208,241,13,26,75,32,133,101,47,132,226,199,174,3,139,186,102,206,19,21,6,166,44,184,63,7,255,61,155,90,233,60,161,86,176,23,97,194,237,176,234,251,116,25,226,11,145,130,13,179,158,222,252,26,235,132,202,117,229,195,232,158,52,183,96,47,219,235,210,51,146,103,15,241,22,194,84,73,169,183,142,81,87,203,6,251,105,254,2,56,164,156,137,219,71,205,59,144,217,70,38,73,57,73,70,131,114,20,249,181,50,184,200,127,251,28,30,92,166,20,252,156,141,128,223,214,176,136,154,210,238,245,131,123,1,114,106,160,197,74,57,4,101,162,185,66,93,219,192,225,68,181,231,74,140,180,121,162,114,142,129,187,73,66,192,218,128,28,39,134,251,0,243,48,55,112,205,204,80,144,149,109,100,247,179,224,228,198,89,225,7,131,170,203,32,130,21,23,249,122,134,208,160,239,23,10,91,107,175,27,56,59,104,18,71,209,245,4,165,227,203,178,69,1,114,130,119,193,171,64,18,182,174,155,16,84,193,55,150,153,90,251,6,94,161,253,223,200,143,16,162,175,93,211,88,243,61,118,144,204,158,163,68,183,243,85,64,42,52,155,32,39,213,93,165,239,188,8,152,93,228,136,71,213,103,158,57,252,54,203,34,230,180,127,56,46,22,5,220,190,103,131,16,64,135,114,68,112,125,205,54,108,113,157,5,31,108,20,138,80,149,170,6,114,65,223,21,159,246,115,158,118,220,203,106,20,66,204,213,59,225,109,136,122,206,137,104,126,66,24,195,83,223,112,36,241,154,219,254,255,248,77,142,202,95,86,171,11,42,188,7,245,217,138,49,224,34,61,121,28,57,25,3,70,9,40,108,107,108,211,160,206,154,77,59,153,161,172,200,23,84,154,131,94,122,115,145,19,13,234,127,86,154,80,149,41,50,98,186,251,36,10,53,159,223,103,104,248,67,154,136,228,46,83,243,36,33,221,157,116,83,109,54,89,171,46,252,120,86,50,220,23,252,185,68,192,125,37,223,233,232,110,16,135,71,175,199,37,75,162,17,48,41,32,39,131,59,145,161,20,26,149,216,99,1,188,240,87,189,8,24,224,227,175,207,156,151,37,76,105,62,202,86,172,9,208,0,186,72,213,78,103,254,132,192,92,113,242,42,224,245,111,181,206,107,130,182,212,63,185,27,28,41,112,220,209,148,172,7,140,225,168,124,67,203,73,76,139,41,226,87,30,125,197,216,76,36,160,168,194,202,181,254,134,0,148,187,242,94,239,72,9,21,148,168,92,66,161,144,73,37,106,39,176,127,116,44,183,89,77,47,138,171,10,169,117,147,107,92,29,184,69,82,220,13,130,34,214,197,214,6,152,46,180,228,77,211,162,47,149,169,145,56,196,174,84,97,93,246,216,30,34,211,137,93,8,161,64,73,106,220,60,107,201,86,86,124,51,9,66,244,168,8,22,125,147,200,68,23,23,247,75,139,87,52,54,5,53,175,14,218,127,126,196,104,220,88,75,122,52,99,226,111,88,137,95,199,196,6,2,87,182,200,67,133,205,210,73,174,53,64,12,134,84,182,73,199,7,65,88,7,24,83,187,31,81,35,236,229,37,177,78,42,143,233,94,241,133,195,255,185,7,218,41,43,231,129,3,23,175,147,37,26,188,70,161,146,126,24,12,38,104,96,209,143,227,254,9,198,24,192,4,227,59,174,32,240,251,5,34,127,186,184,83,193,62,41,187,33,39,239,28,16,118,164,36,171,230,136,212,122,52,86,39,165,85,61,117,145,179,83,209,229,95,227,85,170,136,187,59,115,217,179,60,48,21,67,116,58,14,145,89,89,35,229,5,152,217,138,26,10,189,186,35,83,210,174,165,179,87,168,247,177,43,213,204,247,37,109,164,15,182,108,253,170,140,83,214,151,0,211,81,132,64,43,30,248,18,149,11,44,248,98,107,216,117,38,96,167,82,124,152,140,191,51,40,145,207,31,45,189,144,120,151,236,172,94,196,233,80,172,227,217,187,197,174,24,108,153,189,212,51,44,156,203,149,74,222,95,240,202,168,235,255,91,215,29,201,254,8,156,120,134,162,218,172,153,51,254,189,4,238,93,65,227,158,247,6,74,254,126,91,58,204,84,167,188,223,91,180,79,147,62,150,135,231,158,186,185,126,91,13,115,56,108,78,17,205,175,102,47,20,157,73,175,89,225,242,141,119,215,191,236,127,186,252,109,87,164,233,22,213,98,137,134,97,78,12,13,150,30,160,164,149,154,108,167,156,104,67,228,187,152,143,135,114,154,47,7,21,89,131,179,34,253,135,40,109,220,0,127,213,82,85,64,161,1,113,242,240,66,56,78,225,32,59,26,177,12,19,79,6,212,120,217,177,7,187,76,85,122,133,9,219,81,118,109,201,21,119,47,122,30,190,208,241,78,63,16,91,45,44,253,13,228,18,228,187,96,222,132,166,77,100,226,124,234,61,59,174,40,117,26,163,5,65,107,1,95,18,170,126,100,95,216,113,98,15,186,246,133,3,205,221,228,159,206,212,201,240,175,113,198,72,187,233,28,104,253,239,168,246,139,120,149,143,34,146,39,220,145,216,114,243,109,219,151,117,75,33,162,197,181,62,19,128,118,215,96,101,54,68,109,7,171,133,54,145,1,15,56,224,58,123,172,196,221,3,133,158,85,120,21,246,153,166,1,17,66,48,223,247,230,95,15,223,253,250,109,197,6,190,76,117,7,245,185,143,129,188,191,215,198,20,90,194,172,250,78,233,102,182,120,92,116,208,65,80,84,235,77,57,207,221,127,16,225,96,218,22,104,216,138,195,220,101,236,3,109,87,42,198,95,96,164,202,48,107,45,17,107,246,2,243,229,149,152,83,101,228,91,80,183,254,119,138,201,64,197,135,212,15,171,151,44,69,249,208,188,57,253,250,157,63,153,226,131,155,3,224,56,103,144,28,200,229,192,71,131,21,129,219,235,31,205,144,191,146,253,77,67,78,216,241,242,228,244,174,123,254,65,212,26,35,218,100,1,28,145,247,37,254,116,206,212,40,200,241,209,30,238,181,165,198,211,144,87,158,142,226,70,232,172,134,42,41,121,222,108,17,68,45,47,16,56,26,77,188,99,188,115,118,252,245,11,51,25,44,27,128,31,32,221,54,158,109,102,53,155,4,245,73,26,234,174,198,111,64,52,171,213,56,173,114,145,152,204,191,140,179,22,93,211,35,243,221,136,103,201,155,0,41,110,183,62,30,176,252,190,108,47,23,203,166,160,173,17,124,11,189,244,44,4,13,133,74,224,19,240,200,254,27,57,180,193,89,67,10,147,117,127,169,109,96,98,8,10,21,26,37,181,81,247,202,60,172,58,139,237,116,143,140,46,52,176,49,71,231,243,80,161,14,219,152,25,62,178,232,150,162,47,124,122,155,221,61,212,160,224,158,136,39,24,24,159,93,108,6,145,49,245,189,95,22,153,45,100,83,225,12,97,201,53,242,6,2,23,210,62,108,106,189,178,189,42,64,247,93,171,233,157,196,159,103,239,240,111,60,164,43,151,83,198,183,204,37,185,207,113,120,130,103,10,4,90,144,149,54,51,128,82,233,108,119,172,85,82,79,203,25,184,22,113,202,100,46,34,121,95,234,102,43,243,242,211,223,171,133,152,188,18,134,67,47,2,94,11,17,249,254,0,115,150,132,37,136,76,84,42,91,153,219,138,4,233,91,164,1,243,162,12,134,75,244,55,138,40,252,182,74,245,239,39,45,157,106,56,118,130,15,190,210,138,155,237,239,57,182,77,69,190,113,237,27,178,173,214,149,95,133,12,106,208,89,63,129,174,51,58,43,142,103,103,138,109,123,39,101,45,171,1,233,54,34,208,63,121,151,241,39,0,207,133,172,100,150,134,5,196,133,184,171,253,201,139,186,75,242,123,53,174,38,249,95,72,254,64,108,209,147,37,177,166,69,3,178,95,255,47,41,195,232,6,73,119,89,203,225,150,80,125,183,56,28,82,112,89,167,237,204,73,139,208,233,7,168,90,35,244,133,50,216,254,240,80,227,187,102,135,27,213,192,201,21,175,236,199,100,103,36,247,192,4,133,40,125,16,111,25,177,101,37,180,170,49,230,106,169,123,73,58,231,60,106,230,145,116,211,215,134,199,90,18,243,210,29,225,79,224,248,108,204,147,215,73,244,75,154,145,95,137,151,193,154,146,43,242,175,5,62,42,113,9,57,70,59,133,75,165,250,154,186,143,167,22,47,252,137,102,87,181,104,147,207,195,205,88,18,48,209,126,182,35,179,10,30,175,25,163,6,202,85,185,99,52,208,20,19,242,169,14,253,227,198,85,129,68,11,99,112,59,79,142,105,188,254,123,148,88,153,70,89,84,106,236,34,181,241,51,194,138,62,14,134,245,151,117,235,135,10,139,140,204,146,196,96,242,114,217,131,102,142,129,65,132,108,64,29,42,233,238,33,19,249,17,222,195,125,158,124,202,110,18,183,150,111,199,70,127,8,180,135,203,33,143,230,228,90,44,43,118,241,57,168,162,89,150,106,102,32,60,250,93,143,196,239,12,214,171,73,180,196,199,210,115,112,192,13,9,123,222,213,148,91,19,101,236,101,30,146,43,164,10,156,101,112,151,65,89,151,245,154,56,37,194,99,153,35,80,3,93,62,246,6,68,42,34,155,207,230,215,121,37,213,153,36,165,136,123,181,144,31,215,138,161,118,151,196,108,131,138,93,13,158,182,138,197,184,0,44,139,70,0,204,15,179,245,235,111,229,61,119,1,248,135,70,169,50,116,69,16,223,77,223,248,176,81,63,205,104,150,100,178,216,215,7,243,251,58,16,117,59,213,117,122,156,183,0,72,126,132,100,86,92,240,106,174,220,88,51,75,166,111,176,139,229,215,30,173,166,246,249,201,187,24,250,69,150,214,224,9,17,218,53,173,213,254,11,60,19,32,202,124,40,131,51,99,223,226,217,190,252,29,14,39,73,199,37,180,254,114,46,169,46,109,205,172,86,62,198,113,209,186,149,211,122,42,239,238,71,133,33,39,217,86,131,68,199,243,26,0,143,97,215,140,217,34,11,55,192,118,66,69,203,200,128,171,40,250,94,127,204,76,168,232,153,226,37,150,4,8,22,177,75,64,204,39,19,45,127,173,174,14,222,159,184,66,88,61,250,133,231,114,166,164,33,157,77,203,31,222,189,111,131,178,107,117,10,165,203,18,211,117,188,134,254,238,158,123,143,231,245,189,89,21,88,66,169,241,24,26,210,108,105,249,56,37,196,36,26,110,237,31,34,198,114,72,218,133,14,40,38,0,26,218,130,56,146,228,86,253,43,36,112,162,58,232,178,162,105,114,186,74,187,229,215,195,101,241,14,24,95,246,248,101,255,68,164,79,41,18,245,65,11,228,167,132,169,52,170,196,91,52,224,204,230,105,193,231,254,49,143,85,42,221,140,233,18,131,116,86,127,103,136,113,15,23,95,39,90,226,59,168,56,73,43,227,171,60,251,5,66,24,207,129,225,168,127,243,190,108,173,215,76,110,107,75,120,242,147,252,217,57,234,116,1,133,221,90,162,174,126,61,236,200,53,105,71,155,217,56,85,6,214,13,60,119,234,225,200,186,152,215,237,225,105,85,252,240,252,38,75,220,200,6,243,144,34,127,161,14,197,107,63,75,235,195,72,44,27,244,129,243,201,59,241,45,173,62,200,145,232,76,142,208,183,15,77,119,157,26,157,170,159,104,206,13,248,132,68,229,234,196,252,168,229,154,203,44,177,54,200,235,132,93,52,10,196,60,152,226,220,27,98,85,215,82,144,161,12,76,202,47,71,231,225,223,105,35,201,195,174,188,10,168,199,141,255,108,74,166,226,33,4,203,54,202,178,27,127,250,86,181,225,246,70,219,65,173,49,214,202,71,22,67,184,54,90,182,251,202,40,14,235,63,201,190,75,65,15,33,62,81,56,157,55,187,67,3,223,5,188,105,211,72,202,95,229,207,20,1,219,121,116,56,5,116,227,97,48,200,192,252,86,238,56,125,89,89,89,100,76,5,180,81,31,33,111,202,211,182,51,25,81,28,239,153,125,85,67,149,136,118,157,65,84,65,43,74,86,81,238,45,7,227,222,145,234,95,152,157,225,22,53,47,59,189,252,16,40,26,171,155,247,98,73,206,206,218,9,241,152,213,3,15,107,123,100,86,78,2,200,194,8,78,101,235,150,113,69,232,13,102,131,200,41,240,126,186,238,184,20,62,218,235,221,116,53,44,20,219,104,254,112,139,81,119,100,253,105,53,62,247,159,166,75,128,64,51,7,193,108,154,115,34,146,127,75,102,17,112,81,35,33,255,104,228,11,97,24,252,219,214,122,235,2,28,34,128,252,220,126,248,87,48,200,149,102,191,135,59,48,111,142,210,22,87,41,25,209,90,114,67,98,234,128,53,45,198,155,116,161,66,14,216,226,63,200,18,7,20,213,60,221,77,128,48,20,142,208,197,61,210,161,90,77,80,146,220,80,168,29,93,171,234,195,182,134,136,225,120,206,94,147,141,52,199,5,155,74,143,12,252,50,79,254,135,78,145,222,143,150,128,28,137,206,79,88,83,195,0,213,182,223,225,201,191,235,235,39,175,202,211,139,11,109,8,255,251,237,232,33,37,250,169,184,42,115,205,55,220,211,160,190,225,201,208,87,227,181,15,92,123,111,172,104,71,23,236,206,214,177,119,77,128,149,238,102,224,147,48,143,82,158,83,179,110,112,12,75,86,190,48,208,14,156,92,140,55,64,14,23,106,204,140,48,97,72,62,247,14,217,121,31,224,171,233,69,177,129,185,71,17,87,96,138,78,19,178,198,229,37,235,51,51,208,149,100,111,39,54,197,126,215,245,125,0,18,64,157,246,4,183,62,21,82,209,182,193,74,163,255,99,143,38,119,30,171,116,62,129,241,64,167,205,128,48,19,141,208,126,96,231,17,94,11,123,106,132,252,127,95,4,217,84,100,231,9,56,144,178,55,92,107,154,194,164,113,19,93,117,152,188,49,241,135,95,131,177,63,10,247,179,86,47,153,63,125,70,239,205,3,48,196,135,152,123,146,5,229,21,112,255,72,4,180,42,148,238,234,211,163,111,223,49,176,36,101,182,121,145,65,242,151,27,181,100,235,212,127,238,78,165,2,36,188,117,89,217,137,39,32,249,156,72,106,48,65,177,35,119,166,109,125,93,15,74,133,194,177,8,208,79,4,23,216,37,3,20,67,12,40,52,11,160,213,96,177,234,40,240,251,19,126,81,186,153,249,204,11,91,78,70,238,38,31,243,13,156,49,165,95,148,218,155,179,139,30,216,15,153,27,164,59,189,173,159,141,146,16,21,167,183,161,203,82,140,66,150,182,16,73,40,176,102,55,118,132,173,249,137,117,137,145,90,53,86,164,24,152,171,14,64,192,181,253,238,22,204,59,115,228,173,155,232,15,108,250,14,135,190,177,25,54,114,152,83,38,132,125,185,243,134,112,168,170,99,100,155,125,107,46,165,146,10,12,243,170,39,155,195,220,140,129,9,27,178,166,144,112,200,134,3,146,228,27,60,217,251,147,93,72,56,196,158,217,177,53,113,146,111,93,172,7,71,165,196,105,120,164,255,79,158,235,183,45,61,139,128,87,87,24,202,89,236,50,129,135,90,217,225,115,211,102,32,22,124,87,167,76,209,47,193,179,5,176,1,172,115,53,235,4,198,69,17,146,1,156,60,169,171,3,154,137,1,8,160,180,39,33,145,194,221,167,74,225,147,22,226,175,161,190,155,99,104,36,234,28,206,255,153,106,146,140,248,208,160,159,129,189,81,79,151,34,57,191,19,60,238,132,173,126,112,102,40,167,236,248,169,15,165,62,167,248,117,241,242,52,190,179,82,62,174,253,135,166,242,116,101,164,25,44,212,205,199,182,51,26,85,54,11,16,243,103,183,145,84,222,115,193,84,191,14,243,49,214,76,187,20,39,29,243,173,156,181,219,109,64,24,75,52,179,28,160,231,99,85,33,44,165,96,91,1,116,151,203,247,43,74,128,179,172,198,31,77,89,11,160,120,13,159,140,72,217,110,79,78,206,233,178,98,50,152,74,216,73,133,249,217,70,75,56,129,241,107,234,100,37,103,60,16,188,2,190,11,70,104,226,153,93,247,153,143,161,19,20,220,168,207,59,231,145,117,83,136,104,18,107,25,84,26,105,116,169,98,24,122,32,236,228,193,206,223,235,29,238,49,143,225,2,196,58,61,127,140,102,14,140,100,86,158,130,245,106,213,21,195,130,77,170,38,87,189,28,239,43,9,141,221,172,71,101,23,117,196,97,176,152,245,228,11,197,252,84,206,70,36,202,196,205,27,80,137,39,25,75,180,73,162,224,150,97,44,115,24,151,153,239,190,250,64,81,124,193,49,199,158,225,239,216,251,150,194,11,43,136,66,171,93,122,163,101,50,248,76,30,251,201,114,80,75,69,109,212,155,11,141,217,118,95,15,127,174,149,147,216,251,178,89,253,92,51,157,16,128,60,144,26,219,47,131,125,182,76,241,164,209,6,26,7,92,85,220,173,245,230,208,98,209,124,70,173,192,190,132,55,211,201,186,183,60,108,73,202,134,11,25,98,22,219,173,173,140,39,222,243,91,17,177,81,168,144,244,94,105,34,211,227,16,134,9,254,20,51,4,182,243,203,82,63,238,89,246,230,147,185,200,52,129,113,141,167,177,99,18,247,119,52,84,13,203,187,89,98,35,178,30,13,149,205,77,136,197,164,183,202,225,132,158,34,253,166,180,170,81,56,53,16,116,34,149,120,212,66,17,226,5,193,175,148,81,251,230,23,177,141,43,79,103,153,84,172,51,44,242,34,237,188,74,225,118,144,129,40,56,96,157,254,134,231,14,209,110,23,26,41,253,29,33,247,80,149,196,100,34,23,183,198,124,246,191,174,56,254,31,119,127,229,154,236,190,38,98,101,91,126,182,201,156,27,210,62,101,17,18,95,17,62,112,173,218,95,8,203,29,169,3,23,137,111,219,234,54,156,50,148,31,227,60,56,205,74,105,149,45,57,162,39,83,232,38,150,169,204,161,15,212,82,220,124,196,127,1,123,135,186,208,13,210,224,127,223,143,131,107,123,201,10,21,58,99,135,64,212,81,242,174,16,20,198,65,72,42,58,79,59,206,26,52,133,57,223,232,6,119,87,13,47,214,82,42,153,242,77,203,163,205,22,188,0,129,78,179,114,86,63,119,183,248,180,74,200,49,174,239,118,170,130,129,69,61,251,182,192,219,239,214,192,255,58,247,26,49,105,232,74,79,103,145,214,114,231,134,233,230,182,242,244,118,246,117,136,107,207,19,107,184,247,251,123,157,189,96,101,189,162,223,179,99,10,86,165,128,163,231,16,244,57,68,233,20,250,104,28,166,38,49,110,177,66,17,127,187,199,42,122,137,238,193,107,95,247,227,189,113,10,75,176,213,70,136,141,144,164,87,37,42,23,127,141,164,183,78,139,218,128,235,216,244,18,237,172,200,24,113,21,112,117,16,59,41,136,9,155,210,169,170,75,221,91,65,24,147,102,178,110,106,220,193,124,222,37,240,191,119,132,54,85,182,115,221,35,234,48,168,174,45,235,227,126,189,190,94,228,240,101,211,112,91,127,57,151,48,255,55,129,17,139,254,252,80,114,75,182,22,51,188,91,109,69,192,230,36,179,138,232,162,3,131,1,137,52,56,241,139,77,224,236,177,175,210,192,80,187,135,105,224,116,81,229,132,151,223,232,67,207,191,76,55,255,26,58,42,239,48,161,0,251,40,166,214,231,173,40,122,99,165,8,170,84,14,152,38,0,60,172,198,70,127,95,75,16,127,6,6,164,64,141,172,238,59,222,131,224,43,38,141,127,96,100,62,2,30,34,180,54,230,3,150,5,231,193,31,96,61,201,7,121,144,136,49,68,114,1,180,193,165,67,117,98,92,230,45,153,167,120,227,39,220,201,40,218,176,242,79,255,176,197,84,44,219,188,24,123,109,252,180,10,54,56,205,152,158,23,34,226,122,114,118,86,190,135,145,210,139,53,111,80,254,12,33,99,114,50,69,174,102,63,40,134,203,163,241,201,210,132,197,30,194,21,41,67,111,169,59,137,176,140,87,223,35,219,148,41,17,47,87,132,177,195,184,155,62,44,57,51,61,166,176,0,78,17,239,248,132,24,90,111,0,114,11,243,116,156,217,62,172,237,169,184,102,49,203,132,170,173,228,19,92,247,110,129,213,51,246,166,189,117,14,122,133,32,168,49,250,110,109,130,233,47,207,247,73,245,53,4,163,18,37,68,143,96,159,144,46,41,170,94,167,114,150,192,69,209,251,219,13,111,213,186,98,240,94,100,151,249,137,215,40,31,202,233,102,233,87,154,45,180,231,125,239,156,180,218,112,223,97,62,42,141,65,252,126,67,80,247,250,233,208,232,35,192,160,163,194,226,126,10,45,236,6,185,108,216,204,37,163,11,79,111,48,215,146,155,158,134,141,203,55,89,61,222,33,78,82,125,74,58,124,11,39,39,25,125,19,251,109,165,69,192,6,62,4,243,172,60,180,97,171,114,245,37,98,216,173,83,172,42,223,203,123,98,129,233,163,55,50,102,117,207,223,131,8,155,151,246,17,163,194,153,249,69,72,100,93,139,51,97,70,143,174,24,21,44,73,67,97,203,26,232,224,113,226,185,74,242,203,51,164,179,209,188,168,1,102,93,74,120,214,135,191,193,209,7,112,218,199,145,10,92,23,239,226,242,205,187,159,126,171,125,35,158,53,118,74,19,183,224,31,116,118,13,32,211,205,92,131,123,48,181,32,124,7,233,247,254,24,251,109,189,0,184,187,80,73,194,94,100,239,81,170,145,20,235,132,230,56,141,90,22,151,198,88,153,66,134,20,94,237,62,58,110,218,255,50,111,198,109,211,202,21,39,7,30,238,147,85,35,154,58,236,112,221,70,102,211,120,115,74,109,188,70,229,214,191,122,134,120,195,231,217,122,35,113,9,110,154,50,82,32,35,111,159,191,205,52,223,124,250,77,32,228,68,131,215,255,245,107,10,80,105,104,31,4,173,207,219,31,219,171,182,182,254,211,181,183,202,185,238,165,167,38,248,72,193,90,249,154,165,80,64,209,68,160,49,226,93,135,143,48,97,211,47,187,29,120,160,203,115,39,87,245,227,220,244,5,60,57,251,126,42,117,244,81,69,98,77,242,210,249,188,19,130,253,198,56,95,174,249,187,185,215,132,16,226,25,29,180,25,54,143,69,121,134,79,117,180,218,210,211,236,58,207,231,69,104,95,149,166,212,59,105,131,68,83,21,233,177,143,135,83,237,99,3,20,58,123,234,249,128,199,117,238,163,124,52,215,100,124,76,146,61,253,192,135,196,87,201,115,149,98,141,214,85,252,207,188,13,34,208,166,93,132,22,39,44,115,121,203,93,78,137,69,196,253,197,120,148,36,21,208,5,95,43,5,122,145,41,160,12,117,201,143,36,62,133,73,185,73,185,155,194,182,166,248,96,33,9,112,7,42,39,42,203,253,23,196,161,187,66,234,58,217,44,48,7,139,47,158,58,153,179,83,189,27,100,164,156,234,199,98,117,100,38,11,24,163,169,221,244,159,173,191,177,229,194,60,25,229,142,239,38,104,95,145,238,47,214,188,90,21,66,126,66,111,210,228,101,36,242,172,130,97,234,90,20,62,166,38,11,198,159,44,245,249,131,27,135,234,87,83,2,62,185,253,129,60,125,165,26,164,138,148,193,87,246,201,45,72,3,33,31,191,29,45,33,15,238,109,8,39,100,38,195,128,83,7,133,205,161,144,113,161,194,75,111,13,7,188,92,227,251,80,96,18,64,26,145,25,40,183,204,243,127,122,119,214,146,16,231,175,187,101,92,23,25,172,45,195,139,252,212,135,73,86,24,33,203,30,64,143,202,39,238,180,143,39,141,32,30,65,76,186,57,211,14,143,45,98,183,16,106,103,221,249,6,53,137,24,139,142,183,198,247,95,139,222,54,254,33,32,110,206,70,243,213,3,192,199,172,149,164,83,182,93,148,177,50,21,141,173,13,238,107,195,127,67,110,37,112,43,142,183,230,190,209,160,162,156,23,27,134,24,34,52,140,72,249,61,178,169,148,8,130,66,147,91,31,208,121,252,240,86,4,49,94,172,145,170,231,175,155,91,81,34,65,35,19,119,54,89,16,204,192,75,121,73,147,188,144,117,13,228,38,41,170,216,212,138,219,190,30,66,160,168,25,44,46,139,91,239,138,252,75,214,254,70,38,167,102,27,83,199,3,87,193,132,173,198,46,20,126,199,149,77,169,28,80,101,104,137,62,96,184,186,195,156,232,54,165,152,181,234,109,221,187,146,210,235,81,120,213,202,4,54,76,73,143,91,58,186,245,234,169,42,230,22,18,250,90,107,166,223,111,105,64,154,164,4,224,90,136,137,59,115,161,111,33,203,195,109,85,228,153,230,42,60,71,72,5,2,62,18,247,95,210,226,191,18,86,215,250,188,187,220,235,252,237,222,248,38,43,49,68,167,200,78,234,221,147,5,179,21,224,63,87,13,134,86,163,63,36,111,99,183,191,107,252,17,109,125,244,237,227,124,248,96,249,123,151,124,55,89,15,60,83,228,51,167,78,178,149,160,185,115,84,80,74,205,223,140,130,90,11,7,178,123,40,235,140,10,228,159,27,22,21,27,35,97,198,101,3,45,152,101,159,133,198,240,50,167,96,88,76,87,206,44,39,249,11,105,101,233,91,94,0,117,182,228,62,63,40,7,175,93,108,94,109,10,13,105,155,235,242,84,115,42,225,207,146,64,214,155,15,160,204,116,101,205,129,106,90,130,161,1,205,66,106,134,110,197,2,121,251,255,76,57,17,131,177,22,249,53,191,239,3,209,175,23,202,194,236,120,82,27,150,175,201,140,218,92,66,6,242,27,242,72,21,153,249,76,147,161,201,108,133,37,82,63,157,26,16,157,157,53,227,144,45,33,251,159,166,102,14,146,8,130,61,71,232,239,55,149,154,94,62,201,196,46,66,64,182,197,173,177,174,129,184,239,93,144,26,35,78,229,198,0,35,11,0,24,58,31,116,17,14,148,173,217,199,57,30,154,70,63,65,205,96,139,15,161,221,167,15,248,53,144,210,247,198,28,89,183,77,185,161,137,46,60,33,250,124,201,6,162,14,149,173,139,246,183,196,97,174,62,140,41,85,124,32,241,157,180,188,116,43,88,101,206,143,162,87,136,175,53,8,137,29,26,223,233,139,150,187,232,66,160,175,236,60,249,74,124,88,0,169,71,249,158,190,158,10,136,161,14,192,129,205,123,206,139,139,194,116,10,232,178,229,135,29,133,175,175,159,206,251,200,116,49,111,179,231,204,59,114,82,198,44,18,188,92,104,214,214,0,99,131,131,20,13,139,95,163,166,89,240,125,147,162,92,27,236,208,194,108,76,213,90,135,100,0,183,53,71,191,95,49,61,227,177,149,62,19,73,102,79,254,208,162,75,217,114,173,130,116,114,179,103,102,51,151,84,216,208,210,52,137,180,99,72,124,128,249,247,136,183,36,28,249,242,125,70,239,231,22,75,183,222,194,216,180,98,166,182,159,27,186,214,74,253,234,220,112,80,103,58,215,113,70,28,68,149,92,181,110,119,67,179,179,9,96,140,249,194,72,173,244,144,58,9,141,246,68,237,118,179,124,164,96,125,30,196,126,104,19,176,107,25,7,162,89,236,206,184,139,167,166,16,55,67,7,93,251,90,252,86,252,171,140,238,114,28,106,253,2,64,26,18,192,199,145,70,224,41,158,81,211,254,47,235,74,231,215,176,97,187,165,209,79,109,189,21,14,209,97,193,29,254,42,24,157,72,5,143,9,214,54,90,86,243,143,140,12,163,2,158,213,69,48,232,80,165,123,73,197,247,8,241,232,198,127,142,153,236,153,145,20,27,64,72,56,14,13,147,102,116,211,20,44,176,108,13,229,36,230,81,206,9,197,5,42,177,137,125,239,52,138,145,92,76,16,223,134,138,221,234,177,91,177,210,67,1,151,117,176,201,125,211,227,144,217,180,31,53,97,31,147,33,222,114,225,63,236,245,62,68,54,30,147,134,96,110,84,124,209,201,141,3,62,115,79,24,228,194,3,74,218,184,3,66,224,170,40,123,37,121,61,129,54,53,103,197,43,89,135,6,26,104,193,193,136,152,56,142,183,224,128,35,138,123,231,218,184,64,116,133,134,79,71,93,163,18,65,127,217,137,72,42,147,44,193,117,255,58,201,221,139,83,224,169,171,21,200,243,196,43,229,12,27,96,110,87,50,136,174,144,220,236,35,210,9,136,71,10,14,95,205,206,230,46,210,240,140,197,31,1,18,188,0,238,15,228,67,49,220,86,132,126,70,124,204,88,118,84,251,214,36,171,200,70,160,93,190,20,193,149,122,208,201,60,231,13,227,143,217,98,120,101,241,47,166,37,0,246,166,53,179,69,210,170,111,102,237,39,29,58,140,90,17,30,66,50,240,135,134,156,130,216,158,96,227,238,43,173,150,62,156,252,12,213,121,200,99,178,38,253,248,51,29,232,51,139,88,26,160,174,235,4,96,47,68,39,65,224,118,4,246,129,110,151,23,33,196,101,107,18,57,33,181,138,239,175,105,157,49,247,51,175,4,49,223,166,210,239,121,16,164,212,230,198,33,63,150,165,9,54,147,43,215,241,224,55,27,106,204,89,39,184,161,80,49,4,115,240,147,14,244,80,211,157,188,47,240,27,232,175,82,215,194,147,55,86,12,143,240,196,252,206,171,147,238,96,167,220,204,222,124,57,43,217,33,94,205,196,224,116,99,78,12,233,159,227,1,76,43,79,235,217,146,66,161,211,175,94,65,74,199,243,183,6,81,84,203,242,106,233,76,173,158,214,45,43,108,174,250,106,136,126,230,63,14,251,213,18,71,87,50,64,255,236,85,183,102,109,45,1,174,202,9,149,185,253,197,58,210,45,138,136,51,85,221,138,73,184,106,127,134,253,72,58,18,180,62,151,29,82,139,220,202,116,64,248,20,81,96,109,47,138,242,186,193,36,58,228,83,194,172,38,0,252,218,244,10,112,115,142,57,210,57,11,64,200,229,159,61,193,101,132,118,218,80,148,208,24,56,50,42,216,65,221,198,222,42,94,40,195,189,60,175,28,71,25,114,164,42,45,8,67,46,142,204,238,25,167,37,150,221,46,11,216,39,161,104,150,116,113,1,94,67,6,9,155,180,85,217,5,244,160,99,51,203,177,93,136,13,60,29,150,143,141,45,240,202,86,52,252,208,169,251,4,6,159,54,129,123,18,109,207,1,191,79,38,187,105,43,96,244,160,246,58,53,1,126,98,82,106,12,250,65,44,103,65,155,146,190,0,201,249,32,20,57,171,220,149,156,114,51,66,148,220,137,156,113,120,32,169,126,124,13,130,177,138,31,55,46,148,240,128,29,71,141,116,145,112,8,66,189,190,216,123,114,164,94,213,103,242,213,46,100,240,150,169,179,251,110,47,164,50,174,245,163,245,59,14,243,8,35,82,74,151,19,130,70,32,129,139,54,14,190,35,131,230,71,44,133,253,187,52,219,118,239,235,58,76,31,196,252,32,242,187,197,157,187,55,29,121,51,214,250,24,234,46,96,133,232,102,63,43,191,186,226,113,189,64,205,186,249,119,43,113,194,61,250,58,221,69,191,75,14,152,187,167,243,108,156,124,46,5,218,175,243,118,7,240,85,167,144,192,213,61,210,252,162,165,162,46,86,124,240,63,149,35,88,159,198,71,207,56,140,25,144,133,248,190,191,241,252,13,124,234,108,165,9,106,44,119,178,102,193,221,168,140,143,125,102,211,106,41,163,241,103,12,131,227,10,78,64,224,131,209,128,108,224,131,81,196,188,208,57,0,65,7,171,245,92,68,97,155,26,19,0,220,173,153,62,182,16,55,19,229,89,135,80,157,145,162,168,60,3,54,77,8,252,62,78,45,97,13,187,5,95,233,221,143,244,218,237,9,191,191,111,230,19,235,185,24,229,133,236,211,127,22,70,243,186,237,63,6,52,140,155,111,172,124,143,130,20,198,240,17,48,164,10,74,221,17,240,102,82,73,186,66,214,132,28,226,189,253,197,216,71,13,102,76,54,192,250,157,250,97,33,169,125,119,76,18,127,148,89,55,79,41,27,171,173,241,40,25,242,210,152,51,104,129,66,79,162,178,205,127,78,159,148,90,244,237,62,200,220,157,71,215,30,45,95,17,166,151,2,107,156,25,214,202,113,205,64,70,182,24,9,62,176,176,190,16,176,188,96,117,242,77,22,88,50,108,118,138,246,209,82,199,143,160,77,201,121,197,140,194,143,8,181,195,45,95,221,40,139,214,14,153,166,70,195,180,165,102,177,227,237,193,79,231,55,66,91,102,116,212,200,47,182,152,106,44,255,140,122,66,158,160,250,117,112,5,28,227,9,101,161,115,43,75,216,160,129,201,85,4,155,212,168,94,163,160,204,9,102,25,233,102,160,184,227,106,238,100,129,31,84,122,126,254,145,223,210,150,80,172,229,177,248,245,3,169,238,5,16,2,78,51,54,207,82,72,227,99,136,26,105,129,53,22,17,45,214,181,195,68,36,56,169,195,242,5,8,191,67,154,4,98,246,26,112,153,140,77,237,240,2,154,115,169,245,170,100,202,110,18,149,98,123,104,24,71,192,232,157,222,215,83,47,36,18,129,246,103,237,227,185,218,144,30,199,136,151,160,138,100,74,32,166,208,86,67,75,237,132,120,166,153,52,64,10,225,171,2,81,131,86,59,191,48,93,62,184,125,186,164,181,232,91,66,146,242,21,173,53,43,188,74,248,215,108,185,224,167,76,81,71,206,93,12,235,166,22,241,224,190,133,235,131,111,103,60,230,112,49,52,171,86,194,94,59,123,115,191,87,69,241,194,32,229,82,37,247,66,83,202,39,30,54,213,89,3,78,249,44,22,248,167,57,0,84,189,32,168,147,103,6,140,148,202,187,193,37,38,180,46,29,166,57,72,223,230,106,44,108,111,251,141,251,89,7,111,191,116,203,52,57,144,49,241,196,170,155,145,94,130,81,6,8,48,239,173,230,55,130,69,187,163,225,66,214,151,106,237,182,124,152,252,164,152,71,188,138,18,156,234,158,96,75,48,112,107,71,163,19,180,198,24,225,112,151,114,89,6,217,49,26,232,78,138,51,90,69,91,193,126,130,54,20,217,158,121,249,61,85,203,2,97,83,109,237,170,254,0,91,197,122,244,126,45,233,234,109,127,179,19,219,93,31,65,76,94,19,176,192,62,20,225,161,144,181,212,117,211,254,177,20,119,165,4,191,21,105,172,116,103,36,198,101,166,240,111,212,21,87,239,249,26,153,242,52,76,142,34,251,237,81,66,187,57,122,29,236,37,110,21,148,230,218,247,104,63,1,234,5,69,199,73,134,157,172,42,231,147,224,75,141,129,211,82,4,89,195,246,70,171,181,93,183,55,108,159,166,33,84,4,185,111,204,210,203,121,247,47,11,38,196,128,175,73,224,158,13,7,251,219,162,20,164,80,64,199,241,117,6,96,69,101,173,208,37,165,211,107,165,193,43,31,159,138,214,247,2,33,12,191,208,158,105,240,17,229,141,41,237,45,38,45,115,88,232,28,191,188,150,228,13,47,17,235,94,149,41,105,96,203,124,26,222,106,9,189,50,92,15,120,136,57,57,255,99,51,112,155,217,186,209,181,137,48,198,43,39,230,86,230,26,217,240,223,93,238,195,80,220,79,238,160,255,161,52,146,25,191,179,0,106,203,39,179,207,46,133,153,151,239,88,57,122,189,135,89,178,115,230,216,10,114,143,251,93,168,61,169,202,150,202,196,237,75,49,182,183,125,110,19,34,1,136,14,89,81,155,227,118,201,69,250,152,109,216,132,250,88,147,48,2,191,100,195,211,13,126,162,119,72,133,229,123,207,22,23,212,210,63,155,150,227,57,166,222,129,67,70,42,85,154,245,247,41,193,230,95,156,113,40,103,226,86,19,6,181,49,124,103,224,189,223,33,119,236,24,20,229,68,141,154,5,89,177,163,212,125,152,33,38,48,226,24,141,151,158,51,86,207,22,139,80,172,113,125,82,37,229,71,24,29,22,151,195,95,177,29,49,74,158,121,217,68,52,92,168,158,88,196,251,22,3,155,79,122,252,156,221,200,181,70,100,216,71,156,175,156,86,2,231,130,108,43,211,119,75,181,114,163,95,222,24,246,255,186,183,186,101,37,137,223,53,194,47,117,58,55,235,209,179,14,167,242,26,134,221,36,193,38,118,184,207,96,67,32,145,250,154,128,94,25,66,185,48,57,213,130,222,58,197,173,252,78,101,199,141,206,155,94,81,157,155,216,239,200,168,141,203,59,210,55,17,55,170,5,110,70,51,20,19,17,219,187,198,121,220,48,135,101,52,185,215,244,4,37,229,220,138,211,126,144,244,210,14,194,134,9,176,26,52,128,5,94,173,63,199,171,196,37,142,16,185,13,98,224,38,105,153,24,182,124,179,35,177,69,226,224,127,75,236,2,98,7,44,185,3,14,107,156,129,152,51,36,29,203,211,203,108,162,74,162,216,89,12,128,9,112,14,157,147,3,227,248,177,51,228,239,231,213,231,254,82,42,244,137,106,99,170,156,192,66,71,139,213,5,156,125,195,124,229,130,190,205,89,225,241,254,176,95,30,219,40,248,129,218,116,222,75,183,241,249,60,88,178,52,92,157,156,113,232,162,36,107,47,55,17,155,162,70,224,125,82,84,211,203,26,49,246,193,94,207,161,122,216,126,138,16,206,87,28,38,45,30,196,186,30,68,206,95,156,208,218,236,93,107,125,217,121,46,223,4,69,183,46,238,206,71,72,167,159,167,48,118,25,0,159,147,140,99,166,172,4,113,21,161,52,102,54,219,194,90,106,50,6,156,202,21,86,112,33,45,53,6,124,162,83,226,178,246,1,165,167,177,190,237,128,219,79,114,30,187,31,146,10,157,251,80,124,108,191,233,91,104,68,35,156,13,54,123,191,37,77,245,82,222,206,8,246,133,27,217,87,116,7,145,65,128,81,142,250,19,137,207,10,217,88,150,119,183,30,231,123,9,189,145,113,150,247,204,148,101,142,228,144,127,101,122,157,153,221,45,112,44,139,13,223,94,18,221,245,14,185,252,132,117,15,173,122,121,1,251,109,2,107,25,97,29,180,199,11,124,161,138,37,92,119,254,245,118,34,128,28,100,200,80,5,114,99,208,232,126,215,247,226,193,129,111,229,166,12,107,30,67,118,84,156,100,158,204,44,28,118,134,227,10,22,153,126,77,13,134,137,18,167,115,62,98,60,182,179,66,109,93,146,39,135,247,137,193,45,175,156,83,87,217,63,250,57,154,128,151,152,45,35,43,126,198,229,219,126,200,145,4,236,251,153,196,162,89,73,134,96,119,107,128,190,147,228,64,73,220,100,124,73,203,91,213,77,92,68,50,107,69,237,110,138,228,193,175,162,213,78,39,118,105,39,11,196,157,25,195,35,53,250,121,123,219,197,179,143,206,30,210,251,106,231,243,37,84,55,23,7,30,84,11,121,92,53,9,191,28,49,57,237,112,78,183,12,215,243,99,159,238,14,246,197,136,207,69,0,120,99,89,37,184,54,94,128,204,224,174,118,50,226,59,151,162,115,167,144,223,213,199,4,87,55,193,10,212,169,238,242,254,70,213,252,87,32,245,18,157,79,122,232,143,103,31,93,140,93,243,91,156,91,223,136,12,68,98,200,179,170,185,195,112,27,104,3,205,165,28,186,174,118,57,189,119,144,158,95,158,164,143,139,58,87,217,43,22,68,43,126,240,70,94,163,225,233,248,227,168,70,198,16,51,205,239,192,4,124,244,190,80,130,188,253,65,63,201,98,243,142,139,238,115,52,164,188,234,11,203,33,66,111,40,174,113,78,139,135,102,209,122,166,53,10,2,10,140,215,139,223,100,11,23,208,126,65,214,52,37,98,93,37,250,159,75,209,155,248,86,107,5,114,199,254,105,179,240,132,18,228,65,136,188,180,168,141,149,43,234,13,114,25,92,32,8,212,172,186,194,234,241,77,20,142,76,140,225,110,176,248,93,52,69,8,47,143,25,99,166,56,37,228,218,183,234,205,236,237,168,228,136,179,145,123,254,230,182,37,220,223,96,199,45,24,147,73,86,254,47,90,124,89,129,192,199,167,216,217,62,148,163,46,107,74,67,155,206,30,163,44,42,238,69,77,5,86,126,151,131,136,59,134,63,72,23,50,35,228,75,48,172,147,4,200,35,217,142,56,51,159,145,237,51,218,27,192,43,193,90,63,194,218,149,77,69,58,68,24,177,235,144,245,52,41,241,21,63,202,204,123,60,245,245,147,59,230,53,58,179,177,6,108,72,142,101,202,171,147,1,238,27,183,145,157,7,29,13,111,137,129,183,185,196,139,126,204,48,220,237,170,227,65,153,226,170,245,241,69,250,74,235,39,129,115,94,113,165,212,140,219,239,255,30,2,150,71,167,222,250,123,230,253,102,110,67,175,23,73,166,0,144,47,148,163,151,221,23,81,24,247,230,191,244,11,1,206,112,51,40,182,33,40,163,61,107,169,167,6,202,202,72,255,23,102,172,225,38,148,226,88,109,43,255,21,145,157,184,0,241,95,26,253,89,42,53,13,149,184,8,74,173,119,80,63,39,122,131,186,46,224,96,135,125,146,230,186,215,105,91,230,163,169,125,167,150,59,214,137,125,94,22,30,51,110,143,175,201,170,44,185,136,253,28,105,89,77,41,65,135,12,60,237,170,191,75,127,88,149,34,205,123,6,139,121,217,249,166,254,165,197,104,144,84,48,58,172,21,122,128,85,199,148,36,114,91,239,123,1,206,8,169,49,206,39,142,97,137,189,224,169,198,119,13,171,201,140,49,157,103,118,88,94,210,27,126,242,245,68,55,25,204,114,244,247,64,29,145,137,154,56,172,22,62,19,227,79,143,90,5,12,201,194,154,224,71,103,79,31,119,20,146,114,219,19,44,92,21,211,69,49,20,95,47,183,25,195,60,209,50,238,182,244,59,9,94,112,27,36,210,214,7,152,57,84,87,219,76,117,252,173,214,2,188,162,120,141,43,194,108,127,121,25,148,205,129,10,46,39,41,144,243,52,218,147,187,37,188,247,50,228,177,63,51,214,17,10,240,24,244,129,34,87,146,124,5,230,163,171,120,234,22,101,103,156,68,245,144,114,132,132,244,163,47,127,235,219,88,243,187,140,196,153,78,126,139,116,152,107,147,27,119,0,2,213,231,59,70,73,214,67,31,130,51,71,155,189,211,225,165,140,83,24,36,56,202,105,50,33,140,155,216,216,209,252,54,156,254,20,81,120,206,235,241,53,194,44,177,128,30,239,26,95,124,88,90,21,132,123,188,158,141,127,241,223,95,178,108,21,221,145,222,26,192,180,84,129,78,175,117,146,57,215,116,10,13,53,12,252,227,64,32,115,213,68,143,238,155,225,101,184,132,28,92,127,89,232,1,139,160,185,99,115,92,29,188,211,254,180,85,121,47,205,53,199,122,73,153,119,188,74,163,229,129,90,48,50,178,91,189,168,116,38,32,114,55,89,132,116,208,124,128,113,113,16,206,199,26,163,212,71,1,250,155,96,53,100,44,246,31,136,208,243,220,60,176,23,103,88,245,48,51,59,225,235,226,76,182,53,49,135,126,117,23,4,0,51,62,11,237,65,252,21,246,193,84,14,85,217,111,240,108,226,134,59,194,210,198,214,9,245,99,101,81,3,89,134,225,173,80,61,204,115,250,25,191,22,137,42,177,155,159,237,248,200,39,189,1,66,189,88,8,198,57,47,194,59,150,74,50,244,192,145,124,139,137,9,88,183,226,179,162,219,55,201,222,186,109,36,242,146,104,134,170,9,120,67,123,240,251,118,184,113,206,203,242,204,29,95,103,160,139,24,229,246,174,44,232,1,92,51,119,121,192,74,200,193,169,150,115,168,56,37,31,105,175,166,10,183,252,135,115,233,34,0,229,124,183,246,177,143,42,237,125,2,142,154,240,49,228,213,15,77,123,202,79,84,0,147,189,200,161,106,243,41,87,86,158,216,240,246,100,112,9,91,213,220,206,108,190,57,220,218,99,189,47,194,120,28,127,254,169,178,91,243,109,75,134,210,210,244,242,159,54,217,20,133,68,233,153,234,101,91,233,30,96,171,224,92,91,176,236,182,188,20,131,21,122,84,104,171,14,236,252,249,75,212,235,191,95,11,62,141,94,241,165,26,219,173,197,153,214,168,223,240,94,213,113,148,95,22,212,203,134,117,232,60,147,51,11,201,54,4,81,122,170,58,150,209,147,128,196,78,68,78,148,160,114,198,127,162,120,180,68,133,22,76,101,119,11,93,246,9,232,183,127,140,173,92,221,236,51,178,45,217,246,70,118,91,129,102,24,199,252,7,6,116,81,43,240,49,115,77,164,134,23,10,184,92,26,223,238,174,254,108,5,221,29,205,3,38,30,51,143,196,202,21,102,228,51,105,45,191,54,175,140,175,135,132,56,183,9,116,20,68,132,18,220,233,176,239,82,87,160,87,75,33,255,121,193,156,78,230,23,79,64,52,198,99,148,130,106,107,8,203,26,34,248,194,178,123,242,238,250,69,219,168,219,185,118,64,221,220,7,62,58,172,34,161,85,252,155,52,152,60,87,103,183,167,226,234,225,170,247,90,38,143,81,89,210,156,20,60,194,148,113,179,171,5,77,184,78,26,208,131,200,86,18,46,116,74,134,61,119,29,194,3,117,40,80,168,90,103,191,42,184,95,218,91,28,155,54,146,65,95,188,105,77,14,205,75,249,117,46,221,98,224,169,93,190,83,43,182,146,208,7,135,154,99,250,12,2,189,246,105,220,172,175,69,1,167,218,186,57,136,247,112,149,221,32,11,202,229,160,52,60,200,208,193,198,75,246,250,53,55,150,176,139,93,85,222,206,205,111,9,73,162,186,211,69,140,188,136,164,203,223,18,225,119,181,234,138,60,23,112,75,105,15,203,7,125,177,246,31,45,74,151,48,22,139,175,136,183,250,161,111,94,119,158,113,175,140,79,29,122,65,55,233,80,125,200,31,209,18,35,82,3,116,190,125,208,46,253,125,100,73,160,238,5,244,38,184,200,7,167,119,122,165,28,250,26,52,110,188,151,63,208,63,248,94,165,164,111,163,146,32,37,5,60,85,192,27,61,24,60,161,222,0,4,254,155,189,84,196,0,157,35,12,162,103,138,192,135,38,45,40,41,69,63,30,177,222,41,253,200,54,63,230,237,20,103,172,23,99,192,215,2,181,198,52,12,1,157,162,169,147,206,27,237,188,158,40,214,164,233,240,100,201,245,24,178,38,205,66,140,166,43,132,117,143,233,22,167,190,202,18,188,127,240,184,49,182,87,84,214,121,140,169,20,29,122,133,69,18,168,61,132,146,108,35,131,109,86,101,183,150,34,77,90,194,24,46,232,28,48,183,206,47,100,61,163,165,74,17,92,27,210,106,16,222,186,117,41,103,197,144,3,27,9,248,132,189,88,83,122,219,49,116,2,50,30,40,205,76,130,35,126,83,228,228,138,171,171,135,39,196,227,87,106,235,241,239,86,179,253,11,23,99,7,66,41,158,178,157,76,234,6,5,214,254,184,155,181,84,197,165,122,251,119,249,236,166,219,144,14,253,20,200,71,185,128,249,58,15,196,101,206,51,124,190,50,159,255,10,172,123,168,253,230,89,10,236,71,194,62,129,71,92,165,85,0,198,135,157,141,191,50,13,140,37,124,110,249,46,46,25,251,68,145,8,18,120,51,137,142,119,244,148,246,141,26,132,163,135,241,35,159,49,77,209,163,230,111,6,242,146,195,49,170,2,124,194,17,165,42,155,254,34,50,37,48,67,234,117,90,102,69,129,61,195,172,78,87,34,46,79,146,168,210,166,122,231,226,222,204,251,20,75,223,196,242,130,34,225,110,75,207,175,78,24,239,45,171,104,198,59,0,19,49,11,243,112,43,250,158,62,80,155,237,46,52,188,185,245,171,68,197,202,251,110,93,211,94,67,191,87,157,87,233,13,61,47,52,206,80,194,167,66,67,198,170,244,247,174,171,50,79,255,184,161,14,254,202,162,162,254,221,148,221,251,90,102,154,71,98,61,150,1,32,250,227,57,240,168,21,174,152,107,235,75,2,198,35,117,161,148,210,231,214,184,87,241,102,16,184,144,221,165,158,108,17,177,46,228,156,159,149,123,171,239,250,40,10,62,189,159,144,124,7,64,76,122,161,214,158,46,206,191,99,142,189,68,40,168,172,65,88,130,102,169,121,107,188,201,117,35,139,212,14,176,77,110,172,197,14,238,254,189,108,234,224,228,68,226,121,230,183,185,224,25,14,142,86,3,2,21,133,116,109,24,125,214,126,192,236,107,42,30,208,247,43,102,62,205,11,213,177,80,163,92,245,82,101,244,192,151,191,169,102,204,190,167,232,66,226,12,115,238,131,188,181,235,30,55,68,17,186,125,64,121,44,39,147,240,53,20,40,101,224,109,239,226,32,115,253,200,113,202,118,207,81,168,138,146,224,129,38,168,181,120,87,225,170,24,6,223,254,59,48,103,66,191,112,18,100,232,149,121,191,132,39,231,12,223,111,202,150,238,150,76,143,41,37,183,222,8,16,24,33,99,101,144,218,10,68,70,133,97,95,109,42,67,13,102,0,93,189,206,41,149,160,206,101,195,209,76,22,231,109,76,142,113,78,222,63,202,227,65,140,154,29,47,96,41,58,77,137,107,249,152,7,126,53,105,31,221,134,107,150,14,18,108,110,152,91,57,88,146,199,220,12,79,116,220,134,180,176,224,71,97,52,154,76,94,230,58,14,196,154,89,27,162,219,96,227,91,143,175,92,36,179,222,30,59,163,32,250,146,96,163,83,134,33,18,27,99,127,113,171,35,52,143,96,219,71,71,254,216,30,244,75,88,241,242,50,213,1,83,56,154,152,153,219,130,166,175,82,10,125,111,96,137,38,46,205,11,85,195,29,184,117,250,218,58,49,10,40,30,139,211,81,157,249,51,33,100,201,34,96,197,189,206,48,180,50,2,111,154,109,10,90,116,189,224,85,45,153,10,96,210,142,179,131,174,213,131,9,90,194,235,113,201,152,223,253,134,198,136,215,196,121,114,145,127,197,63,226,22,10,124,149,177,37,12,217,218,113,9,235,142,49,103,237,98,82,140,8,127,97,56,61,78,76,142,106,216,56,78,153,139,60,223,243,28,34,38,199,137,132,50,118,151,58,141,192,20,249,138,53,114,177,45,146,78,147,234,123,244,61,157,119,7,88,41,82,17,102,213,59,93,79,45,40,157,139,219,81,12,134,18,77,1,101,45,228,155,66,227,243,242,202,71,136,205,94,102,239,237,253,62,207,30,222,178,58,135,219,74,150,232,27,209,251,37,198,33,83,209,39,249,183,21,38,213,39,143,198,149,91,161,250,193,43,45,233,70,234,118,173,231,180,151,157,138,7,167,198,81,194,51,164,200,83,56,176,121,167,225,108,50,245,125,137,148,215,111,59,19,64,109,5,114,176,218,137,186,235,94,254,156,96,194,168,34,159,84,171,68,70,215,155,148,244,240,11,54,128,75,56,161,201,231,65,137,194,113,32,89,201,13,141,169,131,94,198,168,132,135,101,50,165,181,8,159,184,15,19,74,16,105,43,25,168,214,106,76,164,64,91,12,74,22,16,124,27,121,145,188,125,255,96,131,33,245,145,180,29,62,194,137,30,62,243,129,77,13,158,163,117,162,206,61,236,135,244,220,166,174,217,73,139,0,254,201,26,125,241,33,68,187,155,235,119,25,72,196,151,8,255,8,84,250,43,102,204,134,121,186,123,144,48,2,235,7,229,41,190,150,181,169,203,226,194,118,180,182,162,220,222,14,52,114,197,229,86,207,201,148,241,246,69,68,231,8,57,6,21,171,44,83,134,151,83,25,48,142,91,248,21,21,213,9,104,208,21,12,133,100,100,144,124,237,193,56,180,34,39,246,232,53,212,121,61,127,221,103,74,114,150,223,11,229,210,6,76,40,95,192,199,167,100,100,64,117,44,73,13,187,42,241,47,212,35,164,55,64,85,88,41,102,68,165,110,72,100,66,38,33,14,166,233,157,80,35,137,1,69,63,111,169,42,19,65,190,106,104,216,90,154,147,190,183,207,177,145,142,190,213,148,10,228,251,99,58,72,148,192,227,20,1,79,110,181,47,89,218,133,7,75,111,229,49,60,97,179,158,28,51,110,139,80,56,147,33,182,227,153,92,32,1,241,44,181,143,24,16,252,26,129,134,63,65,186,1,160,90,254,21,88,43,220,101,222,156,214,211,98,172,42,254,193,103,147,61,229,181,85,228,223,127,163,201,157,106,97,82,251,201,89,32,245,234,92,103,151,70,111,44,210,74,166,88,95,204,82,185,9,218,72,146,27,181,139,97,122,22,228,206,84,237,87,140,101,100,110,216,186,226,110,186,109,140,162,59,52,3,26,96,176,41,84,66,47,216,100,110,106,2,55,106,165,232,43,156,42,193,122,42,74,224,96,101,41,240,141,4,88,29,113,31,121,80,196,152,15,234,154,70,129,228,97,137,99,89,108,64,143,32,111,199,220,209,192,20,24,80,192,202,191,169,156,133,210,36,179,17,149,67,213,52,180,176,134,253,181,179,174,87,217,236,254,162,137,201,192,88,23,89,195,231,73,182,226,224,149,99,172,221,135,5,241,132,86,236,118,69,50,108,27,103,65,17,127,75,11,160,71,85,227,148,153,62,103,83,250,192,254,215,123,252,157,8,112,132,210,193,21,244,168,131,44,69,226,190,243,10,225,163,84,190,118,32,19,193,234,220,32,188,74,90,197,143,70,191,99,113,186,143,49,131,109,253,62,234,221,183,103,238,89,65,67,11,230,9,222,24,95,129,14,228,125,126,166,49,29,239,36,39,124,130,203,200,105,29,231,182,43,1,179,193,103,230,251,205,22,182,65,191,137,110,165,113,180,60,209,87,212,7,69,241,130,157,125,59,225,89,244,120,134,142,170,92,19,65,251,87,163,83,32,185,163,202,187,191,34,192,183,186,236,30,222,225,180,237,142,162,77,93,190,100,248,70,134,164,253,105,255,142,189,83,50,161,225,223,241,240,252,170,90,122,221,22,108,187,81,31,252,76,218,238,217,175,90,110,37,190,8,65,147,181,160,202,39,24,230,218,92,233,102,123,98,72,215,163,152,111,198,25,215,60,213,1,254,4,168,45,13,40,238,142,158,60,70,241,144,183,215,236,146,149,13,234,215,133,3,112,135,7,8,40,195,214,105,244,172,246,200,198,238,153,112,100,59,137,18,122,9,204,17,41,181,111,41,61,21,160,16,170,194,218,178,62,88,92,199,233,200,24,70,246,142,224,164,200,210,237,216,75,100,45,115,160,117,92,38,226,170,215,156,203,215,210,248,231,199,216,248,161,125,167,132,103,180,186,9,249,4,154,16,237,107,80,28,27,235,150,39,210,201,153,66,17,97,165,29,15,167,130,23,77,17,106,160,90,248,47,219,164,20,127,81,248,1,36,254,22,50,208,65,145,45,220,160,93,16,45,62,229,177,187,144,167,142,26,248,232,6,191,77,59,136,49,2,33,116,66,65,146,218,44,111,73,2,222,99,111,24,180,41,67,103,39,216,168,240,207,142,34,241,86,17,173,37,58,64,186,213,98,181,151,159,141,26,22,31,45,92,64,9,10,26,76,181,236,145,18,8,30,219,158,183,71,138,134,56,65,70,34,140,141,13,54,245,29,155,227,200,183,113,40,113,203,86,214,2,162,90,237,5,247,2,186,149,205,73,75,106,255,178,8,39,126,21,96,43,117,216,10,81,98,244,208,25,252,177,189,21,50,204,13,115,42,29,115,2,10,234,207,168,29,131,228,241,82,183,158,85,177,161,142,249,81,208,74,7,73,61,160,142,153,121,63,78,230,152,77,38,100,58,119,15,102,23,145,201,189,165,77,147,230,208,2,84,68,22,86,13,32,68,58,88,73,8,48,139,117,27,222,40,32,182,33,168,89,188,113,162,162,146,225,102,118,158,53,22,82,149,184,240,92,212,243,40,50,170,149,147,223,104,185,45,162,20,59,162,173,157,5,224,233,8,159,219,28,215,102,178,59,121,254,199,162,199,99,2,69,53,6,16,218,9,6,241,44,220,188,45,208,250,244,235,250,209,70,110,222,198,183,219,47,135,143,170,11,226,178,201,194,8,0,115,63,105,158,9,227,172,16,176,218,211,18,70,236,5,109,35,119,143,218,145,213,190,153,247,240,232,191,61,9,58,130,175,235,45,122,195,207,43,194,102,133,91,46,230,18,78,212,122,114,168,4,94,120,96,72,18,12,142,191,141,105,202,78,241,114,85,34,238,84,11,10,254,50,188,122,76,216,117,121,110,3,95,91,62,253,60,174,139,195,120,183,220,61,229,75,22,220,190,134,216,68,90,111,184,152,40,130,43,39,76,144,94,215,83,252,62,127,27,6,175,158,50,87,41,85,95,32,24,14,193,22,92,54,156,254,77,61,50,7,243,25,48,156,89,56,17,33,107,135,110,160,52,80,216,55,217,98,40,102,1,34,70,233,200,205,172,234,156,17,180,123,113,143,67,81,224,51,149,12,213,251,3,2,63,30,249,181,254,120,160,155,133,96,137,181,35,5,182,121,214,39,128,129,237,203,19,137,24,93,101,255,228,209,34,58,241,253,187,131,60,8,241,178,36,11,26,109,21,150,214,31,242,19,60,118,147,158,111,23,164,168,73,67,92,231,211,6,86,222,242,248,107,142,231,119,143,1,168,27,187,91,70,38,230,162,216,232,152,83,71,41,183,182,189,94,221,128,7,217,182,42,49,232,20,23,3,87,95,213,181,137,117,14,161,52,243,122,183,193,90,134,182,58,222,179,72,150,241,129,197,216,227,156,20,75,90,202,71,128,15,137,242,183,117,188,168,252,39,243,76,167,222,12,190,250,197,206,164,145,191,47,206,24,20,40,253,36,4,220,72,143,199,19,105,30,48,219,215,196,37,15,182,38,220,134,239,35,187,29,230,68,215,139,220,215,90,25,184,246,196,149,239,249,142,248,63,141,205,161,28,87,142,170,237,214,67,142,251,97,163,163,242,208,139,28,201,5,249,160,111,232,64,231,207,201,197,196,206,92,127,71,17,57,48,200,25,226,176,113,210,162,108,233,45,224,15,40,196,161,187,228,55,88,74,235,30,68,12,209,70,87,243,159,85,208,70,192,75,111,14,15,239,6,234,134,248,30,113,51,255,128,43,104,82,6,158,241,74,19,174,199,229,132,238,6,70,145,96,242,208,185,17,12,251,210,13,113,233,186,188,29,9,195,244,71,62,26,195,82,44,209,10,230,93,188,92,234,241,145,115,67,77,67,44,210,249,228,5,84,43,160,77,103,214,59,87,195,200,20,129,254,173,229,229,37,115,254,49,72,119,145,188,255,12,95,191,110,239,124,12,213,234,217,4,211,133,39,184,242,103,223,13,5,50,56,74,214,135,66,130,62,223,167,91,175,30,40,134,82,42,167,175,169,33,40,205,88,123,104,96,189,142,226,130,73,0,60,121,128,225,203,146,1,170,4,93,235,72,243,97,77,129,92,246,173,53,161,138,204,83,70,234,80,223,20,176,62,149,150,127,141,182,196,163,80,117,13,31,248,64,166,35,112,96,44,221,70,128,124,229,74,60,65,83,15,20,135,165,184,82,153,163,153,145,137,168,21,68,140,120,76,239,1,57,32,133,38,158,157,114,92,79,139,129,100,233,109,73,206,6,164,101,18,250,41,214,14,185,87,241,153,142,116,3,55,77,138,149,123,112,38,59,191,132,156,136,205,108,175,236,117,66,107,36,241,192,147,149,227,116,253,26,209,34,134,94,214,68,212,25,142,117,207,151,32,13,101,187,154,38,54,165,162,58,254,142,54,86,89,13,232,46,36,31,67,169,250,183,168,205,55,163,165,77,37,211,28,12,51,80,99,47,117,190,69,215,83,246,24,48,152,252,50,167,183,242,94,21,63,211,171,23,199,4,160,172,57,57,92,128,50,52,174,87,77,255,17,221,149,165,195,162,43,38,226,27,221,101,124,188,82,226,222,49,132,246,31,27,81,255,205,69,176,163,195,253,83,47,80,99,157,132,223,160,92,39,120,73,149,51,171,255,67,218,107,160,220,58,236,28,119,180,1,82,24,146,160,44,200,70,141,109,254,12,126,229,95,99,96,3,216,221,136,205,113,142,122,186,243,183,255,22,253,97,176,39,222,179,209,180,233,133,72,37,54,158,28,65,95,13,1,59,153,193,87,230,128,104,160,201,205,2,196,6,125,232,155,188,65,83,240,126,145,178,63,143,0,240,193,78,184,2,226,82,240,49,22,50,167,206,196,168,121,68,212,156,249,154,95,24,93,83,113,168,33,14,246,208,135,139,78,122,101,123,8,177,97,182,122,128,106,140,8,192,100,143,88,196,50,29,207,215,143,65,120,133,133,118,94,128,12,106,130,195,165,203,112,192,173,166,222,59,23,34,6,82,131,16,84,214,205,87,208,140,201,182,166,221,131,122,181,85,150,65,139,133,103,23,179,159,231,7,175,204,95,130,131,126,45,155,135,76,69,145,54,197,251,173,9,206,46,189,122,101,178,24,17,52,231,121,151,60,255,66,47,5,0,134,235,185,232,129,137,35,158,3,110,230,211,73,61,209,224,71,153,55,248,61,100,233,170,140,66,27,177,253,40,208,209,143,4,27,108,105,166,136,60,8,218,119,168,182,107,8,119,5,118,31,219,43,94,70,182,91,68,254,135,245,212,250,26,105,156,109,180,133,177,249,140,89,130,79,55,31,123,18,154,42,191,139,9,240,237,151,107,173,188,134,243,132,118,79,249,197,52,29,174,60,127,48,203,213,101,118,178,117,92,200,49,217,119,172,213,150,231,103,134,168,200,159,174,105,85,8,72,53,243,196,179,102,171,173,207,190,134,186,250,180,231,155,193,203,81,248,175,8,196,145,73,186,178,63,177,60,238,12,42,169,79,173,245,76,171,131,19,102,237,156,201,116,42,209,167,158,198,227,114,197,227,182,212,229,151,110,140,149,239,82,124,137,145,167,26,54,159,102,237,132,139,121,181,115,78,145,179,231,40,243,114,107,190,126,230,152,86,21,43,130,126,87,172,107,120,215,174,119,95,238,138,107,162,109,30,0,156,48,191,59,137,171,39,151,249,219,16,202,29,186,7,225,198,202,213,119,26,30,46,66,61,154,127,212,160,121,30,139,137,77,16,197,1,225,23,181,190,52,124,88,224,250,45,111,131,115,99,26,188,227,244,207,13,101,230,130,96,187,90,109,141,203,246,150,213,238,2,180,162,199,113,129,255,97,7,65,101,37,145,166,70,193,39,68,86,45,6,162,80,189,182,147,237,204,108,173,114,12,139,6,79,110,178,50,39,17,113,41,178,217,61,88,132,240,93,181,152,170,7,71,170,146,115,177,209,87,215,16,157,38,76,45,46,220,16,103,58,125,32,153,241,187,154,232,13,56,84,165,56,94,8,6,118,36,14,96,65,93,68,50,208,97,85,185,103,1,161,83,67,194,38,128,76,181,204,102,151,40,72,219,119,58,243,206,0,99,50,157,241,110,31,75,39,89,181,28,80,34,47,54,40,145,0,60,100,212,148,16,35,19,189,130,103,237,1,19,109,241,72,134,148,103,72,23,209,106,186,211,41,196,18,76,23,75,122,68,251,50,11,252,232,52,72,57,5,52,226,217,252,184,71,71,112,106,214,93,60,250,235,235,115,148,64,183,222,82,158,135,135,145,153,54,138,126,116,216,66,235,51,100,7,1,111,11,231,57,153,174,195,76,173,195,2,137,227,217,61,109,233,31,68,5,179,235,72,80,16,191,118,37,76,119,131,246,39,251,58,127,172,229,32,135,167,216,216,39,54,7,180,45,236,44,47,186,218,5,45,145,201,222,24,126,214,198,237,218,245,74,159,119,201,233,27,224,213,175,46,43,252,104,209,254,53,126,25,166,190,157,66,64,23,226,4,74,69,28,42,238,195,233,33,1,64,116,16,110,32,81,97,57,242,250,108,13,200,31,184,115,30,190,65,111,225,197,90,215,174,221,193,216,165,11,16,3,153,141,181,161,223,213,141,64,243,41,33,65,208,245,48,203,171,242,234,120,183,57,60,85,83,188,148,249,94,62,178,164,119,223,137,180,49,184,166,120,134,127,76,230,216,208,161,5,42,237,196,235,114,222,23,134,110,242,244,163,1,42,228,3,251,93,156,48,46,154,200,19,163,205,213,250,142,212,14,156,210,48,20,148,235,204,232,128,21,3,100,38,184,230,249,138,117,207,253,60,79,102,174,115,184,21,102,194,116,47,69,98,110,200,73,248,186,30,220,75,239,155,228,138,141,255,84,179,127,17,124,167,107,102,248,93,59,11,170,167,110,129,228,140,41,111,215,131,169,31,210,192,131,220,50,29,241,34,235,141,60,96,178,83,126,109,14,186,209,248,63,130,108,186,180,105,95,192,234,29,87,8,197,153,103,55,13,10,116,247,40,153,54,84,199,120,69,98,185,228,4,234,107,80,168,240,218,9,114,58,196,150,245,120,244,210,164,160,201,55,20,40,135,138,179,149,228,199,157,192,174,190,79,35,154,208,104,215,44,229,241,125,186,156,42,60,224,60,98,79,40,64,126,207,165,212,10,115,54,25,33,126,58,236,50,194,209,149,85,111,178,89,79,15,60,227,54,174,229,243,135,42,102,50,171,254,95,21,247,31,125,0,215,95,9,254,115,158,204,23,106,103,28,139,202,110,125,119,242,110,213,56,152,116,42,49,235,231,28,252,0,141,119,191,200,51,122,183,74,56,200,99,174,153,239,174,227,16,247,241,53,17,43,147,201,28,236,24,172,158,183,250,239,232,109,178,138,191,154,85,92,101,93,173,175,120,149,115,204,109,250,109,193,172,203,85,254,72,122,109,173,97,223,35,161,59,23,39,177,164,124,186,70,76,36,143,143,79,179,160,167,125,30,112,233,209,141,126,247,37,119,77,159,6,86,22,186,250,64,148,109,116,69,157,161,219,213,126,74,234,55,4,74,150,191,164,59,229,208,73,147,153,74,155,93,93,177,111,177,180,36,107,46,26,222,118,125,41,31,110,95,84,199,96,81,223,99,229,230,111,208,187,44,207,189,197,162,155,118,66,246,102,5,157,180,61,121,27,171,235,38,194,219,47,109,32,238,247,114,130,158,184,151,243,155,87,210,50,16,172,39,124,229,145,237,44,49,206,229,30,118,171,255,129,65,10,175,28,62,65,30,217,20,113,253,179,149,240,28,118,112,140,20,237,39,7,159,242,230,64,144,209,53,33,213,116,176,141,135,111,225,244,248,107,202,235,131,88,130,60,113,17,151,144,193,21,155,78,5,33,221,177,64,101,141,166,1,217,83,16,24,8,33,203,8,73,180,252,201,36,37,193,112,158,81,36,62,12,87,125,150,121,19,39,92,191,173,210,244,36,77,195,88,140,26,156,4,231,27,111,89,251,35,188,185,246,75,176,127,162,75,144,137,255,124,36,161,108,144,154,177,88,19,197,21,51,61,242,175,177,115,118,58,158,40,174,196,158,97,198,184,209,36,126,232,71,189,204,186,7,102,36,124,234,204,89,172,220,192,86,101,51,175,40,9,191,17,115,155,117,200,237,22,138,77,48,250,240,160,224,117,133,170,182,144,213,211,213,2,243,145,65,254,0,2,248,48,33,249,80,119,29,108,76,228,213,3,143,250,23,23,131,183,155,60,55,214,27,114,225,198,150,10,35,148,123,109,118,26,2,65,205,51,165,231,113,146,183,118,99,110,128,192,107,84,128,130,68,16,88,195,165,35,170,219,153,195,92,132,226,34,20,77,81,240,139,150,107,214,77,155,204,106,79,19,168,44,71,198,240,87,142,60,44,60,246,5,116,90,243,72,82,123,206,123,164,157,159,113,100,46,227,97,151,247,172,49,26,253,214,112,110,75,191,20,199,178,121,153,73,146,167,80,165,179,249,104,118,42,76,8,126,200,69,25,1,35,35,219,85,218,235,253,164,63,211,195,178,60,208,120,222,151,167,79,238,35,131,109,53,18,149,50,40,14,206,218,230,111,82,234,124,19,223,6,18,94,196,199,189,219,79,203,3,86,63,184,11,70,220,145,70,39,204,13,70,25,105,99,18,2,0,24,161,197,244,35,162,11,157,34,54,196,92,138,255,30,83,77,170,69,196,207,11,28,60,155,7,88,6,248,72,159,21,242,123,4,244,230,249,74,32,130,186,174,143,2,140,24,130,73,170,186,195,129,0,221,95,213,21,27,147,128,194,103,91,111,210,249,82,200,180,140,107,187,79,132,95,135,105,220,39,219,47,101,130,232,19,153,84,96,21,214,227,184,212,26,88,77,22,173,250,215,51,120,214,55,206,86,220,178,39,170,15,114,12,97,98,239,4,124,47,250,230,133,149,196,82,209,165,151,0,207,30,106,133,62,251,241,196,196,47,179,145,179,2,155,15,5,165,22,67,52,207,39,246,123,134,219,252,174,231,168,82,8,7,192,229,168,45,215,86,100,235,111,169,107,12,249,89,109,86,160,142,181,238,237,223,92,168,130,150,236,224,116,222,45,18,13,13,164,73,38,27,208,24,138,45,80,4,148,58,149,54,128,230,244,22,230,218,179,87,51,104,223,178,9,209,228,14,206,192,249,41,82,34,115,235,125,150,192,196,1,165,252,62,83,243,157,37,218,134,192,149,232,139,145,253,205,51,17,97,192,121,157,60,181,170,126,156,5,44,196,235,223,123,170,2,118,228,255,243,8,132,196,221,30,242,92,159,112,180,131,51,25,126,253,184,7,4,110,34,217,37,185,91,186,44,77,80,104,181,58,171,9,210,180,17,119,8,141,229,247,64,62,232,121,118,112,133,52,173,5,202,94,170,37,212,28,222,193,97,51,164,107,197,181,220,102,52,58,47,147,194,179,174,14,89,19,221,145,39,174,86,249,64,89,192,101,143,207,156,186,210,1,137,143,225,13,38,98,59,92,137,53,31,64,212,100,157,144,100,131,3,65,115,94,185,87,13,25,176,45,184,207,19,250,197,231,86,217,51,191,125,60,11,95,125,105,236,148,166,54,6,42,0,150,180,138,38,30,235,72,106,14,217,69,184,242,46,197,173,38,89,234,41,197,213,165,79,86,118,231,142,207,69,207,108,20,53,179,160,231,84,99,156,253,80,13,15,65,18,73,160,149,31,76,124,141,4,48,207,86,81,87,66,32,121,213,115,116,230,240,201,247,195,159,66,154,244,180,174,14,101,84,3,66,175,40,177,65,194,101,162,234,26,55,222,21,72,164,219,243,129,30,172,104,212,50,6,152,90,233,235,35,221,207,165,225,44,109,74,127,123,173,56,87,209,84,211,48,214,123,5,105,101,78,188,169,175,36,172,214,19,232,125,217,130,252,99,237,244,61,173,193,82,209,216,57,13,12,202,82,193,78,70,69,206,74,240,191,91,25,179,254,242,177,68,23,139,165,101,32,52,246,25,212,240,38,237,147,60,156,190,36,3,56,163,125,228,107,228,6,235,44,250,90,92,77,158,36,217,168,161,77,26,49,125,99,103,191,115,41,120,16,231,243,69,108,169,115,81,127,195,48,164,132,75,173,147,62,148,220,3,189,186,165,200,86,60,18,172,193,207,129,196,167,69,181,134,232,130,109,48,76,133,202,38,184,207,153,39,149,26,4,242,77,59,193,254,102,222,99,68,91,147,245,252,14,111,57,224,121,244,233,148,97,66,37,162,181,44,60,144,184,181,187,204,143,33,120,225,243,226,97,190,168,25,134,240,146,145,251,166,104,183,243,126,93,104,93,84,55,148,49,84,30,71,204,203,236,226,179,113,247,64,213,92,207,126,35,130,231,86,232,149,34,79,127,8,155,120,228,29,247,142,10,151,52,57,180,40,56,93,99,171,253,160,143,201,101,183,204,59,240,23,208,83,198,151,231,231,147,28,110,4,156,102,57,157,18,249,18,50,20,130,56,53,156,41,45,170,41,117,136,179,222,121,239,18,168,166,237,2,237,98,107,148,236,81,60,2,33,181,218,46,71,254,197,234,84,204,80,27,160,118,123,153,37,55,238,240,199,98,227,116,197,126,232,21,255,98,226,206,152,34,211,121,85,69,183,195,225,202,232,188,79,208,206,156,187,96,21,189,252,76,203,227,241,70,211,61,52,217,12,33,243,41,50,152,77,47,82,19,140,197,235,100,59,65,70,115,52,246,95,80,145,224,57,224,221,213,78,145,49,47,117,102,248,205,92,84,18,215,150,191,135,145,62,36,193,200,52,133,187,34,96,149,139,1,97,248,25,51,64,247,58,93,111,15,225,212,223,114,61,92,11,95,154,153,245,208,78,148,39,150,34,40,110,50,154,11,54,4,145,21,134,166,233,0,193,39,105,2,102,29,28,168,238,231,117,248,142,40,50,56,142,240,142,165,151,16,85,30,155,98,225,239,177,187,143,215,228,29,118,98,85,69,167,21,45,116,143,40,42,152,1,87,158,139,169,81,137,18,54,65,178,145,44,82,225,241,84,208,111,202,139,17,95,107,130,255,148,105,65,106,172,230,171,55,197,239,133,168,4,152,247,235,19,138,175,168,216,216,171,23,160,83,71,40,126,234,228,1,76,145,9,132,135,166,202,190,232,233,218,105,184,138,161,252,19,33,132,61,159,183,129,62,37,37,194,79,104,59,218,204,215,82,166,4,190,36,224,43,97,59,71,51,188,214,175,54,18,10,15,153,110,203,218,59,225,113,185,123,75,111,206,104,24,163,254,170,85,40,105,9,229,41,218,37,240,211,103,89,253,97,34,77,188,114,220,132,215,129,26,109,149,186,128,119,108,19,20,122,172,175,10,20,169,9,104,195,150,51,8,159,140,86,232,226,177,7,196,200,167,207,106,126,27,140,222,219,198,149,46,0,13,93,255,121,205,23,206,245,185,247,15,231,173,156,59,156,16,48,118,254,93,148,203,237,189,158,180,101,52,62,155,57,8,175,171,215,67,69,104,60,72,232,226,185,20,206,65,59,42,125,90,124,100,202,134,141,239,191,110,203,164,223,50,232,219,4,222,205,22,70,62,180,75,143,174,228,44,62,245,202,39,117,215,33,145,80,106,131,177,244,66,46,89,167,198,251,80,38,72,190,90,118,85,34,158,83,17,61,132,124,53,24,63,24,90,249,68,131,245,198,183,117,13,157,137,70,189,73,23,75,77,13,25,88,126,217,87,108,92,8,133,154,15,158,112,113,94,186,162,177,9,232,181,162,55,24,38,161,79,176,4,233,11,158,170,242,240,168,77,25,3,223,158,186,182,26,129,84,106,135,108,205,79,254,175,227,1,238,248,79,5,72,169,217,128,158,1,139,110,157,12,39,55,95,3,2,113,179,81,229,38,144,253,35,77,155,97,157,9,47,133,35,238,97,246,176,156,164,3,236,181,42,140,173,1,46,164,218,168,228,127,219,160,224,59,249,247,7,155,98,77,199,215,146,55,151,221,185,163,241,26,122,137,164,190,205,207,4,237,134,165,74,238,223,226,15,248,242,139,107,210,187,234,4,145,23,231,180,229,53,254,166,201,220,10,14,58,33,230,72,92,230,207,170,109,188,229,137,28,147,22,41,192,213,40,215,216,127,14,228,9,13,85,247,106,247,1,155,206,136,4,23,190,148,170,106,194,155,170,96,227,85,168,247,195,20,113,172,17,34,38,123,79,167,110,206,207,53,66,173,162,178,166,84,120,160,160,218,186,227,34,87,100,212,219,28,84,255,59,138,26,28,227,102,205,94,75,152,55,216,163,46,225,96,152,57,32,57,159,27,251,178,201,231,5,139,31,163,136,69,71,125,19,213,46,252,84,88,215,163,249,153,181,25,227,174,4,105,93,98,251,60,164,4,222,26,165,85,83,87,45,206,132,134,6,108,89,96,76,139,144,143,144,116,59,72,48,184,248,230,195,135,167,29,166,42,207,49,87,221,159,42,168,96,157,181,125,152,96,130,72,48,100,105,145,96,98,200,116,7,131,166,69,99,117,55,141,40,125,106,249,33,118,191,121,159,138,79,27,90,132,13,52,0,61,44,246,212,77,127,107,26,124,234,104,26,14,238,68,79,124,247,99,81,60,135,27,62,83,231,104,214,53,69,104,188,95,120,30,105,222,150,218,223,80,221,209,86,113,125,226,123,36,1,136,94,206,253,124,34,218,2,77,208,172,39,238,148,151,111,237,3,135,99,41,22,142,129,39,56,105,255,31,62,12,171,5,206,94,114,13,174,185,89,199,225,131,239,187,92,132,102,86,138,156,36,55,112,65,191,209,70,60,75,110,59,216,180,148,36,118,238,139,97,222,17,236,209,68,163,76,177,206,58,196,113,2,166,47,131,113,199,180,134,23,174,24,119,20,124,144,29,221,9,90,224,188,131,232,13,244,94,200,129,51,27,11,124,24,154,5,91,171,150,238,212,117,175,71,155,110,168,3,236,162,196,193,74,101,6,238,157,132,151,181,88,122,26,84,194,170,253,198,124,142,133,185,66,4,105,5,152,87,209,178,134,243,242,197,214,209,103,53,218,128,193,9,83,231,55,111,29,235,133,45,107,115,71,203,15,1,69,200,105,216,1,163,183,18,222,54,6,56,48,104,228,237,119,166,90,242,184,97,160,218,194,255,151,131,120,180,104,202,167,157,179,147,77,161,34,65,201,171,236,177,175,0,92,134,255,40,217,133,61,187,44,165,109,184,127,37,189,61,62,60,232,182,210,78,123,118,207,185,156,158,77,117,67,26,37,222,174,87,192,241,152,180,170,218,35,86,86,91,87,98,97,192,129,140,194,233,36,79,152,203,136,73,223,63,26,117,190,88,188,60,42,9,45,54,223,198,207,196,237,26,244,60,233,67,132,223,113,147,253,16,126,10,119,41,159,99,237,109,167,23,248,146,7,166,214,75,0,234,202,90,254,26,71,82,240,116,216,96,236,109,46,104,255,134,115,253,155,36,36,129,188,183,140,151,14,153,244,139,244,252,214,160,8,249,226,35,58,185,116,255,126,128,120,235,190,225,169,185,175,255,64,176,56,247,249,7,18,39,92,249,142,98,47,116,247,126,6,66,208,245,253,217,123,160,123,49,99,18,90,47,9,80,207,212,123,18,61,155,193,44,242,205,146,4,96,210,222,194,220,47,172,241,165,29,155,45,163,105,121,174,115,233,211,216,182,136,24,90,234,77,214,70,94,160,35,59,16,39,71,24,186,43,251,99,53,11,47,60,159,24,144,250,41,114,90,26,97,209,154,96,63,178,67,28,211,107,179,90,253,127,165,163,26,175,163,165,60,47,25,151,210,245,25,91,122,31,176,184,179,128,161,75,71,166,119,40,19,58,101,115,237,145,211,239,250,235,224,4,46,64,94,118,213,191,21,42,27,169,75,217,193,182,121,215,57,216,234,245,160,135,78,21,125,113,51,250,39,177,32,227,61,57,182,118,16,212,181,130,153,240,62,148,127,188,127,160,37,3,231,33,68,181,179,95,116,179,14,247,145,214,104,222,71,140,17,161,171,218,105,81,195,25,20,202,235,110,70,90,42,47,194,109,74,85,60,77,65,92,205,106,16,171,147,0,227,16,251,48,224,101,8,46,29,94,50,36,213,78,254,13,7,254,227,219,219,18,45,213,145,136,25,210,42,32,47,62,61,139,31,140,17,210,249,37,178,80,160,59,139,26,250,178,179,208,129,81,82,239,54,209,224,20,156,174,251,26,130,136,28,68,243,28,42,28,17,51,90,6,39,125,11,249,223,165,193,243,148,129,17,210,146,186,89,202,253,59,205,5,52,237,17,181,104,92,54,142,214,177,178,59,214,195,73,72,186,175,17,1,0,220,146,69,144,120,89,133,146,152,239,230,141,237,0,78,250,117,54,179,45,38,167,90,149,136,233,115,8,227,210,205,255,208,177,5,45,173,12,189,122,109,122,136,191,40,176,51,234,201,4,208,42,147,44,56,120,17,43,69,93,97,143,103,130,166,129,101,7,40,85,92,157,218,212,230,114,139,2,233,64,93,127,49,140,232,168,194,0,74,215,40,158,61,12,247,57,151,103,148,42,210,155,139,211,87,19,0,208,70,224,199,34,241,199,70,169,161,135,61,105,233,172,62,114,0,96,15,45,231,45,55,172,39,55,41,225,133,190,138,162,53,142,120,95,183,32,192,36,208,155,102,233,86,61,53,30,206,83,199,125,72,101,207,29,247,104,10,148,18,184,234,165,202,151,116,193,119,185,112,23,192,20,152,65,174,8,254,94,56,95,112,30,175,131,75,160,36,26,226,61,55,97,225,40,77,212,181,0,239,155,198,208,128,240,202,248,190,135,42,46,22,94,11,61,30,199,55,16,98,142,1,63,173,36,147,172,74,152,45,239,201,204,46,115,27,81,227,120,112,155,184,99,79,214,130,147,122,64,139,9,147,208,82,76,15,123,98,5,74,218,198,40,175,162,34,226,243,95,227,126,94,45,242,141,118,9,49,66,13,62,135,201,56,200,96,255,212,204,11,3,243,18,242,108,74,227,62,173,115,180,224,226,248,249,141,136,245,6,158,110,65,8,248,189,225,236,226,84,45,8,72,133,12,176,12,140,172,135,245,88,80,88,0,185,175,79,207,75,134,219,100,194,29,255,125,135,114,8,126,63,172,235,145,65,229,120,37,197,36,66,254,60,122,61,197,192,6,79,197,152,198,219,179,231,14,155,211,69,154,175,209,49,59,91,6,25,138,1,144,199,28,148,67,149,19,37,147,101,173,173,206,196,37,179,47,184,185,251,43,182,74,221,246,66,82,220,131,113,87,197,241,66,226,95,156,93,186,196,250,229,244,248,189,22,207,27,43,104,3,210,183,207,145,95,190,74,251,145,107,71,36,138,225,83,79,207,145,78,210,137,175,90,23,239,94,181,98,41,136,109,211,114,150,87,255,49,149,169,69,132,65,211,140,205,214,29,22,127,210,12,110,19,72,139,152,200,229,246,220,110,222,227,189,5,36,90,254,53,6,237,122,57,142,108,23,90,140,146,218,237,207,124,148,18,43,1,231,98,177,83,35,133,156,57,105,201,222,84,80,168,12,176,33,62,83,81,72,91,127,176,136,94,105,255,254,90,145,155,68,132,45,203,4,81,16,2,218,66,189,227,170,31,12,196,122,121,143,12,99,122,129,195,234,210,79,14,55,209,162,72,6,182,66,57,203,144,165,124,104,28,239,250,145,78,30,73,201,115,103,29,184,58,64,70,85,21,63,220,48,82,120,182,147,193,160,57,159,29,228,110,185,119,116,208,106,226,116,121,81,43,222,244,81,208,45,54,252,92,150,203,97,118,228,145,19,251,135,68,118,217,134,205,225,179,191,233,152,12,91,197,183,100,112,245,155,90,49,164,31,226,11,161,97,101,12,52,104,87,67,185,88,236,186,244,207,7,33,67,86,181,69,233,84,8,132,228,204,119,32,165,140,91,72,140,72,59,85,160,243,119,182,101,202,174,103,225,103,157,66,245,6,239,65,118,228,82,220,95,37,111,101,138,161,191,68,163,207,254,132,5,33,34,56,45,15,145,79,100,40,250,236,235,36,175,245,20,209,154,13,198,149,155,0,80,11,84,80,172,105,217,187,232,7,132,48,231,150,103,105,189,165,83,77,153,247,75,244,46,186,175,219,208,150,199,180,28,58,132,148,105,13,207,113,32,133,101,252,13,167,207,239,200,38,246,25,126,101,156,150,20,134,155,28,193,203,237,91,8,31,34,172,248,160,57,105,219,239,42,133,226,116,81,43,132,235,167,30,68,43,231,221,164,52,182,249,179,61,153,161,159,137,151,189,73,236,246,163,36,98,19,85,248,126,173,105,179,75,212,179,6,192,100,128,153,211,199,108,66,203,86,207,169,95,199,34,119,154,244,10,13,220,112,98,175,183,40,113,55,27,57,116,86,1,170,179,54,173,252,94,178,69,116,19,143,251,130,194,112,136,117,223,38,229,127,85,195,14,156,30,223,71,155,223,129,124,152,171,136,110,120,95,180,53,100,168,25,3,216,42,54,85,46,69,119,107,155,145,251,64,53,185,193,15,13,139,6,167,11,60,47,89,97,48,152,126,89,204,146,71,95,57,111,150,78,240,251,102,115,113,11,147,15,192,253,231,25,248,245,109,134,153,56,58,101,46,144,2,253,31,2,83,198,61,64,121,63,76,80,67,29,12,66,28,147,254,92,69,68,35,212,156,221,161,237,249,146,56,121,137,145,156,246,183,247,139,124,62,163,212,103,229,186,93,174,69,23,160,26,196,181,43,175,176,60,110,211,55,131,146,61,179,46,79,154,194,63,7,77,202,244,150,202,18,92,217,129,241,239,222,111,51,135,13,231,255,23,171,205,2,165,228,225,46,247,213,245,181,190,140,154,241,182,186,251,24,83,159,137,53,64,138,170,164,60,147,27,90,82,193,36,201,173,182,188,108,188,229,45,193,211,18,253,200,185,25,95,180,93,30,219,69,195,239,222,97,161,110,214,36,114,96,168,76,77,164,53,131,226,197,100,0,42,106,159,84,214,55,249,124,216,170,102,155,118,134,77,181,65,115,14,167,123,89,46,212,228,181,29,222,148,86,228,253,74,236,231,197,148,188,137,167,27,127,12,253,186,84,67,146,211,91,131,122,218,230,239,254,175,168,1,213,249,121,7,221,136,146,201,36,166,47,73,221,190,128,205,126,206,89,121,78,233,57,64,136,20,67,198,178,249,191,17,131,33,149,197,130,104,170,130,142,237,246,170,147,192,156,248,187,123,25,225,139,220,171,61,24,24,114,110,77,3,160,244,82,56,94,113,16,27,118,228,217,56,29,253,10,75,145,97,193,150,89,210,52,60,146,17,127,187,216,5,195,108,15,251,39,157,158,86,49,193,199,155,106,6,73,80,247,203,61,88,81,56,93,158,179,40,245,81,68,136,69,32,237,101,122,112,165,100,55,9,127,59,26,9,41,16,102,92,246,179,125,108,231,225,63,120,88,135,69,195,239,197,51,245,72,72,59,15,231,42,3,184,123,64,176,64,2,15,246,220,67,193,252,8,159,56,20,44,137,45,172,109,183,204,159,101,6,17,221,228,44,160,69,242,153,202,128,203,12,4,126,92,35,50,234,50,118,36,235,41,31,25,142,113,24,62,9,95,20,19,50,125,158,204,53,186,86,53,189,102,153,228,219,22,2,99,14,143,147,221,199,23,113,107,196,224,225,104,121,99,34,19,112,121,28,191,160,245,10,17,84,184,88,225,151,167,54,240,195,72,254,120,18,22,155,131,146,29,227,234,30,101,250,135,69,125,243,191,220,108,252,27,73,15,229,136,53,207,18,173,204,19,205,199,182,167,225,33,249,143,99,91,17,55,149,227,252,128,238,114,212,169,242,145,36,176,68,219,87,139,157,11,63,61,59,211,206,153,189,127,223,109,58,97,39,141,146,29,253,92,94,80,25,18,106,154,118,230,19,134,225,160,83,60,150,40,14,114,137,33,215,197,110,48,190,240,56,91,138,248,129,37,247,39,83,175,2,103,194,229,110,102,216,12,120,6,3,226,163,55,78,249,252,111,226,91,6,137,148,130,47,48,247,229,23,243,182,71,150,137,124,20,124,66,139,32,193,148,161,185,236,79,174,99,200,112,53,55,117,29,34,237,204,153,30,100,212,1,178,63,101,108,21,60,226,164,189,178,191,164,14,130,253,211,82,162,209,199,23,248,243,208,248,249,158,141,215,199,86,0,246,74,146,131,115,160,41,65,31,203,224,248,194,77,33,67,47,171,200,140,46,76,21,188,172,177,183,243,246,224,185,32,56,122,180,233,201,25,233,15,85,45,133,25,16,136,35,136,145,142,15,86,80,133,48,119,224,178,65,40,193,213,90,108,89,160,56,151,217,217,57,103,175,63,242,81,89,154,80,29,72,39,62,162,124,64,207,184,236,170,24,70,121,44,61,235,14,3,108,68,201,57,178,69,188,58,91,211,235,251,154,69,34,123,86,213,66,253,253,216,176,67,99,197,91,185,250,198,244,215,134,106,130,27,155,101,61,23,181,173,83,247,184,185,24,221,87,94,129,150,24,83,250,180,99,14,23,157,95,133,189,98,219,252,120,118,181,213,41,131,138,220,245,32,75,155,209,55,31,197,21,188,175,14,108,96,144,219,70,87,169,105,80,215,39,54,253,164,135,220,113,179,11,26,86,90,17,173,82,168,51,234,219,159,197,190,211,12,96,163,96,156,21,216,237,81,71,8,238,177,222,65,238,18,207,224,198,6,78,77,58,229,128,113,49,80,53,64,60,188,235,183,243,253,19,186,159,48,179,25,11,199,176,100,249,48,94,85,170,164,215,111,157,248,47,235,115,199,148,241,90,5,156,158,194,36,48,2,128,54,251,107,121,73,162,149,9,148,65,58,167,164,203,170,52,197,196,44,120,167,22,204,41,135,101,200,149,248,38,73,57,71,205,69,158,255,72,185,219,30,199,49,162,53,242,190,45,142,206,11,94,30,40,120,221,10,171,209,31,64,30,69,102,138,222,180,169,4,28,97,34,15,174,50,15,217,31,255,141,56,24,233,173,156,216,252,142,255,94,59,43,223,147,253,34,44,189,10,93,55,252,67,27,40,123,12,243,5,33,140,234,16,240,115,171,26,131,179,201,114,216,135,196,14,204,11,226,91,159,139,238,182,65,152,10,212,173,146,189,31,16,197,251,214,140,176,101,41,217,127,19,65,118,112,116,119,159,28,52,102,175,254,92,132,73,106,70,124,121,229,34,136,208,230,102,14,165,73,4,170,233,83,76,138,148,54,152,21,227,68,40,188,180,162,79,72,48,228,26,205,64,66,33,171,221,163,170,114,114,184,172,219,201,168,200,24,77,52,12,80,226,95,105,205,101,189,221,3,5,202,38,226,148,208,76,126,116,245,120,125,186,56,187,96,82,46,133,211,10,66,86,187,156,137,23,160,98,171,226,232,11,114,200,18,250,211,87,122,21,93,163,90,104,194,160,53,194,74,207,94,195,91,24,76,184,136,174,136,22,245,12,54,167,76,106,249,48,251,40,188,97,95,223,30,22,142,194,231,189,143,57,151,51,105,150,197,223,211,167,34,90,118,91,128,229,236,240,185,96,234,208,26,179,111,122,244,232,80,12,38,10,75,30,38,189,236,165,19,26,106,197,252,71,235,185,204,73,177,213,143,142,148,0,198,150,67,125,250,112,233,80,164,49,60,6,157,40,93,68,163,97,177,11,138,69,11,80,35,151,37,226,112,83,104,68,199,208,112,120,18,122,5,174,225,120,249,246,187,239,139,207,193,43,156,214,226,0,98,218,49,189,224,164,249,146,98,223,125,50,17,156,249,81,199,227,5,93,233,167,93,238,114,241,192,104,44,145,2,60,79,168,0,112,62,78,120,31,150,105,225,33,243,194,10,247,239,80,186,67,248,147,112,190,206,149,49,185,35,4,129,193,254,128,152,100,164,105,79,44,168,54,203,1,129,230,43,92,174,4,56,200,148,20,82,211,212,136,193,83,214,240,81,138,39,11,132,114,55,99,194,4,143,40,233,177,238,255,46,166,183,5,115,190,182,171,253,136,6,248,32,219,26,252,55,109,189,224,176,219,6,131,136,170,148,101,102,58,242,121,97,120,125,146,126,232,251,70,200,193,191,199,169,112,172,43,218,147,205,17,215,99,9,141,194,206,149,104,71,115,45,250,190,121,28,115,88,81,131,250,172,238,160,98,146,119,165,113,166,10,172,34,174,43,44,119,114,32,110,169,188,210,22,181,71,3,8,218,196,202,103,105,234,72,209,168,202,3,206,120,58,52,91,169,202,207,73,67,52,223,246,40,85,129,186,17,147,193,231,46,110,139,178,74,210,186,252,20,42,212,66,107,31,239,184,60,105,247,138,212,29,59,35,147,239,109,123,57,144,11,149,66,71,134,57,20,223,47,197,51,83,184,140,102,217,213,245,43,232,173,139,129,135,141,23,147,64,170,6,101,154,52,47,242,34,140,3,101,199,41,95,122,146,104,251,210,114,60,120,85,93,235,23,132,185,200,46,225,58,185,30,23,139,234,67,231,176,36,70,216,129,111,57,23,74,254,117,89,199,41,209,178,61,214,211,184,105,167,86,249,49,90,42,123,168,58,104,222,200,67,41,108,0,17,167,116,177,110,201,116,233,182,36,97,100,6,194,14,109,98,123,229,192,135,60,139,212,178,229,24,178,75,57,129,64,124,38,73,23,182,0,233,69,40,62,242,69,133,151,96,88,46,115,166,144,227,171,12,67,150,150,224,205,128,11,68,98,7,65,199,98,217,18,163,103,246,75,237,111,191,192,188,237,204,240,118,109,98,193,54,170,132,185,37,96,110,213,152,18,190,35,50,82,137,93,149,215,225,221,42,90,5,238,158,171,51,61,216,167,102,11,175,66,32,95,200,136,58,38,185,31,31,7,154,137,77,199,135,129,68,11,138,218,56,51,63,138,232,178,118,35,168,128,222,75,254,4,133,240,20,138,225,42,242,179,147,238,252,236,171,207,216,158,161,187,121,28,211,191,97,168,90,83,211,109,149,65,124,180,9,172,11,247,233,144,178,35,236,201,59,110,14,121,70,14,224,61,254,78,212,28,174,65,117,240,197,140,63,81,231,180,236,142,119,35,45,55,146,227,92,243,89,103,227,113,113,7,241,196,218,216,222,133,210,176,201,227,29,129,190,164,242,224,9,230,82,122,179,114,75,246,39,15,229,149,39,223,54,20,209,236,251,52,201,186,78,73,37,151,126,3,228,78,186,96,42,131,8,164,251,31,66,192,181,12,97,55,186,77,32,219,199,151,33,3,42,85,29,142,29,6,107,115,68,114,214,114,140,199,143,20,245,129,9,78,83,246,169,65,41,122,99,69,204,115,173,8,254,95,66,163,162,48,175,244,113,209,100,147,112,188,220,233,113,5,212,201,138,91,38,191,72,7,99,178,116,234,92,48,244,0,211,154,27,247,206,232,89,85,99,233,132,72,85,200,139,238,153,179,24,123,99,134,246,142,188,239,9,157,112,162,234,185,118,245,59,130,224,204,31,163,171,38,159,221,225,99,216,177,58,35,104,109,10,125,89,23,53,56,37,68,165,189,60,83,249,63,161,240,70,141,1,210,143,125,157,56,227,11,24,55,38,168,16,119,213,155,223,143,131,175,37,234,125,238,16,194,101,201,158,4,110,18,210,221,84,87,14,13,169,250,241,240,1,12,205,98,246,198,75,250,239,249,104,97,127,57,19,15,104,126,28,59,196,119,32,32,82,17,212,81,175,226,118,175,241,105,177,135,71,82,187,16,240,159,71,37,41,230,115,64,156,184,169,24,234,219,0,246,117,253,167,73,143,69,3,130,245,116,43,177,166,154,119,212,153,47,46,26,192,155,252,200,241,110,201,195,252,231,181,147,45,221,62,85,89,150,72,79,230,174,245,52,49,209,202,184,143,160,9,190,63,249,33,193,163,53,123,237,31,46,225,42,225,49,158,14,120,71,133,247,37,52,27,195,168,0,173,254,175,48,203,127,136,142,20,140,58,102,224,52,13,72,195,143,146,84,91,160,228,92,126,63,39,81,150,207,232,13,28,22,22,113,169,45,140,23,5,46,155,127,197,116,25,54,226,104,89,169,95,100,83,211,41,119,115,107,60,190,170,12,213,173,189,220,228,10,211,105,116,245,166,208,229,181,165,201,68,170,57,36,97,78,110,76,75,65,230,77,138,17,146,196,148,196,16,237,121,105,24,158,75,121,236,185,205,129,31,100,68,181,179,248,183,65,29,74,96,126,223,176,27,19,62,148,147,12,48,70,173,22,7,123,162,216,137,16,123,171,81,196,100,84,138,92,119,3,209,28,49,46,184,35,78,201,26,213,233,176,139,204,161,161,100,134,151,46,27,220,236,243,154,104,171,179,29,24,244,219,213,4,109,217,17,167,110,219,11,225,255,47,80,164,122,91,85,104,133,179,78,39,122,132,12,176,53,220,175,184,93,42,5,93,129,217,176,225,1,179,77,53,121,239,203,231,143,218,94,107,129,31,11,195,254,148,78,105,60,149,153,223,20,120,153,7,211,141,71,154,236,170,254,85,202,104,196,108,18,145,215,252,129,244,163,252,137,151,112,146,157,1,59,187,240,13,15,2,216,118,65,35,126,38,27,221,174,235,245,160,106,120,196,95,105,214,48,54,136,226,74,65,88,37,3,224,245,60,140,2,150,249,134,212,251,59,123,169,14,76,79,118,67,227,62,202,182,40,50,114,7,24,44,54,254,33,251,230,193,198,191,167,178,228,71,214,100,187,93,9,99,58,230,102,178,170,160,39,178,130,14,57,7,70,171,249,174,14,35,35,120,237,233,152,182,162,97,118,134,142,150,24,7,159,154,144,20,178,175,155,125,114,58,253,140,118,189,3,236,201,17,137,170,158,6,138,214,209,52,137,203,102,157,11,99,113,92,97,55,117,153,111,20,219,251,13,105,77,46,143,89,53,195,147,116,53,124,195,182,95,154,49,226,94,206,124,56,128,210,109,131,196,167,229,110,5,138,241,184,84,170,48,209,20,77,49,194,144,208,224,23,8,82,52,152,83,235,136,168,48,59,7,125,42,229,139,89,170,227,83,9,67,233,174,188,101,17,74,229,208,35,149,23,105,183,73,116,1,80,193,46,164,25,242,129,1,17,88,87,87,94,55,96,126,151,60,35,202,219,9,3,222,161,131,34,149,198,202,198,131,167,91,75,106,85,22,230,193,8,201,156,81,226,164,111,44,147,161,162,209,240,123,26,148,30,161,104,16,29,236,170,204,149,74,126,34,109,24,139,125,1,32,228,137,89,30,201,147,146,189,177,123,185,72,228,107,91,49,121,163,27,243,72,155,29,183,58,67,212,196,210,201,58,31,102,67,158,141,70,175,80,213,3,99,198,124,34,110,94,209,77,20,85,45,162,82,18,61,189,203,199,56,131,228,230,7,53,226,247,217,35,66,115,37,68,130,210,200,156,186,44,33,11,229,31,84,159,92,194,52,14,158,187,179,106,80,194,179,80,226,202,110,147,204,167,44,63,158,49,55,80,115,164,46,156,244,58,137,134,55,253,220,75,9,103,136,249,242,3,215,220,53,123,17,75,112,40,131,105,76,0,16,17,245,242,195,47,165,106,200,206,26,130,189,65,203,2,99,181,5,143,191,100,128,52,249,154,169,127,159,85,163,175,105,201,79,170,124,33,172,15,229,166,146,194,104,108,129,91,132,33,195,224,4,116,61,113,89,52,79,251,121,2,32,71,98,121,115,214,245,87,160,16,97,250,177,149,55,39,223,212,203,76,231,248,127,176,129,187,75,9,209,101,237,148,65,111,200,193,164,44,66,237,159,220,85,84,91,89,208,128,237,151,180,31,151,237,151,16,114,221,155,43,42,4,83,34,238,79,149,66,231,157,222,132,11,145,104,170,56,236,84,248,183,36,85,4,10,143,170,141,177,87,7,163,114,225,72,248,238,122,146,203,203,157,4,155,198,245,193,60,218,180,175,34,89,80,195,35,71,85,234,238,86,77,49,244,128,157,230,211,30,114,38,88,35,242,190,254,27,132,194,18,236,121,228,133,95,97,44,236,154,28,64,235,14,62,141,6,104,2,239,196,0,239,190,200,189,55,225,88,118,166,28,3,155,39,73,135,166,250,86,28,103,243,78,21,135,177,206,135,183,141,13,148,181,253,155,176,98,53,113,191,110,156,23,111,210,0,12,145,6,255,146,80,247,0,74,171,33,213,96,90,118,193,89,208,79,47,247,61,246,11,199,235,65,231,27,63,41,110,254,129,80,132,0,167,84,59,171,175,164,131,185,207,179,36,207,187,236,180,205,188,150,112,119,170,82,180,155,78,6,33,163,196,74,97,85,204,95,48,248,81,22,74,219,228,3,163,28,111,155,134,69,37,9,187,242,25,75,186,8,17,151,196,130,59,118,14,82,207,194,129,82,65,199,147,72,96,117,243,22,125,145,219,206,184,153,41,144,219,98,96,155,34,94,181,44,163,237,168,33,89,151,218,192,247,57,198,126,236,197,141,63,109,159,157,29,83,185,46,181,8,73,42,95,252,161,116,224,219,172,169,119,219,52,46,170,69,178,172,93,174,0,45,81,139,114,181,102,240,100,159,66,137,156,200,175,244,173,51,117,206,244,24,77,6,23,82,12,37,118,160,225,85,183,69,79,100,126,129,93,155,18,95,145,39,32,118,241,90,236,152,14,20,126,31,234,84,34,120,172,90,243,50,162,34,238,83,91,24,255,99,225,240,27,114,166,100,243,207,98,170,111,107,224,19,79,177,203,231,135,126,205,13,231,108,153,215,16,143,6,18,244,71,18,188,143,224,169,189,54,129,185,202,121,10,142,246,219,251,81,92,184,115,207,55,223,23,9,172,6,80,2,236,96,4,51,62,54,135,46,10,0,229,235,188,235,218,127,115,177,136,157,40,2,71,146,32,245,200,137,190,179,220,117,208,242,197,14,183,79,124,35,171,203,89,139,208,30,50,32,249,148,242,236,98,48,88,255,143,25,1,235,159,210,127,229,219,6,20,19,41,23,220,116,32,214,217,7,197,244,101,247,93,18,117,151,140,84,68,104,42,232,36,226,57,55,57,181,128,52,6,203,130,54,199,103,197,158,184,138,127,61,223,65,111,57,25,181,72,139,155,65,139,48,15,128,95,194,241,163,12,246,39,191,53,212,114,194,90,65,109,13,121,48,171,160,68,35,192,251,149,193,182,207,178,158,107,32,192,59,214,166,145,205,76,194,17,236,248,105,195,184,201,91,214,106,71,163,206,253,189,15,166,160,158,55,182,108,213,82,244,47,221,194,227,48,139,93,104,165,186,46,214,47,63,142,36,158,192,116,253,133,77,50,45,85,208,33,203,120,156,6,55,217,53,210,131,30,194,170,65,32,80,32,81,218,104,125,77,236,131,42,23,51,41,208,230,40,175,127,201,126,254,209,89,221,187,181,101,185,235,139,217,248,49,187,232,192,124,28,52,88,70,236,155,38,60,43,157,178,180,45,203,113,4,9,67,86,60,136,52,5,61,152,126,254,205,152,68,61,64,58,226,75,218,19,204,177,16,138,148,243,180,234,110,6,134,194,139,167,50,151,95,62,160,137,209,208,255,81,199,177,240,114,1,163,160,235,235,172,203,57,245,240,94,121,56,11,132,16,23,152,180,38,90,26,107,103,77,223,70,133,160,220,55,161,159,238,135,127,195,39,208,86,53,94,195,241,255,207,90,238,9,252,64,51,154,107,238,114,42,193,58,242,19,108,172,209,86,71,42,197,80,100,152,114,254,57,174,37,64,50,36,160,251,173,106,84,18,16,170,209,101,166,151,240,142,96,134,97,50,207,93,244,231,22,49,72,181,188,188,85,53,41,160,158,84,157,23,30,169,226,115,33,73,115,107,143,0,226,138,147,191,74,190,144,231,29,158,45,154,232,182,228,53,105,112,118,75,176,179,123,111,233,14,139,90,157,138,223,14,191,88,106,91,191,149,119,119,125,12,238,211,244,188,43,214,146,153,165,147,172,221,81,131,160,19,124,234,236,188,144,176,73,96,127,208,169,247,17,186,160,163,61,186,59,233,72,217,58,90,43,43,23,250,105,188,236,66,19,98,125,250,90,130,162,167,174,46,218,37,184,26,92,237,34,0,26,104,74,167,221,23,105,113,9,187,125,231,185,93,92,121,93,23,185,54,19,90,235,249,3,121,58,43,88,53,140,51,45,206,210,228,223,67,147,216,82,11,167,178,164,218,132,152,116,134,84,112,15,165,106,15,116,46,222,118,186,76,133,157,255,99,27,35,96,230,14,223,36,164,244,30,234,71,169,225,124,239,103,239,185,44,71,223,241,177,16,211,173,64,220,127,244,65,244,249,195,214,90,121,43,248,177,241,128,96,74,224,104,16,53,79,225,14,219,175,78,129,103,35,184,131,156,66,49,75,196,237,145,109,124,157,74,188,157,84,32,153,170,210,235,165,6,155,60,118,114,50,169,40,37,1,220,122,220,107,20,39,19,238,244,128,227,140,103,0,179,250,11,140,38,165,57,63,111,193,84,165,175,223,21,24,232,153,190,211,114,99,96,103,146,32,24,107,66,117,93,27,243,49,114,246,219,30,34,20,17,69,183,243,131,101,22,123,146,89,58,14,130,29,141,36,211,54,162,164,189,208,207,2,157,64,29,178,133,166,206,71,226,123,104,195,207,127,14,140,247,187,212,124,199,222,83,46,134,206,111,75,190,63,73,82,47,139,200,197,11,130,44,168,239,104,124,162,31,115,106,15,77,72,8,188,215,102,185,145,177,146,105,215,243,128,236,120,202,35,200,18,3,56,41,51,228,233,136,75,253,209,15,226,133,173,67,184,30,89,158,18,91,156,153,18,111,152,178,1,79,85,158,151,216,76,58,134,155,146,49,89,17,51,188,208,128,156,11,43,131,131,106,12,149,63,166,121,16,63,219,137,51,65,222,5,172,189,253,110,113,53,167,226,44,245,31,50,38,174,100,68,22,13,112,212,36,155,239,195,60,53,18,123,223,198,86,22,195,153,183,238,240,84,186,32,5,221,42,82,204,140,146,40,142,221,64,66,150,70,55,47,30,39,14,91,230,39,190,250,204,44,92,192,48,150,46,192,2,42,75,126,145,237,31,191,38,153,131,36,227,179,79,231,201,9,204,104,33,64,247,81,36,153,134,244,72,253,218,167,247,131,248,178,75,238,207,226,79,244,209,92,176,76,70,26,233,159,72,80,240,245,86,236,211,60,129,147,52,202,224,10,121,136,140,72,97,73,10,133,96,120,170,207,50,34,150,192,32,223,232,196,218,17,88,13,218,31,177,119,20,156,206,58,133,152,213,248,174,186,249,107,70,175,113,37,10,115,145,51,107,100,20,219,82,204,77,140,219,219,169,215,58,48,94,235,31,79,145,66,12,48,214,3,229,197,44,184,188,88,27,187,162,100,106,211,186,207,12,7,55,129,174,102,0,79,203,232,178,166,41,96,67,20,205,236,10,17,185,214,114,166,94,180,205,186,114,55,253,184,106,217,46,50,15,196,129,214,56,81,178,117,165,228,136,107,226,194,252,239,232,52,189,121,119,33,227,225,214,234,74,40,173,225,105,36,9,32,65,235,127,209,218,119,230,246,90,85,92,208,117,25,145,241,125,158,150,196,130,194,200,251,49,170,85,124,87,213,239,96,184,96,197,63,244,187,217,215,49,3,224,114,164,10,22,251,65,108,238,13,29,254,18,139,129,219,58,169,151,73,96,64,221,26,16,12,14,12,78,9,203,11,80,73,221,118,103,173,1,169,193,215,109,126,166,137,12,12,135,17,81,209,32,12,131,60,0,153,66,201,121,182,155,39,109,173,1,186,45,253,219,88,63,179,91,22,106,108,66,107,17,105,97,59,6,133,136,82,129,125,190,184,234,131,23,198,146,94,243,204,25,190,50,160,81,176,220,38,215,41,120,112,38,74,163,171,24,106,116,214,231,194,77,99,71,195,47,141,134,111,103,119,122,241,34,5,170,123,150,232,85,63,156,112,76,202,78,176,136,79,161,164,245,223,119,235,27,8,99,121,57,0,225,90,143,129,173,209,102,133,158,64,233,181,113,212,237,35,132,15,88,36,85,226,152,217,11,16,251,213,25,7,85,125,48,155,221,141,133,205,66,237,6,5,241,72,247,133,199,177,78,236,71,27,110,205,207,241,40,22,141,156,101,179,172,227,30,248,161,147,84,177,176,26,32,103,36,110,30,67,137,223,121,255,110,247,94,76,30,149,83,111,96,72,165,93,200,58,207,176,213,13,29,75,187,45,112,179,43,234,213,242,216,43,249,33,207,40,167,96,46,219,167,44,111,57,183,96,243,201,5,215,73,106,130,134,7,142,153,17,97,126,88,35,57,154,246,15,16,48,120,187,131,106,242,11,250,99,54,230,135,88,172,62,208,30,127,145,236,44,247,246,202,229,174,206,139,144,172,167,141,73,106,163,33,202,57,80,76,67,219,18,99,153,119,22,223,8,132,90,173,119,88,241,34,158,228,149,129,248,73,110,153,176,170,26,33,117,151,227,204,107,181,26,21,245,164,236,219,77,199,199,35,205,68,49,148,238,100,242,214,99,155,100,23,181,56,99,13,119,225,107,153,143,182,246,225,208,95,196,75,114,87,98,134,84,115,210,91,16,159,38,83,255,6,141,147,176,178,28,7,98,154,157,117,22,186,222,203,229,195,97,78,111,21,1,209,7,216,220,49,206,103,113,12,92,248,125,213,205,208,125,25,23,255,131,122,18,244,102,110,19,246,57,97,29,160,122,12,249,191,178,249,218,202,196,118,95,227,2,202,72,253,166,224,126,142,247,255,235,17,182,40,239,72,49,69,198,190,146,45,197,143,72,232,60,106,114,24,207,64,199,21,148,63,154,255,94,65,161,221,130,35,137,115,115,180,84,241,144,61,126,156,106,22,242,150,187,185,206,193,114,109,233,188,162,195,80,84,37,148,76,38,233,82,107,55,196,65,244,142,66,169,247,79,119,3,176,143,31,254,163,250,36,254,95,244,199,37,243,80,12,199,218,35,41,133,113,33,14,19,65,68,109,255,12,46,255,36,190,184,245,158,28,243,54,230,255,252,10,28,140,185,137,52,36,177,174,246,253,228,33,46,4,171,48,142,104,247,44,43,68,29,108,218,170,183,172,241,193,73,207,219,37,138,1,150,130,219,251,45,165,77,163,56,41,211,48,28,136,245,232,57,137,129,92,21,128,45,154,238,208,32,231,214,120,74,179,72,201,37,186,206,84,50,7,123,49,12,239,253,65,164,149,178,102,109,53,34,240,96,200,137,6,135,145,49,172,151,73,182,67,200,127,30,211,36,85,185,165,56,97,54,221,209,90,70,22,143,152,129,15,204,59,5,143,171,180,132,244,145,20,44,11,142,181,72,223,151,147,26,241,164,157,222,7,97,79,43,35,103,66,163,25,155,118,174,109,181,98,111,56,136,55,63,81,51,89,250,61,148,153,110,132,172,218,99,18,104,242,83,175,53,197,209,126,182,44,53,73,229,104,21,252,214,227,27,176,170,31,200,156,251,40,253,90,104,145,10,1,175,235,135,77,56,137,11,51,99,233,59,250,122,62,196,2,245,142,86,59,143,192,123,130,214,245,182,157,134,228,82,199,243,29,167,83,105,75,4,236,116,174,50,18,89,242,200,87,109,23,221,184,42,3,82,80,103,135,218,190,7,129,98,180,64,149,196,181,217,136,28,58,56,53,14,16,248,30,82,197,85,149,53,2,112,81,243,53,131,126,174,187,3,237,209,3,20,9,246,22,3,194,201,118,169,89,116,66,199,66,16,175,193,47,238,65,137,126,87,148,144,167,191,216,137,23,120,162,24,80,68,168,161,148,167,6,137,56,1,160,59,75,181,56,92,175,90,233,7,212,173,52,242,167,91,64,194,196,220,18,71,186,221,224,84,47,76,156,55,190,180,102,18,21,27,55,125,249,219,154,48,54,210,58,72,73,154,78,48,73,105,233,200,178,230,208,130,172,18,160,79,130,20,166,83,203,232,203,108,136,211,228,152,192,103,222,8,46,245,50,29,25,234,254,228,47,202,93,242,41,33,139,115,212,186,141,90,222,177,4}; diff --git a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_32spp.cpp b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_32spp.cpp index 5a329f85..80832977 100644 --- a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_32spp.cpp +++ b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_32spp.cpp @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // An Owen-scrambled Sobol sequence of 256 samples of 256 dimensions static const int sobol_256spp_256d[256*256] = {32,226,72,70,57,171,246,75,112,81,109,239,120,101,230,103,103,41,249,86,253,99,132,184,214,147,128,248,17,149,163,17,60,40,169,196,77,79,102,23,250,77,75,151,95,123,234,198,25,26,184,114,230,188,105,18,231,233,175,151,19,174,202,71,84,229,247,148,182,127,92,14,41,112,162,253,35,101,137,30,111,134,95,122,28,2,41,254,181,91,101,188,145,31,166,38,53,193,1,122,99,86,178,36,198,169,113,255,97,221,227,231,29,100,30,141,250,254,16,157,2,220,187,95,181,125,207,187,105,119,156,41,16,194,93,216,227,124,138,90,227,1,88,153,233,69,120,36,19,189,120,4,185,220,185,109,184,96,247,173,210,227,54,3,18,9,139,213,156,57,61,101,37,247,21,201,10,143,11,38,146,18,118,129,95,191,75,207,12,252,238,104,47,39,190,229,31,56,20,127,42,178,100,141,93,222,192,247,186,7,224,161,72,100,87,69,218,44,25,195,185,118,179,123,231,170,96,225,204,52,117,60,3,86,25,143,230,18,11,165,72,188,158,3,66,105,50,200,226,145,227,45,183,62,82,176,191,36,248,191,189,122,96,185,146,166,203,78,144,189,67,174,154,182,86,169,90,236,101,40,71,107,81,93,159,82,75,230,157,191,34,35,235,139,150,193,10,142,217,77,154,249,74,13,196,248,56,154,27,6,242,226,105,94,66,67,145,112,31,145,133,68,21,0,44,212,254,153,183,238,98,102,145,199,100,213,196,52,131,141,216,209,236,122,58,249,188,108,8,206,62,199,207,103,160,247,207,255,101,185,1,113,223,126,182,0,50,93,250,174,194,18,65,111,206,104,156,3,48,195,122,212,10,101,235,200,13,183,173,7,192,3,101,228,84,168,121,241,205,122,115,132,155,242,215,22,236,242,69,35,48,245,3,175,68,57,4,15,226,155,222,140,54,48,80,200,194,149,213,68,225,14,182,122,147,195,69,166,191,17,176,58,222,58,190,70,66,153,196,215,121,123,176,190,161,145,203,121,255,27,207,28,113,22,44,232,46,84,181,131,245,220,27,202,161,38,94,208,39,143,52,5,154,85,121,139,226,223,159,246,170,56,94,209,188,71,205,76,16,233,168,172,200,37,19,123,120,202,28,175,232,88,120,107,157,198,111,253,18,24,36,35,43,169,199,197,137,194,12,238,138,232,17,17,58,115,39,234,4,164,225,215,14,185,232,76,215,171,142,206,206,132,90,31,130,24,0,165,34,91,126,113,64,202,144,114,132,125,58,184,234,211,246,238,168,7,1,172,169,218,67,29,185,66,73,49,222,167,243,189,36,116,23,223,219,200,84,67,94,53,79,26,202,204,91,180,221,166,106,18,207,17,128,137,246,235,162,13,129,130,49,76,104,189,138,55,174,71,152,49,116,204,207,103,198,147,225,142,79,8,172,59,234,225,192,168,181,144,185,6,233,243,61,123,46,55,44,16,228,79,156,235,190,115,61,162,115,182,122,230,138,204,140,86,173,80,99,207,211,181,23,141,152,17,180,35,121,168,67,205,107,74,55,229,234,210,6,94,48,186,210,189,2,200,190,181,227,128,211,225,215,228,74,7,188,195,36,82,10,131,96,99,138,63,1,210,39,134,153,112,72,163,196,55,126,37,125,107,234,166,129,80,61,97,121,20,123,222,3,155,219,62,49,207,87,182,26,214,167,142,89,38,36,112,87,100,56,245,240,152,23,7,237,11,185,206,233,203,131,42,53,35,60,40,211,114,9,13,189,130,196,210,173,39,208,56,110,34,240,65,75,234,76,73,34,39,2,118,174,237,52,194,197,28,155,161,135,180,200,3,89,210,26,154,145,45,57,54,85,26,118,207,212,58,101,69,202,184,36,234,219,155,41,29,80,22,193,175,145,100,50,29,149,166,168,162,213,130,36,25,234,78,84,97,191,139,95,156,9,12,41,97,110,222,8,16,250,161,130,45,111,195,83,213,16,141,154,48,124,175,89,25,27,9,172,242,51,167,76,109,69,107,23,80,23,166,12,16,180,156,182,238,148,249,59,130,75,122,59,134,240,69,220,21,230,47,1,124,66,180,77,247,147,103,66,98,211,96,105,213,127,178,144,102,213,33,247,141,232,67,62,86,230,222,146,68,122,27,147,7,85,69,31,22,67,67,78,13,149,221,57,121,176,133,161,84,201,146,119,196,217,19,132,52,76,135,247,107,29,131,248,220,156,248,29,41,36,202,174,136,253,191,226,91,179,96,69,213,172,0,206,75,192,54,69,120,138,218,171,185,232,211,139,8,31,11,50,119,28,197,83,158,170,229,244,195,190,23,213,87,70,17,102,197,39,59,88,152,234,95,106,29,195,236,114,136,6,159,105,101,2,119,184,47,212,218,188,165,163,138,174,114,71,54,127,64,183,39,51,42,209,202,106,96,215,154,56,33,102,25,62,111,9,49,4,98,142,198,128,138,13,74,95,229,42,164,19,175,179,111,138,19,157,125,94,34,221,103,246,144,141,176,129,201,55,100,23,12,139,33,227,91,223,224,69,120,83,245,50,57,190,21,54,86,245,95,250,34,71,249,100,201,144,16,221,0,40,74,133,38,145,48,217,119,132,34,138,67,161,62,221,126,108,207,140,42,156,13,224,198,142,19,55,85,254,155,140,168,250,58,118,137,42,78,8,48,89,195,167,91,243,246,88,23,22,206,17,190,56,125,171,116,245,129,121,57,144,228,159,197,243,217,239,86,188,152,88,239,112,120,245,119,147,189,25,128,240,72,208,29,162,23,152,24,143,226,136,174,171,58,178,10,5,250,209,239,88,62,34,251,156,163,231,247,102,112,46,48,61,233,24,71,54,73,12,81,195,243,115,138,145,194,164,135,148,51,201,104,74,24,78,107,65,246,118,159,165,130,206,34,157,177,180,10,126,163,167,129,75,0,149,115,172,21,242,139,162,170,92,238,35,46,24,108,101,62,26,147,180,210,227,166,103,149,188,192,92,115,141,161,120,90,231,250,181,130,208,232,151,157,141,208,27,81,82,42,162,244,186,62,163,6,254,94,107,138,123,144,14,216,138,235,104,135,98,77,82,57,47,77,171,213,192,134,69,226,93,197,9,63,181,197,169,22,248,190,55,178,250,167,76,157,101,170,138,94,156,44,12,155,102,133,133,149,43,224,51,130,44,138,3,195,25,161,29,216,1,188,160,73,4,196,125,240,92,88,50,192,176,234,39,109,96,39,60,165,226,80,248,179,232,244,141,102,81,131,110,19,206,225,222,115,198,63,195,251,19,155,77,51,194,251,124,13,77,69,106,112,114,187,126,67,222,81,227,163,80,172,25,70,205,111,48,160,111,165,112,243,47,236,107,81,15,83,95,132,80,133,178,116,87,10,195,139,151,122,44,82,111,24,234,156,187,202,250,20,233,186,204,184,154,149,117,78,205,119,71,166,192,239,88,148,154,229,200,139,163,129,12,155,167,252,50,198,46,106,221,91,235,75,2,14,240,122,62,178,218,42,223,213,6,17,212,242,32,190,96,163,121,63,228,65,111,229,63,70,140,232,221,248,216,80,5,145,12,27,33,195,86,111,42,125,70,44,232,82,209,40,234,168,224,215,215,133,247,128,76,248,178,34,253,61,204,193,105,44,227,66,45,238,159,16,241,67,99,178,235,181,68,204,234,144,58,40,132,125,203,25,204,148,151,253,195,198,81,8,54,248,148,248,58,54,235,82,71,67,181,212,241,43,111,111,202,69,166,200,66,87,245,207,70,112,64,26,240,149,82,86,28,104,17,59,72,154,106,1,173,59,21,204,184,231,15,224,161,253,174,78,249,25,217,35,144,180,57,102,174,57,138,227,125,141,246,16,35,201,173,170,31,107,205,169,59,19,52,209,226,49,136,168,13,238,63,53,78,203,68,18,146,228,165,245,244,84,215,78,230,167,83,239,15,210,34,99,90,184,143,187,50,98,95,182,121,47,53,112,15,53,239,130,105,66,142,11,185,224,203,20,44,156,28,197,195,65,118,36,206,88,55,37,18,112,9,20,231,73,6,11,225,79,180,145,124,204,29,245,148,198,53,210,171,103,53,215,106,111,154,237,107,2,249,79,145,126,255,255,53,222,196,57,237,131,6,63,45,70,68,190,191,12,210,247,162,41,135,184,234,206,153,176,115,255,114,178,110,24,25,66,114,55,29,79,253,67,124,245,37,236,13,88,232,186,18,143,178,59,5,237,10,249,253,37,88,46,134,71,53,74,172,186,69,137,11,154,60,68,120,125,100,91,182,239,177,38,28,125,208,165,38,150,207,244,41,88,127,241,251,168,84,195,111,37,211,165,113,3,212,184,180,207,48,52,204,171,213,128,154,138,218,69,214,154,99,201,203,109,93,71,190,5,99,1,72,173,15,149,49,253,51,82,171,179,114,131,68,114,133,15,104,227,141,109,39,68,225,130,50,51,133,154,148,48,28,230,9,43,157,50,133,203,239,37,160,233,120,54,20,116,57,174,116,158,45,8,196,14,200,80,203,212,233,1,0,88,172,214,196,22,192,224,142,138,146,230,105,100,153,155,112,241,124,26,71,253,143,4,191,50,49,88,226,25,142,141,13,12,50,159,122,211,42,168,23,217,253,218,151,135,3,152,114,102,191,76,186,42,124,70,19,56,25,85,234,58,57,225,230,253,56,194,107,134,142,201,213,43,14,33,242,16,141,205,196,99,143,100,115,5,99,128,100,221,174,110,191,83,165,164,78,60,124,209,199,63,185,120,175,43,3,24,40,153,1,83,147,223,112,72,242,148,166,115,36,138,42,13,63,1,45,173,225,83,121,19,23,208,171,146,240,108,150,3,213,83,210,238,72,120,80,197,2,4,159,197,138,216,19,178,24,173,212,237,169,129,129,102,51,63,203,142,11,134,180,207,105,98,133,253,20,224,6,126,194,167,33,132,90,101,179,113,216,222,132,30,88,23,229,210,85,6,154,226,252,17,39,174,208,255,8,11,252,159,110,195,86,250,59,161,218,31,140,167,41,33,201,143,250,68,82,205,44,4,77,43,214,212,60,82,214,41,44,125,236,152,34,64,133,184,58,145,227,65,70,73,166,49,21,158,242,114,42,75,209,36,72,188,192,146,223,138,76,27,235,115,153,105,169,96,209,231,4,33,105,226,175,187,91,218,12,73,168,214,254,98,208,113,214,116,177,49,34,94,22,127,175,12,155,193,56,187,115,187,240,136,234,206,189,250,115,219,154,17,52,62,198,63,225,81,77,90,127,246,219,192,106,223,78,102,88,142,46,208,156,230,196,67,182,18,112,210,126,198,59,15,234,166,243,77,61,149,24,223,70,245,142,178,199,101,195,190,109,78,244,224,12,84,52,158,184,88,212,155,159,128,187,54,48,209,190,202,157,70,122,109,33,221,124,227,1,196,124,121,163,138,238,25,129,134,83,111,124,60,142,46,143,48,85,63,5,77,46,251,193,209,81,108,149,108,1,47,137,175,85,106,148,27,204,145,104,3,152,84,228,215,113,141,6,117,115,151,206,248,61,43,182,198,76,88,12,222,132,75,73,8,205,190,32,12,159,70,205,4,158,0,107,220,104,90,223,181,80,7,111,166,130,16,168,145,218,242,101,35,165,172,12,217,239,157,76,37,238,176,63,124,243,45,101,181,191,200,64,186,170,42,104,154,191,224,67,145,240,72,82,103,93,108,220,251,36,178,110,145,98,136,83,2,171,177,220,23,98,221,2,160,216,219,237,90,105,255,48,157,136,55,102,122,181,7,225,55,229,254,215,169,94,22,44,65,136,50,190,151,198,54,132,81,245,106,71,91,141,176,162,15,210,33,14,140,108,81,17,135,249,17,44,15,121,28,16,114,178,210,7,129,250,11,239,18,86,203,161,124,2,185,178,83,110,168,3,81,125,80,149,8,67,30,212,0,129,8,77,255,114,243,68,8,119,210,232,104,244,127,165,159,26,176,206,160,228,34,116,10,3,91,65,149,163,43,43,44,171,113,113,223,206,17,63,64,215,216,94,118,5,139,66,201,213,30,120,149,18,236,99,41,81,175,245,1,7,171,209,151,134,28,32,122,201,13,18,46,236,215,113,188,192,221,39,69,117,121,255,119,26,59,142,121,126,238,179,163,183,245,98,199,32,46,39,137,236,232,52,138,4,60,86,83,12,100,44,195,49,107,228,105,56,183,18,177,222,50,189,188,97,197,148,94,99,1,198,221,121,206,54,31,212,145,62,73,77,213,189,38,66,13,139,69,173,57,26,11,176,245,141,166,141,203,10,48,45,201,17,131,241,115,13,165,235,28,129,88,72,36,124,169,128,6,145,10,109,219,198,187,90,149,67,215,68,116,33,56,204,217,236,231,0,205,84,97,113,175,30,185,95,187,166,164,123,103,0,218,18,150,180,103,151,153,146,97,15,161,171,246,252,131,198,186,58,55,210,93,58,157,3,142,220,98,50,202,151,2,115,205,200,3,236,146,210,233,71,222,129,198,18,131,29,157,152,63,201,45,197,253,170,121,124,232,64,197,112,22,208,106,99,54,41,247,146,135,234,142,177,3,38,157,234,222,46,189,233,76,41,150,255,135,82,99,244,246,187,81,215,16,76,188,188,104,156,21,239,255,206,97,35,217,194,13,70,106,106,238,171,232,93,223,145,190,50,39,144,48,13,113,146,151,178,156,18,131,231,168,108,178,224,7,44,122,98,87,166,65,220,174,138,98,95,93,188,127,246,195,136,215,160,201,137,35,217,167,126,219,175,109,180,111,127,222,93,69,133,2,58,198,186,238,108,57,157,101,174,249,26,46,210,254,251,76,43,197,209,161,52,197,28,246,173,229,35,43,13,81,122,34,245,212,223,50,135,69,70,192,171,78,9,135,189,54,168,232,131,250,208,59,227,252,247,231,40,235,203,254,51,25,198,223,165,81,140,141,67,194,180,31,194,172,47,195,56,153,118,221,30,217,17,85,154,184,122,15,130,179,86,8,37,33,200,95,144,73,175,68,185,197,128,182,154,171,147,182,86,172,23,236,20,92,194,110,253,124,133,82,127,206,92,34,108,69,170,47,61,41,87,108,218,3,244,7,124,51,153,83,186,164,116,154,85,123,43,135,177,107,28,189,81,241,214,189,235,233,142,6,109,183,130,75,79,107,99,67,31,164,248,227,114,159,230,115,116,115,252,33,75,4,171,191,217,88,245,156,203,48,239,140,253,211,46,184,136,34,21,248,161,128,156,16,88,64,71,34,174,125,70,164,125,92,205,214,79,157,199,223,143,214,138,213,150,169,17,16,181,95,200,208,91,91,55,125,7,1,39,91,6,103,252,246,22,71,110,149,236,73,1,247,51,2,168,88,124,234,86,100,6,94,1,17,215,157,34,238,126,194,222,109,67,175,96,45,252,99,58,3,34,192,251,95,240,36,188,243,191,229,74,164,55,171,108,239,73,208,140,114,46,244,36,30,33,56,14,209,94,86,28,9,153,30,23,102,165,252,98,77,72,233,22,126,152,98,40,246,35,93,137,114,191,114,200,54,214,8,238,145,43,119,180,186,55,74,170,232,166,247,56,233,9,162,16,241,95,47,5,109,72,125,67,35,130,55,138,75,157,246,85,244,3,230,60,226,159,12,234,155,160,180,119,243,253,179,202,194,53,218,65,208,230,212,71,228,29,49,220,31,146,244,249,84,46,237,203,93,171,73,33,115,46,109,10,163,137,73,18,133,213,236,174,230,216,119,127,80,199,18,100,180,236,191,127,152,158,226,45,72,70,181,106,90,21,229,46,41,109,55,237,81,0,158,169,63,40,22,85,246,181,235,161,180,28,175,136,87,132,184,54,121,185,69,89,58,20,54,81,101,87,37,251,152,4,162,108,113,248,178,219,151,240,144,158,242,185,138,4,34,148,255,250,66,75,144,141,25,248,244,89,180,203,97,141,149,179,129,213,186,64,101,242,119,130,121,108,230,198,74,228,155,96,237,140,201,158,44,127,161,120,219,94,11,95,27,145,80,184,107,215,88,252,32,89,59,97,159,249,183,75,131,180,65,184,179,85,80,88,74,128,53,126,191,54,169,0,133,100,248,196,158,91,121,110,12,248,130,87,248,186,85,136,101,181,0,90,45,34,227,84,17,40,96,221,187,167,131,112,48,70,62,240,138,78,245,248,226,203,255,32,242,246,141,200,17,167,32,151,12,72,159,221,190,56,115,237,233,226,113,71,228,167,60,113,127,28,174,27,176,227,160,77,221,157,64,14,166,82,60,78,7,91,16,214,169,78,222,97,33,229,210,4,255,104,234,42,181,7,177,190,23,40,135,53,67,63,28,151,60,167,81,21,190,110,214,160,222,51,228,87,83,113,220,46,182,163,193,79,214,249,120,197,244,197,169,252,20,33,253,246,46,198,16,208,35,110,5,37,236,172,149,234,155,32,36,8,249,70,224,226,40,16,146,131,224,173,250,111,102,227,160,196,255,167,81,196,62,24,6,39,4,245,139,98,158,201,247,5,6,2,61,92,5,65,70,24,206,135,30,246,146,155,22,29,247,25,112,186,5,208,134,240,95,137,29,48,148,222,92,36,165,248,10,244,222,158,131,46,156,217,243,219,101,123,98,209,124,89,178,16,48,173,142,241,134,127,160,217,64,134,35,244,28,253,59,26,10,212,162,143,252,94,0,198,0,16,156,116,145,64,255,206,234,251,104,250,213,247,171,89,86,125,48,237,216,196,160,45,90,227,12,33,58,31,88,200,117,101,36,105,135,49,134,64,181,233,40,63,100,189,192,13,48,58,159,183,105,34,162,170,166,132,83,141,116,29,39,216,84,29,224,211,54,145,251,248,148,150,203,26,51,179,47,134,175,80,66,223,24,221,52,170,59,241,37,95,232,183,15,162,203,144,221,60,248,8,211,255,78,249,55,59,23,131,11,165,152,182,82,168,71,89,48,249,78,107,182,117,73,21,79,42,128,232,89,103,207,13,224,32,236,175,138,201,54,26,98,122,91,253,144,222,108,171,101,120,208,168,40,29,46,64,23,171,248,115,40,80,28,107,143,65,188,142,205,155,234,86,121,157,124,23,44,177,188,201,222,229,244,169,241,155,62,102,187,15,28,49,168,157,29,135,202,9,160,102,125,112,184,31,209,162,114,13,130,215,93,15,255,110,50,54,19,144,98,47,46,170,252,210,5,161,176,69,185,97,187,253,94,124,215,85,69,73,136,150,68,137,217,52,113,151,241,70,44,102,126,10,143,167,133,81,239,233,109,73,171,141,93,133,112,185,133,103,206,49,208,130,79,127,234,48,173,231,82,200,74,68,194,188,185,26,56,199,134,122,3,153,227,174,245,23,34,49,20,68,184,202,1,232,252,31,171,45,85,7,114,187,66,203,169,98,117,144,15,165,104,143,111,174,100,197,60,7,53,248,238,100,12,162,96,40,189,247,101,64,57,57,14,195,114,229,155,228,32,111,37,141,8,8,163,2,223,6,96,54,144,175,85,141,51,77,41,60,192,113,15,103,101,44,30,102,189,100,251,227,71,37,62,123,4,63,119,25,116,47,205,191,156,1,106,136,248,37,151,162,72,226,41,208,133,69,146,114,137,43,245,90,115,117,90,122,134,180,218,136,10,36,210,53,138,90,139,213,130,56,173,119,174,71,72,213,138,87,171,101,156,110,0,164,38,191,156,215,148,220,106,138,50,237,54,37,49,215,127,45,81,226,61,181,195,147,154,208,170,94,34,8,228,121,71,182,239,63,56,65,244,0,70,162,73,198,63,16,134,216,58,187,203,234,115,44,209,105,127,183,130,74,82,203,219,128,128,162,13,47,106,252,31,56,155,184,119,56,139,70,241,3,104,153,43,183,28,68,241,224,25,154,52,51,131,108,142,150,13,106,43,251,166,76,47,218,150,11,125,109,109,179,145,213,217,241,16,32,208,48,33,217,59,171,245,248,174,34,191,77,111,183,221,49,141,59,221,76,224,103,190,107,171,215,232,44,84,133,236,88,227,175,24,57,144,252,229,182,140,36,219,42,92,101,187,212,188,34,205,167,99,168,91,224,154,187,112,52,190,62,212,191,250,250,68,229,248,142,143,161,185,243,117,222,69,61,162,247,179,140,133,135,164,217,144,222,8,114,20,240,161,44,27,187,82,122,237,53,167,43,2,215,122,219,61,163,54,181,154,176,222,239,12,13,63,88,213,167,98,162,94,254,89,113,112,242,88,158,65,229,215,16,126,234,96,129,34,233,231,85,152,90,16,97,32,90,134,18,131,114,130,148,249,76,135,186,171,103,192,83,45,100,96,36,88,217,197,165,86,194,168,112,149,125,108,133,112,117,199,26,221,35,245,88,233,9,113,47,138,31,61,114,47,51,32,197,55,17,175,164,93,204,223,215,203,221,224,147,103,78,214,230,214,71,214,220,169,117,39,0,147,198,108,242,153,155,144,235,250,162,35,53,61,45,156,227,244,108,123,32,227,129,77,252,146,213,168,197,237,147,123,38,228,75,144,165,144,102,113,198,22,145,14,101,195,177,43,62,151,113,96,81,189,204,180,207,197,24,72,76,135,127,181,246,81,18,167,113,85,184,62,190,140,86,209,148,134,111,32,60,108,33,233,115,99,216,239,112,146,92,217,236,252,213,215,98,122,215,64,175,155,179,121,195,7,207,252,163,51,58,143,187,255,188,122,6,199,73,36,149,218,141,142,43,108,99,2,232,187,65,216,24,169,125,102,148,113,59,233,176,194,207,77,204,245,20,43,145,104,88,88,212,187,237,152,64,18,141,254,53,255,111,53,61,62,49,143,145,197,10,207,36,198,166,88,7,199,42,201,145,219,135,53,239,108,162,82,202,181,4,255,82,23,38,141,213,120,0,218,105,2,141,120,255,138,20,27,255,97,202,151,0,166,227,16,196,48,139,91,164,4,170,177,243,27,154,220,212,167,205,179,84,245,205,50,51,155,45,39,99,124,70,27,48,182,173,3,26,38,214,1,26,23,216,248,214,89,78,142,7,44,2,118,103,73,72,202,187,222,242,74,37,84,166,251,191,67,11,231,116,61,33,17,96,93,116,165,173,88,153,105,123,125,159,243,89,143,66,211,213,23,47,204,192,2,231,229,224,32,30,45,9,31,149,216,137,119,152,34,22,131,206,47,216,201,89,197,58,66,204,67,92,0,150,199,161,213,185,96,252,164,78,46,247,41,134,48,118,14,77,30,250,176,12,138,96,58,51,142,9,249,103,99,29,247,189,31,126,29,86,211,201,108,216,195,90,32,119,124,219,207,128,192,119,91,217,60,215,24,182,244,100,241,153,24,3,99,115,167,33,25,239,186,42,198,202,179,57,117,112,11,208,212,50,26,170,22,148,206,252,232,159,56,64,37,184,40,232,109,62,164,199,64,198,112,56,71,12,215,108,220,20,211,118,70,182,19,212,219,182,104,5,188,255,61,162,241,25,176,78,25,176,239,21,205,246,214,246,86,45,101,158,9,252,149,38,59,72,225,119,121,209,20,85,6,84,253,24,182,126,20,150,105,176,238,54,59,96,46,28,214,21,80,112,19,118,125,115,134,244,30,35,230,238,255,199,220,32,200,9,142,2,182,14,101,191,176,143,96,217,200,124,194,43,105,61,93,143,135,53,12,228,233,30,150,173,228,73,179,184,84,21,117,63,245,231,49,129,29,249,46,23,172,195,94,36,76,227,246,71,159,188,8,88,119,49,177,156,203,88,101,195,170,151,183,106,100,9,246,64,254,1,90,4,9,163,154,231,88,68,182,99,67,75,171,107,142,196,79,237,114,70,178,128,33,83,168,67,129,82,214,135,38,206,41,152,140,168,52,239,28,171,28,29,180,246,185,183,243,85,129,112,168,63,139,133,0,162,86,166,48,132,244,159,151,235,175,64,110,168,85,97,233,11,62,25,177,16,57,124,63,250,59,218,136,209,136,192,23,168,160,206,65,84,30,73,213,235,181,104,66,27,98,126,183,219,93,200,115,84,141,57,55,20,131,91,14,228,85,181,19,4,110,176,90,101,40,91,107,155,7,70,21,114,154,141,146,125,246,64,1,216,213,232,23,143,224,115,244,247,144,186,71,134,69,183,141,25,186,91,29,145,163,250,202,181,57,216,172,131,228,242,181,187,52,94,218,252,4,118,44,52,124,160,37,176,17,218,121,140,191,107,102,91,222,49,91,229,106,179,221,170,200,88,38,138,167,10,48,157,47,99,57,137,88,76,206,141,214,208,48,80,226,18,227,6,175,180,63,107,247,251,197,59,51,247,13,109,209,162,206,192,125,112,94,235,247,26,88,14,126,241,225,249,81,162,7,157,238,150,138,24,69,121,155,219,17,169,180,218,93,230,99,92,139,53,179,145,30,14,205,171,75,247,49,194,3,14,177,24,222,122,30,75,174,121,243,104,233,244,81,4,47,70,43,206,113,229,119,231,49,72,144,78,214,29,193,41,75,14,97,19,84,148,246,3,250,243,7,246,233,153,48,135,226,204,199,93,210,3,97,11,106,117,170,122,92,97,150,179,177,220,46,59,17,151,242,160,233,237,81,78,255,87,243,237,113,135,216,131,97,197,224,41,142,85,234,243,135,58,152,220,191,227,149,78,77,30,82,167,63,217,43,227,106,173,223,128,161,49,70,29,184,169,178,179,124,224,2,243,210,229,112,103,15,29,78,229,91,9,68,198,94,135,241,207,69,183,229,46,78,63,189,93,163,10,91,172,13,205,180,217,216,102,237,239,3,217,247,218,0,147,130,158,175,242,39,94,23,238,221,229,211,72,140,103,207,7,73,10,200,247,155,254,35,165,152,2,137,237,154,128,235,215,210,1,132,104,143,128,91,191,225,241,171,220,16,165,209,59,10,1,128,151,229,116,17,20,188,108,57,196,105,197,5,64,216,75,255,49,10,35,243,39,238,142,201,1,32,8,28,116,21,216,226,89,90,231,210,128,81,149,93,249,111,150,128,11,228,231,236,178,74,34,174,187,230,84,78,197,136,17,197,25,242,154,123,24,78,245,178,254,76,70,182,72,15,115,54,62,10,89,172,129,113,97,148,204,240,100,172,169,122,13,95,182,26,184,25,191,255,250,250,137,18,19,72,145,135,112,125,227,63,65,26,54,228,181,30,158,27,191,9,236,168,115,248,144,187,132,253,45,84,154,196,103,30,149,123,53,42,206,172,146,175,44,203,69,239,45,147,0,121,103,125,132,136,192,38,62,79,29,241,17,151,110,28,38,221,234,230,228,182,64,241,144,165,124,145,120,49,50,129,18,33,242,212,143,68,167,109,134,179,113,176,85,93,87,105,133,15,66,249,8,43,9,147,72,30,6,2,85,185,204,160,20,76,70,119,163,67,200,121,228,185,204,22,48,31,122,177,123,93,159,108,114,65,90,91,67,95,139,6,187,3,78,142,38,96,61,68,23,146,93,32,245,153,131,61,126,1,194,201,158,51,161,172,0,176,76,143,229,81,201,36,157,210,139,109,215,12,9,41,152,243,188,240,144,194,27,114,193,162,39,43,9,203,46,137,76,217,93,125,215,74,43,75,0,153,246,95,88,44,134,248,43,87,166,46,133,1,77,197,205,206,31,50,102,178,248,22,226,192,156,203,195,155,193,32,35,158,173,76,75,79,240,112,7,161,130,162,85,225,67,223,15,127,53,24,49,231,201,248,16,114,146,228,17,178,247,166,162,2,32,180,41,188,9,197,103,77,246,35,30,71,112,6,222,168,64,60,248,242,61,201,130,219,58,182,38,143,103,45,104,219,7,121,119,138,183,148,149,107,216,169,2,89,111,185,120,49,74,173,174,35,38,194,214,86,32,216,229,123,41,64,108,178,152,13,174,71,86,192,147,84,112,246,98,151,238,63,210,134,112,5,28,254,154,125,236,82,78,22,114,230,212,88,97,54,211,70,203,48,159,59,21,36,55,56,141,194,247,133,160,138,224,66,180,74,137,37,94,5,120,135,170,119,209,147,221,28,19,215,139,29,199,87,234,102,225,111,74,180,27,169,131,129,29,44,138,81,235,206,181,229,133,192,201,163,110,48,203,245,95,200,183,29,29,31,255,74,216,148,92,109,191,130,29,236,248,204,126,228,208,76,200,13,128,197,198,255,211,23,197,132,124,133,71,155,21,132,233,191,189,212,255,108,47,94,109,53,232,234,95,174,83,223,18,188,255,239,215,139,141,51,127,243,199,103,111,117,45,101,67,184,104,196,20,34,25,184,251,144,47,226,217,214,217,125,47,52,41,242,113,104,13,56,74,44,166,36,63,154,133,145,18,80,160,124,59,47,48,219,63,43,134,67,115,238,189,252,67,6,164,83,181,123,230,213,252,7,222,130,221,30,79,68,34,162,2,61,134,162,207,49,146,161,216,82,98,181,190,57,57,164,128,97,121,148,131,128,152,66,106,247,15,154,148,82,42,174,142,17,249,123,23,138,78,106,245,159,202,19,26,160,50,138,153,136,182,101,89,247,195,169,69,220,50,155,45,140,251,248,183,139,84,17,44,98,83,13,102,234,106,135,22,255,212,246,163,28,11,251,123,18,5,150,221,6,2,137,17,176,56,215,12,166,187,52,149,11,97,119,140,245,13,201,20,98,80,27,26,125,126,58,232,231,83,52,195,75,116,248,147,230,123,171,77,81,168,163,120,39,158,18,54,60,212,117,67,148,122,151,78,51,30,88,27,152,83,92,191,105,162,106,233,12,27,116,4,53,100,189,242,253,169,182,10,105,196,84,229,122,141,80,15,0,38,26,50,176,229,18,32,169,241,202,190,190,225,100,193,44,196,209,193,83,89,43,228,8,127,48,9,221,186,199,251,97,138,218,190,131,202,206,62,148,128,44,48,107,164,177,57,149,171,214,244,57,198,194,87,179,232,10,17,65,243,255,109,19,208,42,55,68,178,164,84,21,57,206,5,27,252,203,144,108,90,231,137,198,221,204,164,204,56,73,223,129,127,246,244,144,140,13,229,195,199,39,42,93,103,202,8,45,68,203,17,186,154,9,154,228,59,255,134,120,125,170,90,18,141,31,17,116,10,189,48,63,147,112,188,11,184,92,95,253,180,92,80,106,57,112,187,229,228,69,3,1,47,47,72,146,48,135,37,111,82,27,20,77,157,222,115,123,120,119,159,196,99,7,116,57,222,119,79,79,212,213,215,145,225,154,187,25,22,126,89,170,169,123,159,94,29,177,63,137,207,167,192,97,134,193,17,236,199,8,35,214,220,156,72,183,180,8,63,200,171,93,216,103,110,145,159,209,158,236,233,50,228,220,144,113,159,214,222,157,156,27,133,183,240,127,191,28,41,222,148,155,247,32,97,96,128,237,98,236,159,107,157,192,176,19,81,248,145,219,183,179,73,178,81,38,137,81,108,189,148,180,164,63,244,107,140,13,253,2,84,88,16,121,200,120,77,203,104,24,207,202,194,62,253,155,102,96,168,116,28,237,163,138,91,149,34,82,230,211,109,230,176,130,28,82,186,233,159,99,238,249,81,38,106,243,246,4,63,80,43,104,47,1,253,236,84,79,158,5,81,26,18,242,70,42,11,229,216,154,236,16,203,159,227,7,207,120,26,197,81,87,177,4,32,197,147,111,255,229,91,211,194,195,230,35,169,151,31,196,33,181,120,192,254,71,84,152,228,208,209,129,98,55,39,210,144,146,192,231,249,121,170,81,218,202,197,150,149,234,93,90,178,167,209,244,86,25,140,141,156,206,14,247,240,217,14,39,99,82,121,16,119,157,210,169,220,50,58,255,48,130,189,120,154,59,60,85,94,135,23,15,171,6,31,212,224,89,73,100,179,91,61,170,128,28,33,227,9,149,128,12,110,120,44,9,52,192,4,24,65,221,114,24,77,109,0,237,94,4,42,232,84,150,134,32,50,33,84,234,130,136,89,117,253,79,60,135,69,29,50,128,196,38,41,43,37,78,168,73,163,249,45,207,177,76,38,115,76,143,118,145,106,166,6,142,230,193,147,145,87,195,222,73,219,219,89,33,68,237,118,120,146,164,74,130,237,16,47,79,228,9,153,184,5,127,80,182,81,105,196,51,244,192,237,160,118,200,191,94,235,152,191,202,161,231,171,19,116,102,94,206,253,175,4,193,18,70,53,214,98,123,181,137,167,190,84,96,169,2,204,232,54,221,169,175,186,172,137,170,75,32,249,57,119,86,19,52,123,234,142,11,108,19,58,84,98,250,242,114,170,31,205,195,117,12,243,41,93,222,0,101,219,102,129,196,192,91,8,186,233,243,37,194,183,162,121,59,93,71,52,178,114,96,72,252,185,254,109,31,107,112,168,64,226,160,216,43,49,74,50,139,112,148,135,148,88,184,35,26,29,171,245,47,96,61,39,146,159,194,252,57,202,244,245,218,216,18,29,71,237,39,25,197,164,184,67,97,53,45,16,218,207,244,97,249,96,167,93,62,103,162,164,67,186,159,2,26,136,32,184,9,167,169,183,210,72,43,253,167,72,211,171,205,117,92,82,32,5,197,107,8,68,106,237,8,142,148,101,227,90,210,67,13,252,233,3,242,79,95,172,175,195,246,251,254,247,71,7,224,252,37,255,4,158,178,131,23,77,77,22,178,114,155,151,162,207,53,98,63,132,143,232,73,194,185,91,243,57,47,83,36,154,42,31,150,56,15,33,40,14,111,70,137,225,158,138,108,119,114,255,48,176,231,182,51,219,163,86,122,80,104,197,169,107,181,97,55,228,63,47,73,106,27,23,65,207,177,34,218,221,147,192,237,165,74,89,152,255,181,169,250,226,99,10,232,6,181,45,3,222,174,26,248,155,12,199,237,65,205,85,22,125,164,146,124,17,73,140,71,36,57,173,173,157,157,161,35,164,157,190,71,67,29,142,133,206,231,64,185,95,111,65,166,220,233,245,73,242,25,16,29,223,124,142,199,177,13,24,198,245,218,190,115,38,32,45,236,12,96,101,63,17,230,151,217,117,234,153,112,111,91,162,196,247,185,166,60,2,8,145,56,160,48,175,226,250,67,51,132,106,42,213,138,119,167,9,240,25,8,56,22,165,218,9,62,218,121,29,43,177,130,210,166,150,15,220,225,225,152,34,255,104,115,223,108,131,55,250,255,49,92,130,20,179,218,73,38,116,122,102,17,118,237,183,109,65,232,122,235,4,68,3,245,160,150,224,73,183,115,6,100,124,166,210,201,82,249,142,15,23,20,60,118,137,170,181,229,205,108,201,240,169,87,195,99,76,138,15,228,158,47,216,146,8,248,175,110,207,39,94,180,173,250,47,24,2,201,150,241,233,238,16,120,75,140,84,49,212,106,98,213,162,86,181,76,170,35,124,116,48,164,197,74,131,117,229,28,19,139,154,0,123,202,110,178,10,79,113,166,22,172,117,191,54,48,27,183,59,223,105,57,148,54,241,188,72,118,58,255,33,235,238,206,33,254,197,162,45,154,226,221,57,145,225,19,36,11,164,245,79,188,132,50,190,248,255,75,183,214,242,69,109,232,147,130,166,70,86,58,124,161,96,88,92,166,32,184,117,117,232,148,14,163,81,163,242,0,239,41,82,240,105,189,74,68,200,164,195,85,62,74,56,226,196,41,2,105,154,95,205,207,232,106,98,226,99,112,210,188,162,203,188,28,65,78,18,252,134,93,120,74,188,64,154,12,133,146,228,14,25,9,13,157,22,83,145,169,201,189,221,137,49,232,138,179,182,165,146,2,109,172,21,172,40,157,230,199,70,170,17,231,133,250,192,45,75,214,33,111,3,120,209,54,12,206,159,226,150,136,96,94,25,66,56,178,106,7,73,214,104,156,236,28,249,93,15,229,9,0,132,16,69,155,125,179,207,94,14,13,244,207,241,54,32,52,63,98,162,154,191,75,209,229,33,193,255,57,31,229,86,153,43,207,166,165,245,54,40,212,29,222,70,136,130,40,74,185,218,104,130,108,129,245,188,86,215,76,131,33,190,168,234,99,175,11,251,216,73,187,108,44,255,201,238,119,247,44,86,81,235,45,3,57,216,75,34,73,180,36,35,240,164,214,36,117,135,41,119,211,38,76,81,196,8,21,97,136,235,119,71,123,36,176,199,227,228,108,128,149,137,5,164,77,148,159,81,47,176,108,234,54,46,235,56,167,178,84,254,105,129,190,49,65,57,236,213,149,152,10,85,206,195,221,92,221,54,74,114,134,198,83,208,132,62,75,99,76,23,147,221,170,238,47,2,231,238,159,31,157,21,230,120,116,37,205,171,183,193,105,172,143,117,1,93,76,23,54,218,89,41,8,34,70,14,172,247,13,165,93,149,104,106,13,209,88,202,31,127,1,56,213,196,57,128,219,160,128,36,102,11,50,241,144,120,109,249,181,6,101,158,193,159,198,121,72,53,117,201,226,238,36,19,89,190,170,97,242,166,133,255,187,116,117,149,110,240,34,46,115,10,173,23,253,193,26,88,218,204,250,37,212,109,250,201,191,194,118,95,136,247,161,207,241,204,135,2,78,149,74,112,131,147,47,174,61,6,17,165,170,245,205,230,27,4,219,42,253,132,224,5,105,216,149,164,189,139,111,218,70,124,62,36,131,167,58,160,166,166,15,182,6,55,43,51,18,46,56,174,90,10,0,14,29,74,85,33,208,147,69,176,90,198,106,36,37,30,25,35,124,178,130,4,84,25,198,20,229,53,83,27,191,7,155,221,115,87,5,220,83,80,84,102,251,48,221,102,199,149,98,72,199,4,97,43,61,78,97,140,141,115,8,36,76,209,170,73,151,35,27,50,135,70,240,173,0,121,54,23,163,78,109,212,129,93,171,216,134,28,83,113,141,233,192,101,187,144,201,55,84,241,226,162,50,111,152,243,114,9,111,93,4,89,234,55,65,28,241,78,143,188,189,252,70,80,238,69,204,212,181,122,171,109,189,186,144,136,240,116,95,234,155,53,70,170,203,113,36,46,45,134,195,163,140,104,104,25,181,136,167,116,55,237,25,77,120,91,44,239,159,52,190,41,227,220,175,171,101,213,127,105,222,163,58,68,40,210,118,247,1,76,42,20,189,248,76,43,113,25,81,37,26,154,234,25,226,251,39,69,143,3,138,235,220,47,9,31,25,63,195,193,72,173,92,80,43,152,143,80,74,126,49,33,238,113,228,171,168,241,82,49,174,116,73,94,130,72,230,253,161,187,183,237,195,41,153,143,130,252,152,169,147,185,106,2,207,13,134,90,175,141,157,242,255,161,154,42,107,178,145,195,16,211,119,181,175,211,84,142,39,77,187,239,159,12,177,186,243,150,95,140,58,167,52,103,146,158,98,247,173,141,219,214,180,87,55,184,155,216,203,67,81,243,45,171,219,220,110,144,106,5,138,225,212,232,110,202,220,68,84,250,115,120,118,200,167,154,108,73,90,190,72,34,47,249,229,114,4,80,142,144,22,68,254,128,128,196,171,194,100,131,176,168,30,203,107,42,65,59,156,176,21,156,53,86,125,203,58,216,87,127,233,238,153,162,195,175,35,133,212,69,25,61,96,246,99,19,132,120,219,58,140,93,223,248,9,43,246,147,166,10,33,40,237,26,6,87,228,81,182,159,34,234,48,74,27,30,186,36,136,63,92,110,3,131,130,27,239,155,0,156,219,146,232,148,189,133,204,227,35,102,6,13,242,251,69,127,251,171,127,248,242,116,126,174,84,115,6,193,135,29,128,225,230,162,23,222,79,106,4,26,156,61,251,88,57,81,76,237,7,19,107,37,95,147,230,99,193,76,98,87,252,124,217,105,200,201,204,245,189,226,154,95,54,19,34,64,85,66,163,243,6,203,46,201,0,174,183,154,181,226,46,152,199,255,75,54,243,29,83,133,231,240,6,21,38,68,184,253,109,54,23,224,31,102,11,112,103,43,17,38,125,238,71,104,161,159,219,136,215,196,141,170,10,56,156,93,207,152,188,114,22,157,0,165,25,138,205,58,248,67,193,58,28,147,32,38,229,221,175,114,14,42,161,2,223,231,204,164,6,92,49,52,64,37,164,223,252,197,118,55,243,108,10,158,239,219,175,244,102,22,194,134,212,9,249,244,43,86,97,41,53,9,224,110,61,250,140,202,187,95,171,204,21,221,58,141,24,176,120,96,194,232,84,28,125,246,218,142,73,131,254,249,22,179,71,110,208,97,247,139,162,171,64,251,79,190,180,190,186,29,110,165,88,119,225,30,58,64,49,68,45,83,93,122,136,199,146,158,106,5,211,222,64,64,160,74,72,185,138,112,186,135,133,95,31,236,77,86,54,59,235,32,245,245,133,152,27,233,115,154,253,233,222,36,218,216,218,211,137,127,103,199,95,165,151,234,33,228,72,167,103,13,43,119,38,71,23,218,227,177,230,222,214,149,81,102,246,94,251,84,233,90,116,77,26,118,194,122,55,75,208,137,52,159,238,73,8,33,157,218,178,213,108,45,131,207,210,31,144,133,204,239,144,183,230,251,195,57,195,154,39,61,36,39,117,126,121,69,224,198,15,198,98,59,82,181,202,28,149,49,219,53,48,163,19,164,57,251,219,61,159,235,12,121,100,151,160,191,93,194,90,22,119,28,191,219,210,170,234,145,2,111,53,86,140,171,46,232,231,111,18,43,83,2,142,131,38,36,99,174,3,26,169,105,31,214,250,212,191,8,1,141,69,73,158,180,248,93,117,146,242,10,188,63,7,61,149,69,118,161,141,117,25,193,18,187,220,194,82,13,30,5,225,194,158,252,56,159,129,5,240,0,213,85,67,54,209,242,151,41,141,172,187,12,215,255,6,5,126,185,11,225,35,202,5,182,98,154,26,217,237,193,140,136,38,71,118,166,44,17,223,179,101,97,16,153,33,21,204,15,219,189,120,219,24,117,23,4,153,22,143,40,174,238,185,27,159,69,251,1,227,108,218,69,111,198,184,236,14,216,136,208,115,154,211,47,149,116,98,114,40,90,83,116,92,109,38,134,140,104,157,197,116,57,122,111,5,224,4,175,201,244,62,210,203,188,216,230,131,214,184,164,54,48,242,179,251,201,77,16,77,13,77,23,34,66,146,24,12,187,238,151,92,139,64,114,217,125,244,175,10,155,138,118,58,245,52,121,17,241,62,231,105,214,169,120,184,4,155,16,20,12,215,206,40,237,161,186,68,63,141,166,178,6,127,126,151,70,195,245,163,96,91,23,138,173,211,99,103,164,14,51,246,20,75,76,135,150,74,215,220,71,15,76,77,215,250,38,227,176,76,17,15,179,232,18,19,165,54,194,146,187,110,158,216,55,66,145,232,119,152,61,63,121,155,194,202,244,22,81,66,36,140,38,108,209,21,139,25,159,255,185,60,117,9,245,95,46,99,220,27,61,151,235,253,38,161,64,188,88,189,117,249,42,176,56,54,107,62,80,240,135,153,86,180,137,121,111,177,208,196,3,194,236,106,173,82,40,195,1,146,180,204,141,11,192,120,252,52,4,116,199,14,254,104,216,4,219,7,221,233,33,47,34,247,94,0,104,240,54,18,128,85,240,255,179,195,197,161,240,178,242,197,103,68,166,60,95,131,245,148,198,163,124,209,39,120,42,206,15,106,91,118,113,89,19,66,66,241,200,64,65,37,82,169,139,136,203,234,192,172,175,27,160,244,10,91,4,183,109,177,183,93,233,92,26,227,67,87,232,184,97,234,202,240,80,213,42,133,15,68,206,0,206,110,170,227,223,113,90,208,60,11,93,245,151,50,51,86,152,199,229,35,248,13,119,64,238,165,152,108,70,48,149,157,110,249,189,25,187,246,251,124,64,0,176,165,128,174,39,200,94,100,193,34,233,19,192,83,39,177,228,74,234,195,128,251,203,238,192,16,66,200,223,179,30,106,195,189,26,217,157,142,161,132,38,20,179,217,79,34,97,189,231,106,19,144,223,172,39,206,91,192,115,254,111,141,170,103,121,61,72,101,60,110,173,73,193,25,89,206,122,137,151,213,60,169,7,42,226,224,249,190,43,17,190,187,240,163,77,26,192,162,70,170,154,216,20,183,212,229,81,56,157,247,123,219,168,91,21,53,107,174,135,98,32,176,146,78,98,190,30,232,190,171,107,188,254,223,5,25,58,134,150,36,28,218,134,107,40,253,245,199,11,1,191,26,173,238,5,142,204,170,161,157,127,172,254,27,185,235,87,15,3,74,170,36,195,132,163,3,126,33,178,173,141,106,23,111,96,111,124,164,68,230,2,210,18,190,148,45,70,148,194,38,160,67,130,166,172,81,5,91,142,239,190,58,3,102,81,212,68,68,73,134,6,117,116,100,47,57,100,207,232,224,125,32,30,193,162,117,36,57,8,27,203,56,199,110,251,56,35,162,240,157,224,0,42,206,199,201,33,95,5,127,132,29,178,152,101,166,1,242,99,155,248,47,71,180,75,84,99,65,91,32,31,136,206,52,48,74,184,208,83,85,179,51,105,125,87,66,145,207,127,71,239,255,157,126,120,139,232,35,64,70,128,118,191,41,217,7,185,86,117,216,187,163,194,206,174,218,56,214,58,160,248,111,154,70,17,108,212,91,199,245,32,108,125,43,198,192,38,68,101,100,147,129,87,52,240,50,91,92,218,108,127,101,155,228,123,77,147,41,86,207,159,139,140,93,22,169,163,63,89,236,154,98,131,93,39,55,237,122,107,6,174,184,202,126,27,199,141,16,52,167,250,44,52,64,134,244,66,235,39,127,190,88,127,61,105,107,157,35,59,146,10,14,155,241,227,170,104,180,47,95,20,235,236,196,100,29,66,255,252,236,249,128,214,5,234,40,241,34,234,45,47,166,217,121,36,243,35,251,23,126,3,133,136,164,113,22,69,236,180,239,139,48,255,146,161,48,135,129,150,245,193,181,210,85,120,4,249,147,174,66,17,136,154,208,148,214,82,198,29,171,4,223,212,84,104,93,95,153,151,59,52,212,150,113,85,179,189,60,151,118,28,93,220,49,114,124,228,164,99,165,40,1,5,200,121,138,132,77,15,5,21,162,216,252,37,141,224,202,125,209,225,242,62,177,195,93,254,238,77,226,148,168,119,167,195,151,180,25,60,215,48,166,94,44,45,114,159,78,24,155,132,119,38,31,231,227,51,37,35,33,239,40,171,12,250,68,190,248,231,228,59,213,61,15,65,53,179,92,176,23,172,176,32,72,135,37,241,24,107,242,184,186,57,99,239,241,14,0,114,211,202,79,176,88,52,130,56,18,75,55,22,208,79,100,1,57,105,53,174,100,13,234,232,158,118,211,9,144,128,160,76,177,166,10,90,95,110,144,254,243,190,208,135,184,198,226,200,27,9,38,241,0,208,210,237,180,2,22,149,157,19,155,249,21,3,55,195,149,105,206,24,110,148,19,249,58,78,186,176,25,100,216,4,198,194,104,71,150,103,193,54,223,28,146,80,51,157,194,14,178,180,189,161,192,44,225,168,111,47,225,151,43,100,26,191,125,146,222,221,199,216,186,126,173,89,90,229,77,60,34,228,75,219,182,85,232,170,22,24,130,197,101,20,253,116,141,176,241,34,223,208,190,53,49,201,93,144,151,241,108,236,120,86,232,128,234,238,83,111,80,172,96,67,34,128,6,29,10,136,122,7,204,83,50,186,1,23,79,169,21,92,114,15,132,236,51,188,123,139,240,236,199,67,208,132,52,13,194,187,174,29,120,140,151,198,252,88,147,102,219,35,162,73,126,98,77,213,8,169,217,193,210,100,239,19,153,49,43,252,194,75,228,65,143,184,39,77,42,202,171,40,113,137,164,157,33,120,131,63,197,218,5,250,238,192,175,128,92,206,161,173,254,238,133,100,158,136,16,101,127,238,52,208,92,82,3,217,66,93,246,228,193,254,74,72,78,122,33,105,54,8,66,93,246,194,222,27,194,33,125,31,125,186,243,13,92,218,44,36,132,226,180,89,124,205,104,135,159,122,252,15,162,223,62,10,250,171,0,131,127,85,178,231,79,207,40,253,46,196,118,242,128,72,35,191,117,82,21,59,50,253,123,77,220,143,104,20,203,224,176,13,252,32,28,67,43,91,75,244,94,186,135,19,180,199,223,127,142,98,37,239,28,103,87,65,235,18,238,103,120,238,30,86,59,98,172,2,220,161,99,43,3,209,122,161,55,146,255,1,36,249,99,184,3,3,168,72,232,46,73,223,106,79,159,210,38,156,147,51,126,50,165,108,52,49,96,42,238,80,99,70,146,206,224,54,97,97,16,213,14,248,251,126,49,66,87,134,179,227,232,143,91,185,125,0,158,183,5,242,48,7,152,160,171,198,163,34,181,199,170,68,125,93,97,109,136,230,150,33,113,56,104,7,226,175,49,100,51,84,213,22,135,7,237,200,148,72,116,142,163,153,122,86,4,164,15,210,118,24,67,210,223,220,137,144,48,144,180,185,234,2,241,154,213,43,109,156,143,172,26,128,135,231,119,24,217,131,61,148,77,141,150,92,115,120,2,154,217,75,86,241,208,171,108,103,82,89,209,129,238,172,132,255,207,27,146,164,74,184,68,92,141,13,124,214,138,185,244,149,236,189,182,103,67,87,10,32,216,220,143,80,210,206,245,104,149,139,20,55,5,113,172,207,125,29,89,249,19,112,108,14,88,182,201,165,18,10,245,121,6,178,148,34,12,59,196,61,173,239,178,241,33,155,25,242,134,32,227,233,188,135,113,163,52,64,251,178,224,118,246,79,167,5,63,212,177,112,180,80,242,169,49,210,21,134,141,17,157,190,91,64,227,91,38,133,159,225,105,247,226,195,200,172,31,220,215,170,68,107,20,234,183,178,143,56,158,107,86,223,172,215,193,84,10,65,89,99,158,61,203,224,96,108,213,54,164,149,13,125,118,120,95,189,114,57,41,211,241,237,209,190,6,62,79,184,242,245,149,195,91,85,198,131,178,227,71,202,112,154,51,82,29,130,223,121,113,6,199,251,129,30,201,68,187,181,197,35,52,79,104,12,235,40,127,72,62,197,101,25,50,235,135,22,61,18,204,9,17,58,139,193,112,118,161,34,157,65,113,190,135,176,140,117,20,216,176,111,50,116,217,162,214,180,80,45,31,21,53,93,2,228,123,100,207,17,230,207,97,240,183,85,31,41,46,45,3,43,72,155,187,165,203,128,67,28,120,236,54,20,65,238,109,110,179,222,136,198,17,77,149,130,251,103,177,204,150,184,189,37,5,55,241,217,14,130,255,116,126,175,235,144,116,140,66,14,51,205,67,99,220,51,208,79,206,154,127,22,85,71,77,215,145,255,44,243,64,209,227,67,73,110,151,218,87,197,55,237,118,245,39,169,244,170,245,203,108,245,142,50,189,176,80,21,202,93,146,1,53,148,177,158,56,213,31,235,149,163,76,7,160,96,185,175,209,247,27,135,158,217,147,16,10,240,197,137,20,206,239,82,56,27,22,220,198,2,89,79,127,31,142,1,6,55,182,200,142,137,107,201,174,111,181,210,207,62,30,104,243,208,79,121,233,86,23,51,192,246,38,237,63,185,68,166,75,123,229,116,251,234,207,59,122,231,68,113,211,62,70,25,143,151,209,232,208,160,147,131,216,54,242,90,239,63,40,144,174,63,16,36,202,26,114,183,89,217,89,136,230,91,48,252,125,202,164,150,89,145,56,123,247,12,54,155,187,186,61,40,196,208,28,136,119,101,36,210,226,52,175,235,200,109,39,72,109,208,243,138,191,212,112,241,255,140,84,135,41,149,18,74,71,117,169,225,47,36,251,47,104,143,61,234,88,50,148,255,119,218,157,33,205,193,198,233,229,11,62,162,92,119,220,137,255,123,184,226,35,157,8,174,39,63,216,248,137,225,131,8,2,82,204,80,214,39,91,209,189,161,6,81,144,36,198,76,197,109,194,10,4,72,54,53,184,115,91,225,10,11,168,200,46,218,124,246,135,15,89,53,166,8,241,71,83,123,154,209,50,174,37,55,123,83,140,20,54,44,56,182,163,26,6,6,190,38,53,147,232,222,149,68,107,255,157,252,151,137,92,252,145,148,33,103,9,72,231,13,116,195,38,2,23,236,159,143,19,6,218,213,124,179,244,182,30,110,173,19,168,90,131,57,252,205,106,250,34,115,21,156,227,2,178,233,51,164,166,165,72,112,14,41,93,38,111,111,37,191,106,207,33,185,185,90,72,233,134,236,98,171,160,112,169,40,190,94,93,171,234,98,137,93,127,65,248,80,186,131,116,191,197,63,31,50,255,195,58,34,142,54,220,246,198,63,55,183,44,126,0,217,209,232,158,8,7,110,86,107,240,61,28,52,138,97,149,20,247,180,192,143,33,83,155,177,22,187,216,48,139,83,169,139,99,123,154,74,125,236,38,59,46,27,30,157,211,15,232,203,47,94,136,56,194,51,139,205,174,21,161,217,7,160,227,59,236,156,91,143,154,27,42,117,22,168,18,246,201,35,37,107,157,58,5,158,76,100,112,62,84,117,50,22,6,96,111,120,207,116,151,161,13,67,239,116,206,98,64,136,103,8,201,197,9,81,239,18,226,93,190,46,81,229,232,167,200,193,215,90,182,212,93,78,67,26,105,97,197,49,164,150,52,143,248,121,13,95,217,227,206,14,80,200,179,171,10,146,200,142,90,137,125,253,146,71,131,33,45,48,69,241,119,153,254,188,241,25,222,97,30,63,46,136,159,57,134,89,0,129,234,189,184,64,200,208,245,48,167,116,134,99,230,3,164,217,19,159,106,99,97,202,22,164,70,66,13,97,32,58,239,114,37,9,60,59,67,157,37,172,251,50,177,13,116,63,7,119,74,90,248,108,175,187,95,134,112,101,157,132,160,143,70,245,232,144,69,184,106,150,9,184,122,224,32,162,162,167,166,203,10,237,99,78,75,217,159,250,237,184,75,97,163,68,55,215,93,14,236,225,12,141,49,8,40,126,117,77,135,80,77,205,97,75,21,26,145,221,123,172,2,182,77,86,93,204,86,114,144,92,13,141,25,97,222,15,100,182,160,159,142,35,220,49,107,187,208,137,105,153,135,0,174,222,172,239,170,133,207,178,208,164,230,211,2,139,92,32,192,133,89,232,32,239,245,110,166,136,37,21,196,131,79,242,98,209,25,180,252,102,119,100,85,102,115,189,106,122,226,157,178,221,143,154,92,187,57,68,241,18,33,225,250,134,114,116,72,134,250,27,40,97,219,30,86,74,184,102,193,26,66,181,24,165,153,255,190,75,185,18,121,114,85,220,59,224,145,174,176,36,67,144,74,196,161,88,9,48,79,220,4,67,25,232,105,176,32,242,28,201,66,116,178,36,164,218,208,31,240,68,239,166,138,242,198,226,27,136,232,255,174,210,152,60,200,61,15,238,2,218,231,198,130,236,180,235,65,221,66,82,162,92,235,251,20,38,65,92,156,106,85,0,144,25,182,28,226,88,153,34,253,19,27,116,90,101,248,35,202,216,184,19,35,2,94,8,209,254,66,212,135,68,219,185,32,107,225,25,227,136,211,138,181,174,112,128,190,66,165,251,135,185,108,40,159,222,177,26,58,26,148,218,89,13,15,27,236,24,118,78,33,185,174,168,219,230,119,230,179,169,161,57,118,97,227,203,9,125,55,136,197,112,94,138,136,230,112,204,245,136,116,59,13,75,68,121,43,122,9,22,252,149,172,182,118,113,61,53,171,44,42,118,178,166,69,222,44,157,34,128,126,179,24,154,159,106,149,17,227,58,143,176,241,222,56,42,62,181,26,208,33,24,30,33,112,83,127,84,65,41,251,206,115,178,2,222,106,153,209,238,98,208,200,210,177,133,86,65,23,104,110,177,161,96,79,57,142,162,15,207,173,153,56,254,250,73,76,74,43,36,200,57,145,60,95,227,21,147,221,41,171,192,107,234,251,74,126,3,247,128,122,243,153,128,202,238,189,17,198,179,70,97,245,190,200,231,176,186,98,217,254,45,230,228,185,78,204,155,64,247,183,255,152,161,26,12,21,183,209,199,194,177,1,221,95,77,76,253,203,104,7,192,167,209,180,50,138,227,189,182,231,239,238,168,59,221,119,154,107,247,102,200,51,40,120,192,133,47,249,238,189,123,233,117,188,210,82,68,72,178,111,103,77,144,205,181,97,1,172,166,152,242,0,187,181,174,188,39,82,5,75,21,213,113,66,102,62,173,169,132,21,120,138,226,211,39,44,143,160,126,74,108,191,13,117,58,148,234,239,194,161,161,156,231,240,170,77,120,106,63,168,175,231,243,60,192,181,236,20,52,239,78,141,78,130,59,219,80,208,24,37,165,109,209,49,251,9,62,80,50,249,181,232,42,228,47,166,191,144,176,206,148,242,148,153,182,121,24,128,65,137,42,161,119,66,94,240,11,55,102,122,7,205,142,144,144,180,47,60,218,192,149,85,15,213,83,8,79,215,104,8,209,172,222,200,242,28,255,51,185,167,33,226,26,65,147,100,114,222,54,27,170,212,207,83,56,170,37,126,121,14,18,40,231,4,14,164,248,6,110,118,48,51,83,228,76,3,131,87,77,86,163,48,72,194,109,53,105,118,111,198,140,133,34,20,119,56,35,236,7,170,176,164,95,86,183,232,105,108,7,25,169,127,50,26,86,83,94,101,58,219,72,205,46,231,78,158,94,221,190,147,92,96,224,0,30,65,191,21,237,118,106,224,247,161,116,33,41,10,92,81,248,232,191,41,72,116,171,89,110,208,62,230,196,11,67,172,81,188,8,212,62,255,199,22,201,68,20,120,21,90,72,70,211,251,61,232,5,238,147,16,91,225,65,103,178,238,63,246,157,100,192,170,206,249,101,28,25,120,125,225,94,105,146,218,75,10,178,103,244,73,77,174,18,113,205,198,233,5,88,129,66,64,72,137,118,81,217,130,206,156,174,224,223,115,249,164,10,160,47,237,255,135,146,236,13,99,71,63,62,20,134,132,135,155,27,21,239,159,60,195,224,248,123,205,45,147,225,233,72,95,151,236,249,144,43,148,51,197,175,100,140,185,170,200,234,37,87,113,85,41,197,41,164,33,181,64,228,58,125,41,220,43,111,47,37,139,69,75,126,166,210,12,7,175,6,63,122,236,237,156,149,142,254,174,11,37,215,82,200,54,62,74,43,2,249,172,218,115,203,91,14,165,110,103,178,200,5,226,141,45,42,68,130,198,173,253,230,217,122,113,39,163,182,160,231,100,179,40,207,8,27,212,22,174,85,58,27,55,118,83,118,244,201,68,167,205,50,31,36,17,250,228,187,200,203,159,109,44,83,197,240,214,82,128,207,62,237,127,108,238,226,36,190,44,152,27,248,90,79,254,43,191,182,206,138,179,239,133,27,56,192,25,166,40,83,172,241,62,178,172,53,58,205,73,6,139,66,50,24,22,193,232,205,173,161,67,139,236,13,114,239,156,46,253,12,218,238,6,255,169,98,117,8,215,156,102,178,212,208,18,175,147,108,96,73,71,115,87,75,254,77,61,212,49,252,42,72,23,95,49,206,208,189,203,240,139,4,56,101,109,139,204,117,23,213,104,47,1,254,115,179,25,96,58,221,157,53,112,19,110,172,118,168,11,21,171,109,123,100,79,124,202,172,155,236,144,86,224,44,183,119,167,51,180,139,191,76,201,173,212,215,120,148,255,149,110,69,229,152,112,197,133,178,122,15,23,55,103,67,13,152,239,59,168,53,175,130,232,143,236,0,96,95,206,91,141,167,127,199,149,82,51,222,51,43,148,225,183,56,32,68,76,97,35,154,233,207,47,2,29,114,143,36,159,81,168,169,22,163,74,208,233,149,204,129,138,138,13,48,180,42,41,155,141,156,228,19,71,135,137,63,119,146,67,61,236,133,52,209,164,39,67,110,28,5,36,100,159,52,79,220,118,89,126,230,63,180,117,243,165,179,147,209,255,162,97,177,43,45,86,56,48,223,195,122,39,130,118,8,183,36,55,42,221,83,72,74,95,130,91,23,121,226,221,206,241,204,44,105,177,188,105,190,84,106,225,244,183,44,76,188,169,150,98,155,208,244,161,94,75,232,173,64,126,153,184,124,75,229,87,31,209,154,93,125,64,53,167,155,250,167,122,169,184,231,14,34,61,208,47,179,182,194,37,87,240,10,125,2,26,125,232,189,207,199,3,153,204,157,148,33,93,160,134,67,238,203,126,198,203,210,112,25,199,23,136,192,135,207,227,224,213,125,17,93,230,177,178,164,152,162,80,107,50,52,221,42,20,128,143,202,168,22,91,223,159,118,214,249,29,184,124,24,124,1,183,54,43,61,91,155,116,241,94,157,187,60,100,244,97,97,177,9,57,90,72,245,38,31,86,172,41,102,15,35,39,4,233,141,9,165,41,137,229,44,122,16,181,99,178,84,124,207,34,140,41,145,250,172,186,100,100,156,162,5,126,187,160,57,183,240,17,46,181,44,120,144,141,151,142,129,195,192,11,203,241,78,134,142,214,106,198,94,141,84,62,51,127,110,9,65,150,68,221,157,131,236,130,114,10,128,197,13,157,252,8,165,223,138,108,179,156,231,156,82,132,196,202,13,64,69,92,110,180,238,15,125,240,30,231,134,56,66,31,193,191,100,72,106,233,11,113,8,121,238,178,117,107,157,215,58,43,212,236,53,215,214,1,16,192,173,175,231,62,113,26,94,248,47,30,36,232,160,227,75,161,127,33,5,192,210,69,155,249,190,217,224,42,17,77,54,231,20,45,5,116,154,154,80,74,148,126,85,137,13,59,123,226,167,20,148,24,19,123,17,78,46,126,232,255,147,20,83,85,103,16,86,141,246,211,162,58,245,162,77,31,51,40,174,164,117,38,201,18,8,240,124,226,180,213,190,92,223,249,184,227,8,168,86,142,19,66,247,142,54,135,218,13,197,216,225,152,61,155,156,171,88,150,158,129,132,144,138,13,21,166,17,156,62,40,147,131,134,66,228,77,177,184,53,207,92,208,3,16,2,45,215,154,73,196,92,47,104,0,94,23,103,132,206,81,105,63,84,231,7,205,95,148,128,250,142,158,42,49,223,26,22,72,27,211,39,245,201,245,4,127,48,221,21,121,201,223,108,209,6,93,31,85,112,207,74,123,201,78,249,139,38,60,134,47,225,21,74,31,177,146,41,144,16,100,28,219,207,21,104,154,200,135,169,238,147,227,243,217,211,187,109,182,74,223,148,201,132,46,26,159,121,196,145,148,161,153,126,127,103,44,44,215,135,248,8,157,23,184,220,82,173,81,229,136,173,243,230,69,68,158,137,156,73,166,209,116,155,166,231,141,186,187,84,175,227,63,227,13,18,245,222,185,2,9,97,179,58,174,246,67,94,255,153,44,100,138,172,19,5,67,221,82,20,224,61,104,222,44,53,106,82,147,130,225,31,218,140,64,109,45,5,216,165,119,100,159,228,18,213,150,192,59,85,135,249,36,228,230,57,28,67,206,105,230,148,212,28,106,92,97,2,31,152,107,208,11,10,205,238,102,126,66,83,190,233,77,232,77,96,85,249,251,119,192,179,5,0,198,67,127,22,157,78,146,64,204,6,39,200,12,229,227,234,242,193,195,141,125,107,248,143,210,251,18,220,67,240,110,48,114,110,15,160,241,14,133,152,132,225,44,134,92,88,11,167,164,225,12,234,164,92,9,175,74,190,164,193,157,232,4,137,216,80,165,124,20,254,221,2,198,63,217,156,135,119,4,178,58,153,215,139,67,52,172,206,47,40,75,33,86,67,63,41,10,20,37,237,37,156,4,13,25,23,201,228,9,237,67,16,22,116,17,184,162,203,188,227,13,110,65,231,79,200,61,118,207,68,161,90,71,47,113,31,224,165,90,23,21,239,63,80,176,54,103,99,60,125,72,207,90,110,231,121,225,205,35,28,16,137,252,136,94,179,14,97,157,227,66,82,219,137,26,78,157,181,147,28,161,251,43,196,201,53,245,149,152,194,86,91,70,203,91,114,199,241,212,180,125,44,131,135,116,26,132,69,27,84,222,132,88,96,163,119,62,129,249,230,33,147,28,124,23,172,231,132,144,182,235,125,193,70,233,206,77,27,210,203,223,213,95,105,230,117,205,214,164,126,23,240,10,34,237,211,43,162,138,230,118,192,86,247,125,167,215,62,26,113,209,175,19,231,246,167,150,22,44,69,31,236,205,198,210,214,123,93,60,9,175,131,96,145,71,92,190,209,201,225,103,43,204,242,98,253,129,95,56,223,107,29,87,165,180,44,49,28,37,42,83,215,122,91,126,77,38,243,71,213,191,223,14,76,247,97,110,190,120,147,167,234,237,10,98,148,45,218,3,23,117,15,148,142,173,118,236,90,31,27,85,54,188,202,253,43,102,109,130,17,8,239,241,89,212,14,29,172,179,90,8,104,5,203,117,188,43,184,167,54,8,100,136,17,55,201,102,193,221,245,173,86,65,162,176,40,92,214,101,18,82,59,131,63,156,187,219,65,190,115,172,242,52,181,80,109,165,136,98,148,149,152,234,86,143,132,100,239,159,119,163,250,30,130,119,190,45,58,208,104,161,144,10,202,200,31,177,215,242,236,78,3,151,34,8,16,172,231,112,71,159,168,32,208,230,50,84,234,214,40,92,65,60,148,117,76,216,111,91,121,177,66,86,123,55,54,126,46,118,241,103,105,245,89,242,0,0,166,87,7,145,164,227,90,30,10,4,88,64,114,70,127,14,161,218,198,16,35,230,115,54,65,108,190,175,186,252,79,33,24,82,118,130,249,181,253,61,28,154,77,227,209,111,63,61,68,223,162,41,90,176,37,114,169,199,77,160,219,199,22,79,240,212,158,243,217,226,74,158,215,193,166,204,82,135,0,106,12,155,150,113,241,197,33,205,6,16,19,118,164,194,115,243,112,162,251,134,203,122,124,61,242,68,140,200,131,168,172,123,48,70,132,227,199,3,196,130,48,55,231,64,216,195,86,36,160,233,137,145,108,224,93,218,61,107,191,138,171,13,215,212,65,223,117,85,120,109,207,141,12,23,221,175,68,130,129,185,138,67,225,85,127,85,215,75,146,79,69,133,10,129,210,51,71,147,116,11,104,76,194,87,78,137,12,108,185,53,10,210,35,135,33,203,224,96,175,47,98,138,83,60,163,16,100,51,21,186,245,7,153,128,164,73,27,189,195,13,61,255,96,12,174,169,37,39,235,177,224,137,71,128,240,63,137,238,255,68,185,212,135,190,156,240,184,158,113,210,241,119,224,63,177,236,63,172,135,117,74,27,187,227,253,246,222,134,197,251,197,243,107,188,160,85,252,111,4,141,195,243,91,73,226,144,131,109,136,10,172,209,186,95,172,96,107,43,22,44,176,226,122,100,50,28,65,163,62,235,88,16,254,97,48,250,64,155,101,21,83,64,255,189,98,142,60,20,184,3,54,87,20,50,178,254,138,105,53,169,141,5,88,57,244,207,138,191,208,185,54,87,134,70,182,197,77,248,201,118,133,148,231,106,241,215,91,61,184,61,250,9,140,91,66,203,141,93,171,166,65,183,29,234,196,85,230,194,177,148,240,126,71,14,92,212,2,120,179,141,11,42,166,15,45,196,187,30,249,247,104,244,5,25,126,208,252,253,157,224,36,138,145,222,221,213,15,204,112,217,50,193,215,194,2,248,214,48,43,229,7,204,79,218,223,82,137,114,228,41,220,68,157,35,245,242,213,255,141,189,192,243,63,72,119,222,107,252,230,192,211,47,186,209,144,213,221,185,22,152,208,54,130,76,100,242,54,210,211,40,29,189,40,7,183,252,209,130,240,76,107,14,110,35,151,57,0,187,180,78,210,153,198,18,212,33,205,72,211,89,150,175,136,7,138,13,18,93,226,93,52,171,126,188,165,113,29,15,231,234,11,67,54,164,115,158,58,48,20,202,65,198,247,224,202,190,45,10,153,146,148,150,218,67,157,27,190,197,15,182,135,56,130,43,203,209,174,134,100,81,179,58,182,229,1,155,224,135,148,214,99,38,92,212,220,49,17,170,248,161,123,88,92,5,119,19,210,149,12,254,121,21,140,38,10,247,25,4,22,186,68,1,211,221,109,182,103,137,4,242,129,66,67,138,61,50,131,83,208,81,53,132,36,86,63,33,62,142,250,210,195,68,246,210,84,77,150,182,48,140,129,1,24,195,122,107,160,22,129,227,250,27,102,21,127,52,229,47,19,58,21,47,132,85,233,11,183,119,3,54,223,94,30,168,153,3,202,62,170,29,46,235,105,186,122,192,71,128,73,149,47,98,46,122,34,64,101,76,177,160,154,47,174,96,118,108,73,203,121,15,19,101,72,99,177,70,118,219,124,182,128,41,154,76,22,204,166,120,224,174,35,27,29,63,8,248,217,183,247,192,11,141,178,28,4,184,73,111,64,221,65,220,21,145,34,163,79,94,28,225,40,146,182,182,2,244,18,250,136,64,65,3,121,52,149,19,150,105,221,244,244,247,77,249,155,100,216,128,178,170,122,153,140,221,2,88,211,227,255,108,191,91,6,185,100,148,31,75,245,179,229,46,107,30,214,20,93,198,142,86,108,83,131,235,38,107,38,203,229,248,160,22,216,41,215,22,55,59,211,156,38,76,79,202,176,49,88,161,162,206,46,81,83,200,99,138,117,40,110,2,84,142,165,212,63,185,183,35,165,96,218,110,177,40,36,21,19,181,76,171,145,175,144,249,115,42,97,99,152,49,128,122,54,8,136,236,196,46,137,181,211,218,83,112,177,64,193,136,89,220,176,221,204,172,174,154,77,96,166,191,132,59,141,90,169,6,46,45,84,193,160,209,49,6,199,255,3,129,73,146,92,31,226,30,164,12,7,148,241,217,3,113,226,199,81,146,95,141,45,176,205,253,233,128,78,74,123,244,138,154,234,99,11,241,18,251,174,123,196,122,254,82,210,2,90,216,87,97,38,253,160,197,255,134,152,168,162,17,72,133,41,122,235,85,154,133,172,162,240,103,107,149,216,192,182,55,27,163,94,52,129,61,154,61,11,135,223,222,154,217,53,135,124,181,120,2,41,107,239,28,32,232,45,27,51,86,176,14,7,40,249,170,100,67,101,131,23,151,200,74,151,82,184,146,40,7,64,240,146,253,80,218,150,108,16,186,224,225,98,8,166,177,252,0,35,95,107,137,80,130,116,129,161,149,37,52,149,240,167,11,50,129,134,80,126,16,233,201,206,97,186,68,205,245,254,241,139,20,5,89,162,39,98,188,107,186,119,233,101,250,245,150,241,120,191,39,29,12,121,31,198,242,252,230,85,160,112,172,171,128,29,103,65,246,39,126,74,92,140,142,56,181,82,101,195,59,71,4,8,9,42,98,180,136,41,26,56,252,4,230,102,239,251,161,183,106,22,54,238,250,59,61,243,9,189,77,195,254,119,234,124,186,211,5,26,88,176,159,87,101,242,100,179,102,218,39,85,82,118,109,146,144,225,73,28,78,77,189,135,29,192,12,95,153,113,248,50,171,113,241,189,121,194,155,247,109,70,124,72,61,27,79,56,185,218,51,155,130,98,183,1,100,60,85,55,160,158,110,41,58,63,216,176,49,228,195,87,118,254,105,223,41,138,84,41,78,214,111,49,206,175,91,190,57,25,68,120,22,127,85,81,202,226,197,123,156,169,249,12,182,148,31,115,211,146,41,208,248,249,197,188,103,47,138,8,117,43,130,28,28,102,44,149,38,221,176,211,11,76,148,186,176,252,87,62,69,3,88,80,123,168,196,245,128,224,186,224,99,220,46,237,181,88,159,161,175,204,237,160,154,13,131,12,99,88,171,231,111,242,238,194,193,15,3,254,152,148,114,131,215,216,106,245,73,197,176,147,149,25,185,200,252,52,225,236,86,240,34,22,76,102,243,132,148,11,204,125,58,185,37,184,188,4,169,89,249,104,232,254,3,96,102,68,177,242,8,251,188,177,100,48,1,248,177,185,181,108,161,130,117,35,229,28,94,131,105,31,242,158,200,167,63,124,21,55,142,139,10,202,5,82,209,8,37,48,22,47,237,174,182,254,11,32,46,255,142,78,113,207,192,187,172,174,16,156,90,26,138,142,57,129,2,59,148,175,197,194,242,205,81,57,214,199,206,60,204,225,254,113,28,148,222,242,209,101,104,98,108,237,223,49,114,212,129,78,146,78,208,40,162,230,188,127,198,195,47,15,146,82,173,159,186,217,133,148,237,194,5,33,102,245,90,65,8,165,35,12,231,205,62,97,232,36,7,127,30,119,233,149,99,221,178,173,102,226,168,250,196,60,181,5,125,126,243,158,64,110,37,30,195,162,229,136,241,198,229,105,88,85,49,14,96,84,216,55,253,53,92,172,24,38,54,35,37,50,118,149,84,244,199,203,56,87,218,44,100,7,25,135,147,55,101,115,200,99,37,8,239,72,221,30,76,8,86,146,55,44,91,241,31,111,230,90,185,168,144,245,50,43,46,238,33,229,223,34,244,14,118,219,103,141,110,249,21,49,255,202,251,214,126,66,144,34,95,94,195,240,131,109,100,123,73,158,69,82,217,206,59,169,190,31,185,211,83,88,73,74,185,229,228,147,57,21,198,39,234,143,84,167,170,144,247,206,56,43,55,104,193,157,220,89,125,173,151,17,4,10,18,124,244,41,133,194,59,11,202,98,174,212,26,19,95,71,26,82,242,133,85,125,4,131,36,108,37,250,255,99,63,15,53,173,129,255,175,83,105,132,142,35,4,243,133,67,237,220,88,25,169,219,83,229,33,83,46,251,0,111,226,87,41,226,98,245,208,93,251,94,207,210,41,146,56,119,137,32,0,61,212,6,161,219,144,112,202,88,124,132,83,197,240,185,196,152,34,202,136,59,198,165,5,136,11,246,158,60,3,176,105,203,207,70,162,187,45,160,39,60,82,115,113,239,37,166,188,235,215,222,227,65,73,188,70,178,98,215,247,7,12,10,4,216,139,202,178,125,231,103,79,61,127,58,10,202,75,42,107,139,214,172,4,14,3,23,73,247,52,158,78,61,218,235,79,191,182,70,127,157,34,208,242,177,248,153,110,42,50,168,186,212,159,202,174,245,161,60,197,47,221,200,111,195,231,35,136,145,196,62,119,52,247,41,50,41,64,94,231,136,149,213,174,127,157,61,143,47,166,152,59,245,186,16,70,32,201,49,239,157,90,225,122,138,88,158,93,59,121,246,69,151,25,182,189,199,100,74,131,123,99,103,185,138,240,169,255,83,8,240,13,159,156,5,223,181,247,243,244,179,90,207,159,36,69,34,174,29,39,12,198,108,220,130,2,10,203,188,206,67,116,209,27,67,170,198,93,113,250,14,198,254,196,37,146,198,0,245,162,19,196,105,30,136,94,211,48,61,213,53,160,236,102,140,240,236,1,246,124,73,73,184,88,243,157,125,154,77,39,104,111,1,205,78,22,233,44,37,253,92,198,51,8,211,150,43,192,106,122,208,21,123,140,14,148,222,144,217,194,15,242,120,80,45,66,71,74,147,132,37,185,45,165,41,76,166,143,130,134,3,4,15,104,214,102,179,162,238,195,200,235,20,223,172,249,110,37,43,216,136,128,232,235,48,215,2,250,173,82,109,146,30,125,217,231,73,206,65,2,40,45,35,163,248,230,102,19,67,102,0,76,64,7,130,23,167,105,28,152,26,73,234,15,36,35,231,146,205,50,217,164,199,154,192,15,19,80,26,30,181,14,197,12,131,88,61,140,86,85,233,182,210,78,143,77,63,177,30,176,10,224,14,137,130,162,84,191,108,227,75,85,115,237,159,119,222,168,131,18,13,22,92,110,176,134,71,180,31,116,154,111,4,116,74,59,2,191,75,114,181,184,238,106,236,202,251,63,247,48,35,155,172,61,122,174,26,38,3,176,42,15,71,195,153,55,66,191,33,169,177,220,36,95,177,66,86,173,31,180,219,166,178,139,120,139,67,88,25,238,233,169,169,111,163,217,54,29,44,34,138,236,199,35,50,82,214,30,125,91,25,222,65,137,125,96,232,78,167,209,68,71,70,1,22,163,34,202,200,71,113,235,157,41,14,32,110,171,235,197,174,10,51,158,251,44,98,199,201,196,168,50,201,99,205,245,153,75,169,17,143,154,52,222,138,28,173,86,92,134,115,136,220,131,85,171,122,218,117,190,117,143,79,26,121,10,50,45,80,241,33,4,253,140,1,159,201,105,123,35,133,81,59,236,16,238,109,215,10,124,211,64,112,180,147,203,106,142,69,97,205,162,177,217,151,174,189,239,69,50,30,166,238,219,120,79,225,197,121,127,91,215,89,102,17,39,158,213,94,164,254,49,125,216,191,222,90,38,224,214,242,60,2,38,241,139,218,34,185,186,30,206,33,43,38,242,81,191,12,1,200,96,167,125,197,194,127,129,244,184,30,74,74,196,174,229,224,226,124,52,137,122,146,108,187,169,127,72,111,131,243,79,149,236,134,103,137,212,161,44,61,183,188,103,150,96,95,88,187,167,31,213,185,63,128,70,10,58,47,69,155,112,231,242,129,19,78,116,74,152,85,44,128,199,241,148,56,48,27,194,180,191,35,170,227,179,166,110,172,88,208,185,53,153,120,109,155,216,205,172,159,59,191,94,49,209,213,90,125,246,132,153,163,89,50,28,91,141,185,11,4,229,210,18,79,36,117,191,90,231,97,92,89,193,98,201,7,9,252,3,100,157,87,134,164,29,218,54,7,117,232,97,226,74,185,43,135,78,199,151,206,137,157,244,201,49,137,164,23,115,134,121,92,128,224,192,100,154,252,124,146,17,129,44,130,237,65,159,194,35,88,56,132,29,163,200,91,112,118,35,100,76,112,87,180,233,171,69,124,62,161,232,54,66,129,248,193,47,232,197,143,236,112,36,132,61,97,179,231,60,124,4,220,161,114,16,84,196,143,200,58,98,2,255,8,3,222,42,146,204,234,68,199,78,202,173,32,215,30,242,64,32,250,49,111,31,174,191,209,40,51,55,101,12,137,212,116,140,72,132,52,104,204,245,218,122,29,236,175,188,112,137,112,129,225,22,84,118,55,75,104,13,207,51,243,102,148,120,49,86,192,53,173,30,143,161,0,187,160,141,185,32,104,37,221,242,44,29,27,162,135,12,4,205,239,98,8,217,237,81,207,29,240,169,209,6,80,56,120,99,193,90,244,235,14,45,162,130,224,62,152,96,147,9,238,188,49,82,151,207,8,240,126,39,228,192,121,199,227,52,238,238,69,130,134,174,90,34,126,176,133,63,234,79,219,126,186,224,106,183,242,244,90,180,161,17,110,155,66,109,222,205,83,121,103,49,85,234,220,198,98,67,0,50,194,21,182,193,118,19,220,4,173,96,221,203,40,186,232,98,162,37,12,169,225,26,229,12,71,121,194,162,100,159,139,30,0,151,86,14,131,219,129,154,212,170,79,126,26,171,90,92,239,0,106,79,97,213,183,128,12,238,216,30,67,114,73,64,191,22,179,225,12,252,220,234,87,55,51,145,66,34,63,168,252,148,87,47,176,54,228,85,152,226,61,198,41,76,94,182,131,134,142,127,97,14,232,78,147,107,91,23,55,184,220,0,132,128,230,214,41,253,146,45,59,69,244,78,228,127,47,234,235,212,197,152,203,251,16,167,93,153,46,245,207,238,82,246,96,131,4,123,250,67,9,15,63,198,214,205,18,51,223,238,190,104,69,185,188,1,61,168,132,22,21,224,86,237,119,49,15,228,241,216,161,180,19,252,22,109,144,133,49,21,97,145,73,250,32,160,0,103,179,235,69,26,206,44,140,184,97,110,167,21,84,228,112,18,154,24,41,60,232,190,168,43,72,248,82,221,13,138,79,89,140,122,61,117,232,17,75,243,217,88,218,235,50,96,182,174,230,168,249,99,90,3,240,143,171,128,49,247,62,32,242,216,73,239,88,172,30,77,172,78,40,138,46,152,178,103,92,139,57,224,167,208,14,63,245,78,69,235,225,103,133,134,96,22,32,104,77,117,153,192,206,38,183,221,117,253,207,240,211,16,89,105,251,119,74,144,222,156,150,154,58,135,38,58,165,24,125,4,181,205,243,117,226,156,243,80,70,66,176,146,37,197,55,215,99,87,148,92,191,170,198,29,60,48,57,132,232,226,100,191,28,143,184,235,205,69,47,243,18,71,89,96,148,5,68,98,120,4,46,222,166,248,156,123,31,13,147,244,29,153,133,248,130,207,112,2,139,131,49,115,58,120,121,244,170,19,97,201,192,75,161,137,127,83,157,78,253,58,222,224,220,83,182,11,236,101,153,140,34,113,36,254,143,112,151,78,23,46,155,32,170,178,239,64,77,243,128,127,240,27,82,213,68,205,87,27,42,124,75,156,9,234,4,161,210,181,7,140,130,78,31,105,100,208,169,223,62,105,229,132,50,56,128,226,5,184,254,213,116,54,2,93,233,67,132,34,39,179,133,27,209,227,163,127,21,38,10,175,140,28,114,70,190,173,123,166,31,176,23,83,27,2,64,147,250,217,95,1,100,211,238,42,151,65,188,182,234,61,134,64,31,245,14,173,167,214,244,223,242,182,230,208,180,241,228,142,135,251,1,188,189,100,175,18,181,117,35,14,102,136,20,208,168,235,41,228,102,112,204,114,197,137,63,144,1,174,122,8,52,194,119,247,169,229,16,103,124,105,126,128,30,165,102,132,107,24,55,253,220,212,101,202,129,150,144,2,88,195,9,152,160,243,97,168,80,228,18,168,79,186,193,151,206,197,164,32,6,58,126,128,178,154,122,20,188,81,123,96,6,46,214,149,107,24,177,129,255,208,247,29,66,228,212,126,81,168,1,76,131,174,108,141,122,248,24,107,113,170,68,235,117,129,83,56,163,148,130,79,104,185,22,138,198,242,77,180,102,47,117,225,233,90,16,225,8,163,241,112,173,15,227,176,197,136,139,114,202,96,151,63,60,96,154,107,17,147,224,206,248,93,53,106,235,229,60,87,165,173,67,60,192,40,25,38,154,183,128,195,41,187,21,254,166,61,76,158,20,29,63,194,131,191,180,111,32,193,245,193,122,94,224,84,142,94,172,150,192,219,151,49,107,61,164,252,204,72,119,227,21,253,120,84,60,176,113,224,172,24,196,92,64,19,6,114,3,127,121,48,40,3,60,52,74,110,225,56,14,140,23,179,58,129,206,230,166,25,190,123,31,5,201,50,253,204,94,174,116,91,166,97,216,90,145,201,152,88,164,18,19,17,202,204,251,146,159,61,233,43,209,63,240,241,168,94,78,86,211,0,62,97,12,204,199,62,218,65,64,9,170,91,210,0,191,56,249,81,51,140,84,246,229,192,59,27,87,104,195,108,174,216,168,188,98,234,57,57,162,193,13,190,155,45,124,40,58,32,99,14,179,68,39,112,92,159,159,36,201,2,226,129,171,120,102,185,148,114,152,162,196,181,56,69,182,37,197,98,228,38,41,142,10,57,84,197,160,183,210,236,9,42,214,224,63,62,31,118,26,251,177,236,185,210,104,244,19,251,195,113,141,34,50,255,204,42,56,117,66,203,139,249,119,14,28,203,175,32,42,245,180,104,11,154,25,127,248,60,200,28,180,91,39,244,161,108,240,140,189,72,32,119,76,235,30,100,46,74,250,110,234,232,192,243,51,124,39,251,186,123,64,23,149,105,161,56,180,49,163,245,34,42,187,145,64,13,82,135,95,186,146,44,214,135,104,194,94,110,93,178,242,130,21,226,63,156,184,127,204,241,167,193,180,9,237,106,90,105,165,19,198,246,140,189,35,66,77,27,170,145,237,170,99,161,189,234,238,51,219,82,212,214,32,43,128,193,45,163,2,216,44,192,84,104,92,99,93,116,94,163,255,90,174,176,184,147,127,46,68,22,63,23,62,151,173,125,237,52,101,54,144,205,184,145,103,197,86,53,11,127,158,118,175,217,13,86,251,47,11,230,181,185,174,212,134,254,17,229,174,154,246,87,107,230,55,252,104,84,104,251,201,66,110,183,24,71,54,10,178,175,12,182,18,163,73,203,244,85,216,175,129,81,60,17,112,71,155,136,34,122,134,137,245,172,152,64,127,55,97,0,148,116,138,88,45,172,16,250,169,10,55,168,155,249,246,117,74,112,183,220,144,84,127,245,255,79,75,162,219,9,150,235,53,199,122,194,58,198,192,83,66,183,114,7,36,198,143,179,218,40,178,248,218,185,108,140,103,50,91,31,235,191,230,109,62,140,189,224,31,241,31,255,48,167,106,18,242,164,95,24,208,232,159,107,188,95,66,187,61,92,245,43,201,191,135,1,41,19,255,103,156,115,9,219,112,48,74,62,113,152,120,196,200,133,105,206,67,75,26,102,159,159,237,244,74,119,46,70,217,24,102,5,82,212,11,224,67,44,241,148,125,122,140,30,141,56,185,122,202,228,228,152,203,143,221,92,116,168,69,113,89,106,187,215,201,255,151,132,143,105,97,52,138,102,179,146,194,72,5,11,142,16,31,119,218,54,11,45,117,143,78,191,169,116,115,101,231,67,196,81,203,175,126,36,74,3,153,52,15,176,118,87,2,10,235,166,166,25,217,24,97,56,174,121,208,62,83,81,159,25,1,81,67,213,89,71,34,140,83,221,7,159,118,96,172,176,235,249,185,28,97,166,17,64,245,165,23,63,251,128,105,12,76,148,92,91,188,236,238,25,184,58,203,60,22,171,192,183,224,144,158,173,39,61,188,92,76,155,181,102,5,187,207,150,94,58,3,250,36,236,210,151,254,24,164,165,111,28,108,229,47,22,146,124,12,137,148,24,184,174,127,13,247,114,83,177,100,178,209,116,247,77,184,99,249,116,52,90,208,48,242,239,23,251,172,248,54,133,62,24,240,90,110,209,64,19,65,231,127,36,40,74,61,89,232,108,40,133,183,241,255,164,20,180,249,37,233,11,144,123,198,10,134,56,30,115,232,181,188,113,167,11,26,133,132,207,13,144,114,236,85,141,70,151,42,10,176,211,160,243,33,210,57,247,197,33,32,215,207,152,153,82,222,95,87,217,232,251,9,157,52,92,92,186,221,244,36,132,244,171,126,222,212,178,213,118,239,52,68,215,228,157,37,229,77,151,40,95,205,177,209,250,59,223,193,65,135,147,161,220,60,30,20,221,12,251,251,237,115,218,76,211,222,227,113,244,133,150,144,25,141,230,202,17,219,118,142,8,254,249,111,8,74,66,92,214,206,5,252,176,47,65,208,174,127,25,182,208,254,125,215,136,104,95,122,148,47,160,24,171,217,115,108,36,46,111,121,54,209,200,78,201,242,47,82,146,153,116,84,30,151,175,199,2,189,89,106,30,113,219,11,101,233,191,165,1,168,238,15,156,187,76,114,205,125,10,232,251,59,152,234,16,241,125,111,195,40,170,83,198,62,219,137,128,20,195,25,33,235,77,95,39,151,116,175,239,44,250,171,84,173,154,211,23,212,157,160,162,208,164,16,244,147,14,14,17,6,104,150,53,108,250,78,227,27,137,22,252,98,238,175,243,37,70,13,183,79,164,152,113,101,78,244,30,197,103,210,103,214,38,156,171,0,17,21,28,178,30,168,20,31,200,208,51,52,113,15,151,103,235,237,40,10,81,34,216,193,173,182,231,138,223,70,74,110,140,135,128,67,193,157,182,109,142,223,157,163,206,148,192,228,100,183,148,130,219,246,217,18,184,83,27,227,178,40,188,85,136,45,33,244,69,87,159,128,40,97,108,157,0,46,148,60,23,222,235,38,205,188,53,18,244,187,182,168,183,237,144,27,24,195,130,65,220,216,15,20,137,249,27,41,218,232,246,197,92,106,119,80,113,188,192,30,233,34,219,39,146,187,114,27,18,165,104,236,249,38,44,105,166,205,230,49,128,243,36,251,113,40,38,25,215,224,120,27,235,159,12,92,34,87,109,158,74,60,6,136,178,187,38,91,137,86,88,121,201,214,195,151,83,64,228,135,143,158,147,97,176,188,111,251,247,113,197,192,23,113,9,177,188,15,65,193,111,153,189,107,45,251,63,75,15,75,144,12,21,147,41,0,174,131,76,50,32,230,156,172,12,21,217,99,174,122,176,90,142,255,218,205,218,102,252,254,211,225,2,68,190,66,50,226,64,173,14,103,174,112,42,47,226,144,59,125,110,69,123,255,9,156,24,136,238,168,115,76,198,25,170,142,181,178,27,82,125,25,38,98,50,248,232,139,82,51,79,162,74,26,73,204,26,40,13,40,2,73,96,105,177,92,99,35,99,110,56,185,105,177,205,31,100,153,114,150,60,150,252,43,129,210,116,71,159,252,129,54,152,242,65,180,226,15,50,224,127,124,175,143,91,38,46,62,8,22,59,186,178,38,77,246,103,48,216,212,109,56,156,174,127,24,51,123,161,249,178,142,219,27,68,158,78,254,94,242,73,34,240,204,200,93,216,7,25,228,165,205,3,19,2,181,77,104,175,11,217,230,194,135,111,69,253,161,56,50,214,192,155,137,146,17,189,167,202,57,121,74,241,142,45,201,161,154,57,125,92,44,130,241,88,74,115,124,14,144,36,13,187,40,11,139,4,59,158,157,206,13,92,151,135,1,219,94,61,152,173,99,202,240,172,225,103,253,248,69,184,171,34,33,169,218,245,125,15,58,199,178,40,202,80,134,75,170,110,92,65,6,58,200,15,51,116,102,229,188,24,164,185,80,221,62,235,227,1,238,159,158,44,47,211,248,136,211,153,57,241,104,231,90,19,39,187,253,118,187,69,91,208,213,90,157,249,110,157,246,186,4,46,212,11,235,27,55,22,236,16,139,224,123,76,76,174,18,156,21,2,25,59,83,147,157,186,202,18,243,139,77,192,205,43,11,67,231,130,169,53,171,6,241,244,138,2,96,125,93,209,194,120,187,162,104,129,237,118,242,149,94,212,207,222,141,202,202,204,103,231,34,132,92,157,95,239,176,202,195,185,87,154,63,219,10,215,8,146,73,190,222,17,110,27,90,35,66,27,93,191,17,12,120,158,138,224,58,68,152,169,243,48,157,252,163,132,148,157,222,184,145,161,202,141,123,93,61,82,14,213,82,53,66,165,100,215,10,77,207,216,139,35,208,176,63,63,80,219,7,147,222,36,12,252,16,92,225,56,96,70,218,129,99,205,25,99,208,253,109,43,104,153,0,224,39,192,163,67,138,85,157,8,128,148,197,89,194,87,99,206,81,141,47,214,217,156,211,187,184,220,33,32,20,31,143,48,136,147,54,141,147,129,53,91,215,115,208,74,187,36,225,92,30,238,23,79,195,80,124,161,28,40,129,212,156,128,13,94,16,64,122,47,166,181,116,236,218,16,106,162,20,12,250,106,59,75,168,173,41,229,75,239,230,135,79,240,61,106,144,243,222,80,207,8,155,238,226,204,246,25,2,83,116,227,42,121,189,61,88,237,200,221,66,111,84,209,44,204,5,74,21,249,236,194,187,52,103,164,109,114,191,27,0,240,99,60,253,103,92,69,90,87,109,109,138,61,171,55,129,98,152,62,65,82,93,47,130,95,171,12,145,48,243,4,220,47,118,144,188,144,153,224,242,141,144,94,218,128,144,77,106,98,182,215,118,91,73,238,22,122,110,3,109,89,91,34,0,57,72,86,228,158,153,209,235,58,200,213,223,68,254,49,210,128,11,87,0,207,25,93,183,141,193,9,142,11,15,213,209,90,220,249,117,222,163,188,42,116,162,111,235,175,70,29,243,205,184,46,214,112,219,68,27,190,37,228,13,196,98,127,58,220,90,248,241,41,128,82,170,102,78,72,99,103,47,49,238,210,203,217,40,130,83,98,143,81,119,52,173,166,24,234,61,253,11,147,118,189,128,69,161,207,122,161,251,67,139,246,0,44,109,95,241,166,224,177,225,201,10,38,201,24,44,192,55,22,191,109,159,167,39,67,213,33,100,6,197,183,223,105,223,51,37,21,232,53,7,12,64,243,13,77,22,76,175,156,127,201,50,147,144,135,179,71,59,88,161,195,29,23,213,184,66,77,202,54,134,198,21,205,74,59,68,197,2,150,28,192,219,164,192,158,231,193,240,26,176,33,136,97,129,95,91,76,114,79,86,97,220,135,80,233,39,150,150,27,223,206,160,84,151,120,226,45,231,200,167,121,200,46,1,132,39,112,88,96,85,173,249,29,67,46,208,224,131,84,81,64,218,16,15,12,243,215,86,157,212,204,147,221,26,11,10,114,75,9,240,8,16,58,152,196,219,149,51,8,94,225,203,7,157,156,249,220,220,207,80,128,47,103,189,58,38,83,183,122,51,230,254,146,160,37,235,226,233,55,164,177,33,246,224,67,54,25,126,27,216,100,83,102,46,231,99,215,206,57,243,30,174,54,153,209,116,17,156,121,215,104,69,33,59,37,187,95,75,158,233,68,148,64,236,174,32,201,143,189,99,126,50,216,65,155,184,98,84,102,243,47,178,99,59,227,198,213,53,206,39,35,180,9,162,212,58,190,48,80,234,176,124,165,130,234,100,117,5,245,122,210,159,134,31,165,144,196,154,81,131,130,236,180,4,23,225,45,144,92,99,117,71,130,142,141,103,81,168,211,2,123,203,171,59,133,24,46,169,116,160,216,233,44,215,66,201,119,51,58,75,50,68,116,127,170,113,129,55,193,109,155,237,246,191,189,150,135,24,5,204,65,201,86,15,202,87,40,122,227,52,245,82,182,54,65,104,165,101,190,208,117,246,203,163,168,171,35,67,186,170,221,100,63,0,206,157,229,28,237,147,132,88,91,215,64,64,22,48,88,246,232,140,146,211,199,110,230,207,238,78,66,78,104,253,244,227,114,94,210,30,6,33,43,1,110,176,2,156,178,126,202,213,183,124,213,218,56,96,100,54,192,53,69,60,180,73,48,142,15,85,251,191,216,147,246,47,251,203,203,138,14,174,9,73,186,102,220,0,200,22,56,137,234,117,155,105,229,151,192,129,193,93,234,222,103,57,195,107,240,92,18,180,41,23,23,255,255,135,26,222,109,47,129,205,129,52,192,82,153,195,24,72,58,156,127,159,210,114,67,196,173,239,17,84,216,115,57,151,70,218,133,179,61,149,175,160,128,222,103,91,202,239,92,198,173,251,58,186,236,105,215,23,167,254,58,4,21,22,17,213,211,230,47,195,183,154,245,187,224,165,236,107,184,195,149,49,79,138,158,97,201,64,138,145,249,37,253,56,175,148,83,197,74,69,186,47,38,63,14,241,224,30,52,152,74,163,144,190,253,92,176,164,109,217,165,118,19,56,214,162,10,193,213,18,95,72,55,150,22,199,50,196,111,155,204,32,122,25,68,234,156,43,178,92,160,204,83,138,2,184,248,7,132,201,144,69,176,216,12,49,175,55,89,163,91,23,159,27,226,183,111,153,13,35,140,237,237,170,126,119,171,55,105,81,53,55,142,131,46,39,136,83,145,158,216,192,73,71,22,117,124,243,85,81,130,52,28,216,143,226,153,141,3,162,141,249,125,8,119,27,65,133,135,123,117,71,161,45,130,255,194,160,178,21,123,106,105,199,3,146,205,115,157,18,61,181,226,101,151,234,244,10,17,216,104,186,3,215,32,157,200,151,190,41,62,181,74,5,160,213,185,70,97,253,164,115,81,108,228,207,4,144,210,54,224,36,93,21,210,109,58,54,121,127,235,182,110,122,161,24,48,114,193,83,31,221,109,136,70,83,212,203,195,232,231,69,5,55,157,106,77,101,19,58,55,127,91,240,85,64,11,229,155,10,93,177,2,144,20,75,121,186,81,171,50,1,196,62,217,231,16,206,250,186,173,24,60,218,230,99,216,36,3,103,61,237,73,61,170,38,35,224,158,166,103,119,128,4,5,152,194,141,234,113,149,54,196,25,235,18,81,227,137,137,138,115,20,204,38,189,115,69,224,31,135,6,32,171,72,87,42,144,71,72,255,171,79,132,159,83,151,209,62,152,25,79,133,19,172,154,90,84,80,101,131,150,37,245,195,199,210,235,98,122,229,215,7,164,79,63,62,80,142,144,161,189,235,24,212,200,109,145,185,104,122,29,112,81,147,15,4,108,147,244,184,155,249,18,80,201,174,227,93,226,109,63,7,17,14,209,141,194,160,30,170,18,60,144,32,224,177,0,106,248,126,107,84,185,179,106,146,13,238,80,251,18,50,96,122,216,217,112,187,148,102,111,47,244,158,22,39,76,59,150,43,22,117,202,253,88,26,166,126,243,142,239,81,69,185,255,93,56,20,32,232,185,22,217,19,198,221,159,42,176,105,127,180,90,189,136,213,241,120,92,0,77,136,165,142,142,126,142,164,219,231,41,237,134,253,191,235,254,252,57,52,25,89,120,215,145,142,87,152,149,107,177,79,86,176,4,105,59,150,254,14,74,110,116,206,16,0,218,98,156,66,18,10,16,202,136,15,80,236,236,233,75,132,186,168,174,233,16,240,124,0,189,243,98,252,33,121,215,44,173,199,127,71,233,97,165,227,102,12,62,59,225,180,119,55,117,95,159,229,177,99,143,111,247,182,37,180,23,219,51,67,250,113,124,122,213,160,93,82,156,170,252,0,1,76,22,11,250,91,147,112,1,233,251,21,112,60,137,25,215,114,231,83,28,55,129,94,198,200,247,80,156,163,198,211,214,235,239,111,210,160,137,128,181,114,163,61,8,94,83,46,49,30,181,239,140,222,109,66,167,226,89,159,32,73,145,21,222,213,65,62,66,94,137,206,128,169,236,73,167,141,150,232,238,36,44,136,68,28,4,21,153,225,253,254,31,210,190,138,17,5,228,142,90,163,91,64,60,208,230,70,88,201,198,140,171,37,112,143,83,251,39,36,63,189,48,135,196,100,189,76,124,37,117,179,153,183,236,97,94,72,5,144,76,23,71,22,137,91,101,17,51,31,37,37,248,167,248,202,225,125,28,24,192,51,67,242,20,243,183,110,138,211,210,110,39,221,189,226,241,100,225,217,111,128,6,152,234,156,179,79,2,139,150,103,51,47,252,21,104,71,84,83,243,17,144,151,52,96,128,26,163,179,77,162,97,109,136,128,106,219,50,111,229,203,148,252,102,19,181,220,239,169,7,60,6,173,111,160,55,24,162,69,223,39,186,222,104,184,206,203,0,68,178,244,108,51,107,230,205,176,248,207,12,225,122,184,184,1,99,226,173,135,71,136,45,243,127,168,160,134,31,180,45,53,1,213,36,43,83,51,59,61,115,223,67,123,54,86,38,128,71,198,210,179,241,150,253,253,1,26,104,127,234,182,86,121,188,19,134,211,19,249,75,96,210,137,255,175,48,38,23,82,107,180,73,87,97,17,31,217,160,77,243,143,164,224,77,154,152,148,205,66,240,48,168,156,21,103,19,214,154,17,173,156,16,31,18,63,134,224,211,145,46,114,33,113,105,125,72,78,202,25,183,28,255,45,63,169,16,225,2,237,156,45,254,223,125,195,250,99,49,156,250,188,216,169,104,171,157,188,114,72,110,29,153,187,99,254,51,237,255,23,98,131,248,193,121,59,142,7,176,78,52,182,134,170,136,125,40,234,245,225,74,212,208,176,105,253,8,32,143,69,180,249,246,10,31,176,129,144,255,199,193,59,12,181,231,207,169,241,243,19,253,220,49,45,195,42,147,102,239,117,186,240,63,156,184,43,225,119,87,44,38,11,106,231,241,208,145,167,222,147,22,240,37,62,139,30,249,0,209,78,164,84,131,254,178,126,91,170,226,29,73,170,154,101,221,202,18,92,146,134,178,38,195,106,88,228,86,86,172,34,113,89,4,85,139,78,39,3,161,49,94,245,107,21,206,162,64,240,35,201,126,89,226,156,229,141,165,29,4,22,197,202,125,44,200,64,176,137,55,95,167,234,104,86,244,217,45,234,206,4,6,171,85,146,235,237,168,81,103,77,204,104,16,110,90,132,100,240,72,96,188,201,254,56,43,229,76,8,144,250,190,182,102,89,64,104,238,222,184,173,138,130,235,233,91,226,30,237,38,236,194,116,180,36,198,97,37,242,32,60,224,15,13,203,190,121,127,41,1,108,205,117,79,104,173,232,164,128,0,31,193,82,164,115,1,175,199,50,22,0,215,136,87,212,105,174,240,47,27,51,93,165,183,61,96,31,150,125,70,38,192,85,215,191,65,159,42,123,59,211,210,39,96,64,53,80,103,134,214,75,89,23,40,114,4,148,61,56,175,176,119,180,61,162,119,184,21,110,204,103,52,202,109,151,202,204,240,215,165,116,96,52,113,64,112,42,171,54,172,169,69,253,44,153,24,232,19,141,73,3,80,141,143,57,23,209,218,79,5,176,20,117,197,223,97,0,0,216,103,205,251,42,189,173,104,182,224,240,187,184,90,150,165,151,54,237,248,21,195,252,26,86,186,43,130,85,173,165,88,77,47,61,60,251,197,177,40,114,201,153,72,161,39,61,136,217,22,39,227,180,112,20,184,0,22,255,248,87,132,120,113,8,6,226,212,166,57,112,185,75,15,83,79,196,106,136,205,5,59,250,63,35,80,140,176,236,196,248,3,221,98,250,104,32,99,152,165,109,139,192,40,49,68,14,50,89,102,202,12,64,120,114,49,227,205,144,18,43,180,65,47,167,89,67,145,180,44,241,173,23,232,86,141,103,210,72,240,225,180,133,221,238,4,125,161,121,44,204,5,162,64,34,84,167,152,247,154,190,162,116,71,83,180,181,174,3,151,227,180,162,28,198,133,1,195,199,54,251,220,4,182,126,209,15,24,207,187,240,50,11,120,250,158,87,125,246,74,64,175,190,21,150,255,202,170,125,38,228,16,24,166,186,7,113,0,133,182,112,138,188,2,24,120,236,10,76,154,89,48,23,228,159,219,144,219,209,76,59,25,100,202,46,203,178,117,252,97,240,97,42,143,205,52,199,220,7,0,109,217,139,126,170,178,227,213,192,16,171,133,173,237,240,186,6,14,155,94,157,194,99,123,174,181,74,164,126,56,178,0,172,77,163,74,172,53,5,161,130,161,162,149,232,150,69,170,172,59,70,142,112,87,58,16,192,67,8,250,29,140,221,17,117,167,133,43,180,141,157,214,18,131,114,105,147,206,25,138,207,188,30,41,9,97,113,247,123,251,56,165,182,239,95,79,152,45,113,160,213,230,249,227,167,149,52,172,156,182,242,134,61,19,90,144,248,100,252,168,76,213,246,126,123,175,8,114,218,41,247,90,229,94,238,86,73,43,35,42,116,168,217,75,167,166,122,230,82,130,255,164,51,9,86,79,111,49,152,198,132,96,62,12,131,23,66,96,51,213,29,13,144,20,26,228,66,41,228,68,254,126,173,192,51,62,41,184,136,182,93,102,144,250,65,236,200,19,121,182,87,125,72,97,132,164,29,130,211,26,115,217,177,199,35,54,132,98,87,138,188,229,34,130,240,81,186,231,130,41,17,74,64,27,41,169,251,229,192,38,247,81,85,224,10,181,80,164,164,112,73,150,53,119,166,144,157,52,98,187,48,28,64,77,33,237,100,1,46,123,40,27,232,128,105,190,126,27,132,205,16,107,184,30,187,240,29,128,81,177,9,175,37,159,188,53,109,59,15,33,102,39,182,31,73,163,176,14,150,178,216,231,41,152,253,100,240,46,106,181,137,111,240,101,204,74,57,134,179,49,230,134,124,152,70,64,166,43,65,203,80,53,157,166,39,138,142,243,74,145,217,9,194,93,128,67,93,129,161,161,254,211,189,239,205,32,171,253,118,141,204,240,183,222,146,198,220,187,58,201,238,218,179,206,89,183,40,198,33,53,38,40,144,216,247,161,189,216,173,9,22,72,148,174,45,3,127,35,125,111,140,15,207,119,246,38,244,195,69,85,106,121,28,241,125,124,103,116,108,152,84,133,165,68,92,5,189,160,223,125,159,69,84,91,214,24,52,36,207,180,152,8,156,70,209,194,220,165,138,212,192,246,132,124,186,64,218,179,23,131,210,117,7,15,197,250,249,187,104,74,19,195,232,168,66,171,125,133,252,89,123,236,67,152,150,187,82,161,241,29,160,206,15,254,101,201,34,79,182,6,88,237,204,67,3,24,199,64,58,22,71,118,31,80,235,148,111,111,74,248,229,15,0,160,215,0,121,227,15,243,58,122,251,203,236,223,102,217,235,105,113,239,209,206,227,198,166,116,250,85,48,71,14,78,216,2,167,129,129,240,167,56,89,118,161,125,49,228,56,221,13,219,207,36,68,253,27,45,219,117,151,229,111,247,206,97,173,132,8,74,182,16,125,54,238,31,46,244,50,250,3,216,182,42,120,67,61,39,106,101,23,248,21,80,151,115,41,105,95,47,32,90,53,3,164,31,12,113,105,26,135,101,186,43,191,173,143,177,4,75,109,96,7,121,5,231,218,250,45,96,254,193,146,225,251,238,21,240,27,207,43,187,7,61,254,195,234,210,152,46,241,186,188,216,234,82,179,109,61,190,139,211,58,36,74,149,107,249,150,196,71,226,167,232,40,42,19,152,17,194,16,94,5,11,57,37,43,99,98,248,81,211,60,69,192,80,94,225,241,197,53,76,100,1,166,253,132,17,3,72,232,72,214,60,18,151,159,15,167,78,27,76,142,22,21,129,121,10,185,35,246,49,165,218,73,182,236,65,1,175,236,230,71,209,189,163,164,179,194,209,86,6,180,219,147,94,15,212,246,83,21,183,250,40,230,78,222,159,74,94,13,20,247,51,90,218,253,125,50,81,72,93,1,200,50,199,223,192,197,223,38,208,98,122,118,7,82,178,154,193,50,199,199,7,184,231,120,39,2,232,41,182,32,75,56,236,176,5,0,113,190,13,109,1,175,212,249,89,21,130,204,162,228,119,244,190,87,252,151,13,40,209,103,93,95,199,103,141,133,122,94,189,161,222,26,229,214,114,137,110,97,84,81,251,213,80,122,215,144,113,154,105,12,130,191,24,0,226,159,46,86,119,142,104,231,72,118,224,91,195,94,179,212,168,32,243,2,25,219,4,197,34,167,252,198,18,155,87,88,62,165,118,253,176,96,152,186,128,214,140,226,59,11,113,104,102,96,136,126,9,13,140,165,46,116,134,52,249,105,131,168,226,83,93,216,194,247,236,251,159,42,118,243,93,85,175,120,106,134,75,146,217,187,183,49,138,190,5,189,3,203,106,166,110,104,108,70,111,165,41,203,34,212,254,32,10,2,238,30,243,126,47,119,175,63,107,73,75,131,105,17,54,253,158,128,179,196,198,64,151,178,55,47,159,191,106,78,234,208,198,108,42,131,2,33,44,121,43,48,137,107,252,205,15,84,242,200,169,148,239,199,117,248,6,151,51,83,45,149,57,75,160,202,27,122,235,14,50,90,135,90,94,140,171,241,123,236,90,200,243,190,6,111,165,246,139,34,141,151,172,38,34,66,201,218,83,110,52,12,146,6,26,248,102,120,174,193,25,147,171,152,87,174,79,55,208,166,73,111,90,214,25,117,239,102,226,213,182,128,93,49,129,174,3,2,180,9,250,166,8,32,141,187,26,55,157,229,144,64,195,91,154,133,56,176,6,198,60,119,115,232,70,213,143,59,250,97,136,50,75,125,198,19,151,141,168,48,163,47,67,211,114,119,103,69,9,119,244,236,196,164,248,228,69,215,205,245,16,57,177,244,43,224,109,172,45,14,5,161,195,63,81,38,117,19,125,248,179,103,199,168,84,151,192,55,216,72,96,43,117,199,103,51,202,42,177,40,169,84,157,153,173,244,141,108,142,38,188,53,35,151,221,147,12,148,111,151,129,212,37,253,142,191,152,21,241,153,150,30,71,95,49,124,83,150,47,109,169,199,96,70,141,167,74,79,11,152,159,93,215,159,185,141,249,140,114,217,75,87,133,177,114,114,27,32,86,10,246,20,157,127,160,164,227,79,194,177,107,49,142,179,84,144,135,178,81,30,7,228,120,116,11,103,210,83,15,94,77,40,116,144,27,125,81,192,231,217,112,4,184,78,6,144,65,184,221,84,114,52,150,241,217,130,114,219,252,15,34,244,209,76,178,193,231,229,38,137,147,0,147,242,150,26,33,32,28,132,60,63,134,221,9,214,135,97,120,217,109,78,130,199,253,153,215,234,19,186,201,199,169,20,132,151,74,179,54,65,25,171,126,126,88,23,247,222,39,52,65,85,45,245,229,214,38,98,14,0,10,216,42,17,230,34,91,84,144,209,31,186,211,140,175,188,80,202,99,174,124,88,40,32,214,235,133,253,145,179,186,102,42,135,61,67,235,163,133,41,35,25,168,87,141,24,186,210,233,150,19,220,120,81,123,169,245,18,197,27,207,176,15,197,115,139,69,152,82,211,148,77,184,232,173,29,253,46,123,173,245,217,54,231,135,218,236,101,196,45,109,136,189,206,68,215,214,77,251,43,39,224,144,62,135,50,114,247,67,110,247,38,143,220,5,1,173,142,88,7,149,152,225,194,10,114,152,121,105,239,242,249,117,29,172,2,39,98,218,33,31,69,93,11,210,222,132,40,251,162,173,144,13,165,165,242,181,202,215,89,196,228,253,39,70,73,153,144,63,184,211,2,204,107,51,166,197,173,14,15,96,66,141,11,12,244,148,50,16,214,9,8,52,6,165,105,91,184,10,10,62,135,250,200,159,69,227,229,86,98,229,73,27,200,217,108,233,211,81,90,93,45,50,50,149,19,35,23,116,202,113,21,211,33,217,140,128,86,228,185,130,140,104,87,180,174,131,213,254,48,90,67,239,159,204,139,229,42,236,142,82,151,187,165,11,12,150,53,56,10,76,97,213,117,217,51,242,133,135,229,78,117,95,26,31,69,32,138,147,70,226,136,42,0,8,199,224,233,35,206,48,207,61,99,52,101,204,118,143,245,236,120,33,226,57,223,53,32,255,6,236,127,223,89,137,99,84,204,80,106,20,237,64,149,193,65,7,41,202,120,56,115,112,137,35,254,243,28,47,4,229,33,115,177,48,219,231,48,63,139,95,214,209,6,170,197,116,222,104,88,254,141,16,48,222,226,9,47,121,65,188,142,38,129,229,60,122,25,131,229,78,249,211,139,93,199,181,248,231,247,38,161,131,223,146,216,88,123,189,77,186,220,2,185,53,173,226,101,153,213,103,171,140,207,44,51,120,168,36,182,213,176,87,166,170,61,250,49,139,249,215,135,168,170,59,95,118,142,249,166,177,121,94,175,159,219,228,219,117,28,222,43,180,225,108,140,7,25,5,94,45,171,5,65,137,255,40,123,190,89,181,94,76,172,91,161,197,240,85,79,172,28,47,57,205,233,102,137,143,28,155,20,20,157,41,148,175,43,167,5,82,171,148,109,247,237,236,176,176,124,1,158,189,93,168,51,115,231,208,228,55,164,123,212,27,25,190,38,1,120,25,153,91,236,95,116,67,210,173,224,156,220,91,207,120,91,114,212,191,71,198,205,146,136,65,91,33,204,192,154,155,243,71,11,55,239,100,89,204,247,199,59,120,22,68,109,137,194,203,81,61,247,11,226,242,210,155,195,209,1,193,108,163,178,20,22,170,30,148,214,80,229,153,91,103,246,237,10,245,110,211,150,205,98,239,92,94,71,206,91,253,204,90,157,216,152,35,148,167,8,201,167,24,239,191,158,102,23,131,159,64,99,81,159,58,193,185,68,1,28,24,38,198,132,80,191,19,122,235,99,129,100,49,253,29,52,194,32,108,106,166,243,179,53,189,96,59,73,241,61,32,223,84,218,118,59,32,64,9,98,239,207,219,101,38,106,54,148,148,25,5,50,107,106,152,242,117,192,102,56,184,19,232,133,157,243,182,52,144,217,94,101,153,221,88,157,52,224,159,93,159,71,2,115,200,230,116,202,177,236,75,20,176,16,39,147,24,150,195,21,251,77,57,185,113,216,168,48,127,164,56,104,92,23,85,141,159,93,53,192,103,163,130,24,85,85,160,61,246,23,185,196,18,158,228,129,148,126,206,52,198,191,182,12,98,112,31,56,160,62,208,196,234,1,56,249,23,61,115,25,164,254,151,45,11,124,107,53,151,131,221,52,249,185,90,5,4,129,177,134,168,239,37,50,111,225,178,53,251,9,5,87,32,111,75,239,38,160,33,50,128,211,5,250,31,61,177,31,115,182,221,118,33,225,75,165,5,43,89,152,62,217,185,246,122,194,98,47,193,42,74,46,144,111,16,231,76,88,151,7,93,68,144,237,82,117,206,167,239,6,137,55,125,14,88,92,201,143,148,62,216,55,224,150,178,38,77,42,167,163,233,124,131,220,55,50,219,117,225,244,220,233,124,27,133,246,213,86,54,152,29,92,98,226,98,54,110,144,186,41,161,225,72,199,30,105,121,160,56,141,23,100,40,88,208,169,32,196,122,95,231,57,244,199,120,13,232,165,250,170,24,34,231,23,205,33,18,214,128,56,165,14,48,104,223,133,183,73,58,100,111,112,115,239,70,81,81,38,94,88,232,164,212,242,0,59,114,36,133,89,252,41,204,37,193,144,244,255,242,124,20,131,112,126,131,187,205,71,229,86,90,197,199,245,45,120,190,56,223,164,63,177,75,188,238,180,176,137,182,95,221,29,158,104,4,224,38,183,94,172,67,44,62,168,237,218,85,159,58,25,168,173,108,204,228,81,18,145,207,176,19,10,212,78,133,108,169,178,117,11,19,155,152,200,117,243,99,143,126,93,75,167,4,103,249,245,27,30,184,78,162,35,174,200,4,59,119,138,195,58,130,59,179,147,48,207,134,201,207,31,90,145,168,212,195,79,220,16,253,80,24,42,159,61,178,241,81,140,246,198,225,166,94,74,63,254,3,218,93,2,74,194,239,192,68,55,75,132,51,79,200,162,72,133,34,87,86,7,157,235,37,94,78,191,150,81,213,162,147,20,232,243,173,36,1,244,91,3,192,10,224,194,229,74,147,19,192,165,168,153,5,127,230,113,185,206,127,146,80,114,246,179,16,31,90,0,242,254,82,189,36,246,211,7,118,168,33,154,220,184,107,101,40,150,196,194,242,253,216,72,132,210,147,230,224,198,34,75,25,74,233,205,159,168,6,197,50,217,127,251,94,27,0,89,55,171,138,10,197,251,46,127,84,139,97,212,131,44,89,5,181,154,11,223,2,106,249,29,222,72,44,89,57,56,8,138,102,140,86,159,219,77,239,32,203,126,142,214,192,72,16,119,161,71,155,250,58,115,189,112,51,213,249,25,85,78,170,171,102,164,103,133,109,37,229,130,167,116,64,21,234,76,246,89,206,141,235,89,223,141,56,47,168,166,97,190,26,197,70,97,133,200,148,53,45,183,39,129,38,122,174,116,58,75,115,221,204,101,52,24,94,177,14,237,2,172,234,210,8,208,25,77,235,113,24,108,216,242,184,180,255,173,101,240,51,246,200,240,13,156,209,93,60,66,170,252,82,230,13,215,146,117,255,210,7,34,122,10,106,156,176,21,68,222,248,33,83,152,206,191,60,18,158,149,114,74,41,60,203,244,210,249,189,212,25,25,75,131,95,76,207,254,188,23,124,249,162,255,170,137,0,81,97,181,221,127,2,120,240,234,80,28,115,105,158,136,89,77,135,103,255,251,8,186,242,63,176,164,122,8,11,128,19,58,243,8,212,252,204,84,170,108,158,179,247,0,254,32,87,139,213,136,45,180,92,145,67,92,246,247,205,97,103,87,101,163,137,0,61,23,230,147,218,153,102,235,104,17,24,246,70,190,79,179,238,178,41,56,128,115,241,148,114,229,173,144,63,54,151,123,191,45,145,222,89,230,29,59,34,163,123,120,56,34,137,149,161,32,221,255,87,39,50,57,112,84,159,209,51,170,143,167,190,117,145,202,12,127,248,132,142,52,118,154,247,22,242,179,161,240,146,155,7,176,79,18,1,228,242,227,81,34,121,92,236,105,176,207,233,51,86,159,119,70,173,14,42,103,31,241,149,157,98,49,61,96,106,94,142,12,146,88,63,16,173,84,14,216,170,188,7,119,188,94,156,24,78,218,117,39,252,216,201,136,241,118,24,231,164,15,9,211,193,68,14,9,140,214,99,95,235,172,219,136,83,12,95,75,88,48,152,236,153,95,137,236,38,125,35,176,220,87,52,101,106,40,172,224,140,105,118,201,227,143,43,59,162,152,247,197,72,70,232,183,21,160,2,64,169,41,69,166,102,52,189,217,130,19,196,230,34,133,35,31,17,193,45,252,112,79,79,223,99,168,154,14,19,74,179,41,246,27,199,128,101,54,80,252,173,165,241,80,26,204,142,255,57,94,25,56,246,22,133,229,144,110,212,118,251,36,49,81,254,183,116,222,99,70,181,22,74,96,199,161,124,176,7,199,9,56,128,64,200,185,222,37,225,144,156,152,22,99,76,208,43,99,207,169,146,220,182,136,30,96,166,118,49,125,40,132,106,49,212,158,91,55,84,208,213,75,63,190,113,71,83,98,109,21,176,11,204,253,157,79,106,111,232,239,253,187,98,141,32,52,39,209,183,100,176,183,32,232,137,209,189,13,67,230,44,99,233,235,31,211,62,149,120,185,114,79,123,8,153,151,112,255,65,154,228,16,226,177,21,18,10,146,172,134,181,123,4,253,122,188,229,98,89,112,147,19,145,108,246,176,210,201,128,231,96,230,39,140,7,175,246,144,253,114,34,223,14,48,134,160,78,112,135,138,197,142,208,213,221,156,197,198,131,42,169,203,191,140,36,205,131,59,11,239,147,205,235,193,132,59,199,198,42,204,244,120,24,172,221,253,85,141,118,110,76,153,91,146,222,142,200,251,52,172,145,250,47,123,86,49,253,220,27,77,170,51,36,179,148,26,32,251,162,197,246,163,248,65,123,233,68,194,166,153,206,118,238,22,134,49,13,218,176,11,183,124,197,148,169,251,224,80,11,209,166,233,229,19,220,114,244,144,246,17,131,119,108,78,6,26,238,121,82,13,57,179,139,149,164,255,235,181,20,240,76,155,71,61,89,192,100,16,244,93,71,199,139,70,203,107,44,233,154,66,40,255,1,15,20,206,89,244,23,68,123,164,177,175,187,170,150,195,150,44,96,99,142,169,220,220,197,235,124,72,198,60,112,180,196,35,190,154,107,29,177,10,243,111,210,61,157,156,223,255,101,5,210,27,224,15,23,138,119,65,201,139,134,84,70,122,22,204,153,5,193,108,54,149,173,173,37,200,81,229,93,72,7,45,14,51,177,85,166,96,189,55,43,70,88,172,251,17,221,163,81,62,196,216,14,31,82,46,38,65,125,42,32,4,9,145,100,31,102,106,231,86,31,167,246,39,11,28,118,34,92,179,80,65,191,115,43,247,211,118,115,124,156,122,145,222,177,73,161,7,117,51,20,29,178,100,26,127,202,208,177,209,121,101,140,194,20,229,139,123,55,186,209,31,33,39,115,64,97,128,152,60,147,70,35,97,4,156,87,181,58,244,132,109,115,229,91,215,10,28,25,21,57,163,234,21,101,81,18,220,78,130,105,85,41,164,78,228,156,201,182,234,93,221,241,194,212,66,84,4,11,81,116,94,234,37,200,8,214,228,253,58,205,250,62,168,189,1,46,223,0,158,154,29,127,247,188,25,193,165,228,117,234,121,149,167,254,11,3,15,12,91,42,46,11,240,230,134,120,108,46,58,63,23,230,140,113,173,206,94,55,63,20,187,32,255,142,32,192,135,161,231,95,115,204,50,125,129,245,15,153,89,124,35,87,200,91,78,68,126,100,158,103,224,232,192,132,174,34,19,19,48,139,182,247,255,70,88,227,139,253,31,10,222,62,188,140,85,169,143,143,14,29,108,159,46,98,211,30,129,63,149,77,230,246,61,181,103,153,124,242,214,63,70,78,193,78,208,159,94,20,59,30,81,88,112,124,123,183,101,239,217,86,232,137,59,250,5,110,107,71,27,31,15,33,62,200,161,218,153,82,134,5,7,141,180,7,152,169,23,182,33,150,252,223,90,209,54,177,15,50,19,8,253,37,226,84,143,33,164,230,38,215,102,42,156,198,36,35,149,175,75,79,102,252,69,215,7,165,103,252,189,221,18,204,32,86,110,22,47,74,38,247,11,126,5,145,242,247,20,9,190,177,121,79,16,110,73,41,45,141,3,247,35,3,252,191,45,7,156,127,115,198,74,194,5,25,124,110,61,109,115,151,84,72,182,140,170,23,217,123,133,98,143,18,53,128,55,78,61,89,152,214,253,63,133,196,183,215,107,107,158,245,129,15,153,169,246,158,65,172,8,47,226,30,126,10,64,163,175,108,218,130,19,89,235,34,206,150,176,199,6,140,234,201,165,130,107,208,64,112,36,44,115,250,199,236,204,60,127,43,124,225,163,49,76,103,210,254,126,180,82,44,230,68,93,12,246,201,186,72,190,172,76,128,42,173,0,221,120,14,150,19,197,121,163,71,111,214,183,143,24,187,70,13,255,228,250,134,173,209,183,166,208,21,225,94,109,145,98,70,255,76,151,190,150,183,152,248,238,224,187,111,4,2,111,236,73,135,133,67,34,193,94,52,159,42,187,59,38,75,152,72,134,112,236,191,233,150,43,156,14,167,70,226,7,114,200,31,140,164,33,84,232,169,15,96,172,175,192,57,229,71,227,101,139,17,90,45,154,32,255,204,159,141,200,159,147,45,152,135,128,51,11,78,181,154,83,92,144,157,134,244,234,140,201,95,218,104,165,146,35,28,223,139,111,128,149,30,162,119,191,217,136,196,219,138,212,22,168,182,19,118,34,168,68,234,104,231,59,166,128,52,254,212,215,218,117,66,31,249,88,61,78,33,130,242,94,66,17,169,102,100,130,251,1,125,169,71,110,165,239,246,162,251,220,185,184,20,76,133,171,122,57,219,218,181,169,220,38,166,27,206,53,166,180,135,172,64,7,187,131,182,110,67,34,191,25,145,197,184,217,30,140,72,15,212,194,123,34,239,194,64,110,117,35,199,82,17,157,252,230,226,228,44,151,158,81,101,191,59,18,175,143,139,235,12,185,50,15,106,29,143,82,247,211,52,208,35,153,64,11,50,37,13,38,232,128,45,104,62,240,201,122,137,83,140,250,178,64,142,202,168,54,119,221,215,71,166,35,108,71,223,239,99,153,12,8,134,64,200,182,235,107,96,111,231,153,200,254,189,247,49,93,127,4,200,77,43,160,120,224,252,243,224,46,190,166,143,82,46,207,86,235,116,203,190,88,18,55,121,70,227,215,107,69,58,245,221,133,33,73,230,34,36,254,49,127,129,180,253,175,209,180,54,94,124,96,104,97,243,225,38,248,166,230,189,233,78,38,61,122,43,51,76,9,219,127,1,239,79,151,48,213,26,208,118,80,108,178,180,167,38,224,5,87,106,12,73,252,109,195,190,244,1,237,106,212,236,116,74,192,255,121,219,152,67,18,77,38,21,51,27,121,200,196,0,84,219,179,46,124,54,85,12,179,49,241,46,197,14,33,28,79,227,246,94,112,66,187,209,230,116,161,40,15,78,57,156,110,138,178,73,41,255,178,62,43,236,180,171,248,21,243,240,13,110,71,67,79,176,57,76,207,194,20,219,223,36,60,83,50,200,87,245,137,235,132,89,144,67,4,174,55,221,14,212,138,175,187,209,186,54,80,178,238,243,36,9,199,108,128,111,120,61,208,105,53,44,233,236,78,63,226,71,197,238,242,101,100,227,70,160,209,41,198,56,65,115,138,237,132,126,95,23,46,122,98,177,164,159,251,98,212,145,111,203,95,36,21,53,163,88,57,51,139,255,60,181,38,187,107,75,128,165,215,232,130,56,103,173,192,192,119,72,104,142,246,79,232,200,17,207,225,61,55,106,74,61,126,180,229,233,187,223,190,82,11,232,15,84,52,13,98,154,199,134,191,227,132,219,235,17,230,249,92,249,34,165,54,132,101,234,209,220,66,6,69,181,50,132,160,155,246,171,5,167,56,49,27,175,90,222,36,13,217,116,128,9,151,3,203,43,43,40,205,132,14,248,28,88,180,107,146,95,19,175,0,109,41,170,148,148,54,179,0,71,101,59,99,221,143,205,42,59,156,112,136,31,59,18,231,136,191,41,46,122,77,101,152,172,123,108,116,111,53,229,4,163,218,156,39,171,198,100,223,236,90,205,126,143,72,67,138,159,241,118,154,239,154,219,34,182,123,33,163,113,46,15,249,238,36,50,215,132,241,226,207,196,181,96,162,212,88,224,190,81,179,12,136,146,122,238,83,129,26,72,105,125,20,146,253,67,112,232,12,188,96,52,161,160,121,241,50,77,49,218,20,78,169,246,196,95,213,12,11,243,170,71,1,244,78,233,115,143,34,201,250,23,100,9,97,17,4,211,193,128,42,106,170,138,9,75,28,208,247,157,32,4,210,106,87,15,97,167,209,22,160,123,52,183,148,194,21,14,53,212,119,43,76,147,154,56,43,175,79,109,103,68,93,115,95,230,242,89,230,162,136,47,37,79,109,220,24,217,83,40,241,45,113,250,138,133,115,120,72,115,222,65,36,226,44,1,172,128,192,152,113,44,162,139,24,194,114,139,90,162,31,228,198,129,96,97,224,87,232,183,43,193,104,251,129,67,148,240,227,100,4,27,202,89,241,226,221,189,142,102,74,1,234,197,88,247,95,217,142,161,58,118,124,174,252,162,242,248,126,19,199,138,191,202,209,59,204,127,100,65,187,50,108,197,107,107,205,55,228,48,246,168,68,28,74,186,102,54,116,29,188,57,221,206,122,202,240,151,15,23,162,146,91,12,88,51,69,3,110,205,52,5,186,49,46,171,126,221,23,30,236,45,162,17,198,211,238,177,147,106,5,203,206,78,143,1,167,153,96,15,225,28,219,223,209,68,221,218,102,32,19,138,90,130,254,63,73,240,165,99,150,83,198,65,210,22,92,216,204,186,182,213,249,35,2,80,190,138,101,47,225,210,232,29,85,90,174,228,82,244,173,189,193,47,20,238,93,189,172,27,25,87,244,243,224,87,201,186,153,42,69,160,195,77,180,136,128,231,197,161,163,94,0,191,87,57,125,254,155,170,223,110,165,95,181,188,82,153,240,68,118,58,137,253,184,248,35,170,207,20,197,246,93,21,36,48,195,147,75,92,94,166,34,77,198,225,189,122,91,111,136,32,138,146,132,33,113,35,32,184,97,10,255,132,98,61,203,100,65,30,160,150,30,85,22,8,32,101,187,142,240,176,3,67,219,207,113,202,242,213,177,61,155,141,225,69,7,10,3,184,65,132,69,241,149,214,97,91,168,150,187,136,18,190,15,66,134,232,239,202,169,247,10,160,246,157,238,77,41,185,221,165,157,108,94,145,231,229,169,101,1,167,15,161,20,158,211,139,204,107,228,206,211,185,65,246,158,167,12,107,190,45,182,28,192,44,106,148,62,159,222,82,10,227,237,251,3,151,152,139,76,162,183,169,202,107,181,200,129,195,124,71,208,135,234,26,203,154,53,208,137,99,150,100,142,114,50,153,183,126,133,1,253,9,202,235,65,46,106,126,8,5,105,93,53,17,35,209,62,117,114,152,57,29,66,71,127,2,130,103,158,7,17,86,195,64,229,219,75,195,212,33,209,50,154,59,27,177,135,24,163,107,219,137,197,220,7,153,96,131,0,65,187,83,25,18,15,100,245,27,6,174,119,25,182,124,115,158,7,84,182,105,34,75,231,222,190,48,233,221,49,119,79,153,174,200,28,223,87,37,72,254,237,189,199,23,239,255,69,27,152,251,104,233,142,231,80,48,149,197,234,170,200,149,73,120,9,20,212,128,69,99,144,23,22,83,89,207,47,19,17,198,156,214,226,55,130,85,146,54,5,58,224,214,6,27,36,31,164,126,182,225,53,4,52,100,11,28,220,125,41,101,102,215,188,97,6,55,113,252,140,78,81,115,58,203,129,115,132,109,206,21,68,78,20,128,95,62,34,72,211,75,41,78,234,223,115,175,57,229,107,227,179,9,162,15,86,211,207,126,44,120,162,65,99,15,187,57,91,18,41,138,119,15,37,90,138,187,40,13,121,164,30,26,160,7,116,143,9,149,10,228,215,85,75,134,113,241,72,248,12,116,160,177,187,166,188,208,252,178,182,169,220,121,139,203,135,116,198,224,193,215,214,189,110,168,68,129,130,192,8,226,15,122,181,16,37,227,17,156,38,246,249,4,89,193,12,237,32,109,66,52,139,50,235,10,231,210,19,204,191,161,192,238,27,142,203,62,146,194,119,135,132,70,245,214,127,209,179,254,19,43,72,110,124,118,71,34,142,134,163,182,130,140,131,160,56,194,13,10,6,8,136,131,171,206,237,108,163,127,8,17,208,116,17,165,125,236,166,45,180,115,123,110,117,255,84,33,201,176,66,60,220,2,92,128,59,50,147,27,232,7,251,48,118,128,215,225,182,113,163,1,165,184,212,132,246,28,57,13,84,140,97,222,230,172,120,254,160,216,70,239,215,0,111,160,68,51,0,31,109,79,49,38,221,94,95,37,226,200,239,75,160,227,1,122,27,49,244,122,133,67,125,60,12,216,60,89,219,92,146,252,169,205,31,71,112,119,174,142,76,205,10,173,28,31,26,119,222,159,151,151,214,150,124,197,51,174,17,3,58,240,120,130,175,51,87,155,106,76,197,143,86,226,95,45,72,196,34,230,99,248,121,236,163,207,67,132,152,165,42,252,107,111,171,10,114,221,71,94,190,87,197,251,236,116,86,60,82,253,64,166,236,178,150,126,252,230,179,186,45,52,123,29,16,175,237,157,13,213,215,69,153,217,233,51,38,227,186,80,200,188,65,110,196,78,3,202,66,175,161,253,111,249,120,23,44,176,170,211,138,243,128,128,115,108,85,27,23,107,91,1,212,31,154,136,228,166,30,96,59,92,34,162,61,242,225,232,47,195,154,45,144,74,125,246,69,128,166,229,187,39,196,152,5,66,133,189,18,245,235,31,214,153,14,205,11,130,1,238,167,83,107,14,41,235,8,139,62,37,74,87,110,189,142,226,150,1,219,52,58,115,150,62,55,66,239,30,11,157,138,57,159,200,148,184,237,250,169,248,88,159,137,188,98,30,50,189,59,15,225,149,129,184,102,146,114,254,181,178,143,54,171,186,63,219,29,83,52,76,222,208,189,242,11,81,188,87,249,54,213,162,246,147,7,72,54,22,48,119,146,108,131,16,194,137,175,45,132,109,33,243,243,40,190,135,54,116,177,29,228,193,151,91,207,114,183,37,198,58,44,53,196,42,118,27,144,95,155,137,80,255,233,76,228,204,81,135,24,99,82,230,130,134,134,90,185,64,21,78,113,200,124,44,66,8,202,250,219,158,245,90,117,100,130,99,79,193,113,76,66,140,147,91,76,194,35,42,183,235,58,162,251,48,190,103,86,96,173,72,202,179,222,118,203,182,225,42,46,211,245,250,204,238,192,46,2,210,178,141,212,84,160,233,228,60,100,58,151,244,252,138,108,189,119,187,104,222,9,36,11,182,33,204,41,164,233,176,152,233,86,233,50,206,99,64,128,110,66,233,201,123,179,225,189,88,55,210,152,178,238,149,204,213,200,212,190,228,170,205,255,165,46,209,51,91,74,229,36,181,120,52,6,82,169,229,225,218,231,110,222,218,6,179,193,106,30,34,243,244,157,149,112,198,254,119,89,250,217,97,62,28,209,188,203,80,211,129,242,222,66,129,254,133,112,29,113,174,62,6,239,237,224,23,116,214,189,215,75,239,171,17,204,68,178,19,31,37,201,108,153,71,126,166,217,28,201,87,186,193,62,200,110,44,41,74,172,66,60,174,120,134,18,85,137,113,240,138,170,198,225,97,115,26,202,243,51,96,31,18,185,179,52,52,98,63,170,11,216,247,18,9,35,203,107,220,12,6,21,178,236,232,102,112,57,211,73,9,28,24,100,146,157,25,199,182,169,71,71,6,60,175,82,210,8,190,110,18,136,70,15,43,13,60,52,12,43,123,111,248,2,36,45,160,215,73,52,54,36,80,105,210,238,113,115,116,84,251,91,72,109,192,195,188,108,51,89,2,189,86,142,28,210,69,246,138,253,85,224,49,223,6,47,125,40,72,173,56,214,70,132,134,51,244,168,101,112,151,126,77,102,143,239,4,13,116,106,10,103,119,126,65,6,31,18,107,68,76,241,127,130,133,186,61,250,68,253,189,150,134,117,83,51,83,25,187,118,78,134,35,123,184,148,245,53,68,14,88,131,0,68,159,141,48,76,196,130,198,34,56,19,203,64,75,87,26,133,28,73,19,242,167,183,2,251,172,114,9,7,155,151,79,86,68,141,54,101,212,74,210,65,219,237,175,83,252,71,245,207,108,46,196,105,180,46,85,217,5,128,221,226,157,62,176,224,25,140,26,228,142,51,187,96,116,42,92,18,197,211,133,4,0,207,161,141,187,60,8,215,220,174,187,41,153,27,83,242,133,205,30,135,7,207,178,168,111,3,85,173,149,137,68,187,204,184,237,209,59,41,154,36,35,7,212,199,183,241,25,178,86,195,41,137,201,81,164,246,218,251,180,218,161,189,193,147,17,147,15,78,69,23,170,86,93,28,58,170,81,208,143,20,240,63,182,158,203,197,94,135,254,11,135,124,183,89,193,71,88,184,98,208,164,134,197,140,75,234,159,83,20,177,109,123,195,118,229,245,116,207,220,6,11,187,253,37,198,220,195,29,176,38,46,67,200,232,90,245,23,105,165,133,57,29,208,185,232,69,180,3,5,19,111,91,226,98,197,90,102,20,243,203,137,88,156,217,18,24,141,253,17,194,150,75,120,212,232,5,187,191,80,176,71,27,94,71,149,230,108,103,17,129,248,166,186,196,171,152,249,136,146,130,38,204,223,106,175,46,105,241,113,125,212,159,243,233,110,229,177,187,141,186,157,99,212,232,218,25,58,4,212,122,110,11,236,187,184,12,168,127,135,212,37,81,184,79,102,171,143,151,189,158,113,56,80,94,110,58,223,118,37,73,53,158,134,151,251,250,216,143,88,233,8,206,211,238,115,195,53,186,238,140,128,150,50,225,14,236,49,195,224,75,85,229,24,20,244,72,136,144,15,96,152,6,156,158,133,144,200,229,50,186,234,205,77,101,31,5,147,136,55,31,158,100,141,179,213,225,15,161,176,225,156,40,169,60,57,227,45,170,44,97,107,83,178,31,102,192,84,212,43,159,32,188,252,47,248,53,6,68,8,126,187,27,46,133,214,4,199,153,29,177,123,35,170,100,66,253,178,46,37,206,97,62,17,208,98,178,195,223,64,76,251,94,132,241,102,36,130,182,53,98,94,253,122,211,197,204,144,195,101,203,40,158,215,192,102,44,87,233,61,81,147,158,79,117,222,27,26,219,168,15,59,142,65,113,172,49,253,190,191,188,12,59,244,226,238,7,59,116,34,120,56,20,118,83,59,78,142,79,43,150,41,207,228,35,234,182,14,86,50,120,254,31,74,82,5,29,39,173,104,87,10,249,237,158,29,211,250,239,50,64,90,200,107,209,100,26,135,182,38,139,177,27,64,6,87,21,235,204,230,235,222,248,48,156,212,204,138,22,36,123,3,40,93,25,200,55,162,51,116,3,140,58,246,81,78,59,89,103,138,23,220,89,171,48,48,203,181,80,163,171,109,173,17,34,188,238,42,205,32,106,18,122,80,8,247,127,26,32,148,141,138,226,57,27,129,234,74,40,235,202,6,106,127,1,11,117,117,236,240,123,227,139,185,241,205,42,57,186,237,83,21,90,3,25,88,42,109,224,140,238,11,177,108,46,111,28,229,139,95,217,72,101,173,235,131,28,2,85,51,19,52,105,218,235,176,84,57,140,165,80,238,93,92,6,47,138,188,132,100,36,219,223,236,201,112,201,190,0,20,146,68,95,16,147,1,52,108,54,185,188,154,104,247,173,127,160,214,230,207,56,112,98,105,62,42,66,97,101,47,220,193,114,23,202,61,21,118,64,16,191,112,119,123,20,117,173,202,70,39,239,112,202,66,142,163,211,106,89,2,97,150,55,78,226,111,190,170,144,53,195,72,96,89,229,178,153,130,164,161,86,154,154,21,95,120,12,31,122,50,142,245,189,124,17,218,35,201,75,20,203,234,97,11,70,151,3,185,169,71,243,91,56,248,117,103,8,162,90,14,193,33,124,194,169,48,150,40,80,127,37,151,74,195,221,99,145,74,172,228,150,120,147,204,160,67,110,187,30,236,197,101,7,127,128,115,7,243,235,20,66,101,40,114,136,254,206,220,67,96,231,89,65,202,234,82,8,131,187,238,220,213,142,223,77,25,167,69,68,87,110,101,200,142,51,26,234,143,164,214,134,215,222,141,23,42,75,147,88,211,199,154,201,24,72,202,13,136,234,25,52,120,254,136,185,193,163,187,133,84,93,81,133,177,73,126,136,46,251,136,144,180,33,34,18,230,128,47,79,79,106,150,8,58,160,248,106,132,183,215,17,146,173,177,243,32,65,1,175,14,45,235,55,127,69,29,175,177,184,199,168,231,173,143,212,218,44,28,243,157,87,243,247,193,142,155,49,191,221,140,235,246,53,125,204,139,60,232,18,220,63,106,61,252,172,154,140,47,208,189,55,163,20,44,108,250,50,252,255,204,45,52,2,76,66,64,241,107,21,163,134,187,242,247,136,203,1,7,118,226,244,67,198,15,238,194,74,9,230,186,185,49,162,49,71,168,31,130,160,103,223,244,225,108,133,142,123,181,164,114,112,172,100,229,165,150,250,57,212,15,63,204,70,163,4,98,111,152,45,37,45,245,228,45,244,111,124,250,163,197,120,243,232,117,56,154,191,145,196,141,125,8,55,90,132,216,85,224,174,60,253,201,63,198,114,202,235,236,103,174,176,192,65,93,161,74,226,65,222,241,126,119,113,174,16,71,68,19,253,160,250,79,117,231,129,159,61,132,104,164,251,78,110,48,246,12,36,172,100,111,152,87,36,40,95,115,60,227,74,123,204,149,244,119,65,162,114,102,121,19,155,249,117,248,51,151,33,42,115,199,237,144,43,180,51,121,129,23,83,127,226,56,9,32,222,44,201,44,21,7,249,122,183,224,239,85,204,10,181,91,19,103,103,133,205,12,229,38,97,31,108,141,82,255,186,32,185,59,95,66,45,15,41,179,36,56,178,53,39,230,128,252,12,104,165,98,132,4,223,238,44,36,222,188,218,52,250,146,212,148,237,85,68,175,72,79,155,38,36,230,62,122,67,208,138,241,5,49,158,119,106,100,178,247,61,154,161,134,111,198,28,192,44,150,189,7,205,154,142,45,190,172,69,107,176,36,105,64,30,153,120,233,138,210,10,19,201,37,119,182,152,85,43,37,56,68,199,14,82,214,220,245,249,231,141,77,20,190,252,61,102,166,209,230,24,109,225,229,78,195,145,93,109,32,127,163,49,126,248,87,165,80,47,35,155,3,51,50,146,244,105,171,122,226,62,82,242,157,209,37,222,157,224,156,21,73,10,238,198,123,110,60,209,122,158,82,5,221,166,227,119,183,251,80,175,245,112,156,150,175,183,247,162,53,159,213,33,71,40,168,227,104,244,244,210,154,12,114,234,6,153,36,147,203,170,108,85,64,250,110,225,137,2,143,243,163,40,173,220,191,63,210,108,131,154,142,83,175,46,56,41,236,83,221,81,161,144,135,172,99,88,139,115,229,148,143,162,9,203,12,44,238,102,165,234,230,179,179,242,16,227,158,20,196,203,126,102,121,194,246,105,131,73,192,81,122,192,229,32,52,68,139,60,16,102,94,4,190,236,77,238,222,73,240,221,6,252,179,240,56,85,108,237,167,95,168,223,161,49,28,186,57,93,43,203,125,223,42,221,67,47,174,96,56,99,204,115,41,252,252,106,153,180,228,242,100,155,42,105,108,181,215,47,150,176,81,36,192,211,244,135,162,127,189,201,80,62,117,91,125,58,245,215,9,16,165,134,52,42,43,225,155,28,21,189,76,85,226,216,155,133,105,120,60,145,152,6,52,150,149,2,255,255,126,255,45,36,58,37,21,112,25,5,210,187,69,74,195,46,226,170,12,90,154,7,142,228,89,148,22,211,1,150,132,252,99,19,215,135,242,15,150,0,17,251,192,38,133,71,164,62,161,144,240,178,62,63,254,50,137,26,207,233,156,52,145,94,86,239,132,26,146,181,46,165,248,100,14,76,252,16,214,130,195,166,67,120,113,30,255,126,197,11,57,108,130,66,163,177,70,30,223,117,244,53,44,13,86,39,70,58,213,212,230,152,164,76,152,10,227,3,6,230,216,73,88,108,91,245,126,137,58,224,132,168,129,199,254,247,134,142,56,81,168,160,119,44,222,123,230,189,204,92,245,18,227,172,58,240,174,149,68,71,210,183,169,241,146,73,86,210,216,156,250,239,161,219,212,210,69,48,33,137,81,185,192,218,197,2,122,26,76,13,121,61,31,44,239,37,158,126,254,241,131,26,167,224,67,133,125,52,204,195,141,119,131,208,214,151,86,54,137,139,144,178,173,220,170,156,70,125,66,38,125,127,135,146,246,160,95,230,1,248,184,55,65,56,225,139,169,106,17,246,153,98,119,248,67,85,148,28,157,200,233,186,149,138,180,147,37,42,212,190,28,189,109,117,242,168,56,133,17,29,241,89,218,5,242,81,50,61,166,175,124,106,47,237,20,201,235,69,95,202,35,243,79,223,34,85,47,100,252,168,29,171,20,189,109,65,14,156,71,195,246,94,104,211,21,29,195,84,33,131,207,221,120,139,57,78,126,88,195,191,172,133,96,242,110,140,236,227,76,154,55,32,134,193,20,204,21,192,232,157,224,147,175,193,96,9,127,18,107,239,96,240,98,139,149,104,92,151,196,170,198,104,185,117,179,26,20,72,48,36,47,32,86,42,189,173,80,71,219,151,79,181,88,45,26,191,38,133,45,54,131,31,109,115,161,163,34,38,89,40,49,173,198,48,17,40,39,121,77,90,70,42,251,130,168,125,184,76,60,95,94,136,227,248,145,210,226,191,137,247,72,210,17,141,52,5,102,220,23,111,146,114,218,208,22,105,9,130,97,83,57,25,228,137,6,99,12,24,29,89,25,101,217,133,196,253,246,158,114,75,8,90,142,28,147,19,22,164,240,205,1,21,145,19,225,61,98,21,22,215,32,158,9,44,97,148,104,201,219,76,43,45,162,73,151,252,188,155,192,134,113,103,109,255,54,42,206,24,76,87,154,98,187,78,193,50,86,191,222,86,162,165,38,191,118,117,72,31,6,174,147,231,105,158,70,133,79,138,223,55,73,210,90,194,194,112,167,14,253,133,160,197,234,193,24,75,239,106,47,115,70,102,75,122,123,87,158,185,162,180,84,210,222,141,172,125,211,117,181,155,250,182,51,247,178,100,123,8,8,173,224,246,222,40,35,31,171,203,195,36,34,6,53,171,105,219,106,216,77,18,130,182,37,225,3,235,196,203,114,168,7,2,10,14,230,118,6,134,118,20,184,145,213,218,127,110,182,193,145,91,202,110,11,96,118,1,8,96,103,167,236,180,15,141,151,253,100,7,112,25,70,89,121,233,178,158,234,47,68,162,185,146,146,7,74,2,17,238,108,171,91,64,92,173,85,82,121,240,175,136,132,26,123,225,64,169,132,53,192,187,113,8,165,133,192,249,61,166,108,170,2,175,11,243,183,162,93,109,51,151,40,206,39,150,0,84,130,215,29,211,96,200,244,193,206,63,137,9,225,205,195,93,147,70,125,177,146,164,76,247,0,61,118,12,73,75,151,145,218,82,180,207,112,233,175,169,104,180,29,149,4,129,248,70,10,159,34,67,208,4,235,146,205,128,223,104,17,16,189,72,150,29,148,21,85,152,237,97,200,84,57,234,9,165,16,73,40,118,10,18,222,171,43,231,169,211,149,179,250,145,227,129,66,53,2,35,228,99,7,1,101,161,122,247,98,103,47,32,194,21,66,228,215,171,211,95,93,47,71,164,197,154,72,46,73,190,186,131,152,104,252,1,237,94,154,240,6,67,188,57,183,3,28,30,181,14,142,247,193,242,88,231,188,86,198,130,125,97,9,115,137,196,6,38,94,170,51,157,253,197,152,195,181,150,253,125,49,6,217,29,102,120,252,248,217,191,232,176,151,7,118,12,126,164,219,67,123,72,16,146,223,203,183,0,196,87,186,185,173,67,246,204,171,20,21,86,98,182,253,7,186,6,120,189,118,3,229,237,60,53,90,120,139,87,229,79,153,85,139,16,81,100,189,150,202,125,164,42,132,10,163,190,85,177,69,169,181,85,186,64,77,182,99,209,185,183,19,5,1,24,167,247,211,71,7,154,124,136,40,199,61,196,217,202,170,170,93,64,20,178,234,247,41,59,124,192,158,211,128,28,144,37,95,61,108,113,150,27,161,102,97,250,86,162,10,193,27,201,55,193,56,84,164,176,59,172,180,2,117,209,83,226,255,156,104,115,80,9,171,177,196,38,252,19,138,252,29,242,231,74,93,205,161,41,158,79,204,211,0,30,248,42,125,237,167,151,3,163,35,219,102,225,38,80,160,246,91,202,15,81,5,104,108,210,239,193,131,146,27,150,17,171,71,221,84,112,204,146,94,186,237,255,206,118,141,107,20,169,226,15,43,75,224,52,120,186,0,134,235,166,30,237,98,31,139,146,29,104,64,56,3,249,66,92,147,217,211,9,31,96,178,69,148,227,230,101,236,243,45,246,172,39,229,59,69,106,63,147,212,148,179,217,10,220,19,61,36,147,54,173,248,250,238,79,181,163,211,105,11,79,136,249,56,91,202,219,147,180,212,42,140,52,110,222,216,92,215,61,213,55,188,33,239,190,201,255,96,1,215,85,244,86,49,152,17,180,172,68,196,115,71,107,182,243,219,136,48,23,116,210,242,8,233,123,235,101,169,61,55,63,1,51,205,161,189,96,59,52,218,197,250,26,88,73,52,217,104,199,216,234,189,209,12,232,29,210,128,20,244,127,219,15,204,123,222,84,167,249,54,43,174,28,118,186,210,116,176,58,78,38,166,130,144,219,92,43,91,180,1,195,20,39,139,0,25,240,204,75,61,178,95,199,10,3,136,139,50,249,155,86,95,70,214,41,166,76,132,6,166,146,35,118,145,100,203,149,154,211,215,94,104,5,44,83,183,45,251,89,212,57,197,144,82,87,170,120,45,105,80,129,100,131,159,10,127,221,163,246,63,192,154,53,205,6,127,117,223,24,147,216,93,28,239,163,214,221,158,12,149,255,83,88,41,136,165,138,1,254,6,44,25,143,22,104,150,94,24,196,25,238,193,216,170,71,103,76,33,52,211,45,205,235,134,41,248,86,65,9,32,255,32,95,30,250,243,251,43,119,170,184,85,107,38,21,98,231,54,218,226,16,72,174,6,221,38,211,120,221,119,117,120,67,209,251,33,84,155,163,163,47,53,96,15,51,76,204,87,153,85,170,54,66,113,12,174,34,104,136,90,62,76,103,210,150,82,37,200,148,44,89,113,229,33,173,240,114,61,21,131,193,157,216,181,193,207,219,29,42,99,21,186,158,11,145,155,4,216,22,244,162,245,120,63,128,57,117,241,213,60,251,251,149,87,153,99,63,22,75,81,103,103,239,199,225,110,110,88,38,125,240,116,161,226,53,38,183,2,223,68,221,87,205,73,201,187,129,82,39,35,166,109,116,96,250,15,15,242,104,227,86,21,140,48,172,188,54,214,185,33,4,199,217,220,218,185,44,244,170,133,64,135,231,135,80,159,130,65,112,36,250,209,241,226,74,174,130,199,202,217,218,87,161,162,130,254,242,150,34,63,117,178,224,76,211,80,201,111,72,69,137,93,62,24,23,249,115,80,83,95,17,166,84,223,132,120,6,53,34,199,208,205,80,109,133,213,92,49,18,214,230,123,245,73,80,228,94,106,241,165,216,84,255,96,177,178,90,92,5,219,185,153,238,208,136,79,150,15,232,139,179,52,146,235,158,62,239,136,154,45,92,190,176,19,91,40,214,152,149,209,222,247,97,175,74,250,98,231,204,211,233,2,168,136,18,202,254,144,196,95,80,187,220,123,31,164,176,207,23,248,81,3,174,138,206,65,83,36,29,70,32,71,21,227,157,254,228,2,4,215,71,27,252,9,219,49,49,23,248,163,43,170,192,126,75,198,97,91,38,182,93,204,141,250,187,145,128,158,103,88,73,178,191,233,253,231,3,169,38,117,163,181,44,217,91,138,15,239,82,140,19,78,13,168,212,227,46,202,225,130,28,150,211,105,239,25,243,208,76,174,52,37,170,87,125,141,221,90,95,41,51,53,205,112,75,54,129,102,51,87,222,28,117,188,154,174,103,66,55,95,247,97,127,31,107,22,117,195,115,97,108,19,52,70,179,212,190,15,8,213,49,139,119,170,201,169,8,199,203,166,183,90,134,185,169,133,135,9,251,66,104,187,220,182,164,82,21,125,132,197,116,14,169,241,211,104,107,169,17,246,140,46,235,236,23,84,93,180,72,214,10,39,185,197,170,73,30,43,35,75,114,202,126,143,2,127,114,206,107,25,116,183,11,43,3,146,183,121,214,79,26,240,70,203,45,88,74,11,137,245,21,38,44,66,143,61,168,69,76,204,92,186,121,203,15,46,213,237,131,23,220,68,52,188,111,185,48,81,35,208,159,218,44,76,71,236,152,61,103,92,247,136,123,88,196,109,213,91,97,190,88,164,237,171,59,217,231,230,51,149,191,114,162,41,91,249,249,25,109,183,231,25,48,30,35,44,156,199,26,146,144,26,85,40,82,54,83,253,102,88,29,52,114,160,176,0,95,4,217,205,123,143,97,62,149,15,178,195,166,156,183,183,170,183,54,232,197,211,241,7,215,241,86,159,151,161,98,116,91,139,14,111,22,41,155,5,43,72,245,246,20,196,27,62,112,149,21,253,42,111,173,148,25,42,199,41,53,84,169,17,246,92,25,211,161,41,159,252,62,243,4,19,121,43,66,199,74,28,208,193,205,33,126,84,173,30,16,26,179,244,95,188,90,6,16,178,251,191,203,121,130,161,12,52,170,24,14,141,2,163,190,6,52,205,187,57,245,252,9,53,65,132,246,126,90,3,26,54,238,222,74,237,35,163,214,83,43,254,139,112,244,74,15,241,20,255,217,117,129,81,233,181,187,160,29,30,245,145,199,163,29,171,87,228,222,50,229,60,139,23,152,179,33,23,124,180,100,223,209,21,191,93,240,166,209,66,67,28,158,237,190,62,80,188,131,151,72,22,159,212,121,139,49,254,184,106,134,122,77,103,165,81,70,69,174,0,7,179,26,152,234,23,37,155,212,120,59,223,226,216,189,170,9,42,206,10,123,140,130,214,229,149,218,74,215,152,151,235,170,53,33,209,190,193,105,61,182,108,226,176,32,213,78,117,106,23,56,121,61,82,213,107,121,107,114,185,20,99,151,57,44,105,153,238,174,24,192,241,254,251,80,193,143,221,0,58,227,109,190,129,185,22,131,37,221,129,34,101,144,152,33,250,198,183,73,236,69,174,215,68,64,181,94,33,132,40,149,248,252,133,191,99,245,130,21,43,49,211,224,204,33,169,240,230,120,107,228,46,140,168,241,32,17,95,48,147,101,16,176,251,83,160,253,105,171,56,79,198,139,36,48,144,120,99,236,171,235,56,117,196,171,178,244,170,61,79,183,32,202,66,50,130,211,99,78,199,73,255,242,30,138,199,156,129,107,187,182,255,144,201,230,138,199,111,154,10,126,232,144,99,117,187,160,97,221,177,191,5,239,139,181,240,32,249,247,61,216,207,154,217,224,246,49,118,3,194,107,197,233,3,242,99,182,58,45,151,176,238,101,118,57,44,123,195,112,61,129,140,199,98,25,86,104,2,141,220,161,128,109,32,8,89,147,249,11,246,14,255,195,81,233,46,89,37,122,225,211,69,132,120,138,169,254,0,72,208,116,247,244,60,55,28,135,15,11,28,174,65,40,253,148,181,6,57,220,134,224,205,255,225,22,228,49,200,228,182,179,141,237,217,9,47,114,203,57,24,173,236,15,100,174,120,178,73,84,236,141,45,188,142,252,66,85,56,248,161,247,21,240,209,145,198,24,158,227,106,158,18,248,204,21,1,99,35,91,187,157,228,98,106,35,231,158,103,53,119,135,62,168,207,48,5,118,236,117,255,204,65,60,49,102,180,55,82,149,17,205,214,182,198,223,77,55,234,99,156,29,161,90,22,138,7,126,240,213,226,110,63,214,97,71,161,203,216,10,31,25,62,71,223,163,238,97,14,115,144,121,112,103,4,186,16,66,51,105,110,65,111,32,206,82,213,231,74,107,199,255,85,48,249,19,123,45,142,3,104,77,86,181,99,8,158,50,3,108,43,23,113,246,189,180,107,134,24,9,137,36,178,9,176,197,63,33,63,164,220,217,243,175,16,197,210,28,16,109,192,143,193,240,252,44,124,8,108,179,168,171,135,107,32,216,49,136,123,109,133,33,176,167,185,189,30,120,210,5,211,14,127,118,199,147,121,246,58,33,239,172,251,87,223,152,144,13,169,216,65,87,59,132,210,118,116,30,68,72,68,155,103,230,81,33,26,21,82,14,73,251,183,147,86,222,194,97,44,169,244,82,155,95,253,205,116,91,165,44,64,31,163,242,253,93,23,26,209,14,33,97,62,148,115,63,247,111,137,13,9,163,215,243,223,218,10,114,82,195,219,233,24,117,167,173,231,13,156,77,46,231,130,200,122,169,91,49,229,215,250,140,73,229,240,44,212,41,117,112,31,126,218,196,58,241,101,147,26,195,148,98,153,198,104,87,90,149,128,60,239,177,50,49,11,242,239,230,196,182,89,101,80,215,168,143,70,48,53,53,215,22,99,194,129,245,128,163,40,102,25,14,99,189,152,35,135,13,16,105,137,188,32,226,246,176,38,30,36,65,146,145,240,83,103,2,107,133,21,172,41,239,28,250,134,170,228,80,43,122,211,87,111,228,168,29,171,79,69,62,152,18,69,203,96,169,144,83,50,37,65,208,1,113,46,2,67,73,221,2,181,73,185,209,20,163,237,141,222,221,69,220,155,12,177,239,150,84,234,58,111,225,3,31,187,110,139,78,139,234,186,202,73,72,34,125,59,43,206,220,68,6,49,123,14,147,144,206,60,95,31,173,236,244,239,64,11,119,89,226,7,117,175,218,115,104,165,195,209,202,140,132,15,6,115,213,209,69,238,7,89,37,249,156,158,67,124,208,100,194,232,148,52,214,125,166,99,224,152,46,109,187,234,230,51,60,189,191,120,28,13,67,152,105,230,40,147,153,215,16,149,231,51,170,159,88,97,228,216,161,34,87,65,129,153,213,186,140,150,104,113,164,25,120,246,58,78,221,124,33,179,135,7,220,233,68,9,15,123,101,187,131,139,95,177,234,29,215,24,57,107,53,194,252,161,247,70,224,245,22,104,10,41,39,213,190,186,249,159,32,28,196,55,153,225,205,18,72,227,70,120,101,199,237,132,225,10,124,88,154,151,215,153,67,177,100,244,99,169,37,127,97,122,188,216,217,79,187,227,87,69,243,42,139,151,228,79,141,154,88,240,7,29,255,165,129,150,70,173,212,207,194,245,243,54,210,111,168,77,71,140,61,28,64,106,8,196,60,68,154,18,110,22,252,63,172,163,34,138,138,105,145,101,244,110,11,75,95,244,220,224,140,191,243,85,79,137,128,246,173,146,28,1,68,146,131,190,104,107,105,10,183,141,149,204,59,176,190,91,3,180,254,33,47,24,58,4,53,177,211,193,103,6,161,57,156,191,177,108,76,83,185,133,20,167,103,26,75,148,54,239,124,182,71,95,160,157,60,112,22,149,136,53,82,150,241,250,192,35,199,124,207,79,66,84,131,7,63,140,114,16,166,158,30,0,73,131,202,144,116,46,50,92,60,23,147,147,14,236,195,64,128,205,63,248,146,1,49,182,30,96,166,149,196,243,131,88,93,119,167,118,22,137,56,179,169,223,194,48,235,4,196,19,7,210,55,75,235,92,247,15,83,174,53,132,172,34,214,91,205,147,70,34,195,103,132,175,68,245,7,227,205,122,160,7,72,137,123,51,243,8,7,82,113,179,53,171,249,151,156,75,82,204,101,194,53,247,2,201,39,125,151,8,4,189,190,40,95,41,72,181,116,99,58,100,136,118,164,13,191,107,164,69,39,229,204,2,248,254,87,112,64,247,106,105,66,193,73,104,67,75,181,248,105,39,227,153,139,164,41,215,76,244,118,95,99,56,13,94,20,67,33,205,238,108,249,81,105,60,177,18,155,229,73,173,205,78,164,144,180,161,191,210,203,150,190,16,55,228,110,203,212,118,15,103,25,67,152,199,2,36,17,117,201,129,88,197,112,153,188,44,58,196,160,131,198,150,19,223,209,224,90,127,231,71,1,40,82,195,12,242,223,233,211,68,210,32,176,1,106,119,179,211,33,221,107,210,194,227,213,88,3,122,19,130,145,199,16,66,179,41,215,40,18,133,40,191,25,49,31,101,27,16,11,60,119,20,186,217,168,204,250,28,173,159,38,166,106,2,35,49,133,30,16,174,41,134,5,154,247,72,247,171,23,225,89,228,141,14,221,122,56,188,54,252,90,121,252,169,8,168,27,59,138,8,245,70,122,230,65,165,140,117,136,206,11,169,209,146,240,8,234,87,27,21,119,136,227,84,138,65,172,42,227,109,202,167,67,219,148,125,32,179,242,176,224,42,235,163,145,195,63,145,122,135,21,164,85,133,249,38,87,145,90,3,151,203,189,99,172,189,248,86,207,193,226,138,44,42,179,190,99,83,127,92,185,32,159,58,246,239,241,246,235,227,205,219,169,42,77,149,0,212,210,172,47,174,68,122,133,7,78,152,86,30,65,58,84,65,40,113,125,213,150,112,146,1,46,218,175,242,206,243,3,22,233,246,135,129,96,57,130,15,151,104,91,220,169,42,107,34,44,14,229,23,97,55,219,134,96,213,252,133,227,120,195,1,46,17,86,212,120,130,91,248,166,233,51,66,254,106,183,117,42,44,36,169,196,204,173,91,96,109,228,171,28,189,45,250,183,121,167,12,164,164,245,225,177,164,170,138,139,161,93,90,83,85,26,198,104,106,203,108,131,144,196,153,22,188,229,99,101,228,68,84,115,35,112,19,129,18,184,189,228,220,191,206,106,106,126,188,176,42,150,208,166,249,215,76,49,78,167,49,137,16,206,210,203,31,206,130,158,233,143,12,168,123,152,246,181,110,5,9,143,33,8,20,72,188,117,52,80,18,200,90,101,236,228,207,56,241,5,217,53,40,86,180,67,214,216,113,227,232,42,4,123,161,29,225,131,69,60,164,193,158,200,54,177,14,32,137,153,25,110,144,200,246,156,194,61,16,88,79,24,113,181,5,133,88,82,165,176,38,251,156,45,231,111,141,37,120,107,195,254,51,23,243,143,18,30,92,222,216,31,27,168,49,204,158,75,50,29,108,173,189,227,162,147,5,233,159,187,189,71,11,14,221,15,68,223,60,234,186,227,182,193,229,131,242,98,115,34,126,30,59,20,56,101,249,9,38,148,110,79,181,179,181,29,240,61,110,204,161,242,160,184,30,38,49,180,136,78,22,156,1,249,192,217,132,67,3,250,243,132,141,231,10,84,231,97,122,73,28,88,116,105,213,193,202,47,183,216,19,80,71,55,14,123,32,194,193,121,208,234,113,73,234,146,93,189,196,164,129,140,201,122,187,60,67,10,121,125,17,246,192,134,16,58,220,3,66,88,63,127,197,206,164,85,151,11,143,43,109,35,215,25,113,90,99,90,205,22,209,122,41,112,244,206,253,59,161,241,168,251,89,190,186,151,193,3,142,219,1,102,68,147,87,145,74,157,223,203,18,248,51,21,219,92,9,251,196,149,82,153,103,27,151,252,54,21,4,47,205,56,172,183,3,29,202,225,83,16,70,15,21,227,219,225,178,248,157,53,135,57,185,163,37,123,167,126,80,187,41,181,17,191,207,228,71,37,158,205,118,62,248,250,194,59,71,214,167,103,233,25,73,205,178,231,128,78,53,113,28,73,140,86,87,88,87,238,196,137,77,234,138,39,195,39,117,89,71,3,123,115,108,182,175,148,180,142,193,159,155,141,71,168,172,98,136,187,112,36,25,146,98,217,160,17,34,77,55,98,189,208,173,74,117,181,200,124,182,123,12,56,62,149,214,75,112,112,107,126,242,224,85,234,235,172,131,250,233,229,99,14,92,194,36,21,156,167,172,215,243,141,214,57,79,177,104,94,207,160,8,3,102,237,50,84,126,223,147,92,211,221,196,52,130,24,176,159,132,65,156,131,71,126,4,33,143,91,104,28,50,153,209,95,181,28,75,113,70,67,27,109,192,39,174,135,252,172,218,211,94,160,62,199,154,79,251,16,22,195,15,22,140,253,36,242,85,72,147,22,121,33,25,195,83,123,67,179,160,66,85,146,45,114,228,93,116,57,55,217,212,216,31,50,167,229,242,19,107,240,57,124,255,142,191,249,148,74,39,163,43,156,151,201,207,220,46,185,27,203,141,137,15,92,5,101,198,159,181,2,84,128,42,9,10,185,221,175,55,128,247,131,98,98,146,152,8,240,110,121,15,67,233,2,21,145,83,105,182,127,239,100,153,185,165,225,124,59,119,26,175,192,81,4,98,42,93,184,200,34,68,13,134,123,5,43,164,167,218,32,67,79,70,4,196,254,131,50,201,157,133,80,79,208,242,155,224,237,252,110,27,249,238,45,235,77,229,182,93,205,123,32,5,3,78,154,69,213,117,216,130,198,46,105,47,78,76,255,250,230,254,99,106,218,110,21,186,185,71,173,236,91,67,119,59,38,141,202,223,39,183,153,239,2,113,168,121,123,54,217,55,237,94,11,1,190,38,16,170,216,147,239,88,254,229,245,220,108,102,247,55,229,237,173,167,179,231,185,82,226,109,53,81,87,15,55,217,69,204,109,3,164,126,143,193,42,141,227,90,36,226,83,128,215,12,177,216,190,140,85,129,225,224,25,74,141,225,41,192,131,60,180,130,169,191,124,58,1,135,224,63,27,9,138,244,124,167,199,35,2,120,62,25,218,238,78,254,29,125,60,19,72,168,31,194,52,28,70,137,193,242,203,2,91,43,138,248,5,135,204,165,116,67,10,198,121,98,100,238,143,43,94,209,39,162,232,129,176,41,254,158,40,195,167,51,206,48,151,123,55,64,65,233,220,176,238,73,3,129,139,129,242,194,88,95,199,147,187,75,237,229,171,30,89,115,154,239,165,169,235,59,98,63,177,91,115,84,142,203,97,103,79,66,2,91,157,207,14,45,246,75,211,46,69,228,42,158,158,132,228,178,36,163,98,194,69,11,37,186,217,155,206,244,54,125,9,122,128,237,37,159,232,91,68,159,92,116,153,244,199,136,214,88,171,186,117,98,60,171,163,232,45,147,151,123,170,237,130,250,83,244,253,125,237,248,178,237,111,15,63,154,122,147,51,15,60,204,111,139,245,231,228,185,51,36,176,237,79,48,4,150,130,163,59,120,29,126,54,40,104,116,142,238,121,237,189,107,191,35,8,119,113,131,109,108,173,24,9,142,108,8,49,51,202,146,192,173,17,1,241,218,187,124,164,246,139,220,70,143,192,138,152,227,175,189,77,209,86,106,63,119,2,159,194,2,163,89,30,119,83,127,152,98,60,123,145,96,155,67,36,124,94,20,93,243,98,219,253,143,238,124,45,39,226,10,242,116,227,184,129,242,21,192,51,94,97,231,64,148,237,211,59,177,198,10,216,238,62,4,109,230,168,9,132,240,215,0,86,29,251,174,78,233,243,27,50,92,197,253,214,2,123,146,246,222,140,146,148,108,237,15,4,222,247,156,154,132,10,40,151,8,10,70,114,132,181,145,136,176,233,7,169,57,111,204,90,220,67,215,132,40,150,216,152,69,54,80,43,171,67,46,100,140,33,185,115,58,154,35,242,247,6,43,31,174,39,80,101,216,73,40,132,227,201,14,85,37,194,50,3,146,118,78,76,36,211,88,24,220,98,14,33,120,148,222,160,20,160,118,195,167,167,92,128,37,5,53,38,72,206,146,123,57,213,135,200,109,71,35,239,160,169,225,222,136,217,153,92,67,165,51,105,189,47,203,155,237,217,9,216,232,29,225,177,49,205,230,232,177,124,66,19,114,207,198,114,64,45,161,124,66,110,85,157,81,102,32,22,83,53,111,196,27,133,196,169,162,223,120,126,235,105,163,132,221,206,150,110,214,226,227,26,172,30,160,193,251,235,130,209,125,165,77,58,39,115,187,196,165,24,148,33,237,15,73,76,51,191,88,212,165,137,89,220,47,35,108,174,114,48,214,113,39,163,180,185,63,88,233,112,0,120,241,137,168,24,63,138,54,82,207,177,179,66,101,46,177,222,3,52,49,103,68,5,246,78,182,234,55,35,29,9,19,192,144,78,132,224,162,148,96,89,62,61,109,6,178,98,241,196,88,167,22,196,56,11,139,35,94,112,213,134,206,158,24,179,145,144,24,250,44,149,253,67,210,8,0,244,166,243,0,180,234,155,46,191,122,41,93,142,70,154,56,201,66,159,207,162,193,63,26,46,204,221,206,29,100,232,161,225,87,106,130,47,154,66,253,50,33,4,103,71,134,239,65,137,220,222,90,200,221,145,253,16,73,125,66,213,113,239,82,209,96,85,98,196,87,143,30,250,24,217,92,120,23,123,71,64,51,243,204,192,239,147,75,30,170,32,161,187,95,176,78,235,9,173,103,112,9,93,39,55,89,66,223,135,55,158,58,28,249,4,53,46,175,138,48,65,135,70,136,1,162,20,77,236,103,41,150,88,60,162,162,221,75,62,108,114,118,100,40,120,101,241,122,160,0,109,225,54,161,239,188,6,149,136,139,198,177,179,32,43,126,52,149,57,217,226,136,215,201,55,32,213,229,87,28,109,36,223,42,151,98,71,107,140,255,230,206,183,84,127,109,108,57,226,37,11,140,188,250,216,82,32,241,186,122,68,173,128,81,29,57,2,23,81,10,233,198,238,113,91,11,7,17,184,180,159,230,116,147,143,120,21,24,1,220,118,49,16,80,204,12,78,41,111,117,193,98,56,148,193,219,160,156,230,56,126,1,172,183,95,204,229,202,75,218,108,245,33,254,8,58,127,98,209,197,176,100,60,110,139,133,80,43,42,133,200,12,216,121,186,89,171,171,252,220,132,121,46,180,75,79,8,157,91,112,112,34,247,193,147,132,119,236,30,223,101,129,132,197,45,134,84,202,92,249,70,208,211,158,206,209,216,202,106,106,96,1,80,249,182,103,247,124,85,169,42,212,67,245,112,214,156,147,143,216,186,202,197,119,5,230,23,226,199,79,150,253,252,85,1,193,145,96,212,15,165,73,246,244,50,249,165,95,254,252,112,62,100,237,167,234,181,238,164,135,224,175,19,225,82,153,135,122,209,81,59,123,165,21,127,99,54,56,18,153,226,205,161,95,202,7,79,126,124,92,208,244,46,5,176,227,206,200,16,140,97,250,131,187,54,34,117,52,52,206,150,201,200,182,45,201,225,80,46,100,113,199,193,12,116,224,253,59,85,244,248,161,239,199,164,208,63,114,103,163,167,185,246,203,19,33,102,53,236,108,3,205,170,155,230,73,204,142,178,233,7,187,171,191,137,254,60,149,218,98,40,42,87,10,3,146,207,162,67,113,25,173,141,27,217,143,225,97,164,2,208,116,57,181,180,112,233,183,114,62,110,197,29,79,155,213,7,115,94,60,229,43,83,79,119,171,196,20,78,239,233,51,87,6,32,5,59,166,121,176,193,0,2,145,150,183,130,7,36,179,159,57,212,66,179,111,151,174,27,202,58,35,12,121,174,29,17,69,244,46,87,1,173,238,194,40,107,180,147,157,209,184,241,104,251,123,242,164,42,31,93,118,82,79,189,47,105,102,158,30,210,164,16,47,140,226,212,235,70,176,78,30,247,193,162,137,19,102,181,9,248,156,29,149,41,73,2,34,88,183,198,106,254,34,124,19,150,32,99,71,253,14,190,121,107,200,168,38,114,205,153,112,139,204,16,149,101,168,127,70,40,156,157,78,179,113,220,4,46,194,124,96,187,139,83,36,28,169,50,209,88,176,134,217,219,55,18,186,165,170,11,175,60,216,24,132,95,218,101,75,194,66,64,184,1,56,29,86,92,86,243,122,204,124,185,21,219,37,111,68,82,178,41,69,127,186,121,223,219,84,41,169,105,54,165,5,128,102,12,67,130,217,46,97,233,254,216,57,121,145,39,46,34,136,82,175,114,153,215,16,119,138,116,45,137,136,230,59,132,221,97,0,150,250,153,211,18,141,254,212,157,9,45,217,191,16,24,133,130,194,151,189,230,92,187,55,12,247,187,8,115,13,29,222,207,59,92,230,24,146,39,165,2,54,188,107,162,190,178,185,22,188,187,172,42,164,239,225,92,55,26,237,230,59,0,75,13,33,47,250,12,161,72,4,185,159,244,163,208,129,102,176,239,178,99,211,97,92,241,234,19,85,70,42,189,55,130,151,119,38,50,126,239,231,40,153,124,51,220,63,234,208,163,211,170,63,37,231,40,152,183,204,90,227,246,208,8,196,85,209,243,92,102,174,199,27,110,145,27,1,158,35,176,107,152,163,227,75,21,184,120,238,57,155,201,3,194,165,57,117,211,136,236,17,128,98,177,93,111,46,94,137,155,5,70,101,212,42,190,79,218,62,143,123,151,171,59,185,175,9,185,245,254,235,130,177,69,252,61,157,29,229,105,128,229,192,180,37,158,214,254,13,129,64,53,209,247,56,140,241,97,250,119,174,250,204,68,97,184,208,29,20,117,25,12,105,234,224,76,223,115,197,177,7,235,247,19,42,20,85,78,15,81,181,192,153,4,160,176,82,106,67,212,194,132,240,190,45,126,79,192,122,42,28,239,165,14,139,14,152,62,129,78,48,66,45,207,97,240,165,178,129,234,169,234,59,12,218,46,249,54,76,20,225,254,11,128,237,242,61,101,16,36,207,202,13,244,205,77,104,204,51,50,1,5,95,211,151,110,251,255,185,191,151,167,102,140,98,163,129,27,38,60,101,197,176,252,212,232,136,208,157,118,51,83,111,209,188,223,78,130,47,24,91,236,170,159,121,55,3,202,0,155,212,180,173,74,37,161,201,91,108,166,174,27,239,60,20,65,158,225,185,85,89,127,76,244,27,86,150,160,201,13,106,79,143,68,200,236,55,107,243,76,149,215,188,118,183,198,159,26,140,136,153,211,173,159,16,57,139,31,93,149,70,6,141,53,112,164,6,184,239,106,159,222,67,158,26,121,136,223,39,46,140,67,170,202,95,88,179,214,186,212,140,8,12,94,34,77,226,17,17,162,210,225,20,151,177,74,9,100,126,170,73,142,33,144,154,131,151,205,235,28,118,190,6,137,98,50,237,7,94,230,246,133,250,179,160,199,89,103,9,203,111,37,216,185,171,40,117,6,107,87,133,165,172,22,140,220,186,41,97,187,57,196,102,220,15,169,194,254,170,33,237,69,78,127,4,30,119,51,251,153,50,179,106,153,232,131,96,100,243,32,78,78,223,191,150,158,39,30,201,43,12,220,233,103,223,247,156,210,213,52,75,203,102,114,46,35,81,55,175,89,207,53,66,198,247,164,132,51,64,124,120,125,108,35,3,184,185,202,162,122,93,58,198,11,176,146,221,62,6,92,250,135,230,38,135,125,76,89,22,140,243,110,14,212,252,94,85,234,86,142,168,158,28,94,124,183,180,213,174,80,170,142,88,83,48,201,169,249,109,156,83,4,161,186,46,235,85,83,86,244,7,52,58,188,19,124,117,35,105,13,185,191,47,252,142,77,194,147,27,235,193,126,138,65,32,134,118,24,227,33,219,142,48,59,235,147,8,183,94,74,184,233,4,78,44,55,20,167,190,216,145,187,105,253,135,93,68,15,204,76,81,176,255,140,229,106,248,29,154,109,79,247,240,181,62,181,2,28,187,26,136,254,180,92,158,140,81,194,11,245,237,48,28,57,112,87,48,233,185,13,251,113,29,199,152,222,226,254,232,119,199,120,251,113,224,226,89,162,215,74,115,227,118,145,197,176,156,161,226,233,79,170,203,163,113,106,144,108,25,85,163,91,129,143,75,216,56,51,156,13,106,116,79,121,79,152,139,128,156,169,174,94,228,172,49,115,235,134,42,145,67,107,214,122,8,49,156,210,218,178,151,67,247,169,0,56,164,44,222,132,125,193,90,153,10,15,29,69,159,229,98,193,181,138,65,215,14,65,89,116,209,247,174,22,72,27,141,214,94,36,169,203,34,123,25,192,248,196,238,148,225,225,253,59,44,43,96,2,26,21,96,123,202,184,253,55,162,172,81,29,95,172,11,133,235,129,224,183,94,71,85,29,23,65,246,242,222,224,109,136,62,63,145,107,248,167,160,195,242,204,135,237,253,107,53,91,77,34,207,186,102,102,84,28,14,44,194,39,232,156,245,132,232,76,102,63,206,240,49,132,118,211,1,70,75,30,42,3,149,207,174,223,160,227,64,221,207,62,64,74,186,97,163,201,85,231,33,84,76,132,47,66,189,73,137,21,77,184,234,168,231,171,247,76,32,229,1,138,186,116,5,60,65,8,57,133,57,165,125,190,51,105,242,89,1,141,234,53,168,34,89,88,55,63,52,10,226,116,30,115,175,214,74,234,133,248,48,242,17,47,155,75,131,130,124,207,192,199,156,142,142,119,122,3,15,49,119,155,82,80,171,180,19,29,133,31,247,222,9,245,206,244,22,69,12,85,112,250,23,97,212,191,32,152,5,115,206,31,197,19,250,138,219,130,3,84,216,78,11,80,213,13,161,199,128,136,64,7,53,223,221,247,108,10,139,128,47,36,225,149,145,94,106,22,86,14,62,13,43,181,226,188,243,228,218,231,144,137,51,46,13,237,21,72,193,233,132,28,220,20,8,4,122,72,237,253,246,222,239,176,0,105,79,66,248,100,211,232,18,217,109,127,11,57,83,34,123,20,60,137,153,193,152,195,96,127,130,205,193,250,201,146,44,174,91,40,108,105,104,231,248,136,114,61,136,124,241,31,128,186,165,230,218,248,76,54,35,51,13,80,241,46,59,34,214,111,253,168,149,252,124,4,81,171,131,110,58,165,172,223,166,5,45,240,154,11,195,26,117,137,238,192,41,98,219,74,113,235,25,234,46,9,144,57,228,196,138,122,230,73,229,42,31,24,18,166,217,131,24,95,177,251,18,240,249,10,235,122,112,16,73,162,6,70,8,231,108,54,87,216,194,174,60,128,244,234,190,212,213,146,128,244,187,133,74,29,128,195,60,234,120,57,168,116,97,234,156,164,173,42,225,70,177,38,184,43,121,148,186,19,207,224,19,253,214,102,184,227,77,205,223,63,242,184,142,75,134,48,96,96,243,151,83,50,87,123,186,147,177,176,62,113,237,99,50,108,201,126,185,218,219,219,241,171,55,44,28,194,49,254,72,63,140,63,178,112,216,15,3,183,189,172,230,154,116,254,246,200,73,82,76,41,15,168,132,147,25,115,46,90,151,15,180,193,60,237,178,105,74,47,191,86,59,221,105,248,98,26,140,49,149,76,146,83,229,173,71,134,78,113,171,186,136,69,240,102,228,167,251,86,198,107,167,79,180,215,210,44,58,98,143,79,188,44,133,107,54,248,165,231,104,149,127,120,62,61,159,252,239,41,101,177,140,108,77,90,49,230,151,125,115,153,80,213,191,17,98,59,202,149,108,239,233,23,177,26,245,216,97,198,111,31,75,248,67,177,55,207,157,212,233,20,69,111,167,232,80,21,144,9,32,199,43,200,181,141,195,9,143,237,154,121,175,158,247,124,39,117,184,48,30,51,103,4,19,16,28,84,98,72,251,204,19,32,194,90,236,170,52,202,181,96,92,120,59,184,47,169,66,177,66,217,150,2,50,182,17,7,131,32,76,227,116,70,174,42,90,163,89,35,33,148,41,240,228,253,31,107,201,210,198,152,13,86,70,112,248,225,121,155,252,134,99,239,2,8,98,108,44,76,227,160,213,104,141,16,130,205,118,253,123,220,48,200,187,80,35,114,62,45,188,107,29,79,220,169,244,147,158,70,102,122,231,232,149,243,55,230,115,28,185,83,39,179,237,221,41,170,240,44,143,39,216,163,87,213,39,157,118,225,99,80,190,57,171,200,20,2,7,166,112,211,127,0,69,167,84,159,62,190,37,46,1,194,192,152,94,188,50,203,38,220,128,2,108,156,32,255,174,254,89,135,44,97,26,237,37,203,70,32,238,3,218,163,213,145,32,244,50,67,233,217,30,131,135,205,0,46,29,143,192,99,180,144,34,96,7,74,212,164,44,215,190,88,252,138,84,97,50,251,203,44,252,175,247,178,155,79,180,28,8,80,184,205,211,9,119,150,32,91,150,4,102,212,89,217,117,71,241,163,146,90,113,142,34,228,139,182,236,101,97,47,152,88,91,161,47,37,246,4,92,89,174,210,15,82,44,118,249,82,198,192,155,172,220,91,168,190,233,35,204,84,24,113,139,102,112,42,108,124,19,27,148,60,159,78,38,239,90,234,5,193,172,28,58,20,182,11,43,162,123,82,184,178,167,19,172,101,106,3,69,146,204,136,46,70,35,133,166,103,74,245,222,246,76,109,232,173,160,36,50,39,140,112,227,59,10,18,127,30,232,161,113,146,233,102,248,171,205,245,154,98,101,53,109,65,36,82,31,241,200,111,216,27,255,10,48,237,213,82,221,17,250,248,215,19,150,56,175,233,19,230,30,233,199,3,100,121,176,189,175,63,20,231,105,113,121,51,88,188,231,109,177,58,34,9,199,121,226,157,183,76,219,41,224,204,61,144,124,88,115,7,214,74,179,178,42,119,144,76,98,58,171,185,134,98,123,177,87,100,213,183,165,147,22,29,151,19,74,146,102,107,158,201,189,0,79,185,36,105,84,104,73,152,103,132,228,196,39,102,113,158,255,56,212,198,37,172,139,31,238,98,184,182,42,69,108,194,245,23,205,45,21,76,115,162,181,174,59,213,233,59,240,184,32,212,226,199,126,11,205,232,217,187,51,197,98,94,117,94,105,152,41,48,22,181,8,146,134,207,30,237,255,240,248,183,191,187,67,210,16,185,191,54,193,2,218,22,99,176,191,233,78,247,165,4,231,131,62,37,109,244,76,194,155,129,212,66,0,101,223,162,211,13,80,169,217,16,68,4,155,216,61,35,76,162,144,217,34,209,73,249,250,253,186,140,124,41,237,124,22,168,97,40,95,47,38,188,204,216,150,184,229,185,174,113,3,154,126,238,50,165,170,12,27,209,53,157,76,118,81,252,10,140,31,103,160,43,171,6,65,205,225,154,85,121,76,216,228,29,241,184,200,160,225,86,4,199,137,80,222,199,30,9,163,177,222,131,91,24,3,147,148,250,20,157,246,166,73,41,246,240,159,85,53,172,227,255,239,211,188,78,85,210,198,63,175,149,47,251,126,139,167,245,143,5,212,41,111,52,133,173,37,114,122,63,214,212,6,98,213,169,140,241,226,233,95,47,169,91,89,117,116,228,30,78,123,163,137,11,19,142,70,121,166,215,141,20,57,100,202,75,131,150,222,136,204,79,199,205,220,46,9,129,92,116,55,148,224,138,82,32,255,250,251,59,239,99,130,13,77,106,233,191,37,70,164,141,160,195,95,192,54,39,178,189,46,17,135,160,255,198,62,249,69,57,5,74,22,165,134,209,143,179,8,28,219,212,141,148,242,233,231,171,234,72,186,111,252,84,120,130,253,206,225,145,123,88,19,194,150,24,168,247,191,92,162,203,56,94,55,72,199,142,76,50,37,253,13,142,159,201,100,153,149,243,217,240,192,204,254,66,239,13,23,161,166,210,210,120,35,7,141,179,109,83,57,146,163,16,195,195,129,214,39,34,155,158,29,244,128,143,18,233,121,150,87,80,227,145,22,207,133,15,10,172,79,48,176,209,68,66,116,22,167,251,162,90,108,98,148,98,84,46,164,185,106,48,68,247,163,112,24,15,78,105,58,173,251,63,10,252,91,83,158,57,178,63,21,40,113,231,82,251,191,134,27,71,131,203,150,222,121,48,211,181,0,62,91,119,123,77,252,183,63,204,142,239,211,87,244,129,213,2,81,221,210,104,182,252,35,116,91,198,172,132,76,148,89,3,74,8,96,232,19,70,18,232,128,18,145,133,229,23,13,93,175,174,68,105,55,192,81,168,1,142,132,193,37,99,188,243,51,14,26,6,195,29,149,159,115,77,169,235,22,66,101,37,224,43,146,152,141,191,222,67,12,74,51,124,129,141,11,37,97,10,50,79,112,123,54,180,89,156,10,237,145,90,99,35,116,84,163,249,196,70,103,144,16,14,13,233,42,5,213,163,203,205,92,6,212,210,195,46,141,24,15,1,215,71,30,31,0,4,24,15,93,217,35,228,173,104,78,117,69,140,243,168,119,62,223,200,171,123,57,184,88,64,53,21,153,201,0,115,146,22,119,84,228,16,189,124,213,148,92,15,178,58,83,69,87,213,137,150,254,92,197,211,157,193,255,150,115,3,222,48,64,41,28,208,245,211,29,135,30,54,205,250,93,94,57,155,196,37,151,90,109,165,11,249,203,106,37,64,103,100,206,108,40,181,36,238,104,208,241,13,26,75,32,133,101,47,132,226,199,174,3,139,186,102,206,19,21,6,166,44,184,63,7,255,61,155,90,233,60,161,86,176,23,97,194,237,176,234,251,116,25,226,11,145,130,13,179,158,222,252,26,235,132,202,117,229,195,232,158,52,183,96,47,219,235,210,51,146,103,15,241,22,194,84,73,169,183,142,81,87,203,6,251,105,254,2,56,164,156,137,219,71,205,59,144,217,70,38,73,57,73,70,131,114,20,249,181,50,184,200,127,251,28,30,92,166,20,252,156,141,128,223,214,176,136,154,210,238,245,131,123,1,114,106,160,197,74,57,4,101,162,185,66,93,219,192,225,68,181,231,74,140,180,121,162,114,142,129,187,73,66,192,218,128,28,39,134,251,0,243,48,55,112,205,204,80,144,149,109,100,247,179,224,228,198,89,225,7,131,170,203,32,130,21,23,249,122,134,208,160,239,23,10,91,107,175,27,56,59,104,18,71,209,245,4,165,227,203,178,69,1,114,130,119,193,171,64,18,182,174,155,16,84,193,55,150,153,90,251,6,94,161,253,223,200,143,16,162,175,93,211,88,243,61,118,144,204,158,163,68,183,243,85,64,42,52,155,32,39,213,93,165,239,188,8,152,93,228,136,71,213,103,158,57,252,54,203,34,230,180,127,56,46,22,5,220,190,103,131,16,64,135,114,68,112,125,205,54,108,113,157,5,31,108,20,138,80,149,170,6,114,65,223,21,159,246,115,158,118,220,203,106,20,66,204,213,59,225,109,136,122,206,137,104,126,66,24,195,83,223,112,36,241,154,219,254,255,248,77,142,202,95,86,171,11,42,188,7,245,217,138,49,224,34,61,121,28,57,25,3,70,9,40,108,107,108,211,160,206,154,77,59,153,161,172,200,23,84,154,131,94,122,115,145,19,13,234,127,86,154,80,149,41,50,98,186,251,36,10,53,159,223,103,104,248,67,154,136,228,46,83,243,36,33,221,157,116,83,109,54,89,171,46,252,120,86,50,220,23,252,185,68,192,125,37,223,233,232,110,16,135,71,175,199,37,75,162,17,48,41,32,39,131,59,145,161,20,26,149,216,99,1,188,240,87,189,8,24,224,227,175,207,156,151,37,76,105,62,202,86,172,9,208,0,186,72,213,78,103,254,132,192,92,113,242,42,224,245,111,181,206,107,130,182,212,63,185,27,28,41,112,220,209,148,172,7,140,225,168,124,67,203,73,76,139,41,226,87,30,125,197,216,76,36,160,168,194,202,181,254,134,0,148,187,242,94,239,72,9,21,148,168,92,66,161,144,73,37,106,39,176,127,116,44,183,89,77,47,138,171,10,169,117,147,107,92,29,184,69,82,220,13,130,34,214,197,214,6,152,46,180,228,77,211,162,47,149,169,145,56,196,174,84,97,93,246,216,30,34,211,137,93,8,161,64,73,106,220,60,107,201,86,86,124,51,9,66,244,168,8,22,125,147,200,68,23,23,247,75,139,87,52,54,5,53,175,14,218,127,126,196,104,220,88,75,122,52,99,226,111,88,137,95,199,196,6,2,87,182,200,67,133,205,210,73,174,53,64,12,134,84,182,73,199,7,65,88,7,24,83,187,31,81,35,236,229,37,177,78,42,143,233,94,241,133,195,255,185,7,218,41,43,231,129,3,23,175,147,37,26,188,70,161,146,126,24,12,38,104,96,209,143,227,254,9,198,24,192,4,227,59,174,32,240,251,5,34,127,186,184,83,193,62,41,187,33,39,239,28,16,118,164,36,171,230,136,212,122,52,86,39,165,85,61,117,145,179,83,209,229,95,227,85,170,136,187,59,115,217,179,60,48,21,67,116,58,14,145,89,89,35,229,5,152,217,138,26,10,189,186,35,83,210,174,165,179,87,168,247,177,43,213,204,247,37,109,164,15,182,108,253,170,140,83,214,151,0,211,81,132,64,43,30,248,18,149,11,44,248,98,107,216,117,38,96,167,82,124,152,140,191,51,40,145,207,31,45,189,144,120,151,236,172,94,196,233,80,172,227,217,187,197,174,24,108,153,189,212,51,44,156,203,149,74,222,95,240,202,168,235,255,91,215,29,201,254,8,156,120,134,162,218,172,153,51,254,189,4,238,93,65,227,158,247,6,74,254,126,91,58,204,84,167,188,223,91,180,79,147,62,150,135,231,158,186,185,126,91,13,115,56,108,78,17,205,175,102,47,20,157,73,175,89,225,242,141,119,215,191,236,127,186,252,109,87,164,233,22,213,98,137,134,97,78,12,13,150,30,160,164,149,154,108,167,156,104,67,228,187,152,143,135,114,154,47,7,21,89,131,179,34,253,135,40,109,220,0,127,213,82,85,64,161,1,113,242,240,66,56,78,225,32,59,26,177,12,19,79,6,212,120,217,177,7,187,76,85,122,133,9,219,81,118,109,201,21,119,47,122,30,190,208,241,78,63,16,91,45,44,253,13,228,18,228,187,96,222,132,166,77,100,226,124,234,61,59,174,40,117,26,163,5,65,107,1,95,18,170,126,100,95,216,113,98,15,186,246,133,3,205,221,228,159,206,212,201,240,175,113,198,72,187,233,28,104,253,239,168,246,139,120,149,143,34,146,39,220,145,216,114,243,109,219,151,117,75,33,162,197,181,62,19,128,118,215,96,101,54,68,109,7,171,133,54,145,1,15,56,224,58,123,172,196,221,3,133,158,85,120,21,246,153,166,1,17,66,48,223,247,230,95,15,223,253,250,109,197,6,190,76,117,7,245,185,143,129,188,191,215,198,20,90,194,172,250,78,233,102,182,120,92,116,208,65,80,84,235,77,57,207,221,127,16,225,96,218,22,104,216,138,195,220,101,236,3,109,87,42,198,95,96,164,202,48,107,45,17,107,246,2,243,229,149,152,83,101,228,91,80,183,254,119,138,201,64,197,135,212,15,171,151,44,69,249,208,188,57,253,250,157,63,153,226,131,155,3,224,56,103,144,28,200,229,192,71,131,21,129,219,235,31,205,144,191,146,253,77,67,78,216,241,242,228,244,174,123,254,65,212,26,35,218,100,1,28,145,247,37,254,116,206,212,40,200,241,209,30,238,181,165,198,211,144,87,158,142,226,70,232,172,134,42,41,121,222,108,17,68,45,47,16,56,26,77,188,99,188,115,118,252,245,11,51,25,44,27,128,31,32,221,54,158,109,102,53,155,4,245,73,26,234,174,198,111,64,52,171,213,56,173,114,145,152,204,191,140,179,22,93,211,35,243,221,136,103,201,155,0,41,110,183,62,30,176,252,190,108,47,23,203,166,160,173,17,124,11,189,244,44,4,13,133,74,224,19,240,200,254,27,57,180,193,89,67,10,147,117,127,169,109,96,98,8,10,21,26,37,181,81,247,202,60,172,58,139,237,116,143,140,46,52,176,49,71,231,243,80,161,14,219,152,25,62,178,232,150,162,47,124,122,155,221,61,212,160,224,158,136,39,24,24,159,93,108,6,145,49,245,189,95,22,153,45,100,83,225,12,97,201,53,242,6,2,23,210,62,108,106,189,178,189,42,64,247,93,171,233,157,196,159,103,239,240,111,60,164,43,151,83,198,183,204,37,185,207,113,120,130,103,10,4,90,144,149,54,51,128,82,233,108,119,172,85,82,79,203,25,184,22,113,202,100,46,34,121,95,234,102,43,243,242,211,223,171,133,152,188,18,134,67,47,2,94,11,17,249,254,0,115,150,132,37,136,76,84,42,91,153,219,138,4,233,91,164,1,243,162,12,134,75,244,55,138,40,252,182,74,245,239,39,45,157,106,56,118,130,15,190,210,138,155,237,239,57,182,77,69,190,113,237,27,178,173,214,149,95,133,12,106,208,89,63,129,174,51,58,43,142,103,103,138,109,123,39,101,45,171,1,233,54,34,208,63,121,151,241,39,0,207,133,172,100,150,134,5,196,133,184,171,253,201,139,186,75,242,123,53,174,38,249,95,72,254,64,108,209,147,37,177,166,69,3,178,95,255,47,41,195,232,6,73,119,89,203,225,150,80,125,183,56,28,82,112,89,167,237,204,73,139,208,233,7,168,90,35,244,133,50,216,254,240,80,227,187,102,135,27,213,192,201,21,175,236,199,100,103,36,247,192,4,133,40,125,16,111,25,177,101,37,180,170,49,230,106,169,123,73,58,231,60,106,230,145,116,211,215,134,199,90,18,243,210,29,225,79,224,248,108,204,147,215,73,244,75,154,145,95,137,151,193,154,146,43,242,175,5,62,42,113,9,57,70,59,133,75,165,250,154,186,143,167,22,47,252,137,102,87,181,104,147,207,195,205,88,18,48,209,126,182,35,179,10,30,175,25,163,6,202,85,185,99,52,208,20,19,242,169,14,253,227,198,85,129,68,11,99,112,59,79,142,105,188,254,123,148,88,153,70,89,84,106,236,34,181,241,51,194,138,62,14,134,245,151,117,235,135,10,139,140,204,146,196,96,242,114,217,131,102,142,129,65,132,108,64,29,42,233,238,33,19,249,17,222,195,125,158,124,202,110,18,183,150,111,199,70,127,8,180,135,203,33,143,230,228,90,44,43,118,241,57,168,162,89,150,106,102,32,60,250,93,143,196,239,12,214,171,73,180,196,199,210,115,112,192,13,9,123,222,213,148,91,19,101,236,101,30,146,43,164,10,156,101,112,151,65,89,151,245,154,56,37,194,99,153,35,80,3,93,62,246,6,68,42,34,155,207,230,215,121,37,213,153,36,165,136,123,181,144,31,215,138,161,118,151,196,108,131,138,93,13,158,182,138,197,184,0,44,139,70,0,204,15,179,245,235,111,229,61,119,1,248,135,70,169,50,116,69,16,223,77,223,248,176,81,63,205,104,150,100,178,216,215,7,243,251,58,16,117,59,213,117,122,156,183,0,72,126,132,100,86,92,240,106,174,220,88,51,75,166,111,176,139,229,215,30,173,166,246,249,201,187,24,250,69,150,214,224,9,17,218,53,173,213,254,11,60,19,32,202,124,40,131,51,99,223,226,217,190,252,29,14,39,73,199,37,180,254,114,46,169,46,109,205,172,86,62,198,113,209,186,149,211,122,42,239,238,71,133,33,39,217,86,131,68,199,243,26,0,143,97,215,140,217,34,11,55,192,118,66,69,203,200,128,171,40,250,94,127,204,76,168,232,153,226,37,150,4,8,22,177,75,64,204,39,19,45,127,173,174,14,222,159,184,66,88,61,250,133,231,114,166,164,33,157,77,203,31,222,189,111,131,178,107,117,10,165,203,18,211,117,188,134,254,238,158,123,143,231,245,189,89,21,88,66,169,241,24,26,210,108,105,249,56,37,196,36,26,110,237,31,34,198,114,72,218,133,14,40,38,0,26,218,130,56,146,228,86,253,43,36,112,162,58,232,178,162,105,114,186,74,187,229,215,195,101,241,14,24,95,246,248,101,255,68,164,79,41,18,245,65,11,228,167,132,169,52,170,196,91,52,224,204,230,105,193,231,254,49,143,85,42,221,140,233,18,131,116,86,127,103,136,113,15,23,95,39,90,226,59,168,56,73,43,227,171,60,251,5,66,24,207,129,225,168,127,243,190,108,173,215,76,110,107,75,120,242,147,252,217,57,234,116,1,133,221,90,162,174,126,61,236,200,53,105,71,155,217,56,85,6,214,13,60,119,234,225,200,186,152,215,237,225,105,85,252,240,252,38,75,220,200,6,243,144,34,127,161,14,197,107,63,75,235,195,72,44,27,244,129,243,201,59,241,45,173,62,200,145,232,76,142,208,183,15,77,119,157,26,157,170,159,104,206,13,248,132,68,229,234,196,252,168,229,154,203,44,177,54,200,235,132,93,52,10,196,60,152,226,220,27,98,85,215,82,144,161,12,76,202,47,71,231,225,223,105,35,201,195,174,188,10,168,199,141,255,108,74,166,226,33,4,203,54,202,178,27,127,250,86,181,225,246,70,219,65,173,49,214,202,71,22,67,184,54,90,182,251,202,40,14,235,63,201,190,75,65,15,33,62,81,56,157,55,187,67,3,223,5,188,105,211,72,202,95,229,207,20,1,219,121,116,56,5,116,227,97,48,200,192,252,86,238,56,125,89,89,89,100,76,5,180,81,31,33,111,202,211,182,51,25,81,28,239,153,125,85,67,149,136,118,157,65,84,65,43,74,86,81,238,45,7,227,222,145,234,95,152,157,225,22,53,47,59,189,252,16,40,26,171,155,247,98,73,206,206,218,9,241,152,213,3,15,107,123,100,86,78,2,200,194,8,78,101,235,150,113,69,232,13,102,131,200,41,240,126,186,238,184,20,62,218,235,221,116,53,44,20,219,104,254,112,139,81,119,100,253,105,53,62,247,159,166,75,128,64,51,7,193,108,154,115,34,146,127,75,102,17,112,81,35,33,255,104,228,11,97,24,252,219,214,122,235,2,28,34,128,252,220,126,248,87,48,200,149,102,191,135,59,48,111,142,210,22,87,41,25,209,90,114,67,98,234,128,53,45,198,155,116,161,66,14,216,226,63,200,18,7,20,213,60,221,77,128,48,20,142,208,197,61,210,161,90,77,80,146,220,80,168,29,93,171,234,195,182,134,136,225,120,206,94,147,141,52,199,5,155,74,143,12,252,50,79,254,135,78,145,222,143,150,128,28,137,206,79,88,83,195,0,213,182,223,225,201,191,235,235,39,175,202,211,139,11,109,8,255,251,237,232,33,37,250,169,184,42,115,205,55,220,211,160,190,225,201,208,87,227,181,15,92,123,111,172,104,71,23,236,206,214,177,119,77,128,149,238,102,224,147,48,143,82,158,83,179,110,112,12,75,86,190,48,208,14,156,92,140,55,64,14,23,106,204,140,48,97,72,62,247,14,217,121,31,224,171,233,69,177,129,185,71,17,87,96,138,78,19,178,198,229,37,235,51,51,208,149,100,111,39,54,197,126,215,245,125,0,18,64,157,246,4,183,62,21,82,209,182,193,74,163,255,99,143,38,119,30,171,116,62,129,241,64,167,205,128,48,19,141,208,126,96,231,17,94,11,123,106,132,252,127,95,4,217,84,100,231,9,56,144,178,55,92,107,154,194,164,113,19,93,117,152,188,49,241,135,95,131,177,63,10,247,179,86,47,153,63,125,70,239,205,3,48,196,135,152,123,146,5,229,21,112,255,72,4,180,42,148,238,234,211,163,111,223,49,176,36,101,182,121,145,65,242,151,27,181,100,235,212,127,238,78,165,2,36,188,117,89,217,137,39,32,249,156,72,106,48,65,177,35,119,166,109,125,93,15,74,133,194,177,8,208,79,4,23,216,37,3,20,67,12,40,52,11,160,213,96,177,234,40,240,251,19,126,81,186,153,249,204,11,91,78,70,238,38,31,243,13,156,49,165,95,148,218,155,179,139,30,216,15,153,27,164,59,189,173,159,141,146,16,21,167,183,161,203,82,140,66,150,182,16,73,40,176,102,55,118,132,173,249,137,117,137,145,90,53,86,164,24,152,171,14,64,192,181,253,238,22,204,59,115,228,173,155,232,15,108,250,14,135,190,177,25,54,114,152,83,38,132,125,185,243,134,112,168,170,99,100,155,125,107,46,165,146,10,12,243,170,39,155,195,220,140,129,9,27,178,166,144,112,200,134,3,146,228,27,60,217,251,147,93,72,56,196,158,217,177,53,113,146,111,93,172,7,71,165,196,105,120,164,255,79,158,235,183,45,61,139,128,87,87,24,202,89,236,50,129,135,90,217,225,115,211,102,32,22,124,87,167,76,209,47,193,179,5,176,1,172,115,53,235,4,198,69,17,146,1,156,60,169,171,3,154,137,1,8,160,180,39,33,145,194,221,167,74,225,147,22,226,175,161,190,155,99,104,36,234,28,206,255,153,106,146,140,248,208,160,159,129,189,81,79,151,34,57,191,19,60,238,132,173,126,112,102,40,167,236,248,169,15,165,62,167,248,117,241,242,52,190,179,82,62,174,253,135,166,242,116,101,164,25,44,212,205,199,182,51,26,85,54,11,16,243,103,183,145,84,222,115,193,84,191,14,243,49,214,76,187,20,39,29,243,173,156,181,219,109,64,24,75,52,179,28,160,231,99,85,33,44,165,96,91,1,116,151,203,247,43,74,128,179,172,198,31,77,89,11,160,120,13,159,140,72,217,110,79,78,206,233,178,98,50,152,74,216,73,133,249,217,70,75,56,129,241,107,234,100,37,103,60,16,188,2,190,11,70,104,226,153,93,247,153,143,161,19,20,220,168,207,59,231,145,117,83,136,104,18,107,25,84,26,105,116,169,98,24,122,32,236,228,193,206,223,235,29,238,49,143,225,2,196,58,61,127,140,102,14,140,100,86,158,130,245,106,213,21,195,130,77,170,38,87,189,28,239,43,9,141,221,172,71,101,23,117,196,97,176,152,245,228,11,197,252,84,206,70,36,202,196,205,27,80,137,39,25,75,180,73,162,224,150,97,44,115,24,151,153,239,190,250,64,81,124,193,49,199,158,225,239,216,251,150,194,11,43,136,66,171,93,122,163,101,50,248,76,30,251,201,114,80,75,69,109,212,155,11,141,217,118,95,15,127,174,149,147,216,251,178,89,253,92,51,157,16,128,60,144,26,219,47,131,125,182,76,241,164,209,6,26,7,92,85,220,173,245,230,208,98,209,124,70,173,192,190,132,55,211,201,186,183,60,108,73,202,134,11,25,98,22,219,173,173,140,39,222,243,91,17,177,81,168,144,244,94,105,34,211,227,16,134,9,254,20,51,4,182,243,203,82,63,238,89,246,230,147,185,200,52,129,113,141,167,177,99,18,247,119,52,84,13,203,187,89,98,35,178,30,13,149,205,77,136,197,164,183,202,225,132,158,34,253,166,180,170,81,56,53,16,116,34,149,120,212,66,17,226,5,193,175,148,81,251,230,23,177,141,43,79,103,153,84,172,51,44,242,34,237,188,74,225,118,144,129,40,56,96,157,254,134,231,14,209,110,23,26,41,253,29,33,247,80,149,196,100,34,23,183,198,124,246,191,174,56,254,31,119,127,229,154,236,190,38,98,101,91,126,182,201,156,27,210,62,101,17,18,95,17,62,112,173,218,95,8,203,29,169,3,23,137,111,219,234,54,156,50,148,31,227,60,56,205,74,105,149,45,57,162,39,83,232,38,150,169,204,161,15,212,82,220,124,196,127,1,123,135,186,208,13,210,224,127,223,143,131,107,123,201,10,21,58,99,135,64,212,81,242,174,16,20,198,65,72,42,58,79,59,206,26,52,133,57,223,232,6,119,87,13,47,214,82,42,153,242,77,203,163,205,22,188,0,129,78,179,114,86,63,119,183,248,180,74,200,49,174,239,118,170,130,129,69,61,251,182,192,219,239,214,192,255,58,247,26,49,105,232,74,79,103,145,214,114,231,134,233,230,182,242,244,118,246,117,136,107,207,19,107,184,247,251,123,157,189,96,101,189,162,223,179,99,10,86,165,128,163,231,16,244,57,68,233,20,250,104,28,166,38,49,110,177,66,17,127,187,199,42,122,137,238,193,107,95,247,227,189,113,10,75,176,213,70,136,141,144,164,87,37,42,23,127,141,164,183,78,139,218,128,235,216,244,18,237,172,200,24,113,21,112,117,16,59,41,136,9,155,210,169,170,75,221,91,65,24,147,102,178,110,106,220,193,124,222,37,240,191,119,132,54,85,182,115,221,35,234,48,168,174,45,235,227,126,189,190,94,228,240,101,211,112,91,127,57,151,48,255,55,129,17,139,254,252,80,114,75,182,22,51,188,91,109,69,192,230,36,179,138,232,162,3,131,1,137,52,56,241,139,77,224,236,177,175,210,192,80,187,135,105,224,116,81,229,132,151,223,232,67,207,191,76,55,255,26,58,42,239,48,161,0,251,40,166,214,231,173,40,122,99,165,8,170,84,14,152,38,0,60,172,198,70,127,95,75,16,127,6,6,164,64,141,172,238,59,222,131,224,43,38,141,127,96,100,62,2,30,34,180,54,230,3,150,5,231,193,31,96,61,201,7,121,144,136,49,68,114,1,180,193,165,67,117,98,92,230,45,153,167,120,227,39,220,201,40,218,176,242,79,255,176,197,84,44,219,188,24,123,109,252,180,10,54,56,205,152,158,23,34,226,122,114,118,86,190,135,145,210,139,53,111,80,254,12,33,99,114,50,69,174,102,63,40,134,203,163,241,201,210,132,197,30,194,21,41,67,111,169,59,137,176,140,87,223,35,219,148,41,17,47,87,132,177,195,184,155,62,44,57,51,61,166,176,0,78,17,239,248,132,24,90,111,0,114,11,243,116,156,217,62,172,237,169,184,102,49,203,132,170,173,228,19,92,247,110,129,213,51,246,166,189,117,14,122,133,32,168,49,250,110,109,130,233,47,207,247,73,245,53,4,163,18,37,68,143,96,159,144,46,41,170,94,167,114,150,192,69,209,251,219,13,111,213,186,98,240,94,100,151,249,137,215,40,31,202,233,102,233,87,154,45,180,231,125,239,156,180,218,112,223,97,62,42,141,65,252,126,67,80,247,250,233,208,232,35,192,160,163,194,226,126,10,45,236,6,185,108,216,204,37,163,11,79,111,48,215,146,155,158,134,141,203,55,89,61,222,33,78,82,125,74,58,124,11,39,39,25,125,19,251,109,165,69,192,6,62,4,243,172,60,180,97,171,114,245,37,98,216,173,83,172,42,223,203,123,98,129,233,163,55,50,102,117,207,223,131,8,155,151,246,17,163,194,153,249,69,72,100,93,139,51,97,70,143,174,24,21,44,73,67,97,203,26,232,224,113,226,185,74,242,203,51,164,179,209,188,168,1,102,93,74,120,214,135,191,193,209,7,112,218,199,145,10,92,23,239,226,242,205,187,159,126,171,125,35,158,53,118,74,19,183,224,31,116,118,13,32,211,205,92,131,123,48,181,32,124,7,233,247,254,24,251,109,189,0,184,187,80,73,194,94,100,239,81,170,145,20,235,132,230,56,141,90,22,151,198,88,153,66,134,20,94,237,62,58,110,218,255,50,111,198,109,211,202,21,39,7,30,238,147,85,35,154,58,236,112,221,70,102,211,120,115,74,109,188,70,229,214,191,122,134,120,195,231,217,122,35,113,9,110,154,50,82,32,35,111,159,191,205,52,223,124,250,77,32,228,68,131,215,255,245,107,10,80,105,104,31,4,173,207,219,31,219,171,182,182,254,211,181,183,202,185,238,165,167,38,248,72,193,90,249,154,165,80,64,209,68,160,49,226,93,135,143,48,97,211,47,187,29,120,160,203,115,39,87,245,227,220,244,5,60,57,251,126,42,117,244,81,69,98,77,242,210,249,188,19,130,253,198,56,95,174,249,187,185,215,132,16,226,25,29,180,25,54,143,69,121,134,79,117,180,218,210,211,236,58,207,231,69,104,95,149,166,212,59,105,131,68,83,21,233,177,143,135,83,237,99,3,20,58,123,234,249,128,199,117,238,163,124,52,215,100,124,76,146,61,253,192,135,196,87,201,115,149,98,141,214,85,252,207,188,13,34,208,166,93,132,22,39,44,115,121,203,93,78,137,69,196,253,197,120,148,36,21,208,5,95,43,5,122,145,41,160,12,117,201,143,36,62,133,73,185,73,185,155,194,182,166,248,96,33,9,112,7,42,39,42,203,253,23,196,161,187,66,234,58,217,44,48,7,139,47,158,58,153,179,83,189,27,100,164,156,234,199,98,117,100,38,11,24,163,169,221,244,159,173,191,177,229,194,60,25,229,142,239,38,104,95,145,238,47,214,188,90,21,66,126,66,111,210,228,101,36,242,172,130,97,234,90,20,62,166,38,11,198,159,44,245,249,131,27,135,234,87,83,2,62,185,253,129,60,125,165,26,164,138,148,193,87,246,201,45,72,3,33,31,191,29,45,33,15,238,109,8,39,100,38,195,128,83,7,133,205,161,144,113,161,194,75,111,13,7,188,92,227,251,80,96,18,64,26,145,25,40,183,204,243,127,122,119,214,146,16,231,175,187,101,92,23,25,172,45,195,139,252,212,135,73,86,24,33,203,30,64,143,202,39,238,180,143,39,141,32,30,65,76,186,57,211,14,143,45,98,183,16,106,103,221,249,6,53,137,24,139,142,183,198,247,95,139,222,54,254,33,32,110,206,70,243,213,3,192,199,172,149,164,83,182,93,148,177,50,21,141,173,13,238,107,195,127,67,110,37,112,43,142,183,230,190,209,160,162,156,23,27,134,24,34,52,140,72,249,61,178,169,148,8,130,66,147,91,31,208,121,252,240,86,4,49,94,172,145,170,231,175,155,91,81,34,65,35,19,119,54,89,16,204,192,75,121,73,147,188,144,117,13,228,38,41,170,216,212,138,219,190,30,66,160,168,25,44,46,139,91,239,138,252,75,214,254,70,38,167,102,27,83,199,3,87,193,132,173,198,46,20,126,199,149,77,169,28,80,101,104,137,62,96,184,186,195,156,232,54,165,152,181,234,109,221,187,146,210,235,81,120,213,202,4,54,76,73,143,91,58,186,245,234,169,42,230,22,18,250,90,107,166,223,111,105,64,154,164,4,224,90,136,137,59,115,161,111,33,203,195,109,85,228,153,230,42,60,71,72,5,2,62,18,247,95,210,226,191,18,86,215,250,188,187,220,235,252,237,222,248,38,43,49,68,167,200,78,234,221,147,5,179,21,224,63,87,13,134,86,163,63,36,111,99,183,191,107,252,17,109,125,244,237,227,124,248,96,249,123,151,124,55,89,15,60,83,228,51,167,78,178,149,160,185,115,84,80,74,205,223,140,130,90,11,7,178,123,40,235,140,10,228,159,27,22,21,27,35,97,198,101,3,45,152,101,159,133,198,240,50,167,96,88,76,87,206,44,39,249,11,105,101,233,91,94,0,117,182,228,62,63,40,7,175,93,108,94,109,10,13,105,155,235,242,84,115,42,225,207,146,64,214,155,15,160,204,116,101,205,129,106,90,130,161,1,205,66,106,134,110,197,2,121,251,255,76,57,17,131,177,22,249,53,191,239,3,209,175,23,202,194,236,120,82,27,150,175,201,140,218,92,66,6,242,27,242,72,21,153,249,76,147,161,201,108,133,37,82,63,157,26,16,157,157,53,227,144,45,33,251,159,166,102,14,146,8,130,61,71,232,239,55,149,154,94,62,201,196,46,66,64,182,197,173,177,174,129,184,239,93,144,26,35,78,229,198,0,35,11,0,24,58,31,116,17,14,148,173,217,199,57,30,154,70,63,65,205,96,139,15,161,221,167,15,248,53,144,210,247,198,28,89,183,77,185,161,137,46,60,33,250,124,201,6,162,14,149,173,139,246,183,196,97,174,62,140,41,85,124,32,241,157,180,188,116,43,88,101,206,143,162,87,136,175,53,8,137,29,26,223,233,139,150,187,232,66,160,175,236,60,249,74,124,88,0,169,71,249,158,190,158,10,136,161,14,192,129,205,123,206,139,139,194,116,10,232,178,229,135,29,133,175,175,159,206,251,200,116,49,111,179,231,204,59,114,82,198,44,18,188,92,104,214,214,0,99,131,131,20,13,139,95,163,166,89,240,125,147,162,92,27,236,208,194,108,76,213,90,135,100,0,183,53,71,191,95,49,61,227,177,149,62,19,73,102,79,254,208,162,75,217,114,173,130,116,114,179,103,102,51,151,84,216,208,210,52,137,180,99,72,124,128,249,247,136,183,36,28,249,242,125,70,239,231,22,75,183,222,194,216,180,98,166,182,159,27,186,214,74,253,234,220,112,80,103,58,215,113,70,28,68,149,92,181,110,119,67,179,179,9,96,140,249,194,72,173,244,144,58,9,141,246,68,237,118,179,124,164,96,125,30,196,126,104,19,176,107,25,7,162,89,236,206,184,139,167,166,16,55,67,7,93,251,90,252,86,252,171,140,238,114,28,106,253,2,64,26,18,192,199,145,70,224,41,158,81,211,254,47,235,74,231,215,176,97,187,165,209,79,109,189,21,14,209,97,193,29,254,42,24,157,72,5,143,9,214,54,90,86,243,143,140,12,163,2,158,213,69,48,232,80,165,123,73,197,247,8,241,232,198,127,142,153,236,153,145,20,27,64,72,56,14,13,147,102,116,211,20,44,176,108,13,229,36,230,81,206,9,197,5,42,177,137,125,239,52,138,145,92,76,16,223,134,138,221,234,177,91,177,210,67,1,151,117,176,201,125,211,227,144,217,180,31,53,97,31,147,33,222,114,225,63,236,245,62,68,54,30,147,134,96,110,84,124,209,201,141,3,62,115,79,24,228,194,3,74,218,184,3,66,224,170,40,123,37,121,61,129,54,53,103,197,43,89,135,6,26,104,193,193,136,152,56,142,183,224,128,35,138,123,231,218,184,64,116,133,134,79,71,93,163,18,65,127,217,137,72,42,147,44,193,117,255,58,201,221,139,83,224,169,171,21,200,243,196,43,229,12,27,96,110,87,50,136,174,144,220,236,35,210,9,136,71,10,14,95,205,206,230,46,210,240,140,197,31,1,18,188,0,238,15,228,67,49,220,86,132,126,70,124,204,88,118,84,251,214,36,171,200,70,160,93,190,20,193,149,122,208,201,60,231,13,227,143,217,98,120,101,241,47,166,37,0,246,166,53,179,69,210,170,111,102,237,39,29,58,140,90,17,30,66,50,240,135,134,156,130,216,158,96,227,238,43,173,150,62,156,252,12,213,121,200,99,178,38,253,248,51,29,232,51,139,88,26,160,174,235,4,96,47,68,39,65,224,118,4,246,129,110,151,23,33,196,101,107,18,57,33,181,138,239,175,105,157,49,247,51,175,4,49,223,166,210,239,121,16,164,212,230,198,33,63,150,165,9,54,147,43,215,241,224,55,27,106,204,89,39,184,161,80,49,4,115,240,147,14,244,80,211,157,188,47,240,27,232,175,82,215,194,147,55,86,12,143,240,196,252,206,171,147,238,96,167,220,204,222,124,57,43,217,33,94,205,196,224,116,99,78,12,233,159,227,1,76,43,79,235,217,146,66,161,211,175,94,65,74,199,243,183,6,81,84,203,242,106,233,76,173,158,214,45,43,108,174,250,106,136,126,230,63,14,251,213,18,71,87,50,64,255,236,85,183,102,109,45,1,174,202,9,149,185,253,197,58,210,45,138,136,51,85,221,138,73,184,106,127,134,253,72,58,18,180,62,151,29,82,139,220,202,116,64,248,20,81,96,109,47,138,242,186,193,36,58,228,83,194,172,38,0,252,218,244,10,112,115,142,57,210,57,11,64,200,229,159,61,193,101,132,118,218,80,148,208,24,56,50,42,216,65,221,198,222,42,94,40,195,189,60,175,28,71,25,114,164,42,45,8,67,46,142,204,238,25,167,37,150,221,46,11,216,39,161,104,150,116,113,1,94,67,6,9,155,180,85,217,5,244,160,99,51,203,177,93,136,13,60,29,150,143,141,45,240,202,86,52,252,208,169,251,4,6,159,54,129,123,18,109,207,1,191,79,38,187,105,43,96,244,160,246,58,53,1,126,98,82,106,12,250,65,44,103,65,155,146,190,0,201,249,32,20,57,171,220,149,156,114,51,66,148,220,137,156,113,120,32,169,126,124,13,130,177,138,31,55,46,148,240,128,29,71,141,116,145,112,8,66,189,190,216,123,114,164,94,213,103,242,213,46,100,240,150,169,179,251,110,47,164,50,174,245,163,245,59,14,243,8,35,82,74,151,19,130,70,32,129,139,54,14,190,35,131,230,71,44,133,253,187,52,219,118,239,235,58,76,31,196,252,32,242,187,197,157,187,55,29,121,51,214,250,24,234,46,96,133,232,102,63,43,191,186,226,113,189,64,205,186,249,119,43,113,194,61,250,58,221,69,191,75,14,152,187,167,243,108,156,124,46,5,218,175,243,118,7,240,85,167,144,192,213,61,210,252,162,165,162,46,86,124,240,63,149,35,88,159,198,71,207,56,140,25,144,133,248,190,191,241,252,13,124,234,108,165,9,106,44,119,178,102,193,221,168,140,143,125,102,211,106,41,163,241,103,12,131,227,10,78,64,224,131,209,128,108,224,131,81,196,188,208,57,0,65,7,171,245,92,68,97,155,26,19,0,220,173,153,62,182,16,55,19,229,89,135,80,157,145,162,168,60,3,54,77,8,252,62,78,45,97,13,187,5,95,233,221,143,244,218,237,9,191,191,111,230,19,235,185,24,229,133,236,211,127,22,70,243,186,237,63,6,52,140,155,111,172,124,143,130,20,198,240,17,48,164,10,74,221,17,240,102,82,73,186,66,214,132,28,226,189,253,197,216,71,13,102,76,54,192,250,157,250,97,33,169,125,119,76,18,127,148,89,55,79,41,27,171,173,241,40,25,242,210,152,51,104,129,66,79,162,178,205,127,78,159,148,90,244,237,62,200,220,157,71,215,30,45,95,17,166,151,2,107,156,25,214,202,113,205,64,70,182,24,9,62,176,176,190,16,176,188,96,117,242,77,22,88,50,108,118,138,246,209,82,199,143,160,77,201,121,197,140,194,143,8,181,195,45,95,221,40,139,214,14,153,166,70,195,180,165,102,177,227,237,193,79,231,55,66,91,102,116,212,200,47,182,152,106,44,255,140,122,66,158,160,250,117,112,5,28,227,9,101,161,115,43,75,216,160,129,201,85,4,155,212,168,94,163,160,204,9,102,25,233,102,160,184,227,106,238,100,129,31,84,122,126,254,145,223,210,150,80,172,229,177,248,245,3,169,238,5,16,2,78,51,54,207,82,72,227,99,136,26,105,129,53,22,17,45,214,181,195,68,36,56,169,195,242,5,8,191,67,154,4,98,246,26,112,153,140,77,237,240,2,154,115,169,245,170,100,202,110,18,149,98,123,104,24,71,192,232,157,222,215,83,47,36,18,129,246,103,237,227,185,218,144,30,199,136,151,160,138,100,74,32,166,208,86,67,75,237,132,120,166,153,52,64,10,225,171,2,81,131,86,59,191,48,93,62,184,125,186,164,181,232,91,66,146,242,21,173,53,43,188,74,248,215,108,185,224,167,76,81,71,206,93,12,235,166,22,241,224,190,133,235,131,111,103,60,230,112,49,52,171,86,194,94,59,123,115,191,87,69,241,194,32,229,82,37,247,66,83,202,39,30,54,213,89,3,78,249,44,22,248,167,57,0,84,189,32,168,147,103,6,140,148,202,187,193,37,38,180,46,29,166,57,72,223,230,106,44,108,111,251,141,251,89,7,111,191,116,203,52,57,144,49,241,196,170,155,145,94,130,81,6,8,48,239,173,230,55,130,69,187,163,225,66,214,151,106,237,182,124,152,252,164,152,71,188,138,18,156,234,158,96,75,48,112,107,71,163,19,180,198,24,225,112,151,114,89,6,217,49,26,232,78,138,51,90,69,91,193,126,130,54,20,217,158,121,249,61,85,203,2,97,83,109,237,170,254,0,91,197,122,244,126,45,233,234,109,127,179,19,219,93,31,65,76,94,19,176,192,62,20,225,161,144,181,212,117,211,254,177,20,119,165,4,191,21,105,172,116,103,36,198,101,166,240,111,212,21,87,239,249,26,153,242,52,76,142,34,251,237,81,66,187,57,122,29,236,37,110,21,148,230,218,247,104,63,1,234,5,69,199,73,134,157,172,42,231,147,224,75,141,129,211,82,4,89,195,246,70,171,181,93,183,55,108,159,166,33,84,4,185,111,204,210,203,121,247,47,11,38,196,128,175,73,224,158,13,7,251,219,162,20,164,80,64,199,241,117,6,96,69,101,173,208,37,165,211,107,165,193,43,31,159,138,214,247,2,33,12,191,208,158,105,240,17,229,141,41,237,45,38,45,115,88,232,28,191,188,150,228,13,47,17,235,94,149,41,105,96,203,124,26,222,106,9,189,50,92,15,120,136,57,57,255,99,51,112,155,217,186,209,181,137,48,198,43,39,230,86,230,26,217,240,223,93,238,195,80,220,79,238,160,255,161,52,146,25,191,179,0,106,203,39,179,207,46,133,153,151,239,88,57,122,189,135,89,178,115,230,216,10,114,143,251,93,168,61,169,202,150,202,196,237,75,49,182,183,125,110,19,34,1,136,14,89,81,155,227,118,201,69,250,152,109,216,132,250,88,147,48,2,191,100,195,211,13,126,162,119,72,133,229,123,207,22,23,212,210,63,155,150,227,57,166,222,129,67,70,42,85,154,245,247,41,193,230,95,156,113,40,103,226,86,19,6,181,49,124,103,224,189,223,33,119,236,24,20,229,68,141,154,5,89,177,163,212,125,152,33,38,48,226,24,141,151,158,51,86,207,22,139,80,172,113,125,82,37,229,71,24,29,22,151,195,95,177,29,49,74,158,121,217,68,52,92,168,158,88,196,251,22,3,155,79,122,252,156,221,200,181,70,100,216,71,156,175,156,86,2,231,130,108,43,211,119,75,181,114,163,95,222,24,246,255,186,183,186,101,37,137,223,53,194,47,117,58,55,235,209,179,14,167,242,26,134,221,36,193,38,118,184,207,96,67,32,145,250,154,128,94,25,66,185,48,57,213,130,222,58,197,173,252,78,101,199,141,206,155,94,81,157,155,216,239,200,168,141,203,59,210,55,17,55,170,5,110,70,51,20,19,17,219,187,198,121,220,48,135,101,52,185,215,244,4,37,229,220,138,211,126,144,244,210,14,194,134,9,176,26,52,128,5,94,173,63,199,171,196,37,142,16,185,13,98,224,38,105,153,24,182,124,179,35,177,69,226,224,127,75,236,2,98,7,44,185,3,14,107,156,129,152,51,36,29,203,211,203,108,162,74,162,216,89,12,128,9,112,14,157,147,3,227,248,177,51,228,239,231,213,231,254,82,42,244,137,106,99,170,156,192,66,71,139,213,5,156,125,195,124,229,130,190,205,89,225,241,254,176,95,30,219,40,248,129,218,116,222,75,183,241,249,60,88,178,52,92,157,156,113,232,162,36,107,47,55,17,155,162,70,224,125,82,84,211,203,26,49,246,193,94,207,161,122,216,126,138,16,206,87,28,38,45,30,196,186,30,68,206,95,156,208,218,236,93,107,125,217,121,46,223,4,69,183,46,238,206,71,72,167,159,167,48,118,25,0,159,147,140,99,166,172,4,113,21,161,52,102,54,219,194,90,106,50,6,156,202,21,86,112,33,45,53,6,124,162,83,226,178,246,1,165,167,177,190,237,128,219,79,114,30,187,31,146,10,157,251,80,124,108,191,233,91,104,68,35,156,13,54,123,191,37,77,245,82,222,206,8,246,133,27,217,87,116,7,145,65,128,81,142,250,19,137,207,10,217,88,150,119,183,30,231,123,9,189,145,113,150,247,204,148,101,142,228,144,127,101,122,157,153,221,45,112,44,139,13,223,94,18,221,245,14,185,252,132,117,15,173,122,121,1,251,109,2,107,25,97,29,180,199,11,124,161,138,37,92,119,254,245,118,34,128,28,100,200,80,5,114,99,208,232,126,215,247,226,193,129,111,229,166,12,107,30,67,118,84,156,100,158,204,44,28,118,134,227,10,22,153,126,77,13,134,137,18,167,115,62,98,60,182,179,66,109,93,146,39,135,247,137,193,45,175,156,83,87,217,63,250,57,154,128,151,152,45,35,43,126,198,229,219,126,200,145,4,236,251,153,196,162,89,73,134,96,119,107,128,190,147,228,64,73,220,100,124,73,203,91,213,77,92,68,50,107,69,237,110,138,228,193,175,162,213,78,39,118,105,39,11,196,157,25,195,35,53,250,121,123,219,197,179,143,206,30,210,251,106,231,243,37,84,55,23,7,30,84,11,121,92,53,9,191,28,49,57,237,112,78,183,12,215,243,99,159,238,14,246,197,136,207,69,0,120,99,89,37,184,54,94,128,204,224,174,118,50,226,59,151,162,115,167,144,223,213,199,4,87,55,193,10,212,169,238,242,254,70,213,252,87,32,245,18,157,79,122,232,143,103,31,93,140,93,243,91,156,91,223,136,12,68,98,200,179,170,185,195,112,27,104,3,205,165,28,186,174,118,57,189,119,144,158,95,158,164,143,139,58,87,217,43,22,68,43,126,240,70,94,163,225,233,248,227,168,70,198,16,51,205,239,192,4,124,244,190,80,130,188,253,65,63,201,98,243,142,139,238,115,52,164,188,234,11,203,33,66,111,40,174,113,78,139,135,102,209,122,166,53,10,2,10,140,215,139,223,100,11,23,208,126,65,214,52,37,98,93,37,250,159,75,209,155,248,86,107,5,114,199,254,105,179,240,132,18,228,65,136,188,180,168,141,149,43,234,13,114,25,92,32,8,212,172,186,194,234,241,77,20,142,76,140,225,110,176,248,93,52,69,8,47,143,25,99,166,56,37,228,218,183,234,205,236,237,168,228,136,179,145,123,254,230,182,37,220,223,96,199,45,24,147,73,86,254,47,90,124,89,129,192,199,167,216,217,62,148,163,46,107,74,67,155,206,30,163,44,42,238,69,77,5,86,126,151,131,136,59,134,63,72,23,50,35,228,75,48,172,147,4,200,35,217,142,56,51,159,145,237,51,218,27,192,43,193,90,63,194,218,149,77,69,58,68,24,177,235,144,245,52,41,241,21,63,202,204,123,60,245,245,147,59,230,53,58,179,177,6,108,72,142,101,202,171,147,1,238,27,183,145,157,7,29,13,111,137,129,183,185,196,139,126,204,48,220,237,170,227,65,153,226,170,245,241,69,250,74,235,39,129,115,94,113,165,212,140,219,239,255,30,2,150,71,167,222,250,123,230,253,102,110,67,175,23,73,166,0,144,47,148,163,151,221,23,81,24,247,230,191,244,11,1,206,112,51,40,182,33,40,163,61,107,169,167,6,202,202,72,255,23,102,172,225,38,148,226,88,109,43,255,21,145,157,184,0,241,95,26,253,89,42,53,13,149,184,8,74,173,119,80,63,39,122,131,186,46,224,96,135,125,146,230,186,215,105,91,230,163,169,125,167,150,59,214,137,125,94,22,30,51,110,143,175,201,170,44,185,136,253,28,105,89,77,41,65,135,12,60,237,170,191,75,127,88,149,34,205,123,6,139,121,217,249,166,254,165,197,104,144,84,48,58,172,21,122,128,85,199,148,36,114,91,239,123,1,206,8,169,49,206,39,142,97,137,189,224,169,198,119,13,171,201,140,49,157,103,118,88,94,210,27,126,242,245,68,55,25,204,114,244,247,64,29,145,137,154,56,172,22,62,19,227,79,143,90,5,12,201,194,154,224,71,103,79,31,119,20,146,114,219,19,44,92,21,211,69,49,20,95,47,183,25,195,60,209,50,238,182,244,59,9,94,112,27,36,210,214,7,152,57,84,87,219,76,117,252,173,214,2,188,162,120,141,43,194,108,127,121,25,148,205,129,10,46,39,41,144,243,52,218,147,187,37,188,247,50,228,177,63,51,214,17,10,240,24,244,129,34,87,146,124,5,230,163,171,120,234,22,101,103,156,68,245,144,114,132,132,244,163,47,127,235,219,88,243,187,140,196,153,78,126,139,116,152,107,147,27,119,0,2,213,231,59,70,73,214,67,31,130,51,71,155,189,211,225,165,140,83,24,36,56,202,105,50,33,140,155,216,216,209,252,54,156,254,20,81,120,206,235,241,53,194,44,177,128,30,239,26,95,124,88,90,21,132,123,188,158,141,127,241,223,95,178,108,21,221,145,222,26,192,180,84,129,78,175,117,146,57,215,116,10,13,53,12,252,227,64,32,115,213,68,143,238,155,225,101,184,132,28,92,127,89,232,1,139,160,185,99,115,92,29,188,211,254,180,85,121,47,205,53,199,122,73,153,119,188,74,163,229,129,90,48,50,178,91,189,168,116,38,32,114,55,89,132,116,208,124,128,113,113,16,206,199,26,163,212,71,1,250,155,96,53,100,44,246,31,136,208,243,220,60,176,23,103,88,245,48,51,59,225,235,226,76,182,53,49,135,126,117,23,4,0,51,62,11,237,65,252,21,246,193,84,14,85,217,111,240,108,226,134,59,194,210,198,214,9,245,99,101,81,3,89,134,225,173,80,61,204,115,250,25,191,22,137,42,177,155,159,237,248,200,39,189,1,66,189,88,8,198,57,47,194,59,150,74,50,244,192,145,124,139,137,9,88,183,226,179,162,219,55,201,222,186,109,36,242,146,104,134,170,9,120,67,123,240,251,118,184,113,206,203,242,204,29,95,103,160,139,24,229,246,174,44,232,1,92,51,119,121,192,74,200,193,169,150,115,168,56,37,31,105,175,166,10,183,252,135,115,233,34,0,229,124,183,246,177,143,42,237,125,2,142,154,240,49,228,213,15,77,123,202,79,84,0,147,189,200,161,106,243,41,87,86,158,216,240,246,100,112,9,91,213,220,206,108,190,57,220,218,99,189,47,194,120,28,127,254,169,178,91,243,109,75,134,210,210,244,242,159,54,217,20,133,68,233,153,234,101,91,233,30,96,171,224,92,91,176,236,182,188,20,131,21,122,84,104,171,14,236,252,249,75,212,235,191,95,11,62,141,94,241,165,26,219,173,197,153,214,168,223,240,94,213,113,148,95,22,212,203,134,117,232,60,147,51,11,201,54,4,81,122,170,58,150,209,147,128,196,78,68,78,148,160,114,198,127,162,120,180,68,133,22,76,101,119,11,93,246,9,232,183,127,140,173,92,221,236,51,178,45,217,246,70,118,91,129,102,24,199,252,7,6,116,81,43,240,49,115,77,164,134,23,10,184,92,26,223,238,174,254,108,5,221,29,205,3,38,30,51,143,196,202,21,102,228,51,105,45,191,54,175,140,175,135,132,56,183,9,116,20,68,132,18,220,233,176,239,82,87,160,87,75,33,255,121,193,156,78,230,23,79,64,52,198,99,148,130,106,107,8,203,26,34,248,194,178,123,242,238,250,69,219,168,219,185,118,64,221,220,7,62,58,172,34,161,85,252,155,52,152,60,87,103,183,167,226,234,225,170,247,90,38,143,81,89,210,156,20,60,194,148,113,179,171,5,77,184,78,26,208,131,200,86,18,46,116,74,134,61,119,29,194,3,117,40,80,168,90,103,191,42,184,95,218,91,28,155,54,146,65,95,188,105,77,14,205,75,249,117,46,221,98,224,169,93,190,83,43,182,146,208,7,135,154,99,250,12,2,189,246,105,220,172,175,69,1,167,218,186,57,136,247,112,149,221,32,11,202,229,160,52,60,200,208,193,198,75,246,250,53,55,150,176,139,93,85,222,206,205,111,9,73,162,186,211,69,140,188,136,164,203,223,18,225,119,181,234,138,60,23,112,75,105,15,203,7,125,177,246,31,45,74,151,48,22,139,175,136,183,250,161,111,94,119,158,113,175,140,79,29,122,65,55,233,80,125,200,31,209,18,35,82,3,116,190,125,208,46,253,125,100,73,160,238,5,244,38,184,200,7,167,119,122,165,28,250,26,52,110,188,151,63,208,63,248,94,165,164,111,163,146,32,37,5,60,85,192,27,61,24,60,161,222,0,4,254,155,189,84,196,0,157,35,12,162,103,138,192,135,38,45,40,41,69,63,30,177,222,41,253,200,54,63,230,237,20,103,172,23,99,192,215,2,181,198,52,12,1,157,162,169,147,206,27,237,188,158,40,214,164,233,240,100,201,245,24,178,38,205,66,140,166,43,132,117,143,233,22,167,190,202,18,188,127,240,184,49,182,87,84,214,121,140,169,20,29,122,133,69,18,168,61,132,146,108,35,131,109,86,101,183,150,34,77,90,194,24,46,232,28,48,183,206,47,100,61,163,165,74,17,92,27,210,106,16,222,186,117,41,103,197,144,3,27,9,248,132,189,88,83,122,219,49,116,2,50,30,40,205,76,130,35,126,83,228,228,138,171,171,135,39,196,227,87,106,235,241,239,86,179,253,11,23,99,7,66,41,158,178,157,76,234,6,5,214,254,184,155,181,84,197,165,122,251,119,249,236,166,219,144,14,253,20,200,71,185,128,249,58,15,196,101,206,51,124,190,50,159,255,10,172,123,168,253,230,89,10,236,71,194,62,129,71,92,165,85,0,198,135,157,141,191,50,13,140,37,124,110,249,46,46,25,251,68,145,8,18,120,51,137,142,119,244,148,246,141,26,132,163,135,241,35,159,49,77,209,163,230,111,6,242,146,195,49,170,2,124,194,17,165,42,155,254,34,50,37,48,67,234,117,90,102,69,129,61,195,172,78,87,34,46,79,146,168,210,166,122,231,226,222,204,251,20,75,223,196,242,130,34,225,110,75,207,175,78,24,239,45,171,104,198,59,0,19,49,11,243,112,43,250,158,62,80,155,237,46,52,188,185,245,171,68,197,202,251,110,93,211,94,67,191,87,157,87,233,13,61,47,52,206,80,194,167,66,67,198,170,244,247,174,171,50,79,255,184,161,14,254,202,162,162,254,221,148,221,251,90,102,154,71,98,61,150,1,32,250,227,57,240,168,21,174,152,107,235,75,2,198,35,117,161,148,210,231,214,184,87,241,102,16,184,144,221,165,158,108,17,177,46,228,156,159,149,123,171,239,250,40,10,62,189,159,144,124,7,64,76,122,161,214,158,46,206,191,99,142,189,68,40,168,172,65,88,130,102,169,121,107,188,201,117,35,139,212,14,176,77,110,172,197,14,238,254,189,108,234,224,228,68,226,121,230,183,185,224,25,14,142,86,3,2,21,133,116,109,24,125,214,126,192,236,107,42,30,208,247,43,102,62,205,11,213,177,80,163,92,245,82,101,244,192,151,191,169,102,204,190,167,232,66,226,12,115,238,131,188,181,235,30,55,68,17,186,125,64,121,44,39,147,240,53,20,40,101,224,109,239,226,32,115,253,200,113,202,118,207,81,168,138,146,224,129,38,168,181,120,87,225,170,24,6,223,254,59,48,103,66,191,112,18,100,232,149,121,191,132,39,231,12,223,111,202,150,238,150,76,143,41,37,183,222,8,16,24,33,99,101,144,218,10,68,70,133,97,95,109,42,67,13,102,0,93,189,206,41,149,160,206,101,195,209,76,22,231,109,76,142,113,78,222,63,202,227,65,140,154,29,47,96,41,58,77,137,107,249,152,7,126,53,105,31,221,134,107,150,14,18,108,110,152,91,57,88,146,199,220,12,79,116,220,134,180,176,224,71,97,52,154,76,94,230,58,14,196,154,89,27,162,219,96,227,91,143,175,92,36,179,222,30,59,163,32,250,146,96,163,83,134,33,18,27,99,127,113,171,35,52,143,96,219,71,71,254,216,30,244,75,88,241,242,50,213,1,83,56,154,152,153,219,130,166,175,82,10,125,111,96,137,38,46,205,11,85,195,29,184,117,250,218,58,49,10,40,30,139,211,81,157,249,51,33,100,201,34,96,197,189,206,48,180,50,2,111,154,109,10,90,116,189,224,85,45,153,10,96,210,142,179,131,174,213,131,9,90,194,235,113,201,152,223,253,134,198,136,215,196,121,114,145,127,197,63,226,22,10,124,149,177,37,12,217,218,113,9,235,142,49,103,237,98,82,140,8,127,97,56,61,78,76,142,106,216,56,78,153,139,60,223,243,28,34,38,199,137,132,50,118,151,58,141,192,20,249,138,53,114,177,45,146,78,147,234,123,244,61,157,119,7,88,41,82,17,102,213,59,93,79,45,40,157,139,219,81,12,134,18,77,1,101,45,228,155,66,227,243,242,202,71,136,205,94,102,239,237,253,62,207,30,222,178,58,135,219,74,150,232,27,209,251,37,198,33,83,209,39,249,183,21,38,213,39,143,198,149,91,161,250,193,43,45,233,70,234,118,173,231,180,151,157,138,7,167,198,81,194,51,164,200,83,56,176,121,167,225,108,50,245,125,137,148,215,111,59,19,64,109,5,114,176,218,137,186,235,94,254,156,96,194,168,34,159,84,171,68,70,215,155,148,244,240,11,54,128,75,56,161,201,231,65,137,194,113,32,89,201,13,141,169,131,94,198,168,132,135,101,50,165,181,8,159,184,15,19,74,16,105,43,25,168,214,106,76,164,64,91,12,74,22,16,124,27,121,145,188,125,255,96,131,33,245,145,180,29,62,194,137,30,62,243,129,77,13,158,163,117,162,206,61,236,135,244,220,166,174,217,73,139,0,254,201,26,125,241,33,68,187,155,235,119,25,72,196,151,8,255,8,84,250,43,102,204,134,121,186,123,144,48,2,235,7,229,41,190,150,181,169,203,226,194,118,180,182,162,220,222,14,52,114,197,229,86,207,201,148,241,246,69,68,231,8,57,6,21,171,44,83,134,151,83,25,48,142,91,248,21,21,213,9,104,208,21,12,133,100,100,144,124,237,193,56,180,34,39,246,232,53,212,121,61,127,221,103,74,114,150,223,11,229,210,6,76,40,95,192,199,167,100,100,64,117,44,73,13,187,42,241,47,212,35,164,55,64,85,88,41,102,68,165,110,72,100,66,38,33,14,166,233,157,80,35,137,1,69,63,111,169,42,19,65,190,106,104,216,90,154,147,190,183,207,177,145,142,190,213,148,10,228,251,99,58,72,148,192,227,20,1,79,110,181,47,89,218,133,7,75,111,229,49,60,97,179,158,28,51,110,139,80,56,147,33,182,227,153,92,32,1,241,44,181,143,24,16,252,26,129,134,63,65,186,1,160,90,254,21,88,43,220,101,222,156,214,211,98,172,42,254,193,103,147,61,229,181,85,228,223,127,163,201,157,106,97,82,251,201,89,32,245,234,92,103,151,70,111,44,210,74,166,88,95,204,82,185,9,218,72,146,27,181,139,97,122,22,228,206,84,237,87,140,101,100,110,216,186,226,110,186,109,140,162,59,52,3,26,96,176,41,84,66,47,216,100,110,106,2,55,106,165,232,43,156,42,193,122,42,74,224,96,101,41,240,141,4,88,29,113,31,121,80,196,152,15,234,154,70,129,228,97,137,99,89,108,64,143,32,111,199,220,209,192,20,24,80,192,202,191,169,156,133,210,36,179,17,149,67,213,52,180,176,134,253,181,179,174,87,217,236,254,162,137,201,192,88,23,89,195,231,73,182,226,224,149,99,172,221,135,5,241,132,86,236,118,69,50,108,27,103,65,17,127,75,11,160,71,85,227,148,153,62,103,83,250,192,254,215,123,252,157,8,112,132,210,193,21,244,168,131,44,69,226,190,243,10,225,163,84,190,118,32,19,193,234,220,32,188,74,90,197,143,70,191,99,113,186,143,49,131,109,253,62,234,221,183,103,238,89,65,67,11,230,9,222,24,95,129,14,228,125,126,166,49,29,239,36,39,124,130,203,200,105,29,231,182,43,1,179,193,103,230,251,205,22,182,65,191,137,110,165,113,180,60,209,87,212,7,69,241,130,157,125,59,225,89,244,120,134,142,170,92,19,65,251,87,163,83,32,185,163,202,187,191,34,192,183,186,236,30,222,225,180,237,142,162,77,93,190,100,248,70,134,164,253,105,255,142,189,83,50,161,225,223,241,240,252,170,90,122,221,22,108,187,81,31,252,76,218,238,217,175,90,110,37,190,8,65,147,181,160,202,39,24,230,218,92,233,102,123,98,72,215,163,152,111,198,25,215,60,213,1,254,4,168,45,13,40,238,142,158,60,70,241,144,183,215,236,146,149,13,234,215,133,3,112,135,7,8,40,195,214,105,244,172,246,200,198,238,153,112,100,59,137,18,122,9,204,17,41,181,111,41,61,21,160,16,170,194,218,178,62,88,92,199,233,200,24,70,246,142,224,164,200,210,237,216,75,100,45,115,160,117,92,38,226,170,215,156,203,215,210,248,231,199,216,248,161,125,167,132,103,180,186,9,249,4,154,16,237,107,80,28,27,235,150,39,210,201,153,66,17,97,165,29,15,167,130,23,77,17,106,160,90,248,47,219,164,20,127,81,248,1,36,254,22,50,208,65,145,45,220,160,93,16,45,62,229,177,187,144,167,142,26,248,232,6,191,77,59,136,49,2,33,116,66,65,146,218,44,111,73,2,222,99,111,24,180,41,67,103,39,216,168,240,207,142,34,241,86,17,173,37,58,64,186,213,98,181,151,159,141,26,22,31,45,92,64,9,10,26,76,181,236,145,18,8,30,219,158,183,71,138,134,56,65,70,34,140,141,13,54,245,29,155,227,200,183,113,40,113,203,86,214,2,162,90,237,5,247,2,186,149,205,73,75,106,255,178,8,39,126,21,96,43,117,216,10,81,98,244,208,25,252,177,189,21,50,204,13,115,42,29,115,2,10,234,207,168,29,131,228,241,82,183,158,85,177,161,142,249,81,208,74,7,73,61,160,142,153,121,63,78,230,152,77,38,100,58,119,15,102,23,145,201,189,165,77,147,230,208,2,84,68,22,86,13,32,68,58,88,73,8,48,139,117,27,222,40,32,182,33,168,89,188,113,162,162,146,225,102,118,158,53,22,82,149,184,240,92,212,243,40,50,170,149,147,223,104,185,45,162,20,59,162,173,157,5,224,233,8,159,219,28,215,102,178,59,121,254,199,162,199,99,2,69,53,6,16,218,9,6,241,44,220,188,45,208,250,244,235,250,209,70,110,222,198,183,219,47,135,143,170,11,226,178,201,194,8,0,115,63,105,158,9,227,172,16,176,218,211,18,70,236,5,109,35,119,143,218,145,213,190,153,247,240,232,191,61,9,58,130,175,235,45,122,195,207,43,194,102,133,91,46,230,18,78,212,122,114,168,4,94,120,96,72,18,12,142,191,141,105,202,78,241,114,85,34,238,84,11,10,254,50,188,122,76,216,117,121,110,3,95,91,62,253,60,174,139,195,120,183,220,61,229,75,22,220,190,134,216,68,90,111,184,152,40,130,43,39,76,144,94,215,83,252,62,127,27,6,175,158,50,87,41,85,95,32,24,14,193,22,92,54,156,254,77,61,50,7,243,25,48,156,89,56,17,33,107,135,110,160,52,80,216,55,217,98,40,102,1,34,70,233,200,205,172,234,156,17,180,123,113,143,67,81,224,51,149,12,213,251,3,2,63,30,249,181,254,120,160,155,133,96,137,181,35,5,182,121,214,39,128,129,237,203,19,137,24,93,101,255,228,209,34,58,241,253,187,131,60,8,241,178,36,11,26,109,21,150,214,31,242,19,60,118,147,158,111,23,164,168,73,67,92,231,211,6,86,222,242,248,107,142,231,119,143,1,168,27,187,91,70,38,230,162,216,232,152,83,71,41,183,182,189,94,221,128,7,217,182,42,49,232,20,23,3,87,95,213,181,137,117,14,161,52,243,122,183,193,90,134,182,58,222,179,72,150,241,129,197,216,227,156,20,75,90,202,71,128,15,137,242,183,117,188,168,252,39,243,76,167,222,12,190,250,197,206,164,145,191,47,206,24,20,40,253,36,4,220,72,143,199,19,105,30,48,219,215,196,37,15,182,38,220,134,239,35,187,29,230,68,215,139,220,215,90,25,184,246,196,149,239,249,142,248,63,141,205,161,28,87,142,170,237,214,67,142,251,97,163,163,242,208,139,28,201,5,249,160,111,232,64,231,207,201,197,196,206,92,127,71,17,57,48,200,25,226,176,113,210,162,108,233,45,224,15,40,196,161,187,228,55,88,74,235,30,68,12,209,70,87,243,159,85,208,70,192,75,111,14,15,239,6,234,134,248,30,113,51,255,128,43,104,82,6,158,241,74,19,174,199,229,132,238,6,70,145,96,242,208,185,17,12,251,210,13,113,233,186,188,29,9,195,244,71,62,26,195,82,44,209,10,230,93,188,92,234,241,145,115,67,77,67,44,210,249,228,5,84,43,160,77,103,214,59,87,195,200,20,129,254,173,229,229,37,115,254,49,72,119,145,188,255,12,95,191,110,239,124,12,213,234,217,4,211,133,39,184,242,103,223,13,5,50,56,74,214,135,66,130,62,223,167,91,175,30,40,134,82,42,167,175,169,33,40,205,88,123,104,96,189,142,226,130,73,0,60,121,128,225,203,146,1,170,4,93,235,72,243,97,77,129,92,246,173,53,161,138,204,83,70,234,80,223,20,176,62,149,150,127,141,182,196,163,80,117,13,31,248,64,166,35,112,96,44,221,70,128,124,229,74,60,65,83,15,20,135,165,184,82,153,163,153,145,137,168,21,68,140,120,76,239,1,57,32,133,38,158,157,114,92,79,139,129,100,233,109,73,206,6,164,101,18,250,41,214,14,185,87,241,153,142,116,3,55,77,138,149,123,112,38,59,191,132,156,136,205,108,175,236,117,66,107,36,241,192,147,149,227,116,253,26,209,34,134,94,214,68,212,25,142,117,207,151,32,13,101,187,154,38,54,165,162,58,254,142,54,86,89,13,232,46,36,31,67,169,250,183,168,205,55,163,165,77,37,211,28,12,51,80,99,47,117,190,69,215,83,246,24,48,152,252,50,167,183,242,94,21,63,211,171,23,199,4,160,172,57,57,92,128,50,52,174,87,77,255,17,221,149,165,195,162,43,38,226,27,221,101,124,188,82,226,222,49,132,246,31,27,81,255,205,69,176,163,195,253,83,47,80,99,157,132,223,160,92,39,120,73,149,51,171,255,67,218,107,160,220,58,236,28,119,180,1,82,24,146,160,44,200,70,141,109,254,12,126,229,95,99,96,3,216,221,136,205,113,142,122,186,243,183,255,22,253,97,176,39,222,179,209,180,233,133,72,37,54,158,28,65,95,13,1,59,153,193,87,230,128,104,160,201,205,2,196,6,125,232,155,188,65,83,240,126,145,178,63,143,0,240,193,78,184,2,226,82,240,49,22,50,167,206,196,168,121,68,212,156,249,154,95,24,93,83,113,168,33,14,246,208,135,139,78,122,101,123,8,177,97,182,122,128,106,140,8,192,100,143,88,196,50,29,207,215,143,65,120,133,133,118,94,128,12,106,130,195,165,203,112,192,173,166,222,59,23,34,6,82,131,16,84,214,205,87,208,140,201,182,166,221,131,122,181,85,150,65,139,133,103,23,179,159,231,7,175,204,95,130,131,126,45,155,135,76,69,145,54,197,251,173,9,206,46,189,122,101,178,24,17,52,231,121,151,60,255,66,47,5,0,134,235,185,232,129,137,35,158,3,110,230,211,73,61,209,224,71,153,55,248,61,100,233,170,140,66,27,177,253,40,208,209,143,4,27,108,105,166,136,60,8,218,119,168,182,107,8,119,5,118,31,219,43,94,70,182,91,68,254,135,245,212,250,26,105,156,109,180,133,177,249,140,89,130,79,55,31,123,18,154,42,191,139,9,240,237,151,107,173,188,134,243,132,118,79,249,197,52,29,174,60,127,48,203,213,101,118,178,117,92,200,49,217,119,172,213,150,231,103,134,168,200,159,174,105,85,8,72,53,243,196,179,102,171,173,207,190,134,186,250,180,231,155,193,203,81,248,175,8,196,145,73,186,178,63,177,60,238,12,42,169,79,173,245,76,171,131,19,102,237,156,201,116,42,209,167,158,198,227,114,197,227,182,212,229,151,110,140,149,239,82,124,137,145,167,26,54,159,102,237,132,139,121,181,115,78,145,179,231,40,243,114,107,190,126,230,152,86,21,43,130,126,87,172,107,120,215,174,119,95,238,138,107,162,109,30,0,156,48,191,59,137,171,39,151,249,219,16,202,29,186,7,225,198,202,213,119,26,30,46,66,61,154,127,212,160,121,30,139,137,77,16,197,1,225,23,181,190,52,124,88,224,250,45,111,131,115,99,26,188,227,244,207,13,101,230,130,96,187,90,109,141,203,246,150,213,238,2,180,162,199,113,129,255,97,7,65,101,37,145,166,70,193,39,68,86,45,6,162,80,189,182,147,237,204,108,173,114,12,139,6,79,110,178,50,39,17,113,41,178,217,61,88,132,240,93,181,152,170,7,71,170,146,115,177,209,87,215,16,157,38,76,45,46,220,16,103,58,125,32,153,241,187,154,232,13,56,84,165,56,94,8,6,118,36,14,96,65,93,68,50,208,97,85,185,103,1,161,83,67,194,38,128,76,181,204,102,151,40,72,219,119,58,243,206,0,99,50,157,241,110,31,75,39,89,181,28,80,34,47,54,40,145,0,60,100,212,148,16,35,19,189,130,103,237,1,19,109,241,72,134,148,103,72,23,209,106,186,211,41,196,18,76,23,75,122,68,251,50,11,252,232,52,72,57,5,52,226,217,252,184,71,71,112,106,214,93,60,250,235,235,115,148,64,183,222,82,158,135,135,145,153,54,138,126,116,216,66,235,51,100,7,1,111,11,231,57,153,174,195,76,173,195,2,137,227,217,61,109,233,31,68,5,179,235,72,80,16,191,118,37,76,119,131,246,39,251,58,127,172,229,32,135,167,216,216,39,54,7,180,45,236,44,47,186,218,5,45,145,201,222,24,126,214,198,237,218,245,74,159,119,201,233,27,224,213,175,46,43,252,104,209,254,53,126,25,166,190,157,66,64,23,226,4,74,69,28,42,238,195,233,33,1,64,116,16,110,32,81,97,57,242,250,108,13,200,31,184,115,30,190,65,111,225,197,90,215,174,221,193,216,165,11,16,3,153,141,181,161,223,213,141,64,243,41,33,65,208,245,48,203,171,242,234,120,183,57,60,85,83,188,148,249,94,62,178,164,119,223,137,180,49,184,166,120,134,127,76,230,216,208,161,5,42,237,196,235,114,222,23,134,110,242,244,163,1,42,228,3,251,93,156,48,46,154,200,19,163,205,213,250,142,212,14,156,210,48,20,148,235,204,232,128,21,3,100,38,184,230,249,138,117,207,253,60,79,102,174,115,184,21,102,194,116,47,69,98,110,200,73,248,186,30,220,75,239,155,228,138,141,255,84,179,127,17,124,167,107,102,248,93,59,11,170,167,110,129,228,140,41,111,215,131,169,31,210,192,131,220,50,29,241,34,235,141,60,96,178,83,126,109,14,186,209,248,63,130,108,186,180,105,95,192,234,29,87,8,197,153,103,55,13,10,116,247,40,153,54,84,199,120,69,98,185,228,4,234,107,80,168,240,218,9,114,58,196,150,245,120,244,210,164,160,201,55,20,40,135,138,179,149,228,199,157,192,174,190,79,35,154,208,104,215,44,229,241,125,186,156,42,60,224,60,98,79,40,64,126,207,165,212,10,115,54,25,33,126,58,236,50,194,209,149,85,111,178,89,79,15,60,227,54,174,229,243,135,42,102,50,171,254,95,21,247,31,125,0,215,95,9,254,115,158,204,23,106,103,28,139,202,110,125,119,242,110,213,56,152,116,42,49,235,231,28,252,0,141,119,191,200,51,122,183,74,56,200,99,174,153,239,174,227,16,247,241,53,17,43,147,201,28,236,24,172,158,183,250,239,232,109,178,138,191,154,85,92,101,93,173,175,120,149,115,204,109,250,109,193,172,203,85,254,72,122,109,173,97,223,35,161,59,23,39,177,164,124,186,70,76,36,143,143,79,179,160,167,125,30,112,233,209,141,126,247,37,119,77,159,6,86,22,186,250,64,148,109,116,69,157,161,219,213,126,74,234,55,4,74,150,191,164,59,229,208,73,147,153,74,155,93,93,177,111,177,180,36,107,46,26,222,118,125,41,31,110,95,84,199,96,81,223,99,229,230,111,208,187,44,207,189,197,162,155,118,66,246,102,5,157,180,61,121,27,171,235,38,194,219,47,109,32,238,247,114,130,158,184,151,243,155,87,210,50,16,172,39,124,229,145,237,44,49,206,229,30,118,171,255,129,65,10,175,28,62,65,30,217,20,113,253,179,149,240,28,118,112,140,20,237,39,7,159,242,230,64,144,209,53,33,213,116,176,141,135,111,225,244,248,107,202,235,131,88,130,60,113,17,151,144,193,21,155,78,5,33,221,177,64,101,141,166,1,217,83,16,24,8,33,203,8,73,180,252,201,36,37,193,112,158,81,36,62,12,87,125,150,121,19,39,92,191,173,210,244,36,77,195,88,140,26,156,4,231,27,111,89,251,35,188,185,246,75,176,127,162,75,144,137,255,124,36,161,108,144,154,177,88,19,197,21,51,61,242,175,177,115,118,58,158,40,174,196,158,97,198,184,209,36,126,232,71,189,204,186,7,102,36,124,234,204,89,172,220,192,86,101,51,175,40,9,191,17,115,155,117,200,237,22,138,77,48,250,240,160,224,117,133,170,182,144,213,211,213,2,243,145,65,254,0,2,248,48,33,249,80,119,29,108,76,228,213,3,143,250,23,23,131,183,155,60,55,214,27,114,225,198,150,10,35,148,123,109,118,26,2,65,205,51,165,231,113,146,183,118,99,110,128,192,107,84,128,130,68,16,88,195,165,35,170,219,153,195,92,132,226,34,20,77,81,240,139,150,107,214,77,155,204,106,79,19,168,44,71,198,240,87,142,60,44,60,246,5,116,90,243,72,82,123,206,123,164,157,159,113,100,46,227,97,151,247,172,49,26,253,214,112,110,75,191,20,199,178,121,153,73,146,167,80,165,179,249,104,118,42,76,8,126,200,69,25,1,35,35,219,85,218,235,253,164,63,211,195,178,60,208,120,222,151,167,79,238,35,131,109,53,18,149,50,40,14,206,218,230,111,82,234,124,19,223,6,18,94,196,199,189,219,79,203,3,86,63,184,11,70,220,145,70,39,204,13,70,25,105,99,18,2,0,24,161,197,244,35,162,11,157,34,54,196,92,138,255,30,83,77,170,69,196,207,11,28,60,155,7,88,6,248,72,159,21,242,123,4,244,230,249,74,32,130,186,174,143,2,140,24,130,73,170,186,195,129,0,221,95,213,21,27,147,128,194,103,91,111,210,249,82,200,180,140,107,187,79,132,95,135,105,220,39,219,47,101,130,232,19,153,84,96,21,214,227,184,212,26,88,77,22,173,250,215,51,120,214,55,206,86,220,178,39,170,15,114,12,97,98,239,4,124,47,250,230,133,149,196,82,209,165,151,0,207,30,106,133,62,251,241,196,196,47,179,145,179,2,155,15,5,165,22,67,52,207,39,246,123,134,219,252,174,231,168,82,8,7,192,229,168,45,215,86,100,235,111,169,107,12,249,89,109,86,160,142,181,238,237,223,92,168,130,150,236,224,116,222,45,18,13,13,164,73,38,27,208,24,138,45,80,4,148,58,149,54,128,230,244,22,230,218,179,87,51,104,223,178,9,209,228,14,206,192,249,41,82,34,115,235,125,150,192,196,1,165,252,62,83,243,157,37,218,134,192,149,232,139,145,253,205,51,17,97,192,121,157,60,181,170,126,156,5,44,196,235,223,123,170,2,118,228,255,243,8,132,196,221,30,242,92,159,112,180,131,51,25,126,253,184,7,4,110,34,217,37,185,91,186,44,77,80,104,181,58,171,9,210,180,17,119,8,141,229,247,64,62,232,121,118,112,133,52,173,5,202,94,170,37,212,28,222,193,97,51,164,107,197,181,220,102,52,58,47,147,194,179,174,14,89,19,221,145,39,174,86,249,64,89,192,101,143,207,156,186,210,1,137,143,225,13,38,98,59,92,137,53,31,64,212,100,157,144,100,131,3,65,115,94,185,87,13,25,176,45,184,207,19,250,197,231,86,217,51,191,125,60,11,95,125,105,236,148,166,54,6,42,0,150,180,138,38,30,235,72,106,14,217,69,184,242,46,197,173,38,89,234,41,197,213,165,79,86,118,231,142,207,69,207,108,20,53,179,160,231,84,99,156,253,80,13,15,65,18,73,160,149,31,76,124,141,4,48,207,86,81,87,66,32,121,213,115,116,230,240,201,247,195,159,66,154,244,180,174,14,101,84,3,66,175,40,177,65,194,101,162,234,26,55,222,21,72,164,219,243,129,30,172,104,212,50,6,152,90,233,235,35,221,207,165,225,44,109,74,127,123,173,56,87,209,84,211,48,214,123,5,105,101,78,188,169,175,36,172,214,19,232,125,217,130,252,99,237,244,61,173,193,82,209,216,57,13,12,202,82,193,78,70,69,206,74,240,191,91,25,179,254,242,177,68,23,139,165,101,32,52,246,25,212,240,38,237,147,60,156,190,36,3,56,163,125,228,107,228,6,235,44,250,90,92,77,158,36,217,168,161,77,26,49,125,99,103,191,115,41,120,16,231,243,69,108,169,115,81,127,195,48,164,132,75,173,147,62,148,220,3,189,186,165,200,86,60,18,172,193,207,129,196,167,69,181,134,232,130,109,48,76,133,202,38,184,207,153,39,149,26,4,242,77,59,193,254,102,222,99,68,91,147,245,252,14,111,57,224,121,244,233,148,97,66,37,162,181,44,60,144,184,181,187,204,143,33,120,225,243,226,97,190,168,25,134,240,146,145,251,166,104,183,243,126,93,104,93,84,55,148,49,84,30,71,204,203,236,226,179,113,247,64,213,92,207,126,35,130,231,86,232,149,34,79,127,8,155,120,228,29,247,142,10,151,52,57,180,40,56,93,99,171,253,160,143,201,101,183,204,59,240,23,208,83,198,151,231,231,147,28,110,4,156,102,57,157,18,249,18,50,20,130,56,53,156,41,45,170,41,117,136,179,222,121,239,18,168,166,237,2,237,98,107,148,236,81,60,2,33,181,218,46,71,254,197,234,84,204,80,27,160,118,123,153,37,55,238,240,199,98,227,116,197,126,232,21,255,98,226,206,152,34,211,121,85,69,183,195,225,202,232,188,79,208,206,156,187,96,21,189,252,76,203,227,241,70,211,61,52,217,12,33,243,41,50,152,77,47,82,19,140,197,235,100,59,65,70,115,52,246,95,80,145,224,57,224,221,213,78,145,49,47,117,102,248,205,92,84,18,215,150,191,135,145,62,36,193,200,52,133,187,34,96,149,139,1,97,248,25,51,64,247,58,93,111,15,225,212,223,114,61,92,11,95,154,153,245,208,78,148,39,150,34,40,110,50,154,11,54,4,145,21,134,166,233,0,193,39,105,2,102,29,28,168,238,231,117,248,142,40,50,56,142,240,142,165,151,16,85,30,155,98,225,239,177,187,143,215,228,29,118,98,85,69,167,21,45,116,143,40,42,152,1,87,158,139,169,81,137,18,54,65,178,145,44,82,225,241,84,208,111,202,139,17,95,107,130,255,148,105,65,106,172,230,171,55,197,239,133,168,4,152,247,235,19,138,175,168,216,216,171,23,160,83,71,40,126,234,228,1,76,145,9,132,135,166,202,190,232,233,218,105,184,138,161,252,19,33,132,61,159,183,129,62,37,37,194,79,104,59,218,204,215,82,166,4,190,36,224,43,97,59,71,51,188,214,175,54,18,10,15,153,110,203,218,59,225,113,185,123,75,111,206,104,24,163,254,170,85,40,105,9,229,41,218,37,240,211,103,89,253,97,34,77,188,114,220,132,215,129,26,109,149,186,128,119,108,19,20,122,172,175,10,20,169,9,104,195,150,51,8,159,140,86,232,226,177,7,196,200,167,207,106,126,27,140,222,219,198,149,46,0,13,93,255,121,205,23,206,245,185,247,15,231,173,156,59,156,16,48,118,254,93,148,203,237,189,158,180,101,52,62,155,57,8,175,171,215,67,69,104,60,72,232,226,185,20,206,65,59,42,125,90,124,100,202,134,141,239,191,110,203,164,223,50,232,219,4,222,205,22,70,62,180,75,143,174,228,44,62,245,202,39,117,215,33,145,80,106,131,177,244,66,46,89,167,198,251,80,38,72,190,90,118,85,34,158,83,17,61,132,124,53,24,63,24,90,249,68,131,245,198,183,117,13,157,137,70,189,73,23,75,77,13,25,88,126,217,87,108,92,8,133,154,15,158,112,113,94,186,162,177,9,232,181,162,55,24,38,161,79,176,4,233,11,158,170,242,240,168,77,25,3,223,158,186,182,26,129,84,106,135,108,205,79,254,175,227,1,238,248,79,5,72,169,217,128,158,1,139,110,157,12,39,55,95,3,2,113,179,81,229,38,144,253,35,77,155,97,157,9,47,133,35,238,97,246,176,156,164,3,236,181,42,140,173,1,46,164,218,168,228,127,219,160,224,59,249,247,7,155,98,77,199,215,146,55,151,221,185,163,241,26,122,137,164,190,205,207,4,237,134,165,74,238,223,226,15,248,242,139,107,210,187,234,4,145,23,231,180,229,53,254,166,201,220,10,14,58,33,230,72,92,230,207,170,109,188,229,137,28,147,22,41,192,213,40,215,216,127,14,228,9,13,85,247,106,247,1,155,206,136,4,23,190,148,170,106,194,155,170,96,227,85,168,247,195,20,113,172,17,34,38,123,79,167,110,206,207,53,66,173,162,178,166,84,120,160,160,218,186,227,34,87,100,212,219,28,84,255,59,138,26,28,227,102,205,94,75,152,55,216,163,46,225,96,152,57,32,57,159,27,251,178,201,231,5,139,31,163,136,69,71,125,19,213,46,252,84,88,215,163,249,153,181,25,227,174,4,105,93,98,251,60,164,4,222,26,165,85,83,87,45,206,132,134,6,108,89,96,76,139,144,143,144,116,59,72,48,184,248,230,195,135,167,29,166,42,207,49,87,221,159,42,168,96,157,181,125,152,96,130,72,48,100,105,145,96,98,200,116,7,131,166,69,99,117,55,141,40,125,106,249,33,118,191,121,159,138,79,27,90,132,13,52,0,61,44,246,212,77,127,107,26,124,234,104,26,14,238,68,79,124,247,99,81,60,135,27,62,83,231,104,214,53,69,104,188,95,120,30,105,222,150,218,223,80,221,209,86,113,125,226,123,36,1,136,94,206,253,124,34,218,2,77,208,172,39,238,148,151,111,237,3,135,99,41,22,142,129,39,56,105,255,31,62,12,171,5,206,94,114,13,174,185,89,199,225,131,239,187,92,132,102,86,138,156,36,55,112,65,191,209,70,60,75,110,59,216,180,148,36,118,238,139,97,222,17,236,209,68,163,76,177,206,58,196,113,2,166,47,131,113,199,180,134,23,174,24,119,20,124,144,29,221,9,90,224,188,131,232,13,244,94,200,129,51,27,11,124,24,154,5,91,171,150,238,212,117,175,71,155,110,168,3,236,162,196,193,74,101,6,238,157,132,151,181,88,122,26,84,194,170,253,198,124,142,133,185,66,4,105,5,152,87,209,178,134,243,242,197,214,209,103,53,218,128,193,9,83,231,55,111,29,235,133,45,107,115,71,203,15,1,69,200,105,216,1,163,183,18,222,54,6,56,48,104,228,237,119,166,90,242,184,97,160,218,194,255,151,131,120,180,104,202,167,157,179,147,77,161,34,65,201,171,236,177,175,0,92,134,255,40,217,133,61,187,44,165,109,184,127,37,189,61,62,60,232,182,210,78,123,118,207,185,156,158,77,117,67,26,37,222,174,87,192,241,152,180,170,218,35,86,86,91,87,98,97,192,129,140,194,233,36,79,152,203,136,73,223,63,26,117,190,88,188,60,42,9,45,54,223,198,207,196,237,26,244,60,233,67,132,223,113,147,253,16,126,10,119,41,159,99,237,109,167,23,248,146,7,166,214,75,0,234,202,90,254,26,71,82,240,116,216,96,236,109,46,104,255,134,115,253,155,36,36,129,188,183,140,151,14,153,244,139,244,252,214,160,8,249,226,35,58,185,116,255,126,128,120,235,190,225,169,185,175,255,64,176,56,247,249,7,18,39,92,249,142,98,47,116,247,126,6,66,208,245,253,217,123,160,123,49,99,18,90,47,9,80,207,212,123,18,61,155,193,44,242,205,146,4,96,210,222,194,220,47,172,241,165,29,155,45,163,105,121,174,115,233,211,216,182,136,24,90,234,77,214,70,94,160,35,59,16,39,71,24,186,43,251,99,53,11,47,60,159,24,144,250,41,114,90,26,97,209,154,96,63,178,67,28,211,107,179,90,253,127,165,163,26,175,163,165,60,47,25,151,210,245,25,91,122,31,176,184,179,128,161,75,71,166,119,40,19,58,101,115,237,145,211,239,250,235,224,4,46,64,94,118,213,191,21,42,27,169,75,217,193,182,121,215,57,216,234,245,160,135,78,21,125,113,51,250,39,177,32,227,61,57,182,118,16,212,181,130,153,240,62,148,127,188,127,160,37,3,231,33,68,181,179,95,116,179,14,247,145,214,104,222,71,140,17,161,171,218,105,81,195,25,20,202,235,110,70,90,42,47,194,109,74,85,60,77,65,92,205,106,16,171,147,0,227,16,251,48,224,101,8,46,29,94,50,36,213,78,254,13,7,254,227,219,219,18,45,213,145,136,25,210,42,32,47,62,61,139,31,140,17,210,249,37,178,80,160,59,139,26,250,178,179,208,129,81,82,239,54,209,224,20,156,174,251,26,130,136,28,68,243,28,42,28,17,51,90,6,39,125,11,249,223,165,193,243,148,129,17,210,146,186,89,202,253,59,205,5,52,237,17,181,104,92,54,142,214,177,178,59,214,195,73,72,186,175,17,1,0,220,146,69,144,120,89,133,146,152,239,230,141,237,0,78,250,117,54,179,45,38,167,90,149,136,233,115,8,227,210,205,255,208,177,5,45,173,12,189,122,109,122,136,191,40,176,51,234,201,4,208,42,147,44,56,120,17,43,69,93,97,143,103,130,166,129,101,7,40,85,92,157,218,212,230,114,139,2,233,64,93,127,49,140,232,168,194,0,74,215,40,158,61,12,247,57,151,103,148,42,210,155,139,211,87,19,0,208,70,224,199,34,241,199,70,169,161,135,61,105,233,172,62,114,0,96,15,45,231,45,55,172,39,55,41,225,133,190,138,162,53,142,120,95,183,32,192,36,208,155,102,233,86,61,53,30,206,83,199,125,72,101,207,29,247,104,10,148,18,184,234,165,202,151,116,193,119,185,112,23,192,20,152,65,174,8,254,94,56,95,112,30,175,131,75,160,36,26,226,61,55,97,225,40,77,212,181,0,239,155,198,208,128,240,202,248,190,135,42,46,22,94,11,61,30,199,55,16,98,142,1,63,173,36,147,172,74,152,45,239,201,204,46,115,27,81,227,120,112,155,184,99,79,214,130,147,122,64,139,9,147,208,82,76,15,123,98,5,74,218,198,40,175,162,34,226,243,95,227,126,94,45,242,141,118,9,49,66,13,62,135,201,56,200,96,255,212,204,11,3,243,18,242,108,74,227,62,173,115,180,224,226,248,249,141,136,245,6,158,110,65,8,248,189,225,236,226,84,45,8,72,133,12,176,12,140,172,135,245,88,80,88,0,185,175,79,207,75,134,219,100,194,29,255,125,135,114,8,126,63,172,235,145,65,229,120,37,197,36,66,254,60,122,61,197,192,6,79,197,152,198,219,179,231,14,155,211,69,154,175,209,49,59,91,6,25,138,1,144,199,28,148,67,149,19,37,147,101,173,173,206,196,37,179,47,184,185,251,43,182,74,221,246,66,82,220,131,113,87,197,241,66,226,95,156,93,186,196,250,229,244,248,189,22,207,27,43,104,3,210,183,207,145,95,190,74,251,145,107,71,36,138,225,83,79,207,145,78,210,137,175,90,23,239,94,181,98,41,136,109,211,114,150,87,255,49,149,169,69,132,65,211,140,205,214,29,22,127,210,12,110,19,72,139,152,200,229,246,220,110,222,227,189,5,36,90,254,53,6,237,122,57,142,108,23,90,140,146,218,237,207,124,148,18,43,1,231,98,177,83,35,133,156,57,105,201,222,84,80,168,12,176,33,62,83,81,72,91,127,176,136,94,105,255,254,90,145,155,68,132,45,203,4,81,16,2,218,66,189,227,170,31,12,196,122,121,143,12,99,122,129,195,234,210,79,14,55,209,162,72,6,182,66,57,203,144,165,124,104,28,239,250,145,78,30,73,201,115,103,29,184,58,64,70,85,21,63,220,48,82,120,182,147,193,160,57,159,29,228,110,185,119,116,208,106,226,116,121,81,43,222,244,81,208,45,54,252,92,150,203,97,118,228,145,19,251,135,68,118,217,134,205,225,179,191,233,152,12,91,197,183,100,112,245,155,90,49,164,31,226,11,161,97,101,12,52,104,87,67,185,88,236,186,244,207,7,33,67,86,181,69,233,84,8,132,228,204,119,32,165,140,91,72,140,72,59,85,160,243,119,182,101,202,174,103,225,103,157,66,245,6,239,65,118,228,82,220,95,37,111,101,138,161,191,68,163,207,254,132,5,33,34,56,45,15,145,79,100,40,250,236,235,36,175,245,20,209,154,13,198,149,155,0,80,11,84,80,172,105,217,187,232,7,132,48,231,150,103,105,189,165,83,77,153,247,75,244,46,186,175,219,208,150,199,180,28,58,132,148,105,13,207,113,32,133,101,252,13,167,207,239,200,38,246,25,126,101,156,150,20,134,155,28,193,203,237,91,8,31,34,172,248,160,57,105,219,239,42,133,226,116,81,43,132,235,167,30,68,43,231,221,164,52,182,249,179,61,153,161,159,137,151,189,73,236,246,163,36,98,19,85,248,126,173,105,179,75,212,179,6,192,100,128,153,211,199,108,66,203,86,207,169,95,199,34,119,154,244,10,13,220,112,98,175,183,40,113,55,27,57,116,86,1,170,179,54,173,252,94,178,69,116,19,143,251,130,194,112,136,117,223,38,229,127,85,195,14,156,30,223,71,155,223,129,124,152,171,136,110,120,95,180,53,100,168,25,3,216,42,54,85,46,69,119,107,155,145,251,64,53,185,193,15,13,139,6,167,11,60,47,89,97,48,152,126,89,204,146,71,95,57,111,150,78,240,251,102,115,113,11,147,15,192,253,231,25,248,245,109,134,153,56,58,101,46,144,2,253,31,2,83,198,61,64,121,63,76,80,67,29,12,66,28,147,254,92,69,68,35,212,156,221,161,237,249,146,56,121,137,145,156,246,183,247,139,124,62,163,212,103,229,186,93,174,69,23,160,26,196,181,43,175,176,60,110,211,55,131,146,61,179,46,79,154,194,63,7,77,202,244,150,202,18,92,217,129,241,239,222,111,51,135,13,231,255,23,171,205,2,165,228,225,46,247,213,245,181,190,140,154,241,182,186,251,24,83,159,137,53,64,138,170,164,60,147,27,90,82,193,36,201,173,182,188,108,188,229,45,193,211,18,253,200,185,25,95,180,93,30,219,69,195,239,222,97,161,110,214,36,114,96,168,76,77,164,53,131,226,197,100,0,42,106,159,84,214,55,249,124,216,170,102,155,118,134,77,181,65,115,14,167,123,89,46,212,228,181,29,222,148,86,228,253,74,236,231,197,148,188,137,167,27,127,12,253,186,84,67,146,211,91,131,122,218,230,239,254,175,168,1,213,249,121,7,221,136,146,201,36,166,47,73,221,190,128,205,126,206,89,121,78,233,57,64,136,20,67,198,178,249,191,17,131,33,149,197,130,104,170,130,142,237,246,170,147,192,156,248,187,123,25,225,139,220,171,61,24,24,114,110,77,3,160,244,82,56,94,113,16,27,118,228,217,56,29,253,10,75,145,97,193,150,89,210,52,60,146,17,127,187,216,5,195,108,15,251,39,157,158,86,49,193,199,155,106,6,73,80,247,203,61,88,81,56,93,158,179,40,245,81,68,136,69,32,237,101,122,112,165,100,55,9,127,59,26,9,41,16,102,92,246,179,125,108,231,225,63,120,88,135,69,195,239,197,51,245,72,72,59,15,231,42,3,184,123,64,176,64,2,15,246,220,67,193,252,8,159,56,20,44,137,45,172,109,183,204,159,101,6,17,221,228,44,160,69,242,153,202,128,203,12,4,126,92,35,50,234,50,118,36,235,41,31,25,142,113,24,62,9,95,20,19,50,125,158,204,53,186,86,53,189,102,153,228,219,22,2,99,14,143,147,221,199,23,113,107,196,224,225,104,121,99,34,19,112,121,28,191,160,245,10,17,84,184,88,225,151,167,54,240,195,72,254,120,18,22,155,131,146,29,227,234,30,101,250,135,69,125,243,191,220,108,252,27,73,15,229,136,53,207,18,173,204,19,205,199,182,167,225,33,249,143,99,91,17,55,149,227,252,128,238,114,212,169,242,145,36,176,68,219,87,139,157,11,63,61,59,211,206,153,189,127,223,109,58,97,39,141,146,29,253,92,94,80,25,18,106,154,118,230,19,134,225,160,83,60,150,40,14,114,137,33,215,197,110,48,190,240,56,91,138,248,129,37,247,39,83,175,2,103,194,229,110,102,216,12,120,6,3,226,163,55,78,249,252,111,226,91,6,137,148,130,47,48,247,229,23,243,182,71,150,137,124,20,124,66,139,32,193,148,161,185,236,79,174,99,200,112,53,55,117,29,34,237,204,153,30,100,212,1,178,63,101,108,21,60,226,164,189,178,191,164,14,130,253,211,82,162,209,199,23,248,243,208,248,249,158,141,215,199,86,0,246,74,146,131,115,160,41,65,31,203,224,248,194,77,33,67,47,171,200,140,46,76,21,188,172,177,183,243,246,224,185,32,56,122,180,233,201,25,233,15,85,45,133,25,16,136,35,136,145,142,15,86,80,133,48,119,224,178,65,40,193,213,90,108,89,160,56,151,217,217,57,103,175,63,242,81,89,154,80,29,72,39,62,162,124,64,207,184,236,170,24,70,121,44,61,235,14,3,108,68,201,57,178,69,188,58,91,211,235,251,154,69,34,123,86,213,66,253,253,216,176,67,99,197,91,185,250,198,244,215,134,106,130,27,155,101,61,23,181,173,83,247,184,185,24,221,87,94,129,150,24,83,250,180,99,14,23,157,95,133,189,98,219,252,120,118,181,213,41,131,138,220,245,32,75,155,209,55,31,197,21,188,175,14,108,96,144,219,70,87,169,105,80,215,39,54,253,164,135,220,113,179,11,26,86,90,17,173,82,168,51,234,219,159,197,190,211,12,96,163,96,156,21,216,237,81,71,8,238,177,222,65,238,18,207,224,198,6,78,77,58,229,128,113,49,80,53,64,60,188,235,183,243,253,19,186,159,48,179,25,11,199,176,100,249,48,94,85,170,164,215,111,157,248,47,235,115,199,148,241,90,5,156,158,194,36,48,2,128,54,251,107,121,73,162,149,9,148,65,58,167,164,203,170,52,197,196,44,120,167,22,204,41,135,101,200,149,248,38,73,57,71,205,69,158,255,72,185,219,30,199,49,162,53,242,190,45,142,206,11,94,30,40,120,221,10,171,209,31,64,30,69,102,138,222,180,169,4,28,97,34,15,174,50,15,217,31,255,141,56,24,233,173,156,216,252,142,255,94,59,43,223,147,253,34,44,189,10,93,55,252,67,27,40,123,12,243,5,33,140,234,16,240,115,171,26,131,179,201,114,216,135,196,14,204,11,226,91,159,139,238,182,65,152,10,212,173,146,189,31,16,197,251,214,140,176,101,41,217,127,19,65,118,112,116,119,159,28,52,102,175,254,92,132,73,106,70,124,121,229,34,136,208,230,102,14,165,73,4,170,233,83,76,138,148,54,152,21,227,68,40,188,180,162,79,72,48,228,26,205,64,66,33,171,221,163,170,114,114,184,172,219,201,168,200,24,77,52,12,80,226,95,105,205,101,189,221,3,5,202,38,226,148,208,76,126,116,245,120,125,186,56,187,96,82,46,133,211,10,66,86,187,156,137,23,160,98,171,226,232,11,114,200,18,250,211,87,122,21,93,163,90,104,194,160,53,194,74,207,94,195,91,24,76,184,136,174,136,22,245,12,54,167,76,106,249,48,251,40,188,97,95,223,30,22,142,194,231,189,143,57,151,51,105,150,197,223,211,167,34,90,118,91,128,229,236,240,185,96,234,208,26,179,111,122,244,232,80,12,38,10,75,30,38,189,236,165,19,26,106,197,252,71,235,185,204,73,177,213,143,142,148,0,198,150,67,125,250,112,233,80,164,49,60,6,157,40,93,68,163,97,177,11,138,69,11,80,35,151,37,226,112,83,104,68,199,208,112,120,18,122,5,174,225,120,249,246,187,239,139,207,193,43,156,214,226,0,98,218,49,189,224,164,249,146,98,223,125,50,17,156,249,81,199,227,5,93,233,167,93,238,114,241,192,104,44,145,2,60,79,168,0,112,62,78,120,31,150,105,225,33,243,194,10,247,239,80,186,67,248,147,112,190,206,149,49,185,35,4,129,193,254,128,152,100,164,105,79,44,168,54,203,1,129,230,43,92,174,4,56,200,148,20,82,211,212,136,193,83,214,240,81,138,39,11,132,114,55,99,194,4,143,40,233,177,238,255,46,166,183,5,115,190,182,171,253,136,6,248,32,219,26,252,55,109,189,224,176,219,6,131,136,170,148,101,102,58,242,121,97,120,125,146,126,232,251,70,200,193,191,199,169,112,172,43,218,147,205,17,215,99,9,141,194,206,149,104,71,115,45,250,190,121,28,115,88,81,131,250,172,238,160,98,146,119,165,113,166,10,172,34,174,43,44,119,114,32,110,169,188,210,22,181,71,3,8,218,196,202,103,105,234,72,209,168,202,3,206,120,58,52,91,169,202,207,73,67,52,223,246,40,85,129,186,17,147,193,231,46,110,139,178,74,210,186,252,20,42,212,66,107,31,239,184,60,105,247,138,212,29,59,35,147,239,109,123,57,144,11,149,66,71,134,57,20,223,47,197,51,83,184,140,102,217,213,245,43,232,173,139,129,135,141,23,147,64,170,6,101,154,52,47,242,34,140,3,101,199,41,95,122,146,104,251,210,114,60,120,85,93,235,23,132,185,200,46,225,58,185,30,23,139,234,67,231,176,36,70,216,129,111,57,23,74,254,117,89,199,41,209,178,61,214,211,184,105,167,86,249,49,90,42,123,168,58,104,222,200,67,41,108,0,17,167,116,177,110,201,116,233,182,36,97,100,6,194,14,109,98,123,229,192,135,60,139,212,178,229,24,178,75,57,129,64,124,38,73,23,182,0,233,69,40,62,242,69,133,151,96,88,46,115,166,144,227,171,12,67,150,150,224,205,128,11,68,98,7,65,199,98,217,18,163,103,246,75,237,111,191,192,188,237,204,240,118,109,98,193,54,170,132,185,37,96,110,213,152,18,190,35,50,82,137,93,149,215,225,221,42,90,5,238,158,171,51,61,216,167,102,11,175,66,32,95,200,136,58,38,185,31,31,7,154,137,77,199,135,129,68,11,138,218,56,51,63,138,232,178,118,35,168,128,222,75,254,4,133,240,20,138,225,42,242,179,147,238,252,236,171,207,216,158,161,187,121,28,211,191,97,168,90,83,211,109,149,65,124,180,9,172,11,247,233,144,178,35,236,201,59,110,14,121,70,14,224,61,254,78,212,28,174,65,117,240,197,140,63,81,231,180,236,142,119,35,45,55,146,227,92,243,89,103,227,113,113,7,241,196,218,216,222,133,210,176,201,227,29,129,190,164,242,224,9,230,82,122,179,114,75,246,39,15,229,149,39,223,54,20,209,236,251,52,201,186,78,73,37,151,126,3,228,78,186,96,42,131,8,164,251,31,66,192,181,12,97,55,186,77,32,219,199,151,33,3,42,85,29,142,29,6,107,115,68,114,214,114,140,199,143,20,245,129,9,78,83,246,169,65,41,122,99,69,204,115,173,8,254,95,66,163,162,48,175,244,113,209,100,147,112,188,220,233,113,5,212,201,138,91,38,191,72,7,99,178,116,234,92,48,244,0,211,154,27,247,206,232,89,85,99,233,132,72,85,200,139,238,153,179,24,123,99,134,246,142,188,239,9,157,112,162,234,185,118,245,59,130,224,204,31,163,171,38,159,221,225,99,216,177,58,35,104,109,10,125,89,23,53,56,37,68,165,189,60,83,249,63,161,240,70,141,1,210,143,125,157,56,227,11,24,55,38,168,16,119,213,155,223,143,131,175,37,234,125,238,16,194,101,201,158,4,110,18,210,221,84,87,14,13,169,250,241,240,1,12,205,98,246,198,75,250,239,249,104,97,127,57,19,15,104,126,28,59,196,119,32,32,82,17,212,81,175,226,118,175,241,105,177,135,71,82,187,16,240,159,71,37,41,230,115,64,156,184,169,24,234,219,0,246,117,253,167,73,143,69,3,130,245,116,43,177,166,154,119,212,153,47,46,26,192,155,252,200,241,110,201,195,252,231,181,147,45,221,62,85,89,150,72,79,230,174,245,52,49,209,202,184,143,160,9,190,63,249,33,193,163,53,123,237,31,46,225,42,225,49,158,14,120,71,133,247,37,52,27,195,168,0,173,254,175,48,203,127,136,142,20,140,58,102,224,52,13,72,195,143,146,84,91,160,228,92,126,63,39,81,150,207,232,13,28,22,22,113,169,45,140,23,5,46,155,127,197,116,25,54,226,104,89,169,95,100,83,211,41,119,115,107,60,190,170,12,213,173,189,220,228,10,211,105,116,245,166,208,229,181,165,201,68,170,57,36,97,78,110,76,75,65,230,77,138,17,146,196,148,196,16,237,121,105,24,158,75,121,236,185,205,129,31,100,68,181,179,248,183,65,29,74,96,126,223,176,27,19,62,148,147,12,48,70,173,22,7,123,162,216,137,16,123,171,81,196,100,84,138,92,119,3,209,28,49,46,184,35,78,201,26,213,233,176,139,204,161,161,100,134,151,46,27,220,236,243,154,104,171,179,29,24,244,219,213,4,109,217,17,167,110,219,11,225,255,47,80,164,122,91,85,104,133,179,78,39,122,132,12,176,53,220,175,184,93,42,5,93,129,217,176,225,1,179,77,53,121,239,203,231,143,218,94,107,129,31,11,195,254,148,78,105,60,149,153,223,20,120,153,7,211,141,71,154,236,170,254,85,202,104,196,108,18,145,215,252,129,244,163,252,137,151,112,146,157,1,59,187,240,13,15,2,216,118,65,35,126,38,27,221,174,235,245,160,106,120,196,95,105,214,48,54,136,226,74,65,88,37,3,224,245,60,140,2,150,249,134,212,251,59,123,169,14,76,79,118,67,227,62,202,182,40,50,114,7,24,44,54,254,33,251,230,193,198,191,167,178,228,71,214,100,187,93,9,99,58,230,102,178,170,160,39,178,130,14,57,7,70,171,249,174,14,35,35,120,237,233,152,182,162,97,118,134,142,150,24,7,159,154,144,20,178,175,155,125,114,58,253,140,118,189,3,236,201,17,137,170,158,6,138,214,209,52,137,203,102,157,11,99,113,92,97,55,117,153,111,20,219,251,13,105,77,46,143,89,53,195,147,116,53,124,195,182,95,154,49,226,94,206,124,56,128,210,109,131,196,167,229,110,5,138,241,184,84,170,48,209,20,77,49,194,144,208,224,23,8,82,52,152,83,235,136,168,48,59,7,125,42,229,139,89,170,227,83,9,67,233,174,188,101,17,74,229,208,35,149,23,105,183,73,116,1,80,193,46,164,25,242,129,1,17,88,87,87,94,55,96,126,151,60,35,202,219,9,3,222,161,131,34,149,198,202,198,131,167,91,75,106,85,22,230,193,8,201,156,81,226,164,111,44,147,161,162,209,240,123,26,148,30,161,104,16,29,236,170,204,149,74,126,34,109,24,139,125,1,32,228,137,89,30,201,147,146,189,177,123,185,72,228,107,91,49,121,163,27,243,72,155,29,183,58,67,212,196,210,201,58,31,102,67,158,141,70,175,80,213,3,99,198,124,34,110,94,209,77,20,85,45,162,82,18,61,189,203,199,56,131,228,230,7,53,226,247,217,35,66,115,37,68,130,210,200,156,186,44,33,11,229,31,84,159,92,194,52,14,158,187,179,106,80,194,179,80,226,202,110,147,204,167,44,63,158,49,55,80,115,164,46,156,244,58,137,134,55,253,220,75,9,103,136,249,242,3,215,220,53,123,17,75,112,40,131,105,76,0,16,17,245,242,195,47,165,106,200,206,26,130,189,65,203,2,99,181,5,143,191,100,128,52,249,154,169,127,159,85,163,175,105,201,79,170,124,33,172,15,229,166,146,194,104,108,129,91,132,33,195,224,4,116,61,113,89,52,79,251,121,2,32,71,98,121,115,214,245,87,160,16,97,250,177,149,55,39,223,212,203,76,231,248,127,176,129,187,75,9,209,101,237,148,65,111,200,193,164,44,66,237,159,220,85,84,91,89,208,128,237,151,180,31,151,237,151,16,114,221,155,43,42,4,83,34,238,79,149,66,231,157,222,132,11,145,104,170,56,236,84,248,183,36,85,4,10,143,170,141,177,87,7,163,114,225,72,248,238,122,146,203,203,157,4,155,198,245,193,60,218,180,175,34,89,80,195,35,71,85,234,238,86,77,49,244,128,157,230,211,30,114,38,88,35,242,190,254,27,132,194,18,236,121,228,133,95,97,44,236,154,28,64,235,14,62,141,6,104,2,239,196,0,239,190,200,189,55,225,88,118,166,28,3,155,39,73,135,166,250,86,28,103,243,78,21,135,177,206,135,183,141,13,148,181,253,155,176,98,53,113,191,110,156,23,111,210,0,12,145,6,255,146,80,247,0,74,171,33,213,96,90,118,193,89,208,79,47,247,61,246,11,199,235,65,231,27,63,41,110,254,129,80,132,0,167,84,59,171,175,164,131,185,207,179,36,207,187,236,180,205,188,150,112,119,170,82,180,155,78,6,33,163,196,74,97,85,204,95,48,248,81,22,74,219,228,3,163,28,111,155,134,69,37,9,187,242,25,75,186,8,17,151,196,130,59,118,14,82,207,194,129,82,65,199,147,72,96,117,243,22,125,145,219,206,184,153,41,144,219,98,96,155,34,94,181,44,163,237,168,33,89,151,218,192,247,57,198,126,236,197,141,63,109,159,157,29,83,185,46,181,8,73,42,95,252,161,116,224,219,172,169,119,219,52,46,170,69,178,172,93,174,0,45,81,139,114,181,102,240,100,159,66,137,156,200,175,244,173,51,117,206,244,24,77,6,23,82,12,37,118,160,225,85,183,69,79,100,126,129,93,155,18,95,145,39,32,118,241,90,236,152,14,20,126,31,234,84,34,120,172,90,243,50,162,34,238,83,91,24,255,99,225,240,27,114,166,100,243,207,98,170,111,107,224,19,79,177,203,231,135,126,205,13,231,108,153,215,16,143,6,18,244,71,18,188,143,224,169,189,54,129,185,202,121,10,142,246,219,251,81,92,184,115,207,55,223,23,9,172,6,80,2,236,96,4,51,62,54,135,46,10,0,229,235,188,235,218,127,115,177,136,157,40,2,71,146,32,245,200,137,190,179,220,117,208,242,197,14,183,79,124,35,171,203,89,139,208,30,50,32,249,148,242,236,98,48,88,255,143,25,1,235,159,210,127,229,219,6,20,19,41,23,220,116,32,214,217,7,197,244,101,247,93,18,117,151,140,84,68,104,42,232,36,226,57,55,57,181,128,52,6,203,130,54,199,103,197,158,184,138,127,61,223,65,111,57,25,181,72,139,155,65,139,48,15,128,95,194,241,163,12,246,39,191,53,212,114,194,90,65,109,13,121,48,171,160,68,35,192,251,149,193,182,207,178,158,107,32,192,59,214,166,145,205,76,194,17,236,248,105,195,184,201,91,214,106,71,163,206,253,189,15,166,160,158,55,182,108,213,82,244,47,221,194,227,48,139,93,104,165,186,46,214,47,63,142,36,158,192,116,253,133,77,50,45,85,208,33,203,120,156,6,55,217,53,210,131,30,194,170,65,32,80,32,81,218,104,125,77,236,131,42,23,51,41,208,230,40,175,127,201,126,254,209,89,221,187,181,101,185,235,139,217,248,49,187,232,192,124,28,52,88,70,236,155,38,60,43,157,178,180,45,203,113,4,9,67,86,60,136,52,5,61,152,126,254,205,152,68,61,64,58,226,75,218,19,204,177,16,138,148,243,180,234,110,6,134,194,139,167,50,151,95,62,160,137,209,208,255,81,199,177,240,114,1,163,160,235,235,172,203,57,245,240,94,121,56,11,132,16,23,152,180,38,90,26,107,103,77,223,70,133,160,220,55,161,159,238,135,127,195,39,208,86,53,94,195,241,255,207,90,238,9,252,64,51,154,107,238,114,42,193,58,242,19,108,172,209,86,71,42,197,80,100,152,114,254,57,174,37,64,50,36,160,251,173,106,84,18,16,170,209,101,166,151,240,142,96,134,97,50,207,93,244,231,22,49,72,181,188,188,85,53,41,160,158,84,157,23,30,169,226,115,33,73,115,107,143,0,226,138,147,191,74,190,144,231,29,158,45,154,232,182,228,53,105,112,118,75,176,179,123,111,233,14,139,90,157,138,223,14,191,88,106,91,191,149,119,119,125,12,238,211,244,188,43,214,146,153,165,147,172,221,81,131,160,19,124,234,236,188,144,176,73,96,127,208,169,247,17,186,160,163,61,186,59,233,72,217,58,90,43,43,23,250,105,188,236,66,19,98,125,250,90,130,162,167,174,46,218,37,184,26,92,237,34,0,26,104,74,167,221,23,105,113,9,187,125,231,185,93,92,121,93,23,185,54,19,90,235,249,3,121,58,43,88,53,140,51,45,206,210,228,223,67,147,216,82,11,167,178,164,218,132,152,116,134,84,112,15,165,106,15,116,46,222,118,186,76,133,157,255,99,27,35,96,230,14,223,36,164,244,30,234,71,169,225,124,239,103,239,185,44,71,223,241,177,16,211,173,64,220,127,244,65,244,249,195,214,90,121,43,248,177,241,128,96,74,224,104,16,53,79,225,14,219,175,78,129,103,35,184,131,156,66,49,75,196,237,145,109,124,157,74,188,157,84,32,153,170,210,235,165,6,155,60,118,114,50,169,40,37,1,220,122,220,107,20,39,19,238,244,128,227,140,103,0,179,250,11,140,38,165,57,63,111,193,84,165,175,223,21,24,232,153,190,211,114,99,96,103,146,32,24,107,66,117,93,27,243,49,114,246,219,30,34,20,17,69,183,243,131,101,22,123,146,89,58,14,130,29,141,36,211,54,162,164,189,208,207,2,157,64,29,178,133,166,206,71,226,123,104,195,207,127,14,140,247,187,212,124,199,222,83,46,134,206,111,75,190,63,73,82,47,139,200,197,11,130,44,168,239,104,124,162,31,115,106,15,77,72,8,188,215,102,185,145,177,146,105,215,243,128,236,120,202,35,200,18,3,56,41,51,228,233,136,75,253,209,15,226,133,173,67,184,30,89,158,18,91,156,153,18,111,152,178,1,79,85,158,151,216,76,58,134,155,146,49,89,17,51,188,208,128,156,11,43,131,131,106,12,149,63,166,121,16,63,219,137,51,65,222,5,172,189,253,110,113,53,167,226,44,245,31,50,38,174,100,68,22,13,112,212,36,155,239,195,60,53,18,123,223,198,86,22,195,153,183,238,240,84,186,32,5,221,42,82,204,140,146,40,142,221,64,66,150,70,55,47,30,39,14,91,230,39,190,250,204,44,92,192,48,150,46,192,2,42,75,126,145,237,31,191,38,153,131,36,227,179,79,231,201,9,204,104,33,64,247,81,36,153,134,244,72,253,218,167,247,131,248,178,75,238,207,226,79,244,209,92,176,76,70,26,233,159,72,80,240,245,86,236,211,60,129,147,52,202,224,10,121,136,140,72,97,73,10,133,96,120,170,207,50,34,150,192,32,223,232,196,218,17,88,13,218,31,177,119,20,156,206,58,133,152,213,248,174,186,249,107,70,175,113,37,10,115,145,51,107,100,20,219,82,204,77,140,219,219,169,215,58,48,94,235,31,79,145,66,12,48,214,3,229,197,44,184,188,88,27,187,162,100,106,211,186,207,12,7,55,129,174,102,0,79,203,232,178,166,41,96,67,20,205,236,10,17,185,214,114,166,94,180,205,186,114,55,253,184,106,217,46,50,15,196,129,214,56,81,178,117,165,228,136,107,226,194,252,239,232,52,189,121,119,33,227,225,214,234,74,40,173,225,105,36,9,32,65,235,127,209,218,119,230,246,90,85,92,208,117,25,145,241,125,158,150,196,130,194,200,251,49,170,85,124,87,213,239,96,184,96,197,63,244,187,217,215,49,3,224,114,164,10,22,251,65,108,238,13,29,254,18,139,129,219,58,169,151,73,96,64,221,26,16,12,14,12,78,9,203,11,80,73,221,118,103,173,1,169,193,215,109,126,166,137,12,12,135,17,81,209,32,12,131,60,0,153,66,201,121,182,155,39,109,173,1,186,45,253,219,88,63,179,91,22,106,108,66,107,17,105,97,59,6,133,136,82,129,125,190,184,234,131,23,198,146,94,243,204,25,190,50,160,81,176,220,38,215,41,120,112,38,74,163,171,24,106,116,214,231,194,77,99,71,195,47,141,134,111,103,119,122,241,34,5,170,123,150,232,85,63,156,112,76,202,78,176,136,79,161,164,245,223,119,235,27,8,99,121,57,0,225,90,143,129,173,209,102,133,158,64,233,181,113,212,237,35,132,15,88,36,85,226,152,217,11,16,251,213,25,7,85,125,48,155,221,141,133,205,66,237,6,5,241,72,247,133,199,177,78,236,71,27,110,205,207,241,40,22,141,156,101,179,172,227,30,248,161,147,84,177,176,26,32,103,36,110,30,67,137,223,121,255,110,247,94,76,30,149,83,111,96,72,165,93,200,58,207,176,213,13,29,75,187,45,112,179,43,234,213,242,216,43,249,33,207,40,167,96,46,219,167,44,111,57,183,96,243,201,5,215,73,106,130,134,7,142,153,17,97,126,88,35,57,154,246,15,16,48,120,187,131,106,242,11,250,99,54,230,135,88,172,62,208,30,127,145,236,44,247,246,202,229,174,206,139,144,172,167,141,73,106,163,33,202,57,80,76,67,219,18,99,153,119,22,223,8,132,90,173,119,88,241,34,158,228,149,129,248,73,110,153,176,170,26,33,117,151,227,204,107,181,26,21,245,164,236,219,77,199,199,35,205,68,49,148,238,100,242,214,99,155,100,23,181,56,99,13,119,225,107,153,143,182,246,225,208,95,196,75,114,87,98,134,84,115,210,91,16,159,38,83,255,6,141,147,176,178,28,7,98,154,157,117,22,186,222,203,229,195,97,78,111,21,1,209,7,216,220,49,206,103,113,12,92,248,125,213,205,208,125,25,23,255,131,122,18,244,102,110,19,246,57,97,29,160,122,12,249,191,178,249,218,202,196,118,95,227,2,202,72,253,166,224,126,142,247,255,235,17,182,40,239,72,49,69,198,190,146,45,197,143,72,232,60,106,114,24,207,64,199,21,148,63,154,255,94,65,161,221,130,35,137,115,115,180,84,241,144,61,126,156,106,22,242,150,187,185,206,193,114,109,233,188,162,195,80,84,37,148,76,38,233,82,107,55,196,65,244,142,66,169,247,79,119,3,176,143,31,254,163,250,36,254,95,244,199,37,243,80,12,199,218,35,41,133,113,33,14,19,65,68,109,255,12,46,255,36,190,184,245,158,28,243,54,230,255,252,10,28,140,185,137,52,36,177,174,246,253,228,33,46,4,171,48,142,104,247,44,43,68,29,108,218,170,183,172,241,193,73,207,219,37,138,1,150,130,219,251,45,165,77,163,56,41,211,48,28,136,245,232,57,137,129,92,21,128,45,154,238,208,32,231,214,120,74,179,72,201,37,186,206,84,50,7,123,49,12,239,253,65,164,149,178,102,109,53,34,240,96,200,137,6,135,145,49,172,151,73,182,67,200,127,30,211,36,85,185,165,56,97,54,221,209,90,70,22,143,152,129,15,204,59,5,143,171,180,132,244,145,20,44,11,142,181,72,223,151,147,26,241,164,157,222,7,97,79,43,35,103,66,163,25,155,118,174,109,181,98,111,56,136,55,63,81,51,89,250,61,148,153,110,132,172,218,99,18,104,242,83,175,53,197,209,126,182,44,53,73,229,104,21,252,214,227,27,176,170,31,200,156,251,40,253,90,104,145,10,1,175,235,135,77,56,137,11,51,99,233,59,250,122,62,196,2,245,142,86,59,143,192,123,130,214,245,182,157,134,228,82,199,243,29,167,83,105,75,4,236,116,174,50,18,89,242,200,87,109,23,221,184,42,3,82,80,103,135,218,190,7,129,98,180,64,149,196,181,217,136,28,58,56,53,14,16,248,30,82,197,85,149,53,2,112,81,243,53,131,126,174,187,3,237,209,3,20,9,246,22,3,194,201,118,169,89,116,66,199,66,16,175,193,47,238,65,137,126,87,148,144,167,191,216,137,23,120,162,24,80,68,168,161,148,167,6,137,56,1,160,59,75,181,56,92,175,90,233,7,212,173,52,242,167,91,64,194,196,220,18,71,186,221,224,84,47,76,156,55,190,180,102,18,21,27,55,125,249,219,154,48,54,210,58,72,73,154,78,48,73,105,233,200,178,230,208,130,172,18,160,79,130,20,166,83,203,232,203,108,136,211,228,152,192,103,222,8,46,245,50,29,25,234,254,228,47,202,93,242,41,33,139,115,212,186,141,90,222,177,4}; diff --git a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_4spp.cpp b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_4spp.cpp index 902b91b9..b23e4482 100644 --- a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_4spp.cpp +++ b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_4spp.cpp @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // An Owen-scrambled Sobol sequence of 256 samples of 256 dimensions static const int sobol_256spp_256d[256*256] = {32,226,72,70,57,171,246,75,112,81,109,239,120,101,230,103,103,41,249,86,253,99,132,184,214,147,128,248,17,149,163,17,60,40,169,196,77,79,102,23,250,77,75,151,95,123,234,198,25,26,184,114,230,188,105,18,231,233,175,151,19,174,202,71,84,229,247,148,182,127,92,14,41,112,162,253,35,101,137,30,111,134,95,122,28,2,41,254,181,91,101,188,145,31,166,38,53,193,1,122,99,86,178,36,198,169,113,255,97,221,227,231,29,100,30,141,250,254,16,157,2,220,187,95,181,125,207,187,105,119,156,41,16,194,93,216,227,124,138,90,227,1,88,153,233,69,120,36,19,189,120,4,185,220,185,109,184,96,247,173,210,227,54,3,18,9,139,213,156,57,61,101,37,247,21,201,10,143,11,38,146,18,118,129,95,191,75,207,12,252,238,104,47,39,190,229,31,56,20,127,42,178,100,141,93,222,192,247,186,7,224,161,72,100,87,69,218,44,25,195,185,118,179,123,231,170,96,225,204,52,117,60,3,86,25,143,230,18,11,165,72,188,158,3,66,105,50,200,226,145,227,45,183,62,82,176,191,36,248,191,189,122,96,185,146,166,203,78,144,189,67,174,154,182,86,169,90,236,101,40,71,107,81,93,159,82,75,230,157,191,34,35,235,139,150,193,10,142,217,77,154,249,74,13,196,248,56,154,27,6,242,226,105,94,66,67,145,112,31,145,133,68,21,0,44,212,254,153,183,238,98,102,145,199,100,213,196,52,131,141,216,209,236,122,58,249,188,108,8,206,62,199,207,103,160,247,207,255,101,185,1,113,223,126,182,0,50,93,250,174,194,18,65,111,206,104,156,3,48,195,122,212,10,101,235,200,13,183,173,7,192,3,101,228,84,168,121,241,205,122,115,132,155,242,215,22,236,242,69,35,48,245,3,175,68,57,4,15,226,155,222,140,54,48,80,200,194,149,213,68,225,14,182,122,147,195,69,166,191,17,176,58,222,58,190,70,66,153,196,215,121,123,176,190,161,145,203,121,255,27,207,28,113,22,44,232,46,84,181,131,245,220,27,202,161,38,94,208,39,143,52,5,154,85,121,139,226,223,159,246,170,56,94,209,188,71,205,76,16,233,168,172,200,37,19,123,120,202,28,175,232,88,120,107,157,198,111,253,18,24,36,35,43,169,199,197,137,194,12,238,138,232,17,17,58,115,39,234,4,164,225,215,14,185,232,76,215,171,142,206,206,132,90,31,130,24,0,165,34,91,126,113,64,202,144,114,132,125,58,184,234,211,246,238,168,7,1,172,169,218,67,29,185,66,73,49,222,167,243,189,36,116,23,223,219,200,84,67,94,53,79,26,202,204,91,180,221,166,106,18,207,17,128,137,246,235,162,13,129,130,49,76,104,189,138,55,174,71,152,49,116,204,207,103,198,147,225,142,79,8,172,59,234,225,192,168,181,144,185,6,233,243,61,123,46,55,44,16,228,79,156,235,190,115,61,162,115,182,122,230,138,204,140,86,173,80,99,207,211,181,23,141,152,17,180,35,121,168,67,205,107,74,55,229,234,210,6,94,48,186,210,189,2,200,190,181,227,128,211,225,215,228,74,7,188,195,36,82,10,131,96,99,138,63,1,210,39,134,153,112,72,163,196,55,126,37,125,107,234,166,129,80,61,97,121,20,123,222,3,155,219,62,49,207,87,182,26,214,167,142,89,38,36,112,87,100,56,245,240,152,23,7,237,11,185,206,233,203,131,42,53,35,60,40,211,114,9,13,189,130,196,210,173,39,208,56,110,34,240,65,75,234,76,73,34,39,2,118,174,237,52,194,197,28,155,161,135,180,200,3,89,210,26,154,145,45,57,54,85,26,118,207,212,58,101,69,202,184,36,234,219,155,41,29,80,22,193,175,145,100,50,29,149,166,168,162,213,130,36,25,234,78,84,97,191,139,95,156,9,12,41,97,110,222,8,16,250,161,130,45,111,195,83,213,16,141,154,48,124,175,89,25,27,9,172,242,51,167,76,109,69,107,23,80,23,166,12,16,180,156,182,238,148,249,59,130,75,122,59,134,240,69,220,21,230,47,1,124,66,180,77,247,147,103,66,98,211,96,105,213,127,178,144,102,213,33,247,141,232,67,62,86,230,222,146,68,122,27,147,7,85,69,31,22,67,67,78,13,149,221,57,121,176,133,161,84,201,146,119,196,217,19,132,52,76,135,247,107,29,131,248,220,156,248,29,41,36,202,174,136,253,191,226,91,179,96,69,213,172,0,206,75,192,54,69,120,138,218,171,185,232,211,139,8,31,11,50,119,28,197,83,158,170,229,244,195,190,23,213,87,70,17,102,197,39,59,88,152,234,95,106,29,195,236,114,136,6,159,105,101,2,119,184,47,212,218,188,165,163,138,174,114,71,54,127,64,183,39,51,42,209,202,106,96,215,154,56,33,102,25,62,111,9,49,4,98,142,198,128,138,13,74,95,229,42,164,19,175,179,111,138,19,157,125,94,34,221,103,246,144,141,176,129,201,55,100,23,12,139,33,227,91,223,224,69,120,83,245,50,57,190,21,54,86,245,95,250,34,71,249,100,201,144,16,221,0,40,74,133,38,145,48,217,119,132,34,138,67,161,62,221,126,108,207,140,42,156,13,224,198,142,19,55,85,254,155,140,168,250,58,118,137,42,78,8,48,89,195,167,91,243,246,88,23,22,206,17,190,56,125,171,116,245,129,121,57,144,228,159,197,243,217,239,86,188,152,88,239,112,120,245,119,147,189,25,128,240,72,208,29,162,23,152,24,143,226,136,174,171,58,178,10,5,250,209,239,88,62,34,251,156,163,231,247,102,112,46,48,61,233,24,71,54,73,12,81,195,243,115,138,145,194,164,135,148,51,201,104,74,24,78,107,65,246,118,159,165,130,206,34,157,177,180,10,126,163,167,129,75,0,149,115,172,21,242,139,162,170,92,238,35,46,24,108,101,62,26,147,180,210,227,166,103,149,188,192,92,115,141,161,120,90,231,250,181,130,208,232,151,157,141,208,27,81,82,42,162,244,186,62,163,6,254,94,107,138,123,144,14,216,138,235,104,135,98,77,82,57,47,77,171,213,192,134,69,226,93,197,9,63,181,197,169,22,248,190,55,178,250,167,76,157,101,170,138,94,156,44,12,155,102,133,133,149,43,224,51,130,44,138,3,195,25,161,29,216,1,188,160,73,4,196,125,240,92,88,50,192,176,234,39,109,96,39,60,165,226,80,248,179,232,244,141,102,81,131,110,19,206,225,222,115,198,63,195,251,19,155,77,51,194,251,124,13,77,69,106,112,114,187,126,67,222,81,227,163,80,172,25,70,205,111,48,160,111,165,112,243,47,236,107,81,15,83,95,132,80,133,178,116,87,10,195,139,151,122,44,82,111,24,234,156,187,202,250,20,233,186,204,184,154,149,117,78,205,119,71,166,192,239,88,148,154,229,200,139,163,129,12,155,167,252,50,198,46,106,221,91,235,75,2,14,240,122,62,178,218,42,223,213,6,17,212,242,32,190,96,163,121,63,228,65,111,229,63,70,140,232,221,248,216,80,5,145,12,27,33,195,86,111,42,125,70,44,232,82,209,40,234,168,224,215,215,133,247,128,76,248,178,34,253,61,204,193,105,44,227,66,45,238,159,16,241,67,99,178,235,181,68,204,234,144,58,40,132,125,203,25,204,148,151,253,195,198,81,8,54,248,148,248,58,54,235,82,71,67,181,212,241,43,111,111,202,69,166,200,66,87,245,207,70,112,64,26,240,149,82,86,28,104,17,59,72,154,106,1,173,59,21,204,184,231,15,224,161,253,174,78,249,25,217,35,144,180,57,102,174,57,138,227,125,141,246,16,35,201,173,170,31,107,205,169,59,19,52,209,226,49,136,168,13,238,63,53,78,203,68,18,146,228,165,245,244,84,215,78,230,167,83,239,15,210,34,99,90,184,143,187,50,98,95,182,121,47,53,112,15,53,239,130,105,66,142,11,185,224,203,20,44,156,28,197,195,65,118,36,206,88,55,37,18,112,9,20,231,73,6,11,225,79,180,145,124,204,29,245,148,198,53,210,171,103,53,215,106,111,154,237,107,2,249,79,145,126,255,255,53,222,196,57,237,131,6,63,45,70,68,190,191,12,210,247,162,41,135,184,234,206,153,176,115,255,114,178,110,24,25,66,114,55,29,79,253,67,124,245,37,236,13,88,232,186,18,143,178,59,5,237,10,249,253,37,88,46,134,71,53,74,172,186,69,137,11,154,60,68,120,125,100,91,182,239,177,38,28,125,208,165,38,150,207,244,41,88,127,241,251,168,84,195,111,37,211,165,113,3,212,184,180,207,48,52,204,171,213,128,154,138,218,69,214,154,99,201,203,109,93,71,190,5,99,1,72,173,15,149,49,253,51,82,171,179,114,131,68,114,133,15,104,227,141,109,39,68,225,130,50,51,133,154,148,48,28,230,9,43,157,50,133,203,239,37,160,233,120,54,20,116,57,174,116,158,45,8,196,14,200,80,203,212,233,1,0,88,172,214,196,22,192,224,142,138,146,230,105,100,153,155,112,241,124,26,71,253,143,4,191,50,49,88,226,25,142,141,13,12,50,159,122,211,42,168,23,217,253,218,151,135,3,152,114,102,191,76,186,42,124,70,19,56,25,85,234,58,57,225,230,253,56,194,107,134,142,201,213,43,14,33,242,16,141,205,196,99,143,100,115,5,99,128,100,221,174,110,191,83,165,164,78,60,124,209,199,63,185,120,175,43,3,24,40,153,1,83,147,223,112,72,242,148,166,115,36,138,42,13,63,1,45,173,225,83,121,19,23,208,171,146,240,108,150,3,213,83,210,238,72,120,80,197,2,4,159,197,138,216,19,178,24,173,212,237,169,129,129,102,51,63,203,142,11,134,180,207,105,98,133,253,20,224,6,126,194,167,33,132,90,101,179,113,216,222,132,30,88,23,229,210,85,6,154,226,252,17,39,174,208,255,8,11,252,159,110,195,86,250,59,161,218,31,140,167,41,33,201,143,250,68,82,205,44,4,77,43,214,212,60,82,214,41,44,125,236,152,34,64,133,184,58,145,227,65,70,73,166,49,21,158,242,114,42,75,209,36,72,188,192,146,223,138,76,27,235,115,153,105,169,96,209,231,4,33,105,226,175,187,91,218,12,73,168,214,254,98,208,113,214,116,177,49,34,94,22,127,175,12,155,193,56,187,115,187,240,136,234,206,189,250,115,219,154,17,52,62,198,63,225,81,77,90,127,246,219,192,106,223,78,102,88,142,46,208,156,230,196,67,182,18,112,210,126,198,59,15,234,166,243,77,61,149,24,223,70,245,142,178,199,101,195,190,109,78,244,224,12,84,52,158,184,88,212,155,159,128,187,54,48,209,190,202,157,70,122,109,33,221,124,227,1,196,124,121,163,138,238,25,129,134,83,111,124,60,142,46,143,48,85,63,5,77,46,251,193,209,81,108,149,108,1,47,137,175,85,106,148,27,204,145,104,3,152,84,228,215,113,141,6,117,115,151,206,248,61,43,182,198,76,88,12,222,132,75,73,8,205,190,32,12,159,70,205,4,158,0,107,220,104,90,223,181,80,7,111,166,130,16,168,145,218,242,101,35,165,172,12,217,239,157,76,37,238,176,63,124,243,45,101,181,191,200,64,186,170,42,104,154,191,224,67,145,240,72,82,103,93,108,220,251,36,178,110,145,98,136,83,2,171,177,220,23,98,221,2,160,216,219,237,90,105,255,48,157,136,55,102,122,181,7,225,55,229,254,215,169,94,22,44,65,136,50,190,151,198,54,132,81,245,106,71,91,141,176,162,15,210,33,14,140,108,81,17,135,249,17,44,15,121,28,16,114,178,210,7,129,250,11,239,18,86,203,161,124,2,185,178,83,110,168,3,81,125,80,149,8,67,30,212,0,129,8,77,255,114,243,68,8,119,210,232,104,244,127,165,159,26,176,206,160,228,34,116,10,3,91,65,149,163,43,43,44,171,113,113,223,206,17,63,64,215,216,94,118,5,139,66,201,213,30,120,149,18,236,99,41,81,175,245,1,7,171,209,151,134,28,32,122,201,13,18,46,236,215,113,188,192,221,39,69,117,121,255,119,26,59,142,121,126,238,179,163,183,245,98,199,32,46,39,137,236,232,52,138,4,60,86,83,12,100,44,195,49,107,228,105,56,183,18,177,222,50,189,188,97,197,148,94,99,1,198,221,121,206,54,31,212,145,62,73,77,213,189,38,66,13,139,69,173,57,26,11,176,245,141,166,141,203,10,48,45,201,17,131,241,115,13,165,235,28,129,88,72,36,124,169,128,6,145,10,109,219,198,187,90,149,67,215,68,116,33,56,204,217,236,231,0,205,84,97,113,175,30,185,95,187,166,164,123,103,0,218,18,150,180,103,151,153,146,97,15,161,171,246,252,131,198,186,58,55,210,93,58,157,3,142,220,98,50,202,151,2,115,205,200,3,236,146,210,233,71,222,129,198,18,131,29,157,152,63,201,45,197,253,170,121,124,232,64,197,112,22,208,106,99,54,41,247,146,135,234,142,177,3,38,157,234,222,46,189,233,76,41,150,255,135,82,99,244,246,187,81,215,16,76,188,188,104,156,21,239,255,206,97,35,217,194,13,70,106,106,238,171,232,93,223,145,190,50,39,144,48,13,113,146,151,178,156,18,131,231,168,108,178,224,7,44,122,98,87,166,65,220,174,138,98,95,93,188,127,246,195,136,215,160,201,137,35,217,167,126,219,175,109,180,111,127,222,93,69,133,2,58,198,186,238,108,57,157,101,174,249,26,46,210,254,251,76,43,197,209,161,52,197,28,246,173,229,35,43,13,81,122,34,245,212,223,50,135,69,70,192,171,78,9,135,189,54,168,232,131,250,208,59,227,252,247,231,40,235,203,254,51,25,198,223,165,81,140,141,67,194,180,31,194,172,47,195,56,153,118,221,30,217,17,85,154,184,122,15,130,179,86,8,37,33,200,95,144,73,175,68,185,197,128,182,154,171,147,182,86,172,23,236,20,92,194,110,253,124,133,82,127,206,92,34,108,69,170,47,61,41,87,108,218,3,244,7,124,51,153,83,186,164,116,154,85,123,43,135,177,107,28,189,81,241,214,189,235,233,142,6,109,183,130,75,79,107,99,67,31,164,248,227,114,159,230,115,116,115,252,33,75,4,171,191,217,88,245,156,203,48,239,140,253,211,46,184,136,34,21,248,161,128,156,16,88,64,71,34,174,125,70,164,125,92,205,214,79,157,199,223,143,214,138,213,150,169,17,16,181,95,200,208,91,91,55,125,7,1,39,91,6,103,252,246,22,71,110,149,236,73,1,247,51,2,168,88,124,234,86,100,6,94,1,17,215,157,34,238,126,194,222,109,67,175,96,45,252,99,58,3,34,192,251,95,240,36,188,243,191,229,74,164,55,171,108,239,73,208,140,114,46,244,36,30,33,56,14,209,94,86,28,9,153,30,23,102,165,252,98,77,72,233,22,126,152,98,40,246,35,93,137,114,191,114,200,54,214,8,238,145,43,119,180,186,55,74,170,232,166,247,56,233,9,162,16,241,95,47,5,109,72,125,67,35,130,55,138,75,157,246,85,244,3,230,60,226,159,12,234,155,160,180,119,243,253,179,202,194,53,218,65,208,230,212,71,228,29,49,220,31,146,244,249,84,46,237,203,93,171,73,33,115,46,109,10,163,137,73,18,133,213,236,174,230,216,119,127,80,199,18,100,180,236,191,127,152,158,226,45,72,70,181,106,90,21,229,46,41,109,55,237,81,0,158,169,63,40,22,85,246,181,235,161,180,28,175,136,87,132,184,54,121,185,69,89,58,20,54,81,101,87,37,251,152,4,162,108,113,248,178,219,151,240,144,158,242,185,138,4,34,148,255,250,66,75,144,141,25,248,244,89,180,203,97,141,149,179,129,213,186,64,101,242,119,130,121,108,230,198,74,228,155,96,237,140,201,158,44,127,161,120,219,94,11,95,27,145,80,184,107,215,88,252,32,89,59,97,159,249,183,75,131,180,65,184,179,85,80,88,74,128,53,126,191,54,169,0,133,100,248,196,158,91,121,110,12,248,130,87,248,186,85,136,101,181,0,90,45,34,227,84,17,40,96,221,187,167,131,112,48,70,62,240,138,78,245,248,226,203,255,32,242,246,141,200,17,167,32,151,12,72,159,221,190,56,115,237,233,226,113,71,228,167,60,113,127,28,174,27,176,227,160,77,221,157,64,14,166,82,60,78,7,91,16,214,169,78,222,97,33,229,210,4,255,104,234,42,181,7,177,190,23,40,135,53,67,63,28,151,60,167,81,21,190,110,214,160,222,51,228,87,83,113,220,46,182,163,193,79,214,249,120,197,244,197,169,252,20,33,253,246,46,198,16,208,35,110,5,37,236,172,149,234,155,32,36,8,249,70,224,226,40,16,146,131,224,173,250,111,102,227,160,196,255,167,81,196,62,24,6,39,4,245,139,98,158,201,247,5,6,2,61,92,5,65,70,24,206,135,30,246,146,155,22,29,247,25,112,186,5,208,134,240,95,137,29,48,148,222,92,36,165,248,10,244,222,158,131,46,156,217,243,219,101,123,98,209,124,89,178,16,48,173,142,241,134,127,160,217,64,134,35,244,28,253,59,26,10,212,162,143,252,94,0,198,0,16,156,116,145,64,255,206,234,251,104,250,213,247,171,89,86,125,48,237,216,196,160,45,90,227,12,33,58,31,88,200,117,101,36,105,135,49,134,64,181,233,40,63,100,189,192,13,48,58,159,183,105,34,162,170,166,132,83,141,116,29,39,216,84,29,224,211,54,145,251,248,148,150,203,26,51,179,47,134,175,80,66,223,24,221,52,170,59,241,37,95,232,183,15,162,203,144,221,60,248,8,211,255,78,249,55,59,23,131,11,165,152,182,82,168,71,89,48,249,78,107,182,117,73,21,79,42,128,232,89,103,207,13,224,32,236,175,138,201,54,26,98,122,91,253,144,222,108,171,101,120,208,168,40,29,46,64,23,171,248,115,40,80,28,107,143,65,188,142,205,155,234,86,121,157,124,23,44,177,188,201,222,229,244,169,241,155,62,102,187,15,28,49,168,157,29,135,202,9,160,102,125,112,184,31,209,162,114,13,130,215,93,15,255,110,50,54,19,144,98,47,46,170,252,210,5,161,176,69,185,97,187,253,94,124,215,85,69,73,136,150,68,137,217,52,113,151,241,70,44,102,126,10,143,167,133,81,239,233,109,73,171,141,93,133,112,185,133,103,206,49,208,130,79,127,234,48,173,231,82,200,74,68,194,188,185,26,56,199,134,122,3,153,227,174,245,23,34,49,20,68,184,202,1,232,252,31,171,45,85,7,114,187,66,203,169,98,117,144,15,165,104,143,111,174,100,197,60,7,53,248,238,100,12,162,96,40,189,247,101,64,57,57,14,195,114,229,155,228,32,111,37,141,8,8,163,2,223,6,96,54,144,175,85,141,51,77,41,60,192,113,15,103,101,44,30,102,189,100,251,227,71,37,62,123,4,63,119,25,116,47,205,191,156,1,106,136,248,37,151,162,72,226,41,208,133,69,146,114,137,43,245,90,115,117,90,122,134,180,218,136,10,36,210,53,138,90,139,213,130,56,173,119,174,71,72,213,138,87,171,101,156,110,0,164,38,191,156,215,148,220,106,138,50,237,54,37,49,215,127,45,81,226,61,181,195,147,154,208,170,94,34,8,228,121,71,182,239,63,56,65,244,0,70,162,73,198,63,16,134,216,58,187,203,234,115,44,209,105,127,183,130,74,82,203,219,128,128,162,13,47,106,252,31,56,155,184,119,56,139,70,241,3,104,153,43,183,28,68,241,224,25,154,52,51,131,108,142,150,13,106,43,251,166,76,47,218,150,11,125,109,109,179,145,213,217,241,16,32,208,48,33,217,59,171,245,248,174,34,191,77,111,183,221,49,141,59,221,76,224,103,190,107,171,215,232,44,84,133,236,88,227,175,24,57,144,252,229,182,140,36,219,42,92,101,187,212,188,34,205,167,99,168,91,224,154,187,112,52,190,62,212,191,250,250,68,229,248,142,143,161,185,243,117,222,69,61,162,247,179,140,133,135,164,217,144,222,8,114,20,240,161,44,27,187,82,122,237,53,167,43,2,215,122,219,61,163,54,181,154,176,222,239,12,13,63,88,213,167,98,162,94,254,89,113,112,242,88,158,65,229,215,16,126,234,96,129,34,233,231,85,152,90,16,97,32,90,134,18,131,114,130,148,249,76,135,186,171,103,192,83,45,100,96,36,88,217,197,165,86,194,168,112,149,125,108,133,112,117,199,26,221,35,245,88,233,9,113,47,138,31,61,114,47,51,32,197,55,17,175,164,93,204,223,215,203,221,224,147,103,78,214,230,214,71,214,220,169,117,39,0,147,198,108,242,153,155,144,235,250,162,35,53,61,45,156,227,244,108,123,32,227,129,77,252,146,213,168,197,237,147,123,38,228,75,144,165,144,102,113,198,22,145,14,101,195,177,43,62,151,113,96,81,189,204,180,207,197,24,72,76,135,127,181,246,81,18,167,113,85,184,62,190,140,86,209,148,134,111,32,60,108,33,233,115,99,216,239,112,146,92,217,236,252,213,215,98,122,215,64,175,155,179,121,195,7,207,252,163,51,58,143,187,255,188,122,6,199,73,36,149,218,141,142,43,108,99,2,232,187,65,216,24,169,125,102,148,113,59,233,176,194,207,77,204,245,20,43,145,104,88,88,212,187,237,152,64,18,141,254,53,255,111,53,61,62,49,143,145,197,10,207,36,198,166,88,7,199,42,201,145,219,135,53,239,108,162,82,202,181,4,255,82,23,38,141,213,120,0,218,105,2,141,120,255,138,20,27,255,97,202,151,0,166,227,16,196,48,139,91,164,4,170,177,243,27,154,220,212,167,205,179,84,245,205,50,51,155,45,39,99,124,70,27,48,182,173,3,26,38,214,1,26,23,216,248,214,89,78,142,7,44,2,118,103,73,72,202,187,222,242,74,37,84,166,251,191,67,11,231,116,61,33,17,96,93,116,165,173,88,153,105,123,125,159,243,89,143,66,211,213,23,47,204,192,2,231,229,224,32,30,45,9,31,149,216,137,119,152,34,22,131,206,47,216,201,89,197,58,66,204,67,92,0,150,199,161,213,185,96,252,164,78,46,247,41,134,48,118,14,77,30,250,176,12,138,96,58,51,142,9,249,103,99,29,247,189,31,126,29,86,211,201,108,216,195,90,32,119,124,219,207,128,192,119,91,217,60,215,24,182,244,100,241,153,24,3,99,115,167,33,25,239,186,42,198,202,179,57,117,112,11,208,212,50,26,170,22,148,206,252,232,159,56,64,37,184,40,232,109,62,164,199,64,198,112,56,71,12,215,108,220,20,211,118,70,182,19,212,219,182,104,5,188,255,61,162,241,25,176,78,25,176,239,21,205,246,214,246,86,45,101,158,9,252,149,38,59,72,225,119,121,209,20,85,6,84,253,24,182,126,20,150,105,176,238,54,59,96,46,28,214,21,80,112,19,118,125,115,134,244,30,35,230,238,255,199,220,32,200,9,142,2,182,14,101,191,176,143,96,217,200,124,194,43,105,61,93,143,135,53,12,228,233,30,150,173,228,73,179,184,84,21,117,63,245,231,49,129,29,249,46,23,172,195,94,36,76,227,246,71,159,188,8,88,119,49,177,156,203,88,101,195,170,151,183,106,100,9,246,64,254,1,90,4,9,163,154,231,88,68,182,99,67,75,171,107,142,196,79,237,114,70,178,128,33,83,168,67,129,82,214,135,38,206,41,152,140,168,52,239,28,171,28,29,180,246,185,183,243,85,129,112,168,63,139,133,0,162,86,166,48,132,244,159,151,235,175,64,110,168,85,97,233,11,62,25,177,16,57,124,63,250,59,218,136,209,136,192,23,168,160,206,65,84,30,73,213,235,181,104,66,27,98,126,183,219,93,200,115,84,141,57,55,20,131,91,14,228,85,181,19,4,110,176,90,101,40,91,107,155,7,70,21,114,154,141,146,125,246,64,1,216,213,232,23,143,224,115,244,247,144,186,71,134,69,183,141,25,186,91,29,145,163,250,202,181,57,216,172,131,228,242,181,187,52,94,218,252,4,118,44,52,124,160,37,176,17,218,121,140,191,107,102,91,222,49,91,229,106,179,221,170,200,88,38,138,167,10,48,157,47,99,57,137,88,76,206,141,214,208,48,80,226,18,227,6,175,180,63,107,247,251,197,59,51,247,13,109,209,162,206,192,125,112,94,235,247,26,88,14,126,241,225,249,81,162,7,157,238,150,138,24,69,121,155,219,17,169,180,218,93,230,99,92,139,53,179,145,30,14,205,171,75,247,49,194,3,14,177,24,222,122,30,75,174,121,243,104,233,244,81,4,47,70,43,206,113,229,119,231,49,72,144,78,214,29,193,41,75,14,97,19,84,148,246,3,250,243,7,246,233,153,48,135,226,204,199,93,210,3,97,11,106,117,170,122,92,97,150,179,177,220,46,59,17,151,242,160,233,237,81,78,255,87,243,237,113,135,216,131,97,197,224,41,142,85,234,243,135,58,152,220,191,227,149,78,77,30,82,167,63,217,43,227,106,173,223,128,161,49,70,29,184,169,178,179,124,224,2,243,210,229,112,103,15,29,78,229,91,9,68,198,94,135,241,207,69,183,229,46,78,63,189,93,163,10,91,172,13,205,180,217,216,102,237,239,3,217,247,218,0,147,130,158,175,242,39,94,23,238,221,229,211,72,140,103,207,7,73,10,200,247,155,254,35,165,152,2,137,237,154,128,235,215,210,1,132,104,143,128,91,191,225,241,171,220,16,165,209,59,10,1,128,151,229,116,17,20,188,108,57,196,105,197,5,64,216,75,255,49,10,35,243,39,238,142,201,1,32,8,28,116,21,216,226,89,90,231,210,128,81,149,93,249,111,150,128,11,228,231,236,178,74,34,174,187,230,84,78,197,136,17,197,25,242,154,123,24,78,245,178,254,76,70,182,72,15,115,54,62,10,89,172,129,113,97,148,204,240,100,172,169,122,13,95,182,26,184,25,191,255,250,250,137,18,19,72,145,135,112,125,227,63,65,26,54,228,181,30,158,27,191,9,236,168,115,248,144,187,132,253,45,84,154,196,103,30,149,123,53,42,206,172,146,175,44,203,69,239,45,147,0,121,103,125,132,136,192,38,62,79,29,241,17,151,110,28,38,221,234,230,228,182,64,241,144,165,124,145,120,49,50,129,18,33,242,212,143,68,167,109,134,179,113,176,85,93,87,105,133,15,66,249,8,43,9,147,72,30,6,2,85,185,204,160,20,76,70,119,163,67,200,121,228,185,204,22,48,31,122,177,123,93,159,108,114,65,90,91,67,95,139,6,187,3,78,142,38,96,61,68,23,146,93,32,245,153,131,61,126,1,194,201,158,51,161,172,0,176,76,143,229,81,201,36,157,210,139,109,215,12,9,41,152,243,188,240,144,194,27,114,193,162,39,43,9,203,46,137,76,217,93,125,215,74,43,75,0,153,246,95,88,44,134,248,43,87,166,46,133,1,77,197,205,206,31,50,102,178,248,22,226,192,156,203,195,155,193,32,35,158,173,76,75,79,240,112,7,161,130,162,85,225,67,223,15,127,53,24,49,231,201,248,16,114,146,228,17,178,247,166,162,2,32,180,41,188,9,197,103,77,246,35,30,71,112,6,222,168,64,60,248,242,61,201,130,219,58,182,38,143,103,45,104,219,7,121,119,138,183,148,149,107,216,169,2,89,111,185,120,49,74,173,174,35,38,194,214,86,32,216,229,123,41,64,108,178,152,13,174,71,86,192,147,84,112,246,98,151,238,63,210,134,112,5,28,254,154,125,236,82,78,22,114,230,212,88,97,54,211,70,203,48,159,59,21,36,55,56,141,194,247,133,160,138,224,66,180,74,137,37,94,5,120,135,170,119,209,147,221,28,19,215,139,29,199,87,234,102,225,111,74,180,27,169,131,129,29,44,138,81,235,206,181,229,133,192,201,163,110,48,203,245,95,200,183,29,29,31,255,74,216,148,92,109,191,130,29,236,248,204,126,228,208,76,200,13,128,197,198,255,211,23,197,132,124,133,71,155,21,132,233,191,189,212,255,108,47,94,109,53,232,234,95,174,83,223,18,188,255,239,215,139,141,51,127,243,199,103,111,117,45,101,67,184,104,196,20,34,25,184,251,144,47,226,217,214,217,125,47,52,41,242,113,104,13,56,74,44,166,36,63,154,133,145,18,80,160,124,59,47,48,219,63,43,134,67,115,238,189,252,67,6,164,83,181,123,230,213,252,7,222,130,221,30,79,68,34,162,2,61,134,162,207,49,146,161,216,82,98,181,190,57,57,164,128,97,121,148,131,128,152,66,106,247,15,154,148,82,42,174,142,17,249,123,23,138,78,106,245,159,202,19,26,160,50,138,153,136,182,101,89,247,195,169,69,220,50,155,45,140,251,248,183,139,84,17,44,98,83,13,102,234,106,135,22,255,212,246,163,28,11,251,123,18,5,150,221,6,2,137,17,176,56,215,12,166,187,52,149,11,97,119,140,245,13,201,20,98,80,27,26,125,126,58,232,231,83,52,195,75,116,248,147,230,123,171,77,81,168,163,120,39,158,18,54,60,212,117,67,148,122,151,78,51,30,88,27,152,83,92,191,105,162,106,233,12,27,116,4,53,100,189,242,253,169,182,10,105,196,84,229,122,141,80,15,0,38,26,50,176,229,18,32,169,241,202,190,190,225,100,193,44,196,209,193,83,89,43,228,8,127,48,9,221,186,199,251,97,138,218,190,131,202,206,62,148,128,44,48,107,164,177,57,149,171,214,244,57,198,194,87,179,232,10,17,65,243,255,109,19,208,42,55,68,178,164,84,21,57,206,5,27,252,203,144,108,90,231,137,198,221,204,164,204,56,73,223,129,127,246,244,144,140,13,229,195,199,39,42,93,103,202,8,45,68,203,17,186,154,9,154,228,59,255,134,120,125,170,90,18,141,31,17,116,10,189,48,63,147,112,188,11,184,92,95,253,180,92,80,106,57,112,187,229,228,69,3,1,47,47,72,146,48,135,37,111,82,27,20,77,157,222,115,123,120,119,159,196,99,7,116,57,222,119,79,79,212,213,215,145,225,154,187,25,22,126,89,170,169,123,159,94,29,177,63,137,207,167,192,97,134,193,17,236,199,8,35,214,220,156,72,183,180,8,63,200,171,93,216,103,110,145,159,209,158,236,233,50,228,220,144,113,159,214,222,157,156,27,133,183,240,127,191,28,41,222,148,155,247,32,97,96,128,237,98,236,159,107,157,192,176,19,81,248,145,219,183,179,73,178,81,38,137,81,108,189,148,180,164,63,244,107,140,13,253,2,84,88,16,121,200,120,77,203,104,24,207,202,194,62,253,155,102,96,168,116,28,237,163,138,91,149,34,82,230,211,109,230,176,130,28,82,186,233,159,99,238,249,81,38,106,243,246,4,63,80,43,104,47,1,253,236,84,79,158,5,81,26,18,242,70,42,11,229,216,154,236,16,203,159,227,7,207,120,26,197,81,87,177,4,32,197,147,111,255,229,91,211,194,195,230,35,169,151,31,196,33,181,120,192,254,71,84,152,228,208,209,129,98,55,39,210,144,146,192,231,249,121,170,81,218,202,197,150,149,234,93,90,178,167,209,244,86,25,140,141,156,206,14,247,240,217,14,39,99,82,121,16,119,157,210,169,220,50,58,255,48,130,189,120,154,59,60,85,94,135,23,15,171,6,31,212,224,89,73,100,179,91,61,170,128,28,33,227,9,149,128,12,110,120,44,9,52,192,4,24,65,221,114,24,77,109,0,237,94,4,42,232,84,150,134,32,50,33,84,234,130,136,89,117,253,79,60,135,69,29,50,128,196,38,41,43,37,78,168,73,163,249,45,207,177,76,38,115,76,143,118,145,106,166,6,142,230,193,147,145,87,195,222,73,219,219,89,33,68,237,118,120,146,164,74,130,237,16,47,79,228,9,153,184,5,127,80,182,81,105,196,51,244,192,237,160,118,200,191,94,235,152,191,202,161,231,171,19,116,102,94,206,253,175,4,193,18,70,53,214,98,123,181,137,167,190,84,96,169,2,204,232,54,221,169,175,186,172,137,170,75,32,249,57,119,86,19,52,123,234,142,11,108,19,58,84,98,250,242,114,170,31,205,195,117,12,243,41,93,222,0,101,219,102,129,196,192,91,8,186,233,243,37,194,183,162,121,59,93,71,52,178,114,96,72,252,185,254,109,31,107,112,168,64,226,160,216,43,49,74,50,139,112,148,135,148,88,184,35,26,29,171,245,47,96,61,39,146,159,194,252,57,202,244,245,218,216,18,29,71,237,39,25,197,164,184,67,97,53,45,16,218,207,244,97,249,96,167,93,62,103,162,164,67,186,159,2,26,136,32,184,9,167,169,183,210,72,43,253,167,72,211,171,205,117,92,82,32,5,197,107,8,68,106,237,8,142,148,101,227,90,210,67,13,252,233,3,242,79,95,172,175,195,246,251,254,247,71,7,224,252,37,255,4,158,178,131,23,77,77,22,178,114,155,151,162,207,53,98,63,132,143,232,73,194,185,91,243,57,47,83,36,154,42,31,150,56,15,33,40,14,111,70,137,225,158,138,108,119,114,255,48,176,231,182,51,219,163,86,122,80,104,197,169,107,181,97,55,228,63,47,73,106,27,23,65,207,177,34,218,221,147,192,237,165,74,89,152,255,181,169,250,226,99,10,232,6,181,45,3,222,174,26,248,155,12,199,237,65,205,85,22,125,164,146,124,17,73,140,71,36,57,173,173,157,157,161,35,164,157,190,71,67,29,142,133,206,231,64,185,95,111,65,166,220,233,245,73,242,25,16,29,223,124,142,199,177,13,24,198,245,218,190,115,38,32,45,236,12,96,101,63,17,230,151,217,117,234,153,112,111,91,162,196,247,185,166,60,2,8,145,56,160,48,175,226,250,67,51,132,106,42,213,138,119,167,9,240,25,8,56,22,165,218,9,62,218,121,29,43,177,130,210,166,150,15,220,225,225,152,34,255,104,115,223,108,131,55,250,255,49,92,130,20,179,218,73,38,116,122,102,17,118,237,183,109,65,232,122,235,4,68,3,245,160,150,224,73,183,115,6,100,124,166,210,201,82,249,142,15,23,20,60,118,137,170,181,229,205,108,201,240,169,87,195,99,76,138,15,228,158,47,216,146,8,248,175,110,207,39,94,180,173,250,47,24,2,201,150,241,233,238,16,120,75,140,84,49,212,106,98,213,162,86,181,76,170,35,124,116,48,164,197,74,131,117,229,28,19,139,154,0,123,202,110,178,10,79,113,166,22,172,117,191,54,48,27,183,59,223,105,57,148,54,241,188,72,118,58,255,33,235,238,206,33,254,197,162,45,154,226,221,57,145,225,19,36,11,164,245,79,188,132,50,190,248,255,75,183,214,242,69,109,232,147,130,166,70,86,58,124,161,96,88,92,166,32,184,117,117,232,148,14,163,81,163,242,0,239,41,82,240,105,189,74,68,200,164,195,85,62,74,56,226,196,41,2,105,154,95,205,207,232,106,98,226,99,112,210,188,162,203,188,28,65,78,18,252,134,93,120,74,188,64,154,12,133,146,228,14,25,9,13,157,22,83,145,169,201,189,221,137,49,232,138,179,182,165,146,2,109,172,21,172,40,157,230,199,70,170,17,231,133,250,192,45,75,214,33,111,3,120,209,54,12,206,159,226,150,136,96,94,25,66,56,178,106,7,73,214,104,156,236,28,249,93,15,229,9,0,132,16,69,155,125,179,207,94,14,13,244,207,241,54,32,52,63,98,162,154,191,75,209,229,33,193,255,57,31,229,86,153,43,207,166,165,245,54,40,212,29,222,70,136,130,40,74,185,218,104,130,108,129,245,188,86,215,76,131,33,190,168,234,99,175,11,251,216,73,187,108,44,255,201,238,119,247,44,86,81,235,45,3,57,216,75,34,73,180,36,35,240,164,214,36,117,135,41,119,211,38,76,81,196,8,21,97,136,235,119,71,123,36,176,199,227,228,108,128,149,137,5,164,77,148,159,81,47,176,108,234,54,46,235,56,167,178,84,254,105,129,190,49,65,57,236,213,149,152,10,85,206,195,221,92,221,54,74,114,134,198,83,208,132,62,75,99,76,23,147,221,170,238,47,2,231,238,159,31,157,21,230,120,116,37,205,171,183,193,105,172,143,117,1,93,76,23,54,218,89,41,8,34,70,14,172,247,13,165,93,149,104,106,13,209,88,202,31,127,1,56,213,196,57,128,219,160,128,36,102,11,50,241,144,120,109,249,181,6,101,158,193,159,198,121,72,53,117,201,226,238,36,19,89,190,170,97,242,166,133,255,187,116,117,149,110,240,34,46,115,10,173,23,253,193,26,88,218,204,250,37,212,109,250,201,191,194,118,95,136,247,161,207,241,204,135,2,78,149,74,112,131,147,47,174,61,6,17,165,170,245,205,230,27,4,219,42,253,132,224,5,105,216,149,164,189,139,111,218,70,124,62,36,131,167,58,160,166,166,15,182,6,55,43,51,18,46,56,174,90,10,0,14,29,74,85,33,208,147,69,176,90,198,106,36,37,30,25,35,124,178,130,4,84,25,198,20,229,53,83,27,191,7,155,221,115,87,5,220,83,80,84,102,251,48,221,102,199,149,98,72,199,4,97,43,61,78,97,140,141,115,8,36,76,209,170,73,151,35,27,50,135,70,240,173,0,121,54,23,163,78,109,212,129,93,171,216,134,28,83,113,141,233,192,101,187,144,201,55,84,241,226,162,50,111,152,243,114,9,111,93,4,89,234,55,65,28,241,78,143,188,189,252,70,80,238,69,204,212,181,122,171,109,189,186,144,136,240,116,95,234,155,53,70,170,203,113,36,46,45,134,195,163,140,104,104,25,181,136,167,116,55,237,25,77,120,91,44,239,159,52,190,41,227,220,175,171,101,213,127,105,222,163,58,68,40,210,118,247,1,76,42,20,189,248,76,43,113,25,81,37,26,154,234,25,226,251,39,69,143,3,138,235,220,47,9,31,25,63,195,193,72,173,92,80,43,152,143,80,74,126,49,33,238,113,228,171,168,241,82,49,174,116,73,94,130,72,230,253,161,187,183,237,195,41,153,143,130,252,152,169,147,185,106,2,207,13,134,90,175,141,157,242,255,161,154,42,107,178,145,195,16,211,119,181,175,211,84,142,39,77,187,239,159,12,177,186,243,150,95,140,58,167,52,103,146,158,98,247,173,141,219,214,180,87,55,184,155,216,203,67,81,243,45,171,219,220,110,144,106,5,138,225,212,232,110,202,220,68,84,250,115,120,118,200,167,154,108,73,90,190,72,34,47,249,229,114,4,80,142,144,22,68,254,128,128,196,171,194,100,131,176,168,30,203,107,42,65,59,156,176,21,156,53,86,125,203,58,216,87,127,233,238,153,162,195,175,35,133,212,69,25,61,96,246,99,19,132,120,219,58,140,93,223,248,9,43,246,147,166,10,33,40,237,26,6,87,228,81,182,159,34,234,48,74,27,30,186,36,136,63,92,110,3,131,130,27,239,155,0,156,219,146,232,148,189,133,204,227,35,102,6,13,242,251,69,127,251,171,127,248,242,116,126,174,84,115,6,193,135,29,128,225,230,162,23,222,79,106,4,26,156,61,251,88,57,81,76,237,7,19,107,37,95,147,230,99,193,76,98,87,252,124,217,105,200,201,204,245,189,226,154,95,54,19,34,64,85,66,163,243,6,203,46,201,0,174,183,154,181,226,46,152,199,255,75,54,243,29,83,133,231,240,6,21,38,68,184,253,109,54,23,224,31,102,11,112,103,43,17,38,125,238,71,104,161,159,219,136,215,196,141,170,10,56,156,93,207,152,188,114,22,157,0,165,25,138,205,58,248,67,193,58,28,147,32,38,229,221,175,114,14,42,161,2,223,231,204,164,6,92,49,52,64,37,164,223,252,197,118,55,243,108,10,158,239,219,175,244,102,22,194,134,212,9,249,244,43,86,97,41,53,9,224,110,61,250,140,202,187,95,171,204,21,221,58,141,24,176,120,96,194,232,84,28,125,246,218,142,73,131,254,249,22,179,71,110,208,97,247,139,162,171,64,251,79,190,180,190,186,29,110,165,88,119,225,30,58,64,49,68,45,83,93,122,136,199,146,158,106,5,211,222,64,64,160,74,72,185,138,112,186,135,133,95,31,236,77,86,54,59,235,32,245,245,133,152,27,233,115,154,253,233,222,36,218,216,218,211,137,127,103,199,95,165,151,234,33,228,72,167,103,13,43,119,38,71,23,218,227,177,230,222,214,149,81,102,246,94,251,84,233,90,116,77,26,118,194,122,55,75,208,137,52,159,238,73,8,33,157,218,178,213,108,45,131,207,210,31,144,133,204,239,144,183,230,251,195,57,195,154,39,61,36,39,117,126,121,69,224,198,15,198,98,59,82,181,202,28,149,49,219,53,48,163,19,164,57,251,219,61,159,235,12,121,100,151,160,191,93,194,90,22,119,28,191,219,210,170,234,145,2,111,53,86,140,171,46,232,231,111,18,43,83,2,142,131,38,36,99,174,3,26,169,105,31,214,250,212,191,8,1,141,69,73,158,180,248,93,117,146,242,10,188,63,7,61,149,69,118,161,141,117,25,193,18,187,220,194,82,13,30,5,225,194,158,252,56,159,129,5,240,0,213,85,67,54,209,242,151,41,141,172,187,12,215,255,6,5,126,185,11,225,35,202,5,182,98,154,26,217,237,193,140,136,38,71,118,166,44,17,223,179,101,97,16,153,33,21,204,15,219,189,120,219,24,117,23,4,153,22,143,40,174,238,185,27,159,69,251,1,227,108,218,69,111,198,184,236,14,216,136,208,115,154,211,47,149,116,98,114,40,90,83,116,92,109,38,134,140,104,157,197,116,57,122,111,5,224,4,175,201,244,62,210,203,188,216,230,131,214,184,164,54,48,242,179,251,201,77,16,77,13,77,23,34,66,146,24,12,187,238,151,92,139,64,114,217,125,244,175,10,155,138,118,58,245,52,121,17,241,62,231,105,214,169,120,184,4,155,16,20,12,215,206,40,237,161,186,68,63,141,166,178,6,127,126,151,70,195,245,163,96,91,23,138,173,211,99,103,164,14,51,246,20,75,76,135,150,74,215,220,71,15,76,77,215,250,38,227,176,76,17,15,179,232,18,19,165,54,194,146,187,110,158,216,55,66,145,232,119,152,61,63,121,155,194,202,244,22,81,66,36,140,38,108,209,21,139,25,159,255,185,60,117,9,245,95,46,99,220,27,61,151,235,253,38,161,64,188,88,189,117,249,42,176,56,54,107,62,80,240,135,153,86,180,137,121,111,177,208,196,3,194,236,106,173,82,40,195,1,146,180,204,141,11,192,120,252,52,4,116,199,14,254,104,216,4,219,7,221,233,33,47,34,247,94,0,104,240,54,18,128,85,240,255,179,195,197,161,240,178,242,197,103,68,166,60,95,131,245,148,198,163,124,209,39,120,42,206,15,106,91,118,113,89,19,66,66,241,200,64,65,37,82,169,139,136,203,234,192,172,175,27,160,244,10,91,4,183,109,177,183,93,233,92,26,227,67,87,232,184,97,234,202,240,80,213,42,133,15,68,206,0,206,110,170,227,223,113,90,208,60,11,93,245,151,50,51,86,152,199,229,35,248,13,119,64,238,165,152,108,70,48,149,157,110,249,189,25,187,246,251,124,64,0,176,165,128,174,39,200,94,100,193,34,233,19,192,83,39,177,228,74,234,195,128,251,203,238,192,16,66,200,223,179,30,106,195,189,26,217,157,142,161,132,38,20,179,217,79,34,97,189,231,106,19,144,223,172,39,206,91,192,115,254,111,141,170,103,121,61,72,101,60,110,173,73,193,25,89,206,122,137,151,213,60,169,7,42,226,224,249,190,43,17,190,187,240,163,77,26,192,162,70,170,154,216,20,183,212,229,81,56,157,247,123,219,168,91,21,53,107,174,135,98,32,176,146,78,98,190,30,232,190,171,107,188,254,223,5,25,58,134,150,36,28,218,134,107,40,253,245,199,11,1,191,26,173,238,5,142,204,170,161,157,127,172,254,27,185,235,87,15,3,74,170,36,195,132,163,3,126,33,178,173,141,106,23,111,96,111,124,164,68,230,2,210,18,190,148,45,70,148,194,38,160,67,130,166,172,81,5,91,142,239,190,58,3,102,81,212,68,68,73,134,6,117,116,100,47,57,100,207,232,224,125,32,30,193,162,117,36,57,8,27,203,56,199,110,251,56,35,162,240,157,224,0,42,206,199,201,33,95,5,127,132,29,178,152,101,166,1,242,99,155,248,47,71,180,75,84,99,65,91,32,31,136,206,52,48,74,184,208,83,85,179,51,105,125,87,66,145,207,127,71,239,255,157,126,120,139,232,35,64,70,128,118,191,41,217,7,185,86,117,216,187,163,194,206,174,218,56,214,58,160,248,111,154,70,17,108,212,91,199,245,32,108,125,43,198,192,38,68,101,100,147,129,87,52,240,50,91,92,218,108,127,101,155,228,123,77,147,41,86,207,159,139,140,93,22,169,163,63,89,236,154,98,131,93,39,55,237,122,107,6,174,184,202,126,27,199,141,16,52,167,250,44,52,64,134,244,66,235,39,127,190,88,127,61,105,107,157,35,59,146,10,14,155,241,227,170,104,180,47,95,20,235,236,196,100,29,66,255,252,236,249,128,214,5,234,40,241,34,234,45,47,166,217,121,36,243,35,251,23,126,3,133,136,164,113,22,69,236,180,239,139,48,255,146,161,48,135,129,150,245,193,181,210,85,120,4,249,147,174,66,17,136,154,208,148,214,82,198,29,171,4,223,212,84,104,93,95,153,151,59,52,212,150,113,85,179,189,60,151,118,28,93,220,49,114,124,228,164,99,165,40,1,5,200,121,138,132,77,15,5,21,162,216,252,37,141,224,202,125,209,225,242,62,177,195,93,254,238,77,226,148,168,119,167,195,151,180,25,60,215,48,166,94,44,45,114,159,78,24,155,132,119,38,31,231,227,51,37,35,33,239,40,171,12,250,68,190,248,231,228,59,213,61,15,65,53,179,92,176,23,172,176,32,72,135,37,241,24,107,242,184,186,57,99,239,241,14,0,114,211,202,79,176,88,52,130,56,18,75,55,22,208,79,100,1,57,105,53,174,100,13,234,232,158,118,211,9,144,128,160,76,177,166,10,90,95,110,144,254,243,190,208,135,184,198,226,200,27,9,38,241,0,208,210,237,180,2,22,149,157,19,155,249,21,3,55,195,149,105,206,24,110,148,19,249,58,78,186,176,25,100,216,4,198,194,104,71,150,103,193,54,223,28,146,80,51,157,194,14,178,180,189,161,192,44,225,168,111,47,225,151,43,100,26,191,125,146,222,221,199,216,186,126,173,89,90,229,77,60,34,228,75,219,182,85,232,170,22,24,130,197,101,20,253,116,141,176,241,34,223,208,190,53,49,201,93,144,151,241,108,236,120,86,232,128,234,238,83,111,80,172,96,67,34,128,6,29,10,136,122,7,204,83,50,186,1,23,79,169,21,92,114,15,132,236,51,188,123,139,240,236,199,67,208,132,52,13,194,187,174,29,120,140,151,198,252,88,147,102,219,35,162,73,126,98,77,213,8,169,217,193,210,100,239,19,153,49,43,252,194,75,228,65,143,184,39,77,42,202,171,40,113,137,164,157,33,120,131,63,197,218,5,250,238,192,175,128,92,206,161,173,254,238,133,100,158,136,16,101,127,238,52,208,92,82,3,217,66,93,246,228,193,254,74,72,78,122,33,105,54,8,66,93,246,194,222,27,194,33,125,31,125,186,243,13,92,218,44,36,132,226,180,89,124,205,104,135,159,122,252,15,162,223,62,10,250,171,0,131,127,85,178,231,79,207,40,253,46,196,118,242,128,72,35,191,117,82,21,59,50,253,123,77,220,143,104,20,203,224,176,13,252,32,28,67,43,91,75,244,94,186,135,19,180,199,223,127,142,98,37,239,28,103,87,65,235,18,238,103,120,238,30,86,59,98,172,2,220,161,99,43,3,209,122,161,55,146,255,1,36,249,99,184,3,3,168,72,232,46,73,223,106,79,159,210,38,156,147,51,126,50,165,108,52,49,96,42,238,80,99,70,146,206,224,54,97,97,16,213,14,248,251,126,49,66,87,134,179,227,232,143,91,185,125,0,158,183,5,242,48,7,152,160,171,198,163,34,181,199,170,68,125,93,97,109,136,230,150,33,113,56,104,7,226,175,49,100,51,84,213,22,135,7,237,200,148,72,116,142,163,153,122,86,4,164,15,210,118,24,67,210,223,220,137,144,48,144,180,185,234,2,241,154,213,43,109,156,143,172,26,128,135,231,119,24,217,131,61,148,77,141,150,92,115,120,2,154,217,75,86,241,208,171,108,103,82,89,209,129,238,172,132,255,207,27,146,164,74,184,68,92,141,13,124,214,138,185,244,149,236,189,182,103,67,87,10,32,216,220,143,80,210,206,245,104,149,139,20,55,5,113,172,207,125,29,89,249,19,112,108,14,88,182,201,165,18,10,245,121,6,178,148,34,12,59,196,61,173,239,178,241,33,155,25,242,134,32,227,233,188,135,113,163,52,64,251,178,224,118,246,79,167,5,63,212,177,112,180,80,242,169,49,210,21,134,141,17,157,190,91,64,227,91,38,133,159,225,105,247,226,195,200,172,31,220,215,170,68,107,20,234,183,178,143,56,158,107,86,223,172,215,193,84,10,65,89,99,158,61,203,224,96,108,213,54,164,149,13,125,118,120,95,189,114,57,41,211,241,237,209,190,6,62,79,184,242,245,149,195,91,85,198,131,178,227,71,202,112,154,51,82,29,130,223,121,113,6,199,251,129,30,201,68,187,181,197,35,52,79,104,12,235,40,127,72,62,197,101,25,50,235,135,22,61,18,204,9,17,58,139,193,112,118,161,34,157,65,113,190,135,176,140,117,20,216,176,111,50,116,217,162,214,180,80,45,31,21,53,93,2,228,123,100,207,17,230,207,97,240,183,85,31,41,46,45,3,43,72,155,187,165,203,128,67,28,120,236,54,20,65,238,109,110,179,222,136,198,17,77,149,130,251,103,177,204,150,184,189,37,5,55,241,217,14,130,255,116,126,175,235,144,116,140,66,14,51,205,67,99,220,51,208,79,206,154,127,22,85,71,77,215,145,255,44,243,64,209,227,67,73,110,151,218,87,197,55,237,118,245,39,169,244,170,245,203,108,245,142,50,189,176,80,21,202,93,146,1,53,148,177,158,56,213,31,235,149,163,76,7,160,96,185,175,209,247,27,135,158,217,147,16,10,240,197,137,20,206,239,82,56,27,22,220,198,2,89,79,127,31,142,1,6,55,182,200,142,137,107,201,174,111,181,210,207,62,30,104,243,208,79,121,233,86,23,51,192,246,38,237,63,185,68,166,75,123,229,116,251,234,207,59,122,231,68,113,211,62,70,25,143,151,209,232,208,160,147,131,216,54,242,90,239,63,40,144,174,63,16,36,202,26,114,183,89,217,89,136,230,91,48,252,125,202,164,150,89,145,56,123,247,12,54,155,187,186,61,40,196,208,28,136,119,101,36,210,226,52,175,235,200,109,39,72,109,208,243,138,191,212,112,241,255,140,84,135,41,149,18,74,71,117,169,225,47,36,251,47,104,143,61,234,88,50,148,255,119,218,157,33,205,193,198,233,229,11,62,162,92,119,220,137,255,123,184,226,35,157,8,174,39,63,216,248,137,225,131,8,2,82,204,80,214,39,91,209,189,161,6,81,144,36,198,76,197,109,194,10,4,72,54,53,184,115,91,225,10,11,168,200,46,218,124,246,135,15,89,53,166,8,241,71,83,123,154,209,50,174,37,55,123,83,140,20,54,44,56,182,163,26,6,6,190,38,53,147,232,222,149,68,107,255,157,252,151,137,92,252,145,148,33,103,9,72,231,13,116,195,38,2,23,236,159,143,19,6,218,213,124,179,244,182,30,110,173,19,168,90,131,57,252,205,106,250,34,115,21,156,227,2,178,233,51,164,166,165,72,112,14,41,93,38,111,111,37,191,106,207,33,185,185,90,72,233,134,236,98,171,160,112,169,40,190,94,93,171,234,98,137,93,127,65,248,80,186,131,116,191,197,63,31,50,255,195,58,34,142,54,220,246,198,63,55,183,44,126,0,217,209,232,158,8,7,110,86,107,240,61,28,52,138,97,149,20,247,180,192,143,33,83,155,177,22,187,216,48,139,83,169,139,99,123,154,74,125,236,38,59,46,27,30,157,211,15,232,203,47,94,136,56,194,51,139,205,174,21,161,217,7,160,227,59,236,156,91,143,154,27,42,117,22,168,18,246,201,35,37,107,157,58,5,158,76,100,112,62,84,117,50,22,6,96,111,120,207,116,151,161,13,67,239,116,206,98,64,136,103,8,201,197,9,81,239,18,226,93,190,46,81,229,232,167,200,193,215,90,182,212,93,78,67,26,105,97,197,49,164,150,52,143,248,121,13,95,217,227,206,14,80,200,179,171,10,146,200,142,90,137,125,253,146,71,131,33,45,48,69,241,119,153,254,188,241,25,222,97,30,63,46,136,159,57,134,89,0,129,234,189,184,64,200,208,245,48,167,116,134,99,230,3,164,217,19,159,106,99,97,202,22,164,70,66,13,97,32,58,239,114,37,9,60,59,67,157,37,172,251,50,177,13,116,63,7,119,74,90,248,108,175,187,95,134,112,101,157,132,160,143,70,245,232,144,69,184,106,150,9,184,122,224,32,162,162,167,166,203,10,237,99,78,75,217,159,250,237,184,75,97,163,68,55,215,93,14,236,225,12,141,49,8,40,126,117,77,135,80,77,205,97,75,21,26,145,221,123,172,2,182,77,86,93,204,86,114,144,92,13,141,25,97,222,15,100,182,160,159,142,35,220,49,107,187,208,137,105,153,135,0,174,222,172,239,170,133,207,178,208,164,230,211,2,139,92,32,192,133,89,232,32,239,245,110,166,136,37,21,196,131,79,242,98,209,25,180,252,102,119,100,85,102,115,189,106,122,226,157,178,221,143,154,92,187,57,68,241,18,33,225,250,134,114,116,72,134,250,27,40,97,219,30,86,74,184,102,193,26,66,181,24,165,153,255,190,75,185,18,121,114,85,220,59,224,145,174,176,36,67,144,74,196,161,88,9,48,79,220,4,67,25,232,105,176,32,242,28,201,66,116,178,36,164,218,208,31,240,68,239,166,138,242,198,226,27,136,232,255,174,210,152,60,200,61,15,238,2,218,231,198,130,236,180,235,65,221,66,82,162,92,235,251,20,38,65,92,156,106,85,0,144,25,182,28,226,88,153,34,253,19,27,116,90,101,248,35,202,216,184,19,35,2,94,8,209,254,66,212,135,68,219,185,32,107,225,25,227,136,211,138,181,174,112,128,190,66,165,251,135,185,108,40,159,222,177,26,58,26,148,218,89,13,15,27,236,24,118,78,33,185,174,168,219,230,119,230,179,169,161,57,118,97,227,203,9,125,55,136,197,112,94,138,136,230,112,204,245,136,116,59,13,75,68,121,43,122,9,22,252,149,172,182,118,113,61,53,171,44,42,118,178,166,69,222,44,157,34,128,126,179,24,154,159,106,149,17,227,58,143,176,241,222,56,42,62,181,26,208,33,24,30,33,112,83,127,84,65,41,251,206,115,178,2,222,106,153,209,238,98,208,200,210,177,133,86,65,23,104,110,177,161,96,79,57,142,162,15,207,173,153,56,254,250,73,76,74,43,36,200,57,145,60,95,227,21,147,221,41,171,192,107,234,251,74,126,3,247,128,122,243,153,128,202,238,189,17,198,179,70,97,245,190,200,231,176,186,98,217,254,45,230,228,185,78,204,155,64,247,183,255,152,161,26,12,21,183,209,199,194,177,1,221,95,77,76,253,203,104,7,192,167,209,180,50,138,227,189,182,231,239,238,168,59,221,119,154,107,247,102,200,51,40,120,192,133,47,249,238,189,123,233,117,188,210,82,68,72,178,111,103,77,144,205,181,97,1,172,166,152,242,0,187,181,174,188,39,82,5,75,21,213,113,66,102,62,173,169,132,21,120,138,226,211,39,44,143,160,126,74,108,191,13,117,58,148,234,239,194,161,161,156,231,240,170,77,120,106,63,168,175,231,243,60,192,181,236,20,52,239,78,141,78,130,59,219,80,208,24,37,165,109,209,49,251,9,62,80,50,249,181,232,42,228,47,166,191,144,176,206,148,242,148,153,182,121,24,128,65,137,42,161,119,66,94,240,11,55,102,122,7,205,142,144,144,180,47,60,218,192,149,85,15,213,83,8,79,215,104,8,209,172,222,200,242,28,255,51,185,167,33,226,26,65,147,100,114,222,54,27,170,212,207,83,56,170,37,126,121,14,18,40,231,4,14,164,248,6,110,118,48,51,83,228,76,3,131,87,77,86,163,48,72,194,109,53,105,118,111,198,140,133,34,20,119,56,35,236,7,170,176,164,95,86,183,232,105,108,7,25,169,127,50,26,86,83,94,101,58,219,72,205,46,231,78,158,94,221,190,147,92,96,224,0,30,65,191,21,237,118,106,224,247,161,116,33,41,10,92,81,248,232,191,41,72,116,171,89,110,208,62,230,196,11,67,172,81,188,8,212,62,255,199,22,201,68,20,120,21,90,72,70,211,251,61,232,5,238,147,16,91,225,65,103,178,238,63,246,157,100,192,170,206,249,101,28,25,120,125,225,94,105,146,218,75,10,178,103,244,73,77,174,18,113,205,198,233,5,88,129,66,64,72,137,118,81,217,130,206,156,174,224,223,115,249,164,10,160,47,237,255,135,146,236,13,99,71,63,62,20,134,132,135,155,27,21,239,159,60,195,224,248,123,205,45,147,225,233,72,95,151,236,249,144,43,148,51,197,175,100,140,185,170,200,234,37,87,113,85,41,197,41,164,33,181,64,228,58,125,41,220,43,111,47,37,139,69,75,126,166,210,12,7,175,6,63,122,236,237,156,149,142,254,174,11,37,215,82,200,54,62,74,43,2,249,172,218,115,203,91,14,165,110,103,178,200,5,226,141,45,42,68,130,198,173,253,230,217,122,113,39,163,182,160,231,100,179,40,207,8,27,212,22,174,85,58,27,55,118,83,118,244,201,68,167,205,50,31,36,17,250,228,187,200,203,159,109,44,83,197,240,214,82,128,207,62,237,127,108,238,226,36,190,44,152,27,248,90,79,254,43,191,182,206,138,179,239,133,27,56,192,25,166,40,83,172,241,62,178,172,53,58,205,73,6,139,66,50,24,22,193,232,205,173,161,67,139,236,13,114,239,156,46,253,12,218,238,6,255,169,98,117,8,215,156,102,178,212,208,18,175,147,108,96,73,71,115,87,75,254,77,61,212,49,252,42,72,23,95,49,206,208,189,203,240,139,4,56,101,109,139,204,117,23,213,104,47,1,254,115,179,25,96,58,221,157,53,112,19,110,172,118,168,11,21,171,109,123,100,79,124,202,172,155,236,144,86,224,44,183,119,167,51,180,139,191,76,201,173,212,215,120,148,255,149,110,69,229,152,112,197,133,178,122,15,23,55,103,67,13,152,239,59,168,53,175,130,232,143,236,0,96,95,206,91,141,167,127,199,149,82,51,222,51,43,148,225,183,56,32,68,76,97,35,154,233,207,47,2,29,114,143,36,159,81,168,169,22,163,74,208,233,149,204,129,138,138,13,48,180,42,41,155,141,156,228,19,71,135,137,63,119,146,67,61,236,133,52,209,164,39,67,110,28,5,36,100,159,52,79,220,118,89,126,230,63,180,117,243,165,179,147,209,255,162,97,177,43,45,86,56,48,223,195,122,39,130,118,8,183,36,55,42,221,83,72,74,95,130,91,23,121,226,221,206,241,204,44,105,177,188,105,190,84,106,225,244,183,44,76,188,169,150,98,155,208,244,161,94,75,232,173,64,126,153,184,124,75,229,87,31,209,154,93,125,64,53,167,155,250,167,122,169,184,231,14,34,61,208,47,179,182,194,37,87,240,10,125,2,26,125,232,189,207,199,3,153,204,157,148,33,93,160,134,67,238,203,126,198,203,210,112,25,199,23,136,192,135,207,227,224,213,125,17,93,230,177,178,164,152,162,80,107,50,52,221,42,20,128,143,202,168,22,91,223,159,118,214,249,29,184,124,24,124,1,183,54,43,61,91,155,116,241,94,157,187,60,100,244,97,97,177,9,57,90,72,245,38,31,86,172,41,102,15,35,39,4,233,141,9,165,41,137,229,44,122,16,181,99,178,84,124,207,34,140,41,145,250,172,186,100,100,156,162,5,126,187,160,57,183,240,17,46,181,44,120,144,141,151,142,129,195,192,11,203,241,78,134,142,214,106,198,94,141,84,62,51,127,110,9,65,150,68,221,157,131,236,130,114,10,128,197,13,157,252,8,165,223,138,108,179,156,231,156,82,132,196,202,13,64,69,92,110,180,238,15,125,240,30,231,134,56,66,31,193,191,100,72,106,233,11,113,8,121,238,178,117,107,157,215,58,43,212,236,53,215,214,1,16,192,173,175,231,62,113,26,94,248,47,30,36,232,160,227,75,161,127,33,5,192,210,69,155,249,190,217,224,42,17,77,54,231,20,45,5,116,154,154,80,74,148,126,85,137,13,59,123,226,167,20,148,24,19,123,17,78,46,126,232,255,147,20,83,85,103,16,86,141,246,211,162,58,245,162,77,31,51,40,174,164,117,38,201,18,8,240,124,226,180,213,190,92,223,249,184,227,8,168,86,142,19,66,247,142,54,135,218,13,197,216,225,152,61,155,156,171,88,150,158,129,132,144,138,13,21,166,17,156,62,40,147,131,134,66,228,77,177,184,53,207,92,208,3,16,2,45,215,154,73,196,92,47,104,0,94,23,103,132,206,81,105,63,84,231,7,205,95,148,128,250,142,158,42,49,223,26,22,72,27,211,39,245,201,245,4,127,48,221,21,121,201,223,108,209,6,93,31,85,112,207,74,123,201,78,249,139,38,60,134,47,225,21,74,31,177,146,41,144,16,100,28,219,207,21,104,154,200,135,169,238,147,227,243,217,211,187,109,182,74,223,148,201,132,46,26,159,121,196,145,148,161,153,126,127,103,44,44,215,135,248,8,157,23,184,220,82,173,81,229,136,173,243,230,69,68,158,137,156,73,166,209,116,155,166,231,141,186,187,84,175,227,63,227,13,18,245,222,185,2,9,97,179,58,174,246,67,94,255,153,44,100,138,172,19,5,67,221,82,20,224,61,104,222,44,53,106,82,147,130,225,31,218,140,64,109,45,5,216,165,119,100,159,228,18,213,150,192,59,85,135,249,36,228,230,57,28,67,206,105,230,148,212,28,106,92,97,2,31,152,107,208,11,10,205,238,102,126,66,83,190,233,77,232,77,96,85,249,251,119,192,179,5,0,198,67,127,22,157,78,146,64,204,6,39,200,12,229,227,234,242,193,195,141,125,107,248,143,210,251,18,220,67,240,110,48,114,110,15,160,241,14,133,152,132,225,44,134,92,88,11,167,164,225,12,234,164,92,9,175,74,190,164,193,157,232,4,137,216,80,165,124,20,254,221,2,198,63,217,156,135,119,4,178,58,153,215,139,67,52,172,206,47,40,75,33,86,67,63,41,10,20,37,237,37,156,4,13,25,23,201,228,9,237,67,16,22,116,17,184,162,203,188,227,13,110,65,231,79,200,61,118,207,68,161,90,71,47,113,31,224,165,90,23,21,239,63,80,176,54,103,99,60,125,72,207,90,110,231,121,225,205,35,28,16,137,252,136,94,179,14,97,157,227,66,82,219,137,26,78,157,181,147,28,161,251,43,196,201,53,245,149,152,194,86,91,70,203,91,114,199,241,212,180,125,44,131,135,116,26,132,69,27,84,222,132,88,96,163,119,62,129,249,230,33,147,28,124,23,172,231,132,144,182,235,125,193,70,233,206,77,27,210,203,223,213,95,105,230,117,205,214,164,126,23,240,10,34,237,211,43,162,138,230,118,192,86,247,125,167,215,62,26,113,209,175,19,231,246,167,150,22,44,69,31,236,205,198,210,214,123,93,60,9,175,131,96,145,71,92,190,209,201,225,103,43,204,242,98,253,129,95,56,223,107,29,87,165,180,44,49,28,37,42,83,215,122,91,126,77,38,243,71,213,191,223,14,76,247,97,110,190,120,147,167,234,237,10,98,148,45,218,3,23,117,15,148,142,173,118,236,90,31,27,85,54,188,202,253,43,102,109,130,17,8,239,241,89,212,14,29,172,179,90,8,104,5,203,117,188,43,184,167,54,8,100,136,17,55,201,102,193,221,245,173,86,65,162,176,40,92,214,101,18,82,59,131,63,156,187,219,65,190,115,172,242,52,181,80,109,165,136,98,148,149,152,234,86,143,132,100,239,159,119,163,250,30,130,119,190,45,58,208,104,161,144,10,202,200,31,177,215,242,236,78,3,151,34,8,16,172,231,112,71,159,168,32,208,230,50,84,234,214,40,92,65,60,148,117,76,216,111,91,121,177,66,86,123,55,54,126,46,118,241,103,105,245,89,242,0,0,166,87,7,145,164,227,90,30,10,4,88,64,114,70,127,14,161,218,198,16,35,230,115,54,65,108,190,175,186,252,79,33,24,82,118,130,249,181,253,61,28,154,77,227,209,111,63,61,68,223,162,41,90,176,37,114,169,199,77,160,219,199,22,79,240,212,158,243,217,226,74,158,215,193,166,204,82,135,0,106,12,155,150,113,241,197,33,205,6,16,19,118,164,194,115,243,112,162,251,134,203,122,124,61,242,68,140,200,131,168,172,123,48,70,132,227,199,3,196,130,48,55,231,64,216,195,86,36,160,233,137,145,108,224,93,218,61,107,191,138,171,13,215,212,65,223,117,85,120,109,207,141,12,23,221,175,68,130,129,185,138,67,225,85,127,85,215,75,146,79,69,133,10,129,210,51,71,147,116,11,104,76,194,87,78,137,12,108,185,53,10,210,35,135,33,203,224,96,175,47,98,138,83,60,163,16,100,51,21,186,245,7,153,128,164,73,27,189,195,13,61,255,96,12,174,169,37,39,235,177,224,137,71,128,240,63,137,238,255,68,185,212,135,190,156,240,184,158,113,210,241,119,224,63,177,236,63,172,135,117,74,27,187,227,253,246,222,134,197,251,197,243,107,188,160,85,252,111,4,141,195,243,91,73,226,144,131,109,136,10,172,209,186,95,172,96,107,43,22,44,176,226,122,100,50,28,65,163,62,235,88,16,254,97,48,250,64,155,101,21,83,64,255,189,98,142,60,20,184,3,54,87,20,50,178,254,138,105,53,169,141,5,88,57,244,207,138,191,208,185,54,87,134,70,182,197,77,248,201,118,133,148,231,106,241,215,91,61,184,61,250,9,140,91,66,203,141,93,171,166,65,183,29,234,196,85,230,194,177,148,240,126,71,14,92,212,2,120,179,141,11,42,166,15,45,196,187,30,249,247,104,244,5,25,126,208,252,253,157,224,36,138,145,222,221,213,15,204,112,217,50,193,215,194,2,248,214,48,43,229,7,204,79,218,223,82,137,114,228,41,220,68,157,35,245,242,213,255,141,189,192,243,63,72,119,222,107,252,230,192,211,47,186,209,144,213,221,185,22,152,208,54,130,76,100,242,54,210,211,40,29,189,40,7,183,252,209,130,240,76,107,14,110,35,151,57,0,187,180,78,210,153,198,18,212,33,205,72,211,89,150,175,136,7,138,13,18,93,226,93,52,171,126,188,165,113,29,15,231,234,11,67,54,164,115,158,58,48,20,202,65,198,247,224,202,190,45,10,153,146,148,150,218,67,157,27,190,197,15,182,135,56,130,43,203,209,174,134,100,81,179,58,182,229,1,155,224,135,148,214,99,38,92,212,220,49,17,170,248,161,123,88,92,5,119,19,210,149,12,254,121,21,140,38,10,247,25,4,22,186,68,1,211,221,109,182,103,137,4,242,129,66,67,138,61,50,131,83,208,81,53,132,36,86,63,33,62,142,250,210,195,68,246,210,84,77,150,182,48,140,129,1,24,195,122,107,160,22,129,227,250,27,102,21,127,52,229,47,19,58,21,47,132,85,233,11,183,119,3,54,223,94,30,168,153,3,202,62,170,29,46,235,105,186,122,192,71,128,73,149,47,98,46,122,34,64,101,76,177,160,154,47,174,96,118,108,73,203,121,15,19,101,72,99,177,70,118,219,124,182,128,41,154,76,22,204,166,120,224,174,35,27,29,63,8,248,217,183,247,192,11,141,178,28,4,184,73,111,64,221,65,220,21,145,34,163,79,94,28,225,40,146,182,182,2,244,18,250,136,64,65,3,121,52,149,19,150,105,221,244,244,247,77,249,155,100,216,128,178,170,122,153,140,221,2,88,211,227,255,108,191,91,6,185,100,148,31,75,245,179,229,46,107,30,214,20,93,198,142,86,108,83,131,235,38,107,38,203,229,248,160,22,216,41,215,22,55,59,211,156,38,76,79,202,176,49,88,161,162,206,46,81,83,200,99,138,117,40,110,2,84,142,165,212,63,185,183,35,165,96,218,110,177,40,36,21,19,181,76,171,145,175,144,249,115,42,97,99,152,49,128,122,54,8,136,236,196,46,137,181,211,218,83,112,177,64,193,136,89,220,176,221,204,172,174,154,77,96,166,191,132,59,141,90,169,6,46,45,84,193,160,209,49,6,199,255,3,129,73,146,92,31,226,30,164,12,7,148,241,217,3,113,226,199,81,146,95,141,45,176,205,253,233,128,78,74,123,244,138,154,234,99,11,241,18,251,174,123,196,122,254,82,210,2,90,216,87,97,38,253,160,197,255,134,152,168,162,17,72,133,41,122,235,85,154,133,172,162,240,103,107,149,216,192,182,55,27,163,94,52,129,61,154,61,11,135,223,222,154,217,53,135,124,181,120,2,41,107,239,28,32,232,45,27,51,86,176,14,7,40,249,170,100,67,101,131,23,151,200,74,151,82,184,146,40,7,64,240,146,253,80,218,150,108,16,186,224,225,98,8,166,177,252,0,35,95,107,137,80,130,116,129,161,149,37,52,149,240,167,11,50,129,134,80,126,16,233,201,206,97,186,68,205,245,254,241,139,20,5,89,162,39,98,188,107,186,119,233,101,250,245,150,241,120,191,39,29,12,121,31,198,242,252,230,85,160,112,172,171,128,29,103,65,246,39,126,74,92,140,142,56,181,82,101,195,59,71,4,8,9,42,98,180,136,41,26,56,252,4,230,102,239,251,161,183,106,22,54,238,250,59,61,243,9,189,77,195,254,119,234,124,186,211,5,26,88,176,159,87,101,242,100,179,102,218,39,85,82,118,109,146,144,225,73,28,78,77,189,135,29,192,12,95,153,113,248,50,171,113,241,189,121,194,155,247,109,70,124,72,61,27,79,56,185,218,51,155,130,98,183,1,100,60,85,55,160,158,110,41,58,63,216,176,49,228,195,87,118,254,105,223,41,138,84,41,78,214,111,49,206,175,91,190,57,25,68,120,22,127,85,81,202,226,197,123,156,169,249,12,182,148,31,115,211,146,41,208,248,249,197,188,103,47,138,8,117,43,130,28,28,102,44,149,38,221,176,211,11,76,148,186,176,252,87,62,69,3,88,80,123,168,196,245,128,224,186,224,99,220,46,237,181,88,159,161,175,204,237,160,154,13,131,12,99,88,171,231,111,242,238,194,193,15,3,254,152,148,114,131,215,216,106,245,73,197,176,147,149,25,185,200,252,52,225,236,86,240,34,22,76,102,243,132,148,11,204,125,58,185,37,184,188,4,169,89,249,104,232,254,3,96,102,68,177,242,8,251,188,177,100,48,1,248,177,185,181,108,161,130,117,35,229,28,94,131,105,31,242,158,200,167,63,124,21,55,142,139,10,202,5,82,209,8,37,48,22,47,237,174,182,254,11,32,46,255,142,78,113,207,192,187,172,174,16,156,90,26,138,142,57,129,2,59,148,175,197,194,242,205,81,57,214,199,206,60,204,225,254,113,28,148,222,242,209,101,104,98,108,237,223,49,114,212,129,78,146,78,208,40,162,230,188,127,198,195,47,15,146,82,173,159,186,217,133,148,237,194,5,33,102,245,90,65,8,165,35,12,231,205,62,97,232,36,7,127,30,119,233,149,99,221,178,173,102,226,168,250,196,60,181,5,125,126,243,158,64,110,37,30,195,162,229,136,241,198,229,105,88,85,49,14,96,84,216,55,253,53,92,172,24,38,54,35,37,50,118,149,84,244,199,203,56,87,218,44,100,7,25,135,147,55,101,115,200,99,37,8,239,72,221,30,76,8,86,146,55,44,91,241,31,111,230,90,185,168,144,245,50,43,46,238,33,229,223,34,244,14,118,219,103,141,110,249,21,49,255,202,251,214,126,66,144,34,95,94,195,240,131,109,100,123,73,158,69,82,217,206,59,169,190,31,185,211,83,88,73,74,185,229,228,147,57,21,198,39,234,143,84,167,170,144,247,206,56,43,55,104,193,157,220,89,125,173,151,17,4,10,18,124,244,41,133,194,59,11,202,98,174,212,26,19,95,71,26,82,242,133,85,125,4,131,36,108,37,250,255,99,63,15,53,173,129,255,175,83,105,132,142,35,4,243,133,67,237,220,88,25,169,219,83,229,33,83,46,251,0,111,226,87,41,226,98,245,208,93,251,94,207,210,41,146,56,119,137,32,0,61,212,6,161,219,144,112,202,88,124,132,83,197,240,185,196,152,34,202,136,59,198,165,5,136,11,246,158,60,3,176,105,203,207,70,162,187,45,160,39,60,82,115,113,239,37,166,188,235,215,222,227,65,73,188,70,178,98,215,247,7,12,10,4,216,139,202,178,125,231,103,79,61,127,58,10,202,75,42,107,139,214,172,4,14,3,23,73,247,52,158,78,61,218,235,79,191,182,70,127,157,34,208,242,177,248,153,110,42,50,168,186,212,159,202,174,245,161,60,197,47,221,200,111,195,231,35,136,145,196,62,119,52,247,41,50,41,64,94,231,136,149,213,174,127,157,61,143,47,166,152,59,245,186,16,70,32,201,49,239,157,90,225,122,138,88,158,93,59,121,246,69,151,25,182,189,199,100,74,131,123,99,103,185,138,240,169,255,83,8,240,13,159,156,5,223,181,247,243,244,179,90,207,159,36,69,34,174,29,39,12,198,108,220,130,2,10,203,188,206,67,116,209,27,67,170,198,93,113,250,14,198,254,196,37,146,198,0,245,162,19,196,105,30,136,94,211,48,61,213,53,160,236,102,140,240,236,1,246,124,73,73,184,88,243,157,125,154,77,39,104,111,1,205,78,22,233,44,37,253,92,198,51,8,211,150,43,192,106,122,208,21,123,140,14,148,222,144,217,194,15,242,120,80,45,66,71,74,147,132,37,185,45,165,41,76,166,143,130,134,3,4,15,104,214,102,179,162,238,195,200,235,20,223,172,249,110,37,43,216,136,128,232,235,48,215,2,250,173,82,109,146,30,125,217,231,73,206,65,2,40,45,35,163,248,230,102,19,67,102,0,76,64,7,130,23,167,105,28,152,26,73,234,15,36,35,231,146,205,50,217,164,199,154,192,15,19,80,26,30,181,14,197,12,131,88,61,140,86,85,233,182,210,78,143,77,63,177,30,176,10,224,14,137,130,162,84,191,108,227,75,85,115,237,159,119,222,168,131,18,13,22,92,110,176,134,71,180,31,116,154,111,4,116,74,59,2,191,75,114,181,184,238,106,236,202,251,63,247,48,35,155,172,61,122,174,26,38,3,176,42,15,71,195,153,55,66,191,33,169,177,220,36,95,177,66,86,173,31,180,219,166,178,139,120,139,67,88,25,238,233,169,169,111,163,217,54,29,44,34,138,236,199,35,50,82,214,30,125,91,25,222,65,137,125,96,232,78,167,209,68,71,70,1,22,163,34,202,200,71,113,235,157,41,14,32,110,171,235,197,174,10,51,158,251,44,98,199,201,196,168,50,201,99,205,245,153,75,169,17,143,154,52,222,138,28,173,86,92,134,115,136,220,131,85,171,122,218,117,190,117,143,79,26,121,10,50,45,80,241,33,4,253,140,1,159,201,105,123,35,133,81,59,236,16,238,109,215,10,124,211,64,112,180,147,203,106,142,69,97,205,162,177,217,151,174,189,239,69,50,30,166,238,219,120,79,225,197,121,127,91,215,89,102,17,39,158,213,94,164,254,49,125,216,191,222,90,38,224,214,242,60,2,38,241,139,218,34,185,186,30,206,33,43,38,242,81,191,12,1,200,96,167,125,197,194,127,129,244,184,30,74,74,196,174,229,224,226,124,52,137,122,146,108,187,169,127,72,111,131,243,79,149,236,134,103,137,212,161,44,61,183,188,103,150,96,95,88,187,167,31,213,185,63,128,70,10,58,47,69,155,112,231,242,129,19,78,116,74,152,85,44,128,199,241,148,56,48,27,194,180,191,35,170,227,179,166,110,172,88,208,185,53,153,120,109,155,216,205,172,159,59,191,94,49,209,213,90,125,246,132,153,163,89,50,28,91,141,185,11,4,229,210,18,79,36,117,191,90,231,97,92,89,193,98,201,7,9,252,3,100,157,87,134,164,29,218,54,7,117,232,97,226,74,185,43,135,78,199,151,206,137,157,244,201,49,137,164,23,115,134,121,92,128,224,192,100,154,252,124,146,17,129,44,130,237,65,159,194,35,88,56,132,29,163,200,91,112,118,35,100,76,112,87,180,233,171,69,124,62,161,232,54,66,129,248,193,47,232,197,143,236,112,36,132,61,97,179,231,60,124,4,220,161,114,16,84,196,143,200,58,98,2,255,8,3,222,42,146,204,234,68,199,78,202,173,32,215,30,242,64,32,250,49,111,31,174,191,209,40,51,55,101,12,137,212,116,140,72,132,52,104,204,245,218,122,29,236,175,188,112,137,112,129,225,22,84,118,55,75,104,13,207,51,243,102,148,120,49,86,192,53,173,30,143,161,0,187,160,141,185,32,104,37,221,242,44,29,27,162,135,12,4,205,239,98,8,217,237,81,207,29,240,169,209,6,80,56,120,99,193,90,244,235,14,45,162,130,224,62,152,96,147,9,238,188,49,82,151,207,8,240,126,39,228,192,121,199,227,52,238,238,69,130,134,174,90,34,126,176,133,63,234,79,219,126,186,224,106,183,242,244,90,180,161,17,110,155,66,109,222,205,83,121,103,49,85,234,220,198,98,67,0,50,194,21,182,193,118,19,220,4,173,96,221,203,40,186,232,98,162,37,12,169,225,26,229,12,71,121,194,162,100,159,139,30,0,151,86,14,131,219,129,154,212,170,79,126,26,171,90,92,239,0,106,79,97,213,183,128,12,238,216,30,67,114,73,64,191,22,179,225,12,252,220,234,87,55,51,145,66,34,63,168,252,148,87,47,176,54,228,85,152,226,61,198,41,76,94,182,131,134,142,127,97,14,232,78,147,107,91,23,55,184,220,0,132,128,230,214,41,253,146,45,59,69,244,78,228,127,47,234,235,212,197,152,203,251,16,167,93,153,46,245,207,238,82,246,96,131,4,123,250,67,9,15,63,198,214,205,18,51,223,238,190,104,69,185,188,1,61,168,132,22,21,224,86,237,119,49,15,228,241,216,161,180,19,252,22,109,144,133,49,21,97,145,73,250,32,160,0,103,179,235,69,26,206,44,140,184,97,110,167,21,84,228,112,18,154,24,41,60,232,190,168,43,72,248,82,221,13,138,79,89,140,122,61,117,232,17,75,243,217,88,218,235,50,96,182,174,230,168,249,99,90,3,240,143,171,128,49,247,62,32,242,216,73,239,88,172,30,77,172,78,40,138,46,152,178,103,92,139,57,224,167,208,14,63,245,78,69,235,225,103,133,134,96,22,32,104,77,117,153,192,206,38,183,221,117,253,207,240,211,16,89,105,251,119,74,144,222,156,150,154,58,135,38,58,165,24,125,4,181,205,243,117,226,156,243,80,70,66,176,146,37,197,55,215,99,87,148,92,191,170,198,29,60,48,57,132,232,226,100,191,28,143,184,235,205,69,47,243,18,71,89,96,148,5,68,98,120,4,46,222,166,248,156,123,31,13,147,244,29,153,133,248,130,207,112,2,139,131,49,115,58,120,121,244,170,19,97,201,192,75,161,137,127,83,157,78,253,58,222,224,220,83,182,11,236,101,153,140,34,113,36,254,143,112,151,78,23,46,155,32,170,178,239,64,77,243,128,127,240,27,82,213,68,205,87,27,42,124,75,156,9,234,4,161,210,181,7,140,130,78,31,105,100,208,169,223,62,105,229,132,50,56,128,226,5,184,254,213,116,54,2,93,233,67,132,34,39,179,133,27,209,227,163,127,21,38,10,175,140,28,114,70,190,173,123,166,31,176,23,83,27,2,64,147,250,217,95,1,100,211,238,42,151,65,188,182,234,61,134,64,31,245,14,173,167,214,244,223,242,182,230,208,180,241,228,142,135,251,1,188,189,100,175,18,181,117,35,14,102,136,20,208,168,235,41,228,102,112,204,114,197,137,63,144,1,174,122,8,52,194,119,247,169,229,16,103,124,105,126,128,30,165,102,132,107,24,55,253,220,212,101,202,129,150,144,2,88,195,9,152,160,243,97,168,80,228,18,168,79,186,193,151,206,197,164,32,6,58,126,128,178,154,122,20,188,81,123,96,6,46,214,149,107,24,177,129,255,208,247,29,66,228,212,126,81,168,1,76,131,174,108,141,122,248,24,107,113,170,68,235,117,129,83,56,163,148,130,79,104,185,22,138,198,242,77,180,102,47,117,225,233,90,16,225,8,163,241,112,173,15,227,176,197,136,139,114,202,96,151,63,60,96,154,107,17,147,224,206,248,93,53,106,235,229,60,87,165,173,67,60,192,40,25,38,154,183,128,195,41,187,21,254,166,61,76,158,20,29,63,194,131,191,180,111,32,193,245,193,122,94,224,84,142,94,172,150,192,219,151,49,107,61,164,252,204,72,119,227,21,253,120,84,60,176,113,224,172,24,196,92,64,19,6,114,3,127,121,48,40,3,60,52,74,110,225,56,14,140,23,179,58,129,206,230,166,25,190,123,31,5,201,50,253,204,94,174,116,91,166,97,216,90,145,201,152,88,164,18,19,17,202,204,251,146,159,61,233,43,209,63,240,241,168,94,78,86,211,0,62,97,12,204,199,62,218,65,64,9,170,91,210,0,191,56,249,81,51,140,84,246,229,192,59,27,87,104,195,108,174,216,168,188,98,234,57,57,162,193,13,190,155,45,124,40,58,32,99,14,179,68,39,112,92,159,159,36,201,2,226,129,171,120,102,185,148,114,152,162,196,181,56,69,182,37,197,98,228,38,41,142,10,57,84,197,160,183,210,236,9,42,214,224,63,62,31,118,26,251,177,236,185,210,104,244,19,251,195,113,141,34,50,255,204,42,56,117,66,203,139,249,119,14,28,203,175,32,42,245,180,104,11,154,25,127,248,60,200,28,180,91,39,244,161,108,240,140,189,72,32,119,76,235,30,100,46,74,250,110,234,232,192,243,51,124,39,251,186,123,64,23,149,105,161,56,180,49,163,245,34,42,187,145,64,13,82,135,95,186,146,44,214,135,104,194,94,110,93,178,242,130,21,226,63,156,184,127,204,241,167,193,180,9,237,106,90,105,165,19,198,246,140,189,35,66,77,27,170,145,237,170,99,161,189,234,238,51,219,82,212,214,32,43,128,193,45,163,2,216,44,192,84,104,92,99,93,116,94,163,255,90,174,176,184,147,127,46,68,22,63,23,62,151,173,125,237,52,101,54,144,205,184,145,103,197,86,53,11,127,158,118,175,217,13,86,251,47,11,230,181,185,174,212,134,254,17,229,174,154,246,87,107,230,55,252,104,84,104,251,201,66,110,183,24,71,54,10,178,175,12,182,18,163,73,203,244,85,216,175,129,81,60,17,112,71,155,136,34,122,134,137,245,172,152,64,127,55,97,0,148,116,138,88,45,172,16,250,169,10,55,168,155,249,246,117,74,112,183,220,144,84,127,245,255,79,75,162,219,9,150,235,53,199,122,194,58,198,192,83,66,183,114,7,36,198,143,179,218,40,178,248,218,185,108,140,103,50,91,31,235,191,230,109,62,140,189,224,31,241,31,255,48,167,106,18,242,164,95,24,208,232,159,107,188,95,66,187,61,92,245,43,201,191,135,1,41,19,255,103,156,115,9,219,112,48,74,62,113,152,120,196,200,133,105,206,67,75,26,102,159,159,237,244,74,119,46,70,217,24,102,5,82,212,11,224,67,44,241,148,125,122,140,30,141,56,185,122,202,228,228,152,203,143,221,92,116,168,69,113,89,106,187,215,201,255,151,132,143,105,97,52,138,102,179,146,194,72,5,11,142,16,31,119,218,54,11,45,117,143,78,191,169,116,115,101,231,67,196,81,203,175,126,36,74,3,153,52,15,176,118,87,2,10,235,166,166,25,217,24,97,56,174,121,208,62,83,81,159,25,1,81,67,213,89,71,34,140,83,221,7,159,118,96,172,176,235,249,185,28,97,166,17,64,245,165,23,63,251,128,105,12,76,148,92,91,188,236,238,25,184,58,203,60,22,171,192,183,224,144,158,173,39,61,188,92,76,155,181,102,5,187,207,150,94,58,3,250,36,236,210,151,254,24,164,165,111,28,108,229,47,22,146,124,12,137,148,24,184,174,127,13,247,114,83,177,100,178,209,116,247,77,184,99,249,116,52,90,208,48,242,239,23,251,172,248,54,133,62,24,240,90,110,209,64,19,65,231,127,36,40,74,61,89,232,108,40,133,183,241,255,164,20,180,249,37,233,11,144,123,198,10,134,56,30,115,232,181,188,113,167,11,26,133,132,207,13,144,114,236,85,141,70,151,42,10,176,211,160,243,33,210,57,247,197,33,32,215,207,152,153,82,222,95,87,217,232,251,9,157,52,92,92,186,221,244,36,132,244,171,126,222,212,178,213,118,239,52,68,215,228,157,37,229,77,151,40,95,205,177,209,250,59,223,193,65,135,147,161,220,60,30,20,221,12,251,251,237,115,218,76,211,222,227,113,244,133,150,144,25,141,230,202,17,219,118,142,8,254,249,111,8,74,66,92,214,206,5,252,176,47,65,208,174,127,25,182,208,254,125,215,136,104,95,122,148,47,160,24,171,217,115,108,36,46,111,121,54,209,200,78,201,242,47,82,146,153,116,84,30,151,175,199,2,189,89,106,30,113,219,11,101,233,191,165,1,168,238,15,156,187,76,114,205,125,10,232,251,59,152,234,16,241,125,111,195,40,170,83,198,62,219,137,128,20,195,25,33,235,77,95,39,151,116,175,239,44,250,171,84,173,154,211,23,212,157,160,162,208,164,16,244,147,14,14,17,6,104,150,53,108,250,78,227,27,137,22,252,98,238,175,243,37,70,13,183,79,164,152,113,101,78,244,30,197,103,210,103,214,38,156,171,0,17,21,28,178,30,168,20,31,200,208,51,52,113,15,151,103,235,237,40,10,81,34,216,193,173,182,231,138,223,70,74,110,140,135,128,67,193,157,182,109,142,223,157,163,206,148,192,228,100,183,148,130,219,246,217,18,184,83,27,227,178,40,188,85,136,45,33,244,69,87,159,128,40,97,108,157,0,46,148,60,23,222,235,38,205,188,53,18,244,187,182,168,183,237,144,27,24,195,130,65,220,216,15,20,137,249,27,41,218,232,246,197,92,106,119,80,113,188,192,30,233,34,219,39,146,187,114,27,18,165,104,236,249,38,44,105,166,205,230,49,128,243,36,251,113,40,38,25,215,224,120,27,235,159,12,92,34,87,109,158,74,60,6,136,178,187,38,91,137,86,88,121,201,214,195,151,83,64,228,135,143,158,147,97,176,188,111,251,247,113,197,192,23,113,9,177,188,15,65,193,111,153,189,107,45,251,63,75,15,75,144,12,21,147,41,0,174,131,76,50,32,230,156,172,12,21,217,99,174,122,176,90,142,255,218,205,218,102,252,254,211,225,2,68,190,66,50,226,64,173,14,103,174,112,42,47,226,144,59,125,110,69,123,255,9,156,24,136,238,168,115,76,198,25,170,142,181,178,27,82,125,25,38,98,50,248,232,139,82,51,79,162,74,26,73,204,26,40,13,40,2,73,96,105,177,92,99,35,99,110,56,185,105,177,205,31,100,153,114,150,60,150,252,43,129,210,116,71,159,252,129,54,152,242,65,180,226,15,50,224,127,124,175,143,91,38,46,62,8,22,59,186,178,38,77,246,103,48,216,212,109,56,156,174,127,24,51,123,161,249,178,142,219,27,68,158,78,254,94,242,73,34,240,204,200,93,216,7,25,228,165,205,3,19,2,181,77,104,175,11,217,230,194,135,111,69,253,161,56,50,214,192,155,137,146,17,189,167,202,57,121,74,241,142,45,201,161,154,57,125,92,44,130,241,88,74,115,124,14,144,36,13,187,40,11,139,4,59,158,157,206,13,92,151,135,1,219,94,61,152,173,99,202,240,172,225,103,253,248,69,184,171,34,33,169,218,245,125,15,58,199,178,40,202,80,134,75,170,110,92,65,6,58,200,15,51,116,102,229,188,24,164,185,80,221,62,235,227,1,238,159,158,44,47,211,248,136,211,153,57,241,104,231,90,19,39,187,253,118,187,69,91,208,213,90,157,249,110,157,246,186,4,46,212,11,235,27,55,22,236,16,139,224,123,76,76,174,18,156,21,2,25,59,83,147,157,186,202,18,243,139,77,192,205,43,11,67,231,130,169,53,171,6,241,244,138,2,96,125,93,209,194,120,187,162,104,129,237,118,242,149,94,212,207,222,141,202,202,204,103,231,34,132,92,157,95,239,176,202,195,185,87,154,63,219,10,215,8,146,73,190,222,17,110,27,90,35,66,27,93,191,17,12,120,158,138,224,58,68,152,169,243,48,157,252,163,132,148,157,222,184,145,161,202,141,123,93,61,82,14,213,82,53,66,165,100,215,10,77,207,216,139,35,208,176,63,63,80,219,7,147,222,36,12,252,16,92,225,56,96,70,218,129,99,205,25,99,208,253,109,43,104,153,0,224,39,192,163,67,138,85,157,8,128,148,197,89,194,87,99,206,81,141,47,214,217,156,211,187,184,220,33,32,20,31,143,48,136,147,54,141,147,129,53,91,215,115,208,74,187,36,225,92,30,238,23,79,195,80,124,161,28,40,129,212,156,128,13,94,16,64,122,47,166,181,116,236,218,16,106,162,20,12,250,106,59,75,168,173,41,229,75,239,230,135,79,240,61,106,144,243,222,80,207,8,155,238,226,204,246,25,2,83,116,227,42,121,189,61,88,237,200,221,66,111,84,209,44,204,5,74,21,249,236,194,187,52,103,164,109,114,191,27,0,240,99,60,253,103,92,69,90,87,109,109,138,61,171,55,129,98,152,62,65,82,93,47,130,95,171,12,145,48,243,4,220,47,118,144,188,144,153,224,242,141,144,94,218,128,144,77,106,98,182,215,118,91,73,238,22,122,110,3,109,89,91,34,0,57,72,86,228,158,153,209,235,58,200,213,223,68,254,49,210,128,11,87,0,207,25,93,183,141,193,9,142,11,15,213,209,90,220,249,117,222,163,188,42,116,162,111,235,175,70,29,243,205,184,46,214,112,219,68,27,190,37,228,13,196,98,127,58,220,90,248,241,41,128,82,170,102,78,72,99,103,47,49,238,210,203,217,40,130,83,98,143,81,119,52,173,166,24,234,61,253,11,147,118,189,128,69,161,207,122,161,251,67,139,246,0,44,109,95,241,166,224,177,225,201,10,38,201,24,44,192,55,22,191,109,159,167,39,67,213,33,100,6,197,183,223,105,223,51,37,21,232,53,7,12,64,243,13,77,22,76,175,156,127,201,50,147,144,135,179,71,59,88,161,195,29,23,213,184,66,77,202,54,134,198,21,205,74,59,68,197,2,150,28,192,219,164,192,158,231,193,240,26,176,33,136,97,129,95,91,76,114,79,86,97,220,135,80,233,39,150,150,27,223,206,160,84,151,120,226,45,231,200,167,121,200,46,1,132,39,112,88,96,85,173,249,29,67,46,208,224,131,84,81,64,218,16,15,12,243,215,86,157,212,204,147,221,26,11,10,114,75,9,240,8,16,58,152,196,219,149,51,8,94,225,203,7,157,156,249,220,220,207,80,128,47,103,189,58,38,83,183,122,51,230,254,146,160,37,235,226,233,55,164,177,33,246,224,67,54,25,126,27,216,100,83,102,46,231,99,215,206,57,243,30,174,54,153,209,116,17,156,121,215,104,69,33,59,37,187,95,75,158,233,68,148,64,236,174,32,201,143,189,99,126,50,216,65,155,184,98,84,102,243,47,178,99,59,227,198,213,53,206,39,35,180,9,162,212,58,190,48,80,234,176,124,165,130,234,100,117,5,245,122,210,159,134,31,165,144,196,154,81,131,130,236,180,4,23,225,45,144,92,99,117,71,130,142,141,103,81,168,211,2,123,203,171,59,133,24,46,169,116,160,216,233,44,215,66,201,119,51,58,75,50,68,116,127,170,113,129,55,193,109,155,237,246,191,189,150,135,24,5,204,65,201,86,15,202,87,40,122,227,52,245,82,182,54,65,104,165,101,190,208,117,246,203,163,168,171,35,67,186,170,221,100,63,0,206,157,229,28,237,147,132,88,91,215,64,64,22,48,88,246,232,140,146,211,199,110,230,207,238,78,66,78,104,253,244,227,114,94,210,30,6,33,43,1,110,176,2,156,178,126,202,213,183,124,213,218,56,96,100,54,192,53,69,60,180,73,48,142,15,85,251,191,216,147,246,47,251,203,203,138,14,174,9,73,186,102,220,0,200,22,56,137,234,117,155,105,229,151,192,129,193,93,234,222,103,57,195,107,240,92,18,180,41,23,23,255,255,135,26,222,109,47,129,205,129,52,192,82,153,195,24,72,58,156,127,159,210,114,67,196,173,239,17,84,216,115,57,151,70,218,133,179,61,149,175,160,128,222,103,91,202,239,92,198,173,251,58,186,236,105,215,23,167,254,58,4,21,22,17,213,211,230,47,195,183,154,245,187,224,165,236,107,184,195,149,49,79,138,158,97,201,64,138,145,249,37,253,56,175,148,83,197,74,69,186,47,38,63,14,241,224,30,52,152,74,163,144,190,253,92,176,164,109,217,165,118,19,56,214,162,10,193,213,18,95,72,55,150,22,199,50,196,111,155,204,32,122,25,68,234,156,43,178,92,160,204,83,138,2,184,248,7,132,201,144,69,176,216,12,49,175,55,89,163,91,23,159,27,226,183,111,153,13,35,140,237,237,170,126,119,171,55,105,81,53,55,142,131,46,39,136,83,145,158,216,192,73,71,22,117,124,243,85,81,130,52,28,216,143,226,153,141,3,162,141,249,125,8,119,27,65,133,135,123,117,71,161,45,130,255,194,160,178,21,123,106,105,199,3,146,205,115,157,18,61,181,226,101,151,234,244,10,17,216,104,186,3,215,32,157,200,151,190,41,62,181,74,5,160,213,185,70,97,253,164,115,81,108,228,207,4,144,210,54,224,36,93,21,210,109,58,54,121,127,235,182,110,122,161,24,48,114,193,83,31,221,109,136,70,83,212,203,195,232,231,69,5,55,157,106,77,101,19,58,55,127,91,240,85,64,11,229,155,10,93,177,2,144,20,75,121,186,81,171,50,1,196,62,217,231,16,206,250,186,173,24,60,218,230,99,216,36,3,103,61,237,73,61,170,38,35,224,158,166,103,119,128,4,5,152,194,141,234,113,149,54,196,25,235,18,81,227,137,137,138,115,20,204,38,189,115,69,224,31,135,6,32,171,72,87,42,144,71,72,255,171,79,132,159,83,151,209,62,152,25,79,133,19,172,154,90,84,80,101,131,150,37,245,195,199,210,235,98,122,229,215,7,164,79,63,62,80,142,144,161,189,235,24,212,200,109,145,185,104,122,29,112,81,147,15,4,108,147,244,184,155,249,18,80,201,174,227,93,226,109,63,7,17,14,209,141,194,160,30,170,18,60,144,32,224,177,0,106,248,126,107,84,185,179,106,146,13,238,80,251,18,50,96,122,216,217,112,187,148,102,111,47,244,158,22,39,76,59,150,43,22,117,202,253,88,26,166,126,243,142,239,81,69,185,255,93,56,20,32,232,185,22,217,19,198,221,159,42,176,105,127,180,90,189,136,213,241,120,92,0,77,136,165,142,142,126,142,164,219,231,41,237,134,253,191,235,254,252,57,52,25,89,120,215,145,142,87,152,149,107,177,79,86,176,4,105,59,150,254,14,74,110,116,206,16,0,218,98,156,66,18,10,16,202,136,15,80,236,236,233,75,132,186,168,174,233,16,240,124,0,189,243,98,252,33,121,215,44,173,199,127,71,233,97,165,227,102,12,62,59,225,180,119,55,117,95,159,229,177,99,143,111,247,182,37,180,23,219,51,67,250,113,124,122,213,160,93,82,156,170,252,0,1,76,22,11,250,91,147,112,1,233,251,21,112,60,137,25,215,114,231,83,28,55,129,94,198,200,247,80,156,163,198,211,214,235,239,111,210,160,137,128,181,114,163,61,8,94,83,46,49,30,181,239,140,222,109,66,167,226,89,159,32,73,145,21,222,213,65,62,66,94,137,206,128,169,236,73,167,141,150,232,238,36,44,136,68,28,4,21,153,225,253,254,31,210,190,138,17,5,228,142,90,163,91,64,60,208,230,70,88,201,198,140,171,37,112,143,83,251,39,36,63,189,48,135,196,100,189,76,124,37,117,179,153,183,236,97,94,72,5,144,76,23,71,22,137,91,101,17,51,31,37,37,248,167,248,202,225,125,28,24,192,51,67,242,20,243,183,110,138,211,210,110,39,221,189,226,241,100,225,217,111,128,6,152,234,156,179,79,2,139,150,103,51,47,252,21,104,71,84,83,243,17,144,151,52,96,128,26,163,179,77,162,97,109,136,128,106,219,50,111,229,203,148,252,102,19,181,220,239,169,7,60,6,173,111,160,55,24,162,69,223,39,186,222,104,184,206,203,0,68,178,244,108,51,107,230,205,176,248,207,12,225,122,184,184,1,99,226,173,135,71,136,45,243,127,168,160,134,31,180,45,53,1,213,36,43,83,51,59,61,115,223,67,123,54,86,38,128,71,198,210,179,241,150,253,253,1,26,104,127,234,182,86,121,188,19,134,211,19,249,75,96,210,137,255,175,48,38,23,82,107,180,73,87,97,17,31,217,160,77,243,143,164,224,77,154,152,148,205,66,240,48,168,156,21,103,19,214,154,17,173,156,16,31,18,63,134,224,211,145,46,114,33,113,105,125,72,78,202,25,183,28,255,45,63,169,16,225,2,237,156,45,254,223,125,195,250,99,49,156,250,188,216,169,104,171,157,188,114,72,110,29,153,187,99,254,51,237,255,23,98,131,248,193,121,59,142,7,176,78,52,182,134,170,136,125,40,234,245,225,74,212,208,176,105,253,8,32,143,69,180,249,246,10,31,176,129,144,255,199,193,59,12,181,231,207,169,241,243,19,253,220,49,45,195,42,147,102,239,117,186,240,63,156,184,43,225,119,87,44,38,11,106,231,241,208,145,167,222,147,22,240,37,62,139,30,249,0,209,78,164,84,131,254,178,126,91,170,226,29,73,170,154,101,221,202,18,92,146,134,178,38,195,106,88,228,86,86,172,34,113,89,4,85,139,78,39,3,161,49,94,245,107,21,206,162,64,240,35,201,126,89,226,156,229,141,165,29,4,22,197,202,125,44,200,64,176,137,55,95,167,234,104,86,244,217,45,234,206,4,6,171,85,146,235,237,168,81,103,77,204,104,16,110,90,132,100,240,72,96,188,201,254,56,43,229,76,8,144,250,190,182,102,89,64,104,238,222,184,173,138,130,235,233,91,226,30,237,38,236,194,116,180,36,198,97,37,242,32,60,224,15,13,203,190,121,127,41,1,108,205,117,79,104,173,232,164,128,0,31,193,82,164,115,1,175,199,50,22,0,215,136,87,212,105,174,240,47,27,51,93,165,183,61,96,31,150,125,70,38,192,85,215,191,65,159,42,123,59,211,210,39,96,64,53,80,103,134,214,75,89,23,40,114,4,148,61,56,175,176,119,180,61,162,119,184,21,110,204,103,52,202,109,151,202,204,240,215,165,116,96,52,113,64,112,42,171,54,172,169,69,253,44,153,24,232,19,141,73,3,80,141,143,57,23,209,218,79,5,176,20,117,197,223,97,0,0,216,103,205,251,42,189,173,104,182,224,240,187,184,90,150,165,151,54,237,248,21,195,252,26,86,186,43,130,85,173,165,88,77,47,61,60,251,197,177,40,114,201,153,72,161,39,61,136,217,22,39,227,180,112,20,184,0,22,255,248,87,132,120,113,8,6,226,212,166,57,112,185,75,15,83,79,196,106,136,205,5,59,250,63,35,80,140,176,236,196,248,3,221,98,250,104,32,99,152,165,109,139,192,40,49,68,14,50,89,102,202,12,64,120,114,49,227,205,144,18,43,180,65,47,167,89,67,145,180,44,241,173,23,232,86,141,103,210,72,240,225,180,133,221,238,4,125,161,121,44,204,5,162,64,34,84,167,152,247,154,190,162,116,71,83,180,181,174,3,151,227,180,162,28,198,133,1,195,199,54,251,220,4,182,126,209,15,24,207,187,240,50,11,120,250,158,87,125,246,74,64,175,190,21,150,255,202,170,125,38,228,16,24,166,186,7,113,0,133,182,112,138,188,2,24,120,236,10,76,154,89,48,23,228,159,219,144,219,209,76,59,25,100,202,46,203,178,117,252,97,240,97,42,143,205,52,199,220,7,0,109,217,139,126,170,178,227,213,192,16,171,133,173,237,240,186,6,14,155,94,157,194,99,123,174,181,74,164,126,56,178,0,172,77,163,74,172,53,5,161,130,161,162,149,232,150,69,170,172,59,70,142,112,87,58,16,192,67,8,250,29,140,221,17,117,167,133,43,180,141,157,214,18,131,114,105,147,206,25,138,207,188,30,41,9,97,113,247,123,251,56,165,182,239,95,79,152,45,113,160,213,230,249,227,167,149,52,172,156,182,242,134,61,19,90,144,248,100,252,168,76,213,246,126,123,175,8,114,218,41,247,90,229,94,238,86,73,43,35,42,116,168,217,75,167,166,122,230,82,130,255,164,51,9,86,79,111,49,152,198,132,96,62,12,131,23,66,96,51,213,29,13,144,20,26,228,66,41,228,68,254,126,173,192,51,62,41,184,136,182,93,102,144,250,65,236,200,19,121,182,87,125,72,97,132,164,29,130,211,26,115,217,177,199,35,54,132,98,87,138,188,229,34,130,240,81,186,231,130,41,17,74,64,27,41,169,251,229,192,38,247,81,85,224,10,181,80,164,164,112,73,150,53,119,166,144,157,52,98,187,48,28,64,77,33,237,100,1,46,123,40,27,232,128,105,190,126,27,132,205,16,107,184,30,187,240,29,128,81,177,9,175,37,159,188,53,109,59,15,33,102,39,182,31,73,163,176,14,150,178,216,231,41,152,253,100,240,46,106,181,137,111,240,101,204,74,57,134,179,49,230,134,124,152,70,64,166,43,65,203,80,53,157,166,39,138,142,243,74,145,217,9,194,93,128,67,93,129,161,161,254,211,189,239,205,32,171,253,118,141,204,240,183,222,146,198,220,187,58,201,238,218,179,206,89,183,40,198,33,53,38,40,144,216,247,161,189,216,173,9,22,72,148,174,45,3,127,35,125,111,140,15,207,119,246,38,244,195,69,85,106,121,28,241,125,124,103,116,108,152,84,133,165,68,92,5,189,160,223,125,159,69,84,91,214,24,52,36,207,180,152,8,156,70,209,194,220,165,138,212,192,246,132,124,186,64,218,179,23,131,210,117,7,15,197,250,249,187,104,74,19,195,232,168,66,171,125,133,252,89,123,236,67,152,150,187,82,161,241,29,160,206,15,254,101,201,34,79,182,6,88,237,204,67,3,24,199,64,58,22,71,118,31,80,235,148,111,111,74,248,229,15,0,160,215,0,121,227,15,243,58,122,251,203,236,223,102,217,235,105,113,239,209,206,227,198,166,116,250,85,48,71,14,78,216,2,167,129,129,240,167,56,89,118,161,125,49,228,56,221,13,219,207,36,68,253,27,45,219,117,151,229,111,247,206,97,173,132,8,74,182,16,125,54,238,31,46,244,50,250,3,216,182,42,120,67,61,39,106,101,23,248,21,80,151,115,41,105,95,47,32,90,53,3,164,31,12,113,105,26,135,101,186,43,191,173,143,177,4,75,109,96,7,121,5,231,218,250,45,96,254,193,146,225,251,238,21,240,27,207,43,187,7,61,254,195,234,210,152,46,241,186,188,216,234,82,179,109,61,190,139,211,58,36,74,149,107,249,150,196,71,226,167,232,40,42,19,152,17,194,16,94,5,11,57,37,43,99,98,248,81,211,60,69,192,80,94,225,241,197,53,76,100,1,166,253,132,17,3,72,232,72,214,60,18,151,159,15,167,78,27,76,142,22,21,129,121,10,185,35,246,49,165,218,73,182,236,65,1,175,236,230,71,209,189,163,164,179,194,209,86,6,180,219,147,94,15,212,246,83,21,183,250,40,230,78,222,159,74,94,13,20,247,51,90,218,253,125,50,81,72,93,1,200,50,199,223,192,197,223,38,208,98,122,118,7,82,178,154,193,50,199,199,7,184,231,120,39,2,232,41,182,32,75,56,236,176,5,0,113,190,13,109,1,175,212,249,89,21,130,204,162,228,119,244,190,87,252,151,13,40,209,103,93,95,199,103,141,133,122,94,189,161,222,26,229,214,114,137,110,97,84,81,251,213,80,122,215,144,113,154,105,12,130,191,24,0,226,159,46,86,119,142,104,231,72,118,224,91,195,94,179,212,168,32,243,2,25,219,4,197,34,167,252,198,18,155,87,88,62,165,118,253,176,96,152,186,128,214,140,226,59,11,113,104,102,96,136,126,9,13,140,165,46,116,134,52,249,105,131,168,226,83,93,216,194,247,236,251,159,42,118,243,93,85,175,120,106,134,75,146,217,187,183,49,138,190,5,189,3,203,106,166,110,104,108,70,111,165,41,203,34,212,254,32,10,2,238,30,243,126,47,119,175,63,107,73,75,131,105,17,54,253,158,128,179,196,198,64,151,178,55,47,159,191,106,78,234,208,198,108,42,131,2,33,44,121,43,48,137,107,252,205,15,84,242,200,169,148,239,199,117,248,6,151,51,83,45,149,57,75,160,202,27,122,235,14,50,90,135,90,94,140,171,241,123,236,90,200,243,190,6,111,165,246,139,34,141,151,172,38,34,66,201,218,83,110,52,12,146,6,26,248,102,120,174,193,25,147,171,152,87,174,79,55,208,166,73,111,90,214,25,117,239,102,226,213,182,128,93,49,129,174,3,2,180,9,250,166,8,32,141,187,26,55,157,229,144,64,195,91,154,133,56,176,6,198,60,119,115,232,70,213,143,59,250,97,136,50,75,125,198,19,151,141,168,48,163,47,67,211,114,119,103,69,9,119,244,236,196,164,248,228,69,215,205,245,16,57,177,244,43,224,109,172,45,14,5,161,195,63,81,38,117,19,125,248,179,103,199,168,84,151,192,55,216,72,96,43,117,199,103,51,202,42,177,40,169,84,157,153,173,244,141,108,142,38,188,53,35,151,221,147,12,148,111,151,129,212,37,253,142,191,152,21,241,153,150,30,71,95,49,124,83,150,47,109,169,199,96,70,141,167,74,79,11,152,159,93,215,159,185,141,249,140,114,217,75,87,133,177,114,114,27,32,86,10,246,20,157,127,160,164,227,79,194,177,107,49,142,179,84,144,135,178,81,30,7,228,120,116,11,103,210,83,15,94,77,40,116,144,27,125,81,192,231,217,112,4,184,78,6,144,65,184,221,84,114,52,150,241,217,130,114,219,252,15,34,244,209,76,178,193,231,229,38,137,147,0,147,242,150,26,33,32,28,132,60,63,134,221,9,214,135,97,120,217,109,78,130,199,253,153,215,234,19,186,201,199,169,20,132,151,74,179,54,65,25,171,126,126,88,23,247,222,39,52,65,85,45,245,229,214,38,98,14,0,10,216,42,17,230,34,91,84,144,209,31,186,211,140,175,188,80,202,99,174,124,88,40,32,214,235,133,253,145,179,186,102,42,135,61,67,235,163,133,41,35,25,168,87,141,24,186,210,233,150,19,220,120,81,123,169,245,18,197,27,207,176,15,197,115,139,69,152,82,211,148,77,184,232,173,29,253,46,123,173,245,217,54,231,135,218,236,101,196,45,109,136,189,206,68,215,214,77,251,43,39,224,144,62,135,50,114,247,67,110,247,38,143,220,5,1,173,142,88,7,149,152,225,194,10,114,152,121,105,239,242,249,117,29,172,2,39,98,218,33,31,69,93,11,210,222,132,40,251,162,173,144,13,165,165,242,181,202,215,89,196,228,253,39,70,73,153,144,63,184,211,2,204,107,51,166,197,173,14,15,96,66,141,11,12,244,148,50,16,214,9,8,52,6,165,105,91,184,10,10,62,135,250,200,159,69,227,229,86,98,229,73,27,200,217,108,233,211,81,90,93,45,50,50,149,19,35,23,116,202,113,21,211,33,217,140,128,86,228,185,130,140,104,87,180,174,131,213,254,48,90,67,239,159,204,139,229,42,236,142,82,151,187,165,11,12,150,53,56,10,76,97,213,117,217,51,242,133,135,229,78,117,95,26,31,69,32,138,147,70,226,136,42,0,8,199,224,233,35,206,48,207,61,99,52,101,204,118,143,245,236,120,33,226,57,223,53,32,255,6,236,127,223,89,137,99,84,204,80,106,20,237,64,149,193,65,7,41,202,120,56,115,112,137,35,254,243,28,47,4,229,33,115,177,48,219,231,48,63,139,95,214,209,6,170,197,116,222,104,88,254,141,16,48,222,226,9,47,121,65,188,142,38,129,229,60,122,25,131,229,78,249,211,139,93,199,181,248,231,247,38,161,131,223,146,216,88,123,189,77,186,220,2,185,53,173,226,101,153,213,103,171,140,207,44,51,120,168,36,182,213,176,87,166,170,61,250,49,139,249,215,135,168,170,59,95,118,142,249,166,177,121,94,175,159,219,228,219,117,28,222,43,180,225,108,140,7,25,5,94,45,171,5,65,137,255,40,123,190,89,181,94,76,172,91,161,197,240,85,79,172,28,47,57,205,233,102,137,143,28,155,20,20,157,41,148,175,43,167,5,82,171,148,109,247,237,236,176,176,124,1,158,189,93,168,51,115,231,208,228,55,164,123,212,27,25,190,38,1,120,25,153,91,236,95,116,67,210,173,224,156,220,91,207,120,91,114,212,191,71,198,205,146,136,65,91,33,204,192,154,155,243,71,11,55,239,100,89,204,247,199,59,120,22,68,109,137,194,203,81,61,247,11,226,242,210,155,195,209,1,193,108,163,178,20,22,170,30,148,214,80,229,153,91,103,246,237,10,245,110,211,150,205,98,239,92,94,71,206,91,253,204,90,157,216,152,35,148,167,8,201,167,24,239,191,158,102,23,131,159,64,99,81,159,58,193,185,68,1,28,24,38,198,132,80,191,19,122,235,99,129,100,49,253,29,52,194,32,108,106,166,243,179,53,189,96,59,73,241,61,32,223,84,218,118,59,32,64,9,98,239,207,219,101,38,106,54,148,148,25,5,50,107,106,152,242,117,192,102,56,184,19,232,133,157,243,182,52,144,217,94,101,153,221,88,157,52,224,159,93,159,71,2,115,200,230,116,202,177,236,75,20,176,16,39,147,24,150,195,21,251,77,57,185,113,216,168,48,127,164,56,104,92,23,85,141,159,93,53,192,103,163,130,24,85,85,160,61,246,23,185,196,18,158,228,129,148,126,206,52,198,191,182,12,98,112,31,56,160,62,208,196,234,1,56,249,23,61,115,25,164,254,151,45,11,124,107,53,151,131,221,52,249,185,90,5,4,129,177,134,168,239,37,50,111,225,178,53,251,9,5,87,32,111,75,239,38,160,33,50,128,211,5,250,31,61,177,31,115,182,221,118,33,225,75,165,5,43,89,152,62,217,185,246,122,194,98,47,193,42,74,46,144,111,16,231,76,88,151,7,93,68,144,237,82,117,206,167,239,6,137,55,125,14,88,92,201,143,148,62,216,55,224,150,178,38,77,42,167,163,233,124,131,220,55,50,219,117,225,244,220,233,124,27,133,246,213,86,54,152,29,92,98,226,98,54,110,144,186,41,161,225,72,199,30,105,121,160,56,141,23,100,40,88,208,169,32,196,122,95,231,57,244,199,120,13,232,165,250,170,24,34,231,23,205,33,18,214,128,56,165,14,48,104,223,133,183,73,58,100,111,112,115,239,70,81,81,38,94,88,232,164,212,242,0,59,114,36,133,89,252,41,204,37,193,144,244,255,242,124,20,131,112,126,131,187,205,71,229,86,90,197,199,245,45,120,190,56,223,164,63,177,75,188,238,180,176,137,182,95,221,29,158,104,4,224,38,183,94,172,67,44,62,168,237,218,85,159,58,25,168,173,108,204,228,81,18,145,207,176,19,10,212,78,133,108,169,178,117,11,19,155,152,200,117,243,99,143,126,93,75,167,4,103,249,245,27,30,184,78,162,35,174,200,4,59,119,138,195,58,130,59,179,147,48,207,134,201,207,31,90,145,168,212,195,79,220,16,253,80,24,42,159,61,178,241,81,140,246,198,225,166,94,74,63,254,3,218,93,2,74,194,239,192,68,55,75,132,51,79,200,162,72,133,34,87,86,7,157,235,37,94,78,191,150,81,213,162,147,20,232,243,173,36,1,244,91,3,192,10,224,194,229,74,147,19,192,165,168,153,5,127,230,113,185,206,127,146,80,114,246,179,16,31,90,0,242,254,82,189,36,246,211,7,118,168,33,154,220,184,107,101,40,150,196,194,242,253,216,72,132,210,147,230,224,198,34,75,25,74,233,205,159,168,6,197,50,217,127,251,94,27,0,89,55,171,138,10,197,251,46,127,84,139,97,212,131,44,89,5,181,154,11,223,2,106,249,29,222,72,44,89,57,56,8,138,102,140,86,159,219,77,239,32,203,126,142,214,192,72,16,119,161,71,155,250,58,115,189,112,51,213,249,25,85,78,170,171,102,164,103,133,109,37,229,130,167,116,64,21,234,76,246,89,206,141,235,89,223,141,56,47,168,166,97,190,26,197,70,97,133,200,148,53,45,183,39,129,38,122,174,116,58,75,115,221,204,101,52,24,94,177,14,237,2,172,234,210,8,208,25,77,235,113,24,108,216,242,184,180,255,173,101,240,51,246,200,240,13,156,209,93,60,66,170,252,82,230,13,215,146,117,255,210,7,34,122,10,106,156,176,21,68,222,248,33,83,152,206,191,60,18,158,149,114,74,41,60,203,244,210,249,189,212,25,25,75,131,95,76,207,254,188,23,124,249,162,255,170,137,0,81,97,181,221,127,2,120,240,234,80,28,115,105,158,136,89,77,135,103,255,251,8,186,242,63,176,164,122,8,11,128,19,58,243,8,212,252,204,84,170,108,158,179,247,0,254,32,87,139,213,136,45,180,92,145,67,92,246,247,205,97,103,87,101,163,137,0,61,23,230,147,218,153,102,235,104,17,24,246,70,190,79,179,238,178,41,56,128,115,241,148,114,229,173,144,63,54,151,123,191,45,145,222,89,230,29,59,34,163,123,120,56,34,137,149,161,32,221,255,87,39,50,57,112,84,159,209,51,170,143,167,190,117,145,202,12,127,248,132,142,52,118,154,247,22,242,179,161,240,146,155,7,176,79,18,1,228,242,227,81,34,121,92,236,105,176,207,233,51,86,159,119,70,173,14,42,103,31,241,149,157,98,49,61,96,106,94,142,12,146,88,63,16,173,84,14,216,170,188,7,119,188,94,156,24,78,218,117,39,252,216,201,136,241,118,24,231,164,15,9,211,193,68,14,9,140,214,99,95,235,172,219,136,83,12,95,75,88,48,152,236,153,95,137,236,38,125,35,176,220,87,52,101,106,40,172,224,140,105,118,201,227,143,43,59,162,152,247,197,72,70,232,183,21,160,2,64,169,41,69,166,102,52,189,217,130,19,196,230,34,133,35,31,17,193,45,252,112,79,79,223,99,168,154,14,19,74,179,41,246,27,199,128,101,54,80,252,173,165,241,80,26,204,142,255,57,94,25,56,246,22,133,229,144,110,212,118,251,36,49,81,254,183,116,222,99,70,181,22,74,96,199,161,124,176,7,199,9,56,128,64,200,185,222,37,225,144,156,152,22,99,76,208,43,99,207,169,146,220,182,136,30,96,166,118,49,125,40,132,106,49,212,158,91,55,84,208,213,75,63,190,113,71,83,98,109,21,176,11,204,253,157,79,106,111,232,239,253,187,98,141,32,52,39,209,183,100,176,183,32,232,137,209,189,13,67,230,44,99,233,235,31,211,62,149,120,185,114,79,123,8,153,151,112,255,65,154,228,16,226,177,21,18,10,146,172,134,181,123,4,253,122,188,229,98,89,112,147,19,145,108,246,176,210,201,128,231,96,230,39,140,7,175,246,144,253,114,34,223,14,48,134,160,78,112,135,138,197,142,208,213,221,156,197,198,131,42,169,203,191,140,36,205,131,59,11,239,147,205,235,193,132,59,199,198,42,204,244,120,24,172,221,253,85,141,118,110,76,153,91,146,222,142,200,251,52,172,145,250,47,123,86,49,253,220,27,77,170,51,36,179,148,26,32,251,162,197,246,163,248,65,123,233,68,194,166,153,206,118,238,22,134,49,13,218,176,11,183,124,197,148,169,251,224,80,11,209,166,233,229,19,220,114,244,144,246,17,131,119,108,78,6,26,238,121,82,13,57,179,139,149,164,255,235,181,20,240,76,155,71,61,89,192,100,16,244,93,71,199,139,70,203,107,44,233,154,66,40,255,1,15,20,206,89,244,23,68,123,164,177,175,187,170,150,195,150,44,96,99,142,169,220,220,197,235,124,72,198,60,112,180,196,35,190,154,107,29,177,10,243,111,210,61,157,156,223,255,101,5,210,27,224,15,23,138,119,65,201,139,134,84,70,122,22,204,153,5,193,108,54,149,173,173,37,200,81,229,93,72,7,45,14,51,177,85,166,96,189,55,43,70,88,172,251,17,221,163,81,62,196,216,14,31,82,46,38,65,125,42,32,4,9,145,100,31,102,106,231,86,31,167,246,39,11,28,118,34,92,179,80,65,191,115,43,247,211,118,115,124,156,122,145,222,177,73,161,7,117,51,20,29,178,100,26,127,202,208,177,209,121,101,140,194,20,229,139,123,55,186,209,31,33,39,115,64,97,128,152,60,147,70,35,97,4,156,87,181,58,244,132,109,115,229,91,215,10,28,25,21,57,163,234,21,101,81,18,220,78,130,105,85,41,164,78,228,156,201,182,234,93,221,241,194,212,66,84,4,11,81,116,94,234,37,200,8,214,228,253,58,205,250,62,168,189,1,46,223,0,158,154,29,127,247,188,25,193,165,228,117,234,121,149,167,254,11,3,15,12,91,42,46,11,240,230,134,120,108,46,58,63,23,230,140,113,173,206,94,55,63,20,187,32,255,142,32,192,135,161,231,95,115,204,50,125,129,245,15,153,89,124,35,87,200,91,78,68,126,100,158,103,224,232,192,132,174,34,19,19,48,139,182,247,255,70,88,227,139,253,31,10,222,62,188,140,85,169,143,143,14,29,108,159,46,98,211,30,129,63,149,77,230,246,61,181,103,153,124,242,214,63,70,78,193,78,208,159,94,20,59,30,81,88,112,124,123,183,101,239,217,86,232,137,59,250,5,110,107,71,27,31,15,33,62,200,161,218,153,82,134,5,7,141,180,7,152,169,23,182,33,150,252,223,90,209,54,177,15,50,19,8,253,37,226,84,143,33,164,230,38,215,102,42,156,198,36,35,149,175,75,79,102,252,69,215,7,165,103,252,189,221,18,204,32,86,110,22,47,74,38,247,11,126,5,145,242,247,20,9,190,177,121,79,16,110,73,41,45,141,3,247,35,3,252,191,45,7,156,127,115,198,74,194,5,25,124,110,61,109,115,151,84,72,182,140,170,23,217,123,133,98,143,18,53,128,55,78,61,89,152,214,253,63,133,196,183,215,107,107,158,245,129,15,153,169,246,158,65,172,8,47,226,30,126,10,64,163,175,108,218,130,19,89,235,34,206,150,176,199,6,140,234,201,165,130,107,208,64,112,36,44,115,250,199,236,204,60,127,43,124,225,163,49,76,103,210,254,126,180,82,44,230,68,93,12,246,201,186,72,190,172,76,128,42,173,0,221,120,14,150,19,197,121,163,71,111,214,183,143,24,187,70,13,255,228,250,134,173,209,183,166,208,21,225,94,109,145,98,70,255,76,151,190,150,183,152,248,238,224,187,111,4,2,111,236,73,135,133,67,34,193,94,52,159,42,187,59,38,75,152,72,134,112,236,191,233,150,43,156,14,167,70,226,7,114,200,31,140,164,33,84,232,169,15,96,172,175,192,57,229,71,227,101,139,17,90,45,154,32,255,204,159,141,200,159,147,45,152,135,128,51,11,78,181,154,83,92,144,157,134,244,234,140,201,95,218,104,165,146,35,28,223,139,111,128,149,30,162,119,191,217,136,196,219,138,212,22,168,182,19,118,34,168,68,234,104,231,59,166,128,52,254,212,215,218,117,66,31,249,88,61,78,33,130,242,94,66,17,169,102,100,130,251,1,125,169,71,110,165,239,246,162,251,220,185,184,20,76,133,171,122,57,219,218,181,169,220,38,166,27,206,53,166,180,135,172,64,7,187,131,182,110,67,34,191,25,145,197,184,217,30,140,72,15,212,194,123,34,239,194,64,110,117,35,199,82,17,157,252,230,226,228,44,151,158,81,101,191,59,18,175,143,139,235,12,185,50,15,106,29,143,82,247,211,52,208,35,153,64,11,50,37,13,38,232,128,45,104,62,240,201,122,137,83,140,250,178,64,142,202,168,54,119,221,215,71,166,35,108,71,223,239,99,153,12,8,134,64,200,182,235,107,96,111,231,153,200,254,189,247,49,93,127,4,200,77,43,160,120,224,252,243,224,46,190,166,143,82,46,207,86,235,116,203,190,88,18,55,121,70,227,215,107,69,58,245,221,133,33,73,230,34,36,254,49,127,129,180,253,175,209,180,54,94,124,96,104,97,243,225,38,248,166,230,189,233,78,38,61,122,43,51,76,9,219,127,1,239,79,151,48,213,26,208,118,80,108,178,180,167,38,224,5,87,106,12,73,252,109,195,190,244,1,237,106,212,236,116,74,192,255,121,219,152,67,18,77,38,21,51,27,121,200,196,0,84,219,179,46,124,54,85,12,179,49,241,46,197,14,33,28,79,227,246,94,112,66,187,209,230,116,161,40,15,78,57,156,110,138,178,73,41,255,178,62,43,236,180,171,248,21,243,240,13,110,71,67,79,176,57,76,207,194,20,219,223,36,60,83,50,200,87,245,137,235,132,89,144,67,4,174,55,221,14,212,138,175,187,209,186,54,80,178,238,243,36,9,199,108,128,111,120,61,208,105,53,44,233,236,78,63,226,71,197,238,242,101,100,227,70,160,209,41,198,56,65,115,138,237,132,126,95,23,46,122,98,177,164,159,251,98,212,145,111,203,95,36,21,53,163,88,57,51,139,255,60,181,38,187,107,75,128,165,215,232,130,56,103,173,192,192,119,72,104,142,246,79,232,200,17,207,225,61,55,106,74,61,126,180,229,233,187,223,190,82,11,232,15,84,52,13,98,154,199,134,191,227,132,219,235,17,230,249,92,249,34,165,54,132,101,234,209,220,66,6,69,181,50,132,160,155,246,171,5,167,56,49,27,175,90,222,36,13,217,116,128,9,151,3,203,43,43,40,205,132,14,248,28,88,180,107,146,95,19,175,0,109,41,170,148,148,54,179,0,71,101,59,99,221,143,205,42,59,156,112,136,31,59,18,231,136,191,41,46,122,77,101,152,172,123,108,116,111,53,229,4,163,218,156,39,171,198,100,223,236,90,205,126,143,72,67,138,159,241,118,154,239,154,219,34,182,123,33,163,113,46,15,249,238,36,50,215,132,241,226,207,196,181,96,162,212,88,224,190,81,179,12,136,146,122,238,83,129,26,72,105,125,20,146,253,67,112,232,12,188,96,52,161,160,121,241,50,77,49,218,20,78,169,246,196,95,213,12,11,243,170,71,1,244,78,233,115,143,34,201,250,23,100,9,97,17,4,211,193,128,42,106,170,138,9,75,28,208,247,157,32,4,210,106,87,15,97,167,209,22,160,123,52,183,148,194,21,14,53,212,119,43,76,147,154,56,43,175,79,109,103,68,93,115,95,230,242,89,230,162,136,47,37,79,109,220,24,217,83,40,241,45,113,250,138,133,115,120,72,115,222,65,36,226,44,1,172,128,192,152,113,44,162,139,24,194,114,139,90,162,31,228,198,129,96,97,224,87,232,183,43,193,104,251,129,67,148,240,227,100,4,27,202,89,241,226,221,189,142,102,74,1,234,197,88,247,95,217,142,161,58,118,124,174,252,162,242,248,126,19,199,138,191,202,209,59,204,127,100,65,187,50,108,197,107,107,205,55,228,48,246,168,68,28,74,186,102,54,116,29,188,57,221,206,122,202,240,151,15,23,162,146,91,12,88,51,69,3,110,205,52,5,186,49,46,171,126,221,23,30,236,45,162,17,198,211,238,177,147,106,5,203,206,78,143,1,167,153,96,15,225,28,219,223,209,68,221,218,102,32,19,138,90,130,254,63,73,240,165,99,150,83,198,65,210,22,92,216,204,186,182,213,249,35,2,80,190,138,101,47,225,210,232,29,85,90,174,228,82,244,173,189,193,47,20,238,93,189,172,27,25,87,244,243,224,87,201,186,153,42,69,160,195,77,180,136,128,231,197,161,163,94,0,191,87,57,125,254,155,170,223,110,165,95,181,188,82,153,240,68,118,58,137,253,184,248,35,170,207,20,197,246,93,21,36,48,195,147,75,92,94,166,34,77,198,225,189,122,91,111,136,32,138,146,132,33,113,35,32,184,97,10,255,132,98,61,203,100,65,30,160,150,30,85,22,8,32,101,187,142,240,176,3,67,219,207,113,202,242,213,177,61,155,141,225,69,7,10,3,184,65,132,69,241,149,214,97,91,168,150,187,136,18,190,15,66,134,232,239,202,169,247,10,160,246,157,238,77,41,185,221,165,157,108,94,145,231,229,169,101,1,167,15,161,20,158,211,139,204,107,228,206,211,185,65,246,158,167,12,107,190,45,182,28,192,44,106,148,62,159,222,82,10,227,237,251,3,151,152,139,76,162,183,169,202,107,181,200,129,195,124,71,208,135,234,26,203,154,53,208,137,99,150,100,142,114,50,153,183,126,133,1,253,9,202,235,65,46,106,126,8,5,105,93,53,17,35,209,62,117,114,152,57,29,66,71,127,2,130,103,158,7,17,86,195,64,229,219,75,195,212,33,209,50,154,59,27,177,135,24,163,107,219,137,197,220,7,153,96,131,0,65,187,83,25,18,15,100,245,27,6,174,119,25,182,124,115,158,7,84,182,105,34,75,231,222,190,48,233,221,49,119,79,153,174,200,28,223,87,37,72,254,237,189,199,23,239,255,69,27,152,251,104,233,142,231,80,48,149,197,234,170,200,149,73,120,9,20,212,128,69,99,144,23,22,83,89,207,47,19,17,198,156,214,226,55,130,85,146,54,5,58,224,214,6,27,36,31,164,126,182,225,53,4,52,100,11,28,220,125,41,101,102,215,188,97,6,55,113,252,140,78,81,115,58,203,129,115,132,109,206,21,68,78,20,128,95,62,34,72,211,75,41,78,234,223,115,175,57,229,107,227,179,9,162,15,86,211,207,126,44,120,162,65,99,15,187,57,91,18,41,138,119,15,37,90,138,187,40,13,121,164,30,26,160,7,116,143,9,149,10,228,215,85,75,134,113,241,72,248,12,116,160,177,187,166,188,208,252,178,182,169,220,121,139,203,135,116,198,224,193,215,214,189,110,168,68,129,130,192,8,226,15,122,181,16,37,227,17,156,38,246,249,4,89,193,12,237,32,109,66,52,139,50,235,10,231,210,19,204,191,161,192,238,27,142,203,62,146,194,119,135,132,70,245,214,127,209,179,254,19,43,72,110,124,118,71,34,142,134,163,182,130,140,131,160,56,194,13,10,6,8,136,131,171,206,237,108,163,127,8,17,208,116,17,165,125,236,166,45,180,115,123,110,117,255,84,33,201,176,66,60,220,2,92,128,59,50,147,27,232,7,251,48,118,128,215,225,182,113,163,1,165,184,212,132,246,28,57,13,84,140,97,222,230,172,120,254,160,216,70,239,215,0,111,160,68,51,0,31,109,79,49,38,221,94,95,37,226,200,239,75,160,227,1,122,27,49,244,122,133,67,125,60,12,216,60,89,219,92,146,252,169,205,31,71,112,119,174,142,76,205,10,173,28,31,26,119,222,159,151,151,214,150,124,197,51,174,17,3,58,240,120,130,175,51,87,155,106,76,197,143,86,226,95,45,72,196,34,230,99,248,121,236,163,207,67,132,152,165,42,252,107,111,171,10,114,221,71,94,190,87,197,251,236,116,86,60,82,253,64,166,236,178,150,126,252,230,179,186,45,52,123,29,16,175,237,157,13,213,215,69,153,217,233,51,38,227,186,80,200,188,65,110,196,78,3,202,66,175,161,253,111,249,120,23,44,176,170,211,138,243,128,128,115,108,85,27,23,107,91,1,212,31,154,136,228,166,30,96,59,92,34,162,61,242,225,232,47,195,154,45,144,74,125,246,69,128,166,229,187,39,196,152,5,66,133,189,18,245,235,31,214,153,14,205,11,130,1,238,167,83,107,14,41,235,8,139,62,37,74,87,110,189,142,226,150,1,219,52,58,115,150,62,55,66,239,30,11,157,138,57,159,200,148,184,237,250,169,248,88,159,137,188,98,30,50,189,59,15,225,149,129,184,102,146,114,254,181,178,143,54,171,186,63,219,29,83,52,76,222,208,189,242,11,81,188,87,249,54,213,162,246,147,7,72,54,22,48,119,146,108,131,16,194,137,175,45,132,109,33,243,243,40,190,135,54,116,177,29,228,193,151,91,207,114,183,37,198,58,44,53,196,42,118,27,144,95,155,137,80,255,233,76,228,204,81,135,24,99,82,230,130,134,134,90,185,64,21,78,113,200,124,44,66,8,202,250,219,158,245,90,117,100,130,99,79,193,113,76,66,140,147,91,76,194,35,42,183,235,58,162,251,48,190,103,86,96,173,72,202,179,222,118,203,182,225,42,46,211,245,250,204,238,192,46,2,210,178,141,212,84,160,233,228,60,100,58,151,244,252,138,108,189,119,187,104,222,9,36,11,182,33,204,41,164,233,176,152,233,86,233,50,206,99,64,128,110,66,233,201,123,179,225,189,88,55,210,152,178,238,149,204,213,200,212,190,228,170,205,255,165,46,209,51,91,74,229,36,181,120,52,6,82,169,229,225,218,231,110,222,218,6,179,193,106,30,34,243,244,157,149,112,198,254,119,89,250,217,97,62,28,209,188,203,80,211,129,242,222,66,129,254,133,112,29,113,174,62,6,239,237,224,23,116,214,189,215,75,239,171,17,204,68,178,19,31,37,201,108,153,71,126,166,217,28,201,87,186,193,62,200,110,44,41,74,172,66,60,174,120,134,18,85,137,113,240,138,170,198,225,97,115,26,202,243,51,96,31,18,185,179,52,52,98,63,170,11,216,247,18,9,35,203,107,220,12,6,21,178,236,232,102,112,57,211,73,9,28,24,100,146,157,25,199,182,169,71,71,6,60,175,82,210,8,190,110,18,136,70,15,43,13,60,52,12,43,123,111,248,2,36,45,160,215,73,52,54,36,80,105,210,238,113,115,116,84,251,91,72,109,192,195,188,108,51,89,2,189,86,142,28,210,69,246,138,253,85,224,49,223,6,47,125,40,72,173,56,214,70,132,134,51,244,168,101,112,151,126,77,102,143,239,4,13,116,106,10,103,119,126,65,6,31,18,107,68,76,241,127,130,133,186,61,250,68,253,189,150,134,117,83,51,83,25,187,118,78,134,35,123,184,148,245,53,68,14,88,131,0,68,159,141,48,76,196,130,198,34,56,19,203,64,75,87,26,133,28,73,19,242,167,183,2,251,172,114,9,7,155,151,79,86,68,141,54,101,212,74,210,65,219,237,175,83,252,71,245,207,108,46,196,105,180,46,85,217,5,128,221,226,157,62,176,224,25,140,26,228,142,51,187,96,116,42,92,18,197,211,133,4,0,207,161,141,187,60,8,215,220,174,187,41,153,27,83,242,133,205,30,135,7,207,178,168,111,3,85,173,149,137,68,187,204,184,237,209,59,41,154,36,35,7,212,199,183,241,25,178,86,195,41,137,201,81,164,246,218,251,180,218,161,189,193,147,17,147,15,78,69,23,170,86,93,28,58,170,81,208,143,20,240,63,182,158,203,197,94,135,254,11,135,124,183,89,193,71,88,184,98,208,164,134,197,140,75,234,159,83,20,177,109,123,195,118,229,245,116,207,220,6,11,187,253,37,198,220,195,29,176,38,46,67,200,232,90,245,23,105,165,133,57,29,208,185,232,69,180,3,5,19,111,91,226,98,197,90,102,20,243,203,137,88,156,217,18,24,141,253,17,194,150,75,120,212,232,5,187,191,80,176,71,27,94,71,149,230,108,103,17,129,248,166,186,196,171,152,249,136,146,130,38,204,223,106,175,46,105,241,113,125,212,159,243,233,110,229,177,187,141,186,157,99,212,232,218,25,58,4,212,122,110,11,236,187,184,12,168,127,135,212,37,81,184,79,102,171,143,151,189,158,113,56,80,94,110,58,223,118,37,73,53,158,134,151,251,250,216,143,88,233,8,206,211,238,115,195,53,186,238,140,128,150,50,225,14,236,49,195,224,75,85,229,24,20,244,72,136,144,15,96,152,6,156,158,133,144,200,229,50,186,234,205,77,101,31,5,147,136,55,31,158,100,141,179,213,225,15,161,176,225,156,40,169,60,57,227,45,170,44,97,107,83,178,31,102,192,84,212,43,159,32,188,252,47,248,53,6,68,8,126,187,27,46,133,214,4,199,153,29,177,123,35,170,100,66,253,178,46,37,206,97,62,17,208,98,178,195,223,64,76,251,94,132,241,102,36,130,182,53,98,94,253,122,211,197,204,144,195,101,203,40,158,215,192,102,44,87,233,61,81,147,158,79,117,222,27,26,219,168,15,59,142,65,113,172,49,253,190,191,188,12,59,244,226,238,7,59,116,34,120,56,20,118,83,59,78,142,79,43,150,41,207,228,35,234,182,14,86,50,120,254,31,74,82,5,29,39,173,104,87,10,249,237,158,29,211,250,239,50,64,90,200,107,209,100,26,135,182,38,139,177,27,64,6,87,21,235,204,230,235,222,248,48,156,212,204,138,22,36,123,3,40,93,25,200,55,162,51,116,3,140,58,246,81,78,59,89,103,138,23,220,89,171,48,48,203,181,80,163,171,109,173,17,34,188,238,42,205,32,106,18,122,80,8,247,127,26,32,148,141,138,226,57,27,129,234,74,40,235,202,6,106,127,1,11,117,117,236,240,123,227,139,185,241,205,42,57,186,237,83,21,90,3,25,88,42,109,224,140,238,11,177,108,46,111,28,229,139,95,217,72,101,173,235,131,28,2,85,51,19,52,105,218,235,176,84,57,140,165,80,238,93,92,6,47,138,188,132,100,36,219,223,236,201,112,201,190,0,20,146,68,95,16,147,1,52,108,54,185,188,154,104,247,173,127,160,214,230,207,56,112,98,105,62,42,66,97,101,47,220,193,114,23,202,61,21,118,64,16,191,112,119,123,20,117,173,202,70,39,239,112,202,66,142,163,211,106,89,2,97,150,55,78,226,111,190,170,144,53,195,72,96,89,229,178,153,130,164,161,86,154,154,21,95,120,12,31,122,50,142,245,189,124,17,218,35,201,75,20,203,234,97,11,70,151,3,185,169,71,243,91,56,248,117,103,8,162,90,14,193,33,124,194,169,48,150,40,80,127,37,151,74,195,221,99,145,74,172,228,150,120,147,204,160,67,110,187,30,236,197,101,7,127,128,115,7,243,235,20,66,101,40,114,136,254,206,220,67,96,231,89,65,202,234,82,8,131,187,238,220,213,142,223,77,25,167,69,68,87,110,101,200,142,51,26,234,143,164,214,134,215,222,141,23,42,75,147,88,211,199,154,201,24,72,202,13,136,234,25,52,120,254,136,185,193,163,187,133,84,93,81,133,177,73,126,136,46,251,136,144,180,33,34,18,230,128,47,79,79,106,150,8,58,160,248,106,132,183,215,17,146,173,177,243,32,65,1,175,14,45,235,55,127,69,29,175,177,184,199,168,231,173,143,212,218,44,28,243,157,87,243,247,193,142,155,49,191,221,140,235,246,53,125,204,139,60,232,18,220,63,106,61,252,172,154,140,47,208,189,55,163,20,44,108,250,50,252,255,204,45,52,2,76,66,64,241,107,21,163,134,187,242,247,136,203,1,7,118,226,244,67,198,15,238,194,74,9,230,186,185,49,162,49,71,168,31,130,160,103,223,244,225,108,133,142,123,181,164,114,112,172,100,229,165,150,250,57,212,15,63,204,70,163,4,98,111,152,45,37,45,245,228,45,244,111,124,250,163,197,120,243,232,117,56,154,191,145,196,141,125,8,55,90,132,216,85,224,174,60,253,201,63,198,114,202,235,236,103,174,176,192,65,93,161,74,226,65,222,241,126,119,113,174,16,71,68,19,253,160,250,79,117,231,129,159,61,132,104,164,251,78,110,48,246,12,36,172,100,111,152,87,36,40,95,115,60,227,74,123,204,149,244,119,65,162,114,102,121,19,155,249,117,248,51,151,33,42,115,199,237,144,43,180,51,121,129,23,83,127,226,56,9,32,222,44,201,44,21,7,249,122,183,224,239,85,204,10,181,91,19,103,103,133,205,12,229,38,97,31,108,141,82,255,186,32,185,59,95,66,45,15,41,179,36,56,178,53,39,230,128,252,12,104,165,98,132,4,223,238,44,36,222,188,218,52,250,146,212,148,237,85,68,175,72,79,155,38,36,230,62,122,67,208,138,241,5,49,158,119,106,100,178,247,61,154,161,134,111,198,28,192,44,150,189,7,205,154,142,45,190,172,69,107,176,36,105,64,30,153,120,233,138,210,10,19,201,37,119,182,152,85,43,37,56,68,199,14,82,214,220,245,249,231,141,77,20,190,252,61,102,166,209,230,24,109,225,229,78,195,145,93,109,32,127,163,49,126,248,87,165,80,47,35,155,3,51,50,146,244,105,171,122,226,62,82,242,157,209,37,222,157,224,156,21,73,10,238,198,123,110,60,209,122,158,82,5,221,166,227,119,183,251,80,175,245,112,156,150,175,183,247,162,53,159,213,33,71,40,168,227,104,244,244,210,154,12,114,234,6,153,36,147,203,170,108,85,64,250,110,225,137,2,143,243,163,40,173,220,191,63,210,108,131,154,142,83,175,46,56,41,236,83,221,81,161,144,135,172,99,88,139,115,229,148,143,162,9,203,12,44,238,102,165,234,230,179,179,242,16,227,158,20,196,203,126,102,121,194,246,105,131,73,192,81,122,192,229,32,52,68,139,60,16,102,94,4,190,236,77,238,222,73,240,221,6,252,179,240,56,85,108,237,167,95,168,223,161,49,28,186,57,93,43,203,125,223,42,221,67,47,174,96,56,99,204,115,41,252,252,106,153,180,228,242,100,155,42,105,108,181,215,47,150,176,81,36,192,211,244,135,162,127,189,201,80,62,117,91,125,58,245,215,9,16,165,134,52,42,43,225,155,28,21,189,76,85,226,216,155,133,105,120,60,145,152,6,52,150,149,2,255,255,126,255,45,36,58,37,21,112,25,5,210,187,69,74,195,46,226,170,12,90,154,7,142,228,89,148,22,211,1,150,132,252,99,19,215,135,242,15,150,0,17,251,192,38,133,71,164,62,161,144,240,178,62,63,254,50,137,26,207,233,156,52,145,94,86,239,132,26,146,181,46,165,248,100,14,76,252,16,214,130,195,166,67,120,113,30,255,126,197,11,57,108,130,66,163,177,70,30,223,117,244,53,44,13,86,39,70,58,213,212,230,152,164,76,152,10,227,3,6,230,216,73,88,108,91,245,126,137,58,224,132,168,129,199,254,247,134,142,56,81,168,160,119,44,222,123,230,189,204,92,245,18,227,172,58,240,174,149,68,71,210,183,169,241,146,73,86,210,216,156,250,239,161,219,212,210,69,48,33,137,81,185,192,218,197,2,122,26,76,13,121,61,31,44,239,37,158,126,254,241,131,26,167,224,67,133,125,52,204,195,141,119,131,208,214,151,86,54,137,139,144,178,173,220,170,156,70,125,66,38,125,127,135,146,246,160,95,230,1,248,184,55,65,56,225,139,169,106,17,246,153,98,119,248,67,85,148,28,157,200,233,186,149,138,180,147,37,42,212,190,28,189,109,117,242,168,56,133,17,29,241,89,218,5,242,81,50,61,166,175,124,106,47,237,20,201,235,69,95,202,35,243,79,223,34,85,47,100,252,168,29,171,20,189,109,65,14,156,71,195,246,94,104,211,21,29,195,84,33,131,207,221,120,139,57,78,126,88,195,191,172,133,96,242,110,140,236,227,76,154,55,32,134,193,20,204,21,192,232,157,224,147,175,193,96,9,127,18,107,239,96,240,98,139,149,104,92,151,196,170,198,104,185,117,179,26,20,72,48,36,47,32,86,42,189,173,80,71,219,151,79,181,88,45,26,191,38,133,45,54,131,31,109,115,161,163,34,38,89,40,49,173,198,48,17,40,39,121,77,90,70,42,251,130,168,125,184,76,60,95,94,136,227,248,145,210,226,191,137,247,72,210,17,141,52,5,102,220,23,111,146,114,218,208,22,105,9,130,97,83,57,25,228,137,6,99,12,24,29,89,25,101,217,133,196,253,246,158,114,75,8,90,142,28,147,19,22,164,240,205,1,21,145,19,225,61,98,21,22,215,32,158,9,44,97,148,104,201,219,76,43,45,162,73,151,252,188,155,192,134,113,103,109,255,54,42,206,24,76,87,154,98,187,78,193,50,86,191,222,86,162,165,38,191,118,117,72,31,6,174,147,231,105,158,70,133,79,138,223,55,73,210,90,194,194,112,167,14,253,133,160,197,234,193,24,75,239,106,47,115,70,102,75,122,123,87,158,185,162,180,84,210,222,141,172,125,211,117,181,155,250,182,51,247,178,100,123,8,8,173,224,246,222,40,35,31,171,203,195,36,34,6,53,171,105,219,106,216,77,18,130,182,37,225,3,235,196,203,114,168,7,2,10,14,230,118,6,134,118,20,184,145,213,218,127,110,182,193,145,91,202,110,11,96,118,1,8,96,103,167,236,180,15,141,151,253,100,7,112,25,70,89,121,233,178,158,234,47,68,162,185,146,146,7,74,2,17,238,108,171,91,64,92,173,85,82,121,240,175,136,132,26,123,225,64,169,132,53,192,187,113,8,165,133,192,249,61,166,108,170,2,175,11,243,183,162,93,109,51,151,40,206,39,150,0,84,130,215,29,211,96,200,244,193,206,63,137,9,225,205,195,93,147,70,125,177,146,164,76,247,0,61,118,12,73,75,151,145,218,82,180,207,112,233,175,169,104,180,29,149,4,129,248,70,10,159,34,67,208,4,235,146,205,128,223,104,17,16,189,72,150,29,148,21,85,152,237,97,200,84,57,234,9,165,16,73,40,118,10,18,222,171,43,231,169,211,149,179,250,145,227,129,66,53,2,35,228,99,7,1,101,161,122,247,98,103,47,32,194,21,66,228,215,171,211,95,93,47,71,164,197,154,72,46,73,190,186,131,152,104,252,1,237,94,154,240,6,67,188,57,183,3,28,30,181,14,142,247,193,242,88,231,188,86,198,130,125,97,9,115,137,196,6,38,94,170,51,157,253,197,152,195,181,150,253,125,49,6,217,29,102,120,252,248,217,191,232,176,151,7,118,12,126,164,219,67,123,72,16,146,223,203,183,0,196,87,186,185,173,67,246,204,171,20,21,86,98,182,253,7,186,6,120,189,118,3,229,237,60,53,90,120,139,87,229,79,153,85,139,16,81,100,189,150,202,125,164,42,132,10,163,190,85,177,69,169,181,85,186,64,77,182,99,209,185,183,19,5,1,24,167,247,211,71,7,154,124,136,40,199,61,196,217,202,170,170,93,64,20,178,234,247,41,59,124,192,158,211,128,28,144,37,95,61,108,113,150,27,161,102,97,250,86,162,10,193,27,201,55,193,56,84,164,176,59,172,180,2,117,209,83,226,255,156,104,115,80,9,171,177,196,38,252,19,138,252,29,242,231,74,93,205,161,41,158,79,204,211,0,30,248,42,125,237,167,151,3,163,35,219,102,225,38,80,160,246,91,202,15,81,5,104,108,210,239,193,131,146,27,150,17,171,71,221,84,112,204,146,94,186,237,255,206,118,141,107,20,169,226,15,43,75,224,52,120,186,0,134,235,166,30,237,98,31,139,146,29,104,64,56,3,249,66,92,147,217,211,9,31,96,178,69,148,227,230,101,236,243,45,246,172,39,229,59,69,106,63,147,212,148,179,217,10,220,19,61,36,147,54,173,248,250,238,79,181,163,211,105,11,79,136,249,56,91,202,219,147,180,212,42,140,52,110,222,216,92,215,61,213,55,188,33,239,190,201,255,96,1,215,85,244,86,49,152,17,180,172,68,196,115,71,107,182,243,219,136,48,23,116,210,242,8,233,123,235,101,169,61,55,63,1,51,205,161,189,96,59,52,218,197,250,26,88,73,52,217,104,199,216,234,189,209,12,232,29,210,128,20,244,127,219,15,204,123,222,84,167,249,54,43,174,28,118,186,210,116,176,58,78,38,166,130,144,219,92,43,91,180,1,195,20,39,139,0,25,240,204,75,61,178,95,199,10,3,136,139,50,249,155,86,95,70,214,41,166,76,132,6,166,146,35,118,145,100,203,149,154,211,215,94,104,5,44,83,183,45,251,89,212,57,197,144,82,87,170,120,45,105,80,129,100,131,159,10,127,221,163,246,63,192,154,53,205,6,127,117,223,24,147,216,93,28,239,163,214,221,158,12,149,255,83,88,41,136,165,138,1,254,6,44,25,143,22,104,150,94,24,196,25,238,193,216,170,71,103,76,33,52,211,45,205,235,134,41,248,86,65,9,32,255,32,95,30,250,243,251,43,119,170,184,85,107,38,21,98,231,54,218,226,16,72,174,6,221,38,211,120,221,119,117,120,67,209,251,33,84,155,163,163,47,53,96,15,51,76,204,87,153,85,170,54,66,113,12,174,34,104,136,90,62,76,103,210,150,82,37,200,148,44,89,113,229,33,173,240,114,61,21,131,193,157,216,181,193,207,219,29,42,99,21,186,158,11,145,155,4,216,22,244,162,245,120,63,128,57,117,241,213,60,251,251,149,87,153,99,63,22,75,81,103,103,239,199,225,110,110,88,38,125,240,116,161,226,53,38,183,2,223,68,221,87,205,73,201,187,129,82,39,35,166,109,116,96,250,15,15,242,104,227,86,21,140,48,172,188,54,214,185,33,4,199,217,220,218,185,44,244,170,133,64,135,231,135,80,159,130,65,112,36,250,209,241,226,74,174,130,199,202,217,218,87,161,162,130,254,242,150,34,63,117,178,224,76,211,80,201,111,72,69,137,93,62,24,23,249,115,80,83,95,17,166,84,223,132,120,6,53,34,199,208,205,80,109,133,213,92,49,18,214,230,123,245,73,80,228,94,106,241,165,216,84,255,96,177,178,90,92,5,219,185,153,238,208,136,79,150,15,232,139,179,52,146,235,158,62,239,136,154,45,92,190,176,19,91,40,214,152,149,209,222,247,97,175,74,250,98,231,204,211,233,2,168,136,18,202,254,144,196,95,80,187,220,123,31,164,176,207,23,248,81,3,174,138,206,65,83,36,29,70,32,71,21,227,157,254,228,2,4,215,71,27,252,9,219,49,49,23,248,163,43,170,192,126,75,198,97,91,38,182,93,204,141,250,187,145,128,158,103,88,73,178,191,233,253,231,3,169,38,117,163,181,44,217,91,138,15,239,82,140,19,78,13,168,212,227,46,202,225,130,28,150,211,105,239,25,243,208,76,174,52,37,170,87,125,141,221,90,95,41,51,53,205,112,75,54,129,102,51,87,222,28,117,188,154,174,103,66,55,95,247,97,127,31,107,22,117,195,115,97,108,19,52,70,179,212,190,15,8,213,49,139,119,170,201,169,8,199,203,166,183,90,134,185,169,133,135,9,251,66,104,187,220,182,164,82,21,125,132,197,116,14,169,241,211,104,107,169,17,246,140,46,235,236,23,84,93,180,72,214,10,39,185,197,170,73,30,43,35,75,114,202,126,143,2,127,114,206,107,25,116,183,11,43,3,146,183,121,214,79,26,240,70,203,45,88,74,11,137,245,21,38,44,66,143,61,168,69,76,204,92,186,121,203,15,46,213,237,131,23,220,68,52,188,111,185,48,81,35,208,159,218,44,76,71,236,152,61,103,92,247,136,123,88,196,109,213,91,97,190,88,164,237,171,59,217,231,230,51,149,191,114,162,41,91,249,249,25,109,183,231,25,48,30,35,44,156,199,26,146,144,26,85,40,82,54,83,253,102,88,29,52,114,160,176,0,95,4,217,205,123,143,97,62,149,15,178,195,166,156,183,183,170,183,54,232,197,211,241,7,215,241,86,159,151,161,98,116,91,139,14,111,22,41,155,5,43,72,245,246,20,196,27,62,112,149,21,253,42,111,173,148,25,42,199,41,53,84,169,17,246,92,25,211,161,41,159,252,62,243,4,19,121,43,66,199,74,28,208,193,205,33,126,84,173,30,16,26,179,244,95,188,90,6,16,178,251,191,203,121,130,161,12,52,170,24,14,141,2,163,190,6,52,205,187,57,245,252,9,53,65,132,246,126,90,3,26,54,238,222,74,237,35,163,214,83,43,254,139,112,244,74,15,241,20,255,217,117,129,81,233,181,187,160,29,30,245,145,199,163,29,171,87,228,222,50,229,60,139,23,152,179,33,23,124,180,100,223,209,21,191,93,240,166,209,66,67,28,158,237,190,62,80,188,131,151,72,22,159,212,121,139,49,254,184,106,134,122,77,103,165,81,70,69,174,0,7,179,26,152,234,23,37,155,212,120,59,223,226,216,189,170,9,42,206,10,123,140,130,214,229,149,218,74,215,152,151,235,170,53,33,209,190,193,105,61,182,108,226,176,32,213,78,117,106,23,56,121,61,82,213,107,121,107,114,185,20,99,151,57,44,105,153,238,174,24,192,241,254,251,80,193,143,221,0,58,227,109,190,129,185,22,131,37,221,129,34,101,144,152,33,250,198,183,73,236,69,174,215,68,64,181,94,33,132,40,149,248,252,133,191,99,245,130,21,43,49,211,224,204,33,169,240,230,120,107,228,46,140,168,241,32,17,95,48,147,101,16,176,251,83,160,253,105,171,56,79,198,139,36,48,144,120,99,236,171,235,56,117,196,171,178,244,170,61,79,183,32,202,66,50,130,211,99,78,199,73,255,242,30,138,199,156,129,107,187,182,255,144,201,230,138,199,111,154,10,126,232,144,99,117,187,160,97,221,177,191,5,239,139,181,240,32,249,247,61,216,207,154,217,224,246,49,118,3,194,107,197,233,3,242,99,182,58,45,151,176,238,101,118,57,44,123,195,112,61,129,140,199,98,25,86,104,2,141,220,161,128,109,32,8,89,147,249,11,246,14,255,195,81,233,46,89,37,122,225,211,69,132,120,138,169,254,0,72,208,116,247,244,60,55,28,135,15,11,28,174,65,40,253,148,181,6,57,220,134,224,205,255,225,22,228,49,200,228,182,179,141,237,217,9,47,114,203,57,24,173,236,15,100,174,120,178,73,84,236,141,45,188,142,252,66,85,56,248,161,247,21,240,209,145,198,24,158,227,106,158,18,248,204,21,1,99,35,91,187,157,228,98,106,35,231,158,103,53,119,135,62,168,207,48,5,118,236,117,255,204,65,60,49,102,180,55,82,149,17,205,214,182,198,223,77,55,234,99,156,29,161,90,22,138,7,126,240,213,226,110,63,214,97,71,161,203,216,10,31,25,62,71,223,163,238,97,14,115,144,121,112,103,4,186,16,66,51,105,110,65,111,32,206,82,213,231,74,107,199,255,85,48,249,19,123,45,142,3,104,77,86,181,99,8,158,50,3,108,43,23,113,246,189,180,107,134,24,9,137,36,178,9,176,197,63,33,63,164,220,217,243,175,16,197,210,28,16,109,192,143,193,240,252,44,124,8,108,179,168,171,135,107,32,216,49,136,123,109,133,33,176,167,185,189,30,120,210,5,211,14,127,118,199,147,121,246,58,33,239,172,251,87,223,152,144,13,169,216,65,87,59,132,210,118,116,30,68,72,68,155,103,230,81,33,26,21,82,14,73,251,183,147,86,222,194,97,44,169,244,82,155,95,253,205,116,91,165,44,64,31,163,242,253,93,23,26,209,14,33,97,62,148,115,63,247,111,137,13,9,163,215,243,223,218,10,114,82,195,219,233,24,117,167,173,231,13,156,77,46,231,130,200,122,169,91,49,229,215,250,140,73,229,240,44,212,41,117,112,31,126,218,196,58,241,101,147,26,195,148,98,153,198,104,87,90,149,128,60,239,177,50,49,11,242,239,230,196,182,89,101,80,215,168,143,70,48,53,53,215,22,99,194,129,245,128,163,40,102,25,14,99,189,152,35,135,13,16,105,137,188,32,226,246,176,38,30,36,65,146,145,240,83,103,2,107,133,21,172,41,239,28,250,134,170,228,80,43,122,211,87,111,228,168,29,171,79,69,62,152,18,69,203,96,169,144,83,50,37,65,208,1,113,46,2,67,73,221,2,181,73,185,209,20,163,237,141,222,221,69,220,155,12,177,239,150,84,234,58,111,225,3,31,187,110,139,78,139,234,186,202,73,72,34,125,59,43,206,220,68,6,49,123,14,147,144,206,60,95,31,173,236,244,239,64,11,119,89,226,7,117,175,218,115,104,165,195,209,202,140,132,15,6,115,213,209,69,238,7,89,37,249,156,158,67,124,208,100,194,232,148,52,214,125,166,99,224,152,46,109,187,234,230,51,60,189,191,120,28,13,67,152,105,230,40,147,153,215,16,149,231,51,170,159,88,97,228,216,161,34,87,65,129,153,213,186,140,150,104,113,164,25,120,246,58,78,221,124,33,179,135,7,220,233,68,9,15,123,101,187,131,139,95,177,234,29,215,24,57,107,53,194,252,161,247,70,224,245,22,104,10,41,39,213,190,186,249,159,32,28,196,55,153,225,205,18,72,227,70,120,101,199,237,132,225,10,124,88,154,151,215,153,67,177,100,244,99,169,37,127,97,122,188,216,217,79,187,227,87,69,243,42,139,151,228,79,141,154,88,240,7,29,255,165,129,150,70,173,212,207,194,245,243,54,210,111,168,77,71,140,61,28,64,106,8,196,60,68,154,18,110,22,252,63,172,163,34,138,138,105,145,101,244,110,11,75,95,244,220,224,140,191,243,85,79,137,128,246,173,146,28,1,68,146,131,190,104,107,105,10,183,141,149,204,59,176,190,91,3,180,254,33,47,24,58,4,53,177,211,193,103,6,161,57,156,191,177,108,76,83,185,133,20,167,103,26,75,148,54,239,124,182,71,95,160,157,60,112,22,149,136,53,82,150,241,250,192,35,199,124,207,79,66,84,131,7,63,140,114,16,166,158,30,0,73,131,202,144,116,46,50,92,60,23,147,147,14,236,195,64,128,205,63,248,146,1,49,182,30,96,166,149,196,243,131,88,93,119,167,118,22,137,56,179,169,223,194,48,235,4,196,19,7,210,55,75,235,92,247,15,83,174,53,132,172,34,214,91,205,147,70,34,195,103,132,175,68,245,7,227,205,122,160,7,72,137,123,51,243,8,7,82,113,179,53,171,249,151,156,75,82,204,101,194,53,247,2,201,39,125,151,8,4,189,190,40,95,41,72,181,116,99,58,100,136,118,164,13,191,107,164,69,39,229,204,2,248,254,87,112,64,247,106,105,66,193,73,104,67,75,181,248,105,39,227,153,139,164,41,215,76,244,118,95,99,56,13,94,20,67,33,205,238,108,249,81,105,60,177,18,155,229,73,173,205,78,164,144,180,161,191,210,203,150,190,16,55,228,110,203,212,118,15,103,25,67,152,199,2,36,17,117,201,129,88,197,112,153,188,44,58,196,160,131,198,150,19,223,209,224,90,127,231,71,1,40,82,195,12,242,223,233,211,68,210,32,176,1,106,119,179,211,33,221,107,210,194,227,213,88,3,122,19,130,145,199,16,66,179,41,215,40,18,133,40,191,25,49,31,101,27,16,11,60,119,20,186,217,168,204,250,28,173,159,38,166,106,2,35,49,133,30,16,174,41,134,5,154,247,72,247,171,23,225,89,228,141,14,221,122,56,188,54,252,90,121,252,169,8,168,27,59,138,8,245,70,122,230,65,165,140,117,136,206,11,169,209,146,240,8,234,87,27,21,119,136,227,84,138,65,172,42,227,109,202,167,67,219,148,125,32,179,242,176,224,42,235,163,145,195,63,145,122,135,21,164,85,133,249,38,87,145,90,3,151,203,189,99,172,189,248,86,207,193,226,138,44,42,179,190,99,83,127,92,185,32,159,58,246,239,241,246,235,227,205,219,169,42,77,149,0,212,210,172,47,174,68,122,133,7,78,152,86,30,65,58,84,65,40,113,125,213,150,112,146,1,46,218,175,242,206,243,3,22,233,246,135,129,96,57,130,15,151,104,91,220,169,42,107,34,44,14,229,23,97,55,219,134,96,213,252,133,227,120,195,1,46,17,86,212,120,130,91,248,166,233,51,66,254,106,183,117,42,44,36,169,196,204,173,91,96,109,228,171,28,189,45,250,183,121,167,12,164,164,245,225,177,164,170,138,139,161,93,90,83,85,26,198,104,106,203,108,131,144,196,153,22,188,229,99,101,228,68,84,115,35,112,19,129,18,184,189,228,220,191,206,106,106,126,188,176,42,150,208,166,249,215,76,49,78,167,49,137,16,206,210,203,31,206,130,158,233,143,12,168,123,152,246,181,110,5,9,143,33,8,20,72,188,117,52,80,18,200,90,101,236,228,207,56,241,5,217,53,40,86,180,67,214,216,113,227,232,42,4,123,161,29,225,131,69,60,164,193,158,200,54,177,14,32,137,153,25,110,144,200,246,156,194,61,16,88,79,24,113,181,5,133,88,82,165,176,38,251,156,45,231,111,141,37,120,107,195,254,51,23,243,143,18,30,92,222,216,31,27,168,49,204,158,75,50,29,108,173,189,227,162,147,5,233,159,187,189,71,11,14,221,15,68,223,60,234,186,227,182,193,229,131,242,98,115,34,126,30,59,20,56,101,249,9,38,148,110,79,181,179,181,29,240,61,110,204,161,242,160,184,30,38,49,180,136,78,22,156,1,249,192,217,132,67,3,250,243,132,141,231,10,84,231,97,122,73,28,88,116,105,213,193,202,47,183,216,19,80,71,55,14,123,32,194,193,121,208,234,113,73,234,146,93,189,196,164,129,140,201,122,187,60,67,10,121,125,17,246,192,134,16,58,220,3,66,88,63,127,197,206,164,85,151,11,143,43,109,35,215,25,113,90,99,90,205,22,209,122,41,112,244,206,253,59,161,241,168,251,89,190,186,151,193,3,142,219,1,102,68,147,87,145,74,157,223,203,18,248,51,21,219,92,9,251,196,149,82,153,103,27,151,252,54,21,4,47,205,56,172,183,3,29,202,225,83,16,70,15,21,227,219,225,178,248,157,53,135,57,185,163,37,123,167,126,80,187,41,181,17,191,207,228,71,37,158,205,118,62,248,250,194,59,71,214,167,103,233,25,73,205,178,231,128,78,53,113,28,73,140,86,87,88,87,238,196,137,77,234,138,39,195,39,117,89,71,3,123,115,108,182,175,148,180,142,193,159,155,141,71,168,172,98,136,187,112,36,25,146,98,217,160,17,34,77,55,98,189,208,173,74,117,181,200,124,182,123,12,56,62,149,214,75,112,112,107,126,242,224,85,234,235,172,131,250,233,229,99,14,92,194,36,21,156,167,172,215,243,141,214,57,79,177,104,94,207,160,8,3,102,237,50,84,126,223,147,92,211,221,196,52,130,24,176,159,132,65,156,131,71,126,4,33,143,91,104,28,50,153,209,95,181,28,75,113,70,67,27,109,192,39,174,135,252,172,218,211,94,160,62,199,154,79,251,16,22,195,15,22,140,253,36,242,85,72,147,22,121,33,25,195,83,123,67,179,160,66,85,146,45,114,228,93,116,57,55,217,212,216,31,50,167,229,242,19,107,240,57,124,255,142,191,249,148,74,39,163,43,156,151,201,207,220,46,185,27,203,141,137,15,92,5,101,198,159,181,2,84,128,42,9,10,185,221,175,55,128,247,131,98,98,146,152,8,240,110,121,15,67,233,2,21,145,83,105,182,127,239,100,153,185,165,225,124,59,119,26,175,192,81,4,98,42,93,184,200,34,68,13,134,123,5,43,164,167,218,32,67,79,70,4,196,254,131,50,201,157,133,80,79,208,242,155,224,237,252,110,27,249,238,45,235,77,229,182,93,205,123,32,5,3,78,154,69,213,117,216,130,198,46,105,47,78,76,255,250,230,254,99,106,218,110,21,186,185,71,173,236,91,67,119,59,38,141,202,223,39,183,153,239,2,113,168,121,123,54,217,55,237,94,11,1,190,38,16,170,216,147,239,88,254,229,245,220,108,102,247,55,229,237,173,167,179,231,185,82,226,109,53,81,87,15,55,217,69,204,109,3,164,126,143,193,42,141,227,90,36,226,83,128,215,12,177,216,190,140,85,129,225,224,25,74,141,225,41,192,131,60,180,130,169,191,124,58,1,135,224,63,27,9,138,244,124,167,199,35,2,120,62,25,218,238,78,254,29,125,60,19,72,168,31,194,52,28,70,137,193,242,203,2,91,43,138,248,5,135,204,165,116,67,10,198,121,98,100,238,143,43,94,209,39,162,232,129,176,41,254,158,40,195,167,51,206,48,151,123,55,64,65,233,220,176,238,73,3,129,139,129,242,194,88,95,199,147,187,75,237,229,171,30,89,115,154,239,165,169,235,59,98,63,177,91,115,84,142,203,97,103,79,66,2,91,157,207,14,45,246,75,211,46,69,228,42,158,158,132,228,178,36,163,98,194,69,11,37,186,217,155,206,244,54,125,9,122,128,237,37,159,232,91,68,159,92,116,153,244,199,136,214,88,171,186,117,98,60,171,163,232,45,147,151,123,170,237,130,250,83,244,253,125,237,248,178,237,111,15,63,154,122,147,51,15,60,204,111,139,245,231,228,185,51,36,176,237,79,48,4,150,130,163,59,120,29,126,54,40,104,116,142,238,121,237,189,107,191,35,8,119,113,131,109,108,173,24,9,142,108,8,49,51,202,146,192,173,17,1,241,218,187,124,164,246,139,220,70,143,192,138,152,227,175,189,77,209,86,106,63,119,2,159,194,2,163,89,30,119,83,127,152,98,60,123,145,96,155,67,36,124,94,20,93,243,98,219,253,143,238,124,45,39,226,10,242,116,227,184,129,242,21,192,51,94,97,231,64,148,237,211,59,177,198,10,216,238,62,4,109,230,168,9,132,240,215,0,86,29,251,174,78,233,243,27,50,92,197,253,214,2,123,146,246,222,140,146,148,108,237,15,4,222,247,156,154,132,10,40,151,8,10,70,114,132,181,145,136,176,233,7,169,57,111,204,90,220,67,215,132,40,150,216,152,69,54,80,43,171,67,46,100,140,33,185,115,58,154,35,242,247,6,43,31,174,39,80,101,216,73,40,132,227,201,14,85,37,194,50,3,146,118,78,76,36,211,88,24,220,98,14,33,120,148,222,160,20,160,118,195,167,167,92,128,37,5,53,38,72,206,146,123,57,213,135,200,109,71,35,239,160,169,225,222,136,217,153,92,67,165,51,105,189,47,203,155,237,217,9,216,232,29,225,177,49,205,230,232,177,124,66,19,114,207,198,114,64,45,161,124,66,110,85,157,81,102,32,22,83,53,111,196,27,133,196,169,162,223,120,126,235,105,163,132,221,206,150,110,214,226,227,26,172,30,160,193,251,235,130,209,125,165,77,58,39,115,187,196,165,24,148,33,237,15,73,76,51,191,88,212,165,137,89,220,47,35,108,174,114,48,214,113,39,163,180,185,63,88,233,112,0,120,241,137,168,24,63,138,54,82,207,177,179,66,101,46,177,222,3,52,49,103,68,5,246,78,182,234,55,35,29,9,19,192,144,78,132,224,162,148,96,89,62,61,109,6,178,98,241,196,88,167,22,196,56,11,139,35,94,112,213,134,206,158,24,179,145,144,24,250,44,149,253,67,210,8,0,244,166,243,0,180,234,155,46,191,122,41,93,142,70,154,56,201,66,159,207,162,193,63,26,46,204,221,206,29,100,232,161,225,87,106,130,47,154,66,253,50,33,4,103,71,134,239,65,137,220,222,90,200,221,145,253,16,73,125,66,213,113,239,82,209,96,85,98,196,87,143,30,250,24,217,92,120,23,123,71,64,51,243,204,192,239,147,75,30,170,32,161,187,95,176,78,235,9,173,103,112,9,93,39,55,89,66,223,135,55,158,58,28,249,4,53,46,175,138,48,65,135,70,136,1,162,20,77,236,103,41,150,88,60,162,162,221,75,62,108,114,118,100,40,120,101,241,122,160,0,109,225,54,161,239,188,6,149,136,139,198,177,179,32,43,126,52,149,57,217,226,136,215,201,55,32,213,229,87,28,109,36,223,42,151,98,71,107,140,255,230,206,183,84,127,109,108,57,226,37,11,140,188,250,216,82,32,241,186,122,68,173,128,81,29,57,2,23,81,10,233,198,238,113,91,11,7,17,184,180,159,230,116,147,143,120,21,24,1,220,118,49,16,80,204,12,78,41,111,117,193,98,56,148,193,219,160,156,230,56,126,1,172,183,95,204,229,202,75,218,108,245,33,254,8,58,127,98,209,197,176,100,60,110,139,133,80,43,42,133,200,12,216,121,186,89,171,171,252,220,132,121,46,180,75,79,8,157,91,112,112,34,247,193,147,132,119,236,30,223,101,129,132,197,45,134,84,202,92,249,70,208,211,158,206,209,216,202,106,106,96,1,80,249,182,103,247,124,85,169,42,212,67,245,112,214,156,147,143,216,186,202,197,119,5,230,23,226,199,79,150,253,252,85,1,193,145,96,212,15,165,73,246,244,50,249,165,95,254,252,112,62,100,237,167,234,181,238,164,135,224,175,19,225,82,153,135,122,209,81,59,123,165,21,127,99,54,56,18,153,226,205,161,95,202,7,79,126,124,92,208,244,46,5,176,227,206,200,16,140,97,250,131,187,54,34,117,52,52,206,150,201,200,182,45,201,225,80,46,100,113,199,193,12,116,224,253,59,85,244,248,161,239,199,164,208,63,114,103,163,167,185,246,203,19,33,102,53,236,108,3,205,170,155,230,73,204,142,178,233,7,187,171,191,137,254,60,149,218,98,40,42,87,10,3,146,207,162,67,113,25,173,141,27,217,143,225,97,164,2,208,116,57,181,180,112,233,183,114,62,110,197,29,79,155,213,7,115,94,60,229,43,83,79,119,171,196,20,78,239,233,51,87,6,32,5,59,166,121,176,193,0,2,145,150,183,130,7,36,179,159,57,212,66,179,111,151,174,27,202,58,35,12,121,174,29,17,69,244,46,87,1,173,238,194,40,107,180,147,157,209,184,241,104,251,123,242,164,42,31,93,118,82,79,189,47,105,102,158,30,210,164,16,47,140,226,212,235,70,176,78,30,247,193,162,137,19,102,181,9,248,156,29,149,41,73,2,34,88,183,198,106,254,34,124,19,150,32,99,71,253,14,190,121,107,200,168,38,114,205,153,112,139,204,16,149,101,168,127,70,40,156,157,78,179,113,220,4,46,194,124,96,187,139,83,36,28,169,50,209,88,176,134,217,219,55,18,186,165,170,11,175,60,216,24,132,95,218,101,75,194,66,64,184,1,56,29,86,92,86,243,122,204,124,185,21,219,37,111,68,82,178,41,69,127,186,121,223,219,84,41,169,105,54,165,5,128,102,12,67,130,217,46,97,233,254,216,57,121,145,39,46,34,136,82,175,114,153,215,16,119,138,116,45,137,136,230,59,132,221,97,0,150,250,153,211,18,141,254,212,157,9,45,217,191,16,24,133,130,194,151,189,230,92,187,55,12,247,187,8,115,13,29,222,207,59,92,230,24,146,39,165,2,54,188,107,162,190,178,185,22,188,187,172,42,164,239,225,92,55,26,237,230,59,0,75,13,33,47,250,12,161,72,4,185,159,244,163,208,129,102,176,239,178,99,211,97,92,241,234,19,85,70,42,189,55,130,151,119,38,50,126,239,231,40,153,124,51,220,63,234,208,163,211,170,63,37,231,40,152,183,204,90,227,246,208,8,196,85,209,243,92,102,174,199,27,110,145,27,1,158,35,176,107,152,163,227,75,21,184,120,238,57,155,201,3,194,165,57,117,211,136,236,17,128,98,177,93,111,46,94,137,155,5,70,101,212,42,190,79,218,62,143,123,151,171,59,185,175,9,185,245,254,235,130,177,69,252,61,157,29,229,105,128,229,192,180,37,158,214,254,13,129,64,53,209,247,56,140,241,97,250,119,174,250,204,68,97,184,208,29,20,117,25,12,105,234,224,76,223,115,197,177,7,235,247,19,42,20,85,78,15,81,181,192,153,4,160,176,82,106,67,212,194,132,240,190,45,126,79,192,122,42,28,239,165,14,139,14,152,62,129,78,48,66,45,207,97,240,165,178,129,234,169,234,59,12,218,46,249,54,76,20,225,254,11,128,237,242,61,101,16,36,207,202,13,244,205,77,104,204,51,50,1,5,95,211,151,110,251,255,185,191,151,167,102,140,98,163,129,27,38,60,101,197,176,252,212,232,136,208,157,118,51,83,111,209,188,223,78,130,47,24,91,236,170,159,121,55,3,202,0,155,212,180,173,74,37,161,201,91,108,166,174,27,239,60,20,65,158,225,185,85,89,127,76,244,27,86,150,160,201,13,106,79,143,68,200,236,55,107,243,76,149,215,188,118,183,198,159,26,140,136,153,211,173,159,16,57,139,31,93,149,70,6,141,53,112,164,6,184,239,106,159,222,67,158,26,121,136,223,39,46,140,67,170,202,95,88,179,214,186,212,140,8,12,94,34,77,226,17,17,162,210,225,20,151,177,74,9,100,126,170,73,142,33,144,154,131,151,205,235,28,118,190,6,137,98,50,237,7,94,230,246,133,250,179,160,199,89,103,9,203,111,37,216,185,171,40,117,6,107,87,133,165,172,22,140,220,186,41,97,187,57,196,102,220,15,169,194,254,170,33,237,69,78,127,4,30,119,51,251,153,50,179,106,153,232,131,96,100,243,32,78,78,223,191,150,158,39,30,201,43,12,220,233,103,223,247,156,210,213,52,75,203,102,114,46,35,81,55,175,89,207,53,66,198,247,164,132,51,64,124,120,125,108,35,3,184,185,202,162,122,93,58,198,11,176,146,221,62,6,92,250,135,230,38,135,125,76,89,22,140,243,110,14,212,252,94,85,234,86,142,168,158,28,94,124,183,180,213,174,80,170,142,88,83,48,201,169,249,109,156,83,4,161,186,46,235,85,83,86,244,7,52,58,188,19,124,117,35,105,13,185,191,47,252,142,77,194,147,27,235,193,126,138,65,32,134,118,24,227,33,219,142,48,59,235,147,8,183,94,74,184,233,4,78,44,55,20,167,190,216,145,187,105,253,135,93,68,15,204,76,81,176,255,140,229,106,248,29,154,109,79,247,240,181,62,181,2,28,187,26,136,254,180,92,158,140,81,194,11,245,237,48,28,57,112,87,48,233,185,13,251,113,29,199,152,222,226,254,232,119,199,120,251,113,224,226,89,162,215,74,115,227,118,145,197,176,156,161,226,233,79,170,203,163,113,106,144,108,25,85,163,91,129,143,75,216,56,51,156,13,106,116,79,121,79,152,139,128,156,169,174,94,228,172,49,115,235,134,42,145,67,107,214,122,8,49,156,210,218,178,151,67,247,169,0,56,164,44,222,132,125,193,90,153,10,15,29,69,159,229,98,193,181,138,65,215,14,65,89,116,209,247,174,22,72,27,141,214,94,36,169,203,34,123,25,192,248,196,238,148,225,225,253,59,44,43,96,2,26,21,96,123,202,184,253,55,162,172,81,29,95,172,11,133,235,129,224,183,94,71,85,29,23,65,246,242,222,224,109,136,62,63,145,107,248,167,160,195,242,204,135,237,253,107,53,91,77,34,207,186,102,102,84,28,14,44,194,39,232,156,245,132,232,76,102,63,206,240,49,132,118,211,1,70,75,30,42,3,149,207,174,223,160,227,64,221,207,62,64,74,186,97,163,201,85,231,33,84,76,132,47,66,189,73,137,21,77,184,234,168,231,171,247,76,32,229,1,138,186,116,5,60,65,8,57,133,57,165,125,190,51,105,242,89,1,141,234,53,168,34,89,88,55,63,52,10,226,116,30,115,175,214,74,234,133,248,48,242,17,47,155,75,131,130,124,207,192,199,156,142,142,119,122,3,15,49,119,155,82,80,171,180,19,29,133,31,247,222,9,245,206,244,22,69,12,85,112,250,23,97,212,191,32,152,5,115,206,31,197,19,250,138,219,130,3,84,216,78,11,80,213,13,161,199,128,136,64,7,53,223,221,247,108,10,139,128,47,36,225,149,145,94,106,22,86,14,62,13,43,181,226,188,243,228,218,231,144,137,51,46,13,237,21,72,193,233,132,28,220,20,8,4,122,72,237,253,246,222,239,176,0,105,79,66,248,100,211,232,18,217,109,127,11,57,83,34,123,20,60,137,153,193,152,195,96,127,130,205,193,250,201,146,44,174,91,40,108,105,104,231,248,136,114,61,136,124,241,31,128,186,165,230,218,248,76,54,35,51,13,80,241,46,59,34,214,111,253,168,149,252,124,4,81,171,131,110,58,165,172,223,166,5,45,240,154,11,195,26,117,137,238,192,41,98,219,74,113,235,25,234,46,9,144,57,228,196,138,122,230,73,229,42,31,24,18,166,217,131,24,95,177,251,18,240,249,10,235,122,112,16,73,162,6,70,8,231,108,54,87,216,194,174,60,128,244,234,190,212,213,146,128,244,187,133,74,29,128,195,60,234,120,57,168,116,97,234,156,164,173,42,225,70,177,38,184,43,121,148,186,19,207,224,19,253,214,102,184,227,77,205,223,63,242,184,142,75,134,48,96,96,243,151,83,50,87,123,186,147,177,176,62,113,237,99,50,108,201,126,185,218,219,219,241,171,55,44,28,194,49,254,72,63,140,63,178,112,216,15,3,183,189,172,230,154,116,254,246,200,73,82,76,41,15,168,132,147,25,115,46,90,151,15,180,193,60,237,178,105,74,47,191,86,59,221,105,248,98,26,140,49,149,76,146,83,229,173,71,134,78,113,171,186,136,69,240,102,228,167,251,86,198,107,167,79,180,215,210,44,58,98,143,79,188,44,133,107,54,248,165,231,104,149,127,120,62,61,159,252,239,41,101,177,140,108,77,90,49,230,151,125,115,153,80,213,191,17,98,59,202,149,108,239,233,23,177,26,245,216,97,198,111,31,75,248,67,177,55,207,157,212,233,20,69,111,167,232,80,21,144,9,32,199,43,200,181,141,195,9,143,237,154,121,175,158,247,124,39,117,184,48,30,51,103,4,19,16,28,84,98,72,251,204,19,32,194,90,236,170,52,202,181,96,92,120,59,184,47,169,66,177,66,217,150,2,50,182,17,7,131,32,76,227,116,70,174,42,90,163,89,35,33,148,41,240,228,253,31,107,201,210,198,152,13,86,70,112,248,225,121,155,252,134,99,239,2,8,98,108,44,76,227,160,213,104,141,16,130,205,118,253,123,220,48,200,187,80,35,114,62,45,188,107,29,79,220,169,244,147,158,70,102,122,231,232,149,243,55,230,115,28,185,83,39,179,237,221,41,170,240,44,143,39,216,163,87,213,39,157,118,225,99,80,190,57,171,200,20,2,7,166,112,211,127,0,69,167,84,159,62,190,37,46,1,194,192,152,94,188,50,203,38,220,128,2,108,156,32,255,174,254,89,135,44,97,26,237,37,203,70,32,238,3,218,163,213,145,32,244,50,67,233,217,30,131,135,205,0,46,29,143,192,99,180,144,34,96,7,74,212,164,44,215,190,88,252,138,84,97,50,251,203,44,252,175,247,178,155,79,180,28,8,80,184,205,211,9,119,150,32,91,150,4,102,212,89,217,117,71,241,163,146,90,113,142,34,228,139,182,236,101,97,47,152,88,91,161,47,37,246,4,92,89,174,210,15,82,44,118,249,82,198,192,155,172,220,91,168,190,233,35,204,84,24,113,139,102,112,42,108,124,19,27,148,60,159,78,38,239,90,234,5,193,172,28,58,20,182,11,43,162,123,82,184,178,167,19,172,101,106,3,69,146,204,136,46,70,35,133,166,103,74,245,222,246,76,109,232,173,160,36,50,39,140,112,227,59,10,18,127,30,232,161,113,146,233,102,248,171,205,245,154,98,101,53,109,65,36,82,31,241,200,111,216,27,255,10,48,237,213,82,221,17,250,248,215,19,150,56,175,233,19,230,30,233,199,3,100,121,176,189,175,63,20,231,105,113,121,51,88,188,231,109,177,58,34,9,199,121,226,157,183,76,219,41,224,204,61,144,124,88,115,7,214,74,179,178,42,119,144,76,98,58,171,185,134,98,123,177,87,100,213,183,165,147,22,29,151,19,74,146,102,107,158,201,189,0,79,185,36,105,84,104,73,152,103,132,228,196,39,102,113,158,255,56,212,198,37,172,139,31,238,98,184,182,42,69,108,194,245,23,205,45,21,76,115,162,181,174,59,213,233,59,240,184,32,212,226,199,126,11,205,232,217,187,51,197,98,94,117,94,105,152,41,48,22,181,8,146,134,207,30,237,255,240,248,183,191,187,67,210,16,185,191,54,193,2,218,22,99,176,191,233,78,247,165,4,231,131,62,37,109,244,76,194,155,129,212,66,0,101,223,162,211,13,80,169,217,16,68,4,155,216,61,35,76,162,144,217,34,209,73,249,250,253,186,140,124,41,237,124,22,168,97,40,95,47,38,188,204,216,150,184,229,185,174,113,3,154,126,238,50,165,170,12,27,209,53,157,76,118,81,252,10,140,31,103,160,43,171,6,65,205,225,154,85,121,76,216,228,29,241,184,200,160,225,86,4,199,137,80,222,199,30,9,163,177,222,131,91,24,3,147,148,250,20,157,246,166,73,41,246,240,159,85,53,172,227,255,239,211,188,78,85,210,198,63,175,149,47,251,126,139,167,245,143,5,212,41,111,52,133,173,37,114,122,63,214,212,6,98,213,169,140,241,226,233,95,47,169,91,89,117,116,228,30,78,123,163,137,11,19,142,70,121,166,215,141,20,57,100,202,75,131,150,222,136,204,79,199,205,220,46,9,129,92,116,55,148,224,138,82,32,255,250,251,59,239,99,130,13,77,106,233,191,37,70,164,141,160,195,95,192,54,39,178,189,46,17,135,160,255,198,62,249,69,57,5,74,22,165,134,209,143,179,8,28,219,212,141,148,242,233,231,171,234,72,186,111,252,84,120,130,253,206,225,145,123,88,19,194,150,24,168,247,191,92,162,203,56,94,55,72,199,142,76,50,37,253,13,142,159,201,100,153,149,243,217,240,192,204,254,66,239,13,23,161,166,210,210,120,35,7,141,179,109,83,57,146,163,16,195,195,129,214,39,34,155,158,29,244,128,143,18,233,121,150,87,80,227,145,22,207,133,15,10,172,79,48,176,209,68,66,116,22,167,251,162,90,108,98,148,98,84,46,164,185,106,48,68,247,163,112,24,15,78,105,58,173,251,63,10,252,91,83,158,57,178,63,21,40,113,231,82,251,191,134,27,71,131,203,150,222,121,48,211,181,0,62,91,119,123,77,252,183,63,204,142,239,211,87,244,129,213,2,81,221,210,104,182,252,35,116,91,198,172,132,76,148,89,3,74,8,96,232,19,70,18,232,128,18,145,133,229,23,13,93,175,174,68,105,55,192,81,168,1,142,132,193,37,99,188,243,51,14,26,6,195,29,149,159,115,77,169,235,22,66,101,37,224,43,146,152,141,191,222,67,12,74,51,124,129,141,11,37,97,10,50,79,112,123,54,180,89,156,10,237,145,90,99,35,116,84,163,249,196,70,103,144,16,14,13,233,42,5,213,163,203,205,92,6,212,210,195,46,141,24,15,1,215,71,30,31,0,4,24,15,93,217,35,228,173,104,78,117,69,140,243,168,119,62,223,200,171,123,57,184,88,64,53,21,153,201,0,115,146,22,119,84,228,16,189,124,213,148,92,15,178,58,83,69,87,213,137,150,254,92,197,211,157,193,255,150,115,3,222,48,64,41,28,208,245,211,29,135,30,54,205,250,93,94,57,155,196,37,151,90,109,165,11,249,203,106,37,64,103,100,206,108,40,181,36,238,104,208,241,13,26,75,32,133,101,47,132,226,199,174,3,139,186,102,206,19,21,6,166,44,184,63,7,255,61,155,90,233,60,161,86,176,23,97,194,237,176,234,251,116,25,226,11,145,130,13,179,158,222,252,26,235,132,202,117,229,195,232,158,52,183,96,47,219,235,210,51,146,103,15,241,22,194,84,73,169,183,142,81,87,203,6,251,105,254,2,56,164,156,137,219,71,205,59,144,217,70,38,73,57,73,70,131,114,20,249,181,50,184,200,127,251,28,30,92,166,20,252,156,141,128,223,214,176,136,154,210,238,245,131,123,1,114,106,160,197,74,57,4,101,162,185,66,93,219,192,225,68,181,231,74,140,180,121,162,114,142,129,187,73,66,192,218,128,28,39,134,251,0,243,48,55,112,205,204,80,144,149,109,100,247,179,224,228,198,89,225,7,131,170,203,32,130,21,23,249,122,134,208,160,239,23,10,91,107,175,27,56,59,104,18,71,209,245,4,165,227,203,178,69,1,114,130,119,193,171,64,18,182,174,155,16,84,193,55,150,153,90,251,6,94,161,253,223,200,143,16,162,175,93,211,88,243,61,118,144,204,158,163,68,183,243,85,64,42,52,155,32,39,213,93,165,239,188,8,152,93,228,136,71,213,103,158,57,252,54,203,34,230,180,127,56,46,22,5,220,190,103,131,16,64,135,114,68,112,125,205,54,108,113,157,5,31,108,20,138,80,149,170,6,114,65,223,21,159,246,115,158,118,220,203,106,20,66,204,213,59,225,109,136,122,206,137,104,126,66,24,195,83,223,112,36,241,154,219,254,255,248,77,142,202,95,86,171,11,42,188,7,245,217,138,49,224,34,61,121,28,57,25,3,70,9,40,108,107,108,211,160,206,154,77,59,153,161,172,200,23,84,154,131,94,122,115,145,19,13,234,127,86,154,80,149,41,50,98,186,251,36,10,53,159,223,103,104,248,67,154,136,228,46,83,243,36,33,221,157,116,83,109,54,89,171,46,252,120,86,50,220,23,252,185,68,192,125,37,223,233,232,110,16,135,71,175,199,37,75,162,17,48,41,32,39,131,59,145,161,20,26,149,216,99,1,188,240,87,189,8,24,224,227,175,207,156,151,37,76,105,62,202,86,172,9,208,0,186,72,213,78,103,254,132,192,92,113,242,42,224,245,111,181,206,107,130,182,212,63,185,27,28,41,112,220,209,148,172,7,140,225,168,124,67,203,73,76,139,41,226,87,30,125,197,216,76,36,160,168,194,202,181,254,134,0,148,187,242,94,239,72,9,21,148,168,92,66,161,144,73,37,106,39,176,127,116,44,183,89,77,47,138,171,10,169,117,147,107,92,29,184,69,82,220,13,130,34,214,197,214,6,152,46,180,228,77,211,162,47,149,169,145,56,196,174,84,97,93,246,216,30,34,211,137,93,8,161,64,73,106,220,60,107,201,86,86,124,51,9,66,244,168,8,22,125,147,200,68,23,23,247,75,139,87,52,54,5,53,175,14,218,127,126,196,104,220,88,75,122,52,99,226,111,88,137,95,199,196,6,2,87,182,200,67,133,205,210,73,174,53,64,12,134,84,182,73,199,7,65,88,7,24,83,187,31,81,35,236,229,37,177,78,42,143,233,94,241,133,195,255,185,7,218,41,43,231,129,3,23,175,147,37,26,188,70,161,146,126,24,12,38,104,96,209,143,227,254,9,198,24,192,4,227,59,174,32,240,251,5,34,127,186,184,83,193,62,41,187,33,39,239,28,16,118,164,36,171,230,136,212,122,52,86,39,165,85,61,117,145,179,83,209,229,95,227,85,170,136,187,59,115,217,179,60,48,21,67,116,58,14,145,89,89,35,229,5,152,217,138,26,10,189,186,35,83,210,174,165,179,87,168,247,177,43,213,204,247,37,109,164,15,182,108,253,170,140,83,214,151,0,211,81,132,64,43,30,248,18,149,11,44,248,98,107,216,117,38,96,167,82,124,152,140,191,51,40,145,207,31,45,189,144,120,151,236,172,94,196,233,80,172,227,217,187,197,174,24,108,153,189,212,51,44,156,203,149,74,222,95,240,202,168,235,255,91,215,29,201,254,8,156,120,134,162,218,172,153,51,254,189,4,238,93,65,227,158,247,6,74,254,126,91,58,204,84,167,188,223,91,180,79,147,62,150,135,231,158,186,185,126,91,13,115,56,108,78,17,205,175,102,47,20,157,73,175,89,225,242,141,119,215,191,236,127,186,252,109,87,164,233,22,213,98,137,134,97,78,12,13,150,30,160,164,149,154,108,167,156,104,67,228,187,152,143,135,114,154,47,7,21,89,131,179,34,253,135,40,109,220,0,127,213,82,85,64,161,1,113,242,240,66,56,78,225,32,59,26,177,12,19,79,6,212,120,217,177,7,187,76,85,122,133,9,219,81,118,109,201,21,119,47,122,30,190,208,241,78,63,16,91,45,44,253,13,228,18,228,187,96,222,132,166,77,100,226,124,234,61,59,174,40,117,26,163,5,65,107,1,95,18,170,126,100,95,216,113,98,15,186,246,133,3,205,221,228,159,206,212,201,240,175,113,198,72,187,233,28,104,253,239,168,246,139,120,149,143,34,146,39,220,145,216,114,243,109,219,151,117,75,33,162,197,181,62,19,128,118,215,96,101,54,68,109,7,171,133,54,145,1,15,56,224,58,123,172,196,221,3,133,158,85,120,21,246,153,166,1,17,66,48,223,247,230,95,15,223,253,250,109,197,6,190,76,117,7,245,185,143,129,188,191,215,198,20,90,194,172,250,78,233,102,182,120,92,116,208,65,80,84,235,77,57,207,221,127,16,225,96,218,22,104,216,138,195,220,101,236,3,109,87,42,198,95,96,164,202,48,107,45,17,107,246,2,243,229,149,152,83,101,228,91,80,183,254,119,138,201,64,197,135,212,15,171,151,44,69,249,208,188,57,253,250,157,63,153,226,131,155,3,224,56,103,144,28,200,229,192,71,131,21,129,219,235,31,205,144,191,146,253,77,67,78,216,241,242,228,244,174,123,254,65,212,26,35,218,100,1,28,145,247,37,254,116,206,212,40,200,241,209,30,238,181,165,198,211,144,87,158,142,226,70,232,172,134,42,41,121,222,108,17,68,45,47,16,56,26,77,188,99,188,115,118,252,245,11,51,25,44,27,128,31,32,221,54,158,109,102,53,155,4,245,73,26,234,174,198,111,64,52,171,213,56,173,114,145,152,204,191,140,179,22,93,211,35,243,221,136,103,201,155,0,41,110,183,62,30,176,252,190,108,47,23,203,166,160,173,17,124,11,189,244,44,4,13,133,74,224,19,240,200,254,27,57,180,193,89,67,10,147,117,127,169,109,96,98,8,10,21,26,37,181,81,247,202,60,172,58,139,237,116,143,140,46,52,176,49,71,231,243,80,161,14,219,152,25,62,178,232,150,162,47,124,122,155,221,61,212,160,224,158,136,39,24,24,159,93,108,6,145,49,245,189,95,22,153,45,100,83,225,12,97,201,53,242,6,2,23,210,62,108,106,189,178,189,42,64,247,93,171,233,157,196,159,103,239,240,111,60,164,43,151,83,198,183,204,37,185,207,113,120,130,103,10,4,90,144,149,54,51,128,82,233,108,119,172,85,82,79,203,25,184,22,113,202,100,46,34,121,95,234,102,43,243,242,211,223,171,133,152,188,18,134,67,47,2,94,11,17,249,254,0,115,150,132,37,136,76,84,42,91,153,219,138,4,233,91,164,1,243,162,12,134,75,244,55,138,40,252,182,74,245,239,39,45,157,106,56,118,130,15,190,210,138,155,237,239,57,182,77,69,190,113,237,27,178,173,214,149,95,133,12,106,208,89,63,129,174,51,58,43,142,103,103,138,109,123,39,101,45,171,1,233,54,34,208,63,121,151,241,39,0,207,133,172,100,150,134,5,196,133,184,171,253,201,139,186,75,242,123,53,174,38,249,95,72,254,64,108,209,147,37,177,166,69,3,178,95,255,47,41,195,232,6,73,119,89,203,225,150,80,125,183,56,28,82,112,89,167,237,204,73,139,208,233,7,168,90,35,244,133,50,216,254,240,80,227,187,102,135,27,213,192,201,21,175,236,199,100,103,36,247,192,4,133,40,125,16,111,25,177,101,37,180,170,49,230,106,169,123,73,58,231,60,106,230,145,116,211,215,134,199,90,18,243,210,29,225,79,224,248,108,204,147,215,73,244,75,154,145,95,137,151,193,154,146,43,242,175,5,62,42,113,9,57,70,59,133,75,165,250,154,186,143,167,22,47,252,137,102,87,181,104,147,207,195,205,88,18,48,209,126,182,35,179,10,30,175,25,163,6,202,85,185,99,52,208,20,19,242,169,14,253,227,198,85,129,68,11,99,112,59,79,142,105,188,254,123,148,88,153,70,89,84,106,236,34,181,241,51,194,138,62,14,134,245,151,117,235,135,10,139,140,204,146,196,96,242,114,217,131,102,142,129,65,132,108,64,29,42,233,238,33,19,249,17,222,195,125,158,124,202,110,18,183,150,111,199,70,127,8,180,135,203,33,143,230,228,90,44,43,118,241,57,168,162,89,150,106,102,32,60,250,93,143,196,239,12,214,171,73,180,196,199,210,115,112,192,13,9,123,222,213,148,91,19,101,236,101,30,146,43,164,10,156,101,112,151,65,89,151,245,154,56,37,194,99,153,35,80,3,93,62,246,6,68,42,34,155,207,230,215,121,37,213,153,36,165,136,123,181,144,31,215,138,161,118,151,196,108,131,138,93,13,158,182,138,197,184,0,44,139,70,0,204,15,179,245,235,111,229,61,119,1,248,135,70,169,50,116,69,16,223,77,223,248,176,81,63,205,104,150,100,178,216,215,7,243,251,58,16,117,59,213,117,122,156,183,0,72,126,132,100,86,92,240,106,174,220,88,51,75,166,111,176,139,229,215,30,173,166,246,249,201,187,24,250,69,150,214,224,9,17,218,53,173,213,254,11,60,19,32,202,124,40,131,51,99,223,226,217,190,252,29,14,39,73,199,37,180,254,114,46,169,46,109,205,172,86,62,198,113,209,186,149,211,122,42,239,238,71,133,33,39,217,86,131,68,199,243,26,0,143,97,215,140,217,34,11,55,192,118,66,69,203,200,128,171,40,250,94,127,204,76,168,232,153,226,37,150,4,8,22,177,75,64,204,39,19,45,127,173,174,14,222,159,184,66,88,61,250,133,231,114,166,164,33,157,77,203,31,222,189,111,131,178,107,117,10,165,203,18,211,117,188,134,254,238,158,123,143,231,245,189,89,21,88,66,169,241,24,26,210,108,105,249,56,37,196,36,26,110,237,31,34,198,114,72,218,133,14,40,38,0,26,218,130,56,146,228,86,253,43,36,112,162,58,232,178,162,105,114,186,74,187,229,215,195,101,241,14,24,95,246,248,101,255,68,164,79,41,18,245,65,11,228,167,132,169,52,170,196,91,52,224,204,230,105,193,231,254,49,143,85,42,221,140,233,18,131,116,86,127,103,136,113,15,23,95,39,90,226,59,168,56,73,43,227,171,60,251,5,66,24,207,129,225,168,127,243,190,108,173,215,76,110,107,75,120,242,147,252,217,57,234,116,1,133,221,90,162,174,126,61,236,200,53,105,71,155,217,56,85,6,214,13,60,119,234,225,200,186,152,215,237,225,105,85,252,240,252,38,75,220,200,6,243,144,34,127,161,14,197,107,63,75,235,195,72,44,27,244,129,243,201,59,241,45,173,62,200,145,232,76,142,208,183,15,77,119,157,26,157,170,159,104,206,13,248,132,68,229,234,196,252,168,229,154,203,44,177,54,200,235,132,93,52,10,196,60,152,226,220,27,98,85,215,82,144,161,12,76,202,47,71,231,225,223,105,35,201,195,174,188,10,168,199,141,255,108,74,166,226,33,4,203,54,202,178,27,127,250,86,181,225,246,70,219,65,173,49,214,202,71,22,67,184,54,90,182,251,202,40,14,235,63,201,190,75,65,15,33,62,81,56,157,55,187,67,3,223,5,188,105,211,72,202,95,229,207,20,1,219,121,116,56,5,116,227,97,48,200,192,252,86,238,56,125,89,89,89,100,76,5,180,81,31,33,111,202,211,182,51,25,81,28,239,153,125,85,67,149,136,118,157,65,84,65,43,74,86,81,238,45,7,227,222,145,234,95,152,157,225,22,53,47,59,189,252,16,40,26,171,155,247,98,73,206,206,218,9,241,152,213,3,15,107,123,100,86,78,2,200,194,8,78,101,235,150,113,69,232,13,102,131,200,41,240,126,186,238,184,20,62,218,235,221,116,53,44,20,219,104,254,112,139,81,119,100,253,105,53,62,247,159,166,75,128,64,51,7,193,108,154,115,34,146,127,75,102,17,112,81,35,33,255,104,228,11,97,24,252,219,214,122,235,2,28,34,128,252,220,126,248,87,48,200,149,102,191,135,59,48,111,142,210,22,87,41,25,209,90,114,67,98,234,128,53,45,198,155,116,161,66,14,216,226,63,200,18,7,20,213,60,221,77,128,48,20,142,208,197,61,210,161,90,77,80,146,220,80,168,29,93,171,234,195,182,134,136,225,120,206,94,147,141,52,199,5,155,74,143,12,252,50,79,254,135,78,145,222,143,150,128,28,137,206,79,88,83,195,0,213,182,223,225,201,191,235,235,39,175,202,211,139,11,109,8,255,251,237,232,33,37,250,169,184,42,115,205,55,220,211,160,190,225,201,208,87,227,181,15,92,123,111,172,104,71,23,236,206,214,177,119,77,128,149,238,102,224,147,48,143,82,158,83,179,110,112,12,75,86,190,48,208,14,156,92,140,55,64,14,23,106,204,140,48,97,72,62,247,14,217,121,31,224,171,233,69,177,129,185,71,17,87,96,138,78,19,178,198,229,37,235,51,51,208,149,100,111,39,54,197,126,215,245,125,0,18,64,157,246,4,183,62,21,82,209,182,193,74,163,255,99,143,38,119,30,171,116,62,129,241,64,167,205,128,48,19,141,208,126,96,231,17,94,11,123,106,132,252,127,95,4,217,84,100,231,9,56,144,178,55,92,107,154,194,164,113,19,93,117,152,188,49,241,135,95,131,177,63,10,247,179,86,47,153,63,125,70,239,205,3,48,196,135,152,123,146,5,229,21,112,255,72,4,180,42,148,238,234,211,163,111,223,49,176,36,101,182,121,145,65,242,151,27,181,100,235,212,127,238,78,165,2,36,188,117,89,217,137,39,32,249,156,72,106,48,65,177,35,119,166,109,125,93,15,74,133,194,177,8,208,79,4,23,216,37,3,20,67,12,40,52,11,160,213,96,177,234,40,240,251,19,126,81,186,153,249,204,11,91,78,70,238,38,31,243,13,156,49,165,95,148,218,155,179,139,30,216,15,153,27,164,59,189,173,159,141,146,16,21,167,183,161,203,82,140,66,150,182,16,73,40,176,102,55,118,132,173,249,137,117,137,145,90,53,86,164,24,152,171,14,64,192,181,253,238,22,204,59,115,228,173,155,232,15,108,250,14,135,190,177,25,54,114,152,83,38,132,125,185,243,134,112,168,170,99,100,155,125,107,46,165,146,10,12,243,170,39,155,195,220,140,129,9,27,178,166,144,112,200,134,3,146,228,27,60,217,251,147,93,72,56,196,158,217,177,53,113,146,111,93,172,7,71,165,196,105,120,164,255,79,158,235,183,45,61,139,128,87,87,24,202,89,236,50,129,135,90,217,225,115,211,102,32,22,124,87,167,76,209,47,193,179,5,176,1,172,115,53,235,4,198,69,17,146,1,156,60,169,171,3,154,137,1,8,160,180,39,33,145,194,221,167,74,225,147,22,226,175,161,190,155,99,104,36,234,28,206,255,153,106,146,140,248,208,160,159,129,189,81,79,151,34,57,191,19,60,238,132,173,126,112,102,40,167,236,248,169,15,165,62,167,248,117,241,242,52,190,179,82,62,174,253,135,166,242,116,101,164,25,44,212,205,199,182,51,26,85,54,11,16,243,103,183,145,84,222,115,193,84,191,14,243,49,214,76,187,20,39,29,243,173,156,181,219,109,64,24,75,52,179,28,160,231,99,85,33,44,165,96,91,1,116,151,203,247,43,74,128,179,172,198,31,77,89,11,160,120,13,159,140,72,217,110,79,78,206,233,178,98,50,152,74,216,73,133,249,217,70,75,56,129,241,107,234,100,37,103,60,16,188,2,190,11,70,104,226,153,93,247,153,143,161,19,20,220,168,207,59,231,145,117,83,136,104,18,107,25,84,26,105,116,169,98,24,122,32,236,228,193,206,223,235,29,238,49,143,225,2,196,58,61,127,140,102,14,140,100,86,158,130,245,106,213,21,195,130,77,170,38,87,189,28,239,43,9,141,221,172,71,101,23,117,196,97,176,152,245,228,11,197,252,84,206,70,36,202,196,205,27,80,137,39,25,75,180,73,162,224,150,97,44,115,24,151,153,239,190,250,64,81,124,193,49,199,158,225,239,216,251,150,194,11,43,136,66,171,93,122,163,101,50,248,76,30,251,201,114,80,75,69,109,212,155,11,141,217,118,95,15,127,174,149,147,216,251,178,89,253,92,51,157,16,128,60,144,26,219,47,131,125,182,76,241,164,209,6,26,7,92,85,220,173,245,230,208,98,209,124,70,173,192,190,132,55,211,201,186,183,60,108,73,202,134,11,25,98,22,219,173,173,140,39,222,243,91,17,177,81,168,144,244,94,105,34,211,227,16,134,9,254,20,51,4,182,243,203,82,63,238,89,246,230,147,185,200,52,129,113,141,167,177,99,18,247,119,52,84,13,203,187,89,98,35,178,30,13,149,205,77,136,197,164,183,202,225,132,158,34,253,166,180,170,81,56,53,16,116,34,149,120,212,66,17,226,5,193,175,148,81,251,230,23,177,141,43,79,103,153,84,172,51,44,242,34,237,188,74,225,118,144,129,40,56,96,157,254,134,231,14,209,110,23,26,41,253,29,33,247,80,149,196,100,34,23,183,198,124,246,191,174,56,254,31,119,127,229,154,236,190,38,98,101,91,126,182,201,156,27,210,62,101,17,18,95,17,62,112,173,218,95,8,203,29,169,3,23,137,111,219,234,54,156,50,148,31,227,60,56,205,74,105,149,45,57,162,39,83,232,38,150,169,204,161,15,212,82,220,124,196,127,1,123,135,186,208,13,210,224,127,223,143,131,107,123,201,10,21,58,99,135,64,212,81,242,174,16,20,198,65,72,42,58,79,59,206,26,52,133,57,223,232,6,119,87,13,47,214,82,42,153,242,77,203,163,205,22,188,0,129,78,179,114,86,63,119,183,248,180,74,200,49,174,239,118,170,130,129,69,61,251,182,192,219,239,214,192,255,58,247,26,49,105,232,74,79,103,145,214,114,231,134,233,230,182,242,244,118,246,117,136,107,207,19,107,184,247,251,123,157,189,96,101,189,162,223,179,99,10,86,165,128,163,231,16,244,57,68,233,20,250,104,28,166,38,49,110,177,66,17,127,187,199,42,122,137,238,193,107,95,247,227,189,113,10,75,176,213,70,136,141,144,164,87,37,42,23,127,141,164,183,78,139,218,128,235,216,244,18,237,172,200,24,113,21,112,117,16,59,41,136,9,155,210,169,170,75,221,91,65,24,147,102,178,110,106,220,193,124,222,37,240,191,119,132,54,85,182,115,221,35,234,48,168,174,45,235,227,126,189,190,94,228,240,101,211,112,91,127,57,151,48,255,55,129,17,139,254,252,80,114,75,182,22,51,188,91,109,69,192,230,36,179,138,232,162,3,131,1,137,52,56,241,139,77,224,236,177,175,210,192,80,187,135,105,224,116,81,229,132,151,223,232,67,207,191,76,55,255,26,58,42,239,48,161,0,251,40,166,214,231,173,40,122,99,165,8,170,84,14,152,38,0,60,172,198,70,127,95,75,16,127,6,6,164,64,141,172,238,59,222,131,224,43,38,141,127,96,100,62,2,30,34,180,54,230,3,150,5,231,193,31,96,61,201,7,121,144,136,49,68,114,1,180,193,165,67,117,98,92,230,45,153,167,120,227,39,220,201,40,218,176,242,79,255,176,197,84,44,219,188,24,123,109,252,180,10,54,56,205,152,158,23,34,226,122,114,118,86,190,135,145,210,139,53,111,80,254,12,33,99,114,50,69,174,102,63,40,134,203,163,241,201,210,132,197,30,194,21,41,67,111,169,59,137,176,140,87,223,35,219,148,41,17,47,87,132,177,195,184,155,62,44,57,51,61,166,176,0,78,17,239,248,132,24,90,111,0,114,11,243,116,156,217,62,172,237,169,184,102,49,203,132,170,173,228,19,92,247,110,129,213,51,246,166,189,117,14,122,133,32,168,49,250,110,109,130,233,47,207,247,73,245,53,4,163,18,37,68,143,96,159,144,46,41,170,94,167,114,150,192,69,209,251,219,13,111,213,186,98,240,94,100,151,249,137,215,40,31,202,233,102,233,87,154,45,180,231,125,239,156,180,218,112,223,97,62,42,141,65,252,126,67,80,247,250,233,208,232,35,192,160,163,194,226,126,10,45,236,6,185,108,216,204,37,163,11,79,111,48,215,146,155,158,134,141,203,55,89,61,222,33,78,82,125,74,58,124,11,39,39,25,125,19,251,109,165,69,192,6,62,4,243,172,60,180,97,171,114,245,37,98,216,173,83,172,42,223,203,123,98,129,233,163,55,50,102,117,207,223,131,8,155,151,246,17,163,194,153,249,69,72,100,93,139,51,97,70,143,174,24,21,44,73,67,97,203,26,232,224,113,226,185,74,242,203,51,164,179,209,188,168,1,102,93,74,120,214,135,191,193,209,7,112,218,199,145,10,92,23,239,226,242,205,187,159,126,171,125,35,158,53,118,74,19,183,224,31,116,118,13,32,211,205,92,131,123,48,181,32,124,7,233,247,254,24,251,109,189,0,184,187,80,73,194,94,100,239,81,170,145,20,235,132,230,56,141,90,22,151,198,88,153,66,134,20,94,237,62,58,110,218,255,50,111,198,109,211,202,21,39,7,30,238,147,85,35,154,58,236,112,221,70,102,211,120,115,74,109,188,70,229,214,191,122,134,120,195,231,217,122,35,113,9,110,154,50,82,32,35,111,159,191,205,52,223,124,250,77,32,228,68,131,215,255,245,107,10,80,105,104,31,4,173,207,219,31,219,171,182,182,254,211,181,183,202,185,238,165,167,38,248,72,193,90,249,154,165,80,64,209,68,160,49,226,93,135,143,48,97,211,47,187,29,120,160,203,115,39,87,245,227,220,244,5,60,57,251,126,42,117,244,81,69,98,77,242,210,249,188,19,130,253,198,56,95,174,249,187,185,215,132,16,226,25,29,180,25,54,143,69,121,134,79,117,180,218,210,211,236,58,207,231,69,104,95,149,166,212,59,105,131,68,83,21,233,177,143,135,83,237,99,3,20,58,123,234,249,128,199,117,238,163,124,52,215,100,124,76,146,61,253,192,135,196,87,201,115,149,98,141,214,85,252,207,188,13,34,208,166,93,132,22,39,44,115,121,203,93,78,137,69,196,253,197,120,148,36,21,208,5,95,43,5,122,145,41,160,12,117,201,143,36,62,133,73,185,73,185,155,194,182,166,248,96,33,9,112,7,42,39,42,203,253,23,196,161,187,66,234,58,217,44,48,7,139,47,158,58,153,179,83,189,27,100,164,156,234,199,98,117,100,38,11,24,163,169,221,244,159,173,191,177,229,194,60,25,229,142,239,38,104,95,145,238,47,214,188,90,21,66,126,66,111,210,228,101,36,242,172,130,97,234,90,20,62,166,38,11,198,159,44,245,249,131,27,135,234,87,83,2,62,185,253,129,60,125,165,26,164,138,148,193,87,246,201,45,72,3,33,31,191,29,45,33,15,238,109,8,39,100,38,195,128,83,7,133,205,161,144,113,161,194,75,111,13,7,188,92,227,251,80,96,18,64,26,145,25,40,183,204,243,127,122,119,214,146,16,231,175,187,101,92,23,25,172,45,195,139,252,212,135,73,86,24,33,203,30,64,143,202,39,238,180,143,39,141,32,30,65,76,186,57,211,14,143,45,98,183,16,106,103,221,249,6,53,137,24,139,142,183,198,247,95,139,222,54,254,33,32,110,206,70,243,213,3,192,199,172,149,164,83,182,93,148,177,50,21,141,173,13,238,107,195,127,67,110,37,112,43,142,183,230,190,209,160,162,156,23,27,134,24,34,52,140,72,249,61,178,169,148,8,130,66,147,91,31,208,121,252,240,86,4,49,94,172,145,170,231,175,155,91,81,34,65,35,19,119,54,89,16,204,192,75,121,73,147,188,144,117,13,228,38,41,170,216,212,138,219,190,30,66,160,168,25,44,46,139,91,239,138,252,75,214,254,70,38,167,102,27,83,199,3,87,193,132,173,198,46,20,126,199,149,77,169,28,80,101,104,137,62,96,184,186,195,156,232,54,165,152,181,234,109,221,187,146,210,235,81,120,213,202,4,54,76,73,143,91,58,186,245,234,169,42,230,22,18,250,90,107,166,223,111,105,64,154,164,4,224,90,136,137,59,115,161,111,33,203,195,109,85,228,153,230,42,60,71,72,5,2,62,18,247,95,210,226,191,18,86,215,250,188,187,220,235,252,237,222,248,38,43,49,68,167,200,78,234,221,147,5,179,21,224,63,87,13,134,86,163,63,36,111,99,183,191,107,252,17,109,125,244,237,227,124,248,96,249,123,151,124,55,89,15,60,83,228,51,167,78,178,149,160,185,115,84,80,74,205,223,140,130,90,11,7,178,123,40,235,140,10,228,159,27,22,21,27,35,97,198,101,3,45,152,101,159,133,198,240,50,167,96,88,76,87,206,44,39,249,11,105,101,233,91,94,0,117,182,228,62,63,40,7,175,93,108,94,109,10,13,105,155,235,242,84,115,42,225,207,146,64,214,155,15,160,204,116,101,205,129,106,90,130,161,1,205,66,106,134,110,197,2,121,251,255,76,57,17,131,177,22,249,53,191,239,3,209,175,23,202,194,236,120,82,27,150,175,201,140,218,92,66,6,242,27,242,72,21,153,249,76,147,161,201,108,133,37,82,63,157,26,16,157,157,53,227,144,45,33,251,159,166,102,14,146,8,130,61,71,232,239,55,149,154,94,62,201,196,46,66,64,182,197,173,177,174,129,184,239,93,144,26,35,78,229,198,0,35,11,0,24,58,31,116,17,14,148,173,217,199,57,30,154,70,63,65,205,96,139,15,161,221,167,15,248,53,144,210,247,198,28,89,183,77,185,161,137,46,60,33,250,124,201,6,162,14,149,173,139,246,183,196,97,174,62,140,41,85,124,32,241,157,180,188,116,43,88,101,206,143,162,87,136,175,53,8,137,29,26,223,233,139,150,187,232,66,160,175,236,60,249,74,124,88,0,169,71,249,158,190,158,10,136,161,14,192,129,205,123,206,139,139,194,116,10,232,178,229,135,29,133,175,175,159,206,251,200,116,49,111,179,231,204,59,114,82,198,44,18,188,92,104,214,214,0,99,131,131,20,13,139,95,163,166,89,240,125,147,162,92,27,236,208,194,108,76,213,90,135,100,0,183,53,71,191,95,49,61,227,177,149,62,19,73,102,79,254,208,162,75,217,114,173,130,116,114,179,103,102,51,151,84,216,208,210,52,137,180,99,72,124,128,249,247,136,183,36,28,249,242,125,70,239,231,22,75,183,222,194,216,180,98,166,182,159,27,186,214,74,253,234,220,112,80,103,58,215,113,70,28,68,149,92,181,110,119,67,179,179,9,96,140,249,194,72,173,244,144,58,9,141,246,68,237,118,179,124,164,96,125,30,196,126,104,19,176,107,25,7,162,89,236,206,184,139,167,166,16,55,67,7,93,251,90,252,86,252,171,140,238,114,28,106,253,2,64,26,18,192,199,145,70,224,41,158,81,211,254,47,235,74,231,215,176,97,187,165,209,79,109,189,21,14,209,97,193,29,254,42,24,157,72,5,143,9,214,54,90,86,243,143,140,12,163,2,158,213,69,48,232,80,165,123,73,197,247,8,241,232,198,127,142,153,236,153,145,20,27,64,72,56,14,13,147,102,116,211,20,44,176,108,13,229,36,230,81,206,9,197,5,42,177,137,125,239,52,138,145,92,76,16,223,134,138,221,234,177,91,177,210,67,1,151,117,176,201,125,211,227,144,217,180,31,53,97,31,147,33,222,114,225,63,236,245,62,68,54,30,147,134,96,110,84,124,209,201,141,3,62,115,79,24,228,194,3,74,218,184,3,66,224,170,40,123,37,121,61,129,54,53,103,197,43,89,135,6,26,104,193,193,136,152,56,142,183,224,128,35,138,123,231,218,184,64,116,133,134,79,71,93,163,18,65,127,217,137,72,42,147,44,193,117,255,58,201,221,139,83,224,169,171,21,200,243,196,43,229,12,27,96,110,87,50,136,174,144,220,236,35,210,9,136,71,10,14,95,205,206,230,46,210,240,140,197,31,1,18,188,0,238,15,228,67,49,220,86,132,126,70,124,204,88,118,84,251,214,36,171,200,70,160,93,190,20,193,149,122,208,201,60,231,13,227,143,217,98,120,101,241,47,166,37,0,246,166,53,179,69,210,170,111,102,237,39,29,58,140,90,17,30,66,50,240,135,134,156,130,216,158,96,227,238,43,173,150,62,156,252,12,213,121,200,99,178,38,253,248,51,29,232,51,139,88,26,160,174,235,4,96,47,68,39,65,224,118,4,246,129,110,151,23,33,196,101,107,18,57,33,181,138,239,175,105,157,49,247,51,175,4,49,223,166,210,239,121,16,164,212,230,198,33,63,150,165,9,54,147,43,215,241,224,55,27,106,204,89,39,184,161,80,49,4,115,240,147,14,244,80,211,157,188,47,240,27,232,175,82,215,194,147,55,86,12,143,240,196,252,206,171,147,238,96,167,220,204,222,124,57,43,217,33,94,205,196,224,116,99,78,12,233,159,227,1,76,43,79,235,217,146,66,161,211,175,94,65,74,199,243,183,6,81,84,203,242,106,233,76,173,158,214,45,43,108,174,250,106,136,126,230,63,14,251,213,18,71,87,50,64,255,236,85,183,102,109,45,1,174,202,9,149,185,253,197,58,210,45,138,136,51,85,221,138,73,184,106,127,134,253,72,58,18,180,62,151,29,82,139,220,202,116,64,248,20,81,96,109,47,138,242,186,193,36,58,228,83,194,172,38,0,252,218,244,10,112,115,142,57,210,57,11,64,200,229,159,61,193,101,132,118,218,80,148,208,24,56,50,42,216,65,221,198,222,42,94,40,195,189,60,175,28,71,25,114,164,42,45,8,67,46,142,204,238,25,167,37,150,221,46,11,216,39,161,104,150,116,113,1,94,67,6,9,155,180,85,217,5,244,160,99,51,203,177,93,136,13,60,29,150,143,141,45,240,202,86,52,252,208,169,251,4,6,159,54,129,123,18,109,207,1,191,79,38,187,105,43,96,244,160,246,58,53,1,126,98,82,106,12,250,65,44,103,65,155,146,190,0,201,249,32,20,57,171,220,149,156,114,51,66,148,220,137,156,113,120,32,169,126,124,13,130,177,138,31,55,46,148,240,128,29,71,141,116,145,112,8,66,189,190,216,123,114,164,94,213,103,242,213,46,100,240,150,169,179,251,110,47,164,50,174,245,163,245,59,14,243,8,35,82,74,151,19,130,70,32,129,139,54,14,190,35,131,230,71,44,133,253,187,52,219,118,239,235,58,76,31,196,252,32,242,187,197,157,187,55,29,121,51,214,250,24,234,46,96,133,232,102,63,43,191,186,226,113,189,64,205,186,249,119,43,113,194,61,250,58,221,69,191,75,14,152,187,167,243,108,156,124,46,5,218,175,243,118,7,240,85,167,144,192,213,61,210,252,162,165,162,46,86,124,240,63,149,35,88,159,198,71,207,56,140,25,144,133,248,190,191,241,252,13,124,234,108,165,9,106,44,119,178,102,193,221,168,140,143,125,102,211,106,41,163,241,103,12,131,227,10,78,64,224,131,209,128,108,224,131,81,196,188,208,57,0,65,7,171,245,92,68,97,155,26,19,0,220,173,153,62,182,16,55,19,229,89,135,80,157,145,162,168,60,3,54,77,8,252,62,78,45,97,13,187,5,95,233,221,143,244,218,237,9,191,191,111,230,19,235,185,24,229,133,236,211,127,22,70,243,186,237,63,6,52,140,155,111,172,124,143,130,20,198,240,17,48,164,10,74,221,17,240,102,82,73,186,66,214,132,28,226,189,253,197,216,71,13,102,76,54,192,250,157,250,97,33,169,125,119,76,18,127,148,89,55,79,41,27,171,173,241,40,25,242,210,152,51,104,129,66,79,162,178,205,127,78,159,148,90,244,237,62,200,220,157,71,215,30,45,95,17,166,151,2,107,156,25,214,202,113,205,64,70,182,24,9,62,176,176,190,16,176,188,96,117,242,77,22,88,50,108,118,138,246,209,82,199,143,160,77,201,121,197,140,194,143,8,181,195,45,95,221,40,139,214,14,153,166,70,195,180,165,102,177,227,237,193,79,231,55,66,91,102,116,212,200,47,182,152,106,44,255,140,122,66,158,160,250,117,112,5,28,227,9,101,161,115,43,75,216,160,129,201,85,4,155,212,168,94,163,160,204,9,102,25,233,102,160,184,227,106,238,100,129,31,84,122,126,254,145,223,210,150,80,172,229,177,248,245,3,169,238,5,16,2,78,51,54,207,82,72,227,99,136,26,105,129,53,22,17,45,214,181,195,68,36,56,169,195,242,5,8,191,67,154,4,98,246,26,112,153,140,77,237,240,2,154,115,169,245,170,100,202,110,18,149,98,123,104,24,71,192,232,157,222,215,83,47,36,18,129,246,103,237,227,185,218,144,30,199,136,151,160,138,100,74,32,166,208,86,67,75,237,132,120,166,153,52,64,10,225,171,2,81,131,86,59,191,48,93,62,184,125,186,164,181,232,91,66,146,242,21,173,53,43,188,74,248,215,108,185,224,167,76,81,71,206,93,12,235,166,22,241,224,190,133,235,131,111,103,60,230,112,49,52,171,86,194,94,59,123,115,191,87,69,241,194,32,229,82,37,247,66,83,202,39,30,54,213,89,3,78,249,44,22,248,167,57,0,84,189,32,168,147,103,6,140,148,202,187,193,37,38,180,46,29,166,57,72,223,230,106,44,108,111,251,141,251,89,7,111,191,116,203,52,57,144,49,241,196,170,155,145,94,130,81,6,8,48,239,173,230,55,130,69,187,163,225,66,214,151,106,237,182,124,152,252,164,152,71,188,138,18,156,234,158,96,75,48,112,107,71,163,19,180,198,24,225,112,151,114,89,6,217,49,26,232,78,138,51,90,69,91,193,126,130,54,20,217,158,121,249,61,85,203,2,97,83,109,237,170,254,0,91,197,122,244,126,45,233,234,109,127,179,19,219,93,31,65,76,94,19,176,192,62,20,225,161,144,181,212,117,211,254,177,20,119,165,4,191,21,105,172,116,103,36,198,101,166,240,111,212,21,87,239,249,26,153,242,52,76,142,34,251,237,81,66,187,57,122,29,236,37,110,21,148,230,218,247,104,63,1,234,5,69,199,73,134,157,172,42,231,147,224,75,141,129,211,82,4,89,195,246,70,171,181,93,183,55,108,159,166,33,84,4,185,111,204,210,203,121,247,47,11,38,196,128,175,73,224,158,13,7,251,219,162,20,164,80,64,199,241,117,6,96,69,101,173,208,37,165,211,107,165,193,43,31,159,138,214,247,2,33,12,191,208,158,105,240,17,229,141,41,237,45,38,45,115,88,232,28,191,188,150,228,13,47,17,235,94,149,41,105,96,203,124,26,222,106,9,189,50,92,15,120,136,57,57,255,99,51,112,155,217,186,209,181,137,48,198,43,39,230,86,230,26,217,240,223,93,238,195,80,220,79,238,160,255,161,52,146,25,191,179,0,106,203,39,179,207,46,133,153,151,239,88,57,122,189,135,89,178,115,230,216,10,114,143,251,93,168,61,169,202,150,202,196,237,75,49,182,183,125,110,19,34,1,136,14,89,81,155,227,118,201,69,250,152,109,216,132,250,88,147,48,2,191,100,195,211,13,126,162,119,72,133,229,123,207,22,23,212,210,63,155,150,227,57,166,222,129,67,70,42,85,154,245,247,41,193,230,95,156,113,40,103,226,86,19,6,181,49,124,103,224,189,223,33,119,236,24,20,229,68,141,154,5,89,177,163,212,125,152,33,38,48,226,24,141,151,158,51,86,207,22,139,80,172,113,125,82,37,229,71,24,29,22,151,195,95,177,29,49,74,158,121,217,68,52,92,168,158,88,196,251,22,3,155,79,122,252,156,221,200,181,70,100,216,71,156,175,156,86,2,231,130,108,43,211,119,75,181,114,163,95,222,24,246,255,186,183,186,101,37,137,223,53,194,47,117,58,55,235,209,179,14,167,242,26,134,221,36,193,38,118,184,207,96,67,32,145,250,154,128,94,25,66,185,48,57,213,130,222,58,197,173,252,78,101,199,141,206,155,94,81,157,155,216,239,200,168,141,203,59,210,55,17,55,170,5,110,70,51,20,19,17,219,187,198,121,220,48,135,101,52,185,215,244,4,37,229,220,138,211,126,144,244,210,14,194,134,9,176,26,52,128,5,94,173,63,199,171,196,37,142,16,185,13,98,224,38,105,153,24,182,124,179,35,177,69,226,224,127,75,236,2,98,7,44,185,3,14,107,156,129,152,51,36,29,203,211,203,108,162,74,162,216,89,12,128,9,112,14,157,147,3,227,248,177,51,228,239,231,213,231,254,82,42,244,137,106,99,170,156,192,66,71,139,213,5,156,125,195,124,229,130,190,205,89,225,241,254,176,95,30,219,40,248,129,218,116,222,75,183,241,249,60,88,178,52,92,157,156,113,232,162,36,107,47,55,17,155,162,70,224,125,82,84,211,203,26,49,246,193,94,207,161,122,216,126,138,16,206,87,28,38,45,30,196,186,30,68,206,95,156,208,218,236,93,107,125,217,121,46,223,4,69,183,46,238,206,71,72,167,159,167,48,118,25,0,159,147,140,99,166,172,4,113,21,161,52,102,54,219,194,90,106,50,6,156,202,21,86,112,33,45,53,6,124,162,83,226,178,246,1,165,167,177,190,237,128,219,79,114,30,187,31,146,10,157,251,80,124,108,191,233,91,104,68,35,156,13,54,123,191,37,77,245,82,222,206,8,246,133,27,217,87,116,7,145,65,128,81,142,250,19,137,207,10,217,88,150,119,183,30,231,123,9,189,145,113,150,247,204,148,101,142,228,144,127,101,122,157,153,221,45,112,44,139,13,223,94,18,221,245,14,185,252,132,117,15,173,122,121,1,251,109,2,107,25,97,29,180,199,11,124,161,138,37,92,119,254,245,118,34,128,28,100,200,80,5,114,99,208,232,126,215,247,226,193,129,111,229,166,12,107,30,67,118,84,156,100,158,204,44,28,118,134,227,10,22,153,126,77,13,134,137,18,167,115,62,98,60,182,179,66,109,93,146,39,135,247,137,193,45,175,156,83,87,217,63,250,57,154,128,151,152,45,35,43,126,198,229,219,126,200,145,4,236,251,153,196,162,89,73,134,96,119,107,128,190,147,228,64,73,220,100,124,73,203,91,213,77,92,68,50,107,69,237,110,138,228,193,175,162,213,78,39,118,105,39,11,196,157,25,195,35,53,250,121,123,219,197,179,143,206,30,210,251,106,231,243,37,84,55,23,7,30,84,11,121,92,53,9,191,28,49,57,237,112,78,183,12,215,243,99,159,238,14,246,197,136,207,69,0,120,99,89,37,184,54,94,128,204,224,174,118,50,226,59,151,162,115,167,144,223,213,199,4,87,55,193,10,212,169,238,242,254,70,213,252,87,32,245,18,157,79,122,232,143,103,31,93,140,93,243,91,156,91,223,136,12,68,98,200,179,170,185,195,112,27,104,3,205,165,28,186,174,118,57,189,119,144,158,95,158,164,143,139,58,87,217,43,22,68,43,126,240,70,94,163,225,233,248,227,168,70,198,16,51,205,239,192,4,124,244,190,80,130,188,253,65,63,201,98,243,142,139,238,115,52,164,188,234,11,203,33,66,111,40,174,113,78,139,135,102,209,122,166,53,10,2,10,140,215,139,223,100,11,23,208,126,65,214,52,37,98,93,37,250,159,75,209,155,248,86,107,5,114,199,254,105,179,240,132,18,228,65,136,188,180,168,141,149,43,234,13,114,25,92,32,8,212,172,186,194,234,241,77,20,142,76,140,225,110,176,248,93,52,69,8,47,143,25,99,166,56,37,228,218,183,234,205,236,237,168,228,136,179,145,123,254,230,182,37,220,223,96,199,45,24,147,73,86,254,47,90,124,89,129,192,199,167,216,217,62,148,163,46,107,74,67,155,206,30,163,44,42,238,69,77,5,86,126,151,131,136,59,134,63,72,23,50,35,228,75,48,172,147,4,200,35,217,142,56,51,159,145,237,51,218,27,192,43,193,90,63,194,218,149,77,69,58,68,24,177,235,144,245,52,41,241,21,63,202,204,123,60,245,245,147,59,230,53,58,179,177,6,108,72,142,101,202,171,147,1,238,27,183,145,157,7,29,13,111,137,129,183,185,196,139,126,204,48,220,237,170,227,65,153,226,170,245,241,69,250,74,235,39,129,115,94,113,165,212,140,219,239,255,30,2,150,71,167,222,250,123,230,253,102,110,67,175,23,73,166,0,144,47,148,163,151,221,23,81,24,247,230,191,244,11,1,206,112,51,40,182,33,40,163,61,107,169,167,6,202,202,72,255,23,102,172,225,38,148,226,88,109,43,255,21,145,157,184,0,241,95,26,253,89,42,53,13,149,184,8,74,173,119,80,63,39,122,131,186,46,224,96,135,125,146,230,186,215,105,91,230,163,169,125,167,150,59,214,137,125,94,22,30,51,110,143,175,201,170,44,185,136,253,28,105,89,77,41,65,135,12,60,237,170,191,75,127,88,149,34,205,123,6,139,121,217,249,166,254,165,197,104,144,84,48,58,172,21,122,128,85,199,148,36,114,91,239,123,1,206,8,169,49,206,39,142,97,137,189,224,169,198,119,13,171,201,140,49,157,103,118,88,94,210,27,126,242,245,68,55,25,204,114,244,247,64,29,145,137,154,56,172,22,62,19,227,79,143,90,5,12,201,194,154,224,71,103,79,31,119,20,146,114,219,19,44,92,21,211,69,49,20,95,47,183,25,195,60,209,50,238,182,244,59,9,94,112,27,36,210,214,7,152,57,84,87,219,76,117,252,173,214,2,188,162,120,141,43,194,108,127,121,25,148,205,129,10,46,39,41,144,243,52,218,147,187,37,188,247,50,228,177,63,51,214,17,10,240,24,244,129,34,87,146,124,5,230,163,171,120,234,22,101,103,156,68,245,144,114,132,132,244,163,47,127,235,219,88,243,187,140,196,153,78,126,139,116,152,107,147,27,119,0,2,213,231,59,70,73,214,67,31,130,51,71,155,189,211,225,165,140,83,24,36,56,202,105,50,33,140,155,216,216,209,252,54,156,254,20,81,120,206,235,241,53,194,44,177,128,30,239,26,95,124,88,90,21,132,123,188,158,141,127,241,223,95,178,108,21,221,145,222,26,192,180,84,129,78,175,117,146,57,215,116,10,13,53,12,252,227,64,32,115,213,68,143,238,155,225,101,184,132,28,92,127,89,232,1,139,160,185,99,115,92,29,188,211,254,180,85,121,47,205,53,199,122,73,153,119,188,74,163,229,129,90,48,50,178,91,189,168,116,38,32,114,55,89,132,116,208,124,128,113,113,16,206,199,26,163,212,71,1,250,155,96,53,100,44,246,31,136,208,243,220,60,176,23,103,88,245,48,51,59,225,235,226,76,182,53,49,135,126,117,23,4,0,51,62,11,237,65,252,21,246,193,84,14,85,217,111,240,108,226,134,59,194,210,198,214,9,245,99,101,81,3,89,134,225,173,80,61,204,115,250,25,191,22,137,42,177,155,159,237,248,200,39,189,1,66,189,88,8,198,57,47,194,59,150,74,50,244,192,145,124,139,137,9,88,183,226,179,162,219,55,201,222,186,109,36,242,146,104,134,170,9,120,67,123,240,251,118,184,113,206,203,242,204,29,95,103,160,139,24,229,246,174,44,232,1,92,51,119,121,192,74,200,193,169,150,115,168,56,37,31,105,175,166,10,183,252,135,115,233,34,0,229,124,183,246,177,143,42,237,125,2,142,154,240,49,228,213,15,77,123,202,79,84,0,147,189,200,161,106,243,41,87,86,158,216,240,246,100,112,9,91,213,220,206,108,190,57,220,218,99,189,47,194,120,28,127,254,169,178,91,243,109,75,134,210,210,244,242,159,54,217,20,133,68,233,153,234,101,91,233,30,96,171,224,92,91,176,236,182,188,20,131,21,122,84,104,171,14,236,252,249,75,212,235,191,95,11,62,141,94,241,165,26,219,173,197,153,214,168,223,240,94,213,113,148,95,22,212,203,134,117,232,60,147,51,11,201,54,4,81,122,170,58,150,209,147,128,196,78,68,78,148,160,114,198,127,162,120,180,68,133,22,76,101,119,11,93,246,9,232,183,127,140,173,92,221,236,51,178,45,217,246,70,118,91,129,102,24,199,252,7,6,116,81,43,240,49,115,77,164,134,23,10,184,92,26,223,238,174,254,108,5,221,29,205,3,38,30,51,143,196,202,21,102,228,51,105,45,191,54,175,140,175,135,132,56,183,9,116,20,68,132,18,220,233,176,239,82,87,160,87,75,33,255,121,193,156,78,230,23,79,64,52,198,99,148,130,106,107,8,203,26,34,248,194,178,123,242,238,250,69,219,168,219,185,118,64,221,220,7,62,58,172,34,161,85,252,155,52,152,60,87,103,183,167,226,234,225,170,247,90,38,143,81,89,210,156,20,60,194,148,113,179,171,5,77,184,78,26,208,131,200,86,18,46,116,74,134,61,119,29,194,3,117,40,80,168,90,103,191,42,184,95,218,91,28,155,54,146,65,95,188,105,77,14,205,75,249,117,46,221,98,224,169,93,190,83,43,182,146,208,7,135,154,99,250,12,2,189,246,105,220,172,175,69,1,167,218,186,57,136,247,112,149,221,32,11,202,229,160,52,60,200,208,193,198,75,246,250,53,55,150,176,139,93,85,222,206,205,111,9,73,162,186,211,69,140,188,136,164,203,223,18,225,119,181,234,138,60,23,112,75,105,15,203,7,125,177,246,31,45,74,151,48,22,139,175,136,183,250,161,111,94,119,158,113,175,140,79,29,122,65,55,233,80,125,200,31,209,18,35,82,3,116,190,125,208,46,253,125,100,73,160,238,5,244,38,184,200,7,167,119,122,165,28,250,26,52,110,188,151,63,208,63,248,94,165,164,111,163,146,32,37,5,60,85,192,27,61,24,60,161,222,0,4,254,155,189,84,196,0,157,35,12,162,103,138,192,135,38,45,40,41,69,63,30,177,222,41,253,200,54,63,230,237,20,103,172,23,99,192,215,2,181,198,52,12,1,157,162,169,147,206,27,237,188,158,40,214,164,233,240,100,201,245,24,178,38,205,66,140,166,43,132,117,143,233,22,167,190,202,18,188,127,240,184,49,182,87,84,214,121,140,169,20,29,122,133,69,18,168,61,132,146,108,35,131,109,86,101,183,150,34,77,90,194,24,46,232,28,48,183,206,47,100,61,163,165,74,17,92,27,210,106,16,222,186,117,41,103,197,144,3,27,9,248,132,189,88,83,122,219,49,116,2,50,30,40,205,76,130,35,126,83,228,228,138,171,171,135,39,196,227,87,106,235,241,239,86,179,253,11,23,99,7,66,41,158,178,157,76,234,6,5,214,254,184,155,181,84,197,165,122,251,119,249,236,166,219,144,14,253,20,200,71,185,128,249,58,15,196,101,206,51,124,190,50,159,255,10,172,123,168,253,230,89,10,236,71,194,62,129,71,92,165,85,0,198,135,157,141,191,50,13,140,37,124,110,249,46,46,25,251,68,145,8,18,120,51,137,142,119,244,148,246,141,26,132,163,135,241,35,159,49,77,209,163,230,111,6,242,146,195,49,170,2,124,194,17,165,42,155,254,34,50,37,48,67,234,117,90,102,69,129,61,195,172,78,87,34,46,79,146,168,210,166,122,231,226,222,204,251,20,75,223,196,242,130,34,225,110,75,207,175,78,24,239,45,171,104,198,59,0,19,49,11,243,112,43,250,158,62,80,155,237,46,52,188,185,245,171,68,197,202,251,110,93,211,94,67,191,87,157,87,233,13,61,47,52,206,80,194,167,66,67,198,170,244,247,174,171,50,79,255,184,161,14,254,202,162,162,254,221,148,221,251,90,102,154,71,98,61,150,1,32,250,227,57,240,168,21,174,152,107,235,75,2,198,35,117,161,148,210,231,214,184,87,241,102,16,184,144,221,165,158,108,17,177,46,228,156,159,149,123,171,239,250,40,10,62,189,159,144,124,7,64,76,122,161,214,158,46,206,191,99,142,189,68,40,168,172,65,88,130,102,169,121,107,188,201,117,35,139,212,14,176,77,110,172,197,14,238,254,189,108,234,224,228,68,226,121,230,183,185,224,25,14,142,86,3,2,21,133,116,109,24,125,214,126,192,236,107,42,30,208,247,43,102,62,205,11,213,177,80,163,92,245,82,101,244,192,151,191,169,102,204,190,167,232,66,226,12,115,238,131,188,181,235,30,55,68,17,186,125,64,121,44,39,147,240,53,20,40,101,224,109,239,226,32,115,253,200,113,202,118,207,81,168,138,146,224,129,38,168,181,120,87,225,170,24,6,223,254,59,48,103,66,191,112,18,100,232,149,121,191,132,39,231,12,223,111,202,150,238,150,76,143,41,37,183,222,8,16,24,33,99,101,144,218,10,68,70,133,97,95,109,42,67,13,102,0,93,189,206,41,149,160,206,101,195,209,76,22,231,109,76,142,113,78,222,63,202,227,65,140,154,29,47,96,41,58,77,137,107,249,152,7,126,53,105,31,221,134,107,150,14,18,108,110,152,91,57,88,146,199,220,12,79,116,220,134,180,176,224,71,97,52,154,76,94,230,58,14,196,154,89,27,162,219,96,227,91,143,175,92,36,179,222,30,59,163,32,250,146,96,163,83,134,33,18,27,99,127,113,171,35,52,143,96,219,71,71,254,216,30,244,75,88,241,242,50,213,1,83,56,154,152,153,219,130,166,175,82,10,125,111,96,137,38,46,205,11,85,195,29,184,117,250,218,58,49,10,40,30,139,211,81,157,249,51,33,100,201,34,96,197,189,206,48,180,50,2,111,154,109,10,90,116,189,224,85,45,153,10,96,210,142,179,131,174,213,131,9,90,194,235,113,201,152,223,253,134,198,136,215,196,121,114,145,127,197,63,226,22,10,124,149,177,37,12,217,218,113,9,235,142,49,103,237,98,82,140,8,127,97,56,61,78,76,142,106,216,56,78,153,139,60,223,243,28,34,38,199,137,132,50,118,151,58,141,192,20,249,138,53,114,177,45,146,78,147,234,123,244,61,157,119,7,88,41,82,17,102,213,59,93,79,45,40,157,139,219,81,12,134,18,77,1,101,45,228,155,66,227,243,242,202,71,136,205,94,102,239,237,253,62,207,30,222,178,58,135,219,74,150,232,27,209,251,37,198,33,83,209,39,249,183,21,38,213,39,143,198,149,91,161,250,193,43,45,233,70,234,118,173,231,180,151,157,138,7,167,198,81,194,51,164,200,83,56,176,121,167,225,108,50,245,125,137,148,215,111,59,19,64,109,5,114,176,218,137,186,235,94,254,156,96,194,168,34,159,84,171,68,70,215,155,148,244,240,11,54,128,75,56,161,201,231,65,137,194,113,32,89,201,13,141,169,131,94,198,168,132,135,101,50,165,181,8,159,184,15,19,74,16,105,43,25,168,214,106,76,164,64,91,12,74,22,16,124,27,121,145,188,125,255,96,131,33,245,145,180,29,62,194,137,30,62,243,129,77,13,158,163,117,162,206,61,236,135,244,220,166,174,217,73,139,0,254,201,26,125,241,33,68,187,155,235,119,25,72,196,151,8,255,8,84,250,43,102,204,134,121,186,123,144,48,2,235,7,229,41,190,150,181,169,203,226,194,118,180,182,162,220,222,14,52,114,197,229,86,207,201,148,241,246,69,68,231,8,57,6,21,171,44,83,134,151,83,25,48,142,91,248,21,21,213,9,104,208,21,12,133,100,100,144,124,237,193,56,180,34,39,246,232,53,212,121,61,127,221,103,74,114,150,223,11,229,210,6,76,40,95,192,199,167,100,100,64,117,44,73,13,187,42,241,47,212,35,164,55,64,85,88,41,102,68,165,110,72,100,66,38,33,14,166,233,157,80,35,137,1,69,63,111,169,42,19,65,190,106,104,216,90,154,147,190,183,207,177,145,142,190,213,148,10,228,251,99,58,72,148,192,227,20,1,79,110,181,47,89,218,133,7,75,111,229,49,60,97,179,158,28,51,110,139,80,56,147,33,182,227,153,92,32,1,241,44,181,143,24,16,252,26,129,134,63,65,186,1,160,90,254,21,88,43,220,101,222,156,214,211,98,172,42,254,193,103,147,61,229,181,85,228,223,127,163,201,157,106,97,82,251,201,89,32,245,234,92,103,151,70,111,44,210,74,166,88,95,204,82,185,9,218,72,146,27,181,139,97,122,22,228,206,84,237,87,140,101,100,110,216,186,226,110,186,109,140,162,59,52,3,26,96,176,41,84,66,47,216,100,110,106,2,55,106,165,232,43,156,42,193,122,42,74,224,96,101,41,240,141,4,88,29,113,31,121,80,196,152,15,234,154,70,129,228,97,137,99,89,108,64,143,32,111,199,220,209,192,20,24,80,192,202,191,169,156,133,210,36,179,17,149,67,213,52,180,176,134,253,181,179,174,87,217,236,254,162,137,201,192,88,23,89,195,231,73,182,226,224,149,99,172,221,135,5,241,132,86,236,118,69,50,108,27,103,65,17,127,75,11,160,71,85,227,148,153,62,103,83,250,192,254,215,123,252,157,8,112,132,210,193,21,244,168,131,44,69,226,190,243,10,225,163,84,190,118,32,19,193,234,220,32,188,74,90,197,143,70,191,99,113,186,143,49,131,109,253,62,234,221,183,103,238,89,65,67,11,230,9,222,24,95,129,14,228,125,126,166,49,29,239,36,39,124,130,203,200,105,29,231,182,43,1,179,193,103,230,251,205,22,182,65,191,137,110,165,113,180,60,209,87,212,7,69,241,130,157,125,59,225,89,244,120,134,142,170,92,19,65,251,87,163,83,32,185,163,202,187,191,34,192,183,186,236,30,222,225,180,237,142,162,77,93,190,100,248,70,134,164,253,105,255,142,189,83,50,161,225,223,241,240,252,170,90,122,221,22,108,187,81,31,252,76,218,238,217,175,90,110,37,190,8,65,147,181,160,202,39,24,230,218,92,233,102,123,98,72,215,163,152,111,198,25,215,60,213,1,254,4,168,45,13,40,238,142,158,60,70,241,144,183,215,236,146,149,13,234,215,133,3,112,135,7,8,40,195,214,105,244,172,246,200,198,238,153,112,100,59,137,18,122,9,204,17,41,181,111,41,61,21,160,16,170,194,218,178,62,88,92,199,233,200,24,70,246,142,224,164,200,210,237,216,75,100,45,115,160,117,92,38,226,170,215,156,203,215,210,248,231,199,216,248,161,125,167,132,103,180,186,9,249,4,154,16,237,107,80,28,27,235,150,39,210,201,153,66,17,97,165,29,15,167,130,23,77,17,106,160,90,248,47,219,164,20,127,81,248,1,36,254,22,50,208,65,145,45,220,160,93,16,45,62,229,177,187,144,167,142,26,248,232,6,191,77,59,136,49,2,33,116,66,65,146,218,44,111,73,2,222,99,111,24,180,41,67,103,39,216,168,240,207,142,34,241,86,17,173,37,58,64,186,213,98,181,151,159,141,26,22,31,45,92,64,9,10,26,76,181,236,145,18,8,30,219,158,183,71,138,134,56,65,70,34,140,141,13,54,245,29,155,227,200,183,113,40,113,203,86,214,2,162,90,237,5,247,2,186,149,205,73,75,106,255,178,8,39,126,21,96,43,117,216,10,81,98,244,208,25,252,177,189,21,50,204,13,115,42,29,115,2,10,234,207,168,29,131,228,241,82,183,158,85,177,161,142,249,81,208,74,7,73,61,160,142,153,121,63,78,230,152,77,38,100,58,119,15,102,23,145,201,189,165,77,147,230,208,2,84,68,22,86,13,32,68,58,88,73,8,48,139,117,27,222,40,32,182,33,168,89,188,113,162,162,146,225,102,118,158,53,22,82,149,184,240,92,212,243,40,50,170,149,147,223,104,185,45,162,20,59,162,173,157,5,224,233,8,159,219,28,215,102,178,59,121,254,199,162,199,99,2,69,53,6,16,218,9,6,241,44,220,188,45,208,250,244,235,250,209,70,110,222,198,183,219,47,135,143,170,11,226,178,201,194,8,0,115,63,105,158,9,227,172,16,176,218,211,18,70,236,5,109,35,119,143,218,145,213,190,153,247,240,232,191,61,9,58,130,175,235,45,122,195,207,43,194,102,133,91,46,230,18,78,212,122,114,168,4,94,120,96,72,18,12,142,191,141,105,202,78,241,114,85,34,238,84,11,10,254,50,188,122,76,216,117,121,110,3,95,91,62,253,60,174,139,195,120,183,220,61,229,75,22,220,190,134,216,68,90,111,184,152,40,130,43,39,76,144,94,215,83,252,62,127,27,6,175,158,50,87,41,85,95,32,24,14,193,22,92,54,156,254,77,61,50,7,243,25,48,156,89,56,17,33,107,135,110,160,52,80,216,55,217,98,40,102,1,34,70,233,200,205,172,234,156,17,180,123,113,143,67,81,224,51,149,12,213,251,3,2,63,30,249,181,254,120,160,155,133,96,137,181,35,5,182,121,214,39,128,129,237,203,19,137,24,93,101,255,228,209,34,58,241,253,187,131,60,8,241,178,36,11,26,109,21,150,214,31,242,19,60,118,147,158,111,23,164,168,73,67,92,231,211,6,86,222,242,248,107,142,231,119,143,1,168,27,187,91,70,38,230,162,216,232,152,83,71,41,183,182,189,94,221,128,7,217,182,42,49,232,20,23,3,87,95,213,181,137,117,14,161,52,243,122,183,193,90,134,182,58,222,179,72,150,241,129,197,216,227,156,20,75,90,202,71,128,15,137,242,183,117,188,168,252,39,243,76,167,222,12,190,250,197,206,164,145,191,47,206,24,20,40,253,36,4,220,72,143,199,19,105,30,48,219,215,196,37,15,182,38,220,134,239,35,187,29,230,68,215,139,220,215,90,25,184,246,196,149,239,249,142,248,63,141,205,161,28,87,142,170,237,214,67,142,251,97,163,163,242,208,139,28,201,5,249,160,111,232,64,231,207,201,197,196,206,92,127,71,17,57,48,200,25,226,176,113,210,162,108,233,45,224,15,40,196,161,187,228,55,88,74,235,30,68,12,209,70,87,243,159,85,208,70,192,75,111,14,15,239,6,234,134,248,30,113,51,255,128,43,104,82,6,158,241,74,19,174,199,229,132,238,6,70,145,96,242,208,185,17,12,251,210,13,113,233,186,188,29,9,195,244,71,62,26,195,82,44,209,10,230,93,188,92,234,241,145,115,67,77,67,44,210,249,228,5,84,43,160,77,103,214,59,87,195,200,20,129,254,173,229,229,37,115,254,49,72,119,145,188,255,12,95,191,110,239,124,12,213,234,217,4,211,133,39,184,242,103,223,13,5,50,56,74,214,135,66,130,62,223,167,91,175,30,40,134,82,42,167,175,169,33,40,205,88,123,104,96,189,142,226,130,73,0,60,121,128,225,203,146,1,170,4,93,235,72,243,97,77,129,92,246,173,53,161,138,204,83,70,234,80,223,20,176,62,149,150,127,141,182,196,163,80,117,13,31,248,64,166,35,112,96,44,221,70,128,124,229,74,60,65,83,15,20,135,165,184,82,153,163,153,145,137,168,21,68,140,120,76,239,1,57,32,133,38,158,157,114,92,79,139,129,100,233,109,73,206,6,164,101,18,250,41,214,14,185,87,241,153,142,116,3,55,77,138,149,123,112,38,59,191,132,156,136,205,108,175,236,117,66,107,36,241,192,147,149,227,116,253,26,209,34,134,94,214,68,212,25,142,117,207,151,32,13,101,187,154,38,54,165,162,58,254,142,54,86,89,13,232,46,36,31,67,169,250,183,168,205,55,163,165,77,37,211,28,12,51,80,99,47,117,190,69,215,83,246,24,48,152,252,50,167,183,242,94,21,63,211,171,23,199,4,160,172,57,57,92,128,50,52,174,87,77,255,17,221,149,165,195,162,43,38,226,27,221,101,124,188,82,226,222,49,132,246,31,27,81,255,205,69,176,163,195,253,83,47,80,99,157,132,223,160,92,39,120,73,149,51,171,255,67,218,107,160,220,58,236,28,119,180,1,82,24,146,160,44,200,70,141,109,254,12,126,229,95,99,96,3,216,221,136,205,113,142,122,186,243,183,255,22,253,97,176,39,222,179,209,180,233,133,72,37,54,158,28,65,95,13,1,59,153,193,87,230,128,104,160,201,205,2,196,6,125,232,155,188,65,83,240,126,145,178,63,143,0,240,193,78,184,2,226,82,240,49,22,50,167,206,196,168,121,68,212,156,249,154,95,24,93,83,113,168,33,14,246,208,135,139,78,122,101,123,8,177,97,182,122,128,106,140,8,192,100,143,88,196,50,29,207,215,143,65,120,133,133,118,94,128,12,106,130,195,165,203,112,192,173,166,222,59,23,34,6,82,131,16,84,214,205,87,208,140,201,182,166,221,131,122,181,85,150,65,139,133,103,23,179,159,231,7,175,204,95,130,131,126,45,155,135,76,69,145,54,197,251,173,9,206,46,189,122,101,178,24,17,52,231,121,151,60,255,66,47,5,0,134,235,185,232,129,137,35,158,3,110,230,211,73,61,209,224,71,153,55,248,61,100,233,170,140,66,27,177,253,40,208,209,143,4,27,108,105,166,136,60,8,218,119,168,182,107,8,119,5,118,31,219,43,94,70,182,91,68,254,135,245,212,250,26,105,156,109,180,133,177,249,140,89,130,79,55,31,123,18,154,42,191,139,9,240,237,151,107,173,188,134,243,132,118,79,249,197,52,29,174,60,127,48,203,213,101,118,178,117,92,200,49,217,119,172,213,150,231,103,134,168,200,159,174,105,85,8,72,53,243,196,179,102,171,173,207,190,134,186,250,180,231,155,193,203,81,248,175,8,196,145,73,186,178,63,177,60,238,12,42,169,79,173,245,76,171,131,19,102,237,156,201,116,42,209,167,158,198,227,114,197,227,182,212,229,151,110,140,149,239,82,124,137,145,167,26,54,159,102,237,132,139,121,181,115,78,145,179,231,40,243,114,107,190,126,230,152,86,21,43,130,126,87,172,107,120,215,174,119,95,238,138,107,162,109,30,0,156,48,191,59,137,171,39,151,249,219,16,202,29,186,7,225,198,202,213,119,26,30,46,66,61,154,127,212,160,121,30,139,137,77,16,197,1,225,23,181,190,52,124,88,224,250,45,111,131,115,99,26,188,227,244,207,13,101,230,130,96,187,90,109,141,203,246,150,213,238,2,180,162,199,113,129,255,97,7,65,101,37,145,166,70,193,39,68,86,45,6,162,80,189,182,147,237,204,108,173,114,12,139,6,79,110,178,50,39,17,113,41,178,217,61,88,132,240,93,181,152,170,7,71,170,146,115,177,209,87,215,16,157,38,76,45,46,220,16,103,58,125,32,153,241,187,154,232,13,56,84,165,56,94,8,6,118,36,14,96,65,93,68,50,208,97,85,185,103,1,161,83,67,194,38,128,76,181,204,102,151,40,72,219,119,58,243,206,0,99,50,157,241,110,31,75,39,89,181,28,80,34,47,54,40,145,0,60,100,212,148,16,35,19,189,130,103,237,1,19,109,241,72,134,148,103,72,23,209,106,186,211,41,196,18,76,23,75,122,68,251,50,11,252,232,52,72,57,5,52,226,217,252,184,71,71,112,106,214,93,60,250,235,235,115,148,64,183,222,82,158,135,135,145,153,54,138,126,116,216,66,235,51,100,7,1,111,11,231,57,153,174,195,76,173,195,2,137,227,217,61,109,233,31,68,5,179,235,72,80,16,191,118,37,76,119,131,246,39,251,58,127,172,229,32,135,167,216,216,39,54,7,180,45,236,44,47,186,218,5,45,145,201,222,24,126,214,198,237,218,245,74,159,119,201,233,27,224,213,175,46,43,252,104,209,254,53,126,25,166,190,157,66,64,23,226,4,74,69,28,42,238,195,233,33,1,64,116,16,110,32,81,97,57,242,250,108,13,200,31,184,115,30,190,65,111,225,197,90,215,174,221,193,216,165,11,16,3,153,141,181,161,223,213,141,64,243,41,33,65,208,245,48,203,171,242,234,120,183,57,60,85,83,188,148,249,94,62,178,164,119,223,137,180,49,184,166,120,134,127,76,230,216,208,161,5,42,237,196,235,114,222,23,134,110,242,244,163,1,42,228,3,251,93,156,48,46,154,200,19,163,205,213,250,142,212,14,156,210,48,20,148,235,204,232,128,21,3,100,38,184,230,249,138,117,207,253,60,79,102,174,115,184,21,102,194,116,47,69,98,110,200,73,248,186,30,220,75,239,155,228,138,141,255,84,179,127,17,124,167,107,102,248,93,59,11,170,167,110,129,228,140,41,111,215,131,169,31,210,192,131,220,50,29,241,34,235,141,60,96,178,83,126,109,14,186,209,248,63,130,108,186,180,105,95,192,234,29,87,8,197,153,103,55,13,10,116,247,40,153,54,84,199,120,69,98,185,228,4,234,107,80,168,240,218,9,114,58,196,150,245,120,244,210,164,160,201,55,20,40,135,138,179,149,228,199,157,192,174,190,79,35,154,208,104,215,44,229,241,125,186,156,42,60,224,60,98,79,40,64,126,207,165,212,10,115,54,25,33,126,58,236,50,194,209,149,85,111,178,89,79,15,60,227,54,174,229,243,135,42,102,50,171,254,95,21,247,31,125,0,215,95,9,254,115,158,204,23,106,103,28,139,202,110,125,119,242,110,213,56,152,116,42,49,235,231,28,252,0,141,119,191,200,51,122,183,74,56,200,99,174,153,239,174,227,16,247,241,53,17,43,147,201,28,236,24,172,158,183,250,239,232,109,178,138,191,154,85,92,101,93,173,175,120,149,115,204,109,250,109,193,172,203,85,254,72,122,109,173,97,223,35,161,59,23,39,177,164,124,186,70,76,36,143,143,79,179,160,167,125,30,112,233,209,141,126,247,37,119,77,159,6,86,22,186,250,64,148,109,116,69,157,161,219,213,126,74,234,55,4,74,150,191,164,59,229,208,73,147,153,74,155,93,93,177,111,177,180,36,107,46,26,222,118,125,41,31,110,95,84,199,96,81,223,99,229,230,111,208,187,44,207,189,197,162,155,118,66,246,102,5,157,180,61,121,27,171,235,38,194,219,47,109,32,238,247,114,130,158,184,151,243,155,87,210,50,16,172,39,124,229,145,237,44,49,206,229,30,118,171,255,129,65,10,175,28,62,65,30,217,20,113,253,179,149,240,28,118,112,140,20,237,39,7,159,242,230,64,144,209,53,33,213,116,176,141,135,111,225,244,248,107,202,235,131,88,130,60,113,17,151,144,193,21,155,78,5,33,221,177,64,101,141,166,1,217,83,16,24,8,33,203,8,73,180,252,201,36,37,193,112,158,81,36,62,12,87,125,150,121,19,39,92,191,173,210,244,36,77,195,88,140,26,156,4,231,27,111,89,251,35,188,185,246,75,176,127,162,75,144,137,255,124,36,161,108,144,154,177,88,19,197,21,51,61,242,175,177,115,118,58,158,40,174,196,158,97,198,184,209,36,126,232,71,189,204,186,7,102,36,124,234,204,89,172,220,192,86,101,51,175,40,9,191,17,115,155,117,200,237,22,138,77,48,250,240,160,224,117,133,170,182,144,213,211,213,2,243,145,65,254,0,2,248,48,33,249,80,119,29,108,76,228,213,3,143,250,23,23,131,183,155,60,55,214,27,114,225,198,150,10,35,148,123,109,118,26,2,65,205,51,165,231,113,146,183,118,99,110,128,192,107,84,128,130,68,16,88,195,165,35,170,219,153,195,92,132,226,34,20,77,81,240,139,150,107,214,77,155,204,106,79,19,168,44,71,198,240,87,142,60,44,60,246,5,116,90,243,72,82,123,206,123,164,157,159,113,100,46,227,97,151,247,172,49,26,253,214,112,110,75,191,20,199,178,121,153,73,146,167,80,165,179,249,104,118,42,76,8,126,200,69,25,1,35,35,219,85,218,235,253,164,63,211,195,178,60,208,120,222,151,167,79,238,35,131,109,53,18,149,50,40,14,206,218,230,111,82,234,124,19,223,6,18,94,196,199,189,219,79,203,3,86,63,184,11,70,220,145,70,39,204,13,70,25,105,99,18,2,0,24,161,197,244,35,162,11,157,34,54,196,92,138,255,30,83,77,170,69,196,207,11,28,60,155,7,88,6,248,72,159,21,242,123,4,244,230,249,74,32,130,186,174,143,2,140,24,130,73,170,186,195,129,0,221,95,213,21,27,147,128,194,103,91,111,210,249,82,200,180,140,107,187,79,132,95,135,105,220,39,219,47,101,130,232,19,153,84,96,21,214,227,184,212,26,88,77,22,173,250,215,51,120,214,55,206,86,220,178,39,170,15,114,12,97,98,239,4,124,47,250,230,133,149,196,82,209,165,151,0,207,30,106,133,62,251,241,196,196,47,179,145,179,2,155,15,5,165,22,67,52,207,39,246,123,134,219,252,174,231,168,82,8,7,192,229,168,45,215,86,100,235,111,169,107,12,249,89,109,86,160,142,181,238,237,223,92,168,130,150,236,224,116,222,45,18,13,13,164,73,38,27,208,24,138,45,80,4,148,58,149,54,128,230,244,22,230,218,179,87,51,104,223,178,9,209,228,14,206,192,249,41,82,34,115,235,125,150,192,196,1,165,252,62,83,243,157,37,218,134,192,149,232,139,145,253,205,51,17,97,192,121,157,60,181,170,126,156,5,44,196,235,223,123,170,2,118,228,255,243,8,132,196,221,30,242,92,159,112,180,131,51,25,126,253,184,7,4,110,34,217,37,185,91,186,44,77,80,104,181,58,171,9,210,180,17,119,8,141,229,247,64,62,232,121,118,112,133,52,173,5,202,94,170,37,212,28,222,193,97,51,164,107,197,181,220,102,52,58,47,147,194,179,174,14,89,19,221,145,39,174,86,249,64,89,192,101,143,207,156,186,210,1,137,143,225,13,38,98,59,92,137,53,31,64,212,100,157,144,100,131,3,65,115,94,185,87,13,25,176,45,184,207,19,250,197,231,86,217,51,191,125,60,11,95,125,105,236,148,166,54,6,42,0,150,180,138,38,30,235,72,106,14,217,69,184,242,46,197,173,38,89,234,41,197,213,165,79,86,118,231,142,207,69,207,108,20,53,179,160,231,84,99,156,253,80,13,15,65,18,73,160,149,31,76,124,141,4,48,207,86,81,87,66,32,121,213,115,116,230,240,201,247,195,159,66,154,244,180,174,14,101,84,3,66,175,40,177,65,194,101,162,234,26,55,222,21,72,164,219,243,129,30,172,104,212,50,6,152,90,233,235,35,221,207,165,225,44,109,74,127,123,173,56,87,209,84,211,48,214,123,5,105,101,78,188,169,175,36,172,214,19,232,125,217,130,252,99,237,244,61,173,193,82,209,216,57,13,12,202,82,193,78,70,69,206,74,240,191,91,25,179,254,242,177,68,23,139,165,101,32,52,246,25,212,240,38,237,147,60,156,190,36,3,56,163,125,228,107,228,6,235,44,250,90,92,77,158,36,217,168,161,77,26,49,125,99,103,191,115,41,120,16,231,243,69,108,169,115,81,127,195,48,164,132,75,173,147,62,148,220,3,189,186,165,200,86,60,18,172,193,207,129,196,167,69,181,134,232,130,109,48,76,133,202,38,184,207,153,39,149,26,4,242,77,59,193,254,102,222,99,68,91,147,245,252,14,111,57,224,121,244,233,148,97,66,37,162,181,44,60,144,184,181,187,204,143,33,120,225,243,226,97,190,168,25,134,240,146,145,251,166,104,183,243,126,93,104,93,84,55,148,49,84,30,71,204,203,236,226,179,113,247,64,213,92,207,126,35,130,231,86,232,149,34,79,127,8,155,120,228,29,247,142,10,151,52,57,180,40,56,93,99,171,253,160,143,201,101,183,204,59,240,23,208,83,198,151,231,231,147,28,110,4,156,102,57,157,18,249,18,50,20,130,56,53,156,41,45,170,41,117,136,179,222,121,239,18,168,166,237,2,237,98,107,148,236,81,60,2,33,181,218,46,71,254,197,234,84,204,80,27,160,118,123,153,37,55,238,240,199,98,227,116,197,126,232,21,255,98,226,206,152,34,211,121,85,69,183,195,225,202,232,188,79,208,206,156,187,96,21,189,252,76,203,227,241,70,211,61,52,217,12,33,243,41,50,152,77,47,82,19,140,197,235,100,59,65,70,115,52,246,95,80,145,224,57,224,221,213,78,145,49,47,117,102,248,205,92,84,18,215,150,191,135,145,62,36,193,200,52,133,187,34,96,149,139,1,97,248,25,51,64,247,58,93,111,15,225,212,223,114,61,92,11,95,154,153,245,208,78,148,39,150,34,40,110,50,154,11,54,4,145,21,134,166,233,0,193,39,105,2,102,29,28,168,238,231,117,248,142,40,50,56,142,240,142,165,151,16,85,30,155,98,225,239,177,187,143,215,228,29,118,98,85,69,167,21,45,116,143,40,42,152,1,87,158,139,169,81,137,18,54,65,178,145,44,82,225,241,84,208,111,202,139,17,95,107,130,255,148,105,65,106,172,230,171,55,197,239,133,168,4,152,247,235,19,138,175,168,216,216,171,23,160,83,71,40,126,234,228,1,76,145,9,132,135,166,202,190,232,233,218,105,184,138,161,252,19,33,132,61,159,183,129,62,37,37,194,79,104,59,218,204,215,82,166,4,190,36,224,43,97,59,71,51,188,214,175,54,18,10,15,153,110,203,218,59,225,113,185,123,75,111,206,104,24,163,254,170,85,40,105,9,229,41,218,37,240,211,103,89,253,97,34,77,188,114,220,132,215,129,26,109,149,186,128,119,108,19,20,122,172,175,10,20,169,9,104,195,150,51,8,159,140,86,232,226,177,7,196,200,167,207,106,126,27,140,222,219,198,149,46,0,13,93,255,121,205,23,206,245,185,247,15,231,173,156,59,156,16,48,118,254,93,148,203,237,189,158,180,101,52,62,155,57,8,175,171,215,67,69,104,60,72,232,226,185,20,206,65,59,42,125,90,124,100,202,134,141,239,191,110,203,164,223,50,232,219,4,222,205,22,70,62,180,75,143,174,228,44,62,245,202,39,117,215,33,145,80,106,131,177,244,66,46,89,167,198,251,80,38,72,190,90,118,85,34,158,83,17,61,132,124,53,24,63,24,90,249,68,131,245,198,183,117,13,157,137,70,189,73,23,75,77,13,25,88,126,217,87,108,92,8,133,154,15,158,112,113,94,186,162,177,9,232,181,162,55,24,38,161,79,176,4,233,11,158,170,242,240,168,77,25,3,223,158,186,182,26,129,84,106,135,108,205,79,254,175,227,1,238,248,79,5,72,169,217,128,158,1,139,110,157,12,39,55,95,3,2,113,179,81,229,38,144,253,35,77,155,97,157,9,47,133,35,238,97,246,176,156,164,3,236,181,42,140,173,1,46,164,218,168,228,127,219,160,224,59,249,247,7,155,98,77,199,215,146,55,151,221,185,163,241,26,122,137,164,190,205,207,4,237,134,165,74,238,223,226,15,248,242,139,107,210,187,234,4,145,23,231,180,229,53,254,166,201,220,10,14,58,33,230,72,92,230,207,170,109,188,229,137,28,147,22,41,192,213,40,215,216,127,14,228,9,13,85,247,106,247,1,155,206,136,4,23,190,148,170,106,194,155,170,96,227,85,168,247,195,20,113,172,17,34,38,123,79,167,110,206,207,53,66,173,162,178,166,84,120,160,160,218,186,227,34,87,100,212,219,28,84,255,59,138,26,28,227,102,205,94,75,152,55,216,163,46,225,96,152,57,32,57,159,27,251,178,201,231,5,139,31,163,136,69,71,125,19,213,46,252,84,88,215,163,249,153,181,25,227,174,4,105,93,98,251,60,164,4,222,26,165,85,83,87,45,206,132,134,6,108,89,96,76,139,144,143,144,116,59,72,48,184,248,230,195,135,167,29,166,42,207,49,87,221,159,42,168,96,157,181,125,152,96,130,72,48,100,105,145,96,98,200,116,7,131,166,69,99,117,55,141,40,125,106,249,33,118,191,121,159,138,79,27,90,132,13,52,0,61,44,246,212,77,127,107,26,124,234,104,26,14,238,68,79,124,247,99,81,60,135,27,62,83,231,104,214,53,69,104,188,95,120,30,105,222,150,218,223,80,221,209,86,113,125,226,123,36,1,136,94,206,253,124,34,218,2,77,208,172,39,238,148,151,111,237,3,135,99,41,22,142,129,39,56,105,255,31,62,12,171,5,206,94,114,13,174,185,89,199,225,131,239,187,92,132,102,86,138,156,36,55,112,65,191,209,70,60,75,110,59,216,180,148,36,118,238,139,97,222,17,236,209,68,163,76,177,206,58,196,113,2,166,47,131,113,199,180,134,23,174,24,119,20,124,144,29,221,9,90,224,188,131,232,13,244,94,200,129,51,27,11,124,24,154,5,91,171,150,238,212,117,175,71,155,110,168,3,236,162,196,193,74,101,6,238,157,132,151,181,88,122,26,84,194,170,253,198,124,142,133,185,66,4,105,5,152,87,209,178,134,243,242,197,214,209,103,53,218,128,193,9,83,231,55,111,29,235,133,45,107,115,71,203,15,1,69,200,105,216,1,163,183,18,222,54,6,56,48,104,228,237,119,166,90,242,184,97,160,218,194,255,151,131,120,180,104,202,167,157,179,147,77,161,34,65,201,171,236,177,175,0,92,134,255,40,217,133,61,187,44,165,109,184,127,37,189,61,62,60,232,182,210,78,123,118,207,185,156,158,77,117,67,26,37,222,174,87,192,241,152,180,170,218,35,86,86,91,87,98,97,192,129,140,194,233,36,79,152,203,136,73,223,63,26,117,190,88,188,60,42,9,45,54,223,198,207,196,237,26,244,60,233,67,132,223,113,147,253,16,126,10,119,41,159,99,237,109,167,23,248,146,7,166,214,75,0,234,202,90,254,26,71,82,240,116,216,96,236,109,46,104,255,134,115,253,155,36,36,129,188,183,140,151,14,153,244,139,244,252,214,160,8,249,226,35,58,185,116,255,126,128,120,235,190,225,169,185,175,255,64,176,56,247,249,7,18,39,92,249,142,98,47,116,247,126,6,66,208,245,253,217,123,160,123,49,99,18,90,47,9,80,207,212,123,18,61,155,193,44,242,205,146,4,96,210,222,194,220,47,172,241,165,29,155,45,163,105,121,174,115,233,211,216,182,136,24,90,234,77,214,70,94,160,35,59,16,39,71,24,186,43,251,99,53,11,47,60,159,24,144,250,41,114,90,26,97,209,154,96,63,178,67,28,211,107,179,90,253,127,165,163,26,175,163,165,60,47,25,151,210,245,25,91,122,31,176,184,179,128,161,75,71,166,119,40,19,58,101,115,237,145,211,239,250,235,224,4,46,64,94,118,213,191,21,42,27,169,75,217,193,182,121,215,57,216,234,245,160,135,78,21,125,113,51,250,39,177,32,227,61,57,182,118,16,212,181,130,153,240,62,148,127,188,127,160,37,3,231,33,68,181,179,95,116,179,14,247,145,214,104,222,71,140,17,161,171,218,105,81,195,25,20,202,235,110,70,90,42,47,194,109,74,85,60,77,65,92,205,106,16,171,147,0,227,16,251,48,224,101,8,46,29,94,50,36,213,78,254,13,7,254,227,219,219,18,45,213,145,136,25,210,42,32,47,62,61,139,31,140,17,210,249,37,178,80,160,59,139,26,250,178,179,208,129,81,82,239,54,209,224,20,156,174,251,26,130,136,28,68,243,28,42,28,17,51,90,6,39,125,11,249,223,165,193,243,148,129,17,210,146,186,89,202,253,59,205,5,52,237,17,181,104,92,54,142,214,177,178,59,214,195,73,72,186,175,17,1,0,220,146,69,144,120,89,133,146,152,239,230,141,237,0,78,250,117,54,179,45,38,167,90,149,136,233,115,8,227,210,205,255,208,177,5,45,173,12,189,122,109,122,136,191,40,176,51,234,201,4,208,42,147,44,56,120,17,43,69,93,97,143,103,130,166,129,101,7,40,85,92,157,218,212,230,114,139,2,233,64,93,127,49,140,232,168,194,0,74,215,40,158,61,12,247,57,151,103,148,42,210,155,139,211,87,19,0,208,70,224,199,34,241,199,70,169,161,135,61,105,233,172,62,114,0,96,15,45,231,45,55,172,39,55,41,225,133,190,138,162,53,142,120,95,183,32,192,36,208,155,102,233,86,61,53,30,206,83,199,125,72,101,207,29,247,104,10,148,18,184,234,165,202,151,116,193,119,185,112,23,192,20,152,65,174,8,254,94,56,95,112,30,175,131,75,160,36,26,226,61,55,97,225,40,77,212,181,0,239,155,198,208,128,240,202,248,190,135,42,46,22,94,11,61,30,199,55,16,98,142,1,63,173,36,147,172,74,152,45,239,201,204,46,115,27,81,227,120,112,155,184,99,79,214,130,147,122,64,139,9,147,208,82,76,15,123,98,5,74,218,198,40,175,162,34,226,243,95,227,126,94,45,242,141,118,9,49,66,13,62,135,201,56,200,96,255,212,204,11,3,243,18,242,108,74,227,62,173,115,180,224,226,248,249,141,136,245,6,158,110,65,8,248,189,225,236,226,84,45,8,72,133,12,176,12,140,172,135,245,88,80,88,0,185,175,79,207,75,134,219,100,194,29,255,125,135,114,8,126,63,172,235,145,65,229,120,37,197,36,66,254,60,122,61,197,192,6,79,197,152,198,219,179,231,14,155,211,69,154,175,209,49,59,91,6,25,138,1,144,199,28,148,67,149,19,37,147,101,173,173,206,196,37,179,47,184,185,251,43,182,74,221,246,66,82,220,131,113,87,197,241,66,226,95,156,93,186,196,250,229,244,248,189,22,207,27,43,104,3,210,183,207,145,95,190,74,251,145,107,71,36,138,225,83,79,207,145,78,210,137,175,90,23,239,94,181,98,41,136,109,211,114,150,87,255,49,149,169,69,132,65,211,140,205,214,29,22,127,210,12,110,19,72,139,152,200,229,246,220,110,222,227,189,5,36,90,254,53,6,237,122,57,142,108,23,90,140,146,218,237,207,124,148,18,43,1,231,98,177,83,35,133,156,57,105,201,222,84,80,168,12,176,33,62,83,81,72,91,127,176,136,94,105,255,254,90,145,155,68,132,45,203,4,81,16,2,218,66,189,227,170,31,12,196,122,121,143,12,99,122,129,195,234,210,79,14,55,209,162,72,6,182,66,57,203,144,165,124,104,28,239,250,145,78,30,73,201,115,103,29,184,58,64,70,85,21,63,220,48,82,120,182,147,193,160,57,159,29,228,110,185,119,116,208,106,226,116,121,81,43,222,244,81,208,45,54,252,92,150,203,97,118,228,145,19,251,135,68,118,217,134,205,225,179,191,233,152,12,91,197,183,100,112,245,155,90,49,164,31,226,11,161,97,101,12,52,104,87,67,185,88,236,186,244,207,7,33,67,86,181,69,233,84,8,132,228,204,119,32,165,140,91,72,140,72,59,85,160,243,119,182,101,202,174,103,225,103,157,66,245,6,239,65,118,228,82,220,95,37,111,101,138,161,191,68,163,207,254,132,5,33,34,56,45,15,145,79,100,40,250,236,235,36,175,245,20,209,154,13,198,149,155,0,80,11,84,80,172,105,217,187,232,7,132,48,231,150,103,105,189,165,83,77,153,247,75,244,46,186,175,219,208,150,199,180,28,58,132,148,105,13,207,113,32,133,101,252,13,167,207,239,200,38,246,25,126,101,156,150,20,134,155,28,193,203,237,91,8,31,34,172,248,160,57,105,219,239,42,133,226,116,81,43,132,235,167,30,68,43,231,221,164,52,182,249,179,61,153,161,159,137,151,189,73,236,246,163,36,98,19,85,248,126,173,105,179,75,212,179,6,192,100,128,153,211,199,108,66,203,86,207,169,95,199,34,119,154,244,10,13,220,112,98,175,183,40,113,55,27,57,116,86,1,170,179,54,173,252,94,178,69,116,19,143,251,130,194,112,136,117,223,38,229,127,85,195,14,156,30,223,71,155,223,129,124,152,171,136,110,120,95,180,53,100,168,25,3,216,42,54,85,46,69,119,107,155,145,251,64,53,185,193,15,13,139,6,167,11,60,47,89,97,48,152,126,89,204,146,71,95,57,111,150,78,240,251,102,115,113,11,147,15,192,253,231,25,248,245,109,134,153,56,58,101,46,144,2,253,31,2,83,198,61,64,121,63,76,80,67,29,12,66,28,147,254,92,69,68,35,212,156,221,161,237,249,146,56,121,137,145,156,246,183,247,139,124,62,163,212,103,229,186,93,174,69,23,160,26,196,181,43,175,176,60,110,211,55,131,146,61,179,46,79,154,194,63,7,77,202,244,150,202,18,92,217,129,241,239,222,111,51,135,13,231,255,23,171,205,2,165,228,225,46,247,213,245,181,190,140,154,241,182,186,251,24,83,159,137,53,64,138,170,164,60,147,27,90,82,193,36,201,173,182,188,108,188,229,45,193,211,18,253,200,185,25,95,180,93,30,219,69,195,239,222,97,161,110,214,36,114,96,168,76,77,164,53,131,226,197,100,0,42,106,159,84,214,55,249,124,216,170,102,155,118,134,77,181,65,115,14,167,123,89,46,212,228,181,29,222,148,86,228,253,74,236,231,197,148,188,137,167,27,127,12,253,186,84,67,146,211,91,131,122,218,230,239,254,175,168,1,213,249,121,7,221,136,146,201,36,166,47,73,221,190,128,205,126,206,89,121,78,233,57,64,136,20,67,198,178,249,191,17,131,33,149,197,130,104,170,130,142,237,246,170,147,192,156,248,187,123,25,225,139,220,171,61,24,24,114,110,77,3,160,244,82,56,94,113,16,27,118,228,217,56,29,253,10,75,145,97,193,150,89,210,52,60,146,17,127,187,216,5,195,108,15,251,39,157,158,86,49,193,199,155,106,6,73,80,247,203,61,88,81,56,93,158,179,40,245,81,68,136,69,32,237,101,122,112,165,100,55,9,127,59,26,9,41,16,102,92,246,179,125,108,231,225,63,120,88,135,69,195,239,197,51,245,72,72,59,15,231,42,3,184,123,64,176,64,2,15,246,220,67,193,252,8,159,56,20,44,137,45,172,109,183,204,159,101,6,17,221,228,44,160,69,242,153,202,128,203,12,4,126,92,35,50,234,50,118,36,235,41,31,25,142,113,24,62,9,95,20,19,50,125,158,204,53,186,86,53,189,102,153,228,219,22,2,99,14,143,147,221,199,23,113,107,196,224,225,104,121,99,34,19,112,121,28,191,160,245,10,17,84,184,88,225,151,167,54,240,195,72,254,120,18,22,155,131,146,29,227,234,30,101,250,135,69,125,243,191,220,108,252,27,73,15,229,136,53,207,18,173,204,19,205,199,182,167,225,33,249,143,99,91,17,55,149,227,252,128,238,114,212,169,242,145,36,176,68,219,87,139,157,11,63,61,59,211,206,153,189,127,223,109,58,97,39,141,146,29,253,92,94,80,25,18,106,154,118,230,19,134,225,160,83,60,150,40,14,114,137,33,215,197,110,48,190,240,56,91,138,248,129,37,247,39,83,175,2,103,194,229,110,102,216,12,120,6,3,226,163,55,78,249,252,111,226,91,6,137,148,130,47,48,247,229,23,243,182,71,150,137,124,20,124,66,139,32,193,148,161,185,236,79,174,99,200,112,53,55,117,29,34,237,204,153,30,100,212,1,178,63,101,108,21,60,226,164,189,178,191,164,14,130,253,211,82,162,209,199,23,248,243,208,248,249,158,141,215,199,86,0,246,74,146,131,115,160,41,65,31,203,224,248,194,77,33,67,47,171,200,140,46,76,21,188,172,177,183,243,246,224,185,32,56,122,180,233,201,25,233,15,85,45,133,25,16,136,35,136,145,142,15,86,80,133,48,119,224,178,65,40,193,213,90,108,89,160,56,151,217,217,57,103,175,63,242,81,89,154,80,29,72,39,62,162,124,64,207,184,236,170,24,70,121,44,61,235,14,3,108,68,201,57,178,69,188,58,91,211,235,251,154,69,34,123,86,213,66,253,253,216,176,67,99,197,91,185,250,198,244,215,134,106,130,27,155,101,61,23,181,173,83,247,184,185,24,221,87,94,129,150,24,83,250,180,99,14,23,157,95,133,189,98,219,252,120,118,181,213,41,131,138,220,245,32,75,155,209,55,31,197,21,188,175,14,108,96,144,219,70,87,169,105,80,215,39,54,253,164,135,220,113,179,11,26,86,90,17,173,82,168,51,234,219,159,197,190,211,12,96,163,96,156,21,216,237,81,71,8,238,177,222,65,238,18,207,224,198,6,78,77,58,229,128,113,49,80,53,64,60,188,235,183,243,253,19,186,159,48,179,25,11,199,176,100,249,48,94,85,170,164,215,111,157,248,47,235,115,199,148,241,90,5,156,158,194,36,48,2,128,54,251,107,121,73,162,149,9,148,65,58,167,164,203,170,52,197,196,44,120,167,22,204,41,135,101,200,149,248,38,73,57,71,205,69,158,255,72,185,219,30,199,49,162,53,242,190,45,142,206,11,94,30,40,120,221,10,171,209,31,64,30,69,102,138,222,180,169,4,28,97,34,15,174,50,15,217,31,255,141,56,24,233,173,156,216,252,142,255,94,59,43,223,147,253,34,44,189,10,93,55,252,67,27,40,123,12,243,5,33,140,234,16,240,115,171,26,131,179,201,114,216,135,196,14,204,11,226,91,159,139,238,182,65,152,10,212,173,146,189,31,16,197,251,214,140,176,101,41,217,127,19,65,118,112,116,119,159,28,52,102,175,254,92,132,73,106,70,124,121,229,34,136,208,230,102,14,165,73,4,170,233,83,76,138,148,54,152,21,227,68,40,188,180,162,79,72,48,228,26,205,64,66,33,171,221,163,170,114,114,184,172,219,201,168,200,24,77,52,12,80,226,95,105,205,101,189,221,3,5,202,38,226,148,208,76,126,116,245,120,125,186,56,187,96,82,46,133,211,10,66,86,187,156,137,23,160,98,171,226,232,11,114,200,18,250,211,87,122,21,93,163,90,104,194,160,53,194,74,207,94,195,91,24,76,184,136,174,136,22,245,12,54,167,76,106,249,48,251,40,188,97,95,223,30,22,142,194,231,189,143,57,151,51,105,150,197,223,211,167,34,90,118,91,128,229,236,240,185,96,234,208,26,179,111,122,244,232,80,12,38,10,75,30,38,189,236,165,19,26,106,197,252,71,235,185,204,73,177,213,143,142,148,0,198,150,67,125,250,112,233,80,164,49,60,6,157,40,93,68,163,97,177,11,138,69,11,80,35,151,37,226,112,83,104,68,199,208,112,120,18,122,5,174,225,120,249,246,187,239,139,207,193,43,156,214,226,0,98,218,49,189,224,164,249,146,98,223,125,50,17,156,249,81,199,227,5,93,233,167,93,238,114,241,192,104,44,145,2,60,79,168,0,112,62,78,120,31,150,105,225,33,243,194,10,247,239,80,186,67,248,147,112,190,206,149,49,185,35,4,129,193,254,128,152,100,164,105,79,44,168,54,203,1,129,230,43,92,174,4,56,200,148,20,82,211,212,136,193,83,214,240,81,138,39,11,132,114,55,99,194,4,143,40,233,177,238,255,46,166,183,5,115,190,182,171,253,136,6,248,32,219,26,252,55,109,189,224,176,219,6,131,136,170,148,101,102,58,242,121,97,120,125,146,126,232,251,70,200,193,191,199,169,112,172,43,218,147,205,17,215,99,9,141,194,206,149,104,71,115,45,250,190,121,28,115,88,81,131,250,172,238,160,98,146,119,165,113,166,10,172,34,174,43,44,119,114,32,110,169,188,210,22,181,71,3,8,218,196,202,103,105,234,72,209,168,202,3,206,120,58,52,91,169,202,207,73,67,52,223,246,40,85,129,186,17,147,193,231,46,110,139,178,74,210,186,252,20,42,212,66,107,31,239,184,60,105,247,138,212,29,59,35,147,239,109,123,57,144,11,149,66,71,134,57,20,223,47,197,51,83,184,140,102,217,213,245,43,232,173,139,129,135,141,23,147,64,170,6,101,154,52,47,242,34,140,3,101,199,41,95,122,146,104,251,210,114,60,120,85,93,235,23,132,185,200,46,225,58,185,30,23,139,234,67,231,176,36,70,216,129,111,57,23,74,254,117,89,199,41,209,178,61,214,211,184,105,167,86,249,49,90,42,123,168,58,104,222,200,67,41,108,0,17,167,116,177,110,201,116,233,182,36,97,100,6,194,14,109,98,123,229,192,135,60,139,212,178,229,24,178,75,57,129,64,124,38,73,23,182,0,233,69,40,62,242,69,133,151,96,88,46,115,166,144,227,171,12,67,150,150,224,205,128,11,68,98,7,65,199,98,217,18,163,103,246,75,237,111,191,192,188,237,204,240,118,109,98,193,54,170,132,185,37,96,110,213,152,18,190,35,50,82,137,93,149,215,225,221,42,90,5,238,158,171,51,61,216,167,102,11,175,66,32,95,200,136,58,38,185,31,31,7,154,137,77,199,135,129,68,11,138,218,56,51,63,138,232,178,118,35,168,128,222,75,254,4,133,240,20,138,225,42,242,179,147,238,252,236,171,207,216,158,161,187,121,28,211,191,97,168,90,83,211,109,149,65,124,180,9,172,11,247,233,144,178,35,236,201,59,110,14,121,70,14,224,61,254,78,212,28,174,65,117,240,197,140,63,81,231,180,236,142,119,35,45,55,146,227,92,243,89,103,227,113,113,7,241,196,218,216,222,133,210,176,201,227,29,129,190,164,242,224,9,230,82,122,179,114,75,246,39,15,229,149,39,223,54,20,209,236,251,52,201,186,78,73,37,151,126,3,228,78,186,96,42,131,8,164,251,31,66,192,181,12,97,55,186,77,32,219,199,151,33,3,42,85,29,142,29,6,107,115,68,114,214,114,140,199,143,20,245,129,9,78,83,246,169,65,41,122,99,69,204,115,173,8,254,95,66,163,162,48,175,244,113,209,100,147,112,188,220,233,113,5,212,201,138,91,38,191,72,7,99,178,116,234,92,48,244,0,211,154,27,247,206,232,89,85,99,233,132,72,85,200,139,238,153,179,24,123,99,134,246,142,188,239,9,157,112,162,234,185,118,245,59,130,224,204,31,163,171,38,159,221,225,99,216,177,58,35,104,109,10,125,89,23,53,56,37,68,165,189,60,83,249,63,161,240,70,141,1,210,143,125,157,56,227,11,24,55,38,168,16,119,213,155,223,143,131,175,37,234,125,238,16,194,101,201,158,4,110,18,210,221,84,87,14,13,169,250,241,240,1,12,205,98,246,198,75,250,239,249,104,97,127,57,19,15,104,126,28,59,196,119,32,32,82,17,212,81,175,226,118,175,241,105,177,135,71,82,187,16,240,159,71,37,41,230,115,64,156,184,169,24,234,219,0,246,117,253,167,73,143,69,3,130,245,116,43,177,166,154,119,212,153,47,46,26,192,155,252,200,241,110,201,195,252,231,181,147,45,221,62,85,89,150,72,79,230,174,245,52,49,209,202,184,143,160,9,190,63,249,33,193,163,53,123,237,31,46,225,42,225,49,158,14,120,71,133,247,37,52,27,195,168,0,173,254,175,48,203,127,136,142,20,140,58,102,224,52,13,72,195,143,146,84,91,160,228,92,126,63,39,81,150,207,232,13,28,22,22,113,169,45,140,23,5,46,155,127,197,116,25,54,226,104,89,169,95,100,83,211,41,119,115,107,60,190,170,12,213,173,189,220,228,10,211,105,116,245,166,208,229,181,165,201,68,170,57,36,97,78,110,76,75,65,230,77,138,17,146,196,148,196,16,237,121,105,24,158,75,121,236,185,205,129,31,100,68,181,179,248,183,65,29,74,96,126,223,176,27,19,62,148,147,12,48,70,173,22,7,123,162,216,137,16,123,171,81,196,100,84,138,92,119,3,209,28,49,46,184,35,78,201,26,213,233,176,139,204,161,161,100,134,151,46,27,220,236,243,154,104,171,179,29,24,244,219,213,4,109,217,17,167,110,219,11,225,255,47,80,164,122,91,85,104,133,179,78,39,122,132,12,176,53,220,175,184,93,42,5,93,129,217,176,225,1,179,77,53,121,239,203,231,143,218,94,107,129,31,11,195,254,148,78,105,60,149,153,223,20,120,153,7,211,141,71,154,236,170,254,85,202,104,196,108,18,145,215,252,129,244,163,252,137,151,112,146,157,1,59,187,240,13,15,2,216,118,65,35,126,38,27,221,174,235,245,160,106,120,196,95,105,214,48,54,136,226,74,65,88,37,3,224,245,60,140,2,150,249,134,212,251,59,123,169,14,76,79,118,67,227,62,202,182,40,50,114,7,24,44,54,254,33,251,230,193,198,191,167,178,228,71,214,100,187,93,9,99,58,230,102,178,170,160,39,178,130,14,57,7,70,171,249,174,14,35,35,120,237,233,152,182,162,97,118,134,142,150,24,7,159,154,144,20,178,175,155,125,114,58,253,140,118,189,3,236,201,17,137,170,158,6,138,214,209,52,137,203,102,157,11,99,113,92,97,55,117,153,111,20,219,251,13,105,77,46,143,89,53,195,147,116,53,124,195,182,95,154,49,226,94,206,124,56,128,210,109,131,196,167,229,110,5,138,241,184,84,170,48,209,20,77,49,194,144,208,224,23,8,82,52,152,83,235,136,168,48,59,7,125,42,229,139,89,170,227,83,9,67,233,174,188,101,17,74,229,208,35,149,23,105,183,73,116,1,80,193,46,164,25,242,129,1,17,88,87,87,94,55,96,126,151,60,35,202,219,9,3,222,161,131,34,149,198,202,198,131,167,91,75,106,85,22,230,193,8,201,156,81,226,164,111,44,147,161,162,209,240,123,26,148,30,161,104,16,29,236,170,204,149,74,126,34,109,24,139,125,1,32,228,137,89,30,201,147,146,189,177,123,185,72,228,107,91,49,121,163,27,243,72,155,29,183,58,67,212,196,210,201,58,31,102,67,158,141,70,175,80,213,3,99,198,124,34,110,94,209,77,20,85,45,162,82,18,61,189,203,199,56,131,228,230,7,53,226,247,217,35,66,115,37,68,130,210,200,156,186,44,33,11,229,31,84,159,92,194,52,14,158,187,179,106,80,194,179,80,226,202,110,147,204,167,44,63,158,49,55,80,115,164,46,156,244,58,137,134,55,253,220,75,9,103,136,249,242,3,215,220,53,123,17,75,112,40,131,105,76,0,16,17,245,242,195,47,165,106,200,206,26,130,189,65,203,2,99,181,5,143,191,100,128,52,249,154,169,127,159,85,163,175,105,201,79,170,124,33,172,15,229,166,146,194,104,108,129,91,132,33,195,224,4,116,61,113,89,52,79,251,121,2,32,71,98,121,115,214,245,87,160,16,97,250,177,149,55,39,223,212,203,76,231,248,127,176,129,187,75,9,209,101,237,148,65,111,200,193,164,44,66,237,159,220,85,84,91,89,208,128,237,151,180,31,151,237,151,16,114,221,155,43,42,4,83,34,238,79,149,66,231,157,222,132,11,145,104,170,56,236,84,248,183,36,85,4,10,143,170,141,177,87,7,163,114,225,72,248,238,122,146,203,203,157,4,155,198,245,193,60,218,180,175,34,89,80,195,35,71,85,234,238,86,77,49,244,128,157,230,211,30,114,38,88,35,242,190,254,27,132,194,18,236,121,228,133,95,97,44,236,154,28,64,235,14,62,141,6,104,2,239,196,0,239,190,200,189,55,225,88,118,166,28,3,155,39,73,135,166,250,86,28,103,243,78,21,135,177,206,135,183,141,13,148,181,253,155,176,98,53,113,191,110,156,23,111,210,0,12,145,6,255,146,80,247,0,74,171,33,213,96,90,118,193,89,208,79,47,247,61,246,11,199,235,65,231,27,63,41,110,254,129,80,132,0,167,84,59,171,175,164,131,185,207,179,36,207,187,236,180,205,188,150,112,119,170,82,180,155,78,6,33,163,196,74,97,85,204,95,48,248,81,22,74,219,228,3,163,28,111,155,134,69,37,9,187,242,25,75,186,8,17,151,196,130,59,118,14,82,207,194,129,82,65,199,147,72,96,117,243,22,125,145,219,206,184,153,41,144,219,98,96,155,34,94,181,44,163,237,168,33,89,151,218,192,247,57,198,126,236,197,141,63,109,159,157,29,83,185,46,181,8,73,42,95,252,161,116,224,219,172,169,119,219,52,46,170,69,178,172,93,174,0,45,81,139,114,181,102,240,100,159,66,137,156,200,175,244,173,51,117,206,244,24,77,6,23,82,12,37,118,160,225,85,183,69,79,100,126,129,93,155,18,95,145,39,32,118,241,90,236,152,14,20,126,31,234,84,34,120,172,90,243,50,162,34,238,83,91,24,255,99,225,240,27,114,166,100,243,207,98,170,111,107,224,19,79,177,203,231,135,126,205,13,231,108,153,215,16,143,6,18,244,71,18,188,143,224,169,189,54,129,185,202,121,10,142,246,219,251,81,92,184,115,207,55,223,23,9,172,6,80,2,236,96,4,51,62,54,135,46,10,0,229,235,188,235,218,127,115,177,136,157,40,2,71,146,32,245,200,137,190,179,220,117,208,242,197,14,183,79,124,35,171,203,89,139,208,30,50,32,249,148,242,236,98,48,88,255,143,25,1,235,159,210,127,229,219,6,20,19,41,23,220,116,32,214,217,7,197,244,101,247,93,18,117,151,140,84,68,104,42,232,36,226,57,55,57,181,128,52,6,203,130,54,199,103,197,158,184,138,127,61,223,65,111,57,25,181,72,139,155,65,139,48,15,128,95,194,241,163,12,246,39,191,53,212,114,194,90,65,109,13,121,48,171,160,68,35,192,251,149,193,182,207,178,158,107,32,192,59,214,166,145,205,76,194,17,236,248,105,195,184,201,91,214,106,71,163,206,253,189,15,166,160,158,55,182,108,213,82,244,47,221,194,227,48,139,93,104,165,186,46,214,47,63,142,36,158,192,116,253,133,77,50,45,85,208,33,203,120,156,6,55,217,53,210,131,30,194,170,65,32,80,32,81,218,104,125,77,236,131,42,23,51,41,208,230,40,175,127,201,126,254,209,89,221,187,181,101,185,235,139,217,248,49,187,232,192,124,28,52,88,70,236,155,38,60,43,157,178,180,45,203,113,4,9,67,86,60,136,52,5,61,152,126,254,205,152,68,61,64,58,226,75,218,19,204,177,16,138,148,243,180,234,110,6,134,194,139,167,50,151,95,62,160,137,209,208,255,81,199,177,240,114,1,163,160,235,235,172,203,57,245,240,94,121,56,11,132,16,23,152,180,38,90,26,107,103,77,223,70,133,160,220,55,161,159,238,135,127,195,39,208,86,53,94,195,241,255,207,90,238,9,252,64,51,154,107,238,114,42,193,58,242,19,108,172,209,86,71,42,197,80,100,152,114,254,57,174,37,64,50,36,160,251,173,106,84,18,16,170,209,101,166,151,240,142,96,134,97,50,207,93,244,231,22,49,72,181,188,188,85,53,41,160,158,84,157,23,30,169,226,115,33,73,115,107,143,0,226,138,147,191,74,190,144,231,29,158,45,154,232,182,228,53,105,112,118,75,176,179,123,111,233,14,139,90,157,138,223,14,191,88,106,91,191,149,119,119,125,12,238,211,244,188,43,214,146,153,165,147,172,221,81,131,160,19,124,234,236,188,144,176,73,96,127,208,169,247,17,186,160,163,61,186,59,233,72,217,58,90,43,43,23,250,105,188,236,66,19,98,125,250,90,130,162,167,174,46,218,37,184,26,92,237,34,0,26,104,74,167,221,23,105,113,9,187,125,231,185,93,92,121,93,23,185,54,19,90,235,249,3,121,58,43,88,53,140,51,45,206,210,228,223,67,147,216,82,11,167,178,164,218,132,152,116,134,84,112,15,165,106,15,116,46,222,118,186,76,133,157,255,99,27,35,96,230,14,223,36,164,244,30,234,71,169,225,124,239,103,239,185,44,71,223,241,177,16,211,173,64,220,127,244,65,244,249,195,214,90,121,43,248,177,241,128,96,74,224,104,16,53,79,225,14,219,175,78,129,103,35,184,131,156,66,49,75,196,237,145,109,124,157,74,188,157,84,32,153,170,210,235,165,6,155,60,118,114,50,169,40,37,1,220,122,220,107,20,39,19,238,244,128,227,140,103,0,179,250,11,140,38,165,57,63,111,193,84,165,175,223,21,24,232,153,190,211,114,99,96,103,146,32,24,107,66,117,93,27,243,49,114,246,219,30,34,20,17,69,183,243,131,101,22,123,146,89,58,14,130,29,141,36,211,54,162,164,189,208,207,2,157,64,29,178,133,166,206,71,226,123,104,195,207,127,14,140,247,187,212,124,199,222,83,46,134,206,111,75,190,63,73,82,47,139,200,197,11,130,44,168,239,104,124,162,31,115,106,15,77,72,8,188,215,102,185,145,177,146,105,215,243,128,236,120,202,35,200,18,3,56,41,51,228,233,136,75,253,209,15,226,133,173,67,184,30,89,158,18,91,156,153,18,111,152,178,1,79,85,158,151,216,76,58,134,155,146,49,89,17,51,188,208,128,156,11,43,131,131,106,12,149,63,166,121,16,63,219,137,51,65,222,5,172,189,253,110,113,53,167,226,44,245,31,50,38,174,100,68,22,13,112,212,36,155,239,195,60,53,18,123,223,198,86,22,195,153,183,238,240,84,186,32,5,221,42,82,204,140,146,40,142,221,64,66,150,70,55,47,30,39,14,91,230,39,190,250,204,44,92,192,48,150,46,192,2,42,75,126,145,237,31,191,38,153,131,36,227,179,79,231,201,9,204,104,33,64,247,81,36,153,134,244,72,253,218,167,247,131,248,178,75,238,207,226,79,244,209,92,176,76,70,26,233,159,72,80,240,245,86,236,211,60,129,147,52,202,224,10,121,136,140,72,97,73,10,133,96,120,170,207,50,34,150,192,32,223,232,196,218,17,88,13,218,31,177,119,20,156,206,58,133,152,213,248,174,186,249,107,70,175,113,37,10,115,145,51,107,100,20,219,82,204,77,140,219,219,169,215,58,48,94,235,31,79,145,66,12,48,214,3,229,197,44,184,188,88,27,187,162,100,106,211,186,207,12,7,55,129,174,102,0,79,203,232,178,166,41,96,67,20,205,236,10,17,185,214,114,166,94,180,205,186,114,55,253,184,106,217,46,50,15,196,129,214,56,81,178,117,165,228,136,107,226,194,252,239,232,52,189,121,119,33,227,225,214,234,74,40,173,225,105,36,9,32,65,235,127,209,218,119,230,246,90,85,92,208,117,25,145,241,125,158,150,196,130,194,200,251,49,170,85,124,87,213,239,96,184,96,197,63,244,187,217,215,49,3,224,114,164,10,22,251,65,108,238,13,29,254,18,139,129,219,58,169,151,73,96,64,221,26,16,12,14,12,78,9,203,11,80,73,221,118,103,173,1,169,193,215,109,126,166,137,12,12,135,17,81,209,32,12,131,60,0,153,66,201,121,182,155,39,109,173,1,186,45,253,219,88,63,179,91,22,106,108,66,107,17,105,97,59,6,133,136,82,129,125,190,184,234,131,23,198,146,94,243,204,25,190,50,160,81,176,220,38,215,41,120,112,38,74,163,171,24,106,116,214,231,194,77,99,71,195,47,141,134,111,103,119,122,241,34,5,170,123,150,232,85,63,156,112,76,202,78,176,136,79,161,164,245,223,119,235,27,8,99,121,57,0,225,90,143,129,173,209,102,133,158,64,233,181,113,212,237,35,132,15,88,36,85,226,152,217,11,16,251,213,25,7,85,125,48,155,221,141,133,205,66,237,6,5,241,72,247,133,199,177,78,236,71,27,110,205,207,241,40,22,141,156,101,179,172,227,30,248,161,147,84,177,176,26,32,103,36,110,30,67,137,223,121,255,110,247,94,76,30,149,83,111,96,72,165,93,200,58,207,176,213,13,29,75,187,45,112,179,43,234,213,242,216,43,249,33,207,40,167,96,46,219,167,44,111,57,183,96,243,201,5,215,73,106,130,134,7,142,153,17,97,126,88,35,57,154,246,15,16,48,120,187,131,106,242,11,250,99,54,230,135,88,172,62,208,30,127,145,236,44,247,246,202,229,174,206,139,144,172,167,141,73,106,163,33,202,57,80,76,67,219,18,99,153,119,22,223,8,132,90,173,119,88,241,34,158,228,149,129,248,73,110,153,176,170,26,33,117,151,227,204,107,181,26,21,245,164,236,219,77,199,199,35,205,68,49,148,238,100,242,214,99,155,100,23,181,56,99,13,119,225,107,153,143,182,246,225,208,95,196,75,114,87,98,134,84,115,210,91,16,159,38,83,255,6,141,147,176,178,28,7,98,154,157,117,22,186,222,203,229,195,97,78,111,21,1,209,7,216,220,49,206,103,113,12,92,248,125,213,205,208,125,25,23,255,131,122,18,244,102,110,19,246,57,97,29,160,122,12,249,191,178,249,218,202,196,118,95,227,2,202,72,253,166,224,126,142,247,255,235,17,182,40,239,72,49,69,198,190,146,45,197,143,72,232,60,106,114,24,207,64,199,21,148,63,154,255,94,65,161,221,130,35,137,115,115,180,84,241,144,61,126,156,106,22,242,150,187,185,206,193,114,109,233,188,162,195,80,84,37,148,76,38,233,82,107,55,196,65,244,142,66,169,247,79,119,3,176,143,31,254,163,250,36,254,95,244,199,37,243,80,12,199,218,35,41,133,113,33,14,19,65,68,109,255,12,46,255,36,190,184,245,158,28,243,54,230,255,252,10,28,140,185,137,52,36,177,174,246,253,228,33,46,4,171,48,142,104,247,44,43,68,29,108,218,170,183,172,241,193,73,207,219,37,138,1,150,130,219,251,45,165,77,163,56,41,211,48,28,136,245,232,57,137,129,92,21,128,45,154,238,208,32,231,214,120,74,179,72,201,37,186,206,84,50,7,123,49,12,239,253,65,164,149,178,102,109,53,34,240,96,200,137,6,135,145,49,172,151,73,182,67,200,127,30,211,36,85,185,165,56,97,54,221,209,90,70,22,143,152,129,15,204,59,5,143,171,180,132,244,145,20,44,11,142,181,72,223,151,147,26,241,164,157,222,7,97,79,43,35,103,66,163,25,155,118,174,109,181,98,111,56,136,55,63,81,51,89,250,61,148,153,110,132,172,218,99,18,104,242,83,175,53,197,209,126,182,44,53,73,229,104,21,252,214,227,27,176,170,31,200,156,251,40,253,90,104,145,10,1,175,235,135,77,56,137,11,51,99,233,59,250,122,62,196,2,245,142,86,59,143,192,123,130,214,245,182,157,134,228,82,199,243,29,167,83,105,75,4,236,116,174,50,18,89,242,200,87,109,23,221,184,42,3,82,80,103,135,218,190,7,129,98,180,64,149,196,181,217,136,28,58,56,53,14,16,248,30,82,197,85,149,53,2,112,81,243,53,131,126,174,187,3,237,209,3,20,9,246,22,3,194,201,118,169,89,116,66,199,66,16,175,193,47,238,65,137,126,87,148,144,167,191,216,137,23,120,162,24,80,68,168,161,148,167,6,137,56,1,160,59,75,181,56,92,175,90,233,7,212,173,52,242,167,91,64,194,196,220,18,71,186,221,224,84,47,76,156,55,190,180,102,18,21,27,55,125,249,219,154,48,54,210,58,72,73,154,78,48,73,105,233,200,178,230,208,130,172,18,160,79,130,20,166,83,203,232,203,108,136,211,228,152,192,103,222,8,46,245,50,29,25,234,254,228,47,202,93,242,41,33,139,115,212,186,141,90,222,177,4}; diff --git a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_64spp.cpp b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_64spp.cpp index 41a28a44..aa5e79a8 100644 --- a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_64spp.cpp +++ b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_64spp.cpp @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // An Owen-scrambled Sobol sequence of 256 samples of 256 dimensions static const int sobol_256spp_256d[256*256] = {32,226,72,70,57,171,246,75,112,81,109,239,120,101,230,103,103,41,249,86,253,99,132,184,214,147,128,248,17,149,163,17,60,40,169,196,77,79,102,23,250,77,75,151,95,123,234,198,25,26,184,114,230,188,105,18,231,233,175,151,19,174,202,71,84,229,247,148,182,127,92,14,41,112,162,253,35,101,137,30,111,134,95,122,28,2,41,254,181,91,101,188,145,31,166,38,53,193,1,122,99,86,178,36,198,169,113,255,97,221,227,231,29,100,30,141,250,254,16,157,2,220,187,95,181,125,207,187,105,119,156,41,16,194,93,216,227,124,138,90,227,1,88,153,233,69,120,36,19,189,120,4,185,220,185,109,184,96,247,173,210,227,54,3,18,9,139,213,156,57,61,101,37,247,21,201,10,143,11,38,146,18,118,129,95,191,75,207,12,252,238,104,47,39,190,229,31,56,20,127,42,178,100,141,93,222,192,247,186,7,224,161,72,100,87,69,218,44,25,195,185,118,179,123,231,170,96,225,204,52,117,60,3,86,25,143,230,18,11,165,72,188,158,3,66,105,50,200,226,145,227,45,183,62,82,176,191,36,248,191,189,122,96,185,146,166,203,78,144,189,67,174,154,182,86,169,90,236,101,40,71,107,81,93,159,82,75,230,157,191,34,35,235,139,150,193,10,142,217,77,154,249,74,13,196,248,56,154,27,6,242,226,105,94,66,67,145,112,31,145,133,68,21,0,44,212,254,153,183,238,98,102,145,199,100,213,196,52,131,141,216,209,236,122,58,249,188,108,8,206,62,199,207,103,160,247,207,255,101,185,1,113,223,126,182,0,50,93,250,174,194,18,65,111,206,104,156,3,48,195,122,212,10,101,235,200,13,183,173,7,192,3,101,228,84,168,121,241,205,122,115,132,155,242,215,22,236,242,69,35,48,245,3,175,68,57,4,15,226,155,222,140,54,48,80,200,194,149,213,68,225,14,182,122,147,195,69,166,191,17,176,58,222,58,190,70,66,153,196,215,121,123,176,190,161,145,203,121,255,27,207,28,113,22,44,232,46,84,181,131,245,220,27,202,161,38,94,208,39,143,52,5,154,85,121,139,226,223,159,246,170,56,94,209,188,71,205,76,16,233,168,172,200,37,19,123,120,202,28,175,232,88,120,107,157,198,111,253,18,24,36,35,43,169,199,197,137,194,12,238,138,232,17,17,58,115,39,234,4,164,225,215,14,185,232,76,215,171,142,206,206,132,90,31,130,24,0,165,34,91,126,113,64,202,144,114,132,125,58,184,234,211,246,238,168,7,1,172,169,218,67,29,185,66,73,49,222,167,243,189,36,116,23,223,219,200,84,67,94,53,79,26,202,204,91,180,221,166,106,18,207,17,128,137,246,235,162,13,129,130,49,76,104,189,138,55,174,71,152,49,116,204,207,103,198,147,225,142,79,8,172,59,234,225,192,168,181,144,185,6,233,243,61,123,46,55,44,16,228,79,156,235,190,115,61,162,115,182,122,230,138,204,140,86,173,80,99,207,211,181,23,141,152,17,180,35,121,168,67,205,107,74,55,229,234,210,6,94,48,186,210,189,2,200,190,181,227,128,211,225,215,228,74,7,188,195,36,82,10,131,96,99,138,63,1,210,39,134,153,112,72,163,196,55,126,37,125,107,234,166,129,80,61,97,121,20,123,222,3,155,219,62,49,207,87,182,26,214,167,142,89,38,36,112,87,100,56,245,240,152,23,7,237,11,185,206,233,203,131,42,53,35,60,40,211,114,9,13,189,130,196,210,173,39,208,56,110,34,240,65,75,234,76,73,34,39,2,118,174,237,52,194,197,28,155,161,135,180,200,3,89,210,26,154,145,45,57,54,85,26,118,207,212,58,101,69,202,184,36,234,219,155,41,29,80,22,193,175,145,100,50,29,149,166,168,162,213,130,36,25,234,78,84,97,191,139,95,156,9,12,41,97,110,222,8,16,250,161,130,45,111,195,83,213,16,141,154,48,124,175,89,25,27,9,172,242,51,167,76,109,69,107,23,80,23,166,12,16,180,156,182,238,148,249,59,130,75,122,59,134,240,69,220,21,230,47,1,124,66,180,77,247,147,103,66,98,211,96,105,213,127,178,144,102,213,33,247,141,232,67,62,86,230,222,146,68,122,27,147,7,85,69,31,22,67,67,78,13,149,221,57,121,176,133,161,84,201,146,119,196,217,19,132,52,76,135,247,107,29,131,248,220,156,248,29,41,36,202,174,136,253,191,226,91,179,96,69,213,172,0,206,75,192,54,69,120,138,218,171,185,232,211,139,8,31,11,50,119,28,197,83,158,170,229,244,195,190,23,213,87,70,17,102,197,39,59,88,152,234,95,106,29,195,236,114,136,6,159,105,101,2,119,184,47,212,218,188,165,163,138,174,114,71,54,127,64,183,39,51,42,209,202,106,96,215,154,56,33,102,25,62,111,9,49,4,98,142,198,128,138,13,74,95,229,42,164,19,175,179,111,138,19,157,125,94,34,221,103,246,144,141,176,129,201,55,100,23,12,139,33,227,91,223,224,69,120,83,245,50,57,190,21,54,86,245,95,250,34,71,249,100,201,144,16,221,0,40,74,133,38,145,48,217,119,132,34,138,67,161,62,221,126,108,207,140,42,156,13,224,198,142,19,55,85,254,155,140,168,250,58,118,137,42,78,8,48,89,195,167,91,243,246,88,23,22,206,17,190,56,125,171,116,245,129,121,57,144,228,159,197,243,217,239,86,188,152,88,239,112,120,245,119,147,189,25,128,240,72,208,29,162,23,152,24,143,226,136,174,171,58,178,10,5,250,209,239,88,62,34,251,156,163,231,247,102,112,46,48,61,233,24,71,54,73,12,81,195,243,115,138,145,194,164,135,148,51,201,104,74,24,78,107,65,246,118,159,165,130,206,34,157,177,180,10,126,163,167,129,75,0,149,115,172,21,242,139,162,170,92,238,35,46,24,108,101,62,26,147,180,210,227,166,103,149,188,192,92,115,141,161,120,90,231,250,181,130,208,232,151,157,141,208,27,81,82,42,162,244,186,62,163,6,254,94,107,138,123,144,14,216,138,235,104,135,98,77,82,57,47,77,171,213,192,134,69,226,93,197,9,63,181,197,169,22,248,190,55,178,250,167,76,157,101,170,138,94,156,44,12,155,102,133,133,149,43,224,51,130,44,138,3,195,25,161,29,216,1,188,160,73,4,196,125,240,92,88,50,192,176,234,39,109,96,39,60,165,226,80,248,179,232,244,141,102,81,131,110,19,206,225,222,115,198,63,195,251,19,155,77,51,194,251,124,13,77,69,106,112,114,187,126,67,222,81,227,163,80,172,25,70,205,111,48,160,111,165,112,243,47,236,107,81,15,83,95,132,80,133,178,116,87,10,195,139,151,122,44,82,111,24,234,156,187,202,250,20,233,186,204,184,154,149,117,78,205,119,71,166,192,239,88,148,154,229,200,139,163,129,12,155,167,252,50,198,46,106,221,91,235,75,2,14,240,122,62,178,218,42,223,213,6,17,212,242,32,190,96,163,121,63,228,65,111,229,63,70,140,232,221,248,216,80,5,145,12,27,33,195,86,111,42,125,70,44,232,82,209,40,234,168,224,215,215,133,247,128,76,248,178,34,253,61,204,193,105,44,227,66,45,238,159,16,241,67,99,178,235,181,68,204,234,144,58,40,132,125,203,25,204,148,151,253,195,198,81,8,54,248,148,248,58,54,235,82,71,67,181,212,241,43,111,111,202,69,166,200,66,87,245,207,70,112,64,26,240,149,82,86,28,104,17,59,72,154,106,1,173,59,21,204,184,231,15,224,161,253,174,78,249,25,217,35,144,180,57,102,174,57,138,227,125,141,246,16,35,201,173,170,31,107,205,169,59,19,52,209,226,49,136,168,13,238,63,53,78,203,68,18,146,228,165,245,244,84,215,78,230,167,83,239,15,210,34,99,90,184,143,187,50,98,95,182,121,47,53,112,15,53,239,130,105,66,142,11,185,224,203,20,44,156,28,197,195,65,118,36,206,88,55,37,18,112,9,20,231,73,6,11,225,79,180,145,124,204,29,245,148,198,53,210,171,103,53,215,106,111,154,237,107,2,249,79,145,126,255,255,53,222,196,57,237,131,6,63,45,70,68,190,191,12,210,247,162,41,135,184,234,206,153,176,115,255,114,178,110,24,25,66,114,55,29,79,253,67,124,245,37,236,13,88,232,186,18,143,178,59,5,237,10,249,253,37,88,46,134,71,53,74,172,186,69,137,11,154,60,68,120,125,100,91,182,239,177,38,28,125,208,165,38,150,207,244,41,88,127,241,251,168,84,195,111,37,211,165,113,3,212,184,180,207,48,52,204,171,213,128,154,138,218,69,214,154,99,201,203,109,93,71,190,5,99,1,72,173,15,149,49,253,51,82,171,179,114,131,68,114,133,15,104,227,141,109,39,68,225,130,50,51,133,154,148,48,28,230,9,43,157,50,133,203,239,37,160,233,120,54,20,116,57,174,116,158,45,8,196,14,200,80,203,212,233,1,0,88,172,214,196,22,192,224,142,138,146,230,105,100,153,155,112,241,124,26,71,253,143,4,191,50,49,88,226,25,142,141,13,12,50,159,122,211,42,168,23,217,253,218,151,135,3,152,114,102,191,76,186,42,124,70,19,56,25,85,234,58,57,225,230,253,56,194,107,134,142,201,213,43,14,33,242,16,141,205,196,99,143,100,115,5,99,128,100,221,174,110,191,83,165,164,78,60,124,209,199,63,185,120,175,43,3,24,40,153,1,83,147,223,112,72,242,148,166,115,36,138,42,13,63,1,45,173,225,83,121,19,23,208,171,146,240,108,150,3,213,83,210,238,72,120,80,197,2,4,159,197,138,216,19,178,24,173,212,237,169,129,129,102,51,63,203,142,11,134,180,207,105,98,133,253,20,224,6,126,194,167,33,132,90,101,179,113,216,222,132,30,88,23,229,210,85,6,154,226,252,17,39,174,208,255,8,11,252,159,110,195,86,250,59,161,218,31,140,167,41,33,201,143,250,68,82,205,44,4,77,43,214,212,60,82,214,41,44,125,236,152,34,64,133,184,58,145,227,65,70,73,166,49,21,158,242,114,42,75,209,36,72,188,192,146,223,138,76,27,235,115,153,105,169,96,209,231,4,33,105,226,175,187,91,218,12,73,168,214,254,98,208,113,214,116,177,49,34,94,22,127,175,12,155,193,56,187,115,187,240,136,234,206,189,250,115,219,154,17,52,62,198,63,225,81,77,90,127,246,219,192,106,223,78,102,88,142,46,208,156,230,196,67,182,18,112,210,126,198,59,15,234,166,243,77,61,149,24,223,70,245,142,178,199,101,195,190,109,78,244,224,12,84,52,158,184,88,212,155,159,128,187,54,48,209,190,202,157,70,122,109,33,221,124,227,1,196,124,121,163,138,238,25,129,134,83,111,124,60,142,46,143,48,85,63,5,77,46,251,193,209,81,108,149,108,1,47,137,175,85,106,148,27,204,145,104,3,152,84,228,215,113,141,6,117,115,151,206,248,61,43,182,198,76,88,12,222,132,75,73,8,205,190,32,12,159,70,205,4,158,0,107,220,104,90,223,181,80,7,111,166,130,16,168,145,218,242,101,35,165,172,12,217,239,157,76,37,238,176,63,124,243,45,101,181,191,200,64,186,170,42,104,154,191,224,67,145,240,72,82,103,93,108,220,251,36,178,110,145,98,136,83,2,171,177,220,23,98,221,2,160,216,219,237,90,105,255,48,157,136,55,102,122,181,7,225,55,229,254,215,169,94,22,44,65,136,50,190,151,198,54,132,81,245,106,71,91,141,176,162,15,210,33,14,140,108,81,17,135,249,17,44,15,121,28,16,114,178,210,7,129,250,11,239,18,86,203,161,124,2,185,178,83,110,168,3,81,125,80,149,8,67,30,212,0,129,8,77,255,114,243,68,8,119,210,232,104,244,127,165,159,26,176,206,160,228,34,116,10,3,91,65,149,163,43,43,44,171,113,113,223,206,17,63,64,215,216,94,118,5,139,66,201,213,30,120,149,18,236,99,41,81,175,245,1,7,171,209,151,134,28,32,122,201,13,18,46,236,215,113,188,192,221,39,69,117,121,255,119,26,59,142,121,126,238,179,163,183,245,98,199,32,46,39,137,236,232,52,138,4,60,86,83,12,100,44,195,49,107,228,105,56,183,18,177,222,50,189,188,97,197,148,94,99,1,198,221,121,206,54,31,212,145,62,73,77,213,189,38,66,13,139,69,173,57,26,11,176,245,141,166,141,203,10,48,45,201,17,131,241,115,13,165,235,28,129,88,72,36,124,169,128,6,145,10,109,219,198,187,90,149,67,215,68,116,33,56,204,217,236,231,0,205,84,97,113,175,30,185,95,187,166,164,123,103,0,218,18,150,180,103,151,153,146,97,15,161,171,246,252,131,198,186,58,55,210,93,58,157,3,142,220,98,50,202,151,2,115,205,200,3,236,146,210,233,71,222,129,198,18,131,29,157,152,63,201,45,197,253,170,121,124,232,64,197,112,22,208,106,99,54,41,247,146,135,234,142,177,3,38,157,234,222,46,189,233,76,41,150,255,135,82,99,244,246,187,81,215,16,76,188,188,104,156,21,239,255,206,97,35,217,194,13,70,106,106,238,171,232,93,223,145,190,50,39,144,48,13,113,146,151,178,156,18,131,231,168,108,178,224,7,44,122,98,87,166,65,220,174,138,98,95,93,188,127,246,195,136,215,160,201,137,35,217,167,126,219,175,109,180,111,127,222,93,69,133,2,58,198,186,238,108,57,157,101,174,249,26,46,210,254,251,76,43,197,209,161,52,197,28,246,173,229,35,43,13,81,122,34,245,212,223,50,135,69,70,192,171,78,9,135,189,54,168,232,131,250,208,59,227,252,247,231,40,235,203,254,51,25,198,223,165,81,140,141,67,194,180,31,194,172,47,195,56,153,118,221,30,217,17,85,154,184,122,15,130,179,86,8,37,33,200,95,144,73,175,68,185,197,128,182,154,171,147,182,86,172,23,236,20,92,194,110,253,124,133,82,127,206,92,34,108,69,170,47,61,41,87,108,218,3,244,7,124,51,153,83,186,164,116,154,85,123,43,135,177,107,28,189,81,241,214,189,235,233,142,6,109,183,130,75,79,107,99,67,31,164,248,227,114,159,230,115,116,115,252,33,75,4,171,191,217,88,245,156,203,48,239,140,253,211,46,184,136,34,21,248,161,128,156,16,88,64,71,34,174,125,70,164,125,92,205,214,79,157,199,223,143,214,138,213,150,169,17,16,181,95,200,208,91,91,55,125,7,1,39,91,6,103,252,246,22,71,110,149,236,73,1,247,51,2,168,88,124,234,86,100,6,94,1,17,215,157,34,238,126,194,222,109,67,175,96,45,252,99,58,3,34,192,251,95,240,36,188,243,191,229,74,164,55,171,108,239,73,208,140,114,46,244,36,30,33,56,14,209,94,86,28,9,153,30,23,102,165,252,98,77,72,233,22,126,152,98,40,246,35,93,137,114,191,114,200,54,214,8,238,145,43,119,180,186,55,74,170,232,166,247,56,233,9,162,16,241,95,47,5,109,72,125,67,35,130,55,138,75,157,246,85,244,3,230,60,226,159,12,234,155,160,180,119,243,253,179,202,194,53,218,65,208,230,212,71,228,29,49,220,31,146,244,249,84,46,237,203,93,171,73,33,115,46,109,10,163,137,73,18,133,213,236,174,230,216,119,127,80,199,18,100,180,236,191,127,152,158,226,45,72,70,181,106,90,21,229,46,41,109,55,237,81,0,158,169,63,40,22,85,246,181,235,161,180,28,175,136,87,132,184,54,121,185,69,89,58,20,54,81,101,87,37,251,152,4,162,108,113,248,178,219,151,240,144,158,242,185,138,4,34,148,255,250,66,75,144,141,25,248,244,89,180,203,97,141,149,179,129,213,186,64,101,242,119,130,121,108,230,198,74,228,155,96,237,140,201,158,44,127,161,120,219,94,11,95,27,145,80,184,107,215,88,252,32,89,59,97,159,249,183,75,131,180,65,184,179,85,80,88,74,128,53,126,191,54,169,0,133,100,248,196,158,91,121,110,12,248,130,87,248,186,85,136,101,181,0,90,45,34,227,84,17,40,96,221,187,167,131,112,48,70,62,240,138,78,245,248,226,203,255,32,242,246,141,200,17,167,32,151,12,72,159,221,190,56,115,237,233,226,113,71,228,167,60,113,127,28,174,27,176,227,160,77,221,157,64,14,166,82,60,78,7,91,16,214,169,78,222,97,33,229,210,4,255,104,234,42,181,7,177,190,23,40,135,53,67,63,28,151,60,167,81,21,190,110,214,160,222,51,228,87,83,113,220,46,182,163,193,79,214,249,120,197,244,197,169,252,20,33,253,246,46,198,16,208,35,110,5,37,236,172,149,234,155,32,36,8,249,70,224,226,40,16,146,131,224,173,250,111,102,227,160,196,255,167,81,196,62,24,6,39,4,245,139,98,158,201,247,5,6,2,61,92,5,65,70,24,206,135,30,246,146,155,22,29,247,25,112,186,5,208,134,240,95,137,29,48,148,222,92,36,165,248,10,244,222,158,131,46,156,217,243,219,101,123,98,209,124,89,178,16,48,173,142,241,134,127,160,217,64,134,35,244,28,253,59,26,10,212,162,143,252,94,0,198,0,16,156,116,145,64,255,206,234,251,104,250,213,247,171,89,86,125,48,237,216,196,160,45,90,227,12,33,58,31,88,200,117,101,36,105,135,49,134,64,181,233,40,63,100,189,192,13,48,58,159,183,105,34,162,170,166,132,83,141,116,29,39,216,84,29,224,211,54,145,251,248,148,150,203,26,51,179,47,134,175,80,66,223,24,221,52,170,59,241,37,95,232,183,15,162,203,144,221,60,248,8,211,255,78,249,55,59,23,131,11,165,152,182,82,168,71,89,48,249,78,107,182,117,73,21,79,42,128,232,89,103,207,13,224,32,236,175,138,201,54,26,98,122,91,253,144,222,108,171,101,120,208,168,40,29,46,64,23,171,248,115,40,80,28,107,143,65,188,142,205,155,234,86,121,157,124,23,44,177,188,201,222,229,244,169,241,155,62,102,187,15,28,49,168,157,29,135,202,9,160,102,125,112,184,31,209,162,114,13,130,215,93,15,255,110,50,54,19,144,98,47,46,170,252,210,5,161,176,69,185,97,187,253,94,124,215,85,69,73,136,150,68,137,217,52,113,151,241,70,44,102,126,10,143,167,133,81,239,233,109,73,171,141,93,133,112,185,133,103,206,49,208,130,79,127,234,48,173,231,82,200,74,68,194,188,185,26,56,199,134,122,3,153,227,174,245,23,34,49,20,68,184,202,1,232,252,31,171,45,85,7,114,187,66,203,169,98,117,144,15,165,104,143,111,174,100,197,60,7,53,248,238,100,12,162,96,40,189,247,101,64,57,57,14,195,114,229,155,228,32,111,37,141,8,8,163,2,223,6,96,54,144,175,85,141,51,77,41,60,192,113,15,103,101,44,30,102,189,100,251,227,71,37,62,123,4,63,119,25,116,47,205,191,156,1,106,136,248,37,151,162,72,226,41,208,133,69,146,114,137,43,245,90,115,117,90,122,134,180,218,136,10,36,210,53,138,90,139,213,130,56,173,119,174,71,72,213,138,87,171,101,156,110,0,164,38,191,156,215,148,220,106,138,50,237,54,37,49,215,127,45,81,226,61,181,195,147,154,208,170,94,34,8,228,121,71,182,239,63,56,65,244,0,70,162,73,198,63,16,134,216,58,187,203,234,115,44,209,105,127,183,130,74,82,203,219,128,128,162,13,47,106,252,31,56,155,184,119,56,139,70,241,3,104,153,43,183,28,68,241,224,25,154,52,51,131,108,142,150,13,106,43,251,166,76,47,218,150,11,125,109,109,179,145,213,217,241,16,32,208,48,33,217,59,171,245,248,174,34,191,77,111,183,221,49,141,59,221,76,224,103,190,107,171,215,232,44,84,133,236,88,227,175,24,57,144,252,229,182,140,36,219,42,92,101,187,212,188,34,205,167,99,168,91,224,154,187,112,52,190,62,212,191,250,250,68,229,248,142,143,161,185,243,117,222,69,61,162,247,179,140,133,135,164,217,144,222,8,114,20,240,161,44,27,187,82,122,237,53,167,43,2,215,122,219,61,163,54,181,154,176,222,239,12,13,63,88,213,167,98,162,94,254,89,113,112,242,88,158,65,229,215,16,126,234,96,129,34,233,231,85,152,90,16,97,32,90,134,18,131,114,130,148,249,76,135,186,171,103,192,83,45,100,96,36,88,217,197,165,86,194,168,112,149,125,108,133,112,117,199,26,221,35,245,88,233,9,113,47,138,31,61,114,47,51,32,197,55,17,175,164,93,204,223,215,203,221,224,147,103,78,214,230,214,71,214,220,169,117,39,0,147,198,108,242,153,155,144,235,250,162,35,53,61,45,156,227,244,108,123,32,227,129,77,252,146,213,168,197,237,147,123,38,228,75,144,165,144,102,113,198,22,145,14,101,195,177,43,62,151,113,96,81,189,204,180,207,197,24,72,76,135,127,181,246,81,18,167,113,85,184,62,190,140,86,209,148,134,111,32,60,108,33,233,115,99,216,239,112,146,92,217,236,252,213,215,98,122,215,64,175,155,179,121,195,7,207,252,163,51,58,143,187,255,188,122,6,199,73,36,149,218,141,142,43,108,99,2,232,187,65,216,24,169,125,102,148,113,59,233,176,194,207,77,204,245,20,43,145,104,88,88,212,187,237,152,64,18,141,254,53,255,111,53,61,62,49,143,145,197,10,207,36,198,166,88,7,199,42,201,145,219,135,53,239,108,162,82,202,181,4,255,82,23,38,141,213,120,0,218,105,2,141,120,255,138,20,27,255,97,202,151,0,166,227,16,196,48,139,91,164,4,170,177,243,27,154,220,212,167,205,179,84,245,205,50,51,155,45,39,99,124,70,27,48,182,173,3,26,38,214,1,26,23,216,248,214,89,78,142,7,44,2,118,103,73,72,202,187,222,242,74,37,84,166,251,191,67,11,231,116,61,33,17,96,93,116,165,173,88,153,105,123,125,159,243,89,143,66,211,213,23,47,204,192,2,231,229,224,32,30,45,9,31,149,216,137,119,152,34,22,131,206,47,216,201,89,197,58,66,204,67,92,0,150,199,161,213,185,96,252,164,78,46,247,41,134,48,118,14,77,30,250,176,12,138,96,58,51,142,9,249,103,99,29,247,189,31,126,29,86,211,201,108,216,195,90,32,119,124,219,207,128,192,119,91,217,60,215,24,182,244,100,241,153,24,3,99,115,167,33,25,239,186,42,198,202,179,57,117,112,11,208,212,50,26,170,22,148,206,252,232,159,56,64,37,184,40,232,109,62,164,199,64,198,112,56,71,12,215,108,220,20,211,118,70,182,19,212,219,182,104,5,188,255,61,162,241,25,176,78,25,176,239,21,205,246,214,246,86,45,101,158,9,252,149,38,59,72,225,119,121,209,20,85,6,84,253,24,182,126,20,150,105,176,238,54,59,96,46,28,214,21,80,112,19,118,125,115,134,244,30,35,230,238,255,199,220,32,200,9,142,2,182,14,101,191,176,143,96,217,200,124,194,43,105,61,93,143,135,53,12,228,233,30,150,173,228,73,179,184,84,21,117,63,245,231,49,129,29,249,46,23,172,195,94,36,76,227,246,71,159,188,8,88,119,49,177,156,203,88,101,195,170,151,183,106,100,9,246,64,254,1,90,4,9,163,154,231,88,68,182,99,67,75,171,107,142,196,79,237,114,70,178,128,33,83,168,67,129,82,214,135,38,206,41,152,140,168,52,239,28,171,28,29,180,246,185,183,243,85,129,112,168,63,139,133,0,162,86,166,48,132,244,159,151,235,175,64,110,168,85,97,233,11,62,25,177,16,57,124,63,250,59,218,136,209,136,192,23,168,160,206,65,84,30,73,213,235,181,104,66,27,98,126,183,219,93,200,115,84,141,57,55,20,131,91,14,228,85,181,19,4,110,176,90,101,40,91,107,155,7,70,21,114,154,141,146,125,246,64,1,216,213,232,23,143,224,115,244,247,144,186,71,134,69,183,141,25,186,91,29,145,163,250,202,181,57,216,172,131,228,242,181,187,52,94,218,252,4,118,44,52,124,160,37,176,17,218,121,140,191,107,102,91,222,49,91,229,106,179,221,170,200,88,38,138,167,10,48,157,47,99,57,137,88,76,206,141,214,208,48,80,226,18,227,6,175,180,63,107,247,251,197,59,51,247,13,109,209,162,206,192,125,112,94,235,247,26,88,14,126,241,225,249,81,162,7,157,238,150,138,24,69,121,155,219,17,169,180,218,93,230,99,92,139,53,179,145,30,14,205,171,75,247,49,194,3,14,177,24,222,122,30,75,174,121,243,104,233,244,81,4,47,70,43,206,113,229,119,231,49,72,144,78,214,29,193,41,75,14,97,19,84,148,246,3,250,243,7,246,233,153,48,135,226,204,199,93,210,3,97,11,106,117,170,122,92,97,150,179,177,220,46,59,17,151,242,160,233,237,81,78,255,87,243,237,113,135,216,131,97,197,224,41,142,85,234,243,135,58,152,220,191,227,149,78,77,30,82,167,63,217,43,227,106,173,223,128,161,49,70,29,184,169,178,179,124,224,2,243,210,229,112,103,15,29,78,229,91,9,68,198,94,135,241,207,69,183,229,46,78,63,189,93,163,10,91,172,13,205,180,217,216,102,237,239,3,217,247,218,0,147,130,158,175,242,39,94,23,238,221,229,211,72,140,103,207,7,73,10,200,247,155,254,35,165,152,2,137,237,154,128,235,215,210,1,132,104,143,128,91,191,225,241,171,220,16,165,209,59,10,1,128,151,229,116,17,20,188,108,57,196,105,197,5,64,216,75,255,49,10,35,243,39,238,142,201,1,32,8,28,116,21,216,226,89,90,231,210,128,81,149,93,249,111,150,128,11,228,231,236,178,74,34,174,187,230,84,78,197,136,17,197,25,242,154,123,24,78,245,178,254,76,70,182,72,15,115,54,62,10,89,172,129,113,97,148,204,240,100,172,169,122,13,95,182,26,184,25,191,255,250,250,137,18,19,72,145,135,112,125,227,63,65,26,54,228,181,30,158,27,191,9,236,168,115,248,144,187,132,253,45,84,154,196,103,30,149,123,53,42,206,172,146,175,44,203,69,239,45,147,0,121,103,125,132,136,192,38,62,79,29,241,17,151,110,28,38,221,234,230,228,182,64,241,144,165,124,145,120,49,50,129,18,33,242,212,143,68,167,109,134,179,113,176,85,93,87,105,133,15,66,249,8,43,9,147,72,30,6,2,85,185,204,160,20,76,70,119,163,67,200,121,228,185,204,22,48,31,122,177,123,93,159,108,114,65,90,91,67,95,139,6,187,3,78,142,38,96,61,68,23,146,93,32,245,153,131,61,126,1,194,201,158,51,161,172,0,176,76,143,229,81,201,36,157,210,139,109,215,12,9,41,152,243,188,240,144,194,27,114,193,162,39,43,9,203,46,137,76,217,93,125,215,74,43,75,0,153,246,95,88,44,134,248,43,87,166,46,133,1,77,197,205,206,31,50,102,178,248,22,226,192,156,203,195,155,193,32,35,158,173,76,75,79,240,112,7,161,130,162,85,225,67,223,15,127,53,24,49,231,201,248,16,114,146,228,17,178,247,166,162,2,32,180,41,188,9,197,103,77,246,35,30,71,112,6,222,168,64,60,248,242,61,201,130,219,58,182,38,143,103,45,104,219,7,121,119,138,183,148,149,107,216,169,2,89,111,185,120,49,74,173,174,35,38,194,214,86,32,216,229,123,41,64,108,178,152,13,174,71,86,192,147,84,112,246,98,151,238,63,210,134,112,5,28,254,154,125,236,82,78,22,114,230,212,88,97,54,211,70,203,48,159,59,21,36,55,56,141,194,247,133,160,138,224,66,180,74,137,37,94,5,120,135,170,119,209,147,221,28,19,215,139,29,199,87,234,102,225,111,74,180,27,169,131,129,29,44,138,81,235,206,181,229,133,192,201,163,110,48,203,245,95,200,183,29,29,31,255,74,216,148,92,109,191,130,29,236,248,204,126,228,208,76,200,13,128,197,198,255,211,23,197,132,124,133,71,155,21,132,233,191,189,212,255,108,47,94,109,53,232,234,95,174,83,223,18,188,255,239,215,139,141,51,127,243,199,103,111,117,45,101,67,184,104,196,20,34,25,184,251,144,47,226,217,214,217,125,47,52,41,242,113,104,13,56,74,44,166,36,63,154,133,145,18,80,160,124,59,47,48,219,63,43,134,67,115,238,189,252,67,6,164,83,181,123,230,213,252,7,222,130,221,30,79,68,34,162,2,61,134,162,207,49,146,161,216,82,98,181,190,57,57,164,128,97,121,148,131,128,152,66,106,247,15,154,148,82,42,174,142,17,249,123,23,138,78,106,245,159,202,19,26,160,50,138,153,136,182,101,89,247,195,169,69,220,50,155,45,140,251,248,183,139,84,17,44,98,83,13,102,234,106,135,22,255,212,246,163,28,11,251,123,18,5,150,221,6,2,137,17,176,56,215,12,166,187,52,149,11,97,119,140,245,13,201,20,98,80,27,26,125,126,58,232,231,83,52,195,75,116,248,147,230,123,171,77,81,168,163,120,39,158,18,54,60,212,117,67,148,122,151,78,51,30,88,27,152,83,92,191,105,162,106,233,12,27,116,4,53,100,189,242,253,169,182,10,105,196,84,229,122,141,80,15,0,38,26,50,176,229,18,32,169,241,202,190,190,225,100,193,44,196,209,193,83,89,43,228,8,127,48,9,221,186,199,251,97,138,218,190,131,202,206,62,148,128,44,48,107,164,177,57,149,171,214,244,57,198,194,87,179,232,10,17,65,243,255,109,19,208,42,55,68,178,164,84,21,57,206,5,27,252,203,144,108,90,231,137,198,221,204,164,204,56,73,223,129,127,246,244,144,140,13,229,195,199,39,42,93,103,202,8,45,68,203,17,186,154,9,154,228,59,255,134,120,125,170,90,18,141,31,17,116,10,189,48,63,147,112,188,11,184,92,95,253,180,92,80,106,57,112,187,229,228,69,3,1,47,47,72,146,48,135,37,111,82,27,20,77,157,222,115,123,120,119,159,196,99,7,116,57,222,119,79,79,212,213,215,145,225,154,187,25,22,126,89,170,169,123,159,94,29,177,63,137,207,167,192,97,134,193,17,236,199,8,35,214,220,156,72,183,180,8,63,200,171,93,216,103,110,145,159,209,158,236,233,50,228,220,144,113,159,214,222,157,156,27,133,183,240,127,191,28,41,222,148,155,247,32,97,96,128,237,98,236,159,107,157,192,176,19,81,248,145,219,183,179,73,178,81,38,137,81,108,189,148,180,164,63,244,107,140,13,253,2,84,88,16,121,200,120,77,203,104,24,207,202,194,62,253,155,102,96,168,116,28,237,163,138,91,149,34,82,230,211,109,230,176,130,28,82,186,233,159,99,238,249,81,38,106,243,246,4,63,80,43,104,47,1,253,236,84,79,158,5,81,26,18,242,70,42,11,229,216,154,236,16,203,159,227,7,207,120,26,197,81,87,177,4,32,197,147,111,255,229,91,211,194,195,230,35,169,151,31,196,33,181,120,192,254,71,84,152,228,208,209,129,98,55,39,210,144,146,192,231,249,121,170,81,218,202,197,150,149,234,93,90,178,167,209,244,86,25,140,141,156,206,14,247,240,217,14,39,99,82,121,16,119,157,210,169,220,50,58,255,48,130,189,120,154,59,60,85,94,135,23,15,171,6,31,212,224,89,73,100,179,91,61,170,128,28,33,227,9,149,128,12,110,120,44,9,52,192,4,24,65,221,114,24,77,109,0,237,94,4,42,232,84,150,134,32,50,33,84,234,130,136,89,117,253,79,60,135,69,29,50,128,196,38,41,43,37,78,168,73,163,249,45,207,177,76,38,115,76,143,118,145,106,166,6,142,230,193,147,145,87,195,222,73,219,219,89,33,68,237,118,120,146,164,74,130,237,16,47,79,228,9,153,184,5,127,80,182,81,105,196,51,244,192,237,160,118,200,191,94,235,152,191,202,161,231,171,19,116,102,94,206,253,175,4,193,18,70,53,214,98,123,181,137,167,190,84,96,169,2,204,232,54,221,169,175,186,172,137,170,75,32,249,57,119,86,19,52,123,234,142,11,108,19,58,84,98,250,242,114,170,31,205,195,117,12,243,41,93,222,0,101,219,102,129,196,192,91,8,186,233,243,37,194,183,162,121,59,93,71,52,178,114,96,72,252,185,254,109,31,107,112,168,64,226,160,216,43,49,74,50,139,112,148,135,148,88,184,35,26,29,171,245,47,96,61,39,146,159,194,252,57,202,244,245,218,216,18,29,71,237,39,25,197,164,184,67,97,53,45,16,218,207,244,97,249,96,167,93,62,103,162,164,67,186,159,2,26,136,32,184,9,167,169,183,210,72,43,253,167,72,211,171,205,117,92,82,32,5,197,107,8,68,106,237,8,142,148,101,227,90,210,67,13,252,233,3,242,79,95,172,175,195,246,251,254,247,71,7,224,252,37,255,4,158,178,131,23,77,77,22,178,114,155,151,162,207,53,98,63,132,143,232,73,194,185,91,243,57,47,83,36,154,42,31,150,56,15,33,40,14,111,70,137,225,158,138,108,119,114,255,48,176,231,182,51,219,163,86,122,80,104,197,169,107,181,97,55,228,63,47,73,106,27,23,65,207,177,34,218,221,147,192,237,165,74,89,152,255,181,169,250,226,99,10,232,6,181,45,3,222,174,26,248,155,12,199,237,65,205,85,22,125,164,146,124,17,73,140,71,36,57,173,173,157,157,161,35,164,157,190,71,67,29,142,133,206,231,64,185,95,111,65,166,220,233,245,73,242,25,16,29,223,124,142,199,177,13,24,198,245,218,190,115,38,32,45,236,12,96,101,63,17,230,151,217,117,234,153,112,111,91,162,196,247,185,166,60,2,8,145,56,160,48,175,226,250,67,51,132,106,42,213,138,119,167,9,240,25,8,56,22,165,218,9,62,218,121,29,43,177,130,210,166,150,15,220,225,225,152,34,255,104,115,223,108,131,55,250,255,49,92,130,20,179,218,73,38,116,122,102,17,118,237,183,109,65,232,122,235,4,68,3,245,160,150,224,73,183,115,6,100,124,166,210,201,82,249,142,15,23,20,60,118,137,170,181,229,205,108,201,240,169,87,195,99,76,138,15,228,158,47,216,146,8,248,175,110,207,39,94,180,173,250,47,24,2,201,150,241,233,238,16,120,75,140,84,49,212,106,98,213,162,86,181,76,170,35,124,116,48,164,197,74,131,117,229,28,19,139,154,0,123,202,110,178,10,79,113,166,22,172,117,191,54,48,27,183,59,223,105,57,148,54,241,188,72,118,58,255,33,235,238,206,33,254,197,162,45,154,226,221,57,145,225,19,36,11,164,245,79,188,132,50,190,248,255,75,183,214,242,69,109,232,147,130,166,70,86,58,124,161,96,88,92,166,32,184,117,117,232,148,14,163,81,163,242,0,239,41,82,240,105,189,74,68,200,164,195,85,62,74,56,226,196,41,2,105,154,95,205,207,232,106,98,226,99,112,210,188,162,203,188,28,65,78,18,252,134,93,120,74,188,64,154,12,133,146,228,14,25,9,13,157,22,83,145,169,201,189,221,137,49,232,138,179,182,165,146,2,109,172,21,172,40,157,230,199,70,170,17,231,133,250,192,45,75,214,33,111,3,120,209,54,12,206,159,226,150,136,96,94,25,66,56,178,106,7,73,214,104,156,236,28,249,93,15,229,9,0,132,16,69,155,125,179,207,94,14,13,244,207,241,54,32,52,63,98,162,154,191,75,209,229,33,193,255,57,31,229,86,153,43,207,166,165,245,54,40,212,29,222,70,136,130,40,74,185,218,104,130,108,129,245,188,86,215,76,131,33,190,168,234,99,175,11,251,216,73,187,108,44,255,201,238,119,247,44,86,81,235,45,3,57,216,75,34,73,180,36,35,240,164,214,36,117,135,41,119,211,38,76,81,196,8,21,97,136,235,119,71,123,36,176,199,227,228,108,128,149,137,5,164,77,148,159,81,47,176,108,234,54,46,235,56,167,178,84,254,105,129,190,49,65,57,236,213,149,152,10,85,206,195,221,92,221,54,74,114,134,198,83,208,132,62,75,99,76,23,147,221,170,238,47,2,231,238,159,31,157,21,230,120,116,37,205,171,183,193,105,172,143,117,1,93,76,23,54,218,89,41,8,34,70,14,172,247,13,165,93,149,104,106,13,209,88,202,31,127,1,56,213,196,57,128,219,160,128,36,102,11,50,241,144,120,109,249,181,6,101,158,193,159,198,121,72,53,117,201,226,238,36,19,89,190,170,97,242,166,133,255,187,116,117,149,110,240,34,46,115,10,173,23,253,193,26,88,218,204,250,37,212,109,250,201,191,194,118,95,136,247,161,207,241,204,135,2,78,149,74,112,131,147,47,174,61,6,17,165,170,245,205,230,27,4,219,42,253,132,224,5,105,216,149,164,189,139,111,218,70,124,62,36,131,167,58,160,166,166,15,182,6,55,43,51,18,46,56,174,90,10,0,14,29,74,85,33,208,147,69,176,90,198,106,36,37,30,25,35,124,178,130,4,84,25,198,20,229,53,83,27,191,7,155,221,115,87,5,220,83,80,84,102,251,48,221,102,199,149,98,72,199,4,97,43,61,78,97,140,141,115,8,36,76,209,170,73,151,35,27,50,135,70,240,173,0,121,54,23,163,78,109,212,129,93,171,216,134,28,83,113,141,233,192,101,187,144,201,55,84,241,226,162,50,111,152,243,114,9,111,93,4,89,234,55,65,28,241,78,143,188,189,252,70,80,238,69,204,212,181,122,171,109,189,186,144,136,240,116,95,234,155,53,70,170,203,113,36,46,45,134,195,163,140,104,104,25,181,136,167,116,55,237,25,77,120,91,44,239,159,52,190,41,227,220,175,171,101,213,127,105,222,163,58,68,40,210,118,247,1,76,42,20,189,248,76,43,113,25,81,37,26,154,234,25,226,251,39,69,143,3,138,235,220,47,9,31,25,63,195,193,72,173,92,80,43,152,143,80,74,126,49,33,238,113,228,171,168,241,82,49,174,116,73,94,130,72,230,253,161,187,183,237,195,41,153,143,130,252,152,169,147,185,106,2,207,13,134,90,175,141,157,242,255,161,154,42,107,178,145,195,16,211,119,181,175,211,84,142,39,77,187,239,159,12,177,186,243,150,95,140,58,167,52,103,146,158,98,247,173,141,219,214,180,87,55,184,155,216,203,67,81,243,45,171,219,220,110,144,106,5,138,225,212,232,110,202,220,68,84,250,115,120,118,200,167,154,108,73,90,190,72,34,47,249,229,114,4,80,142,144,22,68,254,128,128,196,171,194,100,131,176,168,30,203,107,42,65,59,156,176,21,156,53,86,125,203,58,216,87,127,233,238,153,162,195,175,35,133,212,69,25,61,96,246,99,19,132,120,219,58,140,93,223,248,9,43,246,147,166,10,33,40,237,26,6,87,228,81,182,159,34,234,48,74,27,30,186,36,136,63,92,110,3,131,130,27,239,155,0,156,219,146,232,148,189,133,204,227,35,102,6,13,242,251,69,127,251,171,127,248,242,116,126,174,84,115,6,193,135,29,128,225,230,162,23,222,79,106,4,26,156,61,251,88,57,81,76,237,7,19,107,37,95,147,230,99,193,76,98,87,252,124,217,105,200,201,204,245,189,226,154,95,54,19,34,64,85,66,163,243,6,203,46,201,0,174,183,154,181,226,46,152,199,255,75,54,243,29,83,133,231,240,6,21,38,68,184,253,109,54,23,224,31,102,11,112,103,43,17,38,125,238,71,104,161,159,219,136,215,196,141,170,10,56,156,93,207,152,188,114,22,157,0,165,25,138,205,58,248,67,193,58,28,147,32,38,229,221,175,114,14,42,161,2,223,231,204,164,6,92,49,52,64,37,164,223,252,197,118,55,243,108,10,158,239,219,175,244,102,22,194,134,212,9,249,244,43,86,97,41,53,9,224,110,61,250,140,202,187,95,171,204,21,221,58,141,24,176,120,96,194,232,84,28,125,246,218,142,73,131,254,249,22,179,71,110,208,97,247,139,162,171,64,251,79,190,180,190,186,29,110,165,88,119,225,30,58,64,49,68,45,83,93,122,136,199,146,158,106,5,211,222,64,64,160,74,72,185,138,112,186,135,133,95,31,236,77,86,54,59,235,32,245,245,133,152,27,233,115,154,253,233,222,36,218,216,218,211,137,127,103,199,95,165,151,234,33,228,72,167,103,13,43,119,38,71,23,218,227,177,230,222,214,149,81,102,246,94,251,84,233,90,116,77,26,118,194,122,55,75,208,137,52,159,238,73,8,33,157,218,178,213,108,45,131,207,210,31,144,133,204,239,144,183,230,251,195,57,195,154,39,61,36,39,117,126,121,69,224,198,15,198,98,59,82,181,202,28,149,49,219,53,48,163,19,164,57,251,219,61,159,235,12,121,100,151,160,191,93,194,90,22,119,28,191,219,210,170,234,145,2,111,53,86,140,171,46,232,231,111,18,43,83,2,142,131,38,36,99,174,3,26,169,105,31,214,250,212,191,8,1,141,69,73,158,180,248,93,117,146,242,10,188,63,7,61,149,69,118,161,141,117,25,193,18,187,220,194,82,13,30,5,225,194,158,252,56,159,129,5,240,0,213,85,67,54,209,242,151,41,141,172,187,12,215,255,6,5,126,185,11,225,35,202,5,182,98,154,26,217,237,193,140,136,38,71,118,166,44,17,223,179,101,97,16,153,33,21,204,15,219,189,120,219,24,117,23,4,153,22,143,40,174,238,185,27,159,69,251,1,227,108,218,69,111,198,184,236,14,216,136,208,115,154,211,47,149,116,98,114,40,90,83,116,92,109,38,134,140,104,157,197,116,57,122,111,5,224,4,175,201,244,62,210,203,188,216,230,131,214,184,164,54,48,242,179,251,201,77,16,77,13,77,23,34,66,146,24,12,187,238,151,92,139,64,114,217,125,244,175,10,155,138,118,58,245,52,121,17,241,62,231,105,214,169,120,184,4,155,16,20,12,215,206,40,237,161,186,68,63,141,166,178,6,127,126,151,70,195,245,163,96,91,23,138,173,211,99,103,164,14,51,246,20,75,76,135,150,74,215,220,71,15,76,77,215,250,38,227,176,76,17,15,179,232,18,19,165,54,194,146,187,110,158,216,55,66,145,232,119,152,61,63,121,155,194,202,244,22,81,66,36,140,38,108,209,21,139,25,159,255,185,60,117,9,245,95,46,99,220,27,61,151,235,253,38,161,64,188,88,189,117,249,42,176,56,54,107,62,80,240,135,153,86,180,137,121,111,177,208,196,3,194,236,106,173,82,40,195,1,146,180,204,141,11,192,120,252,52,4,116,199,14,254,104,216,4,219,7,221,233,33,47,34,247,94,0,104,240,54,18,128,85,240,255,179,195,197,161,240,178,242,197,103,68,166,60,95,131,245,148,198,163,124,209,39,120,42,206,15,106,91,118,113,89,19,66,66,241,200,64,65,37,82,169,139,136,203,234,192,172,175,27,160,244,10,91,4,183,109,177,183,93,233,92,26,227,67,87,232,184,97,234,202,240,80,213,42,133,15,68,206,0,206,110,170,227,223,113,90,208,60,11,93,245,151,50,51,86,152,199,229,35,248,13,119,64,238,165,152,108,70,48,149,157,110,249,189,25,187,246,251,124,64,0,176,165,128,174,39,200,94,100,193,34,233,19,192,83,39,177,228,74,234,195,128,251,203,238,192,16,66,200,223,179,30,106,195,189,26,217,157,142,161,132,38,20,179,217,79,34,97,189,231,106,19,144,223,172,39,206,91,192,115,254,111,141,170,103,121,61,72,101,60,110,173,73,193,25,89,206,122,137,151,213,60,169,7,42,226,224,249,190,43,17,190,187,240,163,77,26,192,162,70,170,154,216,20,183,212,229,81,56,157,247,123,219,168,91,21,53,107,174,135,98,32,176,146,78,98,190,30,232,190,171,107,188,254,223,5,25,58,134,150,36,28,218,134,107,40,253,245,199,11,1,191,26,173,238,5,142,204,170,161,157,127,172,254,27,185,235,87,15,3,74,170,36,195,132,163,3,126,33,178,173,141,106,23,111,96,111,124,164,68,230,2,210,18,190,148,45,70,148,194,38,160,67,130,166,172,81,5,91,142,239,190,58,3,102,81,212,68,68,73,134,6,117,116,100,47,57,100,207,232,224,125,32,30,193,162,117,36,57,8,27,203,56,199,110,251,56,35,162,240,157,224,0,42,206,199,201,33,95,5,127,132,29,178,152,101,166,1,242,99,155,248,47,71,180,75,84,99,65,91,32,31,136,206,52,48,74,184,208,83,85,179,51,105,125,87,66,145,207,127,71,239,255,157,126,120,139,232,35,64,70,128,118,191,41,217,7,185,86,117,216,187,163,194,206,174,218,56,214,58,160,248,111,154,70,17,108,212,91,199,245,32,108,125,43,198,192,38,68,101,100,147,129,87,52,240,50,91,92,218,108,127,101,155,228,123,77,147,41,86,207,159,139,140,93,22,169,163,63,89,236,154,98,131,93,39,55,237,122,107,6,174,184,202,126,27,199,141,16,52,167,250,44,52,64,134,244,66,235,39,127,190,88,127,61,105,107,157,35,59,146,10,14,155,241,227,170,104,180,47,95,20,235,236,196,100,29,66,255,252,236,249,128,214,5,234,40,241,34,234,45,47,166,217,121,36,243,35,251,23,126,3,133,136,164,113,22,69,236,180,239,139,48,255,146,161,48,135,129,150,245,193,181,210,85,120,4,249,147,174,66,17,136,154,208,148,214,82,198,29,171,4,223,212,84,104,93,95,153,151,59,52,212,150,113,85,179,189,60,151,118,28,93,220,49,114,124,228,164,99,165,40,1,5,200,121,138,132,77,15,5,21,162,216,252,37,141,224,202,125,209,225,242,62,177,195,93,254,238,77,226,148,168,119,167,195,151,180,25,60,215,48,166,94,44,45,114,159,78,24,155,132,119,38,31,231,227,51,37,35,33,239,40,171,12,250,68,190,248,231,228,59,213,61,15,65,53,179,92,176,23,172,176,32,72,135,37,241,24,107,242,184,186,57,99,239,241,14,0,114,211,202,79,176,88,52,130,56,18,75,55,22,208,79,100,1,57,105,53,174,100,13,234,232,158,118,211,9,144,128,160,76,177,166,10,90,95,110,144,254,243,190,208,135,184,198,226,200,27,9,38,241,0,208,210,237,180,2,22,149,157,19,155,249,21,3,55,195,149,105,206,24,110,148,19,249,58,78,186,176,25,100,216,4,198,194,104,71,150,103,193,54,223,28,146,80,51,157,194,14,178,180,189,161,192,44,225,168,111,47,225,151,43,100,26,191,125,146,222,221,199,216,186,126,173,89,90,229,77,60,34,228,75,219,182,85,232,170,22,24,130,197,101,20,253,116,141,176,241,34,223,208,190,53,49,201,93,144,151,241,108,236,120,86,232,128,234,238,83,111,80,172,96,67,34,128,6,29,10,136,122,7,204,83,50,186,1,23,79,169,21,92,114,15,132,236,51,188,123,139,240,236,199,67,208,132,52,13,194,187,174,29,120,140,151,198,252,88,147,102,219,35,162,73,126,98,77,213,8,169,217,193,210,100,239,19,153,49,43,252,194,75,228,65,143,184,39,77,42,202,171,40,113,137,164,157,33,120,131,63,197,218,5,250,238,192,175,128,92,206,161,173,254,238,133,100,158,136,16,101,127,238,52,208,92,82,3,217,66,93,246,228,193,254,74,72,78,122,33,105,54,8,66,93,246,194,222,27,194,33,125,31,125,186,243,13,92,218,44,36,132,226,180,89,124,205,104,135,159,122,252,15,162,223,62,10,250,171,0,131,127,85,178,231,79,207,40,253,46,196,118,242,128,72,35,191,117,82,21,59,50,253,123,77,220,143,104,20,203,224,176,13,252,32,28,67,43,91,75,244,94,186,135,19,180,199,223,127,142,98,37,239,28,103,87,65,235,18,238,103,120,238,30,86,59,98,172,2,220,161,99,43,3,209,122,161,55,146,255,1,36,249,99,184,3,3,168,72,232,46,73,223,106,79,159,210,38,156,147,51,126,50,165,108,52,49,96,42,238,80,99,70,146,206,224,54,97,97,16,213,14,248,251,126,49,66,87,134,179,227,232,143,91,185,125,0,158,183,5,242,48,7,152,160,171,198,163,34,181,199,170,68,125,93,97,109,136,230,150,33,113,56,104,7,226,175,49,100,51,84,213,22,135,7,237,200,148,72,116,142,163,153,122,86,4,164,15,210,118,24,67,210,223,220,137,144,48,144,180,185,234,2,241,154,213,43,109,156,143,172,26,128,135,231,119,24,217,131,61,148,77,141,150,92,115,120,2,154,217,75,86,241,208,171,108,103,82,89,209,129,238,172,132,255,207,27,146,164,74,184,68,92,141,13,124,214,138,185,244,149,236,189,182,103,67,87,10,32,216,220,143,80,210,206,245,104,149,139,20,55,5,113,172,207,125,29,89,249,19,112,108,14,88,182,201,165,18,10,245,121,6,178,148,34,12,59,196,61,173,239,178,241,33,155,25,242,134,32,227,233,188,135,113,163,52,64,251,178,224,118,246,79,167,5,63,212,177,112,180,80,242,169,49,210,21,134,141,17,157,190,91,64,227,91,38,133,159,225,105,247,226,195,200,172,31,220,215,170,68,107,20,234,183,178,143,56,158,107,86,223,172,215,193,84,10,65,89,99,158,61,203,224,96,108,213,54,164,149,13,125,118,120,95,189,114,57,41,211,241,237,209,190,6,62,79,184,242,245,149,195,91,85,198,131,178,227,71,202,112,154,51,82,29,130,223,121,113,6,199,251,129,30,201,68,187,181,197,35,52,79,104,12,235,40,127,72,62,197,101,25,50,235,135,22,61,18,204,9,17,58,139,193,112,118,161,34,157,65,113,190,135,176,140,117,20,216,176,111,50,116,217,162,214,180,80,45,31,21,53,93,2,228,123,100,207,17,230,207,97,240,183,85,31,41,46,45,3,43,72,155,187,165,203,128,67,28,120,236,54,20,65,238,109,110,179,222,136,198,17,77,149,130,251,103,177,204,150,184,189,37,5,55,241,217,14,130,255,116,126,175,235,144,116,140,66,14,51,205,67,99,220,51,208,79,206,154,127,22,85,71,77,215,145,255,44,243,64,209,227,67,73,110,151,218,87,197,55,237,118,245,39,169,244,170,245,203,108,245,142,50,189,176,80,21,202,93,146,1,53,148,177,158,56,213,31,235,149,163,76,7,160,96,185,175,209,247,27,135,158,217,147,16,10,240,197,137,20,206,239,82,56,27,22,220,198,2,89,79,127,31,142,1,6,55,182,200,142,137,107,201,174,111,181,210,207,62,30,104,243,208,79,121,233,86,23,51,192,246,38,237,63,185,68,166,75,123,229,116,251,234,207,59,122,231,68,113,211,62,70,25,143,151,209,232,208,160,147,131,216,54,242,90,239,63,40,144,174,63,16,36,202,26,114,183,89,217,89,136,230,91,48,252,125,202,164,150,89,145,56,123,247,12,54,155,187,186,61,40,196,208,28,136,119,101,36,210,226,52,175,235,200,109,39,72,109,208,243,138,191,212,112,241,255,140,84,135,41,149,18,74,71,117,169,225,47,36,251,47,104,143,61,234,88,50,148,255,119,218,157,33,205,193,198,233,229,11,62,162,92,119,220,137,255,123,184,226,35,157,8,174,39,63,216,248,137,225,131,8,2,82,204,80,214,39,91,209,189,161,6,81,144,36,198,76,197,109,194,10,4,72,54,53,184,115,91,225,10,11,168,200,46,218,124,246,135,15,89,53,166,8,241,71,83,123,154,209,50,174,37,55,123,83,140,20,54,44,56,182,163,26,6,6,190,38,53,147,232,222,149,68,107,255,157,252,151,137,92,252,145,148,33,103,9,72,231,13,116,195,38,2,23,236,159,143,19,6,218,213,124,179,244,182,30,110,173,19,168,90,131,57,252,205,106,250,34,115,21,156,227,2,178,233,51,164,166,165,72,112,14,41,93,38,111,111,37,191,106,207,33,185,185,90,72,233,134,236,98,171,160,112,169,40,190,94,93,171,234,98,137,93,127,65,248,80,186,131,116,191,197,63,31,50,255,195,58,34,142,54,220,246,198,63,55,183,44,126,0,217,209,232,158,8,7,110,86,107,240,61,28,52,138,97,149,20,247,180,192,143,33,83,155,177,22,187,216,48,139,83,169,139,99,123,154,74,125,236,38,59,46,27,30,157,211,15,232,203,47,94,136,56,194,51,139,205,174,21,161,217,7,160,227,59,236,156,91,143,154,27,42,117,22,168,18,246,201,35,37,107,157,58,5,158,76,100,112,62,84,117,50,22,6,96,111,120,207,116,151,161,13,67,239,116,206,98,64,136,103,8,201,197,9,81,239,18,226,93,190,46,81,229,232,167,200,193,215,90,182,212,93,78,67,26,105,97,197,49,164,150,52,143,248,121,13,95,217,227,206,14,80,200,179,171,10,146,200,142,90,137,125,253,146,71,131,33,45,48,69,241,119,153,254,188,241,25,222,97,30,63,46,136,159,57,134,89,0,129,234,189,184,64,200,208,245,48,167,116,134,99,230,3,164,217,19,159,106,99,97,202,22,164,70,66,13,97,32,58,239,114,37,9,60,59,67,157,37,172,251,50,177,13,116,63,7,119,74,90,248,108,175,187,95,134,112,101,157,132,160,143,70,245,232,144,69,184,106,150,9,184,122,224,32,162,162,167,166,203,10,237,99,78,75,217,159,250,237,184,75,97,163,68,55,215,93,14,236,225,12,141,49,8,40,126,117,77,135,80,77,205,97,75,21,26,145,221,123,172,2,182,77,86,93,204,86,114,144,92,13,141,25,97,222,15,100,182,160,159,142,35,220,49,107,187,208,137,105,153,135,0,174,222,172,239,170,133,207,178,208,164,230,211,2,139,92,32,192,133,89,232,32,239,245,110,166,136,37,21,196,131,79,242,98,209,25,180,252,102,119,100,85,102,115,189,106,122,226,157,178,221,143,154,92,187,57,68,241,18,33,225,250,134,114,116,72,134,250,27,40,97,219,30,86,74,184,102,193,26,66,181,24,165,153,255,190,75,185,18,121,114,85,220,59,224,145,174,176,36,67,144,74,196,161,88,9,48,79,220,4,67,25,232,105,176,32,242,28,201,66,116,178,36,164,218,208,31,240,68,239,166,138,242,198,226,27,136,232,255,174,210,152,60,200,61,15,238,2,218,231,198,130,236,180,235,65,221,66,82,162,92,235,251,20,38,65,92,156,106,85,0,144,25,182,28,226,88,153,34,253,19,27,116,90,101,248,35,202,216,184,19,35,2,94,8,209,254,66,212,135,68,219,185,32,107,225,25,227,136,211,138,181,174,112,128,190,66,165,251,135,185,108,40,159,222,177,26,58,26,148,218,89,13,15,27,236,24,118,78,33,185,174,168,219,230,119,230,179,169,161,57,118,97,227,203,9,125,55,136,197,112,94,138,136,230,112,204,245,136,116,59,13,75,68,121,43,122,9,22,252,149,172,182,118,113,61,53,171,44,42,118,178,166,69,222,44,157,34,128,126,179,24,154,159,106,149,17,227,58,143,176,241,222,56,42,62,181,26,208,33,24,30,33,112,83,127,84,65,41,251,206,115,178,2,222,106,153,209,238,98,208,200,210,177,133,86,65,23,104,110,177,161,96,79,57,142,162,15,207,173,153,56,254,250,73,76,74,43,36,200,57,145,60,95,227,21,147,221,41,171,192,107,234,251,74,126,3,247,128,122,243,153,128,202,238,189,17,198,179,70,97,245,190,200,231,176,186,98,217,254,45,230,228,185,78,204,155,64,247,183,255,152,161,26,12,21,183,209,199,194,177,1,221,95,77,76,253,203,104,7,192,167,209,180,50,138,227,189,182,231,239,238,168,59,221,119,154,107,247,102,200,51,40,120,192,133,47,249,238,189,123,233,117,188,210,82,68,72,178,111,103,77,144,205,181,97,1,172,166,152,242,0,187,181,174,188,39,82,5,75,21,213,113,66,102,62,173,169,132,21,120,138,226,211,39,44,143,160,126,74,108,191,13,117,58,148,234,239,194,161,161,156,231,240,170,77,120,106,63,168,175,231,243,60,192,181,236,20,52,239,78,141,78,130,59,219,80,208,24,37,165,109,209,49,251,9,62,80,50,249,181,232,42,228,47,166,191,144,176,206,148,242,148,153,182,121,24,128,65,137,42,161,119,66,94,240,11,55,102,122,7,205,142,144,144,180,47,60,218,192,149,85,15,213,83,8,79,215,104,8,209,172,222,200,242,28,255,51,185,167,33,226,26,65,147,100,114,222,54,27,170,212,207,83,56,170,37,126,121,14,18,40,231,4,14,164,248,6,110,118,48,51,83,228,76,3,131,87,77,86,163,48,72,194,109,53,105,118,111,198,140,133,34,20,119,56,35,236,7,170,176,164,95,86,183,232,105,108,7,25,169,127,50,26,86,83,94,101,58,219,72,205,46,231,78,158,94,221,190,147,92,96,224,0,30,65,191,21,237,118,106,224,247,161,116,33,41,10,92,81,248,232,191,41,72,116,171,89,110,208,62,230,196,11,67,172,81,188,8,212,62,255,199,22,201,68,20,120,21,90,72,70,211,251,61,232,5,238,147,16,91,225,65,103,178,238,63,246,157,100,192,170,206,249,101,28,25,120,125,225,94,105,146,218,75,10,178,103,244,73,77,174,18,113,205,198,233,5,88,129,66,64,72,137,118,81,217,130,206,156,174,224,223,115,249,164,10,160,47,237,255,135,146,236,13,99,71,63,62,20,134,132,135,155,27,21,239,159,60,195,224,248,123,205,45,147,225,233,72,95,151,236,249,144,43,148,51,197,175,100,140,185,170,200,234,37,87,113,85,41,197,41,164,33,181,64,228,58,125,41,220,43,111,47,37,139,69,75,126,166,210,12,7,175,6,63,122,236,237,156,149,142,254,174,11,37,215,82,200,54,62,74,43,2,249,172,218,115,203,91,14,165,110,103,178,200,5,226,141,45,42,68,130,198,173,253,230,217,122,113,39,163,182,160,231,100,179,40,207,8,27,212,22,174,85,58,27,55,118,83,118,244,201,68,167,205,50,31,36,17,250,228,187,200,203,159,109,44,83,197,240,214,82,128,207,62,237,127,108,238,226,36,190,44,152,27,248,90,79,254,43,191,182,206,138,179,239,133,27,56,192,25,166,40,83,172,241,62,178,172,53,58,205,73,6,139,66,50,24,22,193,232,205,173,161,67,139,236,13,114,239,156,46,253,12,218,238,6,255,169,98,117,8,215,156,102,178,212,208,18,175,147,108,96,73,71,115,87,75,254,77,61,212,49,252,42,72,23,95,49,206,208,189,203,240,139,4,56,101,109,139,204,117,23,213,104,47,1,254,115,179,25,96,58,221,157,53,112,19,110,172,118,168,11,21,171,109,123,100,79,124,202,172,155,236,144,86,224,44,183,119,167,51,180,139,191,76,201,173,212,215,120,148,255,149,110,69,229,152,112,197,133,178,122,15,23,55,103,67,13,152,239,59,168,53,175,130,232,143,236,0,96,95,206,91,141,167,127,199,149,82,51,222,51,43,148,225,183,56,32,68,76,97,35,154,233,207,47,2,29,114,143,36,159,81,168,169,22,163,74,208,233,149,204,129,138,138,13,48,180,42,41,155,141,156,228,19,71,135,137,63,119,146,67,61,236,133,52,209,164,39,67,110,28,5,36,100,159,52,79,220,118,89,126,230,63,180,117,243,165,179,147,209,255,162,97,177,43,45,86,56,48,223,195,122,39,130,118,8,183,36,55,42,221,83,72,74,95,130,91,23,121,226,221,206,241,204,44,105,177,188,105,190,84,106,225,244,183,44,76,188,169,150,98,155,208,244,161,94,75,232,173,64,126,153,184,124,75,229,87,31,209,154,93,125,64,53,167,155,250,167,122,169,184,231,14,34,61,208,47,179,182,194,37,87,240,10,125,2,26,125,232,189,207,199,3,153,204,157,148,33,93,160,134,67,238,203,126,198,203,210,112,25,199,23,136,192,135,207,227,224,213,125,17,93,230,177,178,164,152,162,80,107,50,52,221,42,20,128,143,202,168,22,91,223,159,118,214,249,29,184,124,24,124,1,183,54,43,61,91,155,116,241,94,157,187,60,100,244,97,97,177,9,57,90,72,245,38,31,86,172,41,102,15,35,39,4,233,141,9,165,41,137,229,44,122,16,181,99,178,84,124,207,34,140,41,145,250,172,186,100,100,156,162,5,126,187,160,57,183,240,17,46,181,44,120,144,141,151,142,129,195,192,11,203,241,78,134,142,214,106,198,94,141,84,62,51,127,110,9,65,150,68,221,157,131,236,130,114,10,128,197,13,157,252,8,165,223,138,108,179,156,231,156,82,132,196,202,13,64,69,92,110,180,238,15,125,240,30,231,134,56,66,31,193,191,100,72,106,233,11,113,8,121,238,178,117,107,157,215,58,43,212,236,53,215,214,1,16,192,173,175,231,62,113,26,94,248,47,30,36,232,160,227,75,161,127,33,5,192,210,69,155,249,190,217,224,42,17,77,54,231,20,45,5,116,154,154,80,74,148,126,85,137,13,59,123,226,167,20,148,24,19,123,17,78,46,126,232,255,147,20,83,85,103,16,86,141,246,211,162,58,245,162,77,31,51,40,174,164,117,38,201,18,8,240,124,226,180,213,190,92,223,249,184,227,8,168,86,142,19,66,247,142,54,135,218,13,197,216,225,152,61,155,156,171,88,150,158,129,132,144,138,13,21,166,17,156,62,40,147,131,134,66,228,77,177,184,53,207,92,208,3,16,2,45,215,154,73,196,92,47,104,0,94,23,103,132,206,81,105,63,84,231,7,205,95,148,128,250,142,158,42,49,223,26,22,72,27,211,39,245,201,245,4,127,48,221,21,121,201,223,108,209,6,93,31,85,112,207,74,123,201,78,249,139,38,60,134,47,225,21,74,31,177,146,41,144,16,100,28,219,207,21,104,154,200,135,169,238,147,227,243,217,211,187,109,182,74,223,148,201,132,46,26,159,121,196,145,148,161,153,126,127,103,44,44,215,135,248,8,157,23,184,220,82,173,81,229,136,173,243,230,69,68,158,137,156,73,166,209,116,155,166,231,141,186,187,84,175,227,63,227,13,18,245,222,185,2,9,97,179,58,174,246,67,94,255,153,44,100,138,172,19,5,67,221,82,20,224,61,104,222,44,53,106,82,147,130,225,31,218,140,64,109,45,5,216,165,119,100,159,228,18,213,150,192,59,85,135,249,36,228,230,57,28,67,206,105,230,148,212,28,106,92,97,2,31,152,107,208,11,10,205,238,102,126,66,83,190,233,77,232,77,96,85,249,251,119,192,179,5,0,198,67,127,22,157,78,146,64,204,6,39,200,12,229,227,234,242,193,195,141,125,107,248,143,210,251,18,220,67,240,110,48,114,110,15,160,241,14,133,152,132,225,44,134,92,88,11,167,164,225,12,234,164,92,9,175,74,190,164,193,157,232,4,137,216,80,165,124,20,254,221,2,198,63,217,156,135,119,4,178,58,153,215,139,67,52,172,206,47,40,75,33,86,67,63,41,10,20,37,237,37,156,4,13,25,23,201,228,9,237,67,16,22,116,17,184,162,203,188,227,13,110,65,231,79,200,61,118,207,68,161,90,71,47,113,31,224,165,90,23,21,239,63,80,176,54,103,99,60,125,72,207,90,110,231,121,225,205,35,28,16,137,252,136,94,179,14,97,157,227,66,82,219,137,26,78,157,181,147,28,161,251,43,196,201,53,245,149,152,194,86,91,70,203,91,114,199,241,212,180,125,44,131,135,116,26,132,69,27,84,222,132,88,96,163,119,62,129,249,230,33,147,28,124,23,172,231,132,144,182,235,125,193,70,233,206,77,27,210,203,223,213,95,105,230,117,205,214,164,126,23,240,10,34,237,211,43,162,138,230,118,192,86,247,125,167,215,62,26,113,209,175,19,231,246,167,150,22,44,69,31,236,205,198,210,214,123,93,60,9,175,131,96,145,71,92,190,209,201,225,103,43,204,242,98,253,129,95,56,223,107,29,87,165,180,44,49,28,37,42,83,215,122,91,126,77,38,243,71,213,191,223,14,76,247,97,110,190,120,147,167,234,237,10,98,148,45,218,3,23,117,15,148,142,173,118,236,90,31,27,85,54,188,202,253,43,102,109,130,17,8,239,241,89,212,14,29,172,179,90,8,104,5,203,117,188,43,184,167,54,8,100,136,17,55,201,102,193,221,245,173,86,65,162,176,40,92,214,101,18,82,59,131,63,156,187,219,65,190,115,172,242,52,181,80,109,165,136,98,148,149,152,234,86,143,132,100,239,159,119,163,250,30,130,119,190,45,58,208,104,161,144,10,202,200,31,177,215,242,236,78,3,151,34,8,16,172,231,112,71,159,168,32,208,230,50,84,234,214,40,92,65,60,148,117,76,216,111,91,121,177,66,86,123,55,54,126,46,118,241,103,105,245,89,242,0,0,166,87,7,145,164,227,90,30,10,4,88,64,114,70,127,14,161,218,198,16,35,230,115,54,65,108,190,175,186,252,79,33,24,82,118,130,249,181,253,61,28,154,77,227,209,111,63,61,68,223,162,41,90,176,37,114,169,199,77,160,219,199,22,79,240,212,158,243,217,226,74,158,215,193,166,204,82,135,0,106,12,155,150,113,241,197,33,205,6,16,19,118,164,194,115,243,112,162,251,134,203,122,124,61,242,68,140,200,131,168,172,123,48,70,132,227,199,3,196,130,48,55,231,64,216,195,86,36,160,233,137,145,108,224,93,218,61,107,191,138,171,13,215,212,65,223,117,85,120,109,207,141,12,23,221,175,68,130,129,185,138,67,225,85,127,85,215,75,146,79,69,133,10,129,210,51,71,147,116,11,104,76,194,87,78,137,12,108,185,53,10,210,35,135,33,203,224,96,175,47,98,138,83,60,163,16,100,51,21,186,245,7,153,128,164,73,27,189,195,13,61,255,96,12,174,169,37,39,235,177,224,137,71,128,240,63,137,238,255,68,185,212,135,190,156,240,184,158,113,210,241,119,224,63,177,236,63,172,135,117,74,27,187,227,253,246,222,134,197,251,197,243,107,188,160,85,252,111,4,141,195,243,91,73,226,144,131,109,136,10,172,209,186,95,172,96,107,43,22,44,176,226,122,100,50,28,65,163,62,235,88,16,254,97,48,250,64,155,101,21,83,64,255,189,98,142,60,20,184,3,54,87,20,50,178,254,138,105,53,169,141,5,88,57,244,207,138,191,208,185,54,87,134,70,182,197,77,248,201,118,133,148,231,106,241,215,91,61,184,61,250,9,140,91,66,203,141,93,171,166,65,183,29,234,196,85,230,194,177,148,240,126,71,14,92,212,2,120,179,141,11,42,166,15,45,196,187,30,249,247,104,244,5,25,126,208,252,253,157,224,36,138,145,222,221,213,15,204,112,217,50,193,215,194,2,248,214,48,43,229,7,204,79,218,223,82,137,114,228,41,220,68,157,35,245,242,213,255,141,189,192,243,63,72,119,222,107,252,230,192,211,47,186,209,144,213,221,185,22,152,208,54,130,76,100,242,54,210,211,40,29,189,40,7,183,252,209,130,240,76,107,14,110,35,151,57,0,187,180,78,210,153,198,18,212,33,205,72,211,89,150,175,136,7,138,13,18,93,226,93,52,171,126,188,165,113,29,15,231,234,11,67,54,164,115,158,58,48,20,202,65,198,247,224,202,190,45,10,153,146,148,150,218,67,157,27,190,197,15,182,135,56,130,43,203,209,174,134,100,81,179,58,182,229,1,155,224,135,148,214,99,38,92,212,220,49,17,170,248,161,123,88,92,5,119,19,210,149,12,254,121,21,140,38,10,247,25,4,22,186,68,1,211,221,109,182,103,137,4,242,129,66,67,138,61,50,131,83,208,81,53,132,36,86,63,33,62,142,250,210,195,68,246,210,84,77,150,182,48,140,129,1,24,195,122,107,160,22,129,227,250,27,102,21,127,52,229,47,19,58,21,47,132,85,233,11,183,119,3,54,223,94,30,168,153,3,202,62,170,29,46,235,105,186,122,192,71,128,73,149,47,98,46,122,34,64,101,76,177,160,154,47,174,96,118,108,73,203,121,15,19,101,72,99,177,70,118,219,124,182,128,41,154,76,22,204,166,120,224,174,35,27,29,63,8,248,217,183,247,192,11,141,178,28,4,184,73,111,64,221,65,220,21,145,34,163,79,94,28,225,40,146,182,182,2,244,18,250,136,64,65,3,121,52,149,19,150,105,221,244,244,247,77,249,155,100,216,128,178,170,122,153,140,221,2,88,211,227,255,108,191,91,6,185,100,148,31,75,245,179,229,46,107,30,214,20,93,198,142,86,108,83,131,235,38,107,38,203,229,248,160,22,216,41,215,22,55,59,211,156,38,76,79,202,176,49,88,161,162,206,46,81,83,200,99,138,117,40,110,2,84,142,165,212,63,185,183,35,165,96,218,110,177,40,36,21,19,181,76,171,145,175,144,249,115,42,97,99,152,49,128,122,54,8,136,236,196,46,137,181,211,218,83,112,177,64,193,136,89,220,176,221,204,172,174,154,77,96,166,191,132,59,141,90,169,6,46,45,84,193,160,209,49,6,199,255,3,129,73,146,92,31,226,30,164,12,7,148,241,217,3,113,226,199,81,146,95,141,45,176,205,253,233,128,78,74,123,244,138,154,234,99,11,241,18,251,174,123,196,122,254,82,210,2,90,216,87,97,38,253,160,197,255,134,152,168,162,17,72,133,41,122,235,85,154,133,172,162,240,103,107,149,216,192,182,55,27,163,94,52,129,61,154,61,11,135,223,222,154,217,53,135,124,181,120,2,41,107,239,28,32,232,45,27,51,86,176,14,7,40,249,170,100,67,101,131,23,151,200,74,151,82,184,146,40,7,64,240,146,253,80,218,150,108,16,186,224,225,98,8,166,177,252,0,35,95,107,137,80,130,116,129,161,149,37,52,149,240,167,11,50,129,134,80,126,16,233,201,206,97,186,68,205,245,254,241,139,20,5,89,162,39,98,188,107,186,119,233,101,250,245,150,241,120,191,39,29,12,121,31,198,242,252,230,85,160,112,172,171,128,29,103,65,246,39,126,74,92,140,142,56,181,82,101,195,59,71,4,8,9,42,98,180,136,41,26,56,252,4,230,102,239,251,161,183,106,22,54,238,250,59,61,243,9,189,77,195,254,119,234,124,186,211,5,26,88,176,159,87,101,242,100,179,102,218,39,85,82,118,109,146,144,225,73,28,78,77,189,135,29,192,12,95,153,113,248,50,171,113,241,189,121,194,155,247,109,70,124,72,61,27,79,56,185,218,51,155,130,98,183,1,100,60,85,55,160,158,110,41,58,63,216,176,49,228,195,87,118,254,105,223,41,138,84,41,78,214,111,49,206,175,91,190,57,25,68,120,22,127,85,81,202,226,197,123,156,169,249,12,182,148,31,115,211,146,41,208,248,249,197,188,103,47,138,8,117,43,130,28,28,102,44,149,38,221,176,211,11,76,148,186,176,252,87,62,69,3,88,80,123,168,196,245,128,224,186,224,99,220,46,237,181,88,159,161,175,204,237,160,154,13,131,12,99,88,171,231,111,242,238,194,193,15,3,254,152,148,114,131,215,216,106,245,73,197,176,147,149,25,185,200,252,52,225,236,86,240,34,22,76,102,243,132,148,11,204,125,58,185,37,184,188,4,169,89,249,104,232,254,3,96,102,68,177,242,8,251,188,177,100,48,1,248,177,185,181,108,161,130,117,35,229,28,94,131,105,31,242,158,200,167,63,124,21,55,142,139,10,202,5,82,209,8,37,48,22,47,237,174,182,254,11,32,46,255,142,78,113,207,192,187,172,174,16,156,90,26,138,142,57,129,2,59,148,175,197,194,242,205,81,57,214,199,206,60,204,225,254,113,28,148,222,242,209,101,104,98,108,237,223,49,114,212,129,78,146,78,208,40,162,230,188,127,198,195,47,15,146,82,173,159,186,217,133,148,237,194,5,33,102,245,90,65,8,165,35,12,231,205,62,97,232,36,7,127,30,119,233,149,99,221,178,173,102,226,168,250,196,60,181,5,125,126,243,158,64,110,37,30,195,162,229,136,241,198,229,105,88,85,49,14,96,84,216,55,253,53,92,172,24,38,54,35,37,50,118,149,84,244,199,203,56,87,218,44,100,7,25,135,147,55,101,115,200,99,37,8,239,72,221,30,76,8,86,146,55,44,91,241,31,111,230,90,185,168,144,245,50,43,46,238,33,229,223,34,244,14,118,219,103,141,110,249,21,49,255,202,251,214,126,66,144,34,95,94,195,240,131,109,100,123,73,158,69,82,217,206,59,169,190,31,185,211,83,88,73,74,185,229,228,147,57,21,198,39,234,143,84,167,170,144,247,206,56,43,55,104,193,157,220,89,125,173,151,17,4,10,18,124,244,41,133,194,59,11,202,98,174,212,26,19,95,71,26,82,242,133,85,125,4,131,36,108,37,250,255,99,63,15,53,173,129,255,175,83,105,132,142,35,4,243,133,67,237,220,88,25,169,219,83,229,33,83,46,251,0,111,226,87,41,226,98,245,208,93,251,94,207,210,41,146,56,119,137,32,0,61,212,6,161,219,144,112,202,88,124,132,83,197,240,185,196,152,34,202,136,59,198,165,5,136,11,246,158,60,3,176,105,203,207,70,162,187,45,160,39,60,82,115,113,239,37,166,188,235,215,222,227,65,73,188,70,178,98,215,247,7,12,10,4,216,139,202,178,125,231,103,79,61,127,58,10,202,75,42,107,139,214,172,4,14,3,23,73,247,52,158,78,61,218,235,79,191,182,70,127,157,34,208,242,177,248,153,110,42,50,168,186,212,159,202,174,245,161,60,197,47,221,200,111,195,231,35,136,145,196,62,119,52,247,41,50,41,64,94,231,136,149,213,174,127,157,61,143,47,166,152,59,245,186,16,70,32,201,49,239,157,90,225,122,138,88,158,93,59,121,246,69,151,25,182,189,199,100,74,131,123,99,103,185,138,240,169,255,83,8,240,13,159,156,5,223,181,247,243,244,179,90,207,159,36,69,34,174,29,39,12,198,108,220,130,2,10,203,188,206,67,116,209,27,67,170,198,93,113,250,14,198,254,196,37,146,198,0,245,162,19,196,105,30,136,94,211,48,61,213,53,160,236,102,140,240,236,1,246,124,73,73,184,88,243,157,125,154,77,39,104,111,1,205,78,22,233,44,37,253,92,198,51,8,211,150,43,192,106,122,208,21,123,140,14,148,222,144,217,194,15,242,120,80,45,66,71,74,147,132,37,185,45,165,41,76,166,143,130,134,3,4,15,104,214,102,179,162,238,195,200,235,20,223,172,249,110,37,43,216,136,128,232,235,48,215,2,250,173,82,109,146,30,125,217,231,73,206,65,2,40,45,35,163,248,230,102,19,67,102,0,76,64,7,130,23,167,105,28,152,26,73,234,15,36,35,231,146,205,50,217,164,199,154,192,15,19,80,26,30,181,14,197,12,131,88,61,140,86,85,233,182,210,78,143,77,63,177,30,176,10,224,14,137,130,162,84,191,108,227,75,85,115,237,159,119,222,168,131,18,13,22,92,110,176,134,71,180,31,116,154,111,4,116,74,59,2,191,75,114,181,184,238,106,236,202,251,63,247,48,35,155,172,61,122,174,26,38,3,176,42,15,71,195,153,55,66,191,33,169,177,220,36,95,177,66,86,173,31,180,219,166,178,139,120,139,67,88,25,238,233,169,169,111,163,217,54,29,44,34,138,236,199,35,50,82,214,30,125,91,25,222,65,137,125,96,232,78,167,209,68,71,70,1,22,163,34,202,200,71,113,235,157,41,14,32,110,171,235,197,174,10,51,158,251,44,98,199,201,196,168,50,201,99,205,245,153,75,169,17,143,154,52,222,138,28,173,86,92,134,115,136,220,131,85,171,122,218,117,190,117,143,79,26,121,10,50,45,80,241,33,4,253,140,1,159,201,105,123,35,133,81,59,236,16,238,109,215,10,124,211,64,112,180,147,203,106,142,69,97,205,162,177,217,151,174,189,239,69,50,30,166,238,219,120,79,225,197,121,127,91,215,89,102,17,39,158,213,94,164,254,49,125,216,191,222,90,38,224,214,242,60,2,38,241,139,218,34,185,186,30,206,33,43,38,242,81,191,12,1,200,96,167,125,197,194,127,129,244,184,30,74,74,196,174,229,224,226,124,52,137,122,146,108,187,169,127,72,111,131,243,79,149,236,134,103,137,212,161,44,61,183,188,103,150,96,95,88,187,167,31,213,185,63,128,70,10,58,47,69,155,112,231,242,129,19,78,116,74,152,85,44,128,199,241,148,56,48,27,194,180,191,35,170,227,179,166,110,172,88,208,185,53,153,120,109,155,216,205,172,159,59,191,94,49,209,213,90,125,246,132,153,163,89,50,28,91,141,185,11,4,229,210,18,79,36,117,191,90,231,97,92,89,193,98,201,7,9,252,3,100,157,87,134,164,29,218,54,7,117,232,97,226,74,185,43,135,78,199,151,206,137,157,244,201,49,137,164,23,115,134,121,92,128,224,192,100,154,252,124,146,17,129,44,130,237,65,159,194,35,88,56,132,29,163,200,91,112,118,35,100,76,112,87,180,233,171,69,124,62,161,232,54,66,129,248,193,47,232,197,143,236,112,36,132,61,97,179,231,60,124,4,220,161,114,16,84,196,143,200,58,98,2,255,8,3,222,42,146,204,234,68,199,78,202,173,32,215,30,242,64,32,250,49,111,31,174,191,209,40,51,55,101,12,137,212,116,140,72,132,52,104,204,245,218,122,29,236,175,188,112,137,112,129,225,22,84,118,55,75,104,13,207,51,243,102,148,120,49,86,192,53,173,30,143,161,0,187,160,141,185,32,104,37,221,242,44,29,27,162,135,12,4,205,239,98,8,217,237,81,207,29,240,169,209,6,80,56,120,99,193,90,244,235,14,45,162,130,224,62,152,96,147,9,238,188,49,82,151,207,8,240,126,39,228,192,121,199,227,52,238,238,69,130,134,174,90,34,126,176,133,63,234,79,219,126,186,224,106,183,242,244,90,180,161,17,110,155,66,109,222,205,83,121,103,49,85,234,220,198,98,67,0,50,194,21,182,193,118,19,220,4,173,96,221,203,40,186,232,98,162,37,12,169,225,26,229,12,71,121,194,162,100,159,139,30,0,151,86,14,131,219,129,154,212,170,79,126,26,171,90,92,239,0,106,79,97,213,183,128,12,238,216,30,67,114,73,64,191,22,179,225,12,252,220,234,87,55,51,145,66,34,63,168,252,148,87,47,176,54,228,85,152,226,61,198,41,76,94,182,131,134,142,127,97,14,232,78,147,107,91,23,55,184,220,0,132,128,230,214,41,253,146,45,59,69,244,78,228,127,47,234,235,212,197,152,203,251,16,167,93,153,46,245,207,238,82,246,96,131,4,123,250,67,9,15,63,198,214,205,18,51,223,238,190,104,69,185,188,1,61,168,132,22,21,224,86,237,119,49,15,228,241,216,161,180,19,252,22,109,144,133,49,21,97,145,73,250,32,160,0,103,179,235,69,26,206,44,140,184,97,110,167,21,84,228,112,18,154,24,41,60,232,190,168,43,72,248,82,221,13,138,79,89,140,122,61,117,232,17,75,243,217,88,218,235,50,96,182,174,230,168,249,99,90,3,240,143,171,128,49,247,62,32,242,216,73,239,88,172,30,77,172,78,40,138,46,152,178,103,92,139,57,224,167,208,14,63,245,78,69,235,225,103,133,134,96,22,32,104,77,117,153,192,206,38,183,221,117,253,207,240,211,16,89,105,251,119,74,144,222,156,150,154,58,135,38,58,165,24,125,4,181,205,243,117,226,156,243,80,70,66,176,146,37,197,55,215,99,87,148,92,191,170,198,29,60,48,57,132,232,226,100,191,28,143,184,235,205,69,47,243,18,71,89,96,148,5,68,98,120,4,46,222,166,248,156,123,31,13,147,244,29,153,133,248,130,207,112,2,139,131,49,115,58,120,121,244,170,19,97,201,192,75,161,137,127,83,157,78,253,58,222,224,220,83,182,11,236,101,153,140,34,113,36,254,143,112,151,78,23,46,155,32,170,178,239,64,77,243,128,127,240,27,82,213,68,205,87,27,42,124,75,156,9,234,4,161,210,181,7,140,130,78,31,105,100,208,169,223,62,105,229,132,50,56,128,226,5,184,254,213,116,54,2,93,233,67,132,34,39,179,133,27,209,227,163,127,21,38,10,175,140,28,114,70,190,173,123,166,31,176,23,83,27,2,64,147,250,217,95,1,100,211,238,42,151,65,188,182,234,61,134,64,31,245,14,173,167,214,244,223,242,182,230,208,180,241,228,142,135,251,1,188,189,100,175,18,181,117,35,14,102,136,20,208,168,235,41,228,102,112,204,114,197,137,63,144,1,174,122,8,52,194,119,247,169,229,16,103,124,105,126,128,30,165,102,132,107,24,55,253,220,212,101,202,129,150,144,2,88,195,9,152,160,243,97,168,80,228,18,168,79,186,193,151,206,197,164,32,6,58,126,128,178,154,122,20,188,81,123,96,6,46,214,149,107,24,177,129,255,208,247,29,66,228,212,126,81,168,1,76,131,174,108,141,122,248,24,107,113,170,68,235,117,129,83,56,163,148,130,79,104,185,22,138,198,242,77,180,102,47,117,225,233,90,16,225,8,163,241,112,173,15,227,176,197,136,139,114,202,96,151,63,60,96,154,107,17,147,224,206,248,93,53,106,235,229,60,87,165,173,67,60,192,40,25,38,154,183,128,195,41,187,21,254,166,61,76,158,20,29,63,194,131,191,180,111,32,193,245,193,122,94,224,84,142,94,172,150,192,219,151,49,107,61,164,252,204,72,119,227,21,253,120,84,60,176,113,224,172,24,196,92,64,19,6,114,3,127,121,48,40,3,60,52,74,110,225,56,14,140,23,179,58,129,206,230,166,25,190,123,31,5,201,50,253,204,94,174,116,91,166,97,216,90,145,201,152,88,164,18,19,17,202,204,251,146,159,61,233,43,209,63,240,241,168,94,78,86,211,0,62,97,12,204,199,62,218,65,64,9,170,91,210,0,191,56,249,81,51,140,84,246,229,192,59,27,87,104,195,108,174,216,168,188,98,234,57,57,162,193,13,190,155,45,124,40,58,32,99,14,179,68,39,112,92,159,159,36,201,2,226,129,171,120,102,185,148,114,152,162,196,181,56,69,182,37,197,98,228,38,41,142,10,57,84,197,160,183,210,236,9,42,214,224,63,62,31,118,26,251,177,236,185,210,104,244,19,251,195,113,141,34,50,255,204,42,56,117,66,203,139,249,119,14,28,203,175,32,42,245,180,104,11,154,25,127,248,60,200,28,180,91,39,244,161,108,240,140,189,72,32,119,76,235,30,100,46,74,250,110,234,232,192,243,51,124,39,251,186,123,64,23,149,105,161,56,180,49,163,245,34,42,187,145,64,13,82,135,95,186,146,44,214,135,104,194,94,110,93,178,242,130,21,226,63,156,184,127,204,241,167,193,180,9,237,106,90,105,165,19,198,246,140,189,35,66,77,27,170,145,237,170,99,161,189,234,238,51,219,82,212,214,32,43,128,193,45,163,2,216,44,192,84,104,92,99,93,116,94,163,255,90,174,176,184,147,127,46,68,22,63,23,62,151,173,125,237,52,101,54,144,205,184,145,103,197,86,53,11,127,158,118,175,217,13,86,251,47,11,230,181,185,174,212,134,254,17,229,174,154,246,87,107,230,55,252,104,84,104,251,201,66,110,183,24,71,54,10,178,175,12,182,18,163,73,203,244,85,216,175,129,81,60,17,112,71,155,136,34,122,134,137,245,172,152,64,127,55,97,0,148,116,138,88,45,172,16,250,169,10,55,168,155,249,246,117,74,112,183,220,144,84,127,245,255,79,75,162,219,9,150,235,53,199,122,194,58,198,192,83,66,183,114,7,36,198,143,179,218,40,178,248,218,185,108,140,103,50,91,31,235,191,230,109,62,140,189,224,31,241,31,255,48,167,106,18,242,164,95,24,208,232,159,107,188,95,66,187,61,92,245,43,201,191,135,1,41,19,255,103,156,115,9,219,112,48,74,62,113,152,120,196,200,133,105,206,67,75,26,102,159,159,237,244,74,119,46,70,217,24,102,5,82,212,11,224,67,44,241,148,125,122,140,30,141,56,185,122,202,228,228,152,203,143,221,92,116,168,69,113,89,106,187,215,201,255,151,132,143,105,97,52,138,102,179,146,194,72,5,11,142,16,31,119,218,54,11,45,117,143,78,191,169,116,115,101,231,67,196,81,203,175,126,36,74,3,153,52,15,176,118,87,2,10,235,166,166,25,217,24,97,56,174,121,208,62,83,81,159,25,1,81,67,213,89,71,34,140,83,221,7,159,118,96,172,176,235,249,185,28,97,166,17,64,245,165,23,63,251,128,105,12,76,148,92,91,188,236,238,25,184,58,203,60,22,171,192,183,224,144,158,173,39,61,188,92,76,155,181,102,5,187,207,150,94,58,3,250,36,236,210,151,254,24,164,165,111,28,108,229,47,22,146,124,12,137,148,24,184,174,127,13,247,114,83,177,100,178,209,116,247,77,184,99,249,116,52,90,208,48,242,239,23,251,172,248,54,133,62,24,240,90,110,209,64,19,65,231,127,36,40,74,61,89,232,108,40,133,183,241,255,164,20,180,249,37,233,11,144,123,198,10,134,56,30,115,232,181,188,113,167,11,26,133,132,207,13,144,114,236,85,141,70,151,42,10,176,211,160,243,33,210,57,247,197,33,32,215,207,152,153,82,222,95,87,217,232,251,9,157,52,92,92,186,221,244,36,132,244,171,126,222,212,178,213,118,239,52,68,215,228,157,37,229,77,151,40,95,205,177,209,250,59,223,193,65,135,147,161,220,60,30,20,221,12,251,251,237,115,218,76,211,222,227,113,244,133,150,144,25,141,230,202,17,219,118,142,8,254,249,111,8,74,66,92,214,206,5,252,176,47,65,208,174,127,25,182,208,254,125,215,136,104,95,122,148,47,160,24,171,217,115,108,36,46,111,121,54,209,200,78,201,242,47,82,146,153,116,84,30,151,175,199,2,189,89,106,30,113,219,11,101,233,191,165,1,168,238,15,156,187,76,114,205,125,10,232,251,59,152,234,16,241,125,111,195,40,170,83,198,62,219,137,128,20,195,25,33,235,77,95,39,151,116,175,239,44,250,171,84,173,154,211,23,212,157,160,162,208,164,16,244,147,14,14,17,6,104,150,53,108,250,78,227,27,137,22,252,98,238,175,243,37,70,13,183,79,164,152,113,101,78,244,30,197,103,210,103,214,38,156,171,0,17,21,28,178,30,168,20,31,200,208,51,52,113,15,151,103,235,237,40,10,81,34,216,193,173,182,231,138,223,70,74,110,140,135,128,67,193,157,182,109,142,223,157,163,206,148,192,228,100,183,148,130,219,246,217,18,184,83,27,227,178,40,188,85,136,45,33,244,69,87,159,128,40,97,108,157,0,46,148,60,23,222,235,38,205,188,53,18,244,187,182,168,183,237,144,27,24,195,130,65,220,216,15,20,137,249,27,41,218,232,246,197,92,106,119,80,113,188,192,30,233,34,219,39,146,187,114,27,18,165,104,236,249,38,44,105,166,205,230,49,128,243,36,251,113,40,38,25,215,224,120,27,235,159,12,92,34,87,109,158,74,60,6,136,178,187,38,91,137,86,88,121,201,214,195,151,83,64,228,135,143,158,147,97,176,188,111,251,247,113,197,192,23,113,9,177,188,15,65,193,111,153,189,107,45,251,63,75,15,75,144,12,21,147,41,0,174,131,76,50,32,230,156,172,12,21,217,99,174,122,176,90,142,255,218,205,218,102,252,254,211,225,2,68,190,66,50,226,64,173,14,103,174,112,42,47,226,144,59,125,110,69,123,255,9,156,24,136,238,168,115,76,198,25,170,142,181,178,27,82,125,25,38,98,50,248,232,139,82,51,79,162,74,26,73,204,26,40,13,40,2,73,96,105,177,92,99,35,99,110,56,185,105,177,205,31,100,153,114,150,60,150,252,43,129,210,116,71,159,252,129,54,152,242,65,180,226,15,50,224,127,124,175,143,91,38,46,62,8,22,59,186,178,38,77,246,103,48,216,212,109,56,156,174,127,24,51,123,161,249,178,142,219,27,68,158,78,254,94,242,73,34,240,204,200,93,216,7,25,228,165,205,3,19,2,181,77,104,175,11,217,230,194,135,111,69,253,161,56,50,214,192,155,137,146,17,189,167,202,57,121,74,241,142,45,201,161,154,57,125,92,44,130,241,88,74,115,124,14,144,36,13,187,40,11,139,4,59,158,157,206,13,92,151,135,1,219,94,61,152,173,99,202,240,172,225,103,253,248,69,184,171,34,33,169,218,245,125,15,58,199,178,40,202,80,134,75,170,110,92,65,6,58,200,15,51,116,102,229,188,24,164,185,80,221,62,235,227,1,238,159,158,44,47,211,248,136,211,153,57,241,104,231,90,19,39,187,253,118,187,69,91,208,213,90,157,249,110,157,246,186,4,46,212,11,235,27,55,22,236,16,139,224,123,76,76,174,18,156,21,2,25,59,83,147,157,186,202,18,243,139,77,192,205,43,11,67,231,130,169,53,171,6,241,244,138,2,96,125,93,209,194,120,187,162,104,129,237,118,242,149,94,212,207,222,141,202,202,204,103,231,34,132,92,157,95,239,176,202,195,185,87,154,63,219,10,215,8,146,73,190,222,17,110,27,90,35,66,27,93,191,17,12,120,158,138,224,58,68,152,169,243,48,157,252,163,132,148,157,222,184,145,161,202,141,123,93,61,82,14,213,82,53,66,165,100,215,10,77,207,216,139,35,208,176,63,63,80,219,7,147,222,36,12,252,16,92,225,56,96,70,218,129,99,205,25,99,208,253,109,43,104,153,0,224,39,192,163,67,138,85,157,8,128,148,197,89,194,87,99,206,81,141,47,214,217,156,211,187,184,220,33,32,20,31,143,48,136,147,54,141,147,129,53,91,215,115,208,74,187,36,225,92,30,238,23,79,195,80,124,161,28,40,129,212,156,128,13,94,16,64,122,47,166,181,116,236,218,16,106,162,20,12,250,106,59,75,168,173,41,229,75,239,230,135,79,240,61,106,144,243,222,80,207,8,155,238,226,204,246,25,2,83,116,227,42,121,189,61,88,237,200,221,66,111,84,209,44,204,5,74,21,249,236,194,187,52,103,164,109,114,191,27,0,240,99,60,253,103,92,69,90,87,109,109,138,61,171,55,129,98,152,62,65,82,93,47,130,95,171,12,145,48,243,4,220,47,118,144,188,144,153,224,242,141,144,94,218,128,144,77,106,98,182,215,118,91,73,238,22,122,110,3,109,89,91,34,0,57,72,86,228,158,153,209,235,58,200,213,223,68,254,49,210,128,11,87,0,207,25,93,183,141,193,9,142,11,15,213,209,90,220,249,117,222,163,188,42,116,162,111,235,175,70,29,243,205,184,46,214,112,219,68,27,190,37,228,13,196,98,127,58,220,90,248,241,41,128,82,170,102,78,72,99,103,47,49,238,210,203,217,40,130,83,98,143,81,119,52,173,166,24,234,61,253,11,147,118,189,128,69,161,207,122,161,251,67,139,246,0,44,109,95,241,166,224,177,225,201,10,38,201,24,44,192,55,22,191,109,159,167,39,67,213,33,100,6,197,183,223,105,223,51,37,21,232,53,7,12,64,243,13,77,22,76,175,156,127,201,50,147,144,135,179,71,59,88,161,195,29,23,213,184,66,77,202,54,134,198,21,205,74,59,68,197,2,150,28,192,219,164,192,158,231,193,240,26,176,33,136,97,129,95,91,76,114,79,86,97,220,135,80,233,39,150,150,27,223,206,160,84,151,120,226,45,231,200,167,121,200,46,1,132,39,112,88,96,85,173,249,29,67,46,208,224,131,84,81,64,218,16,15,12,243,215,86,157,212,204,147,221,26,11,10,114,75,9,240,8,16,58,152,196,219,149,51,8,94,225,203,7,157,156,249,220,220,207,80,128,47,103,189,58,38,83,183,122,51,230,254,146,160,37,235,226,233,55,164,177,33,246,224,67,54,25,126,27,216,100,83,102,46,231,99,215,206,57,243,30,174,54,153,209,116,17,156,121,215,104,69,33,59,37,187,95,75,158,233,68,148,64,236,174,32,201,143,189,99,126,50,216,65,155,184,98,84,102,243,47,178,99,59,227,198,213,53,206,39,35,180,9,162,212,58,190,48,80,234,176,124,165,130,234,100,117,5,245,122,210,159,134,31,165,144,196,154,81,131,130,236,180,4,23,225,45,144,92,99,117,71,130,142,141,103,81,168,211,2,123,203,171,59,133,24,46,169,116,160,216,233,44,215,66,201,119,51,58,75,50,68,116,127,170,113,129,55,193,109,155,237,246,191,189,150,135,24,5,204,65,201,86,15,202,87,40,122,227,52,245,82,182,54,65,104,165,101,190,208,117,246,203,163,168,171,35,67,186,170,221,100,63,0,206,157,229,28,237,147,132,88,91,215,64,64,22,48,88,246,232,140,146,211,199,110,230,207,238,78,66,78,104,253,244,227,114,94,210,30,6,33,43,1,110,176,2,156,178,126,202,213,183,124,213,218,56,96,100,54,192,53,69,60,180,73,48,142,15,85,251,191,216,147,246,47,251,203,203,138,14,174,9,73,186,102,220,0,200,22,56,137,234,117,155,105,229,151,192,129,193,93,234,222,103,57,195,107,240,92,18,180,41,23,23,255,255,135,26,222,109,47,129,205,129,52,192,82,153,195,24,72,58,156,127,159,210,114,67,196,173,239,17,84,216,115,57,151,70,218,133,179,61,149,175,160,128,222,103,91,202,239,92,198,173,251,58,186,236,105,215,23,167,254,58,4,21,22,17,213,211,230,47,195,183,154,245,187,224,165,236,107,184,195,149,49,79,138,158,97,201,64,138,145,249,37,253,56,175,148,83,197,74,69,186,47,38,63,14,241,224,30,52,152,74,163,144,190,253,92,176,164,109,217,165,118,19,56,214,162,10,193,213,18,95,72,55,150,22,199,50,196,111,155,204,32,122,25,68,234,156,43,178,92,160,204,83,138,2,184,248,7,132,201,144,69,176,216,12,49,175,55,89,163,91,23,159,27,226,183,111,153,13,35,140,237,237,170,126,119,171,55,105,81,53,55,142,131,46,39,136,83,145,158,216,192,73,71,22,117,124,243,85,81,130,52,28,216,143,226,153,141,3,162,141,249,125,8,119,27,65,133,135,123,117,71,161,45,130,255,194,160,178,21,123,106,105,199,3,146,205,115,157,18,61,181,226,101,151,234,244,10,17,216,104,186,3,215,32,157,200,151,190,41,62,181,74,5,160,213,185,70,97,253,164,115,81,108,228,207,4,144,210,54,224,36,93,21,210,109,58,54,121,127,235,182,110,122,161,24,48,114,193,83,31,221,109,136,70,83,212,203,195,232,231,69,5,55,157,106,77,101,19,58,55,127,91,240,85,64,11,229,155,10,93,177,2,144,20,75,121,186,81,171,50,1,196,62,217,231,16,206,250,186,173,24,60,218,230,99,216,36,3,103,61,237,73,61,170,38,35,224,158,166,103,119,128,4,5,152,194,141,234,113,149,54,196,25,235,18,81,227,137,137,138,115,20,204,38,189,115,69,224,31,135,6,32,171,72,87,42,144,71,72,255,171,79,132,159,83,151,209,62,152,25,79,133,19,172,154,90,84,80,101,131,150,37,245,195,199,210,235,98,122,229,215,7,164,79,63,62,80,142,144,161,189,235,24,212,200,109,145,185,104,122,29,112,81,147,15,4,108,147,244,184,155,249,18,80,201,174,227,93,226,109,63,7,17,14,209,141,194,160,30,170,18,60,144,32,224,177,0,106,248,126,107,84,185,179,106,146,13,238,80,251,18,50,96,122,216,217,112,187,148,102,111,47,244,158,22,39,76,59,150,43,22,117,202,253,88,26,166,126,243,142,239,81,69,185,255,93,56,20,32,232,185,22,217,19,198,221,159,42,176,105,127,180,90,189,136,213,241,120,92,0,77,136,165,142,142,126,142,164,219,231,41,237,134,253,191,235,254,252,57,52,25,89,120,215,145,142,87,152,149,107,177,79,86,176,4,105,59,150,254,14,74,110,116,206,16,0,218,98,156,66,18,10,16,202,136,15,80,236,236,233,75,132,186,168,174,233,16,240,124,0,189,243,98,252,33,121,215,44,173,199,127,71,233,97,165,227,102,12,62,59,225,180,119,55,117,95,159,229,177,99,143,111,247,182,37,180,23,219,51,67,250,113,124,122,213,160,93,82,156,170,252,0,1,76,22,11,250,91,147,112,1,233,251,21,112,60,137,25,215,114,231,83,28,55,129,94,198,200,247,80,156,163,198,211,214,235,239,111,210,160,137,128,181,114,163,61,8,94,83,46,49,30,181,239,140,222,109,66,167,226,89,159,32,73,145,21,222,213,65,62,66,94,137,206,128,169,236,73,167,141,150,232,238,36,44,136,68,28,4,21,153,225,253,254,31,210,190,138,17,5,228,142,90,163,91,64,60,208,230,70,88,201,198,140,171,37,112,143,83,251,39,36,63,189,48,135,196,100,189,76,124,37,117,179,153,183,236,97,94,72,5,144,76,23,71,22,137,91,101,17,51,31,37,37,248,167,248,202,225,125,28,24,192,51,67,242,20,243,183,110,138,211,210,110,39,221,189,226,241,100,225,217,111,128,6,152,234,156,179,79,2,139,150,103,51,47,252,21,104,71,84,83,243,17,144,151,52,96,128,26,163,179,77,162,97,109,136,128,106,219,50,111,229,203,148,252,102,19,181,220,239,169,7,60,6,173,111,160,55,24,162,69,223,39,186,222,104,184,206,203,0,68,178,244,108,51,107,230,205,176,248,207,12,225,122,184,184,1,99,226,173,135,71,136,45,243,127,168,160,134,31,180,45,53,1,213,36,43,83,51,59,61,115,223,67,123,54,86,38,128,71,198,210,179,241,150,253,253,1,26,104,127,234,182,86,121,188,19,134,211,19,249,75,96,210,137,255,175,48,38,23,82,107,180,73,87,97,17,31,217,160,77,243,143,164,224,77,154,152,148,205,66,240,48,168,156,21,103,19,214,154,17,173,156,16,31,18,63,134,224,211,145,46,114,33,113,105,125,72,78,202,25,183,28,255,45,63,169,16,225,2,237,156,45,254,223,125,195,250,99,49,156,250,188,216,169,104,171,157,188,114,72,110,29,153,187,99,254,51,237,255,23,98,131,248,193,121,59,142,7,176,78,52,182,134,170,136,125,40,234,245,225,74,212,208,176,105,253,8,32,143,69,180,249,246,10,31,176,129,144,255,199,193,59,12,181,231,207,169,241,243,19,253,220,49,45,195,42,147,102,239,117,186,240,63,156,184,43,225,119,87,44,38,11,106,231,241,208,145,167,222,147,22,240,37,62,139,30,249,0,209,78,164,84,131,254,178,126,91,170,226,29,73,170,154,101,221,202,18,92,146,134,178,38,195,106,88,228,86,86,172,34,113,89,4,85,139,78,39,3,161,49,94,245,107,21,206,162,64,240,35,201,126,89,226,156,229,141,165,29,4,22,197,202,125,44,200,64,176,137,55,95,167,234,104,86,244,217,45,234,206,4,6,171,85,146,235,237,168,81,103,77,204,104,16,110,90,132,100,240,72,96,188,201,254,56,43,229,76,8,144,250,190,182,102,89,64,104,238,222,184,173,138,130,235,233,91,226,30,237,38,236,194,116,180,36,198,97,37,242,32,60,224,15,13,203,190,121,127,41,1,108,205,117,79,104,173,232,164,128,0,31,193,82,164,115,1,175,199,50,22,0,215,136,87,212,105,174,240,47,27,51,93,165,183,61,96,31,150,125,70,38,192,85,215,191,65,159,42,123,59,211,210,39,96,64,53,80,103,134,214,75,89,23,40,114,4,148,61,56,175,176,119,180,61,162,119,184,21,110,204,103,52,202,109,151,202,204,240,215,165,116,96,52,113,64,112,42,171,54,172,169,69,253,44,153,24,232,19,141,73,3,80,141,143,57,23,209,218,79,5,176,20,117,197,223,97,0,0,216,103,205,251,42,189,173,104,182,224,240,187,184,90,150,165,151,54,237,248,21,195,252,26,86,186,43,130,85,173,165,88,77,47,61,60,251,197,177,40,114,201,153,72,161,39,61,136,217,22,39,227,180,112,20,184,0,22,255,248,87,132,120,113,8,6,226,212,166,57,112,185,75,15,83,79,196,106,136,205,5,59,250,63,35,80,140,176,236,196,248,3,221,98,250,104,32,99,152,165,109,139,192,40,49,68,14,50,89,102,202,12,64,120,114,49,227,205,144,18,43,180,65,47,167,89,67,145,180,44,241,173,23,232,86,141,103,210,72,240,225,180,133,221,238,4,125,161,121,44,204,5,162,64,34,84,167,152,247,154,190,162,116,71,83,180,181,174,3,151,227,180,162,28,198,133,1,195,199,54,251,220,4,182,126,209,15,24,207,187,240,50,11,120,250,158,87,125,246,74,64,175,190,21,150,255,202,170,125,38,228,16,24,166,186,7,113,0,133,182,112,138,188,2,24,120,236,10,76,154,89,48,23,228,159,219,144,219,209,76,59,25,100,202,46,203,178,117,252,97,240,97,42,143,205,52,199,220,7,0,109,217,139,126,170,178,227,213,192,16,171,133,173,237,240,186,6,14,155,94,157,194,99,123,174,181,74,164,126,56,178,0,172,77,163,74,172,53,5,161,130,161,162,149,232,150,69,170,172,59,70,142,112,87,58,16,192,67,8,250,29,140,221,17,117,167,133,43,180,141,157,214,18,131,114,105,147,206,25,138,207,188,30,41,9,97,113,247,123,251,56,165,182,239,95,79,152,45,113,160,213,230,249,227,167,149,52,172,156,182,242,134,61,19,90,144,248,100,252,168,76,213,246,126,123,175,8,114,218,41,247,90,229,94,238,86,73,43,35,42,116,168,217,75,167,166,122,230,82,130,255,164,51,9,86,79,111,49,152,198,132,96,62,12,131,23,66,96,51,213,29,13,144,20,26,228,66,41,228,68,254,126,173,192,51,62,41,184,136,182,93,102,144,250,65,236,200,19,121,182,87,125,72,97,132,164,29,130,211,26,115,217,177,199,35,54,132,98,87,138,188,229,34,130,240,81,186,231,130,41,17,74,64,27,41,169,251,229,192,38,247,81,85,224,10,181,80,164,164,112,73,150,53,119,166,144,157,52,98,187,48,28,64,77,33,237,100,1,46,123,40,27,232,128,105,190,126,27,132,205,16,107,184,30,187,240,29,128,81,177,9,175,37,159,188,53,109,59,15,33,102,39,182,31,73,163,176,14,150,178,216,231,41,152,253,100,240,46,106,181,137,111,240,101,204,74,57,134,179,49,230,134,124,152,70,64,166,43,65,203,80,53,157,166,39,138,142,243,74,145,217,9,194,93,128,67,93,129,161,161,254,211,189,239,205,32,171,253,118,141,204,240,183,222,146,198,220,187,58,201,238,218,179,206,89,183,40,198,33,53,38,40,144,216,247,161,189,216,173,9,22,72,148,174,45,3,127,35,125,111,140,15,207,119,246,38,244,195,69,85,106,121,28,241,125,124,103,116,108,152,84,133,165,68,92,5,189,160,223,125,159,69,84,91,214,24,52,36,207,180,152,8,156,70,209,194,220,165,138,212,192,246,132,124,186,64,218,179,23,131,210,117,7,15,197,250,249,187,104,74,19,195,232,168,66,171,125,133,252,89,123,236,67,152,150,187,82,161,241,29,160,206,15,254,101,201,34,79,182,6,88,237,204,67,3,24,199,64,58,22,71,118,31,80,235,148,111,111,74,248,229,15,0,160,215,0,121,227,15,243,58,122,251,203,236,223,102,217,235,105,113,239,209,206,227,198,166,116,250,85,48,71,14,78,216,2,167,129,129,240,167,56,89,118,161,125,49,228,56,221,13,219,207,36,68,253,27,45,219,117,151,229,111,247,206,97,173,132,8,74,182,16,125,54,238,31,46,244,50,250,3,216,182,42,120,67,61,39,106,101,23,248,21,80,151,115,41,105,95,47,32,90,53,3,164,31,12,113,105,26,135,101,186,43,191,173,143,177,4,75,109,96,7,121,5,231,218,250,45,96,254,193,146,225,251,238,21,240,27,207,43,187,7,61,254,195,234,210,152,46,241,186,188,216,234,82,179,109,61,190,139,211,58,36,74,149,107,249,150,196,71,226,167,232,40,42,19,152,17,194,16,94,5,11,57,37,43,99,98,248,81,211,60,69,192,80,94,225,241,197,53,76,100,1,166,253,132,17,3,72,232,72,214,60,18,151,159,15,167,78,27,76,142,22,21,129,121,10,185,35,246,49,165,218,73,182,236,65,1,175,236,230,71,209,189,163,164,179,194,209,86,6,180,219,147,94,15,212,246,83,21,183,250,40,230,78,222,159,74,94,13,20,247,51,90,218,253,125,50,81,72,93,1,200,50,199,223,192,197,223,38,208,98,122,118,7,82,178,154,193,50,199,199,7,184,231,120,39,2,232,41,182,32,75,56,236,176,5,0,113,190,13,109,1,175,212,249,89,21,130,204,162,228,119,244,190,87,252,151,13,40,209,103,93,95,199,103,141,133,122,94,189,161,222,26,229,214,114,137,110,97,84,81,251,213,80,122,215,144,113,154,105,12,130,191,24,0,226,159,46,86,119,142,104,231,72,118,224,91,195,94,179,212,168,32,243,2,25,219,4,197,34,167,252,198,18,155,87,88,62,165,118,253,176,96,152,186,128,214,140,226,59,11,113,104,102,96,136,126,9,13,140,165,46,116,134,52,249,105,131,168,226,83,93,216,194,247,236,251,159,42,118,243,93,85,175,120,106,134,75,146,217,187,183,49,138,190,5,189,3,203,106,166,110,104,108,70,111,165,41,203,34,212,254,32,10,2,238,30,243,126,47,119,175,63,107,73,75,131,105,17,54,253,158,128,179,196,198,64,151,178,55,47,159,191,106,78,234,208,198,108,42,131,2,33,44,121,43,48,137,107,252,205,15,84,242,200,169,148,239,199,117,248,6,151,51,83,45,149,57,75,160,202,27,122,235,14,50,90,135,90,94,140,171,241,123,236,90,200,243,190,6,111,165,246,139,34,141,151,172,38,34,66,201,218,83,110,52,12,146,6,26,248,102,120,174,193,25,147,171,152,87,174,79,55,208,166,73,111,90,214,25,117,239,102,226,213,182,128,93,49,129,174,3,2,180,9,250,166,8,32,141,187,26,55,157,229,144,64,195,91,154,133,56,176,6,198,60,119,115,232,70,213,143,59,250,97,136,50,75,125,198,19,151,141,168,48,163,47,67,211,114,119,103,69,9,119,244,236,196,164,248,228,69,215,205,245,16,57,177,244,43,224,109,172,45,14,5,161,195,63,81,38,117,19,125,248,179,103,199,168,84,151,192,55,216,72,96,43,117,199,103,51,202,42,177,40,169,84,157,153,173,244,141,108,142,38,188,53,35,151,221,147,12,148,111,151,129,212,37,253,142,191,152,21,241,153,150,30,71,95,49,124,83,150,47,109,169,199,96,70,141,167,74,79,11,152,159,93,215,159,185,141,249,140,114,217,75,87,133,177,114,114,27,32,86,10,246,20,157,127,160,164,227,79,194,177,107,49,142,179,84,144,135,178,81,30,7,228,120,116,11,103,210,83,15,94,77,40,116,144,27,125,81,192,231,217,112,4,184,78,6,144,65,184,221,84,114,52,150,241,217,130,114,219,252,15,34,244,209,76,178,193,231,229,38,137,147,0,147,242,150,26,33,32,28,132,60,63,134,221,9,214,135,97,120,217,109,78,130,199,253,153,215,234,19,186,201,199,169,20,132,151,74,179,54,65,25,171,126,126,88,23,247,222,39,52,65,85,45,245,229,214,38,98,14,0,10,216,42,17,230,34,91,84,144,209,31,186,211,140,175,188,80,202,99,174,124,88,40,32,214,235,133,253,145,179,186,102,42,135,61,67,235,163,133,41,35,25,168,87,141,24,186,210,233,150,19,220,120,81,123,169,245,18,197,27,207,176,15,197,115,139,69,152,82,211,148,77,184,232,173,29,253,46,123,173,245,217,54,231,135,218,236,101,196,45,109,136,189,206,68,215,214,77,251,43,39,224,144,62,135,50,114,247,67,110,247,38,143,220,5,1,173,142,88,7,149,152,225,194,10,114,152,121,105,239,242,249,117,29,172,2,39,98,218,33,31,69,93,11,210,222,132,40,251,162,173,144,13,165,165,242,181,202,215,89,196,228,253,39,70,73,153,144,63,184,211,2,204,107,51,166,197,173,14,15,96,66,141,11,12,244,148,50,16,214,9,8,52,6,165,105,91,184,10,10,62,135,250,200,159,69,227,229,86,98,229,73,27,200,217,108,233,211,81,90,93,45,50,50,149,19,35,23,116,202,113,21,211,33,217,140,128,86,228,185,130,140,104,87,180,174,131,213,254,48,90,67,239,159,204,139,229,42,236,142,82,151,187,165,11,12,150,53,56,10,76,97,213,117,217,51,242,133,135,229,78,117,95,26,31,69,32,138,147,70,226,136,42,0,8,199,224,233,35,206,48,207,61,99,52,101,204,118,143,245,236,120,33,226,57,223,53,32,255,6,236,127,223,89,137,99,84,204,80,106,20,237,64,149,193,65,7,41,202,120,56,115,112,137,35,254,243,28,47,4,229,33,115,177,48,219,231,48,63,139,95,214,209,6,170,197,116,222,104,88,254,141,16,48,222,226,9,47,121,65,188,142,38,129,229,60,122,25,131,229,78,249,211,139,93,199,181,248,231,247,38,161,131,223,146,216,88,123,189,77,186,220,2,185,53,173,226,101,153,213,103,171,140,207,44,51,120,168,36,182,213,176,87,166,170,61,250,49,139,249,215,135,168,170,59,95,118,142,249,166,177,121,94,175,159,219,228,219,117,28,222,43,180,225,108,140,7,25,5,94,45,171,5,65,137,255,40,123,190,89,181,94,76,172,91,161,197,240,85,79,172,28,47,57,205,233,102,137,143,28,155,20,20,157,41,148,175,43,167,5,82,171,148,109,247,237,236,176,176,124,1,158,189,93,168,51,115,231,208,228,55,164,123,212,27,25,190,38,1,120,25,153,91,236,95,116,67,210,173,224,156,220,91,207,120,91,114,212,191,71,198,205,146,136,65,91,33,204,192,154,155,243,71,11,55,239,100,89,204,247,199,59,120,22,68,109,137,194,203,81,61,247,11,226,242,210,155,195,209,1,193,108,163,178,20,22,170,30,148,214,80,229,153,91,103,246,237,10,245,110,211,150,205,98,239,92,94,71,206,91,253,204,90,157,216,152,35,148,167,8,201,167,24,239,191,158,102,23,131,159,64,99,81,159,58,193,185,68,1,28,24,38,198,132,80,191,19,122,235,99,129,100,49,253,29,52,194,32,108,106,166,243,179,53,189,96,59,73,241,61,32,223,84,218,118,59,32,64,9,98,239,207,219,101,38,106,54,148,148,25,5,50,107,106,152,242,117,192,102,56,184,19,232,133,157,243,182,52,144,217,94,101,153,221,88,157,52,224,159,93,159,71,2,115,200,230,116,202,177,236,75,20,176,16,39,147,24,150,195,21,251,77,57,185,113,216,168,48,127,164,56,104,92,23,85,141,159,93,53,192,103,163,130,24,85,85,160,61,246,23,185,196,18,158,228,129,148,126,206,52,198,191,182,12,98,112,31,56,160,62,208,196,234,1,56,249,23,61,115,25,164,254,151,45,11,124,107,53,151,131,221,52,249,185,90,5,4,129,177,134,168,239,37,50,111,225,178,53,251,9,5,87,32,111,75,239,38,160,33,50,128,211,5,250,31,61,177,31,115,182,221,118,33,225,75,165,5,43,89,152,62,217,185,246,122,194,98,47,193,42,74,46,144,111,16,231,76,88,151,7,93,68,144,237,82,117,206,167,239,6,137,55,125,14,88,92,201,143,148,62,216,55,224,150,178,38,77,42,167,163,233,124,131,220,55,50,219,117,225,244,220,233,124,27,133,246,213,86,54,152,29,92,98,226,98,54,110,144,186,41,161,225,72,199,30,105,121,160,56,141,23,100,40,88,208,169,32,196,122,95,231,57,244,199,120,13,232,165,250,170,24,34,231,23,205,33,18,214,128,56,165,14,48,104,223,133,183,73,58,100,111,112,115,239,70,81,81,38,94,88,232,164,212,242,0,59,114,36,133,89,252,41,204,37,193,144,244,255,242,124,20,131,112,126,131,187,205,71,229,86,90,197,199,245,45,120,190,56,223,164,63,177,75,188,238,180,176,137,182,95,221,29,158,104,4,224,38,183,94,172,67,44,62,168,237,218,85,159,58,25,168,173,108,204,228,81,18,145,207,176,19,10,212,78,133,108,169,178,117,11,19,155,152,200,117,243,99,143,126,93,75,167,4,103,249,245,27,30,184,78,162,35,174,200,4,59,119,138,195,58,130,59,179,147,48,207,134,201,207,31,90,145,168,212,195,79,220,16,253,80,24,42,159,61,178,241,81,140,246,198,225,166,94,74,63,254,3,218,93,2,74,194,239,192,68,55,75,132,51,79,200,162,72,133,34,87,86,7,157,235,37,94,78,191,150,81,213,162,147,20,232,243,173,36,1,244,91,3,192,10,224,194,229,74,147,19,192,165,168,153,5,127,230,113,185,206,127,146,80,114,246,179,16,31,90,0,242,254,82,189,36,246,211,7,118,168,33,154,220,184,107,101,40,150,196,194,242,253,216,72,132,210,147,230,224,198,34,75,25,74,233,205,159,168,6,197,50,217,127,251,94,27,0,89,55,171,138,10,197,251,46,127,84,139,97,212,131,44,89,5,181,154,11,223,2,106,249,29,222,72,44,89,57,56,8,138,102,140,86,159,219,77,239,32,203,126,142,214,192,72,16,119,161,71,155,250,58,115,189,112,51,213,249,25,85,78,170,171,102,164,103,133,109,37,229,130,167,116,64,21,234,76,246,89,206,141,235,89,223,141,56,47,168,166,97,190,26,197,70,97,133,200,148,53,45,183,39,129,38,122,174,116,58,75,115,221,204,101,52,24,94,177,14,237,2,172,234,210,8,208,25,77,235,113,24,108,216,242,184,180,255,173,101,240,51,246,200,240,13,156,209,93,60,66,170,252,82,230,13,215,146,117,255,210,7,34,122,10,106,156,176,21,68,222,248,33,83,152,206,191,60,18,158,149,114,74,41,60,203,244,210,249,189,212,25,25,75,131,95,76,207,254,188,23,124,249,162,255,170,137,0,81,97,181,221,127,2,120,240,234,80,28,115,105,158,136,89,77,135,103,255,251,8,186,242,63,176,164,122,8,11,128,19,58,243,8,212,252,204,84,170,108,158,179,247,0,254,32,87,139,213,136,45,180,92,145,67,92,246,247,205,97,103,87,101,163,137,0,61,23,230,147,218,153,102,235,104,17,24,246,70,190,79,179,238,178,41,56,128,115,241,148,114,229,173,144,63,54,151,123,191,45,145,222,89,230,29,59,34,163,123,120,56,34,137,149,161,32,221,255,87,39,50,57,112,84,159,209,51,170,143,167,190,117,145,202,12,127,248,132,142,52,118,154,247,22,242,179,161,240,146,155,7,176,79,18,1,228,242,227,81,34,121,92,236,105,176,207,233,51,86,159,119,70,173,14,42,103,31,241,149,157,98,49,61,96,106,94,142,12,146,88,63,16,173,84,14,216,170,188,7,119,188,94,156,24,78,218,117,39,252,216,201,136,241,118,24,231,164,15,9,211,193,68,14,9,140,214,99,95,235,172,219,136,83,12,95,75,88,48,152,236,153,95,137,236,38,125,35,176,220,87,52,101,106,40,172,224,140,105,118,201,227,143,43,59,162,152,247,197,72,70,232,183,21,160,2,64,169,41,69,166,102,52,189,217,130,19,196,230,34,133,35,31,17,193,45,252,112,79,79,223,99,168,154,14,19,74,179,41,246,27,199,128,101,54,80,252,173,165,241,80,26,204,142,255,57,94,25,56,246,22,133,229,144,110,212,118,251,36,49,81,254,183,116,222,99,70,181,22,74,96,199,161,124,176,7,199,9,56,128,64,200,185,222,37,225,144,156,152,22,99,76,208,43,99,207,169,146,220,182,136,30,96,166,118,49,125,40,132,106,49,212,158,91,55,84,208,213,75,63,190,113,71,83,98,109,21,176,11,204,253,157,79,106,111,232,239,253,187,98,141,32,52,39,209,183,100,176,183,32,232,137,209,189,13,67,230,44,99,233,235,31,211,62,149,120,185,114,79,123,8,153,151,112,255,65,154,228,16,226,177,21,18,10,146,172,134,181,123,4,253,122,188,229,98,89,112,147,19,145,108,246,176,210,201,128,231,96,230,39,140,7,175,246,144,253,114,34,223,14,48,134,160,78,112,135,138,197,142,208,213,221,156,197,198,131,42,169,203,191,140,36,205,131,59,11,239,147,205,235,193,132,59,199,198,42,204,244,120,24,172,221,253,85,141,118,110,76,153,91,146,222,142,200,251,52,172,145,250,47,123,86,49,253,220,27,77,170,51,36,179,148,26,32,251,162,197,246,163,248,65,123,233,68,194,166,153,206,118,238,22,134,49,13,218,176,11,183,124,197,148,169,251,224,80,11,209,166,233,229,19,220,114,244,144,246,17,131,119,108,78,6,26,238,121,82,13,57,179,139,149,164,255,235,181,20,240,76,155,71,61,89,192,100,16,244,93,71,199,139,70,203,107,44,233,154,66,40,255,1,15,20,206,89,244,23,68,123,164,177,175,187,170,150,195,150,44,96,99,142,169,220,220,197,235,124,72,198,60,112,180,196,35,190,154,107,29,177,10,243,111,210,61,157,156,223,255,101,5,210,27,224,15,23,138,119,65,201,139,134,84,70,122,22,204,153,5,193,108,54,149,173,173,37,200,81,229,93,72,7,45,14,51,177,85,166,96,189,55,43,70,88,172,251,17,221,163,81,62,196,216,14,31,82,46,38,65,125,42,32,4,9,145,100,31,102,106,231,86,31,167,246,39,11,28,118,34,92,179,80,65,191,115,43,247,211,118,115,124,156,122,145,222,177,73,161,7,117,51,20,29,178,100,26,127,202,208,177,209,121,101,140,194,20,229,139,123,55,186,209,31,33,39,115,64,97,128,152,60,147,70,35,97,4,156,87,181,58,244,132,109,115,229,91,215,10,28,25,21,57,163,234,21,101,81,18,220,78,130,105,85,41,164,78,228,156,201,182,234,93,221,241,194,212,66,84,4,11,81,116,94,234,37,200,8,214,228,253,58,205,250,62,168,189,1,46,223,0,158,154,29,127,247,188,25,193,165,228,117,234,121,149,167,254,11,3,15,12,91,42,46,11,240,230,134,120,108,46,58,63,23,230,140,113,173,206,94,55,63,20,187,32,255,142,32,192,135,161,231,95,115,204,50,125,129,245,15,153,89,124,35,87,200,91,78,68,126,100,158,103,224,232,192,132,174,34,19,19,48,139,182,247,255,70,88,227,139,253,31,10,222,62,188,140,85,169,143,143,14,29,108,159,46,98,211,30,129,63,149,77,230,246,61,181,103,153,124,242,214,63,70,78,193,78,208,159,94,20,59,30,81,88,112,124,123,183,101,239,217,86,232,137,59,250,5,110,107,71,27,31,15,33,62,200,161,218,153,82,134,5,7,141,180,7,152,169,23,182,33,150,252,223,90,209,54,177,15,50,19,8,253,37,226,84,143,33,164,230,38,215,102,42,156,198,36,35,149,175,75,79,102,252,69,215,7,165,103,252,189,221,18,204,32,86,110,22,47,74,38,247,11,126,5,145,242,247,20,9,190,177,121,79,16,110,73,41,45,141,3,247,35,3,252,191,45,7,156,127,115,198,74,194,5,25,124,110,61,109,115,151,84,72,182,140,170,23,217,123,133,98,143,18,53,128,55,78,61,89,152,214,253,63,133,196,183,215,107,107,158,245,129,15,153,169,246,158,65,172,8,47,226,30,126,10,64,163,175,108,218,130,19,89,235,34,206,150,176,199,6,140,234,201,165,130,107,208,64,112,36,44,115,250,199,236,204,60,127,43,124,225,163,49,76,103,210,254,126,180,82,44,230,68,93,12,246,201,186,72,190,172,76,128,42,173,0,221,120,14,150,19,197,121,163,71,111,214,183,143,24,187,70,13,255,228,250,134,173,209,183,166,208,21,225,94,109,145,98,70,255,76,151,190,150,183,152,248,238,224,187,111,4,2,111,236,73,135,133,67,34,193,94,52,159,42,187,59,38,75,152,72,134,112,236,191,233,150,43,156,14,167,70,226,7,114,200,31,140,164,33,84,232,169,15,96,172,175,192,57,229,71,227,101,139,17,90,45,154,32,255,204,159,141,200,159,147,45,152,135,128,51,11,78,181,154,83,92,144,157,134,244,234,140,201,95,218,104,165,146,35,28,223,139,111,128,149,30,162,119,191,217,136,196,219,138,212,22,168,182,19,118,34,168,68,234,104,231,59,166,128,52,254,212,215,218,117,66,31,249,88,61,78,33,130,242,94,66,17,169,102,100,130,251,1,125,169,71,110,165,239,246,162,251,220,185,184,20,76,133,171,122,57,219,218,181,169,220,38,166,27,206,53,166,180,135,172,64,7,187,131,182,110,67,34,191,25,145,197,184,217,30,140,72,15,212,194,123,34,239,194,64,110,117,35,199,82,17,157,252,230,226,228,44,151,158,81,101,191,59,18,175,143,139,235,12,185,50,15,106,29,143,82,247,211,52,208,35,153,64,11,50,37,13,38,232,128,45,104,62,240,201,122,137,83,140,250,178,64,142,202,168,54,119,221,215,71,166,35,108,71,223,239,99,153,12,8,134,64,200,182,235,107,96,111,231,153,200,254,189,247,49,93,127,4,200,77,43,160,120,224,252,243,224,46,190,166,143,82,46,207,86,235,116,203,190,88,18,55,121,70,227,215,107,69,58,245,221,133,33,73,230,34,36,254,49,127,129,180,253,175,209,180,54,94,124,96,104,97,243,225,38,248,166,230,189,233,78,38,61,122,43,51,76,9,219,127,1,239,79,151,48,213,26,208,118,80,108,178,180,167,38,224,5,87,106,12,73,252,109,195,190,244,1,237,106,212,236,116,74,192,255,121,219,152,67,18,77,38,21,51,27,121,200,196,0,84,219,179,46,124,54,85,12,179,49,241,46,197,14,33,28,79,227,246,94,112,66,187,209,230,116,161,40,15,78,57,156,110,138,178,73,41,255,178,62,43,236,180,171,248,21,243,240,13,110,71,67,79,176,57,76,207,194,20,219,223,36,60,83,50,200,87,245,137,235,132,89,144,67,4,174,55,221,14,212,138,175,187,209,186,54,80,178,238,243,36,9,199,108,128,111,120,61,208,105,53,44,233,236,78,63,226,71,197,238,242,101,100,227,70,160,209,41,198,56,65,115,138,237,132,126,95,23,46,122,98,177,164,159,251,98,212,145,111,203,95,36,21,53,163,88,57,51,139,255,60,181,38,187,107,75,128,165,215,232,130,56,103,173,192,192,119,72,104,142,246,79,232,200,17,207,225,61,55,106,74,61,126,180,229,233,187,223,190,82,11,232,15,84,52,13,98,154,199,134,191,227,132,219,235,17,230,249,92,249,34,165,54,132,101,234,209,220,66,6,69,181,50,132,160,155,246,171,5,167,56,49,27,175,90,222,36,13,217,116,128,9,151,3,203,43,43,40,205,132,14,248,28,88,180,107,146,95,19,175,0,109,41,170,148,148,54,179,0,71,101,59,99,221,143,205,42,59,156,112,136,31,59,18,231,136,191,41,46,122,77,101,152,172,123,108,116,111,53,229,4,163,218,156,39,171,198,100,223,236,90,205,126,143,72,67,138,159,241,118,154,239,154,219,34,182,123,33,163,113,46,15,249,238,36,50,215,132,241,226,207,196,181,96,162,212,88,224,190,81,179,12,136,146,122,238,83,129,26,72,105,125,20,146,253,67,112,232,12,188,96,52,161,160,121,241,50,77,49,218,20,78,169,246,196,95,213,12,11,243,170,71,1,244,78,233,115,143,34,201,250,23,100,9,97,17,4,211,193,128,42,106,170,138,9,75,28,208,247,157,32,4,210,106,87,15,97,167,209,22,160,123,52,183,148,194,21,14,53,212,119,43,76,147,154,56,43,175,79,109,103,68,93,115,95,230,242,89,230,162,136,47,37,79,109,220,24,217,83,40,241,45,113,250,138,133,115,120,72,115,222,65,36,226,44,1,172,128,192,152,113,44,162,139,24,194,114,139,90,162,31,228,198,129,96,97,224,87,232,183,43,193,104,251,129,67,148,240,227,100,4,27,202,89,241,226,221,189,142,102,74,1,234,197,88,247,95,217,142,161,58,118,124,174,252,162,242,248,126,19,199,138,191,202,209,59,204,127,100,65,187,50,108,197,107,107,205,55,228,48,246,168,68,28,74,186,102,54,116,29,188,57,221,206,122,202,240,151,15,23,162,146,91,12,88,51,69,3,110,205,52,5,186,49,46,171,126,221,23,30,236,45,162,17,198,211,238,177,147,106,5,203,206,78,143,1,167,153,96,15,225,28,219,223,209,68,221,218,102,32,19,138,90,130,254,63,73,240,165,99,150,83,198,65,210,22,92,216,204,186,182,213,249,35,2,80,190,138,101,47,225,210,232,29,85,90,174,228,82,244,173,189,193,47,20,238,93,189,172,27,25,87,244,243,224,87,201,186,153,42,69,160,195,77,180,136,128,231,197,161,163,94,0,191,87,57,125,254,155,170,223,110,165,95,181,188,82,153,240,68,118,58,137,253,184,248,35,170,207,20,197,246,93,21,36,48,195,147,75,92,94,166,34,77,198,225,189,122,91,111,136,32,138,146,132,33,113,35,32,184,97,10,255,132,98,61,203,100,65,30,160,150,30,85,22,8,32,101,187,142,240,176,3,67,219,207,113,202,242,213,177,61,155,141,225,69,7,10,3,184,65,132,69,241,149,214,97,91,168,150,187,136,18,190,15,66,134,232,239,202,169,247,10,160,246,157,238,77,41,185,221,165,157,108,94,145,231,229,169,101,1,167,15,161,20,158,211,139,204,107,228,206,211,185,65,246,158,167,12,107,190,45,182,28,192,44,106,148,62,159,222,82,10,227,237,251,3,151,152,139,76,162,183,169,202,107,181,200,129,195,124,71,208,135,234,26,203,154,53,208,137,99,150,100,142,114,50,153,183,126,133,1,253,9,202,235,65,46,106,126,8,5,105,93,53,17,35,209,62,117,114,152,57,29,66,71,127,2,130,103,158,7,17,86,195,64,229,219,75,195,212,33,209,50,154,59,27,177,135,24,163,107,219,137,197,220,7,153,96,131,0,65,187,83,25,18,15,100,245,27,6,174,119,25,182,124,115,158,7,84,182,105,34,75,231,222,190,48,233,221,49,119,79,153,174,200,28,223,87,37,72,254,237,189,199,23,239,255,69,27,152,251,104,233,142,231,80,48,149,197,234,170,200,149,73,120,9,20,212,128,69,99,144,23,22,83,89,207,47,19,17,198,156,214,226,55,130,85,146,54,5,58,224,214,6,27,36,31,164,126,182,225,53,4,52,100,11,28,220,125,41,101,102,215,188,97,6,55,113,252,140,78,81,115,58,203,129,115,132,109,206,21,68,78,20,128,95,62,34,72,211,75,41,78,234,223,115,175,57,229,107,227,179,9,162,15,86,211,207,126,44,120,162,65,99,15,187,57,91,18,41,138,119,15,37,90,138,187,40,13,121,164,30,26,160,7,116,143,9,149,10,228,215,85,75,134,113,241,72,248,12,116,160,177,187,166,188,208,252,178,182,169,220,121,139,203,135,116,198,224,193,215,214,189,110,168,68,129,130,192,8,226,15,122,181,16,37,227,17,156,38,246,249,4,89,193,12,237,32,109,66,52,139,50,235,10,231,210,19,204,191,161,192,238,27,142,203,62,146,194,119,135,132,70,245,214,127,209,179,254,19,43,72,110,124,118,71,34,142,134,163,182,130,140,131,160,56,194,13,10,6,8,136,131,171,206,237,108,163,127,8,17,208,116,17,165,125,236,166,45,180,115,123,110,117,255,84,33,201,176,66,60,220,2,92,128,59,50,147,27,232,7,251,48,118,128,215,225,182,113,163,1,165,184,212,132,246,28,57,13,84,140,97,222,230,172,120,254,160,216,70,239,215,0,111,160,68,51,0,31,109,79,49,38,221,94,95,37,226,200,239,75,160,227,1,122,27,49,244,122,133,67,125,60,12,216,60,89,219,92,146,252,169,205,31,71,112,119,174,142,76,205,10,173,28,31,26,119,222,159,151,151,214,150,124,197,51,174,17,3,58,240,120,130,175,51,87,155,106,76,197,143,86,226,95,45,72,196,34,230,99,248,121,236,163,207,67,132,152,165,42,252,107,111,171,10,114,221,71,94,190,87,197,251,236,116,86,60,82,253,64,166,236,178,150,126,252,230,179,186,45,52,123,29,16,175,237,157,13,213,215,69,153,217,233,51,38,227,186,80,200,188,65,110,196,78,3,202,66,175,161,253,111,249,120,23,44,176,170,211,138,243,128,128,115,108,85,27,23,107,91,1,212,31,154,136,228,166,30,96,59,92,34,162,61,242,225,232,47,195,154,45,144,74,125,246,69,128,166,229,187,39,196,152,5,66,133,189,18,245,235,31,214,153,14,205,11,130,1,238,167,83,107,14,41,235,8,139,62,37,74,87,110,189,142,226,150,1,219,52,58,115,150,62,55,66,239,30,11,157,138,57,159,200,148,184,237,250,169,248,88,159,137,188,98,30,50,189,59,15,225,149,129,184,102,146,114,254,181,178,143,54,171,186,63,219,29,83,52,76,222,208,189,242,11,81,188,87,249,54,213,162,246,147,7,72,54,22,48,119,146,108,131,16,194,137,175,45,132,109,33,243,243,40,190,135,54,116,177,29,228,193,151,91,207,114,183,37,198,58,44,53,196,42,118,27,144,95,155,137,80,255,233,76,228,204,81,135,24,99,82,230,130,134,134,90,185,64,21,78,113,200,124,44,66,8,202,250,219,158,245,90,117,100,130,99,79,193,113,76,66,140,147,91,76,194,35,42,183,235,58,162,251,48,190,103,86,96,173,72,202,179,222,118,203,182,225,42,46,211,245,250,204,238,192,46,2,210,178,141,212,84,160,233,228,60,100,58,151,244,252,138,108,189,119,187,104,222,9,36,11,182,33,204,41,164,233,176,152,233,86,233,50,206,99,64,128,110,66,233,201,123,179,225,189,88,55,210,152,178,238,149,204,213,200,212,190,228,170,205,255,165,46,209,51,91,74,229,36,181,120,52,6,82,169,229,225,218,231,110,222,218,6,179,193,106,30,34,243,244,157,149,112,198,254,119,89,250,217,97,62,28,209,188,203,80,211,129,242,222,66,129,254,133,112,29,113,174,62,6,239,237,224,23,116,214,189,215,75,239,171,17,204,68,178,19,31,37,201,108,153,71,126,166,217,28,201,87,186,193,62,200,110,44,41,74,172,66,60,174,120,134,18,85,137,113,240,138,170,198,225,97,115,26,202,243,51,96,31,18,185,179,52,52,98,63,170,11,216,247,18,9,35,203,107,220,12,6,21,178,236,232,102,112,57,211,73,9,28,24,100,146,157,25,199,182,169,71,71,6,60,175,82,210,8,190,110,18,136,70,15,43,13,60,52,12,43,123,111,248,2,36,45,160,215,73,52,54,36,80,105,210,238,113,115,116,84,251,91,72,109,192,195,188,108,51,89,2,189,86,142,28,210,69,246,138,253,85,224,49,223,6,47,125,40,72,173,56,214,70,132,134,51,244,168,101,112,151,126,77,102,143,239,4,13,116,106,10,103,119,126,65,6,31,18,107,68,76,241,127,130,133,186,61,250,68,253,189,150,134,117,83,51,83,25,187,118,78,134,35,123,184,148,245,53,68,14,88,131,0,68,159,141,48,76,196,130,198,34,56,19,203,64,75,87,26,133,28,73,19,242,167,183,2,251,172,114,9,7,155,151,79,86,68,141,54,101,212,74,210,65,219,237,175,83,252,71,245,207,108,46,196,105,180,46,85,217,5,128,221,226,157,62,176,224,25,140,26,228,142,51,187,96,116,42,92,18,197,211,133,4,0,207,161,141,187,60,8,215,220,174,187,41,153,27,83,242,133,205,30,135,7,207,178,168,111,3,85,173,149,137,68,187,204,184,237,209,59,41,154,36,35,7,212,199,183,241,25,178,86,195,41,137,201,81,164,246,218,251,180,218,161,189,193,147,17,147,15,78,69,23,170,86,93,28,58,170,81,208,143,20,240,63,182,158,203,197,94,135,254,11,135,124,183,89,193,71,88,184,98,208,164,134,197,140,75,234,159,83,20,177,109,123,195,118,229,245,116,207,220,6,11,187,253,37,198,220,195,29,176,38,46,67,200,232,90,245,23,105,165,133,57,29,208,185,232,69,180,3,5,19,111,91,226,98,197,90,102,20,243,203,137,88,156,217,18,24,141,253,17,194,150,75,120,212,232,5,187,191,80,176,71,27,94,71,149,230,108,103,17,129,248,166,186,196,171,152,249,136,146,130,38,204,223,106,175,46,105,241,113,125,212,159,243,233,110,229,177,187,141,186,157,99,212,232,218,25,58,4,212,122,110,11,236,187,184,12,168,127,135,212,37,81,184,79,102,171,143,151,189,158,113,56,80,94,110,58,223,118,37,73,53,158,134,151,251,250,216,143,88,233,8,206,211,238,115,195,53,186,238,140,128,150,50,225,14,236,49,195,224,75,85,229,24,20,244,72,136,144,15,96,152,6,156,158,133,144,200,229,50,186,234,205,77,101,31,5,147,136,55,31,158,100,141,179,213,225,15,161,176,225,156,40,169,60,57,227,45,170,44,97,107,83,178,31,102,192,84,212,43,159,32,188,252,47,248,53,6,68,8,126,187,27,46,133,214,4,199,153,29,177,123,35,170,100,66,253,178,46,37,206,97,62,17,208,98,178,195,223,64,76,251,94,132,241,102,36,130,182,53,98,94,253,122,211,197,204,144,195,101,203,40,158,215,192,102,44,87,233,61,81,147,158,79,117,222,27,26,219,168,15,59,142,65,113,172,49,253,190,191,188,12,59,244,226,238,7,59,116,34,120,56,20,118,83,59,78,142,79,43,150,41,207,228,35,234,182,14,86,50,120,254,31,74,82,5,29,39,173,104,87,10,249,237,158,29,211,250,239,50,64,90,200,107,209,100,26,135,182,38,139,177,27,64,6,87,21,235,204,230,235,222,248,48,156,212,204,138,22,36,123,3,40,93,25,200,55,162,51,116,3,140,58,246,81,78,59,89,103,138,23,220,89,171,48,48,203,181,80,163,171,109,173,17,34,188,238,42,205,32,106,18,122,80,8,247,127,26,32,148,141,138,226,57,27,129,234,74,40,235,202,6,106,127,1,11,117,117,236,240,123,227,139,185,241,205,42,57,186,237,83,21,90,3,25,88,42,109,224,140,238,11,177,108,46,111,28,229,139,95,217,72,101,173,235,131,28,2,85,51,19,52,105,218,235,176,84,57,140,165,80,238,93,92,6,47,138,188,132,100,36,219,223,236,201,112,201,190,0,20,146,68,95,16,147,1,52,108,54,185,188,154,104,247,173,127,160,214,230,207,56,112,98,105,62,42,66,97,101,47,220,193,114,23,202,61,21,118,64,16,191,112,119,123,20,117,173,202,70,39,239,112,202,66,142,163,211,106,89,2,97,150,55,78,226,111,190,170,144,53,195,72,96,89,229,178,153,130,164,161,86,154,154,21,95,120,12,31,122,50,142,245,189,124,17,218,35,201,75,20,203,234,97,11,70,151,3,185,169,71,243,91,56,248,117,103,8,162,90,14,193,33,124,194,169,48,150,40,80,127,37,151,74,195,221,99,145,74,172,228,150,120,147,204,160,67,110,187,30,236,197,101,7,127,128,115,7,243,235,20,66,101,40,114,136,254,206,220,67,96,231,89,65,202,234,82,8,131,187,238,220,213,142,223,77,25,167,69,68,87,110,101,200,142,51,26,234,143,164,214,134,215,222,141,23,42,75,147,88,211,199,154,201,24,72,202,13,136,234,25,52,120,254,136,185,193,163,187,133,84,93,81,133,177,73,126,136,46,251,136,144,180,33,34,18,230,128,47,79,79,106,150,8,58,160,248,106,132,183,215,17,146,173,177,243,32,65,1,175,14,45,235,55,127,69,29,175,177,184,199,168,231,173,143,212,218,44,28,243,157,87,243,247,193,142,155,49,191,221,140,235,246,53,125,204,139,60,232,18,220,63,106,61,252,172,154,140,47,208,189,55,163,20,44,108,250,50,252,255,204,45,52,2,76,66,64,241,107,21,163,134,187,242,247,136,203,1,7,118,226,244,67,198,15,238,194,74,9,230,186,185,49,162,49,71,168,31,130,160,103,223,244,225,108,133,142,123,181,164,114,112,172,100,229,165,150,250,57,212,15,63,204,70,163,4,98,111,152,45,37,45,245,228,45,244,111,124,250,163,197,120,243,232,117,56,154,191,145,196,141,125,8,55,90,132,216,85,224,174,60,253,201,63,198,114,202,235,236,103,174,176,192,65,93,161,74,226,65,222,241,126,119,113,174,16,71,68,19,253,160,250,79,117,231,129,159,61,132,104,164,251,78,110,48,246,12,36,172,100,111,152,87,36,40,95,115,60,227,74,123,204,149,244,119,65,162,114,102,121,19,155,249,117,248,51,151,33,42,115,199,237,144,43,180,51,121,129,23,83,127,226,56,9,32,222,44,201,44,21,7,249,122,183,224,239,85,204,10,181,91,19,103,103,133,205,12,229,38,97,31,108,141,82,255,186,32,185,59,95,66,45,15,41,179,36,56,178,53,39,230,128,252,12,104,165,98,132,4,223,238,44,36,222,188,218,52,250,146,212,148,237,85,68,175,72,79,155,38,36,230,62,122,67,208,138,241,5,49,158,119,106,100,178,247,61,154,161,134,111,198,28,192,44,150,189,7,205,154,142,45,190,172,69,107,176,36,105,64,30,153,120,233,138,210,10,19,201,37,119,182,152,85,43,37,56,68,199,14,82,214,220,245,249,231,141,77,20,190,252,61,102,166,209,230,24,109,225,229,78,195,145,93,109,32,127,163,49,126,248,87,165,80,47,35,155,3,51,50,146,244,105,171,122,226,62,82,242,157,209,37,222,157,224,156,21,73,10,238,198,123,110,60,209,122,158,82,5,221,166,227,119,183,251,80,175,245,112,156,150,175,183,247,162,53,159,213,33,71,40,168,227,104,244,244,210,154,12,114,234,6,153,36,147,203,170,108,85,64,250,110,225,137,2,143,243,163,40,173,220,191,63,210,108,131,154,142,83,175,46,56,41,236,83,221,81,161,144,135,172,99,88,139,115,229,148,143,162,9,203,12,44,238,102,165,234,230,179,179,242,16,227,158,20,196,203,126,102,121,194,246,105,131,73,192,81,122,192,229,32,52,68,139,60,16,102,94,4,190,236,77,238,222,73,240,221,6,252,179,240,56,85,108,237,167,95,168,223,161,49,28,186,57,93,43,203,125,223,42,221,67,47,174,96,56,99,204,115,41,252,252,106,153,180,228,242,100,155,42,105,108,181,215,47,150,176,81,36,192,211,244,135,162,127,189,201,80,62,117,91,125,58,245,215,9,16,165,134,52,42,43,225,155,28,21,189,76,85,226,216,155,133,105,120,60,145,152,6,52,150,149,2,255,255,126,255,45,36,58,37,21,112,25,5,210,187,69,74,195,46,226,170,12,90,154,7,142,228,89,148,22,211,1,150,132,252,99,19,215,135,242,15,150,0,17,251,192,38,133,71,164,62,161,144,240,178,62,63,254,50,137,26,207,233,156,52,145,94,86,239,132,26,146,181,46,165,248,100,14,76,252,16,214,130,195,166,67,120,113,30,255,126,197,11,57,108,130,66,163,177,70,30,223,117,244,53,44,13,86,39,70,58,213,212,230,152,164,76,152,10,227,3,6,230,216,73,88,108,91,245,126,137,58,224,132,168,129,199,254,247,134,142,56,81,168,160,119,44,222,123,230,189,204,92,245,18,227,172,58,240,174,149,68,71,210,183,169,241,146,73,86,210,216,156,250,239,161,219,212,210,69,48,33,137,81,185,192,218,197,2,122,26,76,13,121,61,31,44,239,37,158,126,254,241,131,26,167,224,67,133,125,52,204,195,141,119,131,208,214,151,86,54,137,139,144,178,173,220,170,156,70,125,66,38,125,127,135,146,246,160,95,230,1,248,184,55,65,56,225,139,169,106,17,246,153,98,119,248,67,85,148,28,157,200,233,186,149,138,180,147,37,42,212,190,28,189,109,117,242,168,56,133,17,29,241,89,218,5,242,81,50,61,166,175,124,106,47,237,20,201,235,69,95,202,35,243,79,223,34,85,47,100,252,168,29,171,20,189,109,65,14,156,71,195,246,94,104,211,21,29,195,84,33,131,207,221,120,139,57,78,126,88,195,191,172,133,96,242,110,140,236,227,76,154,55,32,134,193,20,204,21,192,232,157,224,147,175,193,96,9,127,18,107,239,96,240,98,139,149,104,92,151,196,170,198,104,185,117,179,26,20,72,48,36,47,32,86,42,189,173,80,71,219,151,79,181,88,45,26,191,38,133,45,54,131,31,109,115,161,163,34,38,89,40,49,173,198,48,17,40,39,121,77,90,70,42,251,130,168,125,184,76,60,95,94,136,227,248,145,210,226,191,137,247,72,210,17,141,52,5,102,220,23,111,146,114,218,208,22,105,9,130,97,83,57,25,228,137,6,99,12,24,29,89,25,101,217,133,196,253,246,158,114,75,8,90,142,28,147,19,22,164,240,205,1,21,145,19,225,61,98,21,22,215,32,158,9,44,97,148,104,201,219,76,43,45,162,73,151,252,188,155,192,134,113,103,109,255,54,42,206,24,76,87,154,98,187,78,193,50,86,191,222,86,162,165,38,191,118,117,72,31,6,174,147,231,105,158,70,133,79,138,223,55,73,210,90,194,194,112,167,14,253,133,160,197,234,193,24,75,239,106,47,115,70,102,75,122,123,87,158,185,162,180,84,210,222,141,172,125,211,117,181,155,250,182,51,247,178,100,123,8,8,173,224,246,222,40,35,31,171,203,195,36,34,6,53,171,105,219,106,216,77,18,130,182,37,225,3,235,196,203,114,168,7,2,10,14,230,118,6,134,118,20,184,145,213,218,127,110,182,193,145,91,202,110,11,96,118,1,8,96,103,167,236,180,15,141,151,253,100,7,112,25,70,89,121,233,178,158,234,47,68,162,185,146,146,7,74,2,17,238,108,171,91,64,92,173,85,82,121,240,175,136,132,26,123,225,64,169,132,53,192,187,113,8,165,133,192,249,61,166,108,170,2,175,11,243,183,162,93,109,51,151,40,206,39,150,0,84,130,215,29,211,96,200,244,193,206,63,137,9,225,205,195,93,147,70,125,177,146,164,76,247,0,61,118,12,73,75,151,145,218,82,180,207,112,233,175,169,104,180,29,149,4,129,248,70,10,159,34,67,208,4,235,146,205,128,223,104,17,16,189,72,150,29,148,21,85,152,237,97,200,84,57,234,9,165,16,73,40,118,10,18,222,171,43,231,169,211,149,179,250,145,227,129,66,53,2,35,228,99,7,1,101,161,122,247,98,103,47,32,194,21,66,228,215,171,211,95,93,47,71,164,197,154,72,46,73,190,186,131,152,104,252,1,237,94,154,240,6,67,188,57,183,3,28,30,181,14,142,247,193,242,88,231,188,86,198,130,125,97,9,115,137,196,6,38,94,170,51,157,253,197,152,195,181,150,253,125,49,6,217,29,102,120,252,248,217,191,232,176,151,7,118,12,126,164,219,67,123,72,16,146,223,203,183,0,196,87,186,185,173,67,246,204,171,20,21,86,98,182,253,7,186,6,120,189,118,3,229,237,60,53,90,120,139,87,229,79,153,85,139,16,81,100,189,150,202,125,164,42,132,10,163,190,85,177,69,169,181,85,186,64,77,182,99,209,185,183,19,5,1,24,167,247,211,71,7,154,124,136,40,199,61,196,217,202,170,170,93,64,20,178,234,247,41,59,124,192,158,211,128,28,144,37,95,61,108,113,150,27,161,102,97,250,86,162,10,193,27,201,55,193,56,84,164,176,59,172,180,2,117,209,83,226,255,156,104,115,80,9,171,177,196,38,252,19,138,252,29,242,231,74,93,205,161,41,158,79,204,211,0,30,248,42,125,237,167,151,3,163,35,219,102,225,38,80,160,246,91,202,15,81,5,104,108,210,239,193,131,146,27,150,17,171,71,221,84,112,204,146,94,186,237,255,206,118,141,107,20,169,226,15,43,75,224,52,120,186,0,134,235,166,30,237,98,31,139,146,29,104,64,56,3,249,66,92,147,217,211,9,31,96,178,69,148,227,230,101,236,243,45,246,172,39,229,59,69,106,63,147,212,148,179,217,10,220,19,61,36,147,54,173,248,250,238,79,181,163,211,105,11,79,136,249,56,91,202,219,147,180,212,42,140,52,110,222,216,92,215,61,213,55,188,33,239,190,201,255,96,1,215,85,244,86,49,152,17,180,172,68,196,115,71,107,182,243,219,136,48,23,116,210,242,8,233,123,235,101,169,61,55,63,1,51,205,161,189,96,59,52,218,197,250,26,88,73,52,217,104,199,216,234,189,209,12,232,29,210,128,20,244,127,219,15,204,123,222,84,167,249,54,43,174,28,118,186,210,116,176,58,78,38,166,130,144,219,92,43,91,180,1,195,20,39,139,0,25,240,204,75,61,178,95,199,10,3,136,139,50,249,155,86,95,70,214,41,166,76,132,6,166,146,35,118,145,100,203,149,154,211,215,94,104,5,44,83,183,45,251,89,212,57,197,144,82,87,170,120,45,105,80,129,100,131,159,10,127,221,163,246,63,192,154,53,205,6,127,117,223,24,147,216,93,28,239,163,214,221,158,12,149,255,83,88,41,136,165,138,1,254,6,44,25,143,22,104,150,94,24,196,25,238,193,216,170,71,103,76,33,52,211,45,205,235,134,41,248,86,65,9,32,255,32,95,30,250,243,251,43,119,170,184,85,107,38,21,98,231,54,218,226,16,72,174,6,221,38,211,120,221,119,117,120,67,209,251,33,84,155,163,163,47,53,96,15,51,76,204,87,153,85,170,54,66,113,12,174,34,104,136,90,62,76,103,210,150,82,37,200,148,44,89,113,229,33,173,240,114,61,21,131,193,157,216,181,193,207,219,29,42,99,21,186,158,11,145,155,4,216,22,244,162,245,120,63,128,57,117,241,213,60,251,251,149,87,153,99,63,22,75,81,103,103,239,199,225,110,110,88,38,125,240,116,161,226,53,38,183,2,223,68,221,87,205,73,201,187,129,82,39,35,166,109,116,96,250,15,15,242,104,227,86,21,140,48,172,188,54,214,185,33,4,199,217,220,218,185,44,244,170,133,64,135,231,135,80,159,130,65,112,36,250,209,241,226,74,174,130,199,202,217,218,87,161,162,130,254,242,150,34,63,117,178,224,76,211,80,201,111,72,69,137,93,62,24,23,249,115,80,83,95,17,166,84,223,132,120,6,53,34,199,208,205,80,109,133,213,92,49,18,214,230,123,245,73,80,228,94,106,241,165,216,84,255,96,177,178,90,92,5,219,185,153,238,208,136,79,150,15,232,139,179,52,146,235,158,62,239,136,154,45,92,190,176,19,91,40,214,152,149,209,222,247,97,175,74,250,98,231,204,211,233,2,168,136,18,202,254,144,196,95,80,187,220,123,31,164,176,207,23,248,81,3,174,138,206,65,83,36,29,70,32,71,21,227,157,254,228,2,4,215,71,27,252,9,219,49,49,23,248,163,43,170,192,126,75,198,97,91,38,182,93,204,141,250,187,145,128,158,103,88,73,178,191,233,253,231,3,169,38,117,163,181,44,217,91,138,15,239,82,140,19,78,13,168,212,227,46,202,225,130,28,150,211,105,239,25,243,208,76,174,52,37,170,87,125,141,221,90,95,41,51,53,205,112,75,54,129,102,51,87,222,28,117,188,154,174,103,66,55,95,247,97,127,31,107,22,117,195,115,97,108,19,52,70,179,212,190,15,8,213,49,139,119,170,201,169,8,199,203,166,183,90,134,185,169,133,135,9,251,66,104,187,220,182,164,82,21,125,132,197,116,14,169,241,211,104,107,169,17,246,140,46,235,236,23,84,93,180,72,214,10,39,185,197,170,73,30,43,35,75,114,202,126,143,2,127,114,206,107,25,116,183,11,43,3,146,183,121,214,79,26,240,70,203,45,88,74,11,137,245,21,38,44,66,143,61,168,69,76,204,92,186,121,203,15,46,213,237,131,23,220,68,52,188,111,185,48,81,35,208,159,218,44,76,71,236,152,61,103,92,247,136,123,88,196,109,213,91,97,190,88,164,237,171,59,217,231,230,51,149,191,114,162,41,91,249,249,25,109,183,231,25,48,30,35,44,156,199,26,146,144,26,85,40,82,54,83,253,102,88,29,52,114,160,176,0,95,4,217,205,123,143,97,62,149,15,178,195,166,156,183,183,170,183,54,232,197,211,241,7,215,241,86,159,151,161,98,116,91,139,14,111,22,41,155,5,43,72,245,246,20,196,27,62,112,149,21,253,42,111,173,148,25,42,199,41,53,84,169,17,246,92,25,211,161,41,159,252,62,243,4,19,121,43,66,199,74,28,208,193,205,33,126,84,173,30,16,26,179,244,95,188,90,6,16,178,251,191,203,121,130,161,12,52,170,24,14,141,2,163,190,6,52,205,187,57,245,252,9,53,65,132,246,126,90,3,26,54,238,222,74,237,35,163,214,83,43,254,139,112,244,74,15,241,20,255,217,117,129,81,233,181,187,160,29,30,245,145,199,163,29,171,87,228,222,50,229,60,139,23,152,179,33,23,124,180,100,223,209,21,191,93,240,166,209,66,67,28,158,237,190,62,80,188,131,151,72,22,159,212,121,139,49,254,184,106,134,122,77,103,165,81,70,69,174,0,7,179,26,152,234,23,37,155,212,120,59,223,226,216,189,170,9,42,206,10,123,140,130,214,229,149,218,74,215,152,151,235,170,53,33,209,190,193,105,61,182,108,226,176,32,213,78,117,106,23,56,121,61,82,213,107,121,107,114,185,20,99,151,57,44,105,153,238,174,24,192,241,254,251,80,193,143,221,0,58,227,109,190,129,185,22,131,37,221,129,34,101,144,152,33,250,198,183,73,236,69,174,215,68,64,181,94,33,132,40,149,248,252,133,191,99,245,130,21,43,49,211,224,204,33,169,240,230,120,107,228,46,140,168,241,32,17,95,48,147,101,16,176,251,83,160,253,105,171,56,79,198,139,36,48,144,120,99,236,171,235,56,117,196,171,178,244,170,61,79,183,32,202,66,50,130,211,99,78,199,73,255,242,30,138,199,156,129,107,187,182,255,144,201,230,138,199,111,154,10,126,232,144,99,117,187,160,97,221,177,191,5,239,139,181,240,32,249,247,61,216,207,154,217,224,246,49,118,3,194,107,197,233,3,242,99,182,58,45,151,176,238,101,118,57,44,123,195,112,61,129,140,199,98,25,86,104,2,141,220,161,128,109,32,8,89,147,249,11,246,14,255,195,81,233,46,89,37,122,225,211,69,132,120,138,169,254,0,72,208,116,247,244,60,55,28,135,15,11,28,174,65,40,253,148,181,6,57,220,134,224,205,255,225,22,228,49,200,228,182,179,141,237,217,9,47,114,203,57,24,173,236,15,100,174,120,178,73,84,236,141,45,188,142,252,66,85,56,248,161,247,21,240,209,145,198,24,158,227,106,158,18,248,204,21,1,99,35,91,187,157,228,98,106,35,231,158,103,53,119,135,62,168,207,48,5,118,236,117,255,204,65,60,49,102,180,55,82,149,17,205,214,182,198,223,77,55,234,99,156,29,161,90,22,138,7,126,240,213,226,110,63,214,97,71,161,203,216,10,31,25,62,71,223,163,238,97,14,115,144,121,112,103,4,186,16,66,51,105,110,65,111,32,206,82,213,231,74,107,199,255,85,48,249,19,123,45,142,3,104,77,86,181,99,8,158,50,3,108,43,23,113,246,189,180,107,134,24,9,137,36,178,9,176,197,63,33,63,164,220,217,243,175,16,197,210,28,16,109,192,143,193,240,252,44,124,8,108,179,168,171,135,107,32,216,49,136,123,109,133,33,176,167,185,189,30,120,210,5,211,14,127,118,199,147,121,246,58,33,239,172,251,87,223,152,144,13,169,216,65,87,59,132,210,118,116,30,68,72,68,155,103,230,81,33,26,21,82,14,73,251,183,147,86,222,194,97,44,169,244,82,155,95,253,205,116,91,165,44,64,31,163,242,253,93,23,26,209,14,33,97,62,148,115,63,247,111,137,13,9,163,215,243,223,218,10,114,82,195,219,233,24,117,167,173,231,13,156,77,46,231,130,200,122,169,91,49,229,215,250,140,73,229,240,44,212,41,117,112,31,126,218,196,58,241,101,147,26,195,148,98,153,198,104,87,90,149,128,60,239,177,50,49,11,242,239,230,196,182,89,101,80,215,168,143,70,48,53,53,215,22,99,194,129,245,128,163,40,102,25,14,99,189,152,35,135,13,16,105,137,188,32,226,246,176,38,30,36,65,146,145,240,83,103,2,107,133,21,172,41,239,28,250,134,170,228,80,43,122,211,87,111,228,168,29,171,79,69,62,152,18,69,203,96,169,144,83,50,37,65,208,1,113,46,2,67,73,221,2,181,73,185,209,20,163,237,141,222,221,69,220,155,12,177,239,150,84,234,58,111,225,3,31,187,110,139,78,139,234,186,202,73,72,34,125,59,43,206,220,68,6,49,123,14,147,144,206,60,95,31,173,236,244,239,64,11,119,89,226,7,117,175,218,115,104,165,195,209,202,140,132,15,6,115,213,209,69,238,7,89,37,249,156,158,67,124,208,100,194,232,148,52,214,125,166,99,224,152,46,109,187,234,230,51,60,189,191,120,28,13,67,152,105,230,40,147,153,215,16,149,231,51,170,159,88,97,228,216,161,34,87,65,129,153,213,186,140,150,104,113,164,25,120,246,58,78,221,124,33,179,135,7,220,233,68,9,15,123,101,187,131,139,95,177,234,29,215,24,57,107,53,194,252,161,247,70,224,245,22,104,10,41,39,213,190,186,249,159,32,28,196,55,153,225,205,18,72,227,70,120,101,199,237,132,225,10,124,88,154,151,215,153,67,177,100,244,99,169,37,127,97,122,188,216,217,79,187,227,87,69,243,42,139,151,228,79,141,154,88,240,7,29,255,165,129,150,70,173,212,207,194,245,243,54,210,111,168,77,71,140,61,28,64,106,8,196,60,68,154,18,110,22,252,63,172,163,34,138,138,105,145,101,244,110,11,75,95,244,220,224,140,191,243,85,79,137,128,246,173,146,28,1,68,146,131,190,104,107,105,10,183,141,149,204,59,176,190,91,3,180,254,33,47,24,58,4,53,177,211,193,103,6,161,57,156,191,177,108,76,83,185,133,20,167,103,26,75,148,54,239,124,182,71,95,160,157,60,112,22,149,136,53,82,150,241,250,192,35,199,124,207,79,66,84,131,7,63,140,114,16,166,158,30,0,73,131,202,144,116,46,50,92,60,23,147,147,14,236,195,64,128,205,63,248,146,1,49,182,30,96,166,149,196,243,131,88,93,119,167,118,22,137,56,179,169,223,194,48,235,4,196,19,7,210,55,75,235,92,247,15,83,174,53,132,172,34,214,91,205,147,70,34,195,103,132,175,68,245,7,227,205,122,160,7,72,137,123,51,243,8,7,82,113,179,53,171,249,151,156,75,82,204,101,194,53,247,2,201,39,125,151,8,4,189,190,40,95,41,72,181,116,99,58,100,136,118,164,13,191,107,164,69,39,229,204,2,248,254,87,112,64,247,106,105,66,193,73,104,67,75,181,248,105,39,227,153,139,164,41,215,76,244,118,95,99,56,13,94,20,67,33,205,238,108,249,81,105,60,177,18,155,229,73,173,205,78,164,144,180,161,191,210,203,150,190,16,55,228,110,203,212,118,15,103,25,67,152,199,2,36,17,117,201,129,88,197,112,153,188,44,58,196,160,131,198,150,19,223,209,224,90,127,231,71,1,40,82,195,12,242,223,233,211,68,210,32,176,1,106,119,179,211,33,221,107,210,194,227,213,88,3,122,19,130,145,199,16,66,179,41,215,40,18,133,40,191,25,49,31,101,27,16,11,60,119,20,186,217,168,204,250,28,173,159,38,166,106,2,35,49,133,30,16,174,41,134,5,154,247,72,247,171,23,225,89,228,141,14,221,122,56,188,54,252,90,121,252,169,8,168,27,59,138,8,245,70,122,230,65,165,140,117,136,206,11,169,209,146,240,8,234,87,27,21,119,136,227,84,138,65,172,42,227,109,202,167,67,219,148,125,32,179,242,176,224,42,235,163,145,195,63,145,122,135,21,164,85,133,249,38,87,145,90,3,151,203,189,99,172,189,248,86,207,193,226,138,44,42,179,190,99,83,127,92,185,32,159,58,246,239,241,246,235,227,205,219,169,42,77,149,0,212,210,172,47,174,68,122,133,7,78,152,86,30,65,58,84,65,40,113,125,213,150,112,146,1,46,218,175,242,206,243,3,22,233,246,135,129,96,57,130,15,151,104,91,220,169,42,107,34,44,14,229,23,97,55,219,134,96,213,252,133,227,120,195,1,46,17,86,212,120,130,91,248,166,233,51,66,254,106,183,117,42,44,36,169,196,204,173,91,96,109,228,171,28,189,45,250,183,121,167,12,164,164,245,225,177,164,170,138,139,161,93,90,83,85,26,198,104,106,203,108,131,144,196,153,22,188,229,99,101,228,68,84,115,35,112,19,129,18,184,189,228,220,191,206,106,106,126,188,176,42,150,208,166,249,215,76,49,78,167,49,137,16,206,210,203,31,206,130,158,233,143,12,168,123,152,246,181,110,5,9,143,33,8,20,72,188,117,52,80,18,200,90,101,236,228,207,56,241,5,217,53,40,86,180,67,214,216,113,227,232,42,4,123,161,29,225,131,69,60,164,193,158,200,54,177,14,32,137,153,25,110,144,200,246,156,194,61,16,88,79,24,113,181,5,133,88,82,165,176,38,251,156,45,231,111,141,37,120,107,195,254,51,23,243,143,18,30,92,222,216,31,27,168,49,204,158,75,50,29,108,173,189,227,162,147,5,233,159,187,189,71,11,14,221,15,68,223,60,234,186,227,182,193,229,131,242,98,115,34,126,30,59,20,56,101,249,9,38,148,110,79,181,179,181,29,240,61,110,204,161,242,160,184,30,38,49,180,136,78,22,156,1,249,192,217,132,67,3,250,243,132,141,231,10,84,231,97,122,73,28,88,116,105,213,193,202,47,183,216,19,80,71,55,14,123,32,194,193,121,208,234,113,73,234,146,93,189,196,164,129,140,201,122,187,60,67,10,121,125,17,246,192,134,16,58,220,3,66,88,63,127,197,206,164,85,151,11,143,43,109,35,215,25,113,90,99,90,205,22,209,122,41,112,244,206,253,59,161,241,168,251,89,190,186,151,193,3,142,219,1,102,68,147,87,145,74,157,223,203,18,248,51,21,219,92,9,251,196,149,82,153,103,27,151,252,54,21,4,47,205,56,172,183,3,29,202,225,83,16,70,15,21,227,219,225,178,248,157,53,135,57,185,163,37,123,167,126,80,187,41,181,17,191,207,228,71,37,158,205,118,62,248,250,194,59,71,214,167,103,233,25,73,205,178,231,128,78,53,113,28,73,140,86,87,88,87,238,196,137,77,234,138,39,195,39,117,89,71,3,123,115,108,182,175,148,180,142,193,159,155,141,71,168,172,98,136,187,112,36,25,146,98,217,160,17,34,77,55,98,189,208,173,74,117,181,200,124,182,123,12,56,62,149,214,75,112,112,107,126,242,224,85,234,235,172,131,250,233,229,99,14,92,194,36,21,156,167,172,215,243,141,214,57,79,177,104,94,207,160,8,3,102,237,50,84,126,223,147,92,211,221,196,52,130,24,176,159,132,65,156,131,71,126,4,33,143,91,104,28,50,153,209,95,181,28,75,113,70,67,27,109,192,39,174,135,252,172,218,211,94,160,62,199,154,79,251,16,22,195,15,22,140,253,36,242,85,72,147,22,121,33,25,195,83,123,67,179,160,66,85,146,45,114,228,93,116,57,55,217,212,216,31,50,167,229,242,19,107,240,57,124,255,142,191,249,148,74,39,163,43,156,151,201,207,220,46,185,27,203,141,137,15,92,5,101,198,159,181,2,84,128,42,9,10,185,221,175,55,128,247,131,98,98,146,152,8,240,110,121,15,67,233,2,21,145,83,105,182,127,239,100,153,185,165,225,124,59,119,26,175,192,81,4,98,42,93,184,200,34,68,13,134,123,5,43,164,167,218,32,67,79,70,4,196,254,131,50,201,157,133,80,79,208,242,155,224,237,252,110,27,249,238,45,235,77,229,182,93,205,123,32,5,3,78,154,69,213,117,216,130,198,46,105,47,78,76,255,250,230,254,99,106,218,110,21,186,185,71,173,236,91,67,119,59,38,141,202,223,39,183,153,239,2,113,168,121,123,54,217,55,237,94,11,1,190,38,16,170,216,147,239,88,254,229,245,220,108,102,247,55,229,237,173,167,179,231,185,82,226,109,53,81,87,15,55,217,69,204,109,3,164,126,143,193,42,141,227,90,36,226,83,128,215,12,177,216,190,140,85,129,225,224,25,74,141,225,41,192,131,60,180,130,169,191,124,58,1,135,224,63,27,9,138,244,124,167,199,35,2,120,62,25,218,238,78,254,29,125,60,19,72,168,31,194,52,28,70,137,193,242,203,2,91,43,138,248,5,135,204,165,116,67,10,198,121,98,100,238,143,43,94,209,39,162,232,129,176,41,254,158,40,195,167,51,206,48,151,123,55,64,65,233,220,176,238,73,3,129,139,129,242,194,88,95,199,147,187,75,237,229,171,30,89,115,154,239,165,169,235,59,98,63,177,91,115,84,142,203,97,103,79,66,2,91,157,207,14,45,246,75,211,46,69,228,42,158,158,132,228,178,36,163,98,194,69,11,37,186,217,155,206,244,54,125,9,122,128,237,37,159,232,91,68,159,92,116,153,244,199,136,214,88,171,186,117,98,60,171,163,232,45,147,151,123,170,237,130,250,83,244,253,125,237,248,178,237,111,15,63,154,122,147,51,15,60,204,111,139,245,231,228,185,51,36,176,237,79,48,4,150,130,163,59,120,29,126,54,40,104,116,142,238,121,237,189,107,191,35,8,119,113,131,109,108,173,24,9,142,108,8,49,51,202,146,192,173,17,1,241,218,187,124,164,246,139,220,70,143,192,138,152,227,175,189,77,209,86,106,63,119,2,159,194,2,163,89,30,119,83,127,152,98,60,123,145,96,155,67,36,124,94,20,93,243,98,219,253,143,238,124,45,39,226,10,242,116,227,184,129,242,21,192,51,94,97,231,64,148,237,211,59,177,198,10,216,238,62,4,109,230,168,9,132,240,215,0,86,29,251,174,78,233,243,27,50,92,197,253,214,2,123,146,246,222,140,146,148,108,237,15,4,222,247,156,154,132,10,40,151,8,10,70,114,132,181,145,136,176,233,7,169,57,111,204,90,220,67,215,132,40,150,216,152,69,54,80,43,171,67,46,100,140,33,185,115,58,154,35,242,247,6,43,31,174,39,80,101,216,73,40,132,227,201,14,85,37,194,50,3,146,118,78,76,36,211,88,24,220,98,14,33,120,148,222,160,20,160,118,195,167,167,92,128,37,5,53,38,72,206,146,123,57,213,135,200,109,71,35,239,160,169,225,222,136,217,153,92,67,165,51,105,189,47,203,155,237,217,9,216,232,29,225,177,49,205,230,232,177,124,66,19,114,207,198,114,64,45,161,124,66,110,85,157,81,102,32,22,83,53,111,196,27,133,196,169,162,223,120,126,235,105,163,132,221,206,150,110,214,226,227,26,172,30,160,193,251,235,130,209,125,165,77,58,39,115,187,196,165,24,148,33,237,15,73,76,51,191,88,212,165,137,89,220,47,35,108,174,114,48,214,113,39,163,180,185,63,88,233,112,0,120,241,137,168,24,63,138,54,82,207,177,179,66,101,46,177,222,3,52,49,103,68,5,246,78,182,234,55,35,29,9,19,192,144,78,132,224,162,148,96,89,62,61,109,6,178,98,241,196,88,167,22,196,56,11,139,35,94,112,213,134,206,158,24,179,145,144,24,250,44,149,253,67,210,8,0,244,166,243,0,180,234,155,46,191,122,41,93,142,70,154,56,201,66,159,207,162,193,63,26,46,204,221,206,29,100,232,161,225,87,106,130,47,154,66,253,50,33,4,103,71,134,239,65,137,220,222,90,200,221,145,253,16,73,125,66,213,113,239,82,209,96,85,98,196,87,143,30,250,24,217,92,120,23,123,71,64,51,243,204,192,239,147,75,30,170,32,161,187,95,176,78,235,9,173,103,112,9,93,39,55,89,66,223,135,55,158,58,28,249,4,53,46,175,138,48,65,135,70,136,1,162,20,77,236,103,41,150,88,60,162,162,221,75,62,108,114,118,100,40,120,101,241,122,160,0,109,225,54,161,239,188,6,149,136,139,198,177,179,32,43,126,52,149,57,217,226,136,215,201,55,32,213,229,87,28,109,36,223,42,151,98,71,107,140,255,230,206,183,84,127,109,108,57,226,37,11,140,188,250,216,82,32,241,186,122,68,173,128,81,29,57,2,23,81,10,233,198,238,113,91,11,7,17,184,180,159,230,116,147,143,120,21,24,1,220,118,49,16,80,204,12,78,41,111,117,193,98,56,148,193,219,160,156,230,56,126,1,172,183,95,204,229,202,75,218,108,245,33,254,8,58,127,98,209,197,176,100,60,110,139,133,80,43,42,133,200,12,216,121,186,89,171,171,252,220,132,121,46,180,75,79,8,157,91,112,112,34,247,193,147,132,119,236,30,223,101,129,132,197,45,134,84,202,92,249,70,208,211,158,206,209,216,202,106,106,96,1,80,249,182,103,247,124,85,169,42,212,67,245,112,214,156,147,143,216,186,202,197,119,5,230,23,226,199,79,150,253,252,85,1,193,145,96,212,15,165,73,246,244,50,249,165,95,254,252,112,62,100,237,167,234,181,238,164,135,224,175,19,225,82,153,135,122,209,81,59,123,165,21,127,99,54,56,18,153,226,205,161,95,202,7,79,126,124,92,208,244,46,5,176,227,206,200,16,140,97,250,131,187,54,34,117,52,52,206,150,201,200,182,45,201,225,80,46,100,113,199,193,12,116,224,253,59,85,244,248,161,239,199,164,208,63,114,103,163,167,185,246,203,19,33,102,53,236,108,3,205,170,155,230,73,204,142,178,233,7,187,171,191,137,254,60,149,218,98,40,42,87,10,3,146,207,162,67,113,25,173,141,27,217,143,225,97,164,2,208,116,57,181,180,112,233,183,114,62,110,197,29,79,155,213,7,115,94,60,229,43,83,79,119,171,196,20,78,239,233,51,87,6,32,5,59,166,121,176,193,0,2,145,150,183,130,7,36,179,159,57,212,66,179,111,151,174,27,202,58,35,12,121,174,29,17,69,244,46,87,1,173,238,194,40,107,180,147,157,209,184,241,104,251,123,242,164,42,31,93,118,82,79,189,47,105,102,158,30,210,164,16,47,140,226,212,235,70,176,78,30,247,193,162,137,19,102,181,9,248,156,29,149,41,73,2,34,88,183,198,106,254,34,124,19,150,32,99,71,253,14,190,121,107,200,168,38,114,205,153,112,139,204,16,149,101,168,127,70,40,156,157,78,179,113,220,4,46,194,124,96,187,139,83,36,28,169,50,209,88,176,134,217,219,55,18,186,165,170,11,175,60,216,24,132,95,218,101,75,194,66,64,184,1,56,29,86,92,86,243,122,204,124,185,21,219,37,111,68,82,178,41,69,127,186,121,223,219,84,41,169,105,54,165,5,128,102,12,67,130,217,46,97,233,254,216,57,121,145,39,46,34,136,82,175,114,153,215,16,119,138,116,45,137,136,230,59,132,221,97,0,150,250,153,211,18,141,254,212,157,9,45,217,191,16,24,133,130,194,151,189,230,92,187,55,12,247,187,8,115,13,29,222,207,59,92,230,24,146,39,165,2,54,188,107,162,190,178,185,22,188,187,172,42,164,239,225,92,55,26,237,230,59,0,75,13,33,47,250,12,161,72,4,185,159,244,163,208,129,102,176,239,178,99,211,97,92,241,234,19,85,70,42,189,55,130,151,119,38,50,126,239,231,40,153,124,51,220,63,234,208,163,211,170,63,37,231,40,152,183,204,90,227,246,208,8,196,85,209,243,92,102,174,199,27,110,145,27,1,158,35,176,107,152,163,227,75,21,184,120,238,57,155,201,3,194,165,57,117,211,136,236,17,128,98,177,93,111,46,94,137,155,5,70,101,212,42,190,79,218,62,143,123,151,171,59,185,175,9,185,245,254,235,130,177,69,252,61,157,29,229,105,128,229,192,180,37,158,214,254,13,129,64,53,209,247,56,140,241,97,250,119,174,250,204,68,97,184,208,29,20,117,25,12,105,234,224,76,223,115,197,177,7,235,247,19,42,20,85,78,15,81,181,192,153,4,160,176,82,106,67,212,194,132,240,190,45,126,79,192,122,42,28,239,165,14,139,14,152,62,129,78,48,66,45,207,97,240,165,178,129,234,169,234,59,12,218,46,249,54,76,20,225,254,11,128,237,242,61,101,16,36,207,202,13,244,205,77,104,204,51,50,1,5,95,211,151,110,251,255,185,191,151,167,102,140,98,163,129,27,38,60,101,197,176,252,212,232,136,208,157,118,51,83,111,209,188,223,78,130,47,24,91,236,170,159,121,55,3,202,0,155,212,180,173,74,37,161,201,91,108,166,174,27,239,60,20,65,158,225,185,85,89,127,76,244,27,86,150,160,201,13,106,79,143,68,200,236,55,107,243,76,149,215,188,118,183,198,159,26,140,136,153,211,173,159,16,57,139,31,93,149,70,6,141,53,112,164,6,184,239,106,159,222,67,158,26,121,136,223,39,46,140,67,170,202,95,88,179,214,186,212,140,8,12,94,34,77,226,17,17,162,210,225,20,151,177,74,9,100,126,170,73,142,33,144,154,131,151,205,235,28,118,190,6,137,98,50,237,7,94,230,246,133,250,179,160,199,89,103,9,203,111,37,216,185,171,40,117,6,107,87,133,165,172,22,140,220,186,41,97,187,57,196,102,220,15,169,194,254,170,33,237,69,78,127,4,30,119,51,251,153,50,179,106,153,232,131,96,100,243,32,78,78,223,191,150,158,39,30,201,43,12,220,233,103,223,247,156,210,213,52,75,203,102,114,46,35,81,55,175,89,207,53,66,198,247,164,132,51,64,124,120,125,108,35,3,184,185,202,162,122,93,58,198,11,176,146,221,62,6,92,250,135,230,38,135,125,76,89,22,140,243,110,14,212,252,94,85,234,86,142,168,158,28,94,124,183,180,213,174,80,170,142,88,83,48,201,169,249,109,156,83,4,161,186,46,235,85,83,86,244,7,52,58,188,19,124,117,35,105,13,185,191,47,252,142,77,194,147,27,235,193,126,138,65,32,134,118,24,227,33,219,142,48,59,235,147,8,183,94,74,184,233,4,78,44,55,20,167,190,216,145,187,105,253,135,93,68,15,204,76,81,176,255,140,229,106,248,29,154,109,79,247,240,181,62,181,2,28,187,26,136,254,180,92,158,140,81,194,11,245,237,48,28,57,112,87,48,233,185,13,251,113,29,199,152,222,226,254,232,119,199,120,251,113,224,226,89,162,215,74,115,227,118,145,197,176,156,161,226,233,79,170,203,163,113,106,144,108,25,85,163,91,129,143,75,216,56,51,156,13,106,116,79,121,79,152,139,128,156,169,174,94,228,172,49,115,235,134,42,145,67,107,214,122,8,49,156,210,218,178,151,67,247,169,0,56,164,44,222,132,125,193,90,153,10,15,29,69,159,229,98,193,181,138,65,215,14,65,89,116,209,247,174,22,72,27,141,214,94,36,169,203,34,123,25,192,248,196,238,148,225,225,253,59,44,43,96,2,26,21,96,123,202,184,253,55,162,172,81,29,95,172,11,133,235,129,224,183,94,71,85,29,23,65,246,242,222,224,109,136,62,63,145,107,248,167,160,195,242,204,135,237,253,107,53,91,77,34,207,186,102,102,84,28,14,44,194,39,232,156,245,132,232,76,102,63,206,240,49,132,118,211,1,70,75,30,42,3,149,207,174,223,160,227,64,221,207,62,64,74,186,97,163,201,85,231,33,84,76,132,47,66,189,73,137,21,77,184,234,168,231,171,247,76,32,229,1,138,186,116,5,60,65,8,57,133,57,165,125,190,51,105,242,89,1,141,234,53,168,34,89,88,55,63,52,10,226,116,30,115,175,214,74,234,133,248,48,242,17,47,155,75,131,130,124,207,192,199,156,142,142,119,122,3,15,49,119,155,82,80,171,180,19,29,133,31,247,222,9,245,206,244,22,69,12,85,112,250,23,97,212,191,32,152,5,115,206,31,197,19,250,138,219,130,3,84,216,78,11,80,213,13,161,199,128,136,64,7,53,223,221,247,108,10,139,128,47,36,225,149,145,94,106,22,86,14,62,13,43,181,226,188,243,228,218,231,144,137,51,46,13,237,21,72,193,233,132,28,220,20,8,4,122,72,237,253,246,222,239,176,0,105,79,66,248,100,211,232,18,217,109,127,11,57,83,34,123,20,60,137,153,193,152,195,96,127,130,205,193,250,201,146,44,174,91,40,108,105,104,231,248,136,114,61,136,124,241,31,128,186,165,230,218,248,76,54,35,51,13,80,241,46,59,34,214,111,253,168,149,252,124,4,81,171,131,110,58,165,172,223,166,5,45,240,154,11,195,26,117,137,238,192,41,98,219,74,113,235,25,234,46,9,144,57,228,196,138,122,230,73,229,42,31,24,18,166,217,131,24,95,177,251,18,240,249,10,235,122,112,16,73,162,6,70,8,231,108,54,87,216,194,174,60,128,244,234,190,212,213,146,128,244,187,133,74,29,128,195,60,234,120,57,168,116,97,234,156,164,173,42,225,70,177,38,184,43,121,148,186,19,207,224,19,253,214,102,184,227,77,205,223,63,242,184,142,75,134,48,96,96,243,151,83,50,87,123,186,147,177,176,62,113,237,99,50,108,201,126,185,218,219,219,241,171,55,44,28,194,49,254,72,63,140,63,178,112,216,15,3,183,189,172,230,154,116,254,246,200,73,82,76,41,15,168,132,147,25,115,46,90,151,15,180,193,60,237,178,105,74,47,191,86,59,221,105,248,98,26,140,49,149,76,146,83,229,173,71,134,78,113,171,186,136,69,240,102,228,167,251,86,198,107,167,79,180,215,210,44,58,98,143,79,188,44,133,107,54,248,165,231,104,149,127,120,62,61,159,252,239,41,101,177,140,108,77,90,49,230,151,125,115,153,80,213,191,17,98,59,202,149,108,239,233,23,177,26,245,216,97,198,111,31,75,248,67,177,55,207,157,212,233,20,69,111,167,232,80,21,144,9,32,199,43,200,181,141,195,9,143,237,154,121,175,158,247,124,39,117,184,48,30,51,103,4,19,16,28,84,98,72,251,204,19,32,194,90,236,170,52,202,181,96,92,120,59,184,47,169,66,177,66,217,150,2,50,182,17,7,131,32,76,227,116,70,174,42,90,163,89,35,33,148,41,240,228,253,31,107,201,210,198,152,13,86,70,112,248,225,121,155,252,134,99,239,2,8,98,108,44,76,227,160,213,104,141,16,130,205,118,253,123,220,48,200,187,80,35,114,62,45,188,107,29,79,220,169,244,147,158,70,102,122,231,232,149,243,55,230,115,28,185,83,39,179,237,221,41,170,240,44,143,39,216,163,87,213,39,157,118,225,99,80,190,57,171,200,20,2,7,166,112,211,127,0,69,167,84,159,62,190,37,46,1,194,192,152,94,188,50,203,38,220,128,2,108,156,32,255,174,254,89,135,44,97,26,237,37,203,70,32,238,3,218,163,213,145,32,244,50,67,233,217,30,131,135,205,0,46,29,143,192,99,180,144,34,96,7,74,212,164,44,215,190,88,252,138,84,97,50,251,203,44,252,175,247,178,155,79,180,28,8,80,184,205,211,9,119,150,32,91,150,4,102,212,89,217,117,71,241,163,146,90,113,142,34,228,139,182,236,101,97,47,152,88,91,161,47,37,246,4,92,89,174,210,15,82,44,118,249,82,198,192,155,172,220,91,168,190,233,35,204,84,24,113,139,102,112,42,108,124,19,27,148,60,159,78,38,239,90,234,5,193,172,28,58,20,182,11,43,162,123,82,184,178,167,19,172,101,106,3,69,146,204,136,46,70,35,133,166,103,74,245,222,246,76,109,232,173,160,36,50,39,140,112,227,59,10,18,127,30,232,161,113,146,233,102,248,171,205,245,154,98,101,53,109,65,36,82,31,241,200,111,216,27,255,10,48,237,213,82,221,17,250,248,215,19,150,56,175,233,19,230,30,233,199,3,100,121,176,189,175,63,20,231,105,113,121,51,88,188,231,109,177,58,34,9,199,121,226,157,183,76,219,41,224,204,61,144,124,88,115,7,214,74,179,178,42,119,144,76,98,58,171,185,134,98,123,177,87,100,213,183,165,147,22,29,151,19,74,146,102,107,158,201,189,0,79,185,36,105,84,104,73,152,103,132,228,196,39,102,113,158,255,56,212,198,37,172,139,31,238,98,184,182,42,69,108,194,245,23,205,45,21,76,115,162,181,174,59,213,233,59,240,184,32,212,226,199,126,11,205,232,217,187,51,197,98,94,117,94,105,152,41,48,22,181,8,146,134,207,30,237,255,240,248,183,191,187,67,210,16,185,191,54,193,2,218,22,99,176,191,233,78,247,165,4,231,131,62,37,109,244,76,194,155,129,212,66,0,101,223,162,211,13,80,169,217,16,68,4,155,216,61,35,76,162,144,217,34,209,73,249,250,253,186,140,124,41,237,124,22,168,97,40,95,47,38,188,204,216,150,184,229,185,174,113,3,154,126,238,50,165,170,12,27,209,53,157,76,118,81,252,10,140,31,103,160,43,171,6,65,205,225,154,85,121,76,216,228,29,241,184,200,160,225,86,4,199,137,80,222,199,30,9,163,177,222,131,91,24,3,147,148,250,20,157,246,166,73,41,246,240,159,85,53,172,227,255,239,211,188,78,85,210,198,63,175,149,47,251,126,139,167,245,143,5,212,41,111,52,133,173,37,114,122,63,214,212,6,98,213,169,140,241,226,233,95,47,169,91,89,117,116,228,30,78,123,163,137,11,19,142,70,121,166,215,141,20,57,100,202,75,131,150,222,136,204,79,199,205,220,46,9,129,92,116,55,148,224,138,82,32,255,250,251,59,239,99,130,13,77,106,233,191,37,70,164,141,160,195,95,192,54,39,178,189,46,17,135,160,255,198,62,249,69,57,5,74,22,165,134,209,143,179,8,28,219,212,141,148,242,233,231,171,234,72,186,111,252,84,120,130,253,206,225,145,123,88,19,194,150,24,168,247,191,92,162,203,56,94,55,72,199,142,76,50,37,253,13,142,159,201,100,153,149,243,217,240,192,204,254,66,239,13,23,161,166,210,210,120,35,7,141,179,109,83,57,146,163,16,195,195,129,214,39,34,155,158,29,244,128,143,18,233,121,150,87,80,227,145,22,207,133,15,10,172,79,48,176,209,68,66,116,22,167,251,162,90,108,98,148,98,84,46,164,185,106,48,68,247,163,112,24,15,78,105,58,173,251,63,10,252,91,83,158,57,178,63,21,40,113,231,82,251,191,134,27,71,131,203,150,222,121,48,211,181,0,62,91,119,123,77,252,183,63,204,142,239,211,87,244,129,213,2,81,221,210,104,182,252,35,116,91,198,172,132,76,148,89,3,74,8,96,232,19,70,18,232,128,18,145,133,229,23,13,93,175,174,68,105,55,192,81,168,1,142,132,193,37,99,188,243,51,14,26,6,195,29,149,159,115,77,169,235,22,66,101,37,224,43,146,152,141,191,222,67,12,74,51,124,129,141,11,37,97,10,50,79,112,123,54,180,89,156,10,237,145,90,99,35,116,84,163,249,196,70,103,144,16,14,13,233,42,5,213,163,203,205,92,6,212,210,195,46,141,24,15,1,215,71,30,31,0,4,24,15,93,217,35,228,173,104,78,117,69,140,243,168,119,62,223,200,171,123,57,184,88,64,53,21,153,201,0,115,146,22,119,84,228,16,189,124,213,148,92,15,178,58,83,69,87,213,137,150,254,92,197,211,157,193,255,150,115,3,222,48,64,41,28,208,245,211,29,135,30,54,205,250,93,94,57,155,196,37,151,90,109,165,11,249,203,106,37,64,103,100,206,108,40,181,36,238,104,208,241,13,26,75,32,133,101,47,132,226,199,174,3,139,186,102,206,19,21,6,166,44,184,63,7,255,61,155,90,233,60,161,86,176,23,97,194,237,176,234,251,116,25,226,11,145,130,13,179,158,222,252,26,235,132,202,117,229,195,232,158,52,183,96,47,219,235,210,51,146,103,15,241,22,194,84,73,169,183,142,81,87,203,6,251,105,254,2,56,164,156,137,219,71,205,59,144,217,70,38,73,57,73,70,131,114,20,249,181,50,184,200,127,251,28,30,92,166,20,252,156,141,128,223,214,176,136,154,210,238,245,131,123,1,114,106,160,197,74,57,4,101,162,185,66,93,219,192,225,68,181,231,74,140,180,121,162,114,142,129,187,73,66,192,218,128,28,39,134,251,0,243,48,55,112,205,204,80,144,149,109,100,247,179,224,228,198,89,225,7,131,170,203,32,130,21,23,249,122,134,208,160,239,23,10,91,107,175,27,56,59,104,18,71,209,245,4,165,227,203,178,69,1,114,130,119,193,171,64,18,182,174,155,16,84,193,55,150,153,90,251,6,94,161,253,223,200,143,16,162,175,93,211,88,243,61,118,144,204,158,163,68,183,243,85,64,42,52,155,32,39,213,93,165,239,188,8,152,93,228,136,71,213,103,158,57,252,54,203,34,230,180,127,56,46,22,5,220,190,103,131,16,64,135,114,68,112,125,205,54,108,113,157,5,31,108,20,138,80,149,170,6,114,65,223,21,159,246,115,158,118,220,203,106,20,66,204,213,59,225,109,136,122,206,137,104,126,66,24,195,83,223,112,36,241,154,219,254,255,248,77,142,202,95,86,171,11,42,188,7,245,217,138,49,224,34,61,121,28,57,25,3,70,9,40,108,107,108,211,160,206,154,77,59,153,161,172,200,23,84,154,131,94,122,115,145,19,13,234,127,86,154,80,149,41,50,98,186,251,36,10,53,159,223,103,104,248,67,154,136,228,46,83,243,36,33,221,157,116,83,109,54,89,171,46,252,120,86,50,220,23,252,185,68,192,125,37,223,233,232,110,16,135,71,175,199,37,75,162,17,48,41,32,39,131,59,145,161,20,26,149,216,99,1,188,240,87,189,8,24,224,227,175,207,156,151,37,76,105,62,202,86,172,9,208,0,186,72,213,78,103,254,132,192,92,113,242,42,224,245,111,181,206,107,130,182,212,63,185,27,28,41,112,220,209,148,172,7,140,225,168,124,67,203,73,76,139,41,226,87,30,125,197,216,76,36,160,168,194,202,181,254,134,0,148,187,242,94,239,72,9,21,148,168,92,66,161,144,73,37,106,39,176,127,116,44,183,89,77,47,138,171,10,169,117,147,107,92,29,184,69,82,220,13,130,34,214,197,214,6,152,46,180,228,77,211,162,47,149,169,145,56,196,174,84,97,93,246,216,30,34,211,137,93,8,161,64,73,106,220,60,107,201,86,86,124,51,9,66,244,168,8,22,125,147,200,68,23,23,247,75,139,87,52,54,5,53,175,14,218,127,126,196,104,220,88,75,122,52,99,226,111,88,137,95,199,196,6,2,87,182,200,67,133,205,210,73,174,53,64,12,134,84,182,73,199,7,65,88,7,24,83,187,31,81,35,236,229,37,177,78,42,143,233,94,241,133,195,255,185,7,218,41,43,231,129,3,23,175,147,37,26,188,70,161,146,126,24,12,38,104,96,209,143,227,254,9,198,24,192,4,227,59,174,32,240,251,5,34,127,186,184,83,193,62,41,187,33,39,239,28,16,118,164,36,171,230,136,212,122,52,86,39,165,85,61,117,145,179,83,209,229,95,227,85,170,136,187,59,115,217,179,60,48,21,67,116,58,14,145,89,89,35,229,5,152,217,138,26,10,189,186,35,83,210,174,165,179,87,168,247,177,43,213,204,247,37,109,164,15,182,108,253,170,140,83,214,151,0,211,81,132,64,43,30,248,18,149,11,44,248,98,107,216,117,38,96,167,82,124,152,140,191,51,40,145,207,31,45,189,144,120,151,236,172,94,196,233,80,172,227,217,187,197,174,24,108,153,189,212,51,44,156,203,149,74,222,95,240,202,168,235,255,91,215,29,201,254,8,156,120,134,162,218,172,153,51,254,189,4,238,93,65,227,158,247,6,74,254,126,91,58,204,84,167,188,223,91,180,79,147,62,150,135,231,158,186,185,126,91,13,115,56,108,78,17,205,175,102,47,20,157,73,175,89,225,242,141,119,215,191,236,127,186,252,109,87,164,233,22,213,98,137,134,97,78,12,13,150,30,160,164,149,154,108,167,156,104,67,228,187,152,143,135,114,154,47,7,21,89,131,179,34,253,135,40,109,220,0,127,213,82,85,64,161,1,113,242,240,66,56,78,225,32,59,26,177,12,19,79,6,212,120,217,177,7,187,76,85,122,133,9,219,81,118,109,201,21,119,47,122,30,190,208,241,78,63,16,91,45,44,253,13,228,18,228,187,96,222,132,166,77,100,226,124,234,61,59,174,40,117,26,163,5,65,107,1,95,18,170,126,100,95,216,113,98,15,186,246,133,3,205,221,228,159,206,212,201,240,175,113,198,72,187,233,28,104,253,239,168,246,139,120,149,143,34,146,39,220,145,216,114,243,109,219,151,117,75,33,162,197,181,62,19,128,118,215,96,101,54,68,109,7,171,133,54,145,1,15,56,224,58,123,172,196,221,3,133,158,85,120,21,246,153,166,1,17,66,48,223,247,230,95,15,223,253,250,109,197,6,190,76,117,7,245,185,143,129,188,191,215,198,20,90,194,172,250,78,233,102,182,120,92,116,208,65,80,84,235,77,57,207,221,127,16,225,96,218,22,104,216,138,195,220,101,236,3,109,87,42,198,95,96,164,202,48,107,45,17,107,246,2,243,229,149,152,83,101,228,91,80,183,254,119,138,201,64,197,135,212,15,171,151,44,69,249,208,188,57,253,250,157,63,153,226,131,155,3,224,56,103,144,28,200,229,192,71,131,21,129,219,235,31,205,144,191,146,253,77,67,78,216,241,242,228,244,174,123,254,65,212,26,35,218,100,1,28,145,247,37,254,116,206,212,40,200,241,209,30,238,181,165,198,211,144,87,158,142,226,70,232,172,134,42,41,121,222,108,17,68,45,47,16,56,26,77,188,99,188,115,118,252,245,11,51,25,44,27,128,31,32,221,54,158,109,102,53,155,4,245,73,26,234,174,198,111,64,52,171,213,56,173,114,145,152,204,191,140,179,22,93,211,35,243,221,136,103,201,155,0,41,110,183,62,30,176,252,190,108,47,23,203,166,160,173,17,124,11,189,244,44,4,13,133,74,224,19,240,200,254,27,57,180,193,89,67,10,147,117,127,169,109,96,98,8,10,21,26,37,181,81,247,202,60,172,58,139,237,116,143,140,46,52,176,49,71,231,243,80,161,14,219,152,25,62,178,232,150,162,47,124,122,155,221,61,212,160,224,158,136,39,24,24,159,93,108,6,145,49,245,189,95,22,153,45,100,83,225,12,97,201,53,242,6,2,23,210,62,108,106,189,178,189,42,64,247,93,171,233,157,196,159,103,239,240,111,60,164,43,151,83,198,183,204,37,185,207,113,120,130,103,10,4,90,144,149,54,51,128,82,233,108,119,172,85,82,79,203,25,184,22,113,202,100,46,34,121,95,234,102,43,243,242,211,223,171,133,152,188,18,134,67,47,2,94,11,17,249,254,0,115,150,132,37,136,76,84,42,91,153,219,138,4,233,91,164,1,243,162,12,134,75,244,55,138,40,252,182,74,245,239,39,45,157,106,56,118,130,15,190,210,138,155,237,239,57,182,77,69,190,113,237,27,178,173,214,149,95,133,12,106,208,89,63,129,174,51,58,43,142,103,103,138,109,123,39,101,45,171,1,233,54,34,208,63,121,151,241,39,0,207,133,172,100,150,134,5,196,133,184,171,253,201,139,186,75,242,123,53,174,38,249,95,72,254,64,108,209,147,37,177,166,69,3,178,95,255,47,41,195,232,6,73,119,89,203,225,150,80,125,183,56,28,82,112,89,167,237,204,73,139,208,233,7,168,90,35,244,133,50,216,254,240,80,227,187,102,135,27,213,192,201,21,175,236,199,100,103,36,247,192,4,133,40,125,16,111,25,177,101,37,180,170,49,230,106,169,123,73,58,231,60,106,230,145,116,211,215,134,199,90,18,243,210,29,225,79,224,248,108,204,147,215,73,244,75,154,145,95,137,151,193,154,146,43,242,175,5,62,42,113,9,57,70,59,133,75,165,250,154,186,143,167,22,47,252,137,102,87,181,104,147,207,195,205,88,18,48,209,126,182,35,179,10,30,175,25,163,6,202,85,185,99,52,208,20,19,242,169,14,253,227,198,85,129,68,11,99,112,59,79,142,105,188,254,123,148,88,153,70,89,84,106,236,34,181,241,51,194,138,62,14,134,245,151,117,235,135,10,139,140,204,146,196,96,242,114,217,131,102,142,129,65,132,108,64,29,42,233,238,33,19,249,17,222,195,125,158,124,202,110,18,183,150,111,199,70,127,8,180,135,203,33,143,230,228,90,44,43,118,241,57,168,162,89,150,106,102,32,60,250,93,143,196,239,12,214,171,73,180,196,199,210,115,112,192,13,9,123,222,213,148,91,19,101,236,101,30,146,43,164,10,156,101,112,151,65,89,151,245,154,56,37,194,99,153,35,80,3,93,62,246,6,68,42,34,155,207,230,215,121,37,213,153,36,165,136,123,181,144,31,215,138,161,118,151,196,108,131,138,93,13,158,182,138,197,184,0,44,139,70,0,204,15,179,245,235,111,229,61,119,1,248,135,70,169,50,116,69,16,223,77,223,248,176,81,63,205,104,150,100,178,216,215,7,243,251,58,16,117,59,213,117,122,156,183,0,72,126,132,100,86,92,240,106,174,220,88,51,75,166,111,176,139,229,215,30,173,166,246,249,201,187,24,250,69,150,214,224,9,17,218,53,173,213,254,11,60,19,32,202,124,40,131,51,99,223,226,217,190,252,29,14,39,73,199,37,180,254,114,46,169,46,109,205,172,86,62,198,113,209,186,149,211,122,42,239,238,71,133,33,39,217,86,131,68,199,243,26,0,143,97,215,140,217,34,11,55,192,118,66,69,203,200,128,171,40,250,94,127,204,76,168,232,153,226,37,150,4,8,22,177,75,64,204,39,19,45,127,173,174,14,222,159,184,66,88,61,250,133,231,114,166,164,33,157,77,203,31,222,189,111,131,178,107,117,10,165,203,18,211,117,188,134,254,238,158,123,143,231,245,189,89,21,88,66,169,241,24,26,210,108,105,249,56,37,196,36,26,110,237,31,34,198,114,72,218,133,14,40,38,0,26,218,130,56,146,228,86,253,43,36,112,162,58,232,178,162,105,114,186,74,187,229,215,195,101,241,14,24,95,246,248,101,255,68,164,79,41,18,245,65,11,228,167,132,169,52,170,196,91,52,224,204,230,105,193,231,254,49,143,85,42,221,140,233,18,131,116,86,127,103,136,113,15,23,95,39,90,226,59,168,56,73,43,227,171,60,251,5,66,24,207,129,225,168,127,243,190,108,173,215,76,110,107,75,120,242,147,252,217,57,234,116,1,133,221,90,162,174,126,61,236,200,53,105,71,155,217,56,85,6,214,13,60,119,234,225,200,186,152,215,237,225,105,85,252,240,252,38,75,220,200,6,243,144,34,127,161,14,197,107,63,75,235,195,72,44,27,244,129,243,201,59,241,45,173,62,200,145,232,76,142,208,183,15,77,119,157,26,157,170,159,104,206,13,248,132,68,229,234,196,252,168,229,154,203,44,177,54,200,235,132,93,52,10,196,60,152,226,220,27,98,85,215,82,144,161,12,76,202,47,71,231,225,223,105,35,201,195,174,188,10,168,199,141,255,108,74,166,226,33,4,203,54,202,178,27,127,250,86,181,225,246,70,219,65,173,49,214,202,71,22,67,184,54,90,182,251,202,40,14,235,63,201,190,75,65,15,33,62,81,56,157,55,187,67,3,223,5,188,105,211,72,202,95,229,207,20,1,219,121,116,56,5,116,227,97,48,200,192,252,86,238,56,125,89,89,89,100,76,5,180,81,31,33,111,202,211,182,51,25,81,28,239,153,125,85,67,149,136,118,157,65,84,65,43,74,86,81,238,45,7,227,222,145,234,95,152,157,225,22,53,47,59,189,252,16,40,26,171,155,247,98,73,206,206,218,9,241,152,213,3,15,107,123,100,86,78,2,200,194,8,78,101,235,150,113,69,232,13,102,131,200,41,240,126,186,238,184,20,62,218,235,221,116,53,44,20,219,104,254,112,139,81,119,100,253,105,53,62,247,159,166,75,128,64,51,7,193,108,154,115,34,146,127,75,102,17,112,81,35,33,255,104,228,11,97,24,252,219,214,122,235,2,28,34,128,252,220,126,248,87,48,200,149,102,191,135,59,48,111,142,210,22,87,41,25,209,90,114,67,98,234,128,53,45,198,155,116,161,66,14,216,226,63,200,18,7,20,213,60,221,77,128,48,20,142,208,197,61,210,161,90,77,80,146,220,80,168,29,93,171,234,195,182,134,136,225,120,206,94,147,141,52,199,5,155,74,143,12,252,50,79,254,135,78,145,222,143,150,128,28,137,206,79,88,83,195,0,213,182,223,225,201,191,235,235,39,175,202,211,139,11,109,8,255,251,237,232,33,37,250,169,184,42,115,205,55,220,211,160,190,225,201,208,87,227,181,15,92,123,111,172,104,71,23,236,206,214,177,119,77,128,149,238,102,224,147,48,143,82,158,83,179,110,112,12,75,86,190,48,208,14,156,92,140,55,64,14,23,106,204,140,48,97,72,62,247,14,217,121,31,224,171,233,69,177,129,185,71,17,87,96,138,78,19,178,198,229,37,235,51,51,208,149,100,111,39,54,197,126,215,245,125,0,18,64,157,246,4,183,62,21,82,209,182,193,74,163,255,99,143,38,119,30,171,116,62,129,241,64,167,205,128,48,19,141,208,126,96,231,17,94,11,123,106,132,252,127,95,4,217,84,100,231,9,56,144,178,55,92,107,154,194,164,113,19,93,117,152,188,49,241,135,95,131,177,63,10,247,179,86,47,153,63,125,70,239,205,3,48,196,135,152,123,146,5,229,21,112,255,72,4,180,42,148,238,234,211,163,111,223,49,176,36,101,182,121,145,65,242,151,27,181,100,235,212,127,238,78,165,2,36,188,117,89,217,137,39,32,249,156,72,106,48,65,177,35,119,166,109,125,93,15,74,133,194,177,8,208,79,4,23,216,37,3,20,67,12,40,52,11,160,213,96,177,234,40,240,251,19,126,81,186,153,249,204,11,91,78,70,238,38,31,243,13,156,49,165,95,148,218,155,179,139,30,216,15,153,27,164,59,189,173,159,141,146,16,21,167,183,161,203,82,140,66,150,182,16,73,40,176,102,55,118,132,173,249,137,117,137,145,90,53,86,164,24,152,171,14,64,192,181,253,238,22,204,59,115,228,173,155,232,15,108,250,14,135,190,177,25,54,114,152,83,38,132,125,185,243,134,112,168,170,99,100,155,125,107,46,165,146,10,12,243,170,39,155,195,220,140,129,9,27,178,166,144,112,200,134,3,146,228,27,60,217,251,147,93,72,56,196,158,217,177,53,113,146,111,93,172,7,71,165,196,105,120,164,255,79,158,235,183,45,61,139,128,87,87,24,202,89,236,50,129,135,90,217,225,115,211,102,32,22,124,87,167,76,209,47,193,179,5,176,1,172,115,53,235,4,198,69,17,146,1,156,60,169,171,3,154,137,1,8,160,180,39,33,145,194,221,167,74,225,147,22,226,175,161,190,155,99,104,36,234,28,206,255,153,106,146,140,248,208,160,159,129,189,81,79,151,34,57,191,19,60,238,132,173,126,112,102,40,167,236,248,169,15,165,62,167,248,117,241,242,52,190,179,82,62,174,253,135,166,242,116,101,164,25,44,212,205,199,182,51,26,85,54,11,16,243,103,183,145,84,222,115,193,84,191,14,243,49,214,76,187,20,39,29,243,173,156,181,219,109,64,24,75,52,179,28,160,231,99,85,33,44,165,96,91,1,116,151,203,247,43,74,128,179,172,198,31,77,89,11,160,120,13,159,140,72,217,110,79,78,206,233,178,98,50,152,74,216,73,133,249,217,70,75,56,129,241,107,234,100,37,103,60,16,188,2,190,11,70,104,226,153,93,247,153,143,161,19,20,220,168,207,59,231,145,117,83,136,104,18,107,25,84,26,105,116,169,98,24,122,32,236,228,193,206,223,235,29,238,49,143,225,2,196,58,61,127,140,102,14,140,100,86,158,130,245,106,213,21,195,130,77,170,38,87,189,28,239,43,9,141,221,172,71,101,23,117,196,97,176,152,245,228,11,197,252,84,206,70,36,202,196,205,27,80,137,39,25,75,180,73,162,224,150,97,44,115,24,151,153,239,190,250,64,81,124,193,49,199,158,225,239,216,251,150,194,11,43,136,66,171,93,122,163,101,50,248,76,30,251,201,114,80,75,69,109,212,155,11,141,217,118,95,15,127,174,149,147,216,251,178,89,253,92,51,157,16,128,60,144,26,219,47,131,125,182,76,241,164,209,6,26,7,92,85,220,173,245,230,208,98,209,124,70,173,192,190,132,55,211,201,186,183,60,108,73,202,134,11,25,98,22,219,173,173,140,39,222,243,91,17,177,81,168,144,244,94,105,34,211,227,16,134,9,254,20,51,4,182,243,203,82,63,238,89,246,230,147,185,200,52,129,113,141,167,177,99,18,247,119,52,84,13,203,187,89,98,35,178,30,13,149,205,77,136,197,164,183,202,225,132,158,34,253,166,180,170,81,56,53,16,116,34,149,120,212,66,17,226,5,193,175,148,81,251,230,23,177,141,43,79,103,153,84,172,51,44,242,34,237,188,74,225,118,144,129,40,56,96,157,254,134,231,14,209,110,23,26,41,253,29,33,247,80,149,196,100,34,23,183,198,124,246,191,174,56,254,31,119,127,229,154,236,190,38,98,101,91,126,182,201,156,27,210,62,101,17,18,95,17,62,112,173,218,95,8,203,29,169,3,23,137,111,219,234,54,156,50,148,31,227,60,56,205,74,105,149,45,57,162,39,83,232,38,150,169,204,161,15,212,82,220,124,196,127,1,123,135,186,208,13,210,224,127,223,143,131,107,123,201,10,21,58,99,135,64,212,81,242,174,16,20,198,65,72,42,58,79,59,206,26,52,133,57,223,232,6,119,87,13,47,214,82,42,153,242,77,203,163,205,22,188,0,129,78,179,114,86,63,119,183,248,180,74,200,49,174,239,118,170,130,129,69,61,251,182,192,219,239,214,192,255,58,247,26,49,105,232,74,79,103,145,214,114,231,134,233,230,182,242,244,118,246,117,136,107,207,19,107,184,247,251,123,157,189,96,101,189,162,223,179,99,10,86,165,128,163,231,16,244,57,68,233,20,250,104,28,166,38,49,110,177,66,17,127,187,199,42,122,137,238,193,107,95,247,227,189,113,10,75,176,213,70,136,141,144,164,87,37,42,23,127,141,164,183,78,139,218,128,235,216,244,18,237,172,200,24,113,21,112,117,16,59,41,136,9,155,210,169,170,75,221,91,65,24,147,102,178,110,106,220,193,124,222,37,240,191,119,132,54,85,182,115,221,35,234,48,168,174,45,235,227,126,189,190,94,228,240,101,211,112,91,127,57,151,48,255,55,129,17,139,254,252,80,114,75,182,22,51,188,91,109,69,192,230,36,179,138,232,162,3,131,1,137,52,56,241,139,77,224,236,177,175,210,192,80,187,135,105,224,116,81,229,132,151,223,232,67,207,191,76,55,255,26,58,42,239,48,161,0,251,40,166,214,231,173,40,122,99,165,8,170,84,14,152,38,0,60,172,198,70,127,95,75,16,127,6,6,164,64,141,172,238,59,222,131,224,43,38,141,127,96,100,62,2,30,34,180,54,230,3,150,5,231,193,31,96,61,201,7,121,144,136,49,68,114,1,180,193,165,67,117,98,92,230,45,153,167,120,227,39,220,201,40,218,176,242,79,255,176,197,84,44,219,188,24,123,109,252,180,10,54,56,205,152,158,23,34,226,122,114,118,86,190,135,145,210,139,53,111,80,254,12,33,99,114,50,69,174,102,63,40,134,203,163,241,201,210,132,197,30,194,21,41,67,111,169,59,137,176,140,87,223,35,219,148,41,17,47,87,132,177,195,184,155,62,44,57,51,61,166,176,0,78,17,239,248,132,24,90,111,0,114,11,243,116,156,217,62,172,237,169,184,102,49,203,132,170,173,228,19,92,247,110,129,213,51,246,166,189,117,14,122,133,32,168,49,250,110,109,130,233,47,207,247,73,245,53,4,163,18,37,68,143,96,159,144,46,41,170,94,167,114,150,192,69,209,251,219,13,111,213,186,98,240,94,100,151,249,137,215,40,31,202,233,102,233,87,154,45,180,231,125,239,156,180,218,112,223,97,62,42,141,65,252,126,67,80,247,250,233,208,232,35,192,160,163,194,226,126,10,45,236,6,185,108,216,204,37,163,11,79,111,48,215,146,155,158,134,141,203,55,89,61,222,33,78,82,125,74,58,124,11,39,39,25,125,19,251,109,165,69,192,6,62,4,243,172,60,180,97,171,114,245,37,98,216,173,83,172,42,223,203,123,98,129,233,163,55,50,102,117,207,223,131,8,155,151,246,17,163,194,153,249,69,72,100,93,139,51,97,70,143,174,24,21,44,73,67,97,203,26,232,224,113,226,185,74,242,203,51,164,179,209,188,168,1,102,93,74,120,214,135,191,193,209,7,112,218,199,145,10,92,23,239,226,242,205,187,159,126,171,125,35,158,53,118,74,19,183,224,31,116,118,13,32,211,205,92,131,123,48,181,32,124,7,233,247,254,24,251,109,189,0,184,187,80,73,194,94,100,239,81,170,145,20,235,132,230,56,141,90,22,151,198,88,153,66,134,20,94,237,62,58,110,218,255,50,111,198,109,211,202,21,39,7,30,238,147,85,35,154,58,236,112,221,70,102,211,120,115,74,109,188,70,229,214,191,122,134,120,195,231,217,122,35,113,9,110,154,50,82,32,35,111,159,191,205,52,223,124,250,77,32,228,68,131,215,255,245,107,10,80,105,104,31,4,173,207,219,31,219,171,182,182,254,211,181,183,202,185,238,165,167,38,248,72,193,90,249,154,165,80,64,209,68,160,49,226,93,135,143,48,97,211,47,187,29,120,160,203,115,39,87,245,227,220,244,5,60,57,251,126,42,117,244,81,69,98,77,242,210,249,188,19,130,253,198,56,95,174,249,187,185,215,132,16,226,25,29,180,25,54,143,69,121,134,79,117,180,218,210,211,236,58,207,231,69,104,95,149,166,212,59,105,131,68,83,21,233,177,143,135,83,237,99,3,20,58,123,234,249,128,199,117,238,163,124,52,215,100,124,76,146,61,253,192,135,196,87,201,115,149,98,141,214,85,252,207,188,13,34,208,166,93,132,22,39,44,115,121,203,93,78,137,69,196,253,197,120,148,36,21,208,5,95,43,5,122,145,41,160,12,117,201,143,36,62,133,73,185,73,185,155,194,182,166,248,96,33,9,112,7,42,39,42,203,253,23,196,161,187,66,234,58,217,44,48,7,139,47,158,58,153,179,83,189,27,100,164,156,234,199,98,117,100,38,11,24,163,169,221,244,159,173,191,177,229,194,60,25,229,142,239,38,104,95,145,238,47,214,188,90,21,66,126,66,111,210,228,101,36,242,172,130,97,234,90,20,62,166,38,11,198,159,44,245,249,131,27,135,234,87,83,2,62,185,253,129,60,125,165,26,164,138,148,193,87,246,201,45,72,3,33,31,191,29,45,33,15,238,109,8,39,100,38,195,128,83,7,133,205,161,144,113,161,194,75,111,13,7,188,92,227,251,80,96,18,64,26,145,25,40,183,204,243,127,122,119,214,146,16,231,175,187,101,92,23,25,172,45,195,139,252,212,135,73,86,24,33,203,30,64,143,202,39,238,180,143,39,141,32,30,65,76,186,57,211,14,143,45,98,183,16,106,103,221,249,6,53,137,24,139,142,183,198,247,95,139,222,54,254,33,32,110,206,70,243,213,3,192,199,172,149,164,83,182,93,148,177,50,21,141,173,13,238,107,195,127,67,110,37,112,43,142,183,230,190,209,160,162,156,23,27,134,24,34,52,140,72,249,61,178,169,148,8,130,66,147,91,31,208,121,252,240,86,4,49,94,172,145,170,231,175,155,91,81,34,65,35,19,119,54,89,16,204,192,75,121,73,147,188,144,117,13,228,38,41,170,216,212,138,219,190,30,66,160,168,25,44,46,139,91,239,138,252,75,214,254,70,38,167,102,27,83,199,3,87,193,132,173,198,46,20,126,199,149,77,169,28,80,101,104,137,62,96,184,186,195,156,232,54,165,152,181,234,109,221,187,146,210,235,81,120,213,202,4,54,76,73,143,91,58,186,245,234,169,42,230,22,18,250,90,107,166,223,111,105,64,154,164,4,224,90,136,137,59,115,161,111,33,203,195,109,85,228,153,230,42,60,71,72,5,2,62,18,247,95,210,226,191,18,86,215,250,188,187,220,235,252,237,222,248,38,43,49,68,167,200,78,234,221,147,5,179,21,224,63,87,13,134,86,163,63,36,111,99,183,191,107,252,17,109,125,244,237,227,124,248,96,249,123,151,124,55,89,15,60,83,228,51,167,78,178,149,160,185,115,84,80,74,205,223,140,130,90,11,7,178,123,40,235,140,10,228,159,27,22,21,27,35,97,198,101,3,45,152,101,159,133,198,240,50,167,96,88,76,87,206,44,39,249,11,105,101,233,91,94,0,117,182,228,62,63,40,7,175,93,108,94,109,10,13,105,155,235,242,84,115,42,225,207,146,64,214,155,15,160,204,116,101,205,129,106,90,130,161,1,205,66,106,134,110,197,2,121,251,255,76,57,17,131,177,22,249,53,191,239,3,209,175,23,202,194,236,120,82,27,150,175,201,140,218,92,66,6,242,27,242,72,21,153,249,76,147,161,201,108,133,37,82,63,157,26,16,157,157,53,227,144,45,33,251,159,166,102,14,146,8,130,61,71,232,239,55,149,154,94,62,201,196,46,66,64,182,197,173,177,174,129,184,239,93,144,26,35,78,229,198,0,35,11,0,24,58,31,116,17,14,148,173,217,199,57,30,154,70,63,65,205,96,139,15,161,221,167,15,248,53,144,210,247,198,28,89,183,77,185,161,137,46,60,33,250,124,201,6,162,14,149,173,139,246,183,196,97,174,62,140,41,85,124,32,241,157,180,188,116,43,88,101,206,143,162,87,136,175,53,8,137,29,26,223,233,139,150,187,232,66,160,175,236,60,249,74,124,88,0,169,71,249,158,190,158,10,136,161,14,192,129,205,123,206,139,139,194,116,10,232,178,229,135,29,133,175,175,159,206,251,200,116,49,111,179,231,204,59,114,82,198,44,18,188,92,104,214,214,0,99,131,131,20,13,139,95,163,166,89,240,125,147,162,92,27,236,208,194,108,76,213,90,135,100,0,183,53,71,191,95,49,61,227,177,149,62,19,73,102,79,254,208,162,75,217,114,173,130,116,114,179,103,102,51,151,84,216,208,210,52,137,180,99,72,124,128,249,247,136,183,36,28,249,242,125,70,239,231,22,75,183,222,194,216,180,98,166,182,159,27,186,214,74,253,234,220,112,80,103,58,215,113,70,28,68,149,92,181,110,119,67,179,179,9,96,140,249,194,72,173,244,144,58,9,141,246,68,237,118,179,124,164,96,125,30,196,126,104,19,176,107,25,7,162,89,236,206,184,139,167,166,16,55,67,7,93,251,90,252,86,252,171,140,238,114,28,106,253,2,64,26,18,192,199,145,70,224,41,158,81,211,254,47,235,74,231,215,176,97,187,165,209,79,109,189,21,14,209,97,193,29,254,42,24,157,72,5,143,9,214,54,90,86,243,143,140,12,163,2,158,213,69,48,232,80,165,123,73,197,247,8,241,232,198,127,142,153,236,153,145,20,27,64,72,56,14,13,147,102,116,211,20,44,176,108,13,229,36,230,81,206,9,197,5,42,177,137,125,239,52,138,145,92,76,16,223,134,138,221,234,177,91,177,210,67,1,151,117,176,201,125,211,227,144,217,180,31,53,97,31,147,33,222,114,225,63,236,245,62,68,54,30,147,134,96,110,84,124,209,201,141,3,62,115,79,24,228,194,3,74,218,184,3,66,224,170,40,123,37,121,61,129,54,53,103,197,43,89,135,6,26,104,193,193,136,152,56,142,183,224,128,35,138,123,231,218,184,64,116,133,134,79,71,93,163,18,65,127,217,137,72,42,147,44,193,117,255,58,201,221,139,83,224,169,171,21,200,243,196,43,229,12,27,96,110,87,50,136,174,144,220,236,35,210,9,136,71,10,14,95,205,206,230,46,210,240,140,197,31,1,18,188,0,238,15,228,67,49,220,86,132,126,70,124,204,88,118,84,251,214,36,171,200,70,160,93,190,20,193,149,122,208,201,60,231,13,227,143,217,98,120,101,241,47,166,37,0,246,166,53,179,69,210,170,111,102,237,39,29,58,140,90,17,30,66,50,240,135,134,156,130,216,158,96,227,238,43,173,150,62,156,252,12,213,121,200,99,178,38,253,248,51,29,232,51,139,88,26,160,174,235,4,96,47,68,39,65,224,118,4,246,129,110,151,23,33,196,101,107,18,57,33,181,138,239,175,105,157,49,247,51,175,4,49,223,166,210,239,121,16,164,212,230,198,33,63,150,165,9,54,147,43,215,241,224,55,27,106,204,89,39,184,161,80,49,4,115,240,147,14,244,80,211,157,188,47,240,27,232,175,82,215,194,147,55,86,12,143,240,196,252,206,171,147,238,96,167,220,204,222,124,57,43,217,33,94,205,196,224,116,99,78,12,233,159,227,1,76,43,79,235,217,146,66,161,211,175,94,65,74,199,243,183,6,81,84,203,242,106,233,76,173,158,214,45,43,108,174,250,106,136,126,230,63,14,251,213,18,71,87,50,64,255,236,85,183,102,109,45,1,174,202,9,149,185,253,197,58,210,45,138,136,51,85,221,138,73,184,106,127,134,253,72,58,18,180,62,151,29,82,139,220,202,116,64,248,20,81,96,109,47,138,242,186,193,36,58,228,83,194,172,38,0,252,218,244,10,112,115,142,57,210,57,11,64,200,229,159,61,193,101,132,118,218,80,148,208,24,56,50,42,216,65,221,198,222,42,94,40,195,189,60,175,28,71,25,114,164,42,45,8,67,46,142,204,238,25,167,37,150,221,46,11,216,39,161,104,150,116,113,1,94,67,6,9,155,180,85,217,5,244,160,99,51,203,177,93,136,13,60,29,150,143,141,45,240,202,86,52,252,208,169,251,4,6,159,54,129,123,18,109,207,1,191,79,38,187,105,43,96,244,160,246,58,53,1,126,98,82,106,12,250,65,44,103,65,155,146,190,0,201,249,32,20,57,171,220,149,156,114,51,66,148,220,137,156,113,120,32,169,126,124,13,130,177,138,31,55,46,148,240,128,29,71,141,116,145,112,8,66,189,190,216,123,114,164,94,213,103,242,213,46,100,240,150,169,179,251,110,47,164,50,174,245,163,245,59,14,243,8,35,82,74,151,19,130,70,32,129,139,54,14,190,35,131,230,71,44,133,253,187,52,219,118,239,235,58,76,31,196,252,32,242,187,197,157,187,55,29,121,51,214,250,24,234,46,96,133,232,102,63,43,191,186,226,113,189,64,205,186,249,119,43,113,194,61,250,58,221,69,191,75,14,152,187,167,243,108,156,124,46,5,218,175,243,118,7,240,85,167,144,192,213,61,210,252,162,165,162,46,86,124,240,63,149,35,88,159,198,71,207,56,140,25,144,133,248,190,191,241,252,13,124,234,108,165,9,106,44,119,178,102,193,221,168,140,143,125,102,211,106,41,163,241,103,12,131,227,10,78,64,224,131,209,128,108,224,131,81,196,188,208,57,0,65,7,171,245,92,68,97,155,26,19,0,220,173,153,62,182,16,55,19,229,89,135,80,157,145,162,168,60,3,54,77,8,252,62,78,45,97,13,187,5,95,233,221,143,244,218,237,9,191,191,111,230,19,235,185,24,229,133,236,211,127,22,70,243,186,237,63,6,52,140,155,111,172,124,143,130,20,198,240,17,48,164,10,74,221,17,240,102,82,73,186,66,214,132,28,226,189,253,197,216,71,13,102,76,54,192,250,157,250,97,33,169,125,119,76,18,127,148,89,55,79,41,27,171,173,241,40,25,242,210,152,51,104,129,66,79,162,178,205,127,78,159,148,90,244,237,62,200,220,157,71,215,30,45,95,17,166,151,2,107,156,25,214,202,113,205,64,70,182,24,9,62,176,176,190,16,176,188,96,117,242,77,22,88,50,108,118,138,246,209,82,199,143,160,77,201,121,197,140,194,143,8,181,195,45,95,221,40,139,214,14,153,166,70,195,180,165,102,177,227,237,193,79,231,55,66,91,102,116,212,200,47,182,152,106,44,255,140,122,66,158,160,250,117,112,5,28,227,9,101,161,115,43,75,216,160,129,201,85,4,155,212,168,94,163,160,204,9,102,25,233,102,160,184,227,106,238,100,129,31,84,122,126,254,145,223,210,150,80,172,229,177,248,245,3,169,238,5,16,2,78,51,54,207,82,72,227,99,136,26,105,129,53,22,17,45,214,181,195,68,36,56,169,195,242,5,8,191,67,154,4,98,246,26,112,153,140,77,237,240,2,154,115,169,245,170,100,202,110,18,149,98,123,104,24,71,192,232,157,222,215,83,47,36,18,129,246,103,237,227,185,218,144,30,199,136,151,160,138,100,74,32,166,208,86,67,75,237,132,120,166,153,52,64,10,225,171,2,81,131,86,59,191,48,93,62,184,125,186,164,181,232,91,66,146,242,21,173,53,43,188,74,248,215,108,185,224,167,76,81,71,206,93,12,235,166,22,241,224,190,133,235,131,111,103,60,230,112,49,52,171,86,194,94,59,123,115,191,87,69,241,194,32,229,82,37,247,66,83,202,39,30,54,213,89,3,78,249,44,22,248,167,57,0,84,189,32,168,147,103,6,140,148,202,187,193,37,38,180,46,29,166,57,72,223,230,106,44,108,111,251,141,251,89,7,111,191,116,203,52,57,144,49,241,196,170,155,145,94,130,81,6,8,48,239,173,230,55,130,69,187,163,225,66,214,151,106,237,182,124,152,252,164,152,71,188,138,18,156,234,158,96,75,48,112,107,71,163,19,180,198,24,225,112,151,114,89,6,217,49,26,232,78,138,51,90,69,91,193,126,130,54,20,217,158,121,249,61,85,203,2,97,83,109,237,170,254,0,91,197,122,244,126,45,233,234,109,127,179,19,219,93,31,65,76,94,19,176,192,62,20,225,161,144,181,212,117,211,254,177,20,119,165,4,191,21,105,172,116,103,36,198,101,166,240,111,212,21,87,239,249,26,153,242,52,76,142,34,251,237,81,66,187,57,122,29,236,37,110,21,148,230,218,247,104,63,1,234,5,69,199,73,134,157,172,42,231,147,224,75,141,129,211,82,4,89,195,246,70,171,181,93,183,55,108,159,166,33,84,4,185,111,204,210,203,121,247,47,11,38,196,128,175,73,224,158,13,7,251,219,162,20,164,80,64,199,241,117,6,96,69,101,173,208,37,165,211,107,165,193,43,31,159,138,214,247,2,33,12,191,208,158,105,240,17,229,141,41,237,45,38,45,115,88,232,28,191,188,150,228,13,47,17,235,94,149,41,105,96,203,124,26,222,106,9,189,50,92,15,120,136,57,57,255,99,51,112,155,217,186,209,181,137,48,198,43,39,230,86,230,26,217,240,223,93,238,195,80,220,79,238,160,255,161,52,146,25,191,179,0,106,203,39,179,207,46,133,153,151,239,88,57,122,189,135,89,178,115,230,216,10,114,143,251,93,168,61,169,202,150,202,196,237,75,49,182,183,125,110,19,34,1,136,14,89,81,155,227,118,201,69,250,152,109,216,132,250,88,147,48,2,191,100,195,211,13,126,162,119,72,133,229,123,207,22,23,212,210,63,155,150,227,57,166,222,129,67,70,42,85,154,245,247,41,193,230,95,156,113,40,103,226,86,19,6,181,49,124,103,224,189,223,33,119,236,24,20,229,68,141,154,5,89,177,163,212,125,152,33,38,48,226,24,141,151,158,51,86,207,22,139,80,172,113,125,82,37,229,71,24,29,22,151,195,95,177,29,49,74,158,121,217,68,52,92,168,158,88,196,251,22,3,155,79,122,252,156,221,200,181,70,100,216,71,156,175,156,86,2,231,130,108,43,211,119,75,181,114,163,95,222,24,246,255,186,183,186,101,37,137,223,53,194,47,117,58,55,235,209,179,14,167,242,26,134,221,36,193,38,118,184,207,96,67,32,145,250,154,128,94,25,66,185,48,57,213,130,222,58,197,173,252,78,101,199,141,206,155,94,81,157,155,216,239,200,168,141,203,59,210,55,17,55,170,5,110,70,51,20,19,17,219,187,198,121,220,48,135,101,52,185,215,244,4,37,229,220,138,211,126,144,244,210,14,194,134,9,176,26,52,128,5,94,173,63,199,171,196,37,142,16,185,13,98,224,38,105,153,24,182,124,179,35,177,69,226,224,127,75,236,2,98,7,44,185,3,14,107,156,129,152,51,36,29,203,211,203,108,162,74,162,216,89,12,128,9,112,14,157,147,3,227,248,177,51,228,239,231,213,231,254,82,42,244,137,106,99,170,156,192,66,71,139,213,5,156,125,195,124,229,130,190,205,89,225,241,254,176,95,30,219,40,248,129,218,116,222,75,183,241,249,60,88,178,52,92,157,156,113,232,162,36,107,47,55,17,155,162,70,224,125,82,84,211,203,26,49,246,193,94,207,161,122,216,126,138,16,206,87,28,38,45,30,196,186,30,68,206,95,156,208,218,236,93,107,125,217,121,46,223,4,69,183,46,238,206,71,72,167,159,167,48,118,25,0,159,147,140,99,166,172,4,113,21,161,52,102,54,219,194,90,106,50,6,156,202,21,86,112,33,45,53,6,124,162,83,226,178,246,1,165,167,177,190,237,128,219,79,114,30,187,31,146,10,157,251,80,124,108,191,233,91,104,68,35,156,13,54,123,191,37,77,245,82,222,206,8,246,133,27,217,87,116,7,145,65,128,81,142,250,19,137,207,10,217,88,150,119,183,30,231,123,9,189,145,113,150,247,204,148,101,142,228,144,127,101,122,157,153,221,45,112,44,139,13,223,94,18,221,245,14,185,252,132,117,15,173,122,121,1,251,109,2,107,25,97,29,180,199,11,124,161,138,37,92,119,254,245,118,34,128,28,100,200,80,5,114,99,208,232,126,215,247,226,193,129,111,229,166,12,107,30,67,118,84,156,100,158,204,44,28,118,134,227,10,22,153,126,77,13,134,137,18,167,115,62,98,60,182,179,66,109,93,146,39,135,247,137,193,45,175,156,83,87,217,63,250,57,154,128,151,152,45,35,43,126,198,229,219,126,200,145,4,236,251,153,196,162,89,73,134,96,119,107,128,190,147,228,64,73,220,100,124,73,203,91,213,77,92,68,50,107,69,237,110,138,228,193,175,162,213,78,39,118,105,39,11,196,157,25,195,35,53,250,121,123,219,197,179,143,206,30,210,251,106,231,243,37,84,55,23,7,30,84,11,121,92,53,9,191,28,49,57,237,112,78,183,12,215,243,99,159,238,14,246,197,136,207,69,0,120,99,89,37,184,54,94,128,204,224,174,118,50,226,59,151,162,115,167,144,223,213,199,4,87,55,193,10,212,169,238,242,254,70,213,252,87,32,245,18,157,79,122,232,143,103,31,93,140,93,243,91,156,91,223,136,12,68,98,200,179,170,185,195,112,27,104,3,205,165,28,186,174,118,57,189,119,144,158,95,158,164,143,139,58,87,217,43,22,68,43,126,240,70,94,163,225,233,248,227,168,70,198,16,51,205,239,192,4,124,244,190,80,130,188,253,65,63,201,98,243,142,139,238,115,52,164,188,234,11,203,33,66,111,40,174,113,78,139,135,102,209,122,166,53,10,2,10,140,215,139,223,100,11,23,208,126,65,214,52,37,98,93,37,250,159,75,209,155,248,86,107,5,114,199,254,105,179,240,132,18,228,65,136,188,180,168,141,149,43,234,13,114,25,92,32,8,212,172,186,194,234,241,77,20,142,76,140,225,110,176,248,93,52,69,8,47,143,25,99,166,56,37,228,218,183,234,205,236,237,168,228,136,179,145,123,254,230,182,37,220,223,96,199,45,24,147,73,86,254,47,90,124,89,129,192,199,167,216,217,62,148,163,46,107,74,67,155,206,30,163,44,42,238,69,77,5,86,126,151,131,136,59,134,63,72,23,50,35,228,75,48,172,147,4,200,35,217,142,56,51,159,145,237,51,218,27,192,43,193,90,63,194,218,149,77,69,58,68,24,177,235,144,245,52,41,241,21,63,202,204,123,60,245,245,147,59,230,53,58,179,177,6,108,72,142,101,202,171,147,1,238,27,183,145,157,7,29,13,111,137,129,183,185,196,139,126,204,48,220,237,170,227,65,153,226,170,245,241,69,250,74,235,39,129,115,94,113,165,212,140,219,239,255,30,2,150,71,167,222,250,123,230,253,102,110,67,175,23,73,166,0,144,47,148,163,151,221,23,81,24,247,230,191,244,11,1,206,112,51,40,182,33,40,163,61,107,169,167,6,202,202,72,255,23,102,172,225,38,148,226,88,109,43,255,21,145,157,184,0,241,95,26,253,89,42,53,13,149,184,8,74,173,119,80,63,39,122,131,186,46,224,96,135,125,146,230,186,215,105,91,230,163,169,125,167,150,59,214,137,125,94,22,30,51,110,143,175,201,170,44,185,136,253,28,105,89,77,41,65,135,12,60,237,170,191,75,127,88,149,34,205,123,6,139,121,217,249,166,254,165,197,104,144,84,48,58,172,21,122,128,85,199,148,36,114,91,239,123,1,206,8,169,49,206,39,142,97,137,189,224,169,198,119,13,171,201,140,49,157,103,118,88,94,210,27,126,242,245,68,55,25,204,114,244,247,64,29,145,137,154,56,172,22,62,19,227,79,143,90,5,12,201,194,154,224,71,103,79,31,119,20,146,114,219,19,44,92,21,211,69,49,20,95,47,183,25,195,60,209,50,238,182,244,59,9,94,112,27,36,210,214,7,152,57,84,87,219,76,117,252,173,214,2,188,162,120,141,43,194,108,127,121,25,148,205,129,10,46,39,41,144,243,52,218,147,187,37,188,247,50,228,177,63,51,214,17,10,240,24,244,129,34,87,146,124,5,230,163,171,120,234,22,101,103,156,68,245,144,114,132,132,244,163,47,127,235,219,88,243,187,140,196,153,78,126,139,116,152,107,147,27,119,0,2,213,231,59,70,73,214,67,31,130,51,71,155,189,211,225,165,140,83,24,36,56,202,105,50,33,140,155,216,216,209,252,54,156,254,20,81,120,206,235,241,53,194,44,177,128,30,239,26,95,124,88,90,21,132,123,188,158,141,127,241,223,95,178,108,21,221,145,222,26,192,180,84,129,78,175,117,146,57,215,116,10,13,53,12,252,227,64,32,115,213,68,143,238,155,225,101,184,132,28,92,127,89,232,1,139,160,185,99,115,92,29,188,211,254,180,85,121,47,205,53,199,122,73,153,119,188,74,163,229,129,90,48,50,178,91,189,168,116,38,32,114,55,89,132,116,208,124,128,113,113,16,206,199,26,163,212,71,1,250,155,96,53,100,44,246,31,136,208,243,220,60,176,23,103,88,245,48,51,59,225,235,226,76,182,53,49,135,126,117,23,4,0,51,62,11,237,65,252,21,246,193,84,14,85,217,111,240,108,226,134,59,194,210,198,214,9,245,99,101,81,3,89,134,225,173,80,61,204,115,250,25,191,22,137,42,177,155,159,237,248,200,39,189,1,66,189,88,8,198,57,47,194,59,150,74,50,244,192,145,124,139,137,9,88,183,226,179,162,219,55,201,222,186,109,36,242,146,104,134,170,9,120,67,123,240,251,118,184,113,206,203,242,204,29,95,103,160,139,24,229,246,174,44,232,1,92,51,119,121,192,74,200,193,169,150,115,168,56,37,31,105,175,166,10,183,252,135,115,233,34,0,229,124,183,246,177,143,42,237,125,2,142,154,240,49,228,213,15,77,123,202,79,84,0,147,189,200,161,106,243,41,87,86,158,216,240,246,100,112,9,91,213,220,206,108,190,57,220,218,99,189,47,194,120,28,127,254,169,178,91,243,109,75,134,210,210,244,242,159,54,217,20,133,68,233,153,234,101,91,233,30,96,171,224,92,91,176,236,182,188,20,131,21,122,84,104,171,14,236,252,249,75,212,235,191,95,11,62,141,94,241,165,26,219,173,197,153,214,168,223,240,94,213,113,148,95,22,212,203,134,117,232,60,147,51,11,201,54,4,81,122,170,58,150,209,147,128,196,78,68,78,148,160,114,198,127,162,120,180,68,133,22,76,101,119,11,93,246,9,232,183,127,140,173,92,221,236,51,178,45,217,246,70,118,91,129,102,24,199,252,7,6,116,81,43,240,49,115,77,164,134,23,10,184,92,26,223,238,174,254,108,5,221,29,205,3,38,30,51,143,196,202,21,102,228,51,105,45,191,54,175,140,175,135,132,56,183,9,116,20,68,132,18,220,233,176,239,82,87,160,87,75,33,255,121,193,156,78,230,23,79,64,52,198,99,148,130,106,107,8,203,26,34,248,194,178,123,242,238,250,69,219,168,219,185,118,64,221,220,7,62,58,172,34,161,85,252,155,52,152,60,87,103,183,167,226,234,225,170,247,90,38,143,81,89,210,156,20,60,194,148,113,179,171,5,77,184,78,26,208,131,200,86,18,46,116,74,134,61,119,29,194,3,117,40,80,168,90,103,191,42,184,95,218,91,28,155,54,146,65,95,188,105,77,14,205,75,249,117,46,221,98,224,169,93,190,83,43,182,146,208,7,135,154,99,250,12,2,189,246,105,220,172,175,69,1,167,218,186,57,136,247,112,149,221,32,11,202,229,160,52,60,200,208,193,198,75,246,250,53,55,150,176,139,93,85,222,206,205,111,9,73,162,186,211,69,140,188,136,164,203,223,18,225,119,181,234,138,60,23,112,75,105,15,203,7,125,177,246,31,45,74,151,48,22,139,175,136,183,250,161,111,94,119,158,113,175,140,79,29,122,65,55,233,80,125,200,31,209,18,35,82,3,116,190,125,208,46,253,125,100,73,160,238,5,244,38,184,200,7,167,119,122,165,28,250,26,52,110,188,151,63,208,63,248,94,165,164,111,163,146,32,37,5,60,85,192,27,61,24,60,161,222,0,4,254,155,189,84,196,0,157,35,12,162,103,138,192,135,38,45,40,41,69,63,30,177,222,41,253,200,54,63,230,237,20,103,172,23,99,192,215,2,181,198,52,12,1,157,162,169,147,206,27,237,188,158,40,214,164,233,240,100,201,245,24,178,38,205,66,140,166,43,132,117,143,233,22,167,190,202,18,188,127,240,184,49,182,87,84,214,121,140,169,20,29,122,133,69,18,168,61,132,146,108,35,131,109,86,101,183,150,34,77,90,194,24,46,232,28,48,183,206,47,100,61,163,165,74,17,92,27,210,106,16,222,186,117,41,103,197,144,3,27,9,248,132,189,88,83,122,219,49,116,2,50,30,40,205,76,130,35,126,83,228,228,138,171,171,135,39,196,227,87,106,235,241,239,86,179,253,11,23,99,7,66,41,158,178,157,76,234,6,5,214,254,184,155,181,84,197,165,122,251,119,249,236,166,219,144,14,253,20,200,71,185,128,249,58,15,196,101,206,51,124,190,50,159,255,10,172,123,168,253,230,89,10,236,71,194,62,129,71,92,165,85,0,198,135,157,141,191,50,13,140,37,124,110,249,46,46,25,251,68,145,8,18,120,51,137,142,119,244,148,246,141,26,132,163,135,241,35,159,49,77,209,163,230,111,6,242,146,195,49,170,2,124,194,17,165,42,155,254,34,50,37,48,67,234,117,90,102,69,129,61,195,172,78,87,34,46,79,146,168,210,166,122,231,226,222,204,251,20,75,223,196,242,130,34,225,110,75,207,175,78,24,239,45,171,104,198,59,0,19,49,11,243,112,43,250,158,62,80,155,237,46,52,188,185,245,171,68,197,202,251,110,93,211,94,67,191,87,157,87,233,13,61,47,52,206,80,194,167,66,67,198,170,244,247,174,171,50,79,255,184,161,14,254,202,162,162,254,221,148,221,251,90,102,154,71,98,61,150,1,32,250,227,57,240,168,21,174,152,107,235,75,2,198,35,117,161,148,210,231,214,184,87,241,102,16,184,144,221,165,158,108,17,177,46,228,156,159,149,123,171,239,250,40,10,62,189,159,144,124,7,64,76,122,161,214,158,46,206,191,99,142,189,68,40,168,172,65,88,130,102,169,121,107,188,201,117,35,139,212,14,176,77,110,172,197,14,238,254,189,108,234,224,228,68,226,121,230,183,185,224,25,14,142,86,3,2,21,133,116,109,24,125,214,126,192,236,107,42,30,208,247,43,102,62,205,11,213,177,80,163,92,245,82,101,244,192,151,191,169,102,204,190,167,232,66,226,12,115,238,131,188,181,235,30,55,68,17,186,125,64,121,44,39,147,240,53,20,40,101,224,109,239,226,32,115,253,200,113,202,118,207,81,168,138,146,224,129,38,168,181,120,87,225,170,24,6,223,254,59,48,103,66,191,112,18,100,232,149,121,191,132,39,231,12,223,111,202,150,238,150,76,143,41,37,183,222,8,16,24,33,99,101,144,218,10,68,70,133,97,95,109,42,67,13,102,0,93,189,206,41,149,160,206,101,195,209,76,22,231,109,76,142,113,78,222,63,202,227,65,140,154,29,47,96,41,58,77,137,107,249,152,7,126,53,105,31,221,134,107,150,14,18,108,110,152,91,57,88,146,199,220,12,79,116,220,134,180,176,224,71,97,52,154,76,94,230,58,14,196,154,89,27,162,219,96,227,91,143,175,92,36,179,222,30,59,163,32,250,146,96,163,83,134,33,18,27,99,127,113,171,35,52,143,96,219,71,71,254,216,30,244,75,88,241,242,50,213,1,83,56,154,152,153,219,130,166,175,82,10,125,111,96,137,38,46,205,11,85,195,29,184,117,250,218,58,49,10,40,30,139,211,81,157,249,51,33,100,201,34,96,197,189,206,48,180,50,2,111,154,109,10,90,116,189,224,85,45,153,10,96,210,142,179,131,174,213,131,9,90,194,235,113,201,152,223,253,134,198,136,215,196,121,114,145,127,197,63,226,22,10,124,149,177,37,12,217,218,113,9,235,142,49,103,237,98,82,140,8,127,97,56,61,78,76,142,106,216,56,78,153,139,60,223,243,28,34,38,199,137,132,50,118,151,58,141,192,20,249,138,53,114,177,45,146,78,147,234,123,244,61,157,119,7,88,41,82,17,102,213,59,93,79,45,40,157,139,219,81,12,134,18,77,1,101,45,228,155,66,227,243,242,202,71,136,205,94,102,239,237,253,62,207,30,222,178,58,135,219,74,150,232,27,209,251,37,198,33,83,209,39,249,183,21,38,213,39,143,198,149,91,161,250,193,43,45,233,70,234,118,173,231,180,151,157,138,7,167,198,81,194,51,164,200,83,56,176,121,167,225,108,50,245,125,137,148,215,111,59,19,64,109,5,114,176,218,137,186,235,94,254,156,96,194,168,34,159,84,171,68,70,215,155,148,244,240,11,54,128,75,56,161,201,231,65,137,194,113,32,89,201,13,141,169,131,94,198,168,132,135,101,50,165,181,8,159,184,15,19,74,16,105,43,25,168,214,106,76,164,64,91,12,74,22,16,124,27,121,145,188,125,255,96,131,33,245,145,180,29,62,194,137,30,62,243,129,77,13,158,163,117,162,206,61,236,135,244,220,166,174,217,73,139,0,254,201,26,125,241,33,68,187,155,235,119,25,72,196,151,8,255,8,84,250,43,102,204,134,121,186,123,144,48,2,235,7,229,41,190,150,181,169,203,226,194,118,180,182,162,220,222,14,52,114,197,229,86,207,201,148,241,246,69,68,231,8,57,6,21,171,44,83,134,151,83,25,48,142,91,248,21,21,213,9,104,208,21,12,133,100,100,144,124,237,193,56,180,34,39,246,232,53,212,121,61,127,221,103,74,114,150,223,11,229,210,6,76,40,95,192,199,167,100,100,64,117,44,73,13,187,42,241,47,212,35,164,55,64,85,88,41,102,68,165,110,72,100,66,38,33,14,166,233,157,80,35,137,1,69,63,111,169,42,19,65,190,106,104,216,90,154,147,190,183,207,177,145,142,190,213,148,10,228,251,99,58,72,148,192,227,20,1,79,110,181,47,89,218,133,7,75,111,229,49,60,97,179,158,28,51,110,139,80,56,147,33,182,227,153,92,32,1,241,44,181,143,24,16,252,26,129,134,63,65,186,1,160,90,254,21,88,43,220,101,222,156,214,211,98,172,42,254,193,103,147,61,229,181,85,228,223,127,163,201,157,106,97,82,251,201,89,32,245,234,92,103,151,70,111,44,210,74,166,88,95,204,82,185,9,218,72,146,27,181,139,97,122,22,228,206,84,237,87,140,101,100,110,216,186,226,110,186,109,140,162,59,52,3,26,96,176,41,84,66,47,216,100,110,106,2,55,106,165,232,43,156,42,193,122,42,74,224,96,101,41,240,141,4,88,29,113,31,121,80,196,152,15,234,154,70,129,228,97,137,99,89,108,64,143,32,111,199,220,209,192,20,24,80,192,202,191,169,156,133,210,36,179,17,149,67,213,52,180,176,134,253,181,179,174,87,217,236,254,162,137,201,192,88,23,89,195,231,73,182,226,224,149,99,172,221,135,5,241,132,86,236,118,69,50,108,27,103,65,17,127,75,11,160,71,85,227,148,153,62,103,83,250,192,254,215,123,252,157,8,112,132,210,193,21,244,168,131,44,69,226,190,243,10,225,163,84,190,118,32,19,193,234,220,32,188,74,90,197,143,70,191,99,113,186,143,49,131,109,253,62,234,221,183,103,238,89,65,67,11,230,9,222,24,95,129,14,228,125,126,166,49,29,239,36,39,124,130,203,200,105,29,231,182,43,1,179,193,103,230,251,205,22,182,65,191,137,110,165,113,180,60,209,87,212,7,69,241,130,157,125,59,225,89,244,120,134,142,170,92,19,65,251,87,163,83,32,185,163,202,187,191,34,192,183,186,236,30,222,225,180,237,142,162,77,93,190,100,248,70,134,164,253,105,255,142,189,83,50,161,225,223,241,240,252,170,90,122,221,22,108,187,81,31,252,76,218,238,217,175,90,110,37,190,8,65,147,181,160,202,39,24,230,218,92,233,102,123,98,72,215,163,152,111,198,25,215,60,213,1,254,4,168,45,13,40,238,142,158,60,70,241,144,183,215,236,146,149,13,234,215,133,3,112,135,7,8,40,195,214,105,244,172,246,200,198,238,153,112,100,59,137,18,122,9,204,17,41,181,111,41,61,21,160,16,170,194,218,178,62,88,92,199,233,200,24,70,246,142,224,164,200,210,237,216,75,100,45,115,160,117,92,38,226,170,215,156,203,215,210,248,231,199,216,248,161,125,167,132,103,180,186,9,249,4,154,16,237,107,80,28,27,235,150,39,210,201,153,66,17,97,165,29,15,167,130,23,77,17,106,160,90,248,47,219,164,20,127,81,248,1,36,254,22,50,208,65,145,45,220,160,93,16,45,62,229,177,187,144,167,142,26,248,232,6,191,77,59,136,49,2,33,116,66,65,146,218,44,111,73,2,222,99,111,24,180,41,67,103,39,216,168,240,207,142,34,241,86,17,173,37,58,64,186,213,98,181,151,159,141,26,22,31,45,92,64,9,10,26,76,181,236,145,18,8,30,219,158,183,71,138,134,56,65,70,34,140,141,13,54,245,29,155,227,200,183,113,40,113,203,86,214,2,162,90,237,5,247,2,186,149,205,73,75,106,255,178,8,39,126,21,96,43,117,216,10,81,98,244,208,25,252,177,189,21,50,204,13,115,42,29,115,2,10,234,207,168,29,131,228,241,82,183,158,85,177,161,142,249,81,208,74,7,73,61,160,142,153,121,63,78,230,152,77,38,100,58,119,15,102,23,145,201,189,165,77,147,230,208,2,84,68,22,86,13,32,68,58,88,73,8,48,139,117,27,222,40,32,182,33,168,89,188,113,162,162,146,225,102,118,158,53,22,82,149,184,240,92,212,243,40,50,170,149,147,223,104,185,45,162,20,59,162,173,157,5,224,233,8,159,219,28,215,102,178,59,121,254,199,162,199,99,2,69,53,6,16,218,9,6,241,44,220,188,45,208,250,244,235,250,209,70,110,222,198,183,219,47,135,143,170,11,226,178,201,194,8,0,115,63,105,158,9,227,172,16,176,218,211,18,70,236,5,109,35,119,143,218,145,213,190,153,247,240,232,191,61,9,58,130,175,235,45,122,195,207,43,194,102,133,91,46,230,18,78,212,122,114,168,4,94,120,96,72,18,12,142,191,141,105,202,78,241,114,85,34,238,84,11,10,254,50,188,122,76,216,117,121,110,3,95,91,62,253,60,174,139,195,120,183,220,61,229,75,22,220,190,134,216,68,90,111,184,152,40,130,43,39,76,144,94,215,83,252,62,127,27,6,175,158,50,87,41,85,95,32,24,14,193,22,92,54,156,254,77,61,50,7,243,25,48,156,89,56,17,33,107,135,110,160,52,80,216,55,217,98,40,102,1,34,70,233,200,205,172,234,156,17,180,123,113,143,67,81,224,51,149,12,213,251,3,2,63,30,249,181,254,120,160,155,133,96,137,181,35,5,182,121,214,39,128,129,237,203,19,137,24,93,101,255,228,209,34,58,241,253,187,131,60,8,241,178,36,11,26,109,21,150,214,31,242,19,60,118,147,158,111,23,164,168,73,67,92,231,211,6,86,222,242,248,107,142,231,119,143,1,168,27,187,91,70,38,230,162,216,232,152,83,71,41,183,182,189,94,221,128,7,217,182,42,49,232,20,23,3,87,95,213,181,137,117,14,161,52,243,122,183,193,90,134,182,58,222,179,72,150,241,129,197,216,227,156,20,75,90,202,71,128,15,137,242,183,117,188,168,252,39,243,76,167,222,12,190,250,197,206,164,145,191,47,206,24,20,40,253,36,4,220,72,143,199,19,105,30,48,219,215,196,37,15,182,38,220,134,239,35,187,29,230,68,215,139,220,215,90,25,184,246,196,149,239,249,142,248,63,141,205,161,28,87,142,170,237,214,67,142,251,97,163,163,242,208,139,28,201,5,249,160,111,232,64,231,207,201,197,196,206,92,127,71,17,57,48,200,25,226,176,113,210,162,108,233,45,224,15,40,196,161,187,228,55,88,74,235,30,68,12,209,70,87,243,159,85,208,70,192,75,111,14,15,239,6,234,134,248,30,113,51,255,128,43,104,82,6,158,241,74,19,174,199,229,132,238,6,70,145,96,242,208,185,17,12,251,210,13,113,233,186,188,29,9,195,244,71,62,26,195,82,44,209,10,230,93,188,92,234,241,145,115,67,77,67,44,210,249,228,5,84,43,160,77,103,214,59,87,195,200,20,129,254,173,229,229,37,115,254,49,72,119,145,188,255,12,95,191,110,239,124,12,213,234,217,4,211,133,39,184,242,103,223,13,5,50,56,74,214,135,66,130,62,223,167,91,175,30,40,134,82,42,167,175,169,33,40,205,88,123,104,96,189,142,226,130,73,0,60,121,128,225,203,146,1,170,4,93,235,72,243,97,77,129,92,246,173,53,161,138,204,83,70,234,80,223,20,176,62,149,150,127,141,182,196,163,80,117,13,31,248,64,166,35,112,96,44,221,70,128,124,229,74,60,65,83,15,20,135,165,184,82,153,163,153,145,137,168,21,68,140,120,76,239,1,57,32,133,38,158,157,114,92,79,139,129,100,233,109,73,206,6,164,101,18,250,41,214,14,185,87,241,153,142,116,3,55,77,138,149,123,112,38,59,191,132,156,136,205,108,175,236,117,66,107,36,241,192,147,149,227,116,253,26,209,34,134,94,214,68,212,25,142,117,207,151,32,13,101,187,154,38,54,165,162,58,254,142,54,86,89,13,232,46,36,31,67,169,250,183,168,205,55,163,165,77,37,211,28,12,51,80,99,47,117,190,69,215,83,246,24,48,152,252,50,167,183,242,94,21,63,211,171,23,199,4,160,172,57,57,92,128,50,52,174,87,77,255,17,221,149,165,195,162,43,38,226,27,221,101,124,188,82,226,222,49,132,246,31,27,81,255,205,69,176,163,195,253,83,47,80,99,157,132,223,160,92,39,120,73,149,51,171,255,67,218,107,160,220,58,236,28,119,180,1,82,24,146,160,44,200,70,141,109,254,12,126,229,95,99,96,3,216,221,136,205,113,142,122,186,243,183,255,22,253,97,176,39,222,179,209,180,233,133,72,37,54,158,28,65,95,13,1,59,153,193,87,230,128,104,160,201,205,2,196,6,125,232,155,188,65,83,240,126,145,178,63,143,0,240,193,78,184,2,226,82,240,49,22,50,167,206,196,168,121,68,212,156,249,154,95,24,93,83,113,168,33,14,246,208,135,139,78,122,101,123,8,177,97,182,122,128,106,140,8,192,100,143,88,196,50,29,207,215,143,65,120,133,133,118,94,128,12,106,130,195,165,203,112,192,173,166,222,59,23,34,6,82,131,16,84,214,205,87,208,140,201,182,166,221,131,122,181,85,150,65,139,133,103,23,179,159,231,7,175,204,95,130,131,126,45,155,135,76,69,145,54,197,251,173,9,206,46,189,122,101,178,24,17,52,231,121,151,60,255,66,47,5,0,134,235,185,232,129,137,35,158,3,110,230,211,73,61,209,224,71,153,55,248,61,100,233,170,140,66,27,177,253,40,208,209,143,4,27,108,105,166,136,60,8,218,119,168,182,107,8,119,5,118,31,219,43,94,70,182,91,68,254,135,245,212,250,26,105,156,109,180,133,177,249,140,89,130,79,55,31,123,18,154,42,191,139,9,240,237,151,107,173,188,134,243,132,118,79,249,197,52,29,174,60,127,48,203,213,101,118,178,117,92,200,49,217,119,172,213,150,231,103,134,168,200,159,174,105,85,8,72,53,243,196,179,102,171,173,207,190,134,186,250,180,231,155,193,203,81,248,175,8,196,145,73,186,178,63,177,60,238,12,42,169,79,173,245,76,171,131,19,102,237,156,201,116,42,209,167,158,198,227,114,197,227,182,212,229,151,110,140,149,239,82,124,137,145,167,26,54,159,102,237,132,139,121,181,115,78,145,179,231,40,243,114,107,190,126,230,152,86,21,43,130,126,87,172,107,120,215,174,119,95,238,138,107,162,109,30,0,156,48,191,59,137,171,39,151,249,219,16,202,29,186,7,225,198,202,213,119,26,30,46,66,61,154,127,212,160,121,30,139,137,77,16,197,1,225,23,181,190,52,124,88,224,250,45,111,131,115,99,26,188,227,244,207,13,101,230,130,96,187,90,109,141,203,246,150,213,238,2,180,162,199,113,129,255,97,7,65,101,37,145,166,70,193,39,68,86,45,6,162,80,189,182,147,237,204,108,173,114,12,139,6,79,110,178,50,39,17,113,41,178,217,61,88,132,240,93,181,152,170,7,71,170,146,115,177,209,87,215,16,157,38,76,45,46,220,16,103,58,125,32,153,241,187,154,232,13,56,84,165,56,94,8,6,118,36,14,96,65,93,68,50,208,97,85,185,103,1,161,83,67,194,38,128,76,181,204,102,151,40,72,219,119,58,243,206,0,99,50,157,241,110,31,75,39,89,181,28,80,34,47,54,40,145,0,60,100,212,148,16,35,19,189,130,103,237,1,19,109,241,72,134,148,103,72,23,209,106,186,211,41,196,18,76,23,75,122,68,251,50,11,252,232,52,72,57,5,52,226,217,252,184,71,71,112,106,214,93,60,250,235,235,115,148,64,183,222,82,158,135,135,145,153,54,138,126,116,216,66,235,51,100,7,1,111,11,231,57,153,174,195,76,173,195,2,137,227,217,61,109,233,31,68,5,179,235,72,80,16,191,118,37,76,119,131,246,39,251,58,127,172,229,32,135,167,216,216,39,54,7,180,45,236,44,47,186,218,5,45,145,201,222,24,126,214,198,237,218,245,74,159,119,201,233,27,224,213,175,46,43,252,104,209,254,53,126,25,166,190,157,66,64,23,226,4,74,69,28,42,238,195,233,33,1,64,116,16,110,32,81,97,57,242,250,108,13,200,31,184,115,30,190,65,111,225,197,90,215,174,221,193,216,165,11,16,3,153,141,181,161,223,213,141,64,243,41,33,65,208,245,48,203,171,242,234,120,183,57,60,85,83,188,148,249,94,62,178,164,119,223,137,180,49,184,166,120,134,127,76,230,216,208,161,5,42,237,196,235,114,222,23,134,110,242,244,163,1,42,228,3,251,93,156,48,46,154,200,19,163,205,213,250,142,212,14,156,210,48,20,148,235,204,232,128,21,3,100,38,184,230,249,138,117,207,253,60,79,102,174,115,184,21,102,194,116,47,69,98,110,200,73,248,186,30,220,75,239,155,228,138,141,255,84,179,127,17,124,167,107,102,248,93,59,11,170,167,110,129,228,140,41,111,215,131,169,31,210,192,131,220,50,29,241,34,235,141,60,96,178,83,126,109,14,186,209,248,63,130,108,186,180,105,95,192,234,29,87,8,197,153,103,55,13,10,116,247,40,153,54,84,199,120,69,98,185,228,4,234,107,80,168,240,218,9,114,58,196,150,245,120,244,210,164,160,201,55,20,40,135,138,179,149,228,199,157,192,174,190,79,35,154,208,104,215,44,229,241,125,186,156,42,60,224,60,98,79,40,64,126,207,165,212,10,115,54,25,33,126,58,236,50,194,209,149,85,111,178,89,79,15,60,227,54,174,229,243,135,42,102,50,171,254,95,21,247,31,125,0,215,95,9,254,115,158,204,23,106,103,28,139,202,110,125,119,242,110,213,56,152,116,42,49,235,231,28,252,0,141,119,191,200,51,122,183,74,56,200,99,174,153,239,174,227,16,247,241,53,17,43,147,201,28,236,24,172,158,183,250,239,232,109,178,138,191,154,85,92,101,93,173,175,120,149,115,204,109,250,109,193,172,203,85,254,72,122,109,173,97,223,35,161,59,23,39,177,164,124,186,70,76,36,143,143,79,179,160,167,125,30,112,233,209,141,126,247,37,119,77,159,6,86,22,186,250,64,148,109,116,69,157,161,219,213,126,74,234,55,4,74,150,191,164,59,229,208,73,147,153,74,155,93,93,177,111,177,180,36,107,46,26,222,118,125,41,31,110,95,84,199,96,81,223,99,229,230,111,208,187,44,207,189,197,162,155,118,66,246,102,5,157,180,61,121,27,171,235,38,194,219,47,109,32,238,247,114,130,158,184,151,243,155,87,210,50,16,172,39,124,229,145,237,44,49,206,229,30,118,171,255,129,65,10,175,28,62,65,30,217,20,113,253,179,149,240,28,118,112,140,20,237,39,7,159,242,230,64,144,209,53,33,213,116,176,141,135,111,225,244,248,107,202,235,131,88,130,60,113,17,151,144,193,21,155,78,5,33,221,177,64,101,141,166,1,217,83,16,24,8,33,203,8,73,180,252,201,36,37,193,112,158,81,36,62,12,87,125,150,121,19,39,92,191,173,210,244,36,77,195,88,140,26,156,4,231,27,111,89,251,35,188,185,246,75,176,127,162,75,144,137,255,124,36,161,108,144,154,177,88,19,197,21,51,61,242,175,177,115,118,58,158,40,174,196,158,97,198,184,209,36,126,232,71,189,204,186,7,102,36,124,234,204,89,172,220,192,86,101,51,175,40,9,191,17,115,155,117,200,237,22,138,77,48,250,240,160,224,117,133,170,182,144,213,211,213,2,243,145,65,254,0,2,248,48,33,249,80,119,29,108,76,228,213,3,143,250,23,23,131,183,155,60,55,214,27,114,225,198,150,10,35,148,123,109,118,26,2,65,205,51,165,231,113,146,183,118,99,110,128,192,107,84,128,130,68,16,88,195,165,35,170,219,153,195,92,132,226,34,20,77,81,240,139,150,107,214,77,155,204,106,79,19,168,44,71,198,240,87,142,60,44,60,246,5,116,90,243,72,82,123,206,123,164,157,159,113,100,46,227,97,151,247,172,49,26,253,214,112,110,75,191,20,199,178,121,153,73,146,167,80,165,179,249,104,118,42,76,8,126,200,69,25,1,35,35,219,85,218,235,253,164,63,211,195,178,60,208,120,222,151,167,79,238,35,131,109,53,18,149,50,40,14,206,218,230,111,82,234,124,19,223,6,18,94,196,199,189,219,79,203,3,86,63,184,11,70,220,145,70,39,204,13,70,25,105,99,18,2,0,24,161,197,244,35,162,11,157,34,54,196,92,138,255,30,83,77,170,69,196,207,11,28,60,155,7,88,6,248,72,159,21,242,123,4,244,230,249,74,32,130,186,174,143,2,140,24,130,73,170,186,195,129,0,221,95,213,21,27,147,128,194,103,91,111,210,249,82,200,180,140,107,187,79,132,95,135,105,220,39,219,47,101,130,232,19,153,84,96,21,214,227,184,212,26,88,77,22,173,250,215,51,120,214,55,206,86,220,178,39,170,15,114,12,97,98,239,4,124,47,250,230,133,149,196,82,209,165,151,0,207,30,106,133,62,251,241,196,196,47,179,145,179,2,155,15,5,165,22,67,52,207,39,246,123,134,219,252,174,231,168,82,8,7,192,229,168,45,215,86,100,235,111,169,107,12,249,89,109,86,160,142,181,238,237,223,92,168,130,150,236,224,116,222,45,18,13,13,164,73,38,27,208,24,138,45,80,4,148,58,149,54,128,230,244,22,230,218,179,87,51,104,223,178,9,209,228,14,206,192,249,41,82,34,115,235,125,150,192,196,1,165,252,62,83,243,157,37,218,134,192,149,232,139,145,253,205,51,17,97,192,121,157,60,181,170,126,156,5,44,196,235,223,123,170,2,118,228,255,243,8,132,196,221,30,242,92,159,112,180,131,51,25,126,253,184,7,4,110,34,217,37,185,91,186,44,77,80,104,181,58,171,9,210,180,17,119,8,141,229,247,64,62,232,121,118,112,133,52,173,5,202,94,170,37,212,28,222,193,97,51,164,107,197,181,220,102,52,58,47,147,194,179,174,14,89,19,221,145,39,174,86,249,64,89,192,101,143,207,156,186,210,1,137,143,225,13,38,98,59,92,137,53,31,64,212,100,157,144,100,131,3,65,115,94,185,87,13,25,176,45,184,207,19,250,197,231,86,217,51,191,125,60,11,95,125,105,236,148,166,54,6,42,0,150,180,138,38,30,235,72,106,14,217,69,184,242,46,197,173,38,89,234,41,197,213,165,79,86,118,231,142,207,69,207,108,20,53,179,160,231,84,99,156,253,80,13,15,65,18,73,160,149,31,76,124,141,4,48,207,86,81,87,66,32,121,213,115,116,230,240,201,247,195,159,66,154,244,180,174,14,101,84,3,66,175,40,177,65,194,101,162,234,26,55,222,21,72,164,219,243,129,30,172,104,212,50,6,152,90,233,235,35,221,207,165,225,44,109,74,127,123,173,56,87,209,84,211,48,214,123,5,105,101,78,188,169,175,36,172,214,19,232,125,217,130,252,99,237,244,61,173,193,82,209,216,57,13,12,202,82,193,78,70,69,206,74,240,191,91,25,179,254,242,177,68,23,139,165,101,32,52,246,25,212,240,38,237,147,60,156,190,36,3,56,163,125,228,107,228,6,235,44,250,90,92,77,158,36,217,168,161,77,26,49,125,99,103,191,115,41,120,16,231,243,69,108,169,115,81,127,195,48,164,132,75,173,147,62,148,220,3,189,186,165,200,86,60,18,172,193,207,129,196,167,69,181,134,232,130,109,48,76,133,202,38,184,207,153,39,149,26,4,242,77,59,193,254,102,222,99,68,91,147,245,252,14,111,57,224,121,244,233,148,97,66,37,162,181,44,60,144,184,181,187,204,143,33,120,225,243,226,97,190,168,25,134,240,146,145,251,166,104,183,243,126,93,104,93,84,55,148,49,84,30,71,204,203,236,226,179,113,247,64,213,92,207,126,35,130,231,86,232,149,34,79,127,8,155,120,228,29,247,142,10,151,52,57,180,40,56,93,99,171,253,160,143,201,101,183,204,59,240,23,208,83,198,151,231,231,147,28,110,4,156,102,57,157,18,249,18,50,20,130,56,53,156,41,45,170,41,117,136,179,222,121,239,18,168,166,237,2,237,98,107,148,236,81,60,2,33,181,218,46,71,254,197,234,84,204,80,27,160,118,123,153,37,55,238,240,199,98,227,116,197,126,232,21,255,98,226,206,152,34,211,121,85,69,183,195,225,202,232,188,79,208,206,156,187,96,21,189,252,76,203,227,241,70,211,61,52,217,12,33,243,41,50,152,77,47,82,19,140,197,235,100,59,65,70,115,52,246,95,80,145,224,57,224,221,213,78,145,49,47,117,102,248,205,92,84,18,215,150,191,135,145,62,36,193,200,52,133,187,34,96,149,139,1,97,248,25,51,64,247,58,93,111,15,225,212,223,114,61,92,11,95,154,153,245,208,78,148,39,150,34,40,110,50,154,11,54,4,145,21,134,166,233,0,193,39,105,2,102,29,28,168,238,231,117,248,142,40,50,56,142,240,142,165,151,16,85,30,155,98,225,239,177,187,143,215,228,29,118,98,85,69,167,21,45,116,143,40,42,152,1,87,158,139,169,81,137,18,54,65,178,145,44,82,225,241,84,208,111,202,139,17,95,107,130,255,148,105,65,106,172,230,171,55,197,239,133,168,4,152,247,235,19,138,175,168,216,216,171,23,160,83,71,40,126,234,228,1,76,145,9,132,135,166,202,190,232,233,218,105,184,138,161,252,19,33,132,61,159,183,129,62,37,37,194,79,104,59,218,204,215,82,166,4,190,36,224,43,97,59,71,51,188,214,175,54,18,10,15,153,110,203,218,59,225,113,185,123,75,111,206,104,24,163,254,170,85,40,105,9,229,41,218,37,240,211,103,89,253,97,34,77,188,114,220,132,215,129,26,109,149,186,128,119,108,19,20,122,172,175,10,20,169,9,104,195,150,51,8,159,140,86,232,226,177,7,196,200,167,207,106,126,27,140,222,219,198,149,46,0,13,93,255,121,205,23,206,245,185,247,15,231,173,156,59,156,16,48,118,254,93,148,203,237,189,158,180,101,52,62,155,57,8,175,171,215,67,69,104,60,72,232,226,185,20,206,65,59,42,125,90,124,100,202,134,141,239,191,110,203,164,223,50,232,219,4,222,205,22,70,62,180,75,143,174,228,44,62,245,202,39,117,215,33,145,80,106,131,177,244,66,46,89,167,198,251,80,38,72,190,90,118,85,34,158,83,17,61,132,124,53,24,63,24,90,249,68,131,245,198,183,117,13,157,137,70,189,73,23,75,77,13,25,88,126,217,87,108,92,8,133,154,15,158,112,113,94,186,162,177,9,232,181,162,55,24,38,161,79,176,4,233,11,158,170,242,240,168,77,25,3,223,158,186,182,26,129,84,106,135,108,205,79,254,175,227,1,238,248,79,5,72,169,217,128,158,1,139,110,157,12,39,55,95,3,2,113,179,81,229,38,144,253,35,77,155,97,157,9,47,133,35,238,97,246,176,156,164,3,236,181,42,140,173,1,46,164,218,168,228,127,219,160,224,59,249,247,7,155,98,77,199,215,146,55,151,221,185,163,241,26,122,137,164,190,205,207,4,237,134,165,74,238,223,226,15,248,242,139,107,210,187,234,4,145,23,231,180,229,53,254,166,201,220,10,14,58,33,230,72,92,230,207,170,109,188,229,137,28,147,22,41,192,213,40,215,216,127,14,228,9,13,85,247,106,247,1,155,206,136,4,23,190,148,170,106,194,155,170,96,227,85,168,247,195,20,113,172,17,34,38,123,79,167,110,206,207,53,66,173,162,178,166,84,120,160,160,218,186,227,34,87,100,212,219,28,84,255,59,138,26,28,227,102,205,94,75,152,55,216,163,46,225,96,152,57,32,57,159,27,251,178,201,231,5,139,31,163,136,69,71,125,19,213,46,252,84,88,215,163,249,153,181,25,227,174,4,105,93,98,251,60,164,4,222,26,165,85,83,87,45,206,132,134,6,108,89,96,76,139,144,143,144,116,59,72,48,184,248,230,195,135,167,29,166,42,207,49,87,221,159,42,168,96,157,181,125,152,96,130,72,48,100,105,145,96,98,200,116,7,131,166,69,99,117,55,141,40,125,106,249,33,118,191,121,159,138,79,27,90,132,13,52,0,61,44,246,212,77,127,107,26,124,234,104,26,14,238,68,79,124,247,99,81,60,135,27,62,83,231,104,214,53,69,104,188,95,120,30,105,222,150,218,223,80,221,209,86,113,125,226,123,36,1,136,94,206,253,124,34,218,2,77,208,172,39,238,148,151,111,237,3,135,99,41,22,142,129,39,56,105,255,31,62,12,171,5,206,94,114,13,174,185,89,199,225,131,239,187,92,132,102,86,138,156,36,55,112,65,191,209,70,60,75,110,59,216,180,148,36,118,238,139,97,222,17,236,209,68,163,76,177,206,58,196,113,2,166,47,131,113,199,180,134,23,174,24,119,20,124,144,29,221,9,90,224,188,131,232,13,244,94,200,129,51,27,11,124,24,154,5,91,171,150,238,212,117,175,71,155,110,168,3,236,162,196,193,74,101,6,238,157,132,151,181,88,122,26,84,194,170,253,198,124,142,133,185,66,4,105,5,152,87,209,178,134,243,242,197,214,209,103,53,218,128,193,9,83,231,55,111,29,235,133,45,107,115,71,203,15,1,69,200,105,216,1,163,183,18,222,54,6,56,48,104,228,237,119,166,90,242,184,97,160,218,194,255,151,131,120,180,104,202,167,157,179,147,77,161,34,65,201,171,236,177,175,0,92,134,255,40,217,133,61,187,44,165,109,184,127,37,189,61,62,60,232,182,210,78,123,118,207,185,156,158,77,117,67,26,37,222,174,87,192,241,152,180,170,218,35,86,86,91,87,98,97,192,129,140,194,233,36,79,152,203,136,73,223,63,26,117,190,88,188,60,42,9,45,54,223,198,207,196,237,26,244,60,233,67,132,223,113,147,253,16,126,10,119,41,159,99,237,109,167,23,248,146,7,166,214,75,0,234,202,90,254,26,71,82,240,116,216,96,236,109,46,104,255,134,115,253,155,36,36,129,188,183,140,151,14,153,244,139,244,252,214,160,8,249,226,35,58,185,116,255,126,128,120,235,190,225,169,185,175,255,64,176,56,247,249,7,18,39,92,249,142,98,47,116,247,126,6,66,208,245,253,217,123,160,123,49,99,18,90,47,9,80,207,212,123,18,61,155,193,44,242,205,146,4,96,210,222,194,220,47,172,241,165,29,155,45,163,105,121,174,115,233,211,216,182,136,24,90,234,77,214,70,94,160,35,59,16,39,71,24,186,43,251,99,53,11,47,60,159,24,144,250,41,114,90,26,97,209,154,96,63,178,67,28,211,107,179,90,253,127,165,163,26,175,163,165,60,47,25,151,210,245,25,91,122,31,176,184,179,128,161,75,71,166,119,40,19,58,101,115,237,145,211,239,250,235,224,4,46,64,94,118,213,191,21,42,27,169,75,217,193,182,121,215,57,216,234,245,160,135,78,21,125,113,51,250,39,177,32,227,61,57,182,118,16,212,181,130,153,240,62,148,127,188,127,160,37,3,231,33,68,181,179,95,116,179,14,247,145,214,104,222,71,140,17,161,171,218,105,81,195,25,20,202,235,110,70,90,42,47,194,109,74,85,60,77,65,92,205,106,16,171,147,0,227,16,251,48,224,101,8,46,29,94,50,36,213,78,254,13,7,254,227,219,219,18,45,213,145,136,25,210,42,32,47,62,61,139,31,140,17,210,249,37,178,80,160,59,139,26,250,178,179,208,129,81,82,239,54,209,224,20,156,174,251,26,130,136,28,68,243,28,42,28,17,51,90,6,39,125,11,249,223,165,193,243,148,129,17,210,146,186,89,202,253,59,205,5,52,237,17,181,104,92,54,142,214,177,178,59,214,195,73,72,186,175,17,1,0,220,146,69,144,120,89,133,146,152,239,230,141,237,0,78,250,117,54,179,45,38,167,90,149,136,233,115,8,227,210,205,255,208,177,5,45,173,12,189,122,109,122,136,191,40,176,51,234,201,4,208,42,147,44,56,120,17,43,69,93,97,143,103,130,166,129,101,7,40,85,92,157,218,212,230,114,139,2,233,64,93,127,49,140,232,168,194,0,74,215,40,158,61,12,247,57,151,103,148,42,210,155,139,211,87,19,0,208,70,224,199,34,241,199,70,169,161,135,61,105,233,172,62,114,0,96,15,45,231,45,55,172,39,55,41,225,133,190,138,162,53,142,120,95,183,32,192,36,208,155,102,233,86,61,53,30,206,83,199,125,72,101,207,29,247,104,10,148,18,184,234,165,202,151,116,193,119,185,112,23,192,20,152,65,174,8,254,94,56,95,112,30,175,131,75,160,36,26,226,61,55,97,225,40,77,212,181,0,239,155,198,208,128,240,202,248,190,135,42,46,22,94,11,61,30,199,55,16,98,142,1,63,173,36,147,172,74,152,45,239,201,204,46,115,27,81,227,120,112,155,184,99,79,214,130,147,122,64,139,9,147,208,82,76,15,123,98,5,74,218,198,40,175,162,34,226,243,95,227,126,94,45,242,141,118,9,49,66,13,62,135,201,56,200,96,255,212,204,11,3,243,18,242,108,74,227,62,173,115,180,224,226,248,249,141,136,245,6,158,110,65,8,248,189,225,236,226,84,45,8,72,133,12,176,12,140,172,135,245,88,80,88,0,185,175,79,207,75,134,219,100,194,29,255,125,135,114,8,126,63,172,235,145,65,229,120,37,197,36,66,254,60,122,61,197,192,6,79,197,152,198,219,179,231,14,155,211,69,154,175,209,49,59,91,6,25,138,1,144,199,28,148,67,149,19,37,147,101,173,173,206,196,37,179,47,184,185,251,43,182,74,221,246,66,82,220,131,113,87,197,241,66,226,95,156,93,186,196,250,229,244,248,189,22,207,27,43,104,3,210,183,207,145,95,190,74,251,145,107,71,36,138,225,83,79,207,145,78,210,137,175,90,23,239,94,181,98,41,136,109,211,114,150,87,255,49,149,169,69,132,65,211,140,205,214,29,22,127,210,12,110,19,72,139,152,200,229,246,220,110,222,227,189,5,36,90,254,53,6,237,122,57,142,108,23,90,140,146,218,237,207,124,148,18,43,1,231,98,177,83,35,133,156,57,105,201,222,84,80,168,12,176,33,62,83,81,72,91,127,176,136,94,105,255,254,90,145,155,68,132,45,203,4,81,16,2,218,66,189,227,170,31,12,196,122,121,143,12,99,122,129,195,234,210,79,14,55,209,162,72,6,182,66,57,203,144,165,124,104,28,239,250,145,78,30,73,201,115,103,29,184,58,64,70,85,21,63,220,48,82,120,182,147,193,160,57,159,29,228,110,185,119,116,208,106,226,116,121,81,43,222,244,81,208,45,54,252,92,150,203,97,118,228,145,19,251,135,68,118,217,134,205,225,179,191,233,152,12,91,197,183,100,112,245,155,90,49,164,31,226,11,161,97,101,12,52,104,87,67,185,88,236,186,244,207,7,33,67,86,181,69,233,84,8,132,228,204,119,32,165,140,91,72,140,72,59,85,160,243,119,182,101,202,174,103,225,103,157,66,245,6,239,65,118,228,82,220,95,37,111,101,138,161,191,68,163,207,254,132,5,33,34,56,45,15,145,79,100,40,250,236,235,36,175,245,20,209,154,13,198,149,155,0,80,11,84,80,172,105,217,187,232,7,132,48,231,150,103,105,189,165,83,77,153,247,75,244,46,186,175,219,208,150,199,180,28,58,132,148,105,13,207,113,32,133,101,252,13,167,207,239,200,38,246,25,126,101,156,150,20,134,155,28,193,203,237,91,8,31,34,172,248,160,57,105,219,239,42,133,226,116,81,43,132,235,167,30,68,43,231,221,164,52,182,249,179,61,153,161,159,137,151,189,73,236,246,163,36,98,19,85,248,126,173,105,179,75,212,179,6,192,100,128,153,211,199,108,66,203,86,207,169,95,199,34,119,154,244,10,13,220,112,98,175,183,40,113,55,27,57,116,86,1,170,179,54,173,252,94,178,69,116,19,143,251,130,194,112,136,117,223,38,229,127,85,195,14,156,30,223,71,155,223,129,124,152,171,136,110,120,95,180,53,100,168,25,3,216,42,54,85,46,69,119,107,155,145,251,64,53,185,193,15,13,139,6,167,11,60,47,89,97,48,152,126,89,204,146,71,95,57,111,150,78,240,251,102,115,113,11,147,15,192,253,231,25,248,245,109,134,153,56,58,101,46,144,2,253,31,2,83,198,61,64,121,63,76,80,67,29,12,66,28,147,254,92,69,68,35,212,156,221,161,237,249,146,56,121,137,145,156,246,183,247,139,124,62,163,212,103,229,186,93,174,69,23,160,26,196,181,43,175,176,60,110,211,55,131,146,61,179,46,79,154,194,63,7,77,202,244,150,202,18,92,217,129,241,239,222,111,51,135,13,231,255,23,171,205,2,165,228,225,46,247,213,245,181,190,140,154,241,182,186,251,24,83,159,137,53,64,138,170,164,60,147,27,90,82,193,36,201,173,182,188,108,188,229,45,193,211,18,253,200,185,25,95,180,93,30,219,69,195,239,222,97,161,110,214,36,114,96,168,76,77,164,53,131,226,197,100,0,42,106,159,84,214,55,249,124,216,170,102,155,118,134,77,181,65,115,14,167,123,89,46,212,228,181,29,222,148,86,228,253,74,236,231,197,148,188,137,167,27,127,12,253,186,84,67,146,211,91,131,122,218,230,239,254,175,168,1,213,249,121,7,221,136,146,201,36,166,47,73,221,190,128,205,126,206,89,121,78,233,57,64,136,20,67,198,178,249,191,17,131,33,149,197,130,104,170,130,142,237,246,170,147,192,156,248,187,123,25,225,139,220,171,61,24,24,114,110,77,3,160,244,82,56,94,113,16,27,118,228,217,56,29,253,10,75,145,97,193,150,89,210,52,60,146,17,127,187,216,5,195,108,15,251,39,157,158,86,49,193,199,155,106,6,73,80,247,203,61,88,81,56,93,158,179,40,245,81,68,136,69,32,237,101,122,112,165,100,55,9,127,59,26,9,41,16,102,92,246,179,125,108,231,225,63,120,88,135,69,195,239,197,51,245,72,72,59,15,231,42,3,184,123,64,176,64,2,15,246,220,67,193,252,8,159,56,20,44,137,45,172,109,183,204,159,101,6,17,221,228,44,160,69,242,153,202,128,203,12,4,126,92,35,50,234,50,118,36,235,41,31,25,142,113,24,62,9,95,20,19,50,125,158,204,53,186,86,53,189,102,153,228,219,22,2,99,14,143,147,221,199,23,113,107,196,224,225,104,121,99,34,19,112,121,28,191,160,245,10,17,84,184,88,225,151,167,54,240,195,72,254,120,18,22,155,131,146,29,227,234,30,101,250,135,69,125,243,191,220,108,252,27,73,15,229,136,53,207,18,173,204,19,205,199,182,167,225,33,249,143,99,91,17,55,149,227,252,128,238,114,212,169,242,145,36,176,68,219,87,139,157,11,63,61,59,211,206,153,189,127,223,109,58,97,39,141,146,29,253,92,94,80,25,18,106,154,118,230,19,134,225,160,83,60,150,40,14,114,137,33,215,197,110,48,190,240,56,91,138,248,129,37,247,39,83,175,2,103,194,229,110,102,216,12,120,6,3,226,163,55,78,249,252,111,226,91,6,137,148,130,47,48,247,229,23,243,182,71,150,137,124,20,124,66,139,32,193,148,161,185,236,79,174,99,200,112,53,55,117,29,34,237,204,153,30,100,212,1,178,63,101,108,21,60,226,164,189,178,191,164,14,130,253,211,82,162,209,199,23,248,243,208,248,249,158,141,215,199,86,0,246,74,146,131,115,160,41,65,31,203,224,248,194,77,33,67,47,171,200,140,46,76,21,188,172,177,183,243,246,224,185,32,56,122,180,233,201,25,233,15,85,45,133,25,16,136,35,136,145,142,15,86,80,133,48,119,224,178,65,40,193,213,90,108,89,160,56,151,217,217,57,103,175,63,242,81,89,154,80,29,72,39,62,162,124,64,207,184,236,170,24,70,121,44,61,235,14,3,108,68,201,57,178,69,188,58,91,211,235,251,154,69,34,123,86,213,66,253,253,216,176,67,99,197,91,185,250,198,244,215,134,106,130,27,155,101,61,23,181,173,83,247,184,185,24,221,87,94,129,150,24,83,250,180,99,14,23,157,95,133,189,98,219,252,120,118,181,213,41,131,138,220,245,32,75,155,209,55,31,197,21,188,175,14,108,96,144,219,70,87,169,105,80,215,39,54,253,164,135,220,113,179,11,26,86,90,17,173,82,168,51,234,219,159,197,190,211,12,96,163,96,156,21,216,237,81,71,8,238,177,222,65,238,18,207,224,198,6,78,77,58,229,128,113,49,80,53,64,60,188,235,183,243,253,19,186,159,48,179,25,11,199,176,100,249,48,94,85,170,164,215,111,157,248,47,235,115,199,148,241,90,5,156,158,194,36,48,2,128,54,251,107,121,73,162,149,9,148,65,58,167,164,203,170,52,197,196,44,120,167,22,204,41,135,101,200,149,248,38,73,57,71,205,69,158,255,72,185,219,30,199,49,162,53,242,190,45,142,206,11,94,30,40,120,221,10,171,209,31,64,30,69,102,138,222,180,169,4,28,97,34,15,174,50,15,217,31,255,141,56,24,233,173,156,216,252,142,255,94,59,43,223,147,253,34,44,189,10,93,55,252,67,27,40,123,12,243,5,33,140,234,16,240,115,171,26,131,179,201,114,216,135,196,14,204,11,226,91,159,139,238,182,65,152,10,212,173,146,189,31,16,197,251,214,140,176,101,41,217,127,19,65,118,112,116,119,159,28,52,102,175,254,92,132,73,106,70,124,121,229,34,136,208,230,102,14,165,73,4,170,233,83,76,138,148,54,152,21,227,68,40,188,180,162,79,72,48,228,26,205,64,66,33,171,221,163,170,114,114,184,172,219,201,168,200,24,77,52,12,80,226,95,105,205,101,189,221,3,5,202,38,226,148,208,76,126,116,245,120,125,186,56,187,96,82,46,133,211,10,66,86,187,156,137,23,160,98,171,226,232,11,114,200,18,250,211,87,122,21,93,163,90,104,194,160,53,194,74,207,94,195,91,24,76,184,136,174,136,22,245,12,54,167,76,106,249,48,251,40,188,97,95,223,30,22,142,194,231,189,143,57,151,51,105,150,197,223,211,167,34,90,118,91,128,229,236,240,185,96,234,208,26,179,111,122,244,232,80,12,38,10,75,30,38,189,236,165,19,26,106,197,252,71,235,185,204,73,177,213,143,142,148,0,198,150,67,125,250,112,233,80,164,49,60,6,157,40,93,68,163,97,177,11,138,69,11,80,35,151,37,226,112,83,104,68,199,208,112,120,18,122,5,174,225,120,249,246,187,239,139,207,193,43,156,214,226,0,98,218,49,189,224,164,249,146,98,223,125,50,17,156,249,81,199,227,5,93,233,167,93,238,114,241,192,104,44,145,2,60,79,168,0,112,62,78,120,31,150,105,225,33,243,194,10,247,239,80,186,67,248,147,112,190,206,149,49,185,35,4,129,193,254,128,152,100,164,105,79,44,168,54,203,1,129,230,43,92,174,4,56,200,148,20,82,211,212,136,193,83,214,240,81,138,39,11,132,114,55,99,194,4,143,40,233,177,238,255,46,166,183,5,115,190,182,171,253,136,6,248,32,219,26,252,55,109,189,224,176,219,6,131,136,170,148,101,102,58,242,121,97,120,125,146,126,232,251,70,200,193,191,199,169,112,172,43,218,147,205,17,215,99,9,141,194,206,149,104,71,115,45,250,190,121,28,115,88,81,131,250,172,238,160,98,146,119,165,113,166,10,172,34,174,43,44,119,114,32,110,169,188,210,22,181,71,3,8,218,196,202,103,105,234,72,209,168,202,3,206,120,58,52,91,169,202,207,73,67,52,223,246,40,85,129,186,17,147,193,231,46,110,139,178,74,210,186,252,20,42,212,66,107,31,239,184,60,105,247,138,212,29,59,35,147,239,109,123,57,144,11,149,66,71,134,57,20,223,47,197,51,83,184,140,102,217,213,245,43,232,173,139,129,135,141,23,147,64,170,6,101,154,52,47,242,34,140,3,101,199,41,95,122,146,104,251,210,114,60,120,85,93,235,23,132,185,200,46,225,58,185,30,23,139,234,67,231,176,36,70,216,129,111,57,23,74,254,117,89,199,41,209,178,61,214,211,184,105,167,86,249,49,90,42,123,168,58,104,222,200,67,41,108,0,17,167,116,177,110,201,116,233,182,36,97,100,6,194,14,109,98,123,229,192,135,60,139,212,178,229,24,178,75,57,129,64,124,38,73,23,182,0,233,69,40,62,242,69,133,151,96,88,46,115,166,144,227,171,12,67,150,150,224,205,128,11,68,98,7,65,199,98,217,18,163,103,246,75,237,111,191,192,188,237,204,240,118,109,98,193,54,170,132,185,37,96,110,213,152,18,190,35,50,82,137,93,149,215,225,221,42,90,5,238,158,171,51,61,216,167,102,11,175,66,32,95,200,136,58,38,185,31,31,7,154,137,77,199,135,129,68,11,138,218,56,51,63,138,232,178,118,35,168,128,222,75,254,4,133,240,20,138,225,42,242,179,147,238,252,236,171,207,216,158,161,187,121,28,211,191,97,168,90,83,211,109,149,65,124,180,9,172,11,247,233,144,178,35,236,201,59,110,14,121,70,14,224,61,254,78,212,28,174,65,117,240,197,140,63,81,231,180,236,142,119,35,45,55,146,227,92,243,89,103,227,113,113,7,241,196,218,216,222,133,210,176,201,227,29,129,190,164,242,224,9,230,82,122,179,114,75,246,39,15,229,149,39,223,54,20,209,236,251,52,201,186,78,73,37,151,126,3,228,78,186,96,42,131,8,164,251,31,66,192,181,12,97,55,186,77,32,219,199,151,33,3,42,85,29,142,29,6,107,115,68,114,214,114,140,199,143,20,245,129,9,78,83,246,169,65,41,122,99,69,204,115,173,8,254,95,66,163,162,48,175,244,113,209,100,147,112,188,220,233,113,5,212,201,138,91,38,191,72,7,99,178,116,234,92,48,244,0,211,154,27,247,206,232,89,85,99,233,132,72,85,200,139,238,153,179,24,123,99,134,246,142,188,239,9,157,112,162,234,185,118,245,59,130,224,204,31,163,171,38,159,221,225,99,216,177,58,35,104,109,10,125,89,23,53,56,37,68,165,189,60,83,249,63,161,240,70,141,1,210,143,125,157,56,227,11,24,55,38,168,16,119,213,155,223,143,131,175,37,234,125,238,16,194,101,201,158,4,110,18,210,221,84,87,14,13,169,250,241,240,1,12,205,98,246,198,75,250,239,249,104,97,127,57,19,15,104,126,28,59,196,119,32,32,82,17,212,81,175,226,118,175,241,105,177,135,71,82,187,16,240,159,71,37,41,230,115,64,156,184,169,24,234,219,0,246,117,253,167,73,143,69,3,130,245,116,43,177,166,154,119,212,153,47,46,26,192,155,252,200,241,110,201,195,252,231,181,147,45,221,62,85,89,150,72,79,230,174,245,52,49,209,202,184,143,160,9,190,63,249,33,193,163,53,123,237,31,46,225,42,225,49,158,14,120,71,133,247,37,52,27,195,168,0,173,254,175,48,203,127,136,142,20,140,58,102,224,52,13,72,195,143,146,84,91,160,228,92,126,63,39,81,150,207,232,13,28,22,22,113,169,45,140,23,5,46,155,127,197,116,25,54,226,104,89,169,95,100,83,211,41,119,115,107,60,190,170,12,213,173,189,220,228,10,211,105,116,245,166,208,229,181,165,201,68,170,57,36,97,78,110,76,75,65,230,77,138,17,146,196,148,196,16,237,121,105,24,158,75,121,236,185,205,129,31,100,68,181,179,248,183,65,29,74,96,126,223,176,27,19,62,148,147,12,48,70,173,22,7,123,162,216,137,16,123,171,81,196,100,84,138,92,119,3,209,28,49,46,184,35,78,201,26,213,233,176,139,204,161,161,100,134,151,46,27,220,236,243,154,104,171,179,29,24,244,219,213,4,109,217,17,167,110,219,11,225,255,47,80,164,122,91,85,104,133,179,78,39,122,132,12,176,53,220,175,184,93,42,5,93,129,217,176,225,1,179,77,53,121,239,203,231,143,218,94,107,129,31,11,195,254,148,78,105,60,149,153,223,20,120,153,7,211,141,71,154,236,170,254,85,202,104,196,108,18,145,215,252,129,244,163,252,137,151,112,146,157,1,59,187,240,13,15,2,216,118,65,35,126,38,27,221,174,235,245,160,106,120,196,95,105,214,48,54,136,226,74,65,88,37,3,224,245,60,140,2,150,249,134,212,251,59,123,169,14,76,79,118,67,227,62,202,182,40,50,114,7,24,44,54,254,33,251,230,193,198,191,167,178,228,71,214,100,187,93,9,99,58,230,102,178,170,160,39,178,130,14,57,7,70,171,249,174,14,35,35,120,237,233,152,182,162,97,118,134,142,150,24,7,159,154,144,20,178,175,155,125,114,58,253,140,118,189,3,236,201,17,137,170,158,6,138,214,209,52,137,203,102,157,11,99,113,92,97,55,117,153,111,20,219,251,13,105,77,46,143,89,53,195,147,116,53,124,195,182,95,154,49,226,94,206,124,56,128,210,109,131,196,167,229,110,5,138,241,184,84,170,48,209,20,77,49,194,144,208,224,23,8,82,52,152,83,235,136,168,48,59,7,125,42,229,139,89,170,227,83,9,67,233,174,188,101,17,74,229,208,35,149,23,105,183,73,116,1,80,193,46,164,25,242,129,1,17,88,87,87,94,55,96,126,151,60,35,202,219,9,3,222,161,131,34,149,198,202,198,131,167,91,75,106,85,22,230,193,8,201,156,81,226,164,111,44,147,161,162,209,240,123,26,148,30,161,104,16,29,236,170,204,149,74,126,34,109,24,139,125,1,32,228,137,89,30,201,147,146,189,177,123,185,72,228,107,91,49,121,163,27,243,72,155,29,183,58,67,212,196,210,201,58,31,102,67,158,141,70,175,80,213,3,99,198,124,34,110,94,209,77,20,85,45,162,82,18,61,189,203,199,56,131,228,230,7,53,226,247,217,35,66,115,37,68,130,210,200,156,186,44,33,11,229,31,84,159,92,194,52,14,158,187,179,106,80,194,179,80,226,202,110,147,204,167,44,63,158,49,55,80,115,164,46,156,244,58,137,134,55,253,220,75,9,103,136,249,242,3,215,220,53,123,17,75,112,40,131,105,76,0,16,17,245,242,195,47,165,106,200,206,26,130,189,65,203,2,99,181,5,143,191,100,128,52,249,154,169,127,159,85,163,175,105,201,79,170,124,33,172,15,229,166,146,194,104,108,129,91,132,33,195,224,4,116,61,113,89,52,79,251,121,2,32,71,98,121,115,214,245,87,160,16,97,250,177,149,55,39,223,212,203,76,231,248,127,176,129,187,75,9,209,101,237,148,65,111,200,193,164,44,66,237,159,220,85,84,91,89,208,128,237,151,180,31,151,237,151,16,114,221,155,43,42,4,83,34,238,79,149,66,231,157,222,132,11,145,104,170,56,236,84,248,183,36,85,4,10,143,170,141,177,87,7,163,114,225,72,248,238,122,146,203,203,157,4,155,198,245,193,60,218,180,175,34,89,80,195,35,71,85,234,238,86,77,49,244,128,157,230,211,30,114,38,88,35,242,190,254,27,132,194,18,236,121,228,133,95,97,44,236,154,28,64,235,14,62,141,6,104,2,239,196,0,239,190,200,189,55,225,88,118,166,28,3,155,39,73,135,166,250,86,28,103,243,78,21,135,177,206,135,183,141,13,148,181,253,155,176,98,53,113,191,110,156,23,111,210,0,12,145,6,255,146,80,247,0,74,171,33,213,96,90,118,193,89,208,79,47,247,61,246,11,199,235,65,231,27,63,41,110,254,129,80,132,0,167,84,59,171,175,164,131,185,207,179,36,207,187,236,180,205,188,150,112,119,170,82,180,155,78,6,33,163,196,74,97,85,204,95,48,248,81,22,74,219,228,3,163,28,111,155,134,69,37,9,187,242,25,75,186,8,17,151,196,130,59,118,14,82,207,194,129,82,65,199,147,72,96,117,243,22,125,145,219,206,184,153,41,144,219,98,96,155,34,94,181,44,163,237,168,33,89,151,218,192,247,57,198,126,236,197,141,63,109,159,157,29,83,185,46,181,8,73,42,95,252,161,116,224,219,172,169,119,219,52,46,170,69,178,172,93,174,0,45,81,139,114,181,102,240,100,159,66,137,156,200,175,244,173,51,117,206,244,24,77,6,23,82,12,37,118,160,225,85,183,69,79,100,126,129,93,155,18,95,145,39,32,118,241,90,236,152,14,20,126,31,234,84,34,120,172,90,243,50,162,34,238,83,91,24,255,99,225,240,27,114,166,100,243,207,98,170,111,107,224,19,79,177,203,231,135,126,205,13,231,108,153,215,16,143,6,18,244,71,18,188,143,224,169,189,54,129,185,202,121,10,142,246,219,251,81,92,184,115,207,55,223,23,9,172,6,80,2,236,96,4,51,62,54,135,46,10,0,229,235,188,235,218,127,115,177,136,157,40,2,71,146,32,245,200,137,190,179,220,117,208,242,197,14,183,79,124,35,171,203,89,139,208,30,50,32,249,148,242,236,98,48,88,255,143,25,1,235,159,210,127,229,219,6,20,19,41,23,220,116,32,214,217,7,197,244,101,247,93,18,117,151,140,84,68,104,42,232,36,226,57,55,57,181,128,52,6,203,130,54,199,103,197,158,184,138,127,61,223,65,111,57,25,181,72,139,155,65,139,48,15,128,95,194,241,163,12,246,39,191,53,212,114,194,90,65,109,13,121,48,171,160,68,35,192,251,149,193,182,207,178,158,107,32,192,59,214,166,145,205,76,194,17,236,248,105,195,184,201,91,214,106,71,163,206,253,189,15,166,160,158,55,182,108,213,82,244,47,221,194,227,48,139,93,104,165,186,46,214,47,63,142,36,158,192,116,253,133,77,50,45,85,208,33,203,120,156,6,55,217,53,210,131,30,194,170,65,32,80,32,81,218,104,125,77,236,131,42,23,51,41,208,230,40,175,127,201,126,254,209,89,221,187,181,101,185,235,139,217,248,49,187,232,192,124,28,52,88,70,236,155,38,60,43,157,178,180,45,203,113,4,9,67,86,60,136,52,5,61,152,126,254,205,152,68,61,64,58,226,75,218,19,204,177,16,138,148,243,180,234,110,6,134,194,139,167,50,151,95,62,160,137,209,208,255,81,199,177,240,114,1,163,160,235,235,172,203,57,245,240,94,121,56,11,132,16,23,152,180,38,90,26,107,103,77,223,70,133,160,220,55,161,159,238,135,127,195,39,208,86,53,94,195,241,255,207,90,238,9,252,64,51,154,107,238,114,42,193,58,242,19,108,172,209,86,71,42,197,80,100,152,114,254,57,174,37,64,50,36,160,251,173,106,84,18,16,170,209,101,166,151,240,142,96,134,97,50,207,93,244,231,22,49,72,181,188,188,85,53,41,160,158,84,157,23,30,169,226,115,33,73,115,107,143,0,226,138,147,191,74,190,144,231,29,158,45,154,232,182,228,53,105,112,118,75,176,179,123,111,233,14,139,90,157,138,223,14,191,88,106,91,191,149,119,119,125,12,238,211,244,188,43,214,146,153,165,147,172,221,81,131,160,19,124,234,236,188,144,176,73,96,127,208,169,247,17,186,160,163,61,186,59,233,72,217,58,90,43,43,23,250,105,188,236,66,19,98,125,250,90,130,162,167,174,46,218,37,184,26,92,237,34,0,26,104,74,167,221,23,105,113,9,187,125,231,185,93,92,121,93,23,185,54,19,90,235,249,3,121,58,43,88,53,140,51,45,206,210,228,223,67,147,216,82,11,167,178,164,218,132,152,116,134,84,112,15,165,106,15,116,46,222,118,186,76,133,157,255,99,27,35,96,230,14,223,36,164,244,30,234,71,169,225,124,239,103,239,185,44,71,223,241,177,16,211,173,64,220,127,244,65,244,249,195,214,90,121,43,248,177,241,128,96,74,224,104,16,53,79,225,14,219,175,78,129,103,35,184,131,156,66,49,75,196,237,145,109,124,157,74,188,157,84,32,153,170,210,235,165,6,155,60,118,114,50,169,40,37,1,220,122,220,107,20,39,19,238,244,128,227,140,103,0,179,250,11,140,38,165,57,63,111,193,84,165,175,223,21,24,232,153,190,211,114,99,96,103,146,32,24,107,66,117,93,27,243,49,114,246,219,30,34,20,17,69,183,243,131,101,22,123,146,89,58,14,130,29,141,36,211,54,162,164,189,208,207,2,157,64,29,178,133,166,206,71,226,123,104,195,207,127,14,140,247,187,212,124,199,222,83,46,134,206,111,75,190,63,73,82,47,139,200,197,11,130,44,168,239,104,124,162,31,115,106,15,77,72,8,188,215,102,185,145,177,146,105,215,243,128,236,120,202,35,200,18,3,56,41,51,228,233,136,75,253,209,15,226,133,173,67,184,30,89,158,18,91,156,153,18,111,152,178,1,79,85,158,151,216,76,58,134,155,146,49,89,17,51,188,208,128,156,11,43,131,131,106,12,149,63,166,121,16,63,219,137,51,65,222,5,172,189,253,110,113,53,167,226,44,245,31,50,38,174,100,68,22,13,112,212,36,155,239,195,60,53,18,123,223,198,86,22,195,153,183,238,240,84,186,32,5,221,42,82,204,140,146,40,142,221,64,66,150,70,55,47,30,39,14,91,230,39,190,250,204,44,92,192,48,150,46,192,2,42,75,126,145,237,31,191,38,153,131,36,227,179,79,231,201,9,204,104,33,64,247,81,36,153,134,244,72,253,218,167,247,131,248,178,75,238,207,226,79,244,209,92,176,76,70,26,233,159,72,80,240,245,86,236,211,60,129,147,52,202,224,10,121,136,140,72,97,73,10,133,96,120,170,207,50,34,150,192,32,223,232,196,218,17,88,13,218,31,177,119,20,156,206,58,133,152,213,248,174,186,249,107,70,175,113,37,10,115,145,51,107,100,20,219,82,204,77,140,219,219,169,215,58,48,94,235,31,79,145,66,12,48,214,3,229,197,44,184,188,88,27,187,162,100,106,211,186,207,12,7,55,129,174,102,0,79,203,232,178,166,41,96,67,20,205,236,10,17,185,214,114,166,94,180,205,186,114,55,253,184,106,217,46,50,15,196,129,214,56,81,178,117,165,228,136,107,226,194,252,239,232,52,189,121,119,33,227,225,214,234,74,40,173,225,105,36,9,32,65,235,127,209,218,119,230,246,90,85,92,208,117,25,145,241,125,158,150,196,130,194,200,251,49,170,85,124,87,213,239,96,184,96,197,63,244,187,217,215,49,3,224,114,164,10,22,251,65,108,238,13,29,254,18,139,129,219,58,169,151,73,96,64,221,26,16,12,14,12,78,9,203,11,80,73,221,118,103,173,1,169,193,215,109,126,166,137,12,12,135,17,81,209,32,12,131,60,0,153,66,201,121,182,155,39,109,173,1,186,45,253,219,88,63,179,91,22,106,108,66,107,17,105,97,59,6,133,136,82,129,125,190,184,234,131,23,198,146,94,243,204,25,190,50,160,81,176,220,38,215,41,120,112,38,74,163,171,24,106,116,214,231,194,77,99,71,195,47,141,134,111,103,119,122,241,34,5,170,123,150,232,85,63,156,112,76,202,78,176,136,79,161,164,245,223,119,235,27,8,99,121,57,0,225,90,143,129,173,209,102,133,158,64,233,181,113,212,237,35,132,15,88,36,85,226,152,217,11,16,251,213,25,7,85,125,48,155,221,141,133,205,66,237,6,5,241,72,247,133,199,177,78,236,71,27,110,205,207,241,40,22,141,156,101,179,172,227,30,248,161,147,84,177,176,26,32,103,36,110,30,67,137,223,121,255,110,247,94,76,30,149,83,111,96,72,165,93,200,58,207,176,213,13,29,75,187,45,112,179,43,234,213,242,216,43,249,33,207,40,167,96,46,219,167,44,111,57,183,96,243,201,5,215,73,106,130,134,7,142,153,17,97,126,88,35,57,154,246,15,16,48,120,187,131,106,242,11,250,99,54,230,135,88,172,62,208,30,127,145,236,44,247,246,202,229,174,206,139,144,172,167,141,73,106,163,33,202,57,80,76,67,219,18,99,153,119,22,223,8,132,90,173,119,88,241,34,158,228,149,129,248,73,110,153,176,170,26,33,117,151,227,204,107,181,26,21,245,164,236,219,77,199,199,35,205,68,49,148,238,100,242,214,99,155,100,23,181,56,99,13,119,225,107,153,143,182,246,225,208,95,196,75,114,87,98,134,84,115,210,91,16,159,38,83,255,6,141,147,176,178,28,7,98,154,157,117,22,186,222,203,229,195,97,78,111,21,1,209,7,216,220,49,206,103,113,12,92,248,125,213,205,208,125,25,23,255,131,122,18,244,102,110,19,246,57,97,29,160,122,12,249,191,178,249,218,202,196,118,95,227,2,202,72,253,166,224,126,142,247,255,235,17,182,40,239,72,49,69,198,190,146,45,197,143,72,232,60,106,114,24,207,64,199,21,148,63,154,255,94,65,161,221,130,35,137,115,115,180,84,241,144,61,126,156,106,22,242,150,187,185,206,193,114,109,233,188,162,195,80,84,37,148,76,38,233,82,107,55,196,65,244,142,66,169,247,79,119,3,176,143,31,254,163,250,36,254,95,244,199,37,243,80,12,199,218,35,41,133,113,33,14,19,65,68,109,255,12,46,255,36,190,184,245,158,28,243,54,230,255,252,10,28,140,185,137,52,36,177,174,246,253,228,33,46,4,171,48,142,104,247,44,43,68,29,108,218,170,183,172,241,193,73,207,219,37,138,1,150,130,219,251,45,165,77,163,56,41,211,48,28,136,245,232,57,137,129,92,21,128,45,154,238,208,32,231,214,120,74,179,72,201,37,186,206,84,50,7,123,49,12,239,253,65,164,149,178,102,109,53,34,240,96,200,137,6,135,145,49,172,151,73,182,67,200,127,30,211,36,85,185,165,56,97,54,221,209,90,70,22,143,152,129,15,204,59,5,143,171,180,132,244,145,20,44,11,142,181,72,223,151,147,26,241,164,157,222,7,97,79,43,35,103,66,163,25,155,118,174,109,181,98,111,56,136,55,63,81,51,89,250,61,148,153,110,132,172,218,99,18,104,242,83,175,53,197,209,126,182,44,53,73,229,104,21,252,214,227,27,176,170,31,200,156,251,40,253,90,104,145,10,1,175,235,135,77,56,137,11,51,99,233,59,250,122,62,196,2,245,142,86,59,143,192,123,130,214,245,182,157,134,228,82,199,243,29,167,83,105,75,4,236,116,174,50,18,89,242,200,87,109,23,221,184,42,3,82,80,103,135,218,190,7,129,98,180,64,149,196,181,217,136,28,58,56,53,14,16,248,30,82,197,85,149,53,2,112,81,243,53,131,126,174,187,3,237,209,3,20,9,246,22,3,194,201,118,169,89,116,66,199,66,16,175,193,47,238,65,137,126,87,148,144,167,191,216,137,23,120,162,24,80,68,168,161,148,167,6,137,56,1,160,59,75,181,56,92,175,90,233,7,212,173,52,242,167,91,64,194,196,220,18,71,186,221,224,84,47,76,156,55,190,180,102,18,21,27,55,125,249,219,154,48,54,210,58,72,73,154,78,48,73,105,233,200,178,230,208,130,172,18,160,79,130,20,166,83,203,232,203,108,136,211,228,152,192,103,222,8,46,245,50,29,25,234,254,228,47,202,93,242,41,33,139,115,212,186,141,90,222,177,4}; diff --git a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_8spp.cpp b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_8spp.cpp index bd852630..09a07e9c 100644 --- a/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_8spp.cpp +++ b/sdk/src/components/sssr/samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d_8spp.cpp @@ -1,3 +1,24 @@ +// This file is part of the FidelityFX SDK. +// +// Copyright (c) 2023 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. + // An Owen-scrambled Sobol sequence of 256 samples of 256 dimensions static const int sobol_256spp_256d[256*256] = {32,226,72,70,57,171,246,75,112,81,109,239,120,101,230,103,103,41,249,86,253,99,132,184,214,147,128,248,17,149,163,17,60,40,169,196,77,79,102,23,250,77,75,151,95,123,234,198,25,26,184,114,230,188,105,18,231,233,175,151,19,174,202,71,84,229,247,148,182,127,92,14,41,112,162,253,35,101,137,30,111,134,95,122,28,2,41,254,181,91,101,188,145,31,166,38,53,193,1,122,99,86,178,36,198,169,113,255,97,221,227,231,29,100,30,141,250,254,16,157,2,220,187,95,181,125,207,187,105,119,156,41,16,194,93,216,227,124,138,90,227,1,88,153,233,69,120,36,19,189,120,4,185,220,185,109,184,96,247,173,210,227,54,3,18,9,139,213,156,57,61,101,37,247,21,201,10,143,11,38,146,18,118,129,95,191,75,207,12,252,238,104,47,39,190,229,31,56,20,127,42,178,100,141,93,222,192,247,186,7,224,161,72,100,87,69,218,44,25,195,185,118,179,123,231,170,96,225,204,52,117,60,3,86,25,143,230,18,11,165,72,188,158,3,66,105,50,200,226,145,227,45,183,62,82,176,191,36,248,191,189,122,96,185,146,166,203,78,144,189,67,174,154,182,86,169,90,236,101,40,71,107,81,93,159,82,75,230,157,191,34,35,235,139,150,193,10,142,217,77,154,249,74,13,196,248,56,154,27,6,242,226,105,94,66,67,145,112,31,145,133,68,21,0,44,212,254,153,183,238,98,102,145,199,100,213,196,52,131,141,216,209,236,122,58,249,188,108,8,206,62,199,207,103,160,247,207,255,101,185,1,113,223,126,182,0,50,93,250,174,194,18,65,111,206,104,156,3,48,195,122,212,10,101,235,200,13,183,173,7,192,3,101,228,84,168,121,241,205,122,115,132,155,242,215,22,236,242,69,35,48,245,3,175,68,57,4,15,226,155,222,140,54,48,80,200,194,149,213,68,225,14,182,122,147,195,69,166,191,17,176,58,222,58,190,70,66,153,196,215,121,123,176,190,161,145,203,121,255,27,207,28,113,22,44,232,46,84,181,131,245,220,27,202,161,38,94,208,39,143,52,5,154,85,121,139,226,223,159,246,170,56,94,209,188,71,205,76,16,233,168,172,200,37,19,123,120,202,28,175,232,88,120,107,157,198,111,253,18,24,36,35,43,169,199,197,137,194,12,238,138,232,17,17,58,115,39,234,4,164,225,215,14,185,232,76,215,171,142,206,206,132,90,31,130,24,0,165,34,91,126,113,64,202,144,114,132,125,58,184,234,211,246,238,168,7,1,172,169,218,67,29,185,66,73,49,222,167,243,189,36,116,23,223,219,200,84,67,94,53,79,26,202,204,91,180,221,166,106,18,207,17,128,137,246,235,162,13,129,130,49,76,104,189,138,55,174,71,152,49,116,204,207,103,198,147,225,142,79,8,172,59,234,225,192,168,181,144,185,6,233,243,61,123,46,55,44,16,228,79,156,235,190,115,61,162,115,182,122,230,138,204,140,86,173,80,99,207,211,181,23,141,152,17,180,35,121,168,67,205,107,74,55,229,234,210,6,94,48,186,210,189,2,200,190,181,227,128,211,225,215,228,74,7,188,195,36,82,10,131,96,99,138,63,1,210,39,134,153,112,72,163,196,55,126,37,125,107,234,166,129,80,61,97,121,20,123,222,3,155,219,62,49,207,87,182,26,214,167,142,89,38,36,112,87,100,56,245,240,152,23,7,237,11,185,206,233,203,131,42,53,35,60,40,211,114,9,13,189,130,196,210,173,39,208,56,110,34,240,65,75,234,76,73,34,39,2,118,174,237,52,194,197,28,155,161,135,180,200,3,89,210,26,154,145,45,57,54,85,26,118,207,212,58,101,69,202,184,36,234,219,155,41,29,80,22,193,175,145,100,50,29,149,166,168,162,213,130,36,25,234,78,84,97,191,139,95,156,9,12,41,97,110,222,8,16,250,161,130,45,111,195,83,213,16,141,154,48,124,175,89,25,27,9,172,242,51,167,76,109,69,107,23,80,23,166,12,16,180,156,182,238,148,249,59,130,75,122,59,134,240,69,220,21,230,47,1,124,66,180,77,247,147,103,66,98,211,96,105,213,127,178,144,102,213,33,247,141,232,67,62,86,230,222,146,68,122,27,147,7,85,69,31,22,67,67,78,13,149,221,57,121,176,133,161,84,201,146,119,196,217,19,132,52,76,135,247,107,29,131,248,220,156,248,29,41,36,202,174,136,253,191,226,91,179,96,69,213,172,0,206,75,192,54,69,120,138,218,171,185,232,211,139,8,31,11,50,119,28,197,83,158,170,229,244,195,190,23,213,87,70,17,102,197,39,59,88,152,234,95,106,29,195,236,114,136,6,159,105,101,2,119,184,47,212,218,188,165,163,138,174,114,71,54,127,64,183,39,51,42,209,202,106,96,215,154,56,33,102,25,62,111,9,49,4,98,142,198,128,138,13,74,95,229,42,164,19,175,179,111,138,19,157,125,94,34,221,103,246,144,141,176,129,201,55,100,23,12,139,33,227,91,223,224,69,120,83,245,50,57,190,21,54,86,245,95,250,34,71,249,100,201,144,16,221,0,40,74,133,38,145,48,217,119,132,34,138,67,161,62,221,126,108,207,140,42,156,13,224,198,142,19,55,85,254,155,140,168,250,58,118,137,42,78,8,48,89,195,167,91,243,246,88,23,22,206,17,190,56,125,171,116,245,129,121,57,144,228,159,197,243,217,239,86,188,152,88,239,112,120,245,119,147,189,25,128,240,72,208,29,162,23,152,24,143,226,136,174,171,58,178,10,5,250,209,239,88,62,34,251,156,163,231,247,102,112,46,48,61,233,24,71,54,73,12,81,195,243,115,138,145,194,164,135,148,51,201,104,74,24,78,107,65,246,118,159,165,130,206,34,157,177,180,10,126,163,167,129,75,0,149,115,172,21,242,139,162,170,92,238,35,46,24,108,101,62,26,147,180,210,227,166,103,149,188,192,92,115,141,161,120,90,231,250,181,130,208,232,151,157,141,208,27,81,82,42,162,244,186,62,163,6,254,94,107,138,123,144,14,216,138,235,104,135,98,77,82,57,47,77,171,213,192,134,69,226,93,197,9,63,181,197,169,22,248,190,55,178,250,167,76,157,101,170,138,94,156,44,12,155,102,133,133,149,43,224,51,130,44,138,3,195,25,161,29,216,1,188,160,73,4,196,125,240,92,88,50,192,176,234,39,109,96,39,60,165,226,80,248,179,232,244,141,102,81,131,110,19,206,225,222,115,198,63,195,251,19,155,77,51,194,251,124,13,77,69,106,112,114,187,126,67,222,81,227,163,80,172,25,70,205,111,48,160,111,165,112,243,47,236,107,81,15,83,95,132,80,133,178,116,87,10,195,139,151,122,44,82,111,24,234,156,187,202,250,20,233,186,204,184,154,149,117,78,205,119,71,166,192,239,88,148,154,229,200,139,163,129,12,155,167,252,50,198,46,106,221,91,235,75,2,14,240,122,62,178,218,42,223,213,6,17,212,242,32,190,96,163,121,63,228,65,111,229,63,70,140,232,221,248,216,80,5,145,12,27,33,195,86,111,42,125,70,44,232,82,209,40,234,168,224,215,215,133,247,128,76,248,178,34,253,61,204,193,105,44,227,66,45,238,159,16,241,67,99,178,235,181,68,204,234,144,58,40,132,125,203,25,204,148,151,253,195,198,81,8,54,248,148,248,58,54,235,82,71,67,181,212,241,43,111,111,202,69,166,200,66,87,245,207,70,112,64,26,240,149,82,86,28,104,17,59,72,154,106,1,173,59,21,204,184,231,15,224,161,253,174,78,249,25,217,35,144,180,57,102,174,57,138,227,125,141,246,16,35,201,173,170,31,107,205,169,59,19,52,209,226,49,136,168,13,238,63,53,78,203,68,18,146,228,165,245,244,84,215,78,230,167,83,239,15,210,34,99,90,184,143,187,50,98,95,182,121,47,53,112,15,53,239,130,105,66,142,11,185,224,203,20,44,156,28,197,195,65,118,36,206,88,55,37,18,112,9,20,231,73,6,11,225,79,180,145,124,204,29,245,148,198,53,210,171,103,53,215,106,111,154,237,107,2,249,79,145,126,255,255,53,222,196,57,237,131,6,63,45,70,68,190,191,12,210,247,162,41,135,184,234,206,153,176,115,255,114,178,110,24,25,66,114,55,29,79,253,67,124,245,37,236,13,88,232,186,18,143,178,59,5,237,10,249,253,37,88,46,134,71,53,74,172,186,69,137,11,154,60,68,120,125,100,91,182,239,177,38,28,125,208,165,38,150,207,244,41,88,127,241,251,168,84,195,111,37,211,165,113,3,212,184,180,207,48,52,204,171,213,128,154,138,218,69,214,154,99,201,203,109,93,71,190,5,99,1,72,173,15,149,49,253,51,82,171,179,114,131,68,114,133,15,104,227,141,109,39,68,225,130,50,51,133,154,148,48,28,230,9,43,157,50,133,203,239,37,160,233,120,54,20,116,57,174,116,158,45,8,196,14,200,80,203,212,233,1,0,88,172,214,196,22,192,224,142,138,146,230,105,100,153,155,112,241,124,26,71,253,143,4,191,50,49,88,226,25,142,141,13,12,50,159,122,211,42,168,23,217,253,218,151,135,3,152,114,102,191,76,186,42,124,70,19,56,25,85,234,58,57,225,230,253,56,194,107,134,142,201,213,43,14,33,242,16,141,205,196,99,143,100,115,5,99,128,100,221,174,110,191,83,165,164,78,60,124,209,199,63,185,120,175,43,3,24,40,153,1,83,147,223,112,72,242,148,166,115,36,138,42,13,63,1,45,173,225,83,121,19,23,208,171,146,240,108,150,3,213,83,210,238,72,120,80,197,2,4,159,197,138,216,19,178,24,173,212,237,169,129,129,102,51,63,203,142,11,134,180,207,105,98,133,253,20,224,6,126,194,167,33,132,90,101,179,113,216,222,132,30,88,23,229,210,85,6,154,226,252,17,39,174,208,255,8,11,252,159,110,195,86,250,59,161,218,31,140,167,41,33,201,143,250,68,82,205,44,4,77,43,214,212,60,82,214,41,44,125,236,152,34,64,133,184,58,145,227,65,70,73,166,49,21,158,242,114,42,75,209,36,72,188,192,146,223,138,76,27,235,115,153,105,169,96,209,231,4,33,105,226,175,187,91,218,12,73,168,214,254,98,208,113,214,116,177,49,34,94,22,127,175,12,155,193,56,187,115,187,240,136,234,206,189,250,115,219,154,17,52,62,198,63,225,81,77,90,127,246,219,192,106,223,78,102,88,142,46,208,156,230,196,67,182,18,112,210,126,198,59,15,234,166,243,77,61,149,24,223,70,245,142,178,199,101,195,190,109,78,244,224,12,84,52,158,184,88,212,155,159,128,187,54,48,209,190,202,157,70,122,109,33,221,124,227,1,196,124,121,163,138,238,25,129,134,83,111,124,60,142,46,143,48,85,63,5,77,46,251,193,209,81,108,149,108,1,47,137,175,85,106,148,27,204,145,104,3,152,84,228,215,113,141,6,117,115,151,206,248,61,43,182,198,76,88,12,222,132,75,73,8,205,190,32,12,159,70,205,4,158,0,107,220,104,90,223,181,80,7,111,166,130,16,168,145,218,242,101,35,165,172,12,217,239,157,76,37,238,176,63,124,243,45,101,181,191,200,64,186,170,42,104,154,191,224,67,145,240,72,82,103,93,108,220,251,36,178,110,145,98,136,83,2,171,177,220,23,98,221,2,160,216,219,237,90,105,255,48,157,136,55,102,122,181,7,225,55,229,254,215,169,94,22,44,65,136,50,190,151,198,54,132,81,245,106,71,91,141,176,162,15,210,33,14,140,108,81,17,135,249,17,44,15,121,28,16,114,178,210,7,129,250,11,239,18,86,203,161,124,2,185,178,83,110,168,3,81,125,80,149,8,67,30,212,0,129,8,77,255,114,243,68,8,119,210,232,104,244,127,165,159,26,176,206,160,228,34,116,10,3,91,65,149,163,43,43,44,171,113,113,223,206,17,63,64,215,216,94,118,5,139,66,201,213,30,120,149,18,236,99,41,81,175,245,1,7,171,209,151,134,28,32,122,201,13,18,46,236,215,113,188,192,221,39,69,117,121,255,119,26,59,142,121,126,238,179,163,183,245,98,199,32,46,39,137,236,232,52,138,4,60,86,83,12,100,44,195,49,107,228,105,56,183,18,177,222,50,189,188,97,197,148,94,99,1,198,221,121,206,54,31,212,145,62,73,77,213,189,38,66,13,139,69,173,57,26,11,176,245,141,166,141,203,10,48,45,201,17,131,241,115,13,165,235,28,129,88,72,36,124,169,128,6,145,10,109,219,198,187,90,149,67,215,68,116,33,56,204,217,236,231,0,205,84,97,113,175,30,185,95,187,166,164,123,103,0,218,18,150,180,103,151,153,146,97,15,161,171,246,252,131,198,186,58,55,210,93,58,157,3,142,220,98,50,202,151,2,115,205,200,3,236,146,210,233,71,222,129,198,18,131,29,157,152,63,201,45,197,253,170,121,124,232,64,197,112,22,208,106,99,54,41,247,146,135,234,142,177,3,38,157,234,222,46,189,233,76,41,150,255,135,82,99,244,246,187,81,215,16,76,188,188,104,156,21,239,255,206,97,35,217,194,13,70,106,106,238,171,232,93,223,145,190,50,39,144,48,13,113,146,151,178,156,18,131,231,168,108,178,224,7,44,122,98,87,166,65,220,174,138,98,95,93,188,127,246,195,136,215,160,201,137,35,217,167,126,219,175,109,180,111,127,222,93,69,133,2,58,198,186,238,108,57,157,101,174,249,26,46,210,254,251,76,43,197,209,161,52,197,28,246,173,229,35,43,13,81,122,34,245,212,223,50,135,69,70,192,171,78,9,135,189,54,168,232,131,250,208,59,227,252,247,231,40,235,203,254,51,25,198,223,165,81,140,141,67,194,180,31,194,172,47,195,56,153,118,221,30,217,17,85,154,184,122,15,130,179,86,8,37,33,200,95,144,73,175,68,185,197,128,182,154,171,147,182,86,172,23,236,20,92,194,110,253,124,133,82,127,206,92,34,108,69,170,47,61,41,87,108,218,3,244,7,124,51,153,83,186,164,116,154,85,123,43,135,177,107,28,189,81,241,214,189,235,233,142,6,109,183,130,75,79,107,99,67,31,164,248,227,114,159,230,115,116,115,252,33,75,4,171,191,217,88,245,156,203,48,239,140,253,211,46,184,136,34,21,248,161,128,156,16,88,64,71,34,174,125,70,164,125,92,205,214,79,157,199,223,143,214,138,213,150,169,17,16,181,95,200,208,91,91,55,125,7,1,39,91,6,103,252,246,22,71,110,149,236,73,1,247,51,2,168,88,124,234,86,100,6,94,1,17,215,157,34,238,126,194,222,109,67,175,96,45,252,99,58,3,34,192,251,95,240,36,188,243,191,229,74,164,55,171,108,239,73,208,140,114,46,244,36,30,33,56,14,209,94,86,28,9,153,30,23,102,165,252,98,77,72,233,22,126,152,98,40,246,35,93,137,114,191,114,200,54,214,8,238,145,43,119,180,186,55,74,170,232,166,247,56,233,9,162,16,241,95,47,5,109,72,125,67,35,130,55,138,75,157,246,85,244,3,230,60,226,159,12,234,155,160,180,119,243,253,179,202,194,53,218,65,208,230,212,71,228,29,49,220,31,146,244,249,84,46,237,203,93,171,73,33,115,46,109,10,163,137,73,18,133,213,236,174,230,216,119,127,80,199,18,100,180,236,191,127,152,158,226,45,72,70,181,106,90,21,229,46,41,109,55,237,81,0,158,169,63,40,22,85,246,181,235,161,180,28,175,136,87,132,184,54,121,185,69,89,58,20,54,81,101,87,37,251,152,4,162,108,113,248,178,219,151,240,144,158,242,185,138,4,34,148,255,250,66,75,144,141,25,248,244,89,180,203,97,141,149,179,129,213,186,64,101,242,119,130,121,108,230,198,74,228,155,96,237,140,201,158,44,127,161,120,219,94,11,95,27,145,80,184,107,215,88,252,32,89,59,97,159,249,183,75,131,180,65,184,179,85,80,88,74,128,53,126,191,54,169,0,133,100,248,196,158,91,121,110,12,248,130,87,248,186,85,136,101,181,0,90,45,34,227,84,17,40,96,221,187,167,131,112,48,70,62,240,138,78,245,248,226,203,255,32,242,246,141,200,17,167,32,151,12,72,159,221,190,56,115,237,233,226,113,71,228,167,60,113,127,28,174,27,176,227,160,77,221,157,64,14,166,82,60,78,7,91,16,214,169,78,222,97,33,229,210,4,255,104,234,42,181,7,177,190,23,40,135,53,67,63,28,151,60,167,81,21,190,110,214,160,222,51,228,87,83,113,220,46,182,163,193,79,214,249,120,197,244,197,169,252,20,33,253,246,46,198,16,208,35,110,5,37,236,172,149,234,155,32,36,8,249,70,224,226,40,16,146,131,224,173,250,111,102,227,160,196,255,167,81,196,62,24,6,39,4,245,139,98,158,201,247,5,6,2,61,92,5,65,70,24,206,135,30,246,146,155,22,29,247,25,112,186,5,208,134,240,95,137,29,48,148,222,92,36,165,248,10,244,222,158,131,46,156,217,243,219,101,123,98,209,124,89,178,16,48,173,142,241,134,127,160,217,64,134,35,244,28,253,59,26,10,212,162,143,252,94,0,198,0,16,156,116,145,64,255,206,234,251,104,250,213,247,171,89,86,125,48,237,216,196,160,45,90,227,12,33,58,31,88,200,117,101,36,105,135,49,134,64,181,233,40,63,100,189,192,13,48,58,159,183,105,34,162,170,166,132,83,141,116,29,39,216,84,29,224,211,54,145,251,248,148,150,203,26,51,179,47,134,175,80,66,223,24,221,52,170,59,241,37,95,232,183,15,162,203,144,221,60,248,8,211,255,78,249,55,59,23,131,11,165,152,182,82,168,71,89,48,249,78,107,182,117,73,21,79,42,128,232,89,103,207,13,224,32,236,175,138,201,54,26,98,122,91,253,144,222,108,171,101,120,208,168,40,29,46,64,23,171,248,115,40,80,28,107,143,65,188,142,205,155,234,86,121,157,124,23,44,177,188,201,222,229,244,169,241,155,62,102,187,15,28,49,168,157,29,135,202,9,160,102,125,112,184,31,209,162,114,13,130,215,93,15,255,110,50,54,19,144,98,47,46,170,252,210,5,161,176,69,185,97,187,253,94,124,215,85,69,73,136,150,68,137,217,52,113,151,241,70,44,102,126,10,143,167,133,81,239,233,109,73,171,141,93,133,112,185,133,103,206,49,208,130,79,127,234,48,173,231,82,200,74,68,194,188,185,26,56,199,134,122,3,153,227,174,245,23,34,49,20,68,184,202,1,232,252,31,171,45,85,7,114,187,66,203,169,98,117,144,15,165,104,143,111,174,100,197,60,7,53,248,238,100,12,162,96,40,189,247,101,64,57,57,14,195,114,229,155,228,32,111,37,141,8,8,163,2,223,6,96,54,144,175,85,141,51,77,41,60,192,113,15,103,101,44,30,102,189,100,251,227,71,37,62,123,4,63,119,25,116,47,205,191,156,1,106,136,248,37,151,162,72,226,41,208,133,69,146,114,137,43,245,90,115,117,90,122,134,180,218,136,10,36,210,53,138,90,139,213,130,56,173,119,174,71,72,213,138,87,171,101,156,110,0,164,38,191,156,215,148,220,106,138,50,237,54,37,49,215,127,45,81,226,61,181,195,147,154,208,170,94,34,8,228,121,71,182,239,63,56,65,244,0,70,162,73,198,63,16,134,216,58,187,203,234,115,44,209,105,127,183,130,74,82,203,219,128,128,162,13,47,106,252,31,56,155,184,119,56,139,70,241,3,104,153,43,183,28,68,241,224,25,154,52,51,131,108,142,150,13,106,43,251,166,76,47,218,150,11,125,109,109,179,145,213,217,241,16,32,208,48,33,217,59,171,245,248,174,34,191,77,111,183,221,49,141,59,221,76,224,103,190,107,171,215,232,44,84,133,236,88,227,175,24,57,144,252,229,182,140,36,219,42,92,101,187,212,188,34,205,167,99,168,91,224,154,187,112,52,190,62,212,191,250,250,68,229,248,142,143,161,185,243,117,222,69,61,162,247,179,140,133,135,164,217,144,222,8,114,20,240,161,44,27,187,82,122,237,53,167,43,2,215,122,219,61,163,54,181,154,176,222,239,12,13,63,88,213,167,98,162,94,254,89,113,112,242,88,158,65,229,215,16,126,234,96,129,34,233,231,85,152,90,16,97,32,90,134,18,131,114,130,148,249,76,135,186,171,103,192,83,45,100,96,36,88,217,197,165,86,194,168,112,149,125,108,133,112,117,199,26,221,35,245,88,233,9,113,47,138,31,61,114,47,51,32,197,55,17,175,164,93,204,223,215,203,221,224,147,103,78,214,230,214,71,214,220,169,117,39,0,147,198,108,242,153,155,144,235,250,162,35,53,61,45,156,227,244,108,123,32,227,129,77,252,146,213,168,197,237,147,123,38,228,75,144,165,144,102,113,198,22,145,14,101,195,177,43,62,151,113,96,81,189,204,180,207,197,24,72,76,135,127,181,246,81,18,167,113,85,184,62,190,140,86,209,148,134,111,32,60,108,33,233,115,99,216,239,112,146,92,217,236,252,213,215,98,122,215,64,175,155,179,121,195,7,207,252,163,51,58,143,187,255,188,122,6,199,73,36,149,218,141,142,43,108,99,2,232,187,65,216,24,169,125,102,148,113,59,233,176,194,207,77,204,245,20,43,145,104,88,88,212,187,237,152,64,18,141,254,53,255,111,53,61,62,49,143,145,197,10,207,36,198,166,88,7,199,42,201,145,219,135,53,239,108,162,82,202,181,4,255,82,23,38,141,213,120,0,218,105,2,141,120,255,138,20,27,255,97,202,151,0,166,227,16,196,48,139,91,164,4,170,177,243,27,154,220,212,167,205,179,84,245,205,50,51,155,45,39,99,124,70,27,48,182,173,3,26,38,214,1,26,23,216,248,214,89,78,142,7,44,2,118,103,73,72,202,187,222,242,74,37,84,166,251,191,67,11,231,116,61,33,17,96,93,116,165,173,88,153,105,123,125,159,243,89,143,66,211,213,23,47,204,192,2,231,229,224,32,30,45,9,31,149,216,137,119,152,34,22,131,206,47,216,201,89,197,58,66,204,67,92,0,150,199,161,213,185,96,252,164,78,46,247,41,134,48,118,14,77,30,250,176,12,138,96,58,51,142,9,249,103,99,29,247,189,31,126,29,86,211,201,108,216,195,90,32,119,124,219,207,128,192,119,91,217,60,215,24,182,244,100,241,153,24,3,99,115,167,33,25,239,186,42,198,202,179,57,117,112,11,208,212,50,26,170,22,148,206,252,232,159,56,64,37,184,40,232,109,62,164,199,64,198,112,56,71,12,215,108,220,20,211,118,70,182,19,212,219,182,104,5,188,255,61,162,241,25,176,78,25,176,239,21,205,246,214,246,86,45,101,158,9,252,149,38,59,72,225,119,121,209,20,85,6,84,253,24,182,126,20,150,105,176,238,54,59,96,46,28,214,21,80,112,19,118,125,115,134,244,30,35,230,238,255,199,220,32,200,9,142,2,182,14,101,191,176,143,96,217,200,124,194,43,105,61,93,143,135,53,12,228,233,30,150,173,228,73,179,184,84,21,117,63,245,231,49,129,29,249,46,23,172,195,94,36,76,227,246,71,159,188,8,88,119,49,177,156,203,88,101,195,170,151,183,106,100,9,246,64,254,1,90,4,9,163,154,231,88,68,182,99,67,75,171,107,142,196,79,237,114,70,178,128,33,83,168,67,129,82,214,135,38,206,41,152,140,168,52,239,28,171,28,29,180,246,185,183,243,85,129,112,168,63,139,133,0,162,86,166,48,132,244,159,151,235,175,64,110,168,85,97,233,11,62,25,177,16,57,124,63,250,59,218,136,209,136,192,23,168,160,206,65,84,30,73,213,235,181,104,66,27,98,126,183,219,93,200,115,84,141,57,55,20,131,91,14,228,85,181,19,4,110,176,90,101,40,91,107,155,7,70,21,114,154,141,146,125,246,64,1,216,213,232,23,143,224,115,244,247,144,186,71,134,69,183,141,25,186,91,29,145,163,250,202,181,57,216,172,131,228,242,181,187,52,94,218,252,4,118,44,52,124,160,37,176,17,218,121,140,191,107,102,91,222,49,91,229,106,179,221,170,200,88,38,138,167,10,48,157,47,99,57,137,88,76,206,141,214,208,48,80,226,18,227,6,175,180,63,107,247,251,197,59,51,247,13,109,209,162,206,192,125,112,94,235,247,26,88,14,126,241,225,249,81,162,7,157,238,150,138,24,69,121,155,219,17,169,180,218,93,230,99,92,139,53,179,145,30,14,205,171,75,247,49,194,3,14,177,24,222,122,30,75,174,121,243,104,233,244,81,4,47,70,43,206,113,229,119,231,49,72,144,78,214,29,193,41,75,14,97,19,84,148,246,3,250,243,7,246,233,153,48,135,226,204,199,93,210,3,97,11,106,117,170,122,92,97,150,179,177,220,46,59,17,151,242,160,233,237,81,78,255,87,243,237,113,135,216,131,97,197,224,41,142,85,234,243,135,58,152,220,191,227,149,78,77,30,82,167,63,217,43,227,106,173,223,128,161,49,70,29,184,169,178,179,124,224,2,243,210,229,112,103,15,29,78,229,91,9,68,198,94,135,241,207,69,183,229,46,78,63,189,93,163,10,91,172,13,205,180,217,216,102,237,239,3,217,247,218,0,147,130,158,175,242,39,94,23,238,221,229,211,72,140,103,207,7,73,10,200,247,155,254,35,165,152,2,137,237,154,128,235,215,210,1,132,104,143,128,91,191,225,241,171,220,16,165,209,59,10,1,128,151,229,116,17,20,188,108,57,196,105,197,5,64,216,75,255,49,10,35,243,39,238,142,201,1,32,8,28,116,21,216,226,89,90,231,210,128,81,149,93,249,111,150,128,11,228,231,236,178,74,34,174,187,230,84,78,197,136,17,197,25,242,154,123,24,78,245,178,254,76,70,182,72,15,115,54,62,10,89,172,129,113,97,148,204,240,100,172,169,122,13,95,182,26,184,25,191,255,250,250,137,18,19,72,145,135,112,125,227,63,65,26,54,228,181,30,158,27,191,9,236,168,115,248,144,187,132,253,45,84,154,196,103,30,149,123,53,42,206,172,146,175,44,203,69,239,45,147,0,121,103,125,132,136,192,38,62,79,29,241,17,151,110,28,38,221,234,230,228,182,64,241,144,165,124,145,120,49,50,129,18,33,242,212,143,68,167,109,134,179,113,176,85,93,87,105,133,15,66,249,8,43,9,147,72,30,6,2,85,185,204,160,20,76,70,119,163,67,200,121,228,185,204,22,48,31,122,177,123,93,159,108,114,65,90,91,67,95,139,6,187,3,78,142,38,96,61,68,23,146,93,32,245,153,131,61,126,1,194,201,158,51,161,172,0,176,76,143,229,81,201,36,157,210,139,109,215,12,9,41,152,243,188,240,144,194,27,114,193,162,39,43,9,203,46,137,76,217,93,125,215,74,43,75,0,153,246,95,88,44,134,248,43,87,166,46,133,1,77,197,205,206,31,50,102,178,248,22,226,192,156,203,195,155,193,32,35,158,173,76,75,79,240,112,7,161,130,162,85,225,67,223,15,127,53,24,49,231,201,248,16,114,146,228,17,178,247,166,162,2,32,180,41,188,9,197,103,77,246,35,30,71,112,6,222,168,64,60,248,242,61,201,130,219,58,182,38,143,103,45,104,219,7,121,119,138,183,148,149,107,216,169,2,89,111,185,120,49,74,173,174,35,38,194,214,86,32,216,229,123,41,64,108,178,152,13,174,71,86,192,147,84,112,246,98,151,238,63,210,134,112,5,28,254,154,125,236,82,78,22,114,230,212,88,97,54,211,70,203,48,159,59,21,36,55,56,141,194,247,133,160,138,224,66,180,74,137,37,94,5,120,135,170,119,209,147,221,28,19,215,139,29,199,87,234,102,225,111,74,180,27,169,131,129,29,44,138,81,235,206,181,229,133,192,201,163,110,48,203,245,95,200,183,29,29,31,255,74,216,148,92,109,191,130,29,236,248,204,126,228,208,76,200,13,128,197,198,255,211,23,197,132,124,133,71,155,21,132,233,191,189,212,255,108,47,94,109,53,232,234,95,174,83,223,18,188,255,239,215,139,141,51,127,243,199,103,111,117,45,101,67,184,104,196,20,34,25,184,251,144,47,226,217,214,217,125,47,52,41,242,113,104,13,56,74,44,166,36,63,154,133,145,18,80,160,124,59,47,48,219,63,43,134,67,115,238,189,252,67,6,164,83,181,123,230,213,252,7,222,130,221,30,79,68,34,162,2,61,134,162,207,49,146,161,216,82,98,181,190,57,57,164,128,97,121,148,131,128,152,66,106,247,15,154,148,82,42,174,142,17,249,123,23,138,78,106,245,159,202,19,26,160,50,138,153,136,182,101,89,247,195,169,69,220,50,155,45,140,251,248,183,139,84,17,44,98,83,13,102,234,106,135,22,255,212,246,163,28,11,251,123,18,5,150,221,6,2,137,17,176,56,215,12,166,187,52,149,11,97,119,140,245,13,201,20,98,80,27,26,125,126,58,232,231,83,52,195,75,116,248,147,230,123,171,77,81,168,163,120,39,158,18,54,60,212,117,67,148,122,151,78,51,30,88,27,152,83,92,191,105,162,106,233,12,27,116,4,53,100,189,242,253,169,182,10,105,196,84,229,122,141,80,15,0,38,26,50,176,229,18,32,169,241,202,190,190,225,100,193,44,196,209,193,83,89,43,228,8,127,48,9,221,186,199,251,97,138,218,190,131,202,206,62,148,128,44,48,107,164,177,57,149,171,214,244,57,198,194,87,179,232,10,17,65,243,255,109,19,208,42,55,68,178,164,84,21,57,206,5,27,252,203,144,108,90,231,137,198,221,204,164,204,56,73,223,129,127,246,244,144,140,13,229,195,199,39,42,93,103,202,8,45,68,203,17,186,154,9,154,228,59,255,134,120,125,170,90,18,141,31,17,116,10,189,48,63,147,112,188,11,184,92,95,253,180,92,80,106,57,112,187,229,228,69,3,1,47,47,72,146,48,135,37,111,82,27,20,77,157,222,115,123,120,119,159,196,99,7,116,57,222,119,79,79,212,213,215,145,225,154,187,25,22,126,89,170,169,123,159,94,29,177,63,137,207,167,192,97,134,193,17,236,199,8,35,214,220,156,72,183,180,8,63,200,171,93,216,103,110,145,159,209,158,236,233,50,228,220,144,113,159,214,222,157,156,27,133,183,240,127,191,28,41,222,148,155,247,32,97,96,128,237,98,236,159,107,157,192,176,19,81,248,145,219,183,179,73,178,81,38,137,81,108,189,148,180,164,63,244,107,140,13,253,2,84,88,16,121,200,120,77,203,104,24,207,202,194,62,253,155,102,96,168,116,28,237,163,138,91,149,34,82,230,211,109,230,176,130,28,82,186,233,159,99,238,249,81,38,106,243,246,4,63,80,43,104,47,1,253,236,84,79,158,5,81,26,18,242,70,42,11,229,216,154,236,16,203,159,227,7,207,120,26,197,81,87,177,4,32,197,147,111,255,229,91,211,194,195,230,35,169,151,31,196,33,181,120,192,254,71,84,152,228,208,209,129,98,55,39,210,144,146,192,231,249,121,170,81,218,202,197,150,149,234,93,90,178,167,209,244,86,25,140,141,156,206,14,247,240,217,14,39,99,82,121,16,119,157,210,169,220,50,58,255,48,130,189,120,154,59,60,85,94,135,23,15,171,6,31,212,224,89,73,100,179,91,61,170,128,28,33,227,9,149,128,12,110,120,44,9,52,192,4,24,65,221,114,24,77,109,0,237,94,4,42,232,84,150,134,32,50,33,84,234,130,136,89,117,253,79,60,135,69,29,50,128,196,38,41,43,37,78,168,73,163,249,45,207,177,76,38,115,76,143,118,145,106,166,6,142,230,193,147,145,87,195,222,73,219,219,89,33,68,237,118,120,146,164,74,130,237,16,47,79,228,9,153,184,5,127,80,182,81,105,196,51,244,192,237,160,118,200,191,94,235,152,191,202,161,231,171,19,116,102,94,206,253,175,4,193,18,70,53,214,98,123,181,137,167,190,84,96,169,2,204,232,54,221,169,175,186,172,137,170,75,32,249,57,119,86,19,52,123,234,142,11,108,19,58,84,98,250,242,114,170,31,205,195,117,12,243,41,93,222,0,101,219,102,129,196,192,91,8,186,233,243,37,194,183,162,121,59,93,71,52,178,114,96,72,252,185,254,109,31,107,112,168,64,226,160,216,43,49,74,50,139,112,148,135,148,88,184,35,26,29,171,245,47,96,61,39,146,159,194,252,57,202,244,245,218,216,18,29,71,237,39,25,197,164,184,67,97,53,45,16,218,207,244,97,249,96,167,93,62,103,162,164,67,186,159,2,26,136,32,184,9,167,169,183,210,72,43,253,167,72,211,171,205,117,92,82,32,5,197,107,8,68,106,237,8,142,148,101,227,90,210,67,13,252,233,3,242,79,95,172,175,195,246,251,254,247,71,7,224,252,37,255,4,158,178,131,23,77,77,22,178,114,155,151,162,207,53,98,63,132,143,232,73,194,185,91,243,57,47,83,36,154,42,31,150,56,15,33,40,14,111,70,137,225,158,138,108,119,114,255,48,176,231,182,51,219,163,86,122,80,104,197,169,107,181,97,55,228,63,47,73,106,27,23,65,207,177,34,218,221,147,192,237,165,74,89,152,255,181,169,250,226,99,10,232,6,181,45,3,222,174,26,248,155,12,199,237,65,205,85,22,125,164,146,124,17,73,140,71,36,57,173,173,157,157,161,35,164,157,190,71,67,29,142,133,206,231,64,185,95,111,65,166,220,233,245,73,242,25,16,29,223,124,142,199,177,13,24,198,245,218,190,115,38,32,45,236,12,96,101,63,17,230,151,217,117,234,153,112,111,91,162,196,247,185,166,60,2,8,145,56,160,48,175,226,250,67,51,132,106,42,213,138,119,167,9,240,25,8,56,22,165,218,9,62,218,121,29,43,177,130,210,166,150,15,220,225,225,152,34,255,104,115,223,108,131,55,250,255,49,92,130,20,179,218,73,38,116,122,102,17,118,237,183,109,65,232,122,235,4,68,3,245,160,150,224,73,183,115,6,100,124,166,210,201,82,249,142,15,23,20,60,118,137,170,181,229,205,108,201,240,169,87,195,99,76,138,15,228,158,47,216,146,8,248,175,110,207,39,94,180,173,250,47,24,2,201,150,241,233,238,16,120,75,140,84,49,212,106,98,213,162,86,181,76,170,35,124,116,48,164,197,74,131,117,229,28,19,139,154,0,123,202,110,178,10,79,113,166,22,172,117,191,54,48,27,183,59,223,105,57,148,54,241,188,72,118,58,255,33,235,238,206,33,254,197,162,45,154,226,221,57,145,225,19,36,11,164,245,79,188,132,50,190,248,255,75,183,214,242,69,109,232,147,130,166,70,86,58,124,161,96,88,92,166,32,184,117,117,232,148,14,163,81,163,242,0,239,41,82,240,105,189,74,68,200,164,195,85,62,74,56,226,196,41,2,105,154,95,205,207,232,106,98,226,99,112,210,188,162,203,188,28,65,78,18,252,134,93,120,74,188,64,154,12,133,146,228,14,25,9,13,157,22,83,145,169,201,189,221,137,49,232,138,179,182,165,146,2,109,172,21,172,40,157,230,199,70,170,17,231,133,250,192,45,75,214,33,111,3,120,209,54,12,206,159,226,150,136,96,94,25,66,56,178,106,7,73,214,104,156,236,28,249,93,15,229,9,0,132,16,69,155,125,179,207,94,14,13,244,207,241,54,32,52,63,98,162,154,191,75,209,229,33,193,255,57,31,229,86,153,43,207,166,165,245,54,40,212,29,222,70,136,130,40,74,185,218,104,130,108,129,245,188,86,215,76,131,33,190,168,234,99,175,11,251,216,73,187,108,44,255,201,238,119,247,44,86,81,235,45,3,57,216,75,34,73,180,36,35,240,164,214,36,117,135,41,119,211,38,76,81,196,8,21,97,136,235,119,71,123,36,176,199,227,228,108,128,149,137,5,164,77,148,159,81,47,176,108,234,54,46,235,56,167,178,84,254,105,129,190,49,65,57,236,213,149,152,10,85,206,195,221,92,221,54,74,114,134,198,83,208,132,62,75,99,76,23,147,221,170,238,47,2,231,238,159,31,157,21,230,120,116,37,205,171,183,193,105,172,143,117,1,93,76,23,54,218,89,41,8,34,70,14,172,247,13,165,93,149,104,106,13,209,88,202,31,127,1,56,213,196,57,128,219,160,128,36,102,11,50,241,144,120,109,249,181,6,101,158,193,159,198,121,72,53,117,201,226,238,36,19,89,190,170,97,242,166,133,255,187,116,117,149,110,240,34,46,115,10,173,23,253,193,26,88,218,204,250,37,212,109,250,201,191,194,118,95,136,247,161,207,241,204,135,2,78,149,74,112,131,147,47,174,61,6,17,165,170,245,205,230,27,4,219,42,253,132,224,5,105,216,149,164,189,139,111,218,70,124,62,36,131,167,58,160,166,166,15,182,6,55,43,51,18,46,56,174,90,10,0,14,29,74,85,33,208,147,69,176,90,198,106,36,37,30,25,35,124,178,130,4,84,25,198,20,229,53,83,27,191,7,155,221,115,87,5,220,83,80,84,102,251,48,221,102,199,149,98,72,199,4,97,43,61,78,97,140,141,115,8,36,76,209,170,73,151,35,27,50,135,70,240,173,0,121,54,23,163,78,109,212,129,93,171,216,134,28,83,113,141,233,192,101,187,144,201,55,84,241,226,162,50,111,152,243,114,9,111,93,4,89,234,55,65,28,241,78,143,188,189,252,70,80,238,69,204,212,181,122,171,109,189,186,144,136,240,116,95,234,155,53,70,170,203,113,36,46,45,134,195,163,140,104,104,25,181,136,167,116,55,237,25,77,120,91,44,239,159,52,190,41,227,220,175,171,101,213,127,105,222,163,58,68,40,210,118,247,1,76,42,20,189,248,76,43,113,25,81,37,26,154,234,25,226,251,39,69,143,3,138,235,220,47,9,31,25,63,195,193,72,173,92,80,43,152,143,80,74,126,49,33,238,113,228,171,168,241,82,49,174,116,73,94,130,72,230,253,161,187,183,237,195,41,153,143,130,252,152,169,147,185,106,2,207,13,134,90,175,141,157,242,255,161,154,42,107,178,145,195,16,211,119,181,175,211,84,142,39,77,187,239,159,12,177,186,243,150,95,140,58,167,52,103,146,158,98,247,173,141,219,214,180,87,55,184,155,216,203,67,81,243,45,171,219,220,110,144,106,5,138,225,212,232,110,202,220,68,84,250,115,120,118,200,167,154,108,73,90,190,72,34,47,249,229,114,4,80,142,144,22,68,254,128,128,196,171,194,100,131,176,168,30,203,107,42,65,59,156,176,21,156,53,86,125,203,58,216,87,127,233,238,153,162,195,175,35,133,212,69,25,61,96,246,99,19,132,120,219,58,140,93,223,248,9,43,246,147,166,10,33,40,237,26,6,87,228,81,182,159,34,234,48,74,27,30,186,36,136,63,92,110,3,131,130,27,239,155,0,156,219,146,232,148,189,133,204,227,35,102,6,13,242,251,69,127,251,171,127,248,242,116,126,174,84,115,6,193,135,29,128,225,230,162,23,222,79,106,4,26,156,61,251,88,57,81,76,237,7,19,107,37,95,147,230,99,193,76,98,87,252,124,217,105,200,201,204,245,189,226,154,95,54,19,34,64,85,66,163,243,6,203,46,201,0,174,183,154,181,226,46,152,199,255,75,54,243,29,83,133,231,240,6,21,38,68,184,253,109,54,23,224,31,102,11,112,103,43,17,38,125,238,71,104,161,159,219,136,215,196,141,170,10,56,156,93,207,152,188,114,22,157,0,165,25,138,205,58,248,67,193,58,28,147,32,38,229,221,175,114,14,42,161,2,223,231,204,164,6,92,49,52,64,37,164,223,252,197,118,55,243,108,10,158,239,219,175,244,102,22,194,134,212,9,249,244,43,86,97,41,53,9,224,110,61,250,140,202,187,95,171,204,21,221,58,141,24,176,120,96,194,232,84,28,125,246,218,142,73,131,254,249,22,179,71,110,208,97,247,139,162,171,64,251,79,190,180,190,186,29,110,165,88,119,225,30,58,64,49,68,45,83,93,122,136,199,146,158,106,5,211,222,64,64,160,74,72,185,138,112,186,135,133,95,31,236,77,86,54,59,235,32,245,245,133,152,27,233,115,154,253,233,222,36,218,216,218,211,137,127,103,199,95,165,151,234,33,228,72,167,103,13,43,119,38,71,23,218,227,177,230,222,214,149,81,102,246,94,251,84,233,90,116,77,26,118,194,122,55,75,208,137,52,159,238,73,8,33,157,218,178,213,108,45,131,207,210,31,144,133,204,239,144,183,230,251,195,57,195,154,39,61,36,39,117,126,121,69,224,198,15,198,98,59,82,181,202,28,149,49,219,53,48,163,19,164,57,251,219,61,159,235,12,121,100,151,160,191,93,194,90,22,119,28,191,219,210,170,234,145,2,111,53,86,140,171,46,232,231,111,18,43,83,2,142,131,38,36,99,174,3,26,169,105,31,214,250,212,191,8,1,141,69,73,158,180,248,93,117,146,242,10,188,63,7,61,149,69,118,161,141,117,25,193,18,187,220,194,82,13,30,5,225,194,158,252,56,159,129,5,240,0,213,85,67,54,209,242,151,41,141,172,187,12,215,255,6,5,126,185,11,225,35,202,5,182,98,154,26,217,237,193,140,136,38,71,118,166,44,17,223,179,101,97,16,153,33,21,204,15,219,189,120,219,24,117,23,4,153,22,143,40,174,238,185,27,159,69,251,1,227,108,218,69,111,198,184,236,14,216,136,208,115,154,211,47,149,116,98,114,40,90,83,116,92,109,38,134,140,104,157,197,116,57,122,111,5,224,4,175,201,244,62,210,203,188,216,230,131,214,184,164,54,48,242,179,251,201,77,16,77,13,77,23,34,66,146,24,12,187,238,151,92,139,64,114,217,125,244,175,10,155,138,118,58,245,52,121,17,241,62,231,105,214,169,120,184,4,155,16,20,12,215,206,40,237,161,186,68,63,141,166,178,6,127,126,151,70,195,245,163,96,91,23,138,173,211,99,103,164,14,51,246,20,75,76,135,150,74,215,220,71,15,76,77,215,250,38,227,176,76,17,15,179,232,18,19,165,54,194,146,187,110,158,216,55,66,145,232,119,152,61,63,121,155,194,202,244,22,81,66,36,140,38,108,209,21,139,25,159,255,185,60,117,9,245,95,46,99,220,27,61,151,235,253,38,161,64,188,88,189,117,249,42,176,56,54,107,62,80,240,135,153,86,180,137,121,111,177,208,196,3,194,236,106,173,82,40,195,1,146,180,204,141,11,192,120,252,52,4,116,199,14,254,104,216,4,219,7,221,233,33,47,34,247,94,0,104,240,54,18,128,85,240,255,179,195,197,161,240,178,242,197,103,68,166,60,95,131,245,148,198,163,124,209,39,120,42,206,15,106,91,118,113,89,19,66,66,241,200,64,65,37,82,169,139,136,203,234,192,172,175,27,160,244,10,91,4,183,109,177,183,93,233,92,26,227,67,87,232,184,97,234,202,240,80,213,42,133,15,68,206,0,206,110,170,227,223,113,90,208,60,11,93,245,151,50,51,86,152,199,229,35,248,13,119,64,238,165,152,108,70,48,149,157,110,249,189,25,187,246,251,124,64,0,176,165,128,174,39,200,94,100,193,34,233,19,192,83,39,177,228,74,234,195,128,251,203,238,192,16,66,200,223,179,30,106,195,189,26,217,157,142,161,132,38,20,179,217,79,34,97,189,231,106,19,144,223,172,39,206,91,192,115,254,111,141,170,103,121,61,72,101,60,110,173,73,193,25,89,206,122,137,151,213,60,169,7,42,226,224,249,190,43,17,190,187,240,163,77,26,192,162,70,170,154,216,20,183,212,229,81,56,157,247,123,219,168,91,21,53,107,174,135,98,32,176,146,78,98,190,30,232,190,171,107,188,254,223,5,25,58,134,150,36,28,218,134,107,40,253,245,199,11,1,191,26,173,238,5,142,204,170,161,157,127,172,254,27,185,235,87,15,3,74,170,36,195,132,163,3,126,33,178,173,141,106,23,111,96,111,124,164,68,230,2,210,18,190,148,45,70,148,194,38,160,67,130,166,172,81,5,91,142,239,190,58,3,102,81,212,68,68,73,134,6,117,116,100,47,57,100,207,232,224,125,32,30,193,162,117,36,57,8,27,203,56,199,110,251,56,35,162,240,157,224,0,42,206,199,201,33,95,5,127,132,29,178,152,101,166,1,242,99,155,248,47,71,180,75,84,99,65,91,32,31,136,206,52,48,74,184,208,83,85,179,51,105,125,87,66,145,207,127,71,239,255,157,126,120,139,232,35,64,70,128,118,191,41,217,7,185,86,117,216,187,163,194,206,174,218,56,214,58,160,248,111,154,70,17,108,212,91,199,245,32,108,125,43,198,192,38,68,101,100,147,129,87,52,240,50,91,92,218,108,127,101,155,228,123,77,147,41,86,207,159,139,140,93,22,169,163,63,89,236,154,98,131,93,39,55,237,122,107,6,174,184,202,126,27,199,141,16,52,167,250,44,52,64,134,244,66,235,39,127,190,88,127,61,105,107,157,35,59,146,10,14,155,241,227,170,104,180,47,95,20,235,236,196,100,29,66,255,252,236,249,128,214,5,234,40,241,34,234,45,47,166,217,121,36,243,35,251,23,126,3,133,136,164,113,22,69,236,180,239,139,48,255,146,161,48,135,129,150,245,193,181,210,85,120,4,249,147,174,66,17,136,154,208,148,214,82,198,29,171,4,223,212,84,104,93,95,153,151,59,52,212,150,113,85,179,189,60,151,118,28,93,220,49,114,124,228,164,99,165,40,1,5,200,121,138,132,77,15,5,21,162,216,252,37,141,224,202,125,209,225,242,62,177,195,93,254,238,77,226,148,168,119,167,195,151,180,25,60,215,48,166,94,44,45,114,159,78,24,155,132,119,38,31,231,227,51,37,35,33,239,40,171,12,250,68,190,248,231,228,59,213,61,15,65,53,179,92,176,23,172,176,32,72,135,37,241,24,107,242,184,186,57,99,239,241,14,0,114,211,202,79,176,88,52,130,56,18,75,55,22,208,79,100,1,57,105,53,174,100,13,234,232,158,118,211,9,144,128,160,76,177,166,10,90,95,110,144,254,243,190,208,135,184,198,226,200,27,9,38,241,0,208,210,237,180,2,22,149,157,19,155,249,21,3,55,195,149,105,206,24,110,148,19,249,58,78,186,176,25,100,216,4,198,194,104,71,150,103,193,54,223,28,146,80,51,157,194,14,178,180,189,161,192,44,225,168,111,47,225,151,43,100,26,191,125,146,222,221,199,216,186,126,173,89,90,229,77,60,34,228,75,219,182,85,232,170,22,24,130,197,101,20,253,116,141,176,241,34,223,208,190,53,49,201,93,144,151,241,108,236,120,86,232,128,234,238,83,111,80,172,96,67,34,128,6,29,10,136,122,7,204,83,50,186,1,23,79,169,21,92,114,15,132,236,51,188,123,139,240,236,199,67,208,132,52,13,194,187,174,29,120,140,151,198,252,88,147,102,219,35,162,73,126,98,77,213,8,169,217,193,210,100,239,19,153,49,43,252,194,75,228,65,143,184,39,77,42,202,171,40,113,137,164,157,33,120,131,63,197,218,5,250,238,192,175,128,92,206,161,173,254,238,133,100,158,136,16,101,127,238,52,208,92,82,3,217,66,93,246,228,193,254,74,72,78,122,33,105,54,8,66,93,246,194,222,27,194,33,125,31,125,186,243,13,92,218,44,36,132,226,180,89,124,205,104,135,159,122,252,15,162,223,62,10,250,171,0,131,127,85,178,231,79,207,40,253,46,196,118,242,128,72,35,191,117,82,21,59,50,253,123,77,220,143,104,20,203,224,176,13,252,32,28,67,43,91,75,244,94,186,135,19,180,199,223,127,142,98,37,239,28,103,87,65,235,18,238,103,120,238,30,86,59,98,172,2,220,161,99,43,3,209,122,161,55,146,255,1,36,249,99,184,3,3,168,72,232,46,73,223,106,79,159,210,38,156,147,51,126,50,165,108,52,49,96,42,238,80,99,70,146,206,224,54,97,97,16,213,14,248,251,126,49,66,87,134,179,227,232,143,91,185,125,0,158,183,5,242,48,7,152,160,171,198,163,34,181,199,170,68,125,93,97,109,136,230,150,33,113,56,104,7,226,175,49,100,51,84,213,22,135,7,237,200,148,72,116,142,163,153,122,86,4,164,15,210,118,24,67,210,223,220,137,144,48,144,180,185,234,2,241,154,213,43,109,156,143,172,26,128,135,231,119,24,217,131,61,148,77,141,150,92,115,120,2,154,217,75,86,241,208,171,108,103,82,89,209,129,238,172,132,255,207,27,146,164,74,184,68,92,141,13,124,214,138,185,244,149,236,189,182,103,67,87,10,32,216,220,143,80,210,206,245,104,149,139,20,55,5,113,172,207,125,29,89,249,19,112,108,14,88,182,201,165,18,10,245,121,6,178,148,34,12,59,196,61,173,239,178,241,33,155,25,242,134,32,227,233,188,135,113,163,52,64,251,178,224,118,246,79,167,5,63,212,177,112,180,80,242,169,49,210,21,134,141,17,157,190,91,64,227,91,38,133,159,225,105,247,226,195,200,172,31,220,215,170,68,107,20,234,183,178,143,56,158,107,86,223,172,215,193,84,10,65,89,99,158,61,203,224,96,108,213,54,164,149,13,125,118,120,95,189,114,57,41,211,241,237,209,190,6,62,79,184,242,245,149,195,91,85,198,131,178,227,71,202,112,154,51,82,29,130,223,121,113,6,199,251,129,30,201,68,187,181,197,35,52,79,104,12,235,40,127,72,62,197,101,25,50,235,135,22,61,18,204,9,17,58,139,193,112,118,161,34,157,65,113,190,135,176,140,117,20,216,176,111,50,116,217,162,214,180,80,45,31,21,53,93,2,228,123,100,207,17,230,207,97,240,183,85,31,41,46,45,3,43,72,155,187,165,203,128,67,28,120,236,54,20,65,238,109,110,179,222,136,198,17,77,149,130,251,103,177,204,150,184,189,37,5,55,241,217,14,130,255,116,126,175,235,144,116,140,66,14,51,205,67,99,220,51,208,79,206,154,127,22,85,71,77,215,145,255,44,243,64,209,227,67,73,110,151,218,87,197,55,237,118,245,39,169,244,170,245,203,108,245,142,50,189,176,80,21,202,93,146,1,53,148,177,158,56,213,31,235,149,163,76,7,160,96,185,175,209,247,27,135,158,217,147,16,10,240,197,137,20,206,239,82,56,27,22,220,198,2,89,79,127,31,142,1,6,55,182,200,142,137,107,201,174,111,181,210,207,62,30,104,243,208,79,121,233,86,23,51,192,246,38,237,63,185,68,166,75,123,229,116,251,234,207,59,122,231,68,113,211,62,70,25,143,151,209,232,208,160,147,131,216,54,242,90,239,63,40,144,174,63,16,36,202,26,114,183,89,217,89,136,230,91,48,252,125,202,164,150,89,145,56,123,247,12,54,155,187,186,61,40,196,208,28,136,119,101,36,210,226,52,175,235,200,109,39,72,109,208,243,138,191,212,112,241,255,140,84,135,41,149,18,74,71,117,169,225,47,36,251,47,104,143,61,234,88,50,148,255,119,218,157,33,205,193,198,233,229,11,62,162,92,119,220,137,255,123,184,226,35,157,8,174,39,63,216,248,137,225,131,8,2,82,204,80,214,39,91,209,189,161,6,81,144,36,198,76,197,109,194,10,4,72,54,53,184,115,91,225,10,11,168,200,46,218,124,246,135,15,89,53,166,8,241,71,83,123,154,209,50,174,37,55,123,83,140,20,54,44,56,182,163,26,6,6,190,38,53,147,232,222,149,68,107,255,157,252,151,137,92,252,145,148,33,103,9,72,231,13,116,195,38,2,23,236,159,143,19,6,218,213,124,179,244,182,30,110,173,19,168,90,131,57,252,205,106,250,34,115,21,156,227,2,178,233,51,164,166,165,72,112,14,41,93,38,111,111,37,191,106,207,33,185,185,90,72,233,134,236,98,171,160,112,169,40,190,94,93,171,234,98,137,93,127,65,248,80,186,131,116,191,197,63,31,50,255,195,58,34,142,54,220,246,198,63,55,183,44,126,0,217,209,232,158,8,7,110,86,107,240,61,28,52,138,97,149,20,247,180,192,143,33,83,155,177,22,187,216,48,139,83,169,139,99,123,154,74,125,236,38,59,46,27,30,157,211,15,232,203,47,94,136,56,194,51,139,205,174,21,161,217,7,160,227,59,236,156,91,143,154,27,42,117,22,168,18,246,201,35,37,107,157,58,5,158,76,100,112,62,84,117,50,22,6,96,111,120,207,116,151,161,13,67,239,116,206,98,64,136,103,8,201,197,9,81,239,18,226,93,190,46,81,229,232,167,200,193,215,90,182,212,93,78,67,26,105,97,197,49,164,150,52,143,248,121,13,95,217,227,206,14,80,200,179,171,10,146,200,142,90,137,125,253,146,71,131,33,45,48,69,241,119,153,254,188,241,25,222,97,30,63,46,136,159,57,134,89,0,129,234,189,184,64,200,208,245,48,167,116,134,99,230,3,164,217,19,159,106,99,97,202,22,164,70,66,13,97,32,58,239,114,37,9,60,59,67,157,37,172,251,50,177,13,116,63,7,119,74,90,248,108,175,187,95,134,112,101,157,132,160,143,70,245,232,144,69,184,106,150,9,184,122,224,32,162,162,167,166,203,10,237,99,78,75,217,159,250,237,184,75,97,163,68,55,215,93,14,236,225,12,141,49,8,40,126,117,77,135,80,77,205,97,75,21,26,145,221,123,172,2,182,77,86,93,204,86,114,144,92,13,141,25,97,222,15,100,182,160,159,142,35,220,49,107,187,208,137,105,153,135,0,174,222,172,239,170,133,207,178,208,164,230,211,2,139,92,32,192,133,89,232,32,239,245,110,166,136,37,21,196,131,79,242,98,209,25,180,252,102,119,100,85,102,115,189,106,122,226,157,178,221,143,154,92,187,57,68,241,18,33,225,250,134,114,116,72,134,250,27,40,97,219,30,86,74,184,102,193,26,66,181,24,165,153,255,190,75,185,18,121,114,85,220,59,224,145,174,176,36,67,144,74,196,161,88,9,48,79,220,4,67,25,232,105,176,32,242,28,201,66,116,178,36,164,218,208,31,240,68,239,166,138,242,198,226,27,136,232,255,174,210,152,60,200,61,15,238,2,218,231,198,130,236,180,235,65,221,66,82,162,92,235,251,20,38,65,92,156,106,85,0,144,25,182,28,226,88,153,34,253,19,27,116,90,101,248,35,202,216,184,19,35,2,94,8,209,254,66,212,135,68,219,185,32,107,225,25,227,136,211,138,181,174,112,128,190,66,165,251,135,185,108,40,159,222,177,26,58,26,148,218,89,13,15,27,236,24,118,78,33,185,174,168,219,230,119,230,179,169,161,57,118,97,227,203,9,125,55,136,197,112,94,138,136,230,112,204,245,136,116,59,13,75,68,121,43,122,9,22,252,149,172,182,118,113,61,53,171,44,42,118,178,166,69,222,44,157,34,128,126,179,24,154,159,106,149,17,227,58,143,176,241,222,56,42,62,181,26,208,33,24,30,33,112,83,127,84,65,41,251,206,115,178,2,222,106,153,209,238,98,208,200,210,177,133,86,65,23,104,110,177,161,96,79,57,142,162,15,207,173,153,56,254,250,73,76,74,43,36,200,57,145,60,95,227,21,147,221,41,171,192,107,234,251,74,126,3,247,128,122,243,153,128,202,238,189,17,198,179,70,97,245,190,200,231,176,186,98,217,254,45,230,228,185,78,204,155,64,247,183,255,152,161,26,12,21,183,209,199,194,177,1,221,95,77,76,253,203,104,7,192,167,209,180,50,138,227,189,182,231,239,238,168,59,221,119,154,107,247,102,200,51,40,120,192,133,47,249,238,189,123,233,117,188,210,82,68,72,178,111,103,77,144,205,181,97,1,172,166,152,242,0,187,181,174,188,39,82,5,75,21,213,113,66,102,62,173,169,132,21,120,138,226,211,39,44,143,160,126,74,108,191,13,117,58,148,234,239,194,161,161,156,231,240,170,77,120,106,63,168,175,231,243,60,192,181,236,20,52,239,78,141,78,130,59,219,80,208,24,37,165,109,209,49,251,9,62,80,50,249,181,232,42,228,47,166,191,144,176,206,148,242,148,153,182,121,24,128,65,137,42,161,119,66,94,240,11,55,102,122,7,205,142,144,144,180,47,60,218,192,149,85,15,213,83,8,79,215,104,8,209,172,222,200,242,28,255,51,185,167,33,226,26,65,147,100,114,222,54,27,170,212,207,83,56,170,37,126,121,14,18,40,231,4,14,164,248,6,110,118,48,51,83,228,76,3,131,87,77,86,163,48,72,194,109,53,105,118,111,198,140,133,34,20,119,56,35,236,7,170,176,164,95,86,183,232,105,108,7,25,169,127,50,26,86,83,94,101,58,219,72,205,46,231,78,158,94,221,190,147,92,96,224,0,30,65,191,21,237,118,106,224,247,161,116,33,41,10,92,81,248,232,191,41,72,116,171,89,110,208,62,230,196,11,67,172,81,188,8,212,62,255,199,22,201,68,20,120,21,90,72,70,211,251,61,232,5,238,147,16,91,225,65,103,178,238,63,246,157,100,192,170,206,249,101,28,25,120,125,225,94,105,146,218,75,10,178,103,244,73,77,174,18,113,205,198,233,5,88,129,66,64,72,137,118,81,217,130,206,156,174,224,223,115,249,164,10,160,47,237,255,135,146,236,13,99,71,63,62,20,134,132,135,155,27,21,239,159,60,195,224,248,123,205,45,147,225,233,72,95,151,236,249,144,43,148,51,197,175,100,140,185,170,200,234,37,87,113,85,41,197,41,164,33,181,64,228,58,125,41,220,43,111,47,37,139,69,75,126,166,210,12,7,175,6,63,122,236,237,156,149,142,254,174,11,37,215,82,200,54,62,74,43,2,249,172,218,115,203,91,14,165,110,103,178,200,5,226,141,45,42,68,130,198,173,253,230,217,122,113,39,163,182,160,231,100,179,40,207,8,27,212,22,174,85,58,27,55,118,83,118,244,201,68,167,205,50,31,36,17,250,228,187,200,203,159,109,44,83,197,240,214,82,128,207,62,237,127,108,238,226,36,190,44,152,27,248,90,79,254,43,191,182,206,138,179,239,133,27,56,192,25,166,40,83,172,241,62,178,172,53,58,205,73,6,139,66,50,24,22,193,232,205,173,161,67,139,236,13,114,239,156,46,253,12,218,238,6,255,169,98,117,8,215,156,102,178,212,208,18,175,147,108,96,73,71,115,87,75,254,77,61,212,49,252,42,72,23,95,49,206,208,189,203,240,139,4,56,101,109,139,204,117,23,213,104,47,1,254,115,179,25,96,58,221,157,53,112,19,110,172,118,168,11,21,171,109,123,100,79,124,202,172,155,236,144,86,224,44,183,119,167,51,180,139,191,76,201,173,212,215,120,148,255,149,110,69,229,152,112,197,133,178,122,15,23,55,103,67,13,152,239,59,168,53,175,130,232,143,236,0,96,95,206,91,141,167,127,199,149,82,51,222,51,43,148,225,183,56,32,68,76,97,35,154,233,207,47,2,29,114,143,36,159,81,168,169,22,163,74,208,233,149,204,129,138,138,13,48,180,42,41,155,141,156,228,19,71,135,137,63,119,146,67,61,236,133,52,209,164,39,67,110,28,5,36,100,159,52,79,220,118,89,126,230,63,180,117,243,165,179,147,209,255,162,97,177,43,45,86,56,48,223,195,122,39,130,118,8,183,36,55,42,221,83,72,74,95,130,91,23,121,226,221,206,241,204,44,105,177,188,105,190,84,106,225,244,183,44,76,188,169,150,98,155,208,244,161,94,75,232,173,64,126,153,184,124,75,229,87,31,209,154,93,125,64,53,167,155,250,167,122,169,184,231,14,34,61,208,47,179,182,194,37,87,240,10,125,2,26,125,232,189,207,199,3,153,204,157,148,33,93,160,134,67,238,203,126,198,203,210,112,25,199,23,136,192,135,207,227,224,213,125,17,93,230,177,178,164,152,162,80,107,50,52,221,42,20,128,143,202,168,22,91,223,159,118,214,249,29,184,124,24,124,1,183,54,43,61,91,155,116,241,94,157,187,60,100,244,97,97,177,9,57,90,72,245,38,31,86,172,41,102,15,35,39,4,233,141,9,165,41,137,229,44,122,16,181,99,178,84,124,207,34,140,41,145,250,172,186,100,100,156,162,5,126,187,160,57,183,240,17,46,181,44,120,144,141,151,142,129,195,192,11,203,241,78,134,142,214,106,198,94,141,84,62,51,127,110,9,65,150,68,221,157,131,236,130,114,10,128,197,13,157,252,8,165,223,138,108,179,156,231,156,82,132,196,202,13,64,69,92,110,180,238,15,125,240,30,231,134,56,66,31,193,191,100,72,106,233,11,113,8,121,238,178,117,107,157,215,58,43,212,236,53,215,214,1,16,192,173,175,231,62,113,26,94,248,47,30,36,232,160,227,75,161,127,33,5,192,210,69,155,249,190,217,224,42,17,77,54,231,20,45,5,116,154,154,80,74,148,126,85,137,13,59,123,226,167,20,148,24,19,123,17,78,46,126,232,255,147,20,83,85,103,16,86,141,246,211,162,58,245,162,77,31,51,40,174,164,117,38,201,18,8,240,124,226,180,213,190,92,223,249,184,227,8,168,86,142,19,66,247,142,54,135,218,13,197,216,225,152,61,155,156,171,88,150,158,129,132,144,138,13,21,166,17,156,62,40,147,131,134,66,228,77,177,184,53,207,92,208,3,16,2,45,215,154,73,196,92,47,104,0,94,23,103,132,206,81,105,63,84,231,7,205,95,148,128,250,142,158,42,49,223,26,22,72,27,211,39,245,201,245,4,127,48,221,21,121,201,223,108,209,6,93,31,85,112,207,74,123,201,78,249,139,38,60,134,47,225,21,74,31,177,146,41,144,16,100,28,219,207,21,104,154,200,135,169,238,147,227,243,217,211,187,109,182,74,223,148,201,132,46,26,159,121,196,145,148,161,153,126,127,103,44,44,215,135,248,8,157,23,184,220,82,173,81,229,136,173,243,230,69,68,158,137,156,73,166,209,116,155,166,231,141,186,187,84,175,227,63,227,13,18,245,222,185,2,9,97,179,58,174,246,67,94,255,153,44,100,138,172,19,5,67,221,82,20,224,61,104,222,44,53,106,82,147,130,225,31,218,140,64,109,45,5,216,165,119,100,159,228,18,213,150,192,59,85,135,249,36,228,230,57,28,67,206,105,230,148,212,28,106,92,97,2,31,152,107,208,11,10,205,238,102,126,66,83,190,233,77,232,77,96,85,249,251,119,192,179,5,0,198,67,127,22,157,78,146,64,204,6,39,200,12,229,227,234,242,193,195,141,125,107,248,143,210,251,18,220,67,240,110,48,114,110,15,160,241,14,133,152,132,225,44,134,92,88,11,167,164,225,12,234,164,92,9,175,74,190,164,193,157,232,4,137,216,80,165,124,20,254,221,2,198,63,217,156,135,119,4,178,58,153,215,139,67,52,172,206,47,40,75,33,86,67,63,41,10,20,37,237,37,156,4,13,25,23,201,228,9,237,67,16,22,116,17,184,162,203,188,227,13,110,65,231,79,200,61,118,207,68,161,90,71,47,113,31,224,165,90,23,21,239,63,80,176,54,103,99,60,125,72,207,90,110,231,121,225,205,35,28,16,137,252,136,94,179,14,97,157,227,66,82,219,137,26,78,157,181,147,28,161,251,43,196,201,53,245,149,152,194,86,91,70,203,91,114,199,241,212,180,125,44,131,135,116,26,132,69,27,84,222,132,88,96,163,119,62,129,249,230,33,147,28,124,23,172,231,132,144,182,235,125,193,70,233,206,77,27,210,203,223,213,95,105,230,117,205,214,164,126,23,240,10,34,237,211,43,162,138,230,118,192,86,247,125,167,215,62,26,113,209,175,19,231,246,167,150,22,44,69,31,236,205,198,210,214,123,93,60,9,175,131,96,145,71,92,190,209,201,225,103,43,204,242,98,253,129,95,56,223,107,29,87,165,180,44,49,28,37,42,83,215,122,91,126,77,38,243,71,213,191,223,14,76,247,97,110,190,120,147,167,234,237,10,98,148,45,218,3,23,117,15,148,142,173,118,236,90,31,27,85,54,188,202,253,43,102,109,130,17,8,239,241,89,212,14,29,172,179,90,8,104,5,203,117,188,43,184,167,54,8,100,136,17,55,201,102,193,221,245,173,86,65,162,176,40,92,214,101,18,82,59,131,63,156,187,219,65,190,115,172,242,52,181,80,109,165,136,98,148,149,152,234,86,143,132,100,239,159,119,163,250,30,130,119,190,45,58,208,104,161,144,10,202,200,31,177,215,242,236,78,3,151,34,8,16,172,231,112,71,159,168,32,208,230,50,84,234,214,40,92,65,60,148,117,76,216,111,91,121,177,66,86,123,55,54,126,46,118,241,103,105,245,89,242,0,0,166,87,7,145,164,227,90,30,10,4,88,64,114,70,127,14,161,218,198,16,35,230,115,54,65,108,190,175,186,252,79,33,24,82,118,130,249,181,253,61,28,154,77,227,209,111,63,61,68,223,162,41,90,176,37,114,169,199,77,160,219,199,22,79,240,212,158,243,217,226,74,158,215,193,166,204,82,135,0,106,12,155,150,113,241,197,33,205,6,16,19,118,164,194,115,243,112,162,251,134,203,122,124,61,242,68,140,200,131,168,172,123,48,70,132,227,199,3,196,130,48,55,231,64,216,195,86,36,160,233,137,145,108,224,93,218,61,107,191,138,171,13,215,212,65,223,117,85,120,109,207,141,12,23,221,175,68,130,129,185,138,67,225,85,127,85,215,75,146,79,69,133,10,129,210,51,71,147,116,11,104,76,194,87,78,137,12,108,185,53,10,210,35,135,33,203,224,96,175,47,98,138,83,60,163,16,100,51,21,186,245,7,153,128,164,73,27,189,195,13,61,255,96,12,174,169,37,39,235,177,224,137,71,128,240,63,137,238,255,68,185,212,135,190,156,240,184,158,113,210,241,119,224,63,177,236,63,172,135,117,74,27,187,227,253,246,222,134,197,251,197,243,107,188,160,85,252,111,4,141,195,243,91,73,226,144,131,109,136,10,172,209,186,95,172,96,107,43,22,44,176,226,122,100,50,28,65,163,62,235,88,16,254,97,48,250,64,155,101,21,83,64,255,189,98,142,60,20,184,3,54,87,20,50,178,254,138,105,53,169,141,5,88,57,244,207,138,191,208,185,54,87,134,70,182,197,77,248,201,118,133,148,231,106,241,215,91,61,184,61,250,9,140,91,66,203,141,93,171,166,65,183,29,234,196,85,230,194,177,148,240,126,71,14,92,212,2,120,179,141,11,42,166,15,45,196,187,30,249,247,104,244,5,25,126,208,252,253,157,224,36,138,145,222,221,213,15,204,112,217,50,193,215,194,2,248,214,48,43,229,7,204,79,218,223,82,137,114,228,41,220,68,157,35,245,242,213,255,141,189,192,243,63,72,119,222,107,252,230,192,211,47,186,209,144,213,221,185,22,152,208,54,130,76,100,242,54,210,211,40,29,189,40,7,183,252,209,130,240,76,107,14,110,35,151,57,0,187,180,78,210,153,198,18,212,33,205,72,211,89,150,175,136,7,138,13,18,93,226,93,52,171,126,188,165,113,29,15,231,234,11,67,54,164,115,158,58,48,20,202,65,198,247,224,202,190,45,10,153,146,148,150,218,67,157,27,190,197,15,182,135,56,130,43,203,209,174,134,100,81,179,58,182,229,1,155,224,135,148,214,99,38,92,212,220,49,17,170,248,161,123,88,92,5,119,19,210,149,12,254,121,21,140,38,10,247,25,4,22,186,68,1,211,221,109,182,103,137,4,242,129,66,67,138,61,50,131,83,208,81,53,132,36,86,63,33,62,142,250,210,195,68,246,210,84,77,150,182,48,140,129,1,24,195,122,107,160,22,129,227,250,27,102,21,127,52,229,47,19,58,21,47,132,85,233,11,183,119,3,54,223,94,30,168,153,3,202,62,170,29,46,235,105,186,122,192,71,128,73,149,47,98,46,122,34,64,101,76,177,160,154,47,174,96,118,108,73,203,121,15,19,101,72,99,177,70,118,219,124,182,128,41,154,76,22,204,166,120,224,174,35,27,29,63,8,248,217,183,247,192,11,141,178,28,4,184,73,111,64,221,65,220,21,145,34,163,79,94,28,225,40,146,182,182,2,244,18,250,136,64,65,3,121,52,149,19,150,105,221,244,244,247,77,249,155,100,216,128,178,170,122,153,140,221,2,88,211,227,255,108,191,91,6,185,100,148,31,75,245,179,229,46,107,30,214,20,93,198,142,86,108,83,131,235,38,107,38,203,229,248,160,22,216,41,215,22,55,59,211,156,38,76,79,202,176,49,88,161,162,206,46,81,83,200,99,138,117,40,110,2,84,142,165,212,63,185,183,35,165,96,218,110,177,40,36,21,19,181,76,171,145,175,144,249,115,42,97,99,152,49,128,122,54,8,136,236,196,46,137,181,211,218,83,112,177,64,193,136,89,220,176,221,204,172,174,154,77,96,166,191,132,59,141,90,169,6,46,45,84,193,160,209,49,6,199,255,3,129,73,146,92,31,226,30,164,12,7,148,241,217,3,113,226,199,81,146,95,141,45,176,205,253,233,128,78,74,123,244,138,154,234,99,11,241,18,251,174,123,196,122,254,82,210,2,90,216,87,97,38,253,160,197,255,134,152,168,162,17,72,133,41,122,235,85,154,133,172,162,240,103,107,149,216,192,182,55,27,163,94,52,129,61,154,61,11,135,223,222,154,217,53,135,124,181,120,2,41,107,239,28,32,232,45,27,51,86,176,14,7,40,249,170,100,67,101,131,23,151,200,74,151,82,184,146,40,7,64,240,146,253,80,218,150,108,16,186,224,225,98,8,166,177,252,0,35,95,107,137,80,130,116,129,161,149,37,52,149,240,167,11,50,129,134,80,126,16,233,201,206,97,186,68,205,245,254,241,139,20,5,89,162,39,98,188,107,186,119,233,101,250,245,150,241,120,191,39,29,12,121,31,198,242,252,230,85,160,112,172,171,128,29,103,65,246,39,126,74,92,140,142,56,181,82,101,195,59,71,4,8,9,42,98,180,136,41,26,56,252,4,230,102,239,251,161,183,106,22,54,238,250,59,61,243,9,189,77,195,254,119,234,124,186,211,5,26,88,176,159,87,101,242,100,179,102,218,39,85,82,118,109,146,144,225,73,28,78,77,189,135,29,192,12,95,153,113,248,50,171,113,241,189,121,194,155,247,109,70,124,72,61,27,79,56,185,218,51,155,130,98,183,1,100,60,85,55,160,158,110,41,58,63,216,176,49,228,195,87,118,254,105,223,41,138,84,41,78,214,111,49,206,175,91,190,57,25,68,120,22,127,85,81,202,226,197,123,156,169,249,12,182,148,31,115,211,146,41,208,248,249,197,188,103,47,138,8,117,43,130,28,28,102,44,149,38,221,176,211,11,76,148,186,176,252,87,62,69,3,88,80,123,168,196,245,128,224,186,224,99,220,46,237,181,88,159,161,175,204,237,160,154,13,131,12,99,88,171,231,111,242,238,194,193,15,3,254,152,148,114,131,215,216,106,245,73,197,176,147,149,25,185,200,252,52,225,236,86,240,34,22,76,102,243,132,148,11,204,125,58,185,37,184,188,4,169,89,249,104,232,254,3,96,102,68,177,242,8,251,188,177,100,48,1,248,177,185,181,108,161,130,117,35,229,28,94,131,105,31,242,158,200,167,63,124,21,55,142,139,10,202,5,82,209,8,37,48,22,47,237,174,182,254,11,32,46,255,142,78,113,207,192,187,172,174,16,156,90,26,138,142,57,129,2,59,148,175,197,194,242,205,81,57,214,199,206,60,204,225,254,113,28,148,222,242,209,101,104,98,108,237,223,49,114,212,129,78,146,78,208,40,162,230,188,127,198,195,47,15,146,82,173,159,186,217,133,148,237,194,5,33,102,245,90,65,8,165,35,12,231,205,62,97,232,36,7,127,30,119,233,149,99,221,178,173,102,226,168,250,196,60,181,5,125,126,243,158,64,110,37,30,195,162,229,136,241,198,229,105,88,85,49,14,96,84,216,55,253,53,92,172,24,38,54,35,37,50,118,149,84,244,199,203,56,87,218,44,100,7,25,135,147,55,101,115,200,99,37,8,239,72,221,30,76,8,86,146,55,44,91,241,31,111,230,90,185,168,144,245,50,43,46,238,33,229,223,34,244,14,118,219,103,141,110,249,21,49,255,202,251,214,126,66,144,34,95,94,195,240,131,109,100,123,73,158,69,82,217,206,59,169,190,31,185,211,83,88,73,74,185,229,228,147,57,21,198,39,234,143,84,167,170,144,247,206,56,43,55,104,193,157,220,89,125,173,151,17,4,10,18,124,244,41,133,194,59,11,202,98,174,212,26,19,95,71,26,82,242,133,85,125,4,131,36,108,37,250,255,99,63,15,53,173,129,255,175,83,105,132,142,35,4,243,133,67,237,220,88,25,169,219,83,229,33,83,46,251,0,111,226,87,41,226,98,245,208,93,251,94,207,210,41,146,56,119,137,32,0,61,212,6,161,219,144,112,202,88,124,132,83,197,240,185,196,152,34,202,136,59,198,165,5,136,11,246,158,60,3,176,105,203,207,70,162,187,45,160,39,60,82,115,113,239,37,166,188,235,215,222,227,65,73,188,70,178,98,215,247,7,12,10,4,216,139,202,178,125,231,103,79,61,127,58,10,202,75,42,107,139,214,172,4,14,3,23,73,247,52,158,78,61,218,235,79,191,182,70,127,157,34,208,242,177,248,153,110,42,50,168,186,212,159,202,174,245,161,60,197,47,221,200,111,195,231,35,136,145,196,62,119,52,247,41,50,41,64,94,231,136,149,213,174,127,157,61,143,47,166,152,59,245,186,16,70,32,201,49,239,157,90,225,122,138,88,158,93,59,121,246,69,151,25,182,189,199,100,74,131,123,99,103,185,138,240,169,255,83,8,240,13,159,156,5,223,181,247,243,244,179,90,207,159,36,69,34,174,29,39,12,198,108,220,130,2,10,203,188,206,67,116,209,27,67,170,198,93,113,250,14,198,254,196,37,146,198,0,245,162,19,196,105,30,136,94,211,48,61,213,53,160,236,102,140,240,236,1,246,124,73,73,184,88,243,157,125,154,77,39,104,111,1,205,78,22,233,44,37,253,92,198,51,8,211,150,43,192,106,122,208,21,123,140,14,148,222,144,217,194,15,242,120,80,45,66,71,74,147,132,37,185,45,165,41,76,166,143,130,134,3,4,15,104,214,102,179,162,238,195,200,235,20,223,172,249,110,37,43,216,136,128,232,235,48,215,2,250,173,82,109,146,30,125,217,231,73,206,65,2,40,45,35,163,248,230,102,19,67,102,0,76,64,7,130,23,167,105,28,152,26,73,234,15,36,35,231,146,205,50,217,164,199,154,192,15,19,80,26,30,181,14,197,12,131,88,61,140,86,85,233,182,210,78,143,77,63,177,30,176,10,224,14,137,130,162,84,191,108,227,75,85,115,237,159,119,222,168,131,18,13,22,92,110,176,134,71,180,31,116,154,111,4,116,74,59,2,191,75,114,181,184,238,106,236,202,251,63,247,48,35,155,172,61,122,174,26,38,3,176,42,15,71,195,153,55,66,191,33,169,177,220,36,95,177,66,86,173,31,180,219,166,178,139,120,139,67,88,25,238,233,169,169,111,163,217,54,29,44,34,138,236,199,35,50,82,214,30,125,91,25,222,65,137,125,96,232,78,167,209,68,71,70,1,22,163,34,202,200,71,113,235,157,41,14,32,110,171,235,197,174,10,51,158,251,44,98,199,201,196,168,50,201,99,205,245,153,75,169,17,143,154,52,222,138,28,173,86,92,134,115,136,220,131,85,171,122,218,117,190,117,143,79,26,121,10,50,45,80,241,33,4,253,140,1,159,201,105,123,35,133,81,59,236,16,238,109,215,10,124,211,64,112,180,147,203,106,142,69,97,205,162,177,217,151,174,189,239,69,50,30,166,238,219,120,79,225,197,121,127,91,215,89,102,17,39,158,213,94,164,254,49,125,216,191,222,90,38,224,214,242,60,2,38,241,139,218,34,185,186,30,206,33,43,38,242,81,191,12,1,200,96,167,125,197,194,127,129,244,184,30,74,74,196,174,229,224,226,124,52,137,122,146,108,187,169,127,72,111,131,243,79,149,236,134,103,137,212,161,44,61,183,188,103,150,96,95,88,187,167,31,213,185,63,128,70,10,58,47,69,155,112,231,242,129,19,78,116,74,152,85,44,128,199,241,148,56,48,27,194,180,191,35,170,227,179,166,110,172,88,208,185,53,153,120,109,155,216,205,172,159,59,191,94,49,209,213,90,125,246,132,153,163,89,50,28,91,141,185,11,4,229,210,18,79,36,117,191,90,231,97,92,89,193,98,201,7,9,252,3,100,157,87,134,164,29,218,54,7,117,232,97,226,74,185,43,135,78,199,151,206,137,157,244,201,49,137,164,23,115,134,121,92,128,224,192,100,154,252,124,146,17,129,44,130,237,65,159,194,35,88,56,132,29,163,200,91,112,118,35,100,76,112,87,180,233,171,69,124,62,161,232,54,66,129,248,193,47,232,197,143,236,112,36,132,61,97,179,231,60,124,4,220,161,114,16,84,196,143,200,58,98,2,255,8,3,222,42,146,204,234,68,199,78,202,173,32,215,30,242,64,32,250,49,111,31,174,191,209,40,51,55,101,12,137,212,116,140,72,132,52,104,204,245,218,122,29,236,175,188,112,137,112,129,225,22,84,118,55,75,104,13,207,51,243,102,148,120,49,86,192,53,173,30,143,161,0,187,160,141,185,32,104,37,221,242,44,29,27,162,135,12,4,205,239,98,8,217,237,81,207,29,240,169,209,6,80,56,120,99,193,90,244,235,14,45,162,130,224,62,152,96,147,9,238,188,49,82,151,207,8,240,126,39,228,192,121,199,227,52,238,238,69,130,134,174,90,34,126,176,133,63,234,79,219,126,186,224,106,183,242,244,90,180,161,17,110,155,66,109,222,205,83,121,103,49,85,234,220,198,98,67,0,50,194,21,182,193,118,19,220,4,173,96,221,203,40,186,232,98,162,37,12,169,225,26,229,12,71,121,194,162,100,159,139,30,0,151,86,14,131,219,129,154,212,170,79,126,26,171,90,92,239,0,106,79,97,213,183,128,12,238,216,30,67,114,73,64,191,22,179,225,12,252,220,234,87,55,51,145,66,34,63,168,252,148,87,47,176,54,228,85,152,226,61,198,41,76,94,182,131,134,142,127,97,14,232,78,147,107,91,23,55,184,220,0,132,128,230,214,41,253,146,45,59,69,244,78,228,127,47,234,235,212,197,152,203,251,16,167,93,153,46,245,207,238,82,246,96,131,4,123,250,67,9,15,63,198,214,205,18,51,223,238,190,104,69,185,188,1,61,168,132,22,21,224,86,237,119,49,15,228,241,216,161,180,19,252,22,109,144,133,49,21,97,145,73,250,32,160,0,103,179,235,69,26,206,44,140,184,97,110,167,21,84,228,112,18,154,24,41,60,232,190,168,43,72,248,82,221,13,138,79,89,140,122,61,117,232,17,75,243,217,88,218,235,50,96,182,174,230,168,249,99,90,3,240,143,171,128,49,247,62,32,242,216,73,239,88,172,30,77,172,78,40,138,46,152,178,103,92,139,57,224,167,208,14,63,245,78,69,235,225,103,133,134,96,22,32,104,77,117,153,192,206,38,183,221,117,253,207,240,211,16,89,105,251,119,74,144,222,156,150,154,58,135,38,58,165,24,125,4,181,205,243,117,226,156,243,80,70,66,176,146,37,197,55,215,99,87,148,92,191,170,198,29,60,48,57,132,232,226,100,191,28,143,184,235,205,69,47,243,18,71,89,96,148,5,68,98,120,4,46,222,166,248,156,123,31,13,147,244,29,153,133,248,130,207,112,2,139,131,49,115,58,120,121,244,170,19,97,201,192,75,161,137,127,83,157,78,253,58,222,224,220,83,182,11,236,101,153,140,34,113,36,254,143,112,151,78,23,46,155,32,170,178,239,64,77,243,128,127,240,27,82,213,68,205,87,27,42,124,75,156,9,234,4,161,210,181,7,140,130,78,31,105,100,208,169,223,62,105,229,132,50,56,128,226,5,184,254,213,116,54,2,93,233,67,132,34,39,179,133,27,209,227,163,127,21,38,10,175,140,28,114,70,190,173,123,166,31,176,23,83,27,2,64,147,250,217,95,1,100,211,238,42,151,65,188,182,234,61,134,64,31,245,14,173,167,214,244,223,242,182,230,208,180,241,228,142,135,251,1,188,189,100,175,18,181,117,35,14,102,136,20,208,168,235,41,228,102,112,204,114,197,137,63,144,1,174,122,8,52,194,119,247,169,229,16,103,124,105,126,128,30,165,102,132,107,24,55,253,220,212,101,202,129,150,144,2,88,195,9,152,160,243,97,168,80,228,18,168,79,186,193,151,206,197,164,32,6,58,126,128,178,154,122,20,188,81,123,96,6,46,214,149,107,24,177,129,255,208,247,29,66,228,212,126,81,168,1,76,131,174,108,141,122,248,24,107,113,170,68,235,117,129,83,56,163,148,130,79,104,185,22,138,198,242,77,180,102,47,117,225,233,90,16,225,8,163,241,112,173,15,227,176,197,136,139,114,202,96,151,63,60,96,154,107,17,147,224,206,248,93,53,106,235,229,60,87,165,173,67,60,192,40,25,38,154,183,128,195,41,187,21,254,166,61,76,158,20,29,63,194,131,191,180,111,32,193,245,193,122,94,224,84,142,94,172,150,192,219,151,49,107,61,164,252,204,72,119,227,21,253,120,84,60,176,113,224,172,24,196,92,64,19,6,114,3,127,121,48,40,3,60,52,74,110,225,56,14,140,23,179,58,129,206,230,166,25,190,123,31,5,201,50,253,204,94,174,116,91,166,97,216,90,145,201,152,88,164,18,19,17,202,204,251,146,159,61,233,43,209,63,240,241,168,94,78,86,211,0,62,97,12,204,199,62,218,65,64,9,170,91,210,0,191,56,249,81,51,140,84,246,229,192,59,27,87,104,195,108,174,216,168,188,98,234,57,57,162,193,13,190,155,45,124,40,58,32,99,14,179,68,39,112,92,159,159,36,201,2,226,129,171,120,102,185,148,114,152,162,196,181,56,69,182,37,197,98,228,38,41,142,10,57,84,197,160,183,210,236,9,42,214,224,63,62,31,118,26,251,177,236,185,210,104,244,19,251,195,113,141,34,50,255,204,42,56,117,66,203,139,249,119,14,28,203,175,32,42,245,180,104,11,154,25,127,248,60,200,28,180,91,39,244,161,108,240,140,189,72,32,119,76,235,30,100,46,74,250,110,234,232,192,243,51,124,39,251,186,123,64,23,149,105,161,56,180,49,163,245,34,42,187,145,64,13,82,135,95,186,146,44,214,135,104,194,94,110,93,178,242,130,21,226,63,156,184,127,204,241,167,193,180,9,237,106,90,105,165,19,198,246,140,189,35,66,77,27,170,145,237,170,99,161,189,234,238,51,219,82,212,214,32,43,128,193,45,163,2,216,44,192,84,104,92,99,93,116,94,163,255,90,174,176,184,147,127,46,68,22,63,23,62,151,173,125,237,52,101,54,144,205,184,145,103,197,86,53,11,127,158,118,175,217,13,86,251,47,11,230,181,185,174,212,134,254,17,229,174,154,246,87,107,230,55,252,104,84,104,251,201,66,110,183,24,71,54,10,178,175,12,182,18,163,73,203,244,85,216,175,129,81,60,17,112,71,155,136,34,122,134,137,245,172,152,64,127,55,97,0,148,116,138,88,45,172,16,250,169,10,55,168,155,249,246,117,74,112,183,220,144,84,127,245,255,79,75,162,219,9,150,235,53,199,122,194,58,198,192,83,66,183,114,7,36,198,143,179,218,40,178,248,218,185,108,140,103,50,91,31,235,191,230,109,62,140,189,224,31,241,31,255,48,167,106,18,242,164,95,24,208,232,159,107,188,95,66,187,61,92,245,43,201,191,135,1,41,19,255,103,156,115,9,219,112,48,74,62,113,152,120,196,200,133,105,206,67,75,26,102,159,159,237,244,74,119,46,70,217,24,102,5,82,212,11,224,67,44,241,148,125,122,140,30,141,56,185,122,202,228,228,152,203,143,221,92,116,168,69,113,89,106,187,215,201,255,151,132,143,105,97,52,138,102,179,146,194,72,5,11,142,16,31,119,218,54,11,45,117,143,78,191,169,116,115,101,231,67,196,81,203,175,126,36,74,3,153,52,15,176,118,87,2,10,235,166,166,25,217,24,97,56,174,121,208,62,83,81,159,25,1,81,67,213,89,71,34,140,83,221,7,159,118,96,172,176,235,249,185,28,97,166,17,64,245,165,23,63,251,128,105,12,76,148,92,91,188,236,238,25,184,58,203,60,22,171,192,183,224,144,158,173,39,61,188,92,76,155,181,102,5,187,207,150,94,58,3,250,36,236,210,151,254,24,164,165,111,28,108,229,47,22,146,124,12,137,148,24,184,174,127,13,247,114,83,177,100,178,209,116,247,77,184,99,249,116,52,90,208,48,242,239,23,251,172,248,54,133,62,24,240,90,110,209,64,19,65,231,127,36,40,74,61,89,232,108,40,133,183,241,255,164,20,180,249,37,233,11,144,123,198,10,134,56,30,115,232,181,188,113,167,11,26,133,132,207,13,144,114,236,85,141,70,151,42,10,176,211,160,243,33,210,57,247,197,33,32,215,207,152,153,82,222,95,87,217,232,251,9,157,52,92,92,186,221,244,36,132,244,171,126,222,212,178,213,118,239,52,68,215,228,157,37,229,77,151,40,95,205,177,209,250,59,223,193,65,135,147,161,220,60,30,20,221,12,251,251,237,115,218,76,211,222,227,113,244,133,150,144,25,141,230,202,17,219,118,142,8,254,249,111,8,74,66,92,214,206,5,252,176,47,65,208,174,127,25,182,208,254,125,215,136,104,95,122,148,47,160,24,171,217,115,108,36,46,111,121,54,209,200,78,201,242,47,82,146,153,116,84,30,151,175,199,2,189,89,106,30,113,219,11,101,233,191,165,1,168,238,15,156,187,76,114,205,125,10,232,251,59,152,234,16,241,125,111,195,40,170,83,198,62,219,137,128,20,195,25,33,235,77,95,39,151,116,175,239,44,250,171,84,173,154,211,23,212,157,160,162,208,164,16,244,147,14,14,17,6,104,150,53,108,250,78,227,27,137,22,252,98,238,175,243,37,70,13,183,79,164,152,113,101,78,244,30,197,103,210,103,214,38,156,171,0,17,21,28,178,30,168,20,31,200,208,51,52,113,15,151,103,235,237,40,10,81,34,216,193,173,182,231,138,223,70,74,110,140,135,128,67,193,157,182,109,142,223,157,163,206,148,192,228,100,183,148,130,219,246,217,18,184,83,27,227,178,40,188,85,136,45,33,244,69,87,159,128,40,97,108,157,0,46,148,60,23,222,235,38,205,188,53,18,244,187,182,168,183,237,144,27,24,195,130,65,220,216,15,20,137,249,27,41,218,232,246,197,92,106,119,80,113,188,192,30,233,34,219,39,146,187,114,27,18,165,104,236,249,38,44,105,166,205,230,49,128,243,36,251,113,40,38,25,215,224,120,27,235,159,12,92,34,87,109,158,74,60,6,136,178,187,38,91,137,86,88,121,201,214,195,151,83,64,228,135,143,158,147,97,176,188,111,251,247,113,197,192,23,113,9,177,188,15,65,193,111,153,189,107,45,251,63,75,15,75,144,12,21,147,41,0,174,131,76,50,32,230,156,172,12,21,217,99,174,122,176,90,142,255,218,205,218,102,252,254,211,225,2,68,190,66,50,226,64,173,14,103,174,112,42,47,226,144,59,125,110,69,123,255,9,156,24,136,238,168,115,76,198,25,170,142,181,178,27,82,125,25,38,98,50,248,232,139,82,51,79,162,74,26,73,204,26,40,13,40,2,73,96,105,177,92,99,35,99,110,56,185,105,177,205,31,100,153,114,150,60,150,252,43,129,210,116,71,159,252,129,54,152,242,65,180,226,15,50,224,127,124,175,143,91,38,46,62,8,22,59,186,178,38,77,246,103,48,216,212,109,56,156,174,127,24,51,123,161,249,178,142,219,27,68,158,78,254,94,242,73,34,240,204,200,93,216,7,25,228,165,205,3,19,2,181,77,104,175,11,217,230,194,135,111,69,253,161,56,50,214,192,155,137,146,17,189,167,202,57,121,74,241,142,45,201,161,154,57,125,92,44,130,241,88,74,115,124,14,144,36,13,187,40,11,139,4,59,158,157,206,13,92,151,135,1,219,94,61,152,173,99,202,240,172,225,103,253,248,69,184,171,34,33,169,218,245,125,15,58,199,178,40,202,80,134,75,170,110,92,65,6,58,200,15,51,116,102,229,188,24,164,185,80,221,62,235,227,1,238,159,158,44,47,211,248,136,211,153,57,241,104,231,90,19,39,187,253,118,187,69,91,208,213,90,157,249,110,157,246,186,4,46,212,11,235,27,55,22,236,16,139,224,123,76,76,174,18,156,21,2,25,59,83,147,157,186,202,18,243,139,77,192,205,43,11,67,231,130,169,53,171,6,241,244,138,2,96,125,93,209,194,120,187,162,104,129,237,118,242,149,94,212,207,222,141,202,202,204,103,231,34,132,92,157,95,239,176,202,195,185,87,154,63,219,10,215,8,146,73,190,222,17,110,27,90,35,66,27,93,191,17,12,120,158,138,224,58,68,152,169,243,48,157,252,163,132,148,157,222,184,145,161,202,141,123,93,61,82,14,213,82,53,66,165,100,215,10,77,207,216,139,35,208,176,63,63,80,219,7,147,222,36,12,252,16,92,225,56,96,70,218,129,99,205,25,99,208,253,109,43,104,153,0,224,39,192,163,67,138,85,157,8,128,148,197,89,194,87,99,206,81,141,47,214,217,156,211,187,184,220,33,32,20,31,143,48,136,147,54,141,147,129,53,91,215,115,208,74,187,36,225,92,30,238,23,79,195,80,124,161,28,40,129,212,156,128,13,94,16,64,122,47,166,181,116,236,218,16,106,162,20,12,250,106,59,75,168,173,41,229,75,239,230,135,79,240,61,106,144,243,222,80,207,8,155,238,226,204,246,25,2,83,116,227,42,121,189,61,88,237,200,221,66,111,84,209,44,204,5,74,21,249,236,194,187,52,103,164,109,114,191,27,0,240,99,60,253,103,92,69,90,87,109,109,138,61,171,55,129,98,152,62,65,82,93,47,130,95,171,12,145,48,243,4,220,47,118,144,188,144,153,224,242,141,144,94,218,128,144,77,106,98,182,215,118,91,73,238,22,122,110,3,109,89,91,34,0,57,72,86,228,158,153,209,235,58,200,213,223,68,254,49,210,128,11,87,0,207,25,93,183,141,193,9,142,11,15,213,209,90,220,249,117,222,163,188,42,116,162,111,235,175,70,29,243,205,184,46,214,112,219,68,27,190,37,228,13,196,98,127,58,220,90,248,241,41,128,82,170,102,78,72,99,103,47,49,238,210,203,217,40,130,83,98,143,81,119,52,173,166,24,234,61,253,11,147,118,189,128,69,161,207,122,161,251,67,139,246,0,44,109,95,241,166,224,177,225,201,10,38,201,24,44,192,55,22,191,109,159,167,39,67,213,33,100,6,197,183,223,105,223,51,37,21,232,53,7,12,64,243,13,77,22,76,175,156,127,201,50,147,144,135,179,71,59,88,161,195,29,23,213,184,66,77,202,54,134,198,21,205,74,59,68,197,2,150,28,192,219,164,192,158,231,193,240,26,176,33,136,97,129,95,91,76,114,79,86,97,220,135,80,233,39,150,150,27,223,206,160,84,151,120,226,45,231,200,167,121,200,46,1,132,39,112,88,96,85,173,249,29,67,46,208,224,131,84,81,64,218,16,15,12,243,215,86,157,212,204,147,221,26,11,10,114,75,9,240,8,16,58,152,196,219,149,51,8,94,225,203,7,157,156,249,220,220,207,80,128,47,103,189,58,38,83,183,122,51,230,254,146,160,37,235,226,233,55,164,177,33,246,224,67,54,25,126,27,216,100,83,102,46,231,99,215,206,57,243,30,174,54,153,209,116,17,156,121,215,104,69,33,59,37,187,95,75,158,233,68,148,64,236,174,32,201,143,189,99,126,50,216,65,155,184,98,84,102,243,47,178,99,59,227,198,213,53,206,39,35,180,9,162,212,58,190,48,80,234,176,124,165,130,234,100,117,5,245,122,210,159,134,31,165,144,196,154,81,131,130,236,180,4,23,225,45,144,92,99,117,71,130,142,141,103,81,168,211,2,123,203,171,59,133,24,46,169,116,160,216,233,44,215,66,201,119,51,58,75,50,68,116,127,170,113,129,55,193,109,155,237,246,191,189,150,135,24,5,204,65,201,86,15,202,87,40,122,227,52,245,82,182,54,65,104,165,101,190,208,117,246,203,163,168,171,35,67,186,170,221,100,63,0,206,157,229,28,237,147,132,88,91,215,64,64,22,48,88,246,232,140,146,211,199,110,230,207,238,78,66,78,104,253,244,227,114,94,210,30,6,33,43,1,110,176,2,156,178,126,202,213,183,124,213,218,56,96,100,54,192,53,69,60,180,73,48,142,15,85,251,191,216,147,246,47,251,203,203,138,14,174,9,73,186,102,220,0,200,22,56,137,234,117,155,105,229,151,192,129,193,93,234,222,103,57,195,107,240,92,18,180,41,23,23,255,255,135,26,222,109,47,129,205,129,52,192,82,153,195,24,72,58,156,127,159,210,114,67,196,173,239,17,84,216,115,57,151,70,218,133,179,61,149,175,160,128,222,103,91,202,239,92,198,173,251,58,186,236,105,215,23,167,254,58,4,21,22,17,213,211,230,47,195,183,154,245,187,224,165,236,107,184,195,149,49,79,138,158,97,201,64,138,145,249,37,253,56,175,148,83,197,74,69,186,47,38,63,14,241,224,30,52,152,74,163,144,190,253,92,176,164,109,217,165,118,19,56,214,162,10,193,213,18,95,72,55,150,22,199,50,196,111,155,204,32,122,25,68,234,156,43,178,92,160,204,83,138,2,184,248,7,132,201,144,69,176,216,12,49,175,55,89,163,91,23,159,27,226,183,111,153,13,35,140,237,237,170,126,119,171,55,105,81,53,55,142,131,46,39,136,83,145,158,216,192,73,71,22,117,124,243,85,81,130,52,28,216,143,226,153,141,3,162,141,249,125,8,119,27,65,133,135,123,117,71,161,45,130,255,194,160,178,21,123,106,105,199,3,146,205,115,157,18,61,181,226,101,151,234,244,10,17,216,104,186,3,215,32,157,200,151,190,41,62,181,74,5,160,213,185,70,97,253,164,115,81,108,228,207,4,144,210,54,224,36,93,21,210,109,58,54,121,127,235,182,110,122,161,24,48,114,193,83,31,221,109,136,70,83,212,203,195,232,231,69,5,55,157,106,77,101,19,58,55,127,91,240,85,64,11,229,155,10,93,177,2,144,20,75,121,186,81,171,50,1,196,62,217,231,16,206,250,186,173,24,60,218,230,99,216,36,3,103,61,237,73,61,170,38,35,224,158,166,103,119,128,4,5,152,194,141,234,113,149,54,196,25,235,18,81,227,137,137,138,115,20,204,38,189,115,69,224,31,135,6,32,171,72,87,42,144,71,72,255,171,79,132,159,83,151,209,62,152,25,79,133,19,172,154,90,84,80,101,131,150,37,245,195,199,210,235,98,122,229,215,7,164,79,63,62,80,142,144,161,189,235,24,212,200,109,145,185,104,122,29,112,81,147,15,4,108,147,244,184,155,249,18,80,201,174,227,93,226,109,63,7,17,14,209,141,194,160,30,170,18,60,144,32,224,177,0,106,248,126,107,84,185,179,106,146,13,238,80,251,18,50,96,122,216,217,112,187,148,102,111,47,244,158,22,39,76,59,150,43,22,117,202,253,88,26,166,126,243,142,239,81,69,185,255,93,56,20,32,232,185,22,217,19,198,221,159,42,176,105,127,180,90,189,136,213,241,120,92,0,77,136,165,142,142,126,142,164,219,231,41,237,134,253,191,235,254,252,57,52,25,89,120,215,145,142,87,152,149,107,177,79,86,176,4,105,59,150,254,14,74,110,116,206,16,0,218,98,156,66,18,10,16,202,136,15,80,236,236,233,75,132,186,168,174,233,16,240,124,0,189,243,98,252,33,121,215,44,173,199,127,71,233,97,165,227,102,12,62,59,225,180,119,55,117,95,159,229,177,99,143,111,247,182,37,180,23,219,51,67,250,113,124,122,213,160,93,82,156,170,252,0,1,76,22,11,250,91,147,112,1,233,251,21,112,60,137,25,215,114,231,83,28,55,129,94,198,200,247,80,156,163,198,211,214,235,239,111,210,160,137,128,181,114,163,61,8,94,83,46,49,30,181,239,140,222,109,66,167,226,89,159,32,73,145,21,222,213,65,62,66,94,137,206,128,169,236,73,167,141,150,232,238,36,44,136,68,28,4,21,153,225,253,254,31,210,190,138,17,5,228,142,90,163,91,64,60,208,230,70,88,201,198,140,171,37,112,143,83,251,39,36,63,189,48,135,196,100,189,76,124,37,117,179,153,183,236,97,94,72,5,144,76,23,71,22,137,91,101,17,51,31,37,37,248,167,248,202,225,125,28,24,192,51,67,242,20,243,183,110,138,211,210,110,39,221,189,226,241,100,225,217,111,128,6,152,234,156,179,79,2,139,150,103,51,47,252,21,104,71,84,83,243,17,144,151,52,96,128,26,163,179,77,162,97,109,136,128,106,219,50,111,229,203,148,252,102,19,181,220,239,169,7,60,6,173,111,160,55,24,162,69,223,39,186,222,104,184,206,203,0,68,178,244,108,51,107,230,205,176,248,207,12,225,122,184,184,1,99,226,173,135,71,136,45,243,127,168,160,134,31,180,45,53,1,213,36,43,83,51,59,61,115,223,67,123,54,86,38,128,71,198,210,179,241,150,253,253,1,26,104,127,234,182,86,121,188,19,134,211,19,249,75,96,210,137,255,175,48,38,23,82,107,180,73,87,97,17,31,217,160,77,243,143,164,224,77,154,152,148,205,66,240,48,168,156,21,103,19,214,154,17,173,156,16,31,18,63,134,224,211,145,46,114,33,113,105,125,72,78,202,25,183,28,255,45,63,169,16,225,2,237,156,45,254,223,125,195,250,99,49,156,250,188,216,169,104,171,157,188,114,72,110,29,153,187,99,254,51,237,255,23,98,131,248,193,121,59,142,7,176,78,52,182,134,170,136,125,40,234,245,225,74,212,208,176,105,253,8,32,143,69,180,249,246,10,31,176,129,144,255,199,193,59,12,181,231,207,169,241,243,19,253,220,49,45,195,42,147,102,239,117,186,240,63,156,184,43,225,119,87,44,38,11,106,231,241,208,145,167,222,147,22,240,37,62,139,30,249,0,209,78,164,84,131,254,178,126,91,170,226,29,73,170,154,101,221,202,18,92,146,134,178,38,195,106,88,228,86,86,172,34,113,89,4,85,139,78,39,3,161,49,94,245,107,21,206,162,64,240,35,201,126,89,226,156,229,141,165,29,4,22,197,202,125,44,200,64,176,137,55,95,167,234,104,86,244,217,45,234,206,4,6,171,85,146,235,237,168,81,103,77,204,104,16,110,90,132,100,240,72,96,188,201,254,56,43,229,76,8,144,250,190,182,102,89,64,104,238,222,184,173,138,130,235,233,91,226,30,237,38,236,194,116,180,36,198,97,37,242,32,60,224,15,13,203,190,121,127,41,1,108,205,117,79,104,173,232,164,128,0,31,193,82,164,115,1,175,199,50,22,0,215,136,87,212,105,174,240,47,27,51,93,165,183,61,96,31,150,125,70,38,192,85,215,191,65,159,42,123,59,211,210,39,96,64,53,80,103,134,214,75,89,23,40,114,4,148,61,56,175,176,119,180,61,162,119,184,21,110,204,103,52,202,109,151,202,204,240,215,165,116,96,52,113,64,112,42,171,54,172,169,69,253,44,153,24,232,19,141,73,3,80,141,143,57,23,209,218,79,5,176,20,117,197,223,97,0,0,216,103,205,251,42,189,173,104,182,224,240,187,184,90,150,165,151,54,237,248,21,195,252,26,86,186,43,130,85,173,165,88,77,47,61,60,251,197,177,40,114,201,153,72,161,39,61,136,217,22,39,227,180,112,20,184,0,22,255,248,87,132,120,113,8,6,226,212,166,57,112,185,75,15,83,79,196,106,136,205,5,59,250,63,35,80,140,176,236,196,248,3,221,98,250,104,32,99,152,165,109,139,192,40,49,68,14,50,89,102,202,12,64,120,114,49,227,205,144,18,43,180,65,47,167,89,67,145,180,44,241,173,23,232,86,141,103,210,72,240,225,180,133,221,238,4,125,161,121,44,204,5,162,64,34,84,167,152,247,154,190,162,116,71,83,180,181,174,3,151,227,180,162,28,198,133,1,195,199,54,251,220,4,182,126,209,15,24,207,187,240,50,11,120,250,158,87,125,246,74,64,175,190,21,150,255,202,170,125,38,228,16,24,166,186,7,113,0,133,182,112,138,188,2,24,120,236,10,76,154,89,48,23,228,159,219,144,219,209,76,59,25,100,202,46,203,178,117,252,97,240,97,42,143,205,52,199,220,7,0,109,217,139,126,170,178,227,213,192,16,171,133,173,237,240,186,6,14,155,94,157,194,99,123,174,181,74,164,126,56,178,0,172,77,163,74,172,53,5,161,130,161,162,149,232,150,69,170,172,59,70,142,112,87,58,16,192,67,8,250,29,140,221,17,117,167,133,43,180,141,157,214,18,131,114,105,147,206,25,138,207,188,30,41,9,97,113,247,123,251,56,165,182,239,95,79,152,45,113,160,213,230,249,227,167,149,52,172,156,182,242,134,61,19,90,144,248,100,252,168,76,213,246,126,123,175,8,114,218,41,247,90,229,94,238,86,73,43,35,42,116,168,217,75,167,166,122,230,82,130,255,164,51,9,86,79,111,49,152,198,132,96,62,12,131,23,66,96,51,213,29,13,144,20,26,228,66,41,228,68,254,126,173,192,51,62,41,184,136,182,93,102,144,250,65,236,200,19,121,182,87,125,72,97,132,164,29,130,211,26,115,217,177,199,35,54,132,98,87,138,188,229,34,130,240,81,186,231,130,41,17,74,64,27,41,169,251,229,192,38,247,81,85,224,10,181,80,164,164,112,73,150,53,119,166,144,157,52,98,187,48,28,64,77,33,237,100,1,46,123,40,27,232,128,105,190,126,27,132,205,16,107,184,30,187,240,29,128,81,177,9,175,37,159,188,53,109,59,15,33,102,39,182,31,73,163,176,14,150,178,216,231,41,152,253,100,240,46,106,181,137,111,240,101,204,74,57,134,179,49,230,134,124,152,70,64,166,43,65,203,80,53,157,166,39,138,142,243,74,145,217,9,194,93,128,67,93,129,161,161,254,211,189,239,205,32,171,253,118,141,204,240,183,222,146,198,220,187,58,201,238,218,179,206,89,183,40,198,33,53,38,40,144,216,247,161,189,216,173,9,22,72,148,174,45,3,127,35,125,111,140,15,207,119,246,38,244,195,69,85,106,121,28,241,125,124,103,116,108,152,84,133,165,68,92,5,189,160,223,125,159,69,84,91,214,24,52,36,207,180,152,8,156,70,209,194,220,165,138,212,192,246,132,124,186,64,218,179,23,131,210,117,7,15,197,250,249,187,104,74,19,195,232,168,66,171,125,133,252,89,123,236,67,152,150,187,82,161,241,29,160,206,15,254,101,201,34,79,182,6,88,237,204,67,3,24,199,64,58,22,71,118,31,80,235,148,111,111,74,248,229,15,0,160,215,0,121,227,15,243,58,122,251,203,236,223,102,217,235,105,113,239,209,206,227,198,166,116,250,85,48,71,14,78,216,2,167,129,129,240,167,56,89,118,161,125,49,228,56,221,13,219,207,36,68,253,27,45,219,117,151,229,111,247,206,97,173,132,8,74,182,16,125,54,238,31,46,244,50,250,3,216,182,42,120,67,61,39,106,101,23,248,21,80,151,115,41,105,95,47,32,90,53,3,164,31,12,113,105,26,135,101,186,43,191,173,143,177,4,75,109,96,7,121,5,231,218,250,45,96,254,193,146,225,251,238,21,240,27,207,43,187,7,61,254,195,234,210,152,46,241,186,188,216,234,82,179,109,61,190,139,211,58,36,74,149,107,249,150,196,71,226,167,232,40,42,19,152,17,194,16,94,5,11,57,37,43,99,98,248,81,211,60,69,192,80,94,225,241,197,53,76,100,1,166,253,132,17,3,72,232,72,214,60,18,151,159,15,167,78,27,76,142,22,21,129,121,10,185,35,246,49,165,218,73,182,236,65,1,175,236,230,71,209,189,163,164,179,194,209,86,6,180,219,147,94,15,212,246,83,21,183,250,40,230,78,222,159,74,94,13,20,247,51,90,218,253,125,50,81,72,93,1,200,50,199,223,192,197,223,38,208,98,122,118,7,82,178,154,193,50,199,199,7,184,231,120,39,2,232,41,182,32,75,56,236,176,5,0,113,190,13,109,1,175,212,249,89,21,130,204,162,228,119,244,190,87,252,151,13,40,209,103,93,95,199,103,141,133,122,94,189,161,222,26,229,214,114,137,110,97,84,81,251,213,80,122,215,144,113,154,105,12,130,191,24,0,226,159,46,86,119,142,104,231,72,118,224,91,195,94,179,212,168,32,243,2,25,219,4,197,34,167,252,198,18,155,87,88,62,165,118,253,176,96,152,186,128,214,140,226,59,11,113,104,102,96,136,126,9,13,140,165,46,116,134,52,249,105,131,168,226,83,93,216,194,247,236,251,159,42,118,243,93,85,175,120,106,134,75,146,217,187,183,49,138,190,5,189,3,203,106,166,110,104,108,70,111,165,41,203,34,212,254,32,10,2,238,30,243,126,47,119,175,63,107,73,75,131,105,17,54,253,158,128,179,196,198,64,151,178,55,47,159,191,106,78,234,208,198,108,42,131,2,33,44,121,43,48,137,107,252,205,15,84,242,200,169,148,239,199,117,248,6,151,51,83,45,149,57,75,160,202,27,122,235,14,50,90,135,90,94,140,171,241,123,236,90,200,243,190,6,111,165,246,139,34,141,151,172,38,34,66,201,218,83,110,52,12,146,6,26,248,102,120,174,193,25,147,171,152,87,174,79,55,208,166,73,111,90,214,25,117,239,102,226,213,182,128,93,49,129,174,3,2,180,9,250,166,8,32,141,187,26,55,157,229,144,64,195,91,154,133,56,176,6,198,60,119,115,232,70,213,143,59,250,97,136,50,75,125,198,19,151,141,168,48,163,47,67,211,114,119,103,69,9,119,244,236,196,164,248,228,69,215,205,245,16,57,177,244,43,224,109,172,45,14,5,161,195,63,81,38,117,19,125,248,179,103,199,168,84,151,192,55,216,72,96,43,117,199,103,51,202,42,177,40,169,84,157,153,173,244,141,108,142,38,188,53,35,151,221,147,12,148,111,151,129,212,37,253,142,191,152,21,241,153,150,30,71,95,49,124,83,150,47,109,169,199,96,70,141,167,74,79,11,152,159,93,215,159,185,141,249,140,114,217,75,87,133,177,114,114,27,32,86,10,246,20,157,127,160,164,227,79,194,177,107,49,142,179,84,144,135,178,81,30,7,228,120,116,11,103,210,83,15,94,77,40,116,144,27,125,81,192,231,217,112,4,184,78,6,144,65,184,221,84,114,52,150,241,217,130,114,219,252,15,34,244,209,76,178,193,231,229,38,137,147,0,147,242,150,26,33,32,28,132,60,63,134,221,9,214,135,97,120,217,109,78,130,199,253,153,215,234,19,186,201,199,169,20,132,151,74,179,54,65,25,171,126,126,88,23,247,222,39,52,65,85,45,245,229,214,38,98,14,0,10,216,42,17,230,34,91,84,144,209,31,186,211,140,175,188,80,202,99,174,124,88,40,32,214,235,133,253,145,179,186,102,42,135,61,67,235,163,133,41,35,25,168,87,141,24,186,210,233,150,19,220,120,81,123,169,245,18,197,27,207,176,15,197,115,139,69,152,82,211,148,77,184,232,173,29,253,46,123,173,245,217,54,231,135,218,236,101,196,45,109,136,189,206,68,215,214,77,251,43,39,224,144,62,135,50,114,247,67,110,247,38,143,220,5,1,173,142,88,7,149,152,225,194,10,114,152,121,105,239,242,249,117,29,172,2,39,98,218,33,31,69,93,11,210,222,132,40,251,162,173,144,13,165,165,242,181,202,215,89,196,228,253,39,70,73,153,144,63,184,211,2,204,107,51,166,197,173,14,15,96,66,141,11,12,244,148,50,16,214,9,8,52,6,165,105,91,184,10,10,62,135,250,200,159,69,227,229,86,98,229,73,27,200,217,108,233,211,81,90,93,45,50,50,149,19,35,23,116,202,113,21,211,33,217,140,128,86,228,185,130,140,104,87,180,174,131,213,254,48,90,67,239,159,204,139,229,42,236,142,82,151,187,165,11,12,150,53,56,10,76,97,213,117,217,51,242,133,135,229,78,117,95,26,31,69,32,138,147,70,226,136,42,0,8,199,224,233,35,206,48,207,61,99,52,101,204,118,143,245,236,120,33,226,57,223,53,32,255,6,236,127,223,89,137,99,84,204,80,106,20,237,64,149,193,65,7,41,202,120,56,115,112,137,35,254,243,28,47,4,229,33,115,177,48,219,231,48,63,139,95,214,209,6,170,197,116,222,104,88,254,141,16,48,222,226,9,47,121,65,188,142,38,129,229,60,122,25,131,229,78,249,211,139,93,199,181,248,231,247,38,161,131,223,146,216,88,123,189,77,186,220,2,185,53,173,226,101,153,213,103,171,140,207,44,51,120,168,36,182,213,176,87,166,170,61,250,49,139,249,215,135,168,170,59,95,118,142,249,166,177,121,94,175,159,219,228,219,117,28,222,43,180,225,108,140,7,25,5,94,45,171,5,65,137,255,40,123,190,89,181,94,76,172,91,161,197,240,85,79,172,28,47,57,205,233,102,137,143,28,155,20,20,157,41,148,175,43,167,5,82,171,148,109,247,237,236,176,176,124,1,158,189,93,168,51,115,231,208,228,55,164,123,212,27,25,190,38,1,120,25,153,91,236,95,116,67,210,173,224,156,220,91,207,120,91,114,212,191,71,198,205,146,136,65,91,33,204,192,154,155,243,71,11,55,239,100,89,204,247,199,59,120,22,68,109,137,194,203,81,61,247,11,226,242,210,155,195,209,1,193,108,163,178,20,22,170,30,148,214,80,229,153,91,103,246,237,10,245,110,211,150,205,98,239,92,94,71,206,91,253,204,90,157,216,152,35,148,167,8,201,167,24,239,191,158,102,23,131,159,64,99,81,159,58,193,185,68,1,28,24,38,198,132,80,191,19,122,235,99,129,100,49,253,29,52,194,32,108,106,166,243,179,53,189,96,59,73,241,61,32,223,84,218,118,59,32,64,9,98,239,207,219,101,38,106,54,148,148,25,5,50,107,106,152,242,117,192,102,56,184,19,232,133,157,243,182,52,144,217,94,101,153,221,88,157,52,224,159,93,159,71,2,115,200,230,116,202,177,236,75,20,176,16,39,147,24,150,195,21,251,77,57,185,113,216,168,48,127,164,56,104,92,23,85,141,159,93,53,192,103,163,130,24,85,85,160,61,246,23,185,196,18,158,228,129,148,126,206,52,198,191,182,12,98,112,31,56,160,62,208,196,234,1,56,249,23,61,115,25,164,254,151,45,11,124,107,53,151,131,221,52,249,185,90,5,4,129,177,134,168,239,37,50,111,225,178,53,251,9,5,87,32,111,75,239,38,160,33,50,128,211,5,250,31,61,177,31,115,182,221,118,33,225,75,165,5,43,89,152,62,217,185,246,122,194,98,47,193,42,74,46,144,111,16,231,76,88,151,7,93,68,144,237,82,117,206,167,239,6,137,55,125,14,88,92,201,143,148,62,216,55,224,150,178,38,77,42,167,163,233,124,131,220,55,50,219,117,225,244,220,233,124,27,133,246,213,86,54,152,29,92,98,226,98,54,110,144,186,41,161,225,72,199,30,105,121,160,56,141,23,100,40,88,208,169,32,196,122,95,231,57,244,199,120,13,232,165,250,170,24,34,231,23,205,33,18,214,128,56,165,14,48,104,223,133,183,73,58,100,111,112,115,239,70,81,81,38,94,88,232,164,212,242,0,59,114,36,133,89,252,41,204,37,193,144,244,255,242,124,20,131,112,126,131,187,205,71,229,86,90,197,199,245,45,120,190,56,223,164,63,177,75,188,238,180,176,137,182,95,221,29,158,104,4,224,38,183,94,172,67,44,62,168,237,218,85,159,58,25,168,173,108,204,228,81,18,145,207,176,19,10,212,78,133,108,169,178,117,11,19,155,152,200,117,243,99,143,126,93,75,167,4,103,249,245,27,30,184,78,162,35,174,200,4,59,119,138,195,58,130,59,179,147,48,207,134,201,207,31,90,145,168,212,195,79,220,16,253,80,24,42,159,61,178,241,81,140,246,198,225,166,94,74,63,254,3,218,93,2,74,194,239,192,68,55,75,132,51,79,200,162,72,133,34,87,86,7,157,235,37,94,78,191,150,81,213,162,147,20,232,243,173,36,1,244,91,3,192,10,224,194,229,74,147,19,192,165,168,153,5,127,230,113,185,206,127,146,80,114,246,179,16,31,90,0,242,254,82,189,36,246,211,7,118,168,33,154,220,184,107,101,40,150,196,194,242,253,216,72,132,210,147,230,224,198,34,75,25,74,233,205,159,168,6,197,50,217,127,251,94,27,0,89,55,171,138,10,197,251,46,127,84,139,97,212,131,44,89,5,181,154,11,223,2,106,249,29,222,72,44,89,57,56,8,138,102,140,86,159,219,77,239,32,203,126,142,214,192,72,16,119,161,71,155,250,58,115,189,112,51,213,249,25,85,78,170,171,102,164,103,133,109,37,229,130,167,116,64,21,234,76,246,89,206,141,235,89,223,141,56,47,168,166,97,190,26,197,70,97,133,200,148,53,45,183,39,129,38,122,174,116,58,75,115,221,204,101,52,24,94,177,14,237,2,172,234,210,8,208,25,77,235,113,24,108,216,242,184,180,255,173,101,240,51,246,200,240,13,156,209,93,60,66,170,252,82,230,13,215,146,117,255,210,7,34,122,10,106,156,176,21,68,222,248,33,83,152,206,191,60,18,158,149,114,74,41,60,203,244,210,249,189,212,25,25,75,131,95,76,207,254,188,23,124,249,162,255,170,137,0,81,97,181,221,127,2,120,240,234,80,28,115,105,158,136,89,77,135,103,255,251,8,186,242,63,176,164,122,8,11,128,19,58,243,8,212,252,204,84,170,108,158,179,247,0,254,32,87,139,213,136,45,180,92,145,67,92,246,247,205,97,103,87,101,163,137,0,61,23,230,147,218,153,102,235,104,17,24,246,70,190,79,179,238,178,41,56,128,115,241,148,114,229,173,144,63,54,151,123,191,45,145,222,89,230,29,59,34,163,123,120,56,34,137,149,161,32,221,255,87,39,50,57,112,84,159,209,51,170,143,167,190,117,145,202,12,127,248,132,142,52,118,154,247,22,242,179,161,240,146,155,7,176,79,18,1,228,242,227,81,34,121,92,236,105,176,207,233,51,86,159,119,70,173,14,42,103,31,241,149,157,98,49,61,96,106,94,142,12,146,88,63,16,173,84,14,216,170,188,7,119,188,94,156,24,78,218,117,39,252,216,201,136,241,118,24,231,164,15,9,211,193,68,14,9,140,214,99,95,235,172,219,136,83,12,95,75,88,48,152,236,153,95,137,236,38,125,35,176,220,87,52,101,106,40,172,224,140,105,118,201,227,143,43,59,162,152,247,197,72,70,232,183,21,160,2,64,169,41,69,166,102,52,189,217,130,19,196,230,34,133,35,31,17,193,45,252,112,79,79,223,99,168,154,14,19,74,179,41,246,27,199,128,101,54,80,252,173,165,241,80,26,204,142,255,57,94,25,56,246,22,133,229,144,110,212,118,251,36,49,81,254,183,116,222,99,70,181,22,74,96,199,161,124,176,7,199,9,56,128,64,200,185,222,37,225,144,156,152,22,99,76,208,43,99,207,169,146,220,182,136,30,96,166,118,49,125,40,132,106,49,212,158,91,55,84,208,213,75,63,190,113,71,83,98,109,21,176,11,204,253,157,79,106,111,232,239,253,187,98,141,32,52,39,209,183,100,176,183,32,232,137,209,189,13,67,230,44,99,233,235,31,211,62,149,120,185,114,79,123,8,153,151,112,255,65,154,228,16,226,177,21,18,10,146,172,134,181,123,4,253,122,188,229,98,89,112,147,19,145,108,246,176,210,201,128,231,96,230,39,140,7,175,246,144,253,114,34,223,14,48,134,160,78,112,135,138,197,142,208,213,221,156,197,198,131,42,169,203,191,140,36,205,131,59,11,239,147,205,235,193,132,59,199,198,42,204,244,120,24,172,221,253,85,141,118,110,76,153,91,146,222,142,200,251,52,172,145,250,47,123,86,49,253,220,27,77,170,51,36,179,148,26,32,251,162,197,246,163,248,65,123,233,68,194,166,153,206,118,238,22,134,49,13,218,176,11,183,124,197,148,169,251,224,80,11,209,166,233,229,19,220,114,244,144,246,17,131,119,108,78,6,26,238,121,82,13,57,179,139,149,164,255,235,181,20,240,76,155,71,61,89,192,100,16,244,93,71,199,139,70,203,107,44,233,154,66,40,255,1,15,20,206,89,244,23,68,123,164,177,175,187,170,150,195,150,44,96,99,142,169,220,220,197,235,124,72,198,60,112,180,196,35,190,154,107,29,177,10,243,111,210,61,157,156,223,255,101,5,210,27,224,15,23,138,119,65,201,139,134,84,70,122,22,204,153,5,193,108,54,149,173,173,37,200,81,229,93,72,7,45,14,51,177,85,166,96,189,55,43,70,88,172,251,17,221,163,81,62,196,216,14,31,82,46,38,65,125,42,32,4,9,145,100,31,102,106,231,86,31,167,246,39,11,28,118,34,92,179,80,65,191,115,43,247,211,118,115,124,156,122,145,222,177,73,161,7,117,51,20,29,178,100,26,127,202,208,177,209,121,101,140,194,20,229,139,123,55,186,209,31,33,39,115,64,97,128,152,60,147,70,35,97,4,156,87,181,58,244,132,109,115,229,91,215,10,28,25,21,57,163,234,21,101,81,18,220,78,130,105,85,41,164,78,228,156,201,182,234,93,221,241,194,212,66,84,4,11,81,116,94,234,37,200,8,214,228,253,58,205,250,62,168,189,1,46,223,0,158,154,29,127,247,188,25,193,165,228,117,234,121,149,167,254,11,3,15,12,91,42,46,11,240,230,134,120,108,46,58,63,23,230,140,113,173,206,94,55,63,20,187,32,255,142,32,192,135,161,231,95,115,204,50,125,129,245,15,153,89,124,35,87,200,91,78,68,126,100,158,103,224,232,192,132,174,34,19,19,48,139,182,247,255,70,88,227,139,253,31,10,222,62,188,140,85,169,143,143,14,29,108,159,46,98,211,30,129,63,149,77,230,246,61,181,103,153,124,242,214,63,70,78,193,78,208,159,94,20,59,30,81,88,112,124,123,183,101,239,217,86,232,137,59,250,5,110,107,71,27,31,15,33,62,200,161,218,153,82,134,5,7,141,180,7,152,169,23,182,33,150,252,223,90,209,54,177,15,50,19,8,253,37,226,84,143,33,164,230,38,215,102,42,156,198,36,35,149,175,75,79,102,252,69,215,7,165,103,252,189,221,18,204,32,86,110,22,47,74,38,247,11,126,5,145,242,247,20,9,190,177,121,79,16,110,73,41,45,141,3,247,35,3,252,191,45,7,156,127,115,198,74,194,5,25,124,110,61,109,115,151,84,72,182,140,170,23,217,123,133,98,143,18,53,128,55,78,61,89,152,214,253,63,133,196,183,215,107,107,158,245,129,15,153,169,246,158,65,172,8,47,226,30,126,10,64,163,175,108,218,130,19,89,235,34,206,150,176,199,6,140,234,201,165,130,107,208,64,112,36,44,115,250,199,236,204,60,127,43,124,225,163,49,76,103,210,254,126,180,82,44,230,68,93,12,246,201,186,72,190,172,76,128,42,173,0,221,120,14,150,19,197,121,163,71,111,214,183,143,24,187,70,13,255,228,250,134,173,209,183,166,208,21,225,94,109,145,98,70,255,76,151,190,150,183,152,248,238,224,187,111,4,2,111,236,73,135,133,67,34,193,94,52,159,42,187,59,38,75,152,72,134,112,236,191,233,150,43,156,14,167,70,226,7,114,200,31,140,164,33,84,232,169,15,96,172,175,192,57,229,71,227,101,139,17,90,45,154,32,255,204,159,141,200,159,147,45,152,135,128,51,11,78,181,154,83,92,144,157,134,244,234,140,201,95,218,104,165,146,35,28,223,139,111,128,149,30,162,119,191,217,136,196,219,138,212,22,168,182,19,118,34,168,68,234,104,231,59,166,128,52,254,212,215,218,117,66,31,249,88,61,78,33,130,242,94,66,17,169,102,100,130,251,1,125,169,71,110,165,239,246,162,251,220,185,184,20,76,133,171,122,57,219,218,181,169,220,38,166,27,206,53,166,180,135,172,64,7,187,131,182,110,67,34,191,25,145,197,184,217,30,140,72,15,212,194,123,34,239,194,64,110,117,35,199,82,17,157,252,230,226,228,44,151,158,81,101,191,59,18,175,143,139,235,12,185,50,15,106,29,143,82,247,211,52,208,35,153,64,11,50,37,13,38,232,128,45,104,62,240,201,122,137,83,140,250,178,64,142,202,168,54,119,221,215,71,166,35,108,71,223,239,99,153,12,8,134,64,200,182,235,107,96,111,231,153,200,254,189,247,49,93,127,4,200,77,43,160,120,224,252,243,224,46,190,166,143,82,46,207,86,235,116,203,190,88,18,55,121,70,227,215,107,69,58,245,221,133,33,73,230,34,36,254,49,127,129,180,253,175,209,180,54,94,124,96,104,97,243,225,38,248,166,230,189,233,78,38,61,122,43,51,76,9,219,127,1,239,79,151,48,213,26,208,118,80,108,178,180,167,38,224,5,87,106,12,73,252,109,195,190,244,1,237,106,212,236,116,74,192,255,121,219,152,67,18,77,38,21,51,27,121,200,196,0,84,219,179,46,124,54,85,12,179,49,241,46,197,14,33,28,79,227,246,94,112,66,187,209,230,116,161,40,15,78,57,156,110,138,178,73,41,255,178,62,43,236,180,171,248,21,243,240,13,110,71,67,79,176,57,76,207,194,20,219,223,36,60,83,50,200,87,245,137,235,132,89,144,67,4,174,55,221,14,212,138,175,187,209,186,54,80,178,238,243,36,9,199,108,128,111,120,61,208,105,53,44,233,236,78,63,226,71,197,238,242,101,100,227,70,160,209,41,198,56,65,115,138,237,132,126,95,23,46,122,98,177,164,159,251,98,212,145,111,203,95,36,21,53,163,88,57,51,139,255,60,181,38,187,107,75,128,165,215,232,130,56,103,173,192,192,119,72,104,142,246,79,232,200,17,207,225,61,55,106,74,61,126,180,229,233,187,223,190,82,11,232,15,84,52,13,98,154,199,134,191,227,132,219,235,17,230,249,92,249,34,165,54,132,101,234,209,220,66,6,69,181,50,132,160,155,246,171,5,167,56,49,27,175,90,222,36,13,217,116,128,9,151,3,203,43,43,40,205,132,14,248,28,88,180,107,146,95,19,175,0,109,41,170,148,148,54,179,0,71,101,59,99,221,143,205,42,59,156,112,136,31,59,18,231,136,191,41,46,122,77,101,152,172,123,108,116,111,53,229,4,163,218,156,39,171,198,100,223,236,90,205,126,143,72,67,138,159,241,118,154,239,154,219,34,182,123,33,163,113,46,15,249,238,36,50,215,132,241,226,207,196,181,96,162,212,88,224,190,81,179,12,136,146,122,238,83,129,26,72,105,125,20,146,253,67,112,232,12,188,96,52,161,160,121,241,50,77,49,218,20,78,169,246,196,95,213,12,11,243,170,71,1,244,78,233,115,143,34,201,250,23,100,9,97,17,4,211,193,128,42,106,170,138,9,75,28,208,247,157,32,4,210,106,87,15,97,167,209,22,160,123,52,183,148,194,21,14,53,212,119,43,76,147,154,56,43,175,79,109,103,68,93,115,95,230,242,89,230,162,136,47,37,79,109,220,24,217,83,40,241,45,113,250,138,133,115,120,72,115,222,65,36,226,44,1,172,128,192,152,113,44,162,139,24,194,114,139,90,162,31,228,198,129,96,97,224,87,232,183,43,193,104,251,129,67,148,240,227,100,4,27,202,89,241,226,221,189,142,102,74,1,234,197,88,247,95,217,142,161,58,118,124,174,252,162,242,248,126,19,199,138,191,202,209,59,204,127,100,65,187,50,108,197,107,107,205,55,228,48,246,168,68,28,74,186,102,54,116,29,188,57,221,206,122,202,240,151,15,23,162,146,91,12,88,51,69,3,110,205,52,5,186,49,46,171,126,221,23,30,236,45,162,17,198,211,238,177,147,106,5,203,206,78,143,1,167,153,96,15,225,28,219,223,209,68,221,218,102,32,19,138,90,130,254,63,73,240,165,99,150,83,198,65,210,22,92,216,204,186,182,213,249,35,2,80,190,138,101,47,225,210,232,29,85,90,174,228,82,244,173,189,193,47,20,238,93,189,172,27,25,87,244,243,224,87,201,186,153,42,69,160,195,77,180,136,128,231,197,161,163,94,0,191,87,57,125,254,155,170,223,110,165,95,181,188,82,153,240,68,118,58,137,253,184,248,35,170,207,20,197,246,93,21,36,48,195,147,75,92,94,166,34,77,198,225,189,122,91,111,136,32,138,146,132,33,113,35,32,184,97,10,255,132,98,61,203,100,65,30,160,150,30,85,22,8,32,101,187,142,240,176,3,67,219,207,113,202,242,213,177,61,155,141,225,69,7,10,3,184,65,132,69,241,149,214,97,91,168,150,187,136,18,190,15,66,134,232,239,202,169,247,10,160,246,157,238,77,41,185,221,165,157,108,94,145,231,229,169,101,1,167,15,161,20,158,211,139,204,107,228,206,211,185,65,246,158,167,12,107,190,45,182,28,192,44,106,148,62,159,222,82,10,227,237,251,3,151,152,139,76,162,183,169,202,107,181,200,129,195,124,71,208,135,234,26,203,154,53,208,137,99,150,100,142,114,50,153,183,126,133,1,253,9,202,235,65,46,106,126,8,5,105,93,53,17,35,209,62,117,114,152,57,29,66,71,127,2,130,103,158,7,17,86,195,64,229,219,75,195,212,33,209,50,154,59,27,177,135,24,163,107,219,137,197,220,7,153,96,131,0,65,187,83,25,18,15,100,245,27,6,174,119,25,182,124,115,158,7,84,182,105,34,75,231,222,190,48,233,221,49,119,79,153,174,200,28,223,87,37,72,254,237,189,199,23,239,255,69,27,152,251,104,233,142,231,80,48,149,197,234,170,200,149,73,120,9,20,212,128,69,99,144,23,22,83,89,207,47,19,17,198,156,214,226,55,130,85,146,54,5,58,224,214,6,27,36,31,164,126,182,225,53,4,52,100,11,28,220,125,41,101,102,215,188,97,6,55,113,252,140,78,81,115,58,203,129,115,132,109,206,21,68,78,20,128,95,62,34,72,211,75,41,78,234,223,115,175,57,229,107,227,179,9,162,15,86,211,207,126,44,120,162,65,99,15,187,57,91,18,41,138,119,15,37,90,138,187,40,13,121,164,30,26,160,7,116,143,9,149,10,228,215,85,75,134,113,241,72,248,12,116,160,177,187,166,188,208,252,178,182,169,220,121,139,203,135,116,198,224,193,215,214,189,110,168,68,129,130,192,8,226,15,122,181,16,37,227,17,156,38,246,249,4,89,193,12,237,32,109,66,52,139,50,235,10,231,210,19,204,191,161,192,238,27,142,203,62,146,194,119,135,132,70,245,214,127,209,179,254,19,43,72,110,124,118,71,34,142,134,163,182,130,140,131,160,56,194,13,10,6,8,136,131,171,206,237,108,163,127,8,17,208,116,17,165,125,236,166,45,180,115,123,110,117,255,84,33,201,176,66,60,220,2,92,128,59,50,147,27,232,7,251,48,118,128,215,225,182,113,163,1,165,184,212,132,246,28,57,13,84,140,97,222,230,172,120,254,160,216,70,239,215,0,111,160,68,51,0,31,109,79,49,38,221,94,95,37,226,200,239,75,160,227,1,122,27,49,244,122,133,67,125,60,12,216,60,89,219,92,146,252,169,205,31,71,112,119,174,142,76,205,10,173,28,31,26,119,222,159,151,151,214,150,124,197,51,174,17,3,58,240,120,130,175,51,87,155,106,76,197,143,86,226,95,45,72,196,34,230,99,248,121,236,163,207,67,132,152,165,42,252,107,111,171,10,114,221,71,94,190,87,197,251,236,116,86,60,82,253,64,166,236,178,150,126,252,230,179,186,45,52,123,29,16,175,237,157,13,213,215,69,153,217,233,51,38,227,186,80,200,188,65,110,196,78,3,202,66,175,161,253,111,249,120,23,44,176,170,211,138,243,128,128,115,108,85,27,23,107,91,1,212,31,154,136,228,166,30,96,59,92,34,162,61,242,225,232,47,195,154,45,144,74,125,246,69,128,166,229,187,39,196,152,5,66,133,189,18,245,235,31,214,153,14,205,11,130,1,238,167,83,107,14,41,235,8,139,62,37,74,87,110,189,142,226,150,1,219,52,58,115,150,62,55,66,239,30,11,157,138,57,159,200,148,184,237,250,169,248,88,159,137,188,98,30,50,189,59,15,225,149,129,184,102,146,114,254,181,178,143,54,171,186,63,219,29,83,52,76,222,208,189,242,11,81,188,87,249,54,213,162,246,147,7,72,54,22,48,119,146,108,131,16,194,137,175,45,132,109,33,243,243,40,190,135,54,116,177,29,228,193,151,91,207,114,183,37,198,58,44,53,196,42,118,27,144,95,155,137,80,255,233,76,228,204,81,135,24,99,82,230,130,134,134,90,185,64,21,78,113,200,124,44,66,8,202,250,219,158,245,90,117,100,130,99,79,193,113,76,66,140,147,91,76,194,35,42,183,235,58,162,251,48,190,103,86,96,173,72,202,179,222,118,203,182,225,42,46,211,245,250,204,238,192,46,2,210,178,141,212,84,160,233,228,60,100,58,151,244,252,138,108,189,119,187,104,222,9,36,11,182,33,204,41,164,233,176,152,233,86,233,50,206,99,64,128,110,66,233,201,123,179,225,189,88,55,210,152,178,238,149,204,213,200,212,190,228,170,205,255,165,46,209,51,91,74,229,36,181,120,52,6,82,169,229,225,218,231,110,222,218,6,179,193,106,30,34,243,244,157,149,112,198,254,119,89,250,217,97,62,28,209,188,203,80,211,129,242,222,66,129,254,133,112,29,113,174,62,6,239,237,224,23,116,214,189,215,75,239,171,17,204,68,178,19,31,37,201,108,153,71,126,166,217,28,201,87,186,193,62,200,110,44,41,74,172,66,60,174,120,134,18,85,137,113,240,138,170,198,225,97,115,26,202,243,51,96,31,18,185,179,52,52,98,63,170,11,216,247,18,9,35,203,107,220,12,6,21,178,236,232,102,112,57,211,73,9,28,24,100,146,157,25,199,182,169,71,71,6,60,175,82,210,8,190,110,18,136,70,15,43,13,60,52,12,43,123,111,248,2,36,45,160,215,73,52,54,36,80,105,210,238,113,115,116,84,251,91,72,109,192,195,188,108,51,89,2,189,86,142,28,210,69,246,138,253,85,224,49,223,6,47,125,40,72,173,56,214,70,132,134,51,244,168,101,112,151,126,77,102,143,239,4,13,116,106,10,103,119,126,65,6,31,18,107,68,76,241,127,130,133,186,61,250,68,253,189,150,134,117,83,51,83,25,187,118,78,134,35,123,184,148,245,53,68,14,88,131,0,68,159,141,48,76,196,130,198,34,56,19,203,64,75,87,26,133,28,73,19,242,167,183,2,251,172,114,9,7,155,151,79,86,68,141,54,101,212,74,210,65,219,237,175,83,252,71,245,207,108,46,196,105,180,46,85,217,5,128,221,226,157,62,176,224,25,140,26,228,142,51,187,96,116,42,92,18,197,211,133,4,0,207,161,141,187,60,8,215,220,174,187,41,153,27,83,242,133,205,30,135,7,207,178,168,111,3,85,173,149,137,68,187,204,184,237,209,59,41,154,36,35,7,212,199,183,241,25,178,86,195,41,137,201,81,164,246,218,251,180,218,161,189,193,147,17,147,15,78,69,23,170,86,93,28,58,170,81,208,143,20,240,63,182,158,203,197,94,135,254,11,135,124,183,89,193,71,88,184,98,208,164,134,197,140,75,234,159,83,20,177,109,123,195,118,229,245,116,207,220,6,11,187,253,37,198,220,195,29,176,38,46,67,200,232,90,245,23,105,165,133,57,29,208,185,232,69,180,3,5,19,111,91,226,98,197,90,102,20,243,203,137,88,156,217,18,24,141,253,17,194,150,75,120,212,232,5,187,191,80,176,71,27,94,71,149,230,108,103,17,129,248,166,186,196,171,152,249,136,146,130,38,204,223,106,175,46,105,241,113,125,212,159,243,233,110,229,177,187,141,186,157,99,212,232,218,25,58,4,212,122,110,11,236,187,184,12,168,127,135,212,37,81,184,79,102,171,143,151,189,158,113,56,80,94,110,58,223,118,37,73,53,158,134,151,251,250,216,143,88,233,8,206,211,238,115,195,53,186,238,140,128,150,50,225,14,236,49,195,224,75,85,229,24,20,244,72,136,144,15,96,152,6,156,158,133,144,200,229,50,186,234,205,77,101,31,5,147,136,55,31,158,100,141,179,213,225,15,161,176,225,156,40,169,60,57,227,45,170,44,97,107,83,178,31,102,192,84,212,43,159,32,188,252,47,248,53,6,68,8,126,187,27,46,133,214,4,199,153,29,177,123,35,170,100,66,253,178,46,37,206,97,62,17,208,98,178,195,223,64,76,251,94,132,241,102,36,130,182,53,98,94,253,122,211,197,204,144,195,101,203,40,158,215,192,102,44,87,233,61,81,147,158,79,117,222,27,26,219,168,15,59,142,65,113,172,49,253,190,191,188,12,59,244,226,238,7,59,116,34,120,56,20,118,83,59,78,142,79,43,150,41,207,228,35,234,182,14,86,50,120,254,31,74,82,5,29,39,173,104,87,10,249,237,158,29,211,250,239,50,64,90,200,107,209,100,26,135,182,38,139,177,27,64,6,87,21,235,204,230,235,222,248,48,156,212,204,138,22,36,123,3,40,93,25,200,55,162,51,116,3,140,58,246,81,78,59,89,103,138,23,220,89,171,48,48,203,181,80,163,171,109,173,17,34,188,238,42,205,32,106,18,122,80,8,247,127,26,32,148,141,138,226,57,27,129,234,74,40,235,202,6,106,127,1,11,117,117,236,240,123,227,139,185,241,205,42,57,186,237,83,21,90,3,25,88,42,109,224,140,238,11,177,108,46,111,28,229,139,95,217,72,101,173,235,131,28,2,85,51,19,52,105,218,235,176,84,57,140,165,80,238,93,92,6,47,138,188,132,100,36,219,223,236,201,112,201,190,0,20,146,68,95,16,147,1,52,108,54,185,188,154,104,247,173,127,160,214,230,207,56,112,98,105,62,42,66,97,101,47,220,193,114,23,202,61,21,118,64,16,191,112,119,123,20,117,173,202,70,39,239,112,202,66,142,163,211,106,89,2,97,150,55,78,226,111,190,170,144,53,195,72,96,89,229,178,153,130,164,161,86,154,154,21,95,120,12,31,122,50,142,245,189,124,17,218,35,201,75,20,203,234,97,11,70,151,3,185,169,71,243,91,56,248,117,103,8,162,90,14,193,33,124,194,169,48,150,40,80,127,37,151,74,195,221,99,145,74,172,228,150,120,147,204,160,67,110,187,30,236,197,101,7,127,128,115,7,243,235,20,66,101,40,114,136,254,206,220,67,96,231,89,65,202,234,82,8,131,187,238,220,213,142,223,77,25,167,69,68,87,110,101,200,142,51,26,234,143,164,214,134,215,222,141,23,42,75,147,88,211,199,154,201,24,72,202,13,136,234,25,52,120,254,136,185,193,163,187,133,84,93,81,133,177,73,126,136,46,251,136,144,180,33,34,18,230,128,47,79,79,106,150,8,58,160,248,106,132,183,215,17,146,173,177,243,32,65,1,175,14,45,235,55,127,69,29,175,177,184,199,168,231,173,143,212,218,44,28,243,157,87,243,247,193,142,155,49,191,221,140,235,246,53,125,204,139,60,232,18,220,63,106,61,252,172,154,140,47,208,189,55,163,20,44,108,250,50,252,255,204,45,52,2,76,66,64,241,107,21,163,134,187,242,247,136,203,1,7,118,226,244,67,198,15,238,194,74,9,230,186,185,49,162,49,71,168,31,130,160,103,223,244,225,108,133,142,123,181,164,114,112,172,100,229,165,150,250,57,212,15,63,204,70,163,4,98,111,152,45,37,45,245,228,45,244,111,124,250,163,197,120,243,232,117,56,154,191,145,196,141,125,8,55,90,132,216,85,224,174,60,253,201,63,198,114,202,235,236,103,174,176,192,65,93,161,74,226,65,222,241,126,119,113,174,16,71,68,19,253,160,250,79,117,231,129,159,61,132,104,164,251,78,110,48,246,12,36,172,100,111,152,87,36,40,95,115,60,227,74,123,204,149,244,119,65,162,114,102,121,19,155,249,117,248,51,151,33,42,115,199,237,144,43,180,51,121,129,23,83,127,226,56,9,32,222,44,201,44,21,7,249,122,183,224,239,85,204,10,181,91,19,103,103,133,205,12,229,38,97,31,108,141,82,255,186,32,185,59,95,66,45,15,41,179,36,56,178,53,39,230,128,252,12,104,165,98,132,4,223,238,44,36,222,188,218,52,250,146,212,148,237,85,68,175,72,79,155,38,36,230,62,122,67,208,138,241,5,49,158,119,106,100,178,247,61,154,161,134,111,198,28,192,44,150,189,7,205,154,142,45,190,172,69,107,176,36,105,64,30,153,120,233,138,210,10,19,201,37,119,182,152,85,43,37,56,68,199,14,82,214,220,245,249,231,141,77,20,190,252,61,102,166,209,230,24,109,225,229,78,195,145,93,109,32,127,163,49,126,248,87,165,80,47,35,155,3,51,50,146,244,105,171,122,226,62,82,242,157,209,37,222,157,224,156,21,73,10,238,198,123,110,60,209,122,158,82,5,221,166,227,119,183,251,80,175,245,112,156,150,175,183,247,162,53,159,213,33,71,40,168,227,104,244,244,210,154,12,114,234,6,153,36,147,203,170,108,85,64,250,110,225,137,2,143,243,163,40,173,220,191,63,210,108,131,154,142,83,175,46,56,41,236,83,221,81,161,144,135,172,99,88,139,115,229,148,143,162,9,203,12,44,238,102,165,234,230,179,179,242,16,227,158,20,196,203,126,102,121,194,246,105,131,73,192,81,122,192,229,32,52,68,139,60,16,102,94,4,190,236,77,238,222,73,240,221,6,252,179,240,56,85,108,237,167,95,168,223,161,49,28,186,57,93,43,203,125,223,42,221,67,47,174,96,56,99,204,115,41,252,252,106,153,180,228,242,100,155,42,105,108,181,215,47,150,176,81,36,192,211,244,135,162,127,189,201,80,62,117,91,125,58,245,215,9,16,165,134,52,42,43,225,155,28,21,189,76,85,226,216,155,133,105,120,60,145,152,6,52,150,149,2,255,255,126,255,45,36,58,37,21,112,25,5,210,187,69,74,195,46,226,170,12,90,154,7,142,228,89,148,22,211,1,150,132,252,99,19,215,135,242,15,150,0,17,251,192,38,133,71,164,62,161,144,240,178,62,63,254,50,137,26,207,233,156,52,145,94,86,239,132,26,146,181,46,165,248,100,14,76,252,16,214,130,195,166,67,120,113,30,255,126,197,11,57,108,130,66,163,177,70,30,223,117,244,53,44,13,86,39,70,58,213,212,230,152,164,76,152,10,227,3,6,230,216,73,88,108,91,245,126,137,58,224,132,168,129,199,254,247,134,142,56,81,168,160,119,44,222,123,230,189,204,92,245,18,227,172,58,240,174,149,68,71,210,183,169,241,146,73,86,210,216,156,250,239,161,219,212,210,69,48,33,137,81,185,192,218,197,2,122,26,76,13,121,61,31,44,239,37,158,126,254,241,131,26,167,224,67,133,125,52,204,195,141,119,131,208,214,151,86,54,137,139,144,178,173,220,170,156,70,125,66,38,125,127,135,146,246,160,95,230,1,248,184,55,65,56,225,139,169,106,17,246,153,98,119,248,67,85,148,28,157,200,233,186,149,138,180,147,37,42,212,190,28,189,109,117,242,168,56,133,17,29,241,89,218,5,242,81,50,61,166,175,124,106,47,237,20,201,235,69,95,202,35,243,79,223,34,85,47,100,252,168,29,171,20,189,109,65,14,156,71,195,246,94,104,211,21,29,195,84,33,131,207,221,120,139,57,78,126,88,195,191,172,133,96,242,110,140,236,227,76,154,55,32,134,193,20,204,21,192,232,157,224,147,175,193,96,9,127,18,107,239,96,240,98,139,149,104,92,151,196,170,198,104,185,117,179,26,20,72,48,36,47,32,86,42,189,173,80,71,219,151,79,181,88,45,26,191,38,133,45,54,131,31,109,115,161,163,34,38,89,40,49,173,198,48,17,40,39,121,77,90,70,42,251,130,168,125,184,76,60,95,94,136,227,248,145,210,226,191,137,247,72,210,17,141,52,5,102,220,23,111,146,114,218,208,22,105,9,130,97,83,57,25,228,137,6,99,12,24,29,89,25,101,217,133,196,253,246,158,114,75,8,90,142,28,147,19,22,164,240,205,1,21,145,19,225,61,98,21,22,215,32,158,9,44,97,148,104,201,219,76,43,45,162,73,151,252,188,155,192,134,113,103,109,255,54,42,206,24,76,87,154,98,187,78,193,50,86,191,222,86,162,165,38,191,118,117,72,31,6,174,147,231,105,158,70,133,79,138,223,55,73,210,90,194,194,112,167,14,253,133,160,197,234,193,24,75,239,106,47,115,70,102,75,122,123,87,158,185,162,180,84,210,222,141,172,125,211,117,181,155,250,182,51,247,178,100,123,8,8,173,224,246,222,40,35,31,171,203,195,36,34,6,53,171,105,219,106,216,77,18,130,182,37,225,3,235,196,203,114,168,7,2,10,14,230,118,6,134,118,20,184,145,213,218,127,110,182,193,145,91,202,110,11,96,118,1,8,96,103,167,236,180,15,141,151,253,100,7,112,25,70,89,121,233,178,158,234,47,68,162,185,146,146,7,74,2,17,238,108,171,91,64,92,173,85,82,121,240,175,136,132,26,123,225,64,169,132,53,192,187,113,8,165,133,192,249,61,166,108,170,2,175,11,243,183,162,93,109,51,151,40,206,39,150,0,84,130,215,29,211,96,200,244,193,206,63,137,9,225,205,195,93,147,70,125,177,146,164,76,247,0,61,118,12,73,75,151,145,218,82,180,207,112,233,175,169,104,180,29,149,4,129,248,70,10,159,34,67,208,4,235,146,205,128,223,104,17,16,189,72,150,29,148,21,85,152,237,97,200,84,57,234,9,165,16,73,40,118,10,18,222,171,43,231,169,211,149,179,250,145,227,129,66,53,2,35,228,99,7,1,101,161,122,247,98,103,47,32,194,21,66,228,215,171,211,95,93,47,71,164,197,154,72,46,73,190,186,131,152,104,252,1,237,94,154,240,6,67,188,57,183,3,28,30,181,14,142,247,193,242,88,231,188,86,198,130,125,97,9,115,137,196,6,38,94,170,51,157,253,197,152,195,181,150,253,125,49,6,217,29,102,120,252,248,217,191,232,176,151,7,118,12,126,164,219,67,123,72,16,146,223,203,183,0,196,87,186,185,173,67,246,204,171,20,21,86,98,182,253,7,186,6,120,189,118,3,229,237,60,53,90,120,139,87,229,79,153,85,139,16,81,100,189,150,202,125,164,42,132,10,163,190,85,177,69,169,181,85,186,64,77,182,99,209,185,183,19,5,1,24,167,247,211,71,7,154,124,136,40,199,61,196,217,202,170,170,93,64,20,178,234,247,41,59,124,192,158,211,128,28,144,37,95,61,108,113,150,27,161,102,97,250,86,162,10,193,27,201,55,193,56,84,164,176,59,172,180,2,117,209,83,226,255,156,104,115,80,9,171,177,196,38,252,19,138,252,29,242,231,74,93,205,161,41,158,79,204,211,0,30,248,42,125,237,167,151,3,163,35,219,102,225,38,80,160,246,91,202,15,81,5,104,108,210,239,193,131,146,27,150,17,171,71,221,84,112,204,146,94,186,237,255,206,118,141,107,20,169,226,15,43,75,224,52,120,186,0,134,235,166,30,237,98,31,139,146,29,104,64,56,3,249,66,92,147,217,211,9,31,96,178,69,148,227,230,101,236,243,45,246,172,39,229,59,69,106,63,147,212,148,179,217,10,220,19,61,36,147,54,173,248,250,238,79,181,163,211,105,11,79,136,249,56,91,202,219,147,180,212,42,140,52,110,222,216,92,215,61,213,55,188,33,239,190,201,255,96,1,215,85,244,86,49,152,17,180,172,68,196,115,71,107,182,243,219,136,48,23,116,210,242,8,233,123,235,101,169,61,55,63,1,51,205,161,189,96,59,52,218,197,250,26,88,73,52,217,104,199,216,234,189,209,12,232,29,210,128,20,244,127,219,15,204,123,222,84,167,249,54,43,174,28,118,186,210,116,176,58,78,38,166,130,144,219,92,43,91,180,1,195,20,39,139,0,25,240,204,75,61,178,95,199,10,3,136,139,50,249,155,86,95,70,214,41,166,76,132,6,166,146,35,118,145,100,203,149,154,211,215,94,104,5,44,83,183,45,251,89,212,57,197,144,82,87,170,120,45,105,80,129,100,131,159,10,127,221,163,246,63,192,154,53,205,6,127,117,223,24,147,216,93,28,239,163,214,221,158,12,149,255,83,88,41,136,165,138,1,254,6,44,25,143,22,104,150,94,24,196,25,238,193,216,170,71,103,76,33,52,211,45,205,235,134,41,248,86,65,9,32,255,32,95,30,250,243,251,43,119,170,184,85,107,38,21,98,231,54,218,226,16,72,174,6,221,38,211,120,221,119,117,120,67,209,251,33,84,155,163,163,47,53,96,15,51,76,204,87,153,85,170,54,66,113,12,174,34,104,136,90,62,76,103,210,150,82,37,200,148,44,89,113,229,33,173,240,114,61,21,131,193,157,216,181,193,207,219,29,42,99,21,186,158,11,145,155,4,216,22,244,162,245,120,63,128,57,117,241,213,60,251,251,149,87,153,99,63,22,75,81,103,103,239,199,225,110,110,88,38,125,240,116,161,226,53,38,183,2,223,68,221,87,205,73,201,187,129,82,39,35,166,109,116,96,250,15,15,242,104,227,86,21,140,48,172,188,54,214,185,33,4,199,217,220,218,185,44,244,170,133,64,135,231,135,80,159,130,65,112,36,250,209,241,226,74,174,130,199,202,217,218,87,161,162,130,254,242,150,34,63,117,178,224,76,211,80,201,111,72,69,137,93,62,24,23,249,115,80,83,95,17,166,84,223,132,120,6,53,34,199,208,205,80,109,133,213,92,49,18,214,230,123,245,73,80,228,94,106,241,165,216,84,255,96,177,178,90,92,5,219,185,153,238,208,136,79,150,15,232,139,179,52,146,235,158,62,239,136,154,45,92,190,176,19,91,40,214,152,149,209,222,247,97,175,74,250,98,231,204,211,233,2,168,136,18,202,254,144,196,95,80,187,220,123,31,164,176,207,23,248,81,3,174,138,206,65,83,36,29,70,32,71,21,227,157,254,228,2,4,215,71,27,252,9,219,49,49,23,248,163,43,170,192,126,75,198,97,91,38,182,93,204,141,250,187,145,128,158,103,88,73,178,191,233,253,231,3,169,38,117,163,181,44,217,91,138,15,239,82,140,19,78,13,168,212,227,46,202,225,130,28,150,211,105,239,25,243,208,76,174,52,37,170,87,125,141,221,90,95,41,51,53,205,112,75,54,129,102,51,87,222,28,117,188,154,174,103,66,55,95,247,97,127,31,107,22,117,195,115,97,108,19,52,70,179,212,190,15,8,213,49,139,119,170,201,169,8,199,203,166,183,90,134,185,169,133,135,9,251,66,104,187,220,182,164,82,21,125,132,197,116,14,169,241,211,104,107,169,17,246,140,46,235,236,23,84,93,180,72,214,10,39,185,197,170,73,30,43,35,75,114,202,126,143,2,127,114,206,107,25,116,183,11,43,3,146,183,121,214,79,26,240,70,203,45,88,74,11,137,245,21,38,44,66,143,61,168,69,76,204,92,186,121,203,15,46,213,237,131,23,220,68,52,188,111,185,48,81,35,208,159,218,44,76,71,236,152,61,103,92,247,136,123,88,196,109,213,91,97,190,88,164,237,171,59,217,231,230,51,149,191,114,162,41,91,249,249,25,109,183,231,25,48,30,35,44,156,199,26,146,144,26,85,40,82,54,83,253,102,88,29,52,114,160,176,0,95,4,217,205,123,143,97,62,149,15,178,195,166,156,183,183,170,183,54,232,197,211,241,7,215,241,86,159,151,161,98,116,91,139,14,111,22,41,155,5,43,72,245,246,20,196,27,62,112,149,21,253,42,111,173,148,25,42,199,41,53,84,169,17,246,92,25,211,161,41,159,252,62,243,4,19,121,43,66,199,74,28,208,193,205,33,126,84,173,30,16,26,179,244,95,188,90,6,16,178,251,191,203,121,130,161,12,52,170,24,14,141,2,163,190,6,52,205,187,57,245,252,9,53,65,132,246,126,90,3,26,54,238,222,74,237,35,163,214,83,43,254,139,112,244,74,15,241,20,255,217,117,129,81,233,181,187,160,29,30,245,145,199,163,29,171,87,228,222,50,229,60,139,23,152,179,33,23,124,180,100,223,209,21,191,93,240,166,209,66,67,28,158,237,190,62,80,188,131,151,72,22,159,212,121,139,49,254,184,106,134,122,77,103,165,81,70,69,174,0,7,179,26,152,234,23,37,155,212,120,59,223,226,216,189,170,9,42,206,10,123,140,130,214,229,149,218,74,215,152,151,235,170,53,33,209,190,193,105,61,182,108,226,176,32,213,78,117,106,23,56,121,61,82,213,107,121,107,114,185,20,99,151,57,44,105,153,238,174,24,192,241,254,251,80,193,143,221,0,58,227,109,190,129,185,22,131,37,221,129,34,101,144,152,33,250,198,183,73,236,69,174,215,68,64,181,94,33,132,40,149,248,252,133,191,99,245,130,21,43,49,211,224,204,33,169,240,230,120,107,228,46,140,168,241,32,17,95,48,147,101,16,176,251,83,160,253,105,171,56,79,198,139,36,48,144,120,99,236,171,235,56,117,196,171,178,244,170,61,79,183,32,202,66,50,130,211,99,78,199,73,255,242,30,138,199,156,129,107,187,182,255,144,201,230,138,199,111,154,10,126,232,144,99,117,187,160,97,221,177,191,5,239,139,181,240,32,249,247,61,216,207,154,217,224,246,49,118,3,194,107,197,233,3,242,99,182,58,45,151,176,238,101,118,57,44,123,195,112,61,129,140,199,98,25,86,104,2,141,220,161,128,109,32,8,89,147,249,11,246,14,255,195,81,233,46,89,37,122,225,211,69,132,120,138,169,254,0,72,208,116,247,244,60,55,28,135,15,11,28,174,65,40,253,148,181,6,57,220,134,224,205,255,225,22,228,49,200,228,182,179,141,237,217,9,47,114,203,57,24,173,236,15,100,174,120,178,73,84,236,141,45,188,142,252,66,85,56,248,161,247,21,240,209,145,198,24,158,227,106,158,18,248,204,21,1,99,35,91,187,157,228,98,106,35,231,158,103,53,119,135,62,168,207,48,5,118,236,117,255,204,65,60,49,102,180,55,82,149,17,205,214,182,198,223,77,55,234,99,156,29,161,90,22,138,7,126,240,213,226,110,63,214,97,71,161,203,216,10,31,25,62,71,223,163,238,97,14,115,144,121,112,103,4,186,16,66,51,105,110,65,111,32,206,82,213,231,74,107,199,255,85,48,249,19,123,45,142,3,104,77,86,181,99,8,158,50,3,108,43,23,113,246,189,180,107,134,24,9,137,36,178,9,176,197,63,33,63,164,220,217,243,175,16,197,210,28,16,109,192,143,193,240,252,44,124,8,108,179,168,171,135,107,32,216,49,136,123,109,133,33,176,167,185,189,30,120,210,5,211,14,127,118,199,147,121,246,58,33,239,172,251,87,223,152,144,13,169,216,65,87,59,132,210,118,116,30,68,72,68,155,103,230,81,33,26,21,82,14,73,251,183,147,86,222,194,97,44,169,244,82,155,95,253,205,116,91,165,44,64,31,163,242,253,93,23,26,209,14,33,97,62,148,115,63,247,111,137,13,9,163,215,243,223,218,10,114,82,195,219,233,24,117,167,173,231,13,156,77,46,231,130,200,122,169,91,49,229,215,250,140,73,229,240,44,212,41,117,112,31,126,218,196,58,241,101,147,26,195,148,98,153,198,104,87,90,149,128,60,239,177,50,49,11,242,239,230,196,182,89,101,80,215,168,143,70,48,53,53,215,22,99,194,129,245,128,163,40,102,25,14,99,189,152,35,135,13,16,105,137,188,32,226,246,176,38,30,36,65,146,145,240,83,103,2,107,133,21,172,41,239,28,250,134,170,228,80,43,122,211,87,111,228,168,29,171,79,69,62,152,18,69,203,96,169,144,83,50,37,65,208,1,113,46,2,67,73,221,2,181,73,185,209,20,163,237,141,222,221,69,220,155,12,177,239,150,84,234,58,111,225,3,31,187,110,139,78,139,234,186,202,73,72,34,125,59,43,206,220,68,6,49,123,14,147,144,206,60,95,31,173,236,244,239,64,11,119,89,226,7,117,175,218,115,104,165,195,209,202,140,132,15,6,115,213,209,69,238,7,89,37,249,156,158,67,124,208,100,194,232,148,52,214,125,166,99,224,152,46,109,187,234,230,51,60,189,191,120,28,13,67,152,105,230,40,147,153,215,16,149,231,51,170,159,88,97,228,216,161,34,87,65,129,153,213,186,140,150,104,113,164,25,120,246,58,78,221,124,33,179,135,7,220,233,68,9,15,123,101,187,131,139,95,177,234,29,215,24,57,107,53,194,252,161,247,70,224,245,22,104,10,41,39,213,190,186,249,159,32,28,196,55,153,225,205,18,72,227,70,120,101,199,237,132,225,10,124,88,154,151,215,153,67,177,100,244,99,169,37,127,97,122,188,216,217,79,187,227,87,69,243,42,139,151,228,79,141,154,88,240,7,29,255,165,129,150,70,173,212,207,194,245,243,54,210,111,168,77,71,140,61,28,64,106,8,196,60,68,154,18,110,22,252,63,172,163,34,138,138,105,145,101,244,110,11,75,95,244,220,224,140,191,243,85,79,137,128,246,173,146,28,1,68,146,131,190,104,107,105,10,183,141,149,204,59,176,190,91,3,180,254,33,47,24,58,4,53,177,211,193,103,6,161,57,156,191,177,108,76,83,185,133,20,167,103,26,75,148,54,239,124,182,71,95,160,157,60,112,22,149,136,53,82,150,241,250,192,35,199,124,207,79,66,84,131,7,63,140,114,16,166,158,30,0,73,131,202,144,116,46,50,92,60,23,147,147,14,236,195,64,128,205,63,248,146,1,49,182,30,96,166,149,196,243,131,88,93,119,167,118,22,137,56,179,169,223,194,48,235,4,196,19,7,210,55,75,235,92,247,15,83,174,53,132,172,34,214,91,205,147,70,34,195,103,132,175,68,245,7,227,205,122,160,7,72,137,123,51,243,8,7,82,113,179,53,171,249,151,156,75,82,204,101,194,53,247,2,201,39,125,151,8,4,189,190,40,95,41,72,181,116,99,58,100,136,118,164,13,191,107,164,69,39,229,204,2,248,254,87,112,64,247,106,105,66,193,73,104,67,75,181,248,105,39,227,153,139,164,41,215,76,244,118,95,99,56,13,94,20,67,33,205,238,108,249,81,105,60,177,18,155,229,73,173,205,78,164,144,180,161,191,210,203,150,190,16,55,228,110,203,212,118,15,103,25,67,152,199,2,36,17,117,201,129,88,197,112,153,188,44,58,196,160,131,198,150,19,223,209,224,90,127,231,71,1,40,82,195,12,242,223,233,211,68,210,32,176,1,106,119,179,211,33,221,107,210,194,227,213,88,3,122,19,130,145,199,16,66,179,41,215,40,18,133,40,191,25,49,31,101,27,16,11,60,119,20,186,217,168,204,250,28,173,159,38,166,106,2,35,49,133,30,16,174,41,134,5,154,247,72,247,171,23,225,89,228,141,14,221,122,56,188,54,252,90,121,252,169,8,168,27,59,138,8,245,70,122,230,65,165,140,117,136,206,11,169,209,146,240,8,234,87,27,21,119,136,227,84,138,65,172,42,227,109,202,167,67,219,148,125,32,179,242,176,224,42,235,163,145,195,63,145,122,135,21,164,85,133,249,38,87,145,90,3,151,203,189,99,172,189,248,86,207,193,226,138,44,42,179,190,99,83,127,92,185,32,159,58,246,239,241,246,235,227,205,219,169,42,77,149,0,212,210,172,47,174,68,122,133,7,78,152,86,30,65,58,84,65,40,113,125,213,150,112,146,1,46,218,175,242,206,243,3,22,233,246,135,129,96,57,130,15,151,104,91,220,169,42,107,34,44,14,229,23,97,55,219,134,96,213,252,133,227,120,195,1,46,17,86,212,120,130,91,248,166,233,51,66,254,106,183,117,42,44,36,169,196,204,173,91,96,109,228,171,28,189,45,250,183,121,167,12,164,164,245,225,177,164,170,138,139,161,93,90,83,85,26,198,104,106,203,108,131,144,196,153,22,188,229,99,101,228,68,84,115,35,112,19,129,18,184,189,228,220,191,206,106,106,126,188,176,42,150,208,166,249,215,76,49,78,167,49,137,16,206,210,203,31,206,130,158,233,143,12,168,123,152,246,181,110,5,9,143,33,8,20,72,188,117,52,80,18,200,90,101,236,228,207,56,241,5,217,53,40,86,180,67,214,216,113,227,232,42,4,123,161,29,225,131,69,60,164,193,158,200,54,177,14,32,137,153,25,110,144,200,246,156,194,61,16,88,79,24,113,181,5,133,88,82,165,176,38,251,156,45,231,111,141,37,120,107,195,254,51,23,243,143,18,30,92,222,216,31,27,168,49,204,158,75,50,29,108,173,189,227,162,147,5,233,159,187,189,71,11,14,221,15,68,223,60,234,186,227,182,193,229,131,242,98,115,34,126,30,59,20,56,101,249,9,38,148,110,79,181,179,181,29,240,61,110,204,161,242,160,184,30,38,49,180,136,78,22,156,1,249,192,217,132,67,3,250,243,132,141,231,10,84,231,97,122,73,28,88,116,105,213,193,202,47,183,216,19,80,71,55,14,123,32,194,193,121,208,234,113,73,234,146,93,189,196,164,129,140,201,122,187,60,67,10,121,125,17,246,192,134,16,58,220,3,66,88,63,127,197,206,164,85,151,11,143,43,109,35,215,25,113,90,99,90,205,22,209,122,41,112,244,206,253,59,161,241,168,251,89,190,186,151,193,3,142,219,1,102,68,147,87,145,74,157,223,203,18,248,51,21,219,92,9,251,196,149,82,153,103,27,151,252,54,21,4,47,205,56,172,183,3,29,202,225,83,16,70,15,21,227,219,225,178,248,157,53,135,57,185,163,37,123,167,126,80,187,41,181,17,191,207,228,71,37,158,205,118,62,248,250,194,59,71,214,167,103,233,25,73,205,178,231,128,78,53,113,28,73,140,86,87,88,87,238,196,137,77,234,138,39,195,39,117,89,71,3,123,115,108,182,175,148,180,142,193,159,155,141,71,168,172,98,136,187,112,36,25,146,98,217,160,17,34,77,55,98,189,208,173,74,117,181,200,124,182,123,12,56,62,149,214,75,112,112,107,126,242,224,85,234,235,172,131,250,233,229,99,14,92,194,36,21,156,167,172,215,243,141,214,57,79,177,104,94,207,160,8,3,102,237,50,84,126,223,147,92,211,221,196,52,130,24,176,159,132,65,156,131,71,126,4,33,143,91,104,28,50,153,209,95,181,28,75,113,70,67,27,109,192,39,174,135,252,172,218,211,94,160,62,199,154,79,251,16,22,195,15,22,140,253,36,242,85,72,147,22,121,33,25,195,83,123,67,179,160,66,85,146,45,114,228,93,116,57,55,217,212,216,31,50,167,229,242,19,107,240,57,124,255,142,191,249,148,74,39,163,43,156,151,201,207,220,46,185,27,203,141,137,15,92,5,101,198,159,181,2,84,128,42,9,10,185,221,175,55,128,247,131,98,98,146,152,8,240,110,121,15,67,233,2,21,145,83,105,182,127,239,100,153,185,165,225,124,59,119,26,175,192,81,4,98,42,93,184,200,34,68,13,134,123,5,43,164,167,218,32,67,79,70,4,196,254,131,50,201,157,133,80,79,208,242,155,224,237,252,110,27,249,238,45,235,77,229,182,93,205,123,32,5,3,78,154,69,213,117,216,130,198,46,105,47,78,76,255,250,230,254,99,106,218,110,21,186,185,71,173,236,91,67,119,59,38,141,202,223,39,183,153,239,2,113,168,121,123,54,217,55,237,94,11,1,190,38,16,170,216,147,239,88,254,229,245,220,108,102,247,55,229,237,173,167,179,231,185,82,226,109,53,81,87,15,55,217,69,204,109,3,164,126,143,193,42,141,227,90,36,226,83,128,215,12,177,216,190,140,85,129,225,224,25,74,141,225,41,192,131,60,180,130,169,191,124,58,1,135,224,63,27,9,138,244,124,167,199,35,2,120,62,25,218,238,78,254,29,125,60,19,72,168,31,194,52,28,70,137,193,242,203,2,91,43,138,248,5,135,204,165,116,67,10,198,121,98,100,238,143,43,94,209,39,162,232,129,176,41,254,158,40,195,167,51,206,48,151,123,55,64,65,233,220,176,238,73,3,129,139,129,242,194,88,95,199,147,187,75,237,229,171,30,89,115,154,239,165,169,235,59,98,63,177,91,115,84,142,203,97,103,79,66,2,91,157,207,14,45,246,75,211,46,69,228,42,158,158,132,228,178,36,163,98,194,69,11,37,186,217,155,206,244,54,125,9,122,128,237,37,159,232,91,68,159,92,116,153,244,199,136,214,88,171,186,117,98,60,171,163,232,45,147,151,123,170,237,130,250,83,244,253,125,237,248,178,237,111,15,63,154,122,147,51,15,60,204,111,139,245,231,228,185,51,36,176,237,79,48,4,150,130,163,59,120,29,126,54,40,104,116,142,238,121,237,189,107,191,35,8,119,113,131,109,108,173,24,9,142,108,8,49,51,202,146,192,173,17,1,241,218,187,124,164,246,139,220,70,143,192,138,152,227,175,189,77,209,86,106,63,119,2,159,194,2,163,89,30,119,83,127,152,98,60,123,145,96,155,67,36,124,94,20,93,243,98,219,253,143,238,124,45,39,226,10,242,116,227,184,129,242,21,192,51,94,97,231,64,148,237,211,59,177,198,10,216,238,62,4,109,230,168,9,132,240,215,0,86,29,251,174,78,233,243,27,50,92,197,253,214,2,123,146,246,222,140,146,148,108,237,15,4,222,247,156,154,132,10,40,151,8,10,70,114,132,181,145,136,176,233,7,169,57,111,204,90,220,67,215,132,40,150,216,152,69,54,80,43,171,67,46,100,140,33,185,115,58,154,35,242,247,6,43,31,174,39,80,101,216,73,40,132,227,201,14,85,37,194,50,3,146,118,78,76,36,211,88,24,220,98,14,33,120,148,222,160,20,160,118,195,167,167,92,128,37,5,53,38,72,206,146,123,57,213,135,200,109,71,35,239,160,169,225,222,136,217,153,92,67,165,51,105,189,47,203,155,237,217,9,216,232,29,225,177,49,205,230,232,177,124,66,19,114,207,198,114,64,45,161,124,66,110,85,157,81,102,32,22,83,53,111,196,27,133,196,169,162,223,120,126,235,105,163,132,221,206,150,110,214,226,227,26,172,30,160,193,251,235,130,209,125,165,77,58,39,115,187,196,165,24,148,33,237,15,73,76,51,191,88,212,165,137,89,220,47,35,108,174,114,48,214,113,39,163,180,185,63,88,233,112,0,120,241,137,168,24,63,138,54,82,207,177,179,66,101,46,177,222,3,52,49,103,68,5,246,78,182,234,55,35,29,9,19,192,144,78,132,224,162,148,96,89,62,61,109,6,178,98,241,196,88,167,22,196,56,11,139,35,94,112,213,134,206,158,24,179,145,144,24,250,44,149,253,67,210,8,0,244,166,243,0,180,234,155,46,191,122,41,93,142,70,154,56,201,66,159,207,162,193,63,26,46,204,221,206,29,100,232,161,225,87,106,130,47,154,66,253,50,33,4,103,71,134,239,65,137,220,222,90,200,221,145,253,16,73,125,66,213,113,239,82,209,96,85,98,196,87,143,30,250,24,217,92,120,23,123,71,64,51,243,204,192,239,147,75,30,170,32,161,187,95,176,78,235,9,173,103,112,9,93,39,55,89,66,223,135,55,158,58,28,249,4,53,46,175,138,48,65,135,70,136,1,162,20,77,236,103,41,150,88,60,162,162,221,75,62,108,114,118,100,40,120,101,241,122,160,0,109,225,54,161,239,188,6,149,136,139,198,177,179,32,43,126,52,149,57,217,226,136,215,201,55,32,213,229,87,28,109,36,223,42,151,98,71,107,140,255,230,206,183,84,127,109,108,57,226,37,11,140,188,250,216,82,32,241,186,122,68,173,128,81,29,57,2,23,81,10,233,198,238,113,91,11,7,17,184,180,159,230,116,147,143,120,21,24,1,220,118,49,16,80,204,12,78,41,111,117,193,98,56,148,193,219,160,156,230,56,126,1,172,183,95,204,229,202,75,218,108,245,33,254,8,58,127,98,209,197,176,100,60,110,139,133,80,43,42,133,200,12,216,121,186,89,171,171,252,220,132,121,46,180,75,79,8,157,91,112,112,34,247,193,147,132,119,236,30,223,101,129,132,197,45,134,84,202,92,249,70,208,211,158,206,209,216,202,106,106,96,1,80,249,182,103,247,124,85,169,42,212,67,245,112,214,156,147,143,216,186,202,197,119,5,230,23,226,199,79,150,253,252,85,1,193,145,96,212,15,165,73,246,244,50,249,165,95,254,252,112,62,100,237,167,234,181,238,164,135,224,175,19,225,82,153,135,122,209,81,59,123,165,21,127,99,54,56,18,153,226,205,161,95,202,7,79,126,124,92,208,244,46,5,176,227,206,200,16,140,97,250,131,187,54,34,117,52,52,206,150,201,200,182,45,201,225,80,46,100,113,199,193,12,116,224,253,59,85,244,248,161,239,199,164,208,63,114,103,163,167,185,246,203,19,33,102,53,236,108,3,205,170,155,230,73,204,142,178,233,7,187,171,191,137,254,60,149,218,98,40,42,87,10,3,146,207,162,67,113,25,173,141,27,217,143,225,97,164,2,208,116,57,181,180,112,233,183,114,62,110,197,29,79,155,213,7,115,94,60,229,43,83,79,119,171,196,20,78,239,233,51,87,6,32,5,59,166,121,176,193,0,2,145,150,183,130,7,36,179,159,57,212,66,179,111,151,174,27,202,58,35,12,121,174,29,17,69,244,46,87,1,173,238,194,40,107,180,147,157,209,184,241,104,251,123,242,164,42,31,93,118,82,79,189,47,105,102,158,30,210,164,16,47,140,226,212,235,70,176,78,30,247,193,162,137,19,102,181,9,248,156,29,149,41,73,2,34,88,183,198,106,254,34,124,19,150,32,99,71,253,14,190,121,107,200,168,38,114,205,153,112,139,204,16,149,101,168,127,70,40,156,157,78,179,113,220,4,46,194,124,96,187,139,83,36,28,169,50,209,88,176,134,217,219,55,18,186,165,170,11,175,60,216,24,132,95,218,101,75,194,66,64,184,1,56,29,86,92,86,243,122,204,124,185,21,219,37,111,68,82,178,41,69,127,186,121,223,219,84,41,169,105,54,165,5,128,102,12,67,130,217,46,97,233,254,216,57,121,145,39,46,34,136,82,175,114,153,215,16,119,138,116,45,137,136,230,59,132,221,97,0,150,250,153,211,18,141,254,212,157,9,45,217,191,16,24,133,130,194,151,189,230,92,187,55,12,247,187,8,115,13,29,222,207,59,92,230,24,146,39,165,2,54,188,107,162,190,178,185,22,188,187,172,42,164,239,225,92,55,26,237,230,59,0,75,13,33,47,250,12,161,72,4,185,159,244,163,208,129,102,176,239,178,99,211,97,92,241,234,19,85,70,42,189,55,130,151,119,38,50,126,239,231,40,153,124,51,220,63,234,208,163,211,170,63,37,231,40,152,183,204,90,227,246,208,8,196,85,209,243,92,102,174,199,27,110,145,27,1,158,35,176,107,152,163,227,75,21,184,120,238,57,155,201,3,194,165,57,117,211,136,236,17,128,98,177,93,111,46,94,137,155,5,70,101,212,42,190,79,218,62,143,123,151,171,59,185,175,9,185,245,254,235,130,177,69,252,61,157,29,229,105,128,229,192,180,37,158,214,254,13,129,64,53,209,247,56,140,241,97,250,119,174,250,204,68,97,184,208,29,20,117,25,12,105,234,224,76,223,115,197,177,7,235,247,19,42,20,85,78,15,81,181,192,153,4,160,176,82,106,67,212,194,132,240,190,45,126,79,192,122,42,28,239,165,14,139,14,152,62,129,78,48,66,45,207,97,240,165,178,129,234,169,234,59,12,218,46,249,54,76,20,225,254,11,128,237,242,61,101,16,36,207,202,13,244,205,77,104,204,51,50,1,5,95,211,151,110,251,255,185,191,151,167,102,140,98,163,129,27,38,60,101,197,176,252,212,232,136,208,157,118,51,83,111,209,188,223,78,130,47,24,91,236,170,159,121,55,3,202,0,155,212,180,173,74,37,161,201,91,108,166,174,27,239,60,20,65,158,225,185,85,89,127,76,244,27,86,150,160,201,13,106,79,143,68,200,236,55,107,243,76,149,215,188,118,183,198,159,26,140,136,153,211,173,159,16,57,139,31,93,149,70,6,141,53,112,164,6,184,239,106,159,222,67,158,26,121,136,223,39,46,140,67,170,202,95,88,179,214,186,212,140,8,12,94,34,77,226,17,17,162,210,225,20,151,177,74,9,100,126,170,73,142,33,144,154,131,151,205,235,28,118,190,6,137,98,50,237,7,94,230,246,133,250,179,160,199,89,103,9,203,111,37,216,185,171,40,117,6,107,87,133,165,172,22,140,220,186,41,97,187,57,196,102,220,15,169,194,254,170,33,237,69,78,127,4,30,119,51,251,153,50,179,106,153,232,131,96,100,243,32,78,78,223,191,150,158,39,30,201,43,12,220,233,103,223,247,156,210,213,52,75,203,102,114,46,35,81,55,175,89,207,53,66,198,247,164,132,51,64,124,120,125,108,35,3,184,185,202,162,122,93,58,198,11,176,146,221,62,6,92,250,135,230,38,135,125,76,89,22,140,243,110,14,212,252,94,85,234,86,142,168,158,28,94,124,183,180,213,174,80,170,142,88,83,48,201,169,249,109,156,83,4,161,186,46,235,85,83,86,244,7,52,58,188,19,124,117,35,105,13,185,191,47,252,142,77,194,147,27,235,193,126,138,65,32,134,118,24,227,33,219,142,48,59,235,147,8,183,94,74,184,233,4,78,44,55,20,167,190,216,145,187,105,253,135,93,68,15,204,76,81,176,255,140,229,106,248,29,154,109,79,247,240,181,62,181,2,28,187,26,136,254,180,92,158,140,81,194,11,245,237,48,28,57,112,87,48,233,185,13,251,113,29,199,152,222,226,254,232,119,199,120,251,113,224,226,89,162,215,74,115,227,118,145,197,176,156,161,226,233,79,170,203,163,113,106,144,108,25,85,163,91,129,143,75,216,56,51,156,13,106,116,79,121,79,152,139,128,156,169,174,94,228,172,49,115,235,134,42,145,67,107,214,122,8,49,156,210,218,178,151,67,247,169,0,56,164,44,222,132,125,193,90,153,10,15,29,69,159,229,98,193,181,138,65,215,14,65,89,116,209,247,174,22,72,27,141,214,94,36,169,203,34,123,25,192,248,196,238,148,225,225,253,59,44,43,96,2,26,21,96,123,202,184,253,55,162,172,81,29,95,172,11,133,235,129,224,183,94,71,85,29,23,65,246,242,222,224,109,136,62,63,145,107,248,167,160,195,242,204,135,237,253,107,53,91,77,34,207,186,102,102,84,28,14,44,194,39,232,156,245,132,232,76,102,63,206,240,49,132,118,211,1,70,75,30,42,3,149,207,174,223,160,227,64,221,207,62,64,74,186,97,163,201,85,231,33,84,76,132,47,66,189,73,137,21,77,184,234,168,231,171,247,76,32,229,1,138,186,116,5,60,65,8,57,133,57,165,125,190,51,105,242,89,1,141,234,53,168,34,89,88,55,63,52,10,226,116,30,115,175,214,74,234,133,248,48,242,17,47,155,75,131,130,124,207,192,199,156,142,142,119,122,3,15,49,119,155,82,80,171,180,19,29,133,31,247,222,9,245,206,244,22,69,12,85,112,250,23,97,212,191,32,152,5,115,206,31,197,19,250,138,219,130,3,84,216,78,11,80,213,13,161,199,128,136,64,7,53,223,221,247,108,10,139,128,47,36,225,149,145,94,106,22,86,14,62,13,43,181,226,188,243,228,218,231,144,137,51,46,13,237,21,72,193,233,132,28,220,20,8,4,122,72,237,253,246,222,239,176,0,105,79,66,248,100,211,232,18,217,109,127,11,57,83,34,123,20,60,137,153,193,152,195,96,127,130,205,193,250,201,146,44,174,91,40,108,105,104,231,248,136,114,61,136,124,241,31,128,186,165,230,218,248,76,54,35,51,13,80,241,46,59,34,214,111,253,168,149,252,124,4,81,171,131,110,58,165,172,223,166,5,45,240,154,11,195,26,117,137,238,192,41,98,219,74,113,235,25,234,46,9,144,57,228,196,138,122,230,73,229,42,31,24,18,166,217,131,24,95,177,251,18,240,249,10,235,122,112,16,73,162,6,70,8,231,108,54,87,216,194,174,60,128,244,234,190,212,213,146,128,244,187,133,74,29,128,195,60,234,120,57,168,116,97,234,156,164,173,42,225,70,177,38,184,43,121,148,186,19,207,224,19,253,214,102,184,227,77,205,223,63,242,184,142,75,134,48,96,96,243,151,83,50,87,123,186,147,177,176,62,113,237,99,50,108,201,126,185,218,219,219,241,171,55,44,28,194,49,254,72,63,140,63,178,112,216,15,3,183,189,172,230,154,116,254,246,200,73,82,76,41,15,168,132,147,25,115,46,90,151,15,180,193,60,237,178,105,74,47,191,86,59,221,105,248,98,26,140,49,149,76,146,83,229,173,71,134,78,113,171,186,136,69,240,102,228,167,251,86,198,107,167,79,180,215,210,44,58,98,143,79,188,44,133,107,54,248,165,231,104,149,127,120,62,61,159,252,239,41,101,177,140,108,77,90,49,230,151,125,115,153,80,213,191,17,98,59,202,149,108,239,233,23,177,26,245,216,97,198,111,31,75,248,67,177,55,207,157,212,233,20,69,111,167,232,80,21,144,9,32,199,43,200,181,141,195,9,143,237,154,121,175,158,247,124,39,117,184,48,30,51,103,4,19,16,28,84,98,72,251,204,19,32,194,90,236,170,52,202,181,96,92,120,59,184,47,169,66,177,66,217,150,2,50,182,17,7,131,32,76,227,116,70,174,42,90,163,89,35,33,148,41,240,228,253,31,107,201,210,198,152,13,86,70,112,248,225,121,155,252,134,99,239,2,8,98,108,44,76,227,160,213,104,141,16,130,205,118,253,123,220,48,200,187,80,35,114,62,45,188,107,29,79,220,169,244,147,158,70,102,122,231,232,149,243,55,230,115,28,185,83,39,179,237,221,41,170,240,44,143,39,216,163,87,213,39,157,118,225,99,80,190,57,171,200,20,2,7,166,112,211,127,0,69,167,84,159,62,190,37,46,1,194,192,152,94,188,50,203,38,220,128,2,108,156,32,255,174,254,89,135,44,97,26,237,37,203,70,32,238,3,218,163,213,145,32,244,50,67,233,217,30,131,135,205,0,46,29,143,192,99,180,144,34,96,7,74,212,164,44,215,190,88,252,138,84,97,50,251,203,44,252,175,247,178,155,79,180,28,8,80,184,205,211,9,119,150,32,91,150,4,102,212,89,217,117,71,241,163,146,90,113,142,34,228,139,182,236,101,97,47,152,88,91,161,47,37,246,4,92,89,174,210,15,82,44,118,249,82,198,192,155,172,220,91,168,190,233,35,204,84,24,113,139,102,112,42,108,124,19,27,148,60,159,78,38,239,90,234,5,193,172,28,58,20,182,11,43,162,123,82,184,178,167,19,172,101,106,3,69,146,204,136,46,70,35,133,166,103,74,245,222,246,76,109,232,173,160,36,50,39,140,112,227,59,10,18,127,30,232,161,113,146,233,102,248,171,205,245,154,98,101,53,109,65,36,82,31,241,200,111,216,27,255,10,48,237,213,82,221,17,250,248,215,19,150,56,175,233,19,230,30,233,199,3,100,121,176,189,175,63,20,231,105,113,121,51,88,188,231,109,177,58,34,9,199,121,226,157,183,76,219,41,224,204,61,144,124,88,115,7,214,74,179,178,42,119,144,76,98,58,171,185,134,98,123,177,87,100,213,183,165,147,22,29,151,19,74,146,102,107,158,201,189,0,79,185,36,105,84,104,73,152,103,132,228,196,39,102,113,158,255,56,212,198,37,172,139,31,238,98,184,182,42,69,108,194,245,23,205,45,21,76,115,162,181,174,59,213,233,59,240,184,32,212,226,199,126,11,205,232,217,187,51,197,98,94,117,94,105,152,41,48,22,181,8,146,134,207,30,237,255,240,248,183,191,187,67,210,16,185,191,54,193,2,218,22,99,176,191,233,78,247,165,4,231,131,62,37,109,244,76,194,155,129,212,66,0,101,223,162,211,13,80,169,217,16,68,4,155,216,61,35,76,162,144,217,34,209,73,249,250,253,186,140,124,41,237,124,22,168,97,40,95,47,38,188,204,216,150,184,229,185,174,113,3,154,126,238,50,165,170,12,27,209,53,157,76,118,81,252,10,140,31,103,160,43,171,6,65,205,225,154,85,121,76,216,228,29,241,184,200,160,225,86,4,199,137,80,222,199,30,9,163,177,222,131,91,24,3,147,148,250,20,157,246,166,73,41,246,240,159,85,53,172,227,255,239,211,188,78,85,210,198,63,175,149,47,251,126,139,167,245,143,5,212,41,111,52,133,173,37,114,122,63,214,212,6,98,213,169,140,241,226,233,95,47,169,91,89,117,116,228,30,78,123,163,137,11,19,142,70,121,166,215,141,20,57,100,202,75,131,150,222,136,204,79,199,205,220,46,9,129,92,116,55,148,224,138,82,32,255,250,251,59,239,99,130,13,77,106,233,191,37,70,164,141,160,195,95,192,54,39,178,189,46,17,135,160,255,198,62,249,69,57,5,74,22,165,134,209,143,179,8,28,219,212,141,148,242,233,231,171,234,72,186,111,252,84,120,130,253,206,225,145,123,88,19,194,150,24,168,247,191,92,162,203,56,94,55,72,199,142,76,50,37,253,13,142,159,201,100,153,149,243,217,240,192,204,254,66,239,13,23,161,166,210,210,120,35,7,141,179,109,83,57,146,163,16,195,195,129,214,39,34,155,158,29,244,128,143,18,233,121,150,87,80,227,145,22,207,133,15,10,172,79,48,176,209,68,66,116,22,167,251,162,90,108,98,148,98,84,46,164,185,106,48,68,247,163,112,24,15,78,105,58,173,251,63,10,252,91,83,158,57,178,63,21,40,113,231,82,251,191,134,27,71,131,203,150,222,121,48,211,181,0,62,91,119,123,77,252,183,63,204,142,239,211,87,244,129,213,2,81,221,210,104,182,252,35,116,91,198,172,132,76,148,89,3,74,8,96,232,19,70,18,232,128,18,145,133,229,23,13,93,175,174,68,105,55,192,81,168,1,142,132,193,37,99,188,243,51,14,26,6,195,29,149,159,115,77,169,235,22,66,101,37,224,43,146,152,141,191,222,67,12,74,51,124,129,141,11,37,97,10,50,79,112,123,54,180,89,156,10,237,145,90,99,35,116,84,163,249,196,70,103,144,16,14,13,233,42,5,213,163,203,205,92,6,212,210,195,46,141,24,15,1,215,71,30,31,0,4,24,15,93,217,35,228,173,104,78,117,69,140,243,168,119,62,223,200,171,123,57,184,88,64,53,21,153,201,0,115,146,22,119,84,228,16,189,124,213,148,92,15,178,58,83,69,87,213,137,150,254,92,197,211,157,193,255,150,115,3,222,48,64,41,28,208,245,211,29,135,30,54,205,250,93,94,57,155,196,37,151,90,109,165,11,249,203,106,37,64,103,100,206,108,40,181,36,238,104,208,241,13,26,75,32,133,101,47,132,226,199,174,3,139,186,102,206,19,21,6,166,44,184,63,7,255,61,155,90,233,60,161,86,176,23,97,194,237,176,234,251,116,25,226,11,145,130,13,179,158,222,252,26,235,132,202,117,229,195,232,158,52,183,96,47,219,235,210,51,146,103,15,241,22,194,84,73,169,183,142,81,87,203,6,251,105,254,2,56,164,156,137,219,71,205,59,144,217,70,38,73,57,73,70,131,114,20,249,181,50,184,200,127,251,28,30,92,166,20,252,156,141,128,223,214,176,136,154,210,238,245,131,123,1,114,106,160,197,74,57,4,101,162,185,66,93,219,192,225,68,181,231,74,140,180,121,162,114,142,129,187,73,66,192,218,128,28,39,134,251,0,243,48,55,112,205,204,80,144,149,109,100,247,179,224,228,198,89,225,7,131,170,203,32,130,21,23,249,122,134,208,160,239,23,10,91,107,175,27,56,59,104,18,71,209,245,4,165,227,203,178,69,1,114,130,119,193,171,64,18,182,174,155,16,84,193,55,150,153,90,251,6,94,161,253,223,200,143,16,162,175,93,211,88,243,61,118,144,204,158,163,68,183,243,85,64,42,52,155,32,39,213,93,165,239,188,8,152,93,228,136,71,213,103,158,57,252,54,203,34,230,180,127,56,46,22,5,220,190,103,131,16,64,135,114,68,112,125,205,54,108,113,157,5,31,108,20,138,80,149,170,6,114,65,223,21,159,246,115,158,118,220,203,106,20,66,204,213,59,225,109,136,122,206,137,104,126,66,24,195,83,223,112,36,241,154,219,254,255,248,77,142,202,95,86,171,11,42,188,7,245,217,138,49,224,34,61,121,28,57,25,3,70,9,40,108,107,108,211,160,206,154,77,59,153,161,172,200,23,84,154,131,94,122,115,145,19,13,234,127,86,154,80,149,41,50,98,186,251,36,10,53,159,223,103,104,248,67,154,136,228,46,83,243,36,33,221,157,116,83,109,54,89,171,46,252,120,86,50,220,23,252,185,68,192,125,37,223,233,232,110,16,135,71,175,199,37,75,162,17,48,41,32,39,131,59,145,161,20,26,149,216,99,1,188,240,87,189,8,24,224,227,175,207,156,151,37,76,105,62,202,86,172,9,208,0,186,72,213,78,103,254,132,192,92,113,242,42,224,245,111,181,206,107,130,182,212,63,185,27,28,41,112,220,209,148,172,7,140,225,168,124,67,203,73,76,139,41,226,87,30,125,197,216,76,36,160,168,194,202,181,254,134,0,148,187,242,94,239,72,9,21,148,168,92,66,161,144,73,37,106,39,176,127,116,44,183,89,77,47,138,171,10,169,117,147,107,92,29,184,69,82,220,13,130,34,214,197,214,6,152,46,180,228,77,211,162,47,149,169,145,56,196,174,84,97,93,246,216,30,34,211,137,93,8,161,64,73,106,220,60,107,201,86,86,124,51,9,66,244,168,8,22,125,147,200,68,23,23,247,75,139,87,52,54,5,53,175,14,218,127,126,196,104,220,88,75,122,52,99,226,111,88,137,95,199,196,6,2,87,182,200,67,133,205,210,73,174,53,64,12,134,84,182,73,199,7,65,88,7,24,83,187,31,81,35,236,229,37,177,78,42,143,233,94,241,133,195,255,185,7,218,41,43,231,129,3,23,175,147,37,26,188,70,161,146,126,24,12,38,104,96,209,143,227,254,9,198,24,192,4,227,59,174,32,240,251,5,34,127,186,184,83,193,62,41,187,33,39,239,28,16,118,164,36,171,230,136,212,122,52,86,39,165,85,61,117,145,179,83,209,229,95,227,85,170,136,187,59,115,217,179,60,48,21,67,116,58,14,145,89,89,35,229,5,152,217,138,26,10,189,186,35,83,210,174,165,179,87,168,247,177,43,213,204,247,37,109,164,15,182,108,253,170,140,83,214,151,0,211,81,132,64,43,30,248,18,149,11,44,248,98,107,216,117,38,96,167,82,124,152,140,191,51,40,145,207,31,45,189,144,120,151,236,172,94,196,233,80,172,227,217,187,197,174,24,108,153,189,212,51,44,156,203,149,74,222,95,240,202,168,235,255,91,215,29,201,254,8,156,120,134,162,218,172,153,51,254,189,4,238,93,65,227,158,247,6,74,254,126,91,58,204,84,167,188,223,91,180,79,147,62,150,135,231,158,186,185,126,91,13,115,56,108,78,17,205,175,102,47,20,157,73,175,89,225,242,141,119,215,191,236,127,186,252,109,87,164,233,22,213,98,137,134,97,78,12,13,150,30,160,164,149,154,108,167,156,104,67,228,187,152,143,135,114,154,47,7,21,89,131,179,34,253,135,40,109,220,0,127,213,82,85,64,161,1,113,242,240,66,56,78,225,32,59,26,177,12,19,79,6,212,120,217,177,7,187,76,85,122,133,9,219,81,118,109,201,21,119,47,122,30,190,208,241,78,63,16,91,45,44,253,13,228,18,228,187,96,222,132,166,77,100,226,124,234,61,59,174,40,117,26,163,5,65,107,1,95,18,170,126,100,95,216,113,98,15,186,246,133,3,205,221,228,159,206,212,201,240,175,113,198,72,187,233,28,104,253,239,168,246,139,120,149,143,34,146,39,220,145,216,114,243,109,219,151,117,75,33,162,197,181,62,19,128,118,215,96,101,54,68,109,7,171,133,54,145,1,15,56,224,58,123,172,196,221,3,133,158,85,120,21,246,153,166,1,17,66,48,223,247,230,95,15,223,253,250,109,197,6,190,76,117,7,245,185,143,129,188,191,215,198,20,90,194,172,250,78,233,102,182,120,92,116,208,65,80,84,235,77,57,207,221,127,16,225,96,218,22,104,216,138,195,220,101,236,3,109,87,42,198,95,96,164,202,48,107,45,17,107,246,2,243,229,149,152,83,101,228,91,80,183,254,119,138,201,64,197,135,212,15,171,151,44,69,249,208,188,57,253,250,157,63,153,226,131,155,3,224,56,103,144,28,200,229,192,71,131,21,129,219,235,31,205,144,191,146,253,77,67,78,216,241,242,228,244,174,123,254,65,212,26,35,218,100,1,28,145,247,37,254,116,206,212,40,200,241,209,30,238,181,165,198,211,144,87,158,142,226,70,232,172,134,42,41,121,222,108,17,68,45,47,16,56,26,77,188,99,188,115,118,252,245,11,51,25,44,27,128,31,32,221,54,158,109,102,53,155,4,245,73,26,234,174,198,111,64,52,171,213,56,173,114,145,152,204,191,140,179,22,93,211,35,243,221,136,103,201,155,0,41,110,183,62,30,176,252,190,108,47,23,203,166,160,173,17,124,11,189,244,44,4,13,133,74,224,19,240,200,254,27,57,180,193,89,67,10,147,117,127,169,109,96,98,8,10,21,26,37,181,81,247,202,60,172,58,139,237,116,143,140,46,52,176,49,71,231,243,80,161,14,219,152,25,62,178,232,150,162,47,124,122,155,221,61,212,160,224,158,136,39,24,24,159,93,108,6,145,49,245,189,95,22,153,45,100,83,225,12,97,201,53,242,6,2,23,210,62,108,106,189,178,189,42,64,247,93,171,233,157,196,159,103,239,240,111,60,164,43,151,83,198,183,204,37,185,207,113,120,130,103,10,4,90,144,149,54,51,128,82,233,108,119,172,85,82,79,203,25,184,22,113,202,100,46,34,121,95,234,102,43,243,242,211,223,171,133,152,188,18,134,67,47,2,94,11,17,249,254,0,115,150,132,37,136,76,84,42,91,153,219,138,4,233,91,164,1,243,162,12,134,75,244,55,138,40,252,182,74,245,239,39,45,157,106,56,118,130,15,190,210,138,155,237,239,57,182,77,69,190,113,237,27,178,173,214,149,95,133,12,106,208,89,63,129,174,51,58,43,142,103,103,138,109,123,39,101,45,171,1,233,54,34,208,63,121,151,241,39,0,207,133,172,100,150,134,5,196,133,184,171,253,201,139,186,75,242,123,53,174,38,249,95,72,254,64,108,209,147,37,177,166,69,3,178,95,255,47,41,195,232,6,73,119,89,203,225,150,80,125,183,56,28,82,112,89,167,237,204,73,139,208,233,7,168,90,35,244,133,50,216,254,240,80,227,187,102,135,27,213,192,201,21,175,236,199,100,103,36,247,192,4,133,40,125,16,111,25,177,101,37,180,170,49,230,106,169,123,73,58,231,60,106,230,145,116,211,215,134,199,90,18,243,210,29,225,79,224,248,108,204,147,215,73,244,75,154,145,95,137,151,193,154,146,43,242,175,5,62,42,113,9,57,70,59,133,75,165,250,154,186,143,167,22,47,252,137,102,87,181,104,147,207,195,205,88,18,48,209,126,182,35,179,10,30,175,25,163,6,202,85,185,99,52,208,20,19,242,169,14,253,227,198,85,129,68,11,99,112,59,79,142,105,188,254,123,148,88,153,70,89,84,106,236,34,181,241,51,194,138,62,14,134,245,151,117,235,135,10,139,140,204,146,196,96,242,114,217,131,102,142,129,65,132,108,64,29,42,233,238,33,19,249,17,222,195,125,158,124,202,110,18,183,150,111,199,70,127,8,180,135,203,33,143,230,228,90,44,43,118,241,57,168,162,89,150,106,102,32,60,250,93,143,196,239,12,214,171,73,180,196,199,210,115,112,192,13,9,123,222,213,148,91,19,101,236,101,30,146,43,164,10,156,101,112,151,65,89,151,245,154,56,37,194,99,153,35,80,3,93,62,246,6,68,42,34,155,207,230,215,121,37,213,153,36,165,136,123,181,144,31,215,138,161,118,151,196,108,131,138,93,13,158,182,138,197,184,0,44,139,70,0,204,15,179,245,235,111,229,61,119,1,248,135,70,169,50,116,69,16,223,77,223,248,176,81,63,205,104,150,100,178,216,215,7,243,251,58,16,117,59,213,117,122,156,183,0,72,126,132,100,86,92,240,106,174,220,88,51,75,166,111,176,139,229,215,30,173,166,246,249,201,187,24,250,69,150,214,224,9,17,218,53,173,213,254,11,60,19,32,202,124,40,131,51,99,223,226,217,190,252,29,14,39,73,199,37,180,254,114,46,169,46,109,205,172,86,62,198,113,209,186,149,211,122,42,239,238,71,133,33,39,217,86,131,68,199,243,26,0,143,97,215,140,217,34,11,55,192,118,66,69,203,200,128,171,40,250,94,127,204,76,168,232,153,226,37,150,4,8,22,177,75,64,204,39,19,45,127,173,174,14,222,159,184,66,88,61,250,133,231,114,166,164,33,157,77,203,31,222,189,111,131,178,107,117,10,165,203,18,211,117,188,134,254,238,158,123,143,231,245,189,89,21,88,66,169,241,24,26,210,108,105,249,56,37,196,36,26,110,237,31,34,198,114,72,218,133,14,40,38,0,26,218,130,56,146,228,86,253,43,36,112,162,58,232,178,162,105,114,186,74,187,229,215,195,101,241,14,24,95,246,248,101,255,68,164,79,41,18,245,65,11,228,167,132,169,52,170,196,91,52,224,204,230,105,193,231,254,49,143,85,42,221,140,233,18,131,116,86,127,103,136,113,15,23,95,39,90,226,59,168,56,73,43,227,171,60,251,5,66,24,207,129,225,168,127,243,190,108,173,215,76,110,107,75,120,242,147,252,217,57,234,116,1,133,221,90,162,174,126,61,236,200,53,105,71,155,217,56,85,6,214,13,60,119,234,225,200,186,152,215,237,225,105,85,252,240,252,38,75,220,200,6,243,144,34,127,161,14,197,107,63,75,235,195,72,44,27,244,129,243,201,59,241,45,173,62,200,145,232,76,142,208,183,15,77,119,157,26,157,170,159,104,206,13,248,132,68,229,234,196,252,168,229,154,203,44,177,54,200,235,132,93,52,10,196,60,152,226,220,27,98,85,215,82,144,161,12,76,202,47,71,231,225,223,105,35,201,195,174,188,10,168,199,141,255,108,74,166,226,33,4,203,54,202,178,27,127,250,86,181,225,246,70,219,65,173,49,214,202,71,22,67,184,54,90,182,251,202,40,14,235,63,201,190,75,65,15,33,62,81,56,157,55,187,67,3,223,5,188,105,211,72,202,95,229,207,20,1,219,121,116,56,5,116,227,97,48,200,192,252,86,238,56,125,89,89,89,100,76,5,180,81,31,33,111,202,211,182,51,25,81,28,239,153,125,85,67,149,136,118,157,65,84,65,43,74,86,81,238,45,7,227,222,145,234,95,152,157,225,22,53,47,59,189,252,16,40,26,171,155,247,98,73,206,206,218,9,241,152,213,3,15,107,123,100,86,78,2,200,194,8,78,101,235,150,113,69,232,13,102,131,200,41,240,126,186,238,184,20,62,218,235,221,116,53,44,20,219,104,254,112,139,81,119,100,253,105,53,62,247,159,166,75,128,64,51,7,193,108,154,115,34,146,127,75,102,17,112,81,35,33,255,104,228,11,97,24,252,219,214,122,235,2,28,34,128,252,220,126,248,87,48,200,149,102,191,135,59,48,111,142,210,22,87,41,25,209,90,114,67,98,234,128,53,45,198,155,116,161,66,14,216,226,63,200,18,7,20,213,60,221,77,128,48,20,142,208,197,61,210,161,90,77,80,146,220,80,168,29,93,171,234,195,182,134,136,225,120,206,94,147,141,52,199,5,155,74,143,12,252,50,79,254,135,78,145,222,143,150,128,28,137,206,79,88,83,195,0,213,182,223,225,201,191,235,235,39,175,202,211,139,11,109,8,255,251,237,232,33,37,250,169,184,42,115,205,55,220,211,160,190,225,201,208,87,227,181,15,92,123,111,172,104,71,23,236,206,214,177,119,77,128,149,238,102,224,147,48,143,82,158,83,179,110,112,12,75,86,190,48,208,14,156,92,140,55,64,14,23,106,204,140,48,97,72,62,247,14,217,121,31,224,171,233,69,177,129,185,71,17,87,96,138,78,19,178,198,229,37,235,51,51,208,149,100,111,39,54,197,126,215,245,125,0,18,64,157,246,4,183,62,21,82,209,182,193,74,163,255,99,143,38,119,30,171,116,62,129,241,64,167,205,128,48,19,141,208,126,96,231,17,94,11,123,106,132,252,127,95,4,217,84,100,231,9,56,144,178,55,92,107,154,194,164,113,19,93,117,152,188,49,241,135,95,131,177,63,10,247,179,86,47,153,63,125,70,239,205,3,48,196,135,152,123,146,5,229,21,112,255,72,4,180,42,148,238,234,211,163,111,223,49,176,36,101,182,121,145,65,242,151,27,181,100,235,212,127,238,78,165,2,36,188,117,89,217,137,39,32,249,156,72,106,48,65,177,35,119,166,109,125,93,15,74,133,194,177,8,208,79,4,23,216,37,3,20,67,12,40,52,11,160,213,96,177,234,40,240,251,19,126,81,186,153,249,204,11,91,78,70,238,38,31,243,13,156,49,165,95,148,218,155,179,139,30,216,15,153,27,164,59,189,173,159,141,146,16,21,167,183,161,203,82,140,66,150,182,16,73,40,176,102,55,118,132,173,249,137,117,137,145,90,53,86,164,24,152,171,14,64,192,181,253,238,22,204,59,115,228,173,155,232,15,108,250,14,135,190,177,25,54,114,152,83,38,132,125,185,243,134,112,168,170,99,100,155,125,107,46,165,146,10,12,243,170,39,155,195,220,140,129,9,27,178,166,144,112,200,134,3,146,228,27,60,217,251,147,93,72,56,196,158,217,177,53,113,146,111,93,172,7,71,165,196,105,120,164,255,79,158,235,183,45,61,139,128,87,87,24,202,89,236,50,129,135,90,217,225,115,211,102,32,22,124,87,167,76,209,47,193,179,5,176,1,172,115,53,235,4,198,69,17,146,1,156,60,169,171,3,154,137,1,8,160,180,39,33,145,194,221,167,74,225,147,22,226,175,161,190,155,99,104,36,234,28,206,255,153,106,146,140,248,208,160,159,129,189,81,79,151,34,57,191,19,60,238,132,173,126,112,102,40,167,236,248,169,15,165,62,167,248,117,241,242,52,190,179,82,62,174,253,135,166,242,116,101,164,25,44,212,205,199,182,51,26,85,54,11,16,243,103,183,145,84,222,115,193,84,191,14,243,49,214,76,187,20,39,29,243,173,156,181,219,109,64,24,75,52,179,28,160,231,99,85,33,44,165,96,91,1,116,151,203,247,43,74,128,179,172,198,31,77,89,11,160,120,13,159,140,72,217,110,79,78,206,233,178,98,50,152,74,216,73,133,249,217,70,75,56,129,241,107,234,100,37,103,60,16,188,2,190,11,70,104,226,153,93,247,153,143,161,19,20,220,168,207,59,231,145,117,83,136,104,18,107,25,84,26,105,116,169,98,24,122,32,236,228,193,206,223,235,29,238,49,143,225,2,196,58,61,127,140,102,14,140,100,86,158,130,245,106,213,21,195,130,77,170,38,87,189,28,239,43,9,141,221,172,71,101,23,117,196,97,176,152,245,228,11,197,252,84,206,70,36,202,196,205,27,80,137,39,25,75,180,73,162,224,150,97,44,115,24,151,153,239,190,250,64,81,124,193,49,199,158,225,239,216,251,150,194,11,43,136,66,171,93,122,163,101,50,248,76,30,251,201,114,80,75,69,109,212,155,11,141,217,118,95,15,127,174,149,147,216,251,178,89,253,92,51,157,16,128,60,144,26,219,47,131,125,182,76,241,164,209,6,26,7,92,85,220,173,245,230,208,98,209,124,70,173,192,190,132,55,211,201,186,183,60,108,73,202,134,11,25,98,22,219,173,173,140,39,222,243,91,17,177,81,168,144,244,94,105,34,211,227,16,134,9,254,20,51,4,182,243,203,82,63,238,89,246,230,147,185,200,52,129,113,141,167,177,99,18,247,119,52,84,13,203,187,89,98,35,178,30,13,149,205,77,136,197,164,183,202,225,132,158,34,253,166,180,170,81,56,53,16,116,34,149,120,212,66,17,226,5,193,175,148,81,251,230,23,177,141,43,79,103,153,84,172,51,44,242,34,237,188,74,225,118,144,129,40,56,96,157,254,134,231,14,209,110,23,26,41,253,29,33,247,80,149,196,100,34,23,183,198,124,246,191,174,56,254,31,119,127,229,154,236,190,38,98,101,91,126,182,201,156,27,210,62,101,17,18,95,17,62,112,173,218,95,8,203,29,169,3,23,137,111,219,234,54,156,50,148,31,227,60,56,205,74,105,149,45,57,162,39,83,232,38,150,169,204,161,15,212,82,220,124,196,127,1,123,135,186,208,13,210,224,127,223,143,131,107,123,201,10,21,58,99,135,64,212,81,242,174,16,20,198,65,72,42,58,79,59,206,26,52,133,57,223,232,6,119,87,13,47,214,82,42,153,242,77,203,163,205,22,188,0,129,78,179,114,86,63,119,183,248,180,74,200,49,174,239,118,170,130,129,69,61,251,182,192,219,239,214,192,255,58,247,26,49,105,232,74,79,103,145,214,114,231,134,233,230,182,242,244,118,246,117,136,107,207,19,107,184,247,251,123,157,189,96,101,189,162,223,179,99,10,86,165,128,163,231,16,244,57,68,233,20,250,104,28,166,38,49,110,177,66,17,127,187,199,42,122,137,238,193,107,95,247,227,189,113,10,75,176,213,70,136,141,144,164,87,37,42,23,127,141,164,183,78,139,218,128,235,216,244,18,237,172,200,24,113,21,112,117,16,59,41,136,9,155,210,169,170,75,221,91,65,24,147,102,178,110,106,220,193,124,222,37,240,191,119,132,54,85,182,115,221,35,234,48,168,174,45,235,227,126,189,190,94,228,240,101,211,112,91,127,57,151,48,255,55,129,17,139,254,252,80,114,75,182,22,51,188,91,109,69,192,230,36,179,138,232,162,3,131,1,137,52,56,241,139,77,224,236,177,175,210,192,80,187,135,105,224,116,81,229,132,151,223,232,67,207,191,76,55,255,26,58,42,239,48,161,0,251,40,166,214,231,173,40,122,99,165,8,170,84,14,152,38,0,60,172,198,70,127,95,75,16,127,6,6,164,64,141,172,238,59,222,131,224,43,38,141,127,96,100,62,2,30,34,180,54,230,3,150,5,231,193,31,96,61,201,7,121,144,136,49,68,114,1,180,193,165,67,117,98,92,230,45,153,167,120,227,39,220,201,40,218,176,242,79,255,176,197,84,44,219,188,24,123,109,252,180,10,54,56,205,152,158,23,34,226,122,114,118,86,190,135,145,210,139,53,111,80,254,12,33,99,114,50,69,174,102,63,40,134,203,163,241,201,210,132,197,30,194,21,41,67,111,169,59,137,176,140,87,223,35,219,148,41,17,47,87,132,177,195,184,155,62,44,57,51,61,166,176,0,78,17,239,248,132,24,90,111,0,114,11,243,116,156,217,62,172,237,169,184,102,49,203,132,170,173,228,19,92,247,110,129,213,51,246,166,189,117,14,122,133,32,168,49,250,110,109,130,233,47,207,247,73,245,53,4,163,18,37,68,143,96,159,144,46,41,170,94,167,114,150,192,69,209,251,219,13,111,213,186,98,240,94,100,151,249,137,215,40,31,202,233,102,233,87,154,45,180,231,125,239,156,180,218,112,223,97,62,42,141,65,252,126,67,80,247,250,233,208,232,35,192,160,163,194,226,126,10,45,236,6,185,108,216,204,37,163,11,79,111,48,215,146,155,158,134,141,203,55,89,61,222,33,78,82,125,74,58,124,11,39,39,25,125,19,251,109,165,69,192,6,62,4,243,172,60,180,97,171,114,245,37,98,216,173,83,172,42,223,203,123,98,129,233,163,55,50,102,117,207,223,131,8,155,151,246,17,163,194,153,249,69,72,100,93,139,51,97,70,143,174,24,21,44,73,67,97,203,26,232,224,113,226,185,74,242,203,51,164,179,209,188,168,1,102,93,74,120,214,135,191,193,209,7,112,218,199,145,10,92,23,239,226,242,205,187,159,126,171,125,35,158,53,118,74,19,183,224,31,116,118,13,32,211,205,92,131,123,48,181,32,124,7,233,247,254,24,251,109,189,0,184,187,80,73,194,94,100,239,81,170,145,20,235,132,230,56,141,90,22,151,198,88,153,66,134,20,94,237,62,58,110,218,255,50,111,198,109,211,202,21,39,7,30,238,147,85,35,154,58,236,112,221,70,102,211,120,115,74,109,188,70,229,214,191,122,134,120,195,231,217,122,35,113,9,110,154,50,82,32,35,111,159,191,205,52,223,124,250,77,32,228,68,131,215,255,245,107,10,80,105,104,31,4,173,207,219,31,219,171,182,182,254,211,181,183,202,185,238,165,167,38,248,72,193,90,249,154,165,80,64,209,68,160,49,226,93,135,143,48,97,211,47,187,29,120,160,203,115,39,87,245,227,220,244,5,60,57,251,126,42,117,244,81,69,98,77,242,210,249,188,19,130,253,198,56,95,174,249,187,185,215,132,16,226,25,29,180,25,54,143,69,121,134,79,117,180,218,210,211,236,58,207,231,69,104,95,149,166,212,59,105,131,68,83,21,233,177,143,135,83,237,99,3,20,58,123,234,249,128,199,117,238,163,124,52,215,100,124,76,146,61,253,192,135,196,87,201,115,149,98,141,214,85,252,207,188,13,34,208,166,93,132,22,39,44,115,121,203,93,78,137,69,196,253,197,120,148,36,21,208,5,95,43,5,122,145,41,160,12,117,201,143,36,62,133,73,185,73,185,155,194,182,166,248,96,33,9,112,7,42,39,42,203,253,23,196,161,187,66,234,58,217,44,48,7,139,47,158,58,153,179,83,189,27,100,164,156,234,199,98,117,100,38,11,24,163,169,221,244,159,173,191,177,229,194,60,25,229,142,239,38,104,95,145,238,47,214,188,90,21,66,126,66,111,210,228,101,36,242,172,130,97,234,90,20,62,166,38,11,198,159,44,245,249,131,27,135,234,87,83,2,62,185,253,129,60,125,165,26,164,138,148,193,87,246,201,45,72,3,33,31,191,29,45,33,15,238,109,8,39,100,38,195,128,83,7,133,205,161,144,113,161,194,75,111,13,7,188,92,227,251,80,96,18,64,26,145,25,40,183,204,243,127,122,119,214,146,16,231,175,187,101,92,23,25,172,45,195,139,252,212,135,73,86,24,33,203,30,64,143,202,39,238,180,143,39,141,32,30,65,76,186,57,211,14,143,45,98,183,16,106,103,221,249,6,53,137,24,139,142,183,198,247,95,139,222,54,254,33,32,110,206,70,243,213,3,192,199,172,149,164,83,182,93,148,177,50,21,141,173,13,238,107,195,127,67,110,37,112,43,142,183,230,190,209,160,162,156,23,27,134,24,34,52,140,72,249,61,178,169,148,8,130,66,147,91,31,208,121,252,240,86,4,49,94,172,145,170,231,175,155,91,81,34,65,35,19,119,54,89,16,204,192,75,121,73,147,188,144,117,13,228,38,41,170,216,212,138,219,190,30,66,160,168,25,44,46,139,91,239,138,252,75,214,254,70,38,167,102,27,83,199,3,87,193,132,173,198,46,20,126,199,149,77,169,28,80,101,104,137,62,96,184,186,195,156,232,54,165,152,181,234,109,221,187,146,210,235,81,120,213,202,4,54,76,73,143,91,58,186,245,234,169,42,230,22,18,250,90,107,166,223,111,105,64,154,164,4,224,90,136,137,59,115,161,111,33,203,195,109,85,228,153,230,42,60,71,72,5,2,62,18,247,95,210,226,191,18,86,215,250,188,187,220,235,252,237,222,248,38,43,49,68,167,200,78,234,221,147,5,179,21,224,63,87,13,134,86,163,63,36,111,99,183,191,107,252,17,109,125,244,237,227,124,248,96,249,123,151,124,55,89,15,60,83,228,51,167,78,178,149,160,185,115,84,80,74,205,223,140,130,90,11,7,178,123,40,235,140,10,228,159,27,22,21,27,35,97,198,101,3,45,152,101,159,133,198,240,50,167,96,88,76,87,206,44,39,249,11,105,101,233,91,94,0,117,182,228,62,63,40,7,175,93,108,94,109,10,13,105,155,235,242,84,115,42,225,207,146,64,214,155,15,160,204,116,101,205,129,106,90,130,161,1,205,66,106,134,110,197,2,121,251,255,76,57,17,131,177,22,249,53,191,239,3,209,175,23,202,194,236,120,82,27,150,175,201,140,218,92,66,6,242,27,242,72,21,153,249,76,147,161,201,108,133,37,82,63,157,26,16,157,157,53,227,144,45,33,251,159,166,102,14,146,8,130,61,71,232,239,55,149,154,94,62,201,196,46,66,64,182,197,173,177,174,129,184,239,93,144,26,35,78,229,198,0,35,11,0,24,58,31,116,17,14,148,173,217,199,57,30,154,70,63,65,205,96,139,15,161,221,167,15,248,53,144,210,247,198,28,89,183,77,185,161,137,46,60,33,250,124,201,6,162,14,149,173,139,246,183,196,97,174,62,140,41,85,124,32,241,157,180,188,116,43,88,101,206,143,162,87,136,175,53,8,137,29,26,223,233,139,150,187,232,66,160,175,236,60,249,74,124,88,0,169,71,249,158,190,158,10,136,161,14,192,129,205,123,206,139,139,194,116,10,232,178,229,135,29,133,175,175,159,206,251,200,116,49,111,179,231,204,59,114,82,198,44,18,188,92,104,214,214,0,99,131,131,20,13,139,95,163,166,89,240,125,147,162,92,27,236,208,194,108,76,213,90,135,100,0,183,53,71,191,95,49,61,227,177,149,62,19,73,102,79,254,208,162,75,217,114,173,130,116,114,179,103,102,51,151,84,216,208,210,52,137,180,99,72,124,128,249,247,136,183,36,28,249,242,125,70,239,231,22,75,183,222,194,216,180,98,166,182,159,27,186,214,74,253,234,220,112,80,103,58,215,113,70,28,68,149,92,181,110,119,67,179,179,9,96,140,249,194,72,173,244,144,58,9,141,246,68,237,118,179,124,164,96,125,30,196,126,104,19,176,107,25,7,162,89,236,206,184,139,167,166,16,55,67,7,93,251,90,252,86,252,171,140,238,114,28,106,253,2,64,26,18,192,199,145,70,224,41,158,81,211,254,47,235,74,231,215,176,97,187,165,209,79,109,189,21,14,209,97,193,29,254,42,24,157,72,5,143,9,214,54,90,86,243,143,140,12,163,2,158,213,69,48,232,80,165,123,73,197,247,8,241,232,198,127,142,153,236,153,145,20,27,64,72,56,14,13,147,102,116,211,20,44,176,108,13,229,36,230,81,206,9,197,5,42,177,137,125,239,52,138,145,92,76,16,223,134,138,221,234,177,91,177,210,67,1,151,117,176,201,125,211,227,144,217,180,31,53,97,31,147,33,222,114,225,63,236,245,62,68,54,30,147,134,96,110,84,124,209,201,141,3,62,115,79,24,228,194,3,74,218,184,3,66,224,170,40,123,37,121,61,129,54,53,103,197,43,89,135,6,26,104,193,193,136,152,56,142,183,224,128,35,138,123,231,218,184,64,116,133,134,79,71,93,163,18,65,127,217,137,72,42,147,44,193,117,255,58,201,221,139,83,224,169,171,21,200,243,196,43,229,12,27,96,110,87,50,136,174,144,220,236,35,210,9,136,71,10,14,95,205,206,230,46,210,240,140,197,31,1,18,188,0,238,15,228,67,49,220,86,132,126,70,124,204,88,118,84,251,214,36,171,200,70,160,93,190,20,193,149,122,208,201,60,231,13,227,143,217,98,120,101,241,47,166,37,0,246,166,53,179,69,210,170,111,102,237,39,29,58,140,90,17,30,66,50,240,135,134,156,130,216,158,96,227,238,43,173,150,62,156,252,12,213,121,200,99,178,38,253,248,51,29,232,51,139,88,26,160,174,235,4,96,47,68,39,65,224,118,4,246,129,110,151,23,33,196,101,107,18,57,33,181,138,239,175,105,157,49,247,51,175,4,49,223,166,210,239,121,16,164,212,230,198,33,63,150,165,9,54,147,43,215,241,224,55,27,106,204,89,39,184,161,80,49,4,115,240,147,14,244,80,211,157,188,47,240,27,232,175,82,215,194,147,55,86,12,143,240,196,252,206,171,147,238,96,167,220,204,222,124,57,43,217,33,94,205,196,224,116,99,78,12,233,159,227,1,76,43,79,235,217,146,66,161,211,175,94,65,74,199,243,183,6,81,84,203,242,106,233,76,173,158,214,45,43,108,174,250,106,136,126,230,63,14,251,213,18,71,87,50,64,255,236,85,183,102,109,45,1,174,202,9,149,185,253,197,58,210,45,138,136,51,85,221,138,73,184,106,127,134,253,72,58,18,180,62,151,29,82,139,220,202,116,64,248,20,81,96,109,47,138,242,186,193,36,58,228,83,194,172,38,0,252,218,244,10,112,115,142,57,210,57,11,64,200,229,159,61,193,101,132,118,218,80,148,208,24,56,50,42,216,65,221,198,222,42,94,40,195,189,60,175,28,71,25,114,164,42,45,8,67,46,142,204,238,25,167,37,150,221,46,11,216,39,161,104,150,116,113,1,94,67,6,9,155,180,85,217,5,244,160,99,51,203,177,93,136,13,60,29,150,143,141,45,240,202,86,52,252,208,169,251,4,6,159,54,129,123,18,109,207,1,191,79,38,187,105,43,96,244,160,246,58,53,1,126,98,82,106,12,250,65,44,103,65,155,146,190,0,201,249,32,20,57,171,220,149,156,114,51,66,148,220,137,156,113,120,32,169,126,124,13,130,177,138,31,55,46,148,240,128,29,71,141,116,145,112,8,66,189,190,216,123,114,164,94,213,103,242,213,46,100,240,150,169,179,251,110,47,164,50,174,245,163,245,59,14,243,8,35,82,74,151,19,130,70,32,129,139,54,14,190,35,131,230,71,44,133,253,187,52,219,118,239,235,58,76,31,196,252,32,242,187,197,157,187,55,29,121,51,214,250,24,234,46,96,133,232,102,63,43,191,186,226,113,189,64,205,186,249,119,43,113,194,61,250,58,221,69,191,75,14,152,187,167,243,108,156,124,46,5,218,175,243,118,7,240,85,167,144,192,213,61,210,252,162,165,162,46,86,124,240,63,149,35,88,159,198,71,207,56,140,25,144,133,248,190,191,241,252,13,124,234,108,165,9,106,44,119,178,102,193,221,168,140,143,125,102,211,106,41,163,241,103,12,131,227,10,78,64,224,131,209,128,108,224,131,81,196,188,208,57,0,65,7,171,245,92,68,97,155,26,19,0,220,173,153,62,182,16,55,19,229,89,135,80,157,145,162,168,60,3,54,77,8,252,62,78,45,97,13,187,5,95,233,221,143,244,218,237,9,191,191,111,230,19,235,185,24,229,133,236,211,127,22,70,243,186,237,63,6,52,140,155,111,172,124,143,130,20,198,240,17,48,164,10,74,221,17,240,102,82,73,186,66,214,132,28,226,189,253,197,216,71,13,102,76,54,192,250,157,250,97,33,169,125,119,76,18,127,148,89,55,79,41,27,171,173,241,40,25,242,210,152,51,104,129,66,79,162,178,205,127,78,159,148,90,244,237,62,200,220,157,71,215,30,45,95,17,166,151,2,107,156,25,214,202,113,205,64,70,182,24,9,62,176,176,190,16,176,188,96,117,242,77,22,88,50,108,118,138,246,209,82,199,143,160,77,201,121,197,140,194,143,8,181,195,45,95,221,40,139,214,14,153,166,70,195,180,165,102,177,227,237,193,79,231,55,66,91,102,116,212,200,47,182,152,106,44,255,140,122,66,158,160,250,117,112,5,28,227,9,101,161,115,43,75,216,160,129,201,85,4,155,212,168,94,163,160,204,9,102,25,233,102,160,184,227,106,238,100,129,31,84,122,126,254,145,223,210,150,80,172,229,177,248,245,3,169,238,5,16,2,78,51,54,207,82,72,227,99,136,26,105,129,53,22,17,45,214,181,195,68,36,56,169,195,242,5,8,191,67,154,4,98,246,26,112,153,140,77,237,240,2,154,115,169,245,170,100,202,110,18,149,98,123,104,24,71,192,232,157,222,215,83,47,36,18,129,246,103,237,227,185,218,144,30,199,136,151,160,138,100,74,32,166,208,86,67,75,237,132,120,166,153,52,64,10,225,171,2,81,131,86,59,191,48,93,62,184,125,186,164,181,232,91,66,146,242,21,173,53,43,188,74,248,215,108,185,224,167,76,81,71,206,93,12,235,166,22,241,224,190,133,235,131,111,103,60,230,112,49,52,171,86,194,94,59,123,115,191,87,69,241,194,32,229,82,37,247,66,83,202,39,30,54,213,89,3,78,249,44,22,248,167,57,0,84,189,32,168,147,103,6,140,148,202,187,193,37,38,180,46,29,166,57,72,223,230,106,44,108,111,251,141,251,89,7,111,191,116,203,52,57,144,49,241,196,170,155,145,94,130,81,6,8,48,239,173,230,55,130,69,187,163,225,66,214,151,106,237,182,124,152,252,164,152,71,188,138,18,156,234,158,96,75,48,112,107,71,163,19,180,198,24,225,112,151,114,89,6,217,49,26,232,78,138,51,90,69,91,193,126,130,54,20,217,158,121,249,61,85,203,2,97,83,109,237,170,254,0,91,197,122,244,126,45,233,234,109,127,179,19,219,93,31,65,76,94,19,176,192,62,20,225,161,144,181,212,117,211,254,177,20,119,165,4,191,21,105,172,116,103,36,198,101,166,240,111,212,21,87,239,249,26,153,242,52,76,142,34,251,237,81,66,187,57,122,29,236,37,110,21,148,230,218,247,104,63,1,234,5,69,199,73,134,157,172,42,231,147,224,75,141,129,211,82,4,89,195,246,70,171,181,93,183,55,108,159,166,33,84,4,185,111,204,210,203,121,247,47,11,38,196,128,175,73,224,158,13,7,251,219,162,20,164,80,64,199,241,117,6,96,69,101,173,208,37,165,211,107,165,193,43,31,159,138,214,247,2,33,12,191,208,158,105,240,17,229,141,41,237,45,38,45,115,88,232,28,191,188,150,228,13,47,17,235,94,149,41,105,96,203,124,26,222,106,9,189,50,92,15,120,136,57,57,255,99,51,112,155,217,186,209,181,137,48,198,43,39,230,86,230,26,217,240,223,93,238,195,80,220,79,238,160,255,161,52,146,25,191,179,0,106,203,39,179,207,46,133,153,151,239,88,57,122,189,135,89,178,115,230,216,10,114,143,251,93,168,61,169,202,150,202,196,237,75,49,182,183,125,110,19,34,1,136,14,89,81,155,227,118,201,69,250,152,109,216,132,250,88,147,48,2,191,100,195,211,13,126,162,119,72,133,229,123,207,22,23,212,210,63,155,150,227,57,166,222,129,67,70,42,85,154,245,247,41,193,230,95,156,113,40,103,226,86,19,6,181,49,124,103,224,189,223,33,119,236,24,20,229,68,141,154,5,89,177,163,212,125,152,33,38,48,226,24,141,151,158,51,86,207,22,139,80,172,113,125,82,37,229,71,24,29,22,151,195,95,177,29,49,74,158,121,217,68,52,92,168,158,88,196,251,22,3,155,79,122,252,156,221,200,181,70,100,216,71,156,175,156,86,2,231,130,108,43,211,119,75,181,114,163,95,222,24,246,255,186,183,186,101,37,137,223,53,194,47,117,58,55,235,209,179,14,167,242,26,134,221,36,193,38,118,184,207,96,67,32,145,250,154,128,94,25,66,185,48,57,213,130,222,58,197,173,252,78,101,199,141,206,155,94,81,157,155,216,239,200,168,141,203,59,210,55,17,55,170,5,110,70,51,20,19,17,219,187,198,121,220,48,135,101,52,185,215,244,4,37,229,220,138,211,126,144,244,210,14,194,134,9,176,26,52,128,5,94,173,63,199,171,196,37,142,16,185,13,98,224,38,105,153,24,182,124,179,35,177,69,226,224,127,75,236,2,98,7,44,185,3,14,107,156,129,152,51,36,29,203,211,203,108,162,74,162,216,89,12,128,9,112,14,157,147,3,227,248,177,51,228,239,231,213,231,254,82,42,244,137,106,99,170,156,192,66,71,139,213,5,156,125,195,124,229,130,190,205,89,225,241,254,176,95,30,219,40,248,129,218,116,222,75,183,241,249,60,88,178,52,92,157,156,113,232,162,36,107,47,55,17,155,162,70,224,125,82,84,211,203,26,49,246,193,94,207,161,122,216,126,138,16,206,87,28,38,45,30,196,186,30,68,206,95,156,208,218,236,93,107,125,217,121,46,223,4,69,183,46,238,206,71,72,167,159,167,48,118,25,0,159,147,140,99,166,172,4,113,21,161,52,102,54,219,194,90,106,50,6,156,202,21,86,112,33,45,53,6,124,162,83,226,178,246,1,165,167,177,190,237,128,219,79,114,30,187,31,146,10,157,251,80,124,108,191,233,91,104,68,35,156,13,54,123,191,37,77,245,82,222,206,8,246,133,27,217,87,116,7,145,65,128,81,142,250,19,137,207,10,217,88,150,119,183,30,231,123,9,189,145,113,150,247,204,148,101,142,228,144,127,101,122,157,153,221,45,112,44,139,13,223,94,18,221,245,14,185,252,132,117,15,173,122,121,1,251,109,2,107,25,97,29,180,199,11,124,161,138,37,92,119,254,245,118,34,128,28,100,200,80,5,114,99,208,232,126,215,247,226,193,129,111,229,166,12,107,30,67,118,84,156,100,158,204,44,28,118,134,227,10,22,153,126,77,13,134,137,18,167,115,62,98,60,182,179,66,109,93,146,39,135,247,137,193,45,175,156,83,87,217,63,250,57,154,128,151,152,45,35,43,126,198,229,219,126,200,145,4,236,251,153,196,162,89,73,134,96,119,107,128,190,147,228,64,73,220,100,124,73,203,91,213,77,92,68,50,107,69,237,110,138,228,193,175,162,213,78,39,118,105,39,11,196,157,25,195,35,53,250,121,123,219,197,179,143,206,30,210,251,106,231,243,37,84,55,23,7,30,84,11,121,92,53,9,191,28,49,57,237,112,78,183,12,215,243,99,159,238,14,246,197,136,207,69,0,120,99,89,37,184,54,94,128,204,224,174,118,50,226,59,151,162,115,167,144,223,213,199,4,87,55,193,10,212,169,238,242,254,70,213,252,87,32,245,18,157,79,122,232,143,103,31,93,140,93,243,91,156,91,223,136,12,68,98,200,179,170,185,195,112,27,104,3,205,165,28,186,174,118,57,189,119,144,158,95,158,164,143,139,58,87,217,43,22,68,43,126,240,70,94,163,225,233,248,227,168,70,198,16,51,205,239,192,4,124,244,190,80,130,188,253,65,63,201,98,243,142,139,238,115,52,164,188,234,11,203,33,66,111,40,174,113,78,139,135,102,209,122,166,53,10,2,10,140,215,139,223,100,11,23,208,126,65,214,52,37,98,93,37,250,159,75,209,155,248,86,107,5,114,199,254,105,179,240,132,18,228,65,136,188,180,168,141,149,43,234,13,114,25,92,32,8,212,172,186,194,234,241,77,20,142,76,140,225,110,176,248,93,52,69,8,47,143,25,99,166,56,37,228,218,183,234,205,236,237,168,228,136,179,145,123,254,230,182,37,220,223,96,199,45,24,147,73,86,254,47,90,124,89,129,192,199,167,216,217,62,148,163,46,107,74,67,155,206,30,163,44,42,238,69,77,5,86,126,151,131,136,59,134,63,72,23,50,35,228,75,48,172,147,4,200,35,217,142,56,51,159,145,237,51,218,27,192,43,193,90,63,194,218,149,77,69,58,68,24,177,235,144,245,52,41,241,21,63,202,204,123,60,245,245,147,59,230,53,58,179,177,6,108,72,142,101,202,171,147,1,238,27,183,145,157,7,29,13,111,137,129,183,185,196,139,126,204,48,220,237,170,227,65,153,226,170,245,241,69,250,74,235,39,129,115,94,113,165,212,140,219,239,255,30,2,150,71,167,222,250,123,230,253,102,110,67,175,23,73,166,0,144,47,148,163,151,221,23,81,24,247,230,191,244,11,1,206,112,51,40,182,33,40,163,61,107,169,167,6,202,202,72,255,23,102,172,225,38,148,226,88,109,43,255,21,145,157,184,0,241,95,26,253,89,42,53,13,149,184,8,74,173,119,80,63,39,122,131,186,46,224,96,135,125,146,230,186,215,105,91,230,163,169,125,167,150,59,214,137,125,94,22,30,51,110,143,175,201,170,44,185,136,253,28,105,89,77,41,65,135,12,60,237,170,191,75,127,88,149,34,205,123,6,139,121,217,249,166,254,165,197,104,144,84,48,58,172,21,122,128,85,199,148,36,114,91,239,123,1,206,8,169,49,206,39,142,97,137,189,224,169,198,119,13,171,201,140,49,157,103,118,88,94,210,27,126,242,245,68,55,25,204,114,244,247,64,29,145,137,154,56,172,22,62,19,227,79,143,90,5,12,201,194,154,224,71,103,79,31,119,20,146,114,219,19,44,92,21,211,69,49,20,95,47,183,25,195,60,209,50,238,182,244,59,9,94,112,27,36,210,214,7,152,57,84,87,219,76,117,252,173,214,2,188,162,120,141,43,194,108,127,121,25,148,205,129,10,46,39,41,144,243,52,218,147,187,37,188,247,50,228,177,63,51,214,17,10,240,24,244,129,34,87,146,124,5,230,163,171,120,234,22,101,103,156,68,245,144,114,132,132,244,163,47,127,235,219,88,243,187,140,196,153,78,126,139,116,152,107,147,27,119,0,2,213,231,59,70,73,214,67,31,130,51,71,155,189,211,225,165,140,83,24,36,56,202,105,50,33,140,155,216,216,209,252,54,156,254,20,81,120,206,235,241,53,194,44,177,128,30,239,26,95,124,88,90,21,132,123,188,158,141,127,241,223,95,178,108,21,221,145,222,26,192,180,84,129,78,175,117,146,57,215,116,10,13,53,12,252,227,64,32,115,213,68,143,238,155,225,101,184,132,28,92,127,89,232,1,139,160,185,99,115,92,29,188,211,254,180,85,121,47,205,53,199,122,73,153,119,188,74,163,229,129,90,48,50,178,91,189,168,116,38,32,114,55,89,132,116,208,124,128,113,113,16,206,199,26,163,212,71,1,250,155,96,53,100,44,246,31,136,208,243,220,60,176,23,103,88,245,48,51,59,225,235,226,76,182,53,49,135,126,117,23,4,0,51,62,11,237,65,252,21,246,193,84,14,85,217,111,240,108,226,134,59,194,210,198,214,9,245,99,101,81,3,89,134,225,173,80,61,204,115,250,25,191,22,137,42,177,155,159,237,248,200,39,189,1,66,189,88,8,198,57,47,194,59,150,74,50,244,192,145,124,139,137,9,88,183,226,179,162,219,55,201,222,186,109,36,242,146,104,134,170,9,120,67,123,240,251,118,184,113,206,203,242,204,29,95,103,160,139,24,229,246,174,44,232,1,92,51,119,121,192,74,200,193,169,150,115,168,56,37,31,105,175,166,10,183,252,135,115,233,34,0,229,124,183,246,177,143,42,237,125,2,142,154,240,49,228,213,15,77,123,202,79,84,0,147,189,200,161,106,243,41,87,86,158,216,240,246,100,112,9,91,213,220,206,108,190,57,220,218,99,189,47,194,120,28,127,254,169,178,91,243,109,75,134,210,210,244,242,159,54,217,20,133,68,233,153,234,101,91,233,30,96,171,224,92,91,176,236,182,188,20,131,21,122,84,104,171,14,236,252,249,75,212,235,191,95,11,62,141,94,241,165,26,219,173,197,153,214,168,223,240,94,213,113,148,95,22,212,203,134,117,232,60,147,51,11,201,54,4,81,122,170,58,150,209,147,128,196,78,68,78,148,160,114,198,127,162,120,180,68,133,22,76,101,119,11,93,246,9,232,183,127,140,173,92,221,236,51,178,45,217,246,70,118,91,129,102,24,199,252,7,6,116,81,43,240,49,115,77,164,134,23,10,184,92,26,223,238,174,254,108,5,221,29,205,3,38,30,51,143,196,202,21,102,228,51,105,45,191,54,175,140,175,135,132,56,183,9,116,20,68,132,18,220,233,176,239,82,87,160,87,75,33,255,121,193,156,78,230,23,79,64,52,198,99,148,130,106,107,8,203,26,34,248,194,178,123,242,238,250,69,219,168,219,185,118,64,221,220,7,62,58,172,34,161,85,252,155,52,152,60,87,103,183,167,226,234,225,170,247,90,38,143,81,89,210,156,20,60,194,148,113,179,171,5,77,184,78,26,208,131,200,86,18,46,116,74,134,61,119,29,194,3,117,40,80,168,90,103,191,42,184,95,218,91,28,155,54,146,65,95,188,105,77,14,205,75,249,117,46,221,98,224,169,93,190,83,43,182,146,208,7,135,154,99,250,12,2,189,246,105,220,172,175,69,1,167,218,186,57,136,247,112,149,221,32,11,202,229,160,52,60,200,208,193,198,75,246,250,53,55,150,176,139,93,85,222,206,205,111,9,73,162,186,211,69,140,188,136,164,203,223,18,225,119,181,234,138,60,23,112,75,105,15,203,7,125,177,246,31,45,74,151,48,22,139,175,136,183,250,161,111,94,119,158,113,175,140,79,29,122,65,55,233,80,125,200,31,209,18,35,82,3,116,190,125,208,46,253,125,100,73,160,238,5,244,38,184,200,7,167,119,122,165,28,250,26,52,110,188,151,63,208,63,248,94,165,164,111,163,146,32,37,5,60,85,192,27,61,24,60,161,222,0,4,254,155,189,84,196,0,157,35,12,162,103,138,192,135,38,45,40,41,69,63,30,177,222,41,253,200,54,63,230,237,20,103,172,23,99,192,215,2,181,198,52,12,1,157,162,169,147,206,27,237,188,158,40,214,164,233,240,100,201,245,24,178,38,205,66,140,166,43,132,117,143,233,22,167,190,202,18,188,127,240,184,49,182,87,84,214,121,140,169,20,29,122,133,69,18,168,61,132,146,108,35,131,109,86,101,183,150,34,77,90,194,24,46,232,28,48,183,206,47,100,61,163,165,74,17,92,27,210,106,16,222,186,117,41,103,197,144,3,27,9,248,132,189,88,83,122,219,49,116,2,50,30,40,205,76,130,35,126,83,228,228,138,171,171,135,39,196,227,87,106,235,241,239,86,179,253,11,23,99,7,66,41,158,178,157,76,234,6,5,214,254,184,155,181,84,197,165,122,251,119,249,236,166,219,144,14,253,20,200,71,185,128,249,58,15,196,101,206,51,124,190,50,159,255,10,172,123,168,253,230,89,10,236,71,194,62,129,71,92,165,85,0,198,135,157,141,191,50,13,140,37,124,110,249,46,46,25,251,68,145,8,18,120,51,137,142,119,244,148,246,141,26,132,163,135,241,35,159,49,77,209,163,230,111,6,242,146,195,49,170,2,124,194,17,165,42,155,254,34,50,37,48,67,234,117,90,102,69,129,61,195,172,78,87,34,46,79,146,168,210,166,122,231,226,222,204,251,20,75,223,196,242,130,34,225,110,75,207,175,78,24,239,45,171,104,198,59,0,19,49,11,243,112,43,250,158,62,80,155,237,46,52,188,185,245,171,68,197,202,251,110,93,211,94,67,191,87,157,87,233,13,61,47,52,206,80,194,167,66,67,198,170,244,247,174,171,50,79,255,184,161,14,254,202,162,162,254,221,148,221,251,90,102,154,71,98,61,150,1,32,250,227,57,240,168,21,174,152,107,235,75,2,198,35,117,161,148,210,231,214,184,87,241,102,16,184,144,221,165,158,108,17,177,46,228,156,159,149,123,171,239,250,40,10,62,189,159,144,124,7,64,76,122,161,214,158,46,206,191,99,142,189,68,40,168,172,65,88,130,102,169,121,107,188,201,117,35,139,212,14,176,77,110,172,197,14,238,254,189,108,234,224,228,68,226,121,230,183,185,224,25,14,142,86,3,2,21,133,116,109,24,125,214,126,192,236,107,42,30,208,247,43,102,62,205,11,213,177,80,163,92,245,82,101,244,192,151,191,169,102,204,190,167,232,66,226,12,115,238,131,188,181,235,30,55,68,17,186,125,64,121,44,39,147,240,53,20,40,101,224,109,239,226,32,115,253,200,113,202,118,207,81,168,138,146,224,129,38,168,181,120,87,225,170,24,6,223,254,59,48,103,66,191,112,18,100,232,149,121,191,132,39,231,12,223,111,202,150,238,150,76,143,41,37,183,222,8,16,24,33,99,101,144,218,10,68,70,133,97,95,109,42,67,13,102,0,93,189,206,41,149,160,206,101,195,209,76,22,231,109,76,142,113,78,222,63,202,227,65,140,154,29,47,96,41,58,77,137,107,249,152,7,126,53,105,31,221,134,107,150,14,18,108,110,152,91,57,88,146,199,220,12,79,116,220,134,180,176,224,71,97,52,154,76,94,230,58,14,196,154,89,27,162,219,96,227,91,143,175,92,36,179,222,30,59,163,32,250,146,96,163,83,134,33,18,27,99,127,113,171,35,52,143,96,219,71,71,254,216,30,244,75,88,241,242,50,213,1,83,56,154,152,153,219,130,166,175,82,10,125,111,96,137,38,46,205,11,85,195,29,184,117,250,218,58,49,10,40,30,139,211,81,157,249,51,33,100,201,34,96,197,189,206,48,180,50,2,111,154,109,10,90,116,189,224,85,45,153,10,96,210,142,179,131,174,213,131,9,90,194,235,113,201,152,223,253,134,198,136,215,196,121,114,145,127,197,63,226,22,10,124,149,177,37,12,217,218,113,9,235,142,49,103,237,98,82,140,8,127,97,56,61,78,76,142,106,216,56,78,153,139,60,223,243,28,34,38,199,137,132,50,118,151,58,141,192,20,249,138,53,114,177,45,146,78,147,234,123,244,61,157,119,7,88,41,82,17,102,213,59,93,79,45,40,157,139,219,81,12,134,18,77,1,101,45,228,155,66,227,243,242,202,71,136,205,94,102,239,237,253,62,207,30,222,178,58,135,219,74,150,232,27,209,251,37,198,33,83,209,39,249,183,21,38,213,39,143,198,149,91,161,250,193,43,45,233,70,234,118,173,231,180,151,157,138,7,167,198,81,194,51,164,200,83,56,176,121,167,225,108,50,245,125,137,148,215,111,59,19,64,109,5,114,176,218,137,186,235,94,254,156,96,194,168,34,159,84,171,68,70,215,155,148,244,240,11,54,128,75,56,161,201,231,65,137,194,113,32,89,201,13,141,169,131,94,198,168,132,135,101,50,165,181,8,159,184,15,19,74,16,105,43,25,168,214,106,76,164,64,91,12,74,22,16,124,27,121,145,188,125,255,96,131,33,245,145,180,29,62,194,137,30,62,243,129,77,13,158,163,117,162,206,61,236,135,244,220,166,174,217,73,139,0,254,201,26,125,241,33,68,187,155,235,119,25,72,196,151,8,255,8,84,250,43,102,204,134,121,186,123,144,48,2,235,7,229,41,190,150,181,169,203,226,194,118,180,182,162,220,222,14,52,114,197,229,86,207,201,148,241,246,69,68,231,8,57,6,21,171,44,83,134,151,83,25,48,142,91,248,21,21,213,9,104,208,21,12,133,100,100,144,124,237,193,56,180,34,39,246,232,53,212,121,61,127,221,103,74,114,150,223,11,229,210,6,76,40,95,192,199,167,100,100,64,117,44,73,13,187,42,241,47,212,35,164,55,64,85,88,41,102,68,165,110,72,100,66,38,33,14,166,233,157,80,35,137,1,69,63,111,169,42,19,65,190,106,104,216,90,154,147,190,183,207,177,145,142,190,213,148,10,228,251,99,58,72,148,192,227,20,1,79,110,181,47,89,218,133,7,75,111,229,49,60,97,179,158,28,51,110,139,80,56,147,33,182,227,153,92,32,1,241,44,181,143,24,16,252,26,129,134,63,65,186,1,160,90,254,21,88,43,220,101,222,156,214,211,98,172,42,254,193,103,147,61,229,181,85,228,223,127,163,201,157,106,97,82,251,201,89,32,245,234,92,103,151,70,111,44,210,74,166,88,95,204,82,185,9,218,72,146,27,181,139,97,122,22,228,206,84,237,87,140,101,100,110,216,186,226,110,186,109,140,162,59,52,3,26,96,176,41,84,66,47,216,100,110,106,2,55,106,165,232,43,156,42,193,122,42,74,224,96,101,41,240,141,4,88,29,113,31,121,80,196,152,15,234,154,70,129,228,97,137,99,89,108,64,143,32,111,199,220,209,192,20,24,80,192,202,191,169,156,133,210,36,179,17,149,67,213,52,180,176,134,253,181,179,174,87,217,236,254,162,137,201,192,88,23,89,195,231,73,182,226,224,149,99,172,221,135,5,241,132,86,236,118,69,50,108,27,103,65,17,127,75,11,160,71,85,227,148,153,62,103,83,250,192,254,215,123,252,157,8,112,132,210,193,21,244,168,131,44,69,226,190,243,10,225,163,84,190,118,32,19,193,234,220,32,188,74,90,197,143,70,191,99,113,186,143,49,131,109,253,62,234,221,183,103,238,89,65,67,11,230,9,222,24,95,129,14,228,125,126,166,49,29,239,36,39,124,130,203,200,105,29,231,182,43,1,179,193,103,230,251,205,22,182,65,191,137,110,165,113,180,60,209,87,212,7,69,241,130,157,125,59,225,89,244,120,134,142,170,92,19,65,251,87,163,83,32,185,163,202,187,191,34,192,183,186,236,30,222,225,180,237,142,162,77,93,190,100,248,70,134,164,253,105,255,142,189,83,50,161,225,223,241,240,252,170,90,122,221,22,108,187,81,31,252,76,218,238,217,175,90,110,37,190,8,65,147,181,160,202,39,24,230,218,92,233,102,123,98,72,215,163,152,111,198,25,215,60,213,1,254,4,168,45,13,40,238,142,158,60,70,241,144,183,215,236,146,149,13,234,215,133,3,112,135,7,8,40,195,214,105,244,172,246,200,198,238,153,112,100,59,137,18,122,9,204,17,41,181,111,41,61,21,160,16,170,194,218,178,62,88,92,199,233,200,24,70,246,142,224,164,200,210,237,216,75,100,45,115,160,117,92,38,226,170,215,156,203,215,210,248,231,199,216,248,161,125,167,132,103,180,186,9,249,4,154,16,237,107,80,28,27,235,150,39,210,201,153,66,17,97,165,29,15,167,130,23,77,17,106,160,90,248,47,219,164,20,127,81,248,1,36,254,22,50,208,65,145,45,220,160,93,16,45,62,229,177,187,144,167,142,26,248,232,6,191,77,59,136,49,2,33,116,66,65,146,218,44,111,73,2,222,99,111,24,180,41,67,103,39,216,168,240,207,142,34,241,86,17,173,37,58,64,186,213,98,181,151,159,141,26,22,31,45,92,64,9,10,26,76,181,236,145,18,8,30,219,158,183,71,138,134,56,65,70,34,140,141,13,54,245,29,155,227,200,183,113,40,113,203,86,214,2,162,90,237,5,247,2,186,149,205,73,75,106,255,178,8,39,126,21,96,43,117,216,10,81,98,244,208,25,252,177,189,21,50,204,13,115,42,29,115,2,10,234,207,168,29,131,228,241,82,183,158,85,177,161,142,249,81,208,74,7,73,61,160,142,153,121,63,78,230,152,77,38,100,58,119,15,102,23,145,201,189,165,77,147,230,208,2,84,68,22,86,13,32,68,58,88,73,8,48,139,117,27,222,40,32,182,33,168,89,188,113,162,162,146,225,102,118,158,53,22,82,149,184,240,92,212,243,40,50,170,149,147,223,104,185,45,162,20,59,162,173,157,5,224,233,8,159,219,28,215,102,178,59,121,254,199,162,199,99,2,69,53,6,16,218,9,6,241,44,220,188,45,208,250,244,235,250,209,70,110,222,198,183,219,47,135,143,170,11,226,178,201,194,8,0,115,63,105,158,9,227,172,16,176,218,211,18,70,236,5,109,35,119,143,218,145,213,190,153,247,240,232,191,61,9,58,130,175,235,45,122,195,207,43,194,102,133,91,46,230,18,78,212,122,114,168,4,94,120,96,72,18,12,142,191,141,105,202,78,241,114,85,34,238,84,11,10,254,50,188,122,76,216,117,121,110,3,95,91,62,253,60,174,139,195,120,183,220,61,229,75,22,220,190,134,216,68,90,111,184,152,40,130,43,39,76,144,94,215,83,252,62,127,27,6,175,158,50,87,41,85,95,32,24,14,193,22,92,54,156,254,77,61,50,7,243,25,48,156,89,56,17,33,107,135,110,160,52,80,216,55,217,98,40,102,1,34,70,233,200,205,172,234,156,17,180,123,113,143,67,81,224,51,149,12,213,251,3,2,63,30,249,181,254,120,160,155,133,96,137,181,35,5,182,121,214,39,128,129,237,203,19,137,24,93,101,255,228,209,34,58,241,253,187,131,60,8,241,178,36,11,26,109,21,150,214,31,242,19,60,118,147,158,111,23,164,168,73,67,92,231,211,6,86,222,242,248,107,142,231,119,143,1,168,27,187,91,70,38,230,162,216,232,152,83,71,41,183,182,189,94,221,128,7,217,182,42,49,232,20,23,3,87,95,213,181,137,117,14,161,52,243,122,183,193,90,134,182,58,222,179,72,150,241,129,197,216,227,156,20,75,90,202,71,128,15,137,242,183,117,188,168,252,39,243,76,167,222,12,190,250,197,206,164,145,191,47,206,24,20,40,253,36,4,220,72,143,199,19,105,30,48,219,215,196,37,15,182,38,220,134,239,35,187,29,230,68,215,139,220,215,90,25,184,246,196,149,239,249,142,248,63,141,205,161,28,87,142,170,237,214,67,142,251,97,163,163,242,208,139,28,201,5,249,160,111,232,64,231,207,201,197,196,206,92,127,71,17,57,48,200,25,226,176,113,210,162,108,233,45,224,15,40,196,161,187,228,55,88,74,235,30,68,12,209,70,87,243,159,85,208,70,192,75,111,14,15,239,6,234,134,248,30,113,51,255,128,43,104,82,6,158,241,74,19,174,199,229,132,238,6,70,145,96,242,208,185,17,12,251,210,13,113,233,186,188,29,9,195,244,71,62,26,195,82,44,209,10,230,93,188,92,234,241,145,115,67,77,67,44,210,249,228,5,84,43,160,77,103,214,59,87,195,200,20,129,254,173,229,229,37,115,254,49,72,119,145,188,255,12,95,191,110,239,124,12,213,234,217,4,211,133,39,184,242,103,223,13,5,50,56,74,214,135,66,130,62,223,167,91,175,30,40,134,82,42,167,175,169,33,40,205,88,123,104,96,189,142,226,130,73,0,60,121,128,225,203,146,1,170,4,93,235,72,243,97,77,129,92,246,173,53,161,138,204,83,70,234,80,223,20,176,62,149,150,127,141,182,196,163,80,117,13,31,248,64,166,35,112,96,44,221,70,128,124,229,74,60,65,83,15,20,135,165,184,82,153,163,153,145,137,168,21,68,140,120,76,239,1,57,32,133,38,158,157,114,92,79,139,129,100,233,109,73,206,6,164,101,18,250,41,214,14,185,87,241,153,142,116,3,55,77,138,149,123,112,38,59,191,132,156,136,205,108,175,236,117,66,107,36,241,192,147,149,227,116,253,26,209,34,134,94,214,68,212,25,142,117,207,151,32,13,101,187,154,38,54,165,162,58,254,142,54,86,89,13,232,46,36,31,67,169,250,183,168,205,55,163,165,77,37,211,28,12,51,80,99,47,117,190,69,215,83,246,24,48,152,252,50,167,183,242,94,21,63,211,171,23,199,4,160,172,57,57,92,128,50,52,174,87,77,255,17,221,149,165,195,162,43,38,226,27,221,101,124,188,82,226,222,49,132,246,31,27,81,255,205,69,176,163,195,253,83,47,80,99,157,132,223,160,92,39,120,73,149,51,171,255,67,218,107,160,220,58,236,28,119,180,1,82,24,146,160,44,200,70,141,109,254,12,126,229,95,99,96,3,216,221,136,205,113,142,122,186,243,183,255,22,253,97,176,39,222,179,209,180,233,133,72,37,54,158,28,65,95,13,1,59,153,193,87,230,128,104,160,201,205,2,196,6,125,232,155,188,65,83,240,126,145,178,63,143,0,240,193,78,184,2,226,82,240,49,22,50,167,206,196,168,121,68,212,156,249,154,95,24,93,83,113,168,33,14,246,208,135,139,78,122,101,123,8,177,97,182,122,128,106,140,8,192,100,143,88,196,50,29,207,215,143,65,120,133,133,118,94,128,12,106,130,195,165,203,112,192,173,166,222,59,23,34,6,82,131,16,84,214,205,87,208,140,201,182,166,221,131,122,181,85,150,65,139,133,103,23,179,159,231,7,175,204,95,130,131,126,45,155,135,76,69,145,54,197,251,173,9,206,46,189,122,101,178,24,17,52,231,121,151,60,255,66,47,5,0,134,235,185,232,129,137,35,158,3,110,230,211,73,61,209,224,71,153,55,248,61,100,233,170,140,66,27,177,253,40,208,209,143,4,27,108,105,166,136,60,8,218,119,168,182,107,8,119,5,118,31,219,43,94,70,182,91,68,254,135,245,212,250,26,105,156,109,180,133,177,249,140,89,130,79,55,31,123,18,154,42,191,139,9,240,237,151,107,173,188,134,243,132,118,79,249,197,52,29,174,60,127,48,203,213,101,118,178,117,92,200,49,217,119,172,213,150,231,103,134,168,200,159,174,105,85,8,72,53,243,196,179,102,171,173,207,190,134,186,250,180,231,155,193,203,81,248,175,8,196,145,73,186,178,63,177,60,238,12,42,169,79,173,245,76,171,131,19,102,237,156,201,116,42,209,167,158,198,227,114,197,227,182,212,229,151,110,140,149,239,82,124,137,145,167,26,54,159,102,237,132,139,121,181,115,78,145,179,231,40,243,114,107,190,126,230,152,86,21,43,130,126,87,172,107,120,215,174,119,95,238,138,107,162,109,30,0,156,48,191,59,137,171,39,151,249,219,16,202,29,186,7,225,198,202,213,119,26,30,46,66,61,154,127,212,160,121,30,139,137,77,16,197,1,225,23,181,190,52,124,88,224,250,45,111,131,115,99,26,188,227,244,207,13,101,230,130,96,187,90,109,141,203,246,150,213,238,2,180,162,199,113,129,255,97,7,65,101,37,145,166,70,193,39,68,86,45,6,162,80,189,182,147,237,204,108,173,114,12,139,6,79,110,178,50,39,17,113,41,178,217,61,88,132,240,93,181,152,170,7,71,170,146,115,177,209,87,215,16,157,38,76,45,46,220,16,103,58,125,32,153,241,187,154,232,13,56,84,165,56,94,8,6,118,36,14,96,65,93,68,50,208,97,85,185,103,1,161,83,67,194,38,128,76,181,204,102,151,40,72,219,119,58,243,206,0,99,50,157,241,110,31,75,39,89,181,28,80,34,47,54,40,145,0,60,100,212,148,16,35,19,189,130,103,237,1,19,109,241,72,134,148,103,72,23,209,106,186,211,41,196,18,76,23,75,122,68,251,50,11,252,232,52,72,57,5,52,226,217,252,184,71,71,112,106,214,93,60,250,235,235,115,148,64,183,222,82,158,135,135,145,153,54,138,126,116,216,66,235,51,100,7,1,111,11,231,57,153,174,195,76,173,195,2,137,227,217,61,109,233,31,68,5,179,235,72,80,16,191,118,37,76,119,131,246,39,251,58,127,172,229,32,135,167,216,216,39,54,7,180,45,236,44,47,186,218,5,45,145,201,222,24,126,214,198,237,218,245,74,159,119,201,233,27,224,213,175,46,43,252,104,209,254,53,126,25,166,190,157,66,64,23,226,4,74,69,28,42,238,195,233,33,1,64,116,16,110,32,81,97,57,242,250,108,13,200,31,184,115,30,190,65,111,225,197,90,215,174,221,193,216,165,11,16,3,153,141,181,161,223,213,141,64,243,41,33,65,208,245,48,203,171,242,234,120,183,57,60,85,83,188,148,249,94,62,178,164,119,223,137,180,49,184,166,120,134,127,76,230,216,208,161,5,42,237,196,235,114,222,23,134,110,242,244,163,1,42,228,3,251,93,156,48,46,154,200,19,163,205,213,250,142,212,14,156,210,48,20,148,235,204,232,128,21,3,100,38,184,230,249,138,117,207,253,60,79,102,174,115,184,21,102,194,116,47,69,98,110,200,73,248,186,30,220,75,239,155,228,138,141,255,84,179,127,17,124,167,107,102,248,93,59,11,170,167,110,129,228,140,41,111,215,131,169,31,210,192,131,220,50,29,241,34,235,141,60,96,178,83,126,109,14,186,209,248,63,130,108,186,180,105,95,192,234,29,87,8,197,153,103,55,13,10,116,247,40,153,54,84,199,120,69,98,185,228,4,234,107,80,168,240,218,9,114,58,196,150,245,120,244,210,164,160,201,55,20,40,135,138,179,149,228,199,157,192,174,190,79,35,154,208,104,215,44,229,241,125,186,156,42,60,224,60,98,79,40,64,126,207,165,212,10,115,54,25,33,126,58,236,50,194,209,149,85,111,178,89,79,15,60,227,54,174,229,243,135,42,102,50,171,254,95,21,247,31,125,0,215,95,9,254,115,158,204,23,106,103,28,139,202,110,125,119,242,110,213,56,152,116,42,49,235,231,28,252,0,141,119,191,200,51,122,183,74,56,200,99,174,153,239,174,227,16,247,241,53,17,43,147,201,28,236,24,172,158,183,250,239,232,109,178,138,191,154,85,92,101,93,173,175,120,149,115,204,109,250,109,193,172,203,85,254,72,122,109,173,97,223,35,161,59,23,39,177,164,124,186,70,76,36,143,143,79,179,160,167,125,30,112,233,209,141,126,247,37,119,77,159,6,86,22,186,250,64,148,109,116,69,157,161,219,213,126,74,234,55,4,74,150,191,164,59,229,208,73,147,153,74,155,93,93,177,111,177,180,36,107,46,26,222,118,125,41,31,110,95,84,199,96,81,223,99,229,230,111,208,187,44,207,189,197,162,155,118,66,246,102,5,157,180,61,121,27,171,235,38,194,219,47,109,32,238,247,114,130,158,184,151,243,155,87,210,50,16,172,39,124,229,145,237,44,49,206,229,30,118,171,255,129,65,10,175,28,62,65,30,217,20,113,253,179,149,240,28,118,112,140,20,237,39,7,159,242,230,64,144,209,53,33,213,116,176,141,135,111,225,244,248,107,202,235,131,88,130,60,113,17,151,144,193,21,155,78,5,33,221,177,64,101,141,166,1,217,83,16,24,8,33,203,8,73,180,252,201,36,37,193,112,158,81,36,62,12,87,125,150,121,19,39,92,191,173,210,244,36,77,195,88,140,26,156,4,231,27,111,89,251,35,188,185,246,75,176,127,162,75,144,137,255,124,36,161,108,144,154,177,88,19,197,21,51,61,242,175,177,115,118,58,158,40,174,196,158,97,198,184,209,36,126,232,71,189,204,186,7,102,36,124,234,204,89,172,220,192,86,101,51,175,40,9,191,17,115,155,117,200,237,22,138,77,48,250,240,160,224,117,133,170,182,144,213,211,213,2,243,145,65,254,0,2,248,48,33,249,80,119,29,108,76,228,213,3,143,250,23,23,131,183,155,60,55,214,27,114,225,198,150,10,35,148,123,109,118,26,2,65,205,51,165,231,113,146,183,118,99,110,128,192,107,84,128,130,68,16,88,195,165,35,170,219,153,195,92,132,226,34,20,77,81,240,139,150,107,214,77,155,204,106,79,19,168,44,71,198,240,87,142,60,44,60,246,5,116,90,243,72,82,123,206,123,164,157,159,113,100,46,227,97,151,247,172,49,26,253,214,112,110,75,191,20,199,178,121,153,73,146,167,80,165,179,249,104,118,42,76,8,126,200,69,25,1,35,35,219,85,218,235,253,164,63,211,195,178,60,208,120,222,151,167,79,238,35,131,109,53,18,149,50,40,14,206,218,230,111,82,234,124,19,223,6,18,94,196,199,189,219,79,203,3,86,63,184,11,70,220,145,70,39,204,13,70,25,105,99,18,2,0,24,161,197,244,35,162,11,157,34,54,196,92,138,255,30,83,77,170,69,196,207,11,28,60,155,7,88,6,248,72,159,21,242,123,4,244,230,249,74,32,130,186,174,143,2,140,24,130,73,170,186,195,129,0,221,95,213,21,27,147,128,194,103,91,111,210,249,82,200,180,140,107,187,79,132,95,135,105,220,39,219,47,101,130,232,19,153,84,96,21,214,227,184,212,26,88,77,22,173,250,215,51,120,214,55,206,86,220,178,39,170,15,114,12,97,98,239,4,124,47,250,230,133,149,196,82,209,165,151,0,207,30,106,133,62,251,241,196,196,47,179,145,179,2,155,15,5,165,22,67,52,207,39,246,123,134,219,252,174,231,168,82,8,7,192,229,168,45,215,86,100,235,111,169,107,12,249,89,109,86,160,142,181,238,237,223,92,168,130,150,236,224,116,222,45,18,13,13,164,73,38,27,208,24,138,45,80,4,148,58,149,54,128,230,244,22,230,218,179,87,51,104,223,178,9,209,228,14,206,192,249,41,82,34,115,235,125,150,192,196,1,165,252,62,83,243,157,37,218,134,192,149,232,139,145,253,205,51,17,97,192,121,157,60,181,170,126,156,5,44,196,235,223,123,170,2,118,228,255,243,8,132,196,221,30,242,92,159,112,180,131,51,25,126,253,184,7,4,110,34,217,37,185,91,186,44,77,80,104,181,58,171,9,210,180,17,119,8,141,229,247,64,62,232,121,118,112,133,52,173,5,202,94,170,37,212,28,222,193,97,51,164,107,197,181,220,102,52,58,47,147,194,179,174,14,89,19,221,145,39,174,86,249,64,89,192,101,143,207,156,186,210,1,137,143,225,13,38,98,59,92,137,53,31,64,212,100,157,144,100,131,3,65,115,94,185,87,13,25,176,45,184,207,19,250,197,231,86,217,51,191,125,60,11,95,125,105,236,148,166,54,6,42,0,150,180,138,38,30,235,72,106,14,217,69,184,242,46,197,173,38,89,234,41,197,213,165,79,86,118,231,142,207,69,207,108,20,53,179,160,231,84,99,156,253,80,13,15,65,18,73,160,149,31,76,124,141,4,48,207,86,81,87,66,32,121,213,115,116,230,240,201,247,195,159,66,154,244,180,174,14,101,84,3,66,175,40,177,65,194,101,162,234,26,55,222,21,72,164,219,243,129,30,172,104,212,50,6,152,90,233,235,35,221,207,165,225,44,109,74,127,123,173,56,87,209,84,211,48,214,123,5,105,101,78,188,169,175,36,172,214,19,232,125,217,130,252,99,237,244,61,173,193,82,209,216,57,13,12,202,82,193,78,70,69,206,74,240,191,91,25,179,254,242,177,68,23,139,165,101,32,52,246,25,212,240,38,237,147,60,156,190,36,3,56,163,125,228,107,228,6,235,44,250,90,92,77,158,36,217,168,161,77,26,49,125,99,103,191,115,41,120,16,231,243,69,108,169,115,81,127,195,48,164,132,75,173,147,62,148,220,3,189,186,165,200,86,60,18,172,193,207,129,196,167,69,181,134,232,130,109,48,76,133,202,38,184,207,153,39,149,26,4,242,77,59,193,254,102,222,99,68,91,147,245,252,14,111,57,224,121,244,233,148,97,66,37,162,181,44,60,144,184,181,187,204,143,33,120,225,243,226,97,190,168,25,134,240,146,145,251,166,104,183,243,126,93,104,93,84,55,148,49,84,30,71,204,203,236,226,179,113,247,64,213,92,207,126,35,130,231,86,232,149,34,79,127,8,155,120,228,29,247,142,10,151,52,57,180,40,56,93,99,171,253,160,143,201,101,183,204,59,240,23,208,83,198,151,231,231,147,28,110,4,156,102,57,157,18,249,18,50,20,130,56,53,156,41,45,170,41,117,136,179,222,121,239,18,168,166,237,2,237,98,107,148,236,81,60,2,33,181,218,46,71,254,197,234,84,204,80,27,160,118,123,153,37,55,238,240,199,98,227,116,197,126,232,21,255,98,226,206,152,34,211,121,85,69,183,195,225,202,232,188,79,208,206,156,187,96,21,189,252,76,203,227,241,70,211,61,52,217,12,33,243,41,50,152,77,47,82,19,140,197,235,100,59,65,70,115,52,246,95,80,145,224,57,224,221,213,78,145,49,47,117,102,248,205,92,84,18,215,150,191,135,145,62,36,193,200,52,133,187,34,96,149,139,1,97,248,25,51,64,247,58,93,111,15,225,212,223,114,61,92,11,95,154,153,245,208,78,148,39,150,34,40,110,50,154,11,54,4,145,21,134,166,233,0,193,39,105,2,102,29,28,168,238,231,117,248,142,40,50,56,142,240,142,165,151,16,85,30,155,98,225,239,177,187,143,215,228,29,118,98,85,69,167,21,45,116,143,40,42,152,1,87,158,139,169,81,137,18,54,65,178,145,44,82,225,241,84,208,111,202,139,17,95,107,130,255,148,105,65,106,172,230,171,55,197,239,133,168,4,152,247,235,19,138,175,168,216,216,171,23,160,83,71,40,126,234,228,1,76,145,9,132,135,166,202,190,232,233,218,105,184,138,161,252,19,33,132,61,159,183,129,62,37,37,194,79,104,59,218,204,215,82,166,4,190,36,224,43,97,59,71,51,188,214,175,54,18,10,15,153,110,203,218,59,225,113,185,123,75,111,206,104,24,163,254,170,85,40,105,9,229,41,218,37,240,211,103,89,253,97,34,77,188,114,220,132,215,129,26,109,149,186,128,119,108,19,20,122,172,175,10,20,169,9,104,195,150,51,8,159,140,86,232,226,177,7,196,200,167,207,106,126,27,140,222,219,198,149,46,0,13,93,255,121,205,23,206,245,185,247,15,231,173,156,59,156,16,48,118,254,93,148,203,237,189,158,180,101,52,62,155,57,8,175,171,215,67,69,104,60,72,232,226,185,20,206,65,59,42,125,90,124,100,202,134,141,239,191,110,203,164,223,50,232,219,4,222,205,22,70,62,180,75,143,174,228,44,62,245,202,39,117,215,33,145,80,106,131,177,244,66,46,89,167,198,251,80,38,72,190,90,118,85,34,158,83,17,61,132,124,53,24,63,24,90,249,68,131,245,198,183,117,13,157,137,70,189,73,23,75,77,13,25,88,126,217,87,108,92,8,133,154,15,158,112,113,94,186,162,177,9,232,181,162,55,24,38,161,79,176,4,233,11,158,170,242,240,168,77,25,3,223,158,186,182,26,129,84,106,135,108,205,79,254,175,227,1,238,248,79,5,72,169,217,128,158,1,139,110,157,12,39,55,95,3,2,113,179,81,229,38,144,253,35,77,155,97,157,9,47,133,35,238,97,246,176,156,164,3,236,181,42,140,173,1,46,164,218,168,228,127,219,160,224,59,249,247,7,155,98,77,199,215,146,55,151,221,185,163,241,26,122,137,164,190,205,207,4,237,134,165,74,238,223,226,15,248,242,139,107,210,187,234,4,145,23,231,180,229,53,254,166,201,220,10,14,58,33,230,72,92,230,207,170,109,188,229,137,28,147,22,41,192,213,40,215,216,127,14,228,9,13,85,247,106,247,1,155,206,136,4,23,190,148,170,106,194,155,170,96,227,85,168,247,195,20,113,172,17,34,38,123,79,167,110,206,207,53,66,173,162,178,166,84,120,160,160,218,186,227,34,87,100,212,219,28,84,255,59,138,26,28,227,102,205,94,75,152,55,216,163,46,225,96,152,57,32,57,159,27,251,178,201,231,5,139,31,163,136,69,71,125,19,213,46,252,84,88,215,163,249,153,181,25,227,174,4,105,93,98,251,60,164,4,222,26,165,85,83,87,45,206,132,134,6,108,89,96,76,139,144,143,144,116,59,72,48,184,248,230,195,135,167,29,166,42,207,49,87,221,159,42,168,96,157,181,125,152,96,130,72,48,100,105,145,96,98,200,116,7,131,166,69,99,117,55,141,40,125,106,249,33,118,191,121,159,138,79,27,90,132,13,52,0,61,44,246,212,77,127,107,26,124,234,104,26,14,238,68,79,124,247,99,81,60,135,27,62,83,231,104,214,53,69,104,188,95,120,30,105,222,150,218,223,80,221,209,86,113,125,226,123,36,1,136,94,206,253,124,34,218,2,77,208,172,39,238,148,151,111,237,3,135,99,41,22,142,129,39,56,105,255,31,62,12,171,5,206,94,114,13,174,185,89,199,225,131,239,187,92,132,102,86,138,156,36,55,112,65,191,209,70,60,75,110,59,216,180,148,36,118,238,139,97,222,17,236,209,68,163,76,177,206,58,196,113,2,166,47,131,113,199,180,134,23,174,24,119,20,124,144,29,221,9,90,224,188,131,232,13,244,94,200,129,51,27,11,124,24,154,5,91,171,150,238,212,117,175,71,155,110,168,3,236,162,196,193,74,101,6,238,157,132,151,181,88,122,26,84,194,170,253,198,124,142,133,185,66,4,105,5,152,87,209,178,134,243,242,197,214,209,103,53,218,128,193,9,83,231,55,111,29,235,133,45,107,115,71,203,15,1,69,200,105,216,1,163,183,18,222,54,6,56,48,104,228,237,119,166,90,242,184,97,160,218,194,255,151,131,120,180,104,202,167,157,179,147,77,161,34,65,201,171,236,177,175,0,92,134,255,40,217,133,61,187,44,165,109,184,127,37,189,61,62,60,232,182,210,78,123,118,207,185,156,158,77,117,67,26,37,222,174,87,192,241,152,180,170,218,35,86,86,91,87,98,97,192,129,140,194,233,36,79,152,203,136,73,223,63,26,117,190,88,188,60,42,9,45,54,223,198,207,196,237,26,244,60,233,67,132,223,113,147,253,16,126,10,119,41,159,99,237,109,167,23,248,146,7,166,214,75,0,234,202,90,254,26,71,82,240,116,216,96,236,109,46,104,255,134,115,253,155,36,36,129,188,183,140,151,14,153,244,139,244,252,214,160,8,249,226,35,58,185,116,255,126,128,120,235,190,225,169,185,175,255,64,176,56,247,249,7,18,39,92,249,142,98,47,116,247,126,6,66,208,245,253,217,123,160,123,49,99,18,90,47,9,80,207,212,123,18,61,155,193,44,242,205,146,4,96,210,222,194,220,47,172,241,165,29,155,45,163,105,121,174,115,233,211,216,182,136,24,90,234,77,214,70,94,160,35,59,16,39,71,24,186,43,251,99,53,11,47,60,159,24,144,250,41,114,90,26,97,209,154,96,63,178,67,28,211,107,179,90,253,127,165,163,26,175,163,165,60,47,25,151,210,245,25,91,122,31,176,184,179,128,161,75,71,166,119,40,19,58,101,115,237,145,211,239,250,235,224,4,46,64,94,118,213,191,21,42,27,169,75,217,193,182,121,215,57,216,234,245,160,135,78,21,125,113,51,250,39,177,32,227,61,57,182,118,16,212,181,130,153,240,62,148,127,188,127,160,37,3,231,33,68,181,179,95,116,179,14,247,145,214,104,222,71,140,17,161,171,218,105,81,195,25,20,202,235,110,70,90,42,47,194,109,74,85,60,77,65,92,205,106,16,171,147,0,227,16,251,48,224,101,8,46,29,94,50,36,213,78,254,13,7,254,227,219,219,18,45,213,145,136,25,210,42,32,47,62,61,139,31,140,17,210,249,37,178,80,160,59,139,26,250,178,179,208,129,81,82,239,54,209,224,20,156,174,251,26,130,136,28,68,243,28,42,28,17,51,90,6,39,125,11,249,223,165,193,243,148,129,17,210,146,186,89,202,253,59,205,5,52,237,17,181,104,92,54,142,214,177,178,59,214,195,73,72,186,175,17,1,0,220,146,69,144,120,89,133,146,152,239,230,141,237,0,78,250,117,54,179,45,38,167,90,149,136,233,115,8,227,210,205,255,208,177,5,45,173,12,189,122,109,122,136,191,40,176,51,234,201,4,208,42,147,44,56,120,17,43,69,93,97,143,103,130,166,129,101,7,40,85,92,157,218,212,230,114,139,2,233,64,93,127,49,140,232,168,194,0,74,215,40,158,61,12,247,57,151,103,148,42,210,155,139,211,87,19,0,208,70,224,199,34,241,199,70,169,161,135,61,105,233,172,62,114,0,96,15,45,231,45,55,172,39,55,41,225,133,190,138,162,53,142,120,95,183,32,192,36,208,155,102,233,86,61,53,30,206,83,199,125,72,101,207,29,247,104,10,148,18,184,234,165,202,151,116,193,119,185,112,23,192,20,152,65,174,8,254,94,56,95,112,30,175,131,75,160,36,26,226,61,55,97,225,40,77,212,181,0,239,155,198,208,128,240,202,248,190,135,42,46,22,94,11,61,30,199,55,16,98,142,1,63,173,36,147,172,74,152,45,239,201,204,46,115,27,81,227,120,112,155,184,99,79,214,130,147,122,64,139,9,147,208,82,76,15,123,98,5,74,218,198,40,175,162,34,226,243,95,227,126,94,45,242,141,118,9,49,66,13,62,135,201,56,200,96,255,212,204,11,3,243,18,242,108,74,227,62,173,115,180,224,226,248,249,141,136,245,6,158,110,65,8,248,189,225,236,226,84,45,8,72,133,12,176,12,140,172,135,245,88,80,88,0,185,175,79,207,75,134,219,100,194,29,255,125,135,114,8,126,63,172,235,145,65,229,120,37,197,36,66,254,60,122,61,197,192,6,79,197,152,198,219,179,231,14,155,211,69,154,175,209,49,59,91,6,25,138,1,144,199,28,148,67,149,19,37,147,101,173,173,206,196,37,179,47,184,185,251,43,182,74,221,246,66,82,220,131,113,87,197,241,66,226,95,156,93,186,196,250,229,244,248,189,22,207,27,43,104,3,210,183,207,145,95,190,74,251,145,107,71,36,138,225,83,79,207,145,78,210,137,175,90,23,239,94,181,98,41,136,109,211,114,150,87,255,49,149,169,69,132,65,211,140,205,214,29,22,127,210,12,110,19,72,139,152,200,229,246,220,110,222,227,189,5,36,90,254,53,6,237,122,57,142,108,23,90,140,146,218,237,207,124,148,18,43,1,231,98,177,83,35,133,156,57,105,201,222,84,80,168,12,176,33,62,83,81,72,91,127,176,136,94,105,255,254,90,145,155,68,132,45,203,4,81,16,2,218,66,189,227,170,31,12,196,122,121,143,12,99,122,129,195,234,210,79,14,55,209,162,72,6,182,66,57,203,144,165,124,104,28,239,250,145,78,30,73,201,115,103,29,184,58,64,70,85,21,63,220,48,82,120,182,147,193,160,57,159,29,228,110,185,119,116,208,106,226,116,121,81,43,222,244,81,208,45,54,252,92,150,203,97,118,228,145,19,251,135,68,118,217,134,205,225,179,191,233,152,12,91,197,183,100,112,245,155,90,49,164,31,226,11,161,97,101,12,52,104,87,67,185,88,236,186,244,207,7,33,67,86,181,69,233,84,8,132,228,204,119,32,165,140,91,72,140,72,59,85,160,243,119,182,101,202,174,103,225,103,157,66,245,6,239,65,118,228,82,220,95,37,111,101,138,161,191,68,163,207,254,132,5,33,34,56,45,15,145,79,100,40,250,236,235,36,175,245,20,209,154,13,198,149,155,0,80,11,84,80,172,105,217,187,232,7,132,48,231,150,103,105,189,165,83,77,153,247,75,244,46,186,175,219,208,150,199,180,28,58,132,148,105,13,207,113,32,133,101,252,13,167,207,239,200,38,246,25,126,101,156,150,20,134,155,28,193,203,237,91,8,31,34,172,248,160,57,105,219,239,42,133,226,116,81,43,132,235,167,30,68,43,231,221,164,52,182,249,179,61,153,161,159,137,151,189,73,236,246,163,36,98,19,85,248,126,173,105,179,75,212,179,6,192,100,128,153,211,199,108,66,203,86,207,169,95,199,34,119,154,244,10,13,220,112,98,175,183,40,113,55,27,57,116,86,1,170,179,54,173,252,94,178,69,116,19,143,251,130,194,112,136,117,223,38,229,127,85,195,14,156,30,223,71,155,223,129,124,152,171,136,110,120,95,180,53,100,168,25,3,216,42,54,85,46,69,119,107,155,145,251,64,53,185,193,15,13,139,6,167,11,60,47,89,97,48,152,126,89,204,146,71,95,57,111,150,78,240,251,102,115,113,11,147,15,192,253,231,25,248,245,109,134,153,56,58,101,46,144,2,253,31,2,83,198,61,64,121,63,76,80,67,29,12,66,28,147,254,92,69,68,35,212,156,221,161,237,249,146,56,121,137,145,156,246,183,247,139,124,62,163,212,103,229,186,93,174,69,23,160,26,196,181,43,175,176,60,110,211,55,131,146,61,179,46,79,154,194,63,7,77,202,244,150,202,18,92,217,129,241,239,222,111,51,135,13,231,255,23,171,205,2,165,228,225,46,247,213,245,181,190,140,154,241,182,186,251,24,83,159,137,53,64,138,170,164,60,147,27,90,82,193,36,201,173,182,188,108,188,229,45,193,211,18,253,200,185,25,95,180,93,30,219,69,195,239,222,97,161,110,214,36,114,96,168,76,77,164,53,131,226,197,100,0,42,106,159,84,214,55,249,124,216,170,102,155,118,134,77,181,65,115,14,167,123,89,46,212,228,181,29,222,148,86,228,253,74,236,231,197,148,188,137,167,27,127,12,253,186,84,67,146,211,91,131,122,218,230,239,254,175,168,1,213,249,121,7,221,136,146,201,36,166,47,73,221,190,128,205,126,206,89,121,78,233,57,64,136,20,67,198,178,249,191,17,131,33,149,197,130,104,170,130,142,237,246,170,147,192,156,248,187,123,25,225,139,220,171,61,24,24,114,110,77,3,160,244,82,56,94,113,16,27,118,228,217,56,29,253,10,75,145,97,193,150,89,210,52,60,146,17,127,187,216,5,195,108,15,251,39,157,158,86,49,193,199,155,106,6,73,80,247,203,61,88,81,56,93,158,179,40,245,81,68,136,69,32,237,101,122,112,165,100,55,9,127,59,26,9,41,16,102,92,246,179,125,108,231,225,63,120,88,135,69,195,239,197,51,245,72,72,59,15,231,42,3,184,123,64,176,64,2,15,246,220,67,193,252,8,159,56,20,44,137,45,172,109,183,204,159,101,6,17,221,228,44,160,69,242,153,202,128,203,12,4,126,92,35,50,234,50,118,36,235,41,31,25,142,113,24,62,9,95,20,19,50,125,158,204,53,186,86,53,189,102,153,228,219,22,2,99,14,143,147,221,199,23,113,107,196,224,225,104,121,99,34,19,112,121,28,191,160,245,10,17,84,184,88,225,151,167,54,240,195,72,254,120,18,22,155,131,146,29,227,234,30,101,250,135,69,125,243,191,220,108,252,27,73,15,229,136,53,207,18,173,204,19,205,199,182,167,225,33,249,143,99,91,17,55,149,227,252,128,238,114,212,169,242,145,36,176,68,219,87,139,157,11,63,61,59,211,206,153,189,127,223,109,58,97,39,141,146,29,253,92,94,80,25,18,106,154,118,230,19,134,225,160,83,60,150,40,14,114,137,33,215,197,110,48,190,240,56,91,138,248,129,37,247,39,83,175,2,103,194,229,110,102,216,12,120,6,3,226,163,55,78,249,252,111,226,91,6,137,148,130,47,48,247,229,23,243,182,71,150,137,124,20,124,66,139,32,193,148,161,185,236,79,174,99,200,112,53,55,117,29,34,237,204,153,30,100,212,1,178,63,101,108,21,60,226,164,189,178,191,164,14,130,253,211,82,162,209,199,23,248,243,208,248,249,158,141,215,199,86,0,246,74,146,131,115,160,41,65,31,203,224,248,194,77,33,67,47,171,200,140,46,76,21,188,172,177,183,243,246,224,185,32,56,122,180,233,201,25,233,15,85,45,133,25,16,136,35,136,145,142,15,86,80,133,48,119,224,178,65,40,193,213,90,108,89,160,56,151,217,217,57,103,175,63,242,81,89,154,80,29,72,39,62,162,124,64,207,184,236,170,24,70,121,44,61,235,14,3,108,68,201,57,178,69,188,58,91,211,235,251,154,69,34,123,86,213,66,253,253,216,176,67,99,197,91,185,250,198,244,215,134,106,130,27,155,101,61,23,181,173,83,247,184,185,24,221,87,94,129,150,24,83,250,180,99,14,23,157,95,133,189,98,219,252,120,118,181,213,41,131,138,220,245,32,75,155,209,55,31,197,21,188,175,14,108,96,144,219,70,87,169,105,80,215,39,54,253,164,135,220,113,179,11,26,86,90,17,173,82,168,51,234,219,159,197,190,211,12,96,163,96,156,21,216,237,81,71,8,238,177,222,65,238,18,207,224,198,6,78,77,58,229,128,113,49,80,53,64,60,188,235,183,243,253,19,186,159,48,179,25,11,199,176,100,249,48,94,85,170,164,215,111,157,248,47,235,115,199,148,241,90,5,156,158,194,36,48,2,128,54,251,107,121,73,162,149,9,148,65,58,167,164,203,170,52,197,196,44,120,167,22,204,41,135,101,200,149,248,38,73,57,71,205,69,158,255,72,185,219,30,199,49,162,53,242,190,45,142,206,11,94,30,40,120,221,10,171,209,31,64,30,69,102,138,222,180,169,4,28,97,34,15,174,50,15,217,31,255,141,56,24,233,173,156,216,252,142,255,94,59,43,223,147,253,34,44,189,10,93,55,252,67,27,40,123,12,243,5,33,140,234,16,240,115,171,26,131,179,201,114,216,135,196,14,204,11,226,91,159,139,238,182,65,152,10,212,173,146,189,31,16,197,251,214,140,176,101,41,217,127,19,65,118,112,116,119,159,28,52,102,175,254,92,132,73,106,70,124,121,229,34,136,208,230,102,14,165,73,4,170,233,83,76,138,148,54,152,21,227,68,40,188,180,162,79,72,48,228,26,205,64,66,33,171,221,163,170,114,114,184,172,219,201,168,200,24,77,52,12,80,226,95,105,205,101,189,221,3,5,202,38,226,148,208,76,126,116,245,120,125,186,56,187,96,82,46,133,211,10,66,86,187,156,137,23,160,98,171,226,232,11,114,200,18,250,211,87,122,21,93,163,90,104,194,160,53,194,74,207,94,195,91,24,76,184,136,174,136,22,245,12,54,167,76,106,249,48,251,40,188,97,95,223,30,22,142,194,231,189,143,57,151,51,105,150,197,223,211,167,34,90,118,91,128,229,236,240,185,96,234,208,26,179,111,122,244,232,80,12,38,10,75,30,38,189,236,165,19,26,106,197,252,71,235,185,204,73,177,213,143,142,148,0,198,150,67,125,250,112,233,80,164,49,60,6,157,40,93,68,163,97,177,11,138,69,11,80,35,151,37,226,112,83,104,68,199,208,112,120,18,122,5,174,225,120,249,246,187,239,139,207,193,43,156,214,226,0,98,218,49,189,224,164,249,146,98,223,125,50,17,156,249,81,199,227,5,93,233,167,93,238,114,241,192,104,44,145,2,60,79,168,0,112,62,78,120,31,150,105,225,33,243,194,10,247,239,80,186,67,248,147,112,190,206,149,49,185,35,4,129,193,254,128,152,100,164,105,79,44,168,54,203,1,129,230,43,92,174,4,56,200,148,20,82,211,212,136,193,83,214,240,81,138,39,11,132,114,55,99,194,4,143,40,233,177,238,255,46,166,183,5,115,190,182,171,253,136,6,248,32,219,26,252,55,109,189,224,176,219,6,131,136,170,148,101,102,58,242,121,97,120,125,146,126,232,251,70,200,193,191,199,169,112,172,43,218,147,205,17,215,99,9,141,194,206,149,104,71,115,45,250,190,121,28,115,88,81,131,250,172,238,160,98,146,119,165,113,166,10,172,34,174,43,44,119,114,32,110,169,188,210,22,181,71,3,8,218,196,202,103,105,234,72,209,168,202,3,206,120,58,52,91,169,202,207,73,67,52,223,246,40,85,129,186,17,147,193,231,46,110,139,178,74,210,186,252,20,42,212,66,107,31,239,184,60,105,247,138,212,29,59,35,147,239,109,123,57,144,11,149,66,71,134,57,20,223,47,197,51,83,184,140,102,217,213,245,43,232,173,139,129,135,141,23,147,64,170,6,101,154,52,47,242,34,140,3,101,199,41,95,122,146,104,251,210,114,60,120,85,93,235,23,132,185,200,46,225,58,185,30,23,139,234,67,231,176,36,70,216,129,111,57,23,74,254,117,89,199,41,209,178,61,214,211,184,105,167,86,249,49,90,42,123,168,58,104,222,200,67,41,108,0,17,167,116,177,110,201,116,233,182,36,97,100,6,194,14,109,98,123,229,192,135,60,139,212,178,229,24,178,75,57,129,64,124,38,73,23,182,0,233,69,40,62,242,69,133,151,96,88,46,115,166,144,227,171,12,67,150,150,224,205,128,11,68,98,7,65,199,98,217,18,163,103,246,75,237,111,191,192,188,237,204,240,118,109,98,193,54,170,132,185,37,96,110,213,152,18,190,35,50,82,137,93,149,215,225,221,42,90,5,238,158,171,51,61,216,167,102,11,175,66,32,95,200,136,58,38,185,31,31,7,154,137,77,199,135,129,68,11,138,218,56,51,63,138,232,178,118,35,168,128,222,75,254,4,133,240,20,138,225,42,242,179,147,238,252,236,171,207,216,158,161,187,121,28,211,191,97,168,90,83,211,109,149,65,124,180,9,172,11,247,233,144,178,35,236,201,59,110,14,121,70,14,224,61,254,78,212,28,174,65,117,240,197,140,63,81,231,180,236,142,119,35,45,55,146,227,92,243,89,103,227,113,113,7,241,196,218,216,222,133,210,176,201,227,29,129,190,164,242,224,9,230,82,122,179,114,75,246,39,15,229,149,39,223,54,20,209,236,251,52,201,186,78,73,37,151,126,3,228,78,186,96,42,131,8,164,251,31,66,192,181,12,97,55,186,77,32,219,199,151,33,3,42,85,29,142,29,6,107,115,68,114,214,114,140,199,143,20,245,129,9,78,83,246,169,65,41,122,99,69,204,115,173,8,254,95,66,163,162,48,175,244,113,209,100,147,112,188,220,233,113,5,212,201,138,91,38,191,72,7,99,178,116,234,92,48,244,0,211,154,27,247,206,232,89,85,99,233,132,72,85,200,139,238,153,179,24,123,99,134,246,142,188,239,9,157,112,162,234,185,118,245,59,130,224,204,31,163,171,38,159,221,225,99,216,177,58,35,104,109,10,125,89,23,53,56,37,68,165,189,60,83,249,63,161,240,70,141,1,210,143,125,157,56,227,11,24,55,38,168,16,119,213,155,223,143,131,175,37,234,125,238,16,194,101,201,158,4,110,18,210,221,84,87,14,13,169,250,241,240,1,12,205,98,246,198,75,250,239,249,104,97,127,57,19,15,104,126,28,59,196,119,32,32,82,17,212,81,175,226,118,175,241,105,177,135,71,82,187,16,240,159,71,37,41,230,115,64,156,184,169,24,234,219,0,246,117,253,167,73,143,69,3,130,245,116,43,177,166,154,119,212,153,47,46,26,192,155,252,200,241,110,201,195,252,231,181,147,45,221,62,85,89,150,72,79,230,174,245,52,49,209,202,184,143,160,9,190,63,249,33,193,163,53,123,237,31,46,225,42,225,49,158,14,120,71,133,247,37,52,27,195,168,0,173,254,175,48,203,127,136,142,20,140,58,102,224,52,13,72,195,143,146,84,91,160,228,92,126,63,39,81,150,207,232,13,28,22,22,113,169,45,140,23,5,46,155,127,197,116,25,54,226,104,89,169,95,100,83,211,41,119,115,107,60,190,170,12,213,173,189,220,228,10,211,105,116,245,166,208,229,181,165,201,68,170,57,36,97,78,110,76,75,65,230,77,138,17,146,196,148,196,16,237,121,105,24,158,75,121,236,185,205,129,31,100,68,181,179,248,183,65,29,74,96,126,223,176,27,19,62,148,147,12,48,70,173,22,7,123,162,216,137,16,123,171,81,196,100,84,138,92,119,3,209,28,49,46,184,35,78,201,26,213,233,176,139,204,161,161,100,134,151,46,27,220,236,243,154,104,171,179,29,24,244,219,213,4,109,217,17,167,110,219,11,225,255,47,80,164,122,91,85,104,133,179,78,39,122,132,12,176,53,220,175,184,93,42,5,93,129,217,176,225,1,179,77,53,121,239,203,231,143,218,94,107,129,31,11,195,254,148,78,105,60,149,153,223,20,120,153,7,211,141,71,154,236,170,254,85,202,104,196,108,18,145,215,252,129,244,163,252,137,151,112,146,157,1,59,187,240,13,15,2,216,118,65,35,126,38,27,221,174,235,245,160,106,120,196,95,105,214,48,54,136,226,74,65,88,37,3,224,245,60,140,2,150,249,134,212,251,59,123,169,14,76,79,118,67,227,62,202,182,40,50,114,7,24,44,54,254,33,251,230,193,198,191,167,178,228,71,214,100,187,93,9,99,58,230,102,178,170,160,39,178,130,14,57,7,70,171,249,174,14,35,35,120,237,233,152,182,162,97,118,134,142,150,24,7,159,154,144,20,178,175,155,125,114,58,253,140,118,189,3,236,201,17,137,170,158,6,138,214,209,52,137,203,102,157,11,99,113,92,97,55,117,153,111,20,219,251,13,105,77,46,143,89,53,195,147,116,53,124,195,182,95,154,49,226,94,206,124,56,128,210,109,131,196,167,229,110,5,138,241,184,84,170,48,209,20,77,49,194,144,208,224,23,8,82,52,152,83,235,136,168,48,59,7,125,42,229,139,89,170,227,83,9,67,233,174,188,101,17,74,229,208,35,149,23,105,183,73,116,1,80,193,46,164,25,242,129,1,17,88,87,87,94,55,96,126,151,60,35,202,219,9,3,222,161,131,34,149,198,202,198,131,167,91,75,106,85,22,230,193,8,201,156,81,226,164,111,44,147,161,162,209,240,123,26,148,30,161,104,16,29,236,170,204,149,74,126,34,109,24,139,125,1,32,228,137,89,30,201,147,146,189,177,123,185,72,228,107,91,49,121,163,27,243,72,155,29,183,58,67,212,196,210,201,58,31,102,67,158,141,70,175,80,213,3,99,198,124,34,110,94,209,77,20,85,45,162,82,18,61,189,203,199,56,131,228,230,7,53,226,247,217,35,66,115,37,68,130,210,200,156,186,44,33,11,229,31,84,159,92,194,52,14,158,187,179,106,80,194,179,80,226,202,110,147,204,167,44,63,158,49,55,80,115,164,46,156,244,58,137,134,55,253,220,75,9,103,136,249,242,3,215,220,53,123,17,75,112,40,131,105,76,0,16,17,245,242,195,47,165,106,200,206,26,130,189,65,203,2,99,181,5,143,191,100,128,52,249,154,169,127,159,85,163,175,105,201,79,170,124,33,172,15,229,166,146,194,104,108,129,91,132,33,195,224,4,116,61,113,89,52,79,251,121,2,32,71,98,121,115,214,245,87,160,16,97,250,177,149,55,39,223,212,203,76,231,248,127,176,129,187,75,9,209,101,237,148,65,111,200,193,164,44,66,237,159,220,85,84,91,89,208,128,237,151,180,31,151,237,151,16,114,221,155,43,42,4,83,34,238,79,149,66,231,157,222,132,11,145,104,170,56,236,84,248,183,36,85,4,10,143,170,141,177,87,7,163,114,225,72,248,238,122,146,203,203,157,4,155,198,245,193,60,218,180,175,34,89,80,195,35,71,85,234,238,86,77,49,244,128,157,230,211,30,114,38,88,35,242,190,254,27,132,194,18,236,121,228,133,95,97,44,236,154,28,64,235,14,62,141,6,104,2,239,196,0,239,190,200,189,55,225,88,118,166,28,3,155,39,73,135,166,250,86,28,103,243,78,21,135,177,206,135,183,141,13,148,181,253,155,176,98,53,113,191,110,156,23,111,210,0,12,145,6,255,146,80,247,0,74,171,33,213,96,90,118,193,89,208,79,47,247,61,246,11,199,235,65,231,27,63,41,110,254,129,80,132,0,167,84,59,171,175,164,131,185,207,179,36,207,187,236,180,205,188,150,112,119,170,82,180,155,78,6,33,163,196,74,97,85,204,95,48,248,81,22,74,219,228,3,163,28,111,155,134,69,37,9,187,242,25,75,186,8,17,151,196,130,59,118,14,82,207,194,129,82,65,199,147,72,96,117,243,22,125,145,219,206,184,153,41,144,219,98,96,155,34,94,181,44,163,237,168,33,89,151,218,192,247,57,198,126,236,197,141,63,109,159,157,29,83,185,46,181,8,73,42,95,252,161,116,224,219,172,169,119,219,52,46,170,69,178,172,93,174,0,45,81,139,114,181,102,240,100,159,66,137,156,200,175,244,173,51,117,206,244,24,77,6,23,82,12,37,118,160,225,85,183,69,79,100,126,129,93,155,18,95,145,39,32,118,241,90,236,152,14,20,126,31,234,84,34,120,172,90,243,50,162,34,238,83,91,24,255,99,225,240,27,114,166,100,243,207,98,170,111,107,224,19,79,177,203,231,135,126,205,13,231,108,153,215,16,143,6,18,244,71,18,188,143,224,169,189,54,129,185,202,121,10,142,246,219,251,81,92,184,115,207,55,223,23,9,172,6,80,2,236,96,4,51,62,54,135,46,10,0,229,235,188,235,218,127,115,177,136,157,40,2,71,146,32,245,200,137,190,179,220,117,208,242,197,14,183,79,124,35,171,203,89,139,208,30,50,32,249,148,242,236,98,48,88,255,143,25,1,235,159,210,127,229,219,6,20,19,41,23,220,116,32,214,217,7,197,244,101,247,93,18,117,151,140,84,68,104,42,232,36,226,57,55,57,181,128,52,6,203,130,54,199,103,197,158,184,138,127,61,223,65,111,57,25,181,72,139,155,65,139,48,15,128,95,194,241,163,12,246,39,191,53,212,114,194,90,65,109,13,121,48,171,160,68,35,192,251,149,193,182,207,178,158,107,32,192,59,214,166,145,205,76,194,17,236,248,105,195,184,201,91,214,106,71,163,206,253,189,15,166,160,158,55,182,108,213,82,244,47,221,194,227,48,139,93,104,165,186,46,214,47,63,142,36,158,192,116,253,133,77,50,45,85,208,33,203,120,156,6,55,217,53,210,131,30,194,170,65,32,80,32,81,218,104,125,77,236,131,42,23,51,41,208,230,40,175,127,201,126,254,209,89,221,187,181,101,185,235,139,217,248,49,187,232,192,124,28,52,88,70,236,155,38,60,43,157,178,180,45,203,113,4,9,67,86,60,136,52,5,61,152,126,254,205,152,68,61,64,58,226,75,218,19,204,177,16,138,148,243,180,234,110,6,134,194,139,167,50,151,95,62,160,137,209,208,255,81,199,177,240,114,1,163,160,235,235,172,203,57,245,240,94,121,56,11,132,16,23,152,180,38,90,26,107,103,77,223,70,133,160,220,55,161,159,238,135,127,195,39,208,86,53,94,195,241,255,207,90,238,9,252,64,51,154,107,238,114,42,193,58,242,19,108,172,209,86,71,42,197,80,100,152,114,254,57,174,37,64,50,36,160,251,173,106,84,18,16,170,209,101,166,151,240,142,96,134,97,50,207,93,244,231,22,49,72,181,188,188,85,53,41,160,158,84,157,23,30,169,226,115,33,73,115,107,143,0,226,138,147,191,74,190,144,231,29,158,45,154,232,182,228,53,105,112,118,75,176,179,123,111,233,14,139,90,157,138,223,14,191,88,106,91,191,149,119,119,125,12,238,211,244,188,43,214,146,153,165,147,172,221,81,131,160,19,124,234,236,188,144,176,73,96,127,208,169,247,17,186,160,163,61,186,59,233,72,217,58,90,43,43,23,250,105,188,236,66,19,98,125,250,90,130,162,167,174,46,218,37,184,26,92,237,34,0,26,104,74,167,221,23,105,113,9,187,125,231,185,93,92,121,93,23,185,54,19,90,235,249,3,121,58,43,88,53,140,51,45,206,210,228,223,67,147,216,82,11,167,178,164,218,132,152,116,134,84,112,15,165,106,15,116,46,222,118,186,76,133,157,255,99,27,35,96,230,14,223,36,164,244,30,234,71,169,225,124,239,103,239,185,44,71,223,241,177,16,211,173,64,220,127,244,65,244,249,195,214,90,121,43,248,177,241,128,96,74,224,104,16,53,79,225,14,219,175,78,129,103,35,184,131,156,66,49,75,196,237,145,109,124,157,74,188,157,84,32,153,170,210,235,165,6,155,60,118,114,50,169,40,37,1,220,122,220,107,20,39,19,238,244,128,227,140,103,0,179,250,11,140,38,165,57,63,111,193,84,165,175,223,21,24,232,153,190,211,114,99,96,103,146,32,24,107,66,117,93,27,243,49,114,246,219,30,34,20,17,69,183,243,131,101,22,123,146,89,58,14,130,29,141,36,211,54,162,164,189,208,207,2,157,64,29,178,133,166,206,71,226,123,104,195,207,127,14,140,247,187,212,124,199,222,83,46,134,206,111,75,190,63,73,82,47,139,200,197,11,130,44,168,239,104,124,162,31,115,106,15,77,72,8,188,215,102,185,145,177,146,105,215,243,128,236,120,202,35,200,18,3,56,41,51,228,233,136,75,253,209,15,226,133,173,67,184,30,89,158,18,91,156,153,18,111,152,178,1,79,85,158,151,216,76,58,134,155,146,49,89,17,51,188,208,128,156,11,43,131,131,106,12,149,63,166,121,16,63,219,137,51,65,222,5,172,189,253,110,113,53,167,226,44,245,31,50,38,174,100,68,22,13,112,212,36,155,239,195,60,53,18,123,223,198,86,22,195,153,183,238,240,84,186,32,5,221,42,82,204,140,146,40,142,221,64,66,150,70,55,47,30,39,14,91,230,39,190,250,204,44,92,192,48,150,46,192,2,42,75,126,145,237,31,191,38,153,131,36,227,179,79,231,201,9,204,104,33,64,247,81,36,153,134,244,72,253,218,167,247,131,248,178,75,238,207,226,79,244,209,92,176,76,70,26,233,159,72,80,240,245,86,236,211,60,129,147,52,202,224,10,121,136,140,72,97,73,10,133,96,120,170,207,50,34,150,192,32,223,232,196,218,17,88,13,218,31,177,119,20,156,206,58,133,152,213,248,174,186,249,107,70,175,113,37,10,115,145,51,107,100,20,219,82,204,77,140,219,219,169,215,58,48,94,235,31,79,145,66,12,48,214,3,229,197,44,184,188,88,27,187,162,100,106,211,186,207,12,7,55,129,174,102,0,79,203,232,178,166,41,96,67,20,205,236,10,17,185,214,114,166,94,180,205,186,114,55,253,184,106,217,46,50,15,196,129,214,56,81,178,117,165,228,136,107,226,194,252,239,232,52,189,121,119,33,227,225,214,234,74,40,173,225,105,36,9,32,65,235,127,209,218,119,230,246,90,85,92,208,117,25,145,241,125,158,150,196,130,194,200,251,49,170,85,124,87,213,239,96,184,96,197,63,244,187,217,215,49,3,224,114,164,10,22,251,65,108,238,13,29,254,18,139,129,219,58,169,151,73,96,64,221,26,16,12,14,12,78,9,203,11,80,73,221,118,103,173,1,169,193,215,109,126,166,137,12,12,135,17,81,209,32,12,131,60,0,153,66,201,121,182,155,39,109,173,1,186,45,253,219,88,63,179,91,22,106,108,66,107,17,105,97,59,6,133,136,82,129,125,190,184,234,131,23,198,146,94,243,204,25,190,50,160,81,176,220,38,215,41,120,112,38,74,163,171,24,106,116,214,231,194,77,99,71,195,47,141,134,111,103,119,122,241,34,5,170,123,150,232,85,63,156,112,76,202,78,176,136,79,161,164,245,223,119,235,27,8,99,121,57,0,225,90,143,129,173,209,102,133,158,64,233,181,113,212,237,35,132,15,88,36,85,226,152,217,11,16,251,213,25,7,85,125,48,155,221,141,133,205,66,237,6,5,241,72,247,133,199,177,78,236,71,27,110,205,207,241,40,22,141,156,101,179,172,227,30,248,161,147,84,177,176,26,32,103,36,110,30,67,137,223,121,255,110,247,94,76,30,149,83,111,96,72,165,93,200,58,207,176,213,13,29,75,187,45,112,179,43,234,213,242,216,43,249,33,207,40,167,96,46,219,167,44,111,57,183,96,243,201,5,215,73,106,130,134,7,142,153,17,97,126,88,35,57,154,246,15,16,48,120,187,131,106,242,11,250,99,54,230,135,88,172,62,208,30,127,145,236,44,247,246,202,229,174,206,139,144,172,167,141,73,106,163,33,202,57,80,76,67,219,18,99,153,119,22,223,8,132,90,173,119,88,241,34,158,228,149,129,248,73,110,153,176,170,26,33,117,151,227,204,107,181,26,21,245,164,236,219,77,199,199,35,205,68,49,148,238,100,242,214,99,155,100,23,181,56,99,13,119,225,107,153,143,182,246,225,208,95,196,75,114,87,98,134,84,115,210,91,16,159,38,83,255,6,141,147,176,178,28,7,98,154,157,117,22,186,222,203,229,195,97,78,111,21,1,209,7,216,220,49,206,103,113,12,92,248,125,213,205,208,125,25,23,255,131,122,18,244,102,110,19,246,57,97,29,160,122,12,249,191,178,249,218,202,196,118,95,227,2,202,72,253,166,224,126,142,247,255,235,17,182,40,239,72,49,69,198,190,146,45,197,143,72,232,60,106,114,24,207,64,199,21,148,63,154,255,94,65,161,221,130,35,137,115,115,180,84,241,144,61,126,156,106,22,242,150,187,185,206,193,114,109,233,188,162,195,80,84,37,148,76,38,233,82,107,55,196,65,244,142,66,169,247,79,119,3,176,143,31,254,163,250,36,254,95,244,199,37,243,80,12,199,218,35,41,133,113,33,14,19,65,68,109,255,12,46,255,36,190,184,245,158,28,243,54,230,255,252,10,28,140,185,137,52,36,177,174,246,253,228,33,46,4,171,48,142,104,247,44,43,68,29,108,218,170,183,172,241,193,73,207,219,37,138,1,150,130,219,251,45,165,77,163,56,41,211,48,28,136,245,232,57,137,129,92,21,128,45,154,238,208,32,231,214,120,74,179,72,201,37,186,206,84,50,7,123,49,12,239,253,65,164,149,178,102,109,53,34,240,96,200,137,6,135,145,49,172,151,73,182,67,200,127,30,211,36,85,185,165,56,97,54,221,209,90,70,22,143,152,129,15,204,59,5,143,171,180,132,244,145,20,44,11,142,181,72,223,151,147,26,241,164,157,222,7,97,79,43,35,103,66,163,25,155,118,174,109,181,98,111,56,136,55,63,81,51,89,250,61,148,153,110,132,172,218,99,18,104,242,83,175,53,197,209,126,182,44,53,73,229,104,21,252,214,227,27,176,170,31,200,156,251,40,253,90,104,145,10,1,175,235,135,77,56,137,11,51,99,233,59,250,122,62,196,2,245,142,86,59,143,192,123,130,214,245,182,157,134,228,82,199,243,29,167,83,105,75,4,236,116,174,50,18,89,242,200,87,109,23,221,184,42,3,82,80,103,135,218,190,7,129,98,180,64,149,196,181,217,136,28,58,56,53,14,16,248,30,82,197,85,149,53,2,112,81,243,53,131,126,174,187,3,237,209,3,20,9,246,22,3,194,201,118,169,89,116,66,199,66,16,175,193,47,238,65,137,126,87,148,144,167,191,216,137,23,120,162,24,80,68,168,161,148,167,6,137,56,1,160,59,75,181,56,92,175,90,233,7,212,173,52,242,167,91,64,194,196,220,18,71,186,221,224,84,47,76,156,55,190,180,102,18,21,27,55,125,249,219,154,48,54,210,58,72,73,154,78,48,73,105,233,200,178,230,208,130,172,18,160,79,130,20,166,83,203,232,203,108,136,211,228,152,192,103,222,8,46,245,50,29,25,234,254,228,47,202,93,242,41,33,139,115,212,186,141,90,222,177,4}; diff --git a/sdk/src/components/vrs/CMakeLists.txt b/sdk/src/components/vrs/CMakeLists.txt index 721fadf8..5cf84902 100644 --- a/sdk/src/components/vrs/CMakeLists.txt +++ b/sdk/src/components/vrs/CMakeLists.txt @@ -1,27 +1,25 @@ # This file is part of the FidelityFX SDK. -# -# Copyright (C) 2023 Advanced Micro Devices, Inc. +# +# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy -# of this softwareand associated documentation files(the “Software”), to deal +# 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 +# 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 noticeand this permission notice shall be included in +# 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 +# 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 +# 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 (FFX_VRS OR FFX_ALL) - # Shared sources set(SHARED_SOURCES ${FFX_SHARED_SOURCES}) diff --git a/sdk/src/components/vrs/ffx_vrs.cpp b/sdk/src/components/vrs/ffx_vrs.cpp index 7b42fb1e..ea0a62d2 100644 --- a/sdk/src/components/vrs/ffx_vrs.cpp +++ b/sdk/src/components/vrs/ffx_vrs.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 // for memset #include // for _countof #include // for fabs, abs, sinf, sqrt, etc. diff --git a/sdk/src/components/vrs/ffx_vrs_private.h b/sdk/src/components/vrs/ffx_vrs_private.h index 6917f39e..a8094274 100644 --- a/sdk/src/components/vrs/ffx_vrs_private.h +++ b/sdk/src/components/vrs/ffx_vrs_private.h @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy -// of this softwareand associated documentation files(the “Software”), to deal +// 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 +// 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 noticeand this permission notice shall be included in +// 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 +// 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 +// 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 diff --git a/sdk/src/shared/ffx_assert.cpp b/sdk/src/shared/ffx_assert.cpp index 4f494393..b183e940 100644 --- a/sdk/src/shared/ffx_assert.cpp +++ b/sdk/src/shared/ffx_assert.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 #include // for malloc() diff --git a/sdk/src/shared/ffx_object_management.cpp b/sdk/src/shared/ffx_object_management.cpp index deb48e9b..51bbde06 100644 --- a/sdk/src/shared/ffx_object_management.cpp +++ b/sdk/src/shared/ffx_object_management.cpp @@ -1,25 +1,25 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 #include "ffx_object_management.h" @@ -29,14 +29,14 @@ void ffxSafeReleasePipeline(FfxInterface* backendInterface, FfxPipelineState* pi backendInterface->fpDestroyPipeline(backendInterface, pipeline, effectContextId); } -void ffxSafeReleaseCopyResource(FfxInterface* backendInterface, FfxResourceInternal resource) +void ffxSafeReleaseCopyResource(FfxInterface* backendInterface, FfxResourceInternal resource, FfxUInt32 effectContextId) { FfxResourceInternal copyResource; copyResource.internalIndex = resource.internalIndex + 1; - backendInterface->fpDestroyResource(backendInterface, copyResource); + backendInterface->fpDestroyResource(backendInterface, copyResource, effectContextId); } -void ffxSafeReleaseResource(FfxInterface* backendInterface, FfxResourceInternal resource) +void ffxSafeReleaseResource(FfxInterface* backendInterface, FfxResourceInternal resource, FfxUInt32 effectContextId) { - backendInterface->fpDestroyResource(backendInterface, resource); + backendInterface->fpDestroyResource(backendInterface, resource, effectContextId); } diff --git a/sdk/src/shared/ffx_object_management.h b/sdk/src/shared/ffx_object_management.h index d44eb8cc..14828f31 100644 --- a/sdk/src/shared/ffx_object_management.h +++ b/sdk/src/shared/ffx_object_management.h @@ -1,34 +1,36 @@ // This file is part of the FidelityFX SDK. -// -// Copyright (C) 2023 Advanced Micro Devices, Inc. +// +// Copyright (c) 2023 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 +// 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 +// 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 : -// +// 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 +// 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 +// 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 + #if defined(__cplusplus) extern "C" { #endif // #if defined(__cplusplus) -void ffxSafeReleasePipeline(FfxInterface* backendInterface, FfxPipelineState* pipeline, FfxUInt32 effectContextId); -void ffxSafeReleaseCopyResource(FfxInterface* backendInterface, FfxResourceInternal resource); -void ffxSafeReleaseResource(FfxInterface* backendInterface, FfxResourceInternal resource); +FFX_API void ffxSafeReleasePipeline(FfxInterface* backendInterface, FfxPipelineState* pipeline, FfxUInt32 effectContextId); +FFX_API void ffxSafeReleaseCopyResource(FfxInterface* backendInterface, FfxResourceInternal resource, FfxUInt32 effectContextId); +FFX_API void ffxSafeReleaseResource(FfxInterface* backendInterface, FfxResourceInternal resource, FfxUInt32 effectContextId); #if defined(__cplusplus) } From 13c34aee76ddb2c286c25c47795fd3203e21d052 Mon Sep 17 00:00:00 2001 From: Edgardwifi <93519575+Edgardwifi@users.noreply.github.com> Date: Sat, 23 Dec 2023 17:40:41 -0500 Subject: [PATCH 2/2] yy --- .vscode/launch.json | 45 +++++++++++++++++++++++++++++++++++++++ CleanAllGeneratedData.bat | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..87dc4e80 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,45 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "shadered", + "request": "launch", + "name": "Ask for file name", + "program": "${workspaceFolder}/${command:AskForProgramName}", + "stopOnEntry": true + }, + { + "type": "shadered", + "request": "launch", + "name": "Ask for file name", + "program": "${workspaceFolder}/${command:AskForProgramName}", + "stopOnEntry": true + }, + + + { + "name": "Python C++ Debugger", + "type": "pythoncpp", + "request": "launch", + "pythonLaunchName": "Python: Current File", + "cppAttachName": "'(Windows) Attach' or '(gdb) Attach'" + }, + { + "name": "Python C++ Debugger", + "type": "pythoncpp", + "request": "launch", + "pythonConfig": "default", + "cppConfig": "!!pick 'default (win) Attach' or 'default (gdb) Attach'" + }, + { + "type": "shadered", + "request": "launch", + "name": "Ask for file name", + "program": "${workspaceFolder}/${command:AskForProgramName}", + "stopOnEntry": true + } + ] +} \ No newline at end of file diff --git a/CleanAllGeneratedData.bat b/CleanAllGeneratedData.bat index 6a9a5cbe..0eac2f3d 100644 --- a/CleanAllGeneratedData.bat +++ b/CleanAllGeneratedData.bat @@ -1,4 +1,4 @@ -@echo off +@echo on echo =============================================================== echo.

  • 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