diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2017-11-13 04:14:15 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2017-11-13 04:14:15 +0000 |
| commit | 1b2530749ea3dc4937cdd7aa37e5a144e6d10183 (patch) | |
| tree | de2a77d6c8ce8a33c2b3070c66549f429e43a017 /unityplugin/UnityEmulator | |
| parent | Updated submodules (diff) | |
| download | DiligentEngine-1b2530749ea3dc4937cdd7aa37e5a144e6d10183.tar.gz DiligentEngine-1b2530749ea3dc4937cdd7aa37e5a144e6d10183.zip | |
Updated to version 2.1
Diffstat (limited to 'unityplugin/UnityEmulator')
51 files changed, 6467 insertions, 0 deletions
diff --git a/unityplugin/UnityEmulator/build/UWP.Shared/UnityEmulatorUWP.Shared.vcxitems b/unityplugin/UnityEmulator/build/UWP.Shared/UnityEmulatorUWP.Shared.vcxitems new file mode 100644 index 0000000..a0d4048 --- /dev/null +++ b/unityplugin/UnityEmulator/build/UWP.Shared/UnityEmulatorUWP.Shared.vcxitems @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup Label="Globals"> + <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> + <HasSharedItems>true</HasSharedItems> + <ItemsProjectGuid>{FBE96ADC-7C36-45B2-BE6D-F173413EB1C6}</ItemsProjectGuid> + <ItemsRootNamespace>AtmosphereSample</ItemsRootNamespace> + <ItemsProjectName>UnityEmulatorUWP.Shared</ItemsProjectName> + <SharedGUID>2c11e612-847b-48ac-a5dd-fd953e773442</SharedGUID> + </PropertyGroup> + <ItemDefinitionGroup> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ProjectCapability Include="SourceItemsFromImports" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UWP\App.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UWP\DeviceResources.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UWP\UnityEmulatorAppMain.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\App.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\DeviceResources.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\DirectXHelper.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\pch2.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\UnityEmulatorAppMain.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\StepTimer.h" /> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/UWP.Shared/UnityEmulatorUWP.Shared.vcxitems.filters b/unityplugin/UnityEmulator/build/UWP.Shared/UnityEmulatorUWP.Shared.vcxitems.filters new file mode 100644 index 0000000..6763a1b --- /dev/null +++ b/unityplugin/UnityEmulator/build/UWP.Shared/UnityEmulatorUWP.Shared.vcxitems.filters @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UWP\App.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UWP\DeviceResources.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UWP\UnityEmulatorAppMain.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\App.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\pch2.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\DeviceResources.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\DirectXHelper.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\StepTimer.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UWP\UnityEmulatorAppMain.h" /> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/UWP/UnityEmulator.vcxproj b/unityplugin/UnityEmulator/build/UWP/UnityEmulator.vcxproj new file mode 100644 index 0000000..074fade --- /dev/null +++ b/unityplugin/UnityEmulator/build/UWP/UnityEmulator.vcxproj @@ -0,0 +1,200 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|ARM"> + <Configuration>Debug</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM"> + <Configuration>Release</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{17597734-2FBF-481F-99D4-3315B70FE3E2}</ProjectGuid> + <Keyword>StaticLibrary</Keyword> + <RootNamespace>UnityEmulator</RootNamespace> + <DefaultLanguage>en-US</DefaultLanguage> + <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion> + <AppContainerApplication>true</AppContainerApplication> + <ApplicationType>Windows Store</ApplicationType> + <WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformMinVersion>10.0.10240.0</WindowsTargetPlatformMinVersion> + <ApplicationTypeRevision>10.0</ApplicationTypeRevision> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + <Import Project="..\Windows.Shared\UnityEmulator.Shared.vcxitems" Label="Shared" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\..\..\diligentcore\Shared\build\UWP\UWP_Win32Dbg.props" /> + <Import Project="..\Windows.Shared\UnityEmulator.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\..\..\diligentcore\Shared\build\UWP\UWP_Win32Rel.props" /> + <Import Project="..\Windows.Shared\UnityEmulator.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\..\..\diligentcore\Shared\build\UWP\UWP_ArmDbg.props" /> + <Import Project="..\Windows.Shared\UnityEmulator.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\..\..\diligentcore\Shared\build\UWP\UWP_ArmRel.props" /> + <Import Project="..\Windows.Shared\UnityEmulator.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\..\..\diligentcore\Shared\build\UWP\UWP_X64Dbg.props" /> + <Import Project="..\Windows.Shared\UnityEmulator.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\..\..\diligentcore\Shared\build\UWP\UWP_X64Rel.props" /> + <Import Project="..\Windows.Shared\UnityEmulator.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <CompileAsWinRT>false</CompileAsWinRT> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + <GenerateWindowsMetadata>false</GenerateWindowsMetadata> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <CompileAsWinRT>false</CompileAsWinRT> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + <GenerateWindowsMetadata>false</GenerateWindowsMetadata> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|arm'"> + <ClCompile> + <CompileAsWinRT>false</CompileAsWinRT> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + <GenerateWindowsMetadata>false</GenerateWindowsMetadata> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|arm'"> + <ClCompile> + <CompileAsWinRT>false</CompileAsWinRT> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + <GenerateWindowsMetadata>false</GenerateWindowsMetadata> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <CompileAsWinRT>false</CompileAsWinRT> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + <GenerateWindowsMetadata>false</GenerateWindowsMetadata> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <CompileAsWinRT>false</CompileAsWinRT> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + <GenerateWindowsMetadata>false</GenerateWindowsMetadata> + </Link> + </ItemDefinitionGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/UWP/UnityEmulator.vcxproj.filters b/unityplugin/UnityEmulator/build/UWP/UnityEmulator.vcxproj.filters new file mode 100644 index 0000000..c31757e --- /dev/null +++ b/unityplugin/UnityEmulator/build/UWP/UnityEmulator.vcxproj.filters @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/Win32/UnityEmulator-Debug.vgdbsettings b/unityplugin/UnityEmulator/build/Win32/UnityEmulator-Debug.vgdbsettings new file mode 100644 index 0000000..3f5b24b --- /dev/null +++ b/unityplugin/UnityEmulator/build/Win32/UnityEmulator-Debug.vgdbsettings @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<VisualGDBProjectSettings2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <ConfigurationName>Debug</ConfigurationName> + <Project xsi:type="com.visualgdb.project.android"> + <CustomSourceDirectories> + <Directories /> + <PathStyle>MinGWWindowsSlash</PathStyle> + </CustomSourceDirectories> + <AndroidProjectPath>$(ProjectDir)</AndroidProjectPath> + </Project> + <Build xsi:type="com.visualgdb.build.android"> + <AndroidPlatform>android-19</AndroidPlatform> + <IsDebugConfiguration>true</IsDebugConfiguration> + <JNIOnlyBuild>true</JNIOnlyBuild> + <AdditionalDirectoriesToDeleteOnClean>bin;obj</AdditionalDirectoriesToDeleteOnClean> + <DeleteANTFilesOnClean>false</DeleteANTFilesOnClean> + <DoNotEditAndroidManifest>false</DoNotEditAndroidManifest> + <CustomActions /> + </Build> + <Debug xsi:type="com.visualgdb.debug.android"> + <AdditionalStartupCommands /> + <AdditionalGDBSettings> + <FilterSpuriousStoppedNotifications>false</FilterSpuriousStoppedNotifications> + <ForceSingleThreadedMode>false</ForceSingleThreadedMode> + <PendingBreakpointsSupported>true</PendingBreakpointsSupported> + <DisableChildRanges>false</DisableChildRanges> + <UseAppleExtensions>false</UseAppleExtensions> + <CanAcceptCommandsWhileRunning>false</CanAcceptCommandsWhileRunning> + <MakeLogFile>false</MakeLogFile> + <IgnoreModuleEventsWhileStepping>true</IgnoreModuleEventsWhileStepping> + <UseRelativePathsOnly>false</UseRelativePathsOnly> + <ExitAction>KillApp</ExitAction> + <Features> + <DisableAutoDetection>false</DisableAutoDetection> + <UseFrameParameter>false</UseFrameParameter> + <SimpleValuesFlagSupported>false</SimpleValuesFlagSupported> + <ListLocalsSupported>false</ListLocalsSupported> + <ByteLevelMemoryCommandsAvailable>false</ByteLevelMemoryCommandsAvailable> + <ThreadInfoSupported>false</ThreadInfoSupported> + <PendingBreakpointsSupported>false</PendingBreakpointsSupported> + <SupportTargetCommand>false</SupportTargetCommand> + </Features> + <DisableDisassembly>false</DisableDisassembly> + <ExamineMemoryWithXCommand>false</ExamineMemoryWithXCommand> + <StepIntoNewInstanceEntry>main</StepIntoNewInstanceEntry> + <ExamineRegistersInRawFormat>true</ExamineRegistersInRawFormat> + </AdditionalGDBSettings> + <LaunchGDBSettings xsi:type="GDBLaunchParametersAndroid" /> + <GenerateCtrlBreakInsteadOfCtrlC>false</GenerateCtrlBreakInsteadOfCtrlC> + <UseDefaultInstallDir>false</UseDefaultInstallDir> + <RemotePort>5039</RemotePort> + <LocalPort>5039</LocalPort> + <GDBServerStartupTimeout>10000</GDBServerStartupTimeout> + <AdditionalGDBServerStartupDelay>0</AdditionalGDBServerStartupDelay> + <DoubleSlashWorkaround>false</DoubleSlashWorkaround> + <AlreadyRunningDecision>Ask</AlreadyRunningDecision> + <ShowLogCat>true</ShowLogCat> + <EnableThreadNameWatcher>true</EnableThreadNameWatcher> + </Debug> + <CustomBuild> + <PreBuildActions /> + <PostBuildActions /> + <PreCleanActions /> + <PostCleanActions /> + </CustomBuild> + <CustomDebug> + <PreDebugActions /> + <PostDebugActions /> + <BreakMode>Default</BreakMode> + </CustomDebug> + <CustomShortcuts> + <Shortcuts /> + <ShowMessageAfterExecuting>true</ShowMessageAfterExecuting> + </CustomShortcuts> + <UserDefinedVariables /> +</VisualGDBProjectSettings2>
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/Win32/UnityEmulator-Release.vgdbsettings b/unityplugin/UnityEmulator/build/Win32/UnityEmulator-Release.vgdbsettings new file mode 100644 index 0000000..669691f --- /dev/null +++ b/unityplugin/UnityEmulator/build/Win32/UnityEmulator-Release.vgdbsettings @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<VisualGDBProjectSettings2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <ConfigurationName>Release</ConfigurationName> + <Project xsi:type="com.visualgdb.project.android"> + <CustomSourceDirectories> + <Directories /> + <PathStyle>MinGWWindowsSlash</PathStyle> + </CustomSourceDirectories> + <AndroidProjectPath>$(ProjectDir)</AndroidProjectPath> + </Project> + <Build xsi:type="com.visualgdb.build.android"> + <AndroidPlatform>android-19</AndroidPlatform> + <IsDebugConfiguration>false</IsDebugConfiguration> + <JNIOnlyBuild>true</JNIOnlyBuild> + <AdditionalDirectoriesToDeleteOnClean>bin;obj</AdditionalDirectoriesToDeleteOnClean> + <DeleteANTFilesOnClean>false</DeleteANTFilesOnClean> + <DoNotEditAndroidManifest>false</DoNotEditAndroidManifest> + <CustomActions /> + </Build> + <Debug xsi:type="com.visualgdb.debug.android"> + <AdditionalStartupCommands /> + <AdditionalGDBSettings> + <FilterSpuriousStoppedNotifications>false</FilterSpuriousStoppedNotifications> + <ForceSingleThreadedMode>false</ForceSingleThreadedMode> + <PendingBreakpointsSupported>true</PendingBreakpointsSupported> + <DisableChildRanges>false</DisableChildRanges> + <UseAppleExtensions>false</UseAppleExtensions> + <CanAcceptCommandsWhileRunning>false</CanAcceptCommandsWhileRunning> + <MakeLogFile>false</MakeLogFile> + <IgnoreModuleEventsWhileStepping>true</IgnoreModuleEventsWhileStepping> + <UseRelativePathsOnly>false</UseRelativePathsOnly> + <ExitAction>KillApp</ExitAction> + <Features> + <DisableAutoDetection>false</DisableAutoDetection> + <UseFrameParameter>false</UseFrameParameter> + <SimpleValuesFlagSupported>false</SimpleValuesFlagSupported> + <ListLocalsSupported>false</ListLocalsSupported> + <ByteLevelMemoryCommandsAvailable>false</ByteLevelMemoryCommandsAvailable> + <ThreadInfoSupported>false</ThreadInfoSupported> + <PendingBreakpointsSupported>false</PendingBreakpointsSupported> + <SupportTargetCommand>false</SupportTargetCommand> + </Features> + <DisableDisassembly>false</DisableDisassembly> + <ExamineMemoryWithXCommand>false</ExamineMemoryWithXCommand> + <StepIntoNewInstanceEntry>main</StepIntoNewInstanceEntry> + <ExamineRegistersInRawFormat>true</ExamineRegistersInRawFormat> + </AdditionalGDBSettings> + <LaunchGDBSettings xsi:type="GDBLaunchParametersAndroid" /> + <GenerateCtrlBreakInsteadOfCtrlC>false</GenerateCtrlBreakInsteadOfCtrlC> + <UseDefaultInstallDir>false</UseDefaultInstallDir> + <RemotePort>5039</RemotePort> + <LocalPort>5039</LocalPort> + <GDBServerStartupTimeout>10000</GDBServerStartupTimeout> + <AdditionalGDBServerStartupDelay>0</AdditionalGDBServerStartupDelay> + <DoubleSlashWorkaround>false</DoubleSlashWorkaround> + <AlreadyRunningDecision>Ask</AlreadyRunningDecision> + <ShowLogCat>true</ShowLogCat> + <EnableThreadNameWatcher>true</EnableThreadNameWatcher> + </Debug> + <CustomBuild> + <PreBuildActions /> + <PostBuildActions /> + <PreCleanActions /> + <PostCleanActions /> + </CustomBuild> + <CustomDebug> + <PreDebugActions /> + <PostDebugActions /> + <BreakMode>Default</BreakMode> + </CustomDebug> + <CustomShortcuts> + <Shortcuts /> + <ShowMessageAfterExecuting>true</ShowMessageAfterExecuting> + </CustomShortcuts> + <UserDefinedVariables /> +</VisualGDBProjectSettings2>
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/Win32/UnityEmulator.vcxproj b/unityplugin/UnityEmulator/build/Win32/UnityEmulator.vcxproj new file mode 100644 index 0000000..d3dd0b6 --- /dev/null +++ b/unityplugin/UnityEmulator/build/Win32/UnityEmulator.vcxproj @@ -0,0 +1,265 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|ARM"> + <Configuration>Debug</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM"> + <Configuration>Release</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{F40021AC-6D7B-4828-81C4-2D04F946A88E}</ProjectGuid> + <RootNamespace>UnityEmulator</RootNamespace> + <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion> + <ProjectName>UnityEmulator</ProjectName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <PlatformToolset>v120</PlatformToolset> + <ConfigurationType>Makefile</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <PlatformToolset>v120</PlatformToolset> + <ConfigurationType>Makefile</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + <Import Project="..\Windows.Shared\UnityEmulator.Shared.vcxitems" Label="Shared" Condition="Exists('..\WindowsStore\UnityEmulator.Shared\UnityEmulator.Shared.vcxitems')" /> + </ImportGroup> + <ImportGroup Label="Shared"> + <Import Project="..\Windows.Shared\UnityEmulator.Shared.vcxitems" Label="Shared" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\..\..\diligentcore\Shared\build\Windows\Win32d.props" /> + <Import Project="..\Windows.Shared\UnityEmulator.props" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\..\..\diligentcore\Shared\build\Windows\Win64d.props" /> + <Import Project="..\Windows.Shared\UnityEmulator.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\..\..\diligentcore\Shared\build\Windows\Win32r.props" /> + <Import Project="..\Windows.Shared\UnityEmulator.props" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\..\..\diligentcore\Shared\build\Windows\Win64r.props" /> + <Import Project="..\Windows.Shared\UnityEmulator.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <Import Project="..\..\..\..\diligentcore\Shared\build\Windows\Android32d.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <Import Project="..\..\..\..\diligentcore\Shared\build\Windows\Android32r.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <NMakeForcedIncludes>$(ProjectDir)..\..\..\..\Common\Android\gcc_Debug.h;$(NMakeForcedIncludes)</NMakeForcedIncludes> + <NMakeOutput> + </NMakeOutput> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <NMakeForcedIncludes>$(ProjectDir)..\..\..\..\Common\Android\gcc_Release.h;$(NMakeForcedIncludes)</NMakeForcedIncludes> + <NMakeOutput> + </NMakeOutput> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>_WINDOWS;PLATFORM_WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + </Link> + <PostBuildEvent> + <Message>Copying D3DCompiler_47.dll to $(TargetDir)...</Message> + <Command>copy "$(VC_ExecutablePath_x86_x86)\D3Dcompiler_47.dll" "$(TargetDir)"</Command> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>_WINDOWS;PLATFORM_WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + </Link> + <PostBuildEvent> + <Message>Copying D3DCompiler_47.dll to $(TargetDir)...</Message> + <Command>copy "$(VC_ExecutablePath_x64_x64)\D3Dcompiler_47.dll" "$(TargetDir)"</Command> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>_WINDOWS;PLATFORM_WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <SubSystem>Windows</SubSystem> + </Link> + <PostBuildEvent> + <Message>Copying D3DCompiler_47.dll to $(TargetDir)...</Message> + <Command>copy "$(VC_ExecutablePath_x86_x86)\D3Dcompiler_47.dll" "$(TargetDir)"</Command> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>_WINDOWS;PLATFORM_WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <SubSystem>Windows</SubSystem> + </Link> + <PostBuildEvent> + <Message>Copying D3DCompiler_47.dll to $(TargetDir)...</Message> + <Command>copy "$(VC_ExecutablePath_x64_x64)\D3Dcompiler_47.dll" "$(TargetDir)"</Command> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\..\src\Android\AndroidMainImpl.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="..\..\src\Android\UnityGraphicsGLESAndroid_Impl.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="..\..\src\DiligentGraphicsAdapterGL.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="..\..\src\UnityGraphicsEmulator.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="..\..\src\UnityGraphicsGLCoreES_Emulator.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="..\..\src\Windows\WinMain.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\..\diligentcore\Common\build\Win32\Common.vcxproj"> + <Project>{7380f7e6-315f-4b4e-92eb-e6aeee865298}</Project> + </ProjectReference> + <ProjectReference Include="..\..\..\..\diligentcore\External\glew\build\Win32\glew_static.vcxproj"> + <Project>{664e6f0d-6784-4760-9565-d54f8eb1edf4}</Project> + </ProjectReference> + <ProjectReference Include="..\..\..\..\diligentcore\Graphics\GraphicsEngineD3D11\build\Win32\GraphicsEngineD3D11.vcxproj"> + <Project>{fe289cc7-15d6-4a76-b9cb-f61cab3192c9}</Project> + </ProjectReference> + <ProjectReference Include="..\..\..\..\diligentcore\Graphics\GraphicsEngineD3D12\build\Win32\GraphicsEngineD3D12.vcxproj"> + <Project>{fff8071a-db82-485b-adc3-f0b675296869}</Project> + </ProjectReference> + <ProjectReference Include="..\..\..\..\diligentcore\Graphics\GraphicsEngineOpenGL\build\Win32\GraphicsEngineOpenGL.vcxproj"> + <Project>{15e346d3-fde6-4b29-88b7-fca14dada501}</Project> + </ProjectReference> + <ProjectReference Include="..\..\..\..\diligentcore\Graphics\GraphicsEngine\build\Win32\GraphicsEngine.vcxproj"> + <Project>{052dd700-477c-4512-a7f4-b05ebef5c80e}</Project> + </ProjectReference> + <ProjectReference Include="..\..\..\..\diligentcore\Platforms\Basic\build\Win32\BasicPlatform.vcxproj"> + <Project>{8ada5f93-7a38-4ad8-b8f5-1ffd4d4f630c}</Project> + </ProjectReference> + <ProjectReference Include="..\..\..\..\diligentcore\Platforms\Win32\build\Win32\WindowsPlatform.vcxproj"> + <Project>{58f32677-436b-412a-bbf8-2b1310d82cd8}</Project> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <None Include="..\..\src\Android\Java\helper\NDKHelper.java" /> + <None Include="..\..\src\Android\Java\UnityEmulator\UnityEmulatorNativeActivity.java" /> + <None Include="..\..\src\Android\Java\UnityEmulator\UnityEmulatorApplication.java" /> + <None Include="jni\Android.mk" /> + <None Include="jni\Application.mk" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\src\Android\UnityGraphicsGLESAndroid_Impl.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/Win32/UnityEmulator.vcxproj.filters b/unityplugin/UnityEmulator/build/Win32/UnityEmulator.vcxproj.filters new file mode 100644 index 0000000..6952802 --- /dev/null +++ b/unityplugin/UnityEmulator/build/Win32/UnityEmulator.vcxproj.filters @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Android"> + <UniqueIdentifier>{154722cc-8c82-4869-8e51-fb073a87f966}</UniqueIdentifier> + </Filter> + <Filter Include="Android\Java"> + <UniqueIdentifier>{fe07d990-c5ac-488d-b7df-b3c66018d0b3}</UniqueIdentifier> + </Filter> + <Filter Include="Android\jni"> + <UniqueIdentifier>{31c218a8-0b04-4224-97ad-909aeff5c135}</UniqueIdentifier> + </Filter> + <Filter Include="Android\src"> + <UniqueIdentifier>{90e91db8-8be2-446b-abee-0365b7dc18a8}</UniqueIdentifier> + </Filter> + <Filter Include="Windows"> + <UniqueIdentifier>{e9f1e7cd-5112-4fb6-854a-3ebfd5efa88b}</UniqueIdentifier> + </Filter> + <Filter Include="Windows\src"> + <UniqueIdentifier>{f1774749-d1e5-4b2c-9f8d-df8ef690d4b5}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\src\Windows\WinMain.cpp"> + <Filter>Windows\src</Filter> + </ClCompile> + <ClCompile Include="..\..\src\Android\AndroidMainImpl.cpp"> + <Filter>Android\src</Filter> + </ClCompile> + <ClCompile Include="..\..\src\Android\UnityGraphicsGLESAndroid_Impl.cpp"> + <Filter>Android\src</Filter> + </ClCompile> + <ClCompile Include="..\..\src\UnityGraphicsGLCoreES_Emulator.cpp"> + <Filter>Android\src</Filter> + </ClCompile> + <ClCompile Include="..\..\src\DiligentGraphicsAdapterGL.cpp"> + <Filter>Android\src</Filter> + </ClCompile> + <ClCompile Include="..\..\src\UnityGraphicsEmulator.cpp"> + <Filter>Android\src</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <None Include="..\..\src\Android\Java\helper\NDKHelper.java"> + <Filter>Android\Java</Filter> + </None> + <None Include="jni\Android.mk"> + <Filter>Android\jni</Filter> + </None> + <None Include="jni\Application.mk"> + <Filter>Android\jni</Filter> + </None> + <None Include="..\..\src\Android\Java\UnityEmulator\UnityEmulatorNativeActivity.java"> + <Filter>Android\Java</Filter> + </None> + <None Include="..\..\src\Android\Java\UnityEmulator\UnityEmulatorApplication.java"> + <Filter>Android\Java</Filter> + </None> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\src\Android\UnityGraphicsGLESAndroid_Impl.h"> + <Filter>Android\src</Filter> + </ClInclude> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/Win32/jni/Android.mk b/unityplugin/UnityEmulator/build/Win32/jni/Android.mk new file mode 100644 index 0000000..45466e4 --- /dev/null +++ b/unityplugin/UnityEmulator/build/Win32/jni/Android.mk @@ -0,0 +1,46 @@ + +DEPENDENCY_PATH := $(call my-dir) +LOCAL_PATH := $(abspath $(DEPENDENCY_PATH)) + +include $(CLEAR_VARS) +# Project configuration +LOCAL_MODULE := UnityEmulator +LOCAL_CFLAGS := -std=c++11 -DENGINE_DLL +LOCAL_CPP_FEATURES := exceptions + +LOCAL_STATIC_LIBRARIES := cpufeatures android_native_app_glue ndk_helper + +# Include paths +PROJECT_ROOT := $(LOCAL_PATH)/../../.. +ENGINE_ROOT := $(PROJECT_ROOT)/../.. +CORE_ROOT := $(ENGINE_ROOT)/diligentcore +TOOLS_ROOT := $(ENGINE_ROOT)/diligenttools +# include directories for static libraries are declared in corresponding LOCAL_EXPORT_C_INCLUDES sections +LOCAL_C_INCLUDES += $(PROJECT_ROOT)/include +LOCAL_C_INCLUDES += $(PROJECT_ROOT)/src +LOCAL_C_INCLUDES += $(PROJECT_ROOT)/../GhostCubePlugin/PluginSource/src/Unity +LOCAL_C_INCLUDES += $(CORE_ROOT)/Common/include +LOCAL_C_INCLUDES += $(CORE_ROOT)/Common/interface +LOCAL_C_INCLUDES += $(CORE_ROOT)/Platforms/interface +LOCAL_C_INCLUDES += $(CORE_ROOT)/Graphics/GraphicsEngine/interface +LOCAL_C_INCLUDES += $(CORE_ROOT)/Graphics/GraphicsEngine/include +LOCAL_C_INCLUDES += $(CORE_ROOT)/Graphics/GraphicsEngineD3DBase/include +LOCAL_C_INCLUDES += $(CORE_ROOT)/Graphics/GraphicsEngineOpenGL/interface +LOCAL_C_INCLUDES += $(CORE_ROOT)/Graphics/HLSL2GLSLConverterLib/interface +LOCAL_C_INCLUDES += $(TOOLS_ROOT)/Graphics/GraphicsTools/include + +# Source files +#VisualGDBAndroid: AutoUpdateSourcesInNextLine +LOCAL_SRC_FILES := ../../../src/Android/AndroidMainImpl.cpp ../../../src/Android/UnityGraphicsGLESAndroid_Impl.cpp ../../../src/DiligentGraphicsAdapterGL.cpp ../../../src/UnityGraphicsEmulator.cpp ../../../src/UnityGraphicsGLCoreES_Emulator.cpp ../../../src/Windows/WinMain.cpp + +# Build instructions +#VisualGDBAndroid: VSExcludeListLocation +VISUALGDB_VS_EXCLUDED_FILES_Release := ../../../Src/Win32/WinMain.cpp +VISUALGDB_VS_EXCLUDED_FILES_Debug := ../../../src/Windows/WinMain.cpp +LOCAL_SRC_FILES := $(filter-out $(VISUALGDB_VS_EXCLUDED_FILES_$(VGDB_VSCONFIG)),$(LOCAL_SRC_FILES)) + +include $(BUILD_STATIC_LIBRARY) + +$(call import-module,android/ndk_helper) +$(call import-module,android/native_app_glue) +$(call import-module,android/cpufeatures) diff --git a/unityplugin/UnityEmulator/build/Win32/jni/Application.mk b/unityplugin/UnityEmulator/build/Win32/jni/Application.mk new file mode 100644 index 0000000..e8ef4b4 --- /dev/null +++ b/unityplugin/UnityEmulator/build/Win32/jni/Application.mk @@ -0,0 +1,7 @@ +# Generated by VisualGDB + +DEPENDENCY_PATH := $(call my-dir) +LOCAL_PATH := $(abspath $(DEPENDENCY_PATH)) +include $(LOCAL_PATH)/../../../../../diligentcore/Common/make/AppCommon.mk + +APP_MODULES := UnityEmulator
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/Windows.Shared/UnityEmulator.Shared.vcxitems b/unityplugin/UnityEmulator/build/Windows.Shared/UnityEmulator.Shared.vcxitems new file mode 100644 index 0000000..37e73bc --- /dev/null +++ b/unityplugin/UnityEmulator/build/Windows.Shared/UnityEmulator.Shared.vcxitems @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup Label="Globals"> + <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> + <HasSharedItems>true</HasSharedItems> + <ItemsProjectGuid>{ae83b976-c8ca-4621-9269-bf47c5789018}</ItemsProjectGuid> + <ItemsRootNamespace>AtmosphereSample</ItemsRootNamespace> + <ItemsProjectName>UnityEmulator.Shared</ItemsProjectName> + <SharedGUID>2c11e612-847b-48ac-a5dd-fd953e773442</SharedGUID> + </PropertyGroup> + <ItemDefinitionGroup> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ProjectCapability Include="SourceItemsFromImports" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DiligentGraphicsAdapter.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DiligentGraphicsAdapterD3D11.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DiligentGraphicsAdapterD3D12.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DiligentGraphicsAdapterGL.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ResourceStateTransitionHandler.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\UnityGraphicsD3D11Emulator.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\UnityGraphicsD3D12Emulator.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\UnityGraphicsEmulator.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\UnityGraphicsGLCoreES_Emulator.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\UnitySceneBase.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsD3D11Impl.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsD3D12Impl.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsGLCore_Impl.h" /> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsGL_Impl.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsD3D11Emulator.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsD3D12Emulator.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsEmulator.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsGLCoreES_Emulator.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DiligentGraphicsAdapterD3D11.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DiligentGraphicsAdapterD3D12.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DiligentGraphicsAdapterGL.cpp" /> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsGLCore_Impl.cpp" /> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/Windows.Shared/UnityEmulator.Shared.vcxitems.filters b/unityplugin/UnityEmulator/build/Windows.Shared/UnityEmulator.Shared.vcxitems.filters new file mode 100644 index 0000000..4fb2f8d --- /dev/null +++ b/unityplugin/UnityEmulator/build/Windows.Shared/UnityEmulator.Shared.vcxitems.filters @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="src"> + <UniqueIdentifier>{74468132-c052-44c1-9407-963d145244d1}</UniqueIdentifier> + </Filter> + <Filter Include="include"> + <UniqueIdentifier>{58f43661-c9a6-48e2-bfaa-818a394b2c36}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\UnitySceneBase.h"> + <Filter>include</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DiligentGraphicsAdapter.h"> + <Filter>include</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DiligentGraphicsAdapterD3D11.h"> + <Filter>include</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DiligentGraphicsAdapterD3D12.h"> + <Filter>include</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\DiligentGraphicsAdapterGL.h"> + <Filter>include</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsD3D11Impl.h"> + <Filter>src</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsD3D12Impl.h"> + <Filter>src</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\ResourceStateTransitionHandler.h"> + <Filter>include</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\UnityGraphicsD3D11Emulator.h"> + <Filter>include</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\UnityGraphicsD3D12Emulator.h"> + <Filter>include</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\UnityGraphicsEmulator.h"> + <Filter>include</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsGLCore_Impl.h"> + <Filter>src</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\include\UnityGraphicsGLCoreES_Emulator.h"> + <Filter>include</Filter> + </ClInclude> + <ClInclude Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsGL_Impl.h"> + <Filter>include</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsD3D11Emulator.cpp"> + <Filter>src</Filter> + </ClCompile> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsEmulator.cpp"> + <Filter>src</Filter> + </ClCompile> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsD3D12Emulator.cpp"> + <Filter>src</Filter> + </ClCompile> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DiligentGraphicsAdapterD3D11.cpp"> + <Filter>src</Filter> + </ClCompile> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DiligentGraphicsAdapterD3D12.cpp"> + <Filter>src</Filter> + </ClCompile> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\DiligentGraphicsAdapterGL.cpp"> + <Filter>src</Filter> + </ClCompile> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsGLCore_Impl.cpp"> + <Filter>src</Filter> + </ClCompile> + <ClCompile Include="$(MSBuildThisFileDirectory)..\..\src\UnityGraphicsGLCoreES_Emulator.cpp"> + <Filter>src</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/build/Windows.Shared/UnityEmulator.props b/unityplugin/UnityEmulator/build/Windows.Shared/UnityEmulator.props new file mode 100644 index 0000000..915b946 --- /dev/null +++ b/unityplugin/UnityEmulator/build/Windows.Shared/UnityEmulator.props @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ImportGroup Label="PropertySheets" /> + <PropertyGroup Label="UserMacros"> + <ProjectRoot>..\..</ProjectRoot> + <AssetsPath>$(ProjectRoot)\build\assets</AssetsPath> + <EngineRoot>$(ProjectRoot)\..\..</EngineRoot> + <CoreRoot>$(EngineRoot)\diligentcore</CoreRoot> + <ToolsRoot>$(EngineRoot)\diligenttools</ToolsRoot> + </PropertyGroup> + <PropertyGroup> + <IncludePath>$(ProjectRoot)\include;$(CoreRoot)\Graphics\GraphicsEngine\interface;$(CoreRoot)\Graphics\GraphicsEngine\include;$(CoreRoot)\Graphics\GraphicsEngineD3D11\interface;$(CoreRoot)\Graphics\GraphicsEngineD3D12\interface;$(CoreRoot)\Graphics\GraphicsEngineD3DBase\include;$(CoreRoot)\Graphics\GraphicsEngineOpenGL\interface;$(CoreRoot)\Graphics\HLSL2GLSLConverterLib\interface;$(CoreRoot)\Common\include;$(CoreRoot)\Common\interface;$(CoreRoot)\Platforms\interface;$(CoreRoot)\Graphics\GraphicsTools\include;$(ToolsRoot)\TextureLoader\interface;$(AssetsPath)\shaders;$(ProjectRoot)\..\GhostCubePlugin\PluginSource\src\Unity;$(ProjectRoot)\src;$(ProjectRoot)\src\UWP;$(CoreRoot)\External\glew\include\GL;$(IncludePath)</IncludePath> + </PropertyGroup> + <ItemDefinitionGroup> + <PostBuildEvent /> + <Link> + <AdditionalDependencies>d3d11.lib;d3d12.lib;d3dcompiler.lib;opengl32.lib;dxgi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <BuildMacro Include="ProjectRoot"> + <Value>$(ProjectRoot)</Value> + </BuildMacro> + <BuildMacro Include="AssetsPath"> + <Value>$(AssetsPath)</Value> + </BuildMacro> + <BuildMacro Include="EngineRoot"> + <Value>$(EngineRoot)</Value> + </BuildMacro> + <BuildMacro Include="CoreRoot"> + <Value>$(CoreRoot)</Value> + </BuildMacro> + <BuildMacro Include="ToolsRoot"> + <Value>$(ToolsRoot)</Value> + </BuildMacro> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/include/DiligentGraphicsAdapter.h b/unityplugin/UnityEmulator/include/DiligentGraphicsAdapter.h new file mode 100644 index 0000000..5af252c --- /dev/null +++ b/unityplugin/UnityEmulator/include/DiligentGraphicsAdapter.h @@ -0,0 +1,50 @@ +/* Copyright 2015-2017 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ +#pragma once + +#include "RenderDevice.h" +#include "DeviceContext.h" +#include "RefCntAutoPtr.h" + +class DiligentGraphicsAdapter +{ +public: + virtual ~DiligentGraphicsAdapter() = 0; + + virtual void BeginFrame() = 0; + virtual void EndFrame() = 0; + virtual void PreSwapChainResize() {} + virtual void PostSwapChainResize() {} + + Diligent::IRenderDevice* GetDevice() { return m_pDevice; } + Diligent::IDeviceContext* GetContext() { return m_pDeviceCtx; } + Diligent::ISwapChain* GetSwapChain() { return m_pProxySwapChain; } + virtual bool UsesReverseZ() = 0; + +protected: + Diligent::RefCntAutoPtr<Diligent::IRenderDevice> m_pDevice; + Diligent::RefCntAutoPtr<Diligent::IDeviceContext> m_pDeviceCtx; + Diligent::RefCntAutoPtr<Diligent::ISwapChain> m_pProxySwapChain; +}; + +inline DiligentGraphicsAdapter::~DiligentGraphicsAdapter() {} diff --git a/unityplugin/UnityEmulator/include/DiligentGraphicsAdapterD3D11.h b/unityplugin/UnityEmulator/include/DiligentGraphicsAdapterD3D11.h new file mode 100644 index 0000000..3e5d64f --- /dev/null +++ b/unityplugin/UnityEmulator/include/DiligentGraphicsAdapterD3D11.h @@ -0,0 +1,41 @@ +/* Copyright 2015-2017 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ +#pragma once + +#include "DiligentGraphicsAdapter.h" + +class DiligentGraphicsAdapterD3D11 : public DiligentGraphicsAdapter +{ +public: + virtual ~DiligentGraphicsAdapterD3D11()override {} + + DiligentGraphicsAdapterD3D11(const class UnityGraphicsD3D11Emulator& UnityGraphicsD3D11)noexcept; + void InitProxySwapChain(); + + virtual void BeginFrame()override final; + virtual void EndFrame()override final; + virtual bool UsesReverseZ()override final; + +private: + const UnityGraphicsD3D11Emulator& m_UnityGraphicsD3D11; +}; diff --git a/unityplugin/UnityEmulator/include/DiligentGraphicsAdapterD3D12.h b/unityplugin/UnityEmulator/include/DiligentGraphicsAdapterD3D12.h new file mode 100644 index 0000000..a9f3cd7 --- /dev/null +++ b/unityplugin/UnityEmulator/include/DiligentGraphicsAdapterD3D12.h @@ -0,0 +1,44 @@ +/* Copyright 2015-2017 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ +#pragma once + +#include "DiligentGraphicsAdapter.h" + +class DiligentGraphicsAdapterD3D12 : public DiligentGraphicsAdapter +{ +public: + virtual ~DiligentGraphicsAdapterD3D12()override {} + + DiligentGraphicsAdapterD3D12(class UnityGraphicsD3D12Emulator& UnityGraphicsD3D12)noexcept; + void InitProxySwapChain(); + + virtual void BeginFrame()override final; + virtual void EndFrame()override final; + virtual void PreSwapChainResize()override final; + virtual void PostSwapChainResize()override final; + virtual bool UsesReverseZ()override final; + +private: + UnityGraphicsD3D12Emulator& m_UnityGraphicsD3D12; + +}; diff --git a/unityplugin/UnityEmulator/include/DiligentGraphicsAdapterGL.h b/unityplugin/UnityEmulator/include/DiligentGraphicsAdapterGL.h new file mode 100644 index 0000000..28770cb --- /dev/null +++ b/unityplugin/UnityEmulator/include/DiligentGraphicsAdapterGL.h @@ -0,0 +1,46 @@ +/* Copyright 2015-2017 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ +#pragma once + +#include "PlatformDefinitions.h" + +#if OPENGL_SUPPORTED + +#include "DiligentGraphicsAdapter.h" + +class DiligentGraphicsAdapterGL : public DiligentGraphicsAdapter +{ +public: + virtual ~DiligentGraphicsAdapterGL()override {} + + DiligentGraphicsAdapterGL(const class UnityGraphicsGLCoreES_Emulator& UnityGraphicsGL)noexcept; + + virtual void BeginFrame()override final; + virtual void EndFrame()override final; + virtual bool UsesReverseZ()override final; + +private: + const UnityGraphicsGLCoreES_Emulator& m_UnityGraphicsGL; +}; + +#endif // OPENGL_SUPPORTED
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/include/ResourceStateTransitionHandler.h b/unityplugin/UnityEmulator/include/ResourceStateTransitionHandler.h new file mode 100644 index 0000000..ba1feea --- /dev/null +++ b/unityplugin/UnityEmulator/include/ResourceStateTransitionHandler.h @@ -0,0 +1,31 @@ +/* Copyright 2015-2017 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ +#pragma once + +struct UnityGraphicsD3D12ResourceState; +class IResourceStateTransitionHandler +{ +public: + virtual ~IResourceStateTransitionHandler(){} + virtual void TransitionResources(int stateCount, UnityGraphicsD3D12ResourceState* states){} +}; diff --git a/unityplugin/UnityEmulator/include/UnityGraphicsD3D11Emulator.h b/unityplugin/UnityEmulator/include/UnityGraphicsD3D11Emulator.h new file mode 100644 index 0000000..5907591 --- /dev/null +++ b/unityplugin/UnityEmulator/include/UnityGraphicsD3D11Emulator.h @@ -0,0 +1,29 @@ +#pragma once + +#include <memory> +#include "UnityGraphicsEmulator.h" + +class UnityGraphicsD3D11Impl; +class UnityGraphicsD3D11Emulator : public UnityGraphicsEmulator +{ +public: + static UnityGraphicsD3D11Emulator& GetInstance(); + void CreateD3D11DeviceAndContext(); + void CreateSwapChain(void *pNativeWndHandle, unsigned int Width, unsigned int Height); + + virtual void Present()override final; + virtual void Release()override final; + virtual void BeginFrame()override final; + virtual void EndFrame()override final; + virtual void ResizeSwapChain(unsigned int Width, unsigned int Height)override final; + virtual bool UsesReverseZ()const override final { return true; } + virtual IUnityInterface* GetUnityGraphicsAPIInterface()override final; + static UnityGraphicsD3D11Impl* GetGraphicsImpl(); + virtual UnityGfxRenderer GetUnityGfxRenderer()override final; + virtual bool SwapChainInitialized()override final; + void* GetD3D11Device(); + +private: + UnityGraphicsD3D11Emulator(); + static std::unique_ptr<UnityGraphicsD3D11Impl> m_GraphicsImpl; +}; diff --git a/unityplugin/UnityEmulator/include/UnityGraphicsD3D12Emulator.h b/unityplugin/UnityEmulator/include/UnityGraphicsD3D12Emulator.h new file mode 100644 index 0000000..b668e39 --- /dev/null +++ b/unityplugin/UnityEmulator/include/UnityGraphicsD3D12Emulator.h @@ -0,0 +1,32 @@ +#pragma once + +#include <memory> +#include "UnityGraphicsEmulator.h" + +class UnityGraphicsD3D12Impl; +class IResourceStateTransitionHandler; + +class UnityGraphicsD3D12Emulator : public UnityGraphicsEmulator +{ +public: + static UnityGraphicsD3D12Emulator& GetInstance(); + void CreateD3D12DeviceAndCommandQueue(); + void CreateSwapChain(void *pNativeWndHandle, unsigned int Width, unsigned int Height); + void SetTransitionHandler(IResourceStateTransitionHandler *pTransitionHandler); + + virtual void Present()override final; + virtual void Release()override final; + virtual void BeginFrame()override final; + virtual void EndFrame()override final; + virtual void ResizeSwapChain(unsigned int Width, unsigned int Height)override final; + virtual bool UsesReverseZ()const override final { return true; } + virtual IUnityInterface* GetUnityGraphicsAPIInterface()override final; + static UnityGraphicsD3D12Impl* GetGraphicsImpl(); + virtual UnityGfxRenderer GetUnityGfxRenderer()override final; + virtual bool SwapChainInitialized()override final; + void* GetD3D12Device(); + +private: + UnityGraphicsD3D12Emulator(); + static std::unique_ptr<UnityGraphicsD3D12Impl> m_GraphicsImpl; +}; diff --git a/unityplugin/UnityEmulator/include/UnityGraphicsEmulator.h b/unityplugin/UnityEmulator/include/UnityGraphicsEmulator.h new file mode 100644 index 0000000..d362836 --- /dev/null +++ b/unityplugin/UnityEmulator/include/UnityGraphicsEmulator.h @@ -0,0 +1,41 @@ +#pragma once + +#include <vector> + +#include "IUnityInterface.h" +#include "IUnityGraphics.h" + + +class UnityGraphicsEmulator +{ +public: + UnityGraphicsEmulator(); + virtual void Release() = 0; + virtual void Present() = 0; + virtual void BeginFrame() = 0; + virtual void EndFrame() = 0; + virtual void ResizeSwapChain(unsigned int Width, unsigned int Height) = 0; + virtual bool SwapChainInitialized() = 0; + virtual bool UsesReverseZ()const { return false; } + virtual IUnityInterface* GetUnityGraphicsAPIInterface() = 0; + IUnityInterfaces &GeUnityInterfaces(); + + static UnityGraphicsEmulator& GetInstance() { return *m_Instance; } + void RegisterInterface(const UnityInterfaceGUID &guid, IUnityInterface* ptr); + IUnityInterface* GetInterface(const UnityInterfaceGUID &guid); + virtual UnityGfxRenderer GetUnityGfxRenderer() = 0; + + void RegisterDeviceEventCallback(IUnityGraphicsDeviceEventCallback callback); + void UnregisterDeviceEventCallback(IUnityGraphicsDeviceEventCallback callback); + void InvokeDeviceEventCallback(UnityGfxDeviceEventType eventType); + +private: + UnityGraphicsEmulator(const UnityGraphicsEmulator&) = delete; + UnityGraphicsEmulator(UnityGraphicsEmulator&&) = delete; + UnityGraphicsEmulator& operator = (const UnityGraphicsEmulator&) = delete; + UnityGraphicsEmulator& operator = (UnityGraphicsEmulator&&) = delete; + + std::vector< std::pair<UnityInterfaceGUID, IUnityInterface*> > m_Interfaces; + static UnityGraphicsEmulator *m_Instance; + std::vector<IUnityGraphicsDeviceEventCallback> m_DeviceEventCallbacks; +}; diff --git a/unityplugin/UnityEmulator/include/UnityGraphicsGLCoreES_Emulator.h b/unityplugin/UnityEmulator/include/UnityGraphicsGLCoreES_Emulator.h new file mode 100644 index 0000000..cc69f93 --- /dev/null +++ b/unityplugin/UnityEmulator/include/UnityGraphicsGLCoreES_Emulator.h @@ -0,0 +1,42 @@ +#pragma once + +#include "PlatformDefinitions.h" + +#if OPENGL_SUPPORTED + +#include <memory> +#include "UnityGraphicsEmulator.h" + +#if defined(PLATFORM_ANDROID) + class UnityGraphicsGLESAndroid_Impl; + using UnityGraphicsGL_Impl = UnityGraphicsGLESAndroid_Impl; +#elif defined( PLATFORM_WIN32 ) || defined( PLATFORM_UNIVERSAL_WINDOWS ) + class UnityGraphicsGLCore_Impl; + using UnityGraphicsGL_Impl = UnityGraphicsGLCore_Impl; +#else +# error Unknown Platform +#endif + + +class UnityGraphicsGLCoreES_Emulator : public UnityGraphicsEmulator +{ +public: + static UnityGraphicsGLCoreES_Emulator& GetInstance(); + void InitGLContext(void *pNativeWndHandle, int MajorVersion, int MinorVersion); + + virtual void Present()override final; + virtual void Release()override final; + virtual void BeginFrame()override final; + virtual void EndFrame()override final; + virtual void ResizeSwapChain(unsigned int Width, unsigned int Height)override final; + virtual IUnityInterface* GetUnityGraphicsAPIInterface()override final; + static UnityGraphicsGL_Impl* GetGraphicsImpl(); + virtual UnityGfxRenderer GetUnityGfxRenderer()override final; + virtual bool SwapChainInitialized()override final; + +private: + UnityGraphicsGLCoreES_Emulator(); + static std::unique_ptr<UnityGraphicsGL_Impl> m_GraphicsImpl; +}; + +#endif // OPENGL_SUPPORTED
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/include/UnitySceneBase.h b/unityplugin/UnityEmulator/include/UnitySceneBase.h new file mode 100644 index 0000000..81ff6c1 --- /dev/null +++ b/unityplugin/UnityEmulator/include/UnitySceneBase.h @@ -0,0 +1,74 @@ +/* Copyright 2015-2017 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ +#pragma once + +#include "RenderDevice.h" +#include "DeviceContext.h" +#include "RefCntAutoPtr.h" +#include "IUnityGraphics.h" +#include "DiligentGraphicsAdapter.h" +#include "ResourceStateTransitionHandler.h" + +typedef void* (*TLoadPluginFunction)(const char *FunctionName); + +class UnitySceneBase +{ +public: + virtual ~UnitySceneBase() = 0; + + virtual void OnPluginLoad(TLoadPluginFunction LoadPluginFunctionCallback) = 0; + + virtual void OnPluginUnload() = 0; + + virtual void OnGraphicsInitialized() = 0; + + virtual void OnWindowResize(int NewWidth, int NewHeight) + { + m_WindowWidth = NewWidth; + m_WindowHeight = NewHeight; + } + + virtual const char* GetSceneName() = 0; + + virtual const char* GetPluginName() = 0; + + virtual void Render(UnityRenderingEvent RenderEventFunc, double CurrTime, double ElapsedTime) = 0; + + void SetDiligentGraphicsAdapter(DiligentGraphicsAdapter *DiligentGraphics) + { + m_DiligentGraphics = DiligentGraphics; + } + + IResourceStateTransitionHandler* GetStateTransitionHandler() { return m_pStateTransitionHandler.get(); } + +protected: + DiligentGraphicsAdapter* m_DiligentGraphics; + std::unique_ptr<IResourceStateTransitionHandler> m_pStateTransitionHandler; + + int m_WindowWidth = 640; + int m_WindowHeight = 480; +}; + +inline UnitySceneBase::~UnitySceneBase() {} + +extern UnitySceneBase* CreateScene(); diff --git a/unityplugin/UnityEmulator/src/Android/AndroidMainImpl.cpp b/unityplugin/UnityEmulator/src/Android/AndroidMainImpl.cpp new file mode 100644 index 0000000..6943301 --- /dev/null +++ b/unityplugin/UnityEmulator/src/Android/AndroidMainImpl.cpp @@ -0,0 +1,565 @@ + /* Copyright 2015-2017 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +//-------------------------------------------------------------------------------- +// Include files +//-------------------------------------------------------------------------------- +#include <jni.h> +#include <errno.h> + +#include <android/sensor.h> +#include <android/log.h> +#include <android_native_app_glue.h> +#include <android/native_window_jni.h> +#include <cpu-features.h> +#include <memory> + +#include "NDKHelper.h" + +#include "Timer.h" + +#include "IUnityInterface.h" +#include "UnityGraphicsGLESAndroid_Impl.h" +#include "UnityGraphicsGLCoreES_Emulator.h" +#include "DiligentGraphicsAdapterGL.h" +#include "UnitySceneBase.h" +#include "StringTools.h" +#include "Errors.h" + +//------------------------------------------------------------------------- +//Preprocessor +//------------------------------------------------------------------------- +#define HELPER_CLASS_NAME "com/sample/helper/NDKHelper" //Class name of helper function +//------------------------------------------------------------------------- +//Shared state for our app. +//------------------------------------------------------------------------- + +extern "C" +{ + void __attribute__((visibility("default"))) UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces); + void __attribute__((visibility("default"))) UNITY_INTERFACE_API UnityPluginUnload(); + UnityRenderingEvent __attribute__((visibility("default"))) UNITY_INTERFACE_API GetRenderEventFunc(); +} + +void* LoadPluginFunction(const char* FunctionName); + +bool LoadPlugin() +{ + // Do nothing. Android automagically sets function pointers + return true; +} + + +struct android_app; +class Engine +{ + bool initialized_resources_; + bool has_focus_; + + ndk_helper::DoubletapDetector doubletap_detector_; + ndk_helper::PinchDetector pinch_detector_; + ndk_helper::DragDetector drag_detector_; + ndk_helper::PerfMonitor monitor_; + + //ndk_helper::TapCamera tap_camera_; + + android_app* app_; + + ASensorManager* sensor_manager_; + const ASensor* accelerometer_sensor_; + ASensorEventQueue* sensor_event_queue_; + + void UpdateFPS( float fFPS ); + void ShowUI(); + //void TransformPosition( ndk_helper::Vec2& vec ); + + std::unique_ptr<DiligentGraphicsAdapter> diligent_graphics_; + std::unique_ptr<UnitySceneBase> scene_; + UnityGraphicsGLCoreES_Emulator *unity_graphics_gles_emulator_ = nullptr; + UnityRenderingEvent render_event_func_ = nullptr; + +public: + static void HandleCmd( struct android_app* app, + int32_t cmd ); + static int32_t HandleInput( android_app* app, + AInputEvent* event ); + + Engine(); + ~Engine(); + void SetState( android_app* state ); + int InitDisplay(); + void LoadResources(); + void UnloadResources(); + void DrawFrame(); + void TermDisplay(); + void TrimMemory(); + bool IsReady(); + void UnloadPlugin(); + + void UpdatePosition( AInputEvent* event, + int32_t iIndex, + float& fX, + float& fY ); + + void InitSensors(); + void ProcessSensors( int32_t id ); + void SuspendSensors(); + void ResumeSensors(); +}; + +//------------------------------------------------------------------------- +//Ctor +//------------------------------------------------------------------------- +Engine::Engine() : + initialized_resources_( false ), + has_focus_( false ), + app_( NULL ), + sensor_manager_( NULL ), + accelerometer_sensor_( NULL ), + sensor_event_queue_( NULL ), + scene_(CreateScene()) +{ + if (!LoadPlugin()) + { + LOG_ERROR_AND_THROW("Failed to load native plugin"); + } + scene_->OnPluginLoad(LoadPluginFunction); + render_event_func_ = GetRenderEventFunc(); +} + +void Engine::UnloadPlugin() +{ + unity_graphics_gles_emulator_->InvokeDeviceEventCallback(kUnityGfxDeviceEventShutdown); + UnityPluginUnload(); +} + +//------------------------------------------------------------------------- +//Dtor +//------------------------------------------------------------------------- +Engine::~Engine() +{ + scene_->OnPluginUnload(); + scene_.reset(); + UnloadPlugin(); + diligent_graphics_.reset(); + unity_graphics_gles_emulator_->Release(); +} + +/** +* Load resources +*/ +void Engine::LoadResources() +{ + scene_->OnGraphicsInitialized(); + + //renderer_.Init(); + //renderer_.Bind( &tap_camera_ ); +} + +/** +* Unload resources +*/ +void Engine::UnloadResources() +{ + //renderer_.Unload(); +} + +/** +* Initialize an EGL context for the current display. +*/ +int Engine::InitDisplay() +{ + if( !initialized_resources_ ) + { + // Init graphics resources + auto &GraphicsGLCoreES_Emulator = UnityGraphicsGLCoreES_Emulator::GetInstance(); + GraphicsGLCoreES_Emulator.InitGLContext(app_->window, 3, 1); + unity_graphics_gles_emulator_ = &GraphicsGLCoreES_Emulator; + diligent_graphics_.reset(new DiligentGraphicsAdapterGL(GraphicsGLCoreES_Emulator)); + + scene_->SetDiligentGraphicsAdapter(diligent_graphics_.get()); + + LoadResources(); + initialized_resources_ = true; + } + else + { + // initialize OpenGL ES and EGL + if( EGL_SUCCESS != unity_graphics_gles_emulator_->GetGraphicsImpl()->Resume( app_->window ) ) + { + UnloadResources(); + LoadResources(); + } + } + + UnityPluginLoad(&unity_graphics_gles_emulator_->GeUnityInterfaces()); + + ShowUI(); + + + auto *graphics_impl = unity_graphics_gles_emulator_->GetGraphicsImpl(); + auto width = graphics_impl->GetBackBufferWidth(); + auto height = graphics_impl->GetBackBufferHeight(); + + scene_->OnWindowResize(width, height); + + //tap_camera_.SetFlip( 1.f, -1.f, -1.f ); + //tap_camera_.SetPinchTransformFactor( 2.f, 2.f, 8.f ); + + return 0; +} + +/** +* Just the current frame in the display. +*/ +void Engine::DrawFrame() +{ + float fFPS; + if( monitor_.Update( fFPS ) ) + { + UpdateFPS( fFPS ); + } + + unity_graphics_gles_emulator_->BeginFrame(); + diligent_graphics_->BeginFrame(); + + static Diligent::Timer timer; + static double prev_time = timer.GetElapsedTime(); + auto curr_time = timer.GetElapsedTime(); + auto elapsed_time = curr_time - prev_time; + prev_time = curr_time; + + scene_->Render(render_event_func_, curr_time, elapsed_time); + + diligent_graphics_->EndFrame(); + unity_graphics_gles_emulator_->EndFrame(); + + unity_graphics_gles_emulator_->Present(); + //if( EGL_SUCCESS != pRenderDevice_->Present() ) + //{ + // UnloadResources(); + // LoadResources(); + //} +} + +/** +* Tear down the EGL context currently associated with the display. +*/ +void Engine::TermDisplay() +{ + unity_graphics_gles_emulator_->GetGraphicsImpl()->Suspend(); +} + +void Engine::TrimMemory() +{ + LOGI( "Trimming memory" ); + unity_graphics_gles_emulator_->GetGraphicsImpl()->Invalidate(); +} + +/** +* Process the next input event. +*/ +int32_t Engine::HandleInput( android_app* app, + AInputEvent* event ) +{ + Engine* eng = (Engine*)app->userData; + if( AInputEvent_getType( event ) == AINPUT_EVENT_TYPE_MOTION ) + { + ndk_helper::GESTURE_STATE doubleTapState = eng->doubletap_detector_.Detect( event ); + ndk_helper::GESTURE_STATE dragState = eng->drag_detector_.Detect( event ); + ndk_helper::GESTURE_STATE pinchState = eng->pinch_detector_.Detect( event ); + + //Double tap detector has a priority over other detectors + if( doubleTapState == ndk_helper::GESTURE_STATE_ACTION ) + { + //Detect double tap + //eng->tap_camera_.Reset( true ); + } + else + { + //Handle drag state + if( dragState & ndk_helper::GESTURE_STATE_START ) + { + //Otherwise, start dragging + ndk_helper::Vec2 v; + eng->drag_detector_.GetPointer( v ); + float fX = 0, fY = 0; + v.Value(fX, fY); + + //eng->TransformPosition( v ); + //eng->tap_camera_.BeginDrag( v ); + } + else if( dragState & ndk_helper::GESTURE_STATE_MOVE ) + { + ndk_helper::Vec2 v; + eng->drag_detector_.GetPointer( v ); + float fX = 0, fY = 0; + v.Value(fX, fY); + + //eng->TransformPosition( v ); + //eng->tap_camera_.Drag( v ); + } + else if( dragState & ndk_helper::GESTURE_STATE_END ) + { + //eng->tap_camera_.EndDrag(); + } + + //Handle pinch state + if( pinchState & ndk_helper::GESTURE_STATE_START ) + { + //Start new pinch + ndk_helper::Vec2 v1; + ndk_helper::Vec2 v2; + eng->pinch_detector_.GetPointers( v1, v2 ); + //eng->TransformPosition( v1 ); + //eng->TransformPosition( v2 ); + //eng->tap_camera_.BeginPinch( v1, v2 ); + } + else if( pinchState & ndk_helper::GESTURE_STATE_MOVE ) + { + //Multi touch + //Start new pinch + ndk_helper::Vec2 v1; + ndk_helper::Vec2 v2; + eng->pinch_detector_.GetPointers( v1, v2 ); + //eng->TransformPosition( v1 ); + //eng->TransformPosition( v2 ); + //eng->tap_camera_.Pinch( v1, v2 ); + } + } + return 1; + } + return 0; +} + +/** +* Process the next main command. +*/ +void Engine::HandleCmd( struct android_app* app, + int32_t cmd ) +{ + Engine* eng = (Engine*)app->userData; + switch( cmd ) + { + case APP_CMD_SAVE_STATE: + break; + case APP_CMD_INIT_WINDOW: + // The window is being shown, get it ready. + if( app->window != NULL ) + { + eng->InitDisplay(); + eng->DrawFrame(); + } + break; + case APP_CMD_TERM_WINDOW: + // The window is being hidden or closed, clean it up. + eng->TermDisplay(); + eng->has_focus_ = false; + break; + case APP_CMD_STOP: + break; + case APP_CMD_GAINED_FOCUS: + eng->ResumeSensors(); + //Start animation + eng->has_focus_ = true; + break; + case APP_CMD_LOST_FOCUS: + eng->SuspendSensors(); + // Also stop animating. + eng->has_focus_ = false; + eng->DrawFrame(); + break; + case APP_CMD_LOW_MEMORY: + //Free up GL resources + eng->TrimMemory(); + break; + } +} + +//------------------------------------------------------------------------- +//Sensor handlers +//------------------------------------------------------------------------- +void Engine::InitSensors() +{ + sensor_manager_ = ASensorManager_getInstance(); + accelerometer_sensor_ = ASensorManager_getDefaultSensor( sensor_manager_, + ASENSOR_TYPE_ACCELEROMETER ); + sensor_event_queue_ = ASensorManager_createEventQueue( sensor_manager_, app_->looper, + LOOPER_ID_USER, NULL, NULL ); +} + +void Engine::ProcessSensors( int32_t id ) +{ + // If a sensor has data, process it now. + if( id == LOOPER_ID_USER ) + { + if( accelerometer_sensor_ != NULL ) + { + ASensorEvent event; + while( ASensorEventQueue_getEvents( sensor_event_queue_, &event, 1 ) > 0 ) + { + } + } + } +} + +void Engine::ResumeSensors() +{ + // When our app gains focus, we start monitoring the accelerometer. + if( accelerometer_sensor_ != NULL ) + { + ASensorEventQueue_enableSensor( sensor_event_queue_, accelerometer_sensor_ ); + // We'd like to get 60 events per second (in us). + ASensorEventQueue_setEventRate( sensor_event_queue_, accelerometer_sensor_, + (1000L / 60) * 1000 ); + } +} + +void Engine::SuspendSensors() +{ + // When our app loses focus, we stop monitoring the accelerometer. + // This is to avoid consuming battery while not being used. + if( accelerometer_sensor_ != NULL ) + { + ASensorEventQueue_disableSensor( sensor_event_queue_, accelerometer_sensor_ ); + } +} + +//------------------------------------------------------------------------- +//Misc +//------------------------------------------------------------------------- +void Engine::SetState( android_app* state ) +{ + app_ = state; + doubletap_detector_.SetConfiguration( app_->config ); + drag_detector_.SetConfiguration( app_->config ); + pinch_detector_.SetConfiguration( app_->config ); +} + +bool Engine::IsReady() +{ + if( has_focus_ ) + return true; + + return false; +} + +//void Engine::TransformPosition( ndk_helper::Vec2& vec ) +//{ +// vec = ndk_helper::Vec2( 2.0f, 2.0f ) * vec +// / ndk_helper::Vec2( pDeviceContext_->GetMainBackBufferDesc().Width, pDeviceContext_->GetMainBackBufferDesc().Height ) +// - ndk_helper::Vec2( 1.f, 1.f ); +//} + +void Engine::ShowUI() +{ + JNIEnv *jni; + app_->activity->vm->AttachCurrentThread( &jni, NULL ); + + //Default class retrieval + jclass clazz = jni->GetObjectClass( app_->activity->clazz ); + jmethodID methodID = jni->GetMethodID( clazz, "showUI", "()V" ); + jni->CallVoidMethod( app_->activity->clazz, methodID ); + + app_->activity->vm->DetachCurrentThread(); + return; +} + +void Engine::UpdateFPS( float fFPS ) +{ + JNIEnv *jni; + app_->activity->vm->AttachCurrentThread( &jni, NULL ); + + //Default class retrieval + jclass clazz = jni->GetObjectClass( app_->activity->clazz ); + jmethodID methodID = jni->GetMethodID( clazz, "updateFPS", "(F)V" ); + jni->CallVoidMethod( app_->activity->clazz, methodID, fFPS ); + + app_->activity->vm->DetachCurrentThread(); + return; +} + +Engine g_engine; + +/** +* This is the main entry point of a native application that is using +* android_native_app_glue. It runs in its own thread, with its own +* event loop for receiving input events and doing other things. +*/ + +// The actual android_main() must be defined in the application project +void android_main_impl( android_app* state ) +{ + app_dummy(); + + g_engine.SetState( state ); + + //Init helper functions + ndk_helper::JNIHelper::Init( state->activity, HELPER_CLASS_NAME ); + + state->userData = &g_engine; + state->onAppCmd = Engine::HandleCmd; + state->onInputEvent = Engine::HandleInput; + +#ifdef USE_NDK_PROFILER + monstartup( "libEngineSandbox.so" ); +#endif + + // Prepare to monitor accelerometer + g_engine.InitSensors(); + + // loop waiting for stuff to do. + while( 1 ) + { + // Read all pending events. + int id; + int events; + android_poll_source* source; + + // If not animating, we will block forever waiting for events. + // If animating, we loop until all events are read, then continue + // to draw the next frame of animation. + while( (id = ALooper_pollAll( g_engine.IsReady() ? 0 : -1, NULL, &events, (void**)&source )) >= 0 ) + { + // Process this event. + if( source != NULL ) + source->process( state, source ); + + g_engine.ProcessSensors( id ); + + // Check if we are exiting. + if( state->destroyRequested != 0 ) + { + g_engine.TermDisplay(); + return; + } + } + + if( g_engine.IsReady() ) + { + // Drawing is throttled to the screen update rate, so there + // is no need to do timing here. + g_engine.DrawFrame(); + } + } +} diff --git a/unityplugin/UnityEmulator/src/Android/Java/UnityEmulator/UnityEmulatorApplication.java b/unityplugin/UnityEmulator/src/Android/Java/UnityEmulator/UnityEmulatorApplication.java new file mode 100644 index 0000000..249f291 --- /dev/null +++ b/unityplugin/UnityEmulator/src/Android/Java/UnityEmulator/UnityEmulatorApplication.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 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. + */ + +package com.DiligentGrpahics.UnityEmulator; + +import javax.microedition.khronos.opengles.GL10; + +import android.app.Application; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.opengl.GLUtils; +import android.util.Log; +import android.widget.Toast; + +public class UnityEmulatorApplication extends Application { + public void onCreate(){ + Log.w("native-activity", "onCreate"); + + final PackageManager pm = getApplicationContext().getPackageManager(); + ApplicationInfo ai; + try { + ai = pm.getApplicationInfo( this.getPackageName(), 0); + } catch (final NameNotFoundException e) { + ai = null; + } + final String applicationName = (String) (ai != null ? pm.getApplicationLabel(ai) : "(unknown)"); + Toast.makeText(this, applicationName, Toast.LENGTH_SHORT).show(); + } +} diff --git a/unityplugin/UnityEmulator/src/Android/Java/UnityEmulator/UnityEmulatorNativeActivity.java b/unityplugin/UnityEmulator/src/Android/Java/UnityEmulator/UnityEmulatorNativeActivity.java new file mode 100644 index 0000000..e30e106 --- /dev/null +++ b/unityplugin/UnityEmulator/src/Android/Java/UnityEmulator/UnityEmulatorNativeActivity.java @@ -0,0 +1,164 @@ +/* + * Copyright 2013 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. + */ + +package com.DiligentGrpahics.UnityEmulator; + +import android.app.NativeActivity; +import android.os.Bundle; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup.MarginLayoutParams; +import android.view.WindowManager.LayoutParams; +import android.widget.LinearLayout; +import android.widget.PopupWindow; +import android.widget.TextView; +import android.util.Log; + +public class UnityEmulatorNativeActivity extends NativeActivity { + + static + { + try{ + System.loadLibrary("GraphicsEngineOpenGL"); + Log.i("native-activity", "Loaded GraphicsEngineOpenGL library\n"); + } catch (UnsatisfiedLinkError e) { + Log.e("native-activity", "Failed to load GraphicsEngineOpenGL library\n" + e); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + String pluginName = getString(R.string.plugin_name); + try{ + System.loadLibrary(pluginName); + Log.i("native-activity", "Loaded " + pluginName + " plugin\n"); + } catch (UnsatisfiedLinkError e) { + Log.e("native-activity", "Failed to load " + pluginName + " plugin\n" + e); + } + + //Hide toolbar + int SDK_INT = android.os.Build.VERSION.SDK_INT; + if(SDK_INT >= 19) + { + setImmersiveSticky(); + + View decorView = getWindow().getDecorView(); + decorView.setOnSystemUiVisibilityChangeListener + (new View.OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int visibility) { + setImmersiveSticky(); + } + }); + } + } + + protected void onResume() { + super.onResume(); + + //Hide toolbar + int SDK_INT = android.os.Build.VERSION.SDK_INT; + if(SDK_INT >= 11 && SDK_INT < 14) + { + getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_HIDDEN); + } + else if(SDK_INT >= 14 && SDK_INT < 19) + { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE); + } + else if(SDK_INT >= 19) + { + setImmersiveSticky(); + } + + } + // Our popup window, you will call it from your C/C++ code later + + void setImmersiveSticky() { + View decorView = getWindow().getDecorView(); + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + } + + UnityEmulatorNativeActivity _activity; + PopupWindow _popupWindow; + TextView _label; + + public void showUI() + { + if( _popupWindow != null ) + return; + + _activity = this; + + this.runOnUiThread(new Runnable() { + @Override + public void run() { + LayoutInflater layoutInflater + = (LayoutInflater)getBaseContext() + .getSystemService(LAYOUT_INFLATER_SERVICE); + View popupView = layoutInflater.inflate(R.layout.widgets, null); + _popupWindow = new PopupWindow( + popupView, + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + + LinearLayout mainLayout = new LinearLayout(_activity); + MarginLayoutParams params = new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + params.setMargins(0, 0, 0, 0); + _activity.setContentView(mainLayout, params); + + // Show our UI over NativeActivity window + _popupWindow.showAtLocation(mainLayout, Gravity.TOP | Gravity.LEFT, 10, 10); + _popupWindow.update(); + + _label = (TextView)popupView.findViewById(R.id.textViewFPS); + + }}); + } + + protected void onPause() + { + super.onPause(); + if (_popupWindow != null) { + _popupWindow.dismiss(); + _popupWindow = null; + } + } + + public void updateFPS(final float fFPS) + { + if( _label == null ) + return; + + _activity = this; + this.runOnUiThread(new Runnable() { + @Override + public void run() { + _label.setText(String.format("%2.2f FPS", fFPS)); + + }}); + } +} + + diff --git a/unityplugin/UnityEmulator/src/Android/Java/helper/NDKHelper.java b/unityplugin/UnityEmulator/src/Android/Java/helper/NDKHelper.java new file mode 100644 index 0000000..3385a5d --- /dev/null +++ b/unityplugin/UnityEmulator/src/Android/Java/helper/NDKHelper.java @@ -0,0 +1,203 @@ +/* + * Copyright 2013 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. + */ + +package com.sample.helper; + +import java.io.File; +import java.io.FileInputStream; + +import javax.microedition.khronos.opengles.GL10; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.media.AudioManager; +import android.media.AudioTrack; +import android.opengl.GLUtils; +import android.util.Log; + +public class NDKHelper +{ + private static Context context; + + public static void setContext(Context c) + { + Log.i("NDKHelper", "setContext:" + c); + context = c; + } + + // + // Load Bitmap + // Java helper is useful decoding PNG, TIFF etc rather than linking libPng + // etc separately + // + private int nextPOT(int i) + { + int pot = 1; + while (pot < i) + pot <<= 1; + return pot; + } + + private Bitmap scaleBitmap(Bitmap bitmapToScale, float newWidth, float newHeight) + { + if (bitmapToScale == null) + return null; + // get the original width and height + int width = bitmapToScale.getWidth(); + int height = bitmapToScale.getHeight(); + // create a matrix for the manipulation + Matrix matrix = new Matrix(); + + // resize the bit map + matrix.postScale(newWidth / width, newHeight / height); + + // recreate the new Bitmap and set it back + return Bitmap.createBitmap(bitmapToScale, 0, 0, bitmapToScale.getWidth(), + bitmapToScale.getHeight(), matrix, true); + } + + public boolean loadTexture(String path) + { + Bitmap bitmap = null; + try + { + String str = path; + if (!path.startsWith("/")) + { + str = "/" + path; + } + + File file = new File(context.getExternalFilesDir(null), str); + if (file.canRead()) + { + bitmap = BitmapFactory.decodeStream(new FileInputStream(file)); + } else + { + bitmap = BitmapFactory.decodeStream(context.getResources().getAssets() + .open(path)); + } + // Matrix matrix = new Matrix(); + // // resize the bit map + // matrix.postScale(-1F, 1F); + // + // // recreate the new Bitmap and set it back + // bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), + // bitmap.getHeight(), matrix, true); + + } catch (Exception e) + { + Log.w("NDKHelper", "Coundn't load a file:" + path); + return false; + } + + if (bitmap != null) + { + GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); + } + return true; + + } + + public Bitmap openBitmap(String path, boolean iScalePOT) + { + Bitmap bitmap = null; + try + { + bitmap = BitmapFactory.decodeStream(context.getResources().getAssets() + .open(path)); + if (iScalePOT) + { + int originalWidth = getBitmapWidth(bitmap); + int originalHeight = getBitmapHeight(bitmap); + int width = nextPOT(originalWidth); + int height = nextPOT(originalHeight); + if (originalWidth != width || originalHeight != height) + { + // Scale it + bitmap = scaleBitmap(bitmap, width, height); + } + } + + } catch (Exception e) + { + Log.w("NDKHelper", "Coundn't load a file:" + path); + } + + return bitmap; + } + + public int getBitmapWidth(Bitmap bmp) + { + return bmp.getWidth(); + } + + public int getBitmapHeight(Bitmap bmp) + { + return bmp.getHeight(); + } + + public void getBitmapPixels(Bitmap bmp, int[] pixels) + { + int w = bmp.getWidth(); + int h = bmp.getHeight(); + bmp.getPixels(pixels, 0, w, 0, 0, w, h); + } + + public void closeBitmap(Bitmap bmp) + { + bmp.recycle(); + } + + public static String getNativeLibraryDirectory(Context appContext) + { + ApplicationInfo ai = context.getApplicationInfo(); + + Log.w("NDKHelper", "ai.nativeLibraryDir:" + ai.nativeLibraryDir); + + if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 + || (ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) + { + return ai.nativeLibraryDir; + } + return "/system/lib/"; + } + + public int getNativeAudioBufferSize() + { + int SDK_INT = android.os.Build.VERSION.SDK_INT; + if (SDK_INT >= 17) + { + AudioManager am = (AudioManager) context + .getSystemService(Context.AUDIO_SERVICE); + String framesPerBuffer = am + .getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER); + return Integer.parseInt(framesPerBuffer); + } else + { + return 0; + } + } + + public int getNativeAudioSampleRate() + { + return AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM); + + } + +} diff --git a/unityplugin/UnityEmulator/src/Android/UnityGraphicsGLESAndroid_Impl.cpp b/unityplugin/UnityEmulator/src/Android/UnityGraphicsGLESAndroid_Impl.cpp new file mode 100644 index 0000000..176d501 --- /dev/null +++ b/unityplugin/UnityEmulator/src/Android/UnityGraphicsGLESAndroid_Impl.cpp @@ -0,0 +1,326 @@ +/* Copyright 2015-2017 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "UnityGraphicsGLESAndroid_Impl.h" +#include "Errors.h" + +#ifndef EGL_CONTEXT_MINOR_VERSION_KHR +# define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB +#endif + +#ifndef EGL_CONTEXT_MAJOR_VERSION_KHR +# define EGL_CONTEXT_MAJOR_VERSION_KHR EGL_CONTEXT_CLIENT_VERSION +#endif + +#ifndef GL_FRAMEBUFFER_SRGB +# define GL_FRAMEBUFFER_SRGB 0x8DB9 +#endif + +bool UnityGraphicsGLESAndroid_Impl::InitEGLSurface() +{ + display_ = eglGetDisplay( EGL_DEFAULT_DISPLAY ); + if( display_ == EGL_NO_DISPLAY ) + { + LOG_ERROR_AND_THROW( "No EGL display found" ); + } + + auto success = eglInitialize( display_, 0, 0 ); + if( !success ) + { + LOG_ERROR_AND_THROW( "Failed to initialise EGL" ); + } + + /* + * Here specify the attributes of the desired configuration. + * Below, we select an EGLConfig with at least 8 bits per color + * component compatible with on-screen windows + */ + const EGLint attribs[] = + { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //Request opengl ES2.0 + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + //EGL_COLORSPACE, EGL_COLORSPACE_sRGB, // does not work + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 24, + //EGL_SAMPLE_BUFFERS , 1, + //EGL_SAMPLES , 4, + EGL_NONE + }; + color_size_ = 8; + depth_size_ = 24; + + // Get a list of EGL frame buffer configurations that match specified attributes + EGLint num_configs; + success = eglChooseConfig( display_, attribs, &config_, 1, &num_configs ); + if( !success ) + { + LOG_ERROR_AND_THROW( "Failed to choose config" ); + } + + if( !num_configs ) + { + //Fall back to 16bit depth buffer + const EGLint attribs[] = + { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //Request opengl ES2.0 + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_NONE + }; + success = eglChooseConfig( display_, attribs, &config_, 1, &num_configs ); + if( !success ) + { + LOG_ERROR_AND_THROW( "Failed to choose 16-bit depth config" ); + } + + depth_size_ = 16; + } + + if( !num_configs ) + { + LOG_ERROR_AND_THROW( "Unable to retrieve EGL config" ); + } + + surface_ = eglCreateWindowSurface( display_, config_, window_, NULL ); + if( surface_ == EGL_NO_SURFACE ) + { + LOG_ERROR_AND_THROW( "Failed to create EGLSurface" ); + } + + screen_width_ = 0; + screen_height_ = 0; + eglQuerySurface( display_, surface_, EGL_WIDTH, &screen_width_ ); + eglQuerySurface( display_, surface_, EGL_HEIGHT, &screen_height_ ); + + /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is + * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). + * As soon as we picked a EGLConfig, we can safely reconfigure the + * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ + EGLint format; + eglGetConfigAttrib( display_, config_, EGL_NATIVE_VISUAL_ID, &format ); + ANativeWindow_setBuffersGeometry( window_, 0, 0, format ); + + return true; +} + +bool UnityGraphicsGLESAndroid_Impl::InitEGLContext() +{ + const EGLint context_attribs[] = + { + EGL_CONTEXT_CLIENT_VERSION, major_version_, + EGL_CONTEXT_MINOR_VERSION_KHR, minor_version_, + EGL_NONE + }; + + LOG_INFO_MESSAGE( "contextAttribs: ", context_attribs[0], ' ', context_attribs[1], '\n' ); + LOG_INFO_MESSAGE( "contextAttribs: ", context_attribs[2], ' ', context_attribs[3], '\n' ); + + context_ = eglCreateContext( display_, config_, NULL, context_attribs ); + if( context_ == EGL_NO_CONTEXT ) + { + LOG_ERROR_AND_THROW( "Failed to create EUnityGraphicsGLESAndroid_Impl" ); + } + + if( eglMakeCurrent( display_, surface_, surface_, context_ ) == EGL_FALSE ) + { + LOG_ERROR_AND_THROW( "Unable to eglMakeCurrent" ); + } + + context_valid_ = true; + return true; +} + +void UnityGraphicsGLESAndroid_Impl::InitGLES() +{ + if( gles_initialized_ ) + return; + + // When GL_FRAMEBUFFER_SRGB is enabled, and if the destination image is in the sRGB colorspace + // then OpenGL will assume the shader's output is in the linear RGB colorspace. It will therefore + // convert the output from linear RGB to sRGB. + // Any writes to images that are not in the sRGB format should not be affected. + // Thus this setting should be just set once and left that way + glEnable(GL_FRAMEBUFFER_SRGB); + if( glGetError() != GL_NO_ERROR ) + LOG_ERROR_MESSAGE("Failed to enable SRGB framebuffers"); + + gles_initialized_ = true; +} + +void UnityGraphicsGLESAndroid_Impl::InitGLContext(void *native_wnd_handle, int major_version, int minor_version) +{ + major_version_ = major_version; + minor_version_ = minor_version; + Init(reinterpret_cast<ANativeWindow*>(native_wnd_handle)); +} + +bool UnityGraphicsGLESAndroid_Impl::Init( ANativeWindow* window ) +{ + if( egl_context_initialized_ ) + return true; + + // + //Initialize EGL + // + window_ = window; + InitEGLSurface(); + InitEGLContext(); + InitGLES(); + + egl_context_initialized_ = true; + + return true; +} + +UnityGraphicsGLESAndroid_Impl::~UnityGraphicsGLESAndroid_Impl() +{ + Terminate(); +} + +void UnityGraphicsGLESAndroid_Impl::ResizeSwapchain(int new_width, int new_height) +{ + screen_width_ = new_width; + screen_height_ = new_height; + // Nothing more needs to be done in GLES +} + +void UnityGraphicsGLESAndroid_Impl::SwapBuffers() +{ + bool b = eglSwapBuffers( display_, surface_ ); + if( !b ) + { + EGLint err = eglGetError(); + if( err == EGL_BAD_SURFACE ) + { + //Recreate surface + InitEGLSurface(); + //return EGL_SUCCESS; //Still consider UnityGraphicsGLESAndroid_Impl is valid + } + else if( err == EGL_CONTEXT_LOST || err == EGL_BAD_CONTEXT ) + { + //Context has been lost!! + context_valid_ = false; + Terminate(); + InitEGLContext(); + } + //return err; + } + //return EGL_SUCCESS; +} + +void UnityGraphicsGLESAndroid_Impl::Terminate() +{ + if( display_ != EGL_NO_DISPLAY ) + { + eglMakeCurrent( display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); + if( context_ != EGL_NO_CONTEXT ) + { + eglDestroyContext( display_, context_ ); + } + + if( surface_ != EGL_NO_SURFACE ) + { + eglDestroySurface( display_, surface_ ); + } + eglTerminate( display_ ); + } + + display_ = EGL_NO_DISPLAY; + context_ = EGL_NO_CONTEXT; + surface_ = EGL_NO_SURFACE; + context_valid_ = false; +} + + +EGLint UnityGraphicsGLESAndroid_Impl::Resume( ANativeWindow* window ) +{ + if( egl_context_initialized_ == false ) + { + Init( window ); + return EGL_SUCCESS; + } + + + //Create surface + window_ = window; + surface_ = eglCreateWindowSurface( display_, config_, window_, NULL ); + int32_t new_screen_width = 0; + int32_t new_screen_height = 0; + eglQuerySurface( display_, surface_, EGL_WIDTH, &new_screen_width ); + eglQuerySurface( display_, surface_, EGL_HEIGHT, &new_screen_height ); + + if( new_screen_width != screen_width_ || new_screen_height != screen_height_ ) + { + screen_width_ = new_screen_width; + screen_height_ = new_screen_height; + //Screen resized + LOG_INFO_MESSAGE( "Screen resized\n" ); + } + + if( eglMakeCurrent( display_, surface_, surface_, context_ ) == EGL_TRUE ) + return EGL_SUCCESS; + + EGLint err = eglGetError(); + LOG_WARNING_MESSAGE( "Unable to eglMakeCurrent ", err, '\n' ); + + if( err == EGL_CONTEXT_LOST ) + { + //Recreate context + LOG_INFO_MESSAGE( "Re-creating egl context\n" ); + InitEGLContext(); + } + else + { + //Recreate surface + Terminate(); + InitEGLSurface(); + InitEGLContext(); + } + + return err; + +} + +void UnityGraphicsGLESAndroid_Impl::Suspend() +{ + if( surface_ != EGL_NO_SURFACE ) + { + eglDestroySurface( display_, surface_ ); + surface_ = EGL_NO_SURFACE; + } +} + +bool UnityGraphicsGLESAndroid_Impl::Invalidate() +{ + Terminate(); + + egl_context_initialized_ = false; + return true; +} diff --git a/unityplugin/UnityEmulator/src/Android/UnityGraphicsGLESAndroid_Impl.h b/unityplugin/UnityEmulator/src/Android/UnityGraphicsGLESAndroid_Impl.h new file mode 100644 index 0000000..1ea7df1 --- /dev/null +++ b/unityplugin/UnityEmulator/src/Android/UnityGraphicsGLESAndroid_Impl.h @@ -0,0 +1,91 @@ +/* Copyright 2015-2017 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include <GLES3/gl3.h> +#include <GLES3/gl3ext.h> + +#include <EGL/egl.h> +#include <android/native_window.h> + +class UnityGraphicsGLESAndroid_Impl +{ +public: + void InitGLContext(void *native_wnd_handle, int major_version, int minor_version); + ~UnityGraphicsGLESAndroid_Impl(); + + bool Init(ANativeWindow* window); + + void ResizeSwapchain(int NewWidth, int NewHeight); + + void SwapBuffers(); + + int GetBackBufferWidth()const { return screen_width_; } + int GetBackBufferHeight()const { return screen_height_; } + GLenum GetBackBufferFormat()const { return GL_RGBA8; } + GLenum GetDepthBufferFormat()const + { + if (depth_size_ == 32) + GL_DEPTH_COMPONENT32F; + else if (depth_size_ == 24) + return GL_DEPTH_COMPONENT24; + else if(depth_size_ == 16) + return GL_DEPTH_COMPONENT16; + else + return 0; + } + EGLContext GetContext() { return context_; } + + bool Invalidate(); + + void Suspend(); + EGLint Resume( ANativeWindow* window ); + +private: + //EGL configurations + ANativeWindow* window_ = nullptr; + EGLDisplay display_ = EGL_NO_DISPLAY; + EGLSurface surface_ = EGL_NO_SURFACE; + EGLContext context_ = EGL_NO_CONTEXT; + EGLConfig config_; + + //Screen parameters + int32_t color_size_ = 0; + int32_t depth_size_ = 0; + int32_t major_version_ = 0; + int32_t minor_version_ = 0; + + //Flags + bool gles_initialized_ = false; + bool egl_context_initialized_ = false; + bool es3_supported_ = false; + float gl_version_ = 0; + bool context_valid_ = false; + + int screen_width_ = 0; + int screen_height_ = 0; + + void InitGLES(); + void Terminate(); + bool InitEGLSurface(); + bool InitEGLContext(); +}; diff --git a/unityplugin/UnityEmulator/src/DiligentGraphicsAdapterD3D11.cpp b/unityplugin/UnityEmulator/src/DiligentGraphicsAdapterD3D11.cpp new file mode 100644 index 0000000..4b02965 --- /dev/null +++ b/unityplugin/UnityEmulator/src/DiligentGraphicsAdapterD3D11.cpp @@ -0,0 +1,127 @@ +#include <d3d11.h> +#include <dxgi1_2.h> + +#include "DiligentGraphicsAdapterD3D11.h" +#include "UnityGraphicsD3D11Emulator.h" +#include "RenderDeviceFactoryD3D11.h" +#include "SwapChainBase.h" +#include "SwapChainD3D11.h" +#include "DefaultRawMemoryAllocator.h" +#include "UnityGraphicsD3D11Impl.h" +#include "DXGITypeConversions.h" + +using namespace Diligent; + +namespace +{ + +class ProxySwapChainD3D11 : public SwapChainBase<ISwapChainD3D11> +{ +public: + using TBase = SwapChainBase<ISwapChainD3D11>; + + ProxySwapChainD3D11( IReferenceCounters *pRefCounters, + IRenderDevice *pDevice, + IDeviceContext *pDeviceContext, + const SwapChainDesc& SCDesc ) : + TBase(pRefCounters, pDevice, pDeviceContext,SCDesc) + {} + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_SwapChainD3D11, TBase) + + virtual IDXGISwapChain *GetDXGISwapChain()override final + { + UNEXPECTED("DXGI swap chain cannot be requested through the proxy swap chain") + return nullptr; + } + + virtual ID3D11RenderTargetView *GetRTV()override final{ return m_pRTV; } + + virtual ID3D11DepthStencilView *GetDSV()override final { return m_pDSV; } + + virtual void Present()override final + { + UNEXPECTED("Present is not expected to be called directly") + } + + virtual void Resize(Uint32 NewWidth, Uint32 NewHeight)override final + { + TBase::Resize(NewWidth, NewHeight, 0); + } + + void SetSwapChainAttribs(ID3D11RenderTargetView *pRTV, ID3D11DepthStencilView *pDSV, Uint32 Width, Uint32 Height) + { + TBase::Resize(Width, Height, 0); + m_pRTV = pRTV; + m_pDSV = pDSV; + } + + void ResetSwapChainAttribs() + { + m_pRTV = nullptr; + m_pDSV = nullptr; + } + +private: + ID3D11RenderTargetView *m_pRTV = nullptr; + ID3D11DepthStencilView *m_pDSV = nullptr; +}; + +} + +DiligentGraphicsAdapterD3D11::DiligentGraphicsAdapterD3D11(const UnityGraphicsD3D11Emulator& UnityGraphicsD3D11)noexcept : + m_UnityGraphicsD3D11(UnityGraphicsD3D11) +{ + auto *GraphicsD3D11Impl = m_UnityGraphicsD3D11.GetGraphicsImpl(); + ID3D11Device *pd3d11Device = GraphicsD3D11Impl->GetD3D11Device(); + ID3D11DeviceContext *pd3d11Context = GraphicsD3D11Impl->GetD3D11Context(); + auto *pFactoryD3d11 = GetEngineFactoryD3D11(); + EngineD3D11Attribs Attribs; + pFactoryD3d11->AttachToD3D11Device(pd3d11Device, pd3d11Context, Attribs, &m_pDevice, &m_pDeviceCtx, 0); +} + +void DiligentGraphicsAdapterD3D11::InitProxySwapChain() +{ + auto *GraphicsD3D11Impl = m_UnityGraphicsD3D11.GetGraphicsImpl(); + D3D11_RENDER_TARGET_VIEW_DESC RTVDesc; + GraphicsD3D11Impl->GetRTV()->GetDesc(&RTVDesc); + D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc; + GraphicsD3D11Impl->GetDSV()->GetDesc(&DSVDesc); + + SwapChainDesc SCDesc; + SCDesc.ColorBufferFormat = DXGI_FormatToTexFormat(RTVDesc.Format); + SCDesc.DepthBufferFormat = DXGI_FormatToTexFormat(DSVDesc.Format); + SCDesc.Width = GraphicsD3D11Impl->GetBackBufferWidth(); + SCDesc.Height = GraphicsD3D11Impl->GetBackBufferHeight(); + // These fields are irrelevant + SCDesc.SamplesCount = 0; + SCDesc.BufferCount = 0; + + auto &DefaultAllocator = DefaultRawMemoryAllocator::GetAllocator(); + auto pProxySwapChainD3D11 = NEW_RC_OBJ(DefaultAllocator, "ProxySwapChainD3D11 instance", ProxySwapChainD3D11)(m_pDevice, m_pDeviceCtx, SCDesc); + pProxySwapChainD3D11->QueryInterface(IID_SwapChain, reinterpret_cast<IObject**>(static_cast<ISwapChain**>(&m_pProxySwapChain))); + + m_pDeviceCtx->SetSwapChain(m_pProxySwapChain); +} + +void DiligentGraphicsAdapterD3D11::BeginFrame() +{ + auto *UnityGraphicsD3D11Impl = m_UnityGraphicsD3D11.GetGraphicsImpl(); + auto *pRTV = UnityGraphicsD3D11Impl->GetRTV(); + auto *pDSV = UnityGraphicsD3D11Impl->GetDSV(); + auto Width = UnityGraphicsD3D11Impl->GetBackBufferWidth(); + auto Height = UnityGraphicsD3D11Impl->GetBackBufferHeight(); + VERIFY_EXPR(pRTV != nullptr && pDSV != nullptr && Width != 0 && Height != 0); + ValidatedCast<ProxySwapChainD3D11>(m_pProxySwapChain.RawPtr())->SetSwapChainAttribs(pRTV, pDSV, Width, Height); +} + +void DiligentGraphicsAdapterD3D11::EndFrame() +{ + ValidatedCast<ProxySwapChainD3D11>(m_pProxySwapChain.RawPtr())->ResetSwapChainAttribs(); + m_pDeviceCtx->InvalidateState(); +} + +bool DiligentGraphicsAdapterD3D11::UsesReverseZ() +{ + return m_UnityGraphicsD3D11.UsesReverseZ(); +}
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/src/DiligentGraphicsAdapterD3D12.cpp b/unityplugin/UnityEmulator/src/DiligentGraphicsAdapterD3D12.cpp new file mode 100644 index 0000000..9aea25d --- /dev/null +++ b/unityplugin/UnityEmulator/src/DiligentGraphicsAdapterD3D12.cpp @@ -0,0 +1,254 @@ + +#define NOMINMAX +#include <D3D12.h> +#include <dxgi1_4.h> +#include <atlbase.h> +#include "UnityGraphicsD3D12Impl.h" +#include "DiligentGraphicsAdapterD3D12.h" +#include "UnityGraphicsD3D12Emulator.h" +#include "SwapChainD3D12.h" +#include "TextureD3D12.h" +#include "RenderDeviceD3D12.h" +#include "DeviceContextD3D12.h" +#include "CommandQueueD3D12.h" +#include "RenderDeviceFactoryD3D12.h" +#include "SwapChainBase.h" +#include "DefaultRawMemoryAllocator.h" +#include "DXGITypeConversions.h" + +using namespace Diligent; + +namespace +{ + +class ProxyCommandQueueD3D12 : public ObjectBase<ICommandQueueD3D12> +{ +public: + using TBase = ObjectBase<ICommandQueueD3D12>; + ProxyCommandQueueD3D12(IReferenceCounters *pRefCounters, UnityGraphicsD3D12Impl& GraphicsD3D12Impl) : + TBase(pRefCounters), + m_GraphicsD3D12Impl(GraphicsD3D12Impl) + { + } + + ~ProxyCommandQueueD3D12() + { + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE( IID_CommandQueueD3D12, TBase ) + + // Returns the fence value that will be signaled next time + virtual UINT64 GetNextFenceValue()override final + { + return m_GraphicsD3D12Impl.GetNextFenceValue(); + } + + // Executes a given command list + virtual UINT64 ExecuteCommandList(ID3D12GraphicsCommandList* commandList)override final + { + return m_GraphicsD3D12Impl.ExecuteCommandList(commandList); + } + + // Returns D3D12 command queue. May return null if queue is anavailable + virtual ID3D12CommandQueue* GetD3D12CommandQueue() + { + return nullptr; + } + + /// Returns value of the last completed fence + virtual Uint64 GetCompletedFenceValue() + { + return m_GraphicsD3D12Impl.GetCompletedFenceValue(); + } + + /// Blocks execution until all pending GPU commands are complete + virtual void IdleGPU() + { + m_GraphicsD3D12Impl.IdleGPU(); + } + +private: + UnityGraphicsD3D12Impl& m_GraphicsD3D12Impl; +}; + + +class ProxySwapChainD3D12 : public SwapChainBase<ISwapChainD3D12> +{ +public: + using TBase = SwapChainBase<ISwapChainD3D12>; + + ProxySwapChainD3D12( IReferenceCounters *pRefCounters, + IRenderDevice *pDevice, + IDeviceContext *pDeviceContext, + const SwapChainDesc& SCDesc ) : + TBase(pRefCounters, pDevice, pDeviceContext,SCDesc) + { + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_SwapChainD3D12, TBase) + + virtual IDXGISwapChain *GetDXGISwapChain()override final + { + UNEXPECTED("DXGI swap chain cannot be requested through the proxy swap chain") + return nullptr; + } + + virtual ITextureViewD3D12* GetCurrentBackBufferRTV() + { + return m_RTVs[m_CurrentBackBufferIndex]; + } + + virtual ITextureViewD3D12* GetDepthBufferDSV() + { + return m_DSV; + } + + virtual void Present()override final + { + UNEXPECTED("Present is not expected to be called directly") + } + + virtual void Resize(Uint32 NewWidth, Uint32 NewHeight)override final + { + TBase::Resize(NewWidth, NewHeight, 0); + } + + void ReleaseBuffers() + { + m_BackBuffers.clear(); + m_RTVs.clear(); + m_DepthBuffer.Release(); + m_DSV.Release(); + } + + void SetBackBufferIndex(Uint32 BackBufferIndex) { m_CurrentBackBufferIndex = BackBufferIndex; } + + void CreateBuffers(IDXGISwapChain3 *pDXGISwapChain, ID3D12Resource *pd3d12DepthBuffer) + { + DXGI_SWAP_CHAIN_DESC1 SwapChainDesc; + pDXGISwapChain->GetDesc1(&SwapChainDesc); + m_SwapChainDesc.BufferCount = SwapChainDesc.BufferCount; + m_SwapChainDesc.SamplesCount = SwapChainDesc.SampleDesc.Count; + m_SwapChainDesc.Width = SwapChainDesc.Width; + m_SwapChainDesc.Height = SwapChainDesc.Height; + m_SwapChainDesc.ColorBufferFormat = DXGI_FormatToTexFormat(SwapChainDesc.Format); + const auto DepthBufferDesc = pd3d12DepthBuffer->GetDesc(); + m_SwapChainDesc.DepthBufferFormat = DXGI_FormatToTexFormat(DepthBufferDesc.Format); + + RefCntAutoPtr<IRenderDeviceD3D12> pRenderDeviceD3D12(m_pRenderDevice, IID_RenderDeviceD3D12); + + m_BackBuffers.reserve(m_SwapChainDesc.BufferCount); + m_RTVs.reserve(m_SwapChainDesc.BufferCount); + for(Uint32 backbuff = 0; backbuff < m_SwapChainDesc.BufferCount; ++backbuff) + { + CComPtr<ID3D12Resource> pd3d12BackBuffer; + auto hr = pDXGISwapChain->GetBuffer(backbuff, __uuidof(pd3d12BackBuffer), reinterpret_cast<void**>( static_cast<ID3D12Resource**>(&pd3d12BackBuffer) )); + if(FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to get back buffer ", backbuff," from the swap chain"); + RefCntAutoPtr<ITexture> pBackBuffer; + pRenderDeviceD3D12->CreateTextureFromD3DResource(pd3d12BackBuffer, &pBackBuffer); + m_BackBuffers.emplace_back( RefCntAutoPtr<ITextureD3D12>(pBackBuffer, IID_TextureD3D12) ); + TextureViewDesc TexViewDesc; + TexViewDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET; + TexViewDesc.Format = TEX_FORMAT_RGBA8_UNORM_SRGB; + RefCntAutoPtr<ITextureView> pRTV; + pBackBuffer->CreateView(TexViewDesc, &pRTV); + m_RTVs.emplace_back(RefCntAutoPtr<ITextureViewD3D12>(pRTV, IID_TextureViewD3D12)); + } + + RefCntAutoPtr<ITexture> pDepthBuffer; + pRenderDeviceD3D12->CreateTextureFromD3DResource(pd3d12DepthBuffer, &pDepthBuffer); + m_DepthBuffer = RefCntAutoPtr<ITextureD3D12>(pDepthBuffer, IID_TextureD3D12); + auto *pDSV = m_DepthBuffer->GetDefaultView(TEXTURE_VIEW_DEPTH_STENCIL); + m_DSV = RefCntAutoPtr<ITextureViewD3D12>(pDSV, IID_TextureViewD3D12); + } + + ITextureD3D12* GetCurrentBackBuffer() { return m_BackBuffers[m_CurrentBackBufferIndex]; } + ITextureD3D12* GetDepthBuffer() { return m_DepthBuffer; } + +private: + std::vector<RefCntAutoPtr<ITextureD3D12>> m_BackBuffers; + std::vector<RefCntAutoPtr<ITextureViewD3D12>> m_RTVs; + RefCntAutoPtr<ITextureD3D12> m_DepthBuffer; + RefCntAutoPtr<ITextureViewD3D12> m_DSV; + Uint32 m_CurrentBackBufferIndex = 0; +}; + +} + + +DiligentGraphicsAdapterD3D12::DiligentGraphicsAdapterD3D12(UnityGraphicsD3D12Emulator& UnityGraphicsD3D12)noexcept : + m_UnityGraphicsD3D12(UnityGraphicsD3D12) +{ + auto *GraphicsImpl = UnityGraphicsD3D12.GetGraphicsImpl(); + auto *d3d12Device = GraphicsImpl->GetD3D12Device(); + + auto &DefaultAllocator = DefaultRawMemoryAllocator::GetAllocator(); + auto CmdQueue = NEW_RC_OBJ(DefaultAllocator, "UnityCommandQueueImpl instance", ProxyCommandQueueD3D12)(*GraphicsImpl); + + auto *pFactoryD3D12 = GetEngineFactoryD3D12(); + EngineD3D12Attribs Attribs; + pFactoryD3D12->AttachToD3D12Device(d3d12Device, CmdQueue, Attribs, &m_pDevice, &m_pDeviceCtx, 0); +} + +void DiligentGraphicsAdapterD3D12::InitProxySwapChain() +{ + auto *GraphicsImpl = m_UnityGraphicsD3D12.GetGraphicsImpl(); + auto &DefaultAllocator = DefaultRawMemoryAllocator::GetAllocator(); + SwapChainDesc SCDesc; + auto ProxySwapChain = NEW_RC_OBJ(DefaultAllocator, "UnityCommandQueueImpl instance", ProxySwapChainD3D12)(m_pDevice, m_pDeviceCtx, SCDesc); + ProxySwapChain->CreateBuffers(GraphicsImpl->GetDXGISwapChain(), GraphicsImpl->GetDepthBuffer()); + m_pProxySwapChain = ProxySwapChain; + m_pDeviceCtx->SetSwapChain(ProxySwapChain); +} + +void DiligentGraphicsAdapterD3D12::PreSwapChainResize() +{ + auto *pProxySwapChainD3D12 = ValidatedCast<ProxySwapChainD3D12>(m_pProxySwapChain.RawPtr()); + auto *pDeviceD3D12 = ValidatedCast<IRenderDeviceD3D12>(m_pDevice.RawPtr()); + pProxySwapChainD3D12->ReleaseBuffers(); + auto *GraphicsImpl = m_UnityGraphicsD3D12.GetGraphicsImpl(); + pDeviceD3D12->FinishFrame(); + // We must idle GPU + GraphicsImpl->IdleGPU(); + // And call FinishFrame() to release references to swap chain resources + pDeviceD3D12->FinishFrame(); +} + +void DiligentGraphicsAdapterD3D12::PostSwapChainResize() +{ + auto *GraphicsImpl = m_UnityGraphicsD3D12.GetGraphicsImpl(); + auto *pProxySwapChainD3D12 = ValidatedCast<ProxySwapChainD3D12>(m_pProxySwapChain.RawPtr()); + pProxySwapChainD3D12->CreateBuffers(GraphicsImpl->GetDXGISwapChain(), GraphicsImpl->GetDepthBuffer()); +} + +void DiligentGraphicsAdapterD3D12::BeginFrame() +{ + auto *GraphicsImpl = m_UnityGraphicsD3D12.GetGraphicsImpl(); + auto *pProxySwapChainD3D12 = ValidatedCast<ProxySwapChainD3D12>(m_pProxySwapChain.RawPtr()); + pProxySwapChainD3D12->SetBackBufferIndex(GraphicsImpl->GetCurrentBackBufferIndex()); + // Unity graphics emulator transitions render target to D3D12_RESOURCE_STATE_RENDER_TARGET, + // and depth buffer to D3D12_RESOURCE_STATE_DEPTH_WRITE state + pProxySwapChainD3D12->GetCurrentBackBuffer()->SetD3D12ResourceState(D3D12_RESOURCE_STATE_RENDER_TARGET); + pProxySwapChainD3D12->GetDepthBuffer()->SetD3D12ResourceState(D3D12_RESOURCE_STATE_DEPTH_WRITE); +} + +void DiligentGraphicsAdapterD3D12::EndFrame() +{ + // Unity graphics emulator expects render target to be D3D12_RESOURCE_STATE_RENDER_TARGET, + // and depth buffer to be in D3D12_RESOURCE_STATE_DEPTH_WRITE state + auto *pCtxD3D12 = ValidatedCast<IDeviceContextD3D12>(m_pDeviceCtx.RawPtr()); + auto *pProxySwapChainD3D12 = ValidatedCast<ProxySwapChainD3D12>(m_pProxySwapChain.RawPtr()); + auto *pCurrentBackBuffer = pProxySwapChainD3D12->GetCurrentBackBuffer(); + auto *pDepthBuffer = pProxySwapChainD3D12->GetDepthBuffer(); + pCtxD3D12->TransitionTextureState(pCurrentBackBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET); + pCtxD3D12->TransitionTextureState(pDepthBuffer, D3D12_RESOURCE_STATE_DEPTH_WRITE); + m_pDeviceCtx->Flush(); + m_pDeviceCtx->InvalidateState(); + ValidatedCast<IRenderDeviceD3D12>(m_pDevice.RawPtr())->FinishFrame(); +} + +bool DiligentGraphicsAdapterD3D12::UsesReverseZ() +{ + return m_UnityGraphicsD3D12.UsesReverseZ(); +} diff --git a/unityplugin/UnityEmulator/src/DiligentGraphicsAdapterGL.cpp b/unityplugin/UnityEmulator/src/DiligentGraphicsAdapterGL.cpp new file mode 100644 index 0000000..4b5ecb1 --- /dev/null +++ b/unityplugin/UnityEmulator/src/DiligentGraphicsAdapterGL.cpp @@ -0,0 +1,103 @@ +#include "DiligentGraphicsAdapterGL.h" + +#if OPENGL_SUPPORTED + +#include "UnityGraphicsGLCoreES_Emulator.h" +#include "RenderDeviceFactoryOpenGL.h" +#include "SwapChainBase.h" +#include "DefaultRawMemoryAllocator.h" +#include "UnityGraphicsGL_Impl.h" + +using namespace Diligent; + +namespace +{ + +class ProxySwapChainGL : public SwapChainBase<ISwapChain> +{ +public: + using TBase = SwapChainBase<ISwapChain>; + + ProxySwapChainGL( IReferenceCounters *pRefCounters, + IRenderDevice *pDevice, + IDeviceContext *pDeviceContext, + const SwapChainDesc& SCDesc ) : + TBase(pRefCounters, pDevice, pDeviceContext,SCDesc) + {} + + virtual void Present()override final + { + UNEXPECTED("Present is not expected to be called directly") + } + + virtual void Resize(Uint32 NewWidth, Uint32 NewHeight)override final + { + TBase::Resize(NewWidth, NewHeight, 0); + } +}; + +} + +DiligentGraphicsAdapterGL::DiligentGraphicsAdapterGL(const UnityGraphicsGLCoreES_Emulator& UnityGraphicsGL)noexcept : + m_UnityGraphicsGL(UnityGraphicsGL) +{ + auto *UnityGraphicsGLImpl = UnityGraphicsGL.GetGraphicsImpl(); + + auto *pFactoryGL = GetEngineFactoryOpenGL(); + EngineCreationAttribs Attribs; + pFactoryGL->AttachToActiveGLContext(Attribs, &m_pDevice, &m_pDeviceCtx); + + auto BackBufferGLFormat = UnityGraphicsGLImpl->GetBackBufferFormat(); + auto DepthBufferGLFormat = UnityGraphicsGLImpl->GetDepthBufferFormat(); + + SwapChainDesc SCDesc; + if(BackBufferGLFormat == GL_RGBA8) + SCDesc.ColorBufferFormat = TEX_FORMAT_RGBA8_UNORM_SRGB; + else + { + UNEXPECTED("Unexpected back buffer format") + } + + if (DepthBufferGLFormat == GL_DEPTH_COMPONENT32F) + SCDesc.DepthBufferFormat = TEX_FORMAT_D32_FLOAT; + else if (DepthBufferGLFormat == GL_DEPTH_COMPONENT24) + SCDesc.DepthBufferFormat = TEX_FORMAT_D24_UNORM_S8_UINT; + else if (DepthBufferGLFormat == GL_DEPTH_COMPONENT16) + SCDesc.DepthBufferFormat = TEX_FORMAT_D16_UNORM; + else + { + UNEXPECTED("Unexpected depth buffer format") + } + + SCDesc.Width = UnityGraphicsGLImpl->GetBackBufferWidth(); + SCDesc.Height = UnityGraphicsGLImpl->GetBackBufferHeight(); + // These fields are irrelevant + SCDesc.SamplesCount = 0; + SCDesc.BufferCount = 0; + + auto &DefaultAllocator = DefaultRawMemoryAllocator::GetAllocator(); + auto pProxySwapChainGL = NEW_RC_OBJ(DefaultAllocator, "ProxySwapChainGL instance", ProxySwapChainGL)(m_pDevice, m_pDeviceCtx, SCDesc); + pProxySwapChainGL->QueryInterface(IID_SwapChain, reinterpret_cast<IObject**>(static_cast<ISwapChain**>(&m_pProxySwapChain))); + + m_pDeviceCtx->SetSwapChain(m_pProxySwapChain); +} + +void DiligentGraphicsAdapterGL::BeginFrame() +{ + auto *UnityGraphicsGLImpl = m_UnityGraphicsGL.GetGraphicsImpl(); + Uint32 Width = UnityGraphicsGLImpl->GetBackBufferWidth(); + Uint32 Height = UnityGraphicsGLImpl->GetBackBufferHeight(); + ValidatedCast<ProxySwapChainGL>(m_pProxySwapChain.RawPtr())->Resize(Width, Height); +} + +void DiligentGraphicsAdapterGL::EndFrame() +{ + m_pDeviceCtx->InvalidateState(); +} + +bool DiligentGraphicsAdapterGL::UsesReverseZ() +{ + return m_UnityGraphicsGL.UsesReverseZ(); +} + +#endif // OPENGL_SUPPORTED
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/src/UWP/App.cpp b/unityplugin/UnityEmulator/src/UWP/App.cpp new file mode 100644 index 0000000..7bd098f --- /dev/null +++ b/unityplugin/UnityEmulator/src/UWP/App.cpp @@ -0,0 +1,252 @@ +/* Copyright 2015-2016 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch2.h" +#include "App.h" + +#include <ppltasks.h> + +using namespace UnityEmulatorApp; + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input; +using namespace Windows::System; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; + +using Microsoft::WRL::ComPtr; + + +// The main function is only used to initialize our IFrameworkView class. +[Platform::MTAThread] +int main(Platform::Array<Platform::String^>^) +{ + auto direct3DApplicationSource = ref new Direct3DApplicationSource(); + CoreApplication::Run(direct3DApplicationSource); + return 0; +} + +IFrameworkView^ Direct3DApplicationSource::CreateView() +{ + return ref new App(); +} + +App::App() : + m_windowClosed(false), + m_windowVisible(true) +{ +} + +// The first method called when the IFrameworkView is being created. +void App::Initialize(CoreApplicationView^ applicationView) +{ + // Register event handlers for app lifecycle. This example includes Activated, so that we + // can make the CoreWindow active and start rendering on the window. + applicationView->Activated += + ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated); + + CoreApplication::Suspending += + ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler<Platform::Object^>(this, &App::OnResuming); +} + +// Called when the CoreWindow object is created (or re-created). +void App::SetWindow(CoreWindow^ window) +{ + window->SizeChanged += + ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged); + + window->VisibilityChanged += + ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged); + + window->Closed += + ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed); + + DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + currentDisplayInformation->DpiChanged += + ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDpiChanged); + + currentDisplayInformation->OrientationChanged += + ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged); + + DisplayInformation::DisplayContentsInvalidated += + ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated); +} + +// Initializes scene resources, or loads a previously saved app state. +void App::Load(Platform::String^ entryPoint) +{ + if (m_main == nullptr) + { + m_main = std::unique_ptr<UnityEmulatorAppMain>(new UnityEmulatorAppMain()); + } +} + +// This method is called after the window becomes active. +void App::Run() +{ + while (!m_windowClosed) + { + if (m_windowVisible) + { + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + + //auto commandQueue = GetDeviceResources()->GetCommandQueue(); + //PIXBeginEvent(commandQueue, 0, L"Update"); + { + m_main->Update(); + } + //PIXEndEvent(commandQueue); + + //PIXBeginEvent(commandQueue, 0, L"Render"); + { + GetDeviceResources()->BeginFrame(); + + m_main->Render(); + + GetDeviceResources()->EndFrame(); + GetDeviceResources()->Present(); + } + //PIXEndEvent(commandQueue); + } + else + { + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); + } + } +} + +// Required for IFrameworkView. +// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView +// class is torn down while the app is in the foreground. +void App::Uninitialize() +{ +} + +// Application lifecycle event handlers. + +void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) +{ + // Run() won't start until the CoreWindow is activated. + CoreWindow::GetForCurrentThread()->Activate(); +} + +void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) +{ + // Save app state asynchronously after requesting a deferral. Holding a deferral + // indicates that the application is busy performing suspending operations. Be + // aware that a deferral may not be held indefinitely. After about five seconds, + // the app will be forced to exit. + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_main->OnSuspending(); + deferral->Complete(); + }); +} + +void App::OnResuming(Platform::Object^ sender, Platform::Object^ args) +{ + // Restore any data or state that was unloaded on suspend. By default, data + // and state are persisted when resuming from suspend. Note that this event + // does not occur if the app was previously terminated. + + m_main->OnResuming(); +} + +// Window event handlers. + +void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) +{ + GetDeviceResources()->SetLogicalSize(Size(sender->Bounds.Width, sender->Bounds.Height)); + m_main->OnWindowSizeChanged(); +} + +void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) +{ + m_windowVisible = args->Visible; +} + +void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) +{ + m_windowClosed = true; +} + +// DisplayInformation event handlers. + +void App::OnDpiChanged(DisplayInformation^ sender, Object^ args) +{ + // Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app + // if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources, + // you should always retrieve it using the GetDpi method. + // See DeviceResources.cpp for more details. + GetDeviceResources()->SetDpi(sender->LogicalDpi); + m_main->OnWindowSizeChanged(); +} + +void App::OnOrientationChanged(DisplayInformation^ sender, Object^ args) +{ + GetDeviceResources()->SetCurrentOrientation(sender->CurrentOrientation); + m_main->OnWindowSizeChanged(); +} + +void App::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) +{ + GetDeviceResources()->ValidateDevice(); +} + +std::shared_ptr<DX::DeviceResources> App::GetDeviceResources() +{ + if (m_deviceResources != nullptr && m_deviceResources->IsDeviceRemoved()) + { + // All references to the existing D3D device must be released before a new device + // can be created. + + m_deviceResources = nullptr; + m_main->OnDeviceRemoved(); + +#if defined(_DEBUG) + ComPtr<IDXGIDebug1> dxgiDebug; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) + { + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL)); + } +#endif + } + + if (m_deviceResources == nullptr) + { + m_deviceResources = std::make_shared<DX::DeviceResources>(); + m_deviceResources->SetWindow(CoreWindow::GetForCurrentThread()); + m_main->CreateRenderers(m_deviceResources); + } + return m_deviceResources; +} diff --git a/unityplugin/UnityEmulator/src/UWP/App.h b/unityplugin/UnityEmulator/src/UWP/App.h new file mode 100644 index 0000000..e762e8f --- /dev/null +++ b/unityplugin/UnityEmulator/src/UWP/App.h @@ -0,0 +1,75 @@ +/* Copyright 2015-2016 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +#include "pch.h" +#include "DeviceResources.h" +#include "UnityEmulatorAppMain.h" + +namespace UnityEmulatorApp +{ + // Main entry point for our app. Connects the app with the Windows shell and handles application lifecycle events. + ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView + { + public: + App(); + + // IFrameworkView methods. + virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView); + virtual void SetWindow(Windows::UI::Core::CoreWindow^ window); + virtual void Load(Platform::String^ entryPoint); + virtual void Run(); + virtual void Uninitialize(); + + protected: + // Application lifecycle event handlers. + void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args); + void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args); + void OnResuming(Platform::Object^ sender, Platform::Object^ args); + + // Window event handlers. + void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args); + void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args); + void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args); + + // DisplayInformation event handlers. + void OnDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args); + void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args); + void OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args); + + private: + std::shared_ptr<DX::DeviceResources> GetDeviceResources(); + + std::shared_ptr<DX::DeviceResources> m_deviceResources; + std::unique_ptr<UnityEmulatorAppMain> m_main; + bool m_windowClosed; + bool m_windowVisible; + }; +} + +ref class Direct3DApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource +{ +public: + virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView(); +}; diff --git a/unityplugin/UnityEmulator/src/UWP/DeviceResources.cpp b/unityplugin/UnityEmulator/src/UWP/DeviceResources.cpp new file mode 100644 index 0000000..c38b510 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UWP/DeviceResources.cpp @@ -0,0 +1,459 @@ +#include "pch2.h" +#include "DeviceResources.h" +#include "DirectXHelper.h" + +#include "IUnityInterface.h" +#include "UnityGraphicsD3D11Emulator.h" +#include "UnityGraphicsD3D12Emulator.h" +#include "DiligentGraphicsAdapterD3D11.h" +#include "DiligentGraphicsAdapterD3D12.h" +#include "ValidatedCast.h" + +#include "UnitySceneBase.h" +#include "StringTools.h" +#include "Errors.h" + +using namespace DirectX; +using namespace Microsoft::WRL; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; +using namespace Windows::UI::Core; +using namespace Windows::UI::Xaml::Controls; +using namespace Platform; +using namespace Diligent; + +namespace DisplayMetrics +{ + // High resolution displays can require a lot of GPU and battery power to render. + // High resolution phones, for example, may suffer from poor battery life if + // games attempt to render at 60 frames per second at full fidelity. + // The decision to render at full fidelity across all platforms and form factors + // should be deliberate. + static const bool SupportHighResolutions = false; + + // The default thresholds that define a "high resolution" display. If the thresholds + // are exceeded and SupportHighResolutions is false, the dimensions will be scaled + // by 50%. + static const float DpiThreshold = 192.0f; // 200% of standard desktop display. + static const float WidthThreshold = 1920.0f; // 1080p width. + static const float HeightThreshold = 1080.0f; // 1080p height. +}; + +// Constants used to calculate screen rotations. +namespace ScreenRotation +{ + // 0-degree Z-rotation + static const XMFLOAT4X4 Rotation0( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 90-degree Z-rotation + static const XMFLOAT4X4 Rotation90( + 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 180-degree Z-rotation + static const XMFLOAT4X4 Rotation180( + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 270-degree Z-rotation + static const XMFLOAT4X4 Rotation270( + 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); +}; + +// Constructor for DeviceResources. +DX::DeviceResources::DeviceResources() : + m_d3dRenderTargetSize(), + m_outputSize(), + m_logicalSize(), + m_nativeOrientation(DisplayOrientations::None), + m_currentOrientation(DisplayOrientations::None), + m_dpi(-1.0f), + m_deviceRemoved(false) +{ + CreateDeviceResources(); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DX::DeviceResources::CreateDeviceResources() +{ + switch (m_DeviceType) + { + case DeviceType::D3D11: + { + auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); + GraphicsD3D11Emulator.CreateD3D11DeviceAndContext(); + m_UnityGraphicsEmulator = &GraphicsD3D11Emulator; + m_DiligentGraphics.reset(new DiligentGraphicsAdapterD3D11(GraphicsD3D11Emulator)); + } + break; + + case DeviceType::D3D12: + { + auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); + GraphicsD3D12Emulator.CreateD3D12DeviceAndCommandQueue(); + m_UnityGraphicsEmulator = &GraphicsD3D12Emulator; + m_DiligentGraphics.reset(new DiligentGraphicsAdapterD3D12(GraphicsD3D12Emulator)); + } + break; + + default: + LOG_ERROR_AND_THROW("Unsupported device type"); + } +} + +DX::DeviceResources::~DeviceResources() +{ + m_DiligentGraphics.reset(); + m_UnityGraphicsEmulator->Release(); +} + +// These resources need to be recreated every time the window size is changed. +void DX::DeviceResources::CreateWindowSizeDependentResources() +{ + UpdateRenderTargetSize(); + + // The width and height of the swap chain must be based on the window's + // natively-oriented width and height. If the window is not in the native + // orientation, the dimensions must be reversed. + DXGI_MODE_ROTATION displayRotation = ComputeDisplayRotation(); + + bool swapDimensions = displayRotation == DXGI_MODE_ROTATION_ROTATE90 || displayRotation == DXGI_MODE_ROTATION_ROTATE270; + auto fWidth = swapDimensions ? m_outputSize.Height : m_outputSize.Width; + auto fHeight = swapDimensions ? m_outputSize.Width : m_outputSize.Height; + + UINT backBufferWidth = lround(fWidth); + UINT backBufferHeight = lround(fHeight); + + if (m_UnityGraphicsEmulator->SwapChainInitialized()) + { + m_DiligentGraphics->PreSwapChainResize(); + // If the swap chain already exists, resize it. + m_UnityGraphicsEmulator->ResizeSwapChain(backBufferWidth, backBufferHeight); + + m_DiligentGraphics->PostSwapChainResize(); + +#if 0 + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { + // If the device was removed for any reason, a new device and swap chain will need to be created. + m_deviceRemoved = true; + + // Do not continue execution of this method. DeviceResources will be destroyed and re-created. + return; + } + else + { + DX::ThrowIfFailed(hr); + } +#endif + } + else + { + auto NativeWndHandle = reinterpret_cast<IUnknown*>(m_window.Get()); + switch (m_DeviceType) + { + case DeviceType::D3D11: + { + auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); + GraphicsD3D11Emulator.CreateSwapChain(NativeWndHandle, backBufferWidth, backBufferHeight); + ValidatedCast<DiligentGraphicsAdapterD3D11>(m_DiligentGraphics.get())->InitProxySwapChain(); + } + break; + + case DeviceType::D3D12: + { + auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); + GraphicsD3D12Emulator.CreateSwapChain(NativeWndHandle, backBufferWidth, backBufferHeight); + ValidatedCast<DiligentGraphicsAdapterD3D12>(m_DiligentGraphics.get())->InitProxySwapChain(); + } + break; + + default: + UNEXPECTED("Unsupported device type"); + } + } + + // Set the proper orientation for the swap chain, and generate + // 3D matrix transformations for rendering to the rotated swap chain. + // The 3D matrix is specified explicitly to avoid rounding errors. + + switch (displayRotation) + { + case DXGI_MODE_ROTATION_IDENTITY: + m_orientationTransform3D = ScreenRotation::Rotation0; + break; + + case DXGI_MODE_ROTATION_ROTATE90: + m_orientationTransform3D = ScreenRotation::Rotation270; + break; + + case DXGI_MODE_ROTATION_ROTATE180: + m_orientationTransform3D = ScreenRotation::Rotation180; + break; + + case DXGI_MODE_ROTATION_ROTATE270: + m_orientationTransform3D = ScreenRotation::Rotation90; + break; + + default: + throw ref new FailureException(); + } +#if 0 + DX::ThrowIfFailed( + m_swapChain->SetRotation(displayRotation) + ); +#endif + + +} + +// Determine the dimensions of the render target and whether it will be scaled down. +void DX::DeviceResources::UpdateRenderTargetSize() +{ + m_effectiveDpi = m_dpi; + + // To improve battery life on high resolution devices, render to a smaller render target + // and allow the GPU to scale the output when it is presented. + if (!DisplayMetrics::SupportHighResolutions && m_dpi > DisplayMetrics::DpiThreshold) + { + float width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_dpi); + float height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_dpi); + + // When the device is in portrait orientation, height > width. Compare the + // larger dimension against the width threshold and the smaller dimension + // against the height threshold. + if (max(width, height) > DisplayMetrics::WidthThreshold && min(width, height) > DisplayMetrics::HeightThreshold) + { + // To scale the app we change the effective DPI. Logical size does not change. + m_effectiveDpi /= 2.0f; + } + } + + // Calculate the necessary render target size in pixels. + m_outputSize.Width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_effectiveDpi); + m_outputSize.Height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_effectiveDpi); + + // Prevent zero size DirectX content from being created. + m_outputSize.Width = max(m_outputSize.Width, 1); + m_outputSize.Height = max(m_outputSize.Height, 1); +} + +// This method is called when the CoreWindow is created (or re-created). +void DX::DeviceResources::SetWindow(CoreWindow^ window) +{ + DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + m_window = window; + m_logicalSize = Windows::Foundation::Size(window->Bounds.Width, window->Bounds.Height); + m_nativeOrientation = currentDisplayInformation->NativeOrientation; + m_currentOrientation = currentDisplayInformation->CurrentOrientation; + m_dpi = currentDisplayInformation->LogicalDpi; + + CreateWindowSizeDependentResources(); +} + +// This method is called in the event handler for the SizeChanged event. +void DX::DeviceResources::SetLogicalSize(Windows::Foundation::Size logicalSize) +{ + if (m_logicalSize != logicalSize) + { + m_logicalSize = logicalSize; + CreateWindowSizeDependentResources(); + } +} + +// This method is called in the event handler for the DpiChanged event. +void DX::DeviceResources::SetDpi(float dpi) +{ + if (dpi != m_dpi) + { + m_dpi = dpi; + + // When the display DPI changes, the logical size of the window (measured in Dips) also changes and needs to be updated. + m_logicalSize = Windows::Foundation::Size(m_window->Bounds.Width, m_window->Bounds.Height); + + CreateWindowSizeDependentResources(); + } +} + +// This method is called in the event handler for the OrientationChanged event. +void DX::DeviceResources::SetCurrentOrientation(DisplayOrientations currentOrientation) +{ + if (m_currentOrientation != currentOrientation) + { + m_currentOrientation = currentOrientation; + CreateWindowSizeDependentResources(); + } +} + +// This method is called in the event handler for the DisplayContentsInvalidated event. +void DX::DeviceResources::ValidateDevice() +{ + // The D3D Device is no longer valid if the default adapter changed since the device + // was created or if the device has been removed. + + ComPtr<IDXGIDevice3> dxgiDevice; + ComPtr<ID3D11Device> d3d11Device; + ComPtr<ID3D12Device> d3d12Device; + + if (m_DeviceType == DeviceType::D3D11) + { + auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); + d3d11Device = reinterpret_cast<ID3D11Device*>(GraphicsD3D11Emulator.GetGraphicsImpl()); + DX::ThrowIfFailed(d3d11Device.As(&dxgiDevice)); + } + else if (m_DeviceType == DeviceType::D3D12) + { + auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); + d3d12Device = reinterpret_cast<ID3D12Device*>(GraphicsD3D12Emulator.GetGraphicsImpl()); + DX::ThrowIfFailed(d3d12Device.As(&dxgiDevice)); + } + + ComPtr<IDXGIAdapter> deviceAdapter; + DX::ThrowIfFailed(dxgiDevice->GetAdapter(&deviceAdapter)); + + ComPtr<IDXGIFactory2> deviceFactory; + DX::ThrowIfFailed(deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory))); + + // First, get the LUID for the default adapter from when the device was created. + + DXGI_ADAPTER_DESC previousDesc; + { + ComPtr<IDXGIAdapter1> previousDefaultAdapter; + DX::ThrowIfFailed(deviceFactory->EnumAdapters1(0, &previousDefaultAdapter)); + + DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc)); + } + + // Next, get the information for the current default adapter. + + DXGI_ADAPTER_DESC currentDesc; + { + ComPtr<IDXGIFactory4> currentDxgiFactory; + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(¤tDxgiFactory))); + + ComPtr<IDXGIAdapter1> currentDefaultAdapter; + DX::ThrowIfFailed(currentDxgiFactory->EnumAdapters1(0, ¤tDefaultAdapter)); + + DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc)); + } + + // If the adapter LUIDs don't match, or if the device reports that it has been removed, + // a new D3D device must be created. + + if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart || + previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart || + d3d11Device && FAILED(d3d11Device->GetDeviceRemovedReason()) || + d3d12Device && FAILED(d3d12Device->GetDeviceRemovedReason())) + { + m_deviceRemoved = true; + } +} + +void DX::DeviceResources::SetResourceStateTransitionHandler(IResourceStateTransitionHandler *pHandler) +{ + if (GetDeviceType() == DeviceType::D3D12) + { + UnityGraphicsD3D12Emulator::GetInstance().SetTransitionHandler(pHandler); + } +} + +void DX::DeviceResources::BeginFrame() +{ + m_UnityGraphicsEmulator->BeginFrame(); + m_DiligentGraphics->BeginFrame(); +} + +void DX::DeviceResources::EndFrame() +{ + m_DiligentGraphics->EndFrame(); + m_UnityGraphicsEmulator->EndFrame(); +} + +// Present the contents of the swap chain to the screen. +void DX::DeviceResources::Present() +{ + m_UnityGraphicsEmulator->Present(); + + //// If the device was removed either by a disconnection or a driver upgrade, we + //// must recreate all device resources. + //if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + //{ + // m_deviceRemoved = true; + //} + //else + //{ + // DX::ThrowIfFailed(hr); + //} +} + + +// This method determines the rotation between the display device's native Orientation and the +// current display orientation. +DXGI_MODE_ROTATION DX::DeviceResources::ComputeDisplayRotation() +{ + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + + // Note: NativeOrientation can only be Landscape or Portrait even though + // the DisplayOrientations enum has other values. + switch (m_nativeOrientation) + { + case DisplayOrientations::Landscape: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + } + break; + + case DisplayOrientations::Portrait: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + } + break; + } + return rotation; +} diff --git a/unityplugin/UnityEmulator/src/UWP/DeviceResources.h b/unityplugin/UnityEmulator/src/UWP/DeviceResources.h new file mode 100644 index 0000000..c91b055 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UWP/DeviceResources.h @@ -0,0 +1,71 @@ +#pragma once + +#include "UnityGraphicsEmulator.h" +#include "DiligentGraphicsAdapter.h" +#include "ResourceStateTransitionHandler.h" + +namespace DX +{ + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(); + ~DeviceResources(); + void SetWindow(Windows::UI::Core::CoreWindow^ window); + void SetLogicalSize(Windows::Foundation::Size logicalSize); + void SetCurrentOrientation(Windows::Graphics::Display::DisplayOrientations currentOrientation); + void SetDpi(float dpi); + void ValidateDevice(); + void BeginFrame(); + void Present(); + void EndFrame(); + DiligentGraphicsAdapter* GetDiligentGraphicsAdapter() { return m_DiligentGraphics.get(); } + UnityGraphicsEmulator* GetUnityGraphicsEmulator() { return m_UnityGraphicsEmulator;} + + Diligent::DeviceType GetDeviceType()const {return m_DeviceType;} + + // The size of the render target, in pixels. + Windows::Foundation::Size GetOutputSize() const { return m_outputSize; } + + // The size of the render target, in dips. + Windows::Foundation::Size GetLogicalSize() const { return m_logicalSize; } + + float GetDpi() const { return m_effectiveDpi; } + bool IsDeviceRemoved() const { return m_deviceRemoved; } + void SetResourceStateTransitionHandler(IResourceStateTransitionHandler *pHandler); + // D3D Accessors. + DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; } + + private: + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + void UpdateRenderTargetSize(); + DXGI_MODE_ROTATION ComputeDisplayRotation(); + + bool m_deviceRemoved = false; + + UnityGraphicsEmulator* m_UnityGraphicsEmulator = nullptr; + + std::unique_ptr<DiligentGraphicsAdapter> m_DiligentGraphics; + + // Cached reference to the Window. + Platform::Agile<Windows::UI::Core::CoreWindow> m_window; + + // Cached device properties. + Windows::Foundation::Size m_d3dRenderTargetSize; + Windows::Foundation::Size m_outputSize; + Windows::Foundation::Size m_logicalSize; + Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; + Windows::Graphics::Display::DisplayOrientations m_currentOrientation; + float m_dpi; + + // This is the DPI that will be reported back to the app. It takes into account whether the app supports high resolution screens or not. + float m_effectiveDpi; + + // Transforms used for display orientation. + DirectX::XMFLOAT4X4 m_orientationTransform3D; + + Diligent::DeviceType m_DeviceType = Diligent::DeviceType::D3D12; + }; +} diff --git a/unityplugin/UnityEmulator/src/UWP/DirectXHelper.h b/unityplugin/UnityEmulator/src/UWP/DirectXHelper.h new file mode 100644 index 0000000..958b355 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UWP/DirectXHelper.h @@ -0,0 +1,58 @@ +#pragma once + +#include <ppltasks.h> // For create_task + +namespace DX +{ + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + // Set a breakpoint on this line to catch Win32 API errors. + throw Platform::Exception::CreateException(hr); + } + } + + // Function that reads from a binary file asynchronously. + inline Concurrency::task<std::vector<byte>> ReadDataAsync(const std::wstring& filename) + { + using namespace Windows::Storage; + using namespace Concurrency; + + auto folder = Windows::ApplicationModel::Package::Current->InstalledLocation; + + return create_task(folder->GetFileAsync(Platform::StringReference(filename.c_str()))).then([](StorageFile^ file) + { + return FileIO::ReadBufferAsync(file); + }).then([](Streams::IBuffer^ fileBuffer) -> std::vector<byte> + { + std::vector<byte> returnBuffer; + returnBuffer.resize(fileBuffer->Length); + Streams::DataReader::FromBuffer(fileBuffer)->ReadBytes(Platform::ArrayReference<byte>(returnBuffer.data(), fileBuffer->Length)); + return returnBuffer; + }); + } + + // Converts a length in device-independent pixels (DIPs) to a length in physical pixels. + inline float ConvertDipsToPixels(float dips, float dpi) + { + static const float dipsPerInch = 96.0f; + return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer. + } + + // Assign a name to the object to aid with debugging. +#if defined(_DEBUG) + inline void SetName(ID3D12Object* pObject, LPCWSTR name) + { + pObject->SetName(name); + } +#else + inline void SetName(ID3D12Object*, LPCWSTR) + { + } +#endif +} + +// Naming helper function for ComPtr<T>. +// Assigns the name of the variable as the name of the object. +#define NAME_D3D12_OBJECT(x) DX::SetName(x.Get(), L#x) diff --git a/unityplugin/UnityEmulator/src/UWP/StepTimer.h b/unityplugin/UnityEmulator/src/UWP/StepTimer.h new file mode 100644 index 0000000..286710c --- /dev/null +++ b/unityplugin/UnityEmulator/src/UWP/StepTimer.h @@ -0,0 +1,183 @@ +#pragma once + +#include <wrl.h> + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + if (!QueryPerformanceFrequency(&m_qpcFrequency)) + { + throw ref new Platform::FailureException(); + } + + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw ref new Platform::FailureException(); + } + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; + } + + // Get elapsed time since the previous Update call. + uint64 GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64 GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32 GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32 GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64 targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64 TicksPerSecond = 10000000; + + static double TicksToSeconds(uint64 ticks) { return static_cast<double>(ticks) / TicksPerSecond; } + static uint64 SecondsToTicks(double seconds) { return static_cast<uint64>(seconds * TicksPerSecond); } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + if (!QueryPerformanceCounter(&m_qpcLastTime)) + { + throw ref new Platform::FailureException(); + } + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template<typename TUpdate> + void Tick(const TUpdate& update) + { + // Query the current time. + LARGE_INTEGER currentTime; + + if (!QueryPerformanceCounter(¤tTime)) + { + throw ref new Platform::FailureException(); + } + + uint64 timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency.QuadPart; + + uint32 lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast<int64>(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast<uint64>(m_qpcFrequency.QuadPart)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency.QuadPart; + } + } + + private: + // Source timing data uses QPC units. + LARGE_INTEGER m_qpcFrequency; + LARGE_INTEGER m_qpcLastTime; + uint64 m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64 m_elapsedTicks; + uint64 m_totalTicks; + uint64 m_leftOverTicks; + + // Members for tracking the framerate. + uint32 m_frameCount; + uint32 m_framesPerSecond; + uint32 m_framesThisSecond; + uint64 m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64 m_targetElapsedTicks; + }; +} diff --git a/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.cpp b/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.cpp new file mode 100644 index 0000000..ea19b7c --- /dev/null +++ b/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.cpp @@ -0,0 +1,209 @@ +/* Copyright 2015-2016 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch2.h" +#include "UnityEmulatorAppMain.h" +#include "DirectXHelper.h" +#include "StringTools.h" +#include "Errors.h" + +using namespace UnityEmulatorApp; +using namespace Windows::Foundation; +using namespace Windows::System::Threading; +using namespace Concurrency; +using namespace Diligent; + +// The DirectX 12 Application template is documented at http://go.microsoft.com/fwlink/?LinkID=613670&clcid=0x409 + +HMODULE UnityEmulatorAppMain::m_DLLHandle; +UnityEmulatorAppMain::TUnityPluginLoad UnityEmulatorAppMain::UnityPluginLoad; +UnityEmulatorAppMain::TUnityPluginUnload UnityEmulatorAppMain::UnityPluginUnload; +UnityEmulatorAppMain::TGetRenderEventFunc UnityEmulatorAppMain::GetRenderEventFunc; +UnityRenderingEvent UnityEmulatorAppMain::RenderEventFunc; + +void* UnityEmulatorAppMain::LoadPluginFunction(const char* FunctionName) +{ + auto Func = GetProcAddress(m_DLLHandle, FunctionName); + VERIFY( Func != nullptr, "Failed to import plugin function \"", FunctionName, "\"." ); + return Func; +} + + +bool UnityEmulatorAppMain::LoadPlugin(const char* LibPath) +{ + auto wLibPath = WidenString(LibPath); + m_DLLHandle = LoadPackagedLibrary( wLibPath.c_str(), 0); + if( m_DLLHandle == NULL ) + { + LOG_ERROR_MESSAGE( "Failed to load ", LibPath, " library." ); + return false; + } + + UnityPluginLoad = reinterpret_cast<TUnityPluginLoad>( GetProcAddress(m_DLLHandle, "UnityPluginLoad") ); + UnityPluginUnload = reinterpret_cast<TUnityPluginUnload>( GetProcAddress(m_DLLHandle, "UnityPluginUnload") ); + GetRenderEventFunc = reinterpret_cast<TGetRenderEventFunc>( GetProcAddress(m_DLLHandle, "GetRenderEventFunc") ); + if( UnityPluginLoad == nullptr || UnityPluginUnload == nullptr || GetRenderEventFunc == nullptr ) + { + LOG_ERROR_MESSAGE( "Failed to import plugin functions from ", LibPath, " library." ); + FreeLibrary( m_DLLHandle ); + return false; + } + + return true; +} + + +// Loads and initializes application assets when the application is loaded. +UnityEmulatorAppMain::UnityEmulatorAppMain() : + m_scene(CreateScene()) +{ +#if defined(PLATFORM_UNIVERSAL_WINDOWS) + FileSystem::SetWorkingDirectory("assets"); +#endif + + std::string LibName = "Assets\\"; + LibName.append(m_scene->GetPluginName()); + +#if _WIN64 +# if _M_ARM >= 7 + LibName += "_arm"; +# else + LibName += "_64"; +# endif +#else +# if _M_ARM >= 7 + LibName += "_arm"; +# else + LibName += "_32"; +# endif +#endif + +#ifdef _DEBUG + LibName += "d"; +#else + LibName += "r"; +#endif + + LibName.append(".dll"); + if (!LoadPlugin(LibName.c_str())) + throw std::runtime_error("Failed to load plugin"); + + m_scene->OnPluginLoad(LoadPluginFunction); + + // TODO: Change the timer settings if you want something other than the default variable timestep mode. + // e.g. for 60 FPS fixed timestep update logic, call: + m_timer.SetFixedTimeStep(true); + m_timer.SetTargetElapsedSeconds(1.0 / 60); +} + +void UnityEmulatorAppMain::UnloadPlugin() +{ + m_deviceResources->GetUnityGraphicsEmulator()->InvokeDeviceEventCallback(kUnityGfxDeviceEventShutdown); + UnityPluginUnload(); + FreeLibrary(m_DLLHandle); + m_DLLHandle = NULL; +} + + +UnityEmulatorAppMain::~UnityEmulatorAppMain() +{ + m_scene->OnPluginUnload(); + m_scene.reset(); + UnloadPlugin(); +} + +// Creates and initializes the renderers. +void UnityEmulatorAppMain::CreateRenderers(const std::shared_ptr<DX::DeviceResources>& deviceResources) +{ + m_deviceResources = deviceResources; + m_scene->SetDiligentGraphicsAdapter(m_deviceResources->GetDiligentGraphicsAdapter()); + m_scene->OnGraphicsInitialized(); + m_deviceResources->SetResourceStateTransitionHandler(m_scene->GetStateTransitionHandler()); + UnityPluginLoad(&m_deviceResources->GetUnityGraphicsEmulator()->GeUnityInterfaces()); + RenderEventFunc = GetRenderEventFunc(); + + OnWindowSizeChanged(); +} + +// Updates the application state once per frame. +void UnityEmulatorAppMain::Update() +{ + // Update scene objects. + m_timer.Tick([&]() + { + + }); +} + +// Renders the current frame according to the current application state. +// Returns true if the frame was rendered and is ready to be displayed. +bool UnityEmulatorAppMain::Render() +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return false; + } + + float CurrTime = static_cast<float>(m_timer.GetTotalSeconds()); + float ElapsedTime = static_cast<float>(m_timer.GetElapsedSeconds()); + m_scene->Render(RenderEventFunc, CurrTime, ElapsedTime); + + return true; +} + +// Updates application state when the window's size changes (e.g. device orientation change) +void UnityEmulatorAppMain::OnWindowSizeChanged() +{ + auto Size = m_deviceResources->GetOutputSize(); + m_scene->OnWindowResize(static_cast<int>(Size.Width), static_cast<int>(Size.Height)); +} + +// Notifies the app that it is being suspended. +void UnityEmulatorAppMain::OnSuspending() +{ + // TODO: Replace this with your app's suspending logic. + + // Process lifetime management may terminate suspended apps at any time, so it is + // good practice to save any state that will allow the app to restart where it left off. + + //m_sceneRenderer->SaveState(); + + // If your application uses video memory allocations that are easy to re-create, + // consider releasing that memory to make it available to other applications. +} + +// Notifes the app that it is no longer suspended. +void UnityEmulatorAppMain::OnResuming() +{ + // TODO: Replace this with your app's resuming logic. +} + +// Notifies renderers that device resources need to be released. +void UnityEmulatorAppMain::OnDeviceRemoved() +{ + // TODO: Save any necessary application or renderer state and release the renderer + // and its resources which are no longer valid. + //m_sceneRenderer->SaveState(); + //m_pSample = nullptr; +} diff --git a/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.h b/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.h new file mode 100644 index 0000000..e722907 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.h @@ -0,0 +1,70 @@ + +/* Copyright 2015-2016 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +#include "StepTimer.h" +#include "DeviceResources.h" +#include "UnitySceneBase.h" +#include "IUnityInterface.h" + +namespace UnityEmulatorApp +{ + class UnityEmulatorAppMain + { + public: + UnityEmulatorAppMain(); + ~UnityEmulatorAppMain(); + void CreateRenderers(const std::shared_ptr<DX::DeviceResources>& deviceResources); + void Update(); + bool Render(); + + void OnWindowSizeChanged(); + void OnSuspending(); + void OnResuming(); + void OnDeviceRemoved(); + + private: + using TUnityPluginLoad = void (UNITY_INTERFACE_API *)(IUnityInterfaces* unityInterfaces); + using TUnityPluginUnload = void (UNITY_INTERFACE_API *)(); + using TGetRenderEventFunc = UnityRenderingEvent(UNITY_INTERFACE_API *)(); + + static HMODULE m_DLLHandle; + static TUnityPluginLoad UnityPluginLoad; + static TUnityPluginUnload UnityPluginUnload; + static TGetRenderEventFunc GetRenderEventFunc; + static UnityRenderingEvent RenderEventFunc; + static void* LoadPluginFunction(const char* FunctionName); + + static bool LoadPlugin(const char* LibName); + void UnloadPlugin(); + + // Cached pointer to device resources. + std::shared_ptr<DX::DeviceResources> m_deviceResources; + std::unique_ptr<UnitySceneBase> m_scene; + + // Rendering loop timer. + DX::StepTimer m_timer; + }; +} diff --git a/unityplugin/UnityEmulator/src/UWP/pch2.h b/unityplugin/UnityEmulator/src/UWP/pch2.h new file mode 100644 index 0000000..b90e80e --- /dev/null +++ b/unityplugin/UnityEmulator/src/UWP/pch2.h @@ -0,0 +1,20 @@ +#pragma once + +#define NOMINIMAX + +#include <wrl.h> +#include <wrl/client.h> +#include <dxgi1_4.h> +#include <d3d12.h> +#include <d3d11.h> +#include <pix.h> +#include <DirectXColors.h> +#include <DirectXMath.h> +#include <memory> +#include <vector> +#include <agile.h> +#include <concrt.h> + +#if defined(_DEBUG) +#include <dxgidebug.h> +#endif diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Emulator.cpp b/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Emulator.cpp new file mode 100644 index 0000000..f6dc7e2 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Emulator.cpp @@ -0,0 +1,370 @@ + +#include <stdexcept> + +#include "UnityGraphicsD3D11Impl.h" + +#include "UnityGraphicsD3D11Emulator.h" +#include "IUnityGraphicsD3D11.h" +#include "DebugUtilities.h" +#include "Errors.h" + + +#if defined(_DEBUG) +// Check for SDK Layer support. +inline bool SdkLayersAvailable() +{ + HRESULT hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. + 0, + D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. + nullptr, // Any feature level will do. + 0, + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + nullptr, // No need to keep the D3D device reference. + nullptr, // No need to know the feature level. + nullptr // No need to keep the D3D device context reference. + ); + + return SUCCEEDED(hr); +} +#endif + +void UnityGraphicsD3D11Impl::CreateDeviceAndContext() +{ + // This flag adds support for surfaces with a different color channel ordering + // than the API default. It is required for compatibility with Direct2D. + // D3D11_CREATE_DEVICE_BGRA_SUPPORT; + UINT creationFlags = 0; + +#if defined(_DEBUG) + if (SdkLayersAvailable()) + { + // If the project is in a debug build, enable debugging via SDK Layers with this flag. + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; + } +#endif + + // This array defines the set of DirectX hardware feature levels this app will support. + // Note the ordering should be preserved. + // Don't forget to declare your application's minimum required feature level in its + // description. All applications are assumed to support 9.1 unless otherwise stated. + D3D_FEATURE_LEVEL featureLevels[] = + { +#ifdef PLATFORM_UNIVERSAL_WINDOWS + D3D_FEATURE_LEVEL_11_1, +#endif + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1 + }; + + // Create the Direct3D 11 API device object and a corresponding context. + D3D_FEATURE_LEVEL d3dFeatureLevel = D3D_FEATURE_LEVEL_11_0; + HRESULT hr = D3D11CreateDevice( + nullptr, // Specify nullptr to use the default adapter. + D3D_DRIVER_TYPE_HARDWARE, // Create a device using the hardware graphics driver. + 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE. + creationFlags, // Set debug and Direct2D compatibility flags. + featureLevels, // List of feature levels this app can support. + ARRAYSIZE(featureLevels), // Size of the list above. + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + &m_d3d11Device, // Returns the Direct3D device created. + &d3dFeatureLevel, // Returns feature level of device created. + &m_d3d11Context // Returns the device immediate context. + ); + + if (FAILED(hr)) + { + // If the initialization fails, fall back to the WARP device. + // For more information on WARP, see: + // http://go.microsoft.com/fwlink/?LinkId=286690 + hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device. + 0, + creationFlags, + featureLevels, + ARRAYSIZE(featureLevels), + D3D11_SDK_VERSION, + &m_d3d11Device, + &d3dFeatureLevel, + &m_d3d11Context + ); + throw std::runtime_error("Failed to create D3D11 native device and immediate context"); + return; + } +} + +void UnityGraphicsD3D11Impl::CreateSwapChain(void* pNativeWndHandle, unsigned int Width, unsigned int Height) +{ + m_BackBufferWidth = 0; + m_BackBufferHeight = 0; + +#ifdef PLATFORM_WIN32 + auto hWnd = reinterpret_cast<HWND>(pNativeWndHandle); + RECT rc; + GetClientRect( hWnd, &rc ); + VERIFY_EXPR(Width = rc.right - rc.left); + VERIFY_EXPR(Height = rc.bottom - rc.top); +#endif + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = m_BackBufferWidth = Width; + swapChainDesc.Height = m_BackBufferHeight = Height; + // Flip model swapchains (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD) only support the following Formats: + // - DXGI_FORMAT_R16G16B16A16_FLOAT + // - DXGI_FORMAT_B8G8R8A8_UNORM + // - DXGI_FORMAT_R8G8B8A8_UNORM + // - DXGI_FORMAT_R10G10B10A2_UNORM + // If RGBA8_UNORM_SRGB swap chain is required, we will create RGBA8_UNORM swap chain, but + // create RGBA8_UNORM_SRGB render target view + swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = 2; + swapChainDesc.Scaling = DXGI_SCALING_NONE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Not used + swapChainDesc.Flags = 0; + + CComPtr<IDXGISwapChain1> pSwapChain1; + +#if defined( PLATFORM_WIN32 ) + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + CComPtr<IDXGIDevice> pDXGIDevice; + m_d3d11Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>( static_cast<IDXGIDevice**>(&pDXGIDevice) ) ); + CComPtr<IDXGIAdapter> pDXGIAdapter; + pDXGIDevice->GetAdapter(&pDXGIAdapter); + CComPtr<IDXGIFactory2> pDXGIFactory; + pDXGIAdapter->GetParent(__uuidof(pDXGIFactory), reinterpret_cast<void**>( static_cast<IDXGIFactory2**>(&pDXGIFactory) )); + + auto hr = pDXGIFactory->CreateSwapChainForHwnd(m_d3d11Device, hWnd, &swapChainDesc, nullptr, nullptr, &pSwapChain1); + if(FAILED(hr)) + throw std::runtime_error( "Failed to create DXGI swap chain" ); + +#elif defined( PLATFORM_UNIVERSAL_WINDOWS ) + + CComPtr<IDXGIDevice3> pDXGIDevice; + m_d3d11Device->QueryInterface(__uuidof(IDXGIDevice3), reinterpret_cast<void**>(static_cast<IDXGIDevice3**>(&pDXGIDevice))); + CComPtr<IDXGIAdapter> pDXGIAdapter; + pDXGIDevice->GetAdapter(&pDXGIAdapter); + CComPtr<IDXGIFactory2> pDXGIFactory; + pDXGIAdapter->GetParent(__uuidof(pDXGIFactory), reinterpret_cast<void**>(static_cast<IDXGIFactory2**>(&pDXGIFactory))); + + HRESULT hr = pDXGIFactory->CreateSwapChainForCoreWindow( + m_d3d11Device, + reinterpret_cast<IUnknown*>(pNativeWndHandle), + &swapChainDesc, + nullptr, + &pSwapChain1); + if(FAILED(hr)) + throw std::runtime_error( "Failed to create DXGI swap chain" ); + + // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and + // ensures that the application will only render after each VSync, minimizing power consumption. + pDXGIDevice->SetMaximumFrameLatency( 1 ); + +#endif + + pSwapChain1->QueryInterface( __uuidof(m_SwapChain), reinterpret_cast<void**>(static_cast<IDXGISwapChain**>(&m_SwapChain)) ); + + CreateRTVandDSV(); +} + +void UnityGraphicsD3D11Impl::CreateRTVandDSV() +{ + m_BackBufferRTV.Release(); + m_DepthBufferDSV.Release(); + + // Create a render target view + CComPtr<ID3D11Texture2D> pBackBuffer; + auto hr = m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(static_cast<ID3D11Texture2D**>(&pBackBuffer))); + VERIFY_EXPR(SUCCEEDED(hr)); + + D3D11_RENDER_TARGET_VIEW_DESC RTVDesc = {}; + RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + // We need to explicitly specify RTV format, as we may need to create RGBA8_UNORM_SRGB RTV for + // a RGBA8_UNORM swap chain + RTVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + RTVDesc.Texture2D.MipSlice = 0; + hr = m_d3d11Device->CreateRenderTargetView(pBackBuffer, &RTVDesc, &m_BackBufferRTV); + VERIFY_EXPR(SUCCEEDED(hr)); + + DXGI_SWAP_CHAIN_DESC SwapChainDesc; + m_SwapChain->GetDesc(&SwapChainDesc); + // Create depth buffer + D3D11_TEXTURE2D_DESC DepthBufferDesc; + DepthBufferDesc.Width = m_BackBufferWidth; + DepthBufferDesc.Height = m_BackBufferHeight; + DepthBufferDesc.MipLevels = 1; + DepthBufferDesc.ArraySize = 1; + auto DepthFormat = DXGI_FORMAT_D32_FLOAT; + DepthBufferDesc.Format = DepthFormat; + DepthBufferDesc.SampleDesc.Count = 1; + DepthBufferDesc.SampleDesc.Quality = 0; + DepthBufferDesc.Usage = D3D11_USAGE_DEFAULT; + DepthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + DepthBufferDesc.CPUAccessFlags = 0; + DepthBufferDesc.MiscFlags = 0; + CComPtr<ID3D11Texture2D> ptex2DDepthBuffer; + hr = m_d3d11Device->CreateTexture2D(&DepthBufferDesc, NULL, &ptex2DDepthBuffer); + VERIFY_EXPR(SUCCEEDED(hr)); + + // Create DSV + m_d3d11Device->CreateDepthStencilView(ptex2DDepthBuffer, NULL, &m_DepthBufferDSV); + VERIFY_EXPR(SUCCEEDED(hr)); + + ID3D11RenderTargetView *DefaultRTV[] = { GetRTV() }; + m_d3d11Context->OMSetRenderTargets(1, DefaultRTV, GetDSV()); +} + + +void UnityGraphicsD3D11Impl::Present() +{ + UINT SyncInterval = 1; // 0 +#ifdef PLATFORM_UNIVERSAL_WINDOWS + SyncInterval = 1; // Interval 0 is not supported on Windows Phone +#endif + + ID3D11RenderTargetView *NullTRV[] = { nullptr }; + m_d3d11Context->OMSetRenderTargets(1, NullTRV, nullptr); + + m_SwapChain->Present( SyncInterval, 0 ); + // A successful Present call for DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL SwapChains unbinds + // backbuffer 0 from all GPU writeable bind points. + // We need to rebind all render targets to make sure that + // the back buffer is not unbound +} + +void UnityGraphicsD3D11Impl::ResizeSwapChain( UINT NewWidth, UINT NewHeight ) +{ + if (NewWidth == 0 || NewHeight == 0) + return; + + ID3D11RenderTargetView *NullTRV[] = { nullptr }; + m_d3d11Context->OMSetRenderTargets(1, NullTRV, nullptr); + // Swap chain cannot be resized until all references are released + m_BackBufferRTV.Release(); + m_DepthBufferDSV.Release(); + try + { + m_BackBufferWidth = NewWidth; + m_BackBufferHeight = NewHeight; + DXGI_SWAP_CHAIN_DESC SCDes; + memset( &SCDes, 0, sizeof( SCDes ) ); + m_SwapChain->GetDesc( &SCDes ); + auto hr = m_SwapChain->ResizeBuffers(SCDes.BufferCount, m_BackBufferWidth, m_BackBufferHeight, SCDes.BufferDesc.Format, + SCDes.Flags); + if(FAILED(hr)) + throw std::runtime_error("Failed to resize the DXGI swap chain"); + + + CreateRTVandDSV(); + } + catch( const std::runtime_error & ) + { + LOG_ERROR( "Failed to resize the swap chain" ); + } +} + + +std::unique_ptr<UnityGraphicsD3D11Impl> UnityGraphicsD3D11Emulator::m_GraphicsImpl; + +UnityGraphicsD3D11Emulator::UnityGraphicsD3D11Emulator() +{ + VERIFY(!m_GraphicsImpl, "Another emulator has already been initialized"); + m_GraphicsImpl.reset( new UnityGraphicsD3D11Impl ); + GeUnityInterfaces().RegisterInterface(IUnityGraphicsD3D11_GUID, GetUnityGraphicsAPIInterface()); +} + +UnityGraphicsD3D11Emulator& UnityGraphicsD3D11Emulator::GetInstance() +{ + static UnityGraphicsD3D11Emulator TheInstance; + return TheInstance; +} + +void UnityGraphicsD3D11Emulator::CreateD3D11DeviceAndContext() +{ + m_GraphicsImpl->CreateDeviceAndContext(); +} + +void UnityGraphicsD3D11Emulator::CreateSwapChain(void *pNativeWndHandle, unsigned int Width, unsigned int Height) +{ + m_GraphicsImpl->CreateSwapChain(pNativeWndHandle, Width, Height); +} + +void UnityGraphicsD3D11Emulator::Present() +{ + m_GraphicsImpl->Present(); +} + +void UnityGraphicsD3D11Emulator::Release() +{ + m_GraphicsImpl.reset(); +} + +void UnityGraphicsD3D11Emulator::ResizeSwapChain(unsigned int Width, unsigned int Height) +{ + m_GraphicsImpl->ResizeSwapChain(Width, Height); +} + +bool UnityGraphicsD3D11Emulator::SwapChainInitialized() +{ + return m_GraphicsImpl->GetSwapChain() != nullptr; +} + +void* UnityGraphicsD3D11Emulator::GetD3D11Device() +{ + return m_GraphicsImpl->GetD3D11Device(); +} + +static ID3D11Device* UNITY_INTERFACE_API UnityGraphicsD3D11_GetDevice() +{ + auto *GraphicsImpl = UnityGraphicsD3D11Emulator::GetGraphicsImpl(); + return GraphicsImpl != nullptr ? GraphicsImpl->GetD3D11Device() : nullptr; +} + +UnityGraphicsD3D11Impl* UnityGraphicsD3D11Emulator::GetGraphicsImpl() +{ + return m_GraphicsImpl.get(); +} + +IUnityInterface* UnityGraphicsD3D11Emulator::GetUnityGraphicsAPIInterface() +{ + static IUnityGraphicsD3D11 UnityGraphicsD3D11; + UnityGraphicsD3D11.GetDevice = UnityGraphicsD3D11_GetDevice; + return &UnityGraphicsD3D11; +} + +UnityGfxRenderer UnityGraphicsD3D11Emulator::GetUnityGfxRenderer() +{ + return kUnityGfxRendererD3D11; +} + +void UnityGraphicsD3D11Emulator::BeginFrame() +{ + auto d3d11Ctx = m_GraphicsImpl->GetD3D11Context(); + ID3D11RenderTargetView *DefaultRTV[] = { m_GraphicsImpl->GetRTV() }; + d3d11Ctx->OMSetRenderTargets(1, DefaultRTV, m_GraphicsImpl->GetDSV()); + D3D11_VIEWPORT Viewport; + Viewport.TopLeftX = 0; + Viewport.TopLeftY = 0; + Viewport.Width = static_cast<float>( m_GraphicsImpl->GetBackBufferWidth() ); + Viewport.Height = static_cast<float>( m_GraphicsImpl->GetBackBufferHeight() ); + Viewport.MinDepth = 0; + Viewport.MaxDepth = 1; + d3d11Ctx->RSSetViewports(1, &Viewport); + float ClearColor[] = { 0, 0, 0.5f, 1 }; + d3d11Ctx->ClearRenderTargetView(DefaultRTV[0], ClearColor); + d3d11Ctx->ClearDepthStencilView(m_GraphicsImpl->GetDSV(), D3D11_CLEAR_DEPTH, UsesReverseZ() ? 0.f : 1.f, 0); +} + +void UnityGraphicsD3D11Emulator::EndFrame() +{ +} diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Impl.h b/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Impl.h new file mode 100644 index 0000000..183522f --- /dev/null +++ b/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Impl.h @@ -0,0 +1,39 @@ +#pragma once + +#if defined(PLATFORM_WIN32) + #include <d3d11.h> +#elif defined(PLATFORM_UNIVERSAL_WINDOWS) + #include <d3d11_2.h> +#endif + +#include <dxgi1_2.h> +#include <atlbase.h> + +#include <memory> + +class UnityGraphicsD3D11Impl +{ +public: + void CreateDeviceAndContext(); + void CreateSwapChain(void* pNativeWndHandle, unsigned int Width, unsigned int Height); + void CreateRTVandDSV(); + void Present(); + void ResizeSwapChain(UINT NewWidth, UINT NewHeight); + + + ID3D11Device* GetD3D11Device() { return m_d3d11Device; } + ID3D11DeviceContext* GetD3D11Context() { return m_d3d11Context; } + ID3D11RenderTargetView* GetRTV() { return m_BackBufferRTV; } + ID3D11DepthStencilView* GetDSV() { return m_DepthBufferDSV; } + UINT GetBackBufferWidth()const { return m_BackBufferWidth; } + UINT GetBackBufferHeight()const { return m_BackBufferHeight; } + IDXGISwapChain* GetSwapChain(){ return m_SwapChain; } + +private: + UINT m_BackBufferWidth = 0, m_BackBufferHeight = 0; + CComPtr<ID3D11Device> m_d3d11Device; + CComPtr<ID3D11DeviceContext> m_d3d11Context; + CComPtr<IDXGISwapChain> m_SwapChain; + CComPtr<ID3D11RenderTargetView> m_BackBufferRTV; + CComPtr<ID3D11DepthStencilView> m_DepthBufferDSV; +}; diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsD3D12Emulator.cpp b/unityplugin/UnityEmulator/src/UnityGraphicsD3D12Emulator.cpp new file mode 100644 index 0000000..45b7332 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UnityGraphicsD3D12Emulator.cpp @@ -0,0 +1,558 @@ + +#include "UnityGraphicsD3D12Impl.h" +#include "UnityGraphicsD3D12Emulator.h" +#include "IUnityGraphicsD3D12.h" +#include "DebugUtilities.h" +#include "Errors.h" + +UnityGraphicsD3D12Impl::UnityGraphicsD3D12Impl() : + m_WaitForGPUEventHandle( CreateEvent(nullptr, false, false, nullptr) ) +{ + VERIFY_EXPR(m_WaitForGPUEventHandle != INVALID_HANDLE_VALUE); +} + +UnityGraphicsD3D12Impl::~UnityGraphicsD3D12Impl() +{ + IdleGPU(); + CloseHandle(m_WaitForGPUEventHandle); +} + +static void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter) +{ + CComPtr<IDXGIAdapter1> adapter; + *ppAdapter = nullptr; + + for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, &adapter); ++adapterIndex) + { + DXGI_ADAPTER_DESC1 desc; + adapter->GetDesc1(&desc); + + if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) + { + // Don't select the Basic Render Driver adapter. + // If you want a software adapter, pass in "/warp" on the command line. + continue; + } + + // Check to see if the adapter supports Direct3D 12, but don't create the + // actual device yet. + if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) + { + break; + } + } + + *ppAdapter = adapter.Detach(); +} + + +void UnityGraphicsD3D12Impl::CreateDeviceAndCommandQueue() +{ +#if defined(_DEBUG) + // Enable the D3D12 debug layer. + { + CComPtr<ID3D12Debug> debugController; + if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(debugController), reinterpret_cast<void**>(static_cast<ID3D12Debug**>(&debugController)) ))) + { + debugController->EnableDebugLayer(); + } + } +#endif + + CComPtr<IDXGIFactory4> factory; + HRESULT hr = CreateDXGIFactory1(__uuidof(factory), reinterpret_cast<void**>(static_cast<IDXGIFactory4**>(&factory)) ); + if(FAILED(hr)) LOG_ERROR_AND_THROW("Failed to create DXGI factory") + + CComPtr<IDXGIAdapter1> hardwareAdapter; + GetHardwareAdapter(factory, &hardwareAdapter); + + hr = D3D12CreateDevice(hardwareAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(m_D3D12Device), reinterpret_cast<void**>(static_cast<ID3D12Device**>(&m_D3D12Device)) ); + if( FAILED(hr)) + { + LOG_WARNING_MESSAGE("Failed to create hardware device. Attempting to create WARP device") + + CComPtr<IDXGIAdapter> warpAdapter; + hr = factory->EnumWarpAdapter( __uuidof(warpAdapter), reinterpret_cast<void**>(static_cast<IDXGIAdapter**>(&warpAdapter)) ); + if(FAILED(hr)) LOG_ERROR_AND_THROW("Failed to enum warp adapter") + + hr = D3D12CreateDevice( warpAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(m_D3D12Device), reinterpret_cast<void**>(static_cast<ID3D12Device**>(&m_D3D12Device)) ); + if(FAILED(hr)) LOG_ERROR_AND_THROW("Failed to crate warp device") + } + +#if _DEBUG + { + CComPtr<ID3D12InfoQueue> pInfoQueue; + hr = m_D3D12Device->QueryInterface(__uuidof(pInfoQueue), reinterpret_cast<void**>(static_cast<ID3D12InfoQueue**>(&pInfoQueue))); + if( SUCCEEDED(hr) ) + { + // Suppress whole categories of messages + //D3D12_MESSAGE_CATEGORY Categories[] = {}; + + // Suppress messages based on their severity level + D3D12_MESSAGE_SEVERITY Severities[] = + { + D3D12_MESSAGE_SEVERITY_INFO + }; + + // Suppress individual messages by their ID + //D3D12_MESSAGE_ID DenyIds[] = {}; + + D3D12_INFO_QUEUE_FILTER NewFilter = {}; + //NewFilter.DenyList.NumCategories = _countof(Categories); + //NewFilter.DenyList.pCategoryList = Categories; + NewFilter.DenyList.NumSeverities = _countof(Severities); + NewFilter.DenyList.pSeverityList = Severities; + //NewFilter.DenyList.NumIDs = _countof(DenyIds); + //NewFilter.DenyList.pIDList = DenyIds; + + hr = pInfoQueue->PushStorageFilter(&NewFilter); + VERIFY(SUCCEEDED(hr), "Failed to push storage filter"); + } + } +#endif + + { + auto hr = m_D3D12Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(m_D3D12FrameFence), reinterpret_cast<void**>(static_cast<ID3D12Fence**>(&m_D3D12FrameFence))); + VERIFY(SUCCEEDED(hr), "Failed to create the fence"); + m_D3D12FrameFence->SetName(L"Completed Frame Fence fence"); + m_D3D12FrameFence->Signal(m_CompletedFenceValue); // 0 cmd lists are completed + } + +#ifndef RELEASE + // Prevent the GPU from overclocking or underclocking to get consistent timings + //d3d12Device->SetStablePowerState(TRUE); +#endif + + // Describe and create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + hr = m_D3D12Device->CreateCommandQueue(&queueDesc, __uuidof(m_D3D12CmdQueue), reinterpret_cast<void**>(static_cast<ID3D12CommandQueue**>(&m_D3D12CmdQueue))); + if(FAILED(hr)) LOG_ERROR_AND_THROW("Failed to create command queue") + + hr = m_D3D12Device->SetName(L"Main Command Queue"); + VERIFY_EXPR(SUCCEEDED(hr)); +} + +void UnityGraphicsD3D12Impl::CreateSwapChain(void* pNativeWndHandle, unsigned int Width, unsigned int Height) +{ +#ifdef PLATFORM_WIN32 + auto hWnd = reinterpret_cast<HWND>(pNativeWndHandle); + RECT rc; + GetClientRect( hWnd, &rc ); + VERIFY_EXPR(Width = rc.right - rc.left); + VERIFY_EXPR(Height = rc.bottom - rc.top); +#endif + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = m_BackBufferWidth = Width; + swapChainDesc.Height = m_BackBufferHeight = Height; + // Flip model swapchains (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD) only support the following Formats: + // - DXGI_FORMAT_R16G16B16A16_FLOAT + // - DXGI_FORMAT_B8G8R8A8_UNORM + // - DXGI_FORMAT_R8G8B8A8_UNORM + // - DXGI_FORMAT_R10G10B10A2_UNORM + // We will create RGBA8_UNORM swap chain, but RGBA8_UNORM_SRGB render target view + swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_BackBuffersCount; + swapChainDesc.Scaling = DXGI_SCALING_NONE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Not used + swapChainDesc.Flags = 0; + + CComPtr<IDXGISwapChain1> pSwapChain1; + CComPtr<IDXGIFactory4> factory; + HRESULT hr = CreateDXGIFactory1(__uuidof(factory), reinterpret_cast<void**>(static_cast<IDXGIFactory4**>(&factory)) ); + if(FAILED(hr))LOG_ERROR_AND_THROW("Failed to create DXGI factory") + +#if defined( PLATFORM_WIN32 ) + hr = factory->CreateSwapChainForHwnd(m_D3D12CmdQueue, hWnd, &swapChainDesc, nullptr, nullptr, &pSwapChain1); + if(FAILED(hr))LOG_ERROR_AND_THROW("Failed to create Swap Chain" ); + + // This sample does not support fullscreen transitions. + hr = factory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER); + +#elif defined( PLATFORM_UNIVERSAL_WINDOWS ) + + hr = factory->CreateSwapChainForCoreWindow( + m_D3D12CmdQueue, + reinterpret_cast<IUnknown*>(pNativeWndHandle), + &swapChainDesc, + nullptr, + &pSwapChain1); + if(FAILED(hr))LOG_ERROR_AND_THROW("Failed to create DXGI swap chain" ); + + // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and + // ensures that the application will only render after each VSync, minimizing power consumption. + //pDXGIDevice->SetMaximumFrameLatency( 1 ); +#endif + + pSwapChain1->QueryInterface(__uuidof(m_SwapChain), reinterpret_cast<void**>( static_cast<IDXGISwapChain3**>(&m_SwapChain) )); + + m_FrameIndex = m_SwapChain->GetCurrentBackBufferIndex(); + + InitBuffersAndViews(); +} + +void UnityGraphicsD3D12Impl::InitBuffersAndViews() +{ + // Create RTV descriptor heap + if (!m_RTVDescriptorHeap) + { + // Describe and create a render target view (RTV) descriptor heap. + D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; + rtvHeapDesc.NumDescriptors = m_BackBuffersCount; + rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + auto hr = m_D3D12Device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_RTVDescriptorHeap)); + if (FAILED(hr))LOG_ERROR_AND_THROW("Failed to create RTV descriptor heap") + + m_rtvDescriptorSize = m_D3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + } + + // Create DSV descriptor heap + if (!m_DSVDescriptorHeap) + { + D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; + rtvHeapDesc.NumDescriptors = 1; + rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + auto hr = m_D3D12Device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_DSVDescriptorHeap)); + if (FAILED(hr))LOG_ERROR_AND_THROW("Failed to create DSV descriptor heap") + } + + { + // Create render target views + D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_RTVDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + // Create a RTV for each frame. + for (UINT n = 0; n < m_BackBuffersCount; n++) + { + auto hr = m_SwapChain->GetBuffer(n, IID_PPV_ARGS(&m_RenderTargets[n])); + + D3D12_RENDER_TARGET_VIEW_DESC RTVDesc = {}; + RTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + RTVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + RTVDesc.Texture2D.MipSlice = 0; + RTVDesc.Texture2D.PlaneSlice = 0; + m_D3D12Device->CreateRenderTargetView(m_RenderTargets[n], &RTVDesc, rtvHandle); + rtvHandle.ptr += m_rtvDescriptorSize; + } + } + + // Create depth-stencil buffer + { + D3D12_HEAP_PROPERTIES HeapProps; + HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + HeapProps.CreationNodeMask = 1; + HeapProps.VisibleNodeMask = 1; + + D3D12_RESOURCE_DESC Desc = {}; + Desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + Desc.Alignment = 0; + Desc.Width = m_BackBufferWidth; + Desc.Height = m_BackBufferHeight; + Desc.DepthOrArraySize = 1; + Desc.MipLevels = 1; + Desc.Format = DXGI_FORMAT_D32_FLOAT; + Desc.SampleDesc.Count = 1; + Desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + Desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE ClearValue = {}; + ClearValue.DepthStencil.Depth = 0.f; + ClearValue.Format = Desc.Format; + auto hr = m_D3D12Device->CreateCommittedResource( &HeapProps, D3D12_HEAP_FLAG_NONE, + &Desc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &ClearValue, __uuidof(m_DepthStencilBuffer), reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&m_DepthStencilBuffer)) ); + if(FAILED(hr))LOG_ERROR_AND_THROW("Failed to create depth-stencil buffer") + + // Create depth-stencil view + D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = m_DSVDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + m_D3D12Device->CreateDepthStencilView(m_DepthStencilBuffer, nullptr, dsvHandle); + } +} + +void UnityGraphicsD3D12Impl::Present() +{ + UINT SyncInterval = 0; +#ifdef PLATFORM_UNIVERSAL_WINDOWS + SyncInterval = 1; // Interval 0 is not supported on Windows Phone +#endif + + //pImmediateCtxD3D12->Flush(); + + auto hr = m_SwapChain->Present( SyncInterval, 0 ); + VERIFY(SUCCEEDED(hr), "Present failed"); + + //auto *pDeviceD3D12 = ValidatedCast<RenderDeviceD3D12Impl>( pImmediateCtxD3D12->GetDevice() ); + //pDeviceD3D12->FinishFrame(); + m_FrameIndex = m_SwapChain->GetCurrentBackBufferIndex(); +} + +void UnityGraphicsD3D12Impl::ResizeSwapChain( UINT NewWidth, UINT NewHeight ) +{ + if (NewWidth == 0 || NewHeight == 0) + return; + + IdleGPU(); + + for (auto &rtv : m_RenderTargets) rtv.Release(); + m_DepthStencilBuffer.Release(); + + m_BackBufferWidth = NewWidth; + m_BackBufferHeight = NewHeight; + + DXGI_SWAP_CHAIN_DESC SCDes; + memset( &SCDes, 0, sizeof( SCDes ) ); + m_SwapChain->GetDesc( &SCDes ); + auto hr = m_SwapChain->ResizeBuffers(SCDes.BufferCount, NewWidth, NewHeight, SCDes.BufferDesc.Format, SCDes.Flags); + if(FAILED(hr)) + LOG_ERROR_MESSAGE("Failed to resize swap chain") + + m_FrameIndex = m_SwapChain->GetCurrentBackBufferIndex(); + + InitBuffersAndViews(); +} + +bool UnityGraphicsD3D12Emulator::SwapChainInitialized() +{ + return m_GraphicsImpl->GetSwapChain() != nullptr; +} + +void* UnityGraphicsD3D12Emulator::GetD3D12Device() +{ + return m_GraphicsImpl->GetD3D12Device(); +} + + +CComPtr<ID3D12CommandAllocator> UnityGraphicsD3D12Impl::GetCommandAllocator() +{ + if (m_CmdAllocator) + return m_CmdAllocator; + + if (!m_DiscardedAllocators.empty()) + { + auto& AllocatorPair = m_DiscardedAllocators.front(); + if ( IsFenceCompleted(AllocatorPair.first) ) + { + m_CmdAllocator = AllocatorPair.second; + auto hr = m_CmdAllocator->Reset(); + VERIFY_EXPR(SUCCEEDED(hr)); + m_DiscardedAllocators.pop_front(); + } + } + + // If no allocators were ready to be reused, create a new one + if (!m_CmdAllocator) + { + auto hr = m_D3D12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(m_CmdAllocator), reinterpret_cast<void**>(&m_CmdAllocator)); + VERIFY(SUCCEEDED(hr), "Failed to create command allocator") + m_CmdAllocator->SetName(L"UnityGraphicsD3D12Impl: cmd list allocator"); + } + + return m_CmdAllocator; +} + +void UnityGraphicsD3D12Impl::DiscardCommandAllocator() +{ + VERIFY_EXPR(m_CmdAllocator); + m_DiscardedAllocators.emplace_back( m_NextFenceValue, m_CmdAllocator ); + m_CmdAllocator.Release(); +} + +bool UnityGraphicsD3D12Impl::IsFenceCompleted(UINT64 FenceValue) +{ + m_CompletedFenceValue = m_D3D12FrameFence->GetCompletedValue(); + return FenceValue <= m_CompletedFenceValue; +} + +void UnityGraphicsD3D12Impl::IdleGPU() +{ + auto SignaledValue = m_NextFenceValue; + m_D3D12CmdQueue->Signal(m_D3D12FrameFence, SignaledValue); + ++m_NextFenceValue; + + if (m_D3D12FrameFence->GetCompletedValue() < SignaledValue) + { + // Wait for the fence + m_D3D12FrameFence->SetEventOnCompletion(SignaledValue, m_WaitForGPUEventHandle); + WaitForSingleObject(m_WaitForGPUEventHandle, INFINITE); + } +} + +UINT64 UnityGraphicsD3D12Impl::ExecuteCommandList(ID3D12CommandList *pCmdList) +{ + ID3D12CommandList *CmdLists[] = { pCmdList }; + m_D3D12CmdQueue->ExecuteCommandLists(1, CmdLists); + auto FenceValue = m_NextFenceValue; + m_D3D12CmdQueue->Signal(m_D3D12FrameFence, m_NextFenceValue++); + return FenceValue; +} + +void UnityGraphicsD3D12Impl::TransitonResourceStates(int stateCount, UnityGraphicsD3D12ResourceState* states) +{ + if (stateCount >= 0) + { + VERIFY(m_pStateTransitionHandler != nullptr, "State transition handler is not set") + m_pStateTransitionHandler->TransitionResources(stateCount, states); + } +} + + +std::unique_ptr<UnityGraphicsD3D12Impl> UnityGraphicsD3D12Emulator::m_GraphicsImpl; + +UnityGraphicsD3D12Emulator::UnityGraphicsD3D12Emulator() +{ + VERIFY(!m_GraphicsImpl, "Another emulator has already been initialized"); + m_GraphicsImpl.reset( new UnityGraphicsD3D12Impl ); + GeUnityInterfaces().RegisterInterface(IUnityGraphicsD3D12v2_GUID, GetUnityGraphicsAPIInterface()); +} + +UnityGraphicsD3D12Emulator& UnityGraphicsD3D12Emulator::GetInstance() +{ + static UnityGraphicsD3D12Emulator TheInstance; + return TheInstance; +} + +void UnityGraphicsD3D12Emulator::CreateD3D12DeviceAndCommandQueue() +{ + m_GraphicsImpl->CreateDeviceAndCommandQueue(); +} + +void UnityGraphicsD3D12Emulator::CreateSwapChain(void *pNativeWndHandle, unsigned int Width, unsigned int Height) +{ + m_GraphicsImpl->CreateSwapChain(pNativeWndHandle, Width, Height); +} + +void UnityGraphicsD3D12Emulator::SetTransitionHandler(IResourceStateTransitionHandler *pTransitionHandler) +{ + m_GraphicsImpl->SetTransitionHandler(pTransitionHandler); +} + +void UnityGraphicsD3D12Emulator::Present() +{ + m_GraphicsImpl->Present(); +} + +void UnityGraphicsD3D12Emulator::Release() +{ + m_GraphicsImpl.reset(); +} + +void UnityGraphicsD3D12Emulator::ResizeSwapChain(unsigned int Width, unsigned int Height) +{ + m_GraphicsImpl->ResizeSwapChain(Width, Height); +} + +static ID3D12Device* UNITY_INTERFACE_API UnityGraphicsD3D12_GetDevice() +{ + auto *GraphicsImpl = UnityGraphicsD3D12Emulator::GetGraphicsImpl(); + return GraphicsImpl != nullptr ? GraphicsImpl->GetD3D12Device() : nullptr; +} + +static UINT64 UNITY_INTERFACE_API UnityGraphicsD3D12_ExecuteCommandList(ID3D12GraphicsCommandList* commandList, int stateCount, UnityGraphicsD3D12ResourceState* states) +{ + auto *GraphicsImpl = UnityGraphicsD3D12Emulator::GetGraphicsImpl(); + if (GraphicsImpl != nullptr) + { + if (stateCount > 0) + GraphicsImpl->TransitonResourceStates(stateCount, states); + return GraphicsImpl->ExecuteCommandList(commandList); + } + return 0; +} + +UINT64 UNITY_INTERFACE_API UnityGraphicsD3D12_GetNextFrameFenceValue() +{ + auto *GraphicsImpl = UnityGraphicsD3D12Emulator::GetGraphicsImpl(); + return GraphicsImpl != nullptr ? GraphicsImpl->GetNextFenceValue() : 0; +} + +static ID3D12Fence* UNITY_INTERFACE_API UnityGraphicsD3D12_GetFrameFence() +{ + auto *GraphicsImpl = UnityGraphicsD3D12Emulator::GetGraphicsImpl(); + return GraphicsImpl != nullptr ? GraphicsImpl->GetFrameFence() : nullptr; +} + +UnityGraphicsD3D12Impl* UnityGraphicsD3D12Emulator::GetGraphicsImpl() +{ + return m_GraphicsImpl.get(); +} + +IUnityInterface* UnityGraphicsD3D12Emulator::GetUnityGraphicsAPIInterface() +{ + static IUnityGraphicsD3D12v2 UnityGraphicsD3D12; + UnityGraphicsD3D12.GetDevice = UnityGraphicsD3D12_GetDevice; + UnityGraphicsD3D12.ExecuteCommandList = UnityGraphicsD3D12_ExecuteCommandList; + UnityGraphicsD3D12.GetFrameFence = UnityGraphicsD3D12_GetFrameFence; + UnityGraphicsD3D12.GetNextFrameFenceValue = UnityGraphicsD3D12_GetNextFrameFenceValue; + return &UnityGraphicsD3D12; +} + +UnityGfxRenderer UnityGraphicsD3D12Emulator::GetUnityGfxRenderer() +{ + return kUnityGfxRendererD3D12; +} + +void UnityGraphicsD3D12Emulator::BeginFrame() +{ + auto Device = m_GraphicsImpl->GetD3D12Device(); + auto CmdListAllocator = m_GraphicsImpl->GetCommandAllocator(); + ID3D12GraphicsCommandList* CmdList; + auto hr = Device->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, CmdListAllocator, nullptr, __uuidof(CmdList), reinterpret_cast<void**>(&CmdList) ); + VERIFY(SUCCEEDED(hr), "Failed to create command list"); + + D3D12_CPU_DESCRIPTOR_HANDLE RTV = m_GraphicsImpl->GetRTV(); + D3D12_CPU_DESCRIPTOR_HANDLE DSV = m_GraphicsImpl->GetDSV(); + CmdList->OMSetRenderTargets(1, &RTV, FALSE, &DSV); + D3D12_VIEWPORT Viewport; + Viewport.TopLeftX = 0; + Viewport.TopLeftY = 0; + Viewport.Width = static_cast<float>( m_GraphicsImpl->GetBackBufferWidth() ); + Viewport.Height = static_cast<float>( m_GraphicsImpl->GetBackBufferHeight() ); + Viewport.MinDepth = 0; + Viewport.MaxDepth = 1; + CmdList->RSSetViewports(1, &Viewport); + float ClearColor[] = { 0, 0, 0.5f, 1 }; + D3D12_RESOURCE_BARRIER RTVBarrier = {}; + RTVBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + RTVBarrier.Transition.pResource = m_GraphicsImpl->GetCurrentBackBuffer(); + RTVBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + RTVBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + RTVBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + CmdList->ResourceBarrier(1, &RTVBarrier); + CmdList->ClearRenderTargetView(RTV, ClearColor, 0, nullptr); + CmdList->ClearDepthStencilView(DSV, D3D12_CLEAR_FLAG_DEPTH, UsesReverseZ() ? 0.f : 1.f, 0, 0, nullptr); + + CmdList->Close(); + m_GraphicsImpl->ExecuteCommandList(CmdList); + CmdList->Release(); +} + +void UnityGraphicsD3D12Emulator::EndFrame() +{ + auto CmdListAllocator = m_GraphicsImpl->GetCommandAllocator(); + ID3D12GraphicsCommandList* CmdList = nullptr; + auto Device = m_GraphicsImpl->GetD3D12Device(); + auto hr = Device->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, CmdListAllocator, nullptr, __uuidof(CmdList), reinterpret_cast<void**>(&CmdList) ); + VERIFY(SUCCEEDED(hr), "Failed to create command list"); + + D3D12_RESOURCE_BARRIER RTVBarrier = {}; + RTVBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + RTVBarrier.Transition.pResource = m_GraphicsImpl->GetCurrentBackBuffer(); + RTVBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + RTVBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + RTVBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + CmdList->ResourceBarrier(1, &RTVBarrier); + CmdList->Close(); + m_GraphicsImpl->ExecuteCommandList(CmdList); + CmdList->Release(); + + m_GraphicsImpl->DiscardCommandAllocator(); +} diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsD3D12Impl.h b/unityplugin/UnityEmulator/src/UnityGraphicsD3D12Impl.h new file mode 100644 index 0000000..df496c7 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UnityGraphicsD3D12Impl.h @@ -0,0 +1,84 @@ +#pragma once + +#include <stdexcept> +#include <deque> + +#define NOMINMAX +#include <D3D12.h> +#include <dxgi1_4.h> +#include <atlbase.h> + +#include "IUnityGraphicsD3D12.h" +#include "ResourceStateTransitionHandler.h" + +class UnityGraphicsD3D12Impl +{ +public: + + UnityGraphicsD3D12Impl(); + ~UnityGraphicsD3D12Impl(); + + void CreateDeviceAndCommandQueue(); + + void CreateSwapChain(void* pNativeWndHandle, unsigned int Width, unsigned int Height); + + void InitBuffersAndViews(); + + void Present(); + void ResizeSwapChain( UINT NewWidth, UINT NewHeight ); + + CComPtr<ID3D12CommandAllocator> GetCommandAllocator(); + + void DiscardCommandAllocator(); + + bool IsFenceCompleted(UINT64 FenceValue); + + void IdleGPU(); + + IDXGISwapChain3* GetDXGISwapChain() { return m_SwapChain; } + ID3D12Resource* GetDepthBuffer() { return m_DepthStencilBuffer; } + ID3D12Device* GetD3D12Device() { return m_D3D12Device; } + ID3D12CommandQueue* GetCommandQueue() { return m_D3D12CmdQueue; } + ID3D12Fence* GetFrameFence() { return m_D3D12FrameFence; } + ID3D12Resource *GetCurrentBackBuffer() { return m_RenderTargets[m_FrameIndex]; } + UINT GetCurrentBackBufferIndex() { return m_FrameIndex; } + + UINT GetBackBufferWidth()const { return m_BackBufferWidth; } + UINT GetBackBufferHeight()const { return m_BackBufferHeight; } + D3D12_CPU_DESCRIPTOR_HANDLE GetDSV() { return m_DSVDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); } + D3D12_CPU_DESCRIPTOR_HANDLE GetRTV() + { + auto RTVHandle = m_RTVDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + RTVHandle.ptr += m_rtvDescriptorSize * m_FrameIndex; + return RTVHandle; + } + UINT64 GetNextFenceValue() { return m_NextFenceValue; } + UINT64 GetCompletedFenceValue() { return m_D3D12FrameFence->GetCompletedValue(); } + UINT64 ExecuteCommandList(ID3D12CommandList *pCmdList); + void SetTransitionHandler(IResourceStateTransitionHandler *pTransitionHandler) { m_pStateTransitionHandler = pTransitionHandler; } + void TransitonResourceStates(int stateCount, UnityGraphicsD3D12ResourceState* states); + IDXGISwapChain3* GetSwapChain(){ return m_SwapChain; } + +private: + + UINT m_BackBufferWidth, m_BackBufferHeight; + static const UINT m_BackBuffersCount = 3; + + UINT m_FrameIndex = 0; + CComPtr<ID3D12Device> m_D3D12Device; + CComPtr<ID3D12CommandQueue> m_D3D12CmdQueue; + CComPtr<IDXGISwapChain3> m_SwapChain; + CComPtr<ID3D12Fence> m_D3D12FrameFence; + UINT64 m_NextFenceValue = 1; + UINT64 m_CompletedFenceValue = 0; + UINT m_rtvDescriptorSize; + CComPtr<ID3D12DescriptorHeap> m_RTVDescriptorHeap; + CComPtr<ID3D12DescriptorHeap> m_DSVDescriptorHeap; + CComPtr<ID3D12Resource> m_RenderTargets[m_BackBuffersCount]; + CComPtr<ID3D12Resource> m_DepthStencilBuffer; + CComPtr<ID3D12CommandAllocator> m_CmdAllocator; + HANDLE m_WaitForGPUEventHandle = {}; + + std::deque< std::pair<UINT64, CComPtr<ID3D12CommandAllocator> > > m_DiscardedAllocators; + IResourceStateTransitionHandler *m_pStateTransitionHandler = nullptr; +}; diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsEmulator.cpp b/unityplugin/UnityEmulator/src/UnityGraphicsEmulator.cpp new file mode 100644 index 0000000..cb21cfb --- /dev/null +++ b/unityplugin/UnityEmulator/src/UnityGraphicsEmulator.cpp @@ -0,0 +1,90 @@ +#include "UnityGraphicsEmulator.h" +#include "DebugUtilities.h" +#include "IUnityGraphics.h" + +UnityGraphicsEmulator *UnityGraphicsEmulator::m_Instance = nullptr; + +UnityGfxRenderer UNITY_INTERFACE_API GetUnityRenderer() +{ + return UnityGraphicsEmulator::GetInstance().GetUnityGfxRenderer(); +} + +void UNITY_INTERFACE_API RegisterUnityDeviceEventCallback(IUnityGraphicsDeviceEventCallback callback) +{ + UnityGraphicsEmulator::GetInstance().RegisterDeviceEventCallback(callback); +} + +void UNITY_INTERFACE_API UnregisterUnityDeviceEventCallback(IUnityGraphicsDeviceEventCallback callback) +{ + UnityGraphicsEmulator::GetInstance().UnregisterDeviceEventCallback(callback); +} + +void UnityGraphicsEmulator::RegisterDeviceEventCallback(IUnityGraphicsDeviceEventCallback callback) +{ + m_DeviceEventCallbacks.emplace_back(callback); +} + +void UnityGraphicsEmulator::UnregisterDeviceEventCallback(IUnityGraphicsDeviceEventCallback callback) +{ + size_t i = 0; + while (i < m_DeviceEventCallbacks.size()) + { + if (m_DeviceEventCallbacks[i] == callback) + m_DeviceEventCallbacks.erase(m_DeviceEventCallbacks.begin() + i); + else + ++i; + } +} + +void UnityGraphicsEmulator::InvokeDeviceEventCallback(UnityGfxDeviceEventType eventType) +{ + for (auto callback : m_DeviceEventCallbacks) + (*callback)(eventType); +} + +//static void Get +UnityGraphicsEmulator::UnityGraphicsEmulator() +{ + VERIFY(m_Instance == nullptr, "Only single instance of UnityGraphicsEmulator must be initialized") + m_Instance = this; + static IUnityGraphics UnityGraphics; + UnityGraphics.GetRenderer = GetUnityRenderer; + UnityGraphics.RegisterDeviceEventCallback = RegisterUnityDeviceEventCallback; + UnityGraphics.UnregisterDeviceEventCallback = UnregisterUnityDeviceEventCallback; + RegisterInterface(IUnityGraphics_GUID, &UnityGraphics); +} + +static IUnityInterface* UNITY_INTERFACE_API GetUnityInterface(UnityInterfaceGUID guid) +{ + return UnityGraphicsEmulator::GetInstance().GetInterface(guid); +} + +static void UNITY_INTERFACE_API RegisterUnityInterface(UnityInterfaceGUID guid, IUnityInterface* ptr) +{ + return UnityGraphicsEmulator::GetInstance().RegisterInterface(guid, ptr); +} + +void UnityGraphicsEmulator::RegisterInterface(const UnityInterfaceGUID &guid, IUnityInterface* ptr) +{ + m_Interfaces.emplace_back(guid, ptr); +} + +IUnityInterface* UnityGraphicsEmulator::GetInterface(const UnityInterfaceGUID &guid) +{ + for (auto &ifaces : m_Interfaces) + { + if (ifaces.first == guid) + return ifaces.second; + } + return nullptr; +} + + +IUnityInterfaces &UnityGraphicsEmulator::GeUnityInterfaces() +{ + static IUnityInterfaces UnityInterfaces; + UnityInterfaces.GetInterface = GetUnityInterface; + UnityInterfaces.RegisterInterface = RegisterUnityInterface; + + return UnityInterfaces; +} diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsGLCoreES_Emulator.cpp b/unityplugin/UnityEmulator/src/UnityGraphicsGLCoreES_Emulator.cpp new file mode 100644 index 0000000..5047b32 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UnityGraphicsGLCoreES_Emulator.cpp @@ -0,0 +1,87 @@ +#include "UnityGraphicsGL_Impl.h" + +#include "UnityGraphicsGLCoreES_Emulator.h" + +#if OPENGL_SUPPORTED + +#include "DebugUtilities.h" +#include "Errors.h" + +std::unique_ptr<UnityGraphicsGL_Impl> UnityGraphicsGLCoreES_Emulator::m_GraphicsImpl; + +UnityGraphicsGLCoreES_Emulator::UnityGraphicsGLCoreES_Emulator() +{ + VERIFY(!m_GraphicsImpl, "Another emulator has already been initialized"); + m_GraphicsImpl.reset( new UnityGraphicsGL_Impl ); + //GeUnityInterfaces().RegisterInterface(IUnityGraphicsGLCoreES__GUID, GetUnityGraphicsAPIInterface()); +} + +void UnityGraphicsGLCoreES_Emulator::InitGLContext(void *pNativeWndHandle, int MajorVersion, int MinorVersion) +{ + m_GraphicsImpl->InitGLContext(pNativeWndHandle, MajorVersion, MinorVersion); +} + +UnityGraphicsGLCoreES_Emulator& UnityGraphicsGLCoreES_Emulator::GetInstance() +{ + static UnityGraphicsGLCoreES_Emulator TheInstance; + return TheInstance; +} + +void UnityGraphicsGLCoreES_Emulator::Present() +{ + m_GraphicsImpl->SwapBuffers(); +} + +void UnityGraphicsGLCoreES_Emulator::Release() +{ + m_GraphicsImpl.reset(); +} + +void UnityGraphicsGLCoreES_Emulator::ResizeSwapChain(unsigned int Width, unsigned int Height) +{ + m_GraphicsImpl->ResizeSwapchain(Width, Height); +} + +bool UnityGraphicsGLCoreES_Emulator::SwapChainInitialized() +{ + return m_GraphicsImpl->GetContext() != NULL; +} + + +UnityGraphicsGL_Impl* UnityGraphicsGLCoreES_Emulator::GetGraphicsImpl() +{ + return m_GraphicsImpl.get(); +} + +IUnityInterface* UnityGraphicsGLCoreES_Emulator::GetUnityGraphicsAPIInterface() +{ + return nullptr; +} + +UnityGfxRenderer UnityGraphicsGLCoreES_Emulator::GetUnityGfxRenderer() +{ + return kUnityGfxRendererOpenGLCore; +} + +void UnityGraphicsGLCoreES_Emulator::BeginFrame() +{ + glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 ); + glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 ); + glClearDepthf( UsesReverseZ() ? 0.f : 1.f ); + static const float ClearColor[4] = { 0, 0, 0.5f, 1 }; + glClearColor(ClearColor[0], ClearColor[1], ClearColor[2], ClearColor[3]); + glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDisable( GL_SCISSOR_TEST ); + glViewport(0, 0, m_GraphicsImpl->GetBackBufferWidth(), m_GraphicsImpl->GetBackBufferHeight() ); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glDepthRangef( 0, 1 ); + auto err = glGetError(); + if( err != GL_NO_ERROR) + LOG_ERROR_MESSAGE("GL Error: ", err) +} + +void UnityGraphicsGLCoreES_Emulator::EndFrame() +{ +} + +#endif // OPENGL_SUPPORTED
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.cpp b/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.cpp new file mode 100644 index 0000000..7a3d8c2 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.cpp @@ -0,0 +1,189 @@ + +#include "UnityGraphicsGLCore_Impl.h" + +#if OPENGL_SUPPORTED + +#include "DebugUtilities.h" +#include "Errors.h" + +void APIENTRY openglCallbackFunction( GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam ) +{ + std::stringstream MessageSS; + + MessageSS << std::endl << "OPENGL DEBUG MESSAGE: " << message << std::endl; + MessageSS << "Type: "; + switch( type ) { + case GL_DEBUG_TYPE_ERROR: + MessageSS << "ERROR"; + break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + MessageSS << "DEPRECATED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + MessageSS << "UNDEFINED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_PORTABILITY: + MessageSS << "PORTABILITY"; + break; + case GL_DEBUG_TYPE_PERFORMANCE: + MessageSS << "PERFORMANCE"; + break; + case GL_DEBUG_TYPE_OTHER: + MessageSS << "OTHER"; + break; + } + MessageSS << std::endl; + + MessageSS << "Severity: "; + switch( severity ){ + case GL_DEBUG_SEVERITY_LOW: + MessageSS << "LOW"; + break; + case GL_DEBUG_SEVERITY_MEDIUM: + MessageSS << "MEDIUM"; + break; + case GL_DEBUG_SEVERITY_HIGH: + MessageSS << "HIGH"; + break; + } + MessageSS << std::endl; + + //MessageSS << "Id: "<< id << std::endl; + + OutputDebugStringA( MessageSS.str().c_str() ); +} + + +UnityGraphicsGLCore_Impl::~UnityGraphicsGLCore_Impl() +{ + if( m_Context ) + { + wglMakeCurrent( m_WindowHandleToDeviceContext, 0 ); + wglDeleteContext( m_Context ); + } +} + +void UnityGraphicsGLCore_Impl::InitGLContext(void *pNativeWndHandle, int MajorVersion, int MinorVersion ) +{ + HWND hWnd = reinterpret_cast<HWND>(pNativeWndHandle); + RECT rc; + GetClientRect( hWnd, &rc ); + m_BackBufferWidth = rc.right - rc.left; + m_BackBufferHeight = rc.bottom - rc.top; + + // See http://www.opengl.org/wiki/Tutorial:_OpenGL_3.1_The_First_Triangle_(C%2B%2B/Win) + // http://www.opengl.org/wiki/Creating_an_OpenGL_Context_(WGL) + PIXELFORMATDESCRIPTOR pfd; + memset( &pfd, 0, sizeof( PIXELFORMATDESCRIPTOR ) ); + pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR ); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 32; + pfd.cDepthBits = 32; + pfd.iLayerType = PFD_MAIN_PLANE; + + m_WindowHandleToDeviceContext = GetDC( hWnd ); + int nPixelFormat = ChoosePixelFormat( m_WindowHandleToDeviceContext, &pfd ); + + if( nPixelFormat == 0 ) + LOG_ERROR_AND_THROW( "Invalid Pixel Format" ); + + BOOL bResult = SetPixelFormat( m_WindowHandleToDeviceContext, nPixelFormat, &pfd ); + if( !bResult ) + LOG_ERROR_AND_THROW( "Failed to set Pixel Format" ); + + // Create standard OpenGL (2.1) rendering context which will be used only temporarily, + HGLRC tempContext = wglCreateContext( m_WindowHandleToDeviceContext ); + // and make it current + wglMakeCurrent( m_WindowHandleToDeviceContext, tempContext ); + + // Initialize GLEW + GLenum err = glewInit(); + if( GLEW_OK != err ) + LOG_ERROR_AND_THROW( "Failed to initialize GLEW" ); + + if( wglewIsSupported( "WGL_ARB_create_context" ) == 1 ) + { + // Setup attributes for a new OpenGL rendering context + int attribs[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, MajorVersion, + WGL_CONTEXT_MINOR_VERSION_ARB, MinorVersion, + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + GL_CONTEXT_PROFILE_MASK, GL_CONTEXT_CORE_PROFILE_BIT, + 0, 0 + }; + +#ifdef _DEBUG + attribs[5] |= WGL_CONTEXT_DEBUG_BIT_ARB; +#endif + + // Create new rendering context + // In order to create new OpenGL rendering context we have to call function wglCreateContextAttribsARB(), + // which is an OpenGL function and requires OpenGL to be active when it is called. + // The only way is to create an old context, activate it, and while it is active create a new one. + // Very inconsistent, but we have to live with it! + m_Context = wglCreateContextAttribsARB( m_WindowHandleToDeviceContext, 0, attribs ); + + // Delete tempContext + wglMakeCurrent( NULL, NULL ); + wglDeleteContext( tempContext ); + // + wglMakeCurrent( m_WindowHandleToDeviceContext, m_Context ); + wglSwapIntervalEXT( 0 ); + } + else + { //It's not possible to make a GL 3.x context. Use the old style context (GL 2.1 and before) + m_Context = tempContext; + } + + //Checking GL version + const GLubyte *GLVersionString = glGetString( GL_VERSION ); + + //Or better yet, use the GL3 way to get the version number + glGetIntegerv( GL_MAJOR_VERSION, &MajorVersion ); + glGetIntegerv( GL_MINOR_VERSION, &MinorVersion ); + LOG_INFO_MESSAGE("Initialized OpenGL ", MajorVersion, '.', MinorVersion, " context") + + if( glDebugMessageCallback ) + { + glEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS ); + glDebugMessageCallback( openglCallbackFunction, nullptr ); + GLuint unusedIds = 0; + glDebugMessageControl( GL_DONT_CARE, + GL_DONT_CARE, + GL_DONT_CARE, + 0, + &unusedIds, + true ); + } + + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + if( glGetError() != GL_NO_ERROR ) + LOG_ERROR_MESSAGE("Failed to enable seamless cubemap filtering"); + + glEnable(GL_FRAMEBUFFER_SRGB); + if( glGetError() != GL_NO_ERROR ) + LOG_ERROR_MESSAGE("Failed to enable SRGB framebuffers"); +} + +void UnityGraphicsGLCore_Impl::ResizeSwapchain(int NewWidth, int NewHeight) +{ + m_BackBufferWidth = NewWidth; + m_BackBufferHeight = NewHeight; + // Nothing more needs to be done in GL +} + +void UnityGraphicsGLCore_Impl::SwapBuffers() +{ + ::SwapBuffers( m_WindowHandleToDeviceContext ); +} + +#endif // OPENGL_SUPPORTED
\ No newline at end of file diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.h b/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.h new file mode 100644 index 0000000..d1bd531 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UnityGraphicsGLCore_Impl.h @@ -0,0 +1,37 @@ +#pragma once + +#include "PlatformDefinitions.h" + +#if OPENGL_SUPPORTED + +#define GLEW_STATIC +#include "glew.h" +#define NOMINMAX +#include "wglew.h" +#include <GL/GL.h> + +class UnityGraphicsGLCore_Impl +{ +public: + ~UnityGraphicsGLCore_Impl(); + + void InitGLContext(void *pNativeWndHandle, int MajorVersion, int MinorVersion); + + void ResizeSwapchain(int NewWidth, int NewHeight); + + void SwapBuffers(); + + int GetBackBufferWidth()const { return m_BackBufferWidth; } + int GetBackBufferHeight()const { return m_BackBufferHeight; } + GLenum GetBackBufferFormat()const { return GL_RGBA8; } + GLenum GetDepthBufferFormat()const { return GL_DEPTH_COMPONENT32F; } + HGLRC GetContext() { return m_Context; } + +private: + int m_BackBufferWidth = 0; + int m_BackBufferHeight = 0; + HDC m_WindowHandleToDeviceContext; + HGLRC m_Context; +}; + +#endif //OPENGL_SUPPORTED diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsGL_Impl.h b/unityplugin/UnityEmulator/src/UnityGraphicsGL_Impl.h new file mode 100644 index 0000000..b9f5105 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UnityGraphicsGL_Impl.h @@ -0,0 +1,11 @@ +#pragma once + +#include "PlatformDefinitions.h" + +#if defined(PLATFORM_ANDROID) +# include "Android\UnityGraphicsGLESAndroid_Impl.h" +#elif defined( PLATFORM_WIN32 ) || defined( PLATFORM_UNIVERSAL_WINDOWS ) +# include "UnityGraphicsGLCore_Impl.h" +#else +# error Unknown Platform +#endif diff --git a/unityplugin/UnityEmulator/src/Windows/WinMain.cpp b/unityplugin/UnityEmulator/src/Windows/WinMain.cpp new file mode 100644 index 0000000..9d3ea78 --- /dev/null +++ b/unityplugin/UnityEmulator/src/Windows/WinMain.cpp @@ -0,0 +1,344 @@ +/* Copyright 2015-2017 Egor Yusov + * + * 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include <memory> +#include <iomanip> + +#define NOMINMAX +#include <Windows.h> + +#include "DeviceCaps.h" +#include "Errors.h" +#include "Timer.h" + +#include "IUnityInterface.h" +#include "UnityGraphicsD3D11Emulator.h" +#include "UnityGraphicsD3D12Emulator.h" +#include "UnityGraphicsGLCoreES_Emulator.h" +#include "DiligentGraphicsAdapterD3D11.h" +#include "DiligentGraphicsAdapterD3D12.h" +#include "DiligentGraphicsAdapterGL.h" +#include "UnitySceneBase.h" +#include "StringTools.h" + +using namespace Diligent; + +LRESULT CALLBACK MessageProc(HWND, UINT, WPARAM, LPARAM); + +UnityGraphicsEmulator *g_GraphicsEmulator = nullptr; + +typedef void (UNITY_INTERFACE_API *TUnityPluginLoad)(IUnityInterfaces* unityInterfaces); +typedef void (UNITY_INTERFACE_API *TUnityPluginUnload)(); +typedef UnityRenderingEvent(UNITY_INTERFACE_API *TGetRenderEventFunc)(); + +TUnityPluginLoad UnityPluginLoad; +TUnityPluginUnload UnityPluginUnload; +TGetRenderEventFunc GetRenderEventFunc; + +std::unique_ptr<DiligentGraphicsAdapter> g_pDiligentGraphics; +std::unique_ptr<UnitySceneBase> g_pScene; + +HMODULE g_DLLHandle; + +static UINT g_WindowWidth = 1024; +static UINT g_WindowHeight = 768; + +static void* LoadPluginFunction(const char* FunctionName) +{ + auto Func = GetProcAddress(g_DLLHandle, FunctionName); + VERIFY( Func != nullptr, "Failed to import plugin function \"", FunctionName, "\"." ); + return Func; +} + +bool LoadPlugin() +{ + std::string LibName = g_pScene->GetPluginName(); +#if _WIN64 + LibName += "_64"; +#else + LibName += "_32"; +#endif + +#ifdef _DEBUG + LibName += "d"; +#else + LibName += "r"; +#endif + + LibName += ".dll"; + g_DLLHandle = LoadLibraryA( LibName.c_str() ); + if( g_DLLHandle == NULL ) + { + LOG_ERROR_MESSAGE( "Failed to load ", LibName, " library." ); + return false; + } + + UnityPluginLoad = reinterpret_cast<TUnityPluginLoad>( GetProcAddress(g_DLLHandle, "UnityPluginLoad") ); + UnityPluginUnload = reinterpret_cast<TUnityPluginUnload>( GetProcAddress(g_DLLHandle, "UnityPluginUnload") ); + GetRenderEventFunc = reinterpret_cast<TGetRenderEventFunc>( GetProcAddress(g_DLLHandle, "GetRenderEventFunc") ); + if( UnityPluginLoad == nullptr || UnityPluginUnload == nullptr || GetRenderEventFunc == nullptr ) + { + LOG_ERROR_MESSAGE( "Failed to import plugin functions from ", LibName, " library." ); + FreeLibrary( g_DLLHandle ); + return false; + } + + return true; +} + + +void UnloadPlugin() +{ + g_GraphicsEmulator->InvokeDeviceEventCallback(kUnityGfxDeviceEventShutdown); + UnityPluginUnload(); + FreeLibrary(g_DLLHandle); +} + +// Main +int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int cmdShow) +{ +#if defined(_DEBUG) || defined(DEBUG) + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); +#endif + + g_pScene.reset(CreateScene()); + + std::wstring Title = WidenString(g_pScene->GetSceneName()); + + DeviceType DevType = DeviceType::Undefined; + std::wstring CmdLine = GetCommandLine(); + std::wstring Key = L"mode="; + auto pos = CmdLine.find( Key ); + if( pos != std::string::npos ) + { + pos += Key.length(); + auto Val = CmdLine.substr( pos ); + if(Val == L"D3D11") + { + DevType = DeviceType::D3D11; + Title.append( L" (D3D11)" ); + } + else if(Val == L"D3D12") + { + DevType = DeviceType::D3D12; + Title.append( L" (D3D12)" ); + } + else if(Val == L"GL") + { + DevType = DeviceType::OpenGL; + Title.append( L" (OpenGL)" ); + } + else + { + LOG_ERROR("Unknown device type. Only the following types are supported: D3D11, D3D12, GL") + return -1; + } + } + else + { + LOG_INFO_MESSAGE("Device type is not specified. Using D3D11 device"); + DevType = DeviceType::D3D11; + Title.append( L" (D3D11)" ); + } + // Register our window class + WNDCLASSEX wcex = { sizeof(WNDCLASSEX), CS_HREDRAW|CS_VREDRAW, MessageProc, + 0L, 0L, instance, NULL, NULL, NULL, NULL, L"SampleApp", NULL }; + RegisterClassEx(&wcex); + + // Create a window + UINT ClientAreaWidth = 1280; + UINT ClientAreaHeight = 1024; + RECT rc = { 0, 0, static_cast<LONG>(ClientAreaWidth), static_cast<LONG>(ClientAreaHeight) }; + AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); + HWND wnd = CreateWindow(L"SampleApp", Title.c_str(), + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, + rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, instance, NULL); + if (!wnd) + { + MessageBox(NULL, L"Cannot create window", L"Error", MB_OK|MB_ICONERROR); + return -1; + } + ShowWindow(wnd, cmdShow); + UpdateWindow(wnd); + + bool IsDX = false; + try + { + switch (DevType) + { + case DeviceType::D3D11: + { + auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); + GraphicsD3D11Emulator.CreateD3D11DeviceAndContext(); + GraphicsD3D11Emulator.CreateSwapChain(wnd, ClientAreaWidth, ClientAreaHeight); + g_GraphicsEmulator = &GraphicsD3D11Emulator; + IsDX = true; + auto *pDiligentAdapterD3D11 = new DiligentGraphicsAdapterD3D11(GraphicsD3D11Emulator); + g_pDiligentGraphics.reset(pDiligentAdapterD3D11); + pDiligentAdapterD3D11->InitProxySwapChain(); + } + break; + + case DeviceType::D3D12: + { + auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); + GraphicsD3D12Emulator.CreateD3D12DeviceAndCommandQueue(); + GraphicsD3D12Emulator.CreateSwapChain(wnd, ClientAreaWidth, ClientAreaHeight); + g_GraphicsEmulator = &GraphicsD3D12Emulator; + IsDX = true; + auto *pDiligentAdapterD3D12 = new DiligentGraphicsAdapterD3D12(GraphicsD3D12Emulator); + g_pDiligentGraphics.reset(pDiligentAdapterD3D12); + pDiligentAdapterD3D12->InitProxySwapChain(); + } + break; + + case DeviceType::OpenGL: + { + auto &GraphicsGLCoreES_Emulator = UnityGraphicsGLCoreES_Emulator::GetInstance(); + GraphicsGLCoreES_Emulator.InitGLContext(wnd, 4, 4); + g_GraphicsEmulator = &GraphicsGLCoreES_Emulator; + g_pDiligentGraphics.reset(new DiligentGraphicsAdapterGL(GraphicsGLCoreES_Emulator)); + } + break; + + default: + LOG_ERROR("Unsupported device type"); + return -1; + } + } + catch (std::runtime_error &err) + { + LOG_ERROR("Failed to initialize unity graphics emulator: ", err.what()); + return -1; + } + + g_pScene->SetDiligentGraphicsAdapter(g_pDiligentGraphics.get()); + g_pScene->OnGraphicsInitialized(); + if (DevType == DeviceType::D3D12) + { + UnityGraphicsD3D12Emulator::GetInstance().SetTransitionHandler(g_pScene->GetStateTransitionHandler()); + } + + if (!LoadPlugin()) + { + return -1; + } + + g_pScene->OnPluginLoad(LoadPluginFunction); + UnityPluginLoad(&g_GraphicsEmulator->GeUnityInterfaces()); + + auto RenderEventFunc = GetRenderEventFunc(); + + Timer timer; + auto PrevTime = timer.GetElapsedTime(); + double filteredFrameTime = 0.0; + + // Main message loop + MSG msg = {0}; + while (WM_QUIT != msg.message) + { + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + else + { + g_GraphicsEmulator->BeginFrame(); + g_pDiligentGraphics->BeginFrame(); + + auto CurrTime = timer.GetElapsedTime(); + auto ElapsedTime = CurrTime - PrevTime; + PrevTime = CurrTime; + float fTime = static_cast<float>(CurrTime); + + g_pScene->Render(RenderEventFunc, CurrTime, ElapsedTime); + + g_pDiligentGraphics->EndFrame(); + g_GraphicsEmulator->EndFrame(); + + g_GraphicsEmulator->Present(); + + double filterScale = 0.2; + filteredFrameTime = filteredFrameTime * (1.0 - filterScale) + filterScale * ElapsedTime; + std::wstringstream fpsCounterSS; + fpsCounterSS << " - " << std::fixed << std::setprecision(1) << filteredFrameTime * 1000; + fpsCounterSS << " ms (" << 1.0 / filteredFrameTime << " fps)"; + SetWindowText(wnd, (Title + fpsCounterSS.str()).c_str()); + } + } + + g_pScene->OnPluginUnload(); + g_pScene.reset(); + UnloadPlugin(); + + g_pDiligentGraphics.reset(); + g_GraphicsEmulator->Release(); + + return (int)msg.wParam; +} + +// Called every time the application receives a message +LRESULT CALLBACK MessageProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + // Send event message to AntTweakBar + switch (message) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(wnd, &ps); + EndPaint(wnd, &ps); + return 0; + } + case WM_SIZE: // Window size has been changed + if(g_GraphicsEmulator) + { + g_WindowWidth = LOWORD(lParam); + g_WindowHeight = HIWORD(lParam); + g_pDiligentGraphics->PreSwapChainResize(); + g_GraphicsEmulator->ResizeSwapChain(g_WindowWidth, g_WindowHeight); + g_pDiligentGraphics->PostSwapChainResize(); + g_pScene->OnWindowResize(g_WindowWidth, g_WindowHeight); + } + return 0; + case WM_CHAR: + if (wParam == VK_ESCAPE) + PostQuitMessage(0); + return 0; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + default: + { + struct WindowMessageData + { + HWND hWnd; + UINT message; + WPARAM wParam; + LPARAM lParam; + }msg{wnd, message, wParam, lParam}; + return DefWindowProc(wnd, message, wParam, lParam); + } + } +} |
