diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml
new file mode 100644
index 0000000..fe9d813
--- /dev/null
+++ b/.github/workflows/build-android.yml
@@ -0,0 +1,25 @@
+name: build android
+
+on:
+ push:
+ branches: [master]
+ pull_request:
+ branches: [master]
+
+jobs:
+ build:
+ runs-on: windows-latest
+ strategy:
+ matrix:
+ use_debug_libraries: [true, false]
+ target_arch_abi: [armeabi-v7a, arm64-v8a, x86, x86_64]
+ steps:
+ - uses: actions/checkout@main
+ with:
+ submodules: 'recursive'
+ - shell: cmd
+ run: |
+ call "%ANDROID_NDK_ROOT%\ndk-build" -C "./thirdparty/Brioche/build-android" "NDK_PROJECT_PATH:=null" "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_${{matrix.use_debug_libraries}}\obj" "NDK_LIBS_OUT:=.\debug_${{matrix.use_debug_libraries}}\lib" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+ call "%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make" -C "./build-GLSL" -f ".\GLSL.mk" "APP_DEBUG:=${{matrix.use_debug_libraries}}"
+ call "%ANDROID_NDK_ROOT%\ndk-build" -C "./build-android" "NDK_PROJECT_PATH:=null" "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_${{matrix.use_debug_libraries}}\obj" "NDK_LIBS_OUT:=.\debug_${{matrix.use_debug_libraries}}\lib" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+ call "%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make" -C "./build-android" -f ".\APK.mk" "ANDROID_SDK_DIR:=%ANDROID_SDK_ROOT%\." "JDK_DIR:=%JAVA_HOME%\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml
new file mode 100644
index 0000000..9df71b9
--- /dev/null
+++ b/.github/workflows/build-linux.yml
@@ -0,0 +1,23 @@
+name: build linux
+
+on:
+ push:
+ branches: [master]
+ pull_request:
+ branches: [master]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ use_debug_libraries: [true, false]
+ steps:
+ - uses: actions/checkout@main
+ with:
+ submodules: 'recursive'
+ - shell: bash
+ run: |
+ make -C "./thirdparty/Brioche/build-linux" -f "Linux.mk" "APP_DEBUG:=${{matrix.use_debug_libraries}}"
+ make -C "./build-GLSL" -f "GLSL.mk" "APP_DEBUG:=${{matrix.use_debug_libraries}}"
+ make -C "./build-linux" -f "Linux.mk" "APP_DEBUG:=${{matrix.use_debug_libraries}}"
diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml
new file mode 100644
index 0000000..02cc20c
--- /dev/null
+++ b/.github/workflows/build-windows.yml
@@ -0,0 +1,23 @@
+name: build windows
+
+on:
+ push:
+ branches: [master]
+ pull_request:
+ branches: [master]
+
+jobs:
+ build:
+ runs-on: windows-latest
+ strategy:
+ matrix:
+ configuration: [Debug, Release]
+ platform: [x86, x64]
+ steps:
+ - uses: actions/checkout@main
+ with:
+ submodules: 'recursive'
+ - uses: microsoft/setup-msbuild@main
+ - shell: cmd
+ run: |
+ msbuild ./build-windows/Demo-Windows.sln /p:Configuration=${{matrix.configuration}} /p:Platform=${{matrix.platform}}
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..fdd8339
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,24 @@
+[submodule "thirdparty/Brioche"]
+ path = thirdparty/Brioche
+ url = git@github.com:HanetakaChou/Brioche.git
+ branch = master
+[submodule "thirdparty/ConvertUTF"]
+ path = thirdparty/ConvertUTF
+ url = git@github.com:HanetakaChou/Import-Asset.git
+ branch = ConvertUTF
+[submodule "thirdparty/CoreRT"]
+ path = thirdparty/CoreRT
+ url = git@github.com:HanetakaChou/Import-Asset.git
+ branch = CoreRT
+[submodule "thirdparty/DirectXMath"]
+ path = thirdparty/DirectXMath
+ url = git@github.com:HanetakaChou/Import-Asset.git
+ branch = DirectXMath
+[submodule "thirdparty/ImportAsset"]
+ path = thirdparty/ImportAsset
+ url = git@github.com:HanetakaChou/Import-Asset.git
+ branch = master
+[submodule "thirdparty/DLB"]
+ path = thirdparty/DLB
+ url = git@github.com:HanetakaChou/Dual-Quaternion-Linear-Blending.git
+ branch = release
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5cc63c2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. [http://fsf.org/]
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e7f9f16
--- /dev/null
+++ b/README.md
@@ -0,0 +1,117 @@
+## glTF Viewer
+
+[![build windows](https://github.com/HanetakaChou/glTF-Viewer/actions/workflows/build-windows.yml/badge.svg)](https://github.com/HanetakaChou/glTF-Viewer/actions/workflows/build-windows.yml)
+
+[![build linux](https://github.com/HanetakaChou/glTF-Viewer/actions/workflows/build-linux.yml/badge.svg)](https://github.com/HanetakaChou/glTF-Viewer/actions/workflows/build-linux.yml)
+
+[![build android](https://github.com/HanetakaChou/glTF-Viewer/actions/workflows/build-android.yml/badge.svg)](https://github.com/HanetakaChou/glTF-Viewer/actions/workflows/build-android.yml)
+
+![](README.png)
+
+```mermaid
+graph LR
+ Demo_Scene["Demo Scene"]
+ Demo_Mesh["Demo Mesh"]
+ Demo_Mesh_Subset["Demo Mesh Subset"]
+ Demo_Mesh_Instance["Demo Mesh Instance"]
+ Demo_Mesh_Skinned_Subset["Demo Mesh Skinned Subset"]
+ Vertex_Position_Buffer["Vertex Position Buffer (e.g., Position)"]
+ Vertex_Varying_Buffer["Vertex Varying Buffer (e.g., Normal, Tangent, Texcoord)"]
+ Vertex_Joint_Buffer["Vertex Joint Buffer (e.g., Joint Indices, Joint Weights)"]
+ Index_Buffer["Index Buffer"]
+ Geometry_Material_Buffer["Geometry Material Buffer (e.g., Flags)"]
+ Material_Texture["Material Texture (e.g., Normal Texture, Emissive Texture, Base Color Texture, Material Roughness Texture)"]
+ GBuffer_Pipeline_Per_Mesh_Subset_Update_Descriptor_Set["
GBuffer Pipeline Per Mesh Subset Update Descriptor Set
Read Only Storage Buffer Vertex Position Buffer Read Only Storage Buffer Vertex Varying Buffer Read Only Storage Buffer Index Buffer Read Only Storage Buffer Geometry Material Buffer Sampled Image Material Textures
"]
+ Skin_Pipeline_Per_Mesh_Instance_Update_Uniform_Buffer["Skin Pipeline Per Mesh Instance Update Uniform Buffer (e.g., Joint Matrices)"]
+ GBuffer_Pipeline_Per_Mesh_Instance_Update_Uniform_Buffer["GBuffer Pipeline Per Mesh Instance Update Uniform Buffer (e.g., Model Transform)"]
+ Skin_Pipeline_Per_Mesh_Instance_Update_Descriptor_Set[" Skin Pipeline Per Mesh Instance Update Descriptor Set
Dynamic Uniform Buffer Skin Pipeline Per Mesh Instance Update Uniform Buffer
"]
+ GBuffer_Pipeline_Per_Mesh_Instance_Update_Descriptor_Set[" GBuffer Pipeline Per Mesh Instance Update Descriptor Set
Dynamic Uniform Buffer GBuffer Pipeline Per Mesh Instance Update Uniform Buffer
"]
+ Skinned_Vertex_Position_Buffer["Skinned Vertex Position Buffer"]
+ Skinned_Vertex_Varying_Buffer["Skinned Vertex Varying Buffer"]
+ Skin_Pipeline_Per_Mesh_Skinned_Subset_Update_Descriptor_Set[" Skin Pipeline Per Mesh Skinned Subset Update Descriptor Set
Read Only Storage Buffer Vertex Position Buffer Read Only Storage Buffer Vertex Varying Buffer Read Only Storage Buffer Vertex Joint Buffer Write Only Storage Buffer Skinned Vertex Position Buffer Write Only Storage Buffer Skinned Vertex Varying Buffer
"]
+ GBuffer_Pipeline_Per_Mesh_Skinned_Subset_Update_Descriptor_Set[" GBuffer Pipeline Per Mesh Skinned Subset Update Descriptor Set
Read Only Storage Buffer Skinned Vertex Position Buffer Read Only Storage Buffer Skinned Vertex Varying Buffer Read Only Storage Buffer Index Buffer Read Only Storage Buffer Geometry Material Buffer Sampled Image Material Textures
"]
+
+ Demo_Scene ---> |"1 ... *"| Demo_Mesh
+ Demo_Mesh ---> |"1 ... *"| Demo_Mesh_Subset
+ Demo_Mesh ---> |"1 ... *"| Demo_Mesh_Instance
+ Demo_Mesh_Instance ---> |"1 ... *"| Demo_Mesh_Skinned_Subset
+ Demo_Mesh_Skinned_Subset <---> |"1 ... 1"| Demo_Mesh_Subset
+ Demo_Mesh_Subset ---> |"1 ... 1"| Vertex_Position_Buffer
+ Demo_Mesh_Subset ---> |"1 ... 1"| Vertex_Varying_Buffer
+ Demo_Mesh_Subset ---> |"1 ... 1"| Vertex_Joint_Buffer
+ Demo_Mesh_Subset ---> |"1 ... 1"| Index_Buffer
+ Demo_Mesh_Subset ---> |"1 ... 1"| Geometry_Material_Buffer
+ Demo_Mesh_Subset ---> |"1 ... *"| Material_Texture
+ Demo_Mesh_Subset ---> |"1 ... 1"| GBuffer_Pipeline_Per_Mesh_Subset_Update_Descriptor_Set
+ Demo_Mesh_Instance ---> |"1 ... 1"| Skin_Pipeline_Per_Mesh_Instance_Update_Uniform_Buffer
+ Demo_Mesh_Instance ---> |"1 ... 1"| GBuffer_Pipeline_Per_Mesh_Instance_Update_Uniform_Buffer
+ Demo_Mesh_Instance ---> |"1 ... 1"| Skin_Pipeline_Per_Mesh_Instance_Update_Descriptor_Set
+ Demo_Mesh_Instance ---> |"1 ... 1"| GBuffer_Pipeline_Per_Mesh_Instance_Update_Descriptor_Set
+ Demo_Mesh_Skinned_Subset ---> |"1 ... 1"| Skinned_Vertex_Position_Buffer
+ Demo_Mesh_Skinned_Subset ---> |"1 ... 1"| Skinned_Vertex_Varying_Buffer
+ Demo_Mesh_Skinned_Subset ---> |"1 ... 1"| Skin_Pipeline_Per_Mesh_Skinned_Subset_Update_Descriptor_Set
+ Demo_Mesh_Skinned_Subset ---> |"1 ... 1"| GBuffer_Pipeline_Per_Mesh_Skinned_Subset_Update_Descriptor_Set
+
+ subgraph Demo_Mesh_Subset_Members["Demo Mesh Subset Members"]
+ Vertex_Position_Buffer
+ Vertex_Varying_Buffer
+ Vertex_Joint_Buffer
+ Index_Buffer
+ Geometry_Material_Buffer
+ Material_Texture
+ GBuffer_Pipeline_Per_Mesh_Subset_Update_Descriptor_Set
+ end
+
+ subgraph Demo_Mesh_Instance_Members["Demo Mesh Instance Members"]
+ Skin_Pipeline_Per_Mesh_Instance_Update_Uniform_Buffer
+ GBuffer_Pipeline_Per_Mesh_Instance_Update_Uniform_Buffer
+ Skin_Pipeline_Per_Mesh_Instance_Update_Descriptor_Set
+ GBuffer_Pipeline_Per_Mesh_Instance_Update_Descriptor_Set
+ end
+
+ subgraph Demo_Mesh_Skinned_Subset_Members["Demo Mesh Skinned Subset Members"]
+ Skinned_Vertex_Position_Buffer
+ Skinned_Vertex_Varying_Buffer
+ Skin_Pipeline_Per_Mesh_Skinned_Subset_Update_Descriptor_Set
+ GBuffer_Pipeline_Per_Mesh_Skinned_Subset_Update_Descriptor_Set
+ end
+```
+
+```mermaid
+graph TD
+ CPU_Write_Upload["CPU Write Upload"]
+ Mesh_Instance_Skin_Pipeline_Upload_Buffer["Mesh Instance Skin Pipeline Upload Buffer"]
+ Mesh_Instance_GBuffer_Pipeline_Upload_Buffer["Mesh Instance GBuffer Pipeline Upload Buffer"]
+ Mesh_Subset_Asset_Vertex_Position_Varying_Buffer["Mesh Subset Asset Vertex Position Buffer Mesh Subset Asset Vertex Varying Buffer"]
+ Mesh_Subset_Asset_Vertex_Joint_Buffer["Mesh Subset Asset Vertex Joint Buffer"]
+ Skin_Pass[" ╔ ╦ ╗ ╠ Skin Pass ╣ ╚ ╩ ╝
"]
+ Mesh_Skinned_Subset_Intermediate_Skinned_Vertex_Position_Varying_Buffer["Mesh Skinned Subset Intermediate Skinned Vertex Position Buffer Mesh Skinned Subset Intermediate Skinned Vertex Varying Buffer"]
+ Mesh_Subset_Asset_Index_Buffer["Mesh Subset Asset Index Buffer"]
+ Mesh_Subset_Asset_Geometry_Metrial_Buffer_Texture["Mesh Subset Asset Geometry Material Buffer Mesh Subset Asset Material Textures"]
+ GBuffer_Pass[" ╔ ╦ ╗ ╠ GBuffer Pass ╣ ╚ ╩ ╝
"]
+ GBuffer_Color_Attachment["GBuffer Color Attachment"]
+ GBuffer_Depth_Attachment["GBuffer Depth Attachment"]
+ Deferred_Shading_Pass[" ╔ ╦ ╗ ╠ Deferred Shading Pass ╣ ╚ ╩ ╝
"]
+ Deferred_Shading_Color_Attachment["Deferred Shading Color Attachment" ]
+ Full_Screen_Transfer_Pass["Full Screen Transfer Pass"]
+ Swap_Chain_Image["Swap Chain Image"]
+
+ CPU_Write_Upload --->|"Frame Throttling Index"| Mesh_Instance_Skin_Pipeline_Upload_Buffer
+ CPU_Write_Upload --->|"Frame Throttling Index"| Mesh_Instance_GBuffer_Pipeline_Upload_Buffer
+ Mesh_Instance_Skin_Pipeline_Upload_Buffer ---> Skin_Pass
+ Mesh_Subset_Asset_Vertex_Position_Varying_Buffer ---> Skin_Pass
+ Mesh_Subset_Asset_Vertex_Joint_Buffer ---> Skin_Pass
+ Skin_Pass --> Mesh_Skinned_Subset_Intermediate_Skinned_Vertex_Position_Varying_Buffer
+ Mesh_Instance_GBuffer_Pipeline_Upload_Buffer ---> GBuffer_Pass
+ Mesh_Subset_Asset_Vertex_Position_Varying_Buffer ---> GBuffer_Pass
+ Mesh_Skinned_Subset_Intermediate_Skinned_Vertex_Position_Varying_Buffer ---> GBuffer_Pass
+ Mesh_Subset_Asset_Index_Buffer ---> GBuffer_Pass
+ Mesh_Subset_Asset_Geometry_Metrial_Buffer_Texture ---> GBuffer_Pass
+ GBuffer_Pass ---> GBuffer_Color_Attachment
+ GBuffer_Pass ---> GBuffer_Depth_Attachment
+ GBuffer_Color_Attachment --> Deferred_Shading_Pass
+ GBuffer_Depth_Attachment --> Deferred_Shading_Pass
+ Deferred_Shading_Pass --> Deferred_Shading_Color_Attachment
+ Deferred_Shading_Color_Attachment --> Full_Screen_Transfer_Pass
+ Full_Screen_Transfer_Pass --> Swap_Chain_Image
+```
diff --git a/README.png b/README.png
new file mode 100644
index 0000000..43e1792
Binary files /dev/null and b/README.png differ
diff --git a/build-GLSL/GLSL.mk b/build-GLSL/GLSL.mk
new file mode 100644
index 0000000..e871f7e
--- /dev/null
+++ b/build-GLSL/GLSL.mk
@@ -0,0 +1,179 @@
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# ====================================================================
+#
+# Host system auto-detection.
+#
+# ====================================================================
+ifeq ($(OS),Windows_NT)
+ # On all modern variants of Windows (including Cygwin and Wine)
+ # the OS environment variable is defined to 'Windows_NT'
+ #
+ # The value of PROCESSOR_ARCHITECTURE will be x86 or AMD64
+ #
+ HOST_OS := windows
+
+ # Trying to detect that we're running from Cygwin is tricky
+ # because we can't use $(OSTYPE): It's a Bash shell variable
+ # that is not exported to sub-processes, and isn't defined by
+ # other shells (for those with really weird setups).
+ #
+ # Instead, we assume that a program named /bin/uname.exe
+ # that can be invoked and returns a valid value corresponds
+ # to a Cygwin installation.
+ #
+ UNAME := $(shell /bin/uname.exe -s 2>NUL)
+ ifneq (,$(filter CYGWIN% MINGW32% MINGW64%,$(UNAME)))
+ HOST_OS := unix
+ _ := $(shell rm -f NUL) # Cleaning up
+ endif
+else
+ HOST_OS := unix
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-mkdir
+# Arguments: 1: directory path
+# Usage : $(call host-mkdir,
+# Rationale: This function expands to the host-specific shell command used
+# to create a path if it doesn't exist.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-mkdir = md $(subst /,\,"$1") >NUL 2>NUL || rem
+else
+host-mkdir = mkdir -p $1
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-rm
+# Arguments: 1: list of files
+# Usage : $(call host-rm,)
+# Rationale: This function expands to the host-specific shell command used
+# to remove some files.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-rm = \
+ $(eval __host_rm_files := $(foreach __host_rm_file,$1,$(subst /,\,$(wildcard $(__host_rm_file)))))\
+ $(if $(__host_rm_files),del /f/q $(__host_rm_files) >NUL 2>NUL || rem)
+else
+host-rm = rm -f $1
+endif
+
+#
+# Copyright (C) YuqiaoZhang(HanetakaChou)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+#
+
+HIDE := @
+
+LOCAL_PATH := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
+SHADERS_DIR := $(LOCAL_PATH)/../shaders
+ifeq (true, $(APP_DEBUG))
+ SPIRV_DIR := $(LOCAL_PATH)/../spirv/debug
+else
+ SPIRV_DIR := $(LOCAL_PATH)/../spirv/release
+endif
+THIRD_PARTY_DIR := $(LOCAL_PATH)/../thirdparty
+ifeq ($(OS),Windows_NT)
+ GLSL_COMPILER_PATH := $(THIRD_PARTY_DIR)/Brioche/thirdparty/shaderc/bin/win32/x64/glslc.exe
+else
+ GLSL_COMPILER_PATH := $(THIRD_PARTY_DIR)/Brioche/thirdparty/shaderc/bin/linux/x64/glslc
+endif
+
+GLSL_COMPILER_FLAGS :=
+ifeq (true, $(APP_DEBUG))
+ GLSL_COMPILER_FLAGS += -g -O0
+else
+ GLSL_COMPILER_FLAGS += -O
+endif
+
+all : \
+ $(SPIRV_DIR)/_internal_full_screen_transfer_vertex.inl \
+ $(SPIRV_DIR)/_internal_full_screen_transfer_fragment.inl \
+ $(SPIRV_DIR)/_internal_skin_compute.inl \
+ $(SPIRV_DIR)/_internal_gbuffer_vertex.inl \
+ $(SPIRV_DIR)/_internal_gbuffer_fragment.inl \
+ $(SPIRV_DIR)/_internal_deferred_shading_vertex.inl \
+ $(SPIRV_DIR)/_internal_deferred_shading_fragment.inl
+
+$(SPIRV_DIR)/_internal_full_screen_transfer_vertex.inl : $(SHADERS_DIR)/support/full_screen_transfer_vertex.sl
+ $(HIDE) $(call host-mkdir,$(SPIRV_DIR))
+ $(HIDE) "$(GLSL_COMPILER_PATH)" -std=310es -mfmt=num -fshader-stage=vert $(GLSL_COMPILER_FLAGS) -MD -MF "$(SPIRV_DIR)/_internal_full_screen_transfer_vertex.d" -o "$(SPIRV_DIR)/_internal_full_screen_transfer_vertex.inl" "$(SHADERS_DIR)/support/full_screen_transfer_vertex.sl"
+
+$(SPIRV_DIR)/_internal_full_screen_transfer_fragment.inl : $(SHADERS_DIR)/support/full_screen_transfer_fragment.sl
+ $(HIDE) $(call host-mkdir,$(SPIRV_DIR))
+ $(HIDE) "$(GLSL_COMPILER_PATH)" -std=310es -mfmt=num -fshader-stage=frag $(GLSL_COMPILER_FLAGS) -MD -MF "$(SPIRV_DIR)/_internal_full_screen_transfer_fragment.d" -o "$(SPIRV_DIR)/_internal_full_screen_transfer_fragment.inl" "$(SHADERS_DIR)/support/full_screen_transfer_fragment.sl"
+
+$(SPIRV_DIR)/_internal_skin_compute.inl : $(SHADERS_DIR)/skin_compute.sl
+ $(HIDE) $(call host-mkdir,$(SPIRV_DIR))
+ $(HIDE) "$(GLSL_COMPILER_PATH)" -std=310es -mfmt=num -fshader-stage=comp $(GLSL_COMPILER_FLAGS) -MD -MF "$(SPIRV_DIR)/_internal_skin_compute.d" -o "$(SPIRV_DIR)/_internal_skin_compute.inl" "$(SHADERS_DIR)/skin_compute.sl"
+
+$(SPIRV_DIR)/_internal_gbuffer_vertex.inl : $(SHADERS_DIR)/gbuffer_vertex.sl
+ $(HIDE) $(call host-mkdir,$(SPIRV_DIR))
+ $(HIDE) "$(GLSL_COMPILER_PATH)" -std=310es -mfmt=num -fshader-stage=vert $(GLSL_COMPILER_FLAGS) -MD -MF "$(SPIRV_DIR)/_internal_gbuffer_vertex.d" -o "$(SPIRV_DIR)/_internal_gbuffer_vertex.inl" "$(SHADERS_DIR)/gbuffer_vertex.sl"
+
+$(SPIRV_DIR)/_internal_gbuffer_fragment.inl : $(SHADERS_DIR)/gbuffer_fragment.sl
+ $(HIDE) $(call host-mkdir,$(SPIRV_DIR))
+ $(HIDE) "$(GLSL_COMPILER_PATH)" -std=310es -mfmt=num -fshader-stage=frag $(GLSL_COMPILER_FLAGS) -MD -MF "$(SPIRV_DIR)/_internal_gbuffer_fragment.d" -o "$(SPIRV_DIR)/_internal_gbuffer_fragment.inl" "$(SHADERS_DIR)/gbuffer_fragment.sl"
+
+$(SPIRV_DIR)/_internal_deferred_shading_vertex.inl : $(SHADERS_DIR)/deferred_shading_vertex.sl
+ $(HIDE) $(call host-mkdir,$(SPIRV_DIR))
+ $(HIDE) "$(GLSL_COMPILER_PATH)" -std=310es -mfmt=num -fshader-stage=vert $(GLSL_COMPILER_FLAGS) -MD -MF "$(SPIRV_DIR)/_internal_deferred_shading_vertex.d" -o "$(SPIRV_DIR)/_internal_deferred_shading_vertex.inl" "$(SHADERS_DIR)/deferred_shading_vertex.sl"
+
+$(SPIRV_DIR)/_internal_deferred_shading_fragment.inl : $(SHADERS_DIR)/deferred_shading_fragment.sl
+ $(HIDE) $(call host-mkdir,$(SPIRV_DIR))
+ $(HIDE) "$(GLSL_COMPILER_PATH)" -std=310es -mfmt=num -fshader-stage=frag $(GLSL_COMPILER_FLAGS) -MD -MF "$(SPIRV_DIR)/_internal_deferred_shading_fragment.d" -o "$(SPIRV_DIR)/_internal_deferred_shading_fragment.inl" "$(SHADERS_DIR)/deferred_shading_fragment.sl"
+
+-include \
+ $(SPIRV_DIR)/_internal_full_screen_transfer_vertex.d \
+ $(SPIRV_DIR)/_internal_full_screen_transfer_fragment.d \
+ $(SPIRV_DIR)/_internal_skin_compute.d \
+ $(SPIRV_DIR)/_internal_gbuffer_vertex.d \
+ $(SPIRV_DIR)/_internal_gbuffer_fragment.d \
+ $(SPIRV_DIR)/_internal_deferred_shading_vertex.d \
+ $(SPIRV_DIR)/_internal_deferred_shading_fragment.d
+
+clean:
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_full_screen_transfer_vertex.inl)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_full_screen_transfer_fragment.inl)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_skin_compute.inl)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_gbuffer_vertex.inl)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_gbuffer_fragment.inl)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_deferred_shading_vertex.inl)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_deferred_shading_fragment.inl)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_full_screen_transfer_vertex.d)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_full_screen_transfer_fragment.d)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_skin_compute.d)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_gbuffer_vertex.d)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_gbuffer_fragment.d)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_deferred_shading_vertex.d)
+ $(HIDE) $(call host-rm,$(SPIRV_DIR)/_internal_deferred_shading_fragment.d)
+
+.PHONY : \
+ all \
+ clean
diff --git a/build-android/.gitignore b/build-android/.gitignore
new file mode 100644
index 0000000..f922774
--- /dev/null
+++ b/build-android/.gitignore
@@ -0,0 +1,11 @@
+/debug_true
+/debug_false
+/keystore
+/flat
+/apk
+
+/.vs
+/.agde
+/bin-agde
+/obj-agde
+/*.vcxproj.user
diff --git a/build-android/APK.mk b/build-android/APK.mk
new file mode 100644
index 0000000..e9f8671
--- /dev/null
+++ b/build-android/APK.mk
@@ -0,0 +1,164 @@
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# ====================================================================
+#
+# Host system auto-detection.
+#
+# ====================================================================
+ifeq ($(OS),Windows_NT)
+ # On all modern variants of Windows (including Cygwin and Wine)
+ # the OS environment variable is defined to 'Windows_NT'
+ #
+ # The value of PROCESSOR_ARCHITECTURE will be x86 or AMD64
+ #
+ HOST_OS := windows
+
+ # Trying to detect that we're running from Cygwin is tricky
+ # because we can't use $(OSTYPE): It's a Bash shell variable
+ # that is not exported to sub-processes, and isn't defined by
+ # other shells (for those with really weird setups).
+ #
+ # Instead, we assume that a program named /bin/uname.exe
+ # that can be invoked and returns a valid value corresponds
+ # to a Cygwin installation.
+ #
+ UNAME := $(shell /bin/uname.exe -s 2>NUL)
+ ifneq (,$(filter CYGWIN% MINGW32% MINGW64%,$(UNAME)))
+ HOST_OS := unix
+ _ := $(shell rm -f NUL) # Cleaning up
+ endif
+else
+ HOST_OS := unix
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-mkdir
+# Arguments: 1: directory path
+# Usage : $(call host-mkdir,
+# Rationale: This function expands to the host-specific shell command used
+# to create a path if it doesn't exist.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-mkdir = md $(subst /,\,"$1") >NUL 2>NUL || rem
+else
+host-mkdir = mkdir -p $1
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-cp
+# Arguments: 1: source file
+# 2: target file
+# Usage : $(call host-cp,,)
+# Rationale: This function expands to the host-specific shell command used
+# to copy a single file
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-cp = copy /b/y $(subst /,\,"$1" "$2") > NUL 2>NUL || rem
+else
+host-cp = cp -f $1 $2
+endif
+
+# -----------------------------------------------------------------------------
+# Function : host-rm
+# Arguments: 1: list of files
+# Usage : $(call host-rm,)
+# Rationale: This function expands to the host-specific shell command used
+# to remove some files.
+# -----------------------------------------------------------------------------
+ifeq ($(HOST_OS),windows)
+host-rm = \
+ $(eval __host_rm_files := $(foreach __host_rm_file,$1,$(subst /,\,$(wildcard $(__host_rm_file)))))\
+ $(if $(__host_rm_files),del /f/q $(__host_rm_files) >NUL 2>NUL || rem)
+else
+host-rm = rm -f $1
+endif
+
+#
+# Copyright (C) YuqiaoZhang(HanetakaChou)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+#
+
+# ANDROID_SDK_BUILD_TOOLS_VERSION := 33.0.2
+# APP_PLATFORM:=android-28
+
+HIDE := @
+
+LOCAL_PATH := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
+KEYSTORE_DIR := $(LOCAL_PATH)/keystore
+RES_DIR := $(LOCAL_PATH)/res
+FLAT_DIR := $(LOCAL_PATH)/flat
+APK_DIR := $(LOCAL_PATH)/apk
+ANDROID_JAR_PATH := $(ANDROID_SDK_DIR)/platforms/$(APP_PLATFORM)/android.jar
+ifeq ($(OS),Windows_NT)
+AAPT2_PATH := $(ANDROID_SDK_DIR)/build-tools/$(ANDROID_SDK_BUILD_TOOLS_VERSION)/aapt2.exe
+ZIPALIGN_PATH := $(ANDROID_SDK_DIR)/build-tools/$(ANDROID_SDK_BUILD_TOOLS_VERSION)/zipalign.exe
+APKSIGNER_PATH := $(ANDROID_SDK_DIR)/build-tools/$(ANDROID_SDK_BUILD_TOOLS_VERSION)/apksigner.bat
+JAR_PATH := $(JDK_DIR)/bin/jar.exe
+KEYTOOL_PATH := $(JDK_DIR)/bin/keytool.exe
+else
+AAPT2_PATH := $(ANDROID_SDK_DIR)/build-tools/$(ANDROID_SDK_BUILD_TOOLS_VERSION)/aapt2
+ZIPALIGN_PATH := $(ANDROID_SDK_DIR)/build-tools/$(ANDROID_SDK_BUILD_TOOLS_VERSION)/zipalign
+APKSIGNER_PATH := $(ANDROID_SDK_DIR)/build-tools/$(ANDROID_SDK_BUILD_TOOLS_VERSION)/apksigner
+JAR_PATH := $(JDK_DIR)/bin/jar
+KEYTOOL_PATH := $(JDK_DIR)/bin/keytool
+endif
+
+all : $(APK_DIR)/demo-android.apk
+
+$(KEYSTORE_DIR)/demo-android-debug.keystore :
+ $(HIDE) $(call host-mkdir,$(KEYSTORE_DIR))
+ $(HIDE) "$(KEYTOOL_PATH)" -genkey -v -keystore "$(KEYSTORE_DIR)/demo-android-debug.keystore" -storepass demo-android -storetype PKCS12 -keypass demo-android -alias demo-android-debug -keyalg RSA -keysize 3072 -validity 1024 -dname "CN=Demo-Android"
+
+$(FLAT_DIR)/values_styles.arsc.flat : $(RES_DIR)/values/styles.xml
+ $(HIDE) $(call host-mkdir,$(FLAT_DIR))
+ $(HIDE) "$(AAPT2_PATH)" compile -o "$(FLAT_DIR)" "$(RES_DIR)\values\styles.xml"
+
+$(APK_DIR)/demo-android-unaligned.apk : $(addprefix $(LOCAL_PATH)/debug_$(APP_DEBUG)/lib/, $(addsuffix /libNativeActivity.so, $(APP_ABI))) $(FLAT_DIR)/values_styles.arsc.flat $(LOCAL_PATH)/AndroidManifest.xml
+ $(HIDE) $(call host-mkdir,$(APK_DIR))
+ $(HIDE) "$(AAPT2_PATH)" link --debug-mode -I "$(ANDROID_JAR_PATH)" "$(FLAT_DIR)/values_styles.arsc.flat" -o "$(APK_DIR)/demo-android-unaligned.apk" --manifest "$(LOCAL_PATH)/AndroidManifest.xml"
+ $(HIDE) "$(JAR_PATH)" uf "$(APK_DIR)/demo-android-unaligned.apk" -C "$(LOCAL_PATH)/debug_$(APP_DEBUG)" lib
+
+$(APK_DIR)/demo-android-unsigned.apk : $(APK_DIR)/demo-android-unaligned.apk
+ $(HIDE) $(call host-mkdir,$(APK_DIR))
+ $(HIDE) "$(ZIPALIGN_PATH)" -f 4 "$(APK_DIR)/demo-android-unaligned.apk" "$(APK_DIR)/demo-android-unsigned.apk"
+
+$(APK_DIR)/demo-android.apk : $(KEYSTORE_DIR)/demo-android-debug.keystore $(APK_DIR)/demo-android-unsigned.apk
+ $(HIDE) $(call host-mkdir,$(APK_DIR))
+ $(HIDE) $(call host-cp,$(APK_DIR)/demo-android-unsigned.apk,$(APK_DIR)/demo-android.apk)
+ $(HIDE) "$(APKSIGNER_PATH)" sign -v --ks "$(KEYSTORE_DIR)/demo-android-debug.keystore" --ks-pass pass:demo-android -ks-key-alias demo-android-debug "$(APK_DIR)/demo-android.apk"
+
+clean:
+ $(HIDE) $(call host-rm,$(KEYSTORE_DIR)/demo-android-debug.keystore)
+ $(HIDE) $(call host-rm,$(FLAT_DIR)/values_styles.arsc.flat)
+ $(HIDE) $(call host-rm,$(APK_DIR)/demo-android-unaligned.apk)
+ $(HIDE) $(call host-rm,$(APK_DIR)/demo-android-unsigned.apk)
+ $(HIDE) $(call host-rm,$(APK_DIR)/demo-android.apk)
+
+.PHONY : \
+ all \
+ clean
\ No newline at end of file
diff --git a/build-android/Android.mk b/build-android/Android.mk
new file mode 100644
index 0000000..ffb6039
--- /dev/null
+++ b/build-android/Android.mk
@@ -0,0 +1,101 @@
+#
+# Copyright (C) YuqiaoZhang(HanetakaChou)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+#
+
+# https://developer.android.com/ndk/guides/android_mk
+
+LOCAL_PATH := $(call my-dir)
+
+# Android Application Library
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := NativeActivity
+
+LOCAL_SRC_FILES := \
+ $(LOCAL_PATH)/../source/support/camera_controller.cpp \
+ $(LOCAL_PATH)/../source/support/main.cpp \
+ $(LOCAL_PATH)/../source/support/renderer.cpp \
+ $(LOCAL_PATH)/../source/support/tick_count.cpp \
+ $(LOCAL_PATH)/../source/demo.cpp \
+ $(LOCAL_PATH)/../thirdparty/ImportAsset/source/import_asset_file_input_stream.cpp \
+ $(LOCAL_PATH)/../thirdparty/ImportAsset/source/import_asset_memory_input_stream.cpp \
+ $(LOCAL_PATH)/../thirdparty/ImportAsset/source/import_dds_image_asset.cpp \
+ $(LOCAL_PATH)/../thirdparty/ImportAsset/source/import_pvr_image_asset.cpp \
+ $(LOCAL_PATH)/../thirdparty/ImportAsset/source/import_gltf_scene_asset_cgltf.cpp \
+ $(LOCAL_PATH)/../thirdparty/ImportAsset/source/import_gltf_scene_asset.cpp \
+ $(LOCAL_PATH)/../thirdparty/ImportAsset/source/import_asset_malloc.cpp
+
+ifeq (arm, $(TARGET_ARCH))
+LOCAL_ARM_MODE := arm
+LOCAL_ARM_NEON := true
+endif
+
+LOCAL_CFLAGS :=
+# LOCAL_CFLAGS += -finput-charset=UTF-8 -fexec-charset=UTF-8
+# LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror=return-type
+LOCAL_CFLAGS += -Dbrx_init_unknown_device=brx_init_vk_device
+LOCAL_CFLAGS += -Dbrx_destroy_unknown_device=brx_destroy_vk_device
+LOCAL_CFLAGS += -DPAL_STDCPP_COMPAT=1
+
+# LOCAL_CPPFLAGS :=
+# LOCAL_CPPFLAGS += -std=c++11
+
+LOCAL_C_INCLUDES :=
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../spirv
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../thirdparty/CoreRT/src/Native/inc/unix
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../thirdparty/DirectXMath/Inc
+
+LOCAL_LDFLAGS :=
+# LOCAL_LDFLAGS += -finput-charset=UTF-8 -fexec-charset=UTF-8
+# the "dynamic linker" can't recognize the old dtags
+LOCAL_LDFLAGS += -Wl,--enable-new-dtags
+# the "chrpath" can only make path shorter
+# LOCAL_LDFLAGS += -Wl,-rpath,XORIGIN
+LOCAL_LDFLAGS += -Wl,--version-script,$(LOCAL_PATH)/libNativeActivity.map
+
+LOCAL_LDLIBS :=
+LOCAL_LDLIBS += -landroid
+
+LOCAL_SHARED_LIBRARIES :=
+LOCAL_SHARED_LIBRARIES := BRX
+
+include $(BUILD_SHARED_LIBRARY)
+
+# BRX
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := BRX
+
+LOCAL_SRC_FILES := $(LOCAL_PATH)/../thirdparty/Brioche/build-android/debug_$(APP_DEBUG)/lib/$(TARGET_ARCH_ABI)/libBRX$(TARGET_SONAME_EXTENSION)
+
+include $(PREBUILT_SHARED_LIBRARY)
+
+# VkLayer_khronos_validation
+
+ifeq (true, $(APP_DEBUG))
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VkLayer_khronos_validation
+
+LOCAL_SRC_FILES := $(LOCAL_PATH)/../thirdparty/Brioche/thirdparty/Vulkan-ValidationLayers/bin/android/$(TARGET_ARCH_ABI)/libVkLayer_khronos_validation$(TARGET_SONAME_EXTENSION)
+
+include $(PREBUILT_SHARED_LIBRARY)
+
+endif
diff --git a/build-android/AndroidManifest.xml b/build-android/AndroidManifest.xml
new file mode 100644
index 0000000..48c8d6a
--- /dev/null
+++ b/build-android/AndroidManifest.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build-android/Application.mk b/build-android/Application.mk
new file mode 100644
index 0000000..3e4399e
--- /dev/null
+++ b/build-android/Application.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (C) YuqiaoZhang(HanetakaChou)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+#
+
+# https://developer.android.com/ndk/guides/application_mk
+
+NDK_TOOLCHAIN_VERSION := clang
+# APP_ABI := x86_64 x86 arm64-v8a armeabi-v7a
+# APP_DEBUG:= true
+# APP_PLATFORM := android-28
+# APP_STL := c++_static
\ No newline at end of file
diff --git a/build-android/Demo-Android.sln b/build-android/Demo-Android.sln
new file mode 100644
index 0000000..57f9c57
--- /dev/null
+++ b/build-android/Demo-Android.sln
@@ -0,0 +1,64 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31314.256
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo-Android", "Demo-Android.vcxproj", "{2610E7F8-A7DA-4314-A677-A88E5E91432F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {719A58B7-8373-4C08-988E-A21F43E7EE23} = {719A58B7-8373-4C08-988E-A21F43E7EE23}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BRX-Android", "..\thirdparty\Brioche\build-android\BRX-Android.vcxproj", "{719A58B7-8373-4C08-988E-A21F43E7EE23}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Android-arm64-v8a = Debug|Android-arm64-v8a
+ Debug|Android-armeabi-v7a = Debug|Android-armeabi-v7a
+ Debug|Android-x86 = Debug|Android-x86
+ Debug|Android-x86_64 = Debug|Android-x86_64
+ Release|Android-arm64-v8a = Release|Android-arm64-v8a
+ Release|Android-armeabi-v7a = Release|Android-armeabi-v7a
+ Release|Android-x86 = Release|Android-x86
+ Release|Android-x86_64 = Release|Android-x86_64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Debug|Android-arm64-v8a.ActiveCfg = Debug|Android-arm64-v8a
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Debug|Android-arm64-v8a.Build.0 = Debug|Android-arm64-v8a
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Debug|Android-armeabi-v7a.ActiveCfg = Debug|Android-armeabi-v7a
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Debug|Android-armeabi-v7a.Build.0 = Debug|Android-armeabi-v7a
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Debug|Android-x86.ActiveCfg = Debug|Android-x86
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Debug|Android-x86.Build.0 = Debug|Android-x86
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Debug|Android-x86_64.ActiveCfg = Debug|Android-x86_64
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Debug|Android-x86_64.Build.0 = Debug|Android-x86_64
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Release|Android-arm64-v8a.ActiveCfg = Release|Android-arm64-v8a
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Release|Android-arm64-v8a.Build.0 = Release|Android-arm64-v8a
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Release|Android-armeabi-v7a.ActiveCfg = Release|Android-armeabi-v7a
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Release|Android-armeabi-v7a.Build.0 = Release|Android-armeabi-v7a
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Release|Android-x86.ActiveCfg = Release|Android-x86
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Release|Android-x86.Build.0 = Release|Android-x86
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Release|Android-x86_64.ActiveCfg = Release|Android-x86_64
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}.Release|Android-x86_64.Build.0 = Release|Android-x86_64
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Debug|Android-arm64-v8a.ActiveCfg = Debug|Android-arm64-v8a
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Debug|Android-arm64-v8a.Build.0 = Debug|Android-arm64-v8a
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Debug|Android-armeabi-v7a.ActiveCfg = Debug|Android-armeabi-v7a
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Debug|Android-armeabi-v7a.Build.0 = Debug|Android-armeabi-v7a
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Debug|Android-x86.ActiveCfg = Debug|Android-x86
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Debug|Android-x86.Build.0 = Debug|Android-x86
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Debug|Android-x86_64.ActiveCfg = Debug|Android-x86_64
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Debug|Android-x86_64.Build.0 = Debug|Android-x86_64
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Release|Android-arm64-v8a.ActiveCfg = Release|Android-arm64-v8a
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Release|Android-arm64-v8a.Build.0 = Release|Android-arm64-v8a
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Release|Android-armeabi-v7a.ActiveCfg = Release|Android-armeabi-v7a
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Release|Android-armeabi-v7a.Build.0 = Release|Android-armeabi-v7a
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Release|Android-x86.ActiveCfg = Release|Android-x86
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Release|Android-x86.Build.0 = Release|Android-x86
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Release|Android-x86_64.ActiveCfg = Release|Android-x86_64
+ {719A58B7-8373-4C08-988E-A21F43E7EE23}.Release|Android-x86_64.Build.0 = Release|Android-x86_64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3142C50D-495E-471E-A6B1-1E555B3ADA9B}
+ EndGlobalSection
+EndGlobal
diff --git a/build-android/Demo-Android.vcxproj b/build-android/Demo-Android.vcxproj
new file mode 100644
index 0000000..5a07ff7
--- /dev/null
+++ b/build-android/Demo-Android.vcxproj
@@ -0,0 +1,308 @@
+
+
+
+
+ Debug
+ Android-arm64-v8a
+
+
+ Debug
+ Android-armeabi-v7a
+
+
+ Debug
+ Android-x86
+
+
+ Debug
+ Android-x86_64
+
+
+ Release
+ Android-arm64-v8a
+
+
+ Release
+ Android-armeabi-v7a
+
+
+ Release
+ Android-x86
+
+
+ Release
+ Android-x86_64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 15.0
+ {2610E7F8-A7DA-4314-A677-A88E5E91432F}
+ MakeFileProj
+ Demo-Android
+ 10.0.18362.0
+
+
+
+ true
+ 25.2.9519653
+ Makefile
+
+
+ false
+ 25.2.9519653
+ Makefile
+
+
+ true
+ 25.2.9519653
+ Makefile
+
+
+ false
+ 25.2.9519653
+ Makefile
+
+
+ 25.2.9519653
+ Makefile
+
+
+ 25.2.9519653
+ Makefile
+
+
+ 25.2.9519653
+ Makefile
+
+
+ 25.2.9519653
+ Makefile
+
+
+
+
+
+
+
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static" -B
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM :=android-28" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+ $(ProjectDir)\apk\demo-android.apk
+ $(ProjectDir)\..\thirdparty\Brioche\build-android\obj\local\$(PlatformTarget);$(ProjectDir)\obj\local\$(PlatformTarget)
+ $(SolutionDir)\bin-agde\$(Platform)\$(Configuration)\
+ $(SolutionDir)\obj-agde\$(Platform)\$(Configuration)\
+
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static" -B
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM :=android-28" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+ $(ProjectDir)\apk\demo-android.apk
+ $(ProjectDir)\..\thirdparty\Brioche\build-android\obj\local\$(PlatformTarget);$(ProjectDir)\obj\local\$(PlatformTarget)
+ $(SolutionDir)\bin-agde\$(Platform)\$(Configuration)\
+ $(SolutionDir)\obj-agde\$(Platform)\$(Configuration)\
+
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static" -B
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM :=android-28" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+ $(ProjectDir)\apk\demo-android.apk
+ $(ProjectDir)\..\thirdparty\Brioche\build-android\obj\local\$(PlatformTarget);$(ProjectDir)\obj\local\$(PlatformTarget)
+ $(SolutionDir)\bin-agde\$(Platform)\$(Configuration)\
+ $(SolutionDir)\obj-agde\$(Platform)\$(Configuration)\
+
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static" -B
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM :=android-28" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+ $(ProjectDir)\apk\demo-android.apk
+ $(ProjectDir)\..\thirdparty\Brioche\build-android\obj\local\$(PlatformTarget);$(ProjectDir)\obj\local\$(PlatformTarget)
+ $(SolutionDir)\bin-agde\$(Platform)\$(Configuration)\
+ $(SolutionDir)\obj-agde\$(Platform)\$(Configuration)\
+
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static" -B
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM :=android-28" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+ $(ProjectDir)\apk\demo-android.apk
+ $(ProjectDir)\..\thirdparty\Brioche\build-android\obj\local\$(PlatformTarget);$(ProjectDir)\obj\local\$(PlatformTarget)
+ $(SolutionDir)\bin-agde\$(Platform)\$(Configuration)\
+ $(SolutionDir)\obj-agde\$(Platform)\$(Configuration)\
+
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static" -B
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM :=android-28" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+ $(ProjectDir)\apk\demo-android.apk
+ $(ProjectDir)\..\thirdparty\Brioche\build-android\obj\local\$(PlatformTarget);$(ProjectDir)\obj\local\$(PlatformTarget)
+ $(SolutionDir)\bin-agde\$(Platform)\$(Configuration)\
+ $(SolutionDir)\obj-agde\$(Platform)\$(Configuration)\
+
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static" -B
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM :=android-28" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+ $(ProjectDir)\apk\demo-android.apk
+ $(ProjectDir)\..\thirdparty\Brioche\build-android\obj\local\$(PlatformTarget);$(ProjectDir)\obj\local\$(PlatformTarget)
+ $(SolutionDir)\bin-agde\$(Platform)\$(Configuration)\
+ $(SolutionDir)\obj-agde\$(Platform)\$(Configuration)\
+
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_DEBUG:=$(UseDebugLibraries)" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM:=android-28" "APP_STL:=c++_static" -B
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" "ANDROID_SDK_DIR:=$(AndroidSdk)\." "JDK_DIR=$(AGDE_JAVA_HOME)\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+
+ call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\APK.mk" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\ndk-build" -C "$(ProjectDir)\." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_$(UseDebugLibraries)\obj" "NDK_LIBS_OUT:=.\debug_$(UseDebugLibraries)\lib" "APP_ABI:=$(PlatformTarget)" "APP_PLATFORM :=android-28" clean
+call "$(AndroidSdk)\ndk\$(AndroidNdkVersion)\prebuilt\windows-x86_64\bin\make" -C "$(ProjectDir)\." -f ".\GLSL.mk" clean
+ $(ProjectDir)\apk\demo-android.apk
+ $(ProjectDir)\..\thirdparty\Brioche\build-android\obj\local\$(PlatformTarget);$(ProjectDir)\obj\local\$(PlatformTarget)
+ $(SolutionDir)\bin-agde\$(Platform)\$(Configuration)\
+ $(SolutionDir)\obj-agde\$(Platform)\$(Configuration)\
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(CleanDependson)
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build-android/Demo-Android.vcxproj.filters b/build-android/Demo-Android.vcxproj.filters
new file mode 100644
index 0000000..5d18170
--- /dev/null
+++ b/build-android/Demo-Android.vcxproj.filters
@@ -0,0 +1,160 @@
+
+
+
+
+
+ {d3d44437-e70c-46bd-8c20-c2cd514ac0e9}
+
+
+ {34b12179-03f8-4980-bf41-3d511b13a773}
+
+
+ {736508dc-56c9-4d65-be52-be367b671481}
+
+
+ {fdeb210d-c2e5-4c62-97d5-6dffea2f65d1}
+
+
+ {b61d08d5-1eee-4c9e-ac04-30cdb0a92f1a}
+
+
+ {e04f4479-55dc-4c69-9e6c-a2db6e3fe81b}
+
+
+ {8254002f-9645-46a6-89ca-55f6c0754a01}
+
+
+
+
+ source\support
+
+
+ source\support
+
+
+ source\support
+
+
+ code
+
+
+ assets
+
+
+ assets
+
+
+ source\support
+
+
+
+
+ source\support
+
+
+ source\support
+
+
+ source\support
+
+
+ code
+
+
+ assets
+
+
+ assets
+
+
+ source\support
+
+
+
+
+ build-android
+
+
+ build-android
+
+
+ build-android
+
+
+ spirv
+
+
+ spirv
+
+
+ spirv
+
+
+ spirv
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders\support
+
+
+ shaders\support
+
+
+ shaders\support
+
+
+ build-android
+
+
+
+
+ build-android
+
+
+
\ No newline at end of file
diff --git a/build-android/build-android.cmd b/build-android/build-android.cmd
new file mode 100644
index 0000000..945b8f4
--- /dev/null
+++ b/build-android/build-android.cmd
@@ -0,0 +1,29 @@
+::
+:: Copyright (C) YuqiaoZhang(HanetakaChou)
+::
+:: This program is free software: you can redistribute it and\or modify
+:: it under the terms of the GNU Lesser General Public License as published
+:: by the Free Software Foundation, either version 3 of the License, or
+:: (at your option) any later version.
+::
+:: This program is distributed in the hope that it will be useful,
+:: but WITHOUT ANY WARRANTY; without even the implied warranty of
+:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+:: GNU Lesser General Public License for more details.
+::
+:: You should have received a copy of the GNU Lesser General Public License
+:: along with this program. If not, see .
+::
+
+@echo off
+
+:: SET ANDROID_NDK_ROOT=C:\Users\Public\Documents\android-sdk\ndk\25.2.9519653
+:: SET ANDROID_SDK_ROOT=C:\Users\Public\Documents\android-sdk
+:: SET JAVA_HOME=C:\Users\Public\Documents\jdk-17
+
+pushd %~dp0
+call "%~dp0..\thirdparty\Brioche\build-android\build-android.cmd"
+call "%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make" -C "%~dp0..\build-GLSL" -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "%ANDROID_NDK_ROOT%\ndk-build" -C "%~dp0." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_false\obj" "NDK_LIBS_OUT:=.\debug_false\lib" "APP_DEBUG:=false" "APP_ABI:=arm64-v8a armeabi-v7a x86 x86_64" "APP_PLATFORM:=android-28" "APP_STL:=c++_static"
+call "%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make" -C "%~dp0." -f ".\APK.mk" "ANDROID_SDK_DIR:=%ANDROID_SDK_ROOT%\." "JDK_DIR:=%JAVA_HOME%\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=arm64-v8a armeabi-v7a x86 x86_64" "APP_PLATFORM:=android-33"
+popd
\ No newline at end of file
diff --git a/build-android/clean-android.cmd b/build-android/clean-android.cmd
new file mode 100644
index 0000000..1ee37c1
--- /dev/null
+++ b/build-android/clean-android.cmd
@@ -0,0 +1,29 @@
+::
+:: Copyright (C) YuqiaoZhang(HanetakaChou)
+::
+:: This program is free software: you can redistribute it and\or modify
+:: it under the terms of the GNU Lesser General Public License as published
+:: by the Free Software Foundation, either version 3 of the License, or
+:: (at your option) any later version.
+::
+:: This program is distributed in the hope that it will be useful,
+:: but WITHOUT ANY WARRANTY; without even the implied warranty of
+:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+:: GNU Lesser General Public License for more details.
+::
+:: You should have received a copy of the GNU Lesser General Public License
+:: along with this program. If not, see .
+::
+
+@echo off
+
+:: SET ANDROID_NDK_ROOT=C:\Users\Public\Documents\android-sdk\ndk\25.2.9519653
+:: SET ANDROID_SDK_ROOT=C:\Users\Public\Documents\android-sdk
+:: SET JAVA_HOME=C:\Users\Public\Documents\jdk-17
+
+pushd %~dp0
+call "%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make" -C "%~dp0." -f ".\APK.mk" clean
+call "%ANDROID_NDK_ROOT%\ndk-build" -C "%~dp0." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_false\obj" "NDK_LIBS_OUT:=.\debug_false\lib" "APP_ABI:=armeabi-v7a arm64-v8a x86 x86_64" "APP_PLATFORM:=android-28" clean
+call "%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make" -C "%~dp0..\build-GLSL" -f ".\GLSL.mk" clean
+call "%~dp0..\thirdparty\Brioche\build-android\clean-android.cmd"
+popd
\ No newline at end of file
diff --git a/build-android/libNativeActivity.map b/build-android/libNativeActivity.map
new file mode 100644
index 0000000..de226bf
--- /dev/null
+++ b/build-android/libNativeActivity.map
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) YuqiaoZhang(HanetakaChou)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+{
+ global:
+ ANativeActivity_onCreate;
+ local:
+ *;
+};
\ No newline at end of file
diff --git a/build-android/rebuild-android.cmd b/build-android/rebuild-android.cmd
new file mode 100644
index 0000000..123a77e
--- /dev/null
+++ b/build-android/rebuild-android.cmd
@@ -0,0 +1,31 @@
+::
+:: Copyright (C) YuqiaoZhang(HanetakaChou)
+::
+:: This program is free software: you can redistribute it and\or modify
+:: it under the terms of the GNU Lesser General Public License as published
+:: by the Free Software Foundation, either version 3 of the License, or
+:: (at your option) any later version.
+::
+:: This program is distributed in the hope that it will be useful,
+:: but WITHOUT ANY WARRANTY; without even the implied warranty of
+:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+:: GNU Lesser General Public License for more details.
+::
+:: You should have received a copy of the GNU Lesser General Public License
+:: along with this program. If not, see .
+::
+
+@echo off
+
+:: SET ANDROID_NDK_ROOT=C:\Users\Public\Documents\android-sdk\ndk\25.2.9519653
+:: SET ANDROID_SDK_ROOT=C:\Users\Public\Documents\android-sdk
+:: SET JAVA_HOME=C:\Users\Public\Documents\jdk-17
+
+pushd %~dp0
+call "%~dp0..\thirdparty\Brioche\build-android\rebuild-android.cmd"
+call "%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make" -C "%~dp0." -f ".\APK.mk" clean
+call "%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make" -C "%~dp0." -f ".\GLSL.mk" clean
+call "%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make" -C "%~dp0." -f ".\GLSL.mk" "APP_DEBUG:=false"
+call "%ANDROID_NDK_ROOT%\ndk-build" -C "%~dp0." NDK_PROJECT_PATH:=null "NDK_APPLICATION_MK:=.\Application.mk" "APP_BUILD_SCRIPT:=.\Android.mk" "NDK_OUT:=.\debug_false\obj" "NDK_LIBS_OUT:=.\debug_false\lib" "APP_DEBUG:=false" "APP_ABI:=arm64-v8a armeabi-v7a x86 x86_64" "APP_PLATFORM:=android-28" "APP_STL:=c++_static" -B
+call "%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make" -C "%~dp0." -f ".\APK.mk" "ANDROID_SDK_DIR:=%ANDROID_SDK_ROOT%\." "JDK_DIR:=%JAVA_HOME%\." "ANDROID_SDK_BUILD_TOOLS_VERSION:=33.0.2" "APP_ABI:=${{matrix.target_arch_abi}}" "APP_DEBUG:=${{matrix.use_debug_libraries}}" "APP_PLATFORM:=android-33"
+popd
\ No newline at end of file
diff --git a/build-android/res/values/styles.xml b/build-android/res/values/styles.xml
new file mode 100644
index 0000000..afd4e15
--- /dev/null
+++ b/build-android/res/values/styles.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/build-linux/.gitignore b/build-linux/.gitignore
new file mode 100644
index 0000000..4c7473d
--- /dev/null
+++ b/build-linux/.gitignore
@@ -0,0 +1,2 @@
+/bin
+/obj
diff --git a/build-linux/Demo-Linux.map b/build-linux/Demo-Linux.map
new file mode 100644
index 0000000..2df9b7d
--- /dev/null
+++ b/build-linux/Demo-Linux.map
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) YuqiaoZhang(HanetakaChou)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+{
+ local:
+ *;
+};
\ No newline at end of file
diff --git a/build-linux/Linux.mk b/build-linux/Linux.mk
new file mode 100644
index 0000000..f1de7a6
--- /dev/null
+++ b/build-linux/Linux.mk
@@ -0,0 +1,233 @@
+#
+# Copyright (C) YuqiaoZhang(HanetakaChou)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+#
+
+HIDE := @
+
+LOCAL_PATH := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
+ifeq (true, $(APP_DEBUG))
+ BIN_DIR := $(LOCAL_PATH)/bin/debug
+ OBJ_DIR := $(LOCAL_PATH)/obj/debug
+else
+ BIN_DIR := $(LOCAL_PATH)/bin/release
+ OBJ_DIR := $(LOCAL_PATH)/obj/release
+endif
+SOURCE_DIR := $(LOCAL_PATH)/../source
+THIRD_PARTY_DIR := $(LOCAL_PATH)/../thirdparty
+
+CC := clang++
+
+C_FLAGS :=
+C_FLAGS += -Wall -Werror=return-type
+# C_FLAGS += -fvisibility=hidden
+C_FLAGS += -fPIE -fPIC
+C_FLAGS += -pthread
+ifeq (true, $(APP_DEBUG))
+ C_FLAGS += -g -O0 -UNDEBUG
+else
+ C_FLAGS += -O2 -DNDEBUG
+endif
+C_FLAGS += -Dbrx_init_unknown_device=brx_init_vk_device
+C_FLAGS += -Dbrx_destroy_unknown_device=brx_destroy_vk_device
+C_FLAGS += -I$(LOCAL_PATH)/../spirv
+C_FLAGS += -DPAL_STDCPP_COMPAT=1
+C_FLAGS += -I$(THIRD_PARTY_DIR)/CoreRT/src/Native/inc/unix
+C_FLAGS += -I$(THIRD_PARTY_DIR)/DirectXMath/Inc
+
+LD_FLAGS :=
+LD_FLAGS += -pthread
+LD_FLAGS += -Wl,--no-undefined
+LD_FLAGS += -Wl,--enable-new-dtags
+LD_FLAGS += -Wl,-rpath,'$$ORIGIN'
+ifneq (true, $(APP_DEBUG))
+ LD_FLAGS += -s
+endif
+
+all : \
+ $(BIN_DIR)/glTF-Viewer
+
+# Link
+ifeq (true, $(APP_DEBUG))
+$(BIN_DIR)/glTF-Viewer: \
+ $(OBJ_DIR)/Demo-support-camera_controller.o \
+ $(OBJ_DIR)/Demo-support-main.o \
+ $(OBJ_DIR)/Demo-support-renderer.o \
+ $(OBJ_DIR)/Demo-support-tick_count.o \
+ $(OBJ_DIR)/Demo-demo.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_file_input_stream.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_memory_input_stream.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_dds_image_asset.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_pvr_image_asset.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset_cgltf.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_malloc.o \
+ $(BIN_DIR)/libBRX.so \
+ $(BIN_DIR)/libVkLayer_khronos_validation.so \
+ $(BIN_DIR)/VkLayer_khronos_validation.json \
+ $(LOCAL_PATH)/Demo-Linux.map
+else
+$(BIN_DIR)/glTF-Viewer: \
+ $(OBJ_DIR)/Demo-support-camera_controller.o \
+ $(OBJ_DIR)/Demo-support-main.o \
+ $(OBJ_DIR)/Demo-support-renderer.o \
+ $(OBJ_DIR)/Demo-support-tick_count.o \
+ $(OBJ_DIR)/Demo-demo.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_file_input_stream.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_memory_input_stream.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_dds_image_asset.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_pvr_image_asset.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset_cgltf.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_malloc.o \
+ $(BIN_DIR)/libBRX.so \
+ $(LOCAL_PATH)/Demo-Linux.map
+endif
+ $(HIDE) mkdir -p $(BIN_DIR)
+ $(HIDE) $(CC) -pie $(LD_FLAGS) \
+ -Wl,--version-script=$(LOCAL_PATH)/Demo-Linux.map \
+ $(OBJ_DIR)/Demo-support-camera_controller.o \
+ $(OBJ_DIR)/Demo-support-main.o \
+ $(OBJ_DIR)/Demo-support-renderer.o \
+ $(OBJ_DIR)/Demo-support-tick_count.o \
+ $(OBJ_DIR)/Demo-demo.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_file_input_stream.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_memory_input_stream.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_dds_image_asset.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_pvr_image_asset.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset_cgltf.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset.o \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_malloc.o \
+ -L$(BIN_DIR) -lBRX \
+ -lxcb \
+ -o $(BIN_DIR)/glTF-Viewer
+
+# Compile
+$(OBJ_DIR)/Demo-support-camera_controller.o: $(SOURCE_DIR)/support/camera_controller.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/support/camera_controller.cpp -MD -MF $(OBJ_DIR)/Demo-support-camera_controller.d -o $(OBJ_DIR)/Demo-support-camera_controller.o
+
+$(OBJ_DIR)/Demo-support-main.o: $(SOURCE_DIR)/support/main.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/support/main.cpp -MD -MF $(OBJ_DIR)/Demo-support-main.d -o $(OBJ_DIR)/Demo-support-main.o
+
+$(OBJ_DIR)/Demo-support-renderer.o: $(SOURCE_DIR)/support/renderer.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/support/renderer.cpp -MD -MF $(OBJ_DIR)/Demo-support-renderer.d -o $(OBJ_DIR)/Demo-support-renderer.o
+
+$(OBJ_DIR)/Demo-support-tick_count.o: $(SOURCE_DIR)/support/tick_count.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/support/tick_count.cpp -MD -MF $(OBJ_DIR)/Demo-support-tick_count.d -o $(OBJ_DIR)/Demo-support-tick_count.o
+
+$(OBJ_DIR)/Demo-demo.o: $(SOURCE_DIR)/demo.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/demo.cpp -MD -MF $(OBJ_DIR)/Demo-demo.d -o $(OBJ_DIR)/Demo-demo.o
+
+$(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_file_input_stream.o: $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_asset_file_input_stream.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_asset_file_input_stream.cpp -MD -MF $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_file_input_stream.d -o $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_file_input_stream.o
+
+$(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_memory_input_stream.o: $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_asset_memory_input_stream.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_asset_memory_input_stream.cpp -MD -MF $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_memory_input_stream.d -o $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_memory_input_stream.o
+
+$(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_dds_image_asset.o: $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_dds_image_asset.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_dds_image_asset.cpp -MD -MF $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_dds_image_asset.d -o $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_dds_image_asset.o
+
+$(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_pvr_image_asset.o: $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_pvr_image_asset.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_pvr_image_asset.cpp -MD -MF $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_pvr_image_asset.d -o $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_pvr_image_asset.o
+
+$(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset_cgltf.o: $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_gltf_scene_asset_cgltf.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_gltf_scene_asset_cgltf.cpp -MD -MF $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset_cgltf.d -o $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset_cgltf.o
+
+$(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset.o: $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_gltf_scene_asset.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_gltf_scene_asset.cpp -MD -MF $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset.d -o $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset.o
+
+$(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_malloc.o: $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_asset_malloc.cpp
+ $(HIDE) mkdir -p $(OBJ_DIR)
+ $(HIDE) $(CC) -c $(C_FLAGS) $(SOURCE_DIR)/../thirdparty/ImportAsset/source/import_asset_malloc.cpp -MD -MF $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_malloc.d -o $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_malloc.o
+
+# Copy
+ifeq (true, $(APP_DEBUG))
+CONFIG_NAME := debug
+else
+CONFIG_NAME := release
+endif
+$(BIN_DIR)/libBRX.so: $(THIRD_PARTY_DIR)/Brioche/build-linux/bin/$(CONFIG_NAME)/libBRX.so
+ $(HIDE) mkdir -p $(BIN_DIR)
+ $(HIDE) cp -f $(THIRD_PARTY_DIR)/Brioche/build-linux/bin/$(CONFIG_NAME)/libBRX.so $(BIN_DIR)/libBRX.so
+
+
+$(BIN_DIR)/libVkLayer_khronos_validation.so: $(THIRD_PARTY_DIR)/Brioche/thirdparty/Vulkan-ValidationLayers/bin/linux/x64/libVkLayer_khronos_validation.so
+ $(HIDE) mkdir -p $(BIN_DIR)
+ $(HIDE) cp -f $(THIRD_PARTY_DIR)/Brioche/thirdparty/Vulkan-ValidationLayers/bin/linux/x64/libVkLayer_khronos_validation.so $(BIN_DIR)/libVkLayer_khronos_validation.so
+
+$(BIN_DIR)/VkLayer_khronos_validation.json: $(THIRD_PARTY_DIR)/Brioche/thirdparty/Vulkan-ValidationLayers/bin/linux/x64/VkLayer_khronos_validation.json
+ $(HIDE) mkdir -p $(BIN_DIR)
+ $(HIDE) cp -f $(THIRD_PARTY_DIR)/Brioche/thirdparty/Vulkan-ValidationLayers/bin/linux/x64/VkLayer_khronos_validation.json $(BIN_DIR)/VkLayer_khronos_validation.json
+
+-include \
+ $(OBJ_DIR)/Demo-support-camera_controller.d \
+ $(OBJ_DIR)/Demo-support-main.d \
+ $(OBJ_DIR)/Demo-support-renderer.d \
+ $(OBJ_DIR)/Demo-support-tick_count.d \
+ $(OBJ_DIR)/Demo-demo.d \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_file_input_stream.d \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_memory_input_stream.d \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_dds_image_asset.d \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_pvr_image_asset.d \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset_cgltf.d \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset.d \
+ $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_malloc.d
+
+clean:
+ $(HIDE) rm -f $(BIN_DIR)/glTF-Viewer
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-support-camera_controller.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-support-main.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-support-renderer.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-support-tick_count.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-demo.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_file_input_stream.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_memory_input_stream.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_dds_image_asset.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_pvr_image_asset.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset_cgltf.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_malloc.o
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-support-camera_controller.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-support-main.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-support-renderer.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-support-tick_count.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-demo.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_file_input_stream.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_memory_input_stream.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_dds_image_asset.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_pvr_image_asset.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset_cgltf.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_gltf_scene_asset.d
+ $(HIDE) rm -f $(OBJ_DIR)/Demo-thirdparty-ImportAsset-import_asset_malloc.d
+ $(HIDE) rm -f $(BIN_DIR)/libBRX.so
+ifeq (true, $(APP_DEBUG))
+ $(HIDE) rm -f $(BIN_DIR)/libVkLayer_khronos_validation.so
+ $(HIDE) rm -f $(BIN_DIR)/VkLayer_khronos_validation.json
+endif
+
+.PHONY : \
+ all \
+ clean
\ No newline at end of file
diff --git a/build-windows/.gitignore b/build-windows/.gitignore
new file mode 100644
index 0000000..b9884c6
--- /dev/null
+++ b/build-windows/.gitignore
@@ -0,0 +1,4 @@
+/.vs
+/bin
+/obj
+/*.vcxproj.user
diff --git a/build-windows/Demo-Windows-D3D12.vcxproj b/build-windows/Demo-Windows-D3D12.vcxproj
new file mode 100644
index 0000000..c24a641
--- /dev/null
+++ b/build-windows/Demo-Windows-D3D12.vcxproj
@@ -0,0 +1,313 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Document
+ Pixel
+ Pixel
+ Pixel
+ Pixel
+
+
+ Document
+ Vertex
+ Vertex
+ Vertex
+ Vertex
+
+
+ Document
+ Pixel
+ Pixel
+ Pixel
+ Pixel
+
+
+
+
+
+ Document
+ Vertex
+ Vertex
+ Vertex
+ Vertex
+
+
+
+
+
+ Document
+ Pixel
+ Pixel
+ Pixel
+ Pixel
+
+
+ Document
+ Compute
+ Compute
+ Compute
+ Compute
+
+
+
+
+ Document
+ Vertex
+ Vertex
+ Vertex
+ Vertex
+
+
+
+
+
+
+
+
+ {78fae1fa-0a6a-4408-9285-030a876b0649}
+
+
+
+ 15.0
+ {8515DB3F-23BB-424F-A356-2967FF78E83E}
+ Win32Proj
+ Demo-Windows-D3D12
+ 10.0
+ Demo-Windows-D3D12
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ glTF-Viewer-D3D12
+
+
+ true
+ $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ glTF-Viewer-D3D12
+
+
+ true
+ $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ glTF-Viewer-D3D12
+
+
+ false
+ $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ glTF-Viewer-D3D12
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ brx_init_unknown_device=brx_init_d3d12_device;brx_destroy_unknown_device=brx_destroy_d3d12_device;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)
+ ..\dxbc;
+
+
+ true
+ true
+ true
+ Windows
+ wmainCRTStartup
+ comdlg32.lib;%(AdditionalDependencies)
+
+
+ 5.1
+ $(SolutionDir)\..\dxbc\$(Configuration)\_internal_%(Filename).inl
+
+ %(Filename)_shader_module_code
+
+
+
+
+ Level3
+ Disabled
+ true
+ brx_init_unknown_device=brx_init_d3d12_device;brx_destroy_unknown_device=brx_destroy_d3d12_device;_WINDOWS;_DEBUG;WIN32;%(PreprocessorDefinitions)
+ ProgramDatabase
+ ..\dxbc;
+
+
+ true
+ Windows
+
+
+
+
+ 209715200
+ 104857600
+ wmainCRTStartup
+ comdlg32.lib;%(AdditionalDependencies)
+
+
+ 5.1
+ $(SolutionDir)\..\dxbc\$(Configuration)\_internal_%(Filename).inl
+
+ %(Filename)_shader_module_code
+
+
+
+
+ Level3
+ Disabled
+ true
+ brx_init_unknown_device=brx_init_d3d12_device;brx_destroy_unknown_device=brx_destroy_d3d12_device;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)
+ ProgramDatabase
+ ..\dxbc;
+
+
+ true
+ Windows
+
+
+
+
+ wmainCRTStartup
+ comdlg32.lib;%(AdditionalDependencies)
+
+
+ 5.1
+ $(SolutionDir)\..\dxbc\$(Configuration)\_internal_%(Filename).inl
+
+ %(Filename)_shader_module_code
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ brx_init_unknown_device=brx_init_d3d12_device;brx_destroy_unknown_device=brx_destroy_d3d12_device;_WINDOWS;NDEBUG;WIN32;%(PreprocessorDefinitions)
+ ..\dxbc;
+
+
+ true
+ true
+ true
+ Windows
+ wmainCRTStartup
+ comdlg32.lib;%(AdditionalDependencies)
+
+
+ 5.1
+ $(SolutionDir)\..\dxbc\$(Configuration)\_internal_%(Filename).inl
+
+ %(Filename)_shader_module_code
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build-windows/Demo-Windows-D3D12.vcxproj.filters b/build-windows/Demo-Windows-D3D12.vcxproj.filters
new file mode 100644
index 0000000..97a6941
--- /dev/null
+++ b/build-windows/Demo-Windows-D3D12.vcxproj.filters
@@ -0,0 +1,220 @@
+
+
+
+
+ {6564cc1a-1902-4833-bf99-8a3fd8b5f6fb}
+
+
+ {0fdd0fa4-cdf6-47e5-9605-a438eac8a7bf}
+
+
+ {4ea7a279-3984-44fb-905e-7243713ff6d4}
+
+
+ {6b62e300-cff7-473b-81b7-b9828e035938}
+
+
+ {1395e396-5ae8-4bc3-87ac-db1a12e3c0db}
+
+
+ {baf2d192-809f-42f3-87ef-cc9338cc67e4}
+
+
+ {878cdbd0-309f-49fe-bec5-bf64a8ea8c95}
+
+
+ {588679ab-dc7d-4f65-8caf-0737dc99ecf4}
+
+
+ {898b0181-2305-475e-b862-b329b30e9416}
+
+
+ {f2a3a172-54d9-4c6d-8db2-64846e2fdbcb}
+
+
+ {bd6f1366-4849-4592-be66-d8fcc6590719}
+
+
+ {c3721dee-ffe8-4532-acfd-9cb41ad2f05a}
+
+
+ {aed9a659-d031-462c-b818-300863bb5b10}
+
+
+ {0a103360-b15d-49fc-87a4-e8d83c7bccfd}
+
+
+
+
+ source
+
+
+ source\support
+
+
+ source\support
+
+
+ source\support
+
+
+ source\support
+
+
+ thirdparty\ConvertUTF\source
+
+
+ thirdparty\ConvertUTF\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+
+
+ source
+
+
+ source\support
+
+
+ source\support
+
+
+ source\support
+
+
+ source\support
+
+
+ thirdparty\ConvertUTF\include
+
+
+ thirdparty\ImportAsset\include
+
+
+ thirdparty\ImportAsset\include
+
+
+ thirdparty\ImportAsset\include
+
+
+ thirdparty\DLB
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+
+
+ dxbc
+
+
+ dxbc
+
+
+ dxbc
+
+
+ shaders
+
+
+ shaders
+
+
+ dxbc
+
+
+ shaders
+
+
+ dxbc
+
+
+ shaders\support
+
+
+ shaders
+
+
+ dxbc
+
+
+ shaders
+
+
+ shaders
+
+
+ thirdparty\ImportAsset\shaders
+
+
+ thirdparty\ImportAsset\shaders
+
+
+ dxbc
+
+
+ thirdparty\DLB
+
+
+ thirdparty\DLB
+
+
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders\support
+
+
+ shaders\support
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+
\ No newline at end of file
diff --git a/build-windows/Demo-Windows-VK.vcxproj b/build-windows/Demo-Windows-VK.vcxproj
new file mode 100644
index 0000000..f72ba2d
--- /dev/null
+++ b/build-windows/Demo-Windows-VK.vcxproj
@@ -0,0 +1,395 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Document
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -O -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -O -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\support\full_screen_transfer_pipeline_layout.sli
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\support\full_screen_transfer_pipeline_layout.sli
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\support\full_screen_transfer_pipeline_layout.sli
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\support\full_screen_transfer_pipeline_layout.sli
+
+
+ Document
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -O -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -O -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\support\full_screen_transfer_pipeline_layout.sli
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\support\full_screen_transfer_pipeline_layout.sli
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\support\full_screen_transfer_pipeline_layout.sli
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\support\full_screen_transfer_pipeline_layout.sli
+
+
+
+
+
+
+ Document
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ Compile GLSL %(Filename)
+ Compile GLSL %(Filename)
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\deferred_shading_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\deferred_shading_pipeline_resource_binding.sli
+ Compile GLSL %(Filename)
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\deferred_shading_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\deferred_shading_pipeline_resource_binding.sli
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+
+
+
+ Document
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\deferred_shading_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\deferred_shading_pipeline_resource_binding.sli
+ Compile GLSL %(Filename)
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\deferred_shading_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\deferred_shading_pipeline_resource_binding.sli
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+
+
+ Document
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ Compile GLSL %(Filename)
+ Compile GLSL %(Filename)
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\gbuffer_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\gbuffer_pipeline_resource_binding.sli
+ Compile GLSL %(Filename)
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\gbuffer_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\gbuffer_pipeline_resource_binding.sli
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=frag -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+
+
+
+ Document
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\gbuffer_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\gbuffer_pipeline_resource_binding.sli
+ Compile GLSL %(Filename)
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\gbuffer_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\gbuffer_pipeline_resource_binding.sli
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=vert -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+
+
+
+ Document
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=comp -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=comp -g -O0 -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=comp -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ "$(SolutionDir)..\thirdparty\Brioche\thirdparty\shaderc\bin\win32\x64\glslc.exe" -std=310es -mfmt=num -fshader-stage=comp -o "$(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl" "%(FullPath)"
+ Compile GLSL %(Filename)
+ Compile GLSL %(Filename)
+ Compile GLSL %(Filename)
+ Compile GLSL %(Filename)
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)\..\spirv\$(Configuration)\_internal_%(Filename).inl
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\skin_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\skin_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\skin_pipeline_resource_binding.sli
+ $(SolutionDir)..\thirdparty\Brioche\shaders\brx_define.sli;$(SolutionDir)..\shaders\skin_pipeline_resource_binding.sli
+
+
+
+
+ Document
+ true
+ true
+
+
+ Document
+ true
+ true
+
+
+ Document
+ true
+ true
+
+
+ Document
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {78fae1fa-0a6a-4408-9285-030a876b0649}
+
+
+
+ 15.0
+ {00ACFB22-3872-4380-BA9D-E1DD24888EF4}
+ Win32Proj
+ Demo-Windows-VK
+ 10.0
+ Demo-Windows-VK
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ glTF-Viewer-VK
+
+
+ true
+ $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ glTF-Viewer-VK
+
+
+ true
+ $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ glTF-Viewer-VK
+
+
+ false
+ $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\
+ $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ glTF-Viewer-VK
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ brx_init_unknown_device=brx_init_vk_device;brx_destroy_unknown_device=brx_destroy_vk_device;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)
+ ..\spirv;
+
+
+ true
+ true
+ true
+ Windows
+ wmainCRTStartup
+ comdlg32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ Disabled
+ true
+ brx_init_unknown_device=brx_init_vk_device;brx_destroy_unknown_device=brx_destroy_vk_device;_WINDOWS;_DEBUG;WIN32;%(PreprocessorDefinitions)
+ ProgramDatabase
+ ..\spirv;
+
+
+ true
+ Windows
+
+
+
+
+ 209715200
+ 104857600
+ wmainCRTStartup
+ comdlg32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ Disabled
+ true
+ brx_init_unknown_device=brx_init_vk_device;brx_destroy_unknown_device=brx_destroy_vk_device;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)
+ ProgramDatabase
+ ..\spirv;
+
+
+ true
+ Windows
+
+
+
+
+ wmainCRTStartup
+ comdlg32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ brx_init_unknown_device=brx_init_vk_device;brx_destroy_unknown_device=brx_destroy_vk_device;_WINDOWS;NDEBUG;WIN32;%(PreprocessorDefinitions)
+ ..\spirv;
+
+
+ true
+ true
+ true
+ Windows
+ wmainCRTStartup
+ comdlg32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build-windows/Demo-Windows-VK.vcxproj.filters b/build-windows/Demo-Windows-VK.vcxproj.filters
new file mode 100644
index 0000000..844128b
--- /dev/null
+++ b/build-windows/Demo-Windows-VK.vcxproj.filters
@@ -0,0 +1,243 @@
+
+
+
+
+ source
+
+
+ source\support
+
+
+ source\support
+
+
+ source\support
+
+
+ source\support
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ConvertUTF\source
+
+
+ thirdparty\ConvertUTF\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+
+
+ source
+
+
+ source\support
+
+
+ source\support
+
+
+ source\support
+
+
+ source\support
+
+
+ thirdparty\ImportAsset\include
+
+
+ thirdparty\ImportAsset\include
+
+
+ thirdparty\ConvertUTF\include
+
+
+ thirdparty\ImportAsset\include
+
+
+ thirdparty\DLB
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+ thirdparty\ImportAsset\source
+
+
+
+
+ shaders\support
+
+
+ shaders\support
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+
+
+ thirdparty\Vulkan-ValidationLayers\x86
+
+
+ thirdparty\Vulkan-ValidationLayers\x86
+
+
+ thirdparty\Vulkan-ValidationLayers\x64
+
+
+ thirdparty\Vulkan-ValidationLayers\x64
+
+
+
+
+ spirv
+
+
+ spirv
+
+
+ shaders\support
+
+
+ spirv
+
+
+ spirv
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ shaders
+
+
+ spirv
+
+
+ spirv
+
+
+ shaders
+
+
+ shaders
+
+
+ thirdparty\ImportAsset\shaders
+
+
+ thirdparty\ImportAsset\shaders
+
+
+ spirv
+
+
+ thirdparty\DLB
+
+
+ thirdparty\DLB
+
+
+
+
+ {5ef8ee9f-5a80-48bd-82a4-0cec12b21719}
+
+
+ {f6b3b0f4-57bb-4f0f-b3c1-af7cb367457c}
+
+
+ {3fd46330-fb50-48b9-9af8-f2bd1292021a}
+
+
+ {0a393837-6c85-4124-89a5-28e5ae120ec4}
+
+
+ {8392cec9-8a4b-4f55-939a-fda75c196bb8}
+
+
+ {20e5e431-be5d-49a8-9c62-4973be7abee1}
+
+
+ {9a26aaf8-9e1c-45da-a6dc-54788eb50266}
+
+
+ {59f24b2c-072f-4fca-91b0-b70b46bd4124}
+
+
+ {acd6da07-575e-4359-9d68-a0998b90dd02}
+
+
+ {c65442bb-15e9-4bfc-bc0c-4c74edddd1f5}
+
+
+ {f090f88f-683a-427f-9207-32271dc25c91}
+
+
+ {4d5eedcd-4e13-4bfb-826d-97363f91be3e}
+
+
+ {7538861b-f7f1-439f-9192-ca28dbf261ad}
+
+
+ {b5d88abe-d344-44b6-9031-e70cc4549238}
+
+
+ {a65309de-7b7b-4e93-9b1d-5a4c03e6a9b9}
+
+
+ {a4b3dcc9-f61b-4648-9680-5f42eb48ade0}
+
+
+ {87c8f33e-e008-4862-9dcd-f4325a3c1c68}
+
+
+
\ No newline at end of file
diff --git a/build-windows/Demo-Windows.sln b/build-windows/Demo-Windows.sln
new file mode 100644
index 0000000..47573a9
--- /dev/null
+++ b/build-windows/Demo-Windows.sln
@@ -0,0 +1,51 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31314.256
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo-Windows-VK", "Demo-Windows-VK.vcxproj", "{00ACFB22-3872-4380-BA9D-E1DD24888EF4}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BRX-Windows", "..\thirdparty\Brioche\build-windows\BRX-Windows.vcxproj", "{78FAE1FA-0A6A-4408-9285-030A876B0649}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo-Windows-D3D12", "Demo-Windows-D3D12.vcxproj", "{8515DB3F-23BB-424F-A356-2967FF78E83E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {00ACFB22-3872-4380-BA9D-E1DD24888EF4}.Debug|x64.ActiveCfg = Debug|x64
+ {00ACFB22-3872-4380-BA9D-E1DD24888EF4}.Debug|x64.Build.0 = Debug|x64
+ {00ACFB22-3872-4380-BA9D-E1DD24888EF4}.Debug|x86.ActiveCfg = Debug|Win32
+ {00ACFB22-3872-4380-BA9D-E1DD24888EF4}.Debug|x86.Build.0 = Debug|Win32
+ {00ACFB22-3872-4380-BA9D-E1DD24888EF4}.Release|x64.ActiveCfg = Release|x64
+ {00ACFB22-3872-4380-BA9D-E1DD24888EF4}.Release|x64.Build.0 = Release|x64
+ {00ACFB22-3872-4380-BA9D-E1DD24888EF4}.Release|x86.ActiveCfg = Release|Win32
+ {00ACFB22-3872-4380-BA9D-E1DD24888EF4}.Release|x86.Build.0 = Release|Win32
+ {78FAE1FA-0A6A-4408-9285-030A876B0649}.Debug|x64.ActiveCfg = Debug|x64
+ {78FAE1FA-0A6A-4408-9285-030A876B0649}.Debug|x64.Build.0 = Debug|x64
+ {78FAE1FA-0A6A-4408-9285-030A876B0649}.Debug|x86.ActiveCfg = Debug|Win32
+ {78FAE1FA-0A6A-4408-9285-030A876B0649}.Debug|x86.Build.0 = Debug|Win32
+ {78FAE1FA-0A6A-4408-9285-030A876B0649}.Release|x64.ActiveCfg = Release|x64
+ {78FAE1FA-0A6A-4408-9285-030A876B0649}.Release|x64.Build.0 = Release|x64
+ {78FAE1FA-0A6A-4408-9285-030A876B0649}.Release|x86.ActiveCfg = Release|Win32
+ {78FAE1FA-0A6A-4408-9285-030A876B0649}.Release|x86.Build.0 = Release|Win32
+ {8515DB3F-23BB-424F-A356-2967FF78E83E}.Debug|x64.ActiveCfg = Debug|x64
+ {8515DB3F-23BB-424F-A356-2967FF78E83E}.Debug|x64.Build.0 = Debug|x64
+ {8515DB3F-23BB-424F-A356-2967FF78E83E}.Debug|x86.ActiveCfg = Debug|Win32
+ {8515DB3F-23BB-424F-A356-2967FF78E83E}.Debug|x86.Build.0 = Debug|Win32
+ {8515DB3F-23BB-424F-A356-2967FF78E83E}.Release|x64.ActiveCfg = Release|x64
+ {8515DB3F-23BB-424F-A356-2967FF78E83E}.Release|x64.Build.0 = Release|x64
+ {8515DB3F-23BB-424F-A356-2967FF78E83E}.Release|x86.ActiveCfg = Release|Win32
+ {8515DB3F-23BB-424F-A356-2967FF78E83E}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C128871C-DA37-4E4F-A583-4089B7086626}
+ EndGlobalSection
+EndGlobal
diff --git a/dxbc/.gitignore b/dxbc/.gitignore
new file mode 100644
index 0000000..70a618f
--- /dev/null
+++ b/dxbc/.gitignore
@@ -0,0 +1,2 @@
+/debug
+/release
diff --git a/dxbc/deferred_shading_fragment.inl b/dxbc/deferred_shading_fragment.inl
new file mode 100644
index 0000000..4978085
--- /dev/null
+++ b/dxbc/deferred_shading_fragment.inl
@@ -0,0 +1,7 @@
+#define BYTE uint8_t
+#ifndef NDEBUG
+#include "debug/_internal_deferred_shading_fragment.inl"
+#else
+#include "release/_internal_deferred_shading_fragment.inl"
+#endif
+#undef BYTE
\ No newline at end of file
diff --git a/dxbc/deferred_shading_vertex.inl b/dxbc/deferred_shading_vertex.inl
new file mode 100644
index 0000000..2b940aa
--- /dev/null
+++ b/dxbc/deferred_shading_vertex.inl
@@ -0,0 +1,7 @@
+#define BYTE uint8_t
+#ifndef NDEBUG
+#include "debug/_internal_deferred_shading_vertex.inl"
+#else
+#include "release/_internal_deferred_shading_vertex.inl"
+#endif
+#undef BYTE
\ No newline at end of file
diff --git a/dxbc/full_screen_transfer_fragment.inl b/dxbc/full_screen_transfer_fragment.inl
new file mode 100644
index 0000000..5d58653
--- /dev/null
+++ b/dxbc/full_screen_transfer_fragment.inl
@@ -0,0 +1,7 @@
+#define BYTE uint8_t
+#ifndef NDEBUG
+#include "debug/_internal_full_screen_transfer_fragment.inl"
+#else
+#include "release/_internal_full_screen_transfer_fragment.inl"
+#endif
+#undef BYTE
\ No newline at end of file
diff --git a/dxbc/full_screen_transfer_vertex.inl b/dxbc/full_screen_transfer_vertex.inl
new file mode 100644
index 0000000..91ddedb
--- /dev/null
+++ b/dxbc/full_screen_transfer_vertex.inl
@@ -0,0 +1,7 @@
+#define BYTE uint8_t
+#ifndef NDEBUG
+#include "debug/_internal_full_screen_transfer_vertex.inl"
+#else
+#include "release/_internal_full_screen_transfer_vertex.inl"
+#endif
+#undef BYTE
\ No newline at end of file
diff --git a/dxbc/gbuffer_fragment.inl b/dxbc/gbuffer_fragment.inl
new file mode 100644
index 0000000..6605c51
--- /dev/null
+++ b/dxbc/gbuffer_fragment.inl
@@ -0,0 +1,7 @@
+#define BYTE uint8_t
+#ifndef NDEBUG
+#include "debug/_internal_gbuffer_fragment.inl"
+#else
+#include "release/_internal_gbuffer_fragment.inl"
+#endif
+#undef BYTE
\ No newline at end of file
diff --git a/dxbc/gbuffer_vertex.inl b/dxbc/gbuffer_vertex.inl
new file mode 100644
index 0000000..dd32572
--- /dev/null
+++ b/dxbc/gbuffer_vertex.inl
@@ -0,0 +1,7 @@
+#define BYTE uint8_t
+#ifndef NDEBUG
+#include "debug/_internal_gbuffer_vertex.inl"
+#else
+#include "release/_internal_gbuffer_vertex.inl"
+#endif
+#undef BYTE
\ No newline at end of file
diff --git a/dxbc/skin_compute.inl b/dxbc/skin_compute.inl
new file mode 100644
index 0000000..b5954de
--- /dev/null
+++ b/dxbc/skin_compute.inl
@@ -0,0 +1,7 @@
+#define BYTE uint8_t
+#ifndef NDEBUG
+#include "debug/_internal_skin_compute.inl"
+#else
+#include "release/_internal_skin_compute.inl"
+#endif
+#undef BYTE
\ No newline at end of file
diff --git a/shaders/common_constant.sli b/shaders/common_constant.sli
new file mode 100644
index 0000000..d01bf1f
--- /dev/null
+++ b/shaders/common_constant.sli
@@ -0,0 +1,38 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _COMMON_CONSTANT_SLI_
+#define _COMMON_CONSTANT_SLI_ 1
+
+#define g_vertex_position_buffer_stride 12u
+#define g_vertex_varying_buffer_stride 12u
+#define g_vertex_joint_buffer_stride 12u
+#define g_index_uint16_buffer_stride 2u
+#define g_index_uint32_buffer_stride 4u
+
+#if defined(__cplusplus)
+static_assert((sizeof(scene_mesh_vertex_position_binding)) == g_vertex_position_buffer_stride, "");
+static_assert(0U == (g_vertex_position_buffer_stride % 4U), "");
+static_assert((sizeof(scene_mesh_vertex_varying_binding)) == g_vertex_varying_buffer_stride, "");
+static_assert(0U == (g_vertex_varying_buffer_stride % 4U), "");
+static_assert((sizeof(scene_mesh_vertex_joint_binding)) == g_vertex_joint_buffer_stride, "");
+static_assert(0U == (g_vertex_joint_buffer_stride % 4U), "");
+static_assert((sizeof(uint16_t)) == g_index_uint16_buffer_stride, "");
+static_assert((sizeof(uint32_t)) == g_index_uint32_buffer_stride, "");
+#endif
+
+#endif
\ No newline at end of file
diff --git a/shaders/common_resource_binding.sli b/shaders/common_resource_binding.sli
new file mode 100644
index 0000000..114c4b1
--- /dev/null
+++ b/shaders/common_resource_binding.sli
@@ -0,0 +1,36 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _COMMON_RESOURCE_BINDING_SLI_
+#define _COMMON_RESOURCE_BINDING_SLI_ 1
+
+#include "../thirdparty/Brioche/shaders/brx_define.sli"
+
+brx_cbuffer(common_none_update_set_uniform_buffer_binding, 0, 0)
+{
+ brx_column_major brx_float4x4 g_view_transform;
+ brx_column_major brx_float4x4 g_projection_transform;
+ brx_column_major brx_float4x4 g_inverse_view_transform;
+ brx_column_major brx_float4x4 g_inverse_projection_transform;
+
+ brx_float g_screen_width;
+ brx_float g_screen_height;
+ brx_float _unused_padding_1;
+ brx_float _unused_padding_2;
+};
+
+#endif
\ No newline at end of file
diff --git a/shaders/deferred_shading_fragment.sl b/shaders/deferred_shading_fragment.sl
new file mode 100644
index 0000000..73ce954
--- /dev/null
+++ b/shaders/deferred_shading_fragment.sl
@@ -0,0 +1,180 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include "deferred_shading_pipeline_resource_binding.sli"
+#include "../thirdparty/ImportAsset/shaders/packed_vector.sli"
+#include "../thirdparty/ImportAsset/shaders/octahedron_mapping.sli"
+#include "math_constant.sli"
+
+#define INVALID_GBUFFER_DEPTH 0.0
+
+brx_root_signature(deferred_shading_root_signature_macro, deferred_shading_root_signature_name)
+brx_early_depth_stencil
+brx_pixel_shader_parameter_begin(main)
+brx_pixel_shader_parameter_in_frag_coord brx_pixel_shader_parameter_split
+brx_pixel_shader_parameter_out(brx_float4, out_color, 0)
+brx_pixel_shader_parameter_end(main)
+{
+ // TODO: single pass deferred shading
+
+ brx_float depth = brx_load_2d(g_depth_texture[0], brx_int3(brx_frag_coord.xy, 0)).x;
+
+ brx_branch
+ if (INVALID_GBUFFER_DEPTH == depth)
+ {
+ out_color = brx_float4(0.0, 0.0, 0.0, 1.0);
+ return;
+ }
+
+ brx_uint4 gbuffer = brx_load_2d(g_gbuffer_texture[0], brx_int3(brx_frag_coord.xy, 0));
+
+ brx_float3 shading_normal_world_space = octahedron_unmap(R16G16_SNORM_to_FLOAT2(gbuffer.x));
+ brx_float3 base_color = R10G10B10A2_UNORM_to_FLOAT4(gbuffer.y).xyz;
+ brx_float2 metallic_roughness = R16G16_UNORM_to_FLOAT2(gbuffer.z);
+ brx_float metallic = metallic_roughness.x;
+ brx_float roughness = metallic_roughness.y;
+ brx_float3 emissive = R10G10B10A2_UNORM_to_FLOAT4(gbuffer.w).xyz;
+
+ const brx_float dielectric_specular = 0.04;
+ // UE4: https://github.com/EpicGames/UnrealEngine/blob/4.21/Engine/Shaders/Private/MobileBasePassPixelShader.usf#L376
+ brx_float3 f0 = brx_clamp((dielectric_specular - dielectric_specular * metallic) + base_color * metallic, 0.0, 1.0);
+ brx_float3 albedo = brx_clamp(base_color - base_color * metallic, 0.0, 1.0);
+
+ brx_float3 surface_position_world_space;
+ {
+ brx_float2 uv = brx_frag_coord.xy / brx_float2(g_screen_width, g_screen_height);
+
+ brx_float surface_position_depth = depth;
+
+ brx_float3 surface_position_ndc_space = brx_float3(uv * brx_float2(2.0, -2.0) + brx_float2(-1.0, 1.0), surface_position_depth);
+
+ brx_float4 surface_position_view_space_with_w = brx_mul(g_inverse_projection_transform, brx_float4(surface_position_ndc_space, 1.0));
+
+ brx_float3 surface_position_view_space = surface_position_view_space_with_w.xyz / surface_position_view_space_with_w.w;
+
+ surface_position_world_space = brx_mul(g_inverse_view_transform, brx_float4(surface_position_view_space, 1.0)).xyz;
+ }
+
+ brx_float3 camera_ray_origin = brx_mul(g_inverse_view_transform, brx_float4(0.0, 0.0, 0.0, 1.0)).xyz;
+
+ // TODO: shadow
+ // TODO: environment lighting
+ brx_float3 outgoing_radiance = brx_float3(0.0, 0.0, 0.0);
+
+ const brx_int incident_light_count = 8;
+
+ const brx_float3 incident_illuminances[incident_light_count] = brx_array_constructor_begin(brx_float3, incident_light_count)
+ brx_float3(0.7, 0.7, 0.7) brx_array_constructor_split
+ brx_float3(0.7, 0.7, 0.7) brx_array_constructor_split
+ brx_float3(0.7, 0.7, 0.7) brx_array_constructor_split
+ brx_float3(0.7, 0.7, 0.7) brx_array_constructor_split
+ brx_float3(0.3, 0.3, 0.3) brx_array_constructor_split
+ brx_float3(0.3, 0.3, 0.3) brx_array_constructor_split
+ brx_float3(0.3, 0.3, 0.3) brx_array_constructor_split
+ brx_float3(0.3, 0.3, 0.3)
+ brx_array_constructor_end;
+
+ const brx_float3 Ls[incident_light_count] = brx_array_constructor_begin(brx_float3, incident_light_count)
+ brx_float3( 1.0, 1.0, 1.0) brx_array_constructor_split
+ brx_float3( 1.0, 1.0, -1.0) brx_array_constructor_split
+ brx_float3(-1.0, 1.0, 1.0) brx_array_constructor_split
+ brx_float3(-1.0, 1.0, -1.0) brx_array_constructor_split
+ brx_float3( 1.0, -1.0, 1.0) brx_array_constructor_split
+ brx_float3( 1.0, -1.0, -1.0) brx_array_constructor_split
+ brx_float3(-1.0, -1.0, 1.0) brx_array_constructor_split
+ brx_float3(-1.0, -1.0, -1.0)
+ brx_array_constructor_end;
+
+ brx_unroll
+ for(brx_int incident_light_index = 0; incident_light_index < incident_light_count; ++incident_light_index)
+ {
+ brx_float3 incident_illuminance = incident_illuminances[incident_light_index];
+ brx_float3 L = brx_normalize(Ls[incident_light_index]);
+
+ brx_float3 V = brx_normalize(camera_ray_origin - surface_position_world_space);
+ brx_float3 N = shading_normal_world_space;
+ brx_float3 H = normalize(L + V);
+ brx_float NdotL = brx_clamp(dot(N, L), 0.0, 1.0);
+ brx_float NdotH = brx_clamp(dot(N, H), 0.0, 1.0);
+ brx_float NdotV = brx_clamp(dot(N, V), 0.0, 1.0);
+ brx_float VdotH = brx_clamp(dot(V, H), 0.0, 1.0);
+
+ brx_float3 brdf_diffuse;
+ {
+ // Lambert
+
+ brdf_diffuse = (1.0 / M_PI) * albedo;
+ }
+
+ brx_float3 brdf_specular;
+ {
+ // Trowbridge Reitz
+
+ // Prevent the roughness to be zero
+ // https://github.com/EpicGames/UnrealEngine/blob/4.27/Engine/Shaders/Private/CapsuleLightIntegrate.ush#L94
+ const brx_float cvar_global_min_roughness_override = 0.02;
+ roughness = brx_max(roughness, cvar_global_min_roughness_override);
+
+ // Real-Time Rendering Fourth Edition / 9.8.1 Normal Distribution Functions: "In the Disney principled shading model, Burley[214] exposes the roughness control to users as g = r2, where r is the user-interface roughness parameter value between 0 and 1."
+ brx_float alpha = roughness * roughness;
+
+ // Equation 9.41 of Real-Time Rendering Fourth Edition: "Although **Trowbridge-Reitz distribution** is technically the correct name"
+ // Equation 8.11 of PBR Book: https://pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models#MicrofacetDistributionFunctions
+ brx_float alpha2 = alpha * alpha;
+ brx_float denominator = 1.0 + NdotH * (NdotH * alpha2 - NdotH);
+ brx_float D = (1.0 / M_PI) * (alpha2 / (denominator * denominator));
+
+ // Lambda:
+ // Equation 8.13 of PBR Book: https://pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models#MaskingandShadowing
+ // Equation 9.42 of Real-Time Rendering Fourth Edition
+ // Figure 8.18 of PBR Book: https://pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models#MaskingandShadowing
+ // Lambda(V) = 0.5*(-1.0 + (1.0/NoV)*sqrt(alpha^2 + (1.0 - alpha^2)*NoV^2))
+ // Lambda(L) = 0.5*(-1.0 + (1.0/NoL)*sqrt(alpha^2 + (1.0 - alpha^2)*NoL^2))
+
+ // G2
+ // Equation 9.31 of Real-Time Rendering Fourth Edition
+ // PBR Book / 8.4.3 Masking and Shadowing: "A more accurate model can be derived assuming that microfacet visibility is more likely the higher up a given point on a microface"
+ // G2 = 1.0/(1.0 + Lambda(V) + Lambda(L)) = (2.0*NoV*NoL)/(NoL*sqrt(alpha^2 + (1.0 - alpha^2)*NoV^2) + NoV*sqrt(alpha^2 + (1.0 - alpha^2)*NoL^2))
+
+ // V = G2/(4.0*NoV*NoL) = 0.5/(NoL*sqrt(alpha^2 + (1.0 - alpha^2)*NoV^2) + NoV*sqrt(alpha^2 + (1.0 - alpha^2)*NoL^2))
+
+ // float alpha2 = alpha * alpha;
+ // float term_v = NdotL * sqrt(alpha2 + (1.0 - alpha2) * NdotV * NdotV);
+ // float term_l = NdotV * sqrt(alpha2 + (1.0 - alpha2) * NdotL * NdotL);
+ // UE: [Vis_SmithJointApprox](https://github.com/EpicGames/UnrealEngine/blob/4.27/Engine/Shaders/Private/BRDF.ush#L380)
+ brx_float term_v = NdotL * (alpha + (1.0 - alpha) * NdotV);
+ brx_float term_l = NdotV * (alpha + (1.0 - alpha) * NdotL);
+ brx_float V = (0.5 / (term_v + term_l));
+
+ // glTF Sample Renderer: [F_Schlick](https://github.com/KhronosGroup/glTF-Sample-Renderer/blob/e5646a2bf87b0871ba3f826fc2335fe117a11411/source/Renderer/shaders/brdf.glsl#L24)
+ const brx_float3 f90 = brx_float3(1.0, 1.0, 1.0);
+
+ brx_float x = brx_clamp(1.0 - VdotH, 0.0, 1.0);
+ brx_float x2 = x * x;
+ brx_float x5 = x * x2 * x2;
+ brx_float3 F = f0 + (f90 - f0) * x5;
+
+ brdf_specular = D * V * F;
+ }
+
+ outgoing_radiance += (brdf_diffuse + brdf_specular) * (NdotL * incident_illuminance);
+ }
+
+ outgoing_radiance += emissive;
+
+ out_color = brx_float4(outgoing_radiance, 1.0);
+}
\ No newline at end of file
diff --git a/shaders/deferred_shading_pipeline_resource_binding.sli b/shaders/deferred_shading_pipeline_resource_binding.sli
new file mode 100644
index 0000000..60e23c5
--- /dev/null
+++ b/shaders/deferred_shading_pipeline_resource_binding.sli
@@ -0,0 +1,35 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _DEFERRED_SHADING_TRANSFER_PIPELINE_LAYOUT_SLI_
+#define _DEFERRED_SHADING_TRANSFER_PIPELINE_LAYOUT_SLI_ 1
+
+#include "../thirdparty/Brioche/shaders/brx_define.sli"
+#include "common_resource_binding.sli"
+
+brx_texture_2d_uint(g_gbuffer_texture, 0, 1, 1);
+
+brx_texture_2d(g_depth_texture, 0, 2, 1);
+
+#define deferred_shading_root_signature_macro \
+ brx_root_signature_root_parameter_begin(deferred_shading_root_signature_name) \
+ brx_root_signature_root_cbv(0, 0) brx_root_signature_root_parameter_split \
+ brx_root_signature_root_descriptor_table_srv(0, 1, 1) brx_root_signature_root_parameter_split \
+ brx_root_signature_root_descriptor_table_srv(0, 2, 1) \
+ brx_root_signature_root_parameter_end
+
+#endif
\ No newline at end of file
diff --git a/shaders/deferred_shading_vertex.sl b/shaders/deferred_shading_vertex.sl
new file mode 100644
index 0000000..c3499ff
--- /dev/null
+++ b/shaders/deferred_shading_vertex.sl
@@ -0,0 +1,33 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include "deferred_shading_pipeline_resource_binding.sli"
+
+brx_root_signature(deferred_shading_root_signature_macro, deferred_shading_root_signature_name)
+brx_vertex_shader_parameter_begin(main)
+brx_vertex_shader_parameter_in_vertex_id brx_vertex_shader_parameter_split
+brx_vertex_shader_parameter_out_position
+brx_vertex_shader_parameter_end(main)
+{
+ const brx_float2 full_screen_triangle_positions[3] = brx_array_constructor_begin(brx_float2, 3)
+ brx_float2(-1.0, -1.0) brx_array_constructor_split
+ brx_float2(3.0, -1.0) brx_array_constructor_split
+ brx_float2(-1.0, 3.0)
+ brx_array_constructor_end;
+
+ brx_position = brx_float4(full_screen_triangle_positions[brx_vertex_id], 0.5, 1.0);
+}
\ No newline at end of file
diff --git a/shaders/gbuffer_fragment.sl b/shaders/gbuffer_fragment.sl
new file mode 100644
index 0000000..35047c2
--- /dev/null
+++ b/shaders/gbuffer_fragment.sl
@@ -0,0 +1,112 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include "gbuffer_pipeline_resource_binding.sli"
+#include "../thirdparty/ImportAsset/shaders/packed_vector.sli"
+#include "../thirdparty/ImportAsset/shaders/octahedron_mapping.sli"
+
+brx_root_signature(gbuffer_root_signature_macro, gbuffer_root_signature_name)
+brx_early_depth_stencil
+brx_pixel_shader_parameter_begin(main)
+brx_pixel_shader_parameter_in_frag_coord brx_pixel_shader_parameter_split
+brx_pixel_shader_parameter_in(brx_float3, in_interpolated_normal, 0) brx_pixel_shader_parameter_split
+brx_pixel_shader_parameter_in(brx_float4, in_interpolated_tangent, 1) brx_pixel_shader_parameter_split
+brx_pixel_shader_parameter_in(brx_float2, in_interpolated_texcoord, 2) brx_pixel_shader_parameter_split
+brx_pixel_shader_parameter_out(brx_uint4, out_gbuffer, 0)
+brx_pixel_shader_parameter_end(main)
+{
+ brx_float3 geometry_normal_world_sapce = brx_normalize(in_interpolated_normal);
+ brx_float4 tangent_world_sapce = brx_float4(brx_normalize(in_interpolated_tangent.xyz), in_interpolated_tangent.w);
+ brx_float2 texcoord = in_interpolated_texcoord;
+
+ brx_uint4 packed_material_buffer_vectors[3];
+ packed_material_buffer_vectors[0] = brx_byte_address_buffer_load4(g_geometry_material_buffers[3], 0);
+ packed_material_buffer_vectors[1] = brx_byte_address_buffer_load4(g_geometry_material_buffers[3], 4 * 4);
+ packed_material_buffer_vectors[2].xy = brx_byte_address_buffer_load2(g_geometry_material_buffers[3], 4 * 4 + 4 * 4);
+ brx_uint geometry_material_flags = packed_material_buffer_vectors[0].x;
+ brx_float normal_texture_scale = brx_uint_as_float(packed_material_buffer_vectors[0].y);
+ brx_float3 emissive_factor = brx_uint_as_float(brx_uint3(packed_material_buffer_vectors[0].zw, packed_material_buffer_vectors[1].x));
+ brx_float3 base_color_factor = brx_uint_as_float(packed_material_buffer_vectors[1].yzw);
+ brx_float metallic_factor = brx_uint_as_float(packed_material_buffer_vectors[2].x);
+ brx_float roughness_factor = brx_uint_as_float(packed_material_buffer_vectors[2].y);
+
+ brx_float3 shading_normal_world_space;
+ brx_branch
+ if(0u != (geometry_material_flags & Material_Flag_Enable_Normal_Texture))
+ {
+ // ["5.20.3. material.normalTextureInfo.scale" of "glTF 2.0 Specification"](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_material_normaltextureinfo_scale)
+ brx_float3 shading_normal_tangent_space = brx_normalize((brx_sample_2d(g_material_textures[0], g_sampler[0], texcoord).xyz * 2.0 - brx_float3(1.0, 1.0, 1.0)) * brx_float3(normal_texture_scale, normal_texture_scale, 1.0));
+ brx_float3 bitangent_world_sapce = brx_cross(geometry_normal_world_sapce, tangent_world_sapce.xyz) * tangent_world_sapce.w;
+ shading_normal_world_space = brx_normalize(tangent_world_sapce.xyz * shading_normal_tangent_space.x + bitangent_world_sapce * shading_normal_tangent_space.y + geometry_normal_world_sapce * shading_normal_tangent_space.z);
+ }
+ else
+ {
+ shading_normal_world_space = geometry_normal_world_sapce;
+ }
+
+ brx_float3 emissive = emissive_factor;
+ brx_branch
+ if(0u != (geometry_material_flags & Material_Flag_Enable_Emissive_Texture))
+ {
+ emissive *= brx_sample_2d(g_material_textures[1], g_sampler[0], texcoord).xyz;
+ }
+
+ brx_float3 base_color = base_color_factor;
+ brx_branch
+ if(0u != (geometry_material_flags & Material_Flag_Enable_Base_Colorl_Texture))
+ {
+ base_color *= brx_sample_2d(g_material_textures[2], g_sampler[0], texcoord).xyz;
+ }
+
+ brx_float metallic = metallic_factor;
+ brx_float roughness = roughness_factor;
+ brx_branch
+ if(0u != (geometry_material_flags & Material_Flag_Enable_Metallic_Roughness_Texture))
+ {
+ brx_float2 metallic_roughness = brx_sample_2d(g_material_textures[3], g_sampler[0], texcoord).bg;
+ metallic *= metallic_roughness.x;
+ roughness *= metallic_roughness.y;
+ }
+
+ // Specular Anti-Aliasing
+ // "7.8.1 Mipmapping BRDF and Normal Maps" of "Real-Time Rendering Third Edition"
+ // "9.13.1 Filtering Normals and Normal Distributions" of "Real-Time Rendering Fourth Edition"
+ // UE4: [NormalCurvatureToRoughness](https://github.com/EpicGames/UnrealEngine/blob/4.27/Engine/Shaders/Private/BasePassPixelShader.usf#L67)
+ // U3D: [TextureNormalVariance ](https://github.com/Unity-Technologies/Graphics/blob/v10.8.1/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl#L214)
+ {
+ const brx_float cvar_normal_curvature_to_roughness_scale = 1.0;
+ const brx_float cvar_normal_curvature_to_roughness_bias = 0.0;
+ const brx_float cvar_normal_curvature_to_roughness_exponent = 0.3333333;
+
+ brx_float3 dn_dx = brx_ddx(geometry_normal_world_sapce);
+ brx_float3 dn_dy = brx_ddy(geometry_normal_world_sapce);
+ brx_float x = brx_dot(dn_dx, dn_dx);
+ brx_float y = brx_dot(dn_dy, dn_dy);
+
+ brx_float curvature_approx = brx_pow(brx_max(x, y), cvar_normal_curvature_to_roughness_exponent);
+ brx_float geometric_aa_roughness = brx_clamp(curvature_approx * cvar_normal_curvature_to_roughness_scale + cvar_normal_curvature_to_roughness_bias, 0.0, 1.0);
+
+ roughness = brx_max(roughness, geometric_aa_roughness);
+ }
+
+ brx_uint packed_shading_normal_world_space = FLOAT2_to_R16G16_SNORM(octahedron_map(shading_normal_world_space));
+ brx_uint packed_base_color = FLOAT4_to_R10G10B10A2_UNORM(brx_float4(base_color.x, base_color.y, base_color.z, 1.0));
+ brx_uint packed_metallic_roughness = FLOAT2_to_R16G16_UNORM(brx_float2(metallic, roughness));
+ brx_uint packed_emissive = FLOAT4_to_R10G10B10A2_UNORM(brx_float4(emissive.x, emissive.y, emissive.z, 1.0));
+
+ out_gbuffer = brx_uint4(packed_shading_normal_world_space, packed_base_color, packed_metallic_roughness, packed_emissive);
+}
\ No newline at end of file
diff --git a/shaders/gbuffer_pipeline_resource_binding.sli b/shaders/gbuffer_pipeline_resource_binding.sli
new file mode 100644
index 0000000..402091e
--- /dev/null
+++ b/shaders/gbuffer_pipeline_resource_binding.sli
@@ -0,0 +1,70 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _GBUFFER_PIPELINE_RESOURCE_BINDING_SLI_
+#define _GBUFFER_PIPELINE_RESOURCE_BINDING_SLI_ 1
+
+#include "../thirdparty/Brioche/shaders/brx_define.sli"
+#include "common_resource_binding.sli"
+
+#define Geometry_Flag_Index_Type_UInt16 0x1u
+#define Material_Flag_Enable_Normal_Texture 0x2u
+#define Material_Flag_Enable_Emissive_Texture 0x4u
+#define Material_Flag_Enable_Base_Colorl_Texture 0x8u
+#define Material_Flag_Enable_Metallic_Roughness_Texture 0x10u
+
+#if defined(__cplusplus)
+struct gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding
+{
+ uint32_t m_geometry_material_flags;
+ float m_normal_texture_scale;
+ float m_emissive_factor_x;
+ float m_emissive_factor_y;
+
+ float m_emissive_factor_z;
+ float m_base_color_factor_x;
+ float m_base_color_factor_y;
+ float m_base_color_factor_z;
+
+ float m_metallic_factor;
+ float m_roughness_factor;
+ uint32_t _unused_padding_1;
+ uint32_t _unused_padding_2;
+};
+#endif
+
+brx_sampler_state(g_sampler, 0, 1, 1);
+
+brx_read_only_byte_address_buffer(g_geometry_material_buffers, 1, 0, 4);
+
+brx_texture_2d(g_material_textures, 1, 4, 4);
+
+brx_cbuffer(gbuffer_pipeline_per_mesh_instance_update_set_uniform_buffer_binding, 2, 0)
+{
+ brx_column_major brx_float4x4 g_model_transform;
+};
+
+#define gbuffer_root_signature_macro \
+ brx_root_signature_root_parameter_begin(gbuffer_root_signature_name) \
+ brx_root_signature_root_cbv(0, 0) brx_root_signature_root_parameter_split \
+ brx_root_signature_root_descriptor_table_sampler(0, 1, 1) brx_root_signature_root_parameter_split \
+ brx_root_signature_root_descriptor_table_srv(1, 0, 4) brx_root_signature_root_parameter_split \
+ brx_root_signature_root_descriptor_table_srv(1, 4, 4) brx_root_signature_root_parameter_split \
+ brx_root_signature_root_cbv(2, 0) \
+ brx_root_signature_root_parameter_end
+
+#endif
\ No newline at end of file
diff --git a/shaders/gbuffer_vertex.sl b/shaders/gbuffer_vertex.sl
new file mode 100644
index 0000000..d30c4d5
--- /dev/null
+++ b/shaders/gbuffer_vertex.sl
@@ -0,0 +1,72 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include "gbuffer_pipeline_resource_binding.sli"
+#include "../thirdparty/ImportAsset/shaders/packed_vector.sli"
+#include "../thirdparty/ImportAsset/shaders/octahedron_mapping.sli"
+#include "common_constant.sli"
+
+brx_root_signature(gbuffer_root_signature_macro, gbuffer_root_signature_name)
+brx_vertex_shader_parameter_begin(main)
+brx_vertex_shader_parameter_in_vertex_id brx_vertex_shader_parameter_split
+brx_vertex_shader_parameter_out_position brx_vertex_shader_parameter_split
+brx_vertex_shader_parameter_out(brx_float3, out_vertex_normal, 0) brx_vertex_shader_parameter_split
+brx_vertex_shader_parameter_out(brx_float4, out_vertex_tagent, 1) brx_vertex_shader_parameter_split
+brx_vertex_shader_parameter_out(brx_float2, out_vertex_texcoord, 2)
+brx_vertex_shader_parameter_end(main)
+{
+ brx_uint geometry_material_flags = brx_byte_address_buffer_load(g_geometry_material_buffers[3], 0);
+
+ brx_uint vertex_index;
+ brx_branch
+ if(0u != (geometry_material_flags & Geometry_Flag_Index_Type_UInt16))
+ {
+ brx_uint index_buffer_offset = (0u == ((g_index_uint16_buffer_stride * brx_uint(brx_vertex_id)) % 4u)) ? (g_index_uint16_buffer_stride * brx_uint(brx_vertex_id)) : ((g_index_uint16_buffer_stride * brx_uint(brx_vertex_id)) - 2u);
+ brx_uint packed_vector_index_buffer = brx_byte_address_buffer_load(g_geometry_material_buffers[2], index_buffer_offset);
+ brx_uint2 unpacked_vector_index_buffer = R16G16_UINT_to_UINT2(packed_vector_index_buffer);
+ vertex_index = (0u == ((g_index_uint16_buffer_stride * brx_uint(brx_vertex_id)) % 4u)) ? unpacked_vector_index_buffer.x : unpacked_vector_index_buffer.y;
+ }
+ else
+ {
+ brx_uint index_buffer_offset = g_index_uint32_buffer_stride * brx_uint(brx_vertex_id);
+ vertex_index = brx_byte_address_buffer_load(g_geometry_material_buffers[2], index_buffer_offset);
+ }
+
+ brx_uint vertex_position_buffer_offset = g_vertex_position_buffer_stride * vertex_index;
+ brx_uint3 packed_vector_vertex_position_buffer = brx_byte_address_buffer_load3(g_geometry_material_buffers[0], vertex_position_buffer_offset);
+ brx_float3 vertex_position_model_space = brx_uint_as_float(packed_vector_vertex_position_buffer);
+
+ brx_uint vertex_varying_buffer_offset = g_vertex_varying_buffer_stride * vertex_index;
+ brx_uint3 packed_vector_vertex_varying_buffer = brx_byte_address_buffer_load3(g_geometry_material_buffers[1], vertex_varying_buffer_offset);
+ brx_float3 vertex_normal_model_space = octahedron_unmap(R16G16_SNORM_to_FLOAT2(packed_vector_vertex_varying_buffer.x));
+ brx_float3 vertex_mapped_tangent_model_space = R15G15B2_SNORM_to_FLOAT3(packed_vector_vertex_varying_buffer.y);
+ brx_float4 vertex_tangent_model_space = brx_float4(octahedron_unmap(vertex_mapped_tangent_model_space.xy), vertex_mapped_tangent_model_space.z);
+ brx_float2 vertex_texcoord = R16G16_UNORM_to_FLOAT2(packed_vector_vertex_varying_buffer.z);
+
+ brx_float3 vertex_position_world_space = brx_mul(g_model_transform, brx_float4(vertex_position_model_space, 1.0)).xyz;
+ brx_float3 vertex_position_view_space = brx_mul(g_view_transform, brx_float4(vertex_position_world_space, 1.0)).xyz;
+ brx_float4 vertex_position_clip_space = brx_mul(g_projection_transform, brx_float4(vertex_position_view_space, 1.0));
+
+ brx_float3 vertex_normal_world_space = brx_mul(g_model_transform, brx_float4(vertex_normal_model_space, 0.0)).xyz;
+
+ brx_float4 vertex_tangent_world_space = brx_float4(brx_mul(g_model_transform, brx_float4(vertex_tangent_model_space.xyz, 0.0)).xyz, vertex_tangent_model_space.w);
+
+ brx_position = vertex_position_clip_space;
+ out_vertex_normal = vertex_normal_world_space;
+ out_vertex_tagent = vertex_tangent_world_space;
+ out_vertex_texcoord = vertex_texcoord;
+}
diff --git a/shaders/math_constant.sli b/shaders/math_constant.sli
new file mode 100644
index 0000000..dbdbb79
--- /dev/null
+++ b/shaders/math_constant.sli
@@ -0,0 +1,23 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _MATH_CONSTANT_SLI_
+#define _MATH_CONSTANT_SLI_ 1
+
+#define M_PI 3.141592653589793238462643
+
+#endif
\ No newline at end of file
diff --git a/shaders/skin_compute.sl b/shaders/skin_compute.sl
new file mode 100644
index 0000000..f418e45
--- /dev/null
+++ b/shaders/skin_compute.sl
@@ -0,0 +1,80 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include "skin_pipeline_resource_binding.sli"
+#include "../thirdparty/ImportAsset/shaders/packed_vector.sli"
+#include "../thirdparty/ImportAsset/shaders/octahedron_mapping.sli"
+#include "common_constant.sli"
+
+#if defined(GL_SPIRV) || defined(VULKAN)
+#define brx_dual_quaternion mat2x4
+#include "../thirdparty/DLB/DLB.glsli"
+#elif defined(HLSL_VERSION) || defined(__HLSL_VERSION)
+#define brx_dual_quaternion float2x4
+#include "../thirdparty/DLB/DLB.hlsli"
+#else
+#error Unknown Compiler
+#endif
+
+#define THREAD_GROUP_X 1
+#define THREAD_GROUP_Y 1
+#define THREAD_GROUP_Z 1
+
+brx_root_signature(skin_root_signature_macro, skin_root_signature_name)
+brx_num_threads(THREAD_GROUP_X, THREAD_GROUP_Y, THREAD_GROUP_Z)
+brx_compute_shader_parameter_begin(main)
+brx_compute_shader_parameter_in_group_id
+brx_pixel_shader_parameter_end(main)
+{
+ brx_uint vertex_index = brx_group_id.x;
+
+ brx_uint vertex_position_buffer_offset = g_vertex_position_buffer_stride * vertex_index;
+ brx_uint3 packed_vector_vertex_position_buffer = brx_byte_address_buffer_load3(g_geometry_buffers[0], vertex_position_buffer_offset);
+ brx_float3 vertex_position_model_space = brx_uint_as_float(packed_vector_vertex_position_buffer);
+
+ brx_uint vertex_varying_buffer_offset = g_vertex_varying_buffer_stride * vertex_index;
+ brx_uint3 packed_vector_vertex_varying_buffer = brx_byte_address_buffer_load3(g_geometry_buffers[1], vertex_varying_buffer_offset);
+ brx_float3 vertex_normal_model_space = octahedron_unmap(R16G16_SNORM_to_FLOAT2(packed_vector_vertex_varying_buffer.x));
+ brx_float3 vertex_mapped_tangent_model_space = R15G15B2_SNORM_to_FLOAT3(packed_vector_vertex_varying_buffer.y);
+ brx_float4 vertex_tangent_model_space = brx_float4(octahedron_unmap(vertex_mapped_tangent_model_space.xy), vertex_mapped_tangent_model_space.z);
+
+ brx_uint vertex_joint_buffer_offset = g_vertex_joint_buffer_stride * vertex_index;
+ brx_uint3 packed_vector_vertex_joint_buffer = brx_byte_address_buffer_load3(g_geometry_buffers[2], vertex_joint_buffer_offset);
+
+ brx_uint4 joint_indices = R16G16B16A16_UINT_to_UINT4(packed_vector_vertex_joint_buffer.xy);
+ brx_float4 joint_weights = R8G8B8A8_UNORM_to_FLOAT4(packed_vector_vertex_joint_buffer.z);
+
+ brx_dual_quaternion dual_quaternion_indices_x = brx_dual_quaternion(g_dual_quaternions[2u * joint_indices.x], g_dual_quaternions[2u * joint_indices.x + 1u]);
+ brx_dual_quaternion dual_quaternion_indices_y = brx_dual_quaternion(g_dual_quaternions[2u * joint_indices.y], g_dual_quaternions[2u * joint_indices.y + 1u]);
+ brx_dual_quaternion dual_quaternion_indices_z = brx_dual_quaternion(g_dual_quaternions[2u * joint_indices.z], g_dual_quaternions[2u * joint_indices.z + 1u]);
+ brx_dual_quaternion dual_quaternion_indices_w = brx_dual_quaternion(g_dual_quaternions[2u * joint_indices.w], g_dual_quaternions[2u * joint_indices.w + 1u]);
+
+ brx_dual_quaternion blend_dual_quaternion = dual_quaternion_linear_blending(dual_quaternion_indices_x, dual_quaternion_indices_y, dual_quaternion_indices_z, dual_quaternion_indices_w, joint_weights);
+
+ brx_float4 blend_quaternion;
+ brx_float3 blend_translation;
+ unit_dual_quaternion_to_rigid_transform(blend_dual_quaternion, blend_quaternion, blend_translation);
+
+ brx_float3 skined_vertex_position_model_space = unit_quaternion_to_rotation_transform(blend_quaternion, vertex_position_model_space) + blend_translation;
+ brx_uint3 packed_vector_skined_vertex_position_buffer = brx_float_as_uint(skined_vertex_position_model_space);
+ brx_byte_address_buffer_store3(g_skinned_geometry_buffers[0], vertex_position_buffer_offset, packed_vector_skined_vertex_position_buffer);
+
+ brx_float3 skined_vertex_normal_model_space = unit_quaternion_to_rotation_transform(blend_quaternion, vertex_normal_model_space);
+ brx_float4 skined_vertex_tangent_model_space = brx_float4(unit_quaternion_to_rotation_transform(blend_quaternion, vertex_tangent_model_space.xyz), vertex_tangent_model_space.w);
+ brx_uint3 packed_vector_skined_vertex_varying_buffer = brx_uint3(FLOAT2_to_R16G16_SNORM(octahedron_map(skined_vertex_normal_model_space)), FLOAT3_to_R15G15B2_SNORM(brx_float3(octahedron_map(skined_vertex_tangent_model_space.xyz), skined_vertex_tangent_model_space.w)), packed_vector_vertex_varying_buffer.z);
+ brx_byte_address_buffer_store3(g_skinned_geometry_buffers[1], vertex_varying_buffer_offset, packed_vector_skined_vertex_varying_buffer);
+}
\ No newline at end of file
diff --git a/shaders/skin_pipeline_resource_binding.sli b/shaders/skin_pipeline_resource_binding.sli
new file mode 100644
index 0000000..2fed8b4
--- /dev/null
+++ b/shaders/skin_pipeline_resource_binding.sli
@@ -0,0 +1,45 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _SKIN_PIPELINE_RESOURCE_BINDING_SLI_
+#define _SKIN_PIPELINE_RESOURCE_BINDING_SLI_ 1
+
+#include "../thirdparty/Brioche/shaders/brx_define.sli"
+
+// D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096
+// Vulkan Core: maxUniformBufferRange 16384 = 16 * 1024
+// Vulkan Roadmap 2022: maxUniformBufferRange 65536 = 16 * 4096
+
+#define MAX_JOINT_COUNT 2048
+
+brx_cbuffer(skin_pipeline_per_mesh_instance_update_set_uniform_buffer_binding, 0, 0)
+{
+ brx_column_major brx_float4 g_dual_quaternions[2 * MAX_JOINT_COUNT];
+};
+
+brx_read_only_byte_address_buffer(g_geometry_buffers, 1, 0, 3);
+
+brx_write_only_byte_address_buffer(g_skinned_geometry_buffers, 1, 1, 2);
+
+#define skin_root_signature_macro \
+ brx_root_signature_root_parameter_begin(skin_root_signature_name) \
+ brx_root_signature_root_cbv(0, 0) brx_root_signature_root_parameter_split \
+ brx_root_signature_root_descriptor_table_srv(1, 0, 3) brx_root_signature_root_parameter_split \
+ brx_root_signature_root_descriptor_table_uav(1, 1, 2) \
+ brx_root_signature_root_parameter_end
+
+#endif
\ No newline at end of file
diff --git a/shaders/support/full_screen_transfer_fragment.sl b/shaders/support/full_screen_transfer_fragment.sl
new file mode 100644
index 0000000..d2cdb51
--- /dev/null
+++ b/shaders/support/full_screen_transfer_fragment.sl
@@ -0,0 +1,45 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include "full_screen_transfer_pipeline_layout.sli"
+
+brx_root_signature(full_screen_transfer_root_signature_macro, full_screen_transfer_root_signature_name)
+brx_early_depth_stencil
+brx_pixel_shader_parameter_begin(main)
+brx_pixel_shader_parameter_in_frag_coord brx_pixel_shader_parameter_split
+brx_pixel_shader_parameter_out(brx_float4, out_image, 0)
+brx_pixel_shader_parameter_end(main)
+{
+ // TODO: HDR swapchain
+ //
+ // DXGI_COLOR_SPACE_TYPE: https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range#setting-up-your-directx-swap-chain
+ // Direct3D 12 HDR sample: https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-hdr-sample-win32/
+ // VK_EXT_swapchain_colorspace: https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html#TRANSFER_CONVERSION
+ // https://developer.nvidia.com/high-dynamic-range-display-development
+ // https://gpuopen.com/learn/using-amd-freesync-2-hdr-color-spaces/
+ //
+ // Options | hardware OETF input | hardware OETF output | Direct3D12 | Vulkan
+ // sRGB | sRGB | Bt709 | DXGI_FORMAT_R8G8B8A8_UNORM + DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 | VK_FORMAT_B8G8R8A8_UNORM + VK_COLOR_SPACE_BT709_NONLINEAR_EXT
+ // sRGB | sRGB | Bt709 | DXGI_FORMAT_R10G10B10A2_UNORM + DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 | VK_FORMAT_A2B10G10R10_UNORM_PACK32 + VK_COLOR_SPACE_BT709_NONLINEAR_EXT
+ // HDR10 | ST2084 | Bt2020 | DXGI_FORMAT_R10G10B10A2_UNORM + DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 | VK_FORMAT_A2B10G10R10_UNORM_PACK32 + VK_COLOR_SPACE_HDR10_ST2084_EXT
+ // scRGB | scRGB | Bt709 | N/A | VK_FORMAT_R16G16B16A16_SFLOAT + VK_COLOR_SPACE_BT709_LINEAR_EXT
+ // Linear BT2020 | Linear BT2020 | Bt2020 | DXGI_FORMAT_R16G16B16A16_FLOAT + DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 | VK_FORMAT_R16G16B16A16_SFLOAT + VK_COLOR_SPACE_BT2020_LINEAR_EXT
+
+ brx_float3 color_linear = brx_load_2d(g_in_texture[0], brx_int3(brx_frag_coord.xy, 0)).xyz;
+ brx_float3 color_srgb = brx_float3(brx_pow(brx_clamp(color_linear.x, 0.0, 1.0), (1.0 / 2.2)), brx_pow(brx_clamp(color_linear.y, 0.0, 1.0), (1.0 / 2.2)), brx_pow(brx_clamp(color_linear.z, 0.0, 1.0), (1.0 / 2.2)));
+ out_image = brx_float4(color_srgb, 1.0);
+}
\ No newline at end of file
diff --git a/shaders/support/full_screen_transfer_pipeline_layout.sli b/shaders/support/full_screen_transfer_pipeline_layout.sli
new file mode 100644
index 0000000..b618702
--- /dev/null
+++ b/shaders/support/full_screen_transfer_pipeline_layout.sli
@@ -0,0 +1,32 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _FULL_SCREEN_TRANSFER_PIPELINE_LAYOUT_SLI_
+#define _FULL_SCREEN_TRANSFER_PIPELINE_LAYOUT_SLI_ 1
+
+#include "../../thirdparty/Brioche/shaders/brx_define.sli"
+
+brx_texture_2d(g_in_texture, 0, 0, 1);
+
+brx_sampler_state(g_sampler, 0, 1, 1);
+
+#define full_screen_transfer_root_signature_macro \
+ brx_root_signature_root_parameter_begin(full_screen_transfer_root_signature_name) \
+ brx_root_signature_root_descriptor_table_srv(0, 0, 1) brx_root_signature_root_parameter_split \
+ brx_root_signature_root_parameter_end
+
+#endif
\ No newline at end of file
diff --git a/shaders/support/full_screen_transfer_vertex.sl b/shaders/support/full_screen_transfer_vertex.sl
new file mode 100644
index 0000000..1bfb9bc
--- /dev/null
+++ b/shaders/support/full_screen_transfer_vertex.sl
@@ -0,0 +1,33 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include "full_screen_transfer_pipeline_layout.sli"
+
+brx_root_signature(full_screen_transfer_root_signature_macro, full_screen_transfer_root_signature_name)
+brx_vertex_shader_parameter_begin(main)
+brx_vertex_shader_parameter_in_vertex_id brx_vertex_shader_parameter_split
+brx_vertex_shader_parameter_out_position
+brx_vertex_shader_parameter_end(main)
+{
+ const brx_float2 full_screen_triangle_positions[3] = brx_array_constructor_begin(brx_float2, 3)
+ brx_float2(-1.0, -1.0) brx_array_constructor_split
+ brx_float2(3.0, -1.0) brx_array_constructor_split
+ brx_float2(-1.0, 3.0)
+ brx_array_constructor_end;
+
+ brx_position = brx_float4(full_screen_triangle_positions[brx_vertex_id], 0.5, 1.0);
+}
\ No newline at end of file
diff --git a/source/demo.cpp b/source/demo.cpp
new file mode 100644
index 0000000..95d8fa9
--- /dev/null
+++ b/source/demo.cpp
@@ -0,0 +1,1449 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include "demo.h"
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#endif
+#include
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+#include
+#include
+#include
+#include
+#include
+#include "support/camera_controller.h"
+#include "../thirdparty/DLB/DLB.h"
+#include "../thirdparty/ImportAsset/include/import_image_asset.h"
+#include "../thirdparty/ImportAsset/include/import_asset_input_stream.h"
+#include "../thirdparty/ImportAsset/shaders/octahedron_mapping.sli"
+#include "../shaders/common_constant.sli"
+#include "../shaders/skin_pipeline_resource_binding.sli"
+#include "../shaders/common_resource_binding.sli"
+#include "../shaders/gbuffer_pipeline_resource_binding.sli"
+#include "../shaders/deferred_shading_pipeline_resource_binding.sli"
+
+static inline uint32_t tbb_align_up(uint32_t value, uint32_t alignment);
+
+static inline DirectX::XMMATRIX XM_CALLCONV DirectX_Math_Matrix_PerspectiveFovRH_ReversedZ(float FovAngleY, float AspectRatio, float NearZ, float FarZ);
+
+static float g_camera_fov = -1.0F;
+
+Demo::Demo()
+{
+}
+
+void Demo::init(brx_device *device, std::vector const &file_names)
+{
+ // Descriptor Layout
+ brx_descriptor_set_layout *skin_pipeline_per_mesh_instance_update_descriptor_set_layout;
+ brx_descriptor_set_layout *skin_pipeline_per_mesh_skinned_subset_update_descriptor_set_layout;
+ brx_descriptor_set_layout *gbuffer_pipeline_none_update_descriptor_set_layout;
+ brx_descriptor_set_layout *gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout;
+ brx_descriptor_set_layout *gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout;
+ {
+ BRX_DESCRIPTOR_SET_LAYOUT_BINDING const skin_pipeline_per_mesh_instance_update_descriptor_set_layout_bindings[] = {
+ {0U, BRX_DESCRIPTOR_TYPE_DYNAMIC_UNIFORM_BUFFER, 1U}};
+ skin_pipeline_per_mesh_instance_update_descriptor_set_layout = device->create_descriptor_set_layout(sizeof(skin_pipeline_per_mesh_instance_update_descriptor_set_layout_bindings) / sizeof(skin_pipeline_per_mesh_instance_update_descriptor_set_layout_bindings[0]), skin_pipeline_per_mesh_instance_update_descriptor_set_layout_bindings);
+
+ BRX_DESCRIPTOR_SET_LAYOUT_BINDING const skin_pipeline_per_mesh_skined_subset_update_descriptor_set_layout_bindings[] = {
+ {0U, BRX_DESCRIPTOR_TYPE_READ_ONLY_STORAGE_BUFFER, 3U},
+ {1U, BRX_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2U}};
+ skin_pipeline_per_mesh_skinned_subset_update_descriptor_set_layout = device->create_descriptor_set_layout(sizeof(skin_pipeline_per_mesh_skined_subset_update_descriptor_set_layout_bindings) / sizeof(skin_pipeline_per_mesh_skined_subset_update_descriptor_set_layout_bindings[0]), skin_pipeline_per_mesh_skined_subset_update_descriptor_set_layout_bindings);
+
+ brx_descriptor_set_layout *const skin_pipeline_descriptor_set_layouts[] = {
+ skin_pipeline_per_mesh_instance_update_descriptor_set_layout, skin_pipeline_per_mesh_skinned_subset_update_descriptor_set_layout};
+ this->m_skin_pipeline_layout = device->create_pipeline_layout(sizeof(skin_pipeline_descriptor_set_layouts) / sizeof(skin_pipeline_descriptor_set_layouts[0]), skin_pipeline_descriptor_set_layouts);
+
+ BRX_DESCRIPTOR_SET_LAYOUT_BINDING const gbuffer_pipeline_none_update_descriptor_set_layout_bindings[] = {
+ {0U, BRX_DESCRIPTOR_TYPE_DYNAMIC_UNIFORM_BUFFER, 1U},
+ {1U, BRX_DESCRIPTOR_TYPE_SAMPLER, 1U}};
+ gbuffer_pipeline_none_update_descriptor_set_layout = device->create_descriptor_set_layout(sizeof(gbuffer_pipeline_none_update_descriptor_set_layout_bindings) / sizeof(gbuffer_pipeline_none_update_descriptor_set_layout_bindings[0]), gbuffer_pipeline_none_update_descriptor_set_layout_bindings);
+
+ BRX_DESCRIPTOR_SET_LAYOUT_BINDING const gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout_bindings[] = {
+ {0U, BRX_DESCRIPTOR_TYPE_READ_ONLY_STORAGE_BUFFER, 4U},
+ {4U, BRX_DESCRIPTOR_TYPE_SAMPLED_IMAGE, DEMO_MESH_SUBSET_METERIAL_TEXTURE_COUNT}};
+ gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout = device->create_descriptor_set_layout(sizeof(gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout_bindings) / sizeof(gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout_bindings[0]), gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout_bindings);
+
+ BRX_DESCRIPTOR_SET_LAYOUT_BINDING const gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout_bindings[] = {
+ {0U, BRX_DESCRIPTOR_TYPE_DYNAMIC_UNIFORM_BUFFER, 1U}};
+ gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout = device->create_descriptor_set_layout(sizeof(gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout_bindings) / sizeof(gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout_bindings[0]), gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout_bindings);
+
+ brx_descriptor_set_layout *const gbuffer_pipeline_descriptor_set_layouts[] = {
+ gbuffer_pipeline_none_update_descriptor_set_layout, gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout, gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout};
+ this->m_gbuffer_pipeline_layout = device->create_pipeline_layout(sizeof(gbuffer_pipeline_descriptor_set_layouts) / sizeof(gbuffer_pipeline_descriptor_set_layouts[0]), gbuffer_pipeline_descriptor_set_layouts);
+
+ BRX_DESCRIPTOR_SET_LAYOUT_BINDING const deferred_shading_pipeline_none_update_descriptor_set_layout_bindings[] = {
+ {0U, BRX_DESCRIPTOR_TYPE_DYNAMIC_UNIFORM_BUFFER, 1U},
+ {1U, BRX_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1U},
+ {2U, BRX_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1U}};
+ this->m_deferred_shading_pipeline_none_update_descriptor_set_layout = device->create_descriptor_set_layout(sizeof(deferred_shading_pipeline_none_update_descriptor_set_layout_bindings) / sizeof(deferred_shading_pipeline_none_update_descriptor_set_layout_bindings[0]), deferred_shading_pipeline_none_update_descriptor_set_layout_bindings);
+
+ brx_descriptor_set_layout *const deferred_shading_pipeline_descriptor_set_layouts[] = {
+ this->m_deferred_shading_pipeline_none_update_descriptor_set_layout};
+ this->m_deferred_shading_pipeline_layout = device->create_pipeline_layout(sizeof(deferred_shading_pipeline_descriptor_set_layouts) / sizeof(deferred_shading_pipeline_descriptor_set_layouts[0]), deferred_shading_pipeline_descriptor_set_layouts);
+ }
+
+ // Render Pass and Pipeline
+ {
+ // Skin Pipeline
+ {
+#include
+ this->m_skin_pipeline = device->create_compute_pipeline(this->m_skin_pipeline_layout, sizeof(skin_compute_shader_module_code), skin_compute_shader_module_code);
+ }
+
+ // GBuffer Render Pass
+ {
+ this->m_gbuffer_color_attachement_format = BRX_COLOR_ATTACHMENT_FORMAT_R32G32B32A32_UINT;
+ this->m_gbuffer_depth_attachement_format = device->get_depth_attachment_image_format();
+
+ BRX_RENDER_PASS_COLOR_ATTACHMENT const color_attachment = {
+ this->m_gbuffer_color_attachement_format,
+ BRX_RENDER_PASS_COLOR_ATTACHMENT_LOAD_OPERATION_CLEAR,
+ BRX_RENDER_PASS_COLOR_ATTACHMENT_STORE_OPERATION_FLUSH_FOR_SAMPLED_IMAGE};
+
+ BRX_RENDER_PASS_DEPTH_STENCIL_ATTACHMENT const depth_stencil_attachment = {
+ this->m_gbuffer_depth_attachement_format,
+ BRX_RENDER_PASS_DEPTH_STENCIL_ATTACHMENT_LOAD_OPERATION_CLEAR,
+ BRX_RENDER_PASS_DEPTH_STENCIL_ATTACHMENT_STORE_OPERATION_FLUSH_FOR_SAMPLED_IMAGE};
+
+ this->m_gbuffer_render_pass = device->create_render_pass(1U, &color_attachment, &depth_stencil_attachment);
+ }
+
+ // GBuffer Pipeline
+ {
+#include
+#include
+ this->m_gbuffer_pipeline = device->create_graphics_pipeline(this->m_gbuffer_render_pass, this->m_gbuffer_pipeline_layout, sizeof(gbuffer_vertex_shader_module_code), gbuffer_vertex_shader_module_code, sizeof(gbuffer_fragment_shader_module_code), gbuffer_fragment_shader_module_code, true, BRX_GRAPHICS_PIPELINE_COMPARE_OPERATION_GREATER);
+ }
+
+ // Deferred Shading Pass
+ {
+ this->m_deferred_shading_color_attachement_format = BRX_COLOR_ATTACHMENT_FORMAT_A2R10G10B10_UNORM_PACK32;
+
+ BRX_RENDER_PASS_COLOR_ATTACHMENT const color_attachment = {
+ this->m_deferred_shading_color_attachement_format,
+ BRX_RENDER_PASS_COLOR_ATTACHMENT_LOAD_OPERATION_CLEAR,
+ BRX_RENDER_PASS_COLOR_ATTACHMENT_STORE_OPERATION_FLUSH_FOR_SAMPLED_IMAGE};
+
+ this->m_deferred_shading_render_pass = device->create_render_pass(1U, &color_attachment, NULL);
+ }
+
+ // Deferred Shading Pipeline
+ {
+#include
+#include
+ this->m_deferred_shading_pipeline = device->create_graphics_pipeline(this->m_deferred_shading_render_pass, this->m_deferred_shading_pipeline_layout, sizeof(deferred_shading_vertex_shader_module_code), deferred_shading_vertex_shader_module_code, sizeof(deferred_shading_fragment_shader_module_code), deferred_shading_fragment_shader_module_code, false, BRX_GRAPHICS_PIPELINE_COMPARE_OPERATION_ALWAYS);
+ }
+ }
+
+ // Asset & Place Holder Texture
+ {
+ brx_upload_command_buffer *const upload_command_buffer = device->create_upload_command_buffer();
+
+ brx_graphics_command_buffer *const graphics_command_buffer = device->create_graphics_command_buffer();
+
+ brx_upload_queue *const upload_queue = device->create_upload_queue();
+
+ brx_graphics_queue *const graphics_queue = device->create_graphics_queue();
+
+ brx_fence *const fence = device->create_fence(true);
+
+ {
+ std::vector staging_upload_buffers;
+
+ device->reset_upload_command_buffer(upload_command_buffer);
+
+ device->reset_graphics_command_buffer(graphics_command_buffer);
+
+ upload_command_buffer->begin();
+
+ graphics_command_buffer->begin();
+
+ import_asset_input_stream_factory *input_stream_factory = import_asset_init_file_input_stream_factory();
+
+ // 60 FPS
+ constexpr float const frame_rate = 60.0F;
+
+ // Asset
+ for (size_t file_name_index = 0U; file_name_index < file_names.size(); ++file_name_index)
+ {
+ std::string const &file_name = file_names[file_name_index];
+
+ std::vector total_mesh_data;
+ if (import_gltf_scene_asset(total_mesh_data, frame_rate, input_stream_factory, file_name.c_str()))
+ {
+ size_t mesh_index_offset = this->m_scene_meshes.size();
+
+ this->m_scene_meshes.resize(mesh_index_offset + total_mesh_data.size());
+
+ for (size_t mesh_index = 0U; mesh_index < total_mesh_data.size(); ++mesh_index)
+ {
+ scene_mesh_data const &in_mesh_data = total_mesh_data[mesh_index];
+
+ Demo_Mesh &out_mesh = this->m_scene_meshes[mesh_index_offset + mesh_index];
+
+ out_mesh.m_skinned = in_mesh_data.m_skinned;
+
+ out_mesh.m_subsets.resize(in_mesh_data.m_subsets.size());
+
+ for (size_t subset_index = 0U; subset_index < in_mesh_data.m_subsets.size(); ++subset_index)
+ {
+ scene_mesh_subset_data const &in_subset_data = in_mesh_data.m_subsets[subset_index];
+
+ Demo_Mesh_Subset &out_subset = out_mesh.m_subsets[subset_index];
+
+ out_subset.m_vertex_count = static_cast(in_subset_data.m_vertex_position_binding.size());
+
+ {
+ uint32_t const vertex_position_buffer_size = sizeof(scene_mesh_vertex_position_binding) * out_subset.m_vertex_count;
+
+ out_subset.m_vertex_position_buffer = device->create_storage_asset_buffer(vertex_position_buffer_size);
+
+ brx_staging_upload_buffer *const vertex_position_staging_upload_buffer = device->create_staging_upload_buffer(vertex_position_buffer_size);
+
+ staging_upload_buffers.push_back(vertex_position_staging_upload_buffer);
+
+ std::memcpy(vertex_position_staging_upload_buffer->get_host_memory_range_base(), in_subset_data.m_vertex_position_binding.data(), vertex_position_buffer_size);
+
+ upload_command_buffer->upload_from_staging_upload_buffer_to_storage_asset_buffer(out_subset.m_vertex_position_buffer, 0U, vertex_position_staging_upload_buffer, 0U, vertex_position_buffer_size);
+ }
+
+ {
+ assert(out_subset.m_vertex_count == in_subset_data.m_vertex_varying_binding.size());
+
+ uint32_t const vertex_varying_buffer_size = sizeof(scene_mesh_vertex_varying_binding) * out_subset.m_vertex_count;
+
+ out_subset.m_vertex_varying_buffer = device->create_storage_asset_buffer(vertex_varying_buffer_size);
+
+ brx_staging_upload_buffer *const vertex_varying_staging_upload_buffer = device->create_staging_upload_buffer(vertex_varying_buffer_size);
+
+ staging_upload_buffers.push_back(vertex_varying_staging_upload_buffer);
+
+ std::memcpy(vertex_varying_staging_upload_buffer->get_host_memory_range_base(), in_subset_data.m_vertex_varying_binding.data(), vertex_varying_buffer_size);
+
+ upload_command_buffer->upload_from_staging_upload_buffer_to_storage_asset_buffer(out_subset.m_vertex_varying_buffer, 0U, vertex_varying_staging_upload_buffer, 0U, vertex_varying_buffer_size);
+ }
+
+ if (!in_mesh_data.m_skinned)
+ {
+ out_subset.m_vertex_joint_buffer = NULL;
+ }
+ else
+ {
+ assert(out_subset.m_vertex_count == in_subset_data.m_vertex_joint_binding.size());
+
+ uint32_t const vertex_joint_buffer_size = sizeof(scene_mesh_vertex_joint_binding) * out_subset.m_vertex_count;
+
+ out_subset.m_vertex_joint_buffer = device->create_storage_asset_buffer(vertex_joint_buffer_size);
+
+ brx_staging_upload_buffer *const vertex_joint_staging_upload_buffer = device->create_staging_upload_buffer(vertex_joint_buffer_size);
+
+ staging_upload_buffers.push_back(vertex_joint_staging_upload_buffer);
+
+ std::memcpy(vertex_joint_staging_upload_buffer->get_host_memory_range_base(), in_subset_data.m_vertex_joint_binding.data(), vertex_joint_buffer_size);
+
+ upload_command_buffer->upload_from_staging_upload_buffer_to_storage_asset_buffer(out_subset.m_vertex_joint_buffer, 0U, vertex_joint_staging_upload_buffer, 0U, vertex_joint_buffer_size);
+ }
+
+ out_subset.m_index_count = static_cast(in_subset_data.m_indices.size());
+
+ {
+ if (in_subset_data.m_max_index <= static_cast(UINT16_MAX))
+ {
+ std::vector converted_indices(static_cast(out_subset.m_index_count));
+ for (uint32_t index_index = 0; index_index < out_subset.m_index_count; ++index_index)
+ {
+ converted_indices[index_index] = static_cast(in_subset_data.m_indices[index_index]);
+ }
+
+ uint32_t const index_buffer_size = sizeof(uint16_t) * out_subset.m_index_count;
+
+ out_subset.m_index_buffer = device->create_storage_asset_buffer(index_buffer_size);
+
+ brx_staging_upload_buffer *const index_staging_upload_buffer = device->create_staging_upload_buffer(index_buffer_size);
+
+ staging_upload_buffers.push_back(index_staging_upload_buffer);
+
+ std::memcpy(index_staging_upload_buffer->get_host_memory_range_base(), converted_indices.data(), index_buffer_size);
+
+ upload_command_buffer->upload_from_staging_upload_buffer_to_storage_asset_buffer(out_subset.m_index_buffer, 0U, index_staging_upload_buffer, 0U, index_buffer_size);
+ }
+ else
+ {
+ uint32_t const index_buffer_size = sizeof(uint32_t) * out_subset.m_index_count;
+
+ out_subset.m_index_buffer = device->create_storage_asset_buffer(index_buffer_size);
+
+ brx_staging_upload_buffer *const index_staging_upload_buffer = device->create_staging_upload_buffer(index_buffer_size);
+
+ staging_upload_buffers.push_back(index_staging_upload_buffer);
+
+ std::memcpy(index_staging_upload_buffer->get_host_memory_range_base(), in_subset_data.m_indices.data(), index_buffer_size);
+
+ upload_command_buffer->upload_from_staging_upload_buffer_to_storage_asset_buffer(out_subset.m_index_buffer, 0U, index_staging_upload_buffer, 0U, index_buffer_size);
+ }
+ }
+
+ {
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination;
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_geometry_material_flags = 0U;
+ if (in_subset_data.m_max_index <= static_cast(UINT16_MAX))
+ {
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_geometry_material_flags |= Geometry_Flag_Index_Type_UInt16;
+ }
+ if (!in_subset_data.m_normal_texture_image_uri.empty())
+ {
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_geometry_material_flags |= Material_Flag_Enable_Normal_Texture;
+ }
+ if (!in_subset_data.m_emissive_texture_image_uri.empty())
+ {
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_geometry_material_flags |= Material_Flag_Enable_Emissive_Texture;
+ }
+ if (!in_subset_data.m_base_color_texture_image_uri.empty())
+ {
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_geometry_material_flags |= Material_Flag_Enable_Base_Colorl_Texture;
+ }
+ if (!in_subset_data.m_metallic_roughness_texture_image_uri.empty())
+ {
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_geometry_material_flags |= Material_Flag_Enable_Metallic_Roughness_Texture;
+ }
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_normal_texture_scale = in_subset_data.m_normal_texture_scale;
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_emissive_factor_x = in_subset_data.m_emissive_factor.x;
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_emissive_factor_y = in_subset_data.m_emissive_factor.y;
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_emissive_factor_z = in_subset_data.m_emissive_factor.z;
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_base_color_factor_x = in_subset_data.m_base_color_factor.x;
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_base_color_factor_y = in_subset_data.m_base_color_factor.y;
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_base_color_factor_z = in_subset_data.m_base_color_factor.z;
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_metallic_factor = in_subset_data.m_metallic_factor;
+ gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination.m_roughness_factor = in_subset_data.m_roughness_factor;
+
+ uint32_t const material_buffer_size = sizeof(gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination);
+
+ out_subset.m_material_buffer = device->create_storage_asset_buffer(material_buffer_size);
+
+ brx_staging_upload_buffer *const material_staging_upload_buffer = device->create_staging_upload_buffer(material_buffer_size);
+
+ staging_upload_buffers.push_back(material_staging_upload_buffer);
+
+ std::memcpy(material_staging_upload_buffer->get_host_memory_range_base(), &gbuffer_pipeline_per_mesh_subset_update_set_geometry_material_storage_buffer_binding_destination, material_buffer_size);
+
+ upload_command_buffer->upload_from_staging_upload_buffer_to_storage_asset_buffer(out_subset.m_material_buffer, 0U, material_staging_upload_buffer, 0U, material_buffer_size);
+ }
+
+ {
+ uint32_t const staging_upload_buffer_offset_alignment = device->get_staging_upload_buffer_offset_alignment();
+ uint32_t const staging_upload_buffer_row_pitch_alignment = device->get_staging_upload_buffer_row_pitch_alignment();
+
+ std::string const *const meterial_texture_image_uris[] = {
+ &in_subset_data.m_normal_texture_image_uri,
+ &in_subset_data.m_emissive_texture_image_uri,
+ &in_subset_data.m_base_color_texture_image_uri,
+ &in_subset_data.m_metallic_roughness_texture_image_uri};
+
+ for (uint32_t mesh_subset_meterial_texture_index = 0U; mesh_subset_meterial_texture_index < DEMO_MESH_SUBSET_METERIAL_TEXTURE_COUNT; ++mesh_subset_meterial_texture_index)
+ {
+ std::string const &meterial_texture_image_uri = (*meterial_texture_image_uris[mesh_subset_meterial_texture_index]);
+
+ if (!meterial_texture_image_uri.empty())
+ {
+ std::string image_asset_file_name_dds;
+ std::string image_asset_file_name_pvr;
+ {
+ std::string image_asset_file_name;
+
+ size_t dir_name_pos = file_name.find_last_of("/\\");
+ if (std::string::npos != dir_name_pos)
+ {
+ image_asset_file_name = file_name.substr(0U, dir_name_pos + 1U);
+ }
+ else
+ {
+ image_asset_file_name += "./";
+ }
+
+ size_t ext_name_pos = meterial_texture_image_uri.find_last_of(".");
+ if (std::string::npos != ext_name_pos)
+ {
+ image_asset_file_name += meterial_texture_image_uri.substr(0U, ext_name_pos + 1U);
+ }
+ else
+ {
+ image_asset_file_name += meterial_texture_image_uri;
+ }
+
+ image_asset_file_name_dds = (image_asset_file_name + "dds");
+ image_asset_file_name_pvr = (image_asset_file_name + "pvr");
+ }
+
+ import_asset_input_stream *import_image_asset_input_stream;
+ bool (*pfn_import_image_asset_header_from_input_stream)(import_asset_input_stream *, BRX_SAMPLED_ASSET_IMAGE_IMPORT_HEADER *, size_t *);
+ bool (*pfn_import_image_asset_data_from_input_stream)(import_asset_input_stream *, BRX_SAMPLED_ASSET_IMAGE_IMPORT_HEADER const *, size_t, void *, size_t, BRX_SAMPLED_ASSET_IMAGE_IMPORT_SUBRESOURCE_MEMCPY_DEST const *);
+ if (device->is_sampled_asset_image_compression_bc_supported() && (NULL != (import_image_asset_input_stream = input_stream_factory->create_instance(image_asset_file_name_dds.c_str()))))
+ {
+ pfn_import_image_asset_header_from_input_stream = import_dds_image_asset_header_from_input_stream;
+ pfn_import_image_asset_data_from_input_stream = import_dds_image_asset_data_from_input_stream;
+ }
+ else if (device->is_sampled_asset_image_compression_astc_supported() && (NULL != (import_image_asset_input_stream = input_stream_factory->create_instance(image_asset_file_name_pvr.c_str()))))
+ {
+ pfn_import_image_asset_header_from_input_stream = import_pvr_image_asset_header_from_input_stream;
+ pfn_import_image_asset_data_from_input_stream = import_pvr_image_asset_data_from_input_stream;
+ }
+ else
+ {
+ // TODO: jpeg
+ // TODO: png
+ import_image_asset_input_stream = NULL;
+ pfn_import_image_asset_header_from_input_stream = NULL;
+ pfn_import_image_asset_data_from_input_stream = NULL;
+ }
+
+ if (NULL != import_image_asset_input_stream && NULL != pfn_import_image_asset_header_from_input_stream && NULL != pfn_import_image_asset_data_from_input_stream)
+ {
+ BRX_SAMPLED_ASSET_IMAGE_IMPORT_HEADER image_asset_header;
+ std::vector subresource_memcpy_dests;
+
+ size_t image_asset_data_offset;
+ bool const res_import_image_asset_header = pfn_import_image_asset_header_from_input_stream(import_image_asset_input_stream, &image_asset_header, &image_asset_data_offset);
+ assert(res_import_image_asset_header);
+
+ uint32_t const subresource_count = image_asset_header.mip_levels;
+ subresource_memcpy_dests.resize(subresource_count);
+
+ // TODO: support more image paramters
+ assert(!image_asset_header.is_cube_map);
+ assert(BRX_SAMPLED_ASSET_IMAGE_TYPE_2D == image_asset_header.type);
+ assert(1U == image_asset_header.depth);
+ assert(1U == image_asset_header.array_layers);
+ uint32_t const total_bytes = brx_sampled_asset_image_import_calculate_subresource_memcpy_dests(image_asset_header.format, image_asset_header.width, image_asset_header.height, 1U, image_asset_header.mip_levels, 1U, 0U, staging_upload_buffer_offset_alignment, staging_upload_buffer_row_pitch_alignment, subresource_count, &subresource_memcpy_dests[0]);
+ brx_staging_upload_buffer *const image_staging_upload_buffer = device->create_staging_upload_buffer(static_cast(total_bytes));
+ staging_upload_buffers.push_back(image_staging_upload_buffer);
+
+ bool const res_import_image_asset_data = pfn_import_image_asset_data_from_input_stream(import_image_asset_input_stream, &image_asset_header, image_asset_data_offset, image_staging_upload_buffer->get_host_memory_range_base(), subresource_count, &subresource_memcpy_dests[0]);
+ assert(res_import_image_asset_data);
+
+ input_stream_factory->destory_instance(import_image_asset_input_stream);
+
+ out_subset.m_material_textures[mesh_subset_meterial_texture_index] = device->create_sampled_asset_image(image_asset_header.format, image_asset_header.width, image_asset_header.height, image_asset_header.mip_levels);
+
+ for (uint32_t mip_level = 0U; mip_level < image_asset_header.mip_levels; ++mip_level)
+ {
+ upload_command_buffer->upload_from_staging_upload_buffer_to_sampled_asset_image(out_subset.m_material_textures[mesh_subset_meterial_texture_index], image_asset_header.format, image_asset_header.width, image_asset_header.height, mip_level, image_staging_upload_buffer, subresource_memcpy_dests[mip_level].staging_upload_buffer_offset, subresource_memcpy_dests[mip_level].output_row_pitch, subresource_memcpy_dests[mip_level].output_row_count);
+ }
+ }
+ else
+ {
+ out_subset.m_material_textures[mesh_subset_meterial_texture_index] = NULL;
+ }
+ }
+ else
+ {
+ out_subset.m_material_textures[mesh_subset_meterial_texture_index] = NULL;
+ }
+ }
+ }
+ }
+
+ out_mesh.m_instances.resize(total_mesh_data[mesh_index].m_instances.size());
+
+ for (size_t instance_index = 0U; instance_index < total_mesh_data[mesh_index].m_instances.size(); ++instance_index)
+ {
+ scene_mesh_instance_data &in_instance_data = total_mesh_data[mesh_index].m_instances[instance_index];
+
+ Demo_Mesh_Instance &out_mesh_instance = out_mesh.m_instances[instance_index];
+
+ out_mesh_instance.m_model_transform = std::move(in_instance_data.m_model_transform);
+ out_mesh_instance.m_animation_skeleton = std::move(in_instance_data.m_animation_skeleton);
+
+ if (!in_mesh_data.m_skinned)
+ {
+ assert(out_mesh_instance.m_subsets.empty());
+ }
+ else
+ {
+ out_mesh_instance.m_subsets.resize(in_mesh_data.m_subsets.size());
+
+ for (size_t subset_index = 0U; subset_index < in_mesh_data.m_subsets.size(); ++subset_index)
+ {
+ scene_mesh_subset_data const &in_subset_data = in_mesh_data.m_subsets[subset_index];
+
+ Demo_Mesh_Skinned_Subset &out_mesh_skinned_subset = out_mesh_instance.m_subsets[subset_index];
+
+ uint32_t const vertex_count = static_cast(in_subset_data.m_vertex_position_binding.size());
+
+ uint32_t const vertex_position_buffer_size = sizeof(scene_mesh_vertex_position_binding) * vertex_count;
+
+ out_mesh_skinned_subset.m_skinned_vertex_position_buffer = device->create_storage_intermediate_buffer(vertex_position_buffer_size);
+
+ assert(vertex_count == in_subset_data.m_vertex_varying_binding.size());
+
+ uint32_t const vertex_varying_buffer_size = sizeof(scene_mesh_vertex_varying_binding) * vertex_count;
+
+ out_mesh_skinned_subset.m_skinned_vertex_varying_buffer = device->create_storage_intermediate_buffer(vertex_varying_buffer_size);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ import_asset_destroy_file_input_stream_factory(input_stream_factory);
+ input_stream_factory = NULL;
+
+ // Place Holder Texture
+ {
+ uint32_t const staging_upload_buffer_offset_alignment = device->get_staging_upload_buffer_offset_alignment();
+ uint32_t const staging_upload_buffer_row_pitch_alignment = device->get_staging_upload_buffer_row_pitch_alignment();
+
+ BRX_SAMPLED_ASSET_IMAGE_FORMAT const format = BRX_SAMPLED_ASSET_IMAGE_FORMAT_R8G8B8A8_UNORM;
+ uint32_t const width = 1U;
+ uint32_t const height = 1U;
+ uint32_t const mip_levels = 1U;
+ this->m_place_holder_texture = device->create_sampled_asset_image(format, width, height, mip_levels);
+
+ std::vector subresource_memcpy_dests;
+ uint32_t const subresource_count = mip_levels;
+ subresource_memcpy_dests.resize(subresource_count);
+
+ uint32_t total_bytes = brx_sampled_asset_image_import_calculate_subresource_memcpy_dests(format, width, height, 1U, mip_levels, 1U, 0U, staging_upload_buffer_offset_alignment, staging_upload_buffer_row_pitch_alignment, subresource_count, &subresource_memcpy_dests[0]);
+ brx_staging_upload_buffer *place_holder_image_staging_upload_buffer = device->create_staging_upload_buffer(total_bytes);
+
+ staging_upload_buffers.push_back(place_holder_image_staging_upload_buffer);
+
+ uint32_t const mip_level = 0U;
+ uint32_t const subresource_index = brx_sampled_asset_image_import_calculate_subresource_index(mip_level, 0U, 0U, mip_levels, 1U);
+ for (uint32_t output_slice_index = 0U; output_slice_index < subresource_memcpy_dests[mip_level].output_slice_count; ++output_slice_index)
+ {
+ for (uint32_t output_row_index = 0U; output_row_index < subresource_memcpy_dests[mip_level].output_row_count; ++output_row_index)
+ {
+ void *destination = reinterpret_cast(reinterpret_cast(place_holder_image_staging_upload_buffer->get_host_memory_range_base()) + (subresource_memcpy_dests[subresource_index].staging_upload_buffer_offset + subresource_memcpy_dests[subresource_index].output_slice_pitch * output_slice_index + subresource_memcpy_dests[subresource_index].output_row_pitch * output_row_index));
+
+ std::memset(destination, 0, subresource_memcpy_dests[mip_level].output_row_size);
+ }
+ }
+
+ upload_command_buffer->upload_from_staging_upload_buffer_to_sampled_asset_image(this->m_place_holder_texture, format, width, height, mip_level, place_holder_image_staging_upload_buffer, subresource_memcpy_dests[mip_level].staging_upload_buffer_offset, subresource_memcpy_dests[mip_level].output_row_pitch, subresource_memcpy_dests[mip_level].output_row_count);
+ }
+
+ // store
+ // release
+ // acquire
+ {
+ std::vector uploaded_storage_asset_buffers;
+ std::vector uploaded_sampled_asset_images;
+ std::vector uploaded_destination_mip_levels;
+
+ // Asset
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh const &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Subset const &scene_mesh_subset = scene_mesh.m_subsets[subset_index];
+
+ uploaded_storage_asset_buffers.push_back(scene_mesh_subset.m_vertex_position_buffer);
+
+ uploaded_storage_asset_buffers.push_back(scene_mesh_subset.m_vertex_varying_buffer);
+
+ if (scene_mesh.m_skinned)
+ {
+ uploaded_storage_asset_buffers.push_back(scene_mesh_subset.m_vertex_joint_buffer);
+ }
+
+ uploaded_storage_asset_buffers.push_back(scene_mesh_subset.m_index_buffer);
+
+ uploaded_storage_asset_buffers.push_back(scene_mesh_subset.m_material_buffer);
+
+ for (uint32_t mesh_subset_meterial_texture_index = 0U; mesh_subset_meterial_texture_index < DEMO_MESH_SUBSET_METERIAL_TEXTURE_COUNT; ++mesh_subset_meterial_texture_index)
+ {
+ brx_sampled_asset_image *const material_texture = scene_mesh_subset.m_material_textures[mesh_subset_meterial_texture_index];
+
+ if (NULL != material_texture)
+ {
+ uint32_t const mip_level_count = material_texture->get_mip_levels();
+
+ for (uint32_t mip_level = 0U; mip_level < mip_level_count; ++mip_level)
+ {
+ uploaded_sampled_asset_images.push_back(material_texture);
+
+ uploaded_destination_mip_levels.push_back(mip_level);
+ }
+ }
+ }
+ }
+ }
+
+ // Place Holder Texture
+ {
+ uploaded_sampled_asset_images.push_back(this->m_place_holder_texture);
+
+ uploaded_destination_mip_levels.push_back(0U);
+ }
+
+ assert(uploaded_sampled_asset_images.size() == uploaded_destination_mip_levels.size());
+
+ upload_command_buffer->release(static_cast(uploaded_storage_asset_buffers.size()), uploaded_storage_asset_buffers.data(), static_cast(uploaded_sampled_asset_images.size()), &uploaded_sampled_asset_images[0], uploaded_destination_mip_levels.data(), 0U, NULL);
+
+ graphics_command_buffer->acquire(static_cast(uploaded_storage_asset_buffers.size()), uploaded_storage_asset_buffers.data(), static_cast(uploaded_sampled_asset_images.size()), &uploaded_sampled_asset_images[0], uploaded_destination_mip_levels.data(), 0U, NULL);
+ }
+
+ upload_command_buffer->end();
+
+ graphics_command_buffer->end();
+
+ upload_queue->submit_and_signal(upload_command_buffer);
+
+ device->reset_fence(fence);
+
+ graphics_queue->wait_and_submit(upload_command_buffer, graphics_command_buffer, fence);
+
+ device->wait_for_fence(fence);
+
+ for (brx_staging_upload_buffer *const staging_upload_buffer : staging_upload_buffers)
+ {
+ device->destroy_staging_upload_buffer(staging_upload_buffer);
+ }
+
+ staging_upload_buffers.clear();
+ }
+
+ device->destroy_fence(fence);
+
+ device->destroy_upload_command_buffer(upload_command_buffer);
+
+ device->destroy_graphics_command_buffer(graphics_command_buffer);
+
+ device->destroy_upload_queue(upload_queue);
+
+ device->destroy_graphics_queue(graphics_queue);
+ }
+
+ // Sampler
+ {
+ this->m_sampler = device->create_sampler(BRX_SAMPLER_FILTER_LINEAR);
+ }
+
+ // Uniform Buffer
+ {
+ this->m_uniform_upload_buffer_offset_alignment = device->get_uniform_upload_buffer_offset_alignment();
+
+ this->m_common_none_update_uniform_buffer = device->create_uniform_upload_buffer(tbb_align_up(static_cast(sizeof(common_none_update_set_uniform_buffer_binding)), this->m_uniform_upload_buffer_offset_alignment) * FRAME_THROTTLING_COUNT);
+
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ if (!scene_mesh.m_skinned)
+ {
+ scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_uniform_buffer = NULL;
+ }
+ else
+ {
+ scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_uniform_buffer = device->create_uniform_upload_buffer(tbb_align_up(static_cast(sizeof(skin_pipeline_per_mesh_instance_update_set_uniform_buffer_binding)), this->m_uniform_upload_buffer_offset_alignment) * FRAME_THROTTLING_COUNT);
+ }
+
+ scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_uniform_buffer = device->create_uniform_upload_buffer(tbb_align_up(static_cast(sizeof(gbuffer_pipeline_per_mesh_instance_update_set_uniform_buffer_binding)), this->m_uniform_upload_buffer_offset_alignment) * FRAME_THROTTLING_COUNT);
+ }
+ }
+ }
+
+ // Descriptor
+ {
+ // GBuffer Pipeline
+ {
+ {
+ this->m_gbuffer_pipeline_none_update_descriptor_set = device->create_descriptor_set(gbuffer_pipeline_none_update_descriptor_set_layout);
+
+ constexpr uint32_t const dynamic_uniform_buffers_range = sizeof(common_none_update_set_uniform_buffer_binding);
+ device->write_descriptor_set(this->m_gbuffer_pipeline_none_update_descriptor_set, 0U, BRX_DESCRIPTOR_TYPE_DYNAMIC_UNIFORM_BUFFER, 0U, 1U, &this->m_common_none_update_uniform_buffer, &dynamic_uniform_buffers_range, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ device->write_descriptor_set(this->m_gbuffer_pipeline_none_update_descriptor_set, 1U, BRX_DESCRIPTOR_TYPE_SAMPLER, 0U, 1U, NULL, NULL, NULL, NULL, NULL, NULL, &this->m_sampler, NULL);
+ }
+
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ if (!scene_mesh.m_skinned)
+ {
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Subset &scene_mesh_subset = scene_mesh.m_subsets[subset_index];
+
+ scene_mesh_subset.m_gbuffer_pipeline_per_mesh_subset_update_descriptor_set = device->create_descriptor_set(gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout);
+
+ brx_read_only_storage_buffer const *const read_only_storage_buffers[] = {
+ scene_mesh_subset.m_vertex_position_buffer->get_read_only_storage_buffer(),
+ scene_mesh_subset.m_vertex_varying_buffer->get_read_only_storage_buffer(),
+ scene_mesh_subset.m_index_buffer->get_read_only_storage_buffer(),
+ scene_mesh_subset.m_material_buffer->get_read_only_storage_buffer()};
+ device->write_descriptor_set(scene_mesh_subset.m_gbuffer_pipeline_per_mesh_subset_update_descriptor_set, 0U, BRX_DESCRIPTOR_TYPE_READ_ONLY_STORAGE_BUFFER, 0U, sizeof(read_only_storage_buffers) / sizeof(read_only_storage_buffers[0]), NULL, NULL, read_only_storage_buffers, NULL, NULL, NULL, NULL, NULL);
+
+ brx_sampled_image const *sample_images[DEMO_MESH_SUBSET_METERIAL_TEXTURE_COUNT];
+ for (uint32_t mesh_subset_meterial_texture_index = 0U; mesh_subset_meterial_texture_index < DEMO_MESH_SUBSET_METERIAL_TEXTURE_COUNT; ++mesh_subset_meterial_texture_index)
+ {
+ brx_sampled_asset_image *material_texture = scene_mesh_subset.m_material_textures[mesh_subset_meterial_texture_index];
+
+ sample_images[mesh_subset_meterial_texture_index] = (NULL != material_texture) ? material_texture->get_sampled_image() : this->m_place_holder_texture->get_sampled_image();
+ }
+ device->write_descriptor_set(scene_mesh_subset.m_gbuffer_pipeline_per_mesh_subset_update_descriptor_set, 4U, BRX_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0U, sizeof(sample_images) / sizeof(sample_images[0]), NULL, NULL, NULL, NULL, sample_images, NULL, NULL, NULL);
+ }
+
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ assert(scene_mesh_instance.m_subsets.empty());
+
+ scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_descriptor_set = NULL;
+
+ scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_descriptor_set = device->create_descriptor_set(gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout);
+
+ constexpr uint32_t const dynamic_uniform_buffers_range = sizeof(gbuffer_pipeline_per_mesh_instance_update_set_uniform_buffer_binding);
+ device->write_descriptor_set(scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_descriptor_set, 0U, BRX_DESCRIPTOR_TYPE_DYNAMIC_UNIFORM_BUFFER, 0U, 1U, &scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_uniform_buffer, &dynamic_uniform_buffers_range, NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+ }
+ else
+ {
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Subset &scene_mesh_subset = scene_mesh.m_subsets[subset_index];
+
+ scene_mesh_subset.m_gbuffer_pipeline_per_mesh_subset_update_descriptor_set = NULL;
+ }
+
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ assert(scene_mesh.m_subsets.size() == scene_mesh_instance.m_subsets.size());
+
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Subset const &scene_mesh_subset = scene_mesh.m_subsets[subset_index];
+
+ Demo_Mesh_Skinned_Subset &scene_mesh_skinned_subset = scene_mesh_instance.m_subsets[subset_index];
+
+ {
+ scene_mesh_skinned_subset.m_skin_pipeline_per_mesh_skinned_subset_update_descriptor_set = device->create_descriptor_set(skin_pipeline_per_mesh_skinned_subset_update_descriptor_set_layout);
+
+ brx_read_only_storage_buffer const *const read_only_storage_buffers[] = {
+ scene_mesh_subset.m_vertex_position_buffer->get_read_only_storage_buffer(),
+ scene_mesh_subset.m_vertex_varying_buffer->get_read_only_storage_buffer(),
+ scene_mesh_subset.m_vertex_joint_buffer->get_read_only_storage_buffer()};
+ device->write_descriptor_set(scene_mesh_skinned_subset.m_skin_pipeline_per_mesh_skinned_subset_update_descriptor_set, 0U, BRX_DESCRIPTOR_TYPE_READ_ONLY_STORAGE_BUFFER, 0U, sizeof(read_only_storage_buffers) / sizeof(read_only_storage_buffers[0]), NULL, NULL, read_only_storage_buffers, NULL, NULL, NULL, NULL, NULL);
+
+ brx_storage_buffer const *const storage_buffers[] = {
+ scene_mesh_skinned_subset.m_skinned_vertex_position_buffer->get_storage_buffer(),
+ scene_mesh_skinned_subset.m_skinned_vertex_varying_buffer->get_storage_buffer()};
+ device->write_descriptor_set(scene_mesh_skinned_subset.m_skin_pipeline_per_mesh_skinned_subset_update_descriptor_set, 1U, BRX_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0U, sizeof(storage_buffers) / sizeof(storage_buffers[0]), NULL, NULL, NULL, storage_buffers, NULL, NULL, NULL, NULL);
+ }
+
+ {
+ scene_mesh_skinned_subset.m_gbuffer_pipeline_per_mesh_skinned_subset_update_descriptor_set = device->create_descriptor_set(gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout);
+
+ brx_read_only_storage_buffer const *const read_only_storage_buffers[] = {
+ scene_mesh_skinned_subset.m_skinned_vertex_position_buffer->get_read_only_storage_buffer(),
+ scene_mesh_skinned_subset.m_skinned_vertex_varying_buffer->get_read_only_storage_buffer(),
+ scene_mesh_subset.m_index_buffer->get_read_only_storage_buffer(),
+ scene_mesh_subset.m_material_buffer->get_read_only_storage_buffer()};
+ device->write_descriptor_set(scene_mesh_skinned_subset.m_gbuffer_pipeline_per_mesh_skinned_subset_update_descriptor_set, 0U, BRX_DESCRIPTOR_TYPE_READ_ONLY_STORAGE_BUFFER, 0U, sizeof(read_only_storage_buffers) / sizeof(read_only_storage_buffers[0]), NULL, NULL, read_only_storage_buffers, NULL, NULL, NULL, NULL, NULL);
+
+ brx_sampled_image const *sample_images[DEMO_MESH_SUBSET_METERIAL_TEXTURE_COUNT];
+ for (uint32_t mesh_subset_meterial_texture_index = 0U; mesh_subset_meterial_texture_index < DEMO_MESH_SUBSET_METERIAL_TEXTURE_COUNT; ++mesh_subset_meterial_texture_index)
+ {
+ brx_sampled_asset_image *material_texture = scene_mesh_subset.m_material_textures[mesh_subset_meterial_texture_index];
+
+ sample_images[mesh_subset_meterial_texture_index] = (NULL != material_texture) ? material_texture->get_sampled_image() : this->m_place_holder_texture->get_sampled_image();
+ }
+ device->write_descriptor_set(scene_mesh_skinned_subset.m_gbuffer_pipeline_per_mesh_skinned_subset_update_descriptor_set, 4U, BRX_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0U, sizeof(sample_images) / sizeof(sample_images[0]), NULL, NULL, NULL, NULL, sample_images, NULL, NULL, NULL);
+ }
+ }
+
+ {
+ scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_descriptor_set = device->create_descriptor_set(skin_pipeline_per_mesh_instance_update_descriptor_set_layout);
+
+ constexpr uint32_t const dynamic_uniform_buffers_range = sizeof(skin_pipeline_per_mesh_instance_update_set_uniform_buffer_binding);
+ device->write_descriptor_set(scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_descriptor_set, 0U, BRX_DESCRIPTOR_TYPE_DYNAMIC_UNIFORM_BUFFER, 0U, 1U, &scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_uniform_buffer, &dynamic_uniform_buffers_range, NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+
+ {
+ scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_descriptor_set = device->create_descriptor_set(gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout);
+
+ constexpr uint32_t const dynamic_uniform_buffers_range = sizeof(gbuffer_pipeline_per_mesh_instance_update_set_uniform_buffer_binding);
+ device->write_descriptor_set(scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_descriptor_set, 0U, BRX_DESCRIPTOR_TYPE_DYNAMIC_UNIFORM_BUFFER, 0U, 1U, &scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_uniform_buffer, &dynamic_uniform_buffers_range, NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+ }
+ }
+ }
+ }
+
+ // Deferred Shading Pipeline
+ {
+ {
+ this->m_deferred_shading_pipeline_none_update_descriptor_set = device->create_descriptor_set(this->m_deferred_shading_pipeline_none_update_descriptor_set_layout);
+
+ constexpr uint32_t const dynamic_uniform_buffers_range = sizeof(common_none_update_set_uniform_buffer_binding);
+ device->write_descriptor_set(this->m_deferred_shading_pipeline_none_update_descriptor_set, 0U, BRX_DESCRIPTOR_TYPE_DYNAMIC_UNIFORM_BUFFER, 0U, 1U, &this->m_common_none_update_uniform_buffer, &dynamic_uniform_buffers_range, NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+ }
+ }
+
+ device->destroy_descriptor_set_layout(skin_pipeline_per_mesh_instance_update_descriptor_set_layout);
+ skin_pipeline_per_mesh_instance_update_descriptor_set_layout = NULL;
+ device->destroy_descriptor_set_layout(skin_pipeline_per_mesh_skinned_subset_update_descriptor_set_layout);
+ skin_pipeline_per_mesh_skinned_subset_update_descriptor_set_layout = NULL;
+ device->destroy_descriptor_set_layout(gbuffer_pipeline_none_update_descriptor_set_layout);
+ gbuffer_pipeline_none_update_descriptor_set_layout = NULL;
+ device->destroy_descriptor_set_layout(gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout);
+ gbuffer_pipeline_per_mesh_subset_update_descriptor_set_layout = NULL;
+ device->destroy_descriptor_set_layout(gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout);
+ gbuffer_pipeline_per_mesh_instance_update_descriptor_set_layout = NULL;
+
+ // Init Intermediate Images
+ this->m_intermediate_width = 0U;
+ this->m_intermediate_height = 0U;
+ this->m_gbuffer_color_attachment = NULL;
+ this->m_gbuffer_depth_attachment = NULL;
+ this->m_deferred_shading_color_attachment = NULL;
+ this->m_gbuffer_frame_buffer = NULL;
+ this->m_deferred_shading_frame_buffer = NULL;
+
+ // Init Camera
+ g_camera_controller.m_eye_position = DirectX::XMFLOAT3(0.0F, 1.3F, 1.0F);
+ g_camera_controller.m_eye_direction = DirectX::XMFLOAT3(0.0F, -0.36F, -0.98F);
+ g_camera_controller.m_up_direction = DirectX::XMFLOAT3(0.0F, 1.0F, 0.0F);
+ g_camera_fov = DirectX::XM_PI * (1.0F / 3.0F);
+
+ // Init Animation Time
+ this->m_animation_time = 0.0F;
+}
+
+void Demo::destroy(brx_device *device)
+{
+ // Descriptor
+ {
+ // GBuffer Pipeline
+ {
+ device->destroy_descriptor_set(this->m_gbuffer_pipeline_none_update_descriptor_set);
+
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ if (!scene_mesh.m_skinned)
+ {
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Subset &scene_mesh_subset = scene_mesh.m_subsets[subset_index];
+
+ device->destroy_descriptor_set(scene_mesh_subset.m_gbuffer_pipeline_per_mesh_subset_update_descriptor_set);
+ }
+
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ assert(scene_mesh_instance.m_subsets.empty());
+
+ assert(NULL == scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_descriptor_set);
+
+ device->destroy_descriptor_set(scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_descriptor_set);
+ }
+ }
+ else
+ {
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Subset &scene_mesh_subset = scene_mesh.m_subsets[subset_index];
+
+ assert(NULL == scene_mesh_subset.m_gbuffer_pipeline_per_mesh_subset_update_descriptor_set);
+ }
+
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Skinned_Subset &scene_mesh_skinned_subset = scene_mesh_instance.m_subsets[subset_index];
+
+ device->destroy_descriptor_set(scene_mesh_skinned_subset.m_skin_pipeline_per_mesh_skinned_subset_update_descriptor_set);
+
+ device->destroy_descriptor_set(scene_mesh_skinned_subset.m_gbuffer_pipeline_per_mesh_skinned_subset_update_descriptor_set);
+ }
+
+ device->destroy_descriptor_set(scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_descriptor_set);
+
+ device->destroy_descriptor_set(scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_descriptor_set);
+ }
+ }
+ }
+ }
+
+ // Deferred Shading Pipeline
+ {
+ device->destroy_descriptor_set_layout(this->m_deferred_shading_pipeline_none_update_descriptor_set_layout);
+
+ device->destroy_descriptor_set(this->m_deferred_shading_pipeline_none_update_descriptor_set);
+ }
+ }
+
+ // Uniform Buffer
+ {
+ device->destroy_uniform_upload_buffer(this->m_common_none_update_uniform_buffer);
+
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ if (!scene_mesh.m_skinned)
+ {
+ assert(NULL == scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_uniform_buffer);
+ }
+ else
+ {
+ device->destroy_uniform_upload_buffer(scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_uniform_buffer);
+ }
+
+ device->destroy_uniform_upload_buffer(scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_uniform_buffer);
+ }
+ }
+ }
+
+ // Sampler
+ {
+ device->destroy_sampler(this->m_sampler);
+ }
+
+ // Place Holder Texture
+ {
+ device->destroy_sampled_asset_image(this->m_place_holder_texture);
+ }
+
+ // Asset
+ {
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Subset &scene_mesh_subset = scene_mesh.m_subsets[subset_index];
+
+ device->destroy_storage_asset_buffer(scene_mesh_subset.m_vertex_position_buffer);
+
+ device->destroy_storage_asset_buffer(scene_mesh_subset.m_vertex_varying_buffer);
+
+ if (scene_mesh.m_skinned)
+ {
+ device->destroy_storage_asset_buffer(scene_mesh_subset.m_vertex_joint_buffer);
+ }
+ else
+ {
+ assert(NULL == scene_mesh_subset.m_vertex_joint_buffer);
+ }
+
+ device->destroy_storage_asset_buffer(scene_mesh_subset.m_index_buffer);
+
+ device->destroy_storage_asset_buffer(scene_mesh_subset.m_material_buffer);
+
+ for (uint32_t mesh_subset_meterial_texture_index = 0U; mesh_subset_meterial_texture_index < DEMO_MESH_SUBSET_METERIAL_TEXTURE_COUNT; ++mesh_subset_meterial_texture_index)
+ {
+ brx_sampled_asset_image *const material_texture = scene_mesh_subset.m_material_textures[mesh_subset_meterial_texture_index];
+
+ if (NULL != material_texture)
+ {
+ device->destroy_sampled_asset_image(material_texture);
+ }
+ }
+ }
+
+ if (!scene_mesh.m_skinned)
+ {
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ assert(scene_mesh_instance.m_subsets.empty());
+ }
+ }
+ else
+ {
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Skinned_Subset &scene_mesh_skinned_subset = scene_mesh_instance.m_subsets[subset_index];
+
+ device->destroy_storage_intermediate_buffer(scene_mesh_skinned_subset.m_skinned_vertex_position_buffer);
+
+ device->destroy_storage_intermediate_buffer(scene_mesh_skinned_subset.m_skinned_vertex_varying_buffer);
+ }
+ }
+ }
+ }
+ }
+
+ // Render Pass and Pipeline
+ {
+ device->destroy_graphics_pipeline(this->m_gbuffer_pipeline);
+
+ device->destroy_pipeline_layout(this->m_gbuffer_pipeline_layout);
+
+ device->destroy_render_pass(this->m_gbuffer_render_pass);
+
+ device->destroy_graphics_pipeline(this->m_deferred_shading_pipeline);
+
+ device->destroy_pipeline_layout(this->m_deferred_shading_pipeline_layout);
+
+ device->destroy_render_pass(this->m_deferred_shading_render_pass);
+
+ device->destroy_compute_pipeline(this->m_skin_pipeline);
+
+ device->destroy_pipeline_layout(this->m_skin_pipeline_layout);
+ }
+}
+
+void Demo::on_swap_chain_attach(brx_device *device, uint32_t swap_chain_image_width, uint32_t swap_chain_image_height)
+{
+ assert(0U == this->m_intermediate_width);
+ assert(0U == this->m_intermediate_height);
+
+ this->m_intermediate_width = swap_chain_image_width;
+ this->m_intermediate_height = swap_chain_image_height;
+
+ // Intermediate Images
+ {
+ assert(NULL == this->m_gbuffer_color_attachment);
+ assert(NULL == this->m_gbuffer_depth_attachment);
+ assert(NULL == this->m_deferred_shading_color_attachment);
+
+ this->m_gbuffer_color_attachment = device->create_color_attachment_image(this->m_gbuffer_color_attachement_format, this->m_intermediate_width, this->m_intermediate_height, true);
+ this->m_gbuffer_depth_attachment = device->create_depth_stencil_attachment_image(this->m_gbuffer_depth_attachement_format, this->m_intermediate_width, this->m_intermediate_height, true);
+ this->m_deferred_shading_color_attachment = device->create_color_attachment_image(this->m_deferred_shading_color_attachement_format, this->m_intermediate_width, this->m_intermediate_height, true);
+ }
+
+ // Frame Buffer
+ {
+ assert(NULL == this->m_gbuffer_frame_buffer);
+ assert(NULL == this->m_deferred_shading_frame_buffer);
+
+ this->m_gbuffer_frame_buffer = device->create_frame_buffer(this->m_gbuffer_render_pass, this->m_intermediate_width, this->m_intermediate_height, 1U, &this->m_gbuffer_color_attachment, this->m_gbuffer_depth_attachment);
+ this->m_deferred_shading_frame_buffer = device->create_frame_buffer(this->m_deferred_shading_render_pass, this->m_intermediate_width, this->m_intermediate_height, 1U, &this->m_deferred_shading_color_attachment, NULL);
+ }
+
+ // Descriptor
+ {
+ // Deferred Shading Pipeline
+ {
+ // The VkDescriptorSetLayout should still be valid when perform write update on VkDescriptorSet
+ assert(NULL != this->m_deferred_shading_pipeline_none_update_descriptor_set_layout);
+ {
+ {
+ brx_sampled_image const *const sampled_images[] = {
+ this->m_gbuffer_color_attachment->get_sampled_image()};
+ device->write_descriptor_set(this->m_deferred_shading_pipeline_none_update_descriptor_set, 1U, BRX_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0U, sizeof(sampled_images) / sizeof(sampled_images[0]), NULL, NULL, NULL, NULL, sampled_images, NULL, NULL, NULL);
+ }
+
+ {
+ brx_sampled_image const *const sampled_images[] = {
+ this->m_gbuffer_depth_attachment->get_sampled_image()};
+ device->write_descriptor_set(this->m_deferred_shading_pipeline_none_update_descriptor_set, 2U, BRX_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0U, sizeof(sampled_images) / sizeof(sampled_images[0]), NULL, NULL, NULL, NULL, sampled_images, NULL, NULL, NULL);
+ }
+ }
+ }
+ }
+}
+
+brx_sampled_image const *Demo::get_sampled_image_for_present()
+{
+ return this->m_deferred_shading_color_attachment->get_sampled_image();
+}
+
+void Demo::on_swap_chain_dettach(brx_device *device)
+{
+ device->destroy_frame_buffer(this->m_gbuffer_frame_buffer);
+ device->destroy_frame_buffer(this->m_deferred_shading_frame_buffer);
+
+ this->m_gbuffer_frame_buffer = NULL;
+ this->m_deferred_shading_frame_buffer = NULL;
+
+ device->destroy_color_attachment_image(this->m_deferred_shading_color_attachment);
+ device->destroy_depth_stencil_attachment_image(this->m_gbuffer_depth_attachment);
+ device->destroy_color_attachment_image(this->m_gbuffer_color_attachment);
+
+ this->m_deferred_shading_color_attachment = NULL;
+ this->m_gbuffer_depth_attachment = NULL;
+ this->m_gbuffer_color_attachment = NULL;
+
+ this->m_intermediate_width = 0U;
+ this->m_intermediate_height = 0U;
+}
+
+void Demo::draw(brx_graphics_command_buffer *command_buffer, float interval_time, uint32_t frame_throttling_index)
+{
+ // Update Uniform Buffer
+ {
+ // Skin Pipeline - Per Mesh Instance Update
+ {
+ this->m_animation_time += interval_time;
+
+ // 60 FPS
+ size_t animetion_frame_index = static_cast(60.0 * this->m_animation_time);
+
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh const &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ if (scene_mesh.m_skinned)
+ {
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance const &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ skin_pipeline_per_mesh_instance_update_set_uniform_buffer_binding *const skin_pipeline_per_mesh_instance_update_set_uniform_buffer_binding_destination = reinterpret_cast(reinterpret_cast(scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_uniform_buffer->get_host_memory_range_base()) + tbb_align_up(static_cast(sizeof(skin_pipeline_per_mesh_instance_update_set_uniform_buffer_binding)), this->m_uniform_upload_buffer_offset_alignment) * frame_throttling_index);
+
+ scene_animation_pose const &pose = scene_mesh_instance.m_animation_skeleton.get_pose(animetion_frame_index);
+
+ assert(pose.get_joint_count() <= MAX_JOINT_COUNT);
+
+ for (uint32_t joint_index = 0U; joint_index < pose.get_joint_count(); ++joint_index)
+ {
+ unit_dual_quaternion_from_rigid_transform(&skin_pipeline_per_mesh_instance_update_set_uniform_buffer_binding_destination->g_dual_quaternions[2 * joint_index], pose.get_quaternion(joint_index), pose.get_translation(joint_index));
+ }
+ }
+ }
+ }
+ }
+
+ // Common - None Update (update frequency denotes the updating of the resource bindings instead of the data)
+ {
+ common_none_update_set_uniform_buffer_binding *const common_none_update_set_uniform_buffer_binding_destination = reinterpret_cast(reinterpret_cast(this->m_common_none_update_uniform_buffer->get_host_memory_range_base()) + tbb_align_up(static_cast(sizeof(common_none_update_set_uniform_buffer_binding)), this->m_uniform_upload_buffer_offset_alignment) * frame_throttling_index);
+
+ DirectX::XMFLOAT3 eye_position = g_camera_controller.m_eye_position;
+ DirectX::XMFLOAT3 eye_direction = g_camera_controller.m_eye_direction;
+ DirectX::XMFLOAT3 up_direction = g_camera_controller.m_up_direction;
+ DirectX::XMMATRIX view_transform = DirectX::XMMatrixLookToRH(DirectX::XMLoadFloat3(&eye_position), DirectX::XMLoadFloat3(&eye_direction), DirectX::XMLoadFloat3(&up_direction));
+ DirectX::XMMATRIX projection_transform = DirectX_Math_Matrix_PerspectiveFovRH_ReversedZ(g_camera_fov, static_cast(this->m_intermediate_width) / static_cast(this->m_intermediate_height), 0.1F, 1000.0F);
+
+ DirectX::XMStoreFloat4x4(&common_none_update_set_uniform_buffer_binding_destination->g_view_transform, view_transform);
+ DirectX::XMStoreFloat4x4(&common_none_update_set_uniform_buffer_binding_destination->g_projection_transform, projection_transform);
+ DirectX::XMStoreFloat4x4(&common_none_update_set_uniform_buffer_binding_destination->g_inverse_view_transform, DirectX::XMMatrixInverse(NULL, view_transform));
+ DirectX::XMStoreFloat4x4(&common_none_update_set_uniform_buffer_binding_destination->g_inverse_projection_transform, DirectX::XMMatrixInverse(NULL, projection_transform));
+
+ common_none_update_set_uniform_buffer_binding_destination->g_screen_width = static_cast(this->m_intermediate_width);
+ common_none_update_set_uniform_buffer_binding_destination->g_screen_height = static_cast(this->m_intermediate_height);
+ }
+
+ // GBuffer Pipeline - Per Mesh Instance Update
+ {
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh const &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance const &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ gbuffer_pipeline_per_mesh_instance_update_set_uniform_buffer_binding *const gbuffer_pipeline_per_mesh_instance_update_set_uniform_buffer_binding_destination = reinterpret_cast(reinterpret_cast(scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_uniform_buffer->get_host_memory_range_base()) + tbb_align_up(static_cast(sizeof(gbuffer_pipeline_per_mesh_instance_update_set_uniform_buffer_binding)), this->m_uniform_upload_buffer_offset_alignment) * frame_throttling_index);
+
+ gbuffer_pipeline_per_mesh_instance_update_set_uniform_buffer_binding_destination->g_model_transform = scene_mesh_instance.m_model_transform;
+ }
+ }
+ }
+ }
+
+ // Skin Pass
+ {
+ std::vector skinned_buffers;
+ // TODO: can we remove this traverse?
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh const &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ if (scene_mesh.m_skinned)
+ {
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance const &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Skinned_Subset const &scene_mesh_skinned_subset = scene_mesh_instance.m_subsets[subset_index];
+
+ skinned_buffers.push_back(scene_mesh_skinned_subset.m_skinned_vertex_position_buffer->get_storage_buffer());
+ skinned_buffers.push_back(scene_mesh_skinned_subset.m_skinned_vertex_varying_buffer->get_storage_buffer());
+ }
+ }
+ }
+ }
+
+ if (!skinned_buffers.empty())
+ {
+ command_buffer->begin_debug_utils_label("Skin Pass");
+
+ std::vector skinned_buffer_load_operations(skinned_buffers.size(), BRX_COMPUTE_PASS_STORAGE_BUFFER_LOAD_OPERATION_DONT_CARE);
+ command_buffer->compute_pass_load(static_cast(skinned_buffers.size()), skinned_buffers.data(), skinned_buffer_load_operations.data(), 0U, NULL, NULL);
+
+ command_buffer->bind_compute_pipeline(this->m_skin_pipeline);
+
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh const &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ if (scene_mesh.m_skinned)
+ {
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance const &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Subset const &scene_mesh_subset = scene_mesh.m_subsets[subset_index];
+
+ Demo_Mesh_Skinned_Subset const &scene_mesh_skinned_subset = scene_mesh_instance.m_subsets[subset_index];
+
+ brx_descriptor_set *const descritor_sets[] = {
+ scene_mesh_instance.m_skin_pipeline_per_mesh_instance_update_descriptor_set,
+ scene_mesh_skinned_subset.m_skin_pipeline_per_mesh_skinned_subset_update_descriptor_set};
+
+ uint32_t const dynamic_offsets[] = {
+ tbb_align_up(static_cast(sizeof(skin_pipeline_per_mesh_instance_update_set_uniform_buffer_binding)), this->m_uniform_upload_buffer_offset_alignment) * frame_throttling_index};
+
+ command_buffer->bind_compute_descriptor_sets(this->m_skin_pipeline_layout, sizeof(descritor_sets) / sizeof(descritor_sets[0]), descritor_sets, sizeof(dynamic_offsets) / sizeof(dynamic_offsets[0]), dynamic_offsets);
+
+ // TODO: support more vertex count
+ constexpr uint32_t const D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION = 65535U;
+ assert(scene_mesh_subset.m_vertex_count <= D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION);
+ command_buffer->dispatch(scene_mesh_subset.m_vertex_count, 1U, 1U);
+ }
+ }
+ }
+ }
+
+ std::vector skinned_buffer_store_operations(skinned_buffers.size(), BRX_COMPUTE_PASS_STORAGE_BUFFER_STORE_OPERATION_FLUSH_FOR_READ_ONLY_STORAGE_BUFFER);
+ command_buffer->compute_pass_store(static_cast(skinned_buffers.size()), skinned_buffers.data(), skinned_buffer_store_operations.data(), 0U, NULL, NULL);
+
+ command_buffer->end_debug_utils_label();
+ }
+ }
+
+ // GBuffer Pass
+ {
+ command_buffer->begin_debug_utils_label("GBuffer Pass");
+
+ float color_clear_values[4] = {0.0F, 0.0F, 0.0F, 0.0F};
+ float depth_clear_value = 0.0F;
+ command_buffer->begin_render_pass(this->m_gbuffer_render_pass, this->m_gbuffer_frame_buffer, this->m_intermediate_width, this->m_intermediate_height, 1U, &color_clear_values, &depth_clear_value, NULL);
+
+ command_buffer->bind_graphics_pipeline(this->m_gbuffer_pipeline);
+
+ command_buffer->set_view_port(this->m_intermediate_width, this->m_intermediate_height);
+
+ command_buffer->set_scissor(this->m_intermediate_width, this->m_intermediate_height);
+
+ for (uint32_t mesh_index = 0; mesh_index < this->m_scene_meshes.size(); ++mesh_index)
+ {
+ Demo_Mesh const &scene_mesh = this->m_scene_meshes[mesh_index];
+
+ for (size_t subset_index = 0U; subset_index < scene_mesh.m_subsets.size(); ++subset_index)
+ {
+ Demo_Mesh_Subset const &scene_mesh_subset = scene_mesh.m_subsets[subset_index];
+
+ for (size_t instance_index = 0U; instance_index < scene_mesh.m_instances.size(); ++instance_index)
+ {
+ Demo_Mesh_Instance const &scene_mesh_instance = scene_mesh.m_instances[instance_index];
+
+ brx_descriptor_set *const descritor_sets[] = {
+ this->m_gbuffer_pipeline_none_update_descriptor_set,
+ (!scene_mesh.m_skinned) ? scene_mesh_subset.m_gbuffer_pipeline_per_mesh_subset_update_descriptor_set : scene_mesh_instance.m_subsets[subset_index].m_gbuffer_pipeline_per_mesh_skinned_subset_update_descriptor_set,
+ scene_mesh_instance.m_gbuffer_pipeline_per_mesh_instance_update_descriptor_set};
+
+ uint32_t const dynamic_offsets[] = {
+ tbb_align_up(static_cast(sizeof(common_none_update_set_uniform_buffer_binding)), this->m_uniform_upload_buffer_offset_alignment) * frame_throttling_index,
+ tbb_align_up(static_cast(sizeof(gbuffer_pipeline_per_mesh_instance_update_set_uniform_buffer_binding)), this->m_uniform_upload_buffer_offset_alignment) * frame_throttling_index};
+
+ command_buffer->bind_graphics_descriptor_sets(this->m_gbuffer_pipeline_layout, sizeof(descritor_sets) / sizeof(descritor_sets[0]), descritor_sets, sizeof(dynamic_offsets) / sizeof(dynamic_offsets[0]), dynamic_offsets);
+
+ command_buffer->draw(scene_mesh_subset.m_index_count, 1U);
+ }
+ }
+ }
+
+ command_buffer->end_render_pass();
+
+ command_buffer->end_debug_utils_label();
+ }
+
+ // Deferred Shading Pass
+ {
+ command_buffer->begin_debug_utils_label("Deferred Shading Pass");
+
+ float color_clear_values[4] = {0.0F, 0.0F, 0.0F, 0.0F};
+ command_buffer->begin_render_pass(this->m_deferred_shading_render_pass, this->m_deferred_shading_frame_buffer, this->m_intermediate_width, this->m_intermediate_height, 1U, &color_clear_values, NULL, NULL);
+
+ command_buffer->bind_graphics_pipeline(this->m_deferred_shading_pipeline);
+
+ command_buffer->set_view_port(this->m_intermediate_width, this->m_intermediate_height);
+
+ command_buffer->set_scissor(this->m_intermediate_width, this->m_intermediate_height);
+
+ brx_descriptor_set *const descritor_sets[] = {
+ this->m_deferred_shading_pipeline_none_update_descriptor_set};
+
+ uint32_t const dynamic_offsets[] = {
+ tbb_align_up(static_cast(sizeof(common_none_update_set_uniform_buffer_binding)), this->m_uniform_upload_buffer_offset_alignment) * frame_throttling_index};
+
+ command_buffer->bind_graphics_descriptor_sets(this->m_deferred_shading_pipeline_layout, sizeof(descritor_sets) / sizeof(descritor_sets[0]), descritor_sets, sizeof(dynamic_offsets) / sizeof(dynamic_offsets[0]), dynamic_offsets);
+
+ command_buffer->draw(3U, 1U);
+
+ command_buffer->end_render_pass();
+
+ command_buffer->end_debug_utils_label();
+ }
+}
+
+static inline uint32_t tbb_align_up(uint32_t value, uint32_t alignment)
+{
+ //
+ // Copyright (c) 2005-2019 Intel Corporation
+ //
+ // Licensed under the Apache License, Version 2.0 (the "License");
+ // you may not use this file except in compliance with the License.
+ // You may obtain a copy of the License at
+ //
+ // http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Unless required by applicable law or agreed to in writing, software
+ // distributed under the License is distributed on an "AS IS" BASIS,
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ // See the License for the specific language governing permissions and
+ // limitations under the License.
+ //
+
+ // [alignUp](https://github.com/oneapi-src/oneTBB/blob/tbb_2019/src/tbbmalloc/shared_utils.h#L42)
+
+ assert(alignment != static_cast(0));
+
+ // power-of-2 alignment
+ assert((alignment & (alignment - static_cast(1))) == static_cast(0));
+
+ return (((value - static_cast(1)) | (alignment - static_cast(1))) + static_cast(1));
+}
+
+static inline DirectX::XMMATRIX XM_CALLCONV DirectX_Math_Matrix_PerspectiveFovRH_ReversedZ(float FovAngleY, float AspectRatio, float NearZ, float FarZ)
+{
+ // [Reversed-Z](https://developer.nvidia.com/content/depth-precision-visualized)
+ //
+ // _ 0 0 0
+ // 0 _ 0 0
+ // 0 0 b -1
+ // 0 0 a 0
+ //
+ // _ 0 0 0
+ // 0 _ 0 0
+ // 0 0 zb -z
+ // 0 0 a
+ //
+ // z' = -b - a/z
+ //
+ // Standard
+ // 0 = -b + a/nearz // z=-nearz
+ // 1 = -b + a/farz // z=-farz
+ // a = farz*nearz/(nearz - farz)
+ // b = farz/(nearz - farz)
+ //
+ // Reversed-Z
+ // 1 = -b + a/nearz // z=-nearz
+ // 0 = -b + a/farz // z=-farz
+ // a = farz*nearz/(farz - nearz)
+ // b = nearz/(farz - nearz)
+
+ // __m128 _mm_shuffle_ps(__m128 lo,__m128 hi, _MM_SHUFFLE(hi3,hi2,lo1,lo0))
+ // Interleave inputs into low 2 floats and high 2 floats of output. Basically
+ // out[0]=lo[lo0];
+ // out[1]=lo[lo1];
+ // out[2]=hi[hi2];
+ // out[3]=hi[hi3];
+
+ // DirectX::XMMatrixPerspectiveFovRH
+
+ float SinFov;
+ float CosFov;
+ DirectX::XMScalarSinCos(&SinFov, &CosFov, 0.5F * FovAngleY);
+
+ float Height = CosFov / SinFov;
+ float Width = Height / AspectRatio;
+ float b = NearZ / (FarZ - NearZ);
+ float a = (FarZ / (FarZ - NearZ)) * NearZ;
+#if defined(_XM_SSE_INTRINSICS_)
+ // Note: This is recorded on the stack
+ DirectX::XMVECTOR rMem = {
+ Width,
+ Height,
+ b,
+ a};
+
+ // Copy from memory to SSE register
+ DirectX::XMVECTOR vValues = rMem;
+ DirectX::XMVECTOR vTemp = _mm_setzero_ps();
+ // Copy x only
+ vTemp = _mm_move_ss(vTemp, vValues);
+ // CosFov / SinFov,0,0,0
+ DirectX::XMMATRIX M;
+ M.r[0] = vTemp;
+ // 0,Height / AspectRatio,0,0
+ vTemp = vValues;
+ vTemp = _mm_and_ps(vTemp, DirectX::g_XMMaskY);
+ M.r[1] = vTemp;
+ // x=b,y=a,0,-1.0f
+ vTemp = _mm_setzero_ps();
+ vValues = _mm_shuffle_ps(vValues, DirectX::g_XMNegIdentityR3, _MM_SHUFFLE(3, 2, 3, 2));
+ // 0,0,b,-1.0f
+ vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(3, 0, 0, 0));
+ M.r[2] = vTemp;
+ // 0,0,a,0.0f
+ vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(2, 1, 0, 0));
+ M.r[3] = vTemp;
+ return M;
+#elif defined(_XM_ARM_NEON_INTRINSICS_)
+ const float32x4_t Zero = vdupq_n_f32(0);
+
+ DirectX::XMMATRIX M;
+ M.r[0] = vsetq_lane_f32(Width, Zero, 0);
+ M.r[1] = vsetq_lane_f32(Height, Zero, 1);
+ M.r[2] = vsetq_lane_f32(b, DirectX::g_XMNegIdentityR3.v, 2);
+ M.r[3] = vsetq_lane_f32(a, Zero, 2);
+ return M;
+#endif
+}
diff --git a/source/demo.h b/source/demo.h
new file mode 100644
index 0000000..1cd4a49
--- /dev/null
+++ b/source/demo.h
@@ -0,0 +1,128 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _DEMO_H_
+#define _DEMO_H_ 1
+
+#include "support/frame_throttling.h"
+#include "../thirdparty/Brioche/include/brx_device.h"
+#include "../thirdparty/ImportAsset/include/import_scene_asset.h"
+#include
+#include
+
+struct Demo_Mesh_Skinned_Subset
+{
+ brx_storage_intermediate_buffer *m_skinned_vertex_position_buffer;
+ brx_storage_intermediate_buffer *m_skinned_vertex_varying_buffer;
+ brx_descriptor_set *m_skin_pipeline_per_mesh_skinned_subset_update_descriptor_set;
+ brx_descriptor_set *m_gbuffer_pipeline_per_mesh_skinned_subset_update_descriptor_set;
+};
+
+struct Demo_Mesh_Instance
+{
+ DirectX::XMFLOAT4X4 m_model_transform;
+ scene_animation_skeleton m_animation_skeleton;
+ std::vector m_subsets;
+ brx_uniform_upload_buffer *m_skin_pipeline_per_mesh_instance_update_uniform_buffer;
+ brx_descriptor_set *m_skin_pipeline_per_mesh_instance_update_descriptor_set;
+ brx_uniform_upload_buffer *m_gbuffer_pipeline_per_mesh_instance_update_uniform_buffer;
+ brx_descriptor_set *m_gbuffer_pipeline_per_mesh_instance_update_descriptor_set;
+};
+
+static constexpr uint32_t const DEMO_MESH_SUBSET_METERIAL_TEXTURE_COUNT = 4U;
+
+struct Demo_Mesh_Subset
+{
+ uint32_t m_vertex_count;
+ brx_storage_asset_buffer *m_vertex_position_buffer;
+ brx_storage_asset_buffer *m_vertex_varying_buffer;
+ brx_storage_asset_buffer *m_vertex_joint_buffer;
+ uint32_t m_index_count;
+ brx_storage_asset_buffer *m_index_buffer;
+ brx_storage_asset_buffer *m_material_buffer;
+ brx_sampled_asset_image *m_material_textures[DEMO_MESH_SUBSET_METERIAL_TEXTURE_COUNT];
+ brx_descriptor_set *m_gbuffer_pipeline_per_mesh_subset_update_descriptor_set;
+};
+
+struct Demo_Mesh
+{
+ bool m_skinned;
+ std::vector m_subsets;
+ std::vector m_instances;
+};
+
+class Demo
+{
+ brx_pipeline_layout *m_skin_pipeline_layout;
+ brx_compute_pipeline *m_skin_pipeline;
+
+ BRX_COLOR_ATTACHMENT_IMAGE_FORMAT m_gbuffer_color_attachement_format;
+ BRX_DEPTH_STENCIL_ATTACHMENT_IMAGE_FORMAT m_gbuffer_depth_attachement_format;
+ brx_render_pass *m_gbuffer_render_pass;
+
+ brx_pipeline_layout *m_gbuffer_pipeline_layout;
+ brx_graphics_pipeline *m_gbuffer_pipeline;
+
+ // TODO: self dependency
+ // TODO: VK_EXT_rasterization_order_attachment_access
+ BRX_COLOR_ATTACHMENT_IMAGE_FORMAT m_deferred_shading_color_attachement_format;
+ brx_render_pass *m_deferred_shading_render_pass;
+
+ brx_pipeline_layout *m_deferred_shading_pipeline_layout;
+ brx_graphics_pipeline *m_deferred_shading_pipeline;
+
+ brx_sampled_asset_image *m_place_holder_texture;
+
+ brx_sampler *m_sampler;
+
+ uint32_t m_uniform_upload_buffer_offset_alignment;
+ brx_uniform_upload_buffer *m_common_none_update_uniform_buffer;
+
+ brx_descriptor_set *m_gbuffer_pipeline_none_update_descriptor_set;
+
+ brx_descriptor_set_layout *m_deferred_shading_pipeline_none_update_descriptor_set_layout;
+ brx_descriptor_set *m_deferred_shading_pipeline_none_update_descriptor_set;
+
+ std::vector m_scene_meshes;
+
+ uint32_t m_intermediate_width;
+ uint32_t m_intermediate_height;
+ brx_color_attachment_image *m_gbuffer_color_attachment;
+ brx_depth_stencil_attachment_image *m_gbuffer_depth_attachment;
+ brx_frame_buffer *m_gbuffer_frame_buffer;
+ brx_color_attachment_image *m_deferred_shading_color_attachment;
+ brx_frame_buffer *m_deferred_shading_frame_buffer;
+
+ float m_animation_time;
+
+public:
+ Demo();
+
+ void init(brx_device *device, std::vector const &file_names);
+
+ void destroy(brx_device *device);
+
+ void on_swap_chain_attach(brx_device *device, uint32_t swap_chain_image_width, uint32_t swap_chain_image_height);
+
+ brx_sampled_image const *get_sampled_image_for_present();
+
+ void on_swap_chain_dettach(brx_device *device);
+
+ void draw(brx_graphics_command_buffer *command_buffer, float interval_time, uint32_t frame_throttling_index);
+};
+
+#endif
\ No newline at end of file
diff --git a/source/support/camera_controller.cpp b/source/support/camera_controller.cpp
new file mode 100644
index 0000000..12a8cfd
--- /dev/null
+++ b/source/support/camera_controller.cpp
@@ -0,0 +1,201 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include
+#include
+#include "camera_controller.h"
+
+class CameraController g_camera_controller;
+
+static float g_SpeedTranslate = 0.25F;
+static float g_RotationTranslate = 2.0F;
+
+CameraController::CameraController() : m_previous_x(-1.0F), m_previous_y(-1.0F)
+{
+}
+
+void CameraController::MoveForward()
+{
+ m_eye_position.x += m_eye_direction.x * g_SpeedTranslate;
+ m_eye_position.y += m_eye_direction.y * g_SpeedTranslate;
+ m_eye_position.z += m_eye_direction.z * g_SpeedTranslate;
+}
+
+void CameraController::MoveBack()
+{
+ m_eye_position.x -= m_eye_direction.x * g_SpeedTranslate;
+ m_eye_position.y -= m_eye_direction.y * g_SpeedTranslate;
+ m_eye_position.z -= m_eye_direction.z * g_SpeedTranslate;
+}
+
+void CameraController::MoveLeft()
+{
+ DirectX::XMFLOAT3 EyeDirection = {m_eye_direction.x, m_eye_direction.y, m_eye_direction.z};
+ DirectX::XMFLOAT3 UpDirection = {m_up_direction.x, m_up_direction.y, m_up_direction.z};
+
+ DirectX::XMVECTOR NegEyeDirection = DirectX::XMVectorNegate(DirectX::XMLoadFloat3(&EyeDirection));
+ DirectX::XMVECTOR AxisForwardDirection = DirectX::XMVector3Normalize(NegEyeDirection);
+ DirectX::XMVECTOR AxisRightDirection = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(DirectX::XMLoadFloat3(&UpDirection), AxisForwardDirection));
+ // DirectX::XMVECTOR AxisViewUpDirection = DirectX::XMVector3Cross(AxisForwardDirection, AxisRightDirection);
+
+ DirectX::XMFLOAT3 AxisRightDirectionF;
+ DirectX::XMStoreFloat3(&AxisRightDirectionF, AxisRightDirection);
+
+ m_eye_position.x -= AxisRightDirectionF.x * g_SpeedTranslate;
+ m_eye_position.y -= AxisRightDirectionF.y * g_SpeedTranslate;
+ m_eye_position.z -= AxisRightDirectionF.z * g_SpeedTranslate;
+}
+
+void CameraController::MoveRight()
+{
+ DirectX::XMFLOAT3 EyeDirection = {m_eye_direction.x, m_eye_direction.y, m_eye_direction.z};
+ DirectX::XMFLOAT3 UpDirection = {m_up_direction.x, m_up_direction.y, m_up_direction.z};
+
+ DirectX::XMVECTOR NegEyeDirection = DirectX::XMVectorNegate(DirectX::XMLoadFloat3(&EyeDirection));
+ DirectX::XMVECTOR AxisForwardDirection = DirectX::XMVector3Normalize(NegEyeDirection);
+ DirectX::XMVECTOR AxisRightDirection = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(DirectX::XMLoadFloat3(&UpDirection), AxisForwardDirection));
+ // DirectX::XMVECTOR AxisViewUpDirection = DirectX::XMVector3Cross(AxisForwardDirection, AxisRightDirection);
+
+ DirectX::XMFLOAT3 AxisRightDirectionF;
+ DirectX::XMStoreFloat3(&AxisRightDirectionF, AxisRightDirection);
+
+ m_eye_position.x += AxisRightDirectionF.x * g_SpeedTranslate;
+ m_eye_position.y += AxisRightDirectionF.y * g_SpeedTranslate;
+ m_eye_position.z += AxisRightDirectionF.z * g_SpeedTranslate;
+}
+
+void CameraController::MoveUp()
+{
+ DirectX::XMFLOAT3 EyeDirection = {m_eye_direction.x, m_eye_direction.y, m_eye_direction.z};
+ DirectX::XMFLOAT3 UpDirection = {m_up_direction.x, m_up_direction.y, m_up_direction.z};
+
+ DirectX::XMVECTOR NegEyeDirection = DirectX::XMVectorNegate(DirectX::XMLoadFloat3(&EyeDirection));
+ DirectX::XMVECTOR AxisForwardDirection = DirectX::XMVector3Normalize(NegEyeDirection);
+ DirectX::XMVECTOR AxisRightDirection = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(DirectX::XMLoadFloat3(&UpDirection), AxisForwardDirection));
+ DirectX::XMVECTOR AxisViewUpDirection = DirectX::XMVector3Cross(AxisForwardDirection, AxisRightDirection);
+
+ DirectX::XMFLOAT3 AxisViewUpDirectionF;
+ DirectX::XMStoreFloat3(&AxisViewUpDirectionF, AxisViewUpDirection);
+
+ m_eye_position.x += AxisViewUpDirectionF.x * g_SpeedTranslate;
+ m_eye_position.y += AxisViewUpDirectionF.y * g_SpeedTranslate;
+ m_eye_position.z += AxisViewUpDirectionF.z * g_SpeedTranslate;
+}
+
+void CameraController::MoveDown()
+{
+ DirectX::XMFLOAT3 EyeDirection = {m_eye_direction.x, m_eye_direction.y, m_eye_direction.z};
+ DirectX::XMFLOAT3 UpDirection = {m_up_direction.x, m_up_direction.y, m_up_direction.z};
+
+ DirectX::XMVECTOR NegEyeDirection = DirectX::XMVectorNegate(DirectX::XMLoadFloat3(&EyeDirection));
+ DirectX::XMVECTOR AxisForwardDirection = DirectX::XMVector3Normalize(NegEyeDirection);
+ DirectX::XMVECTOR AxisRightDirection = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(DirectX::XMLoadFloat3(&UpDirection), AxisForwardDirection));
+ DirectX::XMVECTOR AxisViewUpDirection = DirectX::XMVector3Cross(AxisForwardDirection, AxisRightDirection);
+
+ DirectX::XMFLOAT3 AxisViewUpDirectionF;
+ DirectX::XMStoreFloat3(&AxisViewUpDirectionF, AxisViewUpDirection);
+
+ m_eye_position.x -= AxisViewUpDirectionF.x * g_SpeedTranslate;
+ m_eye_position.y -= AxisViewUpDirectionF.y * g_SpeedTranslate;
+ m_eye_position.z -= AxisViewUpDirectionF.z * g_SpeedTranslate;
+}
+
+void CameraController::OnMouseMove(float x, float y, bool hold)
+{
+ float Current_X = std::min(std::max(0.0f, x), 1.0f);
+ float Current_Y = std::min(std::max(0.0f, y), 1.0f);
+
+ float Offset_X = Current_X - this->m_previous_x;
+ float Offset_Y = Current_Y - this->m_previous_y;
+
+ if (hold && this->m_previous_x > 0.0F && this->m_previous_x < 1.0F && this->m_previous_y > 0.0F && this->m_previous_y < 1.0F)
+ {
+ float LengthNormalized = ::sqrtf(Offset_X * Offset_X + Offset_Y * Offset_Y);
+
+ if ((Offset_Y < Offset_X) && (Offset_Y > -Offset_X))
+ {
+ // right
+ DirectX::XMFLOAT3 EyeDirection = {m_eye_direction.x, m_eye_direction.y, m_eye_direction.z};
+ DirectX::XMFLOAT3 UpDirection = {m_up_direction.x, m_up_direction.y, m_up_direction.z};
+
+ DirectX::XMVECTOR NegEyeDirection = DirectX::XMVectorNegate(DirectX::XMLoadFloat3(&EyeDirection));
+ DirectX::XMVECTOR AxisForwardDirection = DirectX::XMVector3Normalize(NegEyeDirection);
+ DirectX::XMVECTOR AxisRightDirection = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(DirectX::XMLoadFloat3(&UpDirection), AxisForwardDirection));
+ DirectX::XMVECTOR AxisViewUpDirection = DirectX::XMVector3Cross(AxisForwardDirection, AxisRightDirection);
+
+ DirectX::XMFLOAT3 EyeDirectionNew;
+ DirectX::XMStoreFloat3(&EyeDirectionNew, DirectX::XMVectorNegate(DirectX::XMVector3Transform(AxisForwardDirection, DirectX::XMMatrixRotationAxis(AxisViewUpDirection, -g_RotationTranslate * LengthNormalized))));
+ m_eye_direction.x = EyeDirectionNew.x;
+ m_eye_direction.y = EyeDirectionNew.y;
+ m_eye_direction.z = EyeDirectionNew.z;
+ }
+ else if ((Offset_Y < -Offset_X) && (Offset_Y > Offset_X))
+ {
+ // left
+ DirectX::XMFLOAT3 EyeDirection = {m_eye_direction.x, m_eye_direction.y, m_eye_direction.z};
+ DirectX::XMFLOAT3 UpDirection = {m_up_direction.x, m_up_direction.y, m_up_direction.z};
+
+ DirectX::XMVECTOR NegEyeDirection = DirectX::XMVectorNegate(DirectX::XMLoadFloat3(&EyeDirection));
+ DirectX::XMVECTOR AxisForwardDirection = DirectX::XMVector3Normalize(NegEyeDirection);
+ DirectX::XMVECTOR AxisRightDirection = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(DirectX::XMLoadFloat3(&UpDirection), AxisForwardDirection));
+ DirectX::XMVECTOR AxisViewUpDirection = DirectX::XMVector3Cross(AxisForwardDirection, AxisRightDirection);
+
+ DirectX::XMFLOAT3 EyeDirectionNew;
+ DirectX::XMStoreFloat3(&EyeDirectionNew, DirectX::XMVectorNegate(DirectX::XMVector3Transform(AxisForwardDirection, DirectX::XMMatrixRotationAxis(AxisViewUpDirection, g_RotationTranslate * LengthNormalized))));
+ m_eye_direction.x = EyeDirectionNew.x;
+ m_eye_direction.y = EyeDirectionNew.y;
+ m_eye_direction.z = EyeDirectionNew.z;
+ }
+ else if ((Offset_Y < Offset_X) && (Offset_Y < -Offset_X))
+ {
+ // up
+ DirectX::XMFLOAT3 EyeDirection = {m_eye_direction.x, m_eye_direction.y, m_eye_direction.z};
+ DirectX::XMFLOAT3 UpDirection = {m_up_direction.x, m_up_direction.y, m_up_direction.z};
+
+ DirectX::XMVECTOR NegEyeDirection = DirectX::XMVectorNegate(DirectX::XMLoadFloat3(&EyeDirection));
+ DirectX::XMVECTOR AxisForwardDirection = DirectX::XMVector3Normalize(NegEyeDirection);
+ DirectX::XMVECTOR AxisRightDirection = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(DirectX::XMLoadFloat3(&UpDirection), AxisForwardDirection));
+ // DirectX::XMVECTOR AxisViewUpDirection = DirectX::XMVector3Cross(AxisForwardDirection, AxisRightDirection);
+
+ DirectX::XMFLOAT3 EyeDirectionNew;
+ DirectX::XMStoreFloat3(&EyeDirectionNew, DirectX::XMVectorNegate(DirectX::XMVector3Transform(AxisForwardDirection, DirectX::XMMatrixRotationAxis(AxisRightDirection, g_RotationTranslate * LengthNormalized))));
+ m_eye_direction.x = EyeDirectionNew.x;
+ m_eye_direction.y = EyeDirectionNew.y;
+ m_eye_direction.z = EyeDirectionNew.z;
+ }
+ else if ((Offset_Y > Offset_X) && (Offset_Y > -Offset_X))
+ {
+ // down
+ DirectX::XMFLOAT3 EyeDirection = {m_eye_direction.x, m_eye_direction.y, m_eye_direction.z};
+ DirectX::XMFLOAT3 UpDirection = {m_up_direction.x, m_up_direction.y, m_up_direction.z};
+
+ DirectX::XMVECTOR NegEyeDirection = DirectX::XMVectorNegate(DirectX::XMLoadFloat3(&EyeDirection));
+ DirectX::XMVECTOR AxisForwardDirection = DirectX::XMVector3Normalize(NegEyeDirection);
+ DirectX::XMVECTOR AxisRightDirection = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(DirectX::XMLoadFloat3(&UpDirection), AxisForwardDirection));
+ // DirectX::XMVECTOR AxisViewUpDirection = DirectX::XMVector3Cross(AxisForwardDirection, AxisRightDirection);
+
+ DirectX::XMFLOAT3 EyeDirectionNew;
+ DirectX::XMStoreFloat3(&EyeDirectionNew, DirectX::XMVectorNegate(DirectX::XMVector3Transform(AxisForwardDirection, DirectX::XMMatrixRotationAxis(AxisRightDirection, -g_RotationTranslate * LengthNormalized))));
+ m_eye_direction.x = EyeDirectionNew.x;
+ m_eye_direction.y = EyeDirectionNew.y;
+ m_eye_direction.z = EyeDirectionNew.z;
+ }
+ }
+
+ this->m_previous_x = Current_X;
+ this->m_previous_y = Current_Y;
+}
diff --git a/source/support/camera_controller.h b/source/support/camera_controller.h
new file mode 100644
index 0000000..c6f2263
--- /dev/null
+++ b/source/support/camera_controller.h
@@ -0,0 +1,54 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _CAMERA_CONTROLLER_H_
+#define _CAMERA_CONTROLLER_H_ 1
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#endif
+#include
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+class CameraController
+{
+ float m_previous_x;
+ float m_previous_y;
+
+public:
+ DirectX::XMFLOAT3 m_eye_position;
+ DirectX::XMFLOAT3 m_eye_direction;
+ DirectX::XMFLOAT3 m_up_direction;
+
+ CameraController();
+
+ void MoveForward();
+ void MoveBack();
+ void MoveLeft();
+ void MoveRight();
+ void MoveUp();
+ void MoveDown();
+
+ void OnMouseMove(float x, float y, bool hold);
+};
+
+extern class CameraController g_camera_controller;
+
+#endif
\ No newline at end of file
diff --git a/source/support/frame_throttling.h b/source/support/frame_throttling.h
new file mode 100644
index 0000000..44256b0
--- /dev/null
+++ b/source/support/frame_throttling.h
@@ -0,0 +1,26 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _FRAME_THROTTLINE_H_
+#define _FRAME_THROTTLINE_H_ 1
+
+#include
+
+// [Pipeline Throttling](https://community.arm.com/arm-community-blogs/b/graphics-gaming-and-vr-blog/posts/the-mali-gpu-an-abstract-machine-part-1---frame-pipelining)
+static uint32_t constexpr const FRAME_THROTTLING_COUNT = 3U;
+
+#endif
\ No newline at end of file
diff --git a/source/support/main.cpp b/source/support/main.cpp
new file mode 100644
index 0000000..7d66156
--- /dev/null
+++ b/source/support/main.cpp
@@ -0,0 +1,957 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include
+#include
+#include "camera_controller.h"
+#include "renderer.h"
+
+static class renderer *g_renderer = NULL;
+static int32_t g_window_width = -1;
+static int32_t g_window_height = -1;
+
+#if defined(__GNUC__)
+
+#if defined(__linux__)
+
+#if defined(__ANDROID__)
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static void ANativeActivity_Destroy(ANativeActivity *native_activity);
+static void ANativeActivity_WindowFocusChanged(ANativeActivity *native_activity, int hasFocus);
+static void ANativeActivity_NativeWindowCreated(ANativeActivity *native_activity, ANativeWindow *native_window);
+static void ANativeActivity_NativeWindowResized(ANativeActivity *native_activity, ANativeWindow *native_window);
+static void ANativeActivity_NativeWindowRedrawNeeded(ANativeActivity *native_activity, ANativeWindow *native_window);
+static void ANativeActivity_NativeWindowDestroyed(ANativeActivity *native_activity, ANativeWindow *native_window);
+static void ANativeActivity_InputQueueCreated(ANativeActivity *native_activity, AInputQueue *input_queue);
+static void ANativeActivity_InputQueueDestroyed(ANativeActivity *native_activity, AInputQueue *input_queue);
+
+static bool g_this_process_has_inited = false;
+
+static int g_main_thread_looper_draw_callback_fd_read = -1;
+static int g_main_thread_looper_draw_callback_fd_write = -1;
+
+static int main_thread_looper_draw_callback(int fd, int, void *);
+
+static pthread_t g_draw_request_thread;
+bool volatile g_draw_request_thread_running = false;
+
+static void *draw_request_thread_main(void *);
+
+static int main_thread_looper_input_queue_callback(int fd, int, void *input_queue_void);
+
+extern "C" JNIEXPORT void ANativeActivity_onCreate(ANativeActivity *native_activity, void *saved_state, size_t saved_state_size)
+{
+ native_activity->callbacks->onStart = NULL;
+ native_activity->callbacks->onResume = NULL;
+ native_activity->callbacks->onSaveInstanceState = NULL;
+ native_activity->callbacks->onPause = NULL;
+ native_activity->callbacks->onStop = NULL;
+ native_activity->callbacks->onDestroy = ANativeActivity_Destroy;
+ native_activity->callbacks->onWindowFocusChanged = ANativeActivity_WindowFocusChanged;
+ native_activity->callbacks->onNativeWindowCreated = ANativeActivity_NativeWindowCreated;
+ native_activity->callbacks->onNativeWindowResized = ANativeActivity_NativeWindowResized;
+ native_activity->callbacks->onNativeWindowRedrawNeeded = ANativeActivity_NativeWindowRedrawNeeded;
+ native_activity->callbacks->onNativeWindowDestroyed = ANativeActivity_NativeWindowDestroyed;
+ native_activity->callbacks->onInputQueueCreated = ANativeActivity_InputQueueCreated;
+ native_activity->callbacks->onInputQueueDestroyed = ANativeActivity_InputQueueDestroyed;
+ native_activity->callbacks->onContentRectChanged = NULL;
+ native_activity->callbacks->onConfigurationChanged = NULL;
+ native_activity->callbacks->onLowMemory = NULL;
+
+ if (!g_this_process_has_inited)
+ {
+ // TODO: get file name
+ std::vector file_names;
+
+ g_renderer = renderer_init(NULL, file_names);
+
+ // Simulate the following callback on Android:
+ // WM_PAINT
+ // CVDisplayLinkSetOutputCallback
+ // displayLinkWithTarget
+ {
+ // the looper of the main thread
+ ALooper *main_thread_looper = ALooper_forThread();
+ assert(main_thread_looper != NULL);
+
+ // Evidently, the real "draw" is slower than the "request"
+ // There are no message boundaries for "SOCK_STREAM", and We can read all the data once
+ int sv[2];
+ int res_socketpair = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
+ assert(0 == res_socketpair);
+ g_main_thread_looper_draw_callback_fd_read = sv[0];
+ g_main_thread_looper_draw_callback_fd_write = sv[1];
+
+ // the identifier is ignored when callback is not NULL (the ALooper_pollOnce always returns the ALOOPER_POLL_CALLBACK)
+ int res_looper_add_fd = ALooper_addFd(main_thread_looper, g_main_thread_looper_draw_callback_fd_read, -1, ALOOPER_EVENT_INPUT, main_thread_looper_draw_callback, NULL);
+ assert(1 == res_looper_add_fd);
+
+ // the "draw request" thread
+ // TODO: use Load/Store
+ g_draw_request_thread_running = false;
+ int res_ptread_create = pthread_create(&g_draw_request_thread, NULL, draw_request_thread_main, NULL);
+ assert(0 == res_ptread_create);
+ while (!g_draw_request_thread_running)
+ {
+ // pthread_yield();
+ sched_yield();
+ }
+ }
+
+ // Don't worry
+ // Single thread
+ g_this_process_has_inited = true;
+ }
+}
+
+// TODO:
+// destroy before this process terminates
+
+static void ANativeActivity_Destroy(ANativeActivity *native_activity)
+{
+}
+
+static void ANativeActivity_WindowFocusChanged(ANativeActivity *native_activity, int hasFocus)
+{
+}
+
+static void ANativeActivity_NativeWindowCreated(ANativeActivity *native_activity, ANativeWindow *native_window)
+{
+ g_window_width = ANativeWindow_getWidth(native_window);
+ g_window_height = ANativeWindow_getHeight(native_window);
+
+ renderer_attach_window(g_renderer, native_window);
+}
+
+static void ANativeActivity_NativeWindowResized(ANativeActivity *native_activity, ANativeWindow *native_window)
+{
+}
+
+static void ANativeActivity_NativeWindowRedrawNeeded(ANativeActivity *native_activity, ANativeWindow *native_window)
+{
+}
+
+static void ANativeActivity_NativeWindowDestroyed(ANativeActivity *native_activity, ANativeWindow *native_window)
+{
+ renderer_dettach_window(g_renderer);
+
+ g_window_width = -1;
+ g_window_height = -1;
+}
+
+static void ANativeActivity_InputQueueCreated(ANativeActivity *native_activity, AInputQueue *input_queue)
+{
+ // the looper of the main thread
+ ALooper *main_thread_looper = ALooper_forThread();
+ assert(NULL != main_thread_looper);
+
+ // the identifier is ignored when callback is not NULL (the ALooper_pollOnce always returns the ALOOPER_POLL_CALLBACK)
+ AInputQueue_attachLooper(input_queue, main_thread_looper, 0, main_thread_looper_input_queue_callback, input_queue);
+}
+
+static void ANativeActivity_InputQueueDestroyed(ANativeActivity *native_activity, AInputQueue *input_queue)
+{
+ ALooper *looper = ALooper_forThread();
+ assert(NULL != looper);
+
+ AInputQueue_detachLooper(input_queue);
+}
+
+static int main_thread_looper_draw_callback(int fd, int, void *)
+{
+ // Evidently, the real "draw" is slower than the "request"
+ // There are no message boundaries for "SOCK_STREAM", and We can read all the data once
+ {
+ uint8_t buf[4096];
+ ssize_t res_recv;
+ while ((-1 == (res_recv = recv(fd, buf, 4096U, 0))) && (EINTR == errno))
+ {
+ // pthread_yield();
+ sched_yield();
+ }
+ assert(-1 != res_recv);
+ }
+
+ // draw
+ renderer_draw(g_renderer);
+
+ return 1;
+}
+
+static void *draw_request_thread_main(void *)
+{
+ g_draw_request_thread_running = true;
+
+ while (g_draw_request_thread_running)
+ {
+ // 60 FPS
+ uint32_t milli_second = 1000U / 60U;
+
+ // wait
+ {
+ struct timespec request = {((time_t)milli_second) / ((time_t)1000), ((long)1000000) * (((long)milli_second) % ((long)1000))};
+
+ struct timespec remain;
+ int res_nanosleep;
+ while ((-1 == (res_nanosleep = nanosleep(&request, &remain))) && (EINTR == errno))
+ {
+ assert(remain.tv_nsec > 0 || remain.tv_sec > 0);
+ request = remain;
+ }
+ assert(0 == res_nanosleep);
+ }
+
+ // draw request
+ {
+ uint8_t buf[1] = {7}; // seven is the luck number
+ ssize_t res_send;
+ while ((-1 == (res_send = send(g_main_thread_looper_draw_callback_fd_write, buf, 1U, 0))) && (EINTR == errno))
+ {
+ // pthread_yield();
+ sched_yield();
+ }
+ assert(1 == res_send);
+ }
+ }
+
+ return NULL;
+}
+
+static int main_thread_looper_input_queue_callback(int fd, int, void *input_queue_void)
+{
+ AInputQueue *input_queue = static_cast(input_queue_void);
+
+ AInputEvent *input_event;
+ while (AInputQueue_getEvent(input_queue, &input_event) >= 0)
+ {
+ // The app will be "No response" if we don't call AInputQueue_finishEvent and pass the non-zero value for all events which is not pre-dispatched
+ if (0 == AInputQueue_preDispatchEvent(input_queue, input_event))
+ {
+ int handled = 0;
+
+ switch (AInputEvent_getType(input_event))
+ {
+ case AINPUT_EVENT_TYPE_MOTION:
+ {
+
+ float Current_X = AMotionEvent_getX(input_event, 0U);
+ float Current_Y = AMotionEvent_getY(input_event, 0U);
+
+ float CurrentNormalized_X = Current_X / static_cast(g_window_width);
+ float CurrentNormalized_Y = Current_Y / static_cast(g_window_height);
+
+ switch (AMotionEvent_getAction(input_event) & AMOTION_EVENT_ACTION_MASK)
+ {
+ case AMOTION_EVENT_ACTION_DOWN:
+ {
+ g_camera_controller.OnMouseMove(CurrentNormalized_X, CurrentNormalized_Y, false);
+ }
+ break;
+ case AMOTION_EVENT_ACTION_UP:
+ {
+ g_camera_controller.OnMouseMove(CurrentNormalized_X, CurrentNormalized_Y, false);
+ }
+ break;
+ case AMOTION_EVENT_ACTION_MOVE:
+ {
+ g_camera_controller.OnMouseMove(CurrentNormalized_X, CurrentNormalized_Y, true);
+ }
+ break;
+ default:
+ {
+ // Do Nothing
+ }
+ }
+ }
+ break;
+ default:
+ {
+ // Do Nothing
+ }
+ }
+
+ AInputQueue_finishEvent(input_queue, input_event, handled);
+ }
+ }
+
+ return 1;
+}
+#else
+
+#include
+#include
+#include
+#include
+#include
+
+int main(int argc, char *argv[])
+{
+ // Vulkan Validation Layer
+#ifndef NDEBUG
+ {
+ // We assume that the "VkLayer_khronos_validation.json" is at the same directory of the executable file
+ char dir_name[4096];
+ ssize_t res_read_link = readlink("/proc/self/exe", dir_name, sizeof(dir_name) / sizeof(dir_name[0]));
+ assert(-1 != res_read_link);
+
+ for (int i = (res_read_link - 1); i > 0; --i)
+ {
+ if (L'/' == dir_name[i])
+ {
+ dir_name[i] = L'\0';
+ break;
+ }
+ }
+
+ int res_set_env_vk_layer_path = setenv("VK_LAYER_PATH", dir_name, 1);
+ assert(0 == res_set_env_vk_layer_path);
+
+ int res_set_env_ld_library_path = setenv("LD_LIBRARY_PATH", dir_name, 1);
+ assert(0 == res_set_env_ld_library_path);
+ }
+#endif
+
+ std::vector file_names;
+ {
+ if (argc < 2)
+ {
+ puts("Usage: glTF-Viewer \n");
+ return 0;
+ }
+ else
+ {
+ file_names.resize(static_cast(argc - 1));
+
+ for (int arg_index = 1; arg_index < argc; ++arg_index)
+ {
+ file_names[arg_index - 1] = argv[arg_index];
+ }
+ }
+ }
+
+ g_window_width = 1280;
+ g_window_height = 720;
+
+ xcb_connection_t *connection = NULL;
+ xcb_screen_t *screen = NULL;
+ {
+ int screen_number;
+ connection = xcb_connect(NULL, &screen_number);
+ assert(0 == xcb_connection_has_error(connection));
+
+ xcb_setup_t const *setup = xcb_get_setup(connection);
+
+ int i = 0;
+ for (xcb_screen_iterator_t screen_iterator = xcb_setup_roots_iterator(setup); screen_iterator.rem > 0; xcb_screen_next(&screen_iterator))
+ {
+ if (i == screen_number)
+ {
+ screen = screen_iterator.data;
+ break;
+ }
+ ++i;
+ }
+ }
+
+ constexpr uint8_t const depth = 32;
+ xcb_visualid_t visual_id = -1;
+ {
+ for (xcb_depth_iterator_t depth_iterator = xcb_screen_allowed_depths_iterator(screen); depth_iterator.rem > 0; xcb_depth_next(&depth_iterator))
+ {
+ if (depth == depth_iterator.data->depth)
+ {
+ for (xcb_visualtype_iterator_t visual_iterator = xcb_depth_visuals_iterator(depth_iterator.data); visual_iterator.rem > 0; xcb_visualtype_next(&visual_iterator))
+ {
+ if (XCB_VISUAL_CLASS_TRUE_COLOR == visual_iterator.data->_class)
+ {
+ visual_id = visual_iterator.data->visual_id;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ xcb_colormap_t colormap = 0;
+ {
+ colormap = xcb_generate_id(connection);
+
+ xcb_void_cookie_t cookie_create_colormap = xcb_create_colormap_checked(connection, XCB_COLORMAP_ALLOC_NONE, colormap, screen->root, visual_id);
+
+ xcb_generic_error_t *error_create_colormap = xcb_request_check(connection, cookie_create_colormap);
+ assert(NULL == error_create_colormap);
+ }
+
+ xcb_window_t window = 0;
+ {
+ window = xcb_generate_id(connection);
+
+ // Both "border pixel" and "colormap" are required when the depth is NOT equal to the root window's.
+ uint32_t value_mask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_BACKING_STORE | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
+
+ // we need "XCB_EVENT_MASK_BUTTON_PRESS" and "XCB_EVENT_MASK_BUTTON_RELEASE" to use the "state" of the "motion notify" event
+ uint32_t value_list[] = {screen->black_pixel, 0, XCB_BACKING_STORE_NOT_USEFUL, XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_STRUCTURE_NOTIFY, colormap};
+
+ xcb_void_cookie_t cookie_create_window = xcb_create_window_checked(connection, depth, window, screen->root, 0, 0, g_window_width, g_window_height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visual_id, value_mask, value_list);
+
+ xcb_generic_error_t *error_create_window = xcb_request_check(connection, cookie_create_window);
+ assert(NULL == error_create_window);
+ }
+
+ xcb_atom_t atom_wm_protocols = 0;
+ xcb_atom_t atom_wm_delete_window = 0;
+ {
+ xcb_intern_atom_cookie_t cookie_wm_protocols = xcb_intern_atom(connection, 0, 12U, "WM_PROTOCOLS");
+
+ xcb_intern_atom_cookie_t cookie_wm_delete_window = xcb_intern_atom(connection, 0, 16U, "WM_DELETE_WINDOW");
+
+ xcb_generic_error_t *error_intern_atom_reply_wm_protocols;
+ xcb_intern_atom_reply_t *reply_wm_protocols = xcb_intern_atom_reply(connection, cookie_wm_protocols, &error_intern_atom_reply_wm_protocols);
+ assert(NULL == error_intern_atom_reply_wm_protocols);
+ atom_wm_protocols = reply_wm_protocols->atom;
+ free(error_intern_atom_reply_wm_protocols);
+
+ xcb_generic_error_t *error_intern_atom_reply_wm_delete_window;
+ xcb_intern_atom_reply_t *reply_wm_delete_window = xcb_intern_atom_reply(connection, cookie_wm_delete_window, &error_intern_atom_reply_wm_delete_window);
+ assert(NULL == error_intern_atom_reply_wm_delete_window);
+ atom_wm_delete_window = reply_wm_delete_window->atom;
+ free(error_intern_atom_reply_wm_delete_window);
+ }
+
+ {
+ xcb_void_cookie_t cookie_change_property_wm_name = xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8 * sizeof(uint8_t), 11, "glTF Viewer");
+
+ xcb_void_cookie_t cookie_change_property_wm_protocols_delete_window = xcb_change_property_checked(connection, XCB_PROP_MODE_REPLACE, window, atom_wm_protocols, XCB_ATOM_ATOM, 8 * sizeof(uint32_t), sizeof(xcb_atom_t) / sizeof(uint32_t), &atom_wm_delete_window);
+
+ xcb_generic_error_t *error_change_property_net_wm_name = xcb_request_check(connection, cookie_change_property_wm_name);
+ assert(NULL == error_change_property_net_wm_name);
+
+ xcb_generic_error_t *error_change_property_wm_protocols_delete_window = xcb_request_check(connection, cookie_change_property_wm_protocols_delete_window);
+ assert(NULL == error_change_property_wm_protocols_delete_window);
+ }
+
+ {
+ struct brx_xcb_connection_T
+ {
+ xcb_connection_t *m_connection;
+ xcb_visualid_t m_visual_id;
+ };
+ brx_xcb_connection_T brx_xcb_connection = {
+ connection,
+ visual_id};
+
+ g_renderer = renderer_init(&brx_xcb_connection, file_names);
+
+ struct brx_xcb_window_T
+ {
+ xcb_connection_t *m_connection;
+ xcb_window_t m_window;
+ };
+
+ brx_xcb_window_T brx_xcb_window = {
+ connection,
+ window};
+
+ renderer_attach_window(g_renderer, &brx_xcb_window);
+ }
+
+ {
+ xcb_void_cookie_t cookie_map_window = xcb_map_window_checked(connection, window);
+
+ xcb_generic_error_t *error_map_window = xcb_request_check(connection, cookie_map_window);
+ assert(NULL == error_map_window);
+ }
+
+ bool quit = false;
+ while (!quit)
+ {
+ // WSI Event
+ {
+ xcb_generic_event_t *event;
+ while ((event = xcb_poll_for_event(connection)) != NULL)
+ {
+ // The most significant bit(uint8_t(0X80)) in this code is set if the event was generated from a SendEvent request.
+ // https://www.x.org/releases/current/doc/xproto/x11protocol.html#event_format
+ switch (event->response_type & (~uint8_t(0X80)))
+ {
+ case XCB_KEY_PRESS:
+ {
+ assert(XCB_KEY_PRESS == (event->response_type & (~uint8_t(0X80))));
+
+ xcb_key_press_event_t const *const key_press = reinterpret_cast(event);
+
+ // evdev keycode
+ // https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/master/keycodes/evdev
+ // Q
+ constexpr xcb_keycode_t const AD01 = 24;
+ // W
+ constexpr xcb_keycode_t const AD02 = 25;
+ // E
+ constexpr xcb_keycode_t const AD03 = 26;
+ // A
+ constexpr xcb_keycode_t const AC01 = 38;
+ // S
+ constexpr xcb_keycode_t const AC02 = 39;
+ // D
+ constexpr xcb_keycode_t const AC03 = 40;
+
+ switch (key_press->detail)
+ {
+ case AD02:
+ {
+ g_camera_controller.MoveForward();
+ }
+ break;
+ case AC02:
+ {
+ g_camera_controller.MoveBack();
+ }
+ break;
+ case AC01:
+ {
+ g_camera_controller.MoveLeft();
+ }
+ break;
+ case AC03:
+ {
+ g_camera_controller.MoveRight();
+ }
+ break;
+ case AD01:
+ {
+ g_camera_controller.MoveDown();
+ }
+ break;
+ case AD03:
+ {
+ g_camera_controller.MoveUp();
+ }
+ break;
+ }
+ }
+ break;
+ case XCB_MOTION_NOTIFY:
+ {
+ assert(XCB_MOTION_NOTIFY == (event->response_type & (~uint8_t(0X80))));
+
+ xcb_motion_notify_event_t const *const motion_notify = reinterpret_cast(event);
+
+ bool right_button_hold = (0U != (motion_notify->state & XCB_EVENT_MASK_BUTTON_3_MOTION));
+
+ float current_normalized_x = static_cast(motion_notify->event_x) / g_window_width;
+ float current_normalized_y = static_cast(motion_notify->event_y) / g_window_height;
+
+ g_camera_controller.OnMouseMove(current_normalized_x, current_normalized_y, right_button_hold);
+ }
+ break;
+ case XCB_CONFIGURE_NOTIFY:
+ {
+ assert(XCB_CONFIGURE_NOTIFY == (event->response_type & (~uint8_t(0X80))));
+
+ xcb_configure_notify_event_t const *const configure_notify = reinterpret_cast(event);
+
+ if (g_window_width != configure_notify->width || g_window_height != configure_notify->height)
+ {
+ renderer_on_window_resize(g_renderer);
+ g_window_width = configure_notify->width;
+ g_window_height = configure_notify->height;
+ }
+ }
+ break;
+ case XCB_CLIENT_MESSAGE:
+ {
+ assert(XCB_CLIENT_MESSAGE == (event->response_type & (~uint8_t(0X80))));
+
+ xcb_client_message_event_t const *const client_message_event = reinterpret_cast(event);
+ assert(client_message_event->type == atom_wm_protocols && client_message_event->data.data32[0] == atom_wm_delete_window && client_message_event->window == window);
+
+ quit = true;
+ }
+ break;
+ case 0:
+ {
+ assert(0 == (event->response_type & (~uint8_t(0X80))));
+
+ xcb_generic_error_t const *error = reinterpret_cast(event);
+
+ printf("Error Code: %d Major Code: %d", static_cast(error->error_code), static_cast(error->major_code));
+ }
+ break;
+ }
+
+ free(event);
+ }
+ }
+
+ // Render
+ renderer_draw(g_renderer);
+ }
+
+ {
+ xcb_void_cookie_t cookie_free_colormap = xcb_free_colormap_checked(connection, colormap);
+
+ xcb_generic_error_t *error_free_colormap = xcb_request_check(connection, cookie_free_colormap);
+ assert(NULL == error_free_colormap);
+ }
+
+ xcb_disconnect(connection);
+
+ renderer_dettach_window(g_renderer);
+
+ renderer_destroy(g_renderer);
+
+ return 0;
+}
+
+#endif
+#else
+#error Unknown Platform
+#endif
+
+#elif defined(_MSC_VER)
+
+#define NOMINMAX 1
+#define WIN32_LEAN_AND_MEAN 1
+#include
+#include
+#include
+#include
+#include
+#include "../../thirdparty/ConvertUTF/include/ConvertUTF.h"
+
+static LRESULT CALLBACK wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+static HRESULT STDMETHODCALLTYPE NoRegCoCreate(const __wchar_t *dllName, REFCLSID rclsid, REFIID riid, void **ppv);
+
+extern "C" IMAGE_DOS_HEADER __ImageBase;
+
+int wmain(int argc, wchar_t *argv[])
+{
+ // Vulkan Validation Layer
+#ifndef NDEBUG
+ {
+ // We assume that the "VkLayer_khronos_validation.json" is at the same directory of the executable file
+ WCHAR file_name[4096];
+ DWORD res_get_file_name = GetModuleFileNameW(NULL, file_name, sizeof(file_name) / sizeof(file_name[0]));
+ assert(0U != res_get_file_name);
+
+ for (int i = (res_get_file_name - 1); i > 0; --i)
+ {
+ if (L'\\' == file_name[i])
+ {
+ file_name[i] = L'\0';
+ break;
+ }
+ }
+
+ BOOL res_set_environment_variable = SetEnvironmentVariableW(L"VK_LAYER_PATH", file_name);
+ assert(FALSE != res_set_environment_variable);
+ }
+#endif
+
+ // Initialize
+ {
+ std::vector file_names;
+ {
+ if (argc < 2)
+ {
+ HRESULT res_co_initialize_ex = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ assert(SUCCEEDED(res_co_initialize_ex));
+
+ IFileOpenDialog *file_open_dialog = NULL;
+ // HRESULT res_co_create_instance = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&file_open_dialog));
+ HRESULT res_co_create_instance = (NULL != GetOpenFileNameW) ? NoRegCoCreate(L"Comdlg32.dll", CLSID_FileOpenDialog, IID_PPV_ARGS(&file_open_dialog)) : E_FAIL;
+ assert(SUCCEEDED(res_co_create_instance));
+
+ FILEOPENDIALOGOPTIONS file_open_dialog_options;
+ HRESULT res_file_open_dialog_get_options = file_open_dialog->GetOptions(&file_open_dialog_options);
+ assert(SUCCEEDED(res_file_open_dialog_get_options));
+
+ file_open_dialog_options |= FOS_FORCEFILESYSTEM;
+ file_open_dialog_options |= FOS_ALLOWMULTISELECT;
+
+ HRESULT res_file_open_dialog_set_options = file_open_dialog->SetOptions(file_open_dialog_options);
+ assert(SUCCEEDED(res_file_open_dialog_set_options));
+
+ COMDLG_FILTERSPEC const filter_specs[] = {
+ {L"All Files", L"*.*"},
+ {L"glTF Binary", L"*.glb"},
+ {L"glTF Separate", L"*.gltf"}};
+ HRESULT res_file_open_dialog_set_file_types = file_open_dialog->SetFileTypes(sizeof(filter_specs) / sizeof(filter_specs[0]), filter_specs);
+ assert(SUCCEEDED(res_file_open_dialog_set_file_types));
+
+ HRESULT res_file_open_dialog_set_file_type_index = file_open_dialog->SetFileTypeIndex(3U);
+ assert(SUCCEEDED(res_file_open_dialog_set_file_type_index));
+
+ HRESULT res_file_open_dialog_show = file_open_dialog->Show(NULL);
+ if (SUCCEEDED(res_file_open_dialog_show))
+ {
+ IShellItemArray *item_array;
+ HRESULT res_file_open_dialog_get_result = file_open_dialog->GetResults(&item_array);
+ assert(SUCCEEDED(res_file_open_dialog_get_result));
+
+ DWORD item_count;
+ HRESULT res_shell_item_array_get_count = item_array->GetCount(&item_count);
+ assert(SUCCEEDED(res_shell_item_array_get_count));
+
+ file_names.resize(static_cast(item_count));
+
+ for (DWORD item_index = 0U; item_index < item_count; ++item_index)
+ {
+ IShellItem *item;
+ HRESULT res_shell_item_array_get_item_at = item_array->GetItemAt(item_index, &item);
+ assert(SUCCEEDED(res_shell_item_array_get_item_at));
+
+ WCHAR *name;
+ HRESULT res_shell_item_get_display_name = item->GetDisplayName(SIGDN_FILESYSPATH, &name);
+ assert(SUCCEEDED(res_shell_item_get_display_name));
+
+ std::wstring file_name(name);
+
+ CoTaskMemFree(name);
+
+ item->Release();
+
+ bool res_convert_utf16_To_utf8_string = llvm::convertUTF16ToUTF8String(file_name, file_names[item_index]);
+ assert(res_convert_utf16_To_utf8_string);
+ }
+
+ item_array->Release();
+ }
+ else
+ {
+ assert(HRESULT_FROM_WIN32(ERROR_CANCELLED) == res_file_open_dialog_show);
+ return 0;
+ }
+
+ file_open_dialog->Release();
+
+ CoUninitialize();
+ }
+ else
+ {
+ file_names.resize(static_cast(argc - 1));
+
+ for (int arg_index = 1; arg_index < argc; ++arg_index)
+ {
+ std::wstring file_name(argv[1]);
+ bool res_convert_utf16_To_utf8_string = llvm::convertUTF16ToUTF8String(file_name, file_names[arg_index - 1]);
+ assert(res_convert_utf16_To_utf8_string);
+ }
+ }
+ }
+
+ HINSTANCE hInstance = reinterpret_cast(&__ImageBase);
+
+ g_window_width = 1280;
+ g_window_height = 720;
+
+ ATOM hWndCls;
+ {
+ WNDCLASSEXW Desc = {
+ sizeof(WNDCLASSEX),
+ CS_OWNDC,
+ wnd_proc,
+ 0,
+ 0,
+ hInstance,
+ LoadIconW(NULL, IDI_APPLICATION),
+ LoadCursorW(NULL, IDC_ARROW),
+ (HBRUSH)(COLOR_WINDOW + 1),
+ NULL,
+ L"glTF-Viewer:0XFFFFFFFF",
+ LoadIconW(NULL, IDI_APPLICATION),
+ };
+ hWndCls = RegisterClassExW(&Desc);
+ }
+
+ HWND hWnd;
+ {
+ HWND hDesktop = GetDesktopWindow();
+ HMONITOR hMonitor = MonitorFromWindow(hDesktop, MONITOR_DEFAULTTONEAREST);
+ MONITORINFOEXW MonitorInfo;
+ MonitorInfo.cbSize = sizeof(MONITORINFOEXW);
+ GetMonitorInfoW(hMonitor, &MonitorInfo);
+
+ constexpr DWORD const dw_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;
+ constexpr DWORD const dw_ex_style = WS_EX_APPWINDOW;
+
+ RECT rect = {(MonitorInfo.rcWork.left + MonitorInfo.rcWork.right) / 2 - g_window_width / 2,
+ (MonitorInfo.rcWork.bottom + MonitorInfo.rcWork.top) / 2 - g_window_height / 2,
+ (MonitorInfo.rcWork.left + MonitorInfo.rcWork.right) / 2 + g_window_width / 2,
+ (MonitorInfo.rcWork.bottom + MonitorInfo.rcWork.top) / 2 + g_window_height / 2};
+ AdjustWindowRectEx(&rect, dw_style, FALSE, dw_ex_style);
+
+ hWnd = CreateWindowExW(dw_ex_style, MAKEINTATOM(hWndCls), L"glTF Viewer", dw_style, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hDesktop, NULL, hInstance, NULL);
+ }
+
+ g_renderer = renderer_init(NULL, file_names);
+
+ renderer_attach_window(g_renderer, hWnd);
+
+ ShowWindow(hWnd, SW_SHOWDEFAULT);
+
+ BOOL result_update_window = UpdateWindow(hWnd);
+ assert(FALSE != result_update_window);
+ }
+
+ // Run
+ {
+ MSG msg;
+ while (GetMessageW(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+ }
+
+ // Destroy
+ {
+ renderer_dettach_window(g_renderer);
+
+ renderer_destroy(g_renderer);
+ }
+
+ return 0;
+}
+
+static LRESULT CALLBACK wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_DESTROY:
+ {
+ PostQuitMessage(0);
+ }
+ return 0;
+ case WM_PAINT:
+ {
+ renderer_draw(g_renderer);
+ }
+ return 0;
+ case WM_SIZE:
+ {
+ WORD const new_width = LOWORD(lParam);
+ WORD const new_height = HIWORD(lParam);
+
+ if (g_window_width != new_width || g_window_height != new_height)
+ {
+ renderer_on_window_resize(g_renderer);
+ g_window_width = new_width;
+ g_window_height = new_height;
+ }
+ }
+ return 0;
+ case WM_ERASEBKGND:
+ return 1;
+ case WM_KEYDOWN:
+ {
+ switch (wParam)
+ {
+ case 'W':
+ {
+ g_camera_controller.MoveForward();
+ }
+ break;
+ case 'S':
+ {
+ g_camera_controller.MoveBack();
+ }
+ break;
+ case 'A':
+ {
+ g_camera_controller.MoveLeft();
+ }
+ break;
+ case 'D':
+ {
+ g_camera_controller.MoveRight();
+ }
+ break;
+ case 'Q':
+ {
+ g_camera_controller.MoveDown();
+ }
+ break;
+ case 'E':
+ {
+ g_camera_controller.MoveUp();
+ }
+ break;
+ }
+ }
+ return 0;
+ case WM_MOUSEMOVE:
+ {
+ int Current_X = GET_X_LPARAM(lParam);
+ int Current_Y = GET_Y_LPARAM(lParam);
+
+ float CurrentNormalized_X = static_cast(Current_X) / g_window_width;
+ float CurrentNormalized_Y = static_cast(Current_Y) / g_window_height;
+
+ g_camera_controller.OnMouseMove(CurrentNormalized_X, CurrentNormalized_Y, (0 != (wParam & MK_RBUTTON)));
+ }
+ return 0;
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+}
+
+static HRESULT STDMETHODCALLTYPE NoRegCoCreate(const __wchar_t *dllName, REFCLSID rclsid, REFIID riid, void **ppv)
+{
+ HMODULE dynamic_library = LoadLibraryW(dllName);
+ if (NULL == dynamic_library)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ decltype(DllGetClassObject) *pfn_dll_get_class_object = reinterpret_cast(GetProcAddress(dynamic_library, "DllGetClassObject"));
+
+ if (NULL == pfn_dll_get_class_object)
+ {
+ FreeLibrary(dynamic_library);
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ IClassFactory *class_factory = nullptr;
+ HRESULT hr_dll_get_class_object = pfn_dll_get_class_object(rclsid, IID_PPV_ARGS(&class_factory));
+ if (!SUCCEEDED(hr_dll_get_class_object))
+ {
+ FreeLibrary(dynamic_library);
+ return hr_dll_get_class_object;
+ }
+
+ HRESULT hr_class_factory_create_instance = class_factory->CreateInstance(nullptr, riid, ppv);
+ class_factory->Release();
+
+ // TODO: DllCanUnloadNow
+
+ return hr_class_factory_create_instance;
+}
+
+#else
+#error Unknown Compiler
+#endif
\ No newline at end of file
diff --git a/source/support/renderer.cpp b/source/support/renderer.cpp
new file mode 100644
index 0000000..040ffaa
--- /dev/null
+++ b/source/support/renderer.cpp
@@ -0,0 +1,435 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include
+#include
+#include
+#include
+
+#include "renderer.h"
+#include "frame_throttling.h"
+#include "tick_count.h"
+#include "../../thirdparty/Brioche/include/brx_device.h"
+#include "../demo.h"
+
+class renderer
+{
+ brx_device *m_device;
+
+ brx_graphics_queue *m_graphics_queue;
+
+ uint32_t m_frame_throttling_index;
+
+ brx_graphics_command_buffer *m_command_buffers[FRAME_THROTTLING_COUNT];
+ brx_fence *m_fences[FRAME_THROTTLING_COUNT];
+
+ brx_surface *m_surface;
+ brx_swap_chain *m_swap_chain;
+
+ Demo m_demo;
+
+ brx_pipeline_layout *m_full_screen_transfer_pipeline_layout;
+
+ brx_render_pass *m_full_screen_transfer_render_pass;
+ brx_graphics_pipeline *m_full_screen_transfer_pipeline;
+
+ brx_descriptor_set_layout *m_full_screen_transfer_pipeline_none_update_descriptor_set_layout;
+ brx_descriptor_set *m_full_screen_transfer_pipeline_none_update_descriptor_set;
+
+ BRX_COLOR_ATTACHMENT_IMAGE_FORMAT m_swap_chain_image_format;
+ uint32_t m_swap_chain_image_width;
+ uint32_t m_swap_chain_image_height;
+ std::vector m_swap_chain_frame_buffers;
+
+ double m_tick_count_resolution;
+ uint64_t m_tick_count_previous_frame;
+
+ void attach_swap_chain();
+
+ void dettach_swap_chain();
+
+ void create_swap_chain_render_pass_and_pipeline();
+
+ void destroy_swap_chain_render_pass_and_pipeline();
+
+public:
+ renderer();
+
+ ~renderer();
+
+ void init(void *wsi_connection, std::vector const &file_names);
+
+ void destroy();
+
+ void attach_window(void *wsi_window);
+
+ void on_window_resize();
+
+ void dettach_window();
+
+ void draw();
+};
+
+renderer::renderer() : m_surface(NULL), m_swap_chain(NULL)
+{
+}
+
+renderer::~renderer()
+{
+ for (uint32_t frame_throtting_index = 0U; frame_throtting_index < FRAME_THROTTLING_COUNT; ++frame_throtting_index)
+ {
+ assert(NULL == this->m_command_buffers[frame_throtting_index]);
+ assert(NULL == this->m_fences[frame_throtting_index]);
+ }
+
+ assert(NULL == this->m_surface);
+ assert(NULL == this->m_swap_chain);
+
+ assert(NULL == this->m_device);
+}
+
+extern renderer *renderer_init(void *wsi_connection, std::vector const &file_names)
+{
+ renderer *new_renderer = new (malloc(sizeof(renderer))) renderer{};
+ new_renderer->init(wsi_connection, file_names);
+ return new_renderer;
+}
+
+extern void renderer_destroy(renderer *renderer)
+{
+ renderer->destroy();
+ renderer->~renderer();
+ free(renderer);
+}
+
+extern void renderer_attach_window(renderer *renderer, void *wsi_window)
+{
+ renderer->attach_window(wsi_window);
+}
+
+extern void renderer_on_window_resize(renderer *renderer)
+{
+ renderer->on_window_resize();
+}
+
+extern void renderer_dettach_window(renderer *renderer)
+{
+ renderer->dettach_window();
+}
+
+extern void renderer_draw(renderer *renderer)
+{
+ renderer->draw();
+}
+
+void renderer::init(void *wsi_connection, std::vector const &file_names)
+{
+ this->m_device = brx_init_unknown_device(wsi_connection, false);
+
+ this->m_graphics_queue = this->m_device->create_graphics_queue();
+
+ this->m_frame_throttling_index = 0U;
+
+ for (uint32_t frame_throtting_index = 0U; frame_throtting_index < FRAME_THROTTLING_COUNT; ++frame_throtting_index)
+ {
+ this->m_command_buffers[frame_throtting_index] = this->m_device->create_graphics_command_buffer();
+ this->m_fences[frame_throtting_index] = this->m_device->create_fence(true);
+ }
+
+ // Demo Init
+ this->m_demo.init(this->m_device, file_names);
+
+ // Descriptor Layout
+ {
+ BRX_DESCRIPTOR_SET_LAYOUT_BINDING full_screen_transfer_none_update_descriptor_set_layout_bindings[] = {
+ // texture and sampler
+ {0U, BRX_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1U}};
+ this->m_full_screen_transfer_pipeline_none_update_descriptor_set_layout = this->m_device->create_descriptor_set_layout(sizeof(full_screen_transfer_none_update_descriptor_set_layout_bindings) / sizeof(full_screen_transfer_none_update_descriptor_set_layout_bindings[0]), full_screen_transfer_none_update_descriptor_set_layout_bindings);
+
+ brx_descriptor_set_layout *const full_screen_transfer_descriptor_set_layouts[] = {this->m_full_screen_transfer_pipeline_none_update_descriptor_set_layout};
+ this->m_full_screen_transfer_pipeline_layout = this->m_device->create_pipeline_layout(sizeof(full_screen_transfer_descriptor_set_layouts) / sizeof(full_screen_transfer_descriptor_set_layouts[0]), full_screen_transfer_descriptor_set_layouts);
+ }
+
+ // Pipeline
+ {
+ this->m_swap_chain_image_format = BRX_COLOR_ATTACHMENT_FORMAT_B8G8R8A8_UNORM;
+ this->m_full_screen_transfer_render_pass = NULL;
+ this->m_full_screen_transfer_pipeline = NULL;
+ this->create_swap_chain_render_pass_and_pipeline();
+ }
+
+ // Descriptor
+ {
+ this->m_full_screen_transfer_pipeline_none_update_descriptor_set = this->m_device->create_descriptor_set(this->m_full_screen_transfer_pipeline_none_update_descriptor_set_layout);
+ }
+
+ // Init SwapChain Related
+ this->m_swap_chain_image_width = 0U;
+ this->m_swap_chain_image_height = 0U;
+ assert(0U == this->m_swap_chain_frame_buffers.size());
+
+ // Tick Count
+ this->m_tick_count_resolution = (1.0 / static_cast(tick_count_per_second()));
+ this->m_tick_count_previous_frame = tick_count_now();
+}
+
+void renderer::destroy()
+{
+ for (uint32_t frame_throtting_index = 0U; frame_throtting_index < FRAME_THROTTLING_COUNT; ++frame_throtting_index)
+ {
+ this->m_device->wait_for_fence(this->m_fences[frame_throtting_index]);
+ }
+
+ this->m_demo.destroy(this->m_device);
+
+ this->m_device->destroy_descriptor_set(this->m_full_screen_transfer_pipeline_none_update_descriptor_set);
+
+ this->m_device->destroy_descriptor_set_layout(this->m_full_screen_transfer_pipeline_none_update_descriptor_set_layout);
+
+ this->destroy_swap_chain_render_pass_and_pipeline();
+
+ this->m_device->destroy_pipeline_layout(this->m_full_screen_transfer_pipeline_layout);
+
+ for (uint32_t frame_throtting_index = 0U; frame_throtting_index < FRAME_THROTTLING_COUNT; ++frame_throtting_index)
+ {
+ this->m_device->destroy_graphics_command_buffer(this->m_command_buffers[frame_throtting_index]);
+ this->m_command_buffers[frame_throtting_index] = NULL;
+ this->m_device->destroy_fence(this->m_fences[frame_throtting_index]);
+ this->m_fences[frame_throtting_index] = NULL;
+ }
+
+ brx_destroy_unknown_device(this->m_device);
+ this->m_device = NULL;
+}
+
+void renderer::attach_window(void *wsi_window)
+{
+ assert(NULL == this->m_surface);
+
+ this->m_surface = this->m_device->create_surface(wsi_window);
+ this->attach_swap_chain();
+}
+
+void renderer::on_window_resize()
+{
+ for (uint32_t frame_throtting_index = 0U; frame_throtting_index < FRAME_THROTTLING_COUNT; ++frame_throtting_index)
+ {
+ this->m_device->wait_for_fence(this->m_fences[frame_throtting_index]);
+ }
+
+ this->dettach_swap_chain();
+ this->attach_swap_chain();
+}
+
+void renderer::dettach_window()
+{
+ for (uint32_t frame_throtting_index = 0U; frame_throtting_index < FRAME_THROTTLING_COUNT; ++frame_throtting_index)
+ {
+ this->m_device->wait_for_fence(this->m_fences[frame_throtting_index]);
+ }
+
+ this->dettach_swap_chain();
+ this->m_device->destroy_surface(this->m_surface);
+
+ this->m_surface = NULL;
+ this->m_swap_chain = NULL;
+}
+
+void renderer::attach_swap_chain()
+{
+ assert(NULL == this->m_swap_chain);
+ this->m_swap_chain = this->m_device->create_swap_chain(this->m_surface);
+
+ assert(0U == this->m_swap_chain_image_width);
+ assert(0U == this->m_swap_chain_image_height);
+ this->m_swap_chain_image_width = this->m_swap_chain->get_image_width();
+ this->m_swap_chain_image_height = this->m_swap_chain->get_image_height();
+
+ if (this->m_swap_chain_image_format != this->m_swap_chain->get_image_format())
+ {
+ this->m_swap_chain_image_format = this->m_swap_chain->get_image_format();
+ this->destroy_swap_chain_render_pass_and_pipeline();
+ this->create_swap_chain_render_pass_and_pipeline();
+ }
+
+ uint32_t const swap_chain_image_count = this->m_swap_chain->get_image_count();
+ assert(0U == this->m_swap_chain_frame_buffers.size());
+ this->m_swap_chain_frame_buffers.resize(swap_chain_image_count);
+
+ for (uint32_t swap_chain_image_index = 0U; swap_chain_image_index < swap_chain_image_count; ++swap_chain_image_index)
+ {
+ brx_color_attachment_image const *const swap_chain_color_attachment_image = this->m_swap_chain->get_image(swap_chain_image_index);
+
+ this->m_swap_chain_frame_buffers[swap_chain_image_index] = this->m_device->create_frame_buffer(this->m_full_screen_transfer_render_pass, this->m_swap_chain_image_width, this->m_swap_chain_image_height, 1U, &swap_chain_color_attachment_image, NULL);
+ }
+
+ this->m_demo.on_swap_chain_attach(this->m_device, this->m_swap_chain_image_width, this->m_swap_chain_image_height);
+
+ // Descriptor
+ {
+ // Full Screen Transfer Pipeline
+ {
+ // The VkDescriptorSetLayout should still be valid when perform write update on VkDescriptorSet
+ assert(NULL != this->m_full_screen_transfer_pipeline_none_update_descriptor_set_layout);
+ {
+ brx_sampled_image const *const sampled_images[] = {
+ this->m_demo.get_sampled_image_for_present()};
+ this->m_device->write_descriptor_set(this->m_full_screen_transfer_pipeline_none_update_descriptor_set, 0U, BRX_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0U, sizeof(sampled_images) / sizeof(sampled_images[0]), NULL, NULL, NULL, NULL, sampled_images, NULL, NULL, NULL);
+ }
+ }
+ }
+}
+
+void renderer::dettach_swap_chain()
+{
+ this->m_demo.on_swap_chain_dettach(this->m_device);
+
+ uint32_t const swap_chain_image_count = static_cast(this->m_swap_chain_frame_buffers.size());
+ assert(this->m_swap_chain->get_image_count() == swap_chain_image_count);
+
+ for (uint32_t swap_chain_image_index = 0U; swap_chain_image_index < swap_chain_image_count; ++swap_chain_image_index)
+ {
+ this->m_device->destroy_frame_buffer(this->m_swap_chain_frame_buffers[swap_chain_image_index]);
+ }
+
+ this->m_swap_chain_frame_buffers.clear();
+
+ this->m_swap_chain_image_width = 0U;
+ this->m_swap_chain_image_height = 0U;
+
+ this->m_device->destroy_swap_chain(this->m_swap_chain);
+ this->m_swap_chain = NULL;
+}
+
+void renderer::create_swap_chain_render_pass_and_pipeline()
+{
+ assert(NULL == this->m_full_screen_transfer_render_pass);
+ assert(NULL == this->m_full_screen_transfer_pipeline);
+
+ // Render Pass
+ {
+ BRX_RENDER_PASS_COLOR_ATTACHMENT color_attachments[1] = {
+ {this->m_swap_chain_image_format,
+ BRX_RENDER_PASS_COLOR_ATTACHMENT_LOAD_OPERATION_CLEAR,
+ BRX_RENDER_PASS_COLOR_ATTACHMENT_STORE_OPERATION_FLUSH_FOR_PRESENT}};
+
+ this->m_full_screen_transfer_render_pass = this->m_device->create_render_pass(sizeof(color_attachments) / sizeof(color_attachments[0]), color_attachments, NULL);
+ }
+
+ // Pipeline
+ {
+#include
+#include
+ this->m_full_screen_transfer_pipeline = this->m_device->create_graphics_pipeline(this->m_full_screen_transfer_render_pass, this->m_full_screen_transfer_pipeline_layout, sizeof(full_screen_transfer_vertex_shader_module_code), full_screen_transfer_vertex_shader_module_code, sizeof(full_screen_transfer_fragment_shader_module_code), full_screen_transfer_fragment_shader_module_code, false, BRX_GRAPHICS_PIPELINE_COMPARE_OPERATION_ALWAYS);
+ }
+}
+
+void renderer::destroy_swap_chain_render_pass_and_pipeline()
+{
+ this->m_device->destroy_render_pass(this->m_full_screen_transfer_render_pass);
+ this->m_device->destroy_graphics_pipeline(this->m_full_screen_transfer_pipeline);
+
+ this->m_full_screen_transfer_render_pass = NULL;
+ this->m_full_screen_transfer_pipeline = NULL;
+}
+
+void renderer::draw()
+{
+ if (NULL == this->m_surface)
+ {
+ // skip this frame
+ return;
+ }
+
+ assert(NULL != this->m_swap_chain);
+
+ this->m_device->wait_for_fence(this->m_fences[this->m_frame_throttling_index]);
+
+ this->m_device->reset_graphics_command_buffer(this->m_command_buffers[this->m_frame_throttling_index]);
+
+ this->m_command_buffers[this->m_frame_throttling_index]->begin();
+
+ {
+ uint64_t const tick_count_current_frame = tick_count_now();
+ float const interval_time = static_cast(static_cast(tick_count_current_frame - this->m_tick_count_previous_frame) * this->m_tick_count_resolution);
+ this->m_tick_count_previous_frame = tick_count_current_frame;
+
+ this->m_demo.draw(this->m_command_buffers[this->m_frame_throttling_index], interval_time, this->m_frame_throttling_index);
+ }
+
+ uint32_t swap_chain_image_index = -1;
+ bool acquire_next_image_not_out_of_date = this->m_device->acquire_next_image(this->m_command_buffers[this->m_frame_throttling_index], this->m_swap_chain, &swap_chain_image_index);
+ if (!acquire_next_image_not_out_of_date)
+ {
+ // NOTE: we should end the command buffer before we destroy the bound image
+ this->m_command_buffers[this->m_frame_throttling_index]->end();
+
+ for (uint32_t frame_throtting_index = 0U; frame_throtting_index < FRAME_THROTTLING_COUNT; ++frame_throtting_index)
+ {
+ this->m_device->wait_for_fence(this->m_fences[frame_throtting_index]);
+ }
+
+ this->dettach_swap_chain();
+ this->attach_swap_chain();
+
+ // skip this frame
+ return;
+ }
+
+ // draw full screen triangle
+ {
+ this->m_command_buffers[this->m_frame_throttling_index]->begin_debug_utils_label("Full Screen Transfer Pass");
+
+ float color_clear_values[4] = {0.0F, 0.0F, 0.0F, 0.0F};
+ this->m_command_buffers[this->m_frame_throttling_index]->begin_render_pass(this->m_full_screen_transfer_render_pass, this->m_swap_chain_frame_buffers[swap_chain_image_index], this->m_swap_chain_image_width, this->m_swap_chain_image_height, 1U, &color_clear_values, NULL, NULL);
+
+ this->m_command_buffers[this->m_frame_throttling_index]->bind_graphics_pipeline(this->m_full_screen_transfer_pipeline);
+
+ this->m_command_buffers[this->m_frame_throttling_index]->set_view_port(this->m_swap_chain_image_width, this->m_swap_chain_image_height);
+
+ this->m_command_buffers[this->m_frame_throttling_index]->set_scissor(this->m_swap_chain_image_width, this->m_swap_chain_image_height);
+
+ brx_descriptor_set *const descritor_sets[1] = {this->m_full_screen_transfer_pipeline_none_update_descriptor_set};
+ this->m_command_buffers[this->m_frame_throttling_index]->bind_graphics_descriptor_sets(this->m_full_screen_transfer_pipeline_layout, sizeof(descritor_sets) / sizeof(descritor_sets[0]), descritor_sets, 0U, NULL);
+ this->m_command_buffers[this->m_frame_throttling_index]->draw(3U, 1U);
+
+ this->m_command_buffers[this->m_frame_throttling_index]->end_render_pass();
+
+ this->m_command_buffers[this->m_frame_throttling_index]->end_debug_utils_label();
+ }
+
+ this->m_command_buffers[this->m_frame_throttling_index]->end();
+
+ this->m_device->reset_fence(this->m_fences[this->m_frame_throttling_index]);
+
+ bool present_not_out_of_date = this->m_graphics_queue->submit_and_present(this->m_command_buffers[this->m_frame_throttling_index], this->m_swap_chain, swap_chain_image_index, this->m_fences[this->m_frame_throttling_index]);
+ if (!present_not_out_of_date)
+ {
+ for (uint32_t frame_throtting_index = 0U; frame_throtting_index < FRAME_THROTTLING_COUNT; ++frame_throtting_index)
+ {
+ this->m_device->wait_for_fence(this->m_fences[frame_throtting_index]);
+ }
+
+ this->dettach_swap_chain();
+ this->attach_swap_chain();
+
+ // continue this frame
+ }
+
+ ++this->m_frame_throttling_index;
+ this->m_frame_throttling_index %= FRAME_THROTTLING_COUNT;
+}
diff --git a/source/support/renderer.h b/source/support/renderer.h
new file mode 100644
index 0000000..d01a053
--- /dev/null
+++ b/source/support/renderer.h
@@ -0,0 +1,31 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _RENDERER_H_
+#define _RENDERER_H_ 1
+
+#include
+#include
+
+extern class renderer *renderer_init(void *wsi_connection, std::vector const &file_names);
+extern void renderer_destroy(class renderer *renderer);
+extern void renderer_attach_window(class renderer *renderer, void *wsi_window);
+extern void renderer_on_window_resize(class renderer *renderer);
+extern void renderer_dettach_window(class renderer *renderer);
+extern void renderer_draw(class renderer *renderer);
+
+#endif
\ No newline at end of file
diff --git a/source/support/tick_count.cpp b/source/support/tick_count.cpp
new file mode 100644
index 0000000..08f2f3e
--- /dev/null
+++ b/source/support/tick_count.cpp
@@ -0,0 +1,70 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#include "tick_count.h"
+#include
+
+#if defined(__GNUC__)
+
+#include
+
+extern uint64_t tick_count_per_second()
+{
+ constexpr uint64_t const tick_count_per_second = 1000000000ULL;
+ return tick_count_per_second;
+}
+
+extern uint64_t tick_count_now()
+{
+ struct timespec time_monotonic;
+ int result_clock_get_time_monotonic = clock_gettime(CLOCK_MONOTONIC, &time_monotonic);
+ assert(0 == result_clock_get_time_monotonic);
+
+ uint64_t const tick_count_now = static_cast(1000000000ULL) * static_cast(time_monotonic.tv_sec) + static_cast(time_monotonic.tv_nsec);
+ return tick_count_now;
+}
+
+#elif defined(_MSC_VER)
+
+#define NOMINMAX 1
+#define WIN32_LEAN_AND_MEAN 1
+#include
+#include
+
+extern uint64_t tick_count_per_second()
+{
+ LARGE_INTEGER int64_frequency;
+ BOOL result_query_performance_frequency = QueryPerformanceFrequency(&int64_frequency);
+ assert(NULL != result_query_performance_frequency);
+
+ uint64_t const tick_count_per_second = static_cast(int64_frequency.QuadPart);
+ return tick_count_per_second;
+}
+
+extern uint64_t tick_count_now()
+{
+ LARGE_INTEGER int64_performance_count;
+ BOOL result_query_performance_counter = QueryPerformanceCounter(&int64_performance_count);
+ assert(NULL != result_query_performance_counter);
+
+ uint64_t const tick_count_now = static_cast(int64_performance_count.QuadPart);
+ return tick_count_now;
+}
+
+#else
+#error Unknown Compiler
+#endif
\ No newline at end of file
diff --git a/source/support/tick_count.h b/source/support/tick_count.h
new file mode 100644
index 0000000..db67e45
--- /dev/null
+++ b/source/support/tick_count.h
@@ -0,0 +1,28 @@
+//
+// Copyright (C) YuqiaoZhang(HanetakaChou)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+
+#ifndef _TICK_COUNT_H_
+#define _TICK_COUNT_H_ 1
+
+#include
+#include
+
+extern uint64_t tick_count_per_second();
+
+extern uint64_t tick_count_now();
+
+#endif
diff --git a/spirv/.gitignore b/spirv/.gitignore
new file mode 100644
index 0000000..70a618f
--- /dev/null
+++ b/spirv/.gitignore
@@ -0,0 +1,2 @@
+/debug
+/release
diff --git a/spirv/deferred_shading_fragment.inl b/spirv/deferred_shading_fragment.inl
new file mode 100644
index 0000000..6263fb9
--- /dev/null
+++ b/spirv/deferred_shading_fragment.inl
@@ -0,0 +1,7 @@
+constexpr uint32_t const deferred_shading_fragment_shader_module_code[] = {
+#ifndef NDEBUG
+#include "debug/_internal_deferred_shading_fragment.inl"
+#else
+#include "release/_internal_deferred_shading_fragment.inl"
+#endif
+};
\ No newline at end of file
diff --git a/spirv/deferred_shading_vertex.inl b/spirv/deferred_shading_vertex.inl
new file mode 100644
index 0000000..c8e2759
--- /dev/null
+++ b/spirv/deferred_shading_vertex.inl
@@ -0,0 +1,7 @@
+constexpr uint32_t const deferred_shading_vertex_shader_module_code[] = {
+#ifndef NDEBUG
+#include "debug/_internal_deferred_shading_vertex.inl"
+#else
+#include "release/_internal_deferred_shading_vertex.inl"
+#endif
+};
\ No newline at end of file
diff --git a/spirv/full_screen_transfer_fragment.inl b/spirv/full_screen_transfer_fragment.inl
new file mode 100644
index 0000000..02af46e
--- /dev/null
+++ b/spirv/full_screen_transfer_fragment.inl
@@ -0,0 +1,7 @@
+constexpr uint32_t const full_screen_transfer_fragment_shader_module_code[] = {
+#ifndef NDEBUG
+#include "debug/_internal_full_screen_transfer_fragment.inl"
+#else
+#include "release/_internal_full_screen_transfer_fragment.inl"
+#endif
+};
diff --git a/spirv/full_screen_transfer_vertex.inl b/spirv/full_screen_transfer_vertex.inl
new file mode 100644
index 0000000..739c407
--- /dev/null
+++ b/spirv/full_screen_transfer_vertex.inl
@@ -0,0 +1,7 @@
+constexpr uint32_t const full_screen_transfer_vertex_shader_module_code[] = {
+#ifndef NDEBUG
+#include "debug/_internal_full_screen_transfer_vertex.inl"
+#else
+#include "release/_internal_full_screen_transfer_vertex.inl"
+#endif
+};
diff --git a/spirv/gbuffer_fragment.inl b/spirv/gbuffer_fragment.inl
new file mode 100644
index 0000000..9fbf8c7
--- /dev/null
+++ b/spirv/gbuffer_fragment.inl
@@ -0,0 +1,7 @@
+constexpr uint32_t const gbuffer_fragment_shader_module_code[] = {
+#ifndef NDEBUG
+#include "debug/_internal_gbuffer_fragment.inl"
+#else
+#include "release/_internal_gbuffer_fragment.inl"
+#endif
+};
\ No newline at end of file
diff --git a/spirv/gbuffer_vertex.inl b/spirv/gbuffer_vertex.inl
new file mode 100644
index 0000000..6136f97
--- /dev/null
+++ b/spirv/gbuffer_vertex.inl
@@ -0,0 +1,7 @@
+constexpr uint32_t const gbuffer_vertex_shader_module_code[] = {
+#ifndef NDEBUG
+#include "debug/_internal_gbuffer_vertex.inl"
+#else
+#include "release/_internal_gbuffer_vertex.inl"
+#endif
+};
\ No newline at end of file
diff --git a/spirv/skin_compute.inl b/spirv/skin_compute.inl
new file mode 100644
index 0000000..295eec3
--- /dev/null
+++ b/spirv/skin_compute.inl
@@ -0,0 +1,7 @@
+constexpr uint32_t const skin_compute_shader_module_code[] = {
+#ifndef NDEBUG
+#include "debug/_internal_skin_compute.inl"
+#else
+#include "release/_internal_skin_compute.inl"
+#endif
+};
\ No newline at end of file
diff --git a/thirdparty/Brioche b/thirdparty/Brioche
new file mode 160000
index 0000000..18ede08
--- /dev/null
+++ b/thirdparty/Brioche
@@ -0,0 +1 @@
+Subproject commit 18ede08be67d0a6fc2997926e471ab5018b069c0
diff --git a/thirdparty/ConvertUTF b/thirdparty/ConvertUTF
new file mode 160000
index 0000000..5b93321
--- /dev/null
+++ b/thirdparty/ConvertUTF
@@ -0,0 +1 @@
+Subproject commit 5b93321790018086ff99eb9d51acc0d0a95215eb
diff --git a/thirdparty/CoreRT b/thirdparty/CoreRT
new file mode 160000
index 0000000..a4d26a9
--- /dev/null
+++ b/thirdparty/CoreRT
@@ -0,0 +1 @@
+Subproject commit a4d26a90cba87a966769e154fcb01464800bd9ad
diff --git a/thirdparty/DLB b/thirdparty/DLB
new file mode 160000
index 0000000..19e0911
--- /dev/null
+++ b/thirdparty/DLB
@@ -0,0 +1 @@
+Subproject commit 19e09110ff8024afcc8d431fd462656501c9cb59
diff --git a/thirdparty/DirectXMath b/thirdparty/DirectXMath
new file mode 160000
index 0000000..0ab21b3
--- /dev/null
+++ b/thirdparty/DirectXMath
@@ -0,0 +1 @@
+Subproject commit 0ab21b3808cba7c009d7a086b000469ba0e83f73
diff --git a/thirdparty/ImportAsset b/thirdparty/ImportAsset
new file mode 160000
index 0000000..e8d0309
--- /dev/null
+++ b/thirdparty/ImportAsset
@@ -0,0 +1 @@
+Subproject commit e8d0309088fa7f6942cc679d101842b45aee415c