├── .editorconfig ├── .gitignore ├── Build ├── ImageBasedPBR.sln ├── ImageBasedPBR.vcxproj ├── ImageBasedPBR.vcxproj.filters ├── PixelShaders.vcxproj └── VertexShaders.vcxproj ├── Data ├── Meshes │ ├── Cube.gltf │ ├── Cube_data.bin │ ├── Sphere.gltf │ └── Sphere_data.bin ├── Roboto-Medium.ttf ├── Shaders │ └── .gitkeep └── Textures │ └── Newport_Loft.hdr ├── ImageBasedPBR.png ├── LICENSE ├── README.md └── Source ├── CPUAndGPUCommon.h ├── External ├── DirectXMath │ ├── DirectXCollision.h │ ├── DirectXCollision.inl │ ├── DirectXColors.h │ ├── DirectXMath.h │ ├── DirectXMathConvert.inl │ ├── DirectXMathMatrix.inl │ ├── DirectXMathMisc.inl │ ├── DirectXMathVector.inl │ ├── DirectXPackedVector.h │ └── DirectXPackedVector.inl ├── EAAssert │ ├── eaassert.h │ ├── source │ │ └── eaassert.cpp │ └── version.h ├── EABase │ ├── config │ │ ├── eacompiler.h │ │ ├── eacompilertraits.h │ │ └── eaplatform.h │ ├── eabase.h │ ├── eahave.h │ ├── earesult.h │ ├── eastdarg.h │ ├── eaunits.h │ ├── int128.h │ ├── nullptr.h │ └── version.h ├── EASTL │ ├── algorithm.h │ ├── allocator.h │ ├── allocator_malloc.h │ ├── any.h │ ├── array.h │ ├── bitset.h │ ├── bitvector.h │ ├── bonus │ │ ├── adaptors.h │ │ ├── call_traits.h │ │ ├── compressed_pair.h │ │ ├── fixed_ring_buffer.h │ │ ├── fixed_tuple_vector.h │ │ ├── intrusive_sdlist.h │ │ ├── intrusive_slist.h │ │ ├── list_map.h │ │ ├── lru_cache.h │ │ ├── ring_buffer.h │ │ ├── sort_extra.h │ │ ├── sparse_matrix.h │ │ └── tuple_vector.h │ ├── chrono.h │ ├── core_allocator.h │ ├── core_allocator_adapter.h │ ├── deque.h │ ├── fixed_allocator.h │ ├── fixed_function.h │ ├── fixed_hash_map.h │ ├── fixed_hash_set.h │ ├── fixed_list.h │ ├── fixed_map.h │ ├── fixed_set.h │ ├── fixed_slist.h │ ├── fixed_string.h │ ├── fixed_substring.h │ ├── fixed_vector.h │ ├── functional.h │ ├── hash_map.h │ ├── hash_set.h │ ├── heap.h │ ├── initializer_list.h │ ├── internal │ │ ├── allocator_traits.h │ │ ├── allocator_traits_fwd_decls.h │ │ ├── char_traits.h │ │ ├── config.h │ │ ├── copy_help.h │ │ ├── enable_shared.h │ │ ├── fill_help.h │ │ ├── fixed_pool.h │ │ ├── function.h │ │ ├── function_detail.h │ │ ├── function_help.h │ │ ├── functional_base.h │ │ ├── generic_iterator.h │ │ ├── hashtable.h │ │ ├── in_place_t.h │ │ ├── integer_sequence.h │ │ ├── intrusive_hashtable.h │ │ ├── mem_fn.h │ │ ├── memory_base.h │ │ ├── meta.h │ │ ├── move_help.h │ │ ├── pair_fwd_decls.h │ │ ├── piecewise_construct_t.h │ │ ├── red_black_tree.h │ │ ├── smart_ptr.h │ │ ├── thread_support.h │ │ ├── tuple_fwd_decls.h │ │ ├── type_compound.h │ │ ├── type_fundamental.h │ │ ├── type_pod.h │ │ ├── type_properties.h │ │ └── type_transformations.h │ ├── intrusive_hash_map.h │ ├── intrusive_hash_set.h │ ├── intrusive_list.h │ ├── intrusive_ptr.h │ ├── iterator.h │ ├── linked_array.h │ ├── linked_ptr.h │ ├── list.h │ ├── map.h │ ├── memory.h │ ├── meta.h │ ├── numeric.h │ ├── numeric_limits.h │ ├── optional.h │ ├── priority_queue.h │ ├── queue.h │ ├── random.h │ ├── ratio.h │ ├── safe_ptr.h │ ├── scoped_array.h │ ├── scoped_ptr.h │ ├── segmented_vector.h │ ├── set.h │ ├── shared_array.h │ ├── shared_ptr.h │ ├── slist.h │ ├── sort.h │ ├── source │ │ ├── allocator_eastl.cpp │ │ ├── assert.cpp │ │ ├── fixed_pool.cpp │ │ ├── hashtable.cpp │ │ ├── intrusive_list.cpp │ │ ├── numeric_limits.cpp │ │ ├── red_black_tree.cpp │ │ ├── string.cpp │ │ └── thread_support.cpp │ ├── span.h │ ├── stack.h │ ├── string.h │ ├── string_hash_map.h │ ├── string_map.h │ ├── string_view.h │ ├── tuple.h │ ├── type_traits.h │ ├── unique_ptr.h │ ├── unordered_map.h │ ├── unordered_set.h │ ├── utility.h │ ├── variant.h │ ├── vector.h │ ├── vector_map.h │ ├── vector_multimap.h │ ├── vector_multiset.h │ ├── vector_set.h │ ├── version.h │ └── weak_ptr.h ├── EAStdC │ ├── EAAlignment.h │ ├── EABitTricks.h │ ├── EAByteCrackers.h │ ├── EACType.h │ ├── EACallback.h │ ├── EADateTime.h │ ├── EAEndian.h │ ├── EAFixedPoint.h │ ├── EAGlobal.h │ ├── EAHashCRC.h │ ├── EAHashString.h │ ├── EAMathHelp.h │ ├── EAMemory.h │ ├── EAProcess.h │ ├── EARandom.h │ ├── EARandomDistribution.h │ ├── EAScanf.h │ ├── EASingleton.h │ ├── EASprintf.h │ ├── EASprintfOrdered.h │ ├── EAStdC.h │ ├── EAStopwatch.h │ ├── EAString.h │ ├── EATextUtil.h │ ├── Int128_t.h │ ├── Win32 │ │ └── EAMathHelpWin32.inl │ ├── internal │ │ ├── Config.h │ │ ├── EAMemory.inl │ │ ├── IntrusiveList.h │ │ ├── ScanfCore.h │ │ ├── SprintfCore.h │ │ ├── Thread.h │ │ └── stdioEA.h │ ├── source │ │ ├── EACType.cpp │ │ ├── EACallback.cpp │ │ ├── EADateTime.cpp │ │ ├── EAFixedPoint.cpp │ │ ├── EAGlobal.cpp │ │ ├── EAHashCRC.cpp │ │ ├── EAHashString.cpp │ │ ├── EAMemory.cpp │ │ ├── EAProcess.cpp │ │ ├── EARandom.cpp │ │ ├── EAScanf.cpp │ │ ├── EAScanfCore.cpp │ │ ├── EASprintf.cpp │ │ ├── EASprintfCore.cpp │ │ ├── EASprintfOrdered.cpp │ │ ├── EAStdC.cpp │ │ ├── EAStopwatch.cpp │ │ ├── EAString.cpp │ │ ├── EATextUtil.cpp │ │ └── Int128_t.cpp │ └── version.h ├── EAThread │ ├── android │ │ ├── eathread_atomic_android.h │ │ └── eathread_atomic_android_c11.h │ ├── apple │ │ ├── eathread_atomic_apple.h │ │ ├── eathread_callstack_apple.h │ │ └── eathread_sync_apple.h │ ├── arm │ │ └── eathread_sync_arm.h │ ├── armgcc │ │ └── eathread_sync_armgcc.h │ ├── cpp11 │ │ └── eathread_atomic_cpp11.h │ ├── eathread.h │ ├── eathread_atomic.h │ ├── eathread_barrier.h │ ├── eathread_callstack.h │ ├── eathread_callstack_context.h │ ├── eathread_condition.h │ ├── eathread_futex.h │ ├── eathread_list.h │ ├── eathread_mutex.h │ ├── eathread_pool.h │ ├── eathread_rwmutex.h │ ├── eathread_rwmutex_ip.h │ ├── eathread_rwsemalock.h │ ├── eathread_rwspinlock.h │ ├── eathread_rwspinlockw.h │ ├── eathread_semaphore.h │ ├── eathread_spinlock.h │ ├── eathread_storage.h │ ├── eathread_sync.h │ ├── eathread_thread.h │ ├── gcc │ │ ├── eathread_atomic_gcc.h │ │ └── eathread_sync_gcc.h │ ├── internal │ │ ├── atomic.h │ │ ├── config.h │ │ ├── dllinfo.h │ │ ├── eathread_atomic.h │ │ ├── eathread_atomic_standalone.h │ │ ├── eathread_atomic_standalone_gcc.h │ │ ├── eathread_atomic_standalone_msvc.h │ │ ├── eathread_global.h │ │ └── timings.h │ ├── shared_array_mt.h │ ├── shared_ptr_mt.h │ ├── source │ │ ├── android │ │ │ ├── com_ea_EAThread_EAThread.h │ │ │ ├── eathread_android.cpp │ │ │ ├── eathread_fake_atomic_64.cpp │ │ │ └── eathread_semaphore_android.cpp │ │ ├── apple │ │ │ ├── eathread_callstack_apple.cpp │ │ │ └── eathread_semaphore_apple.cpp │ │ ├── arm │ │ │ └── eathread_callstack_arm.cpp │ │ ├── cpp11 │ │ │ ├── eathread_cpp11.cpp │ │ │ ├── eathread_mutex_cpp11.cpp │ │ │ ├── eathread_semaphore_cpp11.cpp │ │ │ └── eathread_thread_cpp11.cpp │ │ ├── eathread.cpp │ │ ├── eathread_barrier.cpp │ │ ├── eathread_callstack.cpp │ │ ├── eathread_condition.cpp │ │ ├── eathread_futex.cpp │ │ ├── eathread_mutex.cpp │ │ ├── eathread_pool.cpp │ │ ├── eathread_rwmutex.cpp │ │ ├── eathread_rwmutex_ip.cpp │ │ ├── eathread_semaphore.cpp │ │ ├── eathread_storage.cpp │ │ ├── eathread_thread.cpp │ │ ├── kettle │ │ │ ├── eathread_barrier_kettle.cpp │ │ │ ├── eathread_callstack_kettle.cpp │ │ │ ├── eathread_condition_kettle.cpp │ │ │ ├── eathread_kettle.cpp │ │ │ ├── eathread_mutex_kettle.cpp │ │ │ ├── eathread_pthread_stack_info.cpp │ │ │ ├── eathread_semaphore_kettle.cpp │ │ │ └── eathread_thread_kettle.cpp │ │ ├── libunwind │ │ │ └── eathread_callstack_libunwind.cpp │ │ ├── null │ │ │ └── eathread_callstack_null.cpp │ │ ├── pc │ │ │ ├── eathread_callstack_win32.cpp │ │ │ ├── eathread_callstack_win64.cpp │ │ │ ├── eathread_mutex_pc.cpp │ │ │ ├── eathread_pc.cpp │ │ │ ├── eathread_semaphore_pc.cpp │ │ │ └── eathread_thread_pc.cpp │ │ ├── unix │ │ │ ├── eathread_barrier_unix.cpp │ │ │ ├── eathread_callstack_glibc.cpp │ │ │ ├── eathread_condition_unix.cpp │ │ │ ├── eathread_mutex_unix.cpp │ │ │ ├── eathread_pthread_stack_info.cpp │ │ │ ├── eathread_semaphore_unix.cpp │ │ │ ├── eathread_thread_unix.cpp │ │ │ └── eathread_unix.cpp │ │ ├── version.cpp │ │ └── x86 │ │ │ └── eathread_callstack_x86.cpp │ ├── version.h │ ├── x86-64 │ │ ├── eathread_atomic_x86-64.h │ │ └── eathread_sync_x86-64.h │ └── x86 │ │ ├── eathread_atomic_x86.h │ │ └── eathread_sync_x86.h ├── cgltf.cpp ├── cgltf.h ├── d3dx12.h ├── imgui │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui_demo.cpp │ ├── imgui_draw.cpp │ ├── imgui_internal.h │ ├── imgui_widgets.cpp │ ├── imstb_rectpack.h │ ├── imstb_textedit.h │ └── imstb_truetype.h ├── stb_image.cpp └── stb_image.h ├── ImageBasedPBR.cpp ├── Library.cpp ├── Library.h └── Shaders ├── Common.hlsli ├── EquirectangularToCube.hlsl ├── GenerateBRDFIntegrationMap.hlsl ├── GenerateIrradianceMap.hlsl ├── GenerateMipmaps.hlsl ├── PrefilterEnvMap.hlsl ├── SampleEnvMap.hlsl ├── SimpleForward.hlsl ├── Test.hlsl └── UserInterface.hlsl /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Baseline 7 | [*] 8 | charset = utf-8 9 | indent_style = tab 10 | indent_size = 4 11 | tab_width = 4 12 | trim_trailing_whitespace = false 13 | max_line_length = 120 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pdb 2 | *.ilk 3 | *.exe 4 | *.cso 5 | *.ipdb 6 | *.iobj 7 | *.user 8 | /Build/.vs 9 | /Build/x64 10 | imgui.ini -------------------------------------------------------------------------------- /Build/ImageBasedPBR.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29009.5 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageBasedPBR", "ImageBasedPBR.vcxproj", "{89B82422-AD60-4402-A07C-68CA8C26D63A}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {04D14098-B9A3-4DF8-8356-76EBEB036B00} = {04D14098-B9A3-4DF8-8356-76EBEB036B00} 9 | {54D728F2-8AAD-41C1-B4D5-42C831AACC22} = {54D728F2-8AAD-41C1-B4D5-42C831AACC22} 10 | EndProjectSection 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VertexShaders", "VertexShaders.vcxproj", "{54D728F2-8AAD-41C1-B4D5-42C831AACC22}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PixelShaders", "PixelShaders.vcxproj", "{04D14098-B9A3-4DF8-8356-76EBEB036B00}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|x64 = Debug|x64 19 | Release|x64 = Release|x64 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {89B82422-AD60-4402-A07C-68CA8C26D63A}.Debug|x64.ActiveCfg = Debug|x64 23 | {89B82422-AD60-4402-A07C-68CA8C26D63A}.Debug|x64.Build.0 = Debug|x64 24 | {89B82422-AD60-4402-A07C-68CA8C26D63A}.Release|x64.ActiveCfg = Release|x64 25 | {89B82422-AD60-4402-A07C-68CA8C26D63A}.Release|x64.Build.0 = Release|x64 26 | {54D728F2-8AAD-41C1-B4D5-42C831AACC22}.Debug|x64.ActiveCfg = Debug|x64 27 | {54D728F2-8AAD-41C1-B4D5-42C831AACC22}.Debug|x64.Build.0 = Debug|x64 28 | {54D728F2-8AAD-41C1-B4D5-42C831AACC22}.Release|x64.ActiveCfg = Release|x64 29 | {54D728F2-8AAD-41C1-B4D5-42C831AACC22}.Release|x64.Build.0 = Release|x64 30 | {04D14098-B9A3-4DF8-8356-76EBEB036B00}.Debug|x64.ActiveCfg = Debug|x64 31 | {04D14098-B9A3-4DF8-8356-76EBEB036B00}.Debug|x64.Build.0 = Debug|x64 32 | {04D14098-B9A3-4DF8-8356-76EBEB036B00}.Release|x64.ActiveCfg = Release|x64 33 | {04D14098-B9A3-4DF8-8356-76EBEB036B00}.Release|x64.Build.0 = Release|x64 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {3FEDA15D-D8B8-475C-9C9B-E1784C81E0E4} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /Build/PixelShaders.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 16.0 15 | {04D14098-B9A3-4DF8-8356-76EBEB036B00} 16 | PS 17 | 10.0 18 | PixelShaders 19 | 20 | 21 | 22 | Application 23 | true 24 | v142 25 | MultiByte 26 | 27 | 28 | Application 29 | false 30 | v142 31 | true 32 | MultiByte 33 | 34 | 35 | 36 | $(Platform)\$(Configuration)\PS\ 37 | $(SolutionDir)..\ 38 | 39 | 40 | $(Platform)\$(Configuration)\PS\ 41 | $(SolutionDir)..\ 42 | 43 | 44 | 45 | MainPS 46 | 6.0 47 | $(OutDir)Data\Shaders\%(Filename).ps.cso 48 | Pixel 49 | 50 | 51 | 52 | 53 | MainPS 54 | 6.0 55 | $(OutDir)Data\Shaders\%(Filename).ps.cso 56 | Pixel 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | Pixel 66 | Pixel 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Build/VertexShaders.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 16.0 15 | {54D728F2-8AAD-41C1-B4D5-42C831AACC22} 16 | VS 17 | 10.0 18 | VertexShaders 19 | 20 | 21 | 22 | Application 23 | true 24 | v142 25 | MultiByte 26 | 27 | 28 | Application 29 | false 30 | v142 31 | true 32 | MultiByte 33 | 34 | 35 | 36 | $(Platform)\$(Configuration)\VS\ 37 | $(SolutionDir)..\ 38 | 39 | 40 | $(Platform)\$(Configuration)\VS\ 41 | $(SolutionDir)..\ 42 | 43 | 44 | 45 | MainVS 46 | 6.0 47 | $(OutDir)Data\Shaders\%(Filename).vs.cso 48 | Vertex 49 | /Ges %(AdditionalOptions) 50 | 51 | 52 | 53 | 54 | MainVS 55 | 6.0 56 | $(OutDir)Data\Shaders\%(Filename).vs.cso 57 | Vertex 58 | /Ges %(AdditionalOptions) 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Data/Meshes/Cube.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset":{ 3 | "version":"2.0", 4 | "generator":"Houdini GLTF 2.0 Exporter" 5 | }, 6 | "accessors":[ 7 | { 8 | "bufferView":0, 9 | "componentType":5121, 10 | "count":36, 11 | "type":"SCALAR", 12 | "min":[0 13 | ], 14 | "max":[35 15 | ] 16 | }, 17 | { 18 | "bufferView":1, 19 | "componentType":5126, 20 | "count":36, 21 | "type":"VEC3", 22 | "min":[-0.5,-0.5,-0.5 23 | ], 24 | "max":[0.5,0.5,0.5 25 | ] 26 | }, 27 | { 28 | "bufferView":2, 29 | "componentType":5126, 30 | "count":36, 31 | "type":"VEC3", 32 | "min":[-1,-1,-1 33 | ], 34 | "max":[1,1,1 35 | ] 36 | } 37 | ], 38 | "buffers":[ 39 | { 40 | "uri":"Cube_data.bin", 41 | "byteLength":900, 42 | "name":"main_buffer" 43 | } 44 | ], 45 | "bufferViews":[ 46 | { 47 | "buffer":0, 48 | "byteLength":36, 49 | "target":34963 50 | }, 51 | { 52 | "buffer":0, 53 | "byteOffset":36, 54 | "byteLength":432, 55 | "target":34962 56 | }, 57 | { 58 | "buffer":0, 59 | "byteOffset":468, 60 | "byteLength":432, 61 | "target":34962 62 | } 63 | ], 64 | "nodes":[ 65 | { 66 | "name":"box1", 67 | "mesh":0 68 | } 69 | ], 70 | "meshes":[ 71 | { 72 | "primitives":[ 73 | { 74 | "attributes":{ 75 | "NORMAL":2, 76 | "POSITION":1 77 | }, 78 | "indices":0 79 | } 80 | ] 81 | } 82 | ], 83 | "scenes":[ 84 | { 85 | "nodes":[0 86 | ] 87 | } 88 | ], 89 | "scene":0 90 | } 91 | -------------------------------------------------------------------------------- /Data/Meshes/Cube_data.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michal-z/ImageBasedPBR/ae3a9110a508bcc48ca786f22c12c3d5db6ddd61/Data/Meshes/Cube_data.bin -------------------------------------------------------------------------------- /Data/Meshes/Sphere.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset":{ 3 | "version":"2.0", 4 | "generator":"Houdini GLTF 2.0 Exporter" 5 | }, 6 | "accessors":[ 7 | { 8 | "bufferView":0, 9 | "componentType":5123, 10 | "count":6912, 11 | "type":"SCALAR", 12 | "min":[0 13 | ], 14 | "max":[1153 15 | ] 16 | }, 17 | { 18 | "bufferView":1, 19 | "componentType":5126, 20 | "count":1154, 21 | "type":"VEC3", 22 | "min":[-0.998026729,-1,-0.998026729 23 | ], 24 | "max":[0.998026729,1,0.998026729 25 | ] 26 | }, 27 | { 28 | "bufferView":2, 29 | "componentType":5126, 30 | "count":1154, 31 | "type":"VEC3", 32 | "min":[-0.99803704,-1,-0.99803704 33 | ], 34 | "max":[0.99803704,1,0.99803704 35 | ] 36 | } 37 | ], 38 | "buffers":[ 39 | { 40 | "uri":"Sphere_data.bin", 41 | "byteLength":41520, 42 | "name":"main_buffer" 43 | } 44 | ], 45 | "bufferViews":[ 46 | { 47 | "buffer":0, 48 | "byteLength":13824, 49 | "target":34963 50 | }, 51 | { 52 | "buffer":0, 53 | "byteOffset":13824, 54 | "byteLength":13848, 55 | "target":34962 56 | }, 57 | { 58 | "buffer":0, 59 | "byteOffset":27672, 60 | "byteLength":13848, 61 | "target":34962 62 | } 63 | ], 64 | "nodes":[ 65 | { 66 | "name":"geo1", 67 | "mesh":0 68 | } 69 | ], 70 | "meshes":[ 71 | { 72 | "primitives":[ 73 | { 74 | "attributes":{ 75 | "NORMAL":2, 76 | "POSITION":1 77 | }, 78 | "indices":0 79 | } 80 | ] 81 | } 82 | ], 83 | "scenes":[ 84 | { 85 | "nodes":[0 86 | ] 87 | } 88 | ], 89 | "scene":0 90 | } 91 | -------------------------------------------------------------------------------- /Data/Meshes/Sphere_data.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michal-z/ImageBasedPBR/ae3a9110a508bcc48ca786f22c12c3d5db6ddd61/Data/Meshes/Sphere_data.bin -------------------------------------------------------------------------------- /Data/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michal-z/ImageBasedPBR/ae3a9110a508bcc48ca786f22c12c3d5db6ddd61/Data/Roboto-Medium.ttf -------------------------------------------------------------------------------- /Data/Shaders/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michal-z/ImageBasedPBR/ae3a9110a508bcc48ca786f22c12c3d5db6ddd61/Data/Shaders/.gitkeep -------------------------------------------------------------------------------- /Data/Textures/Newport_Loft.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michal-z/ImageBasedPBR/ae3a9110a508bcc48ca786f22c12c3d5db6ddd61/Data/Textures/Newport_Loft.hdr -------------------------------------------------------------------------------- /ImageBasedPBR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michal-z/ImageBasedPBR/ae3a9110a508bcc48ca786f22c12c3d5db6ddd61/ImageBasedPBR.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Michal Ziulek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ImageBasedPBR 2 | Image Based Lighting using DirectX 12. 3 | 4 | ![image](/ImageBasedPBR.png) 5 | -------------------------------------------------------------------------------- /Source/CPUAndGPUCommon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | #include "DirectXMath/DirectXMath.h" 5 | typedef XMFLOAT4X4 float4x4; 6 | typedef XMFLOAT4X3 float4x3; 7 | typedef XMFLOAT2 float2; 8 | typedef XMFLOAT3 float3; 9 | typedef XMFLOAT4 float4; 10 | #endif 11 | 12 | #ifdef __cplusplus 13 | #define SALIGN alignas(256) 14 | #else 15 | #define SALIGN 16 | #endif 17 | 18 | struct SALIGN FPerDrawConstantData 19 | { 20 | float4x4 ObjectToClip; 21 | float4x3 ObjectToWorld; 22 | float3 Albedo; 23 | float Metallic; 24 | float Roughness; 25 | float AO; 26 | }; 27 | 28 | struct SALIGN FPerFrameConstantData 29 | { 30 | float4 LightPositions[4]; 31 | float4 LightColors[4]; 32 | float4 ViewerPosition; 33 | }; 34 | 35 | #ifdef __cplusplus 36 | #undef SALIGN 37 | #endif 38 | -------------------------------------------------------------------------------- /Source/External/EAAssert/source/eaassert.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include "EAAssert/eaassert.h" 6 | 7 | #ifndef EA_ASSERT_HAVE_OWN_HEADER 8 | 9 | #include 10 | 11 | #if defined(EA_PLATFORM_MICROSOFT) 12 | #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0400) 13 | #undef _WIN32_WINNT 14 | #define _WIN32_WINNT 0x0400 15 | #endif 16 | #ifndef WIN32_LEAN_AND_MEAN 17 | #define WIN32_LEAN_AND_MEAN 18 | #endif 19 | #pragma warning(push,0) 20 | #include // ::IsDebuggerPresent 21 | #pragma warning(pop) 22 | #endif 23 | 24 | 25 | 26 | 27 | #if !defined(EA_ASSERT_VSNPRINTF) 28 | #if defined(EA_PLATFORM_MICROSOFT) 29 | #define EA_ASSERT_VSNPRINTF _vsnprintf 30 | #define EA_ASSERT_SNPRINTF _snprintf 31 | #else 32 | #define EA_ASSERT_VSNPRINTF vsnprintf 33 | #define EA_ASSERT_SNPRINTF snprintf 34 | #endif 35 | #endif 36 | 37 | 38 | namespace EA { 39 | namespace Assert { 40 | namespace Detail { 41 | namespace { 42 | 43 | #if defined(EA_ASSERT_ENABLED) 44 | static void PlatformPrint(const char *str) 45 | { 46 | #if defined(EA_PLATFORM_MICROSOFT) 47 | if (IsDebuggerPresent()) 48 | { 49 | ::OutputDebugStringA(str); 50 | } 51 | #endif 52 | 53 | puts(str); 54 | 55 | #if defined(EA_PLATFORM_MOBILE) 56 | fflush(stdout); // Mobile platforms need this because otherwise you can easily lose output if the device crashes. 57 | #endif 58 | } 59 | #endif 60 | 61 | bool DefaultFailureCallback(const char* expr, const char* filename, int line, const char* function, const char* msg, va_list args) 62 | { 63 | #if defined(EA_ASSERT_ENABLED) 64 | const int largeEnough = 2048; 65 | char output[largeEnough + 1] = {}; 66 | char fmtMsg[largeEnough + 1] = {}; 67 | 68 | int len = EA_ASSERT_VSNPRINTF(fmtMsg, largeEnough, msg, args); 69 | 70 | if(len==0) 71 | { 72 | len = EA_ASSERT_SNPRINTF(fmtMsg, largeEnough, "none"); 73 | } 74 | 75 | // different platforms return different values for the error, but in both 76 | // cases it'll be out of bounds, so clamp the return value to largeEnough. 77 | if (len < 0 || len > largeEnough) 78 | len = largeEnough; 79 | 80 | fmtMsg[len] = '\0'; 81 | 82 | len = EA_ASSERT_SNPRINTF(output, largeEnough, 83 | "%s(%d) : EA_ASSERT failed: '%s' in function: %s\n, message: %s", 84 | filename, line, expr, function, fmtMsg); 85 | if (len < 0 || len > largeEnough) 86 | len = largeEnough; 87 | 88 | output[len] = '\0'; 89 | 90 | PlatformPrint(output); 91 | #else 92 | EA_UNUSED(expr); 93 | EA_UNUSED(filename); 94 | EA_UNUSED(line); 95 | EA_UNUSED(function); 96 | EA_UNUSED(msg); 97 | EA_UNUSED(args); 98 | #endif 99 | 100 | return true; 101 | } 102 | 103 | FailureCallback gFailureCallback = &DefaultFailureCallback; 104 | }} 105 | 106 | void SetFailureCallback(FailureCallback failureCallback) 107 | { 108 | Detail::gFailureCallback = failureCallback; 109 | } 110 | 111 | FailureCallback GetFailureCallback() 112 | { 113 | return Detail::gFailureCallback; 114 | } 115 | 116 | bool Detail::VCall(const char *expr, const char *filename, int line, const char *function, const char *msg, ...) 117 | { 118 | va_list args; 119 | va_start(args, msg); 120 | bool ret = (*GetFailureCallback())(expr, filename, line, function, msg, args); 121 | va_end(args); 122 | return ret; 123 | } 124 | 125 | bool Detail::Call(const char *expr, const char *filename, int line, const char *function) 126 | { 127 | // Pass an empty string as msg parameter. Some FailureCallback implementation (Frostbite) 128 | // will display only msg and discard the rest of the data when msg is non empty. 129 | return VCall(expr, filename, line, function, ""); 130 | } 131 | 132 | bool Detail::Call(const char *expr, const char *filename, int line, const char *function, const char* msg) 133 | { 134 | return VCall(expr, filename, line, function, "%s", msg); 135 | 136 | } 137 | 138 | }} 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /Source/External/EAAssert/version.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | /** 6 | \file 7 | Define the major, minor and patch versions. 8 | */ 9 | 10 | #ifndef EAASSERT_VERSION_H 11 | #define EAASSERT_VERSION_H 12 | 13 | // Define the major, minor and patch versions. 14 | // This information is updated with each release. 15 | 16 | //! This define indicates the major version number for the filesys package. 17 | //! \sa EAASSERT_VERSION_MAJOR 18 | #define EAASSERT_VERSION_MAJOR 1 19 | //! This define indicates the minor version number for the filesys package. 20 | //! \sa EAASSERT_VERSION_MINOR 21 | #define EAASSERT_VERSION_MINOR 5 22 | //! This define indicates the patch version number for the filesys package. 23 | //! \sa EAASSERT_VERSION_PATCH 24 | #define EAASSERT_VERSION_PATCH 8 25 | 26 | /*! 27 | * This is a utility macro that users may use to create a single version number 28 | * that can be compared against EAASSERT_VERSION. 29 | * 30 | * For example: 31 | * 32 | * \code 33 | * 34 | * #if EAASSERT_VERSION > EAASSERT_CREATE_VERSION_NUMBER( 1, 1, 0 ) 35 | * printf("Filesys version is greater than 1.1.0.\n"); 36 | * #endif 37 | * 38 | * \endcode 39 | */ 40 | #define EAASSERT_CREATE_VERSION_NUMBER( major_ver, minor_ver, patch_ver ) \ 41 | ((major_ver) * 1000000 + (minor_ver) * 1000 + (patch_ver)) 42 | 43 | /*! 44 | * This macro is an aggregate of the major, minor and patch version numbers. 45 | * \sa EAASSERT_CREATE_VERSION_NUMBER 46 | */ 47 | #define EAASSERT_VERSION \ 48 | EAASSERT_CREATE_VERSION_NUMBER( EAASSERT_VERSION_MAJOR, EAASSERT_VERSION_MINOR, EAASSERT_VERSION_PATCH ) 49 | 50 | #define EAASSERT_VERSION_MAJOR_STR EAASSERT_VERSION_STRINGIFY(EAASSERT_VERSION_MAJOR) 51 | #if EAASSERT_VERSION_MINOR >= 10 52 | #define EAASSERT_VERSION_MINOR_STR EAASSERT_VERSION_STRINGIFY(EAASSERT_VERSION_MINOR) 53 | #else 54 | #define EAASSERT_VERSION_MINOR_STR "0" EAASSERT_VERSION_STRINGIFY(EAASSERT_VERSION_MINOR) 55 | #endif 56 | 57 | #if EAASSERT_VERSION_PATCH >= 10 58 | #define EAASSERT_VERSION_PATCH_STR EAASSERT_VERSION_STRINGIFY(EAASSERT_VERSION_PATCH) 59 | #else 60 | #define EAASSERT_VERSION_PATCH_STR "0" EAASSERT_VERSION_STRINGIFY(EAASSERT_VERSION_PATCH) 61 | #endif 62 | 63 | /*! 64 | * This macro returns a string version of the macro 65 | * \sa EAASSERT_VERSION_STRING 66 | */ 67 | #define EAASSERT_VERSION_STRING EAASSERT_VERSION_MAJOR_STR "." EAASSERT_VERSION_MINOR_STR "." EAASSERT_VERSION_PATCH_STR 68 | 69 | #endif // EAASSERT_VERSION_H 70 | -------------------------------------------------------------------------------- /Source/External/EABase/earesult.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | * earesult.h 3 | * 4 | * Copyright (c) Electronic Arts Inc. All rights reserved. 5 | *---------------------------------------------------------------------------*/ 6 | 7 | 8 | #ifndef INCLUDED_earesult_H 9 | #define INCLUDED_earesult_H 10 | 11 | 12 | #include 13 | 14 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 15 | #pragma once /* Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. */ 16 | #endif 17 | 18 | 19 | 20 | /* This result type is width-compatible with most systems. */ 21 | typedef int32_t ea_result_type; 22 | 23 | 24 | namespace EA 25 | { 26 | typedef int32_t result_type; 27 | 28 | enum 29 | { 30 | #ifndef SUCCESS 31 | // Deprecated 32 | // Note: a public MS header has created a define of this name which causes a build error. Fortunately they 33 | // define it to 0 which is compatible. 34 | // see: WindowsSDK\8.1.51641-fb\installed\Include\um\RasError.h 35 | SUCCESS = 0, 36 | #endif 37 | // Deprecated 38 | FAILURE = -1, 39 | 40 | // These values are now the preferred constants 41 | EA_SUCCESS = 0, 42 | EA_FAILURE = -1, 43 | }; 44 | } 45 | 46 | 47 | /* Macro to simplify testing for success. */ 48 | #ifndef EA_SUCCEEDED 49 | #define EA_SUCCEEDED(result) ((result) >= 0) 50 | #endif 51 | 52 | /* Macro to simplfify testing for general failure. */ 53 | #ifndef EA_FAILED 54 | #define EA_FAILED(result) ((result) < 0) 55 | #endif 56 | 57 | 58 | #endif 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /Source/External/EABase/eastdarg.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | * eastdarg.h 3 | * 4 | * Copyright (c) Electronic Arts Inc. All rights reserved. 5 | *---------------------------------------------------------------------------*/ 6 | 7 | 8 | #ifndef INCLUDED_eastdarg_H 9 | #define INCLUDED_eastdarg_H 10 | 11 | 12 | #include 13 | #include 14 | 15 | 16 | // VA_ARG_COUNT 17 | // 18 | // Returns the number of arguments passed to a macro's ... argument. 19 | // This applies to macros only and not functions. 20 | // 21 | // Example usage: 22 | // assert(VA_ARG_COUNT() == 0); 23 | // assert(VA_ARG_COUNT(a) == 1); 24 | // assert(VA_ARG_COUNT(a, b) == 2); 25 | // assert(VA_ARG_COUNT(a, b, c) == 3); 26 | // 27 | #if !defined(VA_ARG_COUNT) 28 | #define VA_ARG_COUNT(...) VA_ARG_COUNT_II((VA_ARG_COUNT_PREFIX_ ## __VA_ARGS__ ## _VA_ARG_COUNT_POSTFIX,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) 29 | #define VA_ARG_COUNT_II(__args) VA_ARG_COUNT_I __args 30 | #define VA_ARG_COUNT_PREFIX__VA_ARG_COUNT_POSTFIX ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0 31 | #define VA_ARG_COUNT_I(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,N,...) N 32 | #endif 33 | 34 | 35 | // va_copy 36 | // 37 | // va_copy is required by C++11 38 | // C++11 and C99 require va_copy to be #defined and implemented. 39 | // http://en.cppreference.com/w/cpp/utility/variadic/va_copy 40 | // 41 | // Example usage: 42 | // void Func(char* p, ...){ 43 | // va_list args, argsCopy; 44 | // va_start(args, p); 45 | // va_copy(argsCopy, args); 46 | // (use args) 47 | // (use argsCopy, which acts the same as args) 48 | // va_end(args); 49 | // va_end(argsCopy); 50 | // } 51 | // 52 | #ifndef va_copy 53 | #if defined(__va_copy) // GCC and others define this for non-C99 compatibility. 54 | #define va_copy(dest, src) __va_copy((dest), (src)) 55 | #else 56 | // This may not work for some platforms, depending on their ABI. 57 | // It works for Microsoft x86,x64, and PowerPC-based platforms. 58 | #define va_copy(dest, src) memcpy(&(dest), &(src), sizeof(va_list)) 59 | #endif 60 | #endif 61 | 62 | 63 | 64 | // va_list_reference 65 | // 66 | // va_list_reference is not part of the C or C++ standards. 67 | // It allows you to pass a va_list by reference to another 68 | // function instead of by value. You cannot simply use va_list& 69 | // as that won't work with many va_list implementations because 70 | // they are implemented as arrays (which can't be passed by 71 | // reference to a function without decaying to a pointer). 72 | // 73 | // Example usage: 74 | // void Test(va_list_reference args){ 75 | // printf("%d", va_arg(args, int)); 76 | // } 77 | // void Func(char* p, ...){ 78 | // va_list args; 79 | // va_start(args, p); 80 | // Test(args); // Upon return args will be modified. 81 | // va_end(args); 82 | // } 83 | #ifndef va_list_reference 84 | #if defined(EA_PLATFORM_MICROSOFT) || (EA_PLATFORM_PTR_SIZE == 4) || (defined(EA_PLATFORM_APPLE) && defined(EA_PROCESSOR_ARM64)) || defined(CS_UNDEFINED_STRING) || (defined(EA_PLATFORM_ANDROID) && defined(EA_PROCESSOR_ARM64)) 85 | // This is required for platform ABIs in which va_list is a struct or pointer. 86 | #define va_list_reference va_list& 87 | #else 88 | // This is required for platform ABIs in which va_list is defined to be an array. 89 | #define va_list_reference va_list 90 | #endif 91 | #endif 92 | 93 | 94 | 95 | 96 | #endif /* Header include guard */ 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Source/External/EABase/eaunits.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | * eaunits.h 3 | * 4 | * Copyright (c) Electronic Arts Inc. All rights reserved. 5 | *---------------------------------------------------------------------------*/ 6 | 7 | 8 | #ifndef INCLUDED_eaunits_h 9 | #define INCLUDED_eaunits_h 10 | 11 | #include 12 | 13 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 14 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 15 | #endif 16 | 17 | // Defining common SI unit macros. 18 | // 19 | // The mebibyte is a multiple of the unit byte for digital information. Technically a 20 | // megabyte (MB) is a power of ten, while a mebibyte (MiB) is a power of two, 21 | // appropriate for binary machines. Many Linux distributions use the unit, but it is 22 | // not widely acknowledged within the industry or media. 23 | // Reference: https://en.wikipedia.org/wiki/Mebibyte 24 | // 25 | // Examples: 26 | // auto size1 = EA_KILOBYTE(16); 27 | // auto size2 = EA_MEGABYTE(128); 28 | // auto size3 = EA_MEBIBYTE(8); 29 | // auto size4 = EA_GIBIBYTE(8); 30 | 31 | // define byte for completeness 32 | #define EA_BYTE(x) (x) 33 | 34 | // Decimal SI units 35 | #define EA_KILOBYTE(x) (size_t(x) * 1000) 36 | #define EA_MEGABYTE(x) (size_t(x) * 1000 * 1000) 37 | #define EA_GIGABYTE(x) (size_t(x) * 1000 * 1000 * 1000) 38 | #define EA_TERABYTE(x) (size_t(x) * 1000 * 1000 * 1000 * 1000) 39 | #define EA_PETABYTE(x) (size_t(x) * 1000 * 1000 * 1000 * 1000 * 1000) 40 | #define EA_EXABYTE(x) (size_t(x) * 1000 * 1000 * 1000 * 1000 * 1000 * 1000) 41 | 42 | // Binary SI units 43 | #define EA_KIBIBYTE(x) (size_t(x) * 1024) 44 | #define EA_MEBIBYTE(x) (size_t(x) * 1024 * 1024) 45 | #define EA_GIBIBYTE(x) (size_t(x) * 1024 * 1024 * 1024) 46 | #define EA_TEBIBYTE(x) (size_t(x) * 1024 * 1024 * 1024 * 1024) 47 | #define EA_PEBIBYTE(x) (size_t(x) * 1024 * 1024 * 1024 * 1024 * 1024) 48 | #define EA_EXBIBYTE(x) (size_t(x) * 1024 * 1024 * 1024 * 1024 * 1024 * 1024) 49 | 50 | #endif // INCLUDED_earesult_H 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Source/External/EABase/nullptr.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | * nullptr.h 3 | * 4 | * Copyright (c) Electronic Arts Inc. All rights reserved. 5 | *---------------------------------------------------------------------------*/ 6 | 7 | 8 | #include 9 | #include 10 | 11 | 12 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 13 | #pragma once /* Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. */ 14 | #endif 15 | 16 | 17 | #if defined(EA_COMPILER_CPP11_ENABLED) && !defined(EA_COMPILER_NO_NULLPTR) && !defined(EA_HAVE_nullptr_t_IMPL) 18 | // The compiler supports nullptr, but the standard library doesn't implement a declaration for std::nullptr_t. So we provide one. 19 | namespace std { typedef decltype(nullptr) nullptr_t; } 20 | #endif 21 | 22 | 23 | 24 | #if defined(EA_COMPILER_NO_NULLPTR) // If the compiler lacks a native version... 25 | 26 | namespace std 27 | { 28 | class nullptr_t 29 | { 30 | public: 31 | template // When tested a pointer, acts as 0. 32 | operator T*() const 33 | { return 0; } 34 | 35 | template // When tested as a member pointer, acts as 0. 36 | operator T C::*() const 37 | { return 0; } 38 | 39 | typedef void* (nullptr_t::*bool_)() const; 40 | operator bool_() const // An rvalue of type std::nullptr_t can be converted to an rvalue of type bool; the resulting value is false. 41 | { return false; } // We can't use operator bool(){ return false; } because bool is convertable to int which breaks other required functionality. 42 | 43 | // We can't enable this without generating warnings about nullptr being uninitialized after being used when created without "= {}". 44 | //void* mSizeofVoidPtr; // sizeof(nullptr_t) == sizeof(void*). Needs to be public if nullptr_t is to be a POD. 45 | 46 | private: 47 | void operator&() const; // Address cannot be taken. 48 | }; 49 | 50 | inline nullptr_t nullptr_get() 51 | { 52 | nullptr_t n = { }; // std::nullptr exists. 53 | return n; 54 | } 55 | 56 | #if !defined(nullptr) // If somebody hasn't already defined nullptr in a custom way... 57 | #define nullptr nullptr_get() 58 | #endif 59 | 60 | } // namespace std 61 | 62 | 63 | template 64 | inline bool operator==(T* p, const std::nullptr_t) 65 | { return p == 0; } 66 | 67 | template 68 | inline bool operator==(const std::nullptr_t, T* p) 69 | { return p == 0; } 70 | 71 | template 72 | inline bool operator==(T U::* p, const std::nullptr_t) 73 | { return p == 0; } 74 | 75 | template 76 | inline bool operator==(const std::nullptr_t, T U::* p) 77 | { return p == 0; } 78 | 79 | inline bool operator==(const std::nullptr_t, const std::nullptr_t) 80 | { return true; } 81 | 82 | inline bool operator!=(const std::nullptr_t, const std::nullptr_t) 83 | { return false; } 84 | 85 | inline bool operator<(const std::nullptr_t, const std::nullptr_t) 86 | { return false; } 87 | 88 | inline bool operator>(const std::nullptr_t, const std::nullptr_t) 89 | { return false; } 90 | 91 | inline bool operator<=(const std::nullptr_t, const std::nullptr_t) 92 | { return true; } 93 | 94 | inline bool operator>=(const std::nullptr_t, const std::nullptr_t) 95 | { return true; } 96 | 97 | 98 | using std::nullptr_t; // exported to global namespace. 99 | using std::nullptr_get; // exported to global namespace. 100 | 101 | #endif // EA_COMPILER_NO_NULLPTR 102 | 103 | -------------------------------------------------------------------------------- /Source/External/EABase/version.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | * version.h 3 | * 4 | * Copyright (c) Electronic Arts Inc. All rights reserved. 5 | *---------------------------------------------------------------------------*/ 6 | 7 | #ifndef INCLUDED_EABASE_VERSION_H 8 | #define INCLUDED_EABASE_VERSION_H 9 | 10 | /////////////////////////////////////////////////////////////////////////////// 11 | // EABASE_VERSION 12 | // 13 | // We more or less follow the conventional EA packaging approach to versioning 14 | // here. A primary distinction here is that minor versions are defined as two 15 | // digit entities (e.g. .03") instead of minimal digit entities ".3"). The logic 16 | // here is that the value is a counter and not a floating point fraction. 17 | // Note that the major version doesn't have leading zeros. 18 | // 19 | // Example version strings: 20 | // "0.91.00" // Major version 0, minor version 91, patch version 0. 21 | // "1.00.00" // Major version 1, minor and patch version 0. 22 | // "3.10.02" // Major version 3, minor version 10, patch version 02. 23 | // "12.03.01" // Major version 12, minor version 03, patch version 24 | // 25 | // Example usage: 26 | // printf("EABASE version: %s", EABASE_VERSION); 27 | // printf("EABASE version: %d.%d.%d", EABASE_VERSION_N / 10000 % 100, EABASE_VERSION_N / 100 % 100, EABASE_VERSION_N % 100); 28 | // 29 | /////////////////////////////////////////////////////////////////////////////// 30 | 31 | #ifndef EABASE_VERSION 32 | #define EABASE_VERSION "2.09.05" 33 | #define EABASE_VERSION_N 20905 34 | #endif 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /Source/External/EASTL/allocator_malloc.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #ifndef EASTL_ALLOCATOR_MALLOC_H 7 | #define EASTL_ALLOCATOR_MALLOC_H 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | // EASTL_ALIGNED_MALLOC_AVAILABLE 16 | // 17 | // Identifies if the standard library provides a built-in aligned version of malloc. 18 | // Defined as 0 or 1, depending on the standard library or platform availability. 19 | // None of the viable C functions provides for an aligned malloc with offset, so we 20 | // don't consider that supported in any case. 21 | // 22 | // Options for aligned allocations: 23 | // C11 aligned_alloc http://linux.die.net/man/3/aligned_alloc 24 | // glibc memalign http://linux.die.net/man/3/posix_memalign 25 | // Posix posix_memalign http://pubs.opengroup.org/onlinepubs/000095399/functions/posix_memalign.html 26 | // VC++ _aligned_malloc http://msdn.microsoft.com/en-us/library/8z34s9c6%28VS.80%29.aspx This is not suitable, since it has a limitation that you need to free via _aligned_free. 27 | // 28 | #if !defined EASTL_ALIGNED_MALLOC_AVAILABLE 29 | #if defined(EA_PLATFORM_POSIX) && !defined(EA_PLATFORM_APPLE) 30 | // memalign is more consistently available than posix_memalign, though its location isn't consistent across 31 | // platforms and compiler libraries. Typically it's declared in one of three headers: stdlib.h, malloc.h, or malloc/malloc.h 32 | #include // memalign, posix_memalign. 33 | #define EASTL_ALIGNED_MALLOC_AVAILABLE 1 34 | 35 | #if defined(__clang__) 36 | #if __has_include() 37 | #include 38 | #elif __has_include() 39 | #include 40 | #endif 41 | #elif defined(EA_PLATFORM_BSD) 42 | #include 43 | #else 44 | #include 45 | #endif 46 | #else 47 | #define EASTL_ALIGNED_MALLOC_AVAILABLE 0 48 | #endif 49 | #endif 50 | 51 | 52 | namespace eastl 53 | { 54 | 55 | /////////////////////////////////////////////////////////////////////////////// 56 | // allocator_malloc 57 | // 58 | // Implements an EASTL allocator that uses malloc/free as opposed to 59 | // new/delete or PPMalloc Malloc/Free. 60 | // 61 | // Example usage: 62 | // vector intVector; 63 | // 64 | class allocator_malloc 65 | { 66 | public: 67 | allocator_malloc(const char* = NULL) 68 | { } 69 | 70 | allocator_malloc(const allocator_malloc&) 71 | { } 72 | 73 | allocator_malloc(const allocator_malloc&, const char*) 74 | { } 75 | 76 | allocator_malloc& operator=(const allocator_malloc&) 77 | { return *this; } 78 | 79 | bool operator==(const allocator_malloc&) 80 | { return true; } 81 | 82 | bool operator!=(const allocator_malloc&) 83 | { return false; } 84 | 85 | void* allocate(size_t n, int /*flags*/ = 0) 86 | { return malloc(n); } 87 | 88 | void* allocate(size_t n, size_t alignment, size_t alignmentOffset, int /*flags*/ = 0) 89 | { 90 | #if EASTL_ALIGNED_MALLOC_AVAILABLE 91 | if((alignmentOffset % alignment) == 0) // We check for (offset % alignmnent == 0) instead of (offset == 0) because any block which is aligned on e.g. 64 also is aligned at an offset of 64 by definition. 92 | return memalign(alignment, n); // memalign is more consistently available than posix_memalign. 93 | #else 94 | if((alignment <= EASTL_SYSTEM_ALLOCATOR_MIN_ALIGNMENT) && ((alignmentOffset % alignment) == 0)) 95 | return malloc(n); 96 | #endif 97 | return NULL; 98 | } 99 | 100 | void deallocate(void* p, size_t /*n*/) 101 | { free(p); } 102 | 103 | const char* get_name() const 104 | { return "allocator_malloc"; } 105 | 106 | void set_name(const char*) 107 | { } 108 | }; 109 | 110 | 111 | } // namespace eastl 112 | 113 | 114 | 115 | #endif // Header include guard 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /Source/External/EASTL/bonus/adaptors.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | /////////////////////////////////////////////////////////////////////////////// 6 | /////////////////////////////////////////////////////////////////////////////// 7 | 8 | 9 | #ifndef EASTL_ADAPTORS_H 10 | #define EASTL_ADAPTORS_H 11 | 12 | 13 | #include 14 | #include 15 | 16 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 17 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 18 | #endif 19 | 20 | EA_DISABLE_VC_WARNING(4512 4626) 21 | #if defined(_MSC_VER) && (_MSC_VER >= 1900) // VS2015+ 22 | EA_DISABLE_VC_WARNING(5027) // move assignment operator was implicitly defined as deleted 23 | #endif 24 | 25 | 26 | namespace eastl 27 | { 28 | /// reverse 29 | /// 30 | /// This adaptor allows reverse iteration of a container in ranged base for-loops. 31 | /// 32 | /// for (auto& i : reverse(c)) { ... } 33 | /// 34 | template 35 | struct reverse_wrapper 36 | { 37 | reverse_wrapper(Container& c) : mContainer(c) {} 38 | Container& mContainer; 39 | }; 40 | 41 | template 42 | auto begin(const reverse_wrapper& w) -> decltype(rbegin(w.mContainer)) 43 | { return rbegin(w.mContainer); } 44 | 45 | template 46 | auto end(const reverse_wrapper& w) -> decltype(rend(w.mContainer)) 47 | { return rend(w.mContainer); } 48 | 49 | template 50 | reverse_wrapper reverse(Container&& c) 51 | { return reverse_wrapper(eastl::forward(c)); } 52 | 53 | } // namespace eastl 54 | 55 | #if defined(_MSC_VER) && (_MSC_VER >= 1900) // VS2015+ 56 | EA_RESTORE_VC_WARNING() 57 | #endif 58 | EA_RESTORE_VC_WARNING() 59 | 60 | #endif // Header include guard 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Source/External/EASTL/bonus/call_traits.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | /////////////////////////////////////////////////////////////////////////////// 6 | // The design for call_traits here is very similar to that found in template 7 | // metaprogramming libraries such as Boost, GCC, and Metrowerks, given that 8 | // these libraries have established this interface as a defacto standard for 9 | // solving this problem. Also, these are described in various books on the 10 | // topic of template metaprogramming, such as "Modern C++ Design". 11 | // 12 | // See http://www.boost.org/libs/utility/call_traits.htm or search for 13 | // call_traits in Google for a description of call_traits. 14 | /////////////////////////////////////////////////////////////////////////////// 15 | 16 | 17 | #ifndef EASTL_CALL_TRAITS_H 18 | #define EASTL_CALL_TRAITS_H 19 | 20 | 21 | #include 22 | #include 23 | 24 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 25 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 26 | #endif 27 | 28 | 29 | 30 | namespace eastl 31 | { 32 | 33 | 34 | template 35 | struct ct_imp2 { typedef const T& param_type; }; 36 | 37 | template 38 | struct ct_imp2 { typedef const T param_type; }; 39 | 40 | template 41 | struct ct_imp { typedef const T& param_type; }; 42 | 43 | template 44 | struct ct_imp { typedef typename ct_imp2::param_type param_type; }; 45 | 46 | template 47 | struct ct_imp { typedef T const param_type; }; 48 | 49 | 50 | 51 | template 52 | struct call_traits 53 | { 54 | public: 55 | typedef T value_type; 56 | typedef T& reference; 57 | typedef const T& const_reference; 58 | typedef typename ct_imp::value, is_arithmetic::value>::param_type param_type; 59 | }; 60 | 61 | 62 | template 63 | struct call_traits 64 | { 65 | typedef T& value_type; 66 | typedef T& reference; 67 | typedef const T& const_reference; 68 | typedef T& param_type; 69 | }; 70 | 71 | 72 | template 73 | struct call_traits 74 | { 75 | private: 76 | typedef T array_type[N]; 77 | 78 | public: 79 | typedef const T* value_type; 80 | typedef array_type& reference; 81 | typedef const array_type& const_reference; 82 | typedef const T* const param_type; 83 | }; 84 | 85 | 86 | template 87 | struct call_traits 88 | { 89 | private: 90 | typedef const T array_type[N]; 91 | 92 | public: 93 | typedef const T* value_type; 94 | typedef array_type& reference; 95 | typedef const array_type& const_reference; 96 | typedef const T* const param_type; 97 | }; 98 | 99 | 100 | } // namespace eastl 101 | 102 | 103 | #endif // Header include guard 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /Source/External/EASTL/bonus/fixed_ring_buffer.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_FIXED_RING_BUFFER_H 6 | #define EASTL_FIXED_RING_BUFFER_H 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 13 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 14 | #endif 15 | 16 | namespace eastl 17 | { 18 | 19 | /// fixed_ring_buffer 20 | /// 21 | /// This is a convenience template alias for creating a fixed-sized 22 | /// ring_buffer using eastl::fixed_vector as its storage container. This has 23 | /// been tricky for users to get correct due to the constructor requirements 24 | /// of eastl::ring_buffer leaking the implementation detail of the sentinel 25 | /// value being used internally. In addition, it was not obvious what the 26 | /// correct allocator_type template parameter should be used for containers 27 | /// providing both a default allocator type and an overflow allocator type. 28 | /// 29 | /// We are over-allocating the fixed_vector container to accommodate the 30 | /// ring_buffer sentinel to prevent that implementation detail leaking into 31 | /// user code. 32 | /// 33 | /// Example usage: 34 | /// 35 | /// fixed_ring_buffer rb = {0, 1, 2, 3, 4, 5, 6, 7}; 36 | /// or 37 | /// fixed_ring_buffer rb(8); // capacity doesn't need to respect sentinel 38 | /// rb.push_back(0); 39 | /// 40 | /// 41 | #if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES) 42 | template 43 | using fixed_ring_buffer = 44 | ring_buffer, typename fixed_vector::overflow_allocator_type>; 45 | #endif 46 | 47 | } // namespace eastl 48 | 49 | #endif // Header include guard 50 | 51 | -------------------------------------------------------------------------------- /Source/External/EASTL/core_allocator.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_CORE_ALLOCATOR_H 6 | #define EASTL_CORE_ALLOCATOR_H 7 | 8 | #if EASTL_CORE_ALLOCATOR_ENABLED 9 | 10 | #include 11 | 12 | namespace EA 13 | { 14 | namespace Allocator 15 | { 16 | /// EASTLCoreAllocatorImpl 17 | /// 18 | /// EASTL provides an out of the box implementation of the 19 | /// ICoreAllocator interface. This is provided as a convenience for 20 | /// users who wish to provide ICoreAllocator implementations for EASTL to use. 21 | /// 22 | /// EASTL has a dependency on coreallocator so to provide an out of 23 | /// the box implementation for EASTLCoreAlloctor and EASTLCoreDeleter 24 | /// that can be used and tested. Historically we could not test 25 | /// ICoreAllocator interface because we relied on the code being linked 26 | /// in user code. 27 | /// 28 | 29 | class EASTLCoreAllocatorImpl : public ICoreAllocator 30 | { 31 | public: 32 | virtual void* Alloc(size_t size, const char* name, unsigned int flags) 33 | { 34 | return ::operator new[](size, name, flags, 0, __FILE__, __LINE__); 35 | } 36 | 37 | virtual void* Alloc(size_t size, const char* name, unsigned int flags, unsigned int alignment, unsigned int alignOffset = 0) 38 | { 39 | return ::operator new[](size, alignment, alignOffset, name, flags, 0, __FILE__, __LINE__); 40 | } 41 | 42 | virtual void Free(void* ptr, size_t size = 0) 43 | { 44 | ::operator delete(static_cast(ptr)); 45 | } 46 | 47 | virtual void* AllocDebug(size_t size, const DebugParams debugParams, unsigned int flags) 48 | { 49 | return Alloc(size, debugParams.mName, flags); 50 | } 51 | 52 | virtual void* AllocDebug(size_t size, const DebugParams debugParams, unsigned int flags, unsigned int align, unsigned int alignOffset = 0) 53 | { 54 | return Alloc(size, debugParams.mName, flags, align, alignOffset); 55 | } 56 | 57 | static EASTLCoreAllocatorImpl* GetDefaultAllocator(); 58 | }; 59 | 60 | inline EASTLCoreAllocatorImpl* EASTLCoreAllocatorImpl::GetDefaultAllocator() 61 | { 62 | static EASTLCoreAllocatorImpl allocator; 63 | return &allocator; 64 | } 65 | } 66 | } 67 | 68 | #endif // EASTL_CORE_ALLOCATOR_ENABLED 69 | #endif // EASTL_CORE_ALLOCATOR_H 70 | 71 | -------------------------------------------------------------------------------- /Source/External/EASTL/fixed_function.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_FIXED_FUNCTION_H 6 | #define EASTL_FIXED_FUNCTION_H 7 | 8 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 9 | #pragma once 10 | #endif 11 | 12 | #include 13 | 14 | namespace eastl 15 | { 16 | #define EASTL_INTERNAL_FIXED_FUNCTION_STATIC_ASSERT(TYPE) \ 17 | static_assert(sizeof(TYPE) <= sizeof(typename Base::FunctorStorageType), \ 18 | "fixed_function local buffer is not large enough to hold the callable object.") 19 | 20 | #define EASTL_INTERNAL_FIXED_FUNCTION_NEW_SIZE_STATIC_ASSERT(NEW_SIZE_IN_BYTES) \ 21 | static_assert(SIZE_IN_BYTES >= NEW_SIZE_IN_BYTES, \ 22 | "fixed_function local buffer is not large enough to hold the new fixed_function type.") 23 | 24 | template 25 | class fixed_function; 26 | 27 | template 28 | class fixed_function : public internal::function_detail 29 | { 30 | using Base = internal::function_detail; 31 | 32 | public: 33 | using typename Base::result_type; 34 | 35 | fixed_function() EA_NOEXCEPT = default; 36 | fixed_function(std::nullptr_t p) EA_NOEXCEPT 37 | : Base(p) 38 | { 39 | } 40 | 41 | fixed_function(const fixed_function& other) 42 | : Base(other) 43 | { 44 | } 45 | 46 | fixed_function(fixed_function&& other) 47 | : Base(eastl::move(other)) 48 | { 49 | } 50 | 51 | template 52 | fixed_function(Functor functor) 53 | : Base(eastl::move(functor)) 54 | { 55 | EASTL_INTERNAL_FIXED_FUNCTION_STATIC_ASSERT(Functor); 56 | } 57 | 58 | template 59 | fixed_function(const fixed_function& other) 60 | : Base(other) 61 | { 62 | EASTL_INTERNAL_FIXED_FUNCTION_NEW_SIZE_STATIC_ASSERT(NEW_SIZE_IN_BYTES); 63 | } 64 | 65 | template 66 | fixed_function(fixed_function&& other) 67 | : Base(eastl::move(other)) 68 | { 69 | EASTL_INTERNAL_FIXED_FUNCTION_NEW_SIZE_STATIC_ASSERT(NEW_SIZE_IN_BYTES); 70 | } 71 | 72 | ~fixed_function() EA_NOEXCEPT = default; 73 | 74 | fixed_function& operator=(const fixed_function& other) 75 | { 76 | Base::operator=(other); 77 | return *this; 78 | } 79 | 80 | fixed_function& operator=(fixed_function&& other) 81 | { 82 | Base::operator=(eastl::move(other)); 83 | return *this; 84 | } 85 | 86 | fixed_function& operator=(std::nullptr_t p) EA_NOEXCEPT 87 | { 88 | Base::operator=(p); 89 | return *this; 90 | } 91 | 92 | template 93 | fixed_function& operator=(const fixed_function& other) 94 | { 95 | EASTL_INTERNAL_FIXED_FUNCTION_NEW_SIZE_STATIC_ASSERT(NEW_SIZE_IN_BYTES); 96 | 97 | Base::operator=(other); 98 | return *this; 99 | } 100 | 101 | template 102 | fixed_function& operator=(fixed_function&& other) 103 | { 104 | EASTL_INTERNAL_FIXED_FUNCTION_NEW_SIZE_STATIC_ASSERT(NEW_SIZE_IN_BYTES); 105 | 106 | Base::operator=(eastl::move(other)); 107 | return *this; 108 | } 109 | 110 | template 111 | fixed_function& operator=(Functor&& functor) 112 | { 113 | EASTL_INTERNAL_FIXED_FUNCTION_STATIC_ASSERT(eastl::decay_t); 114 | Base::operator=(eastl::forward(functor)); 115 | return *this; 116 | } 117 | 118 | template 119 | fixed_function& operator=(eastl::reference_wrapper f) EA_NOEXCEPT 120 | { 121 | EASTL_INTERNAL_FIXED_FUNCTION_STATIC_ASSERT(eastl::reference_wrapper); 122 | Base::operator=(f); 123 | return *this; 124 | } 125 | 126 | void swap(fixed_function& other) EA_NOEXCEPT 127 | { 128 | Base::swap(other); 129 | } 130 | 131 | explicit operator bool() const EA_NOEXCEPT 132 | { 133 | return Base::operator bool(); 134 | } 135 | 136 | R operator ()(Args... args) const 137 | { 138 | return Base::operator ()(eastl::forward(args)...); 139 | } 140 | 141 | #if EASTL_RTTI_ENABLED 142 | const std::type_info& target_type() const EA_NOEXCEPT 143 | { 144 | return Base::target_type(); 145 | } 146 | 147 | template 148 | Functor* target() EA_NOEXCEPT 149 | { 150 | return Base::target(); 151 | } 152 | 153 | template 154 | const Functor* target() const EA_NOEXCEPT 155 | { 156 | return Base::target(); 157 | } 158 | #endif 159 | }; 160 | 161 | template 162 | bool operator==(const fixed_function& f, std::nullptr_t) EA_NOEXCEPT 163 | { 164 | return !f; 165 | } 166 | 167 | template 168 | bool operator==(std::nullptr_t, const fixed_function& f) EA_NOEXCEPT 169 | { 170 | return !f; 171 | } 172 | 173 | template 174 | bool operator!=(const fixed_function& f, std::nullptr_t) EA_NOEXCEPT 175 | { 176 | return !!f; 177 | } 178 | 179 | template 180 | bool operator!=(std::nullptr_t, const fixed_function& f) EA_NOEXCEPT 181 | { 182 | return !!f; 183 | } 184 | 185 | template 186 | void swap(fixed_function& lhs, fixed_function& rhs) 187 | { 188 | lhs.swap(rhs); 189 | } 190 | 191 | } // namespace eastl 192 | 193 | #endif // EASTL_FIXED_FUNCTION_H 194 | -------------------------------------------------------------------------------- /Source/External/EASTL/initializer_list.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | // 4 | // This file #includes if it's available, else it defines 5 | // its own version of std::initializer_list. It does not define eastl::initializer_list 6 | // because that would not provide any use, due to how the C++11 Standard works. 7 | /////////////////////////////////////////////////////////////////////////////// 8 | 9 | 10 | #ifndef EASTL_INITIALIZER_LIST_H 11 | #define EASTL_INITIALIZER_LIST_H 12 | 13 | 14 | #include 15 | #include 16 | 17 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 18 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 19 | #endif 20 | 21 | 22 | #if defined(EA_HAVE_CPP11_INITIALIZER_LIST) // If the compiler can generate calls to std::initializer_list... 23 | 24 | // The initializer_list type must be declared in the std namespace, as that's the 25 | // namespace the compiler uses when generating code to use it. 26 | EA_DISABLE_ALL_VC_WARNINGS() 27 | #include 28 | EA_RESTORE_ALL_VC_WARNINGS() 29 | 30 | #else 31 | 32 | // If you get an error here about initializer_list being already defined, then the EA_HAVE_CPP11_INITIALIZER_LIST define from needs to be updated. 33 | namespace std 34 | { 35 | // See the C++11 Standard, section 18.9. 36 | template 37 | class initializer_list 38 | { 39 | public: 40 | typedef E value_type; 41 | typedef const E& reference; 42 | typedef const E& const_reference; 43 | typedef size_t size_type; 44 | typedef const E* iterator; // Must be const, as initializer_list (and its mpArray) is an immutable temp object. 45 | typedef const E* const_iterator; 46 | 47 | private: 48 | iterator mpArray; 49 | size_type mArraySize; 50 | 51 | // This constructor is private, but the C++ compiler has the ability to call it, as per the C++11 Standard. 52 | initializer_list(const_iterator pArray, size_type arraySize) 53 | : mpArray(pArray), mArraySize(arraySize) { } 54 | 55 | public: 56 | initializer_list() EA_NOEXCEPT // EA_NOEXCEPT requires a recent version of EABase. 57 | : mpArray(NULL), mArraySize(0) { } 58 | 59 | size_type size() const EA_NOEXCEPT { return mArraySize; } 60 | const_iterator begin() const EA_NOEXCEPT { return mpArray; } // Must be const_iterator, as initializer_list (and its mpArray) is an immutable temp object. 61 | const_iterator end() const EA_NOEXCEPT { return mpArray + mArraySize; } 62 | }; 63 | 64 | 65 | template 66 | const T* begin(std::initializer_list ilist) EA_NOEXCEPT 67 | { 68 | return ilist.begin(); 69 | } 70 | 71 | template 72 | const T* end(std::initializer_list ilist) EA_NOEXCEPT 73 | { 74 | return ilist.end(); 75 | } 76 | } 77 | 78 | #endif 79 | 80 | 81 | #endif // Header include guard 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Source/External/EASTL/internal/allocator_traits_fwd_decls.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #ifndef EASTL_INTERNAL_ALLOCATOR_TRAITS_H 7 | #define EASTL_INTERNAL_ALLOCATOR_TRAITS_H 8 | 9 | 10 | #include 11 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 12 | #pragma once 13 | #endif 14 | 15 | #include 16 | #include 17 | 18 | namespace eastl 19 | { 20 | template 21 | struct allocator_traits; 22 | 23 | } // namespace eastl 24 | 25 | #endif // Header include guard 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Source/External/EASTL/internal/enable_shared.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #ifndef EASTL_INTERNAL_ENABLE_SHARED_H 7 | #define EASTL_INTERNAL_ENABLE_SHARED_H 8 | 9 | 10 | #include 11 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 12 | #pragma once 13 | #endif 14 | 15 | namespace eastl 16 | { 17 | 18 | /// enable_shared_from_this 19 | /// 20 | /// This is a helper mixin class that allows you to make any class 21 | /// export a shared_ptr instance that is associated with the class 22 | /// instance. Any class that inherits from this class gets two functions: 23 | /// shared_ptr shared_from_this(); 24 | /// shared_ptr shared_from_this() const; 25 | /// If you call shared_from_this, you get back a shared_ptr that 26 | /// refers to the class. A second call to shared_from_this returns 27 | /// another shared_ptr that is shared with the first one. 28 | /// 29 | /// The trick that happens which is not so obvious here (and which is 30 | /// not mentioned at all in the Boost documentation of their version 31 | /// of this) is that the shared_ptr constructor detects that the 32 | /// class has an enable_shared_from_this mixin and sets up this system 33 | /// automatically for the user. This is done with template tricks. 34 | /// 35 | /// For some additional explanation, see the Boost documentation for 36 | /// their description of their version of enable_shared_from_this. 37 | /// 38 | template 39 | class enable_shared_from_this 40 | { 41 | public: 42 | shared_ptr shared_from_this() 43 | { return shared_ptr(mWeakPtr); } 44 | 45 | shared_ptr shared_from_this() const 46 | { return shared_ptr(mWeakPtr); } 47 | 48 | public: // This is public because the alternative fails on some compilers that we need to support. 49 | mutable weak_ptr mWeakPtr; 50 | 51 | protected: 52 | template friend class shared_ptr; 53 | 54 | EA_CONSTEXPR enable_shared_from_this() EA_NOEXCEPT 55 | { } 56 | 57 | enable_shared_from_this(const enable_shared_from_this&) EA_NOEXCEPT 58 | { } 59 | 60 | enable_shared_from_this& operator=(const enable_shared_from_this&) EA_NOEXCEPT 61 | { return *this; } 62 | 63 | ~enable_shared_from_this() 64 | { } 65 | 66 | }; // enable_shared_from_this 67 | 68 | } // namespace eastl 69 | 70 | 71 | #endif // Header include guard 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Source/External/EASTL/internal/function.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_FUNCTION_H 6 | #define EASTL_FUNCTION_H 7 | 8 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 9 | #pragma once 10 | #endif 11 | 12 | #include 13 | 14 | namespace eastl 15 | { 16 | 17 | /// EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE 18 | /// 19 | /// Defines the size of the SSO buffer which is used to hold the specified capture state of the callable. 20 | /// 21 | #ifndef EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE 22 | #define EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE (2 * sizeof(void*)) 23 | #endif 24 | 25 | static_assert(EASTL_FUNCTION_DEFAULT_CAPTURE_SSO_SIZE >= sizeof(void*), "functor storage must be able to hold at least a pointer!"); 26 | 27 | template 28 | class function; 29 | 30 | template 31 | class function : public internal::function_detail 32 | { 33 | private: 34 | using Base = internal::function_detail; 35 | public: 36 | using typename Base::result_type; 37 | 38 | function() EA_NOEXCEPT = default; 39 | function(std::nullptr_t p) EA_NOEXCEPT 40 | : Base(p) 41 | { 42 | } 43 | 44 | function(const function& other) 45 | : Base(other) 46 | { 47 | } 48 | 49 | function(function&& other) 50 | : Base(eastl::move(other)) 51 | { 52 | } 53 | 54 | template 55 | function(Functor functor) 56 | : Base(eastl::move(functor)) 57 | { 58 | } 59 | 60 | ~function() EA_NOEXCEPT = default; 61 | 62 | function& operator=(const function& other) 63 | { 64 | Base::operator=(other); 65 | return *this; 66 | } 67 | 68 | function& operator=(function&& other) 69 | { 70 | Base::operator=(eastl::move(other)); 71 | return *this; 72 | } 73 | 74 | function& operator=(std::nullptr_t p) EA_NOEXCEPT 75 | { 76 | Base::operator=(p); 77 | return *this; 78 | } 79 | 80 | template 81 | function& operator=(Functor&& functor) 82 | { 83 | Base::operator=(eastl::forward(functor)); 84 | return *this; 85 | } 86 | 87 | template 88 | function& operator=(eastl::reference_wrapper f) EA_NOEXCEPT 89 | { 90 | Base::operator=(f); 91 | return *this; 92 | } 93 | 94 | void swap(function& other) EA_NOEXCEPT 95 | { 96 | Base::swap(other); 97 | } 98 | 99 | explicit operator bool() const EA_NOEXCEPT 100 | { 101 | return Base::operator bool(); 102 | } 103 | 104 | R operator ()(Args... args) const 105 | { 106 | return Base::operator ()(eastl::forward(args)...); 107 | } 108 | 109 | #if EASTL_RTTI_ENABLED 110 | const std::type_info& target_type() const EA_NOEXCEPT 111 | { 112 | return Base::target_type(); 113 | } 114 | 115 | template 116 | Functor* target() EA_NOEXCEPT 117 | { 118 | return Base::target(); 119 | } 120 | 121 | template 122 | const Functor* target() const EA_NOEXCEPT 123 | { 124 | return Base::target(); 125 | } 126 | #endif // EASTL_RTTI_ENABLED 127 | }; 128 | 129 | template 130 | bool operator==(const function& f, std::nullptr_t) EA_NOEXCEPT 131 | { 132 | return !f; 133 | } 134 | 135 | template 136 | bool operator==(std::nullptr_t, const function& f) EA_NOEXCEPT 137 | { 138 | return !f; 139 | } 140 | 141 | template 142 | bool operator!=(const function& f, std::nullptr_t) EA_NOEXCEPT 143 | { 144 | return !!f; 145 | } 146 | 147 | template 148 | bool operator!=(std::nullptr_t, const function& f) EA_NOEXCEPT 149 | { 150 | return !!f; 151 | } 152 | 153 | template 154 | void swap(function& lhs, function& rhs) 155 | { 156 | lhs.swap(rhs); 157 | } 158 | 159 | } // namespace eastl 160 | 161 | #endif // EASTL_FUNCTION_H 162 | -------------------------------------------------------------------------------- /Source/External/EASTL/internal/function_help.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_INTERNAL_FUNCTION_HELP_H 6 | #define EASTL_INTERNAL_FUNCTION_HELP_H 7 | 8 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 9 | #pragma once 10 | #endif 11 | 12 | #include 13 | #include 14 | 15 | namespace eastl 16 | { 17 | namespace internal 18 | { 19 | 20 | ////////////////////////////////////////////////////////////////////// 21 | // is_null 22 | // 23 | template 24 | bool is_null(const T&) 25 | { 26 | return false; 27 | } 28 | 29 | template 30 | bool is_null(Result (*const& function_pointer)(Arguments...)) 31 | { 32 | return function_pointer == nullptr; 33 | } 34 | 35 | template 36 | bool is_null(Result (Class::*const& function_pointer)(Arguments...)) 37 | { 38 | return function_pointer == nullptr; 39 | } 40 | 41 | template 42 | bool is_null(Result (Class::*const& function_pointer)(Arguments...) const) 43 | { 44 | return function_pointer == nullptr; 45 | } 46 | 47 | } // namespace internal 48 | } // namespace eastl 49 | 50 | #endif // Header include guard 51 | 52 | -------------------------------------------------------------------------------- /Source/External/EASTL/internal/in_place_t.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #ifndef EASTL_INTERNAL_IN_PLACE_T_H 7 | #define EASTL_INTERNAL_IN_PLACE_T_H 8 | 9 | 10 | #include 11 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 12 | #pragma once 13 | #endif 14 | 15 | namespace eastl 16 | { 17 | namespace Internal 18 | { 19 | struct in_place_tag {}; 20 | template struct in_place_type_tag {}; 21 | template struct in_place_index_tag {}; 22 | } 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | /// in_place_tag 26 | /// 27 | /// http://en.cppreference.com/w/cpp/utility/in_place_tag 28 | /// 29 | struct in_place_tag 30 | { 31 | in_place_tag() = delete; 32 | 33 | private: 34 | explicit in_place_tag(Internal::in_place_tag) {} 35 | friend inline in_place_tag Internal_ConstructInPlaceTag(); 36 | }; 37 | 38 | // internal factory function for in_place_tag 39 | inline in_place_tag Internal_ConstructInPlaceTag() { return in_place_tag(Internal::in_place_tag{}); } 40 | 41 | 42 | /////////////////////////////////////////////////////////////////////////////// 43 | /// in_place_t / in_place_type_t / in_place_index_t 44 | /// 45 | /// used to disambiguate overloads that take arguments (possibly a parameter 46 | /// pack) for in-place construction of some value. 47 | /// 48 | /// http://en.cppreference.com/w/cpp/utility/optional/in_place_t 49 | /// 50 | using in_place_t = in_place_tag(&)(Internal::in_place_tag); 51 | 52 | template 53 | using in_place_type_t = in_place_tag(&)(Internal::in_place_type_tag); 54 | 55 | template 56 | using in_place_index_t = in_place_tag(&)(Internal::in_place_index_tag); 57 | 58 | 59 | /////////////////////////////////////////////////////////////////////////////// 60 | /// in_place / in_place / in_place 61 | /// 62 | /// http://en.cppreference.com/w/cpp/utility/in_place 63 | /// 64 | inline in_place_tag in_place(Internal::in_place_tag) { return Internal_ConstructInPlaceTag(); } 65 | 66 | template 67 | inline in_place_tag in_place(Internal::in_place_type_tag) { return Internal_ConstructInPlaceTag(); } 68 | 69 | template 70 | inline in_place_tag in_place(Internal::in_place_index_tag) { return Internal_ConstructInPlaceTag(); } 71 | 72 | 73 | } // namespace eastl 74 | 75 | 76 | #endif // Header include guard 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /Source/External/EASTL/internal/integer_sequence.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_INTEGER_SEQUENCE_H 6 | #define EASTL_INTEGER_SEQUENCE_H 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace eastl 13 | { 14 | 15 | #if EASTL_VARIADIC_TEMPLATES_ENABLED && !defined(EA_COMPILER_NO_TEMPLATE_ALIASES) 16 | 17 | // integer_sequence 18 | template 19 | class integer_sequence 20 | { 21 | public: 22 | typedef T value_type; 23 | static_assert(is_integral::value, "eastl::integer_sequence can only be instantiated with an integral type"); 24 | static EA_CONSTEXPR size_t size() EA_NOEXCEPT { return sizeof...(Ints); } 25 | }; 26 | 27 | template 28 | struct make_index_sequence_impl; 29 | 30 | template 31 | struct make_index_sequence_impl> 32 | { 33 | typedef typename make_index_sequence_impl>::type type; 34 | }; 35 | 36 | template 37 | struct make_index_sequence_impl<0, integer_sequence> 38 | { 39 | typedef integer_sequence type; 40 | }; 41 | 42 | template 43 | using index_sequence = integer_sequence; 44 | 45 | template 46 | using make_index_sequence = typename make_index_sequence_impl>::type; 47 | 48 | template 49 | struct integer_sequence_convert_impl; 50 | 51 | template 52 | struct integer_sequence_convert_impl> 53 | { 54 | typedef integer_sequence type; 55 | }; 56 | 57 | template 58 | struct make_integer_sequence_impl 59 | { 60 | typedef typename integer_sequence_convert_impl>::type type; 61 | }; 62 | 63 | template 64 | using make_integer_sequence = typename make_integer_sequence_impl::type; 65 | 66 | // Helper alias template that converts any type parameter pack into an index sequence of the same length 67 | template 68 | using index_sequence_for = make_index_sequence; 69 | 70 | #endif // EASTL_VARIADIC_TEMPLATES_ENABLED 71 | 72 | } // namespace eastl 73 | 74 | #endif // EASTL_INTEGER_SEQUENCE_H 75 | -------------------------------------------------------------------------------- /Source/External/EASTL/internal/memory_base.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_INTERNAL_MEMORY_BASE_H 6 | #define EASTL_INTERNAL_MEMORY_BASE_H 7 | 8 | #include 9 | 10 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 11 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 12 | #endif 13 | 14 | 15 | //////////////////////////////////////////////////////////////////////////////////////////// 16 | // This file contains basic functionality found in the standard library 'memory' header that 17 | // have limited or no dependencies. This allows us to utilize these utilize these functions 18 | // in other EASTL code while avoid circular dependencies. 19 | //////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | namespace eastl 22 | { 23 | /// addressof 24 | /// 25 | /// From the C++11 Standard, section 20.6.12.1 26 | /// Returns the actual address of the object or function referenced by r, even in the presence of an overloaded operator&. 27 | /// 28 | template 29 | T* addressof(T& value) EA_NOEXCEPT 30 | { 31 | return reinterpret_cast(&const_cast(reinterpret_cast(value))); 32 | } 33 | 34 | } // namespace eastl 35 | 36 | #endif // EASTL_INTERNAL_MEMORY_BASE_H 37 | 38 | -------------------------------------------------------------------------------- /Source/External/EASTL/internal/pair_fwd_decls.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_PAIR_FWD_DECLS_H 6 | #define EASTL_PAIR_FWD_DECLS_H 7 | 8 | #include 9 | 10 | namespace eastl 11 | { 12 | template 13 | struct pair; 14 | } 15 | 16 | #endif // EASTL_PAIR_FWD_DECLS_H 17 | -------------------------------------------------------------------------------- /Source/External/EASTL/internal/piecewise_construct_t.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #ifndef EASTL_INTERNAL_PIECEWISE_CONSTRUCT_T_H 7 | #define EASTL_INTERNAL_PIECEWISE_CONSTRUCT_T_H 8 | 9 | 10 | #include 11 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 12 | #pragma once 13 | #endif 14 | 15 | namespace eastl 16 | { 17 | /////////////////////////////////////////////////////////////////////////////// 18 | /// piecewise_construct_t 19 | /// 20 | /// http://en.cppreference.com/w/cpp/utility/piecewise_construct_t 21 | /// 22 | struct piecewise_construct_t 23 | { 24 | explicit piecewise_construct_t() = default; 25 | }; 26 | 27 | 28 | /////////////////////////////////////////////////////////////////////////////// 29 | /// piecewise_construct 30 | /// 31 | /// A tag type used to disambiguate between function overloads that take two tuple arguments. 32 | /// 33 | /// http://en.cppreference.com/w/cpp/utility/piecewise_construct 34 | /// 35 | EA_CONSTEXPR piecewise_construct_t piecewise_construct = eastl::piecewise_construct_t(); 36 | 37 | } // namespace eastl 38 | 39 | 40 | #endif // Header include guard 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Source/External/EASTL/internal/tuple_fwd_decls.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_TUPLE_FWD_DECLS_H 6 | #define EASTL_TUPLE_FWD_DECLS_H 7 | 8 | #include 9 | 10 | #if EASTL_TUPLE_ENABLED 11 | 12 | namespace eastl 13 | { 14 | template 15 | class tuple; 16 | 17 | template 18 | class tuple_size; 19 | 20 | template 21 | class tuple_element; 22 | 23 | template 24 | using tuple_element_t = typename tuple_element::type; 25 | 26 | // const typename for tuple_element_t, for when tuple or TupleImpl cannot itself be const 27 | template 28 | using const_tuple_element_t = typename conditional< 29 | is_lvalue_reference>::value, 30 | add_lvalue_reference_t>>, 31 | const tuple_element_t 32 | >::type; 33 | 34 | // get 35 | template 36 | tuple_element_t>& get(tuple& t); 37 | 38 | template 39 | const_tuple_element_t>& get(const tuple& t); 40 | 41 | template 42 | tuple_element_t>&& get(tuple&& t); 43 | 44 | template 45 | T& get(tuple& t); 46 | 47 | template 48 | const T& get(const tuple& t); 49 | 50 | template 51 | T&& get(tuple&& t); 52 | } 53 | 54 | #endif // EASTL_VARIADIC_TEMPLATES_ENABLED 55 | 56 | #endif // EASTL_TUPLE_FWD_DECLS_H 57 | -------------------------------------------------------------------------------- /Source/External/EASTL/intrusive_hash_map.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_INTRUSIVE_HASH_MAP_H 6 | #define EASTL_INTRUSIVE_HASH_MAP_H 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 15 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 16 | #endif 17 | 18 | 19 | 20 | namespace eastl 21 | { 22 | 23 | /// intrusive_hash_map 24 | /// 25 | /// Template parameters: 26 | /// Key The key object (key in the key/value pair). T must contain a member of type Key named mKey. 27 | /// T The type of object the map holds (a.k.a. value). 28 | /// bucketCount The number of buckets to use. Best if it's a prime number. 29 | /// Hash Hash function. See functional.h for examples of hash functions. 30 | /// Equal Equality testing predicate; tells if two elements are equal. 31 | /// 32 | template , typename Equal = eastl::equal_to > 33 | class intrusive_hash_map : public intrusive_hashtable 34 | { 35 | public: 36 | typedef intrusive_hashtable base_type; 37 | typedef intrusive_hash_map this_type; 38 | 39 | public: 40 | explicit intrusive_hash_map(const Hash& h = Hash(), const Equal& eq = Equal()) 41 | : base_type(h, eq) 42 | { 43 | // Empty 44 | } 45 | 46 | // To consider: Is this feasible, given how initializer_list works by creating a temporary array? Even if it is feasible, is it a good idea? 47 | //intrusive_hash_map(std::initializer_list ilist); 48 | 49 | }; // intrusive_hash_map 50 | 51 | 52 | 53 | 54 | /// intrusive_hash_multimap 55 | /// 56 | /// Implements a intrusive_hash_multimap, which is the same thing as a intrusive_hash_map 57 | /// except that contained elements need not be unique. See the documentation 58 | /// for intrusive_hash_map for details. 59 | /// 60 | /// Template parameters: 61 | /// Key The key object (key in the key/value pair). T must contain a member of type Key named mKey. 62 | /// T The type of object the map holds (a.k.a. value). 63 | /// bucketCount The number of buckets to use. Best if it's a prime number. 64 | /// Hash Hash function. See functional.h for examples of hash functions. 65 | /// Equal Equality testing predicate; tells if two elements are equal. 66 | /// 67 | template , typename Equal = eastl::equal_to > 68 | class intrusive_hash_multimap : public intrusive_hashtable 69 | { 70 | public: 71 | typedef intrusive_hashtable base_type; 72 | typedef intrusive_hash_multimap this_type; 73 | 74 | public: 75 | explicit intrusive_hash_multimap(const Hash& h = Hash(), const Equal& eq = Equal()) 76 | : base_type(h, eq) 77 | { 78 | // Empty 79 | } 80 | 81 | // To consider: Is this feasible, given how initializer_list works by creating a temporary array? Even if it is feasible, is it a good idea? 82 | //intrusive_hash_multimap(std::initializer_list ilist); 83 | 84 | }; // intrusive_hash_multimap 85 | 86 | 87 | 88 | 89 | } // namespace eastl 90 | 91 | 92 | #endif // Header include guard 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Source/External/EASTL/intrusive_hash_set.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_INTRUSIVE_HASH_SET_H 6 | #define EASTL_INTRUSIVE_HASH_SET_H 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 15 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 16 | #endif 17 | 18 | 19 | 20 | namespace eastl 21 | { 22 | 23 | /// intrusive_hash_set 24 | /// 25 | /// Template parameters: 26 | /// T The type of object the set holds (a.k.a. value). 27 | /// bucketCount The number of buckets to use. Best if it's a prime number. 28 | /// Hash Hash function. See functional.h for examples of hash functions. 29 | /// Equal Equality testing predicate; tells if two elements are equal. 30 | /// 31 | template , typename Equal = eastl::equal_to > 32 | class intrusive_hash_set : public intrusive_hashtable 33 | { 34 | public: 35 | typedef intrusive_hashtable base_type; 36 | typedef intrusive_hash_set this_type; 37 | 38 | public: 39 | explicit intrusive_hash_set(const Hash& h = Hash(), const Equal& eq = Equal()) 40 | : base_type(h, eq) 41 | { 42 | // Empty 43 | } 44 | 45 | // To consider: Is this feasible, given how initializer_list works by creating a temporary array? Even if it is feasible, is it a good idea? 46 | //intrusive_hash_set(std::initializer_list ilist); 47 | 48 | }; // intrusive_hash_set 49 | 50 | 51 | 52 | 53 | /// intrusive_hash_multiset 54 | /// 55 | /// Implements a intrusive_hash_multiset, which is the same thing as a intrusive_hash_set 56 | /// except that contained elements need not be unique. See the documentation 57 | /// for intrusive_hash_set for details. 58 | /// 59 | /// Template parameters: 60 | /// T The type of object the set holds (a.k.a. value). 61 | /// bucketCount The number of buckets to use. Best if it's a prime number. 62 | /// Hash Hash function. See functional.h for examples of hash functions. 63 | /// Equal Equality testing predicate; tells if two elements are equal. 64 | /// 65 | template , typename Equal = eastl::equal_to > 66 | class intrusive_hash_multiset : public intrusive_hashtable 67 | { 68 | public: 69 | typedef intrusive_hashtable base_type; 70 | typedef intrusive_hash_multiset this_type; 71 | 72 | public: 73 | explicit intrusive_hash_multiset(const Hash& h = Hash(), const Equal& eq = Equal()) 74 | : base_type(h, eq) 75 | { 76 | // Empty 77 | } 78 | 79 | // To consider: Is this feasible, given how initializer_list works by creating a temporary array? Even if it is feasible, is it a good idea? 80 | //intrusive_hash_multiset(std::initializer_list ilist); 81 | 82 | }; // intrusive_hash_multiset 83 | 84 | 85 | } // namespace eastl 86 | 87 | 88 | #endif // Header include guard 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Source/External/EASTL/source/allocator_eastl.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #include 7 | #include 8 | 9 | 10 | /////////////////////////////////////////////////////////////////////////////// 11 | // ReadMe 12 | // 13 | // This file implements the default application allocator. 14 | // You can replace this allocator.cpp file with a different one, 15 | // you can define EASTL_USER_DEFINED_ALLOCATOR below to ignore this file, 16 | // or you can modify the EASTL config.h file to redefine how allocators work. 17 | /////////////////////////////////////////////////////////////////////////////// 18 | 19 | 20 | #ifndef EASTL_USER_DEFINED_ALLOCATOR // If the user hasn't declared that he has defined an allocator implementation elsewhere... 21 | 22 | namespace eastl 23 | { 24 | 25 | /// gDefaultAllocator 26 | /// Default global allocator instance. 27 | EASTL_API allocator gDefaultAllocator; 28 | EASTL_API allocator* gpDefaultAllocator = &gDefaultAllocator; 29 | 30 | EASTL_API allocator* GetDefaultAllocator() 31 | { 32 | return gpDefaultAllocator; 33 | } 34 | 35 | EASTL_API allocator* SetDefaultAllocator(allocator* pAllocator) 36 | { 37 | allocator* const pPrevAllocator = gpDefaultAllocator; 38 | gpDefaultAllocator = pAllocator; 39 | return pPrevAllocator; 40 | } 41 | 42 | } // namespace eastl 43 | 44 | 45 | #endif // EASTL_USER_DEFINED_ALLOCATOR 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Source/External/EASTL/source/assert.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #if defined(EA_PLATFORM_MICROSOFT) 11 | #pragma warning(push, 0) 12 | #if defined _MSC_VER 13 | #include 14 | #endif 15 | #ifndef WIN32_LEAN_AND_MEAN 16 | #define WIN32_LEAN_AND_MEAN 17 | #endif 18 | #include 19 | #pragma warning(pop) 20 | #elif defined(EA_PLATFORM_ANDROID) 21 | #include 22 | #else 23 | #include 24 | #endif 25 | 26 | 27 | 28 | 29 | namespace eastl 30 | { 31 | 32 | /// gpAssertionFailureFunction 33 | /// 34 | /// Global assertion failure function pointer. Set by SetAssertionFailureFunction. 35 | /// 36 | EASTL_API EASTL_AssertionFailureFunction gpAssertionFailureFunction = AssertionFailureFunctionDefault; 37 | EASTL_API void* gpAssertionFailureFunctionContext = NULL; 38 | 39 | 40 | 41 | /// SetAssertionFailureFunction 42 | /// 43 | /// Sets the function called when an assertion fails. If this function is not called 44 | /// by the user, a default function will be used. The user may supply a context parameter 45 | /// which will be passed back to the user in the function call. This is typically used 46 | /// to store a C++ 'this' pointer, though other things are possible. 47 | /// 48 | /// There is no thread safety here, so the user needs to externally make sure that 49 | /// this function is not called in a thread-unsafe way. The easiest way to do this is 50 | /// to just call this function once from the main thread on application startup. 51 | /// 52 | EASTL_API void SetAssertionFailureFunction(EASTL_AssertionFailureFunction pAssertionFailureFunction, void* pContext) 53 | { 54 | gpAssertionFailureFunction = pAssertionFailureFunction; 55 | gpAssertionFailureFunctionContext = pContext; 56 | } 57 | 58 | 59 | 60 | /// AssertionFailureFunctionDefault 61 | /// 62 | EASTL_API void AssertionFailureFunctionDefault(const char* pExpression, void* /*pContext*/) 63 | { 64 | #if EASTL_ASSERT_ENABLED 65 | #if defined(EA_PLATFORM_MICROSOFT) 66 | printf("%s\n", pExpression); // Write the message to stdout 67 | if( ::IsDebuggerPresent()) 68 | { 69 | OutputDebugStringA(pExpression); 70 | } 71 | #elif defined(EA_PLATFORM_ANDROID) 72 | __android_log_print(ANDROID_LOG_INFO, "PRINTF", "%s\n", pExpression); 73 | #else 74 | printf("%s\n", pExpression); // Write the message to stdout, which happens to be the trace view for many console debug machines. 75 | #endif 76 | #else 77 | EA_UNUSED(pExpression); 78 | #endif 79 | 80 | EASTL_DEBUG_BREAK(); 81 | } 82 | 83 | 84 | /// AssertionFailure 85 | /// 86 | EASTL_API void AssertionFailure(const char* pExpression) 87 | { 88 | if(gpAssertionFailureFunction) 89 | gpAssertionFailureFunction(pExpression, gpAssertionFailureFunctionContext); 90 | } 91 | 92 | 93 | } // namespace eastl 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /Source/External/EASTL/source/fixed_pool.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #include 7 | #include 8 | 9 | 10 | 11 | namespace eastl 12 | { 13 | 14 | 15 | EASTL_API void fixed_pool_base::init(void* pMemory, size_t memorySize, size_t nodeSize, 16 | size_t alignment, size_t /*alignmentOffset*/) 17 | { 18 | // To do: Support alignmentOffset. 19 | 20 | #if EASTL_FIXED_SIZE_TRACKING_ENABLED 21 | mnCurrentSize = 0; 22 | mnPeakSize = 0; 23 | #endif 24 | 25 | if(pMemory) 26 | { 27 | // Assert that alignment is a power of 2 value (e.g. 1, 2, 4, 8, 16, etc.) 28 | EASTL_ASSERT((alignment & (alignment - 1)) == 0); 29 | 30 | // Make sure alignment is a valid value. 31 | if(alignment < 1) 32 | alignment = 1; 33 | 34 | mpNext = (Link*)(((uintptr_t)pMemory + (alignment - 1)) & ~(alignment - 1)); 35 | memorySize -= (uintptr_t)mpNext - (uintptr_t)pMemory; 36 | pMemory = mpNext; 37 | 38 | // The node size must be at least as big as a Link, which itself is sizeof(void*). 39 | if(nodeSize < sizeof(Link)) 40 | nodeSize = ((sizeof(Link) + (alignment - 1))) & ~(alignment - 1); 41 | 42 | // If the user passed in a memory size that wasn't a multiple of the node size, 43 | // we need to chop down the memory size so that the last node is not a whole node. 44 | memorySize = (memorySize / nodeSize) * nodeSize; 45 | 46 | mpCapacity = (Link*)((uintptr_t)pMemory + memorySize); 47 | mpHead = NULL; 48 | mnNodeSize = nodeSize; 49 | } 50 | } 51 | 52 | 53 | } // namespace eastl 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Source/External/EASTL/source/intrusive_list.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include 6 | 7 | 8 | namespace eastl 9 | { 10 | 11 | 12 | EASTL_API void intrusive_list_base::reverse() EA_NOEXCEPT 13 | { 14 | intrusive_list_node* pNode = &mAnchor; 15 | do { 16 | intrusive_list_node* const pTemp = pNode->mpNext; 17 | pNode->mpNext = pNode->mpPrev; 18 | pNode->mpPrev = pTemp; 19 | pNode = pNode->mpPrev; 20 | } 21 | while(pNode != &mAnchor); 22 | } 23 | 24 | 25 | 26 | EASTL_API bool intrusive_list_base::validate() const 27 | { 28 | const intrusive_list_node *p = &mAnchor; 29 | const intrusive_list_node *q = p; 30 | 31 | // We do two tests below: 32 | // 33 | // 1) Prev and next pointers are symmetric. We check (p->next->prev == p) 34 | // for each node, which is enough to verify all links. 35 | // 36 | // 2) Loop check. We bump the q pointer at one-half rate compared to the 37 | // p pointer; (p == q) if and only if we are at the start (which we 38 | // don't check) or if there is a loop somewhere in the list. 39 | 40 | do { 41 | // validate node (even phase) 42 | if (p->mpNext->mpPrev != p) 43 | return false; // broken linkage detected 44 | 45 | // bump only fast pointer 46 | p = p->mpNext; 47 | if (p == &mAnchor) 48 | break; 49 | 50 | if (p == q) 51 | return false; // loop detected 52 | 53 | // validate node (odd phase) 54 | if (p->mpNext->mpPrev != p) 55 | return false; // broken linkage detected 56 | 57 | // bump both pointers 58 | p = p->mpNext; 59 | q = q->mpNext; 60 | 61 | if (p == q) 62 | return false; // loop detected 63 | 64 | } while(p != &mAnchor); 65 | 66 | return true; 67 | } 68 | 69 | 70 | } // namespace eastl 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /Source/External/EASTL/source/thread_support.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #if defined(EA_PLATFORM_MICROSOFT) 12 | #pragma warning(push, 0) 13 | #ifndef WIN32_LEAN_AND_MEAN 14 | #define WIN32_LEAN_AND_MEAN 15 | #endif 16 | #include 17 | #pragma warning(pop) 18 | #endif 19 | 20 | 21 | namespace eastl 22 | { 23 | namespace Internal 24 | { 25 | #if EASTL_CPP11_MUTEX_ENABLED 26 | // We use the C++11 Standard Library mutex as-is. 27 | #else 28 | ///////////////////////////////////////////////////////////////// 29 | // mutex 30 | ///////////////////////////////////////////////////////////////// 31 | 32 | mutex::mutex() 33 | { 34 | #if defined(EA_PLATFORM_MICROSOFT) 35 | static_assert(sizeof(mMutexBuffer) == sizeof(CRITICAL_SECTION), "mMutexBuffer size failure"); 36 | //static_assert(EA_ALIGN_OF(mMutexBuffer) >= EA_ALIGN_OF(CRITICAL_SECTION), "mMutexBuffer alignment failure"); // Enabling this causes the VS2012 compiler to crash. 37 | 38 | #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0403) 39 | InitializeCriticalSection((CRITICAL_SECTION*)mMutexBuffer); 40 | #elif !EA_WINAPI_FAMILY_PARTITION(EA_WINAPI_PARTITION_DESKTOP) 41 | BOOL result = InitializeCriticalSectionEx((CRITICAL_SECTION*)mMutexBuffer, 10, 0); 42 | EASTL_ASSERT(result != 0); EA_UNUSED(result); 43 | #else 44 | BOOL result = InitializeCriticalSectionAndSpinCount((CRITICAL_SECTION*)mMutexBuffer, 10); 45 | EASTL_ASSERT(result != 0); EA_UNUSED(result); 46 | #endif 47 | 48 | #elif defined(EA_PLATFORM_POSIX) 49 | pthread_mutexattr_t attr; 50 | 51 | pthread_mutexattr_init(&attr); 52 | pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); 53 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 54 | pthread_mutex_init(&mMutex, &attr); 55 | pthread_mutexattr_destroy(&attr); 56 | #endif 57 | } 58 | 59 | mutex::~mutex() 60 | { 61 | #if defined(EA_PLATFORM_MICROSOFT) 62 | DeleteCriticalSection((CRITICAL_SECTION*)mMutexBuffer); 63 | #elif defined(EA_PLATFORM_POSIX) 64 | pthread_mutex_destroy(&mMutex); 65 | #endif 66 | } 67 | 68 | void mutex::lock() 69 | { 70 | #if defined(EA_PLATFORM_MICROSOFT) 71 | EnterCriticalSection((CRITICAL_SECTION*)mMutexBuffer); 72 | #elif defined(EA_PLATFORM_POSIX) 73 | pthread_mutex_lock(&mMutex); 74 | #else 75 | EASTL_FAIL_MSG("EASTL thread safety is not implemented yet. See EAThread for how to do this for the given platform."); 76 | #endif 77 | } 78 | 79 | void mutex::unlock() 80 | { 81 | #if defined(EA_PLATFORM_MICROSOFT) 82 | LeaveCriticalSection((CRITICAL_SECTION*)mMutexBuffer); 83 | #elif defined(EA_PLATFORM_POSIX) 84 | pthread_mutex_unlock(&mMutex); 85 | #endif 86 | } 87 | #endif 88 | 89 | 90 | ///////////////////////////////////////////////////////////////// 91 | // shared_ptr_auto_mutex 92 | ///////////////////////////////////////////////////////////////// 93 | 94 | // We could solve this by having single global mutex for all shared_ptrs, a set of mutexes for shared_ptrs, 95 | // a single mutex for every shared_ptr, or have a template parameter that enables mutexes for just some shared_ptrs. 96 | eastl::late_constructed gSharedPtrMutex; 97 | 98 | shared_ptr_auto_mutex::shared_ptr_auto_mutex(const void* /*pSharedPtr*/) 99 | : auto_mutex(*gSharedPtrMutex.get()) 100 | { 101 | } 102 | 103 | 104 | } // namespace Internal 105 | 106 | } // namespace eastl 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /Source/External/EASTL/unordered_map.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_UNORDERED_MAP_H 6 | #define EASTL_UNORDERED_MAP_H 7 | 8 | #include 9 | #include 10 | 11 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 12 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 13 | #endif 14 | 15 | namespace eastl 16 | { 17 | /// unordered_map 18 | /// 19 | /// The original TR1 (technical report 1) used "hash_map" to name a hash 20 | /// table backed associative container of unique key-value pairs. When the 21 | /// container was added to the C++11 standard the committee chose the name 22 | /// "unordered_map" to clarify that internally the elements are NOT sorted in 23 | /// any particular order. We provide a template alias here to ensure feature 24 | /// parity with the original eastl::hash_map. 25 | /// 26 | #if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES) 27 | template , 30 | typename Predicate = eastl::equal_to, 31 | typename Allocator = EASTLAllocatorType, 32 | bool bCacheHashCode = false> 33 | using unordered_map = hash_map; 34 | #endif 35 | 36 | /// unordered_multimap 37 | /// 38 | /// Similar template alias as "unordered_map" except the contained elements 39 | /// need not be unique. See "hash_multimap" for more details. 40 | /// 41 | #if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES) 42 | template , 45 | typename Predicate = eastl::equal_to, 46 | typename Allocator = EASTLAllocatorType, 47 | bool bCacheHashCode = false> 48 | using unordered_multimap = hash_multimap; 49 | #endif 50 | 51 | } // namespace eastl 52 | 53 | #endif // Header include guard 54 | 55 | -------------------------------------------------------------------------------- /Source/External/EASTL/unordered_set.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_UNORDERED_SET_H 6 | #define EASTL_UNORDERED_SET_H 7 | 8 | #include 9 | #include 10 | 11 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 12 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 13 | #endif 14 | 15 | namespace eastl 16 | { 17 | 18 | /// unordered_set 19 | /// 20 | /// The original TR1 (technical report 1) used "hash_set" to name a hash 21 | /// table backed associative container of unique "Key" type objects. When 22 | /// the container was added to the C++11 standard the committee chose the 23 | /// name "unordered_set" to clarify that internally the elements are NOT 24 | /// sorted in any particular order. We provide a template alias here to 25 | /// ensure feature parity with the original eastl::hash_set. 26 | /// 27 | #if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES) 28 | template , 30 | typename Predicate = eastl::equal_to, 31 | typename Allocator = EASTLAllocatorType, 32 | bool bCacheHashCode = false> 33 | using unordered_set = hash_set; 34 | #endif 35 | 36 | /// unordered_multiset 37 | /// 38 | /// Similar template alias as "unordered_set" except the contained elements 39 | /// need not be unique. See "hash_multiset" for more details. 40 | /// 41 | #if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES) 42 | template , 44 | typename Predicate = eastl::equal_to, 45 | typename Allocator = EASTLAllocatorType, 46 | bool bCacheHashCode = false> 47 | using unordered_multiset = hash_multiset; 48 | #endif 49 | 50 | } // namespace eastl 51 | 52 | #endif // Header include guard 53 | 54 | -------------------------------------------------------------------------------- /Source/External/EASTL/version.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTL_VERSION_H 6 | #define EASTL_VERSION_H 7 | 8 | #include 9 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 10 | #pragma once 11 | #endif 12 | 13 | #include 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /Source/External/EASTL/weak_ptr.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #ifndef EASTL_WEAK_PTR_H 7 | #define EASTL_WEAK_PTR_H 8 | 9 | 10 | // This header file is deprecated. The implementation has moved: 11 | #include 12 | 13 | 14 | #endif 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Source/External/EAStdC/EAStdC.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #include 7 | 8 | 9 | #ifndef EASTDC_EASTDC_H 10 | #define EASTDC_EASTDC_H 11 | 12 | 13 | namespace EA 14 | { 15 | namespace StdC 16 | { 17 | /// Does any startup initialization that EAStdC might need. Usually this 18 | /// means allocating structures that can't otherwise be automatically 19 | /// auto-initialized (e.g. due to thread safety problems). 20 | /// Memory may be allocated via EASTDC_NEW within this function. 21 | EASTDC_API void Init(); 22 | 23 | /// Undoes any initialization that Init did. 24 | /// Memory may be freed via EASTDC_DELETE within this function. 25 | EASTDC_API void Shutdown(); 26 | 27 | 28 | 29 | /// SetAssertionsEnabled 30 | /// If enabled then debug builds execute EA_ASSERT and EA_FAIL statements 31 | /// for serious failures that are otherwise silent. For example, the C strtoul 32 | /// function silently fails by default according the the C99 language standard. 33 | /// 34 | /// The assertions this applies to are assertions that check user parameters 35 | /// and thus detect user bugs, in particular those that could otherwise go 36 | /// silently undected. This doesn't apply to assertions that are internal 37 | /// sanity checks. 38 | /// 39 | /// By default assertions are disabled (for compatibility with C99 behavior), 40 | /// but they also require EA_ASSERT to be enabled for the given build. 41 | EASTDC_API void SetAssertionsEnabled(bool enabled); 42 | 43 | /// GetAssertionsEnabled 44 | /// Returns whether assertions are enabled, as described in SetAssertionsEnabled. 45 | EASTDC_API bool GetAssertionsEnabled(); 46 | } 47 | } 48 | 49 | #endif // Header include guard 50 | 51 | 52 | -------------------------------------------------------------------------------- /Source/External/EAStdC/internal/Thread.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTDC_THREAD_H 6 | #define EASTDC_THREAD_H 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | namespace EA 15 | { 16 | namespace StdC 17 | { 18 | /// Safely sets a new value. Returns the old value. 19 | uint32_t AtomicSet(uint32_t* pValue, uint32_t newValue); 20 | 21 | /// Safely increments the value. Returns the new value. 22 | /// This function acts the same as the C++ pre-increment operator. 23 | uint32_t AtomicIncrement(uint32_t* pValue); 24 | 25 | /// Safely decrements the value. Returns the new value. 26 | /// This function acts the same as the C++ pre-decrement operator. 27 | uint32_t AtomicDecrement(uint32_t* pValue); 28 | 29 | /// Safely sets the value to a new value if the original value is equal to 30 | /// a condition value. Returns true if the condition was met and the 31 | /// assignment occurred. The comparison and value setting are done as 32 | /// an atomic operation and thus another thread cannot intervene between 33 | /// the two as would be the case with simple C code. 34 | bool AtomicCompareSwap(uint32_t* pValue, uint32_t newValue, uint32_t condition); 35 | 36 | 37 | /// Mutex 38 | /// 39 | /// Implements a very simple portable Mutex class. 40 | /// 41 | class Mutex 42 | { 43 | public: 44 | void Lock() { mMutex.Lock(); } 45 | void Unlock() { mMutex.Unlock(); } 46 | 47 | protected: 48 | EA::Thread::Mutex mMutex; 49 | }; 50 | } 51 | } 52 | 53 | 54 | 55 | 56 | /////////////////////////////////////////////////////////////////////////////// 57 | // inline implmentation 58 | /////////////////////////////////////////////////////////////////////////////// 59 | namespace EA 60 | { 61 | namespace StdC 62 | { 63 | inline uint32_t AtomicIncrement(uint32_t* pValue) { return EA::Thread::AtomicFetchIncrement(pValue) + 1; } 64 | 65 | inline uint32_t AtomicDecrement(uint32_t* pValue) { return EA::Thread::AtomicFetchDecrement(pValue) - 1; } 66 | 67 | inline uint32_t AtomicSet(uint32_t* pValue, uint32_t newValue) 68 | { 69 | return EA::Thread::AtomicSetValue(pValue, newValue); 70 | } 71 | 72 | inline bool AtomicCompareSwap(uint32_t* pValue, uint32_t newValue, uint32_t condition) 73 | { 74 | return EA::Thread::AtomicSetValueConditional(pValue, newValue, condition); 75 | } 76 | 77 | } // namespace StdC 78 | 79 | } // namespace EA 80 | 81 | 82 | 83 | 84 | #endif // Header include guard 85 | 86 | -------------------------------------------------------------------------------- /Source/External/EAStdC/internal/stdioEA.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | /////////////////////////////////////////////////////////////////////////////// 6 | // stdioEA.h 7 | // 8 | // Declares elements of stdio.h that are missing from various platforms. 9 | // Some platform/compiler combinations don't support some or all of the 10 | // standard C stdio.h functionality, so we declare the functionality 11 | // ourselves here. This doesn't always mean that we implement the functionality. 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | #ifndef EASTDC_INTERNAL_STDIOEA_H 16 | #define EASTDC_INTERNAL_STDIOEA_H 17 | 18 | 19 | #include 20 | 21 | 22 | #if !EASTDC_FILE_AVAILABLE 23 | 24 | #include 25 | 26 | //struct FILE 27 | //{ 28 | // char8_t* mpMemory; 29 | // int32_t mPosition; 30 | //}; 31 | 32 | size_t fread(void* ptr, size_t size, size_t count, FILE* stream); 33 | size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream); 34 | int fwide(FILE* stream, int mode); 35 | char* fgets(char* str, int num, FILE* stream); 36 | int fputs(const char* str, FILE* stream); 37 | int fgetc(FILE* stream); 38 | int ungetc(int character, FILE* stream); 39 | int feof(FILE* stream); 40 | int ferror(FILE* stream); 41 | 42 | #endif // EASTDC_FILE_AVAILABLE 43 | 44 | #endif // Header include guard 45 | -------------------------------------------------------------------------------- /Source/External/EAStdC/source/EAStdC.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #include 7 | #include 8 | 9 | 10 | namespace EA 11 | { 12 | namespace StdC 13 | { 14 | EASTDC_API void Init() 15 | { 16 | SprintfLocal::EASprintfInit(); 17 | } 18 | 19 | EASTDC_API void Shutdown() 20 | { 21 | SprintfLocal::EASprintfShutdown(); 22 | } 23 | 24 | 25 | // Disabled by default, for compatibility with C99 behavior. 26 | bool gAssertionsEnabled = false; 27 | 28 | EASTDC_API void SetAssertionsEnabled(bool enabled) 29 | { 30 | gAssertionsEnabled = enabled; 31 | } 32 | 33 | EASTDC_API bool GetAssertionsEnabled() 34 | { 35 | return gAssertionsEnabled; 36 | } 37 | } 38 | } 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Source/External/EAStdC/version.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EASTDC_VERSION_H 6 | #define EASTDC_VERSION_H 7 | 8 | #include 9 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 10 | #pragma once 11 | #endif 12 | 13 | #include 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /Source/External/EAThread/apple/eathread_callstack_apple.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 6 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 7 | #endif 8 | 9 | 10 | #ifndef EATHREAD_CALLSTACK_APPLE_H 11 | #define EATHREAD_CALLSTACK_APPLE_H 12 | 13 | 14 | #include 15 | 16 | namespace EA 17 | { 18 | namespace Thread 19 | { 20 | 21 | /// ModuleInfoApple 22 | /// 23 | /// This struct is based on the EACallstack ModuleInfo struct, but that can't be used here because 24 | /// this package is a lower level package than EACallstack. 25 | /// 26 | struct ModuleInfoApple 27 | { 28 | char8_t mPath[256]; /// File name or file path 29 | char8_t mName[256]; /// Module name. Usually the same as the file name without the extension. 30 | uint64_t mBaseAddress; /// Base address in memory. 31 | uint64_t mSize; /// Module size in memory. 32 | char mType[32]; /// The type field (e.g. __TEXT) from the vmmap output. 33 | char mPermissions[16]; /// The permissions "r--/rwx" kind of string from the vmmap output. 34 | }; 35 | 36 | 37 | #if EATHREAD_APPLE_GETMODULEINFO_ENABLED 38 | /// GetModuleInfoApple 39 | /// 40 | /// This function exists for the purpose of being a central module/VM map info collecting function, 41 | /// used by a couple functions within this package. 42 | /// Writes as many entries as possible to the user-supplied array, up to the capacity of the array. 43 | /// Returns the required number of entries, which may be more than the user-supplied capacity in the 44 | /// case that the user didn't supply enough. 45 | /// 46 | size_t GetModuleInfoApple(ModuleInfoApple* pModuleInfoAppleArray, size_t moduleInfoAppleArrayCapacity, 47 | const char* pTypeFilter = NULL, bool bEnableCache = true); 48 | #endif 49 | 50 | 51 | } // namespace Callstack 52 | 53 | } // namespace EA 54 | 55 | #endif // Header include guard 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /Source/External/EAThread/apple/eathread_sync_apple.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 6 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 7 | #endif 8 | 9 | ///////////////////////////////////////////////////////////////////////////// 10 | // Functionality related to memory and code generation synchronization. 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | #ifndef EATHREAD_APPLE_EATHREAD_SYNC_APPLE_H 15 | #define EATHREAD_APPLE_EATHREAD_SYNC_APPLE_H 16 | 17 | 18 | #include 19 | #include 20 | 21 | 22 | #define EA_THREAD_SYNC_IMPLEMENTED 23 | 24 | 25 | // EAProcessorPause 26 | // Intel has defined a 'pause' instruction for x86 processors starting with the P4, though this simply 27 | // maps to the otherwise undocumented 'rep nop' instruction. This pause instruction is important for 28 | // high performance spinning, as otherwise a high performance penalty incurs. 29 | 30 | #if defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64) 31 | #define EAProcessorPause() __asm__ __volatile__ ("rep ; nop") 32 | #else 33 | #define EAProcessorPause() 34 | #endif 35 | 36 | 37 | 38 | // EAReadBarrier / EAWriteBarrier / EAReadWriteBarrier 39 | 40 | #define EAReadBarrier OSMemoryBarrier 41 | #define EAWriteBarrier OSMemoryBarrier 42 | #define EAReadWriteBarrier OSMemoryBarrier 43 | 44 | 45 | 46 | // EACompilerMemoryBarrier 47 | 48 | #define EACompilerMemoryBarrier() __asm__ __volatile__ ("":::"memory") 49 | 50 | 51 | 52 | 53 | #endif // EATHREAD_APPLE_EATHREAD_SYNC_APPLE_H 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /Source/External/EAThread/arm/eathread_sync_arm.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 6 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 7 | #endif 8 | 9 | ///////////////////////////////////////////////////////////////////////////// 10 | // Functionality related to memory and code generation synchronization. 11 | // 12 | // Created by Rob Parolin 13 | ///////////////////////////////////////////////////////////////////////////// 14 | 15 | 16 | #ifndef EATHREAD_ARM_EATHREAD_SYNC_ARM_H 17 | #define EATHREAD_ARM_EATHREAD_SYNC_ARM_H 18 | 19 | #include 20 | 21 | 22 | #if defined(EA_COMPILER_CLANG) 23 | #define EA_THREAD_SYNC_IMPLEMENTED 24 | 25 | #define EAProcessorPause() 26 | 27 | #define EAReadBarrier __sync_synchronize 28 | #define EAWriteBarrier __sync_synchronize 29 | #define EAReadWriteBarrier __sync_synchronize 30 | 31 | #define EACompilerMemoryBarrier() __asm__ __volatile__ ("" : : : "memory") 32 | 33 | 34 | #elif defined(EA_COMPILER_GNUC) 35 | #define EA_THREAD_SYNC_IMPLEMENTED 36 | 37 | #define EAProcessorPause() 38 | 39 | #if (((__GNUC__ * 100) + __GNUC_MINOR__) >= 401) // GCC 4.1 or later 40 | #define EAReadBarrier __sync_synchronize 41 | #define EAWriteBarrier __sync_synchronize 42 | #define EAReadWriteBarrier __sync_synchronize 43 | #else 44 | #define EAReadBarrier EACompilerMemoryBarrier 45 | #define EAWriteBarrier EACompilerMemoryBarrier 46 | #define EAReadWriteBarrier EACompilerMemoryBarrier 47 | #endif 48 | 49 | #define EACompilerMemoryBarrier() __asm__ __volatile__ ("" : : : "memory") 50 | 51 | #endif 52 | 53 | #endif // EATHREAD_ARM_EATHREAD_SYNC_ARM_H 54 | 55 | -------------------------------------------------------------------------------- /Source/External/EAThread/armgcc/eathread_sync_armgcc.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 6 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 7 | #endif 8 | 9 | ///////////////////////////////////////////////////////////////////////////// 10 | // Functionality related to memory and code generation synchronization. 11 | // 12 | // Created by Rob Parolin 13 | ///////////////////////////////////////////////////////////////////////////// 14 | 15 | 16 | #ifndef EATHREAD_ARMGCC_EATHREAD_SYNC_ARMGCC_H 17 | #define EATHREAD_ARMGCC_EATHREAD_SYNC_ARMGCC_H 18 | 19 | // Header file should not be included directly. Provided here for backwards compatibility. 20 | // Please use eathread_sync.h 21 | 22 | #if defined(EA_PROCESSOR_ARM) 23 | #include 24 | #endif 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /Source/External/EAThread/gcc/eathread_sync_gcc.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 6 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 7 | #endif 8 | 9 | ///////////////////////////////////////////////////////////////////////////// 10 | // Functionality related to memory and code generation synchronization. 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | #ifndef EATHREAD_GCC_EATHREAD_SYNC_GCC_H 15 | #define EATHREAD_GCC_EATHREAD_SYNC_GCC_H 16 | 17 | 18 | #include 19 | 20 | 21 | #define EA_THREAD_SYNC_IMPLEMENTED 22 | 23 | 24 | // EAProcessorPause 25 | // Intel has defined a 'pause' instruction for x86 processors starting with the P4, though this simply 26 | // maps to the otherwise undocumented 'rep nop' instruction. This pause instruction is important for 27 | // high performance spinning, as otherwise a high performance penalty incurs. 28 | 29 | #if defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64) 30 | #define EAProcessorPause() __asm__ __volatile__ ("rep ; nop") 31 | #else 32 | #define EAProcessorPause() 33 | #endif 34 | 35 | 36 | 37 | // EAReadBarrier / EAWriteBarrier / EAReadWriteBarrier 38 | // The x86 processor memory architecture ensures read and write consistency on both single and 39 | // multi processing systems. This makes programming simpler but limits maximimum system performance. 40 | // We define EAReadBarrier here to be the same as EACompilerMemory barrier in order to limit the 41 | // compiler from making any assumptions at its level about memory usage. Year 2003+ versions of the 42 | // Microsoft SDK define a 'MemoryBarrier' statement which has the same effect as EAReadWriteBarrier. 43 | 44 | #if (((__GNUC__ * 100) + __GNUC_MINOR__) >= 401) // GCC 4.1 or later 45 | #define EAReadBarrier __sync_synchronize 46 | #define EAWriteBarrier __sync_synchronize 47 | #define EAReadWriteBarrier __sync_synchronize 48 | #else 49 | #define EAReadBarrier EACompilerMemoryBarrier 50 | #define EAWriteBarrier EACompilerMemoryBarrier 51 | #define EAReadWriteBarrier EACompilerMemoryBarrier 52 | #endif 53 | 54 | 55 | // EACompilerMemoryBarrier 56 | 57 | #if defined(EA_PROCESSOR_ARM) || defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64) 58 | #define EACompilerMemoryBarrier() __asm__ __volatile__ ("":::"memory") 59 | #else 60 | #define EACompilerMemoryBarrier() 61 | #endif 62 | 63 | 64 | 65 | #endif // EATHREAD_GCC_EATHREAD_SYNC_GCC_H 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Source/External/EAThread/internal/atomic.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EATHREAD_INTERNAL_ATOMIC_H 6 | #define EATHREAD_INTERNAL_ATOMIC_H 7 | 8 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 9 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 10 | #endif 11 | 12 | namespace EA 13 | { 14 | namespace Thread 15 | { 16 | typedef int64_t(*AtomicAdd64Function)(volatile int64_t *ptr, int64_t value); 17 | typedef int64_t(*AtomicGetValue64Function)(volatile int64_t *ptr); 18 | typedef int64_t(*AtomicSetValue64Function)(volatile int64_t *ptr, int64_t value); 19 | typedef bool(*AtomicSetValueConditional64Function)(volatile int64_t *ptr, int64_t value, int64_t condition); 20 | 21 | 22 | extern AtomicAdd64Function AtomicAdd64; 23 | extern AtomicGetValue64Function AtomicGetValue64; 24 | extern AtomicSetValue64Function AtomicSetValue64; 25 | extern AtomicSetValueConditional64Function AtomicSetValueConditional64; 26 | } 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /Source/External/EAThread/internal/dllinfo.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef EATHREAD_DLLINFO_H 6 | #define EATHREAD_DLLINFO_H 7 | 8 | 9 | #include 10 | 11 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 12 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 13 | #endif 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /Source/External/EAThread/internal/eathread_atomic.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | ///////////////////////////////////////////////////////////////////////////// 6 | // eathread_atomic.h 7 | // 8 | // Defines functionality for thread-safe primitive operations. 9 | // 10 | // EAThread atomics do NOT imply the use of read/write barriers. This is 11 | // partly due to historical reasons and partly due to EAThread's internal 12 | // code being optimized for not using barriers. 13 | // 14 | // In future, we are considering migrating the atomics interface which 15 | // defaults atomics to use full read/write barriers while allowing users 16 | // to opt-out of full barrier usage. The new C++11 interface already provides 17 | // similar interfaces. 18 | // 19 | // http://en.cppreference.com/w/cpp/atomic/memory_order 20 | // 21 | // Created by Rob Parolin 22 | ///////////////////////////////////////////////////////////////////////////// 23 | 24 | #ifndef EATHREAD_INTERNAL_EATHREAD_ATOMIC_H 25 | #define EATHREAD_INTERNAL_EATHREAD_ATOMIC_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 33 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 34 | #endif 35 | 36 | #define EA_THREAD_ATOMIC_IMPLEMENTED 37 | 38 | namespace EA 39 | { 40 | namespace Thread 41 | { 42 | /// class AtomicInt 43 | /// 44 | /// Implements thread-safe access to an integer and primary operations on that integer. 45 | /// AtomicIntegers are commonly used as lightweight flags and signals between threads 46 | /// or as the synchronization object for spinlocks. Those familiar with the Win32 API 47 | /// will find that AtomicInt32 is essentially a platform independent interface to 48 | /// the Win32 InterlockedXXX family of functions. Those familiar with Linux may 49 | /// find that AtomicInt32 is essentially a platform independent interface to atomic_t 50 | /// functionality. 51 | /// 52 | /// Note that the reference implementation defined here is itself not thread-safe. 53 | /// A thread-safe version requires platform-specific code. 54 | /// 55 | /// Example usage 56 | /// AtomicInt32 i = 0; 57 | /// 58 | /// ++i; 59 | /// i--; 60 | /// i += 7; 61 | /// i -= 3; 62 | /// i = 2; 63 | /// 64 | /// int x = i.GetValue(); 65 | /// i.Increment(); 66 | /// bool oldValueWas6 = i.SetValueConditional(3, 6); 67 | /// i.Add(4); 68 | /// 69 | template 70 | class AtomicInt 71 | { 72 | public: 73 | typedef AtomicInt ThisType; 74 | typedef T ValueType; 75 | 76 | /// AtomicInt 77 | /// Empty constructor. Intentionally leaves mValue in an unspecified state. 78 | /// This is done so that an AtomicInt acts like a standard built-in integer. 79 | AtomicInt() 80 | {} 81 | 82 | AtomicInt(ValueType n) 83 | { SetValue(n); } 84 | 85 | AtomicInt(const ThisType& x) 86 | { SetValue(x.GetValue()); } 87 | 88 | AtomicInt& operator=(const ThisType& x) 89 | { SetValue(x.GetValue()); return *this; } 90 | 91 | ValueType GetValue() const 92 | { return mValue.load(); } 93 | 94 | ValueType GetValueRaw() const 95 | { return mValue; } 96 | 97 | ValueType SetValue(ValueType n) 98 | { return mValue.exchange(n); } 99 | 100 | bool SetValueConditional(ValueType n, ValueType condition) 101 | { return mValue.compare_exchange_strong(condition, n); } 102 | 103 | ValueType Increment() 104 | { return mValue.operator++(); } 105 | 106 | ValueType Decrement() 107 | { return mValue.operator--(); } 108 | 109 | ValueType Add(ValueType n) 110 | { return mValue.fetch_add(n) + n; } 111 | 112 | // operators 113 | inline operator const ValueType() const { return GetValue(); } 114 | inline ValueType operator =(ValueType n) { return mValue.operator=(n); } 115 | inline ValueType operator+=(ValueType n) { return mValue.operator+=(n); } 116 | inline ValueType operator-=(ValueType n) { return mValue.operator-=(n); } 117 | inline ValueType operator++() { return mValue.operator++(); } 118 | inline ValueType operator++(int) { return mValue.operator++(0); } 119 | inline ValueType operator--() { return mValue.operator--(); } 120 | inline ValueType operator--(int) { return mValue.operator--(0); } 121 | 122 | protected: 123 | std::atomic mValue; 124 | }; 125 | 126 | } // namespace Thread 127 | } // namespace EA 128 | 129 | 130 | #endif // EATHREAD_INTERNAL_EATHREAD_ATOMIC_H 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /Source/External/EAThread/internal/eathread_atomic_standalone.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 6 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 7 | #endif 8 | 9 | /// Standalone atomic functions 10 | /// These act the same as the class functions below. 11 | /// The T return values are the previous value, except for the 12 | /// AtomicFetchSwap function which returns the swapped out value. 13 | /// 14 | /// T AtomicGetValue(volatile T*); 15 | /// T AtomicGetValue(const volatile T*); 16 | /// void AtomicSetValue(volatile T*, T value); 17 | /// T AtomicFetchIncrement(volatile T*); 18 | /// T AtomicFetchDecrement(volatile T*); 19 | /// T AtomicFetchAdd(volatile T*, T value); 20 | /// T AtomicFetchSub(volatile T*, T value); 21 | /// T AtomicFetchOr(volatile T*, T value); 22 | /// T AtomicFetchAnd(volatile T*, T value); 23 | /// T AtomicFetchXor(volatile T*, T value); 24 | /// T AtomicFetchSwap(volatile T*, T value); 25 | /// T AtomicFetchSwapConditional(volatile T*, T value, T condition); 26 | /// bool AtomicSetValueConditional(volatile T*, T value, T condition); 27 | 28 | #if defined(EA_COMPILER_MSVC) 29 | #include 30 | #elif defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG) 31 | #include 32 | #else 33 | #error unsupported platform 34 | #endif 35 | 36 | 37 | -------------------------------------------------------------------------------- /Source/External/EAThread/internal/eathread_global.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 6 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 7 | #endif 8 | 9 | ///////////////////////////////////////////////////////////////////////////// 10 | // NOTE(rparolin): Provides a unified method of access to EAThread global 11 | // variables that (when specified by the user) can become DLL safe by adding a 12 | // dependency on EAStdC EAGlobal implementation. 13 | ///////////////////////////////////////////////////////////////////////////// 14 | 15 | #ifndef EATHREAD_INTERNAL_GLOBAL_H 16 | #define EATHREAD_INTERNAL_GLOBAL_H 17 | 18 | #if EATHREAD_GLOBAL_VARIABLE_DLL_SAFETY 19 | #include 20 | 21 | #define EATHREAD_GLOBALVARS (*EA::StdC::AutoStaticOSGlobalPtr().get()) 22 | #define EATHREAD_GLOBALVARS_CREATE_INSTANCE EA::StdC::AutoStaticOSGlobalPtr gGlobalVarsInstance; 23 | #define EATHREAD_GLOBALVARS_EXTERN_INSTANCE 24 | 25 | #else 26 | #define EATHREAD_GLOBALVARS gEAThreadGlobalVars 27 | #define EATHREAD_GLOBALVARS_CREATE_INSTANCE EA::Thread::EAThreadGlobalVars gEAThreadGlobalVars 28 | #define EATHREAD_GLOBALVARS_EXTERN_INSTANCE extern EA::Thread::EAThreadGlobalVars gEAThreadGlobalVars 29 | 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /Source/External/EAThread/internal/timings.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 6 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 7 | #endif 8 | 9 | #ifndef EATHREAD_INTERNAL_TIMINGS_H 10 | #define EATHREAD_INTERNAL_TIMINGS_H 11 | 12 | namespace EA 13 | { 14 | namespace Thread 15 | { 16 | 17 | #if defined(EA_PLATFORM_SONY) 18 | // RelativeTimeoutFromAbsoluteTimeout returns a relative timeout in microseconds. 19 | inline uint32_t RelativeTimeoutFromAbsoluteTimeout(EA::Thread::ThreadTime timeoutAbsolute) 20 | { 21 | using namespace EA::Thread; 22 | 23 | EAT_ASSERT((timeoutAbsolute == kTimeoutImmediate) || (timeoutAbsolute > EATHREAD_MIN_ABSOLUTE_TIME)); // Assert that the user didn't make the mistake of treating time as relative instead of absolute. 24 | 25 | uint32_t timeoutRelative = 0; 26 | 27 | if (timeoutAbsolute == kTimeoutNone) 28 | { 29 | timeoutRelative = 0xffffffff; 30 | } 31 | else if (timeoutAbsolute == kTimeoutImmediate) 32 | { 33 | timeoutRelative = 0; 34 | } 35 | else 36 | { 37 | ThreadTime timeCurrent(GetThreadTime()); 38 | timeoutRelative = (timeoutAbsolute > timeCurrent) ? EA_THREADTIME_AS_UINT_MICROSECONDS(timeoutAbsolute - timeCurrent) : 0; 39 | } 40 | 41 | EAT_ASSERT((timeoutRelative == 0xffffffff) || (timeoutRelative < 100000000)); // Assert that the timeout is a sane value and didn't wrap around. 42 | 43 | return timeoutRelative; 44 | } 45 | #endif 46 | 47 | } 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/android/com_ea_EAThread_EAThread.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class com_ea_EAThread_EAThread */ 4 | 5 | #ifndef _Included_com_ea_EAThread_EAThread 6 | #define _Included_com_ea_EAThread_EAThread 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | /* 11 | * Class: com_ea_EAThread_EAThread 12 | * Method: Init 13 | * Signature: ()V 14 | */ 15 | JNIEXPORT void JNICALL Java_com_ea_EAThread_EAThread_Init 16 | (JNIEnv *, jclass); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | #endif 22 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/android/eathread_android.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #include 7 | #include 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/android/eathread_fake_atomic_64.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | /// Pseudo implementation of 64 bit primitives modelled after Android's internals. 6 | /// Return values and semantics are intended to be the same as 32 bit versions. 7 | /// 8 | /// Basically just does a mutex lock around the operation. Rather than just 9 | /// one global lock, uses a fixed set of mutexes to lock based on incoming 10 | /// address to reduce contention. 11 | /// 12 | /// Abuses the fact that the initializer for a pthread_mutex_t in Android is 13 | /// simply "{0}" on a volatile int to avoid requiring global initialization of 14 | /// these mutexes. 15 | 16 | 17 | #include 18 | 19 | #if defined(EA_PLATFORM_ANDROID) 20 | 21 | #include 22 | 23 | namespace EA 24 | { 25 | namespace Thread 26 | { 27 | 28 | #define EAT_FAKE_ATOMIC_SWAP_LOCK_COUNT 32U 29 | static pthread_mutex_t sFakeAtomic64SwapLocks[EAT_FAKE_ATOMIC_SWAP_LOCK_COUNT]; 30 | 31 | #define EAT_SWAP_LOCK(addr) &sFakeAtomic64SwapLocks[((unsigned)(void*)(addr) >> 3U) % EAT_FAKE_ATOMIC_SWAP_LOCK_COUNT] 32 | 33 | 34 | int64_t android_fake_atomic_swap_64(int64_t value, volatile int64_t* addr) 35 | { 36 | int64_t oldValue; 37 | pthread_mutex_t* lock = EAT_SWAP_LOCK(addr); 38 | 39 | pthread_mutex_lock(lock); 40 | 41 | oldValue = *addr; 42 | *addr = value; 43 | 44 | pthread_mutex_unlock(lock); 45 | return oldValue; 46 | } 47 | 48 | 49 | int android_fake_atomic_cmpxchg_64(int64_t oldvalue, int64_t newvalue, volatile int64_t* addr) 50 | { 51 | int ret; 52 | pthread_mutex_t* lock = EAT_SWAP_LOCK(addr); 53 | 54 | pthread_mutex_lock(lock); 55 | 56 | if (*addr == oldvalue) 57 | { 58 | *addr = newvalue; 59 | ret = 0; 60 | } 61 | else 62 | { 63 | ret = 1; 64 | } 65 | pthread_mutex_unlock(lock); 66 | return ret; 67 | } 68 | 69 | 70 | int64_t android_fake_atomic_read_64(volatile int64_t* addr) 71 | { 72 | int64_t ret; 73 | pthread_mutex_t* lock = EAT_SWAP_LOCK(addr); 74 | 75 | pthread_mutex_lock(lock); 76 | ret = *addr; 77 | pthread_mutex_unlock(lock); 78 | return ret; 79 | } 80 | 81 | } // namespace Thread 82 | } // namespace EA 83 | 84 | #endif // #if defined(EA_PLATFORM_ANDROID) 85 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/apple/eathread_semaphore_apple.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #include 7 | #include 8 | 9 | #if defined(EA_PLATFORM_APPLE) 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | EASemaphoreData::EASemaphoreData() 23 | : mSemaphore(), mnCount(0), mnMaxCount(INT_MAX) 24 | { 25 | } 26 | 27 | 28 | EA::Thread::SemaphoreParameters::SemaphoreParameters(int initialCount, bool bIntraProcess, const char* /*pName*/) 29 | : mInitialCount(initialCount), mMaxCount(INT_MAX), mbIntraProcess(bIntraProcess) 30 | { 31 | } 32 | 33 | 34 | EA::Thread::Semaphore::Semaphore(const SemaphoreParameters* pSemaphoreParameters, bool bDefaultParameters) 35 | { 36 | if(!pSemaphoreParameters && bDefaultParameters) 37 | { 38 | SemaphoreParameters parameters; 39 | Init(¶meters); 40 | } 41 | else 42 | Init(pSemaphoreParameters); 43 | } 44 | 45 | 46 | EA::Thread::Semaphore::Semaphore(int initialCount) 47 | { 48 | SemaphoreParameters parameters(initialCount); 49 | Init(¶meters); 50 | } 51 | 52 | 53 | EA::Thread::Semaphore::~Semaphore() 54 | { 55 | const kern_return_t result = semaphore_destroy(mach_task_self(), mSemaphoreData.mSemaphore); (void)result; 56 | EAT_ASSERT(KERN_SUCCESS == result); 57 | } 58 | 59 | 60 | bool EA::Thread::Semaphore::Init(const SemaphoreParameters* pSemaphoreParameters) 61 | { 62 | if(pSemaphoreParameters) 63 | { 64 | mSemaphoreData.mnCount = pSemaphoreParameters->mInitialCount; 65 | mSemaphoreData.mnMaxCount = pSemaphoreParameters->mMaxCount; 66 | 67 | if(mSemaphoreData.mnCount < 0) 68 | mSemaphoreData.mnCount = 0; 69 | 70 | // Todo, Jaap Suter, December 2009, do we care about actually supporting this? 71 | mSemaphoreData.mbIntraProcess = pSemaphoreParameters->mbIntraProcess; 72 | 73 | const kern_return_t result = semaphore_create(mach_task_self(), &mSemaphoreData.mSemaphore, SYNC_POLICY_FIFO, static_cast(mSemaphoreData.mnCount)); (void)result; 74 | EAT_ASSERT(KERN_SUCCESS == result); 75 | 76 | return true; 77 | } 78 | 79 | return false; 80 | } 81 | 82 | 83 | int EA::Thread::Semaphore::Wait(const ThreadTime& timeoutAbsolute) 84 | { 85 | kern_return_t result = KERN_SUCCESS; 86 | 87 | if(timeoutAbsolute == kTimeoutNone) 88 | { 89 | result = semaphore_wait(mSemaphoreData.mSemaphore); 90 | 91 | if(result != KERN_SUCCESS) 92 | { 93 | EAT_ASSERT(false); // This is an error condition. 94 | return kResultError; 95 | } 96 | } 97 | else 98 | { 99 | for (;;) 100 | { 101 | ThreadTime timeoutRelative = kTimeoutImmediate; 102 | if (timeoutAbsolute != kTimeoutImmediate) 103 | { 104 | ThreadTime timeCurrent = GetThreadTime(); 105 | timeoutRelative = (timeoutAbsolute > timeCurrent) ? (timeoutAbsolute - timeCurrent) : kTimeoutImmediate; 106 | } 107 | 108 | mach_timespec_t machTimeoutRelative = { (unsigned int)timeoutRelative.tv_sec, (clock_res_t)timeoutRelative.tv_nsec }; 109 | result = semaphore_timedwait(mSemaphoreData.mSemaphore, machTimeoutRelative); 110 | 111 | if (result == KERN_SUCCESS) 112 | break; 113 | 114 | if (result == KERN_OPERATION_TIMED_OUT) 115 | return kResultTimeout; 116 | 117 | // printf("semaphore_timedwait other error: %d\n", result); 118 | } 119 | } 120 | 121 | EAT_ASSERT(mSemaphoreData.mnCount > 0); 122 | return (int)mSemaphoreData.mnCount.Decrement(); // AtomicInt32 operation. Note that the value of the semaphore count could change from the returned value by the time the caller reads it. This is fine but the user should understand this. 123 | } 124 | 125 | 126 | int EA::Thread::Semaphore::Post(int count) 127 | { 128 | // Some systems have a sem_post_multiple which we could take advantage 129 | // of here to atomically post multiple times. 130 | EAT_ASSERT(mSemaphoreData.mnCount >= 0); 131 | 132 | int currentCount = mSemaphoreData.mnCount; 133 | 134 | // If count would cause an overflow exit early 135 | if ((mSemaphoreData.mnMaxCount - count) < currentCount) 136 | return kResultError; 137 | 138 | currentCount += count; 139 | 140 | while(count-- > 0) 141 | { 142 | ++mSemaphoreData.mnCount; // AtomicInt32 operation. 143 | 144 | if(semaphore_signal(mSemaphoreData.mSemaphore) != KERN_SUCCESS) 145 | { 146 | --mSemaphoreData.mnCount; // AtomicInt32 operation. 147 | EAT_ASSERT(false); 148 | return kResultError; 149 | } 150 | } 151 | 152 | // If all count posts occurred... 153 | return currentCount; // It's possible that another thread may have modified this value since we changed it, but that's not important. 154 | } 155 | 156 | 157 | int EA::Thread::Semaphore::GetCount() const 158 | { 159 | return (int)mSemaphoreData.mnCount; 160 | } 161 | 162 | 163 | #endif // #if defined(EA_PLATFORM_APPLE) 164 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/cpp11/eathread_mutex_cpp11.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include "eathread/eathread_mutex.h" 6 | 7 | EAMutexData::EAMutexData() : mnLockCount(0) {} 8 | 9 | EA::Thread::MutexParameters::MutexParameters(bool /*bIntraProcess*/, const char* pName) 10 | { 11 | if(pName) 12 | { 13 | strncpy(mName, pName, sizeof(mName)-1); 14 | mName[sizeof(mName)-1] = 0; 15 | } 16 | else 17 | { 18 | mName[0] = 0; 19 | } 20 | } 21 | 22 | EA::Thread::Mutex::Mutex(const MutexParameters* pMutexParameters, bool bDefaultParameters) 23 | { 24 | if(!pMutexParameters && bDefaultParameters) 25 | { 26 | MutexParameters parameters; 27 | Init(¶meters); 28 | } 29 | else 30 | { 31 | Init(pMutexParameters); 32 | } 33 | } 34 | 35 | EA::Thread::Mutex::~Mutex() 36 | { 37 | EAT_ASSERT(mMutexData.mnLockCount == 0); 38 | } 39 | 40 | bool EA::Thread::Mutex::Init(const MutexParameters* pMutexParameters) 41 | { 42 | if (pMutexParameters) 43 | { 44 | mMutexData.mnLockCount = 0; 45 | return true; 46 | } 47 | return false; 48 | } 49 | 50 | int EA::Thread::Mutex::Lock(const ThreadTime& timeoutAbsolute) 51 | { 52 | if (timeoutAbsolute == kTimeoutNone) 53 | { 54 | mMutexData.mMutex.lock(); 55 | } 56 | else 57 | { 58 | std::chrono::milliseconds timeoutAbsoluteMs(timeoutAbsolute); 59 | std::chrono::time_point timeout_time(timeoutAbsoluteMs); 60 | if (!mMutexData.mMutex.try_lock_until(timeout_time)) 61 | { 62 | return kResultTimeout; 63 | } 64 | } 65 | 66 | EAT_ASSERT((mMutexData.mThreadId = EA::Thread::GetThreadId()) != kThreadIdInvalid); 67 | EAT_ASSERT(mMutexData.mnLockCount >= 0); 68 | 69 | return ++mMutexData.mnLockCount; // This is safe to do because we have the lock. 70 | } 71 | 72 | int EA::Thread::Mutex::Unlock() 73 | { 74 | EAT_ASSERT(mMutexData.mThreadId == EA::Thread::GetThreadId()); 75 | EAT_ASSERT(mMutexData.mnLockCount > 0); 76 | 77 | const int nReturnValue(--mMutexData.mnLockCount); // This is safe to do because we have the lock. 78 | mMutexData.mMutex.unlock(); 79 | return nReturnValue; 80 | } 81 | 82 | int EA::Thread::Mutex::GetLockCount() const 83 | { 84 | return mMutexData.mnLockCount; 85 | } 86 | 87 | bool EA::Thread::Mutex::HasLock() const 88 | { 89 | #if EAT_ASSERT_ENABLED 90 | return (mMutexData.mnLockCount > 0) && (mMutexData.mThreadId == EA::Thread::GetThreadId()); 91 | #else 92 | return (mMutexData.mnLockCount > 0); // This is the best we can do, though it is of limited use, since it doesn't tell you if you are the thread with the lock. 93 | #endif 94 | } 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/cpp11/eathread_semaphore_cpp11.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include "eathread/eathread_semaphore.h" 6 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/eathread_callstack.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include 6 | 7 | #if defined(EA_PLATFORM_WIN32) && EA_WINAPI_FAMILY_PARTITION(EA_WINAPI_PARTITION_DESKTOP) 8 | #include "pc/eathread_callstack_win32.cpp" 9 | #elif defined(EA_PLATFORM_MICROSOFT) && defined(EA_PROCESSOR_X86_64) 10 | #include "pc/eathread_callstack_win64.cpp" 11 | #elif defined(EA_PLATFORM_SONY) 12 | #include "kettle/eathread_callstack_kettle.cpp" 13 | #include "kettle/eathread_pthread_stack_info.cpp" 14 | #elif defined(EA_PLATFORM_ANDROID) && defined(EA_PROCESSOR_X86) 15 | #include "x86/eathread_callstack_x86.cpp" 16 | #include "unix/eathread_pthread_stack_info.cpp" 17 | #elif defined(EA_PLATFORM_ANDROID) 18 | #include "libunwind/eathread_callstack_libunwind.cpp" 19 | #include "unix/eathread_pthread_stack_info.cpp" 20 | #elif defined(EA_PLATFORM_APPLE) // OSX, iPhone, iPhone Simulator 21 | #include "apple/eathread_callstack_apple.cpp" 22 | #include "unix/eathread_pthread_stack_info.cpp" 23 | #elif defined(EA_PROCESSOR_ARM) 24 | #include "arm/eathread_callstack_arm.cpp" 25 | #if !defined(EA_PLATFORM_MICROSOFT) 26 | #include "unix/eathread_pthread_stack_info.cpp" 27 | #endif 28 | #elif (defined(EA_PLATFORM_LINUX) || defined(__CYGWIN__)) && (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64)) 29 | #include "x86/eathread_callstack_x86.cpp" 30 | #include "unix/eathread_pthread_stack_info.cpp" 31 | #elif defined(__GNUC__) || defined(EA_COMPILER_CLANG) 32 | #include "unix/eathread_callstack_glibc.cpp" 33 | #include "unix/eathread_pthread_stack_info.cpp" 34 | #else 35 | #include "null/eathread_callstack_null.cpp" 36 | #endif 37 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/eathread_mutex.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include 6 | 7 | EA_DISABLE_VC_WARNING(4574) 8 | #include 9 | #include 10 | EA_RESTORE_VC_WARNING() 11 | 12 | #if !EA_THREADS_AVAILABLE 13 | #include 14 | #elif EA_USE_CPP11_CONCURRENCY 15 | #include "cpp11/eathread_mutex_cpp11.cpp" 16 | #if defined(CreateMutex) 17 | #undef CreateMutex 18 | #endif 19 | #elif defined(EA_PLATFORM_SONY) 20 | #include "kettle/eathread_mutex_kettle.cpp" 21 | #elif defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE 22 | #include "unix/eathread_mutex_unix.cpp" 23 | #elif defined(EA_PLATFORM_MICROSOFT) 24 | #include "pc/eathread_mutex_pc.cpp" 25 | #endif 26 | 27 | 28 | namespace EA 29 | { 30 | namespace Thread 31 | { 32 | extern Allocator* gpAllocator; 33 | } 34 | } 35 | 36 | 37 | EA::Thread::Mutex* EA::Thread::MutexFactory::CreateMutex() 38 | { 39 | if(gpAllocator) 40 | return new(gpAllocator->Alloc(sizeof(EA::Thread::Mutex))) EA::Thread::Mutex; 41 | else 42 | return new EA::Thread::Mutex; 43 | } 44 | 45 | void EA::Thread::MutexFactory::DestroyMutex(EA::Thread::Mutex* pMutex) 46 | { 47 | if(gpAllocator) 48 | { 49 | pMutex->~Mutex(); 50 | gpAllocator->Free(pMutex); 51 | } 52 | else 53 | delete pMutex; 54 | } 55 | 56 | size_t EA::Thread::MutexFactory::GetMutexSize() 57 | { 58 | return sizeof(EA::Thread::Mutex); 59 | } 60 | 61 | EA::Thread::Mutex* EA::Thread::MutexFactory::ConstructMutex(void* pMemory) 62 | { 63 | return new(pMemory) EA::Thread::Mutex; 64 | } 65 | 66 | void EA::Thread::MutexFactory::DestructMutex(EA::Thread::Mutex* pMutex) 67 | { 68 | pMutex->~Mutex(); 69 | } 70 | 71 | 72 | 73 | /////////////////////////////////////////////////////////////////////////////// 74 | // non-threaded implementation 75 | /////////////////////////////////////////////////////////////////////////////// 76 | 77 | #if defined(EA_THREAD_NONTHREADED_MUTEX) && EA_THREAD_NONTHREADED_MUTEX 78 | 79 | EAMutexData::EAMutexData() 80 | : mnLockCount(0) 81 | { 82 | // Empty 83 | } 84 | 85 | 86 | EA::Thread::MutexParameters::MutexParameters(bool /*bIntraProcess*/, const char* /*pName*/) 87 | : mbIntraProcess(true) 88 | { 89 | } 90 | 91 | 92 | EA::Thread::Mutex::Mutex(const MutexParameters* pMutexParameters, bool bDefaultParameters) 93 | { 94 | if(!pMutexParameters && bDefaultParameters) 95 | { 96 | MutexParameters parameters; 97 | Init(¶meters); 98 | } 99 | else 100 | Init(pMutexParameters); 101 | } 102 | 103 | 104 | EA::Thread::Mutex::~Mutex() 105 | { 106 | EAT_ASSERT(mMutexData.mnLockCount == 0); 107 | } 108 | 109 | 110 | bool EA::Thread::Mutex::Init(const MutexParameters* /*pMutexParameters*/) 111 | { 112 | // Possibly copy pMutexParameters->mName to mMutexData.mName 113 | return true; 114 | } 115 | 116 | 117 | int EA::Thread::Mutex::Lock(const ThreadTime& /*timeoutAbsolute*/) 118 | { 119 | EAT_ASSERT(mMutexData.mnLockCount < 100000); 120 | 121 | return ++mMutexData.mnLockCount; 122 | } 123 | 124 | 125 | int EA::Thread::Mutex::Unlock() 126 | { 127 | EAT_ASSERT(mMutexData.mnLockCount > 0); 128 | 129 | return --mMutexData.mnLockCount; 130 | } 131 | 132 | 133 | int EA::Thread::Mutex::GetLockCount() const 134 | { 135 | return mMutexData.mnLockCount; 136 | } 137 | 138 | 139 | bool EA::Thread::Mutex::HasLock() const 140 | { 141 | return (mMutexData.mnLockCount > 0); 142 | } 143 | 144 | #endif // EA_THREAD_NONTHREADED_MUTEX 145 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/kettle/eathread_barrier_kettle.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | EABarrierData::EABarrierData() 15 | : mCV(), mMutex(), mnHeight(0), mnCurrent(0), mnCycle(0), mbValid(false) 16 | {} 17 | 18 | 19 | EA::Thread::BarrierParameters::BarrierParameters(int height, bool bIntraProcess, const char* pName) 20 | : mHeight(height), mbIntraProcess(bIntraProcess) 21 | { 22 | if(pName) 23 | strncpy(mName, pName, sizeof(mName)-1); 24 | else 25 | mName[0] = 0; 26 | } 27 | 28 | 29 | EA::Thread::Barrier::Barrier(const BarrierParameters* pBarrierParameters, bool bDefaultParameters) 30 | { 31 | if(!pBarrierParameters && bDefaultParameters) 32 | { 33 | BarrierParameters parameters; 34 | Init(¶meters); 35 | } 36 | else 37 | Init(pBarrierParameters); 38 | } 39 | 40 | 41 | EA::Thread::Barrier::Barrier(int height) 42 | { 43 | BarrierParameters parameters(height); 44 | Init(¶meters); 45 | } 46 | 47 | 48 | EA::Thread::Barrier::~Barrier() 49 | { 50 | if(mBarrierData.mbValid){ 51 | EAT_ASSERT(mBarrierData.mnCurrent == mBarrierData.mnHeight); 52 | int result = scePthreadMutexDestroy(&mBarrierData.mMutex); 53 | EA_UNUSED(result); 54 | EAT_ASSERT(result == 0); 55 | result = scePthreadCondDestroy(&mBarrierData.mCV); 56 | EAT_ASSERT(result == 0); 57 | EA_UNUSED( result ); //if compiling without asserts 58 | } 59 | } 60 | 61 | 62 | bool EA::Thread::Barrier::Init(const BarrierParameters* pBarrierParameters) 63 | { 64 | if(pBarrierParameters && !mBarrierData.mbValid) 65 | { 66 | mBarrierData.mbValid = false; 67 | mBarrierData.mnHeight = pBarrierParameters->mHeight; 68 | mBarrierData.mnCurrent = pBarrierParameters->mHeight; 69 | mBarrierData.mnCycle = 0; 70 | 71 | int result = scePthreadMutexInit(&mBarrierData.mMutex, NULL, pBarrierParameters->mName); 72 | if(result == 0){ 73 | result = scePthreadCondInit(&mBarrierData.mCV, NULL, pBarrierParameters->mName); 74 | if(result == 0) 75 | mBarrierData.mbValid = true; 76 | else 77 | scePthreadMutexDestroy(&mBarrierData.mMutex); 78 | } 79 | return mBarrierData.mbValid; 80 | } 81 | return false; 82 | } 83 | 84 | 85 | EA::Thread::Barrier::Result EA::Thread::Barrier::Wait(const ThreadTime& timeoutAbsolute) 86 | { 87 | if(!mBarrierData.mbValid){ 88 | EAT_ASSERT(false); 89 | return kResultError; 90 | } 91 | 92 | int result = scePthreadMutexLock(&mBarrierData.mMutex); 93 | if(result != 0){ 94 | EAT_ASSERT(false); 95 | return kResultError; 96 | } 97 | 98 | const unsigned long nCurrentCycle = (unsigned)mBarrierData.mnCycle; 99 | bool bPrimary = false; 100 | 101 | if(--mBarrierData.mnCurrent == 0){ // This is not an atomic operation. We are within a mutex lock. 102 | // The last barrier can never time out, as its action is always immediate. 103 | mBarrierData.mnCycle++; 104 | mBarrierData.mnCurrent = mBarrierData.mnHeight; 105 | result = scePthreadCondBroadcast(&mBarrierData.mCV); 106 | 107 | // The last thread into the barrier will return a result of 108 | // kResultPrimary rather than kResultSecondary. 109 | if(result == 0) 110 | bPrimary = true; 111 | //else leave result as an error value. 112 | } 113 | else{ 114 | // timeoutMilliseconds 115 | // Wait with cancellation disabled, because pthreads barrier_wait 116 | // should not be a cancellation point. 117 | #if defined(SCE_PTHREAD_CANCEL_DISABLE) 118 | int cancel; 119 | scePthreadSetcancelstate(SCE_PTHREAD_CANCEL_DISABLE, &cancel); 120 | #endif 121 | 122 | // Wait until the barrier's cycle changes, which means that 123 | // it has been broadcast, and we don't want to wait anymore. 124 | while(nCurrentCycle == mBarrierData.mnCycle){ 125 | do{ 126 | // Under SMP systems, pthread_cond_wait can return the success value 'spuriously'. 127 | // This is by design and we must retest the predicate condition and if it has 128 | // not true, we must go back to waiting. 129 | result = scePthreadCondTimedwait(&mBarrierData.mCV, &mBarrierData.mMutex, RelativeTimeoutFromAbsoluteTimeout(timeoutAbsolute)); 130 | } while((result == 0) && (nCurrentCycle == mBarrierData.mnCycle)); 131 | if(result != 0) 132 | break; 133 | } 134 | 135 | #if defined(SCE_PTHREAD_CANCEL_DISABLE) 136 | int cancelTemp; 137 | scePthreadSetcancelstate(cancel, &cancelTemp); 138 | #endif 139 | } 140 | 141 | // We declare a new result2 value because the old one 142 | // might have a special value from above in it. 143 | const int result2 = scePthreadMutexUnlock(&mBarrierData.mMutex); (void)result2; 144 | EAT_ASSERT(result2 == 0); 145 | 146 | if(result == 0) 147 | return bPrimary ? kResultPrimary : kResultSecondary; 148 | else if(result == ETIMEDOUT) 149 | return kResultTimeout; 150 | return kResultError; 151 | } 152 | 153 | 154 | EA::Thread::Barrier* EA::Thread::BarrierFactory::CreateBarrier() 155 | { 156 | EA::Thread::Allocator* pAllocator = EA::Thread::GetAllocator(); 157 | 158 | if(pAllocator) 159 | return new(pAllocator->Alloc(sizeof(EA::Thread::Barrier))) EA::Thread::Barrier; 160 | else 161 | return new EA::Thread::Barrier; 162 | } 163 | 164 | void EA::Thread::BarrierFactory::DestroyBarrier(EA::Thread::Barrier* pBarrier) 165 | { 166 | EA::Thread::Allocator* pAllocator = EA::Thread::GetAllocator(); 167 | 168 | if(pAllocator) 169 | { 170 | pBarrier->~Barrier(); 171 | pAllocator->Free(pBarrier); 172 | } 173 | else 174 | delete pBarrier; 175 | } 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/kettle/eathread_condition_kettle.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | EAConditionData::EAConditionData() 15 | { 16 | memset(&mCV, 0, sizeof(mCV)); 17 | } 18 | 19 | 20 | EA::Thread::ConditionParameters::ConditionParameters(bool bIntraProcess, const char* pName) 21 | : mbIntraProcess(bIntraProcess) 22 | { 23 | if (pName) 24 | { 25 | strncpy(mName, pName, sizeof(mName) - 1); 26 | mName[sizeof(mName) - 1] = 0; 27 | } 28 | else 29 | mName[0] = 0; 30 | } 31 | 32 | 33 | EA::Thread::Condition::Condition(const ConditionParameters* pConditionParameters, bool bDefaultParameters) 34 | { 35 | if(!pConditionParameters && bDefaultParameters) 36 | { 37 | ConditionParameters parameters; 38 | Init(¶meters); 39 | } 40 | else 41 | Init(pConditionParameters); 42 | } 43 | 44 | 45 | EA::Thread::Condition::~Condition() 46 | { 47 | scePthreadCondDestroy(&mConditionData.mCV); 48 | } 49 | 50 | 51 | bool EA::Thread::Condition::Init(const ConditionParameters* pConditionParameters) 52 | { 53 | if(pConditionParameters) 54 | { 55 | ScePthreadCondattr cattr; 56 | scePthreadCondattrInit(&cattr); 57 | const int result = scePthreadCondInit(&mConditionData.mCV, &cattr, pConditionParameters->mName); 58 | EAT_ASSERT(result == 0); 59 | 60 | scePthreadCondattrDestroy(&cattr); 61 | return (result == 0); 62 | } 63 | 64 | return false; 65 | } 66 | 67 | 68 | EA::Thread::Condition::Result EA::Thread::Condition::Wait(Mutex* pMutex, const ThreadTime& timeoutAbsolute) 69 | { 70 | int result; 71 | ScePthreadMutex* pMutex_t; 72 | EAMutexData* pMutexData; 73 | 74 | EAT_ASSERT(pMutex); 75 | 76 | // We have a small problem here in that if we are using the pMutex argument, 77 | // the pthread_cond_wait call will unlock the mutex via the internal mutex data and 78 | // not without calling the Mutex::Lock function. The result is that the Mutex doesn't 79 | // have its lock count value reduced by one and so other threads will see the lock 80 | // count as being 1 when in fact it should be zero. So we account for that here 81 | // by manually maintaining the lock count, which we can do because we have the lock. 82 | EAT_ASSERT(pMutex->GetLockCount() == 1); 83 | pMutexData = (EAMutexData*)pMutex->GetPlatformData(); 84 | pMutexData->SimulateLock(false); 85 | pMutex_t = &pMutexData->mMutex; 86 | 87 | if(timeoutAbsolute == kTimeoutNone) 88 | result = scePthreadCondWait(&mConditionData.mCV, pMutex_t); 89 | else 90 | result = scePthreadCondTimedwait(&mConditionData.mCV, pMutex_t, RelativeTimeoutFromAbsoluteTimeout(timeoutAbsolute)); 91 | 92 | pMutexData->SimulateLock(true); 93 | EAT_ASSERT(!pMutex || (pMutex->GetLockCount() == 1)); 94 | 95 | if(result != 0) 96 | { 97 | if(result == SCE_KERNEL_ERROR_ETIMEDOUT) 98 | return kResultTimeout; 99 | EAT_ASSERT(false); 100 | return kResultError; 101 | } 102 | return kResultOK; 103 | } 104 | 105 | 106 | bool EA::Thread::Condition::Signal(bool bBroadcast) 107 | { 108 | if(bBroadcast) 109 | return (scePthreadCondBroadcast(&mConditionData.mCV) == 0); 110 | return (scePthreadCondSignal(&mConditionData.mCV) == 0); 111 | } 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/kettle/eathread_mutex_kettle.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | EAMutexData::EAMutexData() 13 | : mMutex(), mnLockCount(0) 14 | { 15 | #if EAT_ASSERT_ENABLED 16 | mThreadId = EA::Thread::kThreadIdInvalid; 17 | #endif 18 | 19 | ::memset(&mMutex, 0, sizeof(mMutex)); 20 | } 21 | 22 | void EAMutexData::SimulateLock(bool bLock) 23 | { 24 | if(bLock) 25 | { 26 | ++mnLockCount; 27 | EAT_ASSERT((mThreadId = EA::Thread::GetThreadId()) || true); // Intentionally '=' here and not '=='. 28 | } 29 | else 30 | { 31 | --mnLockCount; 32 | EAT_ASSERT((mThreadId = EA::Thread::kThreadIdInvalid) || true); // Intentionally '=' here and not '=='. 33 | } 34 | } 35 | 36 | 37 | EA::Thread::MutexParameters::MutexParameters(bool bIntraProcess, const char* pName) 38 | : mbIntraProcess(bIntraProcess) 39 | { 40 | mName[0] = '\0'; 41 | 42 | if (pName != nullptr) 43 | { 44 | strncpy(mName, pName, sizeof(mName) - 1); 45 | mName[sizeof(mName) - 1] = '\0'; 46 | } 47 | } 48 | 49 | 50 | EA::Thread::Mutex::Mutex(const MutexParameters* pMutexParameters, bool bDefaultParameters) 51 | { 52 | if(!pMutexParameters && bDefaultParameters) 53 | { 54 | MutexParameters parameters; 55 | Init(¶meters); 56 | } 57 | else 58 | Init(pMutexParameters); 59 | } 60 | 61 | 62 | EA::Thread::Mutex::~Mutex() 63 | { 64 | EAT_ASSERT(mMutexData.mnLockCount == 0); 65 | scePthreadMutexDestroy(&mMutexData.mMutex); 66 | } 67 | 68 | 69 | bool EA::Thread::Mutex::Init(const MutexParameters* pMutexParameters) 70 | { 71 | if(pMutexParameters) 72 | { 73 | mMutexData.mnLockCount = 0; 74 | 75 | ScePthreadMutexattr attr; 76 | scePthreadMutexattrInit(&attr); 77 | 78 | scePthreadMutexattrSettype(&attr, SCE_PTHREAD_MUTEX_RECURSIVE); 79 | 80 | #if defined(SCE_PTHREAD_PROCESS_PRIVATE) // Some pthread_disabled implementations don't recognize this. 81 | if(pMutexParameters->mbIntraProcess) 82 | scePthreadMutexattrSettype(&attr, SCE_PTHREAD_PROCESS_PRIVATE); 83 | else 84 | scePthreadMutexattrSettype(&attr, SCE_PTHREAD_PROCESS_PRIVATE); 85 | #endif 86 | 87 | // kettle mutex name is restricted to 32 bytes INCLUDING null character. See "scePthreadMutexInit" 88 | char mutexNameCopy[32]; 89 | strncpy(mutexNameCopy, pMutexParameters->mName, sizeof(mutexNameCopy) - 1); 90 | mutexNameCopy[sizeof(mutexNameCopy)-1] = '\0'; 91 | 92 | // Sony allocates memory for any length string which reduces the amount of active mutex allowed by the operating 93 | // system. We only provide a string if it is non-zero in length. 94 | int result = SCE_KERNEL_ERROR_EAGAIN; 95 | if (pMutexParameters->mName[0] != '\0') 96 | { 97 | result = scePthreadMutexInit(&mMutexData.mMutex, &attr, mutexNameCopy); 98 | } 99 | 100 | if (result == SCE_KERNEL_ERROR_EAGAIN) 101 | { 102 | // We've hit the limit for named mutexes on PS4, so fallback to an unnamed mutex which has a much higher limit 103 | result = scePthreadMutexInit(&mMutexData.mMutex, &attr, NULL); 104 | } 105 | scePthreadMutexattrDestroy(&attr); 106 | 107 | EAT_ASSERT(SCE_OK == result); 108 | return (SCE_OK == result); 109 | } 110 | 111 | return false; 112 | } 113 | 114 | 115 | int EA::Thread::Mutex::Lock(const ThreadTime& timeoutAbsolute) 116 | { 117 | int result; 118 | 119 | EAT_ASSERT(mMutexData.mnLockCount < 100000); 120 | 121 | if(timeoutAbsolute == kTimeoutNone) 122 | { 123 | result = scePthreadMutexLock(&mMutexData.mMutex); 124 | 125 | if(result != 0) 126 | { 127 | EAT_ASSERT(false); 128 | return kResultError; 129 | } 130 | } 131 | else if(timeoutAbsolute == kTimeoutImmediate) 132 | { 133 | result = scePthreadMutexTrylock(&mMutexData.mMutex); 134 | 135 | if(result != 0) 136 | { 137 | if(result == SCE_KERNEL_ERROR_EBUSY) 138 | return kResultTimeout; 139 | 140 | EAT_ASSERT(false); 141 | return kResultError; 142 | } 143 | } 144 | else 145 | { 146 | result = scePthreadMutexTimedlock(&mMutexData.mMutex, RelativeTimeoutFromAbsoluteTimeout(timeoutAbsolute)); 147 | 148 | if(result != 0) 149 | { 150 | if(result == SCE_KERNEL_ERROR_ETIMEDOUT) 151 | return kResultTimeout; 152 | 153 | EAT_ASSERT(false); 154 | return kResultError; 155 | } 156 | } 157 | 158 | EAT_ASSERT(mMutexData.mThreadId = EA::Thread::GetThreadId()); // Intentionally '=' here and not '=='. 159 | EAT_ASSERT(mMutexData.mnLockCount >= 0); 160 | return ++mMutexData.mnLockCount; // This is safe to do because we have the lock. 161 | } 162 | 163 | 164 | int EA::Thread::Mutex::Unlock() 165 | { 166 | EAT_ASSERT(mMutexData.mThreadId == EA::Thread::GetThreadId()); 167 | EAT_ASSERT(mMutexData.mnLockCount > 0); 168 | 169 | const int nReturnValue(--mMutexData.mnLockCount); // This is safe to do because we have the lock. 170 | 171 | if(scePthreadMutexUnlock(&mMutexData.mMutex) != 0) 172 | { 173 | EAT_ASSERT(false); 174 | return nReturnValue + 1; 175 | } 176 | 177 | return nReturnValue; 178 | } 179 | 180 | 181 | int EA::Thread::Mutex::GetLockCount() const 182 | { 183 | return mMutexData.mnLockCount; 184 | } 185 | 186 | 187 | bool EA::Thread::Mutex::HasLock() const 188 | { 189 | #if EAT_ASSERT_ENABLED 190 | return (mMutexData.mnLockCount > 0) && (mMutexData.mThreadId == GetThreadId()); 191 | #else 192 | return (mMutexData.mnLockCount > 0); // This is the best we can do. 193 | #endif 194 | } 195 | 196 | 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/kettle/eathread_pthread_stack_info.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include 6 | #include 7 | 8 | namespace EA 9 | { 10 | namespace Thread 11 | { 12 | // With some implementations of pthread_disabled, the stack base is returned by pthread_disabled as NULL if it's the main thread, 13 | // or possibly if it's a thread you created but didn't call pthread_disabled_attr_setstack manually to provide your 14 | // own stack. It's impossible for us to tell here whether will be such a NULL return value, so we just do what 15 | // we can and the user nees to beware that a NULL return value means that the system doesn't provide the 16 | // given information for the current thread. This function returns false and sets pBase and pLimit to NULL in 17 | // the case that the thread base and limit weren't returned by the system or were returned as NULL. 18 | bool GetPthreadStackInfo(void** pBase, void** pLimit) 19 | { 20 | bool returnValue = false; 21 | size_t stackSize; 22 | void* pBaseTemp = NULL; 23 | void* pLimitTemp = NULL; 24 | 25 | ScePthreadAttr attr; 26 | 27 | scePthreadAttrInit(&attr); 28 | 29 | int result = scePthreadAttrGet(scePthreadSelf(), &attr); 30 | if(result == 0) // SCE_OK (=0) 31 | { 32 | result = scePthreadAttrGetstack(&attr, &pLimitTemp, &stackSize); 33 | if((result == 0) && (pLimitTemp != NULL)) // If success... 34 | { 35 | pBaseTemp = (void*)((uintptr_t)pLimitTemp + stackSize); // p is returned by pthread_disabled_attr_getstack as the lowest address in the stack, and not the stack base. 36 | returnValue = true; 37 | } 38 | else 39 | { 40 | pBaseTemp = NULL; 41 | pLimitTemp = NULL; 42 | } 43 | } 44 | 45 | scePthreadAttrDestroy(&attr); 46 | 47 | if(pBase) 48 | *pBase = pBaseTemp; 49 | if(pLimit) 50 | *pLimit = pLimitTemp; 51 | 52 | return returnValue; 53 | } 54 | 55 | } // namespace Callstack 56 | } // namespace EA 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/kettle/eathread_semaphore_kettle.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include 6 | #include 7 | 8 | #if defined(EA_PLATFORM_SONY) 9 | 10 | #include 11 | #include 12 | 13 | EASemaphoreData::EASemaphoreData() 14 | : mSemaphore(NULL), mnMaxCount(INT_MAX), mnCount(0) 15 | { 16 | } 17 | 18 | EA::Thread::SemaphoreParameters::SemaphoreParameters(int initialCount, bool bIntraProcess, const char* pName) 19 | : mInitialCount(initialCount), mMaxCount(INT_MAX), mbIntraProcess(bIntraProcess) 20 | { 21 | // Maximum lenght for the semaphore name on Kettle is 32 (including NULL terminator) 22 | EAT_COMPILETIME_ASSERT(sizeof(mName) <= 32); 23 | 24 | if (pName) 25 | { 26 | strncpy(mName, pName, sizeof(mName)-1); 27 | mName[sizeof(mName)-1] = 0; 28 | } 29 | else 30 | { 31 | mName[0] = 0; 32 | } 33 | } 34 | 35 | 36 | EA::Thread::Semaphore::Semaphore(const SemaphoreParameters* pSemaphoreParameters, bool bDefaultParameters) 37 | { 38 | if (!pSemaphoreParameters && bDefaultParameters) 39 | { 40 | SemaphoreParameters parameters; 41 | Init(¶meters); 42 | } 43 | else 44 | { 45 | Init(pSemaphoreParameters); 46 | } 47 | } 48 | 49 | 50 | EA::Thread::Semaphore::Semaphore(int initialCount) 51 | { 52 | SemaphoreParameters parameters(initialCount); 53 | Init(¶meters); 54 | } 55 | 56 | 57 | EA::Thread::Semaphore::~Semaphore() 58 | { 59 | int result = sceKernelDeleteSema(mSemaphoreData.mSemaphore); 60 | EAT_ASSERT(result == SCE_OK); EA_UNUSED(result); 61 | } 62 | 63 | 64 | bool EA::Thread::Semaphore::Init(const SemaphoreParameters* pSemaphoreParameters) 65 | { 66 | if (pSemaphoreParameters 67 | && pSemaphoreParameters->mInitialCount >= 0 68 | && pSemaphoreParameters->mMaxCount >= 0) 69 | { 70 | mSemaphoreData.mnMaxCount = pSemaphoreParameters->mMaxCount; 71 | mSemaphoreData.mnCount = pSemaphoreParameters->mInitialCount; 72 | 73 | int result = sceKernelCreateSema( 74 | &mSemaphoreData.mSemaphore, 75 | pSemaphoreParameters->mName, 76 | SCE_KERNEL_SEMA_ATTR_TH_FIFO, 77 | mSemaphoreData.mnCount, 78 | mSemaphoreData.mnMaxCount, 79 | NULL); 80 | 81 | if (result == SCE_OK) 82 | return true; 83 | } 84 | 85 | // Failure: could not create semaphore 86 | return false; 87 | } 88 | 89 | 90 | int EA::Thread::Semaphore::Wait(const ThreadTime& timeoutAbsolute) 91 | { 92 | int result = 0; 93 | 94 | // Convert timeout from absolute to relative (possibly losing some capacity) 95 | SceKernelUseconds timeoutRelativeUs = static_cast(RelativeTimeoutFromAbsoluteTimeout(timeoutAbsolute)); 96 | do 97 | { 98 | if (timeoutAbsolute == kTimeoutImmediate) 99 | { 100 | result = sceKernelPollSema(mSemaphoreData.mSemaphore, 1); 101 | } 102 | else 103 | { 104 | result = sceKernelWaitSema(mSemaphoreData.mSemaphore, 1, &timeoutRelativeUs); 105 | } 106 | 107 | if (result != SCE_OK) 108 | { 109 | // SCE_KERNEL_ERROR_ETIMEDOUT is the failure case for 'sceKernelWaitSema' 110 | // SCE_KERNEL_ERROR_EBUSY is the failure case for 'sceKernelPollSema' 111 | // We want to consume the SCE_KERNEL_ERROR_EBUSY error code from the polling interface 112 | // users have a consistent error code to check against. 113 | if (result == SCE_KERNEL_ERROR_ETIMEDOUT || result == SCE_KERNEL_ERROR_EBUSY) 114 | { 115 | if (timeoutAbsolute != kTimeoutNone) 116 | return kResultTimeout; 117 | } 118 | else 119 | { 120 | EAT_FAIL_MSG("Semaphore::Wait: sceKernelWaitSema failure."); 121 | return kResultError; 122 | } 123 | } 124 | } while (result != SCE_OK); 125 | 126 | // Success 127 | EAT_ASSERT(mSemaphoreData.mnCount.GetValue() > 0); 128 | return static_cast(mSemaphoreData.mnCount.Decrement()); 129 | } 130 | 131 | 132 | int EA::Thread::Semaphore::Post(int count) 133 | { 134 | EAT_ASSERT(count >= 0); 135 | 136 | const int currentCount = mSemaphoreData.mnCount; 137 | 138 | if (count > 0) 139 | { 140 | // If count would cause an overflow exit early 141 | if ((mSemaphoreData.mnMaxCount - count) < currentCount) 142 | return kResultError; 143 | 144 | // We increment the count before we signal the semaphore so that any waken up 145 | // thread will have the right count immediately 146 | mSemaphoreData.mnCount.Add(count); 147 | 148 | int result = sceKernelSignalSema(mSemaphoreData.mSemaphore, count); 149 | 150 | if (result != SCE_OK) 151 | { 152 | // If not successful set the count back 153 | mSemaphoreData.mnCount.Add(-count); 154 | return kResultError; 155 | } 156 | } 157 | 158 | return currentCount + count; // It's possible that another thread may have modified this value since we changed it, but that's not important. 159 | } 160 | 161 | 162 | int EA::Thread::Semaphore::GetCount() const 163 | { 164 | // There is no way to query the semaphore for the resource count on Kettle, 165 | // we need to rely on our external atomic counter 166 | return mSemaphoreData.mnCount.GetValue(); 167 | } 168 | 169 | #endif // EA_PLATFORM_SONY 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/null/eathread_callstack_null.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | #if defined(_MSC_VER) 12 | #pragma warning(disable: 4172) // returning address of local variable or temporary 13 | #endif 14 | 15 | 16 | namespace EA 17 | { 18 | namespace Thread 19 | { 20 | 21 | 22 | EATHREADLIB_API void InitCallstack() 23 | { 24 | } 25 | 26 | EATHREADLIB_API void ShutdownCallstack() 27 | { 28 | } 29 | 30 | EATHREADLIB_API size_t GetCallstack(void* /*callstack*/[], size_t /*maxDepth*/, const CallstackContext* /*pContext*/) 31 | { 32 | return 0; 33 | } 34 | 35 | EATHREADLIB_API bool GetCallstackContext(CallstackContext& /*context*/, intptr_t /*threadId*/) 36 | { 37 | return false; 38 | } 39 | 40 | EATHREADLIB_API bool GetCallstackContextSysThreadId(CallstackContext& /*context*/, intptr_t /*sysThreadId*/) 41 | { 42 | return false; 43 | } 44 | 45 | EATHREADLIB_API void GetCallstackContext(CallstackContext& context, const Context* /*pContext*/) 46 | { 47 | memset(&context, 0, sizeof(context)); 48 | } 49 | 50 | EATHREADLIB_API size_t GetModuleFromAddress(const void* /*pAddress*/, char* /*pModuleFileName*/, size_t /*moduleNameCapacity*/) 51 | { 52 | return 0; 53 | } 54 | 55 | EATHREADLIB_API ModuleHandle GetModuleHandleFromAddress(const void* /*pAddress*/) 56 | { 57 | return (ModuleHandle)0; 58 | } 59 | 60 | 61 | #if EA_THREADS_AVAILABLE 62 | static EA::Thread::ThreadLocalStorage sStackBase; 63 | #else 64 | static void* sStackBase; 65 | #endif 66 | 67 | /////////////////////////////////////////////////////////////////////////////// 68 | // SetStackBase 69 | // 70 | EATHREADLIB_API void SetStackBase(void* pStackBase) 71 | { 72 | if(pStackBase) 73 | { 74 | #if EA_THREADS_AVAILABLE 75 | sStackBase.SetValue(pStackBase); 76 | #else 77 | sStackBase = pStackBase; 78 | #endif 79 | } 80 | else 81 | { 82 | pStackBase = GetStackBase(); 83 | SetStackBase(pStackBase); 84 | } 85 | } 86 | 87 | 88 | /////////////////////////////////////////////////////////////////////////////// 89 | // GetStackBase 90 | // 91 | EATHREADLIB_API void* GetStackBase() 92 | { 93 | #if EA_THREADS_AVAILABLE 94 | void* pStackBase = sStackBase.GetValue(); 95 | #else 96 | void* pStackBase = sStackBase; 97 | #endif 98 | 99 | if(!pStackBase) 100 | pStackBase = (void*)(((uintptr_t)GetStackLimit() + 4095) & ~4095); // Align up to nearest page, as the stack grows downward. 101 | 102 | return pStackBase; 103 | } 104 | 105 | 106 | /////////////////////////////////////////////////////////////////////////////// 107 | // GetStackLimit 108 | // 109 | EATHREADLIB_API void* GetStackLimit() 110 | { 111 | void* pStack = NULL; 112 | 113 | pStack = &pStack; 114 | 115 | return (void*)((uintptr_t)pStack & ~4095); // Round down to nearest page, as the stack grows downward. 116 | } 117 | 118 | } // namespace Thread 119 | } // namespace EA 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/pc/eathread_callstack_win64.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michal-z/ImageBasedPBR/ae3a9110a508bcc48ca786f22c12c3d5db6ddd61/Source/External/EAThread/source/pc/eathread_callstack_win64.cpp -------------------------------------------------------------------------------- /Source/External/EAThread/source/unix/eathread_condition_unix.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | #if defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE 12 | #include 13 | #include 14 | #include 15 | #include 16 | #ifdef EA_PLATFORM_WINDOWS 17 | #pragma warning(push, 0) 18 | #include // Presumably we are using pthreads-win32. 19 | #pragma warning(pop) 20 | #endif 21 | 22 | 23 | EAConditionData::EAConditionData() 24 | { 25 | memset(&mCV, 0, sizeof(mCV)); 26 | } 27 | 28 | 29 | EA::Thread::ConditionParameters::ConditionParameters(bool bIntraProcess, const char* /*pName*/) 30 | : mbIntraProcess(bIntraProcess) 31 | { 32 | // Empty 33 | } 34 | 35 | 36 | EA::Thread::Condition::Condition(const ConditionParameters* pConditionParameters, bool bDefaultParameters) 37 | { 38 | if(!pConditionParameters && bDefaultParameters) 39 | { 40 | ConditionParameters parameters; 41 | Init(¶meters); 42 | } 43 | else 44 | Init(pConditionParameters); 45 | } 46 | 47 | 48 | EA::Thread::Condition::~Condition() 49 | { 50 | pthread_cond_destroy(&mConditionData.mCV); 51 | } 52 | 53 | 54 | bool EA::Thread::Condition::Init(const ConditionParameters* pConditionParameters) 55 | { 56 | if(pConditionParameters) 57 | { 58 | #if defined(EA_PLATFORM_ANDROID) // Some platforms don't provide pthread_condattr_init, and pthread_condattr_t is just an int. 59 | pthread_condattr_t cattr; 60 | memset(&cattr, 0, sizeof(cattr)); 61 | 62 | const int result = pthread_cond_init(&mConditionData.mCV, &cattr); 63 | 64 | return (result == 0); 65 | #else 66 | pthread_condattr_t cattr; 67 | pthread_condattr_init(&cattr); 68 | 69 | #if defined(PTHREAD_PROCESS_PRIVATE) // Some pthread implementations don't recognize this. PTHREAD_PROCESS_SHARED bugged on iphone 70 | #if defined(EA_PLATFORM_IPHONE) || defined(EA_PLATFORM_OSX) 71 | EAT_ASSERT( pConditionParameters->mbIntraProcess == true ); // shared conditions bugged on apple hardware 72 | #else 73 | if(pConditionParameters->mbIntraProcess) 74 | pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_PRIVATE); 75 | else 76 | pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED); 77 | #endif 78 | #endif 79 | 80 | const int result = pthread_cond_init(&mConditionData.mCV, &cattr); 81 | 82 | pthread_condattr_destroy(&cattr); 83 | 84 | return (result == 0); 85 | #endif 86 | } 87 | 88 | return false; 89 | } 90 | 91 | 92 | EA::Thread::Condition::Result EA::Thread::Condition::Wait(Mutex* pMutex, const ThreadTime& timeoutAbsolute) 93 | { 94 | int result; 95 | pthread_mutex_t* pMutex_t; 96 | EAMutexData* pMutexData; 97 | 98 | EAT_ASSERT(pMutex); 99 | 100 | // We have a small problem here in that if we are using the pMutex argument, 101 | // the pthread_cond_wait call will unlock the mutex via the internal mutex data and 102 | // not without calling the Mutex::Lock function. The result is that the Mutex doesn't 103 | // have its lock count value reduced by one and so other threads will see the lock 104 | // count as being 1 when in fact it should be zero. So we account for that here 105 | // by manually maintaining the lock count, which we can do because we have the lock. 106 | EAT_ASSERT(pMutex->GetLockCount() == 1); 107 | pMutexData = (EAMutexData*)pMutex->GetPlatformData(); 108 | pMutexData->SimulateLock(false); 109 | pMutex_t = &pMutexData->mMutex; 110 | 111 | if(timeoutAbsolute == kTimeoutNone) 112 | result = pthread_cond_wait(&mConditionData.mCV, pMutex_t); 113 | else 114 | result = pthread_cond_timedwait(&mConditionData.mCV, pMutex_t, &timeoutAbsolute); 115 | 116 | pMutexData->SimulateLock(true); 117 | EAT_ASSERT(!pMutex || (pMutex->GetLockCount() == 1)); 118 | 119 | if(result != 0) 120 | { 121 | if(result == ETIMEDOUT) 122 | return kResultTimeout; 123 | EAT_ASSERT(false); 124 | return kResultError; 125 | } 126 | return kResultOK; 127 | } 128 | 129 | 130 | bool EA::Thread::Condition::Signal(bool bBroadcast) 131 | { 132 | if(bBroadcast) 133 | return (pthread_cond_broadcast(&mConditionData.mCV) == 0); 134 | return (pthread_cond_signal(&mConditionData.mCV) == 0); 135 | } 136 | 137 | 138 | #endif // EA_PLATFORM_XXX 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/unix/eathread_pthread_stack_info.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #include 7 | #include 8 | 9 | #if defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_APPLE) 10 | #include 11 | #endif 12 | 13 | namespace EA 14 | { 15 | namespace Thread 16 | { 17 | 18 | #if defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_APPLE) || defined(EA_PLATFORM_SONY) 19 | // With some implementations of pthread, the stack base is returned by pthread as NULL if it's the main thread, 20 | // or possibly if it's a thread you created but didn't call pthread_attr_setstack manually to provide your 21 | // own stack. It's impossible for us to tell here whether will be such a NULL return value, so we just do what 22 | // we can and the user nees to beware that a NULL return value means that the system doesn't provide the 23 | // given information for the current thread. This function returns false and sets pBase and pLimit to NULL in 24 | // the case that the thread base and limit weren't returned by the system or were returned as NULL. 25 | 26 | #if defined(EA_PLATFORM_APPLE) 27 | bool GetPthreadStackInfo(void** pBase, void** pLimit) 28 | { 29 | pthread_t thread = pthread_self(); 30 | void* pBaseTemp = pthread_get_stackaddr_np(thread); 31 | size_t stackSize = pthread_get_stacksize_np(thread); 32 | 33 | if(pBase) 34 | *pBase = pBaseTemp; 35 | if(pLimit) 36 | { 37 | if(pBaseTemp) 38 | *pLimit = (void*)((size_t)pBaseTemp - stackSize); 39 | else 40 | *pLimit = NULL; 41 | } 42 | 43 | return (pBaseTemp != NULL); 44 | } 45 | 46 | #elif defined(EA_PLATFORM_SONY) 47 | bool GetPthreadStackInfo(void** pBase, void** pLimit) 48 | { 49 | bool returnValue = false; 50 | size_t stackSize; 51 | void* pBaseTemp = NULL; 52 | void* pLimitTemp = NULL; 53 | 54 | ScePthreadAttr attr; 55 | 56 | scePthreadAttrInit(&attr); 57 | 58 | int result = scePthreadAttrGet(scePthreadSelf(), &attr); 59 | if(result == 0) // SCE_OK (=0) 60 | { 61 | result = scePthreadAttrGetstack(&attr, &pLimitTemp, &stackSize); 62 | if((result == 0) && (pLimitTemp != NULL)) // If success... 63 | { 64 | pBaseTemp = (void*)((uintptr_t)pLimitTemp + stackSize); // p is returned by pthread_attr_getstack as the lowest address in the stack, and not the stack base. 65 | returnValue = true; 66 | } 67 | else 68 | { 69 | pBaseTemp = NULL; 70 | pLimitTemp = NULL; 71 | } 72 | } 73 | 74 | scePthreadAttrDestroy(&attr); 75 | 76 | if(pBase) 77 | *pBase = pBaseTemp; 78 | if(pLimit) 79 | *pLimit = pLimitTemp; 80 | 81 | return returnValue; 82 | } 83 | #else 84 | bool GetPthreadStackInfo(void** pBase, void** pLimit) 85 | { 86 | bool returnValue = false; 87 | void* pBaseTemp = NULL; 88 | void* pLimitTemp = NULL; 89 | 90 | pthread_attr_t attr; 91 | pthread_attr_init(&attr); 92 | 93 | #if defined(EA_PLATFORM_LINUX) 94 | int result = pthread_getattr_np(pthread_self(), &attr); 95 | #else 96 | int result = pthread_attr_get_np(pthread_self(), &attr); // __BSD__ or __FreeBSD__ 97 | #endif 98 | 99 | if(result == 0) 100 | { 101 | // The pthread_attr_getstack() function returns the stack address and stack size 102 | // attributes of the thread attributes object referred to by attr in the buffers 103 | // pointed to by stackaddr and stacksize, respectively. According to the documentation, 104 | // the stack address reported is the lowest memory address and not the stack 'base'. 105 | // http://pubs.opengroup.org/onlinepubs/007904975/functions/pthread_attr_setstack.html 106 | size_t stackSize; 107 | result = pthread_attr_getstack(&attr, &pLimitTemp, &stackSize); 108 | 109 | if((result == 0) && (pLimitTemp != NULL)) // If success... 110 | { 111 | pBaseTemp = (void*)((uintptr_t)pLimitTemp + stackSize); // p is returned by pthread_attr_getstack as the lowest address in the stack, and not the stack base. 112 | returnValue = true; 113 | } 114 | else 115 | { 116 | pBaseTemp = NULL; 117 | pLimitTemp = NULL; 118 | } 119 | } 120 | 121 | pthread_attr_destroy(&attr); 122 | 123 | if(pBase) 124 | *pBase = pBaseTemp; 125 | if(pLimit) 126 | *pLimit = pLimitTemp; 127 | 128 | return returnValue; 129 | } 130 | #endif 131 | #endif 132 | 133 | 134 | } // namespace Callstack 135 | } // namespace EA 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /Source/External/EAThread/source/version.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #include "eathread/version.h" 6 | 7 | namespace EA 8 | { 9 | namespace Thread 10 | { 11 | const Version gVersion = 12 | { 13 | EATHREAD_VERSION_MAJOR, 14 | EATHREAD_VERSION_MINOR, 15 | EATHREAD_VERSION_PATCH 16 | }; 17 | 18 | const Version* GetVersion() 19 | { 20 | return &gVersion; 21 | } 22 | 23 | bool CheckVersion(int majorVersion, int minorVersion, int patchVersion) 24 | { 25 | return (majorVersion == EATHREAD_VERSION_MAJOR) && 26 | (minorVersion == EATHREAD_VERSION_MINOR) && 27 | (patchVersion == EATHREAD_VERSION_PATCH); 28 | } 29 | } 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /Source/External/EAThread/version.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | 6 | #ifndef EATHREAD_VERSION_H 7 | #define EATHREAD_VERSION_H 8 | 9 | 10 | #include 11 | 12 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 13 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 14 | #endif 15 | 16 | 17 | 18 | namespace EA 19 | { 20 | namespace Thread 21 | { 22 | /// Version contains the version of the library when it was built. 23 | /// This can be used to verify the correct version has been linked 24 | /// into the executable or loaded by the O/S (in the case of a DLL). 25 | struct Version 26 | { 27 | int mMajor; 28 | int mMinor; 29 | int mPatch; 30 | }; 31 | 32 | /// Get the library version information. 33 | EATHREADLIB_API const Version *GetVersion(); 34 | 35 | /// Check that the linked/loaded library is the same as the headers 36 | /// are expecting. 37 | /// 38 | /// If the version numbers passed to CheckVersion match those 39 | /// built into the library when it was compiled, true is returned. 40 | /// If not, false is returned. 41 | EATHREADLIB_API bool CheckVersion(int majorVersion, int minorVersion, int patchVersion); 42 | 43 | } 44 | 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /Source/External/EAThread/x86-64/eathread_sync_x86-64.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 6 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 7 | #endif 8 | 9 | ///////////////////////////////////////////////////////////////////////////// 10 | // Functionality related to memory and code generation synchronization. 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | #ifndef EATHREAD_X86_64_EATHREAD_SYNC_X86_64_H 15 | #define EATHREAD_X86_64_EATHREAD_SYNC_X86_64_H 16 | 17 | 18 | #ifndef INCLUDED_eabase_H 19 | #include "EABase/eabase.h" 20 | #endif 21 | 22 | 23 | #if defined(EA_PROCESSOR_X86_64) 24 | #define EA_THREAD_SYNC_IMPLEMENTED 25 | 26 | #ifdef _MSC_VER 27 | #pragma warning(push, 0) 28 | #include // VS2008 has an acknowledged bug that requires math.h (and possibly also string.h) to be #included before intrin.h. 29 | #include 30 | #pragma warning(pop) 31 | #endif 32 | 33 | // By default, we define EA_TARGET_SMP to be true. The reason for this is that most 34 | // applications that users of this code are likely to write are going to be executables 35 | // which run properly on any system, be it multiprocessing or not. 36 | #ifndef EA_TARGET_SMP 37 | #define EA_TARGET_SMP 1 38 | #endif 39 | 40 | // EAProcessorPause 41 | // Intel has defined a 'pause' instruction for x86 processors starting with the P4, though this simply 42 | // maps to the otherwise undocumented 'rep nop' instruction. This pause instruction is important for 43 | // high performance spinning, as otherwise a high performance penalty incurs. 44 | 45 | #if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_INTEL) || defined(EA_COMPILER_BORLAND) 46 | // Year 2003+ versions of the Microsoft SDK define 'rep nop' as YieldProcessor and/or __yield or _mm_pause. 47 | #pragma intrinsic(_mm_pause) 48 | #define EAProcessorPause() _mm_pause() // The __yield() intrinsic currently doesn't work on x86-64. 49 | #elif defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG) 50 | #define EAProcessorPause() __asm__ __volatile__ ("rep ; nop") 51 | #else 52 | // In this case we use an Intel-style asm statement. If this doesn't work for your compiler then 53 | // there most likely is some way to make the `rep nop` inline asm statement. 54 | #define EAProcessorPause() __asm { rep nop } // Alternatively: { __asm { _emit 0xf3 }; __asm { _emit 0x90 } } 55 | #endif 56 | 57 | 58 | // EAReadBarrier / EAWriteBarrier / EAReadWriteBarrier 59 | // The x86 processor memory architecture ensures read and write consistency on both single and 60 | // multi processing systems. This makes programming simpler but limits maximimum system performance. 61 | // We define EAReadBarrier here to be the same as EACompilerMemory barrier in order to limit the 62 | // compiler from making any assumptions at its level about memory usage. Year 2003+ versions of the 63 | // Microsoft SDK define a 'MemoryBarrier' statement which has the same effect as EAReadWriteBarrier. 64 | #if defined(EA_COMPILER_MSVC) 65 | #pragma intrinsic(_ReadBarrier) 66 | #pragma intrinsic(_WriteBarrier) 67 | #pragma intrinsic(_ReadWriteBarrier) 68 | 69 | #define EAReadBarrier() _ReadBarrier() 70 | #define EAWriteBarrier() _WriteBarrier() 71 | #define EAReadWriteBarrier() _ReadWriteBarrier() 72 | #elif defined(EA_PLATFORM_PS4) 73 | #define EAReadBarrier() __asm__ __volatile__ ("lfence" ::: "memory"); 74 | #define EAWriteBarrier() __asm__ __volatile__ ("sfence" ::: "memory"); 75 | #define EAReadWriteBarrier() __asm__ __volatile__ ("mfence" ::: "memory"); 76 | #elif defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 401) // GCC 4.1 or later 77 | #define EAReadBarrier __sync_synchronize 78 | #define EAWriteBarrier __sync_synchronize 79 | #define EAReadWriteBarrier __sync_synchronize 80 | #else 81 | #define EAReadBarrier EACompilerMemoryBarrier // Need to implement this for non-VC++ 82 | #define EAWriteBarrier EACompilerMemoryBarrier // Need to implement this for non-VC++ 83 | #define EAReadWriteBarrier EACompilerMemoryBarrier // Need to implement this for non-VC++ 84 | #endif 85 | 86 | 87 | // EACompilerMemoryBarrier 88 | #if defined(EA_COMPILER_MSVC) 89 | #define EACompilerMemoryBarrier() _ReadWriteBarrier() 90 | #elif defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG) 91 | #define EACompilerMemoryBarrier() __asm__ __volatile__ ("":::"memory") 92 | #else 93 | #define EACompilerMemoryBarrier() // Possibly `EAT_ASSERT(false)` here? 94 | #endif 95 | 96 | 97 | #endif // EA_PROCESSOR_X86 98 | 99 | 100 | #endif // EATHREAD_X86_64_EATHREAD_SYNC_X86_64_H 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /Source/External/EAThread/x86/eathread_sync_x86.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) Electronic Arts Inc. All rights reserved. 3 | /////////////////////////////////////////////////////////////////////////////// 4 | 5 | #if defined(EA_PRAGMA_ONCE_SUPPORTED) 6 | #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 7 | #endif 8 | 9 | ///////////////////////////////////////////////////////////////////////////// 10 | // Functionality related to memory and code generation synchronization. 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | #ifndef EATHREAD_X86_EATHREAD_SYNC_X86_H 15 | #define EATHREAD_X86_EATHREAD_SYNC_X86_H 16 | 17 | 18 | #ifndef INCLUDED_eabase_H 19 | #include 20 | #endif 21 | 22 | 23 | #if defined(EA_PROCESSOR_X86) 24 | #define EA_THREAD_SYNC_IMPLEMENTED 25 | 26 | // By default, we define EA_TARGET_SMP to be true. The reason for this is that most 27 | // applications that users of this code are likely to write are going to be executables 28 | // which run properly on any system, be it multiprocessing or not. 29 | #ifndef EA_TARGET_SMP 30 | #define EA_TARGET_SMP 1 31 | #endif 32 | 33 | // EAProcessorPause 34 | // Intel has defined a 'pause' instruction for x86 processors starting with the P4, though this simply 35 | // maps to the otherwise undocumented 'rep nop' instruction. This pause instruction is important for 36 | // high performance spinning, as otherwise a high performance penalty incurs. 37 | 38 | #if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_INTEL) || defined(EA_COMPILER_BORLAND) 39 | // Year 2003+ versions of the Microsoft SDK define 'rep nop' as YieldProcessor and/or __yield or _mm_pause. 40 | #define EAProcessorPause() __asm { rep nop } 41 | #elif defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG) 42 | #define EAProcessorPause() __asm__ __volatile__ ("rep ; nop") 43 | #else 44 | // In this case we use an Intel-style asm statement. If this doesn't work for your compiler then 45 | // there most likely is some way to make the `rep nop` inline asm statement. 46 | #define EAProcessorPause() __asm { rep nop } // Alternatively: { __asm { _emit 0xf3 }; __asm { _emit 0x90 } } 47 | #endif 48 | 49 | 50 | // EAReadBarrier / EAWriteBarrier / EAReadWriteBarrier 51 | // The x86 processor memory architecture ensures read and write consistency on both single and 52 | // multi processing systems. This makes programming simpler but limits maximimum system performance. 53 | // We define EAReadBarrier here to be the same as EACompilerMemory barrier in order to limit the 54 | // compiler from making any assumptions at its level about memory usage. Year 2003+ versions of the 55 | // Microsoft SDK define a 'MemoryBarrier' statement which has the same effect as EAReadWriteBarrier. 56 | #if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 401) // GCC 4.1 or later 57 | #define EAReadBarrier __sync_synchronize 58 | #define EAWriteBarrier __sync_synchronize 59 | #define EAReadWriteBarrier __sync_synchronize 60 | #else 61 | #define EAReadBarrier EACompilerMemoryBarrier 62 | #define EAWriteBarrier EACompilerMemoryBarrier 63 | #define EAReadWriteBarrier EACompilerMemoryBarrier 64 | #endif 65 | 66 | // EACompilerMemoryBarrier 67 | #if (defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1300) && defined(EA_PLATFORM_MICROSOFT)) || (defined(EA_COMPILER_INTEL) && (EA_COMPILER_VERSION >= 9999999)) // VC7+ or Intel (unknown version at this time) 68 | extern "C" void _ReadWriteBarrier(); 69 | #pragma intrinsic(_ReadWriteBarrier) 70 | #define EACompilerMemoryBarrier() _ReadWriteBarrier() 71 | #elif defined(EA_COMPILER_GNUC) 72 | #define EACompilerMemoryBarrier() __asm__ __volatile__ ("":::"memory") 73 | #else 74 | #define EACompilerMemoryBarrier() // Possibly `EAT_ASSERT(false)` here? 75 | #endif 76 | 77 | 78 | #endif // EA_PROCESSOR_X86 79 | 80 | 81 | #endif // EATHREAD_X86_EATHREAD_SYNC_X86_H 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /Source/External/cgltf.cpp: -------------------------------------------------------------------------------- 1 | #define CGLTF_IMPLEMENTATION 2 | #include "cgltf.h" -------------------------------------------------------------------------------- /Source/External/stb_image.cpp: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #include "stb_image.h" -------------------------------------------------------------------------------- /Source/Shaders/Common.hlsli: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define PI 3.14159265359f 4 | 5 | float RadicalInverse_VdC(uint Bits) 6 | { 7 | Bits = (Bits << 16u) | (Bits >> 16u); 8 | Bits = ((Bits & 0x55555555u) << 1u) | ((Bits & 0xAAAAAAAAu) >> 1u); 9 | Bits = ((Bits & 0x33333333u) << 2u) | ((Bits & 0xCCCCCCCCu) >> 2u); 10 | Bits = ((Bits & 0x0F0F0F0Fu) << 4u) | ((Bits & 0xF0F0F0F0u) >> 4u); 11 | Bits = ((Bits & 0x00FF00FFu) << 8u) | ((Bits & 0xFF00FF00u) >> 8u); 12 | return (float)Bits * 2.3283064365386963e-10; // / 0x100000000 13 | } 14 | 15 | float2 Hammersley(uint Idx, uint N) 16 | { 17 | return float2(Idx / (float)N, RadicalInverse_VdC(Idx)); 18 | } 19 | 20 | float3 ImportanceSampleGGX(float2 Xi, float Roughness, float3 N) 21 | { 22 | float Alpha = Roughness * Roughness; 23 | float Phi = 2.0f * PI * Xi.x; 24 | float CosTheta = sqrt((1.0f - Xi.y) / (1.0f + (Alpha * Alpha - 1.0f) * Xi.y)); 25 | float SinTheta = sqrt(1.0f - CosTheta * CosTheta); 26 | 27 | float3 H; 28 | H.x = SinTheta * cos(Phi); 29 | H.y = SinTheta * sin(Phi); 30 | H.z = CosTheta; 31 | 32 | float3 UpVector = abs(N.y) < 0.999f ? float3(0.0f, 1.0f, 0.0f) : float3(0.0f, 0.0f, 1.0f); 33 | float3 TangentX = normalize(cross(UpVector, N)); 34 | float3 TangentY = cross(N, TangentX); 35 | 36 | // Tangent to world space. 37 | return TangentX * H.x + TangentY * H.y + N * H.z; 38 | } 39 | 40 | float GeometrySchlickGGX(float CosTheta, float Roughness) 41 | { 42 | float K = (Roughness * Roughness) * 0.5f; 43 | return CosTheta / (CosTheta * (1.0f - K) + K); 44 | } 45 | 46 | float GeometrySmith(float NoL, float NoV, float Roughness) 47 | { 48 | return GeometrySchlickGGX(NoV, Roughness) * GeometrySchlickGGX(NoL, Roughness); 49 | } 50 | -------------------------------------------------------------------------------- /Source/Shaders/EquirectangularToCube.hlsl: -------------------------------------------------------------------------------- 1 | #include "../CPUAndGPUCommon.h" 2 | 3 | #define GRootSignature \ 4 | "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \ 5 | "CBV(b0, visibility = SHADER_VISIBILITY_VERTEX), " \ 6 | "DescriptorTable(SRV(t0), visibility = SHADER_VISIBILITY_PIXEL), " \ 7 | "StaticSampler(" \ 8 | "s0, " \ 9 | "filter = FILTER_MIN_MAG_LINEAR_MIP_POINT, " \ 10 | "visibility = SHADER_VISIBILITY_PIXEL, " \ 11 | "addressU = TEXTURE_ADDRESS_BORDER, " \ 12 | "addressV = TEXTURE_ADDRESS_BORDER)" 13 | 14 | ConstantBuffer GPerDrawCB : register(b0); 15 | 16 | Texture2D GEquirectangularMap : register(t0); 17 | SamplerState GSampler : register(s0); 18 | 19 | float2 SampleSphericalMap(float3 V) 20 | { 21 | float2 UV = float2(atan2(V.z, V.x), asin(V.y)); 22 | UV *= float2(0.1591f, 0.3183f); 23 | UV += 0.5f; 24 | return UV; 25 | } 26 | 27 | [RootSignature(GRootSignature)] 28 | void MainVS( 29 | in float3 InPosition : _Position, 30 | in float3 InNormal : _Normal, 31 | out float4 OutPosition : SV_Position, 32 | out float3 OutPositionOS : _Position) 33 | { 34 | OutPosition = mul(float4(InPosition, 1.0f), GPerDrawCB.ObjectToClip); 35 | OutPositionOS = InPosition; 36 | } 37 | 38 | [RootSignature(GRootSignature)] 39 | void MainPS( 40 | in float4 InPosition : SV_Position, 41 | in float3 InPositionOS : _Position, 42 | out float4 OutColor : SV_Target0) 43 | { 44 | float2 UV = SampleSphericalMap(normalize(InPositionOS)); 45 | OutColor = GEquirectangularMap.SampleLevel(GSampler, UV, 0); 46 | } 47 | -------------------------------------------------------------------------------- /Source/Shaders/GenerateBRDFIntegrationMap.hlsl: -------------------------------------------------------------------------------- 1 | #include "../CPUAndGPUCommon.h" 2 | #include "Common.hlsli" 3 | 4 | #define GRootSignature \ 5 | "RootFlags(0), " \ 6 | "DescriptorTable(UAV(u0))" 7 | 8 | RWTexture2D GBRDFIntegrationMap : register(u0); 9 | 10 | 11 | float2 IntegrateBRDF(float Roughness, float NoV) 12 | { 13 | float3 V; 14 | V.x = 0.0f; 15 | V.y = NoV; // cos 16 | V.z = sqrt(1.0f - NoV * NoV); // sin 17 | 18 | float3 N = float3(0.0f, 1.0f, 0.0f); 19 | 20 | float A = 0.0f; 21 | float B = 0.0f; 22 | const uint NumSamples = 4 * 1024; 23 | 24 | for (uint SampleIdx = 0; SampleIdx < NumSamples; ++SampleIdx) 25 | { 26 | float2 Xi = Hammersley(SampleIdx, NumSamples); 27 | float3 H = ImportanceSampleGGX(Xi, Roughness, N); 28 | float3 L = normalize(2.0f * dot(V, H) * H - V); 29 | 30 | float NoL = saturate(L.y); 31 | float NoH = saturate(H.y); 32 | float VoH = saturate(dot(V, H)); 33 | 34 | if (NoL > 0.0f) 35 | { 36 | float G = GeometrySmith(NoL, NoV, Roughness); 37 | float G_Vis = G * VoH / (NoH * NoV); 38 | float Fc = pow(1.0f - VoH, 5.0f); 39 | A += (1.0f - Fc) * G_Vis; 40 | B += Fc * G_Vis; 41 | } 42 | } 43 | 44 | return float2(A, B) / NumSamples; 45 | } 46 | 47 | [RootSignature(GRootSignature)] 48 | [numthreads(8, 8, 1)] 49 | void MainCS(uint3 ThreadID : SV_DispatchThreadID) 50 | { 51 | float Width, Height; 52 | GBRDFIntegrationMap.GetDimensions(Width, Height); 53 | 54 | float Roughness = (ThreadID.y + 1) / Height; 55 | float NoV = (ThreadID.x + 1) / Width; 56 | 57 | float2 Result = IntegrateBRDF(Roughness, NoV); 58 | 59 | GBRDFIntegrationMap[ThreadID.xy] = float4(Result, 0.0f, 1.0f); 60 | } 61 | -------------------------------------------------------------------------------- /Source/Shaders/GenerateIrradianceMap.hlsl: -------------------------------------------------------------------------------- 1 | #include "../CPUAndGPUCommon.h" 2 | #include "Common.hlsli" 3 | 4 | #define GRootSignature \ 5 | "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \ 6 | "CBV(b0, visibility = SHADER_VISIBILITY_VERTEX), " \ 7 | "DescriptorTable(SRV(t0), visibility = SHADER_VISIBILITY_PIXEL), " \ 8 | "StaticSampler(" \ 9 | "s0, " \ 10 | "filter = FILTER_MIN_MAG_LINEAR_MIP_POINT, " \ 11 | "visibility = SHADER_VISIBILITY_PIXEL, " \ 12 | "addressU = TEXTURE_ADDRESS_BORDER, " \ 13 | "addressV = TEXTURE_ADDRESS_BORDER, " \ 14 | "addressW = TEXTURE_ADDRESS_BORDER)" 15 | 16 | ConstantBuffer GPerDrawCB : register(b0); 17 | TextureCube GEnvMap : register(t0); 18 | SamplerState GSampler : register(s0); 19 | 20 | 21 | [RootSignature(GRootSignature)] 22 | void MainVS( 23 | in float3 InPosition : _Position, 24 | in float3 InNormal : _Normal, 25 | out float4 OutPosition : SV_Position, 26 | out float3 OutPositionOS : _Position) 27 | { 28 | OutPosition = mul(float4(InPosition, 1.0f), GPerDrawCB.ObjectToClip); 29 | OutPositionOS = InPosition; 30 | } 31 | 32 | [RootSignature(GRootSignature)] 33 | void MainPS( 34 | in float4 InPosition : SV_Position, 35 | in float3 InPositionOS : _Position, 36 | out float4 OutColor : SV_Target0) 37 | { 38 | float3 N = normalize(InPositionOS); 39 | 40 | // This is Right-Handed coordinate system and works for upper-left UV coordinate systems. 41 | float3 UpVector = abs(N.y) < 0.999f ? float3(0.0f, 1.0f, 0.0f) : float3(0.0f, 0.0f, 1.0f); 42 | float3 TangentX = normalize(cross(UpVector, N)); 43 | float3 TangentY = cross(N, TangentX); 44 | 45 | int NumSamples = 0; 46 | float3 Irradiance = 0.0f; 47 | 48 | for (float Phi = 0.0f; Phi < (2.0f * PI); Phi += 0.025f) 49 | { 50 | for (float Theta = 0.0f; Theta < (0.5f * PI); Theta += 0.025f) 51 | { 52 | // Point on a hemisphere. 53 | float3 H = float3(sin(Theta) * cos(Phi), sin(Theta) * sin(Phi), cos(Theta)); 54 | 55 | // Transform from tangent space to world space. 56 | float3 SampleVector = TangentX * H.x + TangentY * H.y + N * H.z; 57 | 58 | Irradiance += GEnvMap.SampleLevel(GSampler, SampleVector, 0).rgb * cos(Theta) * sin(Theta); 59 | 60 | NumSamples++; 61 | } 62 | } 63 | 64 | Irradiance = PI * Irradiance * (1.0f / NumSamples); 65 | 66 | OutColor = float4(Irradiance, 1.0f); 67 | } 68 | -------------------------------------------------------------------------------- /Source/Shaders/GenerateMipmaps.hlsl: -------------------------------------------------------------------------------- 1 | #define GRootSignature \ 2 | "RootConstants(b0, num32BitConstants = 2), " \ 3 | "DescriptorTable(SRV(t0), UAV(u0, numDescriptors = 4))" 4 | 5 | Texture2D GSrcMipmap : register(t0); 6 | RWTexture2D GOutMipmap1 : register(u0); 7 | RWTexture2D GOutMipmap2 : register(u1); 8 | RWTexture2D GOutMipmap3 : register(u2); 9 | RWTexture2D GOutMipmap4 : register(u3); 10 | 11 | struct FParams 12 | { 13 | uint SrcMipLevel; 14 | uint NumMipLevels; 15 | }; 16 | ConstantBuffer GParams : register(b0); 17 | 18 | groupshared float GRed[64]; 19 | groupshared float GGreen[64]; 20 | groupshared float GBlue[64]; 21 | groupshared float GAlpha[64]; 22 | 23 | void StoreColor(uint Idx, float4 Color) 24 | { 25 | GRed[Idx] = Color.r; 26 | GGreen[Idx] = Color.g; 27 | GBlue[Idx] = Color.b; 28 | GAlpha[Idx] = Color.a; 29 | } 30 | 31 | float4 LoadColor(uint Idx) 32 | { 33 | return float4(GRed[Idx], GGreen[Idx], GBlue[Idx], GAlpha[Idx]); 34 | } 35 | 36 | [RootSignature(GRootSignature)] 37 | [numthreads(8, 8, 1)] 38 | void MainCS(uint3 GlobalID : SV_DispatchThreadID, uint GroupIdx : SV_GroupIndex) 39 | { 40 | uint x = GlobalID.x * 2; 41 | uint y = GlobalID.y * 2; 42 | 43 | float4 S00 = GSrcMipmap.mips[GParams.SrcMipLevel][uint2(x, y)]; 44 | float4 S10 = GSrcMipmap.mips[GParams.SrcMipLevel][uint2(x + 1, y)]; 45 | float4 S01 = GSrcMipmap.mips[GParams.SrcMipLevel][uint2(x, y + 1)]; 46 | float4 S11 = GSrcMipmap.mips[GParams.SrcMipLevel][uint2(x + 1, y + 1)]; 47 | S00 = 0.25f * (S00 + S01 + S10 + S11); 48 | 49 | GOutMipmap1[GlobalID.xy] = S00; 50 | StoreColor(GroupIdx, S00); 51 | 52 | if (GParams.NumMipLevels == 1) 53 | { 54 | return; 55 | } 56 | GroupMemoryBarrierWithGroupSync(); 57 | 58 | if ((GroupIdx & 0x9) == 0) 59 | { 60 | S10 = LoadColor(GroupIdx + 1); 61 | S01 = LoadColor(GroupIdx + 8); 62 | S11 = LoadColor(GroupIdx + 9); 63 | S00 = 0.25f * (S00 + S01 + S10 + S11); 64 | 65 | GOutMipmap2[GlobalID.xy / 2] = S00; 66 | StoreColor(GroupIdx, S00); 67 | } 68 | 69 | if (GParams.NumMipLevels == 2) 70 | { 71 | return; 72 | } 73 | GroupMemoryBarrierWithGroupSync(); 74 | 75 | if ((GroupIdx & 0x1b) == 0) 76 | { 77 | S10 = LoadColor(GroupIdx + 2); 78 | S01 = LoadColor(GroupIdx + 16); 79 | S11 = LoadColor(GroupIdx + 18); 80 | S00 = 0.25f * (S00 + S01 + S10 + S11); 81 | 82 | GOutMipmap3[GlobalID.xy / 4] = S00; 83 | StoreColor(GroupIdx, S00); 84 | } 85 | 86 | if (GParams.NumMipLevels == 3) 87 | { 88 | return; 89 | } 90 | GroupMemoryBarrierWithGroupSync(); 91 | 92 | if (GroupIdx == 0) 93 | { 94 | S10 = LoadColor(GroupIdx + 4); 95 | S01 = LoadColor(GroupIdx + 32); 96 | S11 = LoadColor(GroupIdx + 36); 97 | S00 = 0.25f * (S00 + S01 + S10 + S11); 98 | 99 | GOutMipmap4[GlobalID.xy / 8] = S00; 100 | StoreColor(GroupIdx, S00); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Source/Shaders/PrefilterEnvMap.hlsl: -------------------------------------------------------------------------------- 1 | #include "../CPUAndGPUCommon.h" 2 | #include "Common.hlsli" 3 | 4 | #define GRootSignature \ 5 | "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \ 6 | "CBV(b0), " \ 7 | "DescriptorTable(SRV(t0), visibility = SHADER_VISIBILITY_PIXEL), " \ 8 | "StaticSampler(" \ 9 | "s0, " \ 10 | "filter = FILTER_MIN_MAG_LINEAR_MIP_POINT, " \ 11 | "visibility = SHADER_VISIBILITY_PIXEL, " \ 12 | "addressU = TEXTURE_ADDRESS_CLAMP, " \ 13 | "addressV = TEXTURE_ADDRESS_CLAMP, " \ 14 | "addressW = TEXTURE_ADDRESS_CLAMP)" 15 | 16 | ConstantBuffer GPerDrawCB : register(b0); 17 | TextureCube GEnvMap : register(t0); 18 | SamplerState GSampler : register(s0); 19 | 20 | 21 | [RootSignature(GRootSignature)] 22 | void MainVS( 23 | in float3 InPosition : _Position, 24 | in float3 InNormal : _Normal, 25 | out float4 OutPosition : SV_Position, 26 | out float3 OutPositionOS : _Position) 27 | { 28 | OutPosition = mul(float4(InPosition, 1.0f), GPerDrawCB.ObjectToClip); 29 | OutPositionOS = InPosition; 30 | } 31 | 32 | [RootSignature(GRootSignature)] 33 | void MainPS( 34 | in float4 InPosition : SV_Position, 35 | in float3 InPositionOS : _Position, 36 | out float4 OutColor : SV_Target0) 37 | { 38 | float Roughness = GPerDrawCB.Roughness; 39 | float3 N = normalize(InPositionOS); 40 | float3 R = N; 41 | float3 V = R; 42 | 43 | float3 PrefilteredColor = 0.0f; 44 | float TotalWeight = 0.0f; 45 | const uint NumSamples = 4 * 1024; 46 | 47 | for (uint SampleIdx = 0; SampleIdx < NumSamples; ++SampleIdx) 48 | { 49 | float2 Xi = Hammersley(SampleIdx, NumSamples); 50 | float3 H = ImportanceSampleGGX(Xi, Roughness, N); 51 | float3 L = normalize(2.0f * dot(V, H) * H - V); 52 | float NoL = saturate(dot(N, L)); 53 | if (NoL > 0.0f) 54 | { 55 | PrefilteredColor += GEnvMap.SampleLevel(GSampler, L, 0).rgb * NoL; 56 | TotalWeight += NoL; 57 | } 58 | } 59 | 60 | OutColor = float4(PrefilteredColor / TotalWeight, 1.0f); 61 | } 62 | -------------------------------------------------------------------------------- /Source/Shaders/SampleEnvMap.hlsl: -------------------------------------------------------------------------------- 1 | #include "../CPUAndGPUCommon.h" 2 | 3 | #define GRootSignature \ 4 | "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \ 5 | "CBV(b0, visibility = SHADER_VISIBILITY_VERTEX), " \ 6 | "DescriptorTable(SRV(t0), visibility = SHADER_VISIBILITY_PIXEL), " \ 7 | "StaticSampler(" \ 8 | "s0, " \ 9 | "filter = FILTER_MIN_MAG_MIP_LINEAR, " \ 10 | "visibility = SHADER_VISIBILITY_PIXEL, " \ 11 | "addressU = TEXTURE_ADDRESS_BORDER, " \ 12 | "addressV = TEXTURE_ADDRESS_BORDER, " \ 13 | "addressW = TEXTURE_ADDRESS_BORDER)" 14 | 15 | ConstantBuffer GPerDrawCB : register(b0); 16 | 17 | TextureCube GEnvMap : register(t0); 18 | SamplerState GSampler : register(s0); 19 | 20 | [RootSignature(GRootSignature)] 21 | void MainVS( 22 | in float3 InPosition : _Position, 23 | in float3 InNormal : _Normal, 24 | out float4 OutPosition : SV_Position, 25 | out float3 OutTexcoords : _Texcoords) 26 | { 27 | OutPosition = mul(float4(InPosition, 1.0f), GPerDrawCB.ObjectToClip).xyww; 28 | OutTexcoords = InPosition; 29 | } 30 | 31 | [RootSignature(GRootSignature)] 32 | void MainPS( 33 | in float4 InPosition : SV_Position, 34 | in float3 InTexcoords : _Texcoords, 35 | out float4 OutColor : SV_Target0) 36 | { 37 | float3 EnvColor = GEnvMap.Sample(GSampler, InTexcoords).rgb; 38 | 39 | EnvColor = EnvColor / (EnvColor + 1.0f); 40 | EnvColor = pow(EnvColor, 1.0f / 2.2f); 41 | 42 | OutColor = float4(EnvColor, 1.0f); 43 | } 44 | -------------------------------------------------------------------------------- /Source/Shaders/SimpleForward.hlsl: -------------------------------------------------------------------------------- 1 | #include "../CPUAndGPUCommon.h" 2 | #include "Common.hlsli" 3 | 4 | #define GRootSignature \ 5 | "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \ 6 | "CBV(b0), " \ 7 | "DescriptorTable(CBV(b1), SRV(t0), SRV(t1), SRV(t2), visibility = SHADER_VISIBILITY_PIXEL), " \ 8 | "StaticSampler(" \ 9 | "s0, " \ 10 | "filter = FILTER_MIN_MAG_MIP_LINEAR, " \ 11 | "visibility = SHADER_VISIBILITY_PIXEL, " \ 12 | "addressU = TEXTURE_ADDRESS_BORDER, " \ 13 | "addressV = TEXTURE_ADDRESS_BORDER, " \ 14 | "addressW = TEXTURE_ADDRESS_BORDER)" 15 | 16 | ConstantBuffer GPerDrawCB : register(b0); 17 | ConstantBuffer GPerFrameCB : register(b1); 18 | TextureCube GIrradianceMap : register(t0); 19 | TextureCube GPrefilteredEnvMap : register(t1); 20 | Texture2D GBRDFIntegrationMap : register(t2); 21 | SamplerState GSampler : register(s0); 22 | 23 | // Trowbridge-Reitz GGX normal distribution function. 24 | float DistributionGGX(float3 N, float3 H, float Roughness) 25 | { 26 | float Alpha = Roughness * Roughness; 27 | float Alpha2 = Alpha * Alpha; 28 | float NoH = dot(N, H); 29 | float NoH2 = NoH * NoH; 30 | float K = NoH2 * Alpha2 + (1.0f - NoH2); 31 | return Alpha2 / (PI * K * K); 32 | } 33 | 34 | float3 FresnelSchlick(float CosTheta, float3 F0) 35 | { 36 | return F0 + (1.0f - F0) * pow(1.0f - CosTheta, 5.0f); 37 | } 38 | 39 | float3 FresnelSchlickRoughness(float CosTheta, float3 F0, float Roughness) 40 | { 41 | return F0 + (max(1.0f - Roughness, F0) - F0) * pow(1.0f - CosTheta, 5.0f); 42 | } 43 | 44 | [RootSignature(GRootSignature)] 45 | void MainVS( 46 | in float3 InPosition : _Position, 47 | in float3 InNormal : _Normal, 48 | out float4 OutPosition : SV_Position, 49 | out float3 OutPositionWS : _Position, 50 | out float3 OutNormalWS : _Normal) 51 | { 52 | OutPosition = mul(float4(InPosition, 1.0f), GPerDrawCB.ObjectToClip); 53 | OutPositionWS = mul(float4(InPosition, 1.0f), GPerDrawCB.ObjectToWorld); 54 | OutNormalWS = mul(InNormal, (float3x3)GPerDrawCB.ObjectToWorld); 55 | } 56 | 57 | [RootSignature(GRootSignature)] 58 | void MainPS( 59 | in float4 InPosition : SV_Position, 60 | in float3 InPositionWS : _Position, 61 | in float3 InNormalWS : _Normal, 62 | out float4 OutColor : SV_Target0) 63 | { 64 | float3 V = normalize(GPerFrameCB.ViewerPosition.xyz - InPositionWS); 65 | float3 N = normalize(InNormalWS); 66 | float NoV = saturate(dot(N, V)); 67 | 68 | float3 Albedo = GPerDrawCB.Albedo; 69 | float Roughness = GPerDrawCB.Roughness; 70 | float Metallic = GPerDrawCB.Metallic; 71 | float AO = GPerDrawCB.AO; 72 | 73 | float3 F0 = float3(0.04f, 0.04f, 0.04f); 74 | F0 = lerp(F0, Albedo, Metallic); 75 | 76 | float3 Lo = 0.0f; 77 | for (int LightIdx = 0; LightIdx < 4; ++LightIdx) 78 | { 79 | float3 LightVector = GPerFrameCB.LightPositions[LightIdx].xyz - InPositionWS; 80 | 81 | float3 L = normalize(LightVector); 82 | float3 H = normalize(L + V); 83 | float NoL = saturate(dot(N, L)); 84 | float HoV = saturate(dot(H, V)); 85 | 86 | float Attenuation = 1.0f / dot(LightVector, LightVector); 87 | float3 Radiance = GPerFrameCB.LightColors[LightIdx].rgb * Attenuation; 88 | 89 | float3 F = FresnelSchlick(HoV, F0); 90 | 91 | float NDF = DistributionGGX(N, H, Roughness); 92 | float G = GeometrySmith(NoL, NoV, (Roughness + 1.0f) * 0.5f); 93 | 94 | float3 Specular = (NDF * G * F) / max(4.0f * NoV * NoL, 0.001f); 95 | 96 | float3 KS = F; 97 | float3 KD = 1.0f - KS; 98 | KD *= 1.0f - Metallic; 99 | 100 | Lo += (KD * (Albedo / PI) + Specular) * Radiance * NoL; 101 | } 102 | 103 | float3 R = reflect(-V, N); 104 | 105 | float3 F = FresnelSchlickRoughness(NoV, F0, Roughness); 106 | 107 | float3 KD = 1.0f - F; 108 | KD *= 1.0f - Metallic; 109 | 110 | float3 Irradiance = GIrradianceMap.SampleLevel(GSampler, N, 0.0f).rgb; 111 | float3 Diffuse = Irradiance * Albedo; 112 | float3 PrefilteredColor = GPrefilteredEnvMap.SampleLevel(GSampler, R, Roughness * 5.0f).rgb; 113 | 114 | float2 EnvBRDF = GBRDFIntegrationMap.SampleLevel(GSampler, float2(min(NoV, 0.999f), Roughness), 0.0f).rg; 115 | 116 | float3 Specular = PrefilteredColor * (F * EnvBRDF.x + EnvBRDF.y); 117 | 118 | float3 Ambient = (KD * Diffuse + Specular) * AO; 119 | 120 | float3 Color = Ambient + Lo; 121 | Color = Color / (Color + 1.0f); 122 | Color = pow(Color, 1.0f / 2.2f); 123 | 124 | OutColor = float4(Color, 1.0f); 125 | } 126 | -------------------------------------------------------------------------------- /Source/Shaders/Test.hlsl: -------------------------------------------------------------------------------- 1 | #define GRootSignature "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)" 2 | 3 | [RootSignature(GRootSignature)] 4 | void MainVS( 5 | in float3 InPosition : _Position, 6 | in float3 InNormal : _Normal, 7 | out float4 OutPosition : SV_Position) 8 | { 9 | OutPosition = float4(InPosition, 1.0f); 10 | } 11 | 12 | [RootSignature(GRootSignature)] 13 | void MainPS( 14 | in float4 InPosition : SV_Position, 15 | out float4 OutColor : SV_Target0) 16 | { 17 | OutColor = float4(0.0f, 0.6f, 0.0f, 1.0f); 18 | } 19 | -------------------------------------------------------------------------------- /Source/Shaders/UserInterface.hlsl: -------------------------------------------------------------------------------- 1 | #define GRootSignature \ 2 | "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \ 3 | "CBV(b0, visibility = SHADER_VISIBILITY_VERTEX), " \ 4 | "DescriptorTable(SRV(t0), visibility = SHADER_VISIBILITY_PIXEL), " \ 5 | "StaticSampler(s0, filter = FILTER_MIN_MAG_MIP_LINEAR, visibility = SHADER_VISIBILITY_PIXEL)" 6 | 7 | cbuffer _ : register(b0) 8 | { 9 | float4x4 GScreenToClipSpace; 10 | } 11 | 12 | Texture2D GTexture : register(t0); 13 | SamplerState GSampler : register(s0); 14 | 15 | [RootSignature(GRootSignature)] 16 | void MainVS( 17 | in float2 InPosition : _Position, 18 | in float2 InTexcoord : _Texcoords, 19 | in float4 InColor : _Color, 20 | out float4 OutPosition : SV_Position, 21 | out float2 OutTexcoord : _Texcoords, 22 | out float4 OutColor : _Color) 23 | { 24 | OutPosition = mul(float4(InPosition, 0.0f, 1.0f), GScreenToClipSpace); 25 | OutTexcoord = InTexcoord; 26 | OutColor = InColor; 27 | } 28 | 29 | [RootSignature(GRootSignature)] 30 | void MainPS( 31 | in float4 InPosition : SV_Position, 32 | in float2 InTexcoord : _Texcoords, 33 | in float4 InColor : _Color, 34 | out float4 OutColor : SV_Target0) 35 | { 36 | OutColor = InColor * GTexture.Sample(GSampler, InTexcoord); 37 | } 38 | --------------------------------------------------------------------------------