summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-03-08 10:01:20 -0800
committerGitHub <noreply@github.com>2021-03-08 10:01:20 -0800
commitfc9968dc4fd58fab37476f48e4405c2743c5349c (patch)
tree6119b293a5a5cc24401dde5ff54287beb28fe63b
parent95ca93938f5d45f4eaf340867965bd77a1724d6c (diff)
Refactor window library. (#1739)
* Refactor window library. * Fix project file * Fix warnings.
-rw-r--r--build/visual-studio/core/core.vcxproj1
-rw-r--r--build/visual-studio/core/core.vcxproj.filters3
-rw-r--r--build/visual-studio/cpu-hello-world/cpu-hello-world.vcxproj2
-rw-r--r--build/visual-studio/gpu-printing/gpu-printing.vcxproj2
-rw-r--r--build/visual-studio/hello-world/hello-world.vcxproj2
-rw-r--r--build/visual-studio/platform/platform.vcxproj176
-rw-r--r--build/visual-studio/platform/platform.vcxproj.filters39
-rw-r--r--build/visual-studio/render-test-tool/render-test-tool.vcxproj10
-rw-r--r--build/visual-studio/shader-object/shader-object.vcxproj2
-rw-r--r--build/visual-studio/shader-toy/shader-toy.vcxproj2
-rw-r--r--examples/gpu-printing/main.cpp22
-rw-r--r--examples/hello-world/main.cpp37
-rw-r--r--examples/shader-toy/main.cpp82
-rw-r--r--premake5.lua16
-rw-r--r--slang.sln2
-rw-r--r--source/core/slang-func-ptr.h202
-rw-r--r--tools/graphics-app-framework/gui.h31
-rw-r--r--tools/graphics-app-framework/window.h133
-rw-r--r--tools/graphics-app-framework/windows/win-window.cpp416
-rw-r--r--tools/platform/gui.cpp (renamed from tools/graphics-app-framework/gui.cpp)8
-rw-r--r--tools/platform/gui.h34
-rw-r--r--tools/platform/model.cpp (renamed from tools/graphics-app-framework/model.cpp)2
-rw-r--r--tools/platform/model.h (renamed from tools/graphics-app-framework/model.h)0
-rw-r--r--tools/platform/performance-counter.h30
-rw-r--r--tools/platform/vector-math.h (renamed from tools/graphics-app-framework/vector-math.h)0
-rw-r--r--tools/platform/window.h235
-rw-r--r--tools/platform/windows/win-window.cpp442
27 files changed, 1235 insertions, 696 deletions
diff --git a/build/visual-studio/core/core.vcxproj b/build/visual-studio/core/core.vcxproj
index 01a7e3eb2..38bcf2ade 100644
--- a/build/visual-studio/core/core.vcxproj
+++ b/build/visual-studio/core/core.vcxproj
@@ -185,6 +185,7 @@
<ClInclude Include="..\..\..\source\core\slang-downstream-compiler.h" />
<ClInclude Include="..\..\..\source\core\slang-exception.h" />
<ClInclude Include="..\..\..\source\core\slang-free-list.h" />
+ <ClInclude Include="..\..\..\source\core\slang-func-ptr.h" />
<ClInclude Include="..\..\..\source\core\slang-gcc-compiler-util.h" />
<ClInclude Include="..\..\..\source\core\slang-hash.h" />
<ClInclude Include="..\..\..\source\core\slang-hex-dump-util.h" />
diff --git a/build/visual-studio/core/core.vcxproj.filters b/build/visual-studio/core/core.vcxproj.filters
index 3c2a7371d..9c718a6fb 100644
--- a/build/visual-studio/core/core.vcxproj.filters
+++ b/build/visual-studio/core/core.vcxproj.filters
@@ -54,6 +54,9 @@
<ClInclude Include="..\..\..\source\core\slang-free-list.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\core\slang-func-ptr.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\core\slang-gcc-compiler-util.h">
<Filter>Header Files</Filter>
</ClInclude>
diff --git a/build/visual-studio/cpu-hello-world/cpu-hello-world.vcxproj b/build/visual-studio/cpu-hello-world/cpu-hello-world.vcxproj
index 2fb93b42c..0ba5973d0 100644
--- a/build/visual-studio/cpu-hello-world/cpu-hello-world.vcxproj
+++ b/build/visual-studio/cpu-hello-world/cpu-hello-world.vcxproj
@@ -180,7 +180,7 @@
<ProjectReference Include="..\gfx-util\gfx-util.vcxproj">
<Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project>
</ProjectReference>
- <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj">
+ <ProjectReference Include="..\platform\platform.vcxproj">
<Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project>
</ProjectReference>
</ItemGroup>
diff --git a/build/visual-studio/gpu-printing/gpu-printing.vcxproj b/build/visual-studio/gpu-printing/gpu-printing.vcxproj
index f7b783f39..b55e289d1 100644
--- a/build/visual-studio/gpu-printing/gpu-printing.vcxproj
+++ b/build/visual-studio/gpu-printing/gpu-printing.vcxproj
@@ -186,7 +186,7 @@
<ProjectReference Include="..\gfx-util\gfx-util.vcxproj">
<Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project>
</ProjectReference>
- <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj">
+ <ProjectReference Include="..\platform\platform.vcxproj">
<Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project>
</ProjectReference>
</ItemGroup>
diff --git a/build/visual-studio/hello-world/hello-world.vcxproj b/build/visual-studio/hello-world/hello-world.vcxproj
index a7a51362b..28f8d1425 100644
--- a/build/visual-studio/hello-world/hello-world.vcxproj
+++ b/build/visual-studio/hello-world/hello-world.vcxproj
@@ -180,7 +180,7 @@
<ProjectReference Include="..\gfx-util\gfx-util.vcxproj">
<Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project>
</ProjectReference>
- <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj">
+ <ProjectReference Include="..\platform\platform.vcxproj">
<Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project>
</ProjectReference>
</ItemGroup>
diff --git a/build/visual-studio/platform/platform.vcxproj b/build/visual-studio/platform/platform.vcxproj
new file mode 100644
index 000000000..518ac20f7
--- /dev/null
+++ b/build/visual-studio/platform/platform.vcxproj
@@ -0,0 +1,176 @@
+<?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|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</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>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</ProjectGuid>
+ <IgnoreWarnCompileDuplicatedFilename>true</IgnoreWarnCompileDuplicatedFilename>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>platform</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </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" />
+ </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" />
+ </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" />
+ </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" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>..\..\..\bin\windows-x86\debug\</OutDir>
+ <IntDir>..\..\..\intermediate\windows-x86\debug\platform\</IntDir>
+ <TargetName>platform</TargetName>
+ <TargetExt>.lib</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>..\..\..\bin\windows-x64\debug\</OutDir>
+ <IntDir>..\..\..\intermediate\windows-x64\debug\platform\</IntDir>
+ <TargetName>platform</TargetName>
+ <TargetExt>.lib</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>..\..\..\bin\windows-x86\release\</OutDir>
+ <IntDir>..\..\..\intermediate\windows-x86\release\platform\</IntDir>
+ <TargetName>platform</TargetName>
+ <TargetExt>.lib</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>..\..\..\bin\windows-x64\release\</OutDir>
+ <IntDir>..\..\..\intermediate\windows-x64\release\platform\</IntDir>
+ <TargetName>platform</TargetName>
+ <TargetExt>.lib</TargetExt>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Optimization>Full</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Optimization>Full</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\tools\platform\gui.h" />
+ <ClInclude Include="..\..\..\tools\platform\model.h" />
+ <ClInclude Include="..\..\..\tools\platform\performance-counter.h" />
+ <ClInclude Include="..\..\..\tools\platform\vector-math.h" />
+ <ClInclude Include="..\..\..\tools\platform\window.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\tools\platform\gui.cpp" />
+ <ClCompile Include="..\..\..\tools\platform\model.cpp" />
+ <ClCompile Include="..\..\..\tools\platform\windows\win-window.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/build/visual-studio/platform/platform.vcxproj.filters b/build/visual-studio/platform/platform.vcxproj.filters
new file mode 100644
index 000000000..17d756451
--- /dev/null
+++ b/build/visual-studio/platform/platform.vcxproj.filters
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{21EB8090-0D4E-1035-B6D3-48EBA215DCB7}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{E9C7FDCE-D52A-8D73-7EB0-C5296AF258F6}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\tools\platform\gui.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\tools\platform\model.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\tools\platform\performance-counter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\tools\platform\vector-math.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\tools\platform\window.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\tools\platform\gui.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\tools\platform\model.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\tools\platform\windows\win-window.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/build/visual-studio/render-test-tool/render-test-tool.vcxproj b/build/visual-studio/render-test-tool/render-test-tool.vcxproj
index 0ce5b5361..8cca49a83 100644
--- a/build/visual-studio/render-test-tool/render-test-tool.vcxproj
+++ b/build/visual-studio/render-test-tool/render-test-tool.vcxproj
@@ -99,7 +99,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_DEBUG;SLANG_SHARED_LIBRARY_TOOL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\graphics-app-framework;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\platform;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -118,7 +118,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_DEBUG;SLANG_SHARED_LIBRARY_TOOL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\graphics-app-framework;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\platform;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -137,7 +137,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>NDEBUG;SLANG_SHARED_LIBRARY_TOOL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\graphics-app-framework;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\platform;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
@@ -160,7 +160,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>NDEBUG;SLANG_SHARED_LIBRARY_TOOL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\graphics-app-framework;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\platform;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
@@ -210,7 +210,7 @@
<ProjectReference Include="..\gfx-util\gfx-util.vcxproj">
<Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project>
</ProjectReference>
- <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj">
+ <ProjectReference Include="..\platform\platform.vcxproj">
<Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project>
</ProjectReference>
</ItemGroup>
diff --git a/build/visual-studio/shader-object/shader-object.vcxproj b/build/visual-studio/shader-object/shader-object.vcxproj
index 1af67af5b..04315f910 100644
--- a/build/visual-studio/shader-object/shader-object.vcxproj
+++ b/build/visual-studio/shader-object/shader-object.vcxproj
@@ -180,7 +180,7 @@
<ProjectReference Include="..\gfx-util\gfx-util.vcxproj">
<Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project>
</ProjectReference>
- <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj">
+ <ProjectReference Include="..\platform\platform.vcxproj">
<Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project>
</ProjectReference>
</ItemGroup>
diff --git a/build/visual-studio/shader-toy/shader-toy.vcxproj b/build/visual-studio/shader-toy/shader-toy.vcxproj
index 9fd7014a3..823841a46 100644
--- a/build/visual-studio/shader-toy/shader-toy.vcxproj
+++ b/build/visual-studio/shader-toy/shader-toy.vcxproj
@@ -181,7 +181,7 @@
<ProjectReference Include="..\gfx-util\gfx-util.vcxproj">
<Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project>
</ProjectReference>
- <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj">
+ <ProjectReference Include="..\platform\platform.vcxproj">
<Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project>
</ProjectReference>
</ItemGroup>
diff --git a/examples/gpu-printing/main.cpp b/examples/gpu-printing/main.cpp
index 63eb31a82..e95233571 100644
--- a/examples/gpu-printing/main.cpp
+++ b/examples/gpu-printing/main.cpp
@@ -6,7 +6,7 @@
using Slang::ComPtr;
#include "slang-gfx.h"
-#include "tools/graphics-app-framework/window.h"
+#include "tools/platform/window.h"
#include "source/core/slang-basic.h"
using namespace gfx;
@@ -44,7 +44,7 @@ ComPtr<slang::IModule> compileShaderModuleFromFile(slang::ISession* slangSession
const SlangResult compileRes = spCompile(slangRequest);
if(auto diagnostics = spGetDiagnosticOutput(slangRequest))
{
- reportError("%s", diagnostics);
+ printf("%s", diagnostics);
}
if(SLANG_FAILED(compileRes))
@@ -63,7 +63,6 @@ struct ExampleProgram
int gWindowWidth = 640;
int gWindowHeight = 480;
-gfx::ApplicationContext* gAppContext;
ComPtr<gfx::IRenderer> gRenderer;
ComPtr<slang::ISession> gSlangSession;
@@ -151,8 +150,6 @@ Result execute()
auto descriptorSet = gRenderer->createDescriptorSet(descriptorSetLayout, IDescriptorSet::Flag::Transient);
if(!descriptorSet) return SLANG_FAIL;
-// descriptorSet->setConstantBuffer(0, 0, gConstantBuffer);
-
gDescriptorSet = descriptorSet;
ComputePipelineStateDesc desc;
@@ -201,21 +198,12 @@ Result execute()
};
-// This "inner" main function is used by the platform abstraction
-// layer to deal with differences in how an entry point needs
-// to be defined for different platforms.
-//
-void innerMain(ApplicationContext* context)
+int main()
{
ExampleProgram app;
-
if (SLANG_FAILED(app.execute()))
{
- return exitApplication(context, 1);
+ return -1;
}
+ return 0;
}
-
-// This macro instantiates an appropriate main function to
-// invoke the `innerMain` above.
-//
-GFX_CONSOLE_MAIN(innerMain)
diff --git a/examples/hello-world/main.cpp b/examples/hello-world/main.cpp
index 47016b48d..330b52a59 100644
--- a/examples/hello-world/main.cpp
+++ b/examples/hello-world/main.cpp
@@ -34,7 +34,7 @@
//
#include "slang-gfx.h"
#include "gfx-util/shader-cursor.h"
-#include "tools/graphics-app-framework/window.h"
+#include "tools/platform/window.h"
#include "slang-com-ptr.h"
#include "source/core/slang-basic.h"
@@ -76,7 +76,7 @@ void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob)
{
if( diagnosticsBlob != nullptr )
{
- reportError("%s", (const char*) diagnosticsBlob->getBufferPointer());
+ printf("%s", (const char*) diagnosticsBlob->getBufferPointer());
}
}
@@ -210,8 +210,7 @@ const uint32_t kSwapchainImageCount = 2;
// of them come from the utility library we are using to simplify
// building an example program.
//
-gfx::ApplicationContext* gAppContext;
-gfx::Window* gWindow;
+RefPtr<platform::Window> gWindow;
Slang::ComPtr<gfx::IRenderer> gRenderer;
ComPtr<gfx::IPipelineState> gPipelineState;
@@ -230,12 +229,12 @@ Slang::Result initialize()
{
// Create a window for our application to render into.
//
- WindowDesc windowDesc;
+ platform::WindowDesc windowDesc;
windowDesc.title = "Hello, World!";
windowDesc.width = gWindowWidth;
windowDesc.height = gWindowHeight;
- gWindow = createWindow(windowDesc);
-
+ gWindow = platform::Application::createWindow(windowDesc);
+ gWindow->events.mainLoop = [this]() { renderFrame(); };
// Initialize the rendering layer.
//
// Note: for now we are hard-coding logic to use the
@@ -323,8 +322,9 @@ Slang::Result initialize()
swapchainDesc.height = gWindowHeight;
swapchainDesc.imageCount = kSwapchainImageCount;
swapchainDesc.queue = gQueue;
- gSwapchain = gRenderer->createSwapchain(
- swapchainDesc, gfx::WindowHandle::FromHwnd(getPlatformWindowHandle(gWindow)));
+ gfx::WindowHandle windowHandle;
+ memcpy(&windowHandle, &gWindow->getNativeHandle(), sizeof(windowHandle));
+ gSwapchain = gRenderer->createSwapchain(swapchainDesc, windowHandle);
IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1};
IFramebufferLayout::AttachmentLayout depthLayout = {gfx::Format::D_Float32, 1};
@@ -405,11 +405,6 @@ Slang::Result initialize()
renderPassDesc.depthStencilAccess = &depthStencilAccess;
gRenderPass = gRenderer->createRenderPassLayout(renderPassDesc);
- // Once we've initialized all the graphics API objects,
- // it is time to show our application window and start rendering.
- //
- showWindow(gWindow);
-
return SLANG_OK;
}
@@ -526,7 +521,6 @@ void finalize()
{
gQueue->wait();
gSwapchain = nullptr;
- destroyWindow(gWindow);
}
};
@@ -535,7 +529,7 @@ void finalize()
// layer to deal with differences in how an entry point needs
// to be defined for different platforms.
//
-void innerMain(ApplicationContext* context)
+int innerMain()
{
// We construct an instance of our example application
// `struct` type, and then walk through the lifecyle
@@ -545,18 +539,17 @@ void innerMain(ApplicationContext* context)
if (SLANG_FAILED(app.initialize()))
{
- return exitApplication(context, 1);
+ return -1;
}
- while(dispatchEvents(context))
- {
- app.renderFrame();
- }
+ platform::Application::run(app.gWindow);
app.finalize();
+
+ return 0;
}
// This macro instantiates an appropriate main function to
// invoke the `innerMain` above.
//
-GFX_UI_MAIN(innerMain)
+PLATFORM_UI_MAIN(innerMain)
diff --git a/examples/shader-toy/main.cpp b/examples/shader-toy/main.cpp
index 0d058fa2c..7c22954c0 100644
--- a/examples/shader-toy/main.cpp
+++ b/examples/shader-toy/main.cpp
@@ -20,9 +20,12 @@ using Slang::ComPtr;
// compiler, and API.
//
#include "slang-gfx.h"
-#include "tools/graphics-app-framework/window.h"
+#include "tools/platform/window.h"
+#include "tools/platform/performance-counter.h"
#include "source/core/slang-basic.h"
+#include <chrono>
+
using namespace gfx;
// In order to display a shader toy effect using rasterization-based shader
@@ -82,7 +85,7 @@ void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob)
{
if( diagnosticsBlob != nullptr )
{
- reportError("%s", (const char*) diagnosticsBlob->getBufferPointer());
+ printf("%s", (const char*) diagnosticsBlob->getBufferPointer());
}
}
@@ -329,8 +332,7 @@ int gWindowWidth = 1024;
int gWindowHeight = 768;
const uint32_t kSwapchainImageCount = 2;
-gfx::ApplicationContext* gAppContext;
-gfx::Window* gWindow;
+Slang::RefPtr<platform::Window> gWindow;
Slang::ComPtr<gfx::IRenderer> gRenderer;
ComPtr<gfx::IBufferResource> gConstantBuffer;
ComPtr<gfx::IPipelineLayout> gPipelineLayout;
@@ -344,13 +346,15 @@ ComPtr<gfx::ICommandQueue> gQueue;
Result initialize()
{
- WindowDesc windowDesc;
+ platform::WindowDesc windowDesc;
windowDesc.title = "Slang Shader Toy";
windowDesc.width = gWindowWidth;
windowDesc.height = gWindowHeight;
- windowDesc.eventHandler = &_handleEvent;
- windowDesc.userData = this;
- gWindow = createWindow(windowDesc);
+ gWindow = platform::Application::createWindow(windowDesc);
+ gWindow->events.mainLoop = [this]() { renderFrame(); };
+ gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { handleEvent(e); };
+ gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { handleEvent(e); };
+ gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { handleEvent(e); };
IRenderer::Desc rendererDesc;
rendererDesc.rendererType = RendererType::DirectX11;
@@ -430,8 +434,9 @@ Result initialize()
swapchainDesc.height = gWindowHeight;
swapchainDesc.imageCount = kSwapchainImageCount;
swapchainDesc.queue = gQueue;
- gSwapchain = gRenderer->createSwapchain(
- swapchainDesc, gfx::WindowHandle::FromHwnd(getPlatformWindowHandle(gWindow)));
+ gfx::WindowHandle windowHandle;
+ memcpy(&windowHandle, &gWindow->getNativeHandle(), sizeof(windowHandle));
+ gSwapchain = gRenderer->createSwapchain(swapchainDesc, windowHandle);
IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1};
IFramebufferLayout::AttachmentLayout depthLayout = {gfx::Format::D_Float32, 1};
@@ -513,9 +518,6 @@ Result initialize()
renderPassDesc.renderTargetAccess = &renderTargetAccess;
renderPassDesc.depthStencilAccess = &depthStencilAccess;
gRenderPass = gRenderer->createRenderPassLayout(renderPassDesc);
-
- showWindow(gWindow);
-
return SLANG_OK;
}
@@ -527,7 +529,7 @@ float clickMouseX = 0.0f;
float clickMouseY = 0.0f;
bool firstTime = true;
-uint64_t startTime = 0;
+platform::TimePoint startTime;
void renderFrame()
{
@@ -535,7 +537,7 @@ void renderFrame()
auto commandBuffer = gQueue->createCommandBuffer();
if( firstTime )
{
- startTime = getCurrentTime();
+ startTime = platform::PerformanceCounter::now();
firstTime = false;
}
@@ -557,7 +559,7 @@ void renderFrame()
uniforms.iMouse[1] = lastMouseY;
uniforms.iMouse[2] = isMouseDown ? clickMouseX : -clickMouseX;
uniforms.iMouse[3] = isMouseClick ? clickMouseY : -clickMouseY;
- uniforms.iTime = float( double(getCurrentTime() - startTime) / double(getTimerFrequency()) );
+ uniforms.iTime = platform::PerformanceCounter::getElapsedTimeInSeconds(startTime);
uniforms.iResolution[0] = float(gWindowWidth);
uniforms.iResolution[1] = float(gWindowHeight);
@@ -588,59 +590,31 @@ void renderFrame()
void finalize()
{
gQueue->wait();
- destroyWindow(gWindow);
-}
-
-void handleEvent(Event const& event)
-{
- switch( event.code )
- {
- case EventCode::MouseDown:
- isMouseDown = true;
- lastMouseX = event.u.mouse.x;
- lastMouseY = event.u.mouse.y;
- break;
-
- case EventCode::MouseMoved:
- lastMouseX = event.u.mouse.x;
- lastMouseY = event.u.mouse.y;
- break;
-
- case EventCode::MouseUp:
- isMouseDown = false;
- lastMouseX = event.u.mouse.x;
- lastMouseY = event.u.mouse.y;
- break;
-
- default:
- break;
- }
}
-static void _handleEvent(Event const& event)
+void handleEvent(const platform::MouseEventArgs& event)
{
- ShaderToyApp* app = (ShaderToyApp*) getUserData(event.window);
- app->handleEvent(event);
+ isMouseDown = ((int)event.buttons & (int)platform::ButtonState::Enum::LeftButton) != 0;
+ lastMouseX = (float)event.x;
+ lastMouseY = (float)event.y;
}
-
};
-void innerMain(ApplicationContext* context)
+int innerMain()
{
ShaderToyApp app;
if (SLANG_FAILED(app.initialize()))
{
- return exitApplication(context, 1);
+ return -1;
}
- while(dispatchEvents(context))
- {
- app.renderFrame();
- }
+ platform::Application::run(app.gWindow);
app.finalize();
+
+ return 0;
}
-GFX_UI_MAIN(innerMain)
+PLATFORM_UI_MAIN(innerMain)
diff --git a/premake5.lua b/premake5.lua
index e4f9b91cc..bd5c72c63 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -525,7 +525,7 @@ function example(name)
-- and the `gfx` abstraction layer (which in turn
-- depends on the `core` library). We specify all of that here,
-- rather than in each example.
- links { "slang", "core", "gfx", "gfx-util", "graphics-app-framework" }
+ links { "slang", "core", "gfx", "gfx-util", "platform" }
end
--
@@ -695,8 +695,8 @@ toolSharedLibrary "slang-reflection-test"
toolSharedLibrary "render-test"
uuid "61F7EB00-7281-4BF3-9470-7C2EA92620C3"
- includedirs { ".", "external", "source", "tools/gfx", "tools/graphics-app-framework" }
- links { "core", "slang", "gfx", "gfx-util", "graphics-app-framework" }
+ includedirs { ".", "external", "source", "tools/gfx", "tools/platform" }
+ links { "core", "slang", "gfx", "gfx-util", "platform" }
if isTargetWindows then
addSourceDir "tools/render-test/windows"
@@ -824,21 +824,21 @@ tool "gfx-util"
addSourceDir "tools/gfx-util"
--
--- `graphics-app-framework` contains all the utils for a simple graphics application.
+-- `platform` contains all the platform abstractions for a GUI application.
--
-tool "graphics-app-framework"
+tool "platform"
uuid "3565fe5e-4fa3-11eb-ae93-0242ac130002"
kind "StaticLib"
pic "On"
includedirs { ".", "external", "source", "external/imgui", "tools/gfx" }
- addSourceDir "tools/graphics-app-framework"
-
+ addSourceDir "tools/platform"
+ addSourceDir "tools/platform/linux"
+ addSourceDir "tools/platform/windows"
-- Include windowing support on Windows.
if isTargetWindows then
systemversion "10.0.14393.0"
- addSourceDir "tools/graphics-app-framework/windows"
end
--
diff --git a/slang.sln b/slang.sln
index 2021ad656..0662c00c3 100644
--- a/slang.sln
+++ b/slang.sln
@@ -47,7 +47,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gfx", "build\visual-studio\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gfx-util", "build\visual-studio\gfx-util\gfx-util.vcxproj", "{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "graphics-app-framework", "build\visual-studio\graphics-app-framework\graphics-app-framework.vcxproj", "{3565FE5E-4FA3-11EB-AE93-0242AC130002}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "platform", "build\visual-studio\platform\platform.vcxproj", "{3565FE5E-4FA3-11EB-AE93-0242AC130002}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-cpp-extractor", "build\visual-studio\slang-cpp-extractor\slang-cpp-extractor.vcxproj", "{CA8A30D1-8FA9-4330-B7F7-84709246D8DC}"
EndProject
diff --git a/source/core/slang-func-ptr.h b/source/core/slang-func-ptr.h
new file mode 100644
index 000000000..c861bc6b8
--- /dev/null
+++ b/source/core/slang-func-ptr.h
@@ -0,0 +1,202 @@
+#ifndef SLANG_CORE_FUNC_PTR_H
+#define SLANG_CORE_FUNC_PTR_H
+
+#include "slang-smart-pointer.h"
+
+namespace Slang
+{
+
+template <typename TResult, typename... Arguments> class FuncPtr : public RefObject
+{
+public:
+ virtual TResult operator()(Arguments...) const = 0;
+ virtual bool operator==(const FuncPtr<TResult, Arguments...>*) { return false; }
+ virtual FuncPtr<TResult, Arguments...>* clone() = 0;
+ virtual ~FuncPtr() {}
+};
+
+template <typename TResult, typename... Arguments>
+class CdeclFuncPtr : public FuncPtr<TResult, Arguments...>
+{
+public:
+ typedef TResult (*FuncType)(Arguments...);
+
+private:
+ FuncType funcPtr;
+
+public:
+ CdeclFuncPtr(FuncType func)
+ : funcPtr(func)
+ {}
+ virtual FuncPtr<TResult, Arguments...>* clone() override
+ {
+ auto rs = new CdeclFuncPtr<TResult, Arguments...>(funcPtr);
+ return rs;
+ }
+
+ virtual TResult operator()(Arguments... params) const override { return funcPtr(params...); }
+
+ virtual bool operator==(const FuncPtr<TResult, Arguments...>* ptr) override
+ {
+ auto cptr = dynamic_cast<const CdeclFuncPtr<TResult, Arguments...>*>(ptr);
+ if (cptr)
+ return funcPtr == cptr->funcPtr;
+ else
+ return false;
+ }
+};
+
+template <typename Class, typename TResult, typename... Arguments>
+class MemberFuncPtr : public FuncPtr<TResult, Arguments...>
+{
+public:
+ typedef TResult (Class::*FuncType)(Arguments...);
+
+private:
+ FuncType funcPtr;
+ Class* object;
+
+public:
+ MemberFuncPtr(Class* obj, FuncType func)
+ : funcPtr(func)
+ , object(obj)
+ {}
+ virtual FuncPtr<TResult, Arguments...>* clone() override
+ {
+ auto rs = new MemberFuncPtr<Class, TResult, Arguments...>(object, funcPtr);
+ return rs;
+ }
+ virtual TResult operator()(Arguments... params) const override
+ {
+ return (object->*funcPtr)(params...);
+ }
+
+ virtual bool operator==(const FuncPtr<TResult, Arguments...>* ptr) override
+ {
+ auto cptr = dynamic_cast<const MemberFuncPtr<Class, TResult, Arguments...>*>(ptr);
+ if (cptr)
+ return funcPtr == cptr->funcPtr && object == cptr->object;
+ else
+ return false;
+ }
+};
+
+template <typename F, typename TResult, typename... Arguments>
+class LambdaFuncPtr : public FuncPtr<TResult, Arguments...>
+{
+private:
+ F func;
+
+public:
+ LambdaFuncPtr(const F& _func)
+ : func(_func)
+ {}
+ virtual TResult operator()(Arguments... params) const override { return func(params...); }
+ virtual FuncPtr<TResult, Arguments...>* clone() override
+ {
+ auto rs = new LambdaFuncPtr<F, TResult, Arguments...>(func);
+ return rs;
+ }
+ virtual bool operator==(const FuncPtr<TResult, Arguments...>* /*ptr*/) override
+ {
+ return false;
+ }
+};
+
+template <typename TResult, typename... Arguments> class Func
+{
+private:
+ RefPtr<FuncPtr<TResult, Arguments...>> funcPtr;
+
+public:
+ Func() {}
+ Func(typename CdeclFuncPtr<TResult, Arguments...>::FuncType func)
+ {
+ funcPtr = new CdeclFuncPtr<TResult, Arguments...>(func);
+ }
+ template <typename Class>
+ Func(Class* object, typename MemberFuncPtr<Class, TResult, Arguments...>::FuncType func)
+ {
+ funcPtr = new MemberFuncPtr<Class, TResult, Arguments...>(object, func);
+ }
+ template <typename TFuncObj> Func(const TFuncObj& func)
+ {
+ funcPtr = new LambdaFuncPtr<TFuncObj, TResult, Arguments...>(func);
+ }
+ Func& operator=(typename CdeclFuncPtr<TResult, Arguments...>::FuncType func)
+ {
+ funcPtr = new CdeclFuncPtr<TResult, Arguments...>(func);
+ return *this;
+ }
+ template <typename Class>
+ Func& operator=(const MemberFuncPtr<Class, TResult, Arguments...>& func)
+ {
+ funcPtr = new MemberFuncPtr<Class, TResult, Arguments...>(func);
+ return *this;
+ }
+ template <typename TFuncObj> Func& operator=(const TFuncObj& func)
+ {
+ funcPtr = new LambdaFuncPtr<TFuncObj, TResult, Arguments...>(func);
+ return *this;
+ }
+ bool operator==(const Func& f) { return *funcPtr == f.funcPtr.Ptr(); }
+ bool operator!=(const Func& f) { return !(*this == f); }
+ TResult operator()(Arguments... params) const { return (*funcPtr)(params...); }
+};
+
+// template<typename... Arguments>
+// using Action = Func<void, Arguments...>;
+
+template <typename... Arguments> class Action : public Func<void, Arguments...>
+{
+private:
+ RefPtr<FuncPtr<void, Arguments...>> funcPtr;
+
+public:
+ Action() {}
+ Action(const Action& proc) { funcPtr = proc.funcPtr; }
+ Action(typename CdeclFuncPtr<void, Arguments...>::FuncType func)
+ {
+ funcPtr = new CdeclFuncPtr<void, Arguments...>(func);
+ }
+ template <typename Class>
+ Action(Class* object, typename MemberFuncPtr<Class, void, Arguments...>::FuncType func)
+ {
+ funcPtr = new MemberFuncPtr<Class, void, Arguments...>(object, func);
+ }
+ template <typename TFuncObj> Action(const TFuncObj& func)
+ {
+ funcPtr = new LambdaFuncPtr<TFuncObj, void, Arguments...>(func);
+ }
+ Action& operator=(typename CdeclFuncPtr<void, Arguments...>::FuncType func)
+ {
+ funcPtr = new CdeclFuncPtr<void, Arguments...>(func);
+ return *this;
+ }
+ template <typename Class>
+ Action& operator=(const MemberFuncPtr<Class, void, Arguments...>& func)
+ {
+ funcPtr = new MemberFuncPtr<Class, void, Arguments...>(func);
+ return *this;
+ }
+ template <typename TFuncObj> Action& operator=(const TFuncObj& func)
+ {
+ funcPtr = new LambdaFuncPtr<TFuncObj, void, Arguments...>(func);
+ return *this;
+ }
+ Action& operator=(const Action& proc)
+ {
+ funcPtr = proc.funcPtr;
+ return *this;
+ }
+ void clear() { funcPtr = nullptr; }
+ void operator()(Arguments... params) const
+ {
+ if (funcPtr)
+ (*funcPtr)(params...);
+ }
+};
+
+} // namespace Slang
+
+#endif
diff --git a/tools/graphics-app-framework/gui.h b/tools/graphics-app-framework/gui.h
deleted file mode 100644
index 680cea14b..000000000
--- a/tools/graphics-app-framework/gui.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// gui.h
-#pragma once
-
-#include "slang-gfx.h"
-#include "vector-math.h"
-#include "window.h"
-#include "slang-com-ptr.h"
-#include "external/imgui/imgui.h"
-#include "source/core/slang-basic.h"
-
-namespace gfx {
-
-struct GUI : Slang::RefObject
-{
- GUI(Window* window, IRenderer* renderer, ICommandQueue* queue, IFramebufferLayout* framebufferLayout);
- ~GUI();
-
- void beginFrame();
- void endFrame(IFramebuffer* framebuffer);
-
-private:
- Slang::ComPtr<IRenderer> renderer;
- Slang::ComPtr<ICommandQueue> queue;
- Slang::ComPtr<IRenderPassLayout> renderPass;
- Slang::ComPtr<IPipelineState> pipelineState;
- Slang::ComPtr<IDescriptorSetLayout> descriptorSetLayout;
- Slang::ComPtr<IPipelineLayout> pipelineLayout;
- Slang::ComPtr<ISamplerState> samplerState;
-};
-
-} // gfx
diff --git a/tools/graphics-app-framework/window.h b/tools/graphics-app-framework/window.h
deleted file mode 100644
index 2e216aacf..000000000
--- a/tools/graphics-app-framework/window.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// window.h
-#pragma once
-
-#include <stdint.h>
-
-namespace gfx {
-
-struct Window;
-
-enum class KeyCode
-{
- Unknown,
-
- // TODO: extend this to cover at least a standard US-English keyboard
-
- A, B, C, D, E, F, G, H, I, J,
- K, L, M, N, O, P, Q, R, S, T,
- U, V, W, X, Y, Z,
-
- Space,
-};
-
-enum class EventCode : uint32_t
-{
- MouseDown,
- MouseUp,
- MouseMoved,
- KeyDown,
- KeyUp,
-};
-
-struct Event
-{
- EventCode code;
- Window* window;
- union
- {
- struct
- {
- float x;
- float y;
- } mouse;
-
- KeyCode key;
- } u;
-};
-
-typedef void (*EventHandler)(Event const&);
-
-struct WindowDesc
-{
- char const* title = nullptr;
- void* userData = nullptr;
- int width = 0;
- int height = 0;
- EventHandler eventHandler = nullptr;
-};
-
-Window* createWindow(WindowDesc const& desc);
-void destroyWindow(Window* window);
-void showWindow(Window* window);
-
-void* getPlatformWindowHandle(Window* window);
-void* getUserData(Window* window);
-
-/// Opaque state provided by platform for a running application.
-typedef struct ApplicationContext ApplicationContext;
-
-/// User-defined application entry-point function.
-typedef void(*ApplicationFunc)(ApplicationContext* context);
-
-/// Dispatch any pending events for application.
-///
-/// @returns `true` if application should keep running.
-bool dispatchEvents(ApplicationContext* context);
-
-/// Exit the application with a given result code
-void exitApplication(ApplicationContext* context, int resultCode);
-
-/// Log a message to an appropriate logging destination.
-void log(char const* message, ...);
-
-/// Report an error to an appropriate logging destination.
-int reportError(char const* message, ...);
-
-uint64_t getCurrentTime();
-
-uint64_t getTimerFrequency();
-
-/// Run an application given the specified callback and command-line arguments.
-int runApplication(
- ApplicationFunc func,
- int argc,
- char const* const* argv);
-
-#define GFX_CONSOLE_MAIN(APPLICATION_ENTRY) \
- int main(int argc, char** argv) { \
- return gfx::runApplication(&(APPLICATION_ENTRY), argc, argv); \
- }
-
-#ifdef _WIN32
-
-int runWindowsApplication(
- ApplicationFunc func,
- void* instance,
- int showCommand);
-
-#ifdef _MSC_VER
-#ifdef _DEBUG
-# define GFX_DUMP_LEAK _CrtDumpMemoryLeaks();
-#endif
-#endif
-#ifndef GFX_DUMP_LEAK
-#define GFX_DUMP_LEAK
-#endif
-#define GFX_UI_MAIN(APPLICATION_ENTRY) \
- int __stdcall WinMain( \
- void* instance, \
- void* /* prevInstance */, \
- void* /* commandLine */, \
- int showCommand) { \
- auto result = gfx::runWindowsApplication(&(APPLICATION_ENTRY), instance, showCommand); \
- GFX_DUMP_LEAK \
- return result; \
- }
-
-#else
-
-#define GFX_UI_MAIN(APPLICATION_ENTRY) GFX_CONSOLE_MAIN(APPLICATION_ENTRY)
-
-#endif
-
-} // gfx
diff --git a/tools/graphics-app-framework/windows/win-window.cpp b/tools/graphics-app-framework/windows/win-window.cpp
deleted file mode 100644
index 2beb65d70..000000000
--- a/tools/graphics-app-framework/windows/win-window.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-// win-window.cpp
-#include "../window.h"
-
-#include "core/slang-smart-pointer.h"
-
-#include <stdio.h>
-
-#ifdef _MSC_VER
-#include <stddef.h>
-#if (_MSC_VER < 1900)
-#define snprintf sprintf_s
-#endif
-#endif
-
-#include <stdint.h>
-
-#if _WIN32
-#include <Windows.h>
-#include <Windowsx.h>
-#else
-#error "The slang-graphics library currently only supports Windows platforms"
-#endif
-
-namespace gfx {
-
-#if _WIN32
-
-struct OSString
-{
- OSString(char const* begin, char const* end)
- {
- _initialize(begin, end - begin);
- }
-
- OSString(char const* begin)
- {
- _initialize(begin, strlen(begin));
- }
-
- ~OSString()
- {
- free(mBegin);
- }
-
- operator WCHAR const*()
- {
- return mBegin;
- }
-
-private:
- WCHAR* mBegin;
- WCHAR* mEnd;
-
- void _initialize(char const* input, size_t inputSize)
- {
- const DWORD dwFlags = 0;
- int outputCodeUnitCount = ::MultiByteToWideChar(CP_UTF8, dwFlags, input, int(inputSize), nullptr, 0);
-
- WCHAR* buffer = (WCHAR*)malloc(sizeof(WCHAR) * (outputCodeUnitCount + 1));
-
- ::MultiByteToWideChar(CP_UTF8, dwFlags, input, int(inputSize), buffer, outputCodeUnitCount);
- buffer[outputCodeUnitCount] = 0;
-
- mBegin = buffer;
- mEnd = buffer + outputCodeUnitCount;
- }
-};
-
-struct ApplicationContext : public Slang::RefObject
-{
- HINSTANCE instance;
- int showCommand = SW_SHOWDEFAULT;
- int resultCode = 0;
-};
-
-static uint64_t gTimerFrequency;
-
-
-static void initApplication(ApplicationContext* context)
-{
- LARGE_INTEGER timerFrequency;
- QueryPerformanceFrequency(&timerFrequency);
- gTimerFrequency = timerFrequency.QuadPart;
-}
-
-/// Run an application given the specified callback and command-line arguments.
-int runApplication(
- ApplicationFunc func,
- int argc,
- char const* const* argv)
-{
- ApplicationContext context;
- context.instance = (HINSTANCE) GetModuleHandle(0);
- initApplication(&context);
- func(&context);
- return context.resultCode;
-}
-
-int runWindowsApplication(
- ApplicationFunc func,
- void* instance,
- int showCommand)
-{
- ApplicationContext context;
- context.instance = (HINSTANCE) instance;
- context.showCommand = showCommand;
- initApplication(&context);
- func(&context);
- return context.resultCode;
-}
-
-struct Window
-{
- HWND handle;
- WNDPROC nativeHook;
- EventHandler eventHandler;
- void* userData;
-};
-
-void setNativeWindowHook(Window* window, WNDPROC proc)
-{
- window->nativeHook = proc;
-}
-
-static KeyCode translateKeyCode(int vkey)
-{
- switch( vkey )
- {
- default:
- return KeyCode::Unknown;
-
-#define CASE(FROM, TO) case FROM: return KeyCode::TO;
- CASE('A', A); CASE('B', B); CASE('C', C); CASE('D', D); CASE('E', E);
- CASE('F', F); CASE('G', G); CASE('H', H); CASE('I', I); CASE('J', J);
- CASE('K', K); CASE('L', M); CASE('M', M); CASE('N', N); CASE('O', O);
- CASE('P', P); CASE('Q', Q); CASE('R', R); CASE('S', S); CASE('T', T);
- CASE('U', U); CASE('V', V); CASE('W', W); CASE('X', X); CASE('Y', Y);
- CASE('Z', Z);
-#undef CASE
-
-#define CASE(FROM, TO) case VK_##FROM: return KeyCode::TO;
- CASE(SPACE, Space);
-#undef CASE
- }
-}
-
-static LRESULT CALLBACK windowProc(
- HWND windowHandle,
- UINT message,
- WPARAM wParam,
- LPARAM lParam)
-{
- Window* window = (Window*) GetWindowLongPtrW(windowHandle, GWLP_USERDATA);
-
- // Give the installed filter a chance to intercept messages.
- // (This is used for ImGui)
- if( window )
- {
- if(auto nativeHook = window->nativeHook)
- {
- auto result = nativeHook(windowHandle, message, wParam, lParam);
- if(result)
- return result;
- }
- }
-
- auto eventHandler = window ? window->eventHandler : nullptr;
-
- switch (message)
- {
- case WM_CREATE:
- {
- auto createInfo = (CREATESTRUCTW*) lParam;
- window = (Window*) createInfo->lpCreateParams;
- window->handle = windowHandle;
-
- SetWindowLongPtrW(windowHandle, GWLP_USERDATA, (LONG_PTR) window);
- }
- break;
-
- case WM_KEYDOWN:
- case WM_KEYUP:
- {
- int virtualKey = (int) wParam;
- auto keyCode = translateKeyCode(virtualKey);
- if(eventHandler)
- {
- Event event;
- event.window = window;
- event.code = message == WM_KEYDOWN ? EventCode::KeyDown : EventCode::KeyUp;
- event.u.key = keyCode;
- eventHandler(event);
- }
- }
- break;
-
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- {
- if(eventHandler)
- {
- Event event;
- event.window = window;
- event.code = message == WM_LBUTTONDOWN ? EventCode::MouseDown : EventCode::MouseUp;
- event.u.mouse.x = (float) GET_X_LPARAM(lParam);
- event.u.mouse.y = (float) GET_Y_LPARAM(lParam);
- eventHandler(event);
- }
- }
- break;
-
- case WM_MOUSEMOVE:
- {
- if(eventHandler)
- {
- Event event;
- event.window = window;
- event.code = EventCode::MouseMoved;
- event.u.mouse.x = (float) GET_X_LPARAM(lParam);
- event.u.mouse.y = (float) GET_Y_LPARAM(lParam);
- eventHandler(event);
- }
- }
- break;
-
- case WM_CLOSE:
- PostQuitMessage(0);
- return 0;
- }
-
-
- return DefWindowProcW(windowHandle, message, wParam, lParam);
-}
-
-
-static ATOM createWindowClassAtom()
-{
- WNDCLASSEXW windowClassDesc;
- windowClassDesc.cbSize = sizeof(windowClassDesc);
- windowClassDesc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
- windowClassDesc.lpfnWndProc = &windowProc;
- windowClassDesc.cbClsExtra = 0;
- windowClassDesc.cbWndExtra = 0;
- windowClassDesc.hInstance = (HINSTANCE) GetModuleHandle(0);
- windowClassDesc.hIcon = 0;
- windowClassDesc.hCursor = LoadCursorW(NULL, IDC_ARROW);
- windowClassDesc.hbrBackground = 0;
- windowClassDesc.lpszMenuName = 0;
- windowClassDesc.lpszClassName = L"SlangGraphicsWindow";
- windowClassDesc.hIconSm = 0;
- ATOM windowClassAtom = RegisterClassExW(&windowClassDesc);
- return windowClassAtom;
-}
-
-static ATOM getWindowClassAtom()
-{
- static ATOM windowClassAtom = createWindowClassAtom();
- return windowClassAtom;
-}
-
-Window* createWindow(WindowDesc const& desc)
-{
- Window* window = new Window();
- window->handle = nullptr;
- window->nativeHook = nullptr;
- window->eventHandler = desc.eventHandler;
- window->userData = desc.userData;
-
- OSString windowTitle(desc.title);
-
- DWORD windowExtendedStyle = 0;
- DWORD windowStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
-
- HINSTANCE instance = (HINSTANCE) GetModuleHandle(0);
-
- RECT windowRect;
- windowRect.left = 0;
- windowRect.top = 0;
- windowRect.bottom = desc.height;
- windowRect.right = desc.width;
- AdjustWindowRect(&windowRect, windowStyle, FALSE);
-
- HWND windowHandle = CreateWindowExW(
- windowExtendedStyle,
- (LPWSTR) getWindowClassAtom(),
- windowTitle,
- windowStyle,
- CW_USEDEFAULT,
- 0, // x, y
- windowRect.right - windowRect.left,
- windowRect.bottom - windowRect.top,
- NULL, // parent
- NULL, // menu
- instance,
- window);
-
-
- if(!windowHandle)
- {
- delete window;
- return nullptr;
- }
-
- window->handle = windowHandle;
- return window;
-}
-
-void destroyWindow(Window* window)
-{
- DestroyWindow(window->handle);
- delete window;
-}
-
-void showWindow(Window* window)
-{
- ShowWindow(window->handle, SW_SHOW);
-}
-
-void* getPlatformWindowHandle(Window* window)
-{
- return window->handle;
-}
-
-void* getUserData(Window* window)
-{
- return window->userData;
-}
-
-bool dispatchEvents(ApplicationContext* context)
-{
- for(;;)
- {
- MSG message;
-
- int result = PeekMessageW(&message, NULL, 0, 0, PM_REMOVE);
- if (result != 0)
- {
- if (message.message == WM_QUIT)
- {
- context->resultCode = (int)message.wParam;
- return false;
- }
-
- TranslateMessage(&message);
- DispatchMessageW(&message);
- }
- else
- {
- return true;
- }
- }
-
-}
-
-void exitApplication(ApplicationContext* context, int resultCode)
-{
- ExitProcess(resultCode);
-}
-
-void log(char const* message, ...)
-{
- va_list args;
- va_start(args, message);
-
- static const int kBufferSize = 1024;
- char messageBuffer[kBufferSize];
- vsnprintf(messageBuffer, kBufferSize - 1, message, args);
- messageBuffer[kBufferSize - 1] = 0;
-
- va_end(args);
-
- fputs(messageBuffer, stderr);
-
- OSString wideMessageBuffer(messageBuffer);
- OutputDebugStringW(wideMessageBuffer);
-}
-
-int reportError(char const* message, ...)
-{
- va_list args;
- va_start(args, message);
-
- static const int kBufferSize = 1024;
- char messageBuffer[kBufferSize];
- vsnprintf(messageBuffer, kBufferSize - 1, message, args);
- messageBuffer[kBufferSize - 1] = 0;
-
- va_end(args);
-
- fputs(messageBuffer, stderr);
-
- OSString wideMessageBuffer(messageBuffer);
- OutputDebugStringW(wideMessageBuffer);
-
- return 1;
-}
-
-uint64_t getCurrentTime()
-{
- LARGE_INTEGER counter;
- QueryPerformanceCounter(&counter);
- return counter.QuadPart;
-}
-
-uint64_t getTimerFrequency()
-{
- return gTimerFrequency;
-}
-
-#else
-
-// TODO: put an SDL version here
-
-#endif
-
-} // gfx
diff --git a/tools/graphics-app-framework/gui.cpp b/tools/platform/gui.cpp
index 3d4283131..cf7e74acc 100644
--- a/tools/graphics-app-framework/gui.cpp
+++ b/tools/platform/gui.cpp
@@ -7,8 +7,10 @@
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
#endif
+using namespace gfx;
-namespace gfx {
+namespace platform
+{
#ifdef _WIN32
LRESULT CALLBACK guiWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -48,7 +50,7 @@ GUI::GUI(
ImGuiIO& io = ImGui::GetIO();
#ifdef _WIN32
- ImGui_ImplWin32_Init(getPlatformWindowHandle(window));
+ ImGui_ImplWin32_Init((HWND)window->getNativeHandle().handleValues[0]);
setNativeWindowHook(window, &guiWindowProc);
#endif
@@ -113,7 +115,7 @@ GUI::GUI(
const SlangResult compileRes = spCompile(slangRequest);
if(auto diagnostics = spGetDiagnosticOutput(slangRequest))
{
- reportError("%s", diagnostics);
+ printf("%s", diagnostics);
}
if(SLANG_FAILED(compileRes))
{
diff --git a/tools/platform/gui.h b/tools/platform/gui.h
new file mode 100644
index 000000000..d22da3299
--- /dev/null
+++ b/tools/platform/gui.h
@@ -0,0 +1,34 @@
+// gui.h
+#pragma once
+
+#include "slang-gfx.h"
+#include "vector-math.h"
+#include "window.h"
+#include "slang-com-ptr.h"
+#include "external/imgui/imgui.h"
+#include "source/core/slang-basic.h"
+
+namespace platform {
+
+struct GUI : Slang::RefObject
+{
+ GUI(Window* window,
+ gfx::IRenderer* renderer,
+ gfx::ICommandQueue* queue,
+ gfx::IFramebufferLayout* framebufferLayout);
+ ~GUI();
+
+ void beginFrame();
+ void endFrame(gfx::IFramebuffer* framebuffer);
+
+private:
+ Slang::ComPtr<gfx::IRenderer> renderer;
+ Slang::ComPtr<gfx::ICommandQueue> queue;
+ Slang::ComPtr<gfx::IRenderPassLayout> renderPass;
+ Slang::ComPtr<gfx::IPipelineState> pipelineState;
+ Slang::ComPtr<gfx::IDescriptorSetLayout> descriptorSetLayout;
+ Slang::ComPtr<gfx::IPipelineLayout> pipelineLayout;
+ Slang::ComPtr<gfx::ISamplerState> samplerState;
+};
+
+} // gfx
diff --git a/tools/graphics-app-framework/model.cpp b/tools/platform/model.cpp
index 6984a6818..f28577631 100644
--- a/tools/graphics-app-framework/model.cpp
+++ b/tools/platform/model.cpp
@@ -231,7 +231,7 @@ Result ModelLoader::load(
if(!diagnostics.empty())
{
- log("%s", diagnostics.c_str());
+ printf("%s", diagnostics.c_str());
}
if(!success)
{
diff --git a/tools/graphics-app-framework/model.h b/tools/platform/model.h
index 412f10a1d..412f10a1d 100644
--- a/tools/graphics-app-framework/model.h
+++ b/tools/platform/model.h
diff --git a/tools/platform/performance-counter.h b/tools/platform/performance-counter.h
new file mode 100644
index 000000000..e9e990f45
--- /dev/null
+++ b/tools/platform/performance-counter.h
@@ -0,0 +1,30 @@
+#ifndef PLATFORM_PERFORMANCE_COUNTER_H
+#define PLATFORM_PERFORMANCE_COUNTER_H
+
+#include <chrono>
+
+namespace platform
+{
+typedef std::chrono::high_resolution_clock::time_point TimePoint;
+typedef std::chrono::high_resolution_clock::duration Duration;
+
+class PerformanceCounter
+{
+public:
+ static inline TimePoint now()
+ {
+ return std::chrono::high_resolution_clock::now();
+ }
+ static inline Duration getElapsedTime(TimePoint counter) { return now() - counter; }
+ static inline float getElapsedTimeInSeconds(TimePoint counter)
+ {
+ return (float)toSeconds(now() - counter);
+ }
+ static inline double toSeconds(Duration duration)
+ {
+ return std::chrono::duration<float>(duration).count();
+ }
+};
+} // namespace platform
+
+#endif
diff --git a/tools/graphics-app-framework/vector-math.h b/tools/platform/vector-math.h
index e35cb46ac..e35cb46ac 100644
--- a/tools/graphics-app-framework/vector-math.h
+++ b/tools/platform/vector-math.h
diff --git a/tools/platform/window.h b/tools/platform/window.h
new file mode 100644
index 000000000..c776c3ffa
--- /dev/null
+++ b/tools/platform/window.h
@@ -0,0 +1,235 @@
+// window.h
+#pragma once
+
+#include "slang-com-ptr.h"
+#include "source/core/slang-basic.h"
+#include "source/core/slang-func-ptr.h"
+
+namespace platform {
+
+enum class KeyCode : uint32_t
+{
+ None = 0,
+ Left = 0x25,
+ Up = 0x26,
+ Down = 0x28,
+ Right = 0x27,
+ Escape = 0x1B,
+ Return = 0x0D,
+ Space = 0x20,
+ Shift = 0x10,
+ Ctrl = 0x11,
+ Alt = 0x12,
+ Backspace = 0x08,
+ Delete = 0x2E,
+ Home = 0x24,
+ End = 0x23,
+ PageUp = 0x21,
+ PageDown = 0x22,
+ Insert = 0x2D,
+ Tab = 0x09,
+ A = 0x41,
+ B = 0x42,
+ C = 0x43,
+ D = 0x44,
+ E = 0x45,
+ F = 0x46,
+ G = 0x47,
+ H = 0x48,
+ I = 0x49,
+ J = 0x4A,
+ K = 0x4B,
+ L = 0x4C,
+ M = 0x4D,
+ N = 0x4E,
+ O = 0x4F,
+ P = 0x50,
+ Q = 0x51,
+ R = 0x52,
+ S = 0x53,
+ T = 0x54,
+ U = 0x55,
+ V = 0x56,
+ W = 0x57,
+ X = 0x58,
+ Y = 0x59,
+ Z = 0x5A,
+ Semicolon = 0xBA,
+ Comma = 0xBC,
+ Dot = 0xBE,
+ Slash = 0xBF,
+ Quote = 0xDE,
+ LBracket = 0xDB,
+ RBracket = 0xDD,
+ Backslash = 0xDC,
+ Minus = 0xBD,
+ Plus = 0xBB,
+ Tilde = 0xC0,
+ Key0 = 0x30,
+ Key1 = 0x31,
+ Key2 = 0x32,
+ Key3 = 0x33,
+ Key4 = 0x34,
+ Key5 = 0x35,
+ Key6 = 0x36,
+ Key7 = 0x37,
+ Key8 = 0x38,
+ Key9 = 0x39,
+ F1 = 0x70,
+ F2 = 0x71,
+ F3 = 0x72,
+ F4 = 0x73,
+ F5 = 0x74,
+ F6 = 0x75,
+ F7 = 0x76,
+ F8 = 0x77,
+ F9 = 0x78,
+ F10 = 0x79,
+ F11 = 0x7A,
+ F12 = 0x7B,
+};
+
+struct WindowHandle
+{
+ enum class Type
+ {
+ Unknown,
+ Win32Handle,
+ XLibHandle,
+ };
+ Type type;
+ intptr_t handleValues[2];
+ static WindowHandle FromHwnd(void* hwnd)
+ {
+ WindowHandle handle = {};
+ handle.type = WindowHandle::Type::Win32Handle;
+ handle.handleValues[0] = (intptr_t)(hwnd);
+ return handle;
+ }
+ static WindowHandle FromXWindow(void* xdisplay, uint32_t xwindow)
+ {
+ WindowHandle handle = {};
+ handle.type = WindowHandle::Type::XLibHandle;
+ handle.handleValues[0] = (intptr_t)(xdisplay);
+ handle.handleValues[1] = xwindow;
+ return handle;
+ }
+};
+
+struct ButtonState
+{
+ enum Enum
+ {
+ None = 0, LeftButton = 1, RightButton = 2, MiddleButton = 4,
+ Shift = 8, Control = 16, Alt = 32
+ };
+};
+
+struct KeyEventArgs
+{
+ KeyCode key;
+ wchar_t keyChar; // For KeyPress event
+ ButtonState::Enum buttons;
+ bool cancelEvent;
+};
+
+struct MouseEventArgs
+{
+ int x, y;
+ int delta;
+ ButtonState::Enum buttons;
+};
+
+struct Rect
+{
+ int x, y;
+ int width, height;
+};
+
+struct WindowDesc
+{
+ char const* title = nullptr;
+ int width = 0;
+ int height = 0;
+};
+
+class Window : public Slang::RefObject
+{
+public:
+ struct Events
+ {
+ Slang::Action<> mainLoop;
+ Slang::Action<> sizeChanged;
+ Slang::Action<> focus;
+ Slang::Action<> lostFocus;
+ Slang::Action<KeyEventArgs&> keyDown;
+ Slang::Action<KeyEventArgs&> keyUp;
+ Slang::Action<KeyEventArgs&> keyPress;
+ Slang::Action<MouseEventArgs> mouseMove;
+ Slang::Action<MouseEventArgs> mouseUp;
+ Slang::Action<MouseEventArgs> mouseDown;
+ };
+
+ Events events;
+
+ virtual void setClientSize(uint32_t width, uint32_t height) = 0;
+ virtual Rect getClientRect() = 0;
+ virtual void centerScreen() = 0;
+ virtual void close() = 0;
+ virtual bool getFocused() = 0;
+ virtual bool getVisible() = 0;
+ virtual WindowHandle getNativeHandle() = 0;
+ virtual void setText(Slang::String text) = 0;
+ virtual void show() = 0;
+ virtual void hide() = 0;
+ virtual int getCurrentDpi() = 0;
+};
+
+class Application
+{
+public:
+ static Window* createWindow(const WindowDesc& desc);
+ static void init();
+ static void run(Window* mainWindow, bool waitForEvents = false);
+ static void quit();
+ static void doEvents();
+ static void dispose();
+};
+
+} // namespace platform
+
+#ifdef _WIN32
+
+# ifdef _MSC_VER
+# ifdef _DEBUG
+# define GFX_DUMP_LEAK _CrtDumpMemoryLeaks();
+# endif
+# endif
+# ifndef GFX_DUMP_LEAK
+# define GFX_DUMP_LEAK
+# endif
+# define PLATFORM_UI_MAIN(APPLICATION_ENTRY) \
+ int __stdcall WinMain( \
+ void* /*instance*/, \
+ void* /* prevInstance */, \
+ void* /* commandLine */, \
+ int /*showCommand*/) \
+ { \
+ platform::Application::init(); \
+ auto result = APPLICATION_ENTRY(); \
+ platform::Application::dispose(); \
+ GFX_DUMP_LEAK \
+ return result; \
+ }
+
+#else
+
+# define PLATFORM_UI_MAIN(APPLICATION_ENTRY) \
+ int main() \
+ { \
+ platform::Application::init(); \
+ auto rs - APPLICATION_ENTRY(); \
+ platform::Application::dispose(); \
+ }
+
+#endif
diff --git a/tools/platform/windows/win-window.cpp b/tools/platform/windows/win-window.cpp
new file mode 100644
index 000000000..0362a6839
--- /dev/null
+++ b/tools/platform/windows/win-window.cpp
@@ -0,0 +1,442 @@
+#ifdef _WIN32
+
+#include "../window.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#include <windowsx.h>
+using namespace Slang;
+
+namespace platform
+{
+
+static const wchar_t* kWindowClassName = L"slang-platform-window";
+
+typedef BOOL(WINAPI* EnableNonClientDpiScalingProc)(_In_ HWND hwnd);
+
+class Win32AppContext
+{
+public:
+ static EnableNonClientDpiScalingProc enableNonClientDpiScaling;
+ static RefPtr<Window> mainWindow;
+ static OrderedDictionary<HWND, Window*> windows;
+ static HWND mainWindowHandle;
+ static bool isTerminated;
+ static bool isWindows81OrGreater;
+};
+
+EnableNonClientDpiScalingProc Win32AppContext::enableNonClientDpiScaling = nullptr;
+HWND Win32AppContext::mainWindowHandle = nullptr;
+RefPtr<Window> Win32AppContext::mainWindow;
+OrderedDictionary<HWND, Window*> Win32AppContext::windows;
+bool Win32AppContext::isTerminated = false;
+bool Win32AppContext::isWindows81OrGreater = false;
+
+
+ButtonState::Enum _addButtonState(ButtonState::Enum val, ButtonState::Enum newState)
+{
+ return (ButtonState::Enum)((int)val | (int)newState);
+}
+
+ButtonState::Enum getModifierState()
+{
+ ButtonState::Enum result = ButtonState::Enum::None;
+ if (GetAsyncKeyState(VK_CONTROL))
+ result = _addButtonState(result, ButtonState::Enum::Control);
+ if (GetAsyncKeyState(VK_SHIFT))
+ result = _addButtonState(result, ButtonState::Enum::Shift);
+ if (GetAsyncKeyState(VK_MENU))
+ result = _addButtonState(result, ButtonState::Enum::Alt);
+ return result;
+}
+
+ButtonState::Enum getModifierState(WPARAM wParam)
+{
+ ButtonState::Enum result = ButtonState::Enum::None;
+ if (wParam & MK_CONTROL)
+ result = _addButtonState(result, ButtonState::Enum::Control);
+ if (wParam & MK_MBUTTON)
+ result = _addButtonState(result, ButtonState::Enum::MiddleButton);
+ if (wParam & MK_RBUTTON)
+ result = _addButtonState(result, ButtonState::Enum::RightButton);
+ if (wParam & MK_SHIFT)
+ result = _addButtonState(result, ButtonState::Enum::Shift);
+ if (GetAsyncKeyState(VK_MENU))
+ result = _addButtonState(result, ButtonState::Enum::Alt);
+ return result;
+}
+
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ bool useDefProc = true;
+ Window* window = nullptr;
+ Win32AppContext::windows.TryGetValue(hWnd, window);
+ switch (message)
+ {
+ case WM_LBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ {
+ int mx = GET_X_LPARAM(lParam);
+ int my = GET_Y_LPARAM(lParam);
+ bool processed = false;
+ if (window)
+ {
+ window->events.mouseUp(MouseEventArgs{
+ mx,
+ my,
+ 0, getModifierState(wParam)});
+ }
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ {
+ int mx = GET_X_LPARAM(lParam);
+ int my = GET_Y_LPARAM(lParam);
+ bool processed = false;
+ if (window)
+ {
+ window->events.mouseDown(MouseEventArgs{mx, my, 0, getModifierState(wParam)});
+ }
+ }
+ break;
+ case WM_MOUSEMOVE:
+ {
+ int mx = GET_X_LPARAM(lParam);
+ int my = GET_Y_LPARAM(lParam);
+ if (window)
+ {
+ window->events.mouseMove(MouseEventArgs{mx, my, 0, getModifierState(wParam)});
+ }
+ }
+ break;
+ case WM_MOUSEWHEEL:
+ {
+ int delta = GET_WHEEL_DELTA_WPARAM(wParam);
+ if (window)
+ {
+ window->events.mouseMove(MouseEventArgs{0, 0, delta, getModifierState(wParam)});
+ }
+ }
+ break;
+ case WM_CHAR:
+ {
+ if (window)
+ {
+ KeyEventArgs keyEventArgs = {
+ KeyCode::None, (wchar_t)(wParam), ButtonState::Enum::None, false};
+ window->events.keyPress(keyEventArgs);
+ if (keyEventArgs.cancelEvent)
+ useDefProc = false;
+ }
+ }
+ break;
+ case WM_KEYDOWN:
+ {
+ if (window)
+ {
+ KeyEventArgs keyEventArgs = {(KeyCode)(wParam), 0, getModifierState(), false};
+ window->events.keyDown(keyEventArgs);
+ if (keyEventArgs.cancelEvent)
+ useDefProc = false;
+ }
+ }
+ break;
+ case WM_KEYUP:
+ {
+ if (window)
+ {
+ KeyEventArgs keyEventArgs = {(KeyCode)(wParam), 0, getModifierState(), false};
+ window->events.keyUp(keyEventArgs);
+ if (keyEventArgs.cancelEvent)
+ useDefProc = false;
+ }
+ }
+ break;
+ case WM_SETFOCUS:
+ {
+ if (window)
+ {
+ window->events.focus();
+ }
+ }
+ break;
+ case WM_KILLFOCUS:
+ {
+ if (window)
+ {
+ window->events.lostFocus();
+ }
+ }
+ break;
+ case WM_SIZE:
+ {
+ if (window)
+ {
+ window->events.sizeChanged();
+ }
+ }
+ break;
+ case WM_NCCREATE:
+ {
+ if (Win32AppContext::enableNonClientDpiScaling)
+ Win32AppContext::enableNonClientDpiScaling(hWnd);
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ break;
+ default:
+ break;
+ }
+ if (message == WM_DESTROY && hWnd == Win32AppContext::mainWindowHandle)
+ {
+ PostQuitMessage(0);
+ return 0;
+ }
+ if (useDefProc)
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ return 0;
+}
+
+void registerWindowClass()
+{
+ WNDCLASSEX wcex;
+
+ wcex.cbSize = sizeof(WNDCLASSEX);
+
+ wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
+ wcex.lpfnWndProc = WndProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = GetModuleHandle(NULL);
+ wcex.hIcon = 0;
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+ wcex.lpszMenuName = 0;
+ wcex.lpszClassName = kWindowClassName;
+ wcex.hIconSm = 0;
+
+ RegisterClassExW(&wcex);
+}
+
+void unregisterWindowClass() { UnregisterClassW(kWindowClassName, GetModuleHandle(NULL)); }
+
+HRESULT(WINAPI* getDpiForMonitor) (void* hmonitor, int dpiType, unsigned int* dpiX, unsigned int* dpiY);
+
+void Application::init()
+{
+ *(FARPROC*)&Win32AppContext::enableNonClientDpiScaling =
+ GetProcAddress(GetModuleHandleA("User32"), "EnableNonClientDpiScaling");
+ void*(WINAPI * RtlGetVersion)(LPOSVERSIONINFOEXW);
+ OSVERSIONINFOEXW osInfo;
+ *(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
+
+ if (RtlGetVersion)
+ {
+ osInfo.dwOSVersionInfoSize = sizeof(osInfo);
+ RtlGetVersion(&osInfo);
+ if (osInfo.dwMajorVersion > 8 || (osInfo.dwMajorVersion == 8 && osInfo.dwMinorVersion >= 1))
+ Win32AppContext::isWindows81OrGreater = true;
+ }
+ HRESULT(WINAPI * setProcessDpiAwareness)(int value);
+ *(FARPROC*)&setProcessDpiAwareness =
+ GetProcAddress(GetModuleHandleA("Shcore"), "SetProcessDpiAwareness");
+ *(FARPROC*)&getDpiForMonitor = GetProcAddress(GetModuleHandleA("Shcore"), "GetDpiForMonitor");
+ if (setProcessDpiAwareness)
+ {
+ if (Win32AppContext::isWindows81OrGreater)
+ setProcessDpiAwareness(2); // PROCESS_PER_MONITOR_DPI_AWARE
+ else
+ setProcessDpiAwareness(1); // PROCESS_SYSTEM_DPI_AWARE
+ }
+ registerWindowClass();
+}
+
+void doEventsImpl(bool waitForEvents)
+{
+ int hasMsg = 0;
+ do
+ {
+ MSG msg = {};
+ hasMsg =
+ (waitForEvents ? GetMessage(&msg, NULL, 0, 0) : PeekMessage(&msg, NULL, 0, 0, TRUE));
+ if (hasMsg)
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ if (msg.message == WM_QUIT)
+ Win32AppContext::isTerminated = true;
+ } while (!Win32AppContext::isTerminated && hasMsg);
+}
+
+void Application::doEvents() { doEventsImpl(false); }
+
+void Application::quit() { Win32AppContext::isTerminated = true; }
+
+void Application::dispose()
+{
+ Win32AppContext::mainWindow = nullptr;
+ Win32AppContext::windows = decltype(Win32AppContext::windows)();
+ unregisterWindowClass();
+}
+
+void Application::run(Window* mainWindow, bool waitForEvents)
+{
+ if (mainWindow)
+ {
+ Win32AppContext::mainWindow = mainWindow;
+ Win32AppContext::mainWindowHandle = (HWND)mainWindow->getNativeHandle().handleValues[0];
+ ShowWindow(Win32AppContext::mainWindowHandle, SW_SHOW);
+ UpdateWindow(Win32AppContext::mainWindowHandle);
+ }
+ while (!Win32AppContext::isTerminated)
+ {
+ doEventsImpl(waitForEvents);
+ if (mainWindow)
+ {
+ mainWindow->events.mainLoop();
+ }
+ }
+}
+
+class Win32PlatformWindow : public Window
+{
+public:
+ HWND handle;
+ DWORD style;
+ bool visible = false;
+ Win32PlatformWindow(const WindowDesc& desc)
+ {
+ DWORD windowExtendedStyle = 0;
+ DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
+ HINSTANCE instance = (HINSTANCE)GetModuleHandle(0);
+
+ RECT windowRect;
+ windowRect.left = 0;
+ windowRect.top = 0;
+ windowRect.bottom = desc.height;
+ windowRect.right = desc.width;
+ AdjustWindowRect(&windowRect, style, FALSE);
+
+ handle = CreateWindowExW(
+ windowExtendedStyle,
+ (LPWSTR)kWindowClassName,
+ String(desc.title).toWString().begin(),
+ style,
+ CW_USEDEFAULT,
+ 0, // x, y
+ windowRect.right,
+ windowRect.bottom,
+ NULL, // parent
+ NULL, // menu
+ instance,
+ NULL);
+
+ if (handle)
+ Win32AppContext::windows[handle] = this;
+ }
+
+ ~Win32PlatformWindow()
+ {
+ if (handle)
+ {
+ Win32AppContext::windows.Remove(handle);
+ }
+ DestroyWindow(handle);
+ }
+
+ virtual void setClientSize(uint32_t width, uint32_t height) override
+ {
+ RECT currentRect;
+ GetWindowRect(handle, &currentRect);
+
+ RECT windowRect;
+ windowRect.left = currentRect.left;
+ windowRect.top = currentRect.top;
+ windowRect.bottom = height;
+ windowRect.right = width;
+ AdjustWindowRect(&windowRect, style, FALSE);
+
+ MoveWindow(
+ handle,
+ windowRect.left,
+ windowRect.top,
+ windowRect.right - windowRect.left,
+ windowRect.bottom - windowRect.top,
+ FALSE);
+ }
+
+ virtual Rect getClientRect() override
+ {
+ RECT currentRect;
+ GetClientRect(handle, &currentRect);
+ Rect rect;
+ rect.x = currentRect.left;
+ rect.y = currentRect.top;
+ rect.width = currentRect.right - currentRect.left;
+ rect.height = currentRect.bottom - currentRect.top;
+ return rect;
+ }
+
+ virtual void centerScreen() override
+ {
+ RECT screenRect;
+ GetClientRect(GetDesktopWindow(), &screenRect);
+ RECT currentRect;
+ GetWindowRect(handle, &currentRect);
+
+ auto width = currentRect.right - currentRect.left;
+ auto height = currentRect.bottom - currentRect.top;
+
+ auto left = (screenRect.right - width) / 2;
+ auto top = (screenRect.bottom - height) / 2;
+
+ MoveWindow(handle, left, top, width, height, FALSE);
+ }
+
+ virtual void close() override {}
+ virtual bool getFocused() override { return GetFocus() == handle; }
+ virtual bool getVisible() override { return visible; }
+ virtual WindowHandle getNativeHandle() override
+ {
+ return WindowHandle::FromHwnd(handle);
+ }
+ virtual void setText(Slang::String text) override
+ {
+ SetWindowText(handle, text.toWString().begin());
+ }
+ virtual void show() override
+ {
+ ShowWindow(handle, SW_SHOW);
+ visible = true;
+ }
+ virtual void hide() override
+ {
+ ShowWindow(handle, SW_HIDE);
+ visible = false;
+ }
+ virtual int getCurrentDpi() override
+ {
+ int dpi = 96;
+ if (Win32AppContext::isWindows81OrGreater && getDpiForMonitor)
+ {
+ getDpiForMonitor(
+ MonitorFromWindow(handle, MONITOR_DEFAULTTOPRIMARY),
+ 0,
+ (UINT*)&dpi,
+ (UINT*)&dpi);
+ return dpi;
+ }
+ dpi = GetDeviceCaps(NULL, LOGPIXELSY);
+ return dpi;
+ }
+};
+
+Window* Application::createWindow(const WindowDesc& desc) { return new Win32PlatformWindow(desc); }
+
+
+} // namespace gfx
+
+#endif