diff options
Diffstat (limited to 'demo')
90 files changed, 23464 insertions, 0 deletions
diff --git a/demo/DemoApp/DemoApp.vcxproj b/demo/DemoApp/DemoApp.vcxproj new file mode 100644 index 0000000..4cae61f --- /dev/null +++ b/demo/DemoApp/DemoApp.vcxproj @@ -0,0 +1,367 @@ +<?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="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Condition="'$(Platform)'=='Win32'"> + <PlatformName>win32</PlatformName> + </PropertyGroup> + <PropertyGroup Condition="'$(Platform)'=='x64'"> + <PlatformName>win64</PlatformName> + </PropertyGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{001BA531-503D-4407-AE6B-A42408E17BFF}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>DemoApp</RootNamespace> + <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup 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" /> + </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)'=='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|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'"> + <LinkIncremental>true</LinkIncremental> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win32;$(SolutionDir)external\SDL2\lib\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86</LibraryPath> + <CustomBuildBeforeTargets>PostBuildEvent</CustomBuildBeforeTargets> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win64;$(SolutionDir)external\SDL2\lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath> + <CustomBuildBeforeTargets>PostBuildEvent</CustomBuildBeforeTargets> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win32;$(SolutionDir)external\SDL2\lib\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86</LibraryPath> + <CustomBuildBeforeTargets>PostBuildEvent</CustomBuildBeforeTargets> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win64;$(SolutionDir)external\SDL2\lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath> + <CustomBuildBeforeTargets>PostBuildEvent</CustomBuildBeforeTargets> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>DLL_SUFFIX=$(Configuration)_$(PlatformName);WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <EntryPointSymbol>mainCRTStartup</EntryPointSymbol> + </Link> + <FxCompile> + <EntryPointName>%(filename)</EntryPointName> + <ShaderModel>5.0</ShaderModel> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + <ObjectFileOutput /> + </FxCompile> + <CustomBuildStep> + <Command>copy "$(SolutionDir)external\SDL2\lib\x86\SDL2.dll" "$(outDir)" +copy "$(SolutionDir)Lib\$(PlatformName)\*.dll" "$(outDir)"</Command> + </CustomBuildStep> + <CustomBuildStep> + <Message>Copying DLLs</Message> + </CustomBuildStep> + <CustomBuildStep> + <Outputs>SDL2.dll</Outputs> + </CustomBuildStep> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>DLL_SUFFIX=$(Configuration)_$(PlatformName);_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <EntryPointSymbol>mainCRTStartup</EntryPointSymbol> + </Link> + <FxCompile> + <EntryPointName>%(filename)</EntryPointName> + <ShaderModel>5.0</ShaderModel> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + <ObjectFileOutput /> + </FxCompile> + <CustomBuildStep> + <Command>copy "$(SolutionDir)external\SDL2\lib\x64\SDL2.dll" "$(outDir)" +copy "$(SolutionDir)Lib\$(PlatformName)\*.dll" "$(outDir)"</Command> + </CustomBuildStep> + <CustomBuildStep> + <Message>Copying DLLs</Message> + </CustomBuildStep> + <CustomBuildStep> + <Outputs>SDL2.dll</Outputs> + </CustomBuildStep> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>DLL_SUFFIX=$(Configuration)_$(PlatformName);WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <EntryPointSymbol>mainCRTStartup</EntryPointSymbol> + </Link> + <FxCompile> + <EntryPointName>%(filename)</EntryPointName> + <ShaderModel>5.0</ShaderModel> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + <ObjectFileOutput /> + </FxCompile> + <CustomBuildStep> + <Command>copy "$(SolutionDir)external\SDL2\lib\x86\SDL2.dll" "$(outDir)" +copy "$(SolutionDir)Lib\$(PlatformName)\*.dll" "$(outDir)"</Command> + </CustomBuildStep> + <CustomBuildStep> + <Message>Copying DLLs</Message> + </CustomBuildStep> + <CustomBuildStep> + <Outputs>SDL2.dll</Outputs> + </CustomBuildStep> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>DLL_SUFFIX=$(Configuration)_$(PlatformName);NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <EntryPointSymbol>mainCRTStartup</EntryPointSymbol> + </Link> + <FxCompile> + <EntryPointName>%(filename)</EntryPointName> + <ShaderModel>5.0</ShaderModel> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + <ObjectFileOutput /> + </FxCompile> + <CustomBuildStep> + <Command>copy "$(SolutionDir)external\SDL2\lib\x64\SDL2.dll" "$(outDir)" +copy "$(SolutionDir)Lib\$(PlatformName)\*.dll" "$(outDir)"</Command> + </CustomBuildStep> + <CustomBuildStep> + <Message>Copying DLLs</Message> + </CustomBuildStep> + <CustomBuildStep> + <Outputs>SDL2.dll</Outputs> + </CustomBuildStep> + </ItemDefinitionGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <ItemGroup> + <ClCompile Include="appGraphCtxLoader.cpp" /> + <ClCompile Include="bitmap.cpp" /> + <ClCompile Include="computeContextLoader.cpp" /> + <ClCompile Include="curveEditor.cpp" /> + <ClCompile Include="imgui.cpp" /> + <ClCompile Include="imguiGraph.cpp" /> + <ClCompile Include="imguiGraphLoader.cpp" /> + <ClCompile Include="imguiser.cpp" /> + <ClCompile Include="loader.cpp" /> + <ClCompile Include="main.cpp" /> + <ClCompile Include="mesh.cpp" /> + <ClCompile Include="meshLoader.cpp" /> + <ClCompile Include="NvFlowInteropLoader.cpp" /> + <ClCompile Include="scene.cpp" /> + <ClCompile Include="scene2DTextureEmitter.cpp" /> + <ClCompile Include="sceneCustomEmit.cpp" /> + <ClCompile Include="sceneFlow.cpp" /> + <ClCompile Include="sceneSDF.cpp" /> + <ClCompile Include="sceneSimpleFlame.cpp" /> + <ClCompile Include="sceneSimpleSmoke.cpp" /> + </ItemGroup> + <ItemGroup> + <Manifest Include="app.manifest" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="appGraphCtx.h" /> + <ClInclude Include="bitmap.h" /> + <ClInclude Include="camera.h" /> + <ClInclude Include="computeContext.h" /> + <ClInclude Include="curveEditor.h" /> + <ClInclude Include="flowShaderParams.h" /> + <ClInclude Include="imgui.h" /> + <ClInclude Include="imguiGraph.h" /> + <ClInclude Include="imguiInterop.h" /> + <ClInclude Include="imguiser.h" /> + <ClInclude Include="loader.h" /> + <ClInclude Include="mesh.h" /> + <ClInclude Include="meshInterop.h" /> + <ClInclude Include="NvFlowInterop.h" /> + <ClInclude Include="preset0.h" /> + <ClInclude Include="preset1.h" /> + <ClInclude Include="presetFireBall.h" /> + <ClInclude Include="presetFlame.h" /> + <ClInclude Include="presetSmoke.h" /> + <ClInclude Include="scene.h" /> + <ClInclude Include="stb_truetype.h" /> + </ItemGroup> + <ItemGroup> + <FxCompile Include="..\Shaders\customEmitAllocCS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">5.0</ShaderModel> + </FxCompile> + <FxCompile Include="..\Shaders\customEmitEmit2CS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">5.0</ShaderModel> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + </FxCompile> + <FxCompile Include="..\Shaders\customEmitEmitCS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">5.0</ShaderModel> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + </FxCompile> + <FxCompile Include="..\Shaders\customLightingCS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">5.0</ShaderModel> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compute</ShaderType> + <ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">5.0</ShaderModel> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\include;$(SolutionDir)\NvFlow;</AdditionalIncludeDirectories> + </FxCompile> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/demo/DemoApp/DemoApp.vcxproj.filters b/demo/DemoApp/DemoApp.vcxproj.filters new file mode 100644 index 0000000..94b9d93 --- /dev/null +++ b/demo/DemoApp/DemoApp.vcxproj.filters @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Shaders"> + <UniqueIdentifier>{12de0363-d75b-4f29-bd10-e8b9832dd449}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="imgui.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="imguiGraph.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="loader.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="imguiGraphLoader.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="NvFlowInteropLoader.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="bitmap.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="sceneSimpleFlame.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="scene2DTextureEmitter.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="mesh.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="meshLoader.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="appGraphCtxLoader.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="sceneSDF.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="curveEditor.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="imguiser.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="scene.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="computeContextLoader.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="sceneSimpleSmoke.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="sceneCustomEmit.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="sceneFlow.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <Manifest Include="app.manifest"> + <Filter>Resource Files</Filter> + </Manifest> + </ItemGroup> + <ItemGroup> + <ClInclude Include="appGraphCtx.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="scene.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="mesh.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="camera.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="imgui.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="imguiGraph.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="stb_truetype.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="loader.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="NvFlowInterop.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="bitmap.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="meshInterop.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="imguiInterop.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="curveEditor.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="imguiser.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="preset0.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="presetFlame.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="computeContext.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="preset1.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="presetSmoke.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="flowShaderParams.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="presetFireBall.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <FxCompile Include="..\Shaders\customLightingCS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + <FxCompile Include="..\Shaders\customEmitAllocCS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + <FxCompile Include="..\Shaders\customEmitEmitCS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + <FxCompile Include="..\Shaders\customEmitEmit2CS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/demo/DemoApp/NvFlowInterop.h b/demo/DemoApp/NvFlowInterop.h new file mode 100644 index 0000000..de93a24 --- /dev/null +++ b/demo/DemoApp/NvFlowInterop.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#ifndef NV_FLOW_INTEROP_H +#define NV_FLOW_INTEROP_H + +#include "appGraphCtx.h" +#include "NvFlow.h" + +NV_FLOW_API NvFlowContext* NvFlowInteropCreateContext(AppGraphCtx* appctx); + +NV_FLOW_API NvFlowDepthStencilView* NvFlowInteropCreateDepthStencilView(AppGraphCtx* appctx, NvFlowContext* flowctx); + +NV_FLOW_API NvFlowRenderTargetView* NvFlowInteropCreateRenderTargetView(AppGraphCtx* appctx, NvFlowContext* flowctx); + +NV_FLOW_API void NvFlowInteropUpdateContext(NvFlowContext* context, AppGraphCtx* appctx); + +NV_FLOW_API void NvFlowInteropUpdateDepthStencilView(NvFlowDepthStencilView* view, AppGraphCtx* appctx, NvFlowContext* flowctx); + +NV_FLOW_API void NvFlowInteropUpdateRenderTargetView(NvFlowRenderTargetView* view, AppGraphCtx* appctx, NvFlowContext* flowctx); + +#endif
\ No newline at end of file diff --git a/demo/DemoApp/NvFlowInteropLoader.cpp b/demo/DemoApp/NvFlowInteropLoader.cpp new file mode 100644 index 0000000..6224373 --- /dev/null +++ b/demo/DemoApp/NvFlowInteropLoader.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <SDL.h> + +#include "loader.h" + +#include "NvFlowInterop.h" + +namespace +{ + ModuleLoader<16u, SDL_LoadObject, SDL_UnloadObject, SDL_LoadFunction> g_loader; +} + +void loadNvFlowInterop(AppGraphCtxType type) +{ + const char* moduleName = demoAppDLLName(type); + + g_loader.loadModule(moduleName); +} + +void unloadNvFlowInterop() +{ + g_loader.unloadModule(); +} + +// Functions +NvFlowContext* NvFlowInteropCreateContext(AppGraphCtx* appctx) +{ + return g_loader.function<0>(NvFlowInteropCreateContext, "NvFlowInteropCreateContext", appctx); +} + +NvFlowDepthStencilView* NvFlowInteropCreateDepthStencilView(AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + return g_loader.function<1>(NvFlowInteropCreateDepthStencilView, "NvFlowInteropCreateDepthStencilView", appctx, flowctx); +} + +NvFlowRenderTargetView* NvFlowInteropCreateRenderTargetView(AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + return g_loader.function<2>(NvFlowInteropCreateRenderTargetView, "NvFlowInteropCreateRenderTargetView", appctx, flowctx); +} + +void NvFlowInteropUpdateContext(NvFlowContext* context, AppGraphCtx* appctx) +{ + return g_loader.function<3>(NvFlowInteropUpdateContext, "NvFlowInteropUpdateContext", context, appctx); +} + +void NvFlowInteropUpdateDepthStencilView(NvFlowDepthStencilView* view, AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + return g_loader.function<4>(NvFlowInteropUpdateDepthStencilView, "NvFlowInteropUpdateDepthStencilView", view, appctx, flowctx); +} + +void NvFlowInteropUpdateRenderTargetView(NvFlowRenderTargetView* view, AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + return g_loader.function<5>(NvFlowInteropUpdateRenderTargetView, "NvFlowInteropUpdateRenderTargetView", view, appctx, flowctx); +}
\ No newline at end of file diff --git a/demo/DemoApp/app.manifest b/demo/DemoApp/app.manifest new file mode 100644 index 0000000..5dea26f --- /dev/null +++ b/demo/DemoApp/app.manifest @@ -0,0 +1,7 @@ +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" > + <asmv3:application> + <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> + <dpiAware>true</dpiAware> + </asmv3:windowsSettings> + </asmv3:application> +</assembly>
\ No newline at end of file diff --git a/demo/DemoApp/appGraphCtx.h b/demo/DemoApp/appGraphCtx.h new file mode 100644 index 0000000..2f41c36 --- /dev/null +++ b/demo/DemoApp/appGraphCtx.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +#define APP_GRAPH_CTX_API extern "C" __declspec(dllexport) + +struct SDL_Window; + +struct AppGraphCtx; + +APP_GRAPH_CTX_API AppGraphCtx* AppGraphCtxCreate(int deviceID); + +APP_GRAPH_CTX_API bool AppGraphCtxUpdateSize(AppGraphCtx* context, SDL_Window* window, bool fullscreen); + +APP_GRAPH_CTX_API void AppGraphCtxReleaseRenderTarget(AppGraphCtx* context); + +APP_GRAPH_CTX_API void AppGraphCtxRelease(AppGraphCtx* context); + +APP_GRAPH_CTX_API void AppGraphCtxFrameStart(AppGraphCtx* context, float clearColor[4]); + +APP_GRAPH_CTX_API void AppGraphCtxFramePresent(AppGraphCtx* context, bool fullsync); + +APP_GRAPH_CTX_API void AppGraphCtxWaitForFrames(AppGraphCtx* context, unsigned int maxFramesInFlight); + +APP_GRAPH_CTX_API void AppGraphCtxProfileEnable(AppGraphCtx* context, bool enabled); + +APP_GRAPH_CTX_API void AppGraphCtxProfileBegin(AppGraphCtx* context, const char* label); + +APP_GRAPH_CTX_API void AppGraphCtxProfileEnd(AppGraphCtx* context, const char* label); + +APP_GRAPH_CTX_API bool AppGraphCtxProfileGet(AppGraphCtx* context, const char** plabel, float* cpuTime, float* gpuTime, int index); + +APP_GRAPH_CTX_API size_t AppGraphCtxDedicatedVideoMemory(AppGraphCtx* context);
\ No newline at end of file diff --git a/demo/DemoApp/appGraphCtxLoader.cpp b/demo/DemoApp/appGraphCtxLoader.cpp new file mode 100644 index 0000000..f724a93 --- /dev/null +++ b/demo/DemoApp/appGraphCtxLoader.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <SDL.h> + +#include "loader.h" + +#include "appGraphCtx.h" + +namespace +{ + ModuleLoader<16u, SDL_LoadObject, SDL_UnloadObject, SDL_LoadFunction> g_loader; +} + +void loadAppGraphCtx(AppGraphCtxType type) +{ + const char* moduleName = demoAppDLLName(type); + + g_loader.loadModule(moduleName); +} + +void unloadAppGraphCtx() +{ + g_loader.unloadModule(); +} + +AppGraphCtx* AppGraphCtxCreate(int deviceID) +{ + return g_loader.function<0>(AppGraphCtxCreate, "AppGraphCtxCreate", deviceID); +} + +bool AppGraphCtxUpdateSize(AppGraphCtx* context, SDL_Window* window, bool fullscreen) +{ + return g_loader.function<1>(AppGraphCtxUpdateSize, "AppGraphCtxUpdateSize", context, window, fullscreen); +} + +void AppGraphCtxReleaseRenderTarget(AppGraphCtx* context) +{ + return g_loader.function<2>(AppGraphCtxReleaseRenderTarget, "AppGraphCtxReleaseRenderTarget", context); +} + +void AppGraphCtxRelease(AppGraphCtx* context) +{ + return g_loader.function<3>(AppGraphCtxRelease, "AppGraphCtxRelease", context); +} + +void AppGraphCtxFrameStart(AppGraphCtx* context, float clearColor[4]) +{ + return g_loader.function<4>(AppGraphCtxFrameStart, "AppGraphCtxFrameStart", context, clearColor); +} + +void AppGraphCtxFramePresent(AppGraphCtx* context, bool fullsync) +{ + return g_loader.function<5>(AppGraphCtxFramePresent, "AppGraphCtxFramePresent", context, fullsync); +} + +void AppGraphCtxWaitForFrames(AppGraphCtx* context, unsigned int maxFramesInFlight) +{ + return g_loader.function<6>(AppGraphCtxWaitForFrames, "AppGraphCtxWaitForFrames", context, maxFramesInFlight); +} + +void AppGraphCtxProfileEnable(AppGraphCtx* context, bool enabled) +{ + return g_loader.function<7>(AppGraphCtxProfileEnable, "AppGraphCtxProfileEnable", context, enabled); +} + +void AppGraphCtxProfileBegin(AppGraphCtx* context, const char* label) +{ + return g_loader.function<8>(AppGraphCtxProfileBegin, "AppGraphCtxProfileBegin", context, label); +} + +void AppGraphCtxProfileEnd(AppGraphCtx* context, const char* label) +{ + return g_loader.function<9>(AppGraphCtxProfileEnd, "AppGraphCtxProfileEnd", context, label); +} + +bool AppGraphCtxProfileGet(AppGraphCtx* context, const char** plabel, float* cpuTime, float* gpuTime, int index) +{ + return g_loader.function<10>(AppGraphCtxProfileGet, "AppGraphCtxProfileGet", context, plabel, cpuTime, gpuTime, index); +} + +size_t AppGraphCtxDedicatedVideoMemory(AppGraphCtx* context) +{ + return g_loader.function<11>(AppGraphCtxDedicatedVideoMemory, "AppGraphCtxDedicatedVideoMemory", context); +}
\ No newline at end of file diff --git a/demo/DemoApp/bitmap.cpp b/demo/DemoApp/bitmap.cpp new file mode 100644 index 0000000..e909653 --- /dev/null +++ b/demo/DemoApp/bitmap.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <stdio.h> + +#include "bitmap.h" + +Bitmap::Bitmap() : data(NULL) +{ + +} + +Bitmap::~Bitmap() +{ + delete[] data; + data = NULL; +} + +int Bitmap::create(int w, int h, int bpp) +{ + const int imagesize = w*h*(bpp / 8); + headerField0 = 'B'; + headerField1 = 'M'; + size = 54 + imagesize; + reserved1 = 0; + reserved2 = 0; + offset = 54; + headerSize = 40; + width = w; + height = h; + colorPlanes = 1; + bitsPerPixel = bpp; + compressionMethod = 0; + imageSize = imagesize; + hRes = 2000; + vRes = 2000; + numColors = 0; + numImportantColors = 0; + data = new unsigned char[imagesize]; + return 0; +} + +int Bitmap::write(FILE* stream) +{ + if (stream == NULL || data == NULL) return -1; + fwrite(&headerField0, 1, 1, stream); + fwrite(&headerField1, 1, 1, stream); + fwrite(&size, 4, 1, stream); + fwrite(&reserved1, 2, 1, stream); + fwrite(&reserved2, 2, 1, stream); + fwrite(&offset, 4, 1, stream); + fwrite(&headerSize, 4, 1, stream); + fwrite(&width, 4, 1, stream); + fwrite(&height, 4, 1, stream); + fwrite(&colorPlanes, 2, 1, stream); + fwrite(&bitsPerPixel, 2, 1, stream); + fwrite(&compressionMethod, 4, 1, stream); + fwrite(&imageSize, 4, 1, stream); + fwrite(&hRes, 4, 1, stream); + fwrite(&vRes, 4, 1, stream); + fwrite(&numColors, 4, 1, stream); + fwrite(&numImportantColors, 4, 1, stream); + + if (compressionMethod == 0) + { + fwrite(data, 1, imageSize, stream); + } + else + { + printf("Write format not supported\n"); + return -1; + } + + return 0; +} + +int Bitmap::read(FILE* stream) +{ + if (stream == NULL) return -1; + size_t readCount = 0; + readCount += fread(&headerField0, 1, 1, stream); + readCount += fread(&headerField1, 1, 1, stream); + readCount += fread(&size, 4, 1, stream); + readCount += fread(&reserved1, 2, 1, stream); + readCount += fread(&reserved2, 2, 1, stream); + readCount += fread(&offset, 4, 1, stream); + readCount += fread(&headerSize, 4, 1, stream); + readCount += fread(&width, 4, 1, stream); + readCount += fread(&height, 4, 1, stream); + readCount += fread(&colorPlanes, 2, 1, stream); + readCount += fread(&bitsPerPixel, 2, 1, stream); + readCount += fread(&compressionMethod, 4, 1, stream); + readCount += fread(&imageSize, 4, 1, stream); + readCount += fread(&hRes, 4, 1, stream); + readCount += fread(&vRes, 4, 1, stream); + readCount += fread(&numColors, 4, 1, stream); + readCount += fread(&numImportantColors, 4, 1, stream); + + if (compressionMethod == 0) + { + delete[] data; + data = new unsigned char[imageSize]; + readCount += fread(data, 1, imageSize, stream); + } + else + { + printf("Write format not supported\n"); + return -1; + } + + return 0; +} diff --git a/demo/DemoApp/bitmap.h b/demo/DemoApp/bitmap.h new file mode 100644 index 0000000..092c4be --- /dev/null +++ b/demo/DemoApp/bitmap.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +struct Bitmap +{ + // Header Elements + char headerField0, headerField1; + unsigned int size; + unsigned short reserved1; + unsigned short reserved2; + unsigned int offset; + unsigned int headerSize; + unsigned int width; + unsigned int height; + unsigned short colorPlanes; + unsigned short bitsPerPixel; + unsigned int compressionMethod; + unsigned int imageSize; + unsigned int hRes; + unsigned int vRes; + unsigned int numColors; + unsigned int numImportantColors; + // Internal + unsigned char* data; + + Bitmap(); + ~Bitmap(); + int create(int w, int h, int bpp); + int write(FILE* stream); + int read(FILE* stream); + +}; diff --git a/demo/DemoApp/camera.h b/demo/DemoApp/camera.h new file mode 100644 index 0000000..388d52e --- /dev/null +++ b/demo/DemoApp/camera.h @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#ifndef CAMERA_H +#define CAMERA_H + +#include <stdint.h> +#include <DirectXMath.h> + +struct Camera +{ + uint32_t rotationActive; + uint32_t zoomActive; + uint32_t translateActive; + int mouseXprev; + int mouseYprev; + + float defaultZoomVal; + float zoomVal; + + DirectX::XMMATRIX pan; + DirectX::XMMATRIX tilt; + DirectX::XMMATRIX rotation; + DirectX::XMMATRIX zoom; + DirectX::XMMATRIX translate; + DirectX::XMMATRIX view; + DirectX::XMMATRIX projection; + + bool isProjectionRH = false; + + void getViewMatrix(DirectX::XMMATRIX& viewMatrix) + { + view = + DirectX::XMMatrixMultiply( + DirectX::XMMatrixMultiply( + translate, + rotation + ), + zoom + ); + if (isProjectionRH) + { + view = DirectX::XMMatrixMultiply( + DirectX::XMMatrixMultiply( + DirectX::XMMatrixScaling(1.f, 1.f, -1.f), + view + ), + DirectX::XMMatrixScaling(1.f, 1.f, -1.f) + ); + } + viewMatrix = view; + } + + void getProjectionMatrix(DirectX::XMMATRIX& projMatrix, int winw, int winh) + { + if (isProjectionRH) + { + projection = DirectX::XMMatrixPerspectiveFovRH(DirectX::XM_PI / 4.f, float(winw) / float(winh), 0.1f, 1000.f); + projMatrix = projection; + } + else + { + projection = DirectX::XMMatrixPerspectiveFovLH(DirectX::XM_PI / 4.f, float(winw) / float(winh), 0.1f, 1000.f); + projMatrix = projection; + } + } + + void rotationStart(int x, int y) + { + mouseXprev = x; + mouseYprev = y; + rotationActive = true; + } + + void rotationMove(int x, int y, int winw, int winh) + { + if (rotationActive) + { + int dx = -(x - mouseXprev); + int dy = -(y - mouseYprev); + + const float gainX = 2.f * 3.14f / (winw); + const float gainY = 2.f * 3.14f / (winh); + + float rotx = float(gainY * dy); + float roty = float(gainX * dx); + float rotMagn = sqrtf(rotx*rotx + roty*roty); + + // tilt + { + DirectX::XMVECTOR rotVec = { 1.f,0.f,0.f,0.f }; + const float angle = rotx; + DirectX::XMMATRIX dtilt = DirectX::XMMatrixRotationAxis(rotVec, angle); + tilt = DirectX::XMMatrixMultiply(dtilt, tilt); + } + // pan + { + DirectX::XMVECTOR rotVec = { 0.f,1.f,0.f,0.f }; + const float angle = roty; + DirectX::XMMATRIX dpan = DirectX::XMMatrixRotationAxis(rotVec, angle); + pan = DirectX::XMMatrixMultiply(dpan, pan); + } + rotation = DirectX::XMMatrixMultiply(pan, tilt); + + mouseXprev = x; + mouseYprev = y; + } + } + + void rotationEnd(int x, int y) + { + mouseXprev = x; + mouseYprev = y; + rotationActive = false; + } + + void zoomStart(int x, int y) + { + mouseXprev = x; + mouseYprev = y; + zoomActive = true; + } + + void zoomMove(int x, int y, int winw, int winh) + { + if (zoomActive) + { + float dx = -float(x - mouseXprev); + float dy = -float(y - mouseYprev); + + const float gain = 3.14f / float(winh); + + //zoom = DirectX::XMMatrixMultiply(zoom, DirectX::XMMatrixScaling(1.f, 1.f, 1.f + gain*dy)); + zoomVal *= (1.f + gain*dy); + zoom = DirectX::XMMatrixTranslation(0.f, 0.f, zoomVal); + + mouseXprev = x; + mouseYprev = y; + } + } + + void zoomEnd(int x, int y) + { + mouseXprev = x; + mouseYprev = y; + zoomActive = false; + } + + void translateStart(int x, int y) + { + mouseXprev = x; + mouseYprev = y; + translateActive = true; + } + + void translateMove(int x, int y, int winw, int winh) + { + if (translateActive) + { + float dx = float(x - mouseXprev); + float dy = -float(y - mouseYprev); + + const float gainX = isProjectionRH ? -2.f / (winw) : +2.f / (winw); + const float gainY = isProjectionRH ? -2.f / (winh) : +2.f / (winh); + + // find rotation center in screen space + DirectX::XMVECTOR centerScreen = { 0.f,0.f,0.f,1.f }; + centerScreen = DirectX::XMVector4Transform(centerScreen, DirectX::XMMatrixMultiply(zoom, projection)); + DirectX::XMFLOAT4 centerScreen4; + DirectX::XMStoreFloat4(¢erScreen4, centerScreen); + + // produce transform for inverse project, zoom, rotate + DirectX::XMVECTOR det; + DirectX::XMMATRIX viewProjInv = + DirectX::XMMatrixInverse( + &det, + DirectX::XMMatrixMultiply( + DirectX::XMMatrixMultiply( + rotation, + zoom + ), + projection + ) + ); + + // transform screen offset to world offset + DirectX::XMVECTOR offsetScreen = { gainX*dx, gainY*dy, centerScreen4.z / centerScreen4.w, 1.f }; + DirectX::XMVECTOR offsetWorld = + DirectX::XMVector4Transform( + offsetScreen, + viewProjInv + ); + DirectX::XMFLOAT4 offsetWorld4; + DirectX::XMStoreFloat4(&offsetWorld4, offsetWorld); + offsetWorld4.x /= offsetWorld4.w; + offsetWorld4.y /= offsetWorld4.w; + offsetWorld4.z /= offsetWorld4.w; + + // apply offset to net world translation + translate = + DirectX::XMMatrixMultiply( + DirectX::XMMatrixTranslation(offsetWorld4.x, offsetWorld4.y, offsetWorld4.z), + translate + ); + + mouseXprev = x; + mouseYprev = y; + } + } + + void translateEnd(int x, int y) + { + mouseXprev = x; + mouseYprev = y; + translateActive = false; + } + + void init(int winw, int winh) + { + rotationActive = 0u; + zoomActive = 0u; + translateActive = 0u; + defaultZoomVal = 7.f; + zoomVal = defaultZoomVal; + pan = DirectX::XMMatrixIdentity(); + { + //DirectX::XMVECTOR rotVec = {1.f,0.f,0.f,0.f}; + //const float angle = -DirectX::XM_PI / 4.f; + //tilt = DirectX::XMMatrixRotationAxis(rotVec,angle); + + DirectX::XMVECTOR rotVec = { 1.f,0.f,0.f,0.f }; + const float angle = 0.f; + tilt = DirectX::XMMatrixRotationAxis(rotVec, angle); + } + rotation = DirectX::XMMatrixMultiply(pan, tilt); + zoom = DirectX::XMMatrixTranslation(0.f, 0.f, zoomVal); + translate = DirectX::XMMatrixIdentity(); + view = DirectX::XMMatrixIdentity(); + projection = DirectX::XMMatrixPerspectiveFovLH(DirectX::XM_PI / 4.f, float(winw) / float(winh), 0.1f, 1000.f); + } + + Camera() + { + init(1024, 1024); + } +}; + +#endif
\ No newline at end of file diff --git a/demo/DemoApp/computeContext.h b/demo/DemoApp/computeContext.h new file mode 100644 index 0000000..bd55f13 --- /dev/null +++ b/demo/DemoApp/computeContext.h @@ -0,0 +1,103 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#pragma once + +#define COMPUTE_API extern "C" __declspec(dllexport) + +struct ComputeContextDesc; +struct ComputeContext; + +struct ComputeShaderDesc +{ + const void* cs; + unsigned long long cs_length; +}; +struct ComputeShader; + +struct ComputeConstantBufferDesc +{ + unsigned int sizeInBytes; +}; +struct ComputeConstantBuffer; + +struct ComputeResourceDesc; +struct ComputeResource; + +struct ComputeResourceRWDesc; +struct ComputeResourceRW; + +static const unsigned int ComputeDispatchMaxResources = 16u; +static const unsigned int ComputeDispatchMaxResourcesRW = 8u; + +struct ComputeDispatchParams +{ + ComputeShader* shader; + unsigned int gridDim[3u]; + ComputeConstantBuffer* constantBuffer; + ComputeResource* resources[ComputeDispatchMaxResources]; + ComputeResourceRW* resourcesRW[ComputeDispatchMaxResourcesRW]; +}; + +COMPUTE_API ComputeContext* ComputeContextCreate(ComputeContextDesc* desc); + +COMPUTE_API void ComputeContextUpdate(ComputeContext* context, ComputeContextDesc* desc); + +COMPUTE_API void ComputeContextRelease(ComputeContext* context); + + +COMPUTE_API ComputeShader* ComputeShaderCreate(ComputeContext* context, const ComputeShaderDesc* desc); + +COMPUTE_API void ComputeShaderRelease(ComputeShader* shader); + + +COMPUTE_API ComputeConstantBuffer* ComputeConstantBufferCreate(ComputeContext* context, const ComputeConstantBufferDesc* desc); + +COMPUTE_API void ComputeConstantBufferRelease(ComputeConstantBuffer* constantBuffer); + +COMPUTE_API void* ComputeConstantBufferMap(ComputeContext* context, ComputeConstantBuffer* constantBuffer); + +COMPUTE_API void ComputeConstantBufferUnmap(ComputeContext* context, ComputeConstantBuffer* constantBuffer); + + +COMPUTE_API ComputeResource* ComputeResourceCreate(ComputeContext* context, const ComputeResourceDesc* desc); + +COMPUTE_API void ComputeResourceUpdate(ComputeContext* context, ComputeResource* resource, const ComputeResourceDesc* desc); + +COMPUTE_API void ComputeResourceRelease(ComputeResource* resource); + + +COMPUTE_API ComputeResourceRW* ComputeResourceRWCreate(ComputeContext* context, const ComputeResourceRWDesc* desc); + +COMPUTE_API void ComputeResourceRWUpdate(ComputeContext* context, ComputeResourceRW* resourceRW, const ComputeResourceRWDesc* desc); + +COMPUTE_API void ComputeResourceRWRelease(ComputeResourceRW* resourceRW); + +COMPUTE_API ComputeResource* ComputeResourceRWGetResource(ComputeResourceRW* resourceRW); + + +COMPUTE_API void ComputeContextDispatch(ComputeContext* context, const ComputeDispatchParams* params); + +// interoperation with NvFlow +struct NvFlowContext; +struct NvFlowResource; +struct NvFlowResourceRW; + +COMPUTE_API ComputeContext* ComputeContextNvFlowContextCreate(NvFlowContext* flowContext); + +COMPUTE_API void ComputeContextNvFlowContextUpdate(ComputeContext* computeContext, NvFlowContext* flowContext); + +COMPUTE_API ComputeResource* ComputeResourceNvFlowCreate(ComputeContext* context, NvFlowContext* flowContext, NvFlowResource* flowResource); + +COMPUTE_API void ComputeResourceNvFlowUpdate(ComputeContext* context, ComputeResource* resource, NvFlowContext* flowContext, NvFlowResource* flowResource); + +COMPUTE_API ComputeResourceRW* ComputeResourceRWNvFlowCreate(ComputeContext* context, NvFlowContext* flowContext, NvFlowResourceRW* flowResourceRW); + +COMPUTE_API void ComputeResourceRWNvFlowUpdate(ComputeContext* context, ComputeResourceRW* resourceRW, NvFlowContext* flowContext, NvFlowResourceRW* flowResourceRW);
\ No newline at end of file diff --git a/demo/DemoApp/computeContextLoader.cpp b/demo/DemoApp/computeContextLoader.cpp new file mode 100644 index 0000000..593b2ce --- /dev/null +++ b/demo/DemoApp/computeContextLoader.cpp @@ -0,0 +1,147 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include <SDL.h> + +#include "loader.h" + +#include "computeContext.h" + +namespace +{ + ModuleLoader<32u, SDL_LoadObject, SDL_UnloadObject, SDL_LoadFunction> g_loader; +} + +void loadComputeContext(AppGraphCtxType type) +{ + const char* moduleName = demoAppDLLName(type); + + g_loader.loadModule(moduleName); +} + +void unloadComputeContext() +{ + g_loader.unloadModule(); +} + +ComputeContext* ComputeContextCreate(ComputeContextDesc* desc) +{ + return g_loader.function<0>(ComputeContextCreate, "ComputeContextCreate", desc); +} + +void ComputeContextUpdate(ComputeContext* context, ComputeContextDesc* desc) +{ + return g_loader.function<1>(ComputeContextUpdate, "ComputeContextUpdate", context, desc); +} + +void ComputeContextRelease(ComputeContext* context) +{ + return g_loader.function<2>(ComputeContextRelease, "ComputeContextRelease", context); +} + +ComputeShader* ComputeShaderCreate(ComputeContext* context, const ComputeShaderDesc* desc) +{ + return g_loader.function<3>(ComputeShaderCreate, "ComputeShaderCreate", context, desc); +} + +void ComputeShaderRelease(ComputeShader* shader) +{ + return g_loader.function<4>(ComputeShaderRelease, "ComputeShaderRelease", shader); +} + +ComputeConstantBuffer* ComputeConstantBufferCreate(ComputeContext* context, const ComputeConstantBufferDesc* desc) +{ + return g_loader.function<5>(ComputeConstantBufferCreate, "ComputeConstantBufferCreate", context, desc); +} + +void ComputeConstantBufferRelease(ComputeConstantBuffer* constantBuffer) +{ + return g_loader.function<6>(ComputeConstantBufferRelease, "ComputeConstantBufferRelease", constantBuffer); +} + +void* ComputeConstantBufferMap(ComputeContext* context, ComputeConstantBuffer* constantBuffer) +{ + return g_loader.function<7>(ComputeConstantBufferMap, "ComputeConstantBufferMap", context, constantBuffer); +} + +void ComputeConstantBufferUnmap(ComputeContext* context, ComputeConstantBuffer* constantBuffer) +{ + return g_loader.function<8>(ComputeConstantBufferUnmap, "ComputeConstantBufferUnmap", context, constantBuffer); +} + +ComputeResource* ComputeResourceCreate(ComputeContext* context, const ComputeResourceDesc* desc) +{ + return g_loader.function<9>(ComputeResourceCreate, "ComputeResourceCreate", context, desc); +} + +void ComputeResourceUpdate(ComputeContext* context, ComputeResource* resource, const ComputeResourceDesc* desc) +{ + return g_loader.function<10>(ComputeResourceUpdate, "ComputeResourceUpdate", context, resource, desc); +} + +void ComputeResourceRelease(ComputeResource* resource) +{ + return g_loader.function<11>(ComputeResourceRelease, "ComputeResourceRelease", resource); +} + +ComputeResourceRW* ComputeResourceRWCreate(ComputeContext* context, const ComputeResourceRWDesc* desc) +{ + return g_loader.function<12>(ComputeResourceRWCreate, "ComputeResourceRWCreate", context, desc); +} + +void ComputeResourceRWUpdate(ComputeContext* context, ComputeResourceRW* resourceRW, const ComputeResourceRWDesc* desc) +{ + return g_loader.function<13>(ComputeResourceRWUpdate, "ComputeResourceRWUpdate", context, resourceRW, desc); +} + +void ComputeResourceRWRelease(ComputeResourceRW* resourceRW) +{ + return g_loader.function<14>(ComputeResourceRWRelease, "ComputeResourceRWRelease", resourceRW); +} + +void ComputeContextDispatch(ComputeContext* context, const ComputeDispatchParams* params) +{ + return g_loader.function<15>(ComputeContextDispatch, "ComputeContextDispatch", context, params); +} + +ComputeContext* ComputeContextNvFlowContextCreate(NvFlowContext* flowContext) +{ + return g_loader.function<16>(ComputeContextNvFlowContextCreate, "ComputeContextNvFlowContextCreate", flowContext); +} + +void ComputeContextNvFlowContextUpdate(ComputeContext* computeContext, NvFlowContext* flowContext) +{ + return g_loader.function<17>(ComputeContextNvFlowContextUpdate, "ComputeContextNvFlowContextUpdate", computeContext, flowContext); +} + +ComputeResource* ComputeResourceNvFlowCreate(ComputeContext* context, NvFlowContext* flowContext, NvFlowResource* flowResource) +{ + return g_loader.function<18>(ComputeResourceNvFlowCreate, "ComputeResourceNvFlowCreate", context, flowContext, flowResource); +} + +void ComputeResourceNvFlowUpdate(ComputeContext* context, ComputeResource* resource, NvFlowContext* flowContext, NvFlowResource* flowResource) +{ + return g_loader.function<19>(ComputeResourceNvFlowUpdate, "ComputeResourceNvFlowUpdate", context, resource, flowContext, flowResource); +} + +ComputeResourceRW* ComputeResourceRWNvFlowCreate(ComputeContext* context, NvFlowContext* flowContext, NvFlowResourceRW* flowResourceRW) +{ + return g_loader.function<20>(ComputeResourceRWNvFlowCreate, "ComputeResourceRWNvFlowCreate", context, flowContext, flowResourceRW); +} + +void ComputeResourceRWNvFlowUpdate(ComputeContext* context, ComputeResourceRW* resourceRW, NvFlowContext* flowContext, NvFlowResourceRW* flowResourceRW) +{ + return g_loader.function<21>(ComputeResourceRWNvFlowUpdate, "ComputeResourceRWNvFlowUpdate", context, resourceRW, flowContext, flowResourceRW); +} + +ComputeResource* ComputeResourceRWGetResource(ComputeResourceRW* resourceRW) +{ + return g_loader.function<22>(ComputeResourceRWGetResource, "ComputeResourceRWGetResource", resourceRW); +}
\ No newline at end of file diff --git a/demo/DemoApp/curveEditor.cpp b/demo/DemoApp/curveEditor.cpp new file mode 100644 index 0000000..095ca17 --- /dev/null +++ b/demo/DemoApp/curveEditor.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include "imgui.h" + +#include "curveEditor.h" + +namespace +{ + unsigned char colorInByte(float v) + { + const float cScale = 255.f; + v *= cScale; + if (v < 0.f) v = 0.f; + if (v > 255.f) v = 255.f; + return (unsigned char) v; + } + + unsigned int colorInBytes(float r, float g, float b, float a) + { + return imguiRGBA(colorInByte(r), colorInByte(g), colorInByte(b), colorInByte(a)); + } +}; + +bool curveEditor(CurveEditState* editState, const CurveEditParams* params) +{ + const float sliderWidth = 256u; + + const float border = 20; + const float ptSize0 = 12.f; + const float ptOffset0 = -6.f; + const float ptSize1 = 9.f; + const float ptOffset1 = -4.5f; + + float graphx = params->editorBounds.x + border; + float graphy = params->editorBounds.y + border; + float graphw = float(params->editorBounds.w - 2 * border) - sliderWidth - border; + float graphh = float(params->editorBounds.h - 2 * border); + + float xscale = graphw / (params->rangeMax.x - params->rangeMin.x); + float ascale = graphh / (params->rangeMax.a - params->rangeMin.a); + float xoffset = -xscale * params->rangeMin.x + graphx; + float aoffset = -ascale * params->rangeMin.a + graphy; + + bool isMouseOverPoint = false; + int mousePointIdx = 0; + int mx = params->mouseState.x; + int my = params->mouseState.y; + + bool modified = false; + { + // make a copy of the active point, in case it is modified + editState->point = params->points[editState->activePointIndex]; + } + + // draw graph backgroud + { + imguiDrawRoundedRect( + (float)params->editorBounds.x, + (float)params->editorBounds.y, + (float)params->editorBounds.w - sliderWidth - border, + (float)params->editorBounds.h, + 6.f, + imguiRGBA(0, 0, 0, 192) + ); + } + + // draw border + { + float pts[4][2] = { + { graphx, graphy }, + { graphx + graphw, graphy }, + { graphx + graphw, graphy + graphh }, + { graphx, graphy + graphh } + }; + imguiDrawLine(pts[0][0], pts[0][1], pts[1][0], pts[1][1], 2.f, 0xCFCFCFCF); + imguiDrawLine(pts[1][0], pts[1][1], pts[2][0], pts[2][1], 2.f, 0xCFCFCFCF); + imguiDrawLine(pts[2][0], pts[2][1], pts[3][0], pts[3][1], 2.f, 0xCFCFCFCF); + imguiDrawLine(pts[3][0], pts[3][1], pts[0][0], pts[0][1], 2.f, 0xCFCFCFCF); + } + + // process mouse input + { + // check if mouse is still active + if ((params->mouseState.but & IMGUI_MBUT_LEFT) == 0) + { + editState->pointMoveActive = false; + } + // check for overlap + if (!editState->pointMoveActive) + { + for (unsigned int i = 0; i < params->numPoints; i++) + { + CurvePoint& pt = params->points[i]; + + float x = xscale * pt.x + xoffset; + float a = ascale * pt.a + aoffset; + + // check if mouse overlaps point + if (float(mx) >= x + ptOffset0 && float(mx) <= x - ptOffset0 && + float(my) >= a + ptOffset0 && float(my) <= a - ptOffset0) + { + isMouseOverPoint = true; + mousePointIdx = i; + } + } + } + // support dragging points + if (isMouseOverPoint) + { + if (params->mouseState.but & IMGUI_MBUT_LEFT) + { + if (editState->activePointIndex != mousePointIdx) + { + editState->activePointIndex = mousePointIdx; + editState->point = params->points[editState->activePointIndex]; + } + if (!editState->pointMoveActive) + { + editState->pointMoveActive = true; + editState->pointMoveX = mx; + editState->pointMoveY = my; + } + } + } + if (editState->pointMoveActive) + { + CurvePoint& pt = params->points[editState->activePointIndex]; + + int dmx = mx - editState->pointMoveX; + int dmy = my - editState->pointMoveY; + editState->pointMoveX = mx; + editState->pointMoveY = my; + + // inverse transform + float dx = dmx / xscale; + float da = dmy / ascale; + + auto& point = editState->point; + point = pt; + point.x += dx; + point.a += da; + + modified = true; + } + } + + // draw lines and points + { + float x0, a0, x1, a1; + { + CurvePoint& pt = params->points[0]; + + x0 = xscale * pt.x + xoffset; + a0 = ascale * pt.a + aoffset; + } + for (unsigned int i = 1; i < params->numPoints; i++) + { + CurvePoint& pt = params->points[i]; + + // scale based on min max + x1 = xscale * pt.x + xoffset; + a1 = ascale * pt.a + aoffset; + + imguiDrawLine(x0, a0, x1, a1, 2.f, 0xFFFFFFFF); + + x0 = x1; + a0 = a1; + } + + int activeIdx = editState->activePointIndex; + unsigned int activeColor = imguiRGBA(255, 196, 0, 255); + for (unsigned int i = 0; i < params->numPoints; i++) + { + CurvePoint& pt = params->points[i]; + + float x = xscale * pt.x + xoffset; + float a = ascale * pt.a + aoffset; + + imguiDrawRect(x + ptOffset0, a + ptOffset0, ptSize0, ptSize0, (i == activeIdx) ? activeColor : 0xFFFFFFFF); + imguiDrawRect(x + ptOffset1, a + ptOffset1, ptSize1, ptSize1, colorInBytes(pt.r, pt.g, pt.b, 1.f)); + } + // highlight mouse point as needed + if (isMouseOverPoint) + { + unsigned int mouseColor = imguiRGBA(255, 196, 0, 128); + + CurvePoint& pt = params->points[mousePointIdx]; + + float x = xscale * pt.x + xoffset; + float a = ascale * pt.a + aoffset; + + imguiDrawRect(x + ptOffset0, a + ptOffset0, ptSize0, ptSize0, mouseColor); + } + } + + // sliders + { + static int scroll = 0; + + imguiBeginScrollArea("Curve Editor", + int(graphx + graphw + 2 * border), int(params->editorBounds.y), + int(params->editorBounds.w - graphw - 3*border), int(params->editorBounds.h), + &scroll); + + // keep active index valid + if (editState->activePointIndex >= (int)params->numPoints) + { + editState->activePointIndex = params->numPoints - 1; + if (editState->activePointIndex < 0) editState->activePointIndex = 0; + } + + float val = float(editState->activePointIndex); + if(imguiSlider("Active Point ID", &val, 0.f, float(params->numPoints) - 1.f, 1.f, true)) + { + editState->activePointIndex = int(val); + editState->point = params->points[editState->activePointIndex]; + } + + imguiSeparatorLine(); + + // get active point data + auto& point = editState->point; + + if (imguiSlider("x", &point.x, params->rangeMin.x, params->rangeMax.x, 0.01f, true)) modified = true; + if (imguiSlider("r", &point.r, params->rangeMin.r, params->rangeMax.r, 0.01f, true)) modified = true; + if (imguiSlider("g", &point.g, params->rangeMin.g, params->rangeMax.g, 0.01f, true)) modified = true; + if (imguiSlider("b", &point.b, params->rangeMin.b, params->rangeMax.b, 0.01f, true)) modified = true; + if (imguiSlider("a", &point.a, params->rangeMin.a, params->rangeMax.a, 0.01f, true)) modified = true; + + // enforce constraints + { + int activeIdx = editState->activePointIndex; + + // do not allow points to cross with their neighbors + if (activeIdx > 0) + { + float xmin = params->points[activeIdx - 1].x; + if (point.x < xmin) + { + point.x = xmin; + modified = true; + } + } + if (activeIdx + 1 < (int)params->numPoints) + { + float xmax = params->points[activeIdx + 1].x; + if (point.x > xmax) + { + point.x = xmax; + modified = true; + } + } + + // enforce that curve must span x range + { + if (activeIdx == 0) + { + point.x = params->rangeMin.x; + modified = true; + } + if (activeIdx == params->numPoints - 1) + { + point.x = params->rangeMax.x; + modified = true; + } + } + } + + editState->action = modified ? CURVE_POINT_MODIFY : CURVE_POINT_NO_ACTION; + + if (imguiButton("Add Point", true)) + { + editState->action = CURVE_POINT_INSERT; + // generate interpolated new point + int bidx = editState->activePointIndex + 1; + if (bidx >= (int)params->numPoints) + { + bidx = editState->activePointIndex; + } + else + { + editState->activePointIndex++; + } + + const auto ptb = params->points[bidx]; + point.x = 0.5f * point.x + 0.5f * ptb.x; + point.r = 0.5f * point.r + 0.5f * ptb.r; + point.g = 0.5f * point.g + 0.5f * ptb.g; + point.b = 0.5f * point.b + 0.5f * ptb.b; + point.a = 0.5f * point.a + 0.5f * ptb.a; + } + + if (imguiButton("Remove Point", true)) + { + // ignore if 2 or less + if (params->numPoints > 2) + { + editState->action = CURVE_POINT_REMOVE; + } + } + + imguiEndScrollArea(); + } + + return (editState->action != CURVE_POINT_NO_ACTION); +}
\ No newline at end of file diff --git a/demo/DemoApp/curveEditor.h b/demo/DemoApp/curveEditor.h new file mode 100644 index 0000000..f20fb5b --- /dev/null +++ b/demo/DemoApp/curveEditor.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +struct CurveMouseState +{ + int x; + int y; + unsigned char but; +}; + +struct CurveEditorBounds +{ + int x, y, w, h; +}; + +struct CurvePoint +{ + float x; + float r, g, b, a; +}; + +enum CurvePointAction +{ + CURVE_POINT_NO_ACTION, + CURVE_POINT_MODIFY, + CURVE_POINT_INSERT, + CURVE_POINT_REMOVE, +}; + +struct CurveEditParams +{ + CurveMouseState mouseState; + CurveEditorBounds editorBounds; + CurvePoint rangeMin; + CurvePoint rangeMax; + CurvePoint* points; + unsigned int numPoints; +}; + +struct CurveEditState +{ + int activePointIndex; + int action; + bool pointMoveActive; + int pointMoveX; + int pointMoveY; + CurvePoint point; +}; + +bool curveEditor(CurveEditState* editState, const CurveEditParams* params);
\ No newline at end of file diff --git a/demo/DemoApp/customEmitAllocCS.hlsl.h b/demo/DemoApp/customEmitAllocCS.hlsl.h new file mode 100644 index 0000000..64e7d9e --- /dev/null +++ b/demo/DemoApp/customEmitAllocCS.hlsl.h @@ -0,0 +1,225 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer params +// { +// +// uint4 minMaskIdx; // Offset: 0 Size: 16 +// uint4 maxMaskIdx; // Offset: 16 Size: 16 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// maskUAV UAV uint 3d u0 1 +// params cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[2], immediateIndexed +dcl_uav_typed_texture3d (uint,uint,uint,uint) u0 +dcl_input vThreadID.xyz +dcl_temps 2 +dcl_thread_group 8, 8, 8 +iadd r0.xyzw, vThreadID.xyzz, cb0[0].xyzz +ige r1.xyz, r0.xywx, cb0[0].xyzx +and r1.x, r1.y, r1.x +and r1.x, r1.z, r1.x +ilt r1.yzw, r0.xxyw, cb0[1].xxyz +and r1.y, r1.z, r1.y +and r1.y, r1.w, r1.y +and r1.x, r1.y, r1.x +if_nz r1.x + store_uav_typed u0.xyzw, r0.xyzw, l(1,1,1,1) +endif +ret +// Approximately 12 instruction slots used +#endif + +const BYTE g_customEmitAllocCS[] = +{ + 68, 88, 66, 67, 40, 49, + 206, 141, 171, 96, 209, 139, + 236, 95, 146, 56, 48, 52, + 47, 50, 1, 0, 0, 0, + 212, 3, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 160, 1, 0, 0, 176, 1, + 0, 0, 192, 1, 0, 0, + 56, 3, 0, 0, 82, 68, + 69, 70, 100, 1, 0, 0, + 1, 0, 0, 0, 140, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 83, 67, 0, 1, 0, 0, + 59, 1, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 124, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 132, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 109, 97, + 115, 107, 85, 65, 86, 0, + 112, 97, 114, 97, 109, 115, + 0, 171, 132, 0, 0, 0, + 2, 0, 0, 0, 164, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 244, 0, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 2, 0, 0, 0, + 12, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 48, 1, 0, 0, 16, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 12, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 109, 105, + 110, 77, 97, 115, 107, 73, + 100, 120, 0, 78, 118, 70, + 108, 111, 119, 85, 105, 110, + 116, 52, 0, 171, 1, 0, + 19, 0, 1, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 0, 0, 0, 109, 97, + 120, 77, 97, 115, 107, 73, + 100, 120, 0, 77, 105, 99, + 114, 111, 115, 111, 102, 116, + 32, 40, 82, 41, 32, 72, + 76, 83, 76, 32, 83, 104, + 97, 100, 101, 114, 32, 67, + 111, 109, 112, 105, 108, 101, + 114, 32, 49, 48, 46, 49, + 0, 171, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 112, 1, 0, 0, + 80, 0, 5, 0, 92, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 156, 40, + 0, 4, 0, 224, 17, 0, + 0, 0, 0, 0, 68, 68, + 0, 0, 95, 0, 0, 2, + 114, 0, 2, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 155, 0, 0, 4, 8, 0, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 10, + 2, 0, 70, 138, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 8, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 3, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 34, 0, 0, 8, 226, 0, + 16, 0, 1, 0, 0, 0, + 6, 13, 16, 0, 0, 0, + 0, 0, 6, 137, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 164, 0, 0, 10, + 242, 224, 17, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 21, 0, 0, 1, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 12, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 5, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0 +}; diff --git a/demo/DemoApp/customEmitEmit2CS.hlsl.h b/demo/DemoApp/customEmitEmit2CS.hlsl.h new file mode 100644 index 0000000..7bbd512 --- /dev/null +++ b/demo/DemoApp/customEmitEmit2CS.hlsl.h @@ -0,0 +1,503 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer params +// { +// +// struct NvFlowShaderPointParams +// { +// +// uint4 isVTR; // Offset: 0 +// uint4 blockDim; // Offset: 16 +// uint4 blockDimBits; // Offset: 32 +// uint4 poolGridDim; // Offset: 48 +// uint4 gridDim; // Offset: 64 +// +// } customEmitParams; // Offset: 0 Size: 80 +// uint4 minVidx; // Offset: 80 Size: 16 +// uint4 maxVidx; // Offset: 96 Size: 16 +// float4 targetValue; // Offset: 112 Size: 16 +// float4 blendRate; // Offset: 128 Size: 16 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// blockList texture uint buf t0 1 +// blockTable texture uint 3d t1 1 +// dataSRV texture float4 3d t2 1 +// dataUAV UAV float4 3d u0 1 +// params cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[9], immediateIndexed +dcl_resource_buffer (uint,uint,uint,uint) t0 +dcl_resource_texture3d (uint,uint,uint,uint) t1 +dcl_resource_texture3d (float,float,float,float) t2 +dcl_uav_typed_texture3d (float,float,float,float) u0 +dcl_input vThreadID.xyz +dcl_temps 6 +dcl_thread_group 8, 8, 8 +ushr r0.x, vThreadID.x, cb0[2].x +ld_indexable(buffer)(uint,uint,uint,uint) r0.x, r0.xxxx, t0.xyzw +not r0.x, r0.x +and r1.x, r0.x, l(1023) +ubfe r1.yz, l(0, 10, 10, 0), l(0, 10, 20, 0), r0.xxxx +ishl r0.xyz, r1.xyzx, cb0[2].xyzx +iadd r1.xyz, cb0[1].xyzx, l(-1, -1, -1, 0) +and r2.xyz, r1.xyzx, vThreadID.xyzx +or r0.xyz, r0.xyzx, r2.xyzx +if_nz cb0[0].x + mov r2.xyz, r0.xyzx +else + ishr r3.xyz, r0.xyzx, cb0[2].xyzx + mov r3.w, l(0) + ld_indexable(texture3d)(uint,uint,uint,uint) r0.w, r3.xyzw, t1.yzwx + not r0.w, r0.w + and r3.x, r0.w, l(1023) + ubfe r3.yz, l(0, 10, 10, 0), l(0, 10, 20, 0), r0.wwww + ishl r3.xyz, r3.xyzx, cb0[2].xyzx + and r1.xyz, r1.xyzx, r0.xyzx + or r2.xyz, r1.xyzx, r3.xyzx +endif +mov r2.w, l(0) +ld_indexable(texture3d)(float,float,float,float) r1.xyzw, r2.xyzw, t2.xyzw +ige r3.xyz, r0.xyzx, cb0[5].xyzx +and r0.w, r3.y, r3.x +and r0.w, r3.z, r0.w +ilt r0.xyz, r0.xyzx, cb0[6].xyzx +and r0.x, r0.y, r0.x +and r0.x, r0.z, r0.x +and r0.x, r0.x, r0.w +add r3.xyzw, -cb0[8].xyzw, l(1.000000, 1.000000, 1.000000, 1.000000) +mul r4.xyzw, cb0[7].xyzw, cb0[8].xyzw +mad r5.xyzw, r3.xyzw, r1.xyzw, r4.xyzw +mad r3.xyzw, r3.xyzw, r5.xyzw, r4.xyzw +movc r0.xyzw, r0.xxxx, r3.xyzw, r1.xyzw +store_uav_typed u0.xyzw, r2.xyzz, r0.xyzw +ret +// Approximately 38 instruction slots used +#endif + +const BYTE g_customEmitEmit2CS[] = +{ + 68, 88, 66, 67, 63, 249, + 53, 68, 110, 243, 167, 44, + 138, 46, 81, 217, 135, 232, + 162, 70, 1, 0, 0, 0, + 80, 9, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 184, 3, 0, 0, 200, 3, + 0, 0, 216, 3, 0, 0, + 180, 8, 0, 0, 82, 68, + 69, 70, 124, 3, 0, 0, + 1, 0, 0, 0, 8, 1, + 0, 0, 5, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 83, 67, 0, 1, 0, 0, + 82, 3, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 1, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 230, 0, 0, 0, + 2, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 255, 255, 255, 255, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 241, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 8, 0, + 0, 0, 255, 255, 255, 255, + 2, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 249, 0, 0, 0, 4, 0, + 0, 0, 5, 0, 0, 0, + 8, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 13, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 98, 108, + 111, 99, 107, 76, 105, 115, + 116, 0, 98, 108, 111, 99, + 107, 84, 97, 98, 108, 101, + 0, 100, 97, 116, 97, 83, + 82, 86, 0, 100, 97, 116, + 97, 85, 65, 86, 0, 112, + 97, 114, 97, 109, 115, 0, + 1, 1, 0, 0, 5, 0, + 0, 0, 32, 1, 0, 0, + 144, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 1, 0, 0, 0, 0, + 0, 0, 80, 0, 0, 0, + 2, 0, 0, 0, 176, 2, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 212, 2, + 0, 0, 80, 0, 0, 0, + 16, 0, 0, 0, 2, 0, + 0, 0, 220, 2, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 3, 0, 0, + 96, 0, 0, 0, 16, 0, + 0, 0, 2, 0, 0, 0, + 220, 2, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 8, 3, 0, 0, 112, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 36, 3, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 72, 3, + 0, 0, 128, 0, 0, 0, + 16, 0, 0, 0, 2, 0, + 0, 0, 36, 3, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 99, 117, 115, 116, + 111, 109, 69, 109, 105, 116, + 80, 97, 114, 97, 109, 115, + 0, 78, 118, 70, 108, 111, + 119, 83, 104, 97, 100, 101, + 114, 80, 111, 105, 110, 116, + 80, 97, 114, 97, 109, 115, + 0, 105, 115, 86, 84, 82, + 0, 78, 118, 70, 108, 111, + 119, 85, 105, 110, 116, 52, + 0, 171, 1, 0, 19, 0, + 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 23, 2, + 0, 0, 98, 108, 111, 99, + 107, 68, 105, 109, 0, 98, + 108, 111, 99, 107, 68, 105, + 109, 66, 105, 116, 115, 0, + 112, 111, 111, 108, 71, 114, + 105, 100, 68, 105, 109, 0, + 103, 114, 105, 100, 68, 105, + 109, 0, 171, 171, 17, 2, + 0, 0, 36, 2, 0, 0, + 0, 0, 0, 0, 72, 2, + 0, 0, 36, 2, 0, 0, + 16, 0, 0, 0, 81, 2, + 0, 0, 36, 2, 0, 0, + 32, 0, 0, 0, 94, 2, + 0, 0, 36, 2, 0, 0, + 48, 0, 0, 0, 106, 2, + 0, 0, 36, 2, 0, 0, + 64, 0, 0, 0, 5, 0, + 0, 0, 1, 0, 20, 0, + 0, 0, 5, 0, 116, 2, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 249, 1, 0, 0, 109, 105, + 110, 86, 105, 100, 120, 0, + 1, 0, 19, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 23, 2, 0, 0, + 109, 97, 120, 86, 105, 100, + 120, 0, 116, 97, 114, 103, + 101, 116, 86, 97, 108, 117, + 101, 0, 78, 118, 70, 108, + 111, 119, 70, 108, 111, 97, + 116, 52, 0, 171, 171, 171, + 1, 0, 3, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 20, 3, 0, 0, + 98, 108, 101, 110, 100, 82, + 97, 116, 101, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 171, 171, 73, 83, + 71, 78, 8, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 79, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 83, 72, 69, 88, 212, 4, + 0, 0, 80, 0, 5, 0, + 53, 1, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 88, 8, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 68, 68, 0, 0, 88, 40, + 0, 4, 0, 112, 16, 0, + 1, 0, 0, 0, 68, 68, + 0, 0, 88, 40, 0, 4, + 0, 112, 16, 0, 2, 0, + 0, 0, 85, 85, 0, 0, + 156, 40, 0, 4, 0, 224, + 17, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 95, 0, + 0, 2, 114, 0, 2, 0, + 104, 0, 0, 2, 6, 0, + 0, 0, 155, 0, 0, 4, + 8, 0, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 85, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 2, 0, 10, 128, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 45, 0, + 0, 137, 66, 0, 0, 128, + 3, 17, 17, 0, 18, 0, + 16, 0, 0, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 70, 126, 16, 0, + 0, 0, 0, 0, 59, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 3, 0, 0, 138, 0, + 0, 15, 98, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 20, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 8, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 30, 0, 0, 11, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 6, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 2, 0, 60, 0, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 4, 10, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 42, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 137, + 66, 1, 0, 128, 3, 17, + 17, 0, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 150, 115, 16, 0, 1, 0, + 0, 0, 59, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 255, 3, + 0, 0, 138, 0, 0, 15, + 98, 0, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 20, 0, + 0, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 41, 0, 0, 8, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 21, 0, 0, 1, 54, 0, + 0, 5, 130, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 137, 66, 1, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 2, 0, 0, 0, + 33, 0, 0, 8, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 1, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 34, 0, + 0, 8, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 12, 242, 0, + 16, 0, 3, 0, 0, 0, + 70, 142, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 56, 0, 0, 9, 242, 0, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 50, 0, 0, 9, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 242, 0, + 16, 0, 3, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 55, 0, 0, 9, 242, 0, + 16, 0, 0, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 164, 0, 0, 7, 242, 224, + 17, 0, 0, 0, 0, 0, + 70, 10, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 38, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 6, 0, 0, 0, 14, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0 +}; diff --git a/demo/DemoApp/customEmitEmitCS.hlsl.h b/demo/DemoApp/customEmitEmitCS.hlsl.h new file mode 100644 index 0000000..aad9db6 --- /dev/null +++ b/demo/DemoApp/customEmitEmitCS.hlsl.h @@ -0,0 +1,431 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer params +// { +// +// struct NvFlowShaderPointParams +// { +// +// uint4 isVTR; // Offset: 0 +// uint4 blockDim; // Offset: 16 +// uint4 blockDimBits; // Offset: 32 +// uint4 poolGridDim; // Offset: 48 +// uint4 gridDim; // Offset: 64 +// +// } customEmitParams; // Offset: 0 Size: 80 +// uint4 minVidx; // Offset: 80 Size: 16 +// uint4 maxVidx; // Offset: 96 Size: 16 +// float4 targetValue; // Offset: 112 Size: 16 +// float4 blendRate; // Offset: 128 Size: 16 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// blockTable texture uint 3d t1 1 +// dataSRV texture float4 3d t2 1 +// dataUAV UAV float4 3d u0 1 +// params cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[9], immediateIndexed +dcl_resource_texture3d (uint,uint,uint,uint) t1 +dcl_resource_texture3d (float,float,float,float) t2 +dcl_uav_typed_texture3d (float,float,float,float) u0 +dcl_input vThreadID.xyz +dcl_temps 4 +dcl_thread_group 8, 8, 8 +iadd r0.xyz, vThreadID.xyzx, cb0[5].xyzx +ige r1.xyz, r0.xyzx, cb0[5].xyzx +and r1.x, r1.y, r1.x +and r1.x, r1.z, r1.x +ilt r1.yzw, r0.xxyz, cb0[6].xxyz +and r1.y, r1.z, r1.y +and r1.y, r1.w, r1.y +and r1.x, r1.y, r1.x +if_nz r1.x + if_z cb0[0].x + ishr r1.xyz, r0.xyzx, cb0[2].xyzx + mov r1.w, l(0) + ld_indexable(texture3d)(uint,uint,uint,uint) r1.x, r1.xyzw, t1.xyzw + not r1.x, r1.x + and r2.x, r1.x, l(1023) + ubfe r2.yz, l(0, 10, 10, 0), l(0, 10, 20, 0), r1.xxxx + ishl r1.xyz, r2.xyzx, cb0[2].xyzx + iadd r2.xyz, cb0[1].xyzx, l(-1, -1, -1, 0) + and r2.xyz, r0.xyzx, r2.xyzx + or r0.xyz, r1.xyzx, r2.xyzx + endif + mov r0.w, l(0) + ld_indexable(texture3d)(float,float,float,float) r1.xyzw, r0.xyzw, t2.xyzw + add r2.xyzw, -cb0[8].xyzw, l(1.000000, 1.000000, 1.000000, 1.000000) + mul r3.xyzw, cb0[7].xyzw, cb0[8].xyzw + mad r1.xyzw, r2.xyzw, r1.xyzw, r3.xyzw + store_uav_typed u0.xyzw, r0.xyzz, r1.xyzw +endif +ret +// Approximately 29 instruction slots used +#endif + +const BYTE g_customEmitEmitCS[] = +{ + 68, 88, 66, 67, 185, 132, + 145, 219, 25, 247, 37, 83, + 81, 8, 147, 1, 228, 138, + 141, 6, 1, 0, 0, 0, + 228, 7, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 144, 3, 0, 0, 160, 3, + 0, 0, 176, 3, 0, 0, + 72, 7, 0, 0, 82, 68, + 69, 70, 84, 3, 0, 0, + 1, 0, 0, 0, 224, 0, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 83, 67, 0, 1, 0, 0, + 42, 3, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 188, 0, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 199, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 255, 255, 255, 255, 2, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 207, 0, + 0, 0, 4, 0, 0, 0, + 5, 0, 0, 0, 8, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 215, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 98, 108, 111, 99, + 107, 84, 97, 98, 108, 101, + 0, 100, 97, 116, 97, 83, + 82, 86, 0, 100, 97, 116, + 97, 85, 65, 86, 0, 112, + 97, 114, 97, 109, 115, 0, + 171, 171, 215, 0, 0, 0, + 5, 0, 0, 0, 248, 0, + 0, 0, 144, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 192, 1, 0, 0, + 0, 0, 0, 0, 80, 0, + 0, 0, 2, 0, 0, 0, + 136, 2, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 172, 2, 0, 0, 80, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 180, 2, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 216, 2, + 0, 0, 96, 0, 0, 0, + 16, 0, 0, 0, 2, 0, + 0, 0, 180, 2, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 224, 2, 0, 0, + 112, 0, 0, 0, 16, 0, + 0, 0, 2, 0, 0, 0, + 252, 2, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 32, 3, 0, 0, 128, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 252, 2, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 99, 117, + 115, 116, 111, 109, 69, 109, + 105, 116, 80, 97, 114, 97, + 109, 115, 0, 78, 118, 70, + 108, 111, 119, 83, 104, 97, + 100, 101, 114, 80, 111, 105, + 110, 116, 80, 97, 114, 97, + 109, 115, 0, 105, 115, 86, + 84, 82, 0, 78, 118, 70, + 108, 111, 119, 85, 105, 110, + 116, 52, 0, 171, 1, 0, + 19, 0, 1, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 239, 1, 0, 0, 98, 108, + 111, 99, 107, 68, 105, 109, + 0, 98, 108, 111, 99, 107, + 68, 105, 109, 66, 105, 116, + 115, 0, 112, 111, 111, 108, + 71, 114, 105, 100, 68, 105, + 109, 0, 103, 114, 105, 100, + 68, 105, 109, 0, 171, 171, + 233, 1, 0, 0, 252, 1, + 0, 0, 0, 0, 0, 0, + 32, 2, 0, 0, 252, 1, + 0, 0, 16, 0, 0, 0, + 41, 2, 0, 0, 252, 1, + 0, 0, 32, 0, 0, 0, + 54, 2, 0, 0, 252, 1, + 0, 0, 48, 0, 0, 0, + 66, 2, 0, 0, 252, 1, + 0, 0, 64, 0, 0, 0, + 5, 0, 0, 0, 1, 0, + 20, 0, 0, 0, 5, 0, + 76, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 209, 1, 0, 0, + 109, 105, 110, 86, 105, 100, + 120, 0, 1, 0, 19, 0, + 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 239, 1, + 0, 0, 109, 97, 120, 86, + 105, 100, 120, 0, 116, 97, + 114, 103, 101, 116, 86, 97, + 108, 117, 101, 0, 78, 118, + 70, 108, 111, 119, 70, 108, + 111, 97, 116, 52, 0, 171, + 171, 171, 1, 0, 3, 0, + 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 236, 2, + 0, 0, 98, 108, 101, 110, + 100, 82, 97, 116, 101, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 171, 171, + 73, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 79, 83, + 71, 78, 8, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 83, 72, 69, 88, + 144, 3, 0, 0, 80, 0, + 5, 0, 228, 0, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 9, 0, + 0, 0, 88, 40, 0, 4, + 0, 112, 16, 0, 1, 0, + 0, 0, 68, 68, 0, 0, + 88, 40, 0, 4, 0, 112, + 16, 0, 2, 0, 0, 0, + 85, 85, 0, 0, 156, 40, + 0, 4, 0, 224, 17, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 95, 0, 0, 2, + 114, 0, 2, 0, 104, 0, + 0, 2, 4, 0, 0, 0, + 155, 0, 0, 4, 8, 0, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 30, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 2, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 33, 0, 0, 8, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 34, 0, 0, 8, 226, 0, + 16, 0, 1, 0, 0, 0, + 6, 9, 16, 0, 0, 0, + 0, 0, 6, 137, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 1, 0, 0, 7, + 34, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 34, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 1, 0, + 0, 7, 18, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 1, 0, + 0, 0, 31, 0, 0, 4, + 10, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 42, 0, 0, 8, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 137, 66, 1, 0, 128, + 3, 17, 17, 0, 18, 0, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 126, 16, 0, + 1, 0, 0, 0, 59, 0, + 0, 5, 18, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 3, 0, 0, 138, 0, + 0, 15, 98, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 20, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 1, 0, 0, 0, 41, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 30, 0, 0, 11, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 60, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 21, 0, + 0, 1, 54, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 137, 66, 1, 0, 128, + 67, 85, 21, 0, 242, 0, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 70, 126, 16, 0, + 2, 0, 0, 0, 0, 0, + 0, 12, 242, 0, 16, 0, + 2, 0, 0, 0, 70, 142, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 56, 0, + 0, 9, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 50, 0, + 0, 9, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 164, 0, + 0, 7, 242, 224, 17, 0, + 0, 0, 0, 0, 70, 10, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 21, 0, 0, 1, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 29, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 6, 0, 0, 0, + 9, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0 +}; diff --git a/demo/DemoApp/customLightingCS.hlsl.h b/demo/DemoApp/customLightingCS.hlsl.h new file mode 100644 index 0000000..538d193 --- /dev/null +++ b/demo/DemoApp/customLightingCS.hlsl.h @@ -0,0 +1,785 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer params +// { +// +// struct NvFlowShaderLinearParams +// { +// +// uint4 isVTR; // Offset: 0 +// uint4 blockDim; // Offset: 16 +// uint4 blockDimBits; // Offset: 32 +// uint4 poolGridDim; // Offset: 48 +// uint4 gridDim; // Offset: 64 +// float4 blockDimInv; // Offset: 80 +// uint4 linearBlockDim; // Offset: 96 +// uint4 linearBlockOffset; // Offset: 112 +// float4 dimInv; // Offset: 128 +// float4 vdim; // Offset: 144 +// float4 vdimInv; // Offset: 160 +// +// } exportParams; // Offset: 0 Size: 176 +// +// struct NvFlowShaderLinearParams +// { +// +// uint4 isVTR; // Offset: 176 +// uint4 blockDim; // Offset: 192 +// uint4 blockDimBits; // Offset: 208 +// uint4 poolGridDim; // Offset: 224 +// uint4 gridDim; // Offset: 240 +// float4 blockDimInv; // Offset: 256 +// uint4 linearBlockDim; // Offset: 272 +// uint4 linearBlockOffset; // Offset: 288 +// float4 dimInv; // Offset: 304 +// float4 vdim; // Offset: 320 +// float4 vdimInv; // Offset: 336 +// +// } importParams; // Offset: 176 Size: 176 +// +// struct Light +// { +// +// float4 location; // Offset: 352 +// float4 intensity; // Offset: 368 +// float4 bias; // Offset: 384 +// float4 falloff; // Offset: 400 +// +// } light[3]; // Offset: 352 Size: 192 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// borderSampler sampler NA NA s0 1 +// exportBlockTable texture uint 3d t1 1 +// exportData texture float4 3d t2 1 +// importBlockList texture uint buf t3 1 +// importBlockTable texture uint 3d t4 1 +// importDataRW UAV float4 3d u0 1 +// params cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[34], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture3d (uint,uint,uint,uint) t1 +dcl_resource_texture3d (float,float,float,float) t2 +dcl_resource_buffer (uint,uint,uint,uint) t3 +dcl_resource_texture3d (uint,uint,uint,uint) t4 +dcl_uav_typed_texture3d (float,float,float,float) u0 +dcl_input vThreadID.xyz +dcl_temps 7 +dcl_thread_group 8, 8, 8 +ushr r0.x, vThreadID.x, cb0[13].x +ld_indexable(buffer)(uint,uint,uint,uint) r0.x, r0.xxxx, t3.xyzw +not r0.x, r0.x +and r1.x, r0.x, l(1023) +ubfe r1.yz, l(0, 10, 10, 0), l(0, 10, 20, 0), r0.xxxx +ishl r0.xyz, r1.xyzx, cb0[13].xyzx +iadd r1.xyz, cb0[12].xyzx, l(-1, -1, -1, 0) +and r2.xyz, r1.xyzx, vThreadID.xyzx +or r0.xyz, r0.xyzx, r2.xyzx +itof r2.xyz, r0.xyzx +add r2.xyz, r2.xyzx, l(0.500000, 0.500000, 0.500000, 0.000000) +mul r3.xyz, r2.xyzx, cb0[10].xyzx +mad r3.xyz, r3.xyzx, l(2.000000, 2.000000, 2.000000, 0.000000), l(-1.000000, -1.000000, -1.000000, 0.000000) +if_z cb0[0].x + mul r4.xyz, r2.xyzx, cb0[5].xyzx + round_ni r4.xyz, r4.xyzx + ftoi r5.xyz, r4.xyzx + mov r5.w, l(0) + ld_indexable(texture3d)(uint,uint,uint,uint) r0.w, r5.xyzw, t1.yzwx + not r0.w, r0.w + and r5.x, r0.w, l(1023) + ubfe r5.yz, l(0, 10, 10, 0), l(0, 10, 20, 0), r0.wwww + imul null, r5.xyz, r5.xyzx, cb0[6].xyzx + utof r5.xyz, r5.xyzx + utof r6.xyz, cb0[1].xyzx + mad r4.xyz, cb0[5].xyzx, r2.xyzx, -r4.xyzx + mad r4.xyz, r6.xyzx, r4.xyzx, r5.xyzx + utof r5.xyz, cb0[7].xyzx + add r2.xyz, r4.xyzx, r5.xyzx +endif +mul r2.xyz, r2.xyzx, cb0[8].xyzx +sample_l_indexable(texture3d)(float,float,float,float) r0.w, r2.xyzx, t2.yzwx, s0, l(0.000000) +mul r2.xyz, r0.wwww, l(0.100000, 0.100000, 0.100000, 0.000000) +add r4.xyz, r3.xyzx, -cb0[22].xyzx +dp3 r1.w, r4.xyzx, r4.xyzx +mul r4.xyzw, cb0[23].xyzw, cb0[24].xyzw +mad r5.xyzw, cb0[25].xyzw, r1.wwww, cb0[24].xyzw +div r4.xyzw, r4.xyzw, r5.xyzw +mov r2.w, l(0.250000) +add r2.xyzw, r2.xyzw, r4.xyzw +add r4.xyz, r3.xyzx, -cb0[26].xyzx +dp3 r1.w, r4.xyzx, r4.xyzx +mul r4.xyzw, cb0[27].xyzw, cb0[28].xyzw +mad r5.xyzw, cb0[29].xyzw, r1.wwww, cb0[28].xyzw +div r4.xyzw, r4.xyzw, r5.xyzw +add r2.xyzw, r2.xyzw, r4.xyzw +add r3.xyz, r3.xyzx, -cb0[30].xyzx +dp3 r1.w, r3.xyzx, r3.xyzx +mul r3.xyzw, cb0[31].xyzw, cb0[32].xyzw +mad r4.xyzw, cb0[33].xyzw, r1.wwww, cb0[32].xyzw +div r3.xyzw, r3.xyzw, r4.xyzw +add r2.xyzw, r2.xyzw, r3.xyzw +add r0.w, r0.w, l(-0.250000) +max r0.w, r0.w, l(0.000000) +mul r0.w, r0.w, r2.w +mul r2.w, r0.w, l(0.250000) +if_z cb0[11].x + ishr r3.xyz, r0.xyzx, cb0[13].xyzx + mov r3.w, l(0) + ld_indexable(texture3d)(uint,uint,uint,uint) r0.w, r3.xyzw, t4.yzwx + not r0.w, r0.w + and r3.x, r0.w, l(1023) + ubfe r3.yz, l(0, 10, 10, 0), l(0, 10, 20, 0), r0.wwww + ishl r3.xyz, r3.xyzx, cb0[13].xyzx + and r1.xyz, r1.xyzx, r0.xyzx + or r0.xyz, r1.xyzx, r3.xyzx +endif +store_uav_typed u0.xyzw, r0.xyzz, r2.xyzw +ret +// Approximately 69 instruction slots used +#endif + +const BYTE g_customLightingCS[] = +{ + 68, 88, 66, 67, 81, 60, + 238, 114, 184, 37, 48, 25, + 88, 28, 231, 151, 12, 178, + 59, 182, 1, 0, 0, 0, + 108, 14, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 208, 4, 0, 0, 224, 4, + 0, 0, 240, 4, 0, 0, + 208, 13, 0, 0, 82, 68, + 69, 70, 148, 4, 0, 0, + 1, 0, 0, 0, 124, 1, + 0, 0, 7, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 83, 67, 0, 1, 0, 0, + 108, 4, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 28, 1, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 42, 1, 0, 0, + 2, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 255, 255, 255, 255, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 59, 1, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 8, 0, + 0, 0, 255, 255, 255, 255, + 2, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 70, 1, 0, 0, 2, 0, + 0, 0, 4, 0, 0, 0, + 1, 0, 0, 0, 255, 255, + 255, 255, 3, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 86, 1, 0, 0, + 2, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 255, 255, 255, 255, 4, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 103, 1, + 0, 0, 4, 0, 0, 0, + 5, 0, 0, 0, 8, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 116, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 98, 111, 114, 100, + 101, 114, 83, 97, 109, 112, + 108, 101, 114, 0, 101, 120, + 112, 111, 114, 116, 66, 108, + 111, 99, 107, 84, 97, 98, + 108, 101, 0, 101, 120, 112, + 111, 114, 116, 68, 97, 116, + 97, 0, 105, 109, 112, 111, + 114, 116, 66, 108, 111, 99, + 107, 76, 105, 115, 116, 0, + 105, 109, 112, 111, 114, 116, + 66, 108, 111, 99, 107, 84, + 97, 98, 108, 101, 0, 105, + 109, 112, 111, 114, 116, 68, + 97, 116, 97, 82, 87, 0, + 112, 97, 114, 97, 109, 115, + 0, 171, 116, 1, 0, 0, + 3, 0, 0, 0, 148, 1, + 0, 0, 32, 2, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 12, 2, 0, 0, + 0, 0, 0, 0, 176, 0, + 0, 0, 2, 0, 0, 0, + 140, 3, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 176, 3, 0, 0, 176, 0, + 0, 0, 176, 0, 0, 0, + 2, 0, 0, 0, 140, 3, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 189, 3, + 0, 0, 96, 1, 0, 0, + 192, 0, 0, 0, 2, 0, + 0, 0, 72, 4, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 101, 120, 112, 111, + 114, 116, 80, 97, 114, 97, + 109, 115, 0, 78, 118, 70, + 108, 111, 119, 83, 104, 97, + 100, 101, 114, 76, 105, 110, + 101, 97, 114, 80, 97, 114, + 97, 109, 115, 0, 105, 115, + 86, 84, 82, 0, 78, 118, + 70, 108, 111, 119, 85, 105, + 110, 116, 52, 0, 1, 0, + 19, 0, 1, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 2, 0, 0, 98, 108, + 111, 99, 107, 68, 105, 109, + 0, 98, 108, 111, 99, 107, + 68, 105, 109, 66, 105, 116, + 115, 0, 112, 111, 111, 108, + 71, 114, 105, 100, 68, 105, + 109, 0, 103, 114, 105, 100, + 68, 105, 109, 0, 98, 108, + 111, 99, 107, 68, 105, 109, + 73, 110, 118, 0, 78, 118, + 70, 108, 111, 119, 70, 108, + 111, 97, 116, 52, 0, 171, + 1, 0, 3, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 158, 2, 0, 0, + 108, 105, 110, 101, 97, 114, + 66, 108, 111, 99, 107, 68, + 105, 109, 0, 108, 105, 110, + 101, 97, 114, 66, 108, 111, + 99, 107, 79, 102, 102, 115, + 101, 116, 0, 100, 105, 109, + 73, 110, 118, 0, 118, 100, + 105, 109, 0, 118, 100, 105, + 109, 73, 110, 118, 0, 171, + 171, 171, 50, 2, 0, 0, + 68, 2, 0, 0, 0, 0, + 0, 0, 104, 2, 0, 0, + 68, 2, 0, 0, 16, 0, + 0, 0, 113, 2, 0, 0, + 68, 2, 0, 0, 32, 0, + 0, 0, 126, 2, 0, 0, + 68, 2, 0, 0, 48, 0, + 0, 0, 138, 2, 0, 0, + 68, 2, 0, 0, 64, 0, + 0, 0, 146, 2, 0, 0, + 172, 2, 0, 0, 80, 0, + 0, 0, 208, 2, 0, 0, + 68, 2, 0, 0, 96, 0, + 0, 0, 223, 2, 0, 0, + 68, 2, 0, 0, 112, 0, + 0, 0, 241, 2, 0, 0, + 172, 2, 0, 0, 128, 0, + 0, 0, 248, 2, 0, 0, + 172, 2, 0, 0, 144, 0, + 0, 0, 253, 2, 0, 0, + 172, 2, 0, 0, 160, 0, + 0, 0, 5, 0, 0, 0, + 1, 0, 44, 0, 0, 0, + 11, 0, 8, 3, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 25, 2, + 0, 0, 105, 109, 112, 111, + 114, 116, 80, 97, 114, 97, + 109, 115, 0, 108, 105, 103, + 104, 116, 0, 76, 105, 103, + 104, 116, 0, 108, 111, 99, + 97, 116, 105, 111, 110, 0, + 102, 108, 111, 97, 116, 52, + 0, 171, 171, 171, 1, 0, + 3, 0, 1, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 210, 3, 0, 0, 105, 110, + 116, 101, 110, 115, 105, 116, + 121, 0, 98, 105, 97, 115, + 0, 102, 97, 108, 108, 111, + 102, 102, 0, 171, 201, 3, + 0, 0, 220, 3, 0, 0, + 0, 0, 0, 0, 0, 4, + 0, 0, 220, 3, 0, 0, + 16, 0, 0, 0, 10, 4, + 0, 0, 220, 3, 0, 0, + 32, 0, 0, 0, 15, 4, + 0, 0, 220, 3, 0, 0, + 48, 0, 0, 0, 5, 0, + 0, 0, 1, 0, 16, 0, + 3, 0, 4, 0, 24, 4, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 195, 3, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 216, 8, 0, 0, + 80, 0, 5, 0, 54, 2, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 34, 0, 0, 0, 90, 0, + 0, 3, 0, 96, 16, 0, + 0, 0, 0, 0, 88, 40, + 0, 4, 0, 112, 16, 0, + 1, 0, 0, 0, 68, 68, + 0, 0, 88, 40, 0, 4, + 0, 112, 16, 0, 2, 0, + 0, 0, 85, 85, 0, 0, + 88, 8, 0, 4, 0, 112, + 16, 0, 3, 0, 0, 0, + 68, 68, 0, 0, 88, 40, + 0, 4, 0, 112, 16, 0, + 4, 0, 0, 0, 68, 68, + 0, 0, 156, 40, 0, 4, + 0, 224, 17, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 95, 0, 0, 2, 114, 0, + 2, 0, 104, 0, 0, 2, + 7, 0, 0, 0, 155, 0, + 0, 4, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, + 0, 0, 85, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 2, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 45, 0, 0, 137, 66, 0, + 0, 128, 3, 17, 17, 0, + 18, 0, 16, 0, 0, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 126, + 16, 0, 3, 0, 0, 0, + 59, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 255, 3, 0, 0, + 138, 0, 0, 15, 98, 0, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 10, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 20, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, + 41, 0, 0, 8, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 30, 0, 0, 11, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 6, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 2, 0, 60, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 43, 0, 0, 5, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 10, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 50, 0, + 0, 15, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 64, 0, 0, 0, 64, + 0, 0, 0, 64, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 191, 0, 0, + 128, 191, 0, 0, 128, 191, + 0, 0, 0, 0, 31, 0, + 0, 4, 10, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 65, 0, + 0, 5, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 27, 0, 0, 5, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 5, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 137, 66, 1, 0, 128, + 3, 17, 17, 0, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 150, 115, 16, 0, + 1, 0, 0, 0, 59, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 3, 0, 0, 138, 0, + 0, 15, 98, 0, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 20, 0, 0, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 38, 0, + 0, 9, 0, 208, 0, 0, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 86, 0, + 0, 5, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 86, 0, 0, 6, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 50, 0, 0, 11, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 86, 0, 0, 6, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 21, 0, 0, 1, 56, 0, + 0, 8, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 72, 0, 0, 141, 66, 1, + 0, 128, 67, 85, 21, 0, + 130, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 150, 115, + 16, 0, 2, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 10, 114, 0, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 205, 204, + 204, 61, 205, 204, 204, 61, + 205, 204, 204, 61, 0, 0, + 0, 0, 0, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 22, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 56, 0, 0, 9, 242, 0, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 23, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 24, 0, 0, 0, + 50, 0, 0, 11, 242, 0, + 16, 0, 5, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 25, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 24, 0, + 0, 0, 14, 0, 0, 7, + 242, 0, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 62, 0, 0, 0, 7, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 130, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 26, 0, 0, 0, + 16, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 56, 0, + 0, 9, 242, 0, 16, 0, + 4, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 27, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 50, 0, + 0, 11, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 28, 0, 0, 0, + 14, 0, 0, 7, 242, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 0, 0, + 0, 7, 242, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 9, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 130, + 32, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 0, 16, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 9, 242, 0, + 16, 0, 3, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 31, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 32, 0, 0, 0, + 50, 0, 0, 11, 242, 0, + 16, 0, 4, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 33, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 32, 0, + 0, 0, 14, 0, 0, 7, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 190, 52, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 62, 31, 0, 0, 4, + 10, 128, 32, 0, 0, 0, + 0, 0, 11, 0, 0, 0, + 42, 0, 0, 8, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 13, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 137, 66, 1, 0, 128, + 3, 17, 17, 0, 130, 0, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 150, 115, 16, 0, + 4, 0, 0, 0, 59, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 7, 18, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 3, 0, 0, 138, 0, + 0, 15, 98, 0, 16, 0, + 3, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, + 20, 0, 0, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 41, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 13, 0, 0, 0, + 1, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 164, 0, 0, 7, 242, 224, + 17, 0, 0, 0, 0, 0, + 70, 10, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 69, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 32, 0, 0, 0, + 5, 0, 0, 0, 11, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0 +}; diff --git a/demo/DemoApp/flowShaderParams.h b/demo/DemoApp/flowShaderParams.h new file mode 100644 index 0000000..1c769ef --- /dev/null +++ b/demo/DemoApp/flowShaderParams.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#define NV_FLOW_SHADER_UTILS 1 + +#include "NvFlowShader.h"
\ No newline at end of file diff --git a/demo/DemoApp/imgui.cpp b/demo/DemoApp/imgui.cpp new file mode 100644 index 0000000..cccaf3f --- /dev/null +++ b/demo/DemoApp/imgui.cpp @@ -0,0 +1,697 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen [email protected] +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#include <stdio.h> +#include <string.h> +#define _USE_MATH_DEFINES +#include <math.h> +#include "imgui.h" + +#ifdef WIN32 +# define snprintf _snprintf +#endif + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static const unsigned TEXT_POOL_SIZE = 8000; +static char g_textPool[TEXT_POOL_SIZE]; +static unsigned g_textPoolSize = 0; +static const char* allocText(const char* text) +{ + int len = (int)(strlen(text) + 1); + if (g_textPoolSize + len >= TEXT_POOL_SIZE) + return 0; + char* dst = &g_textPool[g_textPoolSize]; + memcpy(dst, text, len); + g_textPoolSize += len; + return dst; +} + +static const unsigned GFXCMD_QUEUE_SIZE = 5000; +static imguiGfxCmd g_gfxCmdQueue[GFXCMD_QUEUE_SIZE]; +static unsigned g_gfxCmdQueueSize = 0; + +static void resetGfxCmdQueue() +{ + g_gfxCmdQueueSize = 0; + g_textPoolSize = 0; +} + +static void addGfxCmdScissor(int x, int y, int w, int h) +{ + if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE) + return; + imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++]; + cmd.type = IMGUI_GFXCMD_SCISSOR; + cmd.flags = x < 0 ? 0 : 1; // on/off flag. + cmd.col = 0; + cmd.rect.x = (short)x; + cmd.rect.y = (short)y; + cmd.rect.w = (short)w; + cmd.rect.h = (short)h; +} + +static void addGfxCmdRect(float x, float y, float w, float h, unsigned int color) +{ + if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE) + return; + imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++]; + cmd.type = IMGUI_GFXCMD_RECT; + cmd.flags = 0; + cmd.col = color; + cmd.rect.x = (short)(x*8.0f); + cmd.rect.y = (short)(y*8.0f); + cmd.rect.w = (short)(w*8.0f); + cmd.rect.h = (short)(h*8.0f); + cmd.rect.r = 0; +} + +static void addGfxCmdLine(float x0, float y0, float x1, float y1, float r, unsigned int color) +{ + if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE) + return; + imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++]; + cmd.type = IMGUI_GFXCMD_LINE; + cmd.flags = 0; + cmd.col = color; + cmd.line.x0 = (short)(x0*8.0f); + cmd.line.y0 = (short)(y0*8.0f); + cmd.line.x1 = (short)(x1*8.0f); + cmd.line.y1 = (short)(y1*8.0f); + cmd.line.r = (short)(r*8.0f); +} + +static void addGfxCmdRoundedRect(float x, float y, float w, float h, float r, unsigned int color) +{ + if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE) + return; + imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++]; + cmd.type = IMGUI_GFXCMD_RECT; + cmd.flags = 0; + cmd.col = color; + cmd.rect.x = (short)(x*8.0f); + cmd.rect.y = (short)(y*8.0f); + cmd.rect.w = (short)(w*8.0f); + cmd.rect.h = (short)(h*8.0f); + cmd.rect.r = (short)(r*8.0f); +} + +static void addGfxCmdTriangle(int x, int y, int w, int h, int flags, unsigned int color) +{ + if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE) + return; + imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++]; + cmd.type = IMGUI_GFXCMD_TRIANGLE; + cmd.flags = (char)flags; + cmd.col = color; + cmd.rect.x = (short)(x*8.0f); + cmd.rect.y = (short)(y*8.0f); + cmd.rect.w = (short)(w*8.0f); + cmd.rect.h = (short)(h*8.0f); +} + +static void addGfxCmdText(int x, int y, int align, const char* text, unsigned int color) +{ + if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE) + return; + imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++]; + cmd.type = IMGUI_GFXCMD_TEXT; + cmd.flags = 0; + cmd.col = color; + cmd.text.x = (short)x; + cmd.text.y = (short)y; + cmd.text.align = (short)align; + cmd.text.text = allocText(text); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +struct GuiState +{ + GuiState() : + left(false), leftPressed(false), leftReleased(false), + mx(-1), my(-1), scroll(0), + active(0), hot(0), hotToBe(0), isHot(false), isActive(false), wentActive(false), + dragX(0), dragY(0), dragOrig(0), widgetX(0), widgetY(0), widgetW(100), + insideCurrentScroll(false), areaId(0), widgetId(0) + { + } + + bool left; + bool leftPressed, leftReleased; + int mx, my; + int scroll; + unsigned int active; + unsigned int hot; + unsigned int hotToBe; + bool isHot; + bool isActive; + bool wentActive; + int dragX, dragY; + float dragOrig; + int widgetX, widgetY, widgetW; + bool insideCurrentScroll; + + unsigned int areaId; + unsigned int widgetId; +}; + +static GuiState g_state; + +// Begin Add Android Support +#ifdef ANDROID +void setStateLeft(bool bLeftDown) +{ + g_state.left = bLeftDown; +} +#endif +// End Add Android Support + +inline bool anyActive() +{ + return g_state.active != 0; +} + +inline bool isActive(unsigned int id) +{ + return g_state.active == id; +} + +inline bool isHot(unsigned int id) +{ + return g_state.hot == id; +} + +inline bool inRect(int x, int y, int w, int h, bool checkScroll = true) +{ + return (!checkScroll || g_state.insideCurrentScroll) && g_state.mx >= x && g_state.mx <= x + w && g_state.my >= y && g_state.my <= y + h; +} + +inline void clearInput() +{ + g_state.leftPressed = false; + g_state.leftReleased = false; + g_state.scroll = 0; +} + +inline void clearActive() +{ + g_state.active = 0; + // mark all UI for this frame as processed + clearInput(); +} + +inline void setActive(unsigned int id) +{ + g_state.active = id; + g_state.wentActive = true; +} + +inline void setHot(unsigned int id) +{ + g_state.hotToBe = id; + // Begin Add Android Support +#ifdef ANDROID + g_state.hot = id; +#endif + // End Add Android Support +} + + +static bool buttonLogic(unsigned int id, bool over) +{ + bool res = false; + // process down + if (!anyActive()) + { + if (over) + setHot(id); + // Begin Add Android Support +#ifdef ANDROID + if (isHot(id) && g_state.leftPressed && over) + setActive(id); +#else + if (isHot(id) && g_state.leftPressed) + setActive(id); +#endif + // End Add Android Support + } + + // if button is active, then react on left up + if (isActive(id)) + { + g_state.isActive = true; + if (over) + setHot(id); + if (g_state.leftReleased) + { + if (isHot(id)) + res = true; + clearActive(); + } + } + + if (isHot(id)) + g_state.isHot = true; + + return res; +} + +static void updateInput(int mx, int my, unsigned char mbut, int scroll) +{ + bool left = (mbut & IMGUI_MBUT_LEFT) != 0; + + g_state.mx = mx; + g_state.my = my; + g_state.leftPressed = !g_state.left && left; + g_state.leftReleased = g_state.left && !left; + g_state.left = left; + + g_state.scroll = scroll; +} + +void imguiBeginFrame(int mx, int my, unsigned char mbut, int scroll) +{ + updateInput(mx, my, mbut, scroll); + + g_state.hot = g_state.hotToBe; + g_state.hotToBe = 0; + + g_state.wentActive = false; + g_state.isActive = false; + g_state.isHot = false; + + g_state.widgetX = 0; + g_state.widgetY = 0; + g_state.widgetW = 0; + + g_state.areaId = 1; + g_state.widgetId = 1; + + resetGfxCmdQueue(); +} + +void imguiEndFrame() +{ + clearInput(); +} + +const imguiGfxCmd* imguiGetRenderQueue() +{ + return g_gfxCmdQueue; +} + +int imguiGetRenderQueueSize() +{ + return g_gfxCmdQueueSize; +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static const int BUTTON_HEIGHT = 20; +static const int SLIDER_HEIGHT = 20; +static const int SLIDER_MARKER_WIDTH = 10; +static const int CHECK_SIZE = 8; +static const int DEFAULT_SPACING = 4; +static const int TEXT_HEIGHT = 8; +static const int SCROLL_AREA_PADDING = 6; +static const int INDENT_SIZE = 16; +static const int AREA_HEADER = 28; + +static int g_scrollTop = 0; +static int g_scrollBottom = 0; +static int g_scrollRight = 0; +static int g_scrollAreaTop = 0; +static int* g_scrollVal = 0; +static int g_focusTop = 0; +static int g_focusBottom = 0; +static unsigned int g_scrollId = 0; +static bool g_insideScrollArea = false; + +bool imguiBeginScrollArea(const char* name, int x, int y, int w, int h, int* scroll) +{ + g_state.areaId++; + g_state.widgetId = 0; + g_scrollId = (g_state.areaId << 16) | g_state.widgetId; + + g_state.widgetX = x + SCROLL_AREA_PADDING; + g_state.widgetY = y + h - AREA_HEADER + (*scroll); + g_state.widgetW = w - SCROLL_AREA_PADDING * 4; + g_scrollTop = y - AREA_HEADER + h; + g_scrollBottom = y + SCROLL_AREA_PADDING; + g_scrollRight = x + w - SCROLL_AREA_PADDING * 3; + g_scrollVal = scroll; + + g_scrollAreaTop = g_state.widgetY; + + g_focusTop = y - AREA_HEADER; + g_focusBottom = y - AREA_HEADER + h; + + g_insideScrollArea = inRect(x, y, w, h, false); + g_state.insideCurrentScroll = g_insideScrollArea; + + addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, 6, imguiRGBA(0, 0, 0, 192)); + + addGfxCmdText(x + AREA_HEADER / 2, y + h - AREA_HEADER / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, name, imguiRGBA(255, 255, 255, 128)); + + addGfxCmdScissor(x + SCROLL_AREA_PADDING, y + SCROLL_AREA_PADDING, w - SCROLL_AREA_PADDING * 4, h - AREA_HEADER - SCROLL_AREA_PADDING); + + return g_insideScrollArea; +} + +void imguiEndScrollArea() +{ + // Disable scissoring. + addGfxCmdScissor(-1, -1, -1, -1); + + // Draw scroll bar + int x = g_scrollRight + SCROLL_AREA_PADDING / 2; + int y = g_scrollBottom; + int w = SCROLL_AREA_PADDING * 2; + int h = g_scrollTop - g_scrollBottom; + + int stop = g_scrollAreaTop; + int sbot = g_state.widgetY; + int sh = stop - sbot; // The scrollable area height. + + float barHeight = (float)h / (float)sh; + + if (barHeight < 1) + { + float barY = (float)(y - sbot) / (float)sh; + if (barY < 0) barY = 0; + if (barY > 1) barY = 1; + + // Handle scroll bar logic. + unsigned int hid = g_scrollId; + int hx = x; + int hy = y + (int)(barY*h); + int hw = w; + int hh = (int)(barHeight*h); + + const int range = h - (hh - 1); + bool over = inRect(hx, hy, hw, hh); + buttonLogic(hid, over); + if (isActive(hid)) + { + float u = (float)(hy - y) / (float)range; + if (g_state.wentActive) + { + g_state.dragY = g_state.my; + g_state.dragOrig = u; + } + if (g_state.dragY != g_state.my) + { + u = g_state.dragOrig + (g_state.my - g_state.dragY) / (float)range; + if (u < 0) u = 0; + if (u > 1) u = 1; + *g_scrollVal = (int)((1 - u) * (sh - h)); + } + } + + // BG + addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, (float)w / 2 - 1, imguiRGBA(0, 0, 0, 196)); + // Bar + if (isActive(hid)) + addGfxCmdRoundedRect((float)hx, (float)hy, (float)hw, (float)hh, (float)w / 2 - 1, imguiRGBA(255, 196, 0, 196)); + else + addGfxCmdRoundedRect((float)hx, (float)hy, (float)hw, (float)hh, (float)w / 2 - 1, isHot(hid) ? imguiRGBA(255, 196, 0, 96) : imguiRGBA(255, 255, 255, 64)); + + // Handle mouse scrolling. + if (g_insideScrollArea) // && !anyActive()) + { + if (g_state.scroll) + { + *g_scrollVal += 20 * g_state.scroll; + if (*g_scrollVal < 0) *g_scrollVal = 0; + if (*g_scrollVal >(sh - h)) *g_scrollVal = (sh - h); + } + } + } + g_state.insideCurrentScroll = false; +} + +bool imguiButton(const char* text, bool enabled) +{ + g_state.widgetId++; + unsigned int id = (g_state.areaId << 16) | g_state.widgetId; + + int x = g_state.widgetX; + int y = g_state.widgetY - BUTTON_HEIGHT; + int w = g_state.widgetW; + int h = BUTTON_HEIGHT; + g_state.widgetY -= BUTTON_HEIGHT + DEFAULT_SPACING; + + bool over = enabled && inRect(x, y, w, h); + bool res = buttonLogic(id, over); + + addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, (float)BUTTON_HEIGHT / 2 - 1, imguiRGBA(128, 128, 128, isActive(id) ? 196 : 96)); + if (enabled) + addGfxCmdText(x + BUTTON_HEIGHT / 2, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, isHot(id) ? imguiRGBA(255, 196, 0, 255) : imguiRGBA(255, 255, 255, 200)); + else + addGfxCmdText(x + BUTTON_HEIGHT / 2, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, imguiRGBA(128, 128, 128, 200)); + + return res; +} + +bool imguiItem(const char* text, bool enabled, unsigned int color) +{ + g_state.widgetId++; + unsigned int id = (g_state.areaId << 16) | g_state.widgetId; + + int x = g_state.widgetX; + int y = g_state.widgetY - BUTTON_HEIGHT; + int w = g_state.widgetW; + int h = BUTTON_HEIGHT; + g_state.widgetY -= BUTTON_HEIGHT + DEFAULT_SPACING; + + bool over = enabled && inRect(x, y, w, h); + bool res = buttonLogic(id, over); + + if (isHot(id)) + addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, 2.0f, imguiRGBA(255, 196, 0, isActive(id) ? 196 : 96)); + + if (enabled) + addGfxCmdText(x + BUTTON_HEIGHT / 2, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, color); + else + addGfxCmdText(x + BUTTON_HEIGHT / 2, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, color); + + return res; +} + +bool imguiCheck(const char* text, bool checked, bool enabled) +{ + g_state.widgetId++; + unsigned int id = (g_state.areaId << 16) | g_state.widgetId; + + int x = g_state.widgetX; + int y = g_state.widgetY - BUTTON_HEIGHT; + int w = g_state.widgetW; + int h = BUTTON_HEIGHT; + g_state.widgetY -= BUTTON_HEIGHT + DEFAULT_SPACING; + + bool over = enabled && inRect(x, y, w, h); + bool res = buttonLogic(id, over); + + const int cx = x + BUTTON_HEIGHT / 2 - CHECK_SIZE / 2; + const int cy = y + BUTTON_HEIGHT / 2 - CHECK_SIZE / 2; + addGfxCmdRoundedRect((float)cx - 3, (float)cy - 3, (float)CHECK_SIZE + 6, (float)CHECK_SIZE + 6, 4, imguiRGBA(128, 128, 128, isActive(id) ? 196 : 96)); + if (checked) + { + if (enabled) + addGfxCmdRoundedRect((float)cx, (float)cy, (float)CHECK_SIZE, (float)CHECK_SIZE, (float)CHECK_SIZE / 2 - 1, imguiRGBA(255, 255, 255, isActive(id) ? 255 : 200)); + else + addGfxCmdRoundedRect((float)cx, (float)cy, (float)CHECK_SIZE, (float)CHECK_SIZE, (float)CHECK_SIZE / 2 - 1, imguiRGBA(128, 128, 128, 200)); + } + + if (enabled) + addGfxCmdText(x + BUTTON_HEIGHT, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, isHot(id) ? imguiRGBA(255, 196, 0, 255) : imguiRGBA(255, 255, 255, 200)); + else + addGfxCmdText(x + BUTTON_HEIGHT, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, imguiRGBA(128, 128, 128, 200)); + + return res; +} + +bool imguiCollapse(const char* text, const char* subtext, bool checked, bool enabled) +{ + g_state.widgetId++; + unsigned int id = (g_state.areaId << 16) | g_state.widgetId; + + int x = g_state.widgetX; + int y = g_state.widgetY - BUTTON_HEIGHT; + int w = g_state.widgetW; + int h = BUTTON_HEIGHT; + g_state.widgetY -= BUTTON_HEIGHT; // + DEFAULT_SPACING; + + const int cx = x + BUTTON_HEIGHT / 2 - CHECK_SIZE / 2; + const int cy = y + BUTTON_HEIGHT / 2 - CHECK_SIZE / 2; + + bool over = enabled && inRect(x, y, w, h); + bool res = buttonLogic(id, over); + + if (checked) + addGfxCmdTriangle(cx, cy, CHECK_SIZE, CHECK_SIZE, 2, imguiRGBA(255, 255, 255, isActive(id) ? 255 : 200)); + else + addGfxCmdTriangle(cx, cy, CHECK_SIZE, CHECK_SIZE, 1, imguiRGBA(255, 255, 255, isActive(id) ? 255 : 200)); + + if (enabled) + addGfxCmdText(x + BUTTON_HEIGHT, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, isHot(id) ? imguiRGBA(255, 196, 0, 255) : imguiRGBA(255, 255, 255, 200)); + else + addGfxCmdText(x + BUTTON_HEIGHT, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, imguiRGBA(128, 128, 128, 200)); + + if (subtext) + addGfxCmdText(x + w - BUTTON_HEIGHT / 2, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_RIGHT, subtext, imguiRGBA(255, 255, 255, 128)); + + return res; +} + +void imguiLabel(const char* text) +{ + int x = g_state.widgetX; + int y = g_state.widgetY - BUTTON_HEIGHT; + g_state.widgetY -= BUTTON_HEIGHT; + addGfxCmdText(x, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, imguiRGBA(255, 255, 255, 255)); +} + +void imguiValue(const char* text) +{ + const int x = g_state.widgetX; + const int y = g_state.widgetY - BUTTON_HEIGHT; + const int w = g_state.widgetW; + g_state.widgetY -= BUTTON_HEIGHT; + + addGfxCmdText(x + w - BUTTON_HEIGHT / 2, y + BUTTON_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_RIGHT, text, imguiRGBA(255, 255, 255, 200)); +} + +bool imguiSlider(const char* text, float* val, float vmin, float vmax, float vinc, bool enabled) +{ + g_state.widgetId++; + unsigned int id = (g_state.areaId << 16) | g_state.widgetId; + + int x = g_state.widgetX; + int y = g_state.widgetY - BUTTON_HEIGHT; + int w = g_state.widgetW; + int h = SLIDER_HEIGHT; + g_state.widgetY -= SLIDER_HEIGHT + DEFAULT_SPACING; + + addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, 4.0f, imguiRGBA(0, 0, 0, 128)); + + const int range = w - SLIDER_MARKER_WIDTH; + + float u = (*val - vmin) / (vmax - vmin); + if (u < 0) u = 0; + if (u > 1) u = 1; + int m = (int)(u * range); + + bool over = enabled && inRect(x + m, y, SLIDER_MARKER_WIDTH, SLIDER_HEIGHT); + bool res = buttonLogic(id, over); + bool valChanged = false; + + if (isActive(id)) + { + if (g_state.wentActive) + { + g_state.dragX = g_state.mx; + g_state.dragOrig = u; + } + if (g_state.dragX != g_state.mx) + { + u = g_state.dragOrig + (float)(g_state.mx - g_state.dragX) / (float)range; + if (u < 0) u = 0; + if (u > 1) u = 1; + *val = vmin + u*(vmax - vmin); + *val = floorf(*val / vinc + 0.5f)*vinc; // Snap to vinc + m = (int)(u * range); + valChanged = true; + } + } + + if (isActive(id)) + addGfxCmdRoundedRect((float)(x + m), (float)y, (float)SLIDER_MARKER_WIDTH, (float)SLIDER_HEIGHT, 4.0f, imguiRGBA(255, 255, 255, 255)); + else + addGfxCmdRoundedRect((float)(x + m), (float)y, (float)SLIDER_MARKER_WIDTH, (float)SLIDER_HEIGHT, 4.0f, isHot(id) ? imguiRGBA(255, 196, 0, 128) : imguiRGBA(255, 255, 255, 64)); + + // TODO: fix this, take a look at 'nicenum'. + int digits = (int)(ceilf(log10f(vinc))); + char fmt[16]; + snprintf(fmt, 16, "%%.%df", digits >= 0 ? 0 : -digits); + char msg[128]; + snprintf(msg, 128, fmt, *val); + + if (enabled) + { + addGfxCmdText(x + SLIDER_HEIGHT / 2, y + SLIDER_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, isHot(id) ? imguiRGBA(255, 196, 0, 255) : imguiRGBA(255, 255, 255, 200)); + addGfxCmdText(x + w - SLIDER_HEIGHT / 2, y + SLIDER_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_RIGHT, msg, isHot(id) ? imguiRGBA(255, 196, 0, 255) : imguiRGBA(255, 255, 255, 200)); + } + else + { + addGfxCmdText(x + SLIDER_HEIGHT / 2, y + SLIDER_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_LEFT, text, imguiRGBA(128, 128, 128, 200)); + addGfxCmdText(x + w - SLIDER_HEIGHT / 2, y + SLIDER_HEIGHT / 2 - TEXT_HEIGHT / 2, IMGUI_ALIGN_RIGHT, msg, imguiRGBA(128, 128, 128, 200)); + } + + return res || valChanged; +} + + +void imguiIndent() +{ + g_state.widgetX += INDENT_SIZE; + g_state.widgetW -= INDENT_SIZE; +} + +void imguiUnindent() +{ + g_state.widgetX -= INDENT_SIZE; + g_state.widgetW += INDENT_SIZE; +} + +void imguiSeparator() +{ + g_state.widgetY -= DEFAULT_SPACING * 3; +} + +void imguiSeparatorLine() +{ + int x = g_state.widgetX; + int y = g_state.widgetY - DEFAULT_SPACING * 2; + int w = g_state.widgetW; + int h = 1; + g_state.widgetY -= DEFAULT_SPACING * 4; + + addGfxCmdRect((float)x, (float)y, (float)w, (float)h, imguiRGBA(255, 255, 255, 32)); +} + +void imguiDrawText(int x, int y, int align, const char* text, unsigned int color) +{ + addGfxCmdText(x, y, align, text, color); +} + +void imguiDrawLine(float x0, float y0, float x1, float y1, float r, unsigned int color) +{ + addGfxCmdLine(x0, y0, x1, y1, r, color); +} + +void imguiDrawRect(float x, float y, float w, float h, unsigned int color) +{ + addGfxCmdRect(x, y, w, h, color); +} + +void imguiDrawRoundedRect(float x, float y, float w, float h, float r, unsigned int color) +{ + addGfxCmdRoundedRect(x, y, w, h, r, color); +} + diff --git a/demo/DemoApp/imgui.h b/demo/DemoApp/imgui.h new file mode 100644 index 0000000..e01f374 --- /dev/null +++ b/demo/DemoApp/imgui.h @@ -0,0 +1,108 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen [email protected] +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef IMGUI_H +#define IMGUI_H + +enum imguiMouseButton +{ + IMGUI_MBUT_LEFT = 0x01, + IMGUI_MBUT_RIGHT = 0x02, +}; + +enum imguiTextAlign +{ + IMGUI_ALIGN_LEFT, + IMGUI_ALIGN_CENTER, + IMGUI_ALIGN_RIGHT, +}; + +inline unsigned int imguiRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 255) +{ + return (r) | (g << 8) | (b << 16) | (a << 24); +} + +void imguiBeginFrame(int mx, int my, unsigned char mbut, int scroll); +void imguiEndFrame(); + +bool imguiBeginScrollArea(const char* name, int x, int y, int w, int h, int* scroll); +void imguiEndScrollArea(); + +void imguiIndent(); +void imguiUnindent(); +void imguiSeparator(); +void imguiSeparatorLine(); + +bool imguiButton(const char* text, bool enabled = true); +bool imguiItem(const char* text, bool enabled = true, unsigned int color = imguiRGBA(255, 255, 255, 200)); +bool imguiCheck(const char* text, bool checked, bool enabled = true); +bool imguiCollapse(const char* text, const char* subtext, bool checked, bool enabled = true); +void imguiLabel(const char* text); +void imguiValue(const char* text); +bool imguiSlider(const char* text, float* val, float vmin, float vmax, float vinc, bool enabled = true); + +void imguiDrawText(int x, int y, int align, const char* text, unsigned int color); +void imguiDrawLine(float x0, float y0, float x1, float y1, float r, unsigned int color); +void imguiDrawRoundedRect(float x, float y, float w, float h, float r, unsigned int color); +void imguiDrawRect(float x, float y, float w, float h, unsigned int color); + +// Pull render interface. +enum imguiGfxCmdType +{ + IMGUI_GFXCMD_RECT, + IMGUI_GFXCMD_TRIANGLE, + IMGUI_GFXCMD_LINE, + IMGUI_GFXCMD_TEXT, + IMGUI_GFXCMD_SCISSOR, +}; + +struct imguiGfxRect +{ + short x, y, w, h, r; +}; + +struct imguiGfxText +{ + short x, y, align; + const char* text; +}; + +struct imguiGfxLine +{ + short x0, y0, x1, y1, r; +}; + +struct imguiGfxCmd +{ + char type; + char flags; + char pad[2]; + unsigned int col; + union + { + imguiGfxLine line; + imguiGfxRect rect; + imguiGfxText text; + }; +}; + +const imguiGfxCmd* imguiGetRenderQueue(); +int imguiGetRenderQueueSize(); + + +#endif // IMGUI_H
\ No newline at end of file diff --git a/demo/DemoApp/imguiGraph.cpp b/demo/DemoApp/imguiGraph.cpp new file mode 100644 index 0000000..345b74a --- /dev/null +++ b/demo/DemoApp/imguiGraph.cpp @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#define _USE_MATH_DEFINES +#include <math.h> +#include "imgui.h" + +#include <stdio.h> +#include <stdint.h> + +#include "imguiGraph.h" + +// Some math headers don't have PI defined. +static const float PI = 3.14159265f; + +void imguifree(void* ptr, void* userptr); +void* imguimalloc(size_t size, void* userptr); + +#define STBTT_malloc(x,y) imguimalloc(x,y) +#define STBTT_free(x,y) imguifree(x,y) +#define STB_TRUETYPE_IMPLEMENTATION +#include "stb_truetype.h" + +void imguifree(void* ptr, void* /*userptr*/) +{ + free(ptr); +} + +void* imguimalloc(size_t size, void* /*userptr*/) +{ + return malloc(size); +} + +static const unsigned TEMP_COORD_COUNT = 100; +static float g_tempCoords[TEMP_COORD_COUNT * 2]; +static float g_tempNormals[TEMP_COORD_COUNT * 2]; + +static const int CIRCLE_VERTS = 8 * 4; +static float g_circleVerts[CIRCLE_VERTS * 2]; + +static stbtt_bakedchar g_cdata[96]; // ASCII 32..126 is 95 glyphs + +inline unsigned int RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + return (r) | (g << 8) | (b << 16) | (a << 24); +} + +static void drawPolygon(const float* coords, unsigned numCoords, float r, unsigned int col) +{ + if (numCoords > TEMP_COORD_COUNT) numCoords = TEMP_COORD_COUNT; + + for (unsigned i = 0, j = numCoords - 1; i < numCoords; j = i++) + { + const float* v0 = &coords[j * 2]; + const float* v1 = &coords[i * 2]; + float dx = v1[0] - v0[0]; + float dy = v1[1] - v0[1]; + float d = sqrtf(dx*dx + dy*dy); + if (d > 0) + { + d = 1.0f / d; + dx *= d; + dy *= d; + } + g_tempNormals[j * 2 + 0] = dy; + g_tempNormals[j * 2 + 1] = -dx; + } + + for (unsigned i = 0, j = numCoords - 1; i < numCoords; j = i++) + { + float dlx0 = g_tempNormals[j * 2 + 0]; + float dly0 = g_tempNormals[j * 2 + 1]; + float dlx1 = g_tempNormals[i * 2 + 0]; + float dly1 = g_tempNormals[i * 2 + 1]; + float dmx = (dlx0 + dlx1) * 0.5f; + float dmy = (dly0 + dly1) * 0.5f; + float dmr2 = dmx*dmx + dmy*dmy; + if (dmr2 > 0.000001f) + { + float scale = 1.0f / dmr2; + if (scale > 10.0f) scale = 10.0f; + dmx *= scale; + dmy *= scale; + } + g_tempCoords[i * 2 + 0] = coords[i * 2 + 0] + dmx*r; + g_tempCoords[i * 2 + 1] = coords[i * 2 + 1] + dmy*r; + } + + unsigned int colTrans = RGBA(col & 0xff, (col >> 8) & 0xff, (col >> 16) & 0xff, 0); + + imguiGraphColor4ubv((uint8_t*)&col); + + for (unsigned i = 0, j = numCoords - 1; i < numCoords; j = i++) + { + imguiGraphVertex2fv(&coords[i * 2]); + imguiGraphVertex2fv(&coords[j * 2]); + imguiGraphColor4ubv((uint8_t*)&colTrans); + imguiGraphVertex2fv(&g_tempCoords[j * 2]); + + imguiGraphVertex2fv(&g_tempCoords[j * 2]); + imguiGraphVertex2fv(&g_tempCoords[i * 2]); + + imguiGraphColor4ubv((uint8_t*)&col); + imguiGraphVertex2fv(&coords[i * 2]); + } + + imguiGraphColor4ubv((uint8_t*)&col); + for (unsigned i = 2; i < numCoords; ++i) + { + imguiGraphVertex2fv(&coords[0]); + imguiGraphVertex2fv(&coords[(i - 1) * 2]); + imguiGraphVertex2fv(&coords[i * 2]); + } +} + +static void drawRect(float x, float y, float w, float h, float fth, unsigned int col) +{ + float verts[4 * 2] = + { + x + 0.5f, y + 0.5f, + x + w - 0.5f, y + 0.5f, + x + w - 0.5f, y + h - 0.5f, + x + 0.5f, y + h - 0.5f, + }; + drawPolygon(verts, 4, fth, col); +} + +/* +static void drawEllipse(float x, float y, float w, float h, float fth, unsigned int col) +{ +float verts[CIRCLE_VERTS*2]; +const float* cverts = g_circleVerts; +float* v = verts; + +for (int i = 0; i < CIRCLE_VERTS; ++i) +{ +*v++ = x + cverts[i*2]*w; +*v++ = y + cverts[i*2+1]*h; +} + +drawPolygon(verts, CIRCLE_VERTS, fth, col); +} +*/ + +static void drawRoundedRect(float x, float y, float w, float h, float r, float fth, unsigned int col) +{ + const unsigned n = CIRCLE_VERTS / 4; + float verts[(n + 1) * 4 * 2]; + const float* cverts = g_circleVerts; + float* v = verts; + + for (unsigned i = 0; i <= n; ++i) + { + *v++ = x + w - r + cverts[i * 2] * r; + *v++ = y + h - r + cverts[i * 2 + 1] * r; + } + + for (unsigned i = n; i <= n * 2; ++i) + { + *v++ = x + r + cverts[i * 2] * r; + *v++ = y + h - r + cverts[i * 2 + 1] * r; + } + + for (unsigned i = n * 2; i <= n * 3; ++i) + { + *v++ = x + r + cverts[i * 2] * r; + *v++ = y + r + cverts[i * 2 + 1] * r; + } + + for (unsigned i = n * 3; i < n * 4; ++i) + { + *v++ = x + w - r + cverts[i * 2] * r; + *v++ = y + r + cverts[i * 2 + 1] * r; + } + *v++ = x + w - r + cverts[0] * r; + *v++ = y + r + cverts[1] * r; + + drawPolygon(verts, (n + 1) * 4, fth, col); +} + + +static void drawLine(float x0, float y0, float x1, float y1, float r, float fth, unsigned int col) +{ + float dx = x1 - x0; + float dy = y1 - y0; + float d = sqrtf(dx*dx + dy*dy); + if (d > 0.0001f) + { + d = 1.0f / d; + dx *= d; + dy *= d; + } + float nx = dy; + float ny = -dx; + float verts[4 * 2]; + r -= fth; + r *= 0.5f; + if (r < 0.01f) r = 0.01f; + dx *= r; + dy *= r; + nx *= r; + ny *= r; + + verts[0] = x0 - dx - nx; + verts[1] = y0 - dy - ny; + + verts[2] = x0 - dx + nx; + verts[3] = y0 - dy + ny; + + verts[4] = x1 + dx + nx; + verts[5] = y1 + dy + ny; + + verts[6] = x1 + dx - nx; + verts[7] = y1 + dy - ny; + + drawPolygon(verts, 4, fth, col); +} + + +bool imguiGraphInit(const char* fontpath, const ImguiGraphDesc* desc) +{ + imguiGraphContextInit(desc); + + for (int i = 0; i < CIRCLE_VERTS; ++i) + { + float a = (float)i / (float)CIRCLE_VERTS * PI * 2; + g_circleVerts[i * 2 + 0] = cosf(a); + g_circleVerts[i * 2 + 1] = sinf(a); + } + + // Load font. + FILE* fp = fopen(fontpath, "rb"); + if (!fp) return false; + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + unsigned char* ttfBuffer = (unsigned char*)malloc(size); + if (!ttfBuffer) + { + fclose(fp); + return false; + } + + size_t len = fread(ttfBuffer, 1, size, fp); + (void)len; + + fclose(fp); + fp = 0; + + unsigned char* bmap = (unsigned char*)malloc(512 * 512); + if (!bmap) + { + free(ttfBuffer); + return false; + } + + stbtt_BakeFontBitmap(ttfBuffer, 0, 15.0f, bmap, 512, 512, 32, 96, g_cdata); + + // can free ttf_buffer at this point + imguiGraphFontTextureInit(bmap); + + free(ttfBuffer); + free(bmap); + + return true; +} + +void imguiGraphUpdate(const ImguiGraphDesc* desc) +{ + imguiGraphContextUpdate(desc); +} + +void imguiGraphDestroy() +{ + imguiGraphFontTextureRelease(); + + imguiGraphContextDestroy(); +} + +static void getBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, + float *xpos, float *ypos, stbtt_aligned_quad *q) +{ + stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor(*xpos + b->xoff); + int round_y = STBTT_ifloor(*ypos - b->yoff); + + q->x0 = (float)round_x; + q->y0 = (float)round_y; + q->x1 = (float)round_x + b->x1 - b->x0; + q->y1 = (float)round_y - b->y1 + b->y0; + + q->s0 = b->x0 / (float)pw; + q->t0 = b->y0 / (float)pw; + q->s1 = b->x1 / (float)ph; + q->t1 = b->y1 / (float)ph; + + *xpos += b->xadvance; +} + +static const float g_tabStops[4] = { 150, 210, 270, 330 }; + +static float getTextLength(stbtt_bakedchar *chardata, const char* text) +{ + float xpos = 0; + float len = 0; + while (*text) + { + int c = (unsigned char)*text; + if (c == '\t') + { + for (int i = 0; i < 4; ++i) + { + if (xpos < g_tabStops[i]) + { + xpos = g_tabStops[i]; + break; + } + } + } + else if (c >= 32 && c < 128) + { + stbtt_bakedchar *b = chardata + c - 32; + int round_x = STBTT_ifloor((xpos + b->xoff) + 0.5); + len = round_x + b->x1 - b->x0 + 0.5f; + xpos += b->xadvance; + } + ++text; + } + return len; +} + +static void drawText(float x, float y, const char *text, int align, unsigned int col) +{ + if (!text) return; + + if (align == IMGUI_ALIGN_CENTER) + x -= getTextLength(g_cdata, text) / 2; + else if (align == IMGUI_ALIGN_RIGHT) + x -= getTextLength(g_cdata, text); + + imguiGraphColor4ub(col & 0xff, (col >> 8) & 0xff, (col >> 16) & 0xff, (col >> 24) & 0xff); + + imguiGraphFontTextureEnable(); + + // assume orthographic projection with units = screen pixels, origin at top left + const float ox = x; + + while (*text) + { + int c = (unsigned char)*text; + if (c == '\t') + { + for (int i = 0; i < 4; ++i) + { + if (x < g_tabStops[i] + ox) + { + x = g_tabStops[i] + ox; + break; + } + } + } + else if (c >= 32 && c < 128) + { + stbtt_aligned_quad q; + getBakedQuad(g_cdata, 512, 512, c - 32, &x, &y, &q); + + imguiGraphTexCoord2f(q.s0, q.t0); + imguiGraphVertex2f(q.x0, q.y0); + imguiGraphTexCoord2f(q.s1, q.t1); + imguiGraphVertex2f(q.x1, q.y1); + imguiGraphTexCoord2f(q.s1, q.t0); + imguiGraphVertex2f(q.x1, q.y0); + + imguiGraphTexCoord2f(q.s0, q.t0); + imguiGraphVertex2f(q.x0, q.y0); + imguiGraphTexCoord2f(q.s0, q.t1); + imguiGraphVertex2f(q.x0, q.y1); + imguiGraphTexCoord2f(q.s1, q.t1); + imguiGraphVertex2f(q.x1, q.y1); + } + ++text; + } + + imguiGraphFontTextureDisable(); +} + + +void imguiGraphDraw() +{ + const imguiGfxCmd* q = imguiGetRenderQueue(); + int nq = imguiGetRenderQueueSize(); + + const float s = 1.0f / 8.0f; + + imguiGraphRecordBegin(); + + imguiGraphDisableScissor(); + for (int i = 0; i < nq; ++i) + { + const imguiGfxCmd& cmd = q[i]; + if (cmd.type == IMGUI_GFXCMD_RECT) + { + if (cmd.rect.r == 0) + { + drawRect((float)cmd.rect.x*s + 0.5f, (float)cmd.rect.y*s + 0.5f, + (float)cmd.rect.w*s - 1, (float)cmd.rect.h*s - 1, + 1.0f, cmd.col); + } + else + { + drawRoundedRect((float)cmd.rect.x*s + 0.5f, (float)cmd.rect.y*s + 0.5f, + (float)cmd.rect.w*s - 1, (float)cmd.rect.h*s - 1, + (float)cmd.rect.r*s, 1.0f, cmd.col); + } + } + else if (cmd.type == IMGUI_GFXCMD_LINE) + { + drawLine(cmd.line.x0*s, cmd.line.y0*s, cmd.line.x1*s, cmd.line.y1*s, cmd.line.r*s, 1.0f, cmd.col); + } + else if (cmd.type == IMGUI_GFXCMD_TRIANGLE) + { + if (cmd.flags == 1) + { + const float verts[3 * 2] = + { + (float)cmd.rect.x*s + 0.5f, (float)cmd.rect.y*s + 0.5f, + (float)cmd.rect.x*s + 0.5f + (float)cmd.rect.w*s - 1, (float)cmd.rect.y*s + 0.5f + (float)cmd.rect.h*s / 2 - 0.5f, + (float)cmd.rect.x*s + 0.5f, (float)cmd.rect.y*s + 0.5f + (float)cmd.rect.h*s - 1, + }; + drawPolygon(verts, 3, 1.0f, cmd.col); + } + if (cmd.flags == 2) + { + const float verts[3 * 2] = + { + (float)cmd.rect.x*s + 0.5f, (float)cmd.rect.y*s + 0.5f + (float)cmd.rect.h*s - 1, + (float)cmd.rect.x*s + 0.5f + (float)cmd.rect.w*s / 2 - 0.5f, (float)cmd.rect.y*s + 0.5f, + (float)cmd.rect.x*s + 0.5f + (float)cmd.rect.w*s - 1, (float)cmd.rect.y*s + 0.5f + (float)cmd.rect.h*s - 1, + }; + drawPolygon(verts, 3, 1.0f, cmd.col); + } + } + else if (cmd.type == IMGUI_GFXCMD_TEXT) + { + drawText(cmd.text.x, cmd.text.y, cmd.text.text, cmd.text.align, cmd.col); + } + else if (cmd.type == IMGUI_GFXCMD_SCISSOR) + { + if (cmd.flags) + { + imguiGraphEnableScissor(cmd.rect.x, cmd.rect.y, cmd.rect.w, cmd.rect.h); + } + else + { + imguiGraphDisableScissor(); + } + } + } + imguiGraphDisableScissor(); + + imguiGraphRecordEnd(); +} diff --git a/demo/DemoApp/imguiGraph.h b/demo/DemoApp/imguiGraph.h new file mode 100644 index 0000000..0d64aa7 --- /dev/null +++ b/demo/DemoApp/imguiGraph.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +#include <stdint.h> + +#define IMGUI_GRAPH_API extern "C" __declspec(dllexport) + +struct ImguiGraphDesc; + +typedef bool (*imguiGraphInit_t)(const char* fontpath, const ImguiGraphDesc* desc); + +typedef void (*imguiGraphUpdate_t)(const ImguiGraphDesc* desc); + +bool imguiGraphInit(const char* fontpath, const ImguiGraphDesc* desc); + +void imguiGraphUpdate(const ImguiGraphDesc* desc); + +void imguiGraphDestroy(); + +void imguiGraphDraw(); + +// Below are the functions that must be implemented per graphics API + +IMGUI_GRAPH_API void imguiGraphContextInit(const ImguiGraphDesc* desc); + +IMGUI_GRAPH_API void imguiGraphContextUpdate(const ImguiGraphDesc* desc); + +IMGUI_GRAPH_API void imguiGraphContextDestroy(); + +IMGUI_GRAPH_API void imguiGraphRecordBegin(); + +IMGUI_GRAPH_API void imguiGraphRecordEnd(); + +IMGUI_GRAPH_API void imguiGraphVertex2f(float x, float y); + +IMGUI_GRAPH_API void imguiGraphVertex2fv(const float* v); + +IMGUI_GRAPH_API void imguiGraphTexCoord2f(float u, float v); + +IMGUI_GRAPH_API void imguiGraphColor4ub(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha); + +IMGUI_GRAPH_API void imguiGraphColor4ubv(const uint8_t* v); + +IMGUI_GRAPH_API void imguiGraphFontTextureEnable(); + +IMGUI_GRAPH_API void imguiGraphFontTextureDisable(); + +IMGUI_GRAPH_API void imguiGraphEnableScissor(int x, int y, int width, int height); + +IMGUI_GRAPH_API void imguiGraphDisableScissor(); + +IMGUI_GRAPH_API void imguiGraphFontTextureInit(unsigned char* data); + +IMGUI_GRAPH_API void imguiGraphFontTextureRelease();
\ No newline at end of file diff --git a/demo/DemoApp/imguiGraphLoader.cpp b/demo/DemoApp/imguiGraphLoader.cpp new file mode 100644 index 0000000..155e9f3 --- /dev/null +++ b/demo/DemoApp/imguiGraphLoader.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <SDL.h> + +#include "loader.h" + +#include "imguiGraph.h" +#include "imguiInterop.h" + +namespace +{ + ModuleLoader<24u, SDL_LoadObject, SDL_UnloadObject, SDL_LoadFunction> g_loader; +} + +void loadImgui(AppGraphCtxType type) +{ + const char* moduleName = demoAppDLLName(type); + + g_loader.loadModule(moduleName); +} + +void unloadImgui() +{ + g_loader.unloadModule(); +} + +// Below are the functions that must be implemented per graphics API + +void imguiGraphContextInit(const ImguiGraphDesc* desc) +{ + return g_loader.function<0>(imguiGraphContextInit, "imguiGraphContextInit", desc); +} + +void imguiGraphContextUpdate(const ImguiGraphDesc* desc) +{ + return g_loader.function<1>(imguiGraphContextUpdate, "imguiGraphContextUpdate", desc); +} + +void imguiGraphContextDestroy() +{ + return g_loader.function<2>(imguiGraphContextDestroy, "imguiGraphContextDestroy"); +} + +void imguiGraphRecordBegin() +{ + return g_loader.function<3>(imguiGraphRecordBegin, "imguiGraphRecordBegin"); +} + +void imguiGraphRecordEnd() +{ + return g_loader.function<4>(imguiGraphRecordEnd, "imguiGraphRecordEnd"); +} + +void imguiGraphVertex2f(float x, float y) +{ + return g_loader.function<5>(imguiGraphVertex2f, "imguiGraphVertex2f", x, y); +} + +void imguiGraphVertex2fv(const float* v) +{ + return g_loader.function<6>(imguiGraphVertex2fv, "imguiGraphVertex2fv", v); +} + +void imguiGraphTexCoord2f(float u, float v) +{ + return g_loader.function<7>(imguiGraphTexCoord2f, "imguiGraphTexCoord2f", u, v); +} + +void imguiGraphColor4ub(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) +{ + return g_loader.function<8>(imguiGraphColor4ub, "imguiGraphColor4ub", red, green, blue, alpha); +} + +void imguiGraphColor4ubv(const uint8_t* v) +{ + return g_loader.function<9>(imguiGraphColor4ubv, "imguiGraphColor4ubv", v); +} + +void imguiGraphFontTextureEnable() +{ + return g_loader.function<10>(imguiGraphFontTextureEnable, "imguiGraphFontTextureEnable"); +} + +void imguiGraphFontTextureDisable() +{ + return g_loader.function<11>(imguiGraphFontTextureDisable, "imguiGraphFontTextureDisable"); +} + +void imguiGraphEnableScissor(int x, int y, int width, int height) +{ + return g_loader.function<12>(imguiGraphEnableScissor, "imguiGraphEnableScissor", x, y, width, height); +} + +void imguiGraphDisableScissor() +{ + return g_loader.function<13>(imguiGraphDisableScissor, "imguiGraphDisableScissor"); +} + +void imguiGraphFontTextureInit(unsigned char* data) +{ + return g_loader.function<14>(imguiGraphFontTextureInit, "imguiGraphFontTextureInit",data); +} + +void imguiGraphFontTextureRelease() +{ + return g_loader.function<15>(imguiGraphFontTextureRelease, "imguiGraphFontTextureRelease"); +} + +bool imguiInteropGraphInit(imguiGraphInit_t func, const char* fontpath, AppGraphCtx* appctx) +{ + return g_loader.function<16>(imguiInteropGraphInit, "imguiInteropGraphInit", func, fontpath, appctx); +} + +void imguiInteropGraphUpdate(imguiGraphUpdate_t func, AppGraphCtx* appctx) +{ + return g_loader.function<17>(imguiInteropGraphUpdate, "imguiInteropGraphUpdate", func, appctx); +}
\ No newline at end of file diff --git a/demo/DemoApp/imguiInterop.h b/demo/DemoApp/imguiInterop.h new file mode 100644 index 0000000..3cbbe96 --- /dev/null +++ b/demo/DemoApp/imguiInterop.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +#include "imguiGraph.h" + +#include "appGraphCtx.h" + +IMGUI_GRAPH_API bool imguiInteropGraphInit(imguiGraphInit_t func, const char* fontpath, AppGraphCtx* appctx); + +IMGUI_GRAPH_API void imguiInteropGraphUpdate(imguiGraphUpdate_t func, AppGraphCtx* appctx);
\ No newline at end of file diff --git a/demo/DemoApp/imguiser.cpp b/demo/DemoApp/imguiser.cpp new file mode 100644 index 0000000..64018d0 --- /dev/null +++ b/demo/DemoApp/imguiser.cpp @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include "imguiser.h" + +#include <stdio.h> + +#include <vector> + +namespace +{ + std::vector<ImserNode> g_nodes; + + bool g_shouldSave = false; + bool g_shouldLoad = false; + bool g_shouldLoadC = false; + bool g_saveProcessActive = false; + bool g_loadProcessActive = false; + + char g_saveFilename[256u]; + char g_loadFilename[256u]; + const ImserNode* g_loadC_nodes = nullptr; + unsigned int g_loadC_sizeInBytes = 0; + + const int TEXT_POOL_CAP = 16u * 1024u; + char g_textPool[TEXT_POOL_CAP]; + int g_textPoolIdx = 0; + + char* allocText(const char* text) + { + if (text == nullptr) + { + return nullptr; + } + int len = (int)(strlen(text) + 1); + if (g_textPoolIdx + len < TEXT_POOL_CAP) + { + char* dst = &g_textPool[g_textPoolIdx]; + memcpy(dst, text, len); + g_textPoolIdx += len; + return dst; + } + return nullptr; + } + + struct TreeNode + { + int node; + int parent; + int childStart; + int childEnd; + int next; + int childCount; + }; + + std::vector<TreeNode> g_treeNodes; + int g_treeNodeIdxScope = 0; + int g_treeNodeIdxSearch = 0; + int g_treeNoMatchGroupRef = 0; + + bool treeSearch(const char* name) + { + if (g_treeNoMatchGroupRef != 0) + { + return false; + } + if (name != nullptr) + { + if (g_treeNodes[g_treeNodeIdxSearch].parent != g_treeNodeIdxScope) + { + g_treeNodeIdxSearch = g_treeNodes[g_treeNodeIdxScope].childStart; + } + int startIdx = g_treeNodeIdxSearch; + do + { + int nodeIdx = g_treeNodes[g_treeNodeIdxSearch].node; + if (nodeIdx != -1 && strcmp(g_nodes[nodeIdx].name, name) == 0) + { + return true; + } + // increment seach with wrap + g_treeNodeIdxSearch = g_treeNodes[g_treeNodeIdxSearch].next; + if (g_treeNodeIdxSearch == -1) + { + g_treeNodeIdxSearch = g_treeNodes[g_treeNodeIdxScope].childStart; + } + } while (startIdx != g_treeNodeIdxSearch); + } + else + { + g_treeNodeIdxSearch = g_treeNodes[g_treeNodeIdxSearch].next; + if (g_treeNodeIdxSearch == -1) + { + g_treeNodeIdxSearch = g_treeNodes[g_treeNodeIdxScope].childStart; + } + } + return false; + } +} + +static void imguiserDoSave(const char* filename); +static void imguiserDoLoad(const char* filename); +static void imguiserDoLoadC(const ImserNode* nodes, unsigned int sizeInBytes); + +void imguiserInit() +{ + g_nodes.reserve(4096u); + g_treeNodes.reserve(4096u); + + g_shouldSave = false; + g_shouldLoad = false; + g_shouldLoadC = false; + g_saveProcessActive = false; + g_loadProcessActive = false; + g_saveFilename[0] = '\0'; + g_loadFilename[0] = '\0'; + g_loadC_nodes = nullptr; + g_loadC_sizeInBytes = 0; +} + +void imguiserUpdate() +{ + if (g_saveProcessActive) + { + imguiserDoSave(g_saveFilename); + g_saveProcessActive = false; + } + if (g_loadProcessActive) + { + g_loadProcessActive = false; + } + if (g_shouldSave) + { + g_saveProcessActive = true; + g_shouldSave = false; + } + if (g_shouldLoad) + { + imguiserDoLoad(g_loadFilename); + if(g_shouldLoad) g_loadProcessActive = true; + g_shouldLoad = false; + } + if (g_shouldLoadC) + { + imguiserDoLoadC(g_loadC_nodes, g_loadC_sizeInBytes); + if (g_shouldLoadC) g_loadProcessActive = true; + g_shouldLoadC = false; + } +} + +void imguiserDestroy() +{ + +} + +void imguiserBeginFrame() +{ + if (!g_loadProcessActive) + { + g_nodes.clear(); + // reset text pool + g_textPoolIdx = 0; + } + g_treeNodeIdxScope = 0; + g_treeNodeIdxSearch = 0; + g_treeNoMatchGroupRef = 0; +} + +void imguiserEndFrame() +{ + +} + +void imguiserBeginGroup(const char* name, int* numItems) +{ + if (g_saveProcessActive) + { + ImserNode group = imserNodeGroupBegin(name); + + g_nodes.push_back(group); + } + if (g_loadProcessActive) + { + // search for group with matching name + if (treeSearch(name)) + { + g_treeNodeIdxScope = g_treeNodeIdxSearch; + if (g_treeNodeIdxScope == -1) g_treeNodeIdxScope = 0; + g_treeNodeIdxSearch = g_treeNodes[g_treeNodeIdxScope].childStart; + + if (numItems) + { + *numItems = g_treeNodes[g_treeNodeIdxScope].childCount; + } + } + else + { + g_treeNoMatchGroupRef++; + g_treeNodeIdxScope++; + } + } +} + +void imguiserEndGroup() +{ + if (g_saveProcessActive) + { + ImserNode group = imserNodeGroupEnd(); + + g_nodes.push_back(group); + } + if (g_loadProcessActive) + { + if (g_treeNoMatchGroupRef == 0) + { + g_treeNodeIdxScope = g_treeNodes[g_treeNodeIdxScope].parent; + if (g_treeNodeIdxScope == -1) g_treeNodeIdxScope = 0; + g_treeNodeIdxSearch = 0; + } + else + { + g_treeNoMatchGroupRef--; + g_treeNodeIdxScope--; + } + } +} + +void imguiserValue1f(const char* text, float* val) +{ + if (g_saveProcessActive) + { + ImserNode item = imserNodeValue1f(text, *val); + + g_nodes.push_back(item); + } + if (g_loadProcessActive) + { + if (text != nullptr) + { + if (treeSearch(text)) + { + *val = g_nodes[g_treeNodes[g_treeNodeIdxSearch].node].valFloat; + } + } + else + { + *val = g_nodes[g_treeNodes[g_treeNodeIdxSearch].node].valFloat; + treeSearch(nullptr); + } + } +} + +void imguiserValueBool(const char* text, bool* val) +{ + if (g_saveProcessActive) + { + ImserNode item = imserNodeValueBool(text, *val); + + g_nodes.push_back(item); + } + if (g_loadProcessActive) + { + if (text != nullptr) + { + if (treeSearch(text)) + { + *val = g_nodes[g_treeNodes[g_treeNodeIdxSearch].node].valBool; + } + } + else + { + *val = g_nodes[g_treeNodes[g_treeNodeIdxSearch].node].valBool; + treeSearch(nullptr); + } + } +} + +bool imguiserCheck(const char* text, bool checked, bool enabled) +{ + auto ret = imguiCheck(text, checked, enabled); + + bool temp = checked; + imguiserValueBool(text, &temp); + if (temp != checked) ret = true; + + return ret; +} + +bool imguiserSlider(const char* text, float* val, float vmin, float vmax, float vinc, bool enabled) +{ + auto ret = imguiSlider(text, val, vmin, vmax, vinc, enabled); + + float temp = *val; + imguiserValue1f(text, val); + if (temp != *val) ret = true; + + return ret; +} + +bool imguiserOffscreenUpdate() +{ + return g_saveProcessActive || g_loadProcessActive; +} + +void imguiserSave(const char* filename) +{ + g_shouldSave = true; + int len = int(strlen(filename) + 1); + if (len > 256u) len = 256u; + memcpy(g_saveFilename, filename, len); +} + +void imguiserLoad(const char* filename) +{ + g_shouldLoad = true; + int len = int(strlen(filename) + 1); + if (len > 256u) len = 256u; + memcpy(g_loadFilename, filename, len); +} + +void imguiserLoadC(const ImserNode* nodes, unsigned int sizeInBytes) +{ + g_shouldLoadC = true; + g_loadC_nodes = nodes; + g_loadC_sizeInBytes = sizeInBytes; +} + +inline void fprintTabs(FILE* file, unsigned int count) +{ + static const char tabs[11u] = "\t\t\t\t\t\t\t\t\t\t"; + char format[] = "%.Xs"; + format[2] = '0' + (char)((count >= 10) ? 9 : count); + fprintf(file, format, tabs); +} + +static void imguiserDoSave(const char* filename) +{ + FILE* file = nullptr; + fopen_s(&file, filename, "w"); + + unsigned int tabAmount = 0; + if (file) + { + fprintf(file, "const ImserNode g_root[] = {\n"); + tabAmount++; + + for (size_t i = 0u; i < g_nodes.size(); i++) + { + ImserNode& node = g_nodes[i]; + + switch (node.typeID) + { + case IMSER_TYPE_GROUP_BEGIN: + fprintTabs(file, tabAmount); + fprintf(file, "imserNodeGroupBegin(\"%s\"),\n", node.name); + tabAmount++; + break; + case IMSER_TYPE_GROUP_END: + tabAmount--; + fprintTabs(file, tabAmount); + fprintf(file, "imserNodeGroupEnd(),\n"); + break; + case IMSER_TYPE_FLOAT: + fprintTabs(file, tabAmount); + if(node.name) fprintf(file, "imserNodeValue1f(\"%s\", %ff),\n", node.name, node.valFloat); + else fprintf(file, "imserNodeValue1f(nullptr, %ff),\n", node.valFloat); + break; + case IMSER_TYPE_BOOL: + fprintTabs(file, tabAmount); + if(node.name) fprintf(file, "imserNodeValueBool(\"%s\", %s),\n", node.name, node.valBool ? "true" : "false"); + else fprintf(file, "imserNodeValueBool(nullptr, %s),\n", node.valBool ? "true" : "false"); + break; + } + } + + fprintf(file, "};"); + + fclose(file); + } +} + +inline void skipWS(FILE* file) +{ + fscanf(file, "%*[ \t\n\v\f\r]"); +} + +inline const char* extractName(FILE* file, char* buf) +{ + const char* name = nullptr; + skipWS(file); + char c = fgetc(file); + if (c == '\"') + { + fscanf(file, "%255[^\"]", buf); + + name = allocText(buf); + } + return name; +} + +inline float extractValue1f(FILE* file, char* buf) +{ + float value = 0.f; + fscanf(file, "%f", &value); + return value; +} + +inline bool extractBool(FILE* file, char* buf) +{ + skipWS(file); + fscanf(file, "%255[^,) \t\n\v\f\r]", buf); + bool val = false; + if (strcmp(buf, "true") == 0) val = true; + return val; +} + +static void generateTree() +{ + // generate tree for faster searching + { + g_treeNodes.clear(); + + // create root node + { + TreeNode n; + n.node = -1; + n.parent = -1; + n.childStart = -1; + n.childEnd = -1; + n.next = -1; + g_treeNodes.push_back(n); + } + // generate tree by playing node list and tracking state + int numNodes = (int)g_nodes.size(); + int treeNodeIdx = 0; + for (int nodeIdx = 0; nodeIdx < numNodes; nodeIdx++) + { + ImserNode& node = g_nodes[nodeIdx]; + + if (node.typeID == IMSER_TYPE_GROUP_BEGIN) + { + // create new node + TreeNode n; + n.node = nodeIdx; + n.parent = treeNodeIdx; + n.childStart = -1; + n.childEnd = -1; + n.next = -1; + n.childCount = 0; + + if (g_treeNodes[treeNodeIdx].childEnd != -1) + { + g_treeNodes[g_treeNodes[treeNodeIdx].childEnd].next = (int)g_treeNodes.size(); + } + else + { + g_treeNodes[treeNodeIdx].childStart = (int)g_treeNodes.size(); + } + g_treeNodes[treeNodeIdx].childEnd = (int)g_treeNodes.size(); + g_treeNodes[treeNodeIdx].childCount++; + + treeNodeIdx = (int)g_treeNodes.size(); + + g_treeNodes.push_back(n); + } + else if (node.typeID == IMSER_TYPE_GROUP_END) + { + // move active scope back to parent + if (treeNodeIdx != -1) + { + treeNodeIdx = g_treeNodes[treeNodeIdx].parent; + } + } + else if (node.typeID == IMSER_TYPE_FLOAT || node.typeID == IMSER_TYPE_BOOL) + { + TreeNode n; + n.node = nodeIdx; + n.parent = treeNodeIdx; + n.childStart = -1; + n.childEnd = -1; + n.next = -1; + n.childCount = 0; + + if (g_treeNodes[treeNodeIdx].childEnd != -1) + { + g_treeNodes[g_treeNodes[treeNodeIdx].childEnd].next = (int)g_treeNodes.size(); + } + else + { + g_treeNodes[treeNodeIdx].childStart = (int)g_treeNodes.size(); + } + g_treeNodes[treeNodeIdx].childEnd = (int)g_treeNodes.size(); + g_treeNodes[treeNodeIdx].childCount++; + + g_treeNodes.push_back(n); + } + } + } +} + +static void imguiserDoLoad(const char* filename) +{ + FILE* file = nullptr; + fopen_s(&file, filename, "r"); + + const unsigned int bufSize = 256u; + char buf[bufSize]; + + if (file) + { + // enable save process + g_saveProcessActive = true; + g_nodes.clear(); + // reset text pool + g_textPoolIdx = 0; + + // scan to 'ImserNode' + while (!feof(file)) + { + fscanf(file, "%255s,", buf); + if (strcmp("ImserNode", buf) == 0) + { + break; + } + } + // scan to '{' + while (!feof(file)) + { + if (fgetc(file) == '{') + { + break; + } + } + // start reading commands + while (!feof(file)) + { + // get command name + skipWS(file); + fscanf(file, "%255[^(](", buf); + if (strcmp(buf, "imserNodeGroupBegin") == 0) + { + auto name = extractName(file, buf); + imguiserBeginGroup(name, nullptr); + } + else if (strcmp(buf, "imserNodeGroupEnd") == 0) + { + imguiserEndGroup(); + } + else if (strcmp(buf, "imserNodeValue1f") == 0) + { + auto name = extractName(file, buf); + fscanf(file, "%[^,],", buf); + float val = extractValue1f(file, buf); + imguiserValue1f(name, &val); + } + else if (strcmp(buf, "imserNodeValueBool") == 0) + { + auto name = extractName(file, buf); + fscanf(file, "%[^,],", buf); + bool val = extractBool(file, buf); + imguiserValueBool(name, &val); + } + + // scan past close of command + fscanf(file, "%[^,],", buf); + } + + // disable save process + g_saveProcessActive = false; + + fclose(file); + } + else + { + g_shouldLoad = false; + return; + } + + generateTree(); +} + +static void imguiserDoLoadC(const ImserNode* nodes, unsigned int sizeInBytes) +{ + // copy to g_nodes + unsigned int numNodes = sizeInBytes / sizeof(ImserNode); + + g_nodes.clear(); + // reset text pool + g_textPoolIdx = 0; + + g_nodes.resize(numNodes); + for (size_t i = 0; i < g_nodes.size(); i++) + { + g_nodes[i] = nodes[i]; + } + + generateTree(); +} + +ImserNode imserNodeGroupBegin(const char* name) +{ + ImserNode group; + group.name = name; + group.typeID = IMSER_TYPE_GROUP_BEGIN; + group.valBool = false; + return group; +} + +ImserNode imserNodeGroupEnd() +{ + ImserNode group; + group.name = nullptr; + group.typeID = IMSER_TYPE_GROUP_END; + group.valBool = false; + return group; +} + +ImserNode imserNodeValue1f(const char* name, float value) +{ + ImserNode item; + item.name = name; + item.typeID = IMSER_TYPE_FLOAT; + item.valFloat = value; + return item; +} + +ImserNode imserNodeValueBool(const char* name, bool value) +{ + ImserNode item; + item.name = name; + item.typeID = IMSER_TYPE_BOOL; + item.valBool = value; + return item; +}
\ No newline at end of file diff --git a/demo/DemoApp/imguiser.h b/demo/DemoApp/imguiser.h new file mode 100644 index 0000000..2ff3495 --- /dev/null +++ b/demo/DemoApp/imguiser.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +#include "imgui.h" + +struct ImserNode; + +/// ******************* imguiser public interface ******************** + +void imguiserInit(); + +void imguiserUpdate(); + +void imguiserDestroy(); + +void imguiserBeginFrame(); + +void imguiserEndFrame(); + +void imguiserBeginGroup(const char* name, int* numItems); + +void imguiserEndGroup(); + +bool imguiserCheck(const char* text, bool checked, bool enabled = true); + +bool imguiserSlider(const char* text, float* val, float vmin, float vmax, float vinc, bool enabled = true); + +bool imguiserOffscreenUpdate(); + +void imguiserValue1f(const char* text, float* val); + +void imguiserValueBool(const char* text, bool* val); + +void imguiserSave(const char* filename); + +void imguiserLoad(const char* filename); + +void imguiserLoadC(const ImserNode* nodes, unsigned int sizeInBytes); + +/// **************** imguiser serialization protocol ********************* + +enum ImserType +{ + IMSER_TYPE_GROUP_BEGIN = 0, + IMSER_TYPE_GROUP_END = 1, + IMSER_TYPE_FLOAT = 2, + IMSER_TYPE_BOOL = 3, +}; + +struct ImserNode +{ + const char* name; + ImserType typeID; + union + { + float valFloat; + bool valBool; + }; +}; + +ImserNode imserNodeGroupBegin(const char* name); + +ImserNode imserNodeGroupEnd(); + +ImserNode imserNodeValue1f(const char* name, float value); + +ImserNode imserNodeValueBool(const char* name, bool value);
\ No newline at end of file diff --git a/demo/DemoApp/loader.cpp b/demo/DemoApp/loader.cpp new file mode 100644 index 0000000..3b4e5be --- /dev/null +++ b/demo/DemoApp/loader.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include "loader.h" + +#include <SDL.h> + +#include "appGraphCtx.h" +#include "mesh.h" +#include "imgui.h" + +#include "NvFlowInterop.h" +#include "NvFlow.h" + +void loadModules(AppGraphCtxType type) +{ + loadAppGraphCtx(type); + loadNvFlowInterop(type); + loadMesh(type); + loadImgui(type); + loadComputeContext(type); +} + +void unloadModules() +{ + unloadComputeContext(); + unloadImgui(); + unloadMesh(); + unloadNvFlowInterop(); + unloadAppGraphCtx(); +}
\ No newline at end of file diff --git a/demo/DemoApp/loader.h b/demo/DemoApp/loader.h new file mode 100644 index 0000000..3028325 --- /dev/null +++ b/demo/DemoApp/loader.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +enum AppGraphCtxType +{ + APP_CONTEXT_D3D11 = 1, + APP_CONTEXT_D3D12 = 2 +}; + +#ifndef DEMOAPP_STR +#define XDEMOAPP_STR(s) DEMOAPP_STR(s) +#define DEMOAPP_STR(s) #s +#endif + +namespace +{ + const char* demoAppDLLName(AppGraphCtxType type) + { + return (type == APP_CONTEXT_D3D12) ? + "DemoAppD3D12" XDEMOAPP_STR(DLL_SUFFIX) ".dll" : + "DemoAppD3D11" XDEMOAPP_STR(DLL_SUFFIX) ".dll"; + } + + const char* nvFlowDLLName(AppGraphCtxType type) + { + return (type == APP_CONTEXT_D3D12) ? + "NvFlowD3D12" XDEMOAPP_STR(DLL_SUFFIX) ".dll" : + "NvFlowD3D11" XDEMOAPP_STR(DLL_SUFFIX) ".dll"; + } +} + +void loadModules(AppGraphCtxType type); +void unloadModules(); + +void loadAppGraphCtx(AppGraphCtxType type); +void unloadAppGraphCtx(); + +void loadNvFlowInterop(AppGraphCtxType type); +void unloadNvFlowInterop(); + +void loadMesh(AppGraphCtxType type); +void unloadMesh(); + +void loadImgui(AppGraphCtxType type); +void unloadImgui(); + +void loadComputeContext(AppGraphCtxType type); +void unloadComputeContext(); + +template<unsigned int maxFunctionCount, void* loadobject(const char*), void unloadobject(void*), void* loadfunction(void*,const char*)> +struct ModuleLoader +{ + static const int m_functionCount = maxFunctionCount; + void** m_functionPtrs[m_functionCount] = { nullptr }; + const char* m_functionNames[m_functionCount] = { nullptr }; + + void* m_module = nullptr; + + void* loadFunction(const char* name, int uid, void** ptr) + { + m_functionPtrs[uid] = ptr; + m_functionNames[uid] = name; + return SDL_LoadFunction(m_module, name); + } + + template <int uid, class ret, class ...Args> + ret function(ret(*)(Args...args), const char* name, Args...args) + { + static void* func = loadFunction(name, uid, &func); + + return ((ret(*)(Args...args))func)(args...); + } + + void loadModule(const char* moduleName) + { + m_module = loadobject(moduleName); + + // load functions with non-null names + for (int i = 0; i < m_functionCount; i++) + { + const char* name = m_functionNames[i]; + void** funcPtr = m_functionPtrs[i]; + if (name && funcPtr) + { + *funcPtr = loadfunction(m_module, name); + } + } + } + + void unloadModule() + { + unloadobject(m_module); + + for (int i = 0; i < m_functionCount; i++) + { + void** funcPtr = m_functionPtrs[i]; + if (funcPtr) + { + *funcPtr = nullptr; + } + } + } + + ModuleLoader() {} +};
\ No newline at end of file diff --git a/demo/DemoApp/main.cpp b/demo/DemoApp/main.cpp new file mode 100644 index 0000000..e35ea43 --- /dev/null +++ b/demo/DemoApp/main.cpp @@ -0,0 +1,605 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <stdint.h> +#include <stdio.h> +#include <assert.h> + +#include <SDL.h> +#include <SDL_video.h> +#include <SDL_syswm.h> + +#include "appGraphCtx.h" +#include "scene.h" + +#include "imgui.h" +#include "imguiGraph.h" +#include "imguiInterop.h" +#include "imguiser.h" + +#include "loader.h" + +#include "camera.h" + +#include <thread> + +const int gWinWdefault = 2560 / 2; +const int gWinHdefault = 1600 / 2; +int gWinW = gWinWdefault; +int gWinH = gWinHdefault; + +SDL_Window* gWin = nullptr; +bool gFullscreen = false; + +bool gUseD3D12 = false; +int gAppRunCount = 1; + +AppGraphCtx* gAppGraphCtx = nullptr; +Scene* gScene = nullptr; + +Uint64 gTimerFreq = 0u; +Uint64 gTimerCount = 0; +float gDeltaTime = 0.f; +float gFixedDt = 1.f / 60.f; +bool gFixedTimeStepMode = false; + +bool gPaused = false; +bool gProfileEnabled = false; + +Camera gCamera; +bool gCameraActive = false; + +int gMouseX = 0; +int gMouseY = 0; +unsigned char gMouseButton = 0; + +const int g_imguiBorder = 20; +const int g_imguiWidth = 200; +const int g_imguiHeight = 250; +bool gImguiActive = false; +bool g_imguiHide = false; + +bool gClearDark = false; +float gClearVal[4] = { 0.33f,0.33f,0.33f,1.f }; + +void toggleDark() +{ + gClearDark = !gClearDark; + if (gClearDark) + { + gClearVal[0] = 0.f; + gClearVal[1] = 0.f; + gClearVal[2] = 0.f; + gClearVal[3] = 1.f; + } + else + { + gClearVal[0] = 0.33f; + gClearVal[1] = 0.33f; + gClearVal[2] = 0.33f; + gClearVal[3] = 1.f; + } +} + +bool appGraphCtxUpdateSize() +{ + return AppGraphCtxUpdateSize(gAppGraphCtx, gWin, gFullscreen); +} + +void appReleaseRenderTargets() +{ + AppGraphCtxReleaseRenderTarget(gAppGraphCtx); +} + +#define LEAK_TEST 0 + +#if LEAK_TEST +struct AppMemRefCount +{ + int refCount = 0; + AppMemRefCount() {} + ~AppMemRefCount() + { + if (refCount != 0) + { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Flow Demo App", "Error: Memory Leak", nullptr); + } + } +}; +AppMemRefCount gAppMemRefCount; + +void* appMalloc(size_t size) +{ + gAppMemRefCount.refCount++; + return malloc(size); +} + +void appFree(void* ptr) +{ + if(ptr) gAppMemRefCount.refCount--; + free(ptr); +} +#endif + +void appInit() +{ + loadModules(gUseD3D12 ? APP_CONTEXT_D3D12 : APP_CONTEXT_D3D11); + +#if LEAK_TEST + NvFlowSetMallocFunc(appMalloc); + NvFlowSetFreeFunc(appFree); +#endif + + // create app graph context + gAppGraphCtx = AppGraphCtxCreate(0); + + appGraphCtxUpdateSize(); + + gScene = getScene(0); + + AppGraphCtxFrameStart(gAppGraphCtx, gClearVal); + + gScene->init(gAppGraphCtx, gWinW, gWinH); + + // create imgui, connect to app graph context + imguiInteropGraphInit(imguiGraphInit, "../../data/DroidSans.ttf", gAppGraphCtx); + imguiserInit(); + + AppGraphCtxFramePresent(gAppGraphCtx, true); +} + +void appRender() +{ + DirectX::XMMATRIX projection; + DirectX::XMMATRIX view; + gCamera.getViewMatrix(view); + gCamera.getProjectionMatrix(projection, gWinW, gWinH); + + bool valid = appGraphCtxUpdateSize(); + + if (!valid) + { + return; + } + + AppGraphCtxFrameStart(gAppGraphCtx, gClearVal); + + // interop update + imguiInteropGraphUpdate(imguiGraphUpdate, gAppGraphCtx); + + // timer update + { + Uint64 oldCount = gTimerCount; + gTimerFreq = SDL_GetPerformanceFrequency(); + gTimerCount = SDL_GetPerformanceCounter(); + if (oldCount > 0) + { + gDeltaTime = (float(gTimerCount - oldCount)) / float(gTimerFreq); + } + if (gFixedTimeStepMode) + { + gDeltaTime = gFixedDt; + } + } + + static unsigned int maxFramesInFlight = 4; + + // imgui update + Scene* newScene = gScene; + { + imguiserBeginFrame(); + imguiBeginFrame(gMouseX, gMouseY, gMouseButton, 0); + + // print profile information as needed + if (gProfileEnabled) + { + const int lineSpace = 16; + + imguiDrawText(g_imguiWidth + g_imguiBorder, gWinH - 2 * g_imguiBorder, IMGUI_ALIGN_LEFT, "Performance:", 0xFFFFFFFF); + + const char* label = nullptr; + float cpuTime = 0.f; + float gpuTime = 0.f; + int index = 0; + char buf[80]; + buf[79] = 0; + // print frame time + { + static double frameSum = 0.0; + static double frameCount = 0.0; + frameSum += gDeltaTime; + frameCount += 1.0; + frameSum *= 0.99; + frameCount *= 0.99; + double frameAve = frameSum / frameCount; + + snprintf(buf, 79, "Frame: %.3f ms", 1000.f * frameAve); + imguiDrawText(g_imguiWidth + g_imguiBorder, gWinH - 2 * g_imguiBorder - (index + 1) * lineSpace, IMGUI_ALIGN_LEFT, buf, 0xFFFFFFFF); + index++; + + snprintf(buf, 79, "MaxFramesInFlight: %d", maxFramesInFlight); + imguiDrawText(g_imguiWidth + g_imguiBorder, gWinH - 2 * g_imguiBorder - (index + 1) * lineSpace, IMGUI_ALIGN_LEFT, buf, 0xFFFFFFFF); + index++; + } + int profileIndex = 0; + while (AppGraphCtxProfileGet(gAppGraphCtx, &label, &cpuTime, &gpuTime, profileIndex)) + { + snprintf(buf, 79, "%s: gpu(%.3f) cpu(%.3f) ms", label, 1000.f * gpuTime, 1000.f * cpuTime); + imguiDrawText(g_imguiWidth + g_imguiBorder, gWinH - 2 * g_imguiBorder - (index + 1) * lineSpace, IMGUI_ALIGN_LEFT,buf, 0xFFFFFFFF); + index++; + profileIndex++; + } + + // print memory usage + int statIdx = 0; + while(gScene && gScene->getStats(index, statIdx, buf)) + { + imguiDrawText(g_imguiWidth + g_imguiBorder, gWinH - 2 * g_imguiBorder - (index + 1) * lineSpace, IMGUI_ALIGN_LEFT, buf, 0xFFFFFFFF); + statIdx++; + index++; + } + } + + static int scrollScene = 0u; + + int sceneX = g_imguiBorder; + int sceneY = gWinH - g_imguiHeight; + int sceneW = g_imguiWidth - g_imguiBorder; + int sceneH = g_imguiHeight - g_imguiBorder; + + imguiBeginScrollArea("Scene", + sceneX, sceneY, + sceneW, sceneH, + &scrollScene); + + for (int i = 0; true; i++) + { + Scene* scene = getScene(i); + if (scene == nullptr) break; + if (imguiItem(scene->m_name, true)) + { + newScene = scene; + } + } + + imguiEndScrollArea(); + + gScene->imgui( + sceneX, sceneY, + sceneW, sceneH + ); + + imguiEndFrame(); + imguiserEndFrame(); + imguiserUpdate(); + } + + // TODO: less synchronization preferred here + if (gScene->shouldReset() || (newScene != gScene)) + { + imguiGraphDraw(); + + AppGraphCtxFramePresent(gAppGraphCtx, true); + + AppGraphCtxFrameStart(gAppGraphCtx, gClearVal); + + if (newScene != gScene) + { + gScene->release(); + gScene = newScene; + gScene->init(gAppGraphCtx, gWinW, gWinH); + } + else + { + gScene->reset(); + } + + imguiGraphDraw(); + + AppGraphCtxFramePresent(gAppGraphCtx, true); + + AppGraphCtxFrameStart(gAppGraphCtx, gClearVal); + } + + if(!gPaused) gScene->update(gDeltaTime); + + gScene->preDraw(); + + gScene->draw(projection,view); + + if (!g_imguiHide) + { + imguiGraphDraw(); + } + + AppGraphCtxFramePresent(gAppGraphCtx, false); + + // throttle frames in flight + maxFramesInFlight = 4u; + { + static double frameSum = 0.0; + static double frameCount = 0.0; + frameSum += gDeltaTime; + frameCount += 1.0; + frameSum *= 0.99; + frameCount *= 0.99; + double frameAve = frameSum / frameCount; + double targetLatency = 1.f / 60.f; + double numFrames = targetLatency / frameAve; + if (numFrames < 2.0) + { + maxFramesInFlight = 2; + } + else if (numFrames > 6.0) + { + maxFramesInFlight = 6; + } + else + { + maxFramesInFlight = (unsigned int)numFrames; + } + } + AppGraphCtxWaitForFrames(gAppGraphCtx, maxFramesInFlight); +} + +void appRelease() +{ + // do this first, since it flushes all GPU work + appReleaseRenderTargets(); + + gScene->release(); + + imguiserDestroy(); + imguiGraphDestroy(); + + AppGraphCtxRelease(gAppGraphCtx); + + gAppGraphCtx = nullptr; + + NvFlowDeferredRelease(2000.f); + + unloadModules(); +} + +bool imguiMouseEvent(SDL_Event& e) +{ + int x = 0; + int y = 0; + if (e.type == SDL_MOUSEBUTTONDOWN || e.type == SDL_MOUSEBUTTONUP) { + x = e.button.x; + y = e.button.y; + } + else if (e.type == SDL_MOUSEMOTION) { + x = e.motion.x; + y = e.motion.y; + } + + if (e.type == SDL_MOUSEBUTTONDOWN) { + if (e.button.button == SDL_BUTTON_LEFT) { + gMouseButton = IMGUI_MBUT_LEFT; + } + else if (e.button.button == SDL_BUTTON_RIGHT) { + gMouseButton = IMGUI_MBUT_RIGHT; + } + } + else if (e.type == SDL_MOUSEBUTTONUP) { + if (e.button.button == SDL_BUTTON_LEFT) { + gMouseButton = 0; + } + else if (e.button.button == SDL_BUTTON_RIGHT) { + gMouseButton = 0; + } + } + else if (e.type == SDL_MOUSEMOTION) { + gMouseX = e.motion.x; + gMouseY = gWinH - 1 - e.motion.y; + } + + bool active = gScene->imguiMouse(gMouseX, gMouseY, gMouseButton); + + active = active || (x < g_imguiWidth && y < g_imguiHeight); + + if (g_imguiHide) + { + active = false; + } + + return active; +} + +void mouseEvent(SDL_Event& e) +{ + if (e.type == SDL_MOUSEBUTTONDOWN) + { + if (!gCameraActive && !g_imguiHide) + { + gImguiActive = imguiMouseEvent(e); + } + if (!gImguiActive) + { + if (e.button.button == SDL_BUTTON_LEFT) + { + gCamera.rotationStart(e.button.x, e.button.y); + gCameraActive = true; + } + else if (e.button.button == SDL_BUTTON_MIDDLE) + { + gCamera.translateStart(e.button.x, e.button.y); + gCameraActive = true; + } + else if (e.button.button == SDL_BUTTON_RIGHT) + { + gCamera.zoomStart(e.button.x, e.button.y); + gCameraActive = true; + } + } + } + else if (e.type == SDL_MOUSEBUTTONUP) + { + { + gImguiActive = imguiMouseEvent(e); + } + { + if (e.button.button == SDL_BUTTON_LEFT) + { + gCamera.rotationEnd(e.button.x, e.button.y); + gCameraActive = false; + } + else if (e.button.button == SDL_BUTTON_MIDDLE) + { + gCamera.translateEnd(e.button.x, e.button.y); + gCameraActive = false; + } + else if (e.button.button == SDL_BUTTON_RIGHT) + { + gCamera.zoomEnd(e.button.x, e.button.y); + gCameraActive = false; + } + } + } + else if (e.type == SDL_MOUSEMOTION) + { + gImguiActive = imguiMouseEvent(e); + + gCamera.rotationMove(e.motion.x, e.motion.y, gWinW, gWinH); + gCamera.zoomMove(e.motion.x, e.motion.y, gWinW, gWinH); + gCamera.translateMove(e.motion.x, e.motion.y, gWinW, gWinH); + } +} + +int main(int argc, char** argv) +{ + for (int i = 1; i < argc; i++) + { + if (0 == strcmp(argv[i], "-d3d12")) + { + gUseD3D12 = true; + } + } + + if (SDL_Init(SDL_INIT_VIDEO)) + { + fprintf(stderr, "Failed to init SDL: %s\n", SDL_GetError()); + return 1; + } + + // preserve across transitions + gCamera.init(gWinW, gWinH); + + for (; gAppRunCount > 0; gAppRunCount--) + { + const char* winName = gUseD3D12 ? "NvFlow Demo App D3D12" : "NvFlow Demo App D3D11"; + + gWin = SDL_CreateWindow(winName, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + gWinW, gWinH, SDL_WINDOW_RESIZABLE /*| SDL_WINDOW_OPENGL*/); + if (gWin == nullptr) + { + return -1; + } + + appInit(); + + bool shouldRun = true; + while (shouldRun) + { + appRender(); + + SDL_Event e; + while (SDL_PollEvent(&e)) + { + if (e.type == SDL_QUIT) + { + shouldRun = false; + break; + } + else if (e.type == SDL_WINDOWEVENT) + { + if (e.window.event == SDL_WINDOWEVENT_RESIZED) + { + gWinW = e.window.data1; + gWinH = e.window.data2; + + gScene->resize(gWinW, gWinH); + } + } + else if (e.type == SDL_KEYDOWN) + { + if (e.key.keysym.sym == SDLK_ESCAPE) + { + shouldRun = false; + } + if (e.key.keysym.sym == SDLK_F1) + { + gCamera.isProjectionRH = !gCamera.isProjectionRH; + } + if (e.key.keysym.sym == SDLK_F11) + { + gFullscreen = !gFullscreen; + + appReleaseRenderTargets(); + + SDL_SetWindowFullscreen(gWin, gFullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + + //appInitRenderTargets(); + } + if (e.key.keysym.sym == SDLK_F10) + { + gAppRunCount++; + shouldRun = false; + } + if (e.key.keysym.sym == SDLK_q) + { + gFixedTimeStepMode = !gFixedTimeStepMode; + } + if (e.key.keysym.sym == SDLK_w) + { + gProfileEnabled = !gProfileEnabled; + if(gAppGraphCtx) AppGraphCtxProfileEnable(gAppGraphCtx, gProfileEnabled); + } + if (e.key.keysym.sym == SDLK_SPACE) + { + if (gScene) gScene->shoot(); + } + if (e.key.keysym.sym == SDLK_p) + { + gPaused = !gPaused; + } + if (e.key.keysym.sym == SDLK_d) + { + toggleDark(); + } + if (e.key.keysym.sym == SDLK_g) + { + g_imguiHide = !g_imguiHide; + } + } + else if (e.type == SDL_KEYUP) + { + } + else if (e.type == SDL_MOUSEBUTTONDOWN || e.type == SDL_MOUSEBUTTONUP || e.type == SDL_MOUSEMOTION) + { + mouseEvent(e); + } + } + } + + appRelease(); + + SDL_DestroyWindow(gWin); + + // mark module changes + gUseD3D12 = !gUseD3D12; + gFullscreen = false; + } + + SDL_Quit(); + + return 0; +}
\ No newline at end of file diff --git a/demo/DemoApp/mesh.cpp b/demo/DemoApp/mesh.cpp new file mode 100644 index 0000000..26acb2f --- /dev/null +++ b/demo/DemoApp/mesh.cpp @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include "mesh.h" + +#include <vector> + +struct Mesh +{ + std::vector<MeshVertex> m_vertices; + std::vector<MeshUint> m_indices; + + float m_bounds[6] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }; + + MeshContext* m_context = nullptr; + MeshIndexBuffer* m_indexBuffer = nullptr; + MeshVertexBuffer* m_vertexBuffer = nullptr; + + Mesh() {} + + void loadFromPLY(const char* filename); + + void computeBounds(); + + void normalize(); +}; + +Mesh* MeshCreate(MeshContext* context) +{ + Mesh* mesh = new Mesh; + + mesh->m_context = context; + + return mesh; +} + +void MeshLoadFromFile(Mesh* mesh, const char* filename) +{ + MeshIndexBufferRelease(mesh->m_indexBuffer); + MeshVertexBufferRelease(mesh->m_vertexBuffer); + + mesh->loadFromPLY(filename); + + mesh->computeBounds(); + + mesh->normalize(); + + mesh->m_vertexBuffer = MeshVertexBufferCreate(mesh->m_context, &mesh->m_vertices[0], (MeshUint)mesh->m_vertices.size()); + mesh->m_indexBuffer = MeshIndexBufferCreate(mesh->m_context, &mesh->m_indices[0], (MeshUint)mesh->m_indices.size()); +} + +void MeshGetData(Mesh* mesh, MeshData* data) +{ + data->numVertices = (MeshUint) mesh->m_vertices.size(); + data->positions = &mesh->m_vertices[0].x; + data->positionStride = sizeof(MeshVertex); + data->normals = &mesh->m_vertices[0].nx; + data->normalStride = sizeof(MeshVertex); + + data->numIndices = (MeshUint) mesh->m_indices.size(); + data->indices = &mesh->m_indices[0]; + + data->boundsMin[0] = mesh->m_bounds[0]; + data->boundsMin[1] = mesh->m_bounds[1]; + data->boundsMin[2] = mesh->m_bounds[2]; + data->boundsMax[0] = mesh->m_bounds[3]; + data->boundsMax[1] = mesh->m_bounds[4]; + data->boundsMax[2] = mesh->m_bounds[5]; +} + +void MeshDraw(Mesh* mesh, const MeshDrawParams* params) +{ + MeshContextDrawParams drawParams; + drawParams.params = params; + drawParams.indexBuffer = mesh->m_indexBuffer; + drawParams.vertexBuffer = mesh->m_vertexBuffer; + + MeshContextDraw(mesh->m_context, &drawParams); +} + +void MeshRelease(Mesh* mesh) +{ + if (mesh == nullptr) return; + + MeshIndexBufferRelease(mesh->m_indexBuffer); + MeshVertexBufferRelease(mesh->m_vertexBuffer); + + delete mesh; +} + +/// **************** Private functions ******************************* + +void Mesh::computeBounds() +{ + size_t imax = m_vertices.size(); + if (imax >= 1) + { + m_bounds[0] = m_bounds[3] = m_vertices[0].x; + m_bounds[1] = m_bounds[4] = m_vertices[0].y; + m_bounds[2] = m_bounds[5] = m_vertices[0].z; + + for (size_t i = 1; i < imax; i++) + { + m_bounds[0] = fminf(m_bounds[0], m_vertices[i].x); + m_bounds[3] = fmaxf(m_bounds[3], m_vertices[i].x); + m_bounds[1] = fminf(m_bounds[1], m_vertices[i].y); + m_bounds[4] = fmaxf(m_bounds[4], m_vertices[i].y); + m_bounds[2] = fminf(m_bounds[2], m_vertices[i].z); + m_bounds[5] = fmaxf(m_bounds[5], m_vertices[i].z); + } + } +} + +void Mesh::normalize() +{ + size_t imax = m_vertices.size(); + for (size_t i = 0; i < imax; i++) + { + float x, y, z, w; + x = m_vertices[i].nx; + y = m_vertices[i].ny; + z = m_vertices[i].nz; + w = sqrtf(x*x + y*y + z*z); + if (w > 0.f) + { + x /= w; + y /= w; + z /= w; + } + m_vertices[i].nx = x; + m_vertices[i].ny = y; + m_vertices[i].nz = z; + } +} + +/// ****************** PLY mesh support ******************************* + +namespace +{ + struct PLYLoader + { + enum ElementType + { + ELEM_VERTEX = 0, + ELEM_FACE, + ELEM_EDGE, + ELEM_INVALID + }; + + enum Format + { + FORMAT_ASCII = 0, + FORMAT_BINARY_LITTLE_ENDIAN, + FORMAT_BINARY_BIG_ENDIAN, + FORMAT_INVALID + }; + + // temporary variables + FILE* file = nullptr; + + static const int bufSize = 1024u; + char buf[bufSize]; + + ElementType elementType = ELEM_INVALID; + Format format = FORMAT_INVALID; + + int numElements[ELEM_INVALID] = { 0 }; + int numProperties[ELEM_INVALID] = { 0 }; + + int elementList[ELEM_INVALID] = { 0 }; + int elementListIdx = 0; + + // captured variables + std::vector<MeshVertex>& m_vertices; + std::vector<uint32_t>& m_indices; + + // capture in constructor + PLYLoader(Mesh& mesh) : + m_vertices(mesh.m_vertices), + m_indices(mesh.m_indices) + { + } + + // utility functions + void getline() + { + fgets(buf, bufSize, file); + }; + void getstr() + { + fscanf_s(file, "%s", buf, bufSize); + }; + int getint() + { + int i = 0; + fscanf_s(file, "%d", &i); + return i; + }; + bool match(const char* key) + { + return strncmp(buf, key, bufSize) == 0; + }; + + // temporary state + int elemType = ELEM_INVALID; + int elemNum = 0; + int elemProperties = 0; + + template<class getFloatType, class advanceFuncType> + void getVertices(getFloatType getFloat, advanceFuncType advanceFunc) + { + for (int i = 0; i < elemNum; i++) + { + float data[6]; + for (int j = 0; j < elemProperties; j++) + { + float val = getFloat(); + if (j < 6) data[j] = val; + } + m_vertices.push_back(MeshVertex{ + data[0], data[1], data[2], + data[3], data[4], data[5] + }); + advanceFunc(); + } + } + + template<class getCountType, class getIndexType, class advanceFuncType> + void getIndices(getCountType getCount, getIndexType getIndex, advanceFuncType advanceFunc) + { + for (int i = 0; i < elemNum; i++) + { + int count = getCount(); + int indices[4]; + if (count > 0) indices[0] = getIndex(); + if (count > 1) indices[1] = getIndex(); + if (count > 2) indices[2] = getIndex(); + if (count > 3) indices[3] = getIndex(); + + if (count >= 3) + { + m_indices.push_back(indices[0]); + m_indices.push_back(indices[1]); + m_indices.push_back(indices[2]); + } + if (count == 4) + { + m_indices.push_back(indices[2]); + m_indices.push_back(indices[3]); + m_indices.push_back(indices[0]); + } + advanceFunc(); + } + } + + // main phases + bool parseHeader() + { + // verify file format + getstr(); + if (match("ply")) + { + // extra header information + while (feof(file) == 0) + { + getstr(); + if (match("element")) + { + getstr(); + if (match("vertex")) { + elementType = ELEM_VERTEX; + } + else if (match("face")) { + elementType = ELEM_FACE; + } + else if (match("edge")) { + elementType = ELEM_EDGE; + } + unsigned int idx = (unsigned int)elementType; + if (idx < ELEM_INVALID) + { + numElements[idx] = getint(); + } + if (elementListIdx < ELEM_INVALID) + { + elementList[elementListIdx++] = elementType; + } + } + else if (match("format")) + { + getstr(); + if (match("ascii")) { + format = FORMAT_ASCII; + } + else if (match("binary_big_endian")) { + format = FORMAT_BINARY_BIG_ENDIAN; + } + else if (match("binary_little_endian")) { + format = FORMAT_BINARY_LITTLE_ENDIAN; + } + } + else if (match("property")) + { + unsigned int idx = (unsigned int)elementType; + if (idx < ELEM_INVALID) + { + numProperties[idx]++; + } + } + else if (match("end_header")) + { + break; + } + } // end read header + + // advance past newline + getline(); + return true; + } + return false; + } + + void loadData() + { + // read in each element type + for (int eidx = 0; eidx < elementListIdx; eidx++) + { + elemType = elementList[eidx]; + elemNum = numElements[elemType]; + elemProperties = numProperties[elemType]; + + if (elemType == ELEM_VERTEX) + { + // size vertex buffers + m_vertices.reserve(elemNum); + + if (format == FORMAT_ASCII) + { + getVertices( + [&]() + { + float val = 0.f; + fscanf_s(file, "%f", &val); + return val; + }, + [&]() + { + getline(); + } + ); + } + else if (format == FORMAT_BINARY_BIG_ENDIAN) + { + getVertices( + [&]() + { + char data0[4]; + fread(data0, sizeof(float), 1, file); + union + { + char data1[4]; + float val; + }; + data1[0] = data0[3]; + data1[1] = data0[2]; + data1[2] = data0[1]; + data1[3] = data0[0]; + return val; + }, + [&]() + { + } + ); + } + else if (format == FORMAT_BINARY_LITTLE_ENDIAN) + { + getVertices( + [&]() + { + float val = 0.f; + fread(&val, sizeof(float), 1, file); + return val; + }, + [&]() + { + } + ); + } + } + else if (elemType == ELEM_FACE) + { + // size vertex buffers + m_indices.reserve(3 * elemNum); + + if (format == FORMAT_ASCII) + { + getIndices( + [&]() + { + return getint(); + }, + [&]() + { + return getint(); + }, + [&]() + { + getline(); + } + ); + } + else if (format == FORMAT_BINARY_BIG_ENDIAN) + { + getIndices( + [&]() + { + int val = 0; + fread(&val, 1, 1, file); + return val; + }, + [&]() + { + char data0[4]; + fread(data0, sizeof(float), 1, file); + union + { + char data1[4]; + int val; + }; + data1[0] = data0[3]; + data1[1] = data0[2]; + data1[2] = data0[1]; + data1[3] = data0[0]; + return val; + }, + [&]() + { + } + ); + } + else if (format == FORMAT_BINARY_LITTLE_ENDIAN) + { + getIndices( + [&]() + { + int val = 0; + fread(&val, 1, 1, file); + return val; + }, + [&]() + { + int val; + fread(&val, sizeof(int), 1, file); + return val; + }, + [&]() + { + } + ); + } + } + else if (elemType == ELEM_EDGE) + { + + } + } + } + + // main entry point + void operator()(const char* filename) + { + fopen_s(&file, filename, "rb"); + if (file) + { + if (parseHeader()) + { + loadData(); + } + fclose(file); + } + } + }; +} + +void Mesh::loadFromPLY(const char* filename) +{ + PLYLoader loader(*this); + loader(filename); +}
\ No newline at end of file diff --git a/demo/DemoApp/mesh.h b/demo/DemoApp/mesh.h new file mode 100644 index 0000000..9861bac --- /dev/null +++ b/demo/DemoApp/mesh.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +#include <DirectXMath.h> + +#define MESH_API extern "C" __declspec(dllexport) + +/// ****************** Mesh Context Public ******************************* + +typedef unsigned int MeshUint; +typedef unsigned char MeshUint8; + +struct MeshContext; + +struct MeshContextDesc; + +MESH_API MeshContext* MeshContextCreate(const MeshContextDesc* desc); + +MESH_API void MeshContextUpdate(MeshContext* context, const MeshContextDesc* desc); + +MESH_API void MeshContextRelease(MeshContext* context); + +/// ****************** Mesh Interface Public ********************** + +struct Mesh; + +enum MeshRenderMode +{ + MESH_RENDER_SOLID = 0 +}; + +struct MeshDrawParams +{ + MeshUint renderMode; + DirectX::XMMATRIX projection; + DirectX::XMMATRIX view; + DirectX::XMMATRIX model; +}; + +struct MeshData +{ + MeshUint numVertices; + float* positions; + MeshUint positionStride; + float* normals; + MeshUint normalStride; + + MeshUint numIndices; + MeshUint* indices; + + float boundsMin[3]; + float boundsMax[3]; +}; + +MESH_API Mesh* MeshCreate(MeshContext* context); + +MESH_API void MeshLoadFromFile(Mesh* mesh, const char* filename); + +MESH_API void MeshGetData(Mesh* mesh, MeshData* data); + +MESH_API void MeshDraw(Mesh* mesh, const MeshDrawParams* params); + +MESH_API void MeshRelease(Mesh* mesh); + +/// ****************** Mesh Context Implementation ******************************* + +struct MeshVertex +{ + float x, y, z; + float nx, ny, nz; +}; + +struct MeshIndexBuffer; +struct MeshVertexBuffer; + +MESH_API MeshIndexBuffer* MeshIndexBufferCreate(MeshContext* context, MeshUint* indices, MeshUint numIndices); + +MESH_API void MeshIndexBufferRelease(MeshIndexBuffer* buffer); + +MESH_API MeshVertexBuffer* MeshVertexBufferCreate(MeshContext* context, MeshVertex* vertices, MeshUint numVertices); + +MESH_API void MeshVertexBufferRelease(MeshVertexBuffer* buffer); + +struct MeshContextDrawParams +{ + const MeshDrawParams* params; + MeshIndexBuffer* indexBuffer; + MeshVertexBuffer* vertexBuffer; +}; + +MESH_API void MeshContextDraw(MeshContext* context, const MeshContextDrawParams* params);
\ No newline at end of file diff --git a/demo/DemoApp/meshInterop.h b/demo/DemoApp/meshInterop.h new file mode 100644 index 0000000..d8b1102 --- /dev/null +++ b/demo/DemoApp/meshInterop.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +#include "mesh.h" + +#include "appGraphCtx.h" + +MESH_API MeshContext* MeshInteropContextCreate(AppGraphCtx* appctx); + +MESH_API void MeshInteropContextUpdate(MeshContext* context, AppGraphCtx* appctx);
\ No newline at end of file diff --git a/demo/DemoApp/meshLoader.cpp b/demo/DemoApp/meshLoader.cpp new file mode 100644 index 0000000..99e5e49 --- /dev/null +++ b/demo/DemoApp/meshLoader.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <SDL.h> + +#include "loader.h" + +#include "mesh.h" +#include "meshInterop.h" + +namespace +{ + ModuleLoader<16u, SDL_LoadObject, SDL_UnloadObject, SDL_LoadFunction> g_loader; +} + +void loadMesh(AppGraphCtxType type) +{ + const char* moduleName = demoAppDLLName(type); + + g_loader.loadModule(moduleName); +} + +void unloadMesh() +{ + g_loader.unloadModule(); +} + +MeshContext* MeshContextCreate(const MeshContextDesc* desc) +{ + return g_loader.function<0>(MeshContextCreate, "MeshContextCreate", desc); +} + +void MeshContextUpdate(MeshContext* context, const MeshContextDesc* desc) +{ + return g_loader.function<1>(MeshContextUpdate, "MeshContextUpdate", context, desc); +} + +void MeshContextRelease(MeshContext* context) +{ + return g_loader.function<2>(MeshContextRelease, "MeshContextRelease", context); +} + +MeshIndexBuffer* MeshIndexBufferCreate(MeshContext* context, MeshUint* indices, MeshUint numIndices) +{ + return g_loader.function<3>(MeshIndexBufferCreate, "MeshIndexBufferCreate", context, indices, numIndices); +} + +void MeshIndexBufferRelease(MeshIndexBuffer* buffer) +{ + return g_loader.function<4>(MeshIndexBufferRelease, "MeshIndexBufferRelease", buffer); +} + +MeshVertexBuffer* MeshVertexBufferCreate(MeshContext* context, MeshVertex* vertices, MeshUint numVertices) +{ + return g_loader.function<5>(MeshVertexBufferCreate, "MeshVertexBufferCreate", context, vertices, numVertices); +} + +void MeshVertexBufferRelease(MeshVertexBuffer* buffer) +{ + return g_loader.function<6>(MeshVertexBufferRelease, "MeshVertexBufferRelease", buffer); +} + +void MeshContextDraw(MeshContext* context, const MeshContextDrawParams* params) +{ + return g_loader.function<7>(MeshContextDraw, "MeshContextDraw", context, params); +} + +MeshContext* MeshInteropContextCreate(AppGraphCtx* appctx) +{ + return g_loader.function<8>(MeshInteropContextCreate, "MeshInteropContextCreate", appctx); +} + +void MeshInteropContextUpdate(MeshContext* context, AppGraphCtx* appctx) +{ + return g_loader.function<9>(MeshInteropContextUpdate, "MeshInteropContextUpdate", context, appctx); +}
\ No newline at end of file diff --git a/demo/DemoApp/preset0.h b/demo/DemoApp/preset0.h new file mode 100644 index 0000000..aba3666 --- /dev/null +++ b/demo/DemoApp/preset0.h @@ -0,0 +1,63 @@ +const ImserNode g_root[] = { + imserNodeGroupBegin("Effect"), + imserNodeGroupBegin("Fluid Simulation"), + imserNodeGroupBegin("Damping"), + imserNodeValue1f("Velocity", 0.100000f), + imserNodeValue1f("Smoke", 0.250000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("Fade"), + imserNodeValue1f("Velocity", 0.100000f), + imserNodeValue1f("Smoke", 0.250000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("MacCormack Correction"), + imserNodeValue1f("Velocity", 0.500000f), + imserNodeValue1f("Smoke", 0.500000f), + imserNodeGroupEnd(), + imserNodeValue1f("Vorticity Strength", 9.000000f), + imserNodeGroupBegin("Combustion"), + imserNodeValue1f("Ignition Temp", 0.050000f), + imserNodeValue1f("Cooling Rate", 1.500000f), + imserNodeGroupEnd(), + imserNodeGroupEnd(), + imserNodeGroupBegin("Emitter"), + imserNodeValue1f("Emit Velocity", -8.000000f), + imserNodeValue1f("Emit Smoke", 0.500000f), + imserNodeValue1f("Emit Temp", 2.000000f), + imserNodeValue1f("Emit Fuel", 1.400000f), + imserNodeValue1f("Alloc Scale", 1.000000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("Rendering"), + imserNodeValue1f("Alpha Scale", 0.200000f), + imserNodeValue1f("Render Mode", 0.000000f), + imserNodeValueBool("Debug Render", false), + imserNodeValueBool("Edit ColorMap", false), + imserNodeGroupEnd(), + imserNodeGroupBegin("colormap"), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.490000f), + imserNodeValue1f(nullptr, 1.450000f), + imserNodeValue1f(nullptr, 1.260000f), + imserNodeValue1f(nullptr, 0.025294f), + imserNodeValue1f(nullptr, 0.384255f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.580000f), + imserNodeValue1f(nullptr, 0.490000f), + imserNodeValue1f(nullptr, 0.109803f), + imserNodeValue1f(nullptr, 0.620718f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.830000f), + imserNodeValue1f(nullptr, 0.540000f), + imserNodeValue1f(nullptr, 0.456667f), + imserNodeValue1f(nullptr, 0.850000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.240000f), + imserNodeValue1f(nullptr, 0.190000f), + imserNodeValue1f(nullptr, 0.350000f), + imserNodeValue1f(nullptr, 1.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.150000f), + imserNodeValue1f(nullptr, 0.130000f), + imserNodeValue1f(nullptr, 0.100000f), + imserNodeGroupEnd(), + imserNodeGroupEnd(), +};
\ No newline at end of file diff --git a/demo/DemoApp/preset1.h b/demo/DemoApp/preset1.h new file mode 100644 index 0000000..dded481 --- /dev/null +++ b/demo/DemoApp/preset1.h @@ -0,0 +1,63 @@ +const ImserNode g_root[] = { + imserNodeGroupBegin("Effect"), + imserNodeGroupBegin("Fluid Simulation"), + imserNodeGroupBegin("Damping"), + imserNodeValue1f("Velocity", 0.100000f), + imserNodeValue1f("Smoke", 0.250000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("Fade"), + imserNodeValue1f("Velocity", 0.100000f), + imserNodeValue1f("Smoke", 0.250000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("MacCormack Correction"), + imserNodeValue1f("Velocity", 0.500000f), + imserNodeValue1f("Smoke", 0.500000f), + imserNodeGroupEnd(), + imserNodeValue1f("Vorticity Strength", 9.000000f), + imserNodeGroupBegin("Combustion"), + imserNodeValue1f("Ignition Temp", 0.050000f), + imserNodeValue1f("Cooling Rate", 1.500000f), + imserNodeGroupEnd(), + imserNodeGroupEnd(), + imserNodeGroupBegin("Emitter"), + imserNodeValue1f("Emit Velocity", -8.000000f), + imserNodeValue1f("Emit Smoke", 0.500000f), + imserNodeValue1f("Emit Temp", 2.000000f), + imserNodeValue1f("Emit Fuel", 1.400000f), + imserNodeValue1f("Alloc Scale", 1.000000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("Rendering"), + imserNodeValue1f("Alpha Scale", 0.200000f), + imserNodeValue1f("Render Mode", 6.000000f), + imserNodeValueBool("Debug Render", false), + imserNodeValueBool("Edit ColorMap", false), + imserNodeGroupEnd(), + imserNodeGroupBegin("colormap"), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.490000f), + imserNodeValue1f(nullptr, 1.450000f), + imserNodeValue1f(nullptr, 1.260000f), + imserNodeValue1f(nullptr, 0.025294f), + imserNodeValue1f(nullptr, 0.384255f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.580000f), + imserNodeValue1f(nullptr, 0.490000f), + imserNodeValue1f(nullptr, 0.109803f), + imserNodeValue1f(nullptr, 0.620718f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.830000f), + imserNodeValue1f(nullptr, 0.540000f), + imserNodeValue1f(nullptr, 0.456667f), + imserNodeValue1f(nullptr, 0.850000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.240000f), + imserNodeValue1f(nullptr, 0.190000f), + imserNodeValue1f(nullptr, 0.350000f), + imserNodeValue1f(nullptr, 1.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.150000f), + imserNodeValue1f(nullptr, 0.130000f), + imserNodeValue1f(nullptr, 0.100000f), + imserNodeGroupEnd(), + imserNodeGroupEnd(), +};
\ No newline at end of file diff --git a/demo/DemoApp/presetFireBall.h b/demo/DemoApp/presetFireBall.h new file mode 100644 index 0000000..08b9588 --- /dev/null +++ b/demo/DemoApp/presetFireBall.h @@ -0,0 +1,85 @@ +const ImserNode g_root[] = { + imserNodeGroupBegin("Effect"), + imserNodeGroupBegin("colormap"), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.150000f), + imserNodeValue1f(nullptr, 0.160000f), + imserNodeValue1f(nullptr, 0.150000f), + imserNodeValue1f(nullptr, 0.004902f), + imserNodeValue1f(nullptr, 0.050000f), + imserNodeValue1f(nullptr, 0.220000f), + imserNodeValue1f(nullptr, 0.220000f), + imserNodeValue1f(nullptr, 0.220000f), + imserNodeValue1f(nullptr, 0.504902f), + imserNodeValue1f(nullptr, 0.600000f), + imserNodeValue1f(nullptr, 0.835294f), + imserNodeValue1f(nullptr, 0.392157f), + imserNodeValue1f(nullptr, 0.117647f), + imserNodeValue1f(nullptr, 0.800000f), + imserNodeValue1f(nullptr, 0.850000f), + imserNodeValue1f(nullptr, 1.270000f), + imserNodeValue1f(nullptr, 1.200000f), + imserNodeValue1f(nullptr, 0.390000f), + imserNodeValue1f(nullptr, 0.800000f), + imserNodeValue1f(nullptr, 1.000000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 0.700000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("colormapMat0"), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.050000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.270000f), + imserNodeValue1f(nullptr, 0.299019f), + imserNodeValue1f(nullptr, 0.173204f), + imserNodeValue1f(nullptr, 0.350000f), + imserNodeValue1f(nullptr, 0.140000f), + imserNodeValue1f(nullptr, 1.130000f), + imserNodeValue1f(nullptr, 0.662746f), + imserNodeValue1f(nullptr, 0.709116f), + imserNodeValue1f(nullptr, 0.070000f), + imserNodeValue1f(nullptr, 0.080000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 0.726471f), + imserNodeValue1f(nullptr, 1.000000f), + imserNodeValue1f(nullptr, 0.110000f), + imserNodeValue1f(nullptr, 1.080000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 0.700000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("colormapMat1"), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.050000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.500000f), + imserNodeValue1f(nullptr, 0.600000f), + imserNodeValue1f(nullptr, 0.835294f), + imserNodeValue1f(nullptr, 1.220000f), + imserNodeValue1f(nullptr, 1.360000f), + imserNodeValue1f(nullptr, 0.800000f), + imserNodeValue1f(nullptr, 0.850000f), + imserNodeValue1f(nullptr, 1.270000f), + imserNodeValue1f(nullptr, 1.200000f), + imserNodeValue1f(nullptr, 0.390000f), + imserNodeValue1f(nullptr, 0.800000f), + imserNodeValue1f(nullptr, 1.000000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 0.700000f), + imserNodeGroupEnd(), + imserNodeGroupEnd(), +};
\ No newline at end of file diff --git a/demo/DemoApp/presetFlame.h b/demo/DemoApp/presetFlame.h new file mode 100644 index 0000000..f0a9bea --- /dev/null +++ b/demo/DemoApp/presetFlame.h @@ -0,0 +1,85 @@ +const ImserNode g_root[] = { + imserNodeGroupBegin("Effect"), + imserNodeGroupBegin("colormap"), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.050000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.500000f), + imserNodeValue1f(nullptr, 0.600000f), + imserNodeValue1f(nullptr, 0.835294f), + imserNodeValue1f(nullptr, 0.392157f), + imserNodeValue1f(nullptr, 0.117647f), + imserNodeValue1f(nullptr, 0.800000f), + imserNodeValue1f(nullptr, 0.850000f), + imserNodeValue1f(nullptr, 1.270000f), + imserNodeValue1f(nullptr, 1.200000f), + imserNodeValue1f(nullptr, 0.390000f), + imserNodeValue1f(nullptr, 0.800000f), + imserNodeValue1f(nullptr, 1.000000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 0.700000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("colormapMat0"), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.050000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.270000f), + imserNodeValue1f(nullptr, 0.299019f), + imserNodeValue1f(nullptr, 0.173204f), + imserNodeValue1f(nullptr, 0.350000f), + imserNodeValue1f(nullptr, 0.140000f), + imserNodeValue1f(nullptr, 1.130000f), + imserNodeValue1f(nullptr, 0.662746f), + imserNodeValue1f(nullptr, 0.709116f), + imserNodeValue1f(nullptr, 0.070000f), + imserNodeValue1f(nullptr, 0.080000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 0.726471f), + imserNodeValue1f(nullptr, 1.000000f), + imserNodeValue1f(nullptr, 0.110000f), + imserNodeValue1f(nullptr, 1.080000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 0.700000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("colormapMat1"), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.050000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.500000f), + imserNodeValue1f(nullptr, 0.600000f), + imserNodeValue1f(nullptr, 0.835294f), + imserNodeValue1f(nullptr, 1.220000f), + imserNodeValue1f(nullptr, 1.360000f), + imserNodeValue1f(nullptr, 0.800000f), + imserNodeValue1f(nullptr, 0.850000f), + imserNodeValue1f(nullptr, 1.270000f), + imserNodeValue1f(nullptr, 1.200000f), + imserNodeValue1f(nullptr, 0.390000f), + imserNodeValue1f(nullptr, 0.800000f), + imserNodeValue1f(nullptr, 1.000000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 1.500000f), + imserNodeValue1f(nullptr, 0.700000f), + imserNodeGroupEnd(), + imserNodeGroupEnd(), +};
\ No newline at end of file diff --git a/demo/DemoApp/presetSmoke.h b/demo/DemoApp/presetSmoke.h new file mode 100644 index 0000000..6229870 --- /dev/null +++ b/demo/DemoApp/presetSmoke.h @@ -0,0 +1,46 @@ +const ImserNode g_root[] = { + imserNodeGroupBegin("Effect"), + imserNodeGroupBegin("Emitter"), + imserNodeValue1f("Emit Smoke", 9.800000f), + imserNodeValue1f("Emit Temp", 8.900001f), + imserNodeValue1f("Emit Fuel", 1.800000f), + imserNodeValue1f("Max Emit Dist", 0.400000f), + imserNodeValue1f("Min Emit Dist", 0.140000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("Rendering"), + imserNodeValue1f("Alpha Scale", 0.20000f), + imserNodeGroupEnd(), + imserNodeGroupBegin("colormap"), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.025000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.000000f), + imserNodeValue1f(nullptr, 0.250277f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.362745f), + imserNodeValue1f(nullptr, 0.600000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.800000f), + imserNodeValue1f(nullptr, 0.850000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.800000f), + imserNodeValue1f(nullptr, 1.000000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.990000f), + imserNodeValue1f(nullptr, 0.700000f), + imserNodeGroupEnd(), + imserNodeGroupEnd(), +};
\ No newline at end of file diff --git a/demo/DemoApp/scene.cpp b/demo/DemoApp/scene.cpp new file mode 100644 index 0000000..3ad7cce --- /dev/null +++ b/demo/DemoApp/scene.cpp @@ -0,0 +1,1036 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include "scene.h" + +#include <stdio.h> + +#include "loader.h" +#include "imgui.h" +#include "imguiser.h" + +#include "scene.h" + +#include <SDL.h> + +/// Scene registry here + +namespace Scenes +{ + SceneSimpleFlame sceneSimpleFlame; + SceneSimpleFlameThrower sceneSimpleFlameThrower; + SceneSimpleFlameAnimated sceneSimpleFlameAnimated; + Scene2DTextureEmitter scene2DTextureEmitter1(false); + Scene2DTextureEmitter scene2DTextureEmitter2(true); + SceneSimpleFlameMesh sceneSimpleFlameMesh; + SceneSimpleFlameCollision sceneSimpleFlameCollision; + //SceneSimpleFlameCulling sceneSimpleFlameCulling; + SceneSimpleFlameConvex sceneSimpleFlameConvex; + SceneSimpleFlameCapsule sceneSimpleFlameCapsule; + SceneSDFTest sceneSDFTest; + SceneCustomLighting sceneCustomLighting; + SceneSimpleSmoke sceneSimpleSmoke; + SceneDynamicCoupleRate sceneDynamicCoupleRate; + SceneCustomEmit sceneCustomEmit; + SceneSimpleFlameDouble sceneSimpleFlame2; + SceneSimpleFlameFuelMap sceneSimpleFlameFuelMap; + SceneSimpleFlameParticleSurface sceneParticleSurface; + SceneSimpleFlameBall sceneSimpleFlameBall; + + const int count = 18; + Scene* list[count] = { + &scene2DTextureEmitter1, + &scene2DTextureEmitter2, + &sceneSimpleFlame, + &sceneSimpleFlameThrower, + &sceneSimpleFlameAnimated, + &sceneSimpleFlameMesh, + &sceneSDFTest, + &sceneSimpleFlameCollision, + //&sceneSimpleFlameCulling, + &sceneSimpleFlameConvex, + &sceneSimpleFlameCapsule, + &sceneSimpleSmoke, + &sceneCustomLighting, + &sceneDynamicCoupleRate, + &sceneCustomEmit, + &sceneSimpleFlame2, + &sceneSimpleFlameFuelMap, + &sceneParticleSurface, + &sceneSimpleFlameBall + }; +}; + +Scene* getScene(int index) +{ + if (index < Scenes::count) + { + return Scenes::list[index]; + } + return nullptr; +} + +void pointsToImage(NvFlowFloat4* image, int imageDim, const CurvePoint* pts, int numPts) +{ + using namespace DirectX; + for (int i = 0; i < imageDim; i++) + { + float u = (float(i) + 0.5f) / float(imageDim); + + // find the closest higher and lower control points + int xloweri = -1; + float xlowerVal = 0.f; + int xhigheri = -1; + float xhigherVal = 1.f; + for (int pt = 0; pt < numPts; pt++) + { + if (pts[pt].x <= u && pts[pt].x >= xlowerVal) + { + xloweri = pt; + xlowerVal = pts[pt].x; + } + if (pts[pt].x >= u && pts[pt].x <= xhigherVal) + { + xhigheri = pt; + xhigherVal = pts[pt].x; + } + } + + // get values for interpolation + XMVECTOR a = (xloweri >= 0) ? XMLoadFloat4((XMFLOAT4*)&pts[xloweri].r) : XMVectorSet(0.f, 0.f, 0.f, 0.f); + XMVECTOR b = (xhigheri >= 0) ? XMLoadFloat4((XMFLOAT4*)&pts[xhigheri].r) : XMVectorSet(1.f, 1.f, 1.f, 1.f); + float t = (u - xlowerVal) / (xhigherVal - xlowerVal); + XMVECTOR c = XMVectorLerp(a, b, t); + + XMStoreFloat4((XMFLOAT4*)&image[i], c); + } +} + +void Scene::update(float dt) +{ + int numSteps = m_timeStepper.getNumSteps(dt); + + for (int i = 0; i < numSteps; i++) + { + doUpdate(m_timeStepper.m_fixedDt); + } +} + +void Scene::resize(int winw, int winh) +{ + m_winw = winw; + m_winh = winh; +} + +bool Scene::imguiMouse(int mx, int my, unsigned char mbut) +{ + m_mx = mx; + m_my = my; + m_mbut = mbut; + return false; +} + +// ************************* SceneFluid ***************************************** + +void SceneFluid::imguiDesc() +{ + { + bool enableVTR = (m_flowGridActor.m_gridDesc.enableVTR != false); + if (imguiCheck("Enable VTR", enableVTR, true)) + { + if (enableVTR == false) + { + NvFlowSupport support; + if (NvFlowGridQuerySupport(m_flowGridActor.m_grid, m_flowContext.m_gridContext, &support) == eNvFlowSuccess) + { + m_flowGridActor.m_gridDesc.enableVTR = support.supportsVTR; + } + } + else + { + m_flowGridActor.m_gridDesc.enableVTR = false; + } + m_shouldReset = true; + } + bool lowResDensity = m_flowGridActor.m_gridDesc.densityMultiRes == eNvFlowMultiRes1x1x1; + if (imguiCheck("Low Res Density", lowResDensity, true)) + { + if (m_flowGridActor.m_gridDesc.densityMultiRes == eNvFlowMultiRes1x1x1) + { + m_flowGridActor.m_gridDesc.densityMultiRes = eNvFlowMultiRes2x2x2; + } + else + { + m_flowGridActor.m_gridDesc.densityMultiRes = eNvFlowMultiRes1x1x1; + } + m_shouldReset = true; + } + if (imguiCheck("Low Latency Mapping", m_flowGridActor.m_gridDesc.lowLatencyMapping, true)) + { + m_flowGridActor.m_gridDesc.lowLatencyMapping = !m_flowGridActor.m_gridDesc.lowLatencyMapping; + m_shouldReset = true; + } + } + { + if (!m_flowContext.m_multiGPUSupported) + { + m_flowContext.m_enableMultiGPU = false; + } + if (imguiCheck("Enable MultiGPU", m_flowContext.m_enableMultiGPU, true)) + { + m_flowContext.m_enableMultiGPU = !m_flowContext.m_enableMultiGPU; + if (!m_flowContext.m_multiGPUSupported) + { + m_flowContext.m_enableMultiGPU = false; + } + else + { + m_shouldReset = true; + } + } + } + { + if (!m_flowContext.m_commandQueueSupported) + { + m_flowContext.m_enableCommandQueue = false; + } + if (imguiCheck("Enable MultiQueue", m_flowContext.m_enableCommandQueue, true)) + { + m_flowContext.m_enableCommandQueue = !m_flowContext.m_enableCommandQueue; + if (!m_flowContext.m_commandQueueSupported) + { + m_flowContext.m_enableCommandQueue = false; + } + else + { + m_shouldReset = true; + } + } + } + + float oldMemoryLimit = m_flowGridActor.m_memoryLimit; + imguiserSlider("Memory Limit", &m_flowGridActor.m_memoryLimit, 1.f, 6.f, 1.f, true); + if (oldMemoryLimit != m_flowGridActor.m_memoryLimit) + { + m_flowGridActor.m_gridDesc.residentScale = m_flowGridActor.m_memoryLimit * m_flowGridActor.m_memoryScale; + m_shouldReset = true; + } + + if (imguiButton("Reset", true)) + { + m_shouldReset = true; + } + + if (imguiButton("Grid Reset", true)) + { + m_shouldGridReset = true; + } + + float cellSizeLogf = float(m_flowGridActor.m_cellSizeLogScale); + if (imguiserSlider("Cell Size Log Scale", &cellSizeLogf, -6.f, 6.f, 1.f, true)) + { + m_flowGridActor.m_cellSizeLogScale = int(cellSizeLogf); + m_shouldGridReset = true; + } + if (imguiserSlider("Cell Size Scale", &m_flowGridActor.m_cellSizeScale, 0.8f, 1.25f, 0.001f, true)) + { + m_shouldGridReset = true; + } + + imguiDescExtra(); +} + +void SceneFluid::imguiFluidSim() +{ + imguiSeparatorLine(); + imguiLabel("Fluid Simulation"); + imguiserBeginGroup("Fluid Simulation", nullptr); + + imguiSeparator(); + imguiLabel("Damping"); + imguiserBeginGroup("Damping", nullptr); + imguiserSlider("Velocity", &m_flowGridActor.m_materialParams.velocity.damping, 0.f, 1.f, 0.01f, true); + imguiserSlider("Smoke", &m_flowGridActor.m_materialParams.smoke.damping, 0.f, 1.f, 0.01f, true); + imguiserSlider("Temp", &m_flowGridActor.m_materialParams.temperature.damping, 0.f, 1.f, 0.01f, true); + imguiserSlider("Fuel", &m_flowGridActor.m_materialParams.fuel.damping, 0.f, 1.f, 0.01f, true); + imguiserEndGroup(); + + imguiSeparator(); + imguiLabel("Fade"); + imguiserBeginGroup("Fade", nullptr); + imguiserSlider("Velocity", &m_flowGridActor.m_materialParams.velocity.fade, 0.f, 1.f, 0.01f, true); + imguiserSlider("Smoke", &m_flowGridActor.m_materialParams.smoke.fade, 0.f, 1.f, 0.01f, true); + imguiserSlider("Temp", &m_flowGridActor.m_materialParams.temperature.fade, 0.f, 1.f, 0.01f, true); + imguiserSlider("Fuel", &m_flowGridActor.m_materialParams.fuel.fade, 0.f, 1.f, 0.01f, true); + imguiserEndGroup(); + + imguiSeparator(); + imguiLabel("MacCormack Correction"); + imguiserBeginGroup("MacCormack Correction", nullptr); + imguiserSlider("Velocity", &m_flowGridActor.m_materialParams.velocity.macCormackBlendFactor, 0.f, 1.f, 0.01f, true); + imguiserSlider("Smoke", &m_flowGridActor.m_materialParams.smoke.macCormackBlendFactor, 0.f, 1.f, 0.01f, true); + imguiserSlider("Temp", &m_flowGridActor.m_materialParams.temperature.macCormackBlendFactor, 0.f, 1.f, 0.01f, true); + imguiserSlider("Fuel", &m_flowGridActor.m_materialParams.fuel.macCormackBlendFactor, 0.f, 1.f, 0.01f, true); + imguiserEndGroup(); + imguiLabel("MacCormack Threshold"); + imguiserBeginGroup("MacCormack Threshold", nullptr); + imguiserSlider("Velocity", &m_flowGridActor.m_materialParams.velocity.macCormackBlendThreshold, 0.f, 0.01f, 0.001f, true); + imguiserSlider("Smoke", &m_flowGridActor.m_materialParams.smoke.macCormackBlendThreshold, 0.f, 0.01f, 0.001f, true); + imguiserSlider("Temp", &m_flowGridActor.m_materialParams.temperature.macCormackBlendThreshold, 0.f, 0.01f, 0.001f, true); + imguiserSlider("Fuel", &m_flowGridActor.m_materialParams.fuel.macCormackBlendThreshold, 0.f, 0.01f, 0.001f, true); + imguiserEndGroup(); + + imguiserSlider("Vorticity Strength", &m_flowGridActor.m_materialParams.vorticityStrength, 0.f, 20.f, 0.1f, true); + imguiserSlider("Vorticity Vel Mask", &m_flowGridActor.m_materialParams.vorticityVelocityMask, 0.f, 1.f, 0.01f, true); + + if (imguiCheck("Legacy Pressure", m_flowGridActor.m_gridParams.pressureLegacyMode, true)) + { + m_flowGridActor.m_gridParams.pressureLegacyMode = !m_flowGridActor.m_gridParams.pressureLegacyMode; + } + + imguiSeparator(); + imguiLabel("Combustion"); + imguiserBeginGroup("Combustion", nullptr); + imguiserSlider("Ignition Temp", &m_flowGridActor.m_materialParams.ignitionTemp, 0.f, 0.5f, 0.05f, true); + imguiserSlider("Cooling Rate", &m_flowGridActor.m_materialParams.coolingRate, 0.f, 10.f, 0.1f, true); + imguiserSlider("Buoyancy", &m_flowGridActor.m_materialParams.buoyancyPerTemp, 0.f, 10.f, 0.1f, true); + imguiserSlider("Expansion", &m_flowGridActor.m_materialParams.divergencePerBurn, 0.f, 10.f, 0.1f, true); + imguiserSlider("Smoke Per Burn", &m_flowGridActor.m_materialParams.smokePerBurn, 0.f, 10.f, 0.1f, true); + imguiserSlider("Temp Per Burn", &m_flowGridActor.m_materialParams.tempPerBurn, 0.f, 10.f, 0.1f, true); + imguiserSlider("Fuel Per Burn", &m_flowGridActor.m_materialParams.fuelPerBurn, 0.f, 10.f, 0.1f, true); + imguiserSlider("Burn Per Temp", &m_flowGridActor.m_materialParams.burnPerTemp, 0.f, 10.f, 0.1f, true); + imguiserEndGroup(); + + imguiFluidSimExtra(); + + imguiserEndGroup(); +} + +void SceneFluid::imguiFluidRender() +{ + imguiSeparatorLine(); + imguiLabel("Rendering"); + imguiserBeginGroup("Rendering", nullptr); + imguiserSlider("Alpha Scale", &m_flowGridActor.m_renderMaterialDefaultParams.alphaScale, 0.f, 1.f, 0.01f, true); + imguiserSlider("Additive", &m_flowGridActor.m_renderMaterialDefaultParams.additiveFactor, 0.f, 1.f, 0.01f, true); + float renderModef = (float)m_flowGridActor.m_renderParams.renderMode; + if (imguiserSlider("Render Mode", &renderModef, 0.f, float(eNvFlowVolumeRenderModeCount) - 1.f, 1.f, true)) + { + m_flowGridActor.m_renderParams.renderMode = (NvFlowVolumeRenderMode)((NvFlowUint)renderModef); + } + float renderChannelf = (float)m_flowGridActor.m_renderParams.renderChannel; + if (imguiserSlider("Render Channel", &renderChannelf, 0.f, float(eNvFlowGridTextureChannelCount) - 1.f, 1.f, true)) + { + m_flowGridActor.m_renderParams.renderChannel = (NvFlowGridTextureChannel)((NvFlowUint)renderChannelf); + } + if (imguiserCheck("Separate Lighting", m_flowGridActor.m_separateLighting, true)) + { + m_flowGridActor.m_separateLighting = !m_flowGridActor.m_separateLighting; + } + if (imguiserCheck("Debug Render", m_flowGridActor.m_renderParams.debugMode, true)) + { + m_flowGridActor.m_renderParams.debugMode = !m_flowGridActor.m_renderParams.debugMode; + } + if (m_flowGridActor.m_renderParams.debugMode) + { + imguiIndent(); + if (imguiserCheck("Blocks", (m_flowGridActor.m_gridParams.debugVisFlags & eNvFlowGridDebugVisBlocks) != 0, true)) + { + m_flowGridActor.m_gridParams.debugVisFlags = NvFlowGridDebugVisFlags(m_flowGridActor.m_gridParams.debugVisFlags ^ eNvFlowGridDebugVisBlocks); + } + if (imguiserCheck("Emit Bounds", (m_flowGridActor.m_gridParams.debugVisFlags & eNvFlowGridDebugVisEmitBounds) != 0, true)) + { + m_flowGridActor.m_gridParams.debugVisFlags = NvFlowGridDebugVisFlags(m_flowGridActor.m_gridParams.debugVisFlags ^ eNvFlowGridDebugVisEmitBounds); + } + if (imguiserCheck("Shapes Simple", (m_flowGridActor.m_gridParams.debugVisFlags & eNvFlowGridDebugVisShapesSimple) != 0, true)) + { + m_flowGridActor.m_gridParams.debugVisFlags = NvFlowGridDebugVisFlags(m_flowGridActor.m_gridParams.debugVisFlags ^ eNvFlowGridDebugVisShapesSimple); + } + imguiUnindent(); + } + if (imguiserCheck("Edit ColorMap Default", m_flowGridActor.m_colorMap.m_curveEditorActiveDefault, true)) + { + m_flowGridActor.m_colorMap.m_curveEditorActiveDefault = !m_flowGridActor.m_colorMap.m_curveEditorActiveDefault; + } + if (imguiserCheck("Edit ColorMap Mat0", m_flowGridActor.m_colorMap.m_curveEditorActiveMat0, true)) + { + m_flowGridActor.m_colorMap.m_curveEditorActiveMat0 = !m_flowGridActor.m_colorMap.m_curveEditorActiveMat0; + } + if (imguiserCheck("Edit ColorMap Mat1", m_flowGridActor.m_colorMap.m_curveEditorActiveMat1, true)) + { + m_flowGridActor.m_colorMap.m_curveEditorActiveMat1 = !m_flowGridActor.m_colorMap.m_curveEditorActiveMat1; + } + if (imguiserCheck("Multires", m_flowGridActor.m_renderParams.multiRes.enabled, true)) + { + m_flowGridActor.m_renderParams.multiRes.enabled = !m_flowGridActor.m_renderParams.multiRes.enabled; + } + if (imguiserCheck("Lens Matched", m_flowGridActor.m_renderParams.lensMatchedShading.enabled, true)) + { + m_flowGridActor.m_renderParams.lensMatchedShading.enabled = !m_flowGridActor.m_renderParams.lensMatchedShading.enabled; + } + if (m_flowGridActor.m_renderParams.multiRes.enabled) + { + m_flowGridActor.m_renderParams.multiRes.viewport.width = (float)m_winw; + m_flowGridActor.m_renderParams.multiRes.viewport.height = (float)m_winh; + m_flowGridActor.m_renderParams.multiRes.nonMultiResWidth = (float)m_winw; + m_flowGridActor.m_renderParams.multiRes.nonMultiResHeight = (float)m_winh; + } + if (m_flowGridActor.m_renderParams.lensMatchedShading.enabled) + { + m_flowGridActor.m_renderParams.lensMatchedShading.viewport.width = (float)m_winw; + m_flowGridActor.m_renderParams.lensMatchedShading.viewport.height = (float)m_winh; + m_flowGridActor.m_renderParams.lensMatchedShading.nonLMSWidth = (float)m_winw; + m_flowGridActor.m_renderParams.lensMatchedShading.nonLMSHeight = (float)m_winh; + } + imguiserSlider("Screen Percentage", &m_flowGridActor.m_renderParams.screenPercentage, 0.1f, 1.f, 0.01f, true); + float smoothVal = float(m_flowGridActor.m_renderParams.smoothColorUpsample); + if (imguiserSlider("Upsample Smooth", &smoothVal, 0.f, 1.f, 1.f, true)) + { + m_flowGridActor.m_renderParams.smoothColorUpsample = smoothVal > 0.5f; + } + if (imguiserCheck("Generate Depth", m_flowGridActor.m_renderParams.generateDepth, true)) + { + m_flowGridActor.m_renderParams.generateDepth = !m_flowGridActor.m_renderParams.generateDepth; + } + if (imguiserCheck("Generate Depth Vis", m_flowGridActor.m_renderParams.generateDepthDebugMode, true)) + { + m_flowGridActor.m_renderParams.generateDepthDebugMode = !m_flowGridActor.m_renderParams.generateDepthDebugMode; + } + + imguiLabel("MultiRes Ray March"); + float multiResRayMarchf = (float)m_flowGridActor.m_renderParams.multiResRayMarch; + if (imguiserSlider("MultiRes levels", &multiResRayMarchf, 0.f, 4.f, 1.f, true)) + { + m_flowGridActor.m_renderParams.multiResRayMarch = (NvFlowMultiResRayMarch)NvFlowUint(multiResRayMarchf); + } + imguiserSlider("Sampling Rate", &m_flowGridActor.m_renderParams.multiResSamplingScale, 0.1f, 10.f, 0.1f, true); + + imguiLabel("Volume Shadow"); + if (imguiserCheck("Enabled", m_flowGridActor.m_enableVolumeShadow, true)) + { + m_flowGridActor.m_enableVolumeShadow = !m_flowGridActor.m_enableVolumeShadow; + m_shouldReset = true; + } + if (m_flowGridActor.m_enableVolumeShadow) + { + if (imguiserCheck("Force Apply", m_flowGridActor.m_forceApplyShadow, true)) + { + m_flowGridActor.m_forceApplyShadow = !m_flowGridActor.m_forceApplyShadow; + } + imguiserSlider("Light Pan", &m_flowGridActor.m_shadowPan, -4.f, 4.f, 0.01f, true); + imguiserSlider("Light Tilt", &m_flowGridActor.m_shadowTilt, -4.f, 4.f, 0.01f, true); + if (imguiserSlider("Memory Scale", &m_flowGridActor.m_shadowResidentScale, 0.5f, 2.f, 0.1f, true)) + { + m_shouldReset = true; + } + imguiserSlider("Intensity Scale", &m_flowGridActor.m_shadowIntensityScale, 0.f, 5.f, 0.01f, true); + imguiserSlider("Min Intensity", &m_flowGridActor.m_shadowMinIntensity, 0.0f, 1.f, 0.01f, true); + imguiserSlider("BlendTempFactor", &m_flowGridActor.m_shadowBlendCompMask.x, -5.f, 5.f, 0.1f, true); + imguiserSlider("BlendBias", &m_flowGridActor.m_shadowBlendBias, -5.0f, 5.f, 0.1f, true); + if (imguiserCheck("Debug Vis", m_flowGridActor.m_shadowDebugVis, true)) + { + m_flowGridActor.m_shadowDebugVis = !m_flowGridActor.m_shadowDebugVis; + } + } + + imguiLabel("Cross Section"); + if (imguiserCheck("Enabled", m_flowGridActor.m_enableCrossSection, true)) + { + m_flowGridActor.m_enableCrossSection = !m_flowGridActor.m_enableCrossSection; + } + if (m_flowGridActor.m_enableCrossSection) + { + if (imguiserCheck("Fullscreen", m_flowGridActor.m_crossSectionParams.fullscreen, true)) + { + m_flowGridActor.m_crossSectionParams.fullscreen = !m_flowGridActor.m_crossSectionParams.fullscreen; + } + if (imguiserCheck("Point Filter", m_flowGridActor.m_crossSectionParams.pointFilter, true)) + { + m_flowGridActor.m_crossSectionParams.pointFilter = !m_flowGridActor.m_crossSectionParams.pointFilter; + } + if (imguiserCheck("Velocity Vectors", m_flowGridActor.m_crossSectionParams.velocityVectors, true)) + { + m_flowGridActor.m_crossSectionParams.velocityVectors = !m_flowGridActor.m_crossSectionParams.velocityVectors; + } + if (imguiserCheck("Outline Cells", m_flowGridActor.m_crossSectionParams.outlineCells, true)) + { + m_flowGridActor.m_crossSectionParams.outlineCells = !m_flowGridActor.m_crossSectionParams.outlineCells; + } + + float axis = float(m_flowGridActor.m_crossSectionParams.crossSectionAxis); + if (imguiserSlider("Axis", &axis, 0.f, 2.f, 1.f, true)) + { + m_flowGridActor.m_crossSectionParams.crossSectionAxis = NvFlowUint(axis); + } + imguiserSlider("PosX", &m_flowGridActor.m_crossSectionParams.crossSectionPosition.x, -1.f, 1.f, 0.01f, true); + imguiserSlider("PosY", &m_flowGridActor.m_crossSectionParams.crossSectionPosition.y, -1.f, 1.f, 0.01f, true); + imguiserSlider("PosZ", &m_flowGridActor.m_crossSectionParams.crossSectionPosition.z, -1.f, 1.f, 0.01f, true); + imguiserSlider("Scale", &m_flowGridActor.m_crossSectionScale, 0.25f, 20.f, 0.1f, true); + + float renderModef = (float)m_flowGridActor.m_crossSectionParams.renderMode; + if (imguiserSlider("Cross Render Mode", &renderModef, 0.f, float(eNvFlowVolumeRenderModeCount) - 1.f, 1.f, true)) + { + m_flowGridActor.m_crossSectionParams.renderMode = (NvFlowVolumeRenderMode)((NvFlowUint)renderModef); + } + float renderChannelf = (float)m_flowGridActor.m_crossSectionParams.renderChannel; + if (imguiserSlider("Cross Render Channel", &renderChannelf, 0.f, float(eNvFlowGridTextureChannelCount) - 1.f, 1.f, true)) + { + m_flowGridActor.m_crossSectionParams.renderChannel = (NvFlowGridTextureChannel)((NvFlowUint)renderChannelf); + } + imguiserSlider("Intensity", &m_flowGridActor.m_crossSectionParams.intensityScale, 0.01f, 10.f, 0.01f, true); + imguiserSlider("Background Color", &m_flowGridActor.m_crossSectionBackgroundColor, 0.f, 1.f, 1.f, true); + imguiserSlider("Line Color R", &m_flowGridActor.m_crossSectionLineColor.x, 0.f, 1.f, 0.01f, true); + imguiserSlider("Line Color G", &m_flowGridActor.m_crossSectionLineColor.y, 0.f, 1.f, 0.01f, true); + imguiserSlider("Line Color B", &m_flowGridActor.m_crossSectionLineColor.z, 0.f, 1.f, 0.01f, true); + imguiserSlider("Cell Color R", &m_flowGridActor.m_crossSectionParams.cellColor.x, 0.f, 1.f, 0.01f, true); + imguiserSlider("Cell Color G", &m_flowGridActor.m_crossSectionParams.cellColor.y, 0.f, 1.f, 0.01f, true); + imguiserSlider("Cell Color B", &m_flowGridActor.m_crossSectionParams.cellColor.z, 0.f, 1.f, 0.01f, true); + + imguiserSlider("Velocity Scale", &m_flowGridActor.m_crossSectionParams.velocityScale, 0.1f, 10.f, 0.01f, true); + imguiserSlider("Vector Length", &m_flowGridActor.m_crossSectionParams.vectorLengthScale, 0.1f, 2.f, 0.01f, true); + } + + imguiFluidRenderExtra(); + imguiserEndGroup(); +} + +void SceneFluid::imguiFluidEmitter() +{ + imguiSeparatorLine(); + imguiLabel("Emitter"); + imguiserBeginGroup("Emitter", nullptr); + imguiserSlider("Emit Velocity", &m_emitParams.velocityLinear.y, -16.f, 16.f, 0.1f, true); + imguiserSlider("Emit Smoke", &m_emitParams.smoke, 0.f, 10.f, 0.1f, true); + imguiserSlider("Emit Temp", &m_emitParams.temperature, 0.f, 10.f, 0.1f, true); + imguiserSlider("Emit Fuel", &m_emitParams.fuel, 0.f, 10.f, 0.1f, true); + imguiserSlider("Max Emit Dist", &m_emitParams.maxActiveDist, -1.f, 1.f, 0.01f, true); + imguiserSlider("Min Emit Dist", &m_emitParams.minActiveDist, -1.f, 1.f, 0.01f, true); + imguiserSlider("Max Edge Dist", &m_emitParams.maxEdgeDist, 0.f, 1.f, 0.01f, true); + imguiserSlider("Min Edge Dist", &m_emitParams.minEdgeDist, 0.f, 1.f, 0.01f, true); + imguiserSlider("Fuel Release Temp", &m_emitParams.fuelReleaseTemp, 0.f, 1.f, 0.01f, true); + imguiserSlider("Fuel Release", &m_emitParams.fuelRelease, 0.f, 10.f, 0.1f, true); + //imguiserSlider("Slip Thickness", &m_emitParams.slipThickness, 0.f, 1.f, 0.01f, true); + //imguiserSlider("Slip Factor", &m_emitParams.slipFactor, 0.f, 1.f, 0.01f, true); + float allocScale = m_emitParams.allocationScale.x; + if (imguiserSlider("Alloc Scale", &allocScale, 0.f, 2.f, 0.01f, true)) + { + m_emitParams.allocationScale = { allocScale, allocScale, allocScale }; + } + imguiserSlider("Alloc Predict", &m_emitParams.allocationPredict, 0.f, 1.f, 0.01f, true); + imguiFluidEmitterExtra(); + imguiserEndGroup(); +} + +void SceneFluid::imguiFluidAlloc() +{ + imguiSeparatorLine(); + imguiLabel("Fluid Allocation"); + imguiserBeginGroup("Fluid Allocation", nullptr); + + if (imguiserCheck("Big Effect Mode", m_flowGridActor.m_gridParams.bigEffectMode, true)) + { + m_flowGridActor.m_gridParams.bigEffectMode = !m_flowGridActor.m_gridParams.bigEffectMode; + } + imguiserSlider("Predict Time", &m_flowGridActor.m_gridParams.bigEffectPredictTime, 0.f, 1.f, 0.01f, true); + + imguiserSlider("Velocity Weight", &m_flowGridActor.m_materialParams.velocity.allocWeight, 0.f, 1.f, 0.01f, true); + imguiserSlider("Smoke Weight", &m_flowGridActor.m_materialParams.smoke.allocWeight, 0.f, 1.f, 0.01f, true); + imguiserSlider("Temp Weight", &m_flowGridActor.m_materialParams.temperature.allocWeight, 0.f, 1.f, 0.01f, true); + imguiserSlider("Fuel Weight", &m_flowGridActor.m_materialParams.fuel.allocWeight, 0.f, 1.f, 0.01f, true); + imguiserSlider("Velocity Threshold", &m_flowGridActor.m_materialParams.velocity.allocThreshold, 0.f, 1.f, 0.01f, true); + imguiserSlider("Smoke Threshold", &m_flowGridActor.m_materialParams.smoke.allocThreshold, 0.f, 1.f, 0.01f, true); + imguiserSlider("Temp Threshold", &m_flowGridActor.m_materialParams.temperature.allocThreshold, 0.f, 1.f, 0.01f, true); + imguiserSlider("Fuel Threshold", &m_flowGridActor.m_materialParams.fuel.allocThreshold, 0.f, 1.f, 0.01f, true); + + imguiFluidAllocExtra(); + imguiserEndGroup(); +} + +void SceneFluid::imguiFluidTime() +{ + imguiSeparatorLine(); + imguiLabel("Simulation Update Time"); + { + NvFlowQueryTime timeGPU, timeCPU; + if (NvFlowGridQueryTime(m_flowGridActor.m_grid, &timeGPU, &timeCPU) == eNvFlowSuccess) + { + char buf[80]; + snprintf(buf, sizeof(buf), "GPU: %.3f ms", 1000.f * timeGPU.simulation); + imguiValue(buf); + snprintf(buf, sizeof(buf), "CPU: %.3f ms", 1000.f * timeCPU.simulation); + imguiValue(buf); + } + } + imguiFluidTimeExtra(); +} + +void SceneFluid::imguiLoadSave() +{ + imguiSeparatorLine(); + + static float saveSlot = 0.f; + imguiSlider("Save Slot", &saveSlot, 0.f, 7.f, 1.f, true); + + char buf[256u]; + snprintf(buf, 256u, "../../data/save%d.h", int(saveSlot)); + + if (imguiButton("Save")) + { + imguiserSave(buf); + } + + if (imguiButton("Load")) + { + imguiserLoad(buf); + } +} + +void SceneFluid::imgui(int xIn, int yIn, int wIn, int hIn) +{ + static int scroll = 0u; + + int border = xIn; + int x = xIn; + int y = border; + int w = wIn; + int h = m_winh - (hIn + border) - 2 * border; + m_editorWidth = x + w; + + imguiBeginScrollArea("Options", + x, y, + w, h, + &scroll); + + imguiserBeginGroup("Effect", nullptr); + + imguiDesc(); + + imguiSeparatorLine(); + + m_projectile.imgui(); + + imguiFluidSim(); + + imguiFluidEmitter(); + + imguiFluidRender(); + + imguiFluidAlloc(); + + imguiLoadSave(); + + imguiFluidTime(); + + imguiEndScrollArea(); + + m_flowGridActor.m_colorMap.imguiUpdate(this, m_flowContext.m_renderContext, border, x, y, w, h); + + imguiserEndGroup(); +} + +bool SceneFluid::imguiMouse(int mx, int my, unsigned char mbut) +{ + Scene::imguiMouse(mx, my, mbut); + + if (mx < m_editorWidth) return true; + + if (m_flowGridActor.m_colorMap.colorMapActive(mx, my, mbut)) return true; + + return false; +} + +void SceneFluid::reset() +{ + release(); + SDL_Delay(30); + init(m_appctx, m_winw, m_winh); + m_shouldReset = false; +} + +NvFlowUint64 SceneFluid::getGridGPUMemUsage() +{ + NvFlowUint64 totalBytes = 0u; + + if (m_flowGridActor.m_grid) + { + NvFlowGridGPUMemUsage(m_flowGridActor.m_grid, &totalBytes); + } + + return totalBytes; +} + +bool SceneFluid::getStats(int lineIdx, int statIdx, char* buf) +{ + switch (statIdx) + { + case 0: + { + NvFlowUint64 totalBytes = getGridGPUMemUsage(); + snprintf(buf, 79, "GridGPUMem: %llu bytes", totalBytes); + return true; + } + case 1: + { + NvFlowUint numLayers = m_flowGridActor.m_statNumLayers; + snprintf(buf, 79, "NumLayers: %d layers", numLayers); + return true; + } + case 2: + { + NvFlowUint numBlocks = m_flowGridActor.m_statNumDensityBlocks; + NvFlowUint maxBlocks = m_flowGridActor.m_statMaxDensityBlocks; + snprintf(buf, 79, "Density: %d blocks active of %d", numBlocks, maxBlocks); + return true; + } + case 3: + { + NvFlowUint numBlocks = m_flowGridActor.m_statNumVelocityBlocks; + NvFlowUint maxBlocks = m_flowGridActor.m_statMaxVelocityBlocks; + snprintf(buf, 79, "Velocity: %d blocks active of %d", numBlocks, maxBlocks); + return true; + } + case 4: + { + NvFlowUint numCells = m_flowGridActor.m_statNumDensityCells; + snprintf(buf, 79, "Density: %d cells active", numCells); + return true; + } + case 5: + { + NvFlowUint numCells = m_flowGridActor.m_statNumVelocityCells; + snprintf(buf, 79, "Velocity: %d cells active", numCells); + return true; + } + case 6: + { + if (m_flowGridActor.m_statVolumeShadowBlocks > 0u) + { + NvFlowUint numBlocks = m_flowGridActor.m_statVolumeShadowBlocks; + snprintf(buf, 79, "Shadow: %d blocks active", numBlocks); + return true; + } + return false; + } + case 7: + { + if (m_flowGridActor.m_statVolumeShadowCells > 0u) + { + NvFlowUint numCells = m_flowGridActor.m_statVolumeShadowCells; + snprintf(buf, 79, "Shadow: %d cells active", numCells); + return true; + } + return false; + } + default: + { + return false; + } + } +} + +// ***************************** Projectile ******************************** + +void Projectile::init(AppGraphCtx* appctx, NvFlowContext* context) +{ + NvFlowGridEmitParamsDefaults(&m_emitParams); + m_emitParams.bounds.x.x = m_radius; + m_emitParams.bounds.y.y = m_radius; + m_emitParams.bounds.z.z = m_radius; + m_emitParams.bounds.w.y = 0.f; + + m_emitParams.velocityCoupleRate = { 10.f, 10.f, 10.f }; + + m_emitParams.temperature = 0.f; + m_emitParams.temperatureCoupleRate = 10.f; + + m_emitParams.fuel = 0.f; + m_emitParams.fuelCoupleRate = 10.f; + + m_emitParams.smoke = 0.f; + m_emitParams.smokeCoupleRate = 10.f; + + m_emitParams.allocationScale = { 0.f, 0.f, 0.f }; + + updateEmitterMode(); + + m_appctx = appctx; + m_meshContext = MeshInteropContextCreate(appctx); + m_mesh = MeshCreate(m_meshContext); + + MeshLoadFromFile(m_mesh, "../../data/sphere_high.ply"); + + NvFlowShapeSDFDesc shapeDesc; + NvFlowShapeSDFDescDefaults(&shapeDesc); + shapeDesc.resolution = { 32u, 32u, 32u }; + m_shape = NvFlowCreateShapeSDF(context, &shapeDesc); + + // generate sphere SDF + const float radius = 0.8f; + auto mappedData = NvFlowShapeSDFMap(m_shape, context); + if (mappedData.data) + { + for (NvFlowUint k = 0; k < mappedData.dim.z; k++) + for (NvFlowUint j = 0; j < mappedData.dim.y; j++) + for (NvFlowUint i = 0; i < mappedData.dim.x; i++) + { + float& val = mappedData.data[k * mappedData.depthPitch + j * mappedData.rowPitch + i]; + + float x = 2.f * (float(i) + 0.5f) / float(mappedData.dim.x) - 1.f; + float y = 2.f * (float(j) + 0.5f) / float(mappedData.dim.y) - 1.f; + float z = 2.f * (float(k) + 0.5f) / float(mappedData.dim.z) - 1.f; + + float d = sqrtf(x*x + y*y + z*z); + float v = d - radius; + + val = v; + } + NvFlowShapeSDFUnmap(m_shape, context); + } +} + +void Projectile::updatePosition(Path& path, float dt) +{ + if (path.m_active) + { + path.m_time -= dt; + if (path.m_time > path.m_timeEnd) + { + float wx = path.m_direction[0]; + float wy = path.m_direction[1]; + float wz = path.m_direction[2]; + + m_emitParams.smoke = 0.f; + m_emitParams.temperature = m_temperature; + m_emitParams.fuel = m_fuel; + m_emitParams.velocityLinear.x = -m_speed * wx; + m_emitParams.velocityLinear.y = -m_speed * wy; + m_emitParams.velocityLinear.z = -m_speed * wz; + float dist = m_speed * path.m_time; + path.m_position[0] = dist * wx + path.m_offset[0]; + path.m_position[1] = dist * wy + path.m_offset[1]; + path.m_position[2] = dist * wz + path.m_offset[2]; + m_emitParams.bounds.w.x = path.m_position[0]; + m_emitParams.bounds.w.y = path.m_position[1]; + m_emitParams.bounds.w.z = path.m_position[2]; + } + else + { + path.m_time = path.m_timeEnd; + path.m_active = false; + } + } +} + +void Projectile::update(NvFlowContext* context, NvFlowGrid* grid, float dt) +{ + int maxActive = -1; + for (int i = 0; i < m_pathsSize; i++) + { + Path& path = m_paths[i]; + if (path.m_active) + { + maxActive = i; + const int numSubSteps = 4; + const float convert = 3.14159f / 180.f; + float stepdt = dt / float(numSubSteps); + for (int i = 0; i < numSubSteps; i++) + { + updatePosition(path, stepdt); + + NvFlowShapeDesc shapeDesc; + shapeDesc.sphere.radius = 0.8f; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeSphere; + m_emitParams.deltaTime = stepdt; + + NvFlowGridEmit(grid, &shapeDesc, 1u, &m_emitParams, 1u); + } + } + } + m_pathsSize = maxActive + 1; +} + +void Projectile::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + m_view = view; + m_projection = projection; + + MeshInteropContextUpdate(m_meshContext, m_appctx); + + if (m_shouldDrawMesh) + { + for (int i = 0; i < m_pathsSize; i++) + { + Path& path = m_paths[i]; + if (path.m_active) + { + MeshDrawParams meshDrawParams; + meshDrawParams.renderMode = MESH_RENDER_SOLID; + meshDrawParams.projection = projection; + meshDrawParams.view = view; + meshDrawParams.model = DirectX::XMMatrixMultiply( + DirectX::XMMatrixScaling(0.8f * m_radius, 0.8f * m_radius, 0.8f * m_radius), + DirectX::XMMatrixTranslation(path.m_position[0], path.m_position[1], path.m_position[2]) + ); + + MeshDraw(m_mesh, &meshDrawParams); + } + } + } +} + +void Projectile::shoot() +{ + // find open path + int allocIdx = 0; + bool allocSuccess = false; + for (; allocIdx < m_pathsCap; allocIdx++) + { + Path& path = m_paths[allocIdx]; + if (!path.m_active) + { + allocSuccess = true; + break; + } + } + if (allocSuccess) + { + // update size + if (allocIdx + 1 > m_pathsSize) + { + m_pathsSize = allocIdx + 1; + } + // create path reference + Path& path = m_paths[allocIdx]; + path.m_active = true; + // compute direction + { + using namespace DirectX; + // compute eye direction + XMVECTOR screenDir = XMVectorSet(1.f, 0.f, 0.f, 0.f); + XMMATRIX viewInv = XMMatrixInverse(nullptr, m_view); + XMVECTOR worldDir = XMVector4Transform(screenDir, viewInv); + worldDir = XMVector3Normalize(worldDir); + + XMMATRIX viewProj = XMMatrixMultiply(m_view, m_projection); + XMMATRIX viewProjInv = XMMatrixInverse(nullptr, viewProj); + + float txp = 0.f; + float txn = 0.f; + { + XMVECTOR pos = XMVectorSet(0.f, 0.f, 0.f, 1.f); + XMVECTOR screencenter = XMVector4Transform(pos, viewProj); + screencenter = screencenter / XMVectorSplatW(screencenter); + + pos = worldDir + XMVectorSet(0.f, 0.f, 0.f, 1.f); + XMVECTOR screenpos = XMVector4Transform(pos, viewProj); + screenpos = screenpos / XMVectorSplatW(screenpos); + + // compute world offset + XMVECTOR offset = XMVectorSet(1.f, 0.f, 1.f, 1.f) * screencenter; + offset = XMVector4Transform(offset, viewProjInv); + offset = offset / XMVectorSplatW(offset); + path.m_offset[0] = XMVectorGetX(offset); + path.m_offset[1] = XMVectorGetY(offset); + path.m_offset[2] = XMVectorGetZ(offset); + + float x0 = XMVectorGetX(screencenter); + float x1 = XMVectorGetX(screenpos); + txp = (+1.f - x0) / (x1 - x0); + txn = (-1.f - x0) / (x1 - x0); + } + path.m_timeBegin = txp / m_speed; + path.m_timeEnd = txn / m_speed; + path.m_time = path.m_timeBegin; + + path.m_direction[0] = XMVectorGetX(worldDir); + path.m_direction[1] = XMVectorGetY(worldDir); + path.m_direction[2] = XMVectorGetZ(worldDir); + } + // set zeroth position + updatePosition(path, 0.f); + } +} + +void Projectile::updateEmitterMode() +{ + if (m_fireBallMode) + { + if (m_prediction) + { + m_emitParams.allocationScale = { 1.f, 1.f, 1.f }; + m_emitParams.allocationPredict = 0.4f; + } + else + { + m_emitParams.allocationScale = { 1.f, 1.f, 1.f }; + m_emitParams.allocationPredict = 0.f; + } + m_temperature = 2.f; + m_fuel = 2.f; + } + else + { + m_emitParams.allocationScale = { 0.f, 0.f, 0.f }; + m_emitParams.allocationPredict = 0.f; + m_temperature = 10.f; + m_fuel = 0.f; + } +} + +void Projectile::imgui() +{ + if (imguiButton("Shoot", true)) + { + shoot(); + } + if (imguiCheck("Fire Ball", m_fireBallMode)) + { + m_fireBallMode = !m_fireBallMode; + updateEmitterMode(); + } + if (imguiSlider("Radius", &m_radius, 0.f, 1.f, 0.01f, true)) + { + m_emitParams.bounds.x.x = m_radius; + m_emitParams.bounds.y.y = m_radius; + m_emitParams.bounds.z.z = m_radius; + } + imguiSlider("Speed", &m_speed, 0.f, 32.f, 0.1f, true); + imguiSlider("Temperature", &m_temperature, 0.f, 10.f, 0.1f, true); + if (m_fireBallMode) + { + imguiSlider("Fuel", &m_fuel, 0.f, 10.f, 0.1f, true); + if (imguiCheck("Prediction", m_prediction)) + { + m_prediction = !m_prediction; + updateEmitterMode(); + } + } + if (imguiCheck("Draw Projectile", m_shouldDrawMesh)) + { + m_shouldDrawMesh = !m_shouldDrawMesh; + } +} + +void Projectile::release() +{ + // set all projectiles inactive + for (int i = 0; i < m_pathsSize; i++) + { + Path& path = m_paths[i]; + path.m_active = false; + } + + NvFlowReleaseShapeSDF(m_shape); + + MeshRelease(m_mesh); + MeshContextRelease(m_meshContext); +}
\ No newline at end of file diff --git a/demo/DemoApp/scene.h b/demo/DemoApp/scene.h new file mode 100644 index 0000000..fee39e4 --- /dev/null +++ b/demo/DemoApp/scene.h @@ -0,0 +1,838 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#ifndef SCENE_H +#define SCENE_H + +#include <DirectXMath.h> + +#include <vector> + +#include "mesh.h" +#include "meshInterop.h" +#include "bitmap.h" +#include "curveEditor.h" + +#include "NvFlow.h" +#include "NvFlowInterop.h" + +struct AppGraphCtx; + +struct TimeStepper +{ + float m_deltaTime = 0.f; + float m_timeError = 0.f; + float m_fixedDt = (1.f / 60.f); + int m_maxSteps = 1; + + TimeStepper() {} + + int getNumSteps(float dt) + { + m_deltaTime = dt; + + // compute time steps + m_timeError += m_deltaTime; + + int numSteps = int(m_timeError / m_fixedDt); + if (numSteps < 0) numSteps = 0; + + m_timeError -= m_fixedDt * float(numSteps); + + if (numSteps > m_maxSteps) numSteps = m_maxSteps; + + return numSteps; + } +}; + +struct Scene +{ + Scene(const char* name) : m_name(name) {} + + virtual void init(AppGraphCtx* context, int winw, int winh) = 0; + virtual void resize(int winw, int winh); + virtual void update(float dt) final; + virtual void preDraw() = 0; + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) = 0; + virtual void release() = 0; + + virtual void shoot() = 0; + + virtual NvFlowUint64 getGridGPUMemUsage() = 0; + virtual bool getStats(int lineIdx, int statIdx, char* buf) = 0; + + virtual void imgui(int x, int y, int w, int h) = 0; + virtual bool imguiMouse(int mx, int my, unsigned char mbut); + + virtual bool shouldReset() = 0; + virtual void reset() = 0; + + const char* m_name; + + int m_mx = 0; + int m_my = 0; + unsigned char m_mbut; + int m_winw = 0; + int m_winh = 0; + +protected: + virtual void doUpdate(float dt) = 0; + + AppGraphCtx* m_context = nullptr; + TimeStepper m_timeStepper; + + int m_editorWidth = 0; + + friend struct ColorMapped; +}; + +struct FlowColorMap +{ + NvFlowRenderMaterialPool* m_materialPool = nullptr; + NvFlowRenderMaterialHandle m_materialDefault; + NvFlowRenderMaterialHandle m_material0; + NvFlowRenderMaterialHandle m_material1; + + unsigned int m_curveEditorHeight = 264u; + + bool m_curveEditorActiveDefault = false; + bool m_curveEditorActiveMat0 = false; + bool m_curveEditorActiveMat1 = false; + CurveEditState m_editStateDefault = { 0, 0 }; + CurveEditState m_editStateMat0 = { 0, 0 }; + CurveEditState m_editStateMat1 = { 0, 0 }; + std::vector<CurvePoint> m_curvePointsDefault; + std::vector<CurvePoint> m_curvePointsMat0; + std::vector<CurvePoint> m_curvePointsMat1; + + void initColorMap(NvFlowContext* context, const CurvePoint* pts, int numPoints, bool ptsEnabled); + void updateColorMap(NvFlowContext* context); + void imguiUpdate(Scene* scene, NvFlowContext* context, int border, int x, int y, int w, int h); + bool colorMapActive(int mx, int my, unsigned char mbut); +}; + +struct FlowContext +{ + AppGraphCtx* m_appctx = nullptr; + + NvFlowContext* m_renderContext = nullptr; + NvFlowDepthStencilView* m_dsv = nullptr; + NvFlowRenderTargetView* m_rtv = nullptr; + + NvFlowDevice* m_renderDevice = nullptr; + NvFlowDevice* m_gridDevice = nullptr; + NvFlowDeviceQueue* m_gridQueue = nullptr; + NvFlowDeviceQueue* m_gridCopyQueue = nullptr; + NvFlowDeviceQueue* m_renderCopyQueue = nullptr; + NvFlowContext* m_gridContext = nullptr; + NvFlowContext* m_gridCopyContext = nullptr; + NvFlowContext* m_renderCopyContext = nullptr; + + bool m_multiGPUSupported = false; + bool m_commandQueueSupported = false; + bool m_enableMultiGPU = false; + bool m_enableCommandQueue = false; + bool m_multiGPUActive = false; + bool m_commandQueueActive = false; + + int m_maxFramesInFlight = 3u; + int m_framesInFlight = 0; + + FlowContext() {} + ~FlowContext() {} + + void init(AppGraphCtx* appctx); + void release(); + + bool updateBegin(); + void updateEnd(); + void preDrawBegin(); + void preDrawEnd(); + void drawBegin(); + void drawEnd(); + +protected: + void createComputeContext(); + void releaseComputeContext(); + int computeContextBegin(); + void computeContextEnd(); +}; + +struct FlowGridActor +{ + AppGraphCtx* m_appctx = nullptr; + + NvFlowGrid* m_grid = nullptr; + NvFlowGridProxy* m_gridProxy = nullptr; + NvFlowVolumeRender* m_volumeRender = nullptr; + NvFlowVolumeShadow* m_volumeShadow = nullptr; + NvFlowCrossSection* m_crossSection = nullptr; + + NvFlowGridDesc m_gridDesc; + NvFlowGridParams m_gridParams; + NvFlowGridMaterialParams m_materialParams; + NvFlowRenderMaterialParams m_renderMaterialDefaultParams; + NvFlowRenderMaterialParams m_renderMaterialMat0Params; + NvFlowRenderMaterialParams m_renderMaterialMat1Params; + NvFlowVolumeRenderParams m_renderParams; + NvFlowCrossSectionParams m_crossSectionParams; + + FlowColorMap m_colorMap; + + NvFlowGridExport* m_gridExportDebugVis = nullptr; + NvFlowGridExport* m_gridExportOverride = nullptr; + NvFlowVolumeRenderParams m_renderParamsOverride; + bool m_separateLighting = false; + + float m_memoryLimit = 3.f; + float m_memoryScale = 0.125f * 0.075f; + int m_cellSizeLogScale = 0; + float m_cellSizeScale = 1.f; + + bool m_enableVolumeShadow = false; + bool m_forceApplyShadow = false; + float m_shadowResidentScale = 1.f; + float m_shadowIntensityScale = 0.5f; + float m_shadowMinIntensity = 0.15f; + NvFlowFloat4 m_shadowBlendCompMask = { 0.f, 0.f, 0.f, 0.f }; + float m_shadowBlendBias = 1.f; + bool m_shadowDebugVis = false; + float m_shadowPan = 0.f; + float m_shadowTilt = 0.f; + + bool m_shadowWasForceApplied = false; + NvFlowFloat4 m_forceIntensityCompMask = { 0.f, 0.f, 0.f, 0.f }; + float m_forceIntensityBias = 1.f; + + bool m_enableCrossSection = false; + float m_crossSectionScale = 2.f; + float m_crossSectionBackgroundColor = 0.f; + NvFlowFloat3 m_crossSectionLineColor = { 141.f / 255.f, 199.f / 255.f, 63.f / 255.f }; + + NvFlowUint m_statNumLayers = 0u; + NvFlowUint m_statNumDensityBlocks = 0u; + NvFlowUint m_statNumDensityCells = 0u; + NvFlowUint m_statMaxDensityBlocks = 0u; + NvFlowUint m_statNumVelocityBlocks = 0u; + NvFlowUint m_statNumVelocityCells = 0u; + NvFlowUint m_statMaxVelocityBlocks = 0u; + + NvFlowUint m_statVolumeShadowBlocks = 0u; + NvFlowUint m_statVolumeShadowCells = 0u; + + FlowGridActor() {} + ~FlowGridActor() {} + + void initParams(size_t vramAmount); + void init(FlowContext* flowContext, AppGraphCtx* appctx); + void release(); + + void updatePreEmit(FlowContext* flowContext, float dt); + void updatePostEmit(FlowContext* flowContext, float dt, bool shouldUpdate, bool shouldReset); + void preDraw(FlowContext* flowContext); + void draw(FlowContext* flowContext, DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); +}; + +struct Projectile +{ + struct Path + { + float m_time = 0.f; + float m_timeBegin = 0.f; + float m_timeEnd = 0.f; + bool m_active = false; + + float m_direction[3] = { 1.f, 0.f, 0.f }; + float m_offset[3] = { 0.f, 0.f, 0.f }; + float m_position[3] = { 0.f, 0.f, 0.f }; + }; + + static const int m_pathsCap = 32u; + Path m_paths[m_pathsCap]; + int m_pathsSize = 0; + + NvFlowShapeSDF* m_shape = nullptr; + NvFlowGridEmitParams m_emitParams; + + float m_radius = 0.15f; + float m_speed = 8.f; + float m_temperature = 10.f; + float m_fuel = 0.f; + + DirectX::XMMATRIX m_view; + DirectX::XMMATRIX m_projection; + + AppGraphCtx* m_appctx = nullptr; + MeshContext* m_meshContext = nullptr; + Mesh* m_mesh = nullptr; + bool m_shouldDrawMesh = true; + bool m_fireBallMode = false; + bool m_prediction = true; + + Projectile() {} + + void init(AppGraphCtx* appctx, NvFlowContext* context); + + void shoot(); + + void update(NvFlowContext* context, NvFlowGrid* grid, float dt); + + void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + + void imgui(); + + void release(); + +protected: + void updatePosition(Path& path, float dt); + + void updateEmitterMode(); +}; + +struct SceneFluid : public Scene +{ + SceneFluid(const char* name) : Scene(name) {} + + virtual void initParams() = 0; + + void imguiDesc(); + void imguiFluidSim(); + void imguiFluidEmitter(); + void imguiFluidRender(); + void imguiFluidAlloc(); + void imguiFluidTime(); + void imguiLoadSave(); + + virtual void imguiDescExtra() {} + virtual void imguiFluidSimExtra() {} + virtual void imguiFluidEmitterExtra() {} + virtual void imguiFluidRenderExtra() {} + virtual void imguiFluidAllocExtra() {} + virtual void imguiFluidTimeExtra() {} + + virtual void imgui(int x, int y, int w, int h); + virtual bool imguiMouse(int mx, int my, unsigned char mbut); + + virtual void shoot() { m_projectile.shoot(); } + + virtual NvFlowUint64 getGridGPUMemUsage(); + virtual bool getStats(int lineIdx, int statIdx, char* buf); + + AppGraphCtx* m_appctx = nullptr; + + FlowContext m_flowContext; + FlowGridActor m_flowGridActor; + + Projectile m_projectile; + + NvFlowShapeSDF* m_shape = nullptr; + + NvFlowGridEmitParams m_emitParams; + + bool m_isFirstRun = true; + bool m_shouldReset = false; + bool m_shouldGridReset = false; + bool m_shouldLoadPreset = false; + + virtual bool shouldReset() { return m_shouldReset; } + virtual void reset(); +}; + +struct SceneSimpleFlame : public SceneFluid +{ + SceneSimpleFlame() : SceneFluid("Simple Flame") {} + + virtual void init(AppGraphCtx* context, int winw, int winh); + virtual void doUpdate(float dt); + virtual void preDraw(); + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + virtual void release(); + virtual void imgui(int x, int y, int w, int h); + + virtual void initParams(); +}; + +struct SceneSimpleFlameDouble : public SceneSimpleFlame +{ + SceneSimpleFlameDouble() { m_name = "Multi Material"; } + + virtual void init(AppGraphCtx* context, int winw, int winh); + virtual void doUpdate(float dt); + virtual void preDraw(); + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + virtual void release(); + virtual void imgui(int x, int y, int w, int h); + + virtual void initParams(); + + NvFlowGridEmitParams m_emitParamsA; + NvFlowGridEmitParams m_emitParamsB; + NvFlowGridMaterialHandle m_materialA; + NvFlowGridMaterialHandle m_materialB; +}; + +struct SceneSimpleFlameFuelMap : public SceneSimpleFlame +{ + SceneSimpleFlameFuelMap() { m_name = "Fuel Map"; } + + virtual void init(AppGraphCtx* context, int winw, int winh); + virtual void doUpdate(float dt); + virtual void preDraw(); + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + virtual void release(); + virtual void imgui(int x, int y, int w, int h); + + virtual void initParams(); +}; + +struct SceneSimpleFlameParticleSurface : public SceneSimpleFlame +{ + SceneSimpleFlameParticleSurface() { m_name = "Particle Surface"; } + + virtual void init(AppGraphCtx* context, int winw, int winh); + virtual void doUpdate(float dt); + virtual void preDraw(); + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + virtual void release(); + virtual void imgui(int x, int y, int w, int h); + virtual void imguiFluidRenderExtra(); + + virtual void initParams(); + + static void emitCustomAllocFunc(void* userdata, const NvFlowGridEmitCustomAllocParams* params); + static void emitCustomEmitVelocityFunc(void* userdata, NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params); + static void emitCustomEmitDensityFunc(void* userdata, NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params); + + void doEmitCustomAllocFunc(const NvFlowGridEmitCustomAllocParams* params); + void doEmitCustomEmitVelocityFunc(NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params); + void doEmitCustomEmitDensityFunc(NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params); + + NvFlowParticleSurface* m_particleSurface = nullptr; + + NvFlowParticleSurfaceParams m_particleParams = {}; + NvFlowParticleSurfaceEmitParams m_surfaceEmitParams = {}; + + bool m_visualizeSurface = true; + float m_time = 0.f; + + std::vector<float> m_positions; +}; + +struct SceneSimpleFlameThrower : public SceneSimpleFlame +{ + float time = 0.f; + + SceneSimpleFlameThrower() { m_name = "Simple Flame Thrower"; } + + virtual void initParams() + { + SceneSimpleFlame::initParams(); + + m_flowGridActor.m_gridParams.gravity = { 0.f, -0.5f, 0.f }; + + m_flowGridActor.m_materialParams.smoke.damping = 0.4f; + m_flowGridActor.m_materialParams.smoke.fade = 0.4f; + m_flowGridActor.m_materialParams.vorticityStrength = 20.f; + + m_emitParams.fuel = 2.0f; + m_emitParams.temperature = 3.f; + m_emitParams.smoke = 0.5f; + + m_emitParams.bounds.x.x = 0.5f; + m_emitParams.bounds.y.y = 0.5f; + m_emitParams.bounds.z.z = 0.5f; + + m_emitParams.allocationScale = { 1.f, 1.f, 1.f }; + m_emitParams.allocationPredict = 0.05f; + } + + void init(AppGraphCtx* context, int winw, int winh) + { + SceneSimpleFlame::init(context, winw, winh); + } + + void doUpdate(float dt) + { + time += dt; + + const float rate = 8.f; + const float period = 2.f * 3.14159265f / rate; + if (time > period) time -= period; + + m_emitParams.bounds.w.x = 0.f; // 2.f * cosf(rate * time); + m_emitParams.bounds.w.z = 0.f; // 2.f * sinf(rate * time); + + float a = 0.25f * cosf(rate * time); + + m_emitParams.velocityLinear.x = +32.f * cosf(a); + m_emitParams.velocityLinear.y = -2.f + 64.f * (1.f - cosf(a)); + m_emitParams.velocityLinear.z = +32.f * sinf(a); + + SceneSimpleFlame::doUpdate(dt); + } + + void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) + { + SceneSimpleFlame::draw(projection, view); + } + + void release() + { + SceneSimpleFlame::release(); + } +}; + +struct SceneSimpleFlameBall : public SceneSimpleFlame +{ + float time = 0.f; + float m_radius = 0.6f; + + SceneSimpleFlameBall() { m_name = "Simple Flame Ball"; } + + virtual void initParams(); + + void init(AppGraphCtx* context, int winw, int winh); + + void doUpdate(float dt); + + void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + + void imguiFluidRenderExtra(); + + void imguiFluidEmitterExtra(); + + void imguiFluidSimExtra(); + + void imgui(int xIn, int yIn, int wIn, int hIn); + + void release(); +}; + +struct SceneSimpleFlameAnimated : public SceneSimpleFlame +{ + float time = 0.f; + + SceneSimpleFlameAnimated() { m_name = "Simple Flame Animated"; } + + virtual void initParams() + { + SceneSimpleFlame::initParams(); + + m_flowGridActor.m_gridParams.gravity = { 0.f, -0.5f, 0.f }; + + m_emitParams.fuel = 1.4f; + m_emitParams.temperature = 3.f; + m_emitParams.smoke = 0.5f; + + m_emitParams.allocationScale = { 1.33f, 1.33f, 1.33f }; + } + + void init(AppGraphCtx* context, int winw, int winh) + { + SceneSimpleFlame::init(context, winw, winh); + } + + void doUpdate(float dt) + { + time += dt; + + const float rate = 0.375f; + const float period = 2.f * 3.14159265f / rate; + if (time > period) time -= period; + + m_emitParams.bounds.w.x = 2.f * cosf(rate * time); + m_emitParams.bounds.w.z = 2.f * sinf(rate * time); + + m_emitParams.velocityLinear.x = +8.f * sinf(rate * time); + m_emitParams.velocityLinear.y = -2.f; + m_emitParams.velocityLinear.z = -8.f * cosf(rate * time); + + m_emitParams.predictVelocityWeight = 1.f; + m_emitParams.predictVelocity.x = -4.f * sinf(rate * time); + m_emitParams.predictVelocity.y = 0.f; + m_emitParams.predictVelocity.z = +4.f * cosf(rate * time); + + SceneSimpleFlame::doUpdate(dt); + } + + void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) + { + SceneSimpleFlame::draw(projection, view); + } + + void release() + { + SceneSimpleFlame::release(); + } +}; + +struct SceneDynamicCoupleRate : public SceneSimpleFlame +{ + float theta = 0.f; + float rate = 0.25f; + float coupleRateScale = 0.1f; + float emitterScale = 1.f; + + SceneDynamicCoupleRate() { m_name = "Dynamic Couple Rate"; } + + virtual void initParams(); + + void doUpdate(float dt); + + virtual void imguiFluidEmitterExtra(); + + static float positionFunc(float theta); + static float velocityFunc(float theta, float rate); +}; + +struct SceneSimpleFlameMesh : public SceneSimpleFlame +{ + MeshContext* m_meshContext = nullptr; + Mesh* m_mesh = nullptr; + NvFlowSDFGen* m_sdfGen = nullptr; + NvFlowShapeSDF* m_teapotShape = nullptr; + bool m_shouldDrawMesh = true; + + NvFlowFloat3 m_sdfScale = { 0.25f, 0.25f, 0.25f }; + NvFlowFloat3 m_emitterScale = { 0.5f, 0.5f, 0.5f }; + NvFlowFloat3 m_emitterOffset = { 0.f, 0.33f, 0.f }; + + const char* m_meshPath = "../../data/teapot.ply"; + + NvFlowGridEmitParams m_teapotEmitParams; + + bool m_animate = true; + float m_time = 0.f; + + SceneSimpleFlameMesh() { m_name = "Simple Flame Mesh"; } + + virtual void initParams(); + + virtual void init(AppGraphCtx* context, int winw, int winh); + + virtual void doUpdate(float dt); + + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + + virtual void release(); + + virtual void imguiFluidRenderExtra(); + + virtual void imguiFluidEmitterExtra(); +}; + +struct SceneSimpleFlameCollision : public SceneSimpleFlameMesh +{ + SceneSimpleFlameCollision() + { + m_name = "Simple Flame Collision"; + m_meshPath = "../../data/box.ply"; + m_sdfScale = { 0.75f, 0.75f, 0.75f }; + m_emitterScale = { 1.5f, 0.125f, 1.5f }; + m_emitterOffset = { 0.f, 0.6f, 0.f }; + } +}; + +struct SceneSimpleFlameCulling : public SceneSimpleFlame +{ + SceneSimpleFlameCulling() { m_name = "Simple Flame Culling"; } + + virtual void initParams(); + + virtual void doUpdate(float dt); + + virtual void imguiFluidEmitterExtra(); + + NvFlowUint m_emitGridR = 8u; +}; + +struct SceneSimpleFlameConvex : public SceneSimpleFlame +{ + SceneSimpleFlameConvex() { m_name = "Convex"; } + + virtual void initParams(); + + virtual void doUpdate(float dt); + + virtual void imguiFluidEmitterExtra(); + + float m_size = 0.75f; + float m_distanceScale = 1.f; +}; + +struct SceneSimpleFlameCapsule : public SceneSimpleFlame +{ + SceneSimpleFlameCapsule() { m_name = "Capsule"; } + + virtual void initParams(); + + virtual void doUpdate(float dt); + + virtual void imguiFluidEmitterExtra(); + + float m_capsuleRadius = 0.25f; + float m_capsuleLength = 0.75f; + float m_distanceScale = 3.5f; + bool m_boxMode = false; +}; + +struct Scene2DTextureEmitter : public SceneFluid +{ + Scene2DTextureEmitter(bool animEnabled) : SceneFluid(animEnabled ? "Logo Pulsed" : "Logo Steady"), m_animEnabled(animEnabled) {} + + virtual void init(AppGraphCtx* context, int winw, int winh); + virtual void doUpdate(float dt); + virtual void preDraw(); + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + virtual void release(); + virtual void imguiFluidEmitterExtra(); + + virtual void initParams(); + + Bitmap m_bitmap; + + float m_animTime = 0.f; + bool m_animEnabled = false; + + void animChanged(); +}; + +struct SceneSDFTest : public SceneFluid +{ + SceneSDFTest() : SceneFluid("SDF Test") {} + + virtual void init(AppGraphCtx* context, int winw, int winh); + virtual void doUpdate(float dt); + virtual void preDraw(); + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + virtual void release(); + virtual void imgui(int x, int y, int w, int h); + + virtual void initParams(); + + NvFlowSDFGen* m_sdfGen = nullptr; + + MeshContext* m_meshContext = nullptr; + Mesh* m_mesh = nullptr; +}; + +struct ComputeContext; +struct ComputeShader; +struct ComputeConstantBuffer; +struct ComputeResource; +struct ComputeResourceRW; + +struct SceneCustomLighting : public SceneSDFTest +{ + SceneCustomLighting() { m_name = "Custom Lighting"; } + + virtual void init(AppGraphCtx* context, int winw, int winh); + virtual void doUpdate(float dt); + virtual void preDraw(); + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + virtual void release(); + virtual void imgui(int x, int y, int w, int h); + + virtual void initParams(); + + float m_time = 0.f; + + NvFlowGridImport* m_import = nullptr; + + ComputeContext* m_computeContext = nullptr; + ComputeShader* m_computeShader = nullptr; + ComputeConstantBuffer* m_computeConstantBuffer = nullptr; + ComputeResource* m_exportBlockList = nullptr; + ComputeResource* m_exportBlockTable = nullptr; + ComputeResource* m_exportData = nullptr; + ComputeResource* m_importBlockList = nullptr; + ComputeResource* m_importBlockTable = nullptr; + ComputeResourceRW* m_importDataRW = nullptr; +}; + +struct SceneSimpleSmoke : public SceneFluid +{ + SceneSimpleSmoke() : SceneFluid("Simple Smoke") {} + + virtual void init(AppGraphCtx* context, int winw, int winh); + virtual void doUpdate(float dt); + virtual void preDraw(); + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + virtual void release(); + virtual void imgui(int x, int y, int w, int h); + + virtual void imguiFluidEmitterExtra(); + virtual void imguiFluidRenderExtra(); + + virtual void initParams(); + + NvFlowVolumeShadow* m_volumeShadow = nullptr; + + bool m_animate = false; + bool m_animateOld = false; + float theta = 0.f; + float rate = 0.125f; + float coupleRateScale = 0.1f; + + static NvFlowFloat3 positionFunc(float theta); + static NvFlowFloat3 velocityFunc(float theta, float rate); +}; + +struct SceneCustomEmit : public SceneFluid +{ + SceneCustomEmit() : SceneFluid("Custom Emit") {} + + virtual void init(AppGraphCtx* context, int winw, int winh); + virtual void doUpdate(float dt); + virtual void preDraw(); + virtual void draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view); + virtual void release(); + virtual void imgui(int x, int y, int w, int h); + + virtual void imguiFluidEmitterExtra(); + + virtual void initParams(); + + static void emitCustomAllocFunc(void* userdata, const NvFlowGridEmitCustomAllocParams* params); + static void emitCustomEmitVelocityFunc(void* userdata, NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params); + static void emitCustomEmitDensityFunc(void* userdata, NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params); + + void doEmitCustomAllocFunc(const NvFlowGridEmitCustomAllocParams* params); + void doEmitCustomEmitVelocityFunc(NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params); + void doEmitCustomEmitDensityFunc(NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params); + + struct CustomEmitParams + { + NvFlowUint radius; + NvFlowFloat4 targetValue; + NvFlowFloat4 blendRate; + }; + + void doEmitCustomEmit(NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params, const CustomEmitParams* customParams); + + ComputeContext* m_customContext = nullptr; + ComputeShader* m_customEmitAllocCS = nullptr; + ComputeShader* m_customEmitEmitCS = nullptr; + ComputeShader* m_customEmitEmit2CS = nullptr; + ComputeConstantBuffer* m_customConstantBuffer = nullptr; + + ComputeResourceRW* m_allocMask = nullptr; + ComputeResource* m_blockTable = nullptr; + ComputeResource* m_blockList = nullptr; + ComputeResourceRW* m_dataRW[2u] = { nullptr }; + + bool m_fullDomain = false; +}; + +Scene* getScene(int index); + +void pointsToImage(NvFlowFloat4* image, int imageDim, const CurvePoint* pts, int numPts); + +#endif
\ No newline at end of file diff --git a/demo/DemoApp/scene2DTextureEmitter.cpp b/demo/DemoApp/scene2DTextureEmitter.cpp new file mode 100644 index 0000000..c2d3984 --- /dev/null +++ b/demo/DemoApp/scene2DTextureEmitter.cpp @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <stdio.h> +#include <string.h> + +#include "loader.h" +#include "imgui.h" +#include "imguiser.h" + +namespace Preset0 +{ +#include "preset0.h" +} + +#include "scene.h" + +#include <SDL.h> + +void Scene2DTextureEmitter::initParams() +{ + m_flowGridActor.initParams(AppGraphCtxDedicatedVideoMemory(m_appctx)); + + // set emitter defaults + NvFlowGridEmitParamsDefaults(&m_emitParams); + + m_emitParams.bounds.x.x = 1.5f; + m_emitParams.bounds.y.y = 1.5f; + m_emitParams.bounds.z.z = 0.125f; + m_emitParams.velocityLinear.y = 0.f; + m_emitParams.fuel = 1.4f; + m_emitParams.smoke = 0.5f; + + FILE* file = nullptr; + fopen_s(&file, "../../data/GeforceClaw.bmp", "rb"); + if (file) + { + m_bitmap.read(file); + fclose(file); + } + + // grid parameter overrides + m_flowGridActor.m_gridParams.gravity = NvFlowFloat3{ 0.f, -1.f, 0.f }; + //m_flowGridActor.m_gridParams.combustion.buoyancyPerTemp = 2.f; + m_flowGridActor.m_materialParams.smokePerBurn = 4.f; + m_flowGridActor.m_materialParams.tempPerBurn = 8.f; + m_flowGridActor.m_materialParams.smoke.fade = 0.4f; +} + +void Scene2DTextureEmitter::init(AppGraphCtx* appctx, int winw, int winh) +{ + m_appctx = appctx; + + if (!m_shouldReset || m_isFirstRun) + { + initParams(); + m_isFirstRun = false; + } + + m_flowContext.init(appctx); + + m_flowGridActor.init(&m_flowContext, appctx); + + // more compute resources + NvFlowShapeSDFDesc shapeDesc; + //NvFlowShapeSDFDescDefaults(&shapeDesc); + shapeDesc.resolution.x = m_bitmap.width; + shapeDesc.resolution.y = m_bitmap.height; + shapeDesc.resolution.z = 1u; + m_shape = NvFlowCreateShapeSDF(m_flowContext.m_gridContext, &shapeDesc); + + // generate SDF from bitmap + auto mappedData = NvFlowShapeSDFMap(m_shape, m_flowContext.m_gridContext); + if (mappedData.data) + { + NvFlowUint bmRowPitch = ((m_bitmap.bitsPerPixel * m_bitmap.width + 31) / 32) * 4; + + for (NvFlowUint k = 0; k < mappedData.dim.z; k++) + for (NvFlowUint j = 0; j < mappedData.dim.y; j++) + for (NvFlowUint i = 0; i < mappedData.dim.x; i++) + { + float& val = mappedData.data[k * mappedData.depthPitch + j * mappedData.rowPitch + i]; + + float v = 0.5f; + + NvFlowUint byteIdx = j * bmRowPitch + (i >> 3); + NvFlowUint mask = 128 >> (i & 7); + + NvFlowUint inval = mask & m_bitmap.data[byteIdx]; + + if (inval) + { + v = -0.5f; + } + + val = v; + } + NvFlowShapeSDFUnmap(m_shape, m_flowContext.m_gridContext); + } + + animChanged(); + + // create default color map + { + const int numPoints = 5; + const CurvePoint pts[numPoints] = + { + {0.f, 0.f,0.f,0.f,0.f }, + {0.05f,0.f,0.f,0.f,0.5f}, + {0.6f,0.7f * 141.f / 255.f, 0.7f * 199.f / 255.f, 0.7f * 63.f / 255.f,0.8f}, + {0.85f,0.9f * 141.f / 255.f, 0.9f * 199.f / 255.f, 0.9f * 63.f / 255.f,0.8f}, + {1.f,1.5f * 141.f / 255.f, 1.5f * 199.f / 255.f, 1.5f * 63.f / 255.f,0.5f} + }; + + auto& colorMap = m_flowGridActor.m_colorMap; + colorMap.initColorMap(m_flowContext.m_renderContext, pts, numPoints, (colorMap.m_curvePointsDefault.size() == 0)); + } + + m_projectile.init(m_appctx, m_flowContext.m_gridContext); + + resize(winw, winh); +} + +void Scene2DTextureEmitter::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + { + m_animTime += dt; + if (m_animTime > 8.f) m_animTime = 0.f; + + if (m_animEnabled) + { + if (m_animTime < 2.f) + { + m_emitParams.temperature = 0.f; + m_emitParams.smoke = 0.f; + m_emitParams.fuel = 1.4f; + m_emitParams.velocityLinear.y = 1.f; + } + else if (m_animTime < 2.25f) + { + m_emitParams.temperature = 5.f; + m_emitParams.smoke = 0.5f; + m_emitParams.velocityLinear.y = 8.f; + } + else if (m_animTime < 2.5f) + { + m_emitParams.temperature = 0.f; + m_emitParams.fuel = 0.f; + m_emitParams.smoke = 0.f; + m_emitParams.velocityLinear.y = 0.f; + } + } + + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + NvFlowShapeDesc shapeDesc; + shapeDesc.sdf.sdfOffset = 0u; // m_shape; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeSDF; + m_emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &m_emitParams, 1u); + + NvFlowShapeSDF* sdfs[] = { m_shape }; + NvFlowGridUpdateEmitSDFs(m_flowGridActor.m_grid, sdfs, 1u); + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + } + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +void Scene2DTextureEmitter::preDraw() +{ + m_flowContext.preDrawBegin(); + + m_flowGridActor.preDraw(&m_flowContext); + + m_flowContext.preDrawEnd(); +} + +void Scene2DTextureEmitter::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + m_projectile.draw(projection, view); + + m_flowContext.drawBegin(); + + m_flowGridActor.draw(&m_flowContext, projection, view); + + m_flowContext.drawEnd(); +} + +void Scene2DTextureEmitter::release() +{ + m_projectile.release(); + + m_flowGridActor.release(); + + NvFlowReleaseShapeSDF(m_shape); + + m_flowContext.release(); +} + +void Scene2DTextureEmitter::animChanged() +{ + if (!m_animEnabled) + { + m_emitParams.temperature = 1.f; + m_emitParams.smoke = 0.5f; + m_emitParams.fuel = 1.2f; + m_emitParams.velocityLinear.y = -1.f; + } + else + { + m_animTime = 0.f; + } +} + +void Scene2DTextureEmitter::imguiFluidEmitterExtra() +{ + imguiSeparatorLine(); + + imguiLabel("Effect"); + + if (imguiserCheck("Pulsed", m_animEnabled, true)) + { + m_animEnabled = !m_animEnabled; + animChanged(); + } +}
\ No newline at end of file diff --git a/demo/DemoApp/sceneCustomEmit.cpp b/demo/DemoApp/sceneCustomEmit.cpp new file mode 100644 index 0000000..c52db59 --- /dev/null +++ b/demo/DemoApp/sceneCustomEmit.cpp @@ -0,0 +1,435 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include <stdio.h> +#include <string.h> + +#include "loader.h" +#include "imgui.h" +#include "imguiser.h" + +namespace PresetFlame +{ +#include "presetFlame.h" +} + +#include "scene.h" + +#include <SDL.h> + +#include "computeContext.h" + +namespace +{ + // Need BYTE defined for shader bytecode + typedef unsigned char BYTE; + #include "customEmitAllocCS.hlsl.h" + #include "customEmitEmitCS.hlsl.h" + #include "customEmitEmit2CS.hlsl.h" +} + +void SceneCustomEmit::initParams() +{ + m_flowGridActor.initParams(AppGraphCtxDedicatedVideoMemory(m_appctx)); + + // set emitter defaults + NvFlowGridEmitParamsDefaults(&m_emitParams); + + m_emitParams.bounds.x.x = 0.25f; + m_emitParams.bounds.y.y = 0.25f; + m_emitParams.bounds.z.z = 0.25f; + m_emitParams.velocityLinear.y = 8.f; + m_emitParams.fuel = 1.9f; + m_emitParams.smoke = 0.5f; + + // grid parameter overrides + m_flowGridActor.m_gridParams.gravity = NvFlowFloat3{ 0.f, -1.f, 0.f }; + + m_shouldLoadPreset = true; +} + +void SceneCustomEmit::init(AppGraphCtx* appctx, int winw, int winh) +{ + m_appctx = appctx; + + if (!m_shouldReset || m_isFirstRun) + { + initParams(); + m_isFirstRun = false; + } + + m_flowContext.init(appctx); + + m_flowGridActor.init(&m_flowContext, appctx); + + // create default color map + { + const int numPoints = 5; + const CurvePoint pts[numPoints] = { + { 0.f, 0.f,0.f,0.f,0.f }, + { 0.05f, 0.f,0.f,0.f,0.5f }, + { 0.6f, 213.f / 255.f,100.f / 255.f,30.f / 255.f,0.8f }, + { 0.85f, 255.f / 255.f,240.f / 255.f,0.f,0.8f }, + { 1.f, 1.f,1.f,1.f,0.7f } + }; + + auto& colorMap = m_flowGridActor.m_colorMap; + colorMap.initColorMap(m_flowContext.m_renderContext, pts, numPoints, (colorMap.m_curvePointsDefault.size() == 0)); + } + + m_projectile.init(m_appctx, m_flowContext.m_gridContext); + + resize(winw, winh); + + // create app compute resources + { + m_customContext = ComputeContextNvFlowContextCreate(m_flowContext.m_gridContext); + + ComputeShaderDesc shaderDesc = {}; + shaderDesc.cs = g_customEmitAllocCS; + shaderDesc.cs_length = sizeof(g_customEmitAllocCS); + m_customEmitAllocCS = ComputeShaderCreate(m_customContext, &shaderDesc); + + shaderDesc.cs = g_customEmitEmitCS; + shaderDesc.cs_length = sizeof(g_customEmitEmitCS); + m_customEmitEmitCS = ComputeShaderCreate(m_customContext, &shaderDesc); + + shaderDesc.cs = g_customEmitEmit2CS; + shaderDesc.cs_length = sizeof(g_customEmitEmit2CS); + m_customEmitEmit2CS = ComputeShaderCreate(m_customContext, &shaderDesc); + + ComputeConstantBufferDesc cbDesc = {}; + cbDesc.sizeInBytes = 1024 * sizeof(float); + m_customConstantBuffer = ComputeConstantBufferCreate(m_customContext, &cbDesc); + } + + // register callbacks + { + NvFlowGridEmitCustomRegisterAllocFunc(m_flowGridActor.m_grid, emitCustomAllocFunc, this); + NvFlowGridEmitCustomRegisterEmitFunc(m_flowGridActor.m_grid, eNvFlowGridTextureChannelVelocity, emitCustomEmitVelocityFunc, this); + NvFlowGridEmitCustomRegisterEmitFunc(m_flowGridActor.m_grid, eNvFlowGridTextureChannelDensity, emitCustomEmitDensityFunc, this); + } +} + +void SceneCustomEmit::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + ComputeContextNvFlowContextUpdate(m_customContext, m_flowContext.m_gridContext); + + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + NvFlowShapeDesc shapeDesc; + shapeDesc.sphere.radius = 0.8f; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeSphere; + m_emitParams.deltaTime = dt; + + // Disable traditional emitters here + //NvFlowGridEmit(m_grid, &shapeDesc, 1u, &m_emitParams, 1u); + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +namespace +{ + void updateResource(ComputeResource*& computeResource, NvFlowResource* flowResource, ComputeContext* customContext, NvFlowContext* flowContext) + { + if (computeResource) { + ComputeResourceNvFlowUpdate(customContext, computeResource, flowContext, flowResource); + } + else { + computeResource = ComputeResourceNvFlowCreate(customContext, flowContext, flowResource); + } + } + void updateResourceRW(ComputeResourceRW*& computeResourceRW, NvFlowResourceRW* flowResourceRW, ComputeContext* customContext, NvFlowContext* flowContext) + { + if (computeResourceRW) { + ComputeResourceRWNvFlowUpdate(customContext, computeResourceRW, flowContext, flowResourceRW); + } + else { + computeResourceRW = ComputeResourceRWNvFlowCreate(customContext, flowContext, flowResourceRW); + } + } +} + +void SceneCustomEmit::doEmitCustomAllocFunc(const NvFlowGridEmitCustomAllocParams* params) +{ + updateResourceRW(m_allocMask, params->maskResourceRW, m_customContext, m_flowContext.m_renderContext); + + struct ShaderParams + { + NvFlowUint4 minMaskIdx; + NvFlowUint4 maxMaskIdx; + }; + + NvFlowDim maskDim = params->maskDim; + + NvFlowUint radius = 1u; + + NvFlowUint4 minMaskIdx, maxMaskIdx; + + minMaskIdx.x = maskDim.x / 2 - radius; + minMaskIdx.y = maskDim.y / 2 - radius; + minMaskIdx.z = maskDim.z / 2 - radius; + minMaskIdx.w = 0u; + + maxMaskIdx.x = maskDim.x / 2 + radius + 1; + maxMaskIdx.y = maskDim.y / 2 + radius + 1; + maxMaskIdx.z = maskDim.z / 2 + radius + 1; + maxMaskIdx.w = 0u; + + auto mapped = (ShaderParams*)ComputeConstantBufferMap(m_customContext, m_customConstantBuffer); + + mapped->minMaskIdx = minMaskIdx; + mapped->maxMaskIdx = maxMaskIdx; + + ComputeConstantBufferUnmap(m_customContext, m_customConstantBuffer); + + ComputeDispatchParams dparams = {}; + dparams.shader = m_customEmitAllocCS; + dparams.constantBuffer = m_customConstantBuffer; + dparams.gridDim[0] = (maxMaskIdx.x - minMaskIdx.x + 7) / 8; + dparams.gridDim[1] = (maxMaskIdx.y - minMaskIdx.y + 7) / 8; + dparams.gridDim[2] = (maxMaskIdx.z - minMaskIdx.z + 7) / 8; + dparams.resourcesRW[0] = m_allocMask; + + ComputeContextDispatch(m_customContext, &dparams); +} + +void SceneCustomEmit::doEmitCustomEmit(NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* layeredParams, const CustomEmitParams* customParams) +{ + // for each layer + for (NvFlowUint layerIdx = 0u; layerIdx < layeredParams->numLayers; layerIdx++) + { + NvFlowGridEmitCustomEmitLayerParams paramsInst = {}; + NvFlowGridEmitCustomGetLayerParams(layeredParams, 0u, ¶msInst); + auto params = ¶msInst; + + updateResource(m_blockTable, params->blockTable, m_customContext, m_flowContext.m_renderContext); + updateResource(m_blockList, params->blockList, m_customContext, m_flowContext.m_renderContext); + updateResourceRW(m_dataRW[0u], params->dataRW[0u], m_customContext, m_flowContext.m_renderContext); + updateResourceRW(m_dataRW[1u], params->dataRW[1u], m_customContext, m_flowContext.m_renderContext); + + struct ShaderParams + { + NvFlowShaderPointParams customEmitParams; + + NvFlowUint4 minVidx; + NvFlowUint4 maxVidx; + NvFlowFloat4 targetValue; + NvFlowFloat4 blendRate; + }; + + const auto& gridDim = params->shaderParams.gridDim; + const auto& blockDim = params->shaderParams.blockDim; + + NvFlowUint4 vdim; + vdim.x = gridDim.x * blockDim.x; + vdim.y = gridDim.y * blockDim.y; + vdim.z = gridDim.z * blockDim.z; + vdim.w = 1u; + + const NvFlowUint radius = customParams->radius; + + NvFlowUint4 minVidx, maxVidx; + + minVidx.x = vdim.x / 2 - radius; + minVidx.y = vdim.y / 2 - radius; + minVidx.z = vdim.z / 2 - radius; + minVidx.w = 0u; + + maxVidx.x = vdim.x / 2 + radius + 1; + maxVidx.y = vdim.y / 2 + radius + 1; + maxVidx.z = vdim.z / 2 + radius + 1; + maxVidx.w = 0u; + + auto mapped = (ShaderParams*)ComputeConstantBufferMap(m_customContext, m_customConstantBuffer); + + mapped->customEmitParams = params->shaderParams; + + mapped->minVidx = minVidx; + mapped->maxVidx = maxVidx; + mapped->targetValue = customParams->targetValue; + mapped->blendRate = customParams->blendRate; + + ComputeConstantBufferUnmap(m_customContext, m_customConstantBuffer); + + if (m_fullDomain) + { + ComputeDispatchParams dparams = {}; + dparams.shader = m_customEmitEmit2CS; + dparams.constantBuffer = m_customConstantBuffer; + dparams.gridDim[0] = (params->numBlocks * params->shaderParams.blockDim.x + 7) / 8; + dparams.gridDim[1] = (params->shaderParams.blockDim.y + 7) / 8; + dparams.gridDim[2] = (params->shaderParams.blockDim.z + 7) / 8; + dparams.resources[0] = m_blockList; + dparams.resources[1] = m_blockTable; + + NvFlowUint localDataFrontIdx = *dataFrontIdx; + // single pass + { + dparams.resources[2] = ComputeResourceRWGetResource(m_dataRW[localDataFrontIdx]); + dparams.resourcesRW[0] = m_dataRW[localDataFrontIdx ^ 1u]; + ComputeContextDispatch(m_customContext, &dparams); + localDataFrontIdx = localDataFrontIdx ^ 1u; + } + } + else + { + ComputeDispatchParams dparams = {}; + dparams.shader = m_customEmitEmitCS; + dparams.constantBuffer = m_customConstantBuffer; + dparams.gridDim[0] = (maxVidx.x - minVidx.x + 7) / 8; + dparams.gridDim[1] = (maxVidx.y - minVidx.y + 7) / 8; + dparams.gridDim[2] = (maxVidx.z - minVidx.z + 7) / 8; + dparams.resources[0] = m_blockList; + dparams.resources[1] = m_blockTable; + + NvFlowUint localDataFrontIdx = *dataFrontIdx; + // doing this twice allow the write to be incomplete + for (int i = 0; i < 2; i++) + { + dparams.resources[2] = ComputeResourceRWGetResource(m_dataRW[localDataFrontIdx]); + dparams.resourcesRW[0] = m_dataRW[localDataFrontIdx ^ 1u]; + ComputeContextDispatch(m_customContext, &dparams); + localDataFrontIdx = localDataFrontIdx ^ 1u; + } + } + } + // dataFrontIdx must be uniform across layers + if (m_fullDomain) + { + (*dataFrontIdx) = (*dataFrontIdx) ^ 1u; + } + else + { + (*dataFrontIdx) = (*dataFrontIdx) ^ 1u; + (*dataFrontIdx) = (*dataFrontIdx) ^ 1u; + } +} + +void SceneCustomEmit::doEmitCustomEmitVelocityFunc(NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params) +{ + CustomEmitParams customParams = {}; + customParams.radius = 4u; + customParams.targetValue = { 0.f, 1.f, 0.f, 0.f }; + customParams.blendRate = { 0.01f, 0.01f, 0.01f, 0.01f }; + + doEmitCustomEmit(dataFrontIdx, params, &customParams); +} + +void SceneCustomEmit::doEmitCustomEmitDensityFunc(NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params) +{ + CustomEmitParams customParams = {}; + customParams.radius = 8u; + customParams.targetValue = { 1.f, 1.f, 0.f, 1.f }; + customParams.blendRate = { 0.01f, 0.01f, 0.01f, 0.01f }; + + doEmitCustomEmit(dataFrontIdx, params, &customParams); +} + +void SceneCustomEmit::emitCustomAllocFunc(void* userdata, const NvFlowGridEmitCustomAllocParams* params) +{ + ((SceneCustomEmit*)(userdata))->doEmitCustomAllocFunc(params); +} + +void SceneCustomEmit::emitCustomEmitVelocityFunc(void* userdata, NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params) +{ + ((SceneCustomEmit*)(userdata))->doEmitCustomEmitVelocityFunc(dataFrontIdx, params); +} + +void SceneCustomEmit::emitCustomEmitDensityFunc(void* userdata, NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params) +{ + ((SceneCustomEmit*)(userdata))->doEmitCustomEmitDensityFunc(dataFrontIdx, params); +} + +void SceneCustomEmit::preDraw() +{ + m_flowContext.preDrawBegin(); + + m_flowGridActor.preDraw(&m_flowContext); + + m_flowContext.preDrawEnd(); +} + +void SceneCustomEmit::imguiFluidEmitterExtra() +{ + if (imguiserCheck("Full Domain", m_fullDomain, true)) + { + m_fullDomain = !m_fullDomain; + } +} + +void SceneCustomEmit::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + m_projectile.draw(projection, view); + + m_flowContext.drawBegin(); + + m_flowGridActor.draw(&m_flowContext, projection, view); + + m_flowContext.drawEnd(); +} + +void SceneCustomEmit::release() +{ + // release app compute resources + { + ComputeConstantBufferRelease(m_customConstantBuffer); + + ComputeShaderRelease(m_customEmitAllocCS); + ComputeShaderRelease(m_customEmitEmitCS); + ComputeShaderRelease(m_customEmitEmit2CS); + + ComputeContextRelease(m_customContext); + + if (m_allocMask) ComputeResourceRWRelease(m_allocMask); + if (m_blockTable) ComputeResourceRelease(m_blockTable); + if (m_blockList) ComputeResourceRelease(m_blockList); + if (m_dataRW[0]) ComputeResourceRWRelease(m_dataRW[0u]); + if (m_dataRW[1]) ComputeResourceRWRelease(m_dataRW[1u]); + + m_allocMask = nullptr; + m_blockTable = nullptr; + m_blockList = nullptr; + m_dataRW[0] = nullptr; + m_dataRW[1] = nullptr; + } + + m_projectile.release(); + + m_flowGridActor.release(); + + m_flowContext.release(); +} + +void SceneCustomEmit::imgui(int xIn, int yIn, int wIn, int hIn) +{ + SceneFluid::imgui(xIn, yIn, wIn, hIn); + + if (m_shouldLoadPreset) + { + imguiserLoadC(PresetFlame::g_root, sizeof(PresetFlame::g_root)); + m_shouldLoadPreset = false; + } +}
\ No newline at end of file diff --git a/demo/DemoApp/sceneFlow.cpp b/demo/DemoApp/sceneFlow.cpp new file mode 100644 index 0000000..80f87b1 --- /dev/null +++ b/demo/DemoApp/sceneFlow.cpp @@ -0,0 +1,822 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include "scene.h" + +#include "imgui.h" +#include "imguiser.h" + +// ******************** FlowContext ************************ + +void FlowContext::init(AppGraphCtx* appctx) +{ + m_appctx = appctx; + + m_renderContext = NvFlowInteropCreateContext(appctx); + m_dsv = NvFlowInteropCreateDepthStencilView(appctx, m_renderContext); + m_rtv = NvFlowInteropCreateRenderTargetView(appctx, m_renderContext); + + // establishes m_gridContext + createComputeContext(); +} + +void FlowContext::createComputeContext() +{ + m_multiGPUSupported = NvFlowDedicatedDeviceAvailable(m_renderContext); + m_multiGPUActive = m_multiGPUSupported && m_enableMultiGPU; + if (m_multiGPUActive) + { + NvFlowDeviceDesc deviceDesc = {}; + NvFlowDeviceDescDefaults(&deviceDesc); + + deviceDesc.mode = eNvFlowDeviceModeProxy; + m_renderDevice = NvFlowCreateDevice(m_renderContext, &deviceDesc); + deviceDesc.mode = eNvFlowDeviceModeUnique; + m_gridDevice = NvFlowCreateDevice(m_renderContext, &deviceDesc); + + NvFlowDeviceQueueDesc deviceQueueDesc = {}; + deviceQueueDesc.queueType = eNvFlowDeviceQueueTypeGraphics; + deviceQueueDesc.lowLatency = false; + m_gridQueue = NvFlowCreateDeviceQueue(m_gridDevice, &deviceQueueDesc); + deviceQueueDesc.queueType = eNvFlowDeviceQueueTypeCopy; + m_gridCopyQueue = NvFlowCreateDeviceQueue(m_gridDevice, &deviceQueueDesc); + m_renderCopyQueue = NvFlowCreateDeviceQueue(m_renderDevice, &deviceQueueDesc); + + m_gridContext = NvFlowDeviceQueueCreateContext(m_gridQueue); + m_gridCopyContext = NvFlowDeviceQueueCreateContext(m_gridCopyQueue); + m_renderCopyContext = NvFlowDeviceQueueCreateContext(m_renderCopyQueue); + + NvFlowDeviceQueueStatus status = {}; + NvFlowDeviceQueueUpdateContext(m_gridQueue, m_gridContext, &status); + } + else + { + m_commandQueueSupported = NvFlowDedicatedDeviceQueueAvailable(m_renderContext); + m_commandQueueActive = m_commandQueueSupported && m_enableCommandQueue; + if (m_commandQueueActive) + { + NvFlowDeviceDesc deviceDesc = {}; + NvFlowDeviceDescDefaults(&deviceDesc); + + deviceDesc.mode = eNvFlowDeviceModeProxy; + m_renderDevice = NvFlowCreateDevice(m_renderContext, &deviceDesc); + m_gridDevice = m_renderDevice; + + NvFlowDeviceQueueDesc deviceQueueDesc = {}; + deviceQueueDesc.queueType = eNvFlowDeviceQueueTypeCompute; + deviceQueueDesc.lowLatency = true; + m_gridQueue = NvFlowCreateDeviceQueue(m_gridDevice, &deviceQueueDesc); + deviceQueueDesc.queueType = eNvFlowDeviceQueueTypeCopy; + m_gridCopyQueue = NvFlowCreateDeviceQueue(m_gridDevice, &deviceQueueDesc); + m_renderCopyQueue = m_gridCopyQueue; + + m_gridContext = NvFlowDeviceQueueCreateContext(m_gridQueue); + m_gridCopyContext = NvFlowDeviceQueueCreateContext(m_gridCopyQueue); + m_renderCopyContext = m_gridCopyContext; + + NvFlowDeviceQueueStatus status = {}; + NvFlowDeviceQueueUpdateContext(m_gridQueue, m_gridContext, &status); + } + else + { + m_gridContext = m_renderContext; + m_gridCopyContext = m_renderContext; + m_renderCopyContext = m_renderContext; + } + } +} + +void FlowContext::release() +{ + NvFlowReleaseRenderTargetView(m_rtv); + NvFlowReleaseDepthStencilView(m_dsv); + NvFlowReleaseContext(m_renderContext); + + releaseComputeContext(); +} + +void FlowContext::releaseComputeContext() +{ + if (m_gridDevice != m_renderDevice) + { + NvFlowReleaseContext(m_gridContext); + NvFlowReleaseContext(m_gridCopyContext); + NvFlowReleaseContext(m_renderCopyContext); + m_gridContext = nullptr; + m_gridCopyContext = nullptr; + m_renderCopyContext = nullptr; + + NvFlowReleaseDeviceQueue(m_gridQueue); + NvFlowReleaseDeviceQueue(m_gridCopyQueue); + NvFlowReleaseDeviceQueue(m_renderCopyQueue); + m_gridQueue = nullptr; + m_gridCopyQueue = nullptr; + m_renderCopyQueue = nullptr; + + NvFlowReleaseDevice(m_gridDevice); + NvFlowReleaseDevice(m_renderDevice); + m_gridDevice = nullptr; + m_renderDevice = nullptr; + } + else if (m_gridContext != m_renderContext) + { + NvFlowReleaseContext(m_gridContext); + NvFlowReleaseContext(m_gridCopyContext); + m_gridContext = nullptr; + m_gridCopyContext = nullptr; + m_renderCopyContext = nullptr; + + NvFlowReleaseDeviceQueue(m_gridQueue); + NvFlowReleaseDeviceQueue(m_gridCopyQueue); + m_gridQueue = nullptr; + m_gridCopyQueue = nullptr; + m_renderCopyQueue = nullptr; + + NvFlowReleaseDevice(m_gridDevice); + m_gridDevice = nullptr; + m_renderDevice = nullptr; + } + else + { + m_gridContext = nullptr; + m_gridCopyContext = nullptr; + m_renderCopyContext = nullptr; + + m_gridQueue = nullptr; + m_gridCopyQueue = nullptr; + m_renderCopyQueue = nullptr; + + m_gridDevice = nullptr; + m_renderDevice = nullptr; + } +} + +int FlowContext::computeContextBegin() +{ + int framesInFlight = 0u; + if (m_gridDevice != m_renderDevice) + { + NvFlowDeviceQueueStatus status = {}; + NvFlowDeviceQueueUpdateContext(m_gridQueue, m_gridContext, &status); + framesInFlight = status.framesInFlight; + + NvFlowDeviceQueueUpdateContext(m_gridCopyQueue, m_gridCopyContext, &status); + NvFlowDeviceQueueUpdateContext(m_renderCopyQueue, m_renderCopyContext, &status); + } + else if (m_gridContext != m_renderContext) + { + NvFlowDeviceQueueStatus status = {}; + NvFlowDeviceQueueUpdateContext(m_gridQueue, m_gridContext, &status); + framesInFlight = status.framesInFlight; + + NvFlowDeviceQueueUpdateContext(m_gridCopyQueue, m_gridCopyContext, &status); + } + else + { + NvFlowInteropUpdateContext(m_renderContext, m_appctx); + NvFlowContextPush(m_gridContext); + } + return framesInFlight; +} + +void FlowContext::computeContextEnd() +{ + if (m_gridDevice != m_renderDevice) + { + NvFlowDeviceQueueConditionalFlush(m_gridQueue, m_gridContext); + NvFlowDeviceQueueConditionalFlush(m_gridCopyQueue, m_gridCopyContext); + NvFlowDeviceQueueConditionalFlush(m_renderCopyQueue, m_renderCopyContext); + } + else if (m_gridContext != m_renderContext) + { + NvFlowDeviceQueueConditionalFlush(m_gridQueue, m_gridContext); + NvFlowDeviceQueueConditionalFlush(m_gridCopyQueue, m_gridCopyContext); + } + else + { + NvFlowContextPop(m_gridContext); + } +} + +bool FlowContext::updateBegin() +{ + m_framesInFlight = computeContextBegin(); + bool shouldFlush = (m_framesInFlight < m_maxFramesInFlight); + + if (shouldFlush) + { + NvFlowContextFlushRequestPush(m_gridContext); + NvFlowContextFlushRequestPush(m_gridCopyContext); + NvFlowContextFlushRequestPush(m_renderCopyContext); + } + + return shouldFlush; +} + +void FlowContext::updateEnd() +{ + computeContextEnd(); +} + +void FlowContext::preDrawBegin() +{ + if (m_gridDevice != m_renderDevice) + { + // update fence status on grid queue, no need to flush + NvFlowDeviceQueueStatus status = {}; + NvFlowDeviceQueueUpdateContext(m_gridQueue, m_gridContext, &status); + NvFlowDeviceQueueUpdateContext(m_gridCopyQueue, m_gridCopyContext, &status); + NvFlowDeviceQueueUpdateContext(m_renderCopyQueue, m_renderCopyContext, &status); + } + else if (m_gridContext != m_renderContext) + { + // update fence status on grid queue, no need to flush + NvFlowDeviceQueueStatus status = {}; + NvFlowDeviceQueueUpdateContext(m_gridQueue, m_gridContext, &status); + NvFlowDeviceQueueUpdateContext(m_gridCopyQueue, m_gridCopyContext, &status); + } + + NvFlowInteropUpdateContext(m_renderContext, m_appctx); + NvFlowContextPush(m_renderContext); +} + +void FlowContext::preDrawEnd() +{ + NvFlowContextPop(m_renderContext); + + // This will make gridProxy flush work + if (m_gridDevice != m_renderDevice) + { + //NvFlowDeviceQueueFlush(m_gridQueue, m_gridContext); + NvFlowDeviceQueueConditionalFlush(m_gridCopyQueue, m_gridCopyContext); + NvFlowDeviceQueueConditionalFlush(m_renderCopyQueue, m_renderCopyContext); + } + else if (m_gridContext != m_renderContext) + { + //NvFlowDeviceQueueFlush(m_gridQueue, m_gridContext); + NvFlowDeviceQueueConditionalFlush(m_gridCopyQueue, m_gridCopyContext); + } +} + +void FlowContext::drawBegin() +{ + NvFlowInteropUpdateContext(m_renderContext, m_appctx); + NvFlowInteropUpdateDepthStencilView(m_dsv, m_appctx, m_renderContext); + NvFlowInteropUpdateRenderTargetView(m_rtv, m_appctx, m_renderContext); + NvFlowContextPush(m_renderContext); +} + +void FlowContext::drawEnd() +{ + NvFlowContextPop(m_renderContext); +} + +// ******************* FlowGridActor ************************* + +void FlowGridActor::initParams(size_t vramAmount) +{ + NvFlowGridDescDefaults(&m_gridDesc); + NvFlowGridParamsDefaults(&m_gridParams); + NvFlowGridMaterialParamsDefaults(&m_materialParams); + NvFlowRenderMaterialParamsDefaults(&m_renderMaterialDefaultParams); + NvFlowRenderMaterialParamsDefaults(&m_renderMaterialMat0Params); + NvFlowRenderMaterialParamsDefaults(&m_renderMaterialMat1Params); + NvFlowVolumeRenderParamsDefaults(&m_renderParams); + NvFlowCrossSectionParamsDefaults(&m_crossSectionParams); + + m_renderMaterialMat0Params.material = NvFlowGridMaterialHandle{ nullptr, 1u }; + m_renderMaterialMat1Params.material = NvFlowGridMaterialHandle{ nullptr, 1u }; + + // default VTR off on debug build + #ifdef _DEBUG + m_gridDesc.enableVTR = false; + #endif + + // attempt to pick good memory limits based on vramAmount + { + if (vramAmount <= 2ull * 1024ull * 1024ull * 1024ull) + { + m_memoryLimit = 1.f; + } + else if (vramAmount <= 3ull * 1024ull * 1024ull * 1024ull) + { + m_memoryLimit = 2.f; + } + } + + m_gridDesc.residentScale = m_memoryLimit * m_memoryScale; + + // configure gravity + m_gridParams.gravity = NvFlowFloat3{ 0.f, -1.f, 0.f }; +} + +void FlowGridActor::init(FlowContext* flowContext, AppGraphCtx* appctx) +{ + m_appctx = appctx; + + // create compute resources + m_grid = NvFlowCreateGrid(flowContext->m_gridContext, &m_gridDesc); + + auto proxyGridExport = NvFlowGridGetGridExport(flowContext->m_gridContext, m_grid); + + NvFlowGridProxyDesc proxyDesc = {}; + proxyDesc.gridContext = flowContext->m_gridContext; + proxyDesc.renderContext = flowContext->m_renderContext; + proxyDesc.gridCopyContext = flowContext->m_gridCopyContext; + proxyDesc.renderCopyContext = flowContext->m_renderCopyContext; + proxyDesc.gridExport = proxyGridExport; + proxyDesc.proxyType = eNvFlowGridProxyTypePassThrough; + if (flowContext->m_multiGPUActive) + { + proxyDesc.proxyType = eNvFlowGridProxyTypeMultiGPU; + } + else if (flowContext->m_commandQueueActive) + { + proxyDesc.proxyType = eNvFlowGridProxyTypeInterQueue; + } + + m_gridProxy = NvFlowCreateGridProxy(&proxyDesc); + + auto gridExport = NvFlowGridProxyGetGridExport(m_gridProxy, flowContext->m_renderContext); + + // create render resources + NvFlowVolumeRenderDesc volumeRenderDesc; + volumeRenderDesc.gridExport = gridExport; + + m_volumeRender = NvFlowCreateVolumeRender(flowContext->m_renderContext, &volumeRenderDesc); + + NvFlowCrossSectionDesc crossSectionDesc = {}; + crossSectionDesc.gridExport = gridExport; + + m_crossSection = NvFlowCreateCrossSection(flowContext->m_renderContext, &crossSectionDesc); + + NvFlowRenderMaterialPoolDesc materialPoolDesc = {}; + materialPoolDesc.colorMapResolution = 64u; + m_colorMap.m_materialPool = NvFlowCreateRenderMaterialPool(flowContext->m_renderContext, &materialPoolDesc); + + NvFlowRenderMaterialParams materialParams = {}; + NvFlowRenderMaterialParamsDefaults(&materialParams); + m_colorMap.m_materialDefault = NvFlowGetDefaultRenderMaterial(m_colorMap.m_materialPool); + + // set invalid by default for mat0 and mat1 + materialParams.material = NvFlowGridMaterialHandle{ nullptr, 1u }; + m_colorMap.m_material0 = NvFlowCreateRenderMaterial(flowContext->m_renderContext, m_colorMap.m_materialPool, &materialParams); + m_colorMap.m_material1 = NvFlowCreateRenderMaterial(flowContext->m_renderContext, m_colorMap.m_materialPool, &materialParams); + + m_renderParams.materialPool = m_colorMap.m_materialPool; + + if (m_enableVolumeShadow) + { + NvFlowVolumeShadowDesc volumeShadowDesc = {}; + volumeShadowDesc.gridExport = gridExport; + volumeShadowDesc.mapWidth = 4 * 256u; + volumeShadowDesc.mapHeight = 4 * 256u; + volumeShadowDesc.mapDepth = 4 * 256u; + + volumeShadowDesc.minResidentScale = 0.25f * (1.f / 64.f); + volumeShadowDesc.maxResidentScale = m_shadowResidentScale * 4.f * 0.25f * (1.f / 64.f); + + m_volumeShadow = NvFlowCreateVolumeShadow(flowContext->m_renderContext, &volumeShadowDesc); + } +} + +void FlowGridActor::release() +{ + NvFlowReleaseGrid(m_grid); + NvFlowReleaseGridProxy(m_gridProxy); + NvFlowReleaseVolumeRender(m_volumeRender); + NvFlowReleaseCrossSection(m_crossSection); + NvFlowReleaseRenderMaterialPool(m_colorMap.m_materialPool); + if (m_volumeShadow) NvFlowReleaseVolumeShadow(m_volumeShadow); + m_volumeShadow = nullptr; +} + +void FlowGridActor::updatePreEmit(FlowContext* flowContext, float dt) +{ + NvFlowGridSetParams(m_grid, &m_gridParams); + NvFlowGridSetMaterialParams(m_grid, NvFlowGridGetDefaultMaterial(m_grid), &m_materialParams); + NvFlowRenderMaterialUpdate(m_colorMap.m_materialDefault, &m_renderMaterialDefaultParams); + NvFlowRenderMaterialUpdate(m_colorMap.m_material0, &m_renderMaterialMat0Params); + NvFlowRenderMaterialUpdate(m_colorMap.m_material1, &m_renderMaterialMat1Params); +} + +void FlowGridActor::updatePostEmit(FlowContext* flowContext, float dt, bool shouldUpdate, bool shouldReset) +{ + if (shouldReset) + { + NvFlowGridResetDesc resetDesc = {}; + NvFlowGridResetDescDefaults(&resetDesc); + + resetDesc.initialLocation = m_gridDesc.initialLocation; + resetDesc.halfSize = m_gridDesc.halfSize; + + float scale = powf(1.26f, float(m_cellSizeLogScale)) * m_cellSizeScale; + resetDesc.halfSize.x *= scale; + resetDesc.halfSize.y *= scale; + resetDesc.halfSize.z *= scale; + + NvFlowGridReset(m_grid, &resetDesc); + } + + if (shouldUpdate) + { + NvFlowGridUpdate(m_grid, flowContext->m_gridContext, dt); + + // collect stats + if (m_grid) + { + auto gridExport = NvFlowGridGetGridExport(flowContext->m_gridContext, m_grid); + + // grab for debug vis use + if (flowContext->m_gridContext == flowContext->m_renderContext) + { + m_gridExportDebugVis = gridExport; + } + else + { + m_gridExportDebugVis = nullptr; + } + + if (gridExport) + { + NvFlowUint* numBlockss[2] = { &m_statNumVelocityBlocks , &m_statNumDensityBlocks }; + NvFlowUint* numCellss[2] = { &m_statNumVelocityCells , &m_statNumDensityCells }; + NvFlowUint* maxBlockss[2] = { &m_statMaxVelocityBlocks , &m_statMaxDensityBlocks }; + NvFlowGridTextureChannel channels[2] = { eNvFlowGridTextureChannelVelocity, eNvFlowGridTextureChannelDensity }; + for (NvFlowUint passID = 0u; passID < 2; passID++) + { + NvFlowUint& numBlocks = *numBlockss[passID]; + NvFlowUint& numCells = *numCellss[passID]; + NvFlowUint& maxBlocks = *maxBlockss[passID]; + + auto handle = NvFlowGridExportGetHandle(gridExport, flowContext->m_gridContext, channels[passID]); + + NvFlowGridExportLayeredView layeredView = {}; + NvFlowGridExportGetLayeredView(handle, &layeredView); + + m_statNumLayers = handle.numLayerViews; + numBlocks = 0u; + maxBlocks = layeredView.mapping.maxBlocks; + + for (NvFlowUint layerIdx = 0u; layerIdx < handle.numLayerViews; layerIdx++) + { + NvFlowGridExportLayerView layerView = {}; + NvFlowGridExportGetLayerView(handle, layerIdx, &layerView); + + numBlocks += layerView.mapping.numBlocks; + } + + numCells = layeredView.mapping.shaderParams.blockDim.w * numBlocks; + } + } + } + + if (m_enableVolumeShadow && m_volumeShadow) + { + NvFlowVolumeShadowStats stats = {}; + NvFlowVolumeShadowGetStats(m_volumeShadow, &stats); + m_statVolumeShadowBlocks = stats.shadowBlocksActive; + m_statVolumeShadowCells = stats.shadowCellsActive; + } + else + { + m_statVolumeShadowBlocks = 0u; + m_statVolumeShadowCells = 0u; + } + + auto gridExport = NvFlowGridGetGridExport(flowContext->m_gridContext, m_grid); + NvFlowGridProxyFlushParams flushParams = {}; + flushParams.gridContext = flowContext->m_gridContext; + flushParams.gridCopyContext = flowContext->m_gridCopyContext; + flushParams.renderCopyContext = flowContext->m_renderCopyContext; + NvFlowGridProxyPush(m_gridProxy, gridExport, &flushParams); + } +} + +void FlowGridActor::preDraw(FlowContext* flowContext) +{ + //auto gridView = NvFlowGridGetGridView(m_grid, m_renderContext); + + AppGraphCtxProfileBegin(m_appctx, "UpdateGridView"); + + NvFlowGridProxyFlushParams flushParams = {}; + flushParams.gridContext = flowContext->m_gridContext; + flushParams.gridCopyContext = flowContext->m_gridCopyContext; + flushParams.renderCopyContext = flowContext->m_renderCopyContext; + NvFlowGridProxyFlush(m_gridProxy, &flushParams); + + auto gridExport = NvFlowGridProxyGetGridExport(m_gridProxy, flowContext->m_renderContext); + + AppGraphCtxProfileEnd(m_appctx, "UpdateGridView"); + + // replicate render params for override + m_renderParamsOverride = m_renderParams; + + // shadow force apply + if (m_enableVolumeShadow && m_forceApplyShadow && !m_shadowWasForceApplied) + { + m_shadowWasForceApplied = true; + m_forceIntensityCompMask = m_renderMaterialDefaultParams.intensityCompMask; + m_forceIntensityBias = m_renderMaterialDefaultParams.intensityBias; + m_renderMaterialDefaultParams.intensityCompMask = { 0.f, 0.f, 1.f, 0.f }; + m_renderMaterialDefaultParams.intensityBias = 0.f; + } + if ((!m_enableVolumeShadow || !m_forceApplyShadow) && m_shadowWasForceApplied) + { + m_renderMaterialDefaultParams.intensityCompMask = m_forceIntensityCompMask; + m_renderMaterialDefaultParams.intensityBias = m_forceIntensityBias; + m_shadowWasForceApplied = false; + } + + // volume shadow + if (m_enableVolumeShadow) + { + AppGraphCtxProfileBegin(m_appctx, "VolumeShadows"); + + NvFlowVolumeShadowParams shadowParams = {}; + + const float halfSize = 2.f * (0.5f * (7.5f - 5.f)); + const float center = 0.5f * (7.5f + 5.f); + + DirectX::XMMATRIX projMat = DirectX::XMMatrixPerspectiveFovLH(DirectX::XM_PI / 4.f, 1.f, center - halfSize, center + halfSize); + DirectX::XMMATRIX viewMat = DirectX::XMMatrixMultiply( + DirectX::XMMatrixMultiply( + DirectX::XMMatrixScaling(0.25f, 0.25f, 0.25f), + DirectX::XMMatrixMultiply( + DirectX::XMMatrixRotationRollPitchYaw(0.f, DirectX::XM_PI / 4.f * m_shadowPan, 0.f), + DirectX::XMMatrixMultiply( + DirectX::XMMatrixRotationRollPitchYaw(-DirectX::XM_PI / 4.f, 0.f, 0.f), + DirectX::XMMatrixMultiply( + DirectX::XMMatrixRotationRollPitchYaw(0.f, DirectX::XM_PI / 4.f, 0.f), + DirectX::XMMatrixRotationAxis(DirectX::XMVectorSet(1.f, 1.f, 0.f, 1.f), -DirectX::XM_PI / 4.f * m_shadowTilt) + ) + ) + ) + ), + DirectX::XMMatrixTranslation(0.f, 0.f, 7.f) + ); + + memcpy(&shadowParams.projectionMatrix, &projMat, sizeof(NvFlowFloat4x4)); + memcpy(&shadowParams.viewMatrix, &viewMat, sizeof(NvFlowFloat4x4)); + + shadowParams.materialPool = m_renderParams.materialPool; + shadowParams.intensityScale = m_shadowIntensityScale; + shadowParams.minIntensity = m_shadowMinIntensity; + shadowParams.shadowBlendCompMask = m_shadowBlendCompMask; + shadowParams.shadowBlendBias = m_shadowBlendBias; + + shadowParams.renderChannel = m_renderParams.renderChannel; + shadowParams.renderMode = eNvFlowVolumeRenderMode_colormap; + + NvFlowVolumeShadowUpdate(m_volumeShadow, flowContext->m_renderContext, gridExport, &shadowParams); + + gridExport = NvFlowVolumeShadowGetGridExport(m_volumeShadow, flowContext->m_renderContext); + + AppGraphCtxProfileEnd(m_appctx, "VolumeShadows"); + } + + if (m_separateLighting) + { + AppGraphCtxProfileBegin(m_appctx, "Lighting"); + + NvFlowVolumeLightingParams lightingParams = {}; + lightingParams.materialPool = m_renderParams.materialPool; + lightingParams.renderChannel = m_renderParams.renderChannel; + lightingParams.renderMode = m_renderParams.renderMode; + + m_renderParamsOverride.renderMode = eNvFlowVolumeRenderMode_raw; + + gridExport = NvFlowVolumeRenderLightGridExport(m_volumeRender, flowContext->m_renderContext, gridExport, &lightingParams); + + AppGraphCtxProfileEnd(m_appctx, "Lighting"); + } + + m_gridExportOverride = gridExport; +} + +void FlowGridActor::draw(FlowContext* flowContext, DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + memcpy(&m_renderParamsOverride.projectionMatrix, &projection, sizeof(m_renderParamsOverride.projectionMatrix)); + memcpy(&m_renderParamsOverride.viewMatrix, &view, sizeof(m_renderParamsOverride.viewMatrix)); + m_renderParamsOverride.depthStencilView = flowContext->m_dsv; + m_renderParamsOverride.renderTargetView = flowContext->m_rtv; + + AppGraphCtxProfileBegin(m_appctx, "Render"); + + if (m_renderParams.generateDepth) + { + // ray march with target to composite against + { + auto renderParamsCopy = m_renderParamsOverride; + + // invalidate renderTargetView since it is not required here + renderParamsCopy.renderTargetView = nullptr; + + renderParamsCopy.preColorCompositeOnly = true; + renderParamsCopy.colorCompositeOnly = false; + + NvFlowVolumeRenderGridExport(m_volumeRender, flowContext->m_renderContext, m_gridExportOverride, &renderParamsCopy); + } + // composite to target + { + auto renderParamsCopy = m_renderParamsOverride; + + renderParamsCopy.preColorCompositeOnly = false; + renderParamsCopy.colorCompositeOnly = true; + + NvFlowVolumeRenderGridExport(m_volumeRender, flowContext->m_renderContext, m_gridExportOverride, &renderParamsCopy); + } + } + else + { + NvFlowVolumeRenderGridExport(m_volumeRender, flowContext->m_renderContext, m_gridExportOverride, &m_renderParamsOverride); + } + + AppGraphCtxProfileEnd(m_appctx, "Render"); + + if (m_enableCrossSection) + { + AppGraphCtxProfileBegin(m_appctx, "CrossSection"); + + if (flowContext->m_gridContext != flowContext->m_renderContext) + { + m_gridExportDebugVis = nullptr; + } + + m_crossSectionParams.gridExport = m_gridExportOverride; + m_crossSectionParams.gridExportDebugVis = m_gridExportDebugVis; + + // update parameters + memcpy(&m_crossSectionParams.projectionMatrix, &projection, sizeof(m_crossSectionParams.projectionMatrix)); + memcpy(&m_crossSectionParams.viewMatrix, &view, sizeof(m_crossSectionParams.viewMatrix)); + m_crossSectionParams.depthStencilView = flowContext->m_dsv; + m_crossSectionParams.renderTargetView = flowContext->m_rtv; + + float scale = powf(1.26f, float(m_cellSizeLogScale)) * m_cellSizeScale; + m_crossSectionParams.crossSectionScale = scale * m_crossSectionScale; + + int backgroundID = int(m_crossSectionBackgroundColor); + m_crossSectionParams.backgroundColor = { 0.f, 0.f, 0.f, 1.f }; + if (backgroundID == 1) m_crossSectionParams.backgroundColor = { 0.33f, 0.33f, 0.33f, 1.f }; + + m_crossSectionParams.lineColor = { m_crossSectionLineColor.x, m_crossSectionLineColor.y, m_crossSectionLineColor.z, 1.f }; + + m_crossSectionParams.materialPool = m_renderParams.materialPool; + + NvFlowCrossSectionRender(m_crossSection, flowContext->m_renderContext, &m_crossSectionParams); + + AppGraphCtxProfileEnd(m_appctx, "CrossSection"); + } + + if (m_enableVolumeShadow && m_shadowDebugVis) + { + NvFlowVolumeShadowDebugRenderParams params = {}; + + params.renderTargetView = flowContext->m_rtv; + + memcpy(¶ms.projectionMatrix, &projection, sizeof(NvFlowFloat4x4)); + memcpy(¶ms.viewMatrix, &view, sizeof(NvFlowFloat4x4)); + + NvFlowVolumeShadowDebugRender(m_volumeShadow, flowContext->m_renderContext, ¶ms); + } +} + +// *********************** Flow Color Map ***************************************** + +void FlowColorMap::updateColorMap(NvFlowContext* context) +{ + NvFlowRenderMaterialHandle materials[3u] = { m_materialDefault, m_material0, m_material1 }; + std::vector<CurvePoint>* curves[3u] = {&m_curvePointsDefault, &m_curvePointsMat0, &m_curvePointsMat1 }; + for (NvFlowUint matIdx = 0u; matIdx < 3u; matIdx++) + { + auto& curve = *curves[matIdx]; + auto mapped = NvFlowRenderMaterialColorMap(context, materials[matIdx]); + if (mapped.data) + { + pointsToImage(mapped.data, mapped.dim, &curve[0], (unsigned int)curve.size()); + + NvFlowRenderMaterialColorUnmap(context, materials[matIdx]); + } + } +} + +void FlowColorMap::imguiUpdate(Scene* scene, NvFlowContext* context, int border, int x, int y, int w, int h) +{ + bool actives[3u] = { m_curveEditorActiveDefault, m_curveEditorActiveMat0, m_curveEditorActiveMat1 }; + CurveEditState* editStates[3u] = { &m_editStateDefault, &m_editStateMat0 , &m_editStateMat1 }; + std::vector<CurvePoint>* curves[3u] = { &m_curvePointsDefault, &m_curvePointsMat0, &m_curvePointsMat1 }; + + for (NvFlowUint matIdx = 0u; matIdx < 3u; matIdx++) + { + auto& editState = *editStates[matIdx]; + auto& curve = *curves[matIdx]; + + if (actives[matIdx]) + { + // curve editor + { + CurveEditParams params; + params.mouseState.x = scene->m_mx; + params.mouseState.y = scene->m_my; + params.mouseState.but = scene->m_mbut; + params.editorBounds.x = x + w + border; + params.editorBounds.y = y; + params.editorBounds.w = scene->m_winw - w - 3 * border; + params.editorBounds.h = m_curveEditorHeight - border; + params.rangeMin = { 0.f, 0.f, 0.f, 0.f, 0.f }; + params.rangeMax = { 1.f, 1.5f, 1.5f, 1.5f, 1.f }; + params.points = &curve[0]; + params.numPoints = (unsigned int)curve.size(); + + if (curveEditor(&editState, ¶ms)) + { + if (editState.action == CURVE_POINT_MODIFY) + { + curve[editState.activePointIndex] = editState.point; + } + if (editState.action == CURVE_POINT_INSERT) + { + curve.insert(curve.begin() + editState.activePointIndex, editState.point); + } + if (editState.action == CURVE_POINT_REMOVE) + { + curve.erase(curve.begin() + editState.activePointIndex); + } + + updateColorMap(context); + } + } + + break; + } + } + + if (imguiserOffscreenUpdate()) + { + const char* groupNames[3u] = {"colormap", "colormapMat0", "colormapMat1"}; + for (NvFlowUint matIdx = 0u; matIdx < 3u; matIdx++) + { + auto& curve = *curves[matIdx]; + + int oldNumItems = (int)curve.size(); + int numItems = 5 * oldNumItems; + imguiserBeginGroup(groupNames[matIdx], &numItems); + numItems /= 5; + if (oldNumItems != numItems) + { + curve.resize(numItems); + } + + for (size_t i = 0; i < curve.size(); i++) + { + auto& pt = curve[i]; + + imguiserValue1f(nullptr, &pt.x); + imguiserValue1f(nullptr, &pt.r); + imguiserValue1f(nullptr, &pt.g); + imguiserValue1f(nullptr, &pt.b); + imguiserValue1f(nullptr, &pt.a); + } + + imguiserEndGroup(); + } + + updateColorMap(context); + } +} + +bool FlowColorMap::colorMapActive(int mx, int my, unsigned char mbut) +{ + bool editorActive = m_curveEditorActiveDefault || m_curveEditorActiveMat0 || m_curveEditorActiveMat1; + return (editorActive && my < (int)m_curveEditorHeight); +} + +void FlowColorMap::initColorMap(NvFlowContext* context, const CurvePoint* pts, int numPoints, bool ptsEnabled) +{ + if (ptsEnabled) + { + m_curvePointsDefault.reserve(numPoints); + m_curvePointsMat0.reserve(numPoints); + m_curvePointsMat1.reserve(numPoints); + + m_curvePointsDefault.clear(); + m_curvePointsMat0.clear(); + m_curvePointsMat1.clear(); + + for (int i = 0; i < numPoints; i++) + { + m_curvePointsDefault.push_back(pts[i]); + m_curvePointsMat0.push_back(pts[i]); + m_curvePointsMat1.push_back(pts[i]); + } + } + + updateColorMap(context); +}
\ No newline at end of file diff --git a/demo/DemoApp/sceneSDF.cpp b/demo/DemoApp/sceneSDF.cpp new file mode 100644 index 0000000..301e260 --- /dev/null +++ b/demo/DemoApp/sceneSDF.cpp @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <stdio.h> +#include <string.h> + +#include "loader.h" +#include "imgui.h" +#include "imguiser.h" + +namespace Preset0 +{ +#include "preset0.h" +} +namespace Preset1 +{ +#include "preset1.h" +} + +#include "scene.h" + +#include <SDL.h> + +void SceneSDFTest::initParams() +{ + m_flowGridActor.initParams(AppGraphCtxDedicatedVideoMemory(m_appctx)); + + // set emitter defaults + NvFlowGridEmitParamsDefaults(&m_emitParams); + + m_emitParams.bounds.x.x = 1.5f; + m_emitParams.bounds.y.y = 1.5f; + m_emitParams.bounds.z.z = 1.5f; + m_emitParams.velocityLinear.y = -8.f; + m_emitParams.fuel = 1.4f; + m_emitParams.smoke = 0.5f; + + // grid parameter overrides + m_flowGridActor.m_separateLighting = false; // disable separate lighting, lower quality due to nonlinear colormap + + m_flowGridActor.m_gridDesc.halfSize.x = 16.f; + m_flowGridActor.m_gridDesc.halfSize.y = 16.f; + m_flowGridActor.m_gridDesc.halfSize.z = 16.f; + + m_flowGridActor.m_materialParams.smoke.damping = 0.25f; + m_flowGridActor.m_materialParams.smoke.fade = 0.25f; + m_flowGridActor.m_renderMaterialDefaultParams.alphaScale = 0.2f; + + m_flowGridActor.m_gridParams.gravity = NvFlowFloat3{ 0.f, -0.5f, 0.f }; + + m_shouldLoadPreset = true; +} + +void SceneSDFTest::init(AppGraphCtx* appctx, int winw, int winh) +{ + using namespace DirectX; + + m_appctx = appctx; + + if (!m_shouldReset || m_isFirstRun) + { + initParams(); + m_isFirstRun = false; + } + + m_flowContext.init(appctx); + + m_flowGridActor.init(&m_flowContext, appctx); + + NvFlowSDFGenDesc sdfDesc; + sdfDesc.resolution = { 128u, 128u, 128u }; + + m_sdfGen = NvFlowCreateSDFGen(m_flowContext.m_gridContext, &sdfDesc); + + m_meshContext = MeshInteropContextCreate(appctx); + m_mesh = MeshCreate(m_meshContext); + + MeshLoadFromFile(m_mesh, "../../data/bunny.ply"); + + MeshData meshData; + MeshGetData(m_mesh, &meshData); + + NvFlowSDFGenReset(m_sdfGen, m_flowContext.m_gridContext); + + XMMATRIX modelMatrix = XMMatrixMultiply( + XMMatrixScaling(8.f, 8.f, 8.f), + XMMatrixTranslation(0.f, -0.75f, 0.f) + ); + + NvFlowSDFGenMeshParams meshParams; + meshParams.numVertices = meshData.numVertices; + meshParams.positions = meshData.positions; + meshParams.positionStride = meshData.positionStride; + meshParams.normals = meshData.normals; + meshParams.normalStride = meshData.normalStride; + meshParams.numIndices = meshData.numIndices; + meshParams.indices = meshData.indices; + XMStoreFloat4x4((XMFLOAT4X4*)&meshParams.modelMatrix, modelMatrix); + meshParams.renderTargetView = m_flowContext.m_multiGPUActive ? nullptr : m_flowContext.m_rtv; + meshParams.depthStencilView = m_flowContext.m_multiGPUActive ? nullptr : m_flowContext.m_dsv; + + NvFlowSDFGenVoxelize(m_sdfGen, m_flowContext.m_gridContext, &meshParams); + + NvFlowSDFGenUpdate(m_sdfGen, m_flowContext.m_gridContext); + + // create shape from SDF + m_shape = NvFlowCreateShapeSDFFromTexture3D( + m_flowContext.m_gridContext, + NvFlowSDFGenShape(m_sdfGen, m_flowContext.m_gridContext) + ); + + // create default color map + { + const int numPoints = 5; + const CurvePoint pts[numPoints] = { + {0.f,0.f,0.f,0.f,0.f}, + {0.05f,0.2f,0.2f,0.2f,0.25f}, + {0.6f,0.35f * 141.f / 255.f, 0.1f * 199.f / 255.f, 0.7f * 63.f / 255.f,0.8f}, + {0.85f,0.75f * 141.f / 255.f, 0.15f * 199.f / 255.f, 1.f * 63.f / 255.f,0.8f}, + {1.f,1.25f * 141.f / 255.f, 0.2f * 199.f / 255.f, 3.f * 63.f / 255.f,0.5f} + }; + + auto& colorMap = m_flowGridActor.m_colorMap; + colorMap.initColorMap(m_flowContext.m_renderContext, pts, numPoints, (colorMap.m_curvePointsDefault.size() == 0)); + } + + m_projectile.init(m_appctx, m_flowContext.m_gridContext); + + resize(winw, winh); +} + +void SceneSDFTest::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + { + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + NvFlowShapeDesc shapeDesc; + shapeDesc.sdf.sdfOffset = 0u; // m_shape; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeSDF; + m_emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &m_emitParams, 1u); + + NvFlowShapeSDF* sdfs[] = { m_shape }; + NvFlowGridUpdateEmitSDFs(m_flowGridActor.m_grid, sdfs, 1u); + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + } + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +void SceneSDFTest::preDraw() +{ + m_flowContext.preDrawBegin(); + + m_flowGridActor.preDraw(&m_flowContext); + + m_flowContext.preDrawEnd(); +} + +void SceneSDFTest::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + m_projectile.draw(projection, view); + + //MeshInteropContextUpdate(m_meshContext, m_appctx); + + //MeshDrawParams meshDrawParams; + //meshDrawParams.renderMode = MESH_RENDER_SOLID; + //meshDrawParams.projection = projection; + //meshDrawParams.view = view; + //meshDrawParams.model = DirectX::XMMatrixMultiply( + // DirectX::XMMatrixScaling(0.25f, 0.25f, 0.25f), + // DirectX::XMMatrixTranslation(0.f, 0.0f, 0.f) + // ); + + //MeshDraw(m_mesh, &meshDrawParams); + + m_flowContext.drawBegin(); + +#if 0 + memcpy(&m_renderParams.projectionMatrix, &projection, sizeof(m_renderParams.projectionMatrix)); + memcpy(&m_renderParams.viewMatrix, &view, sizeof(m_renderParams.viewMatrix)); + m_renderParams.modelMatrix = { + 1.5f, 0.f, 0.f, 0.f, + 0.f, 1.5f, 0.f, 0.f, + 0.f, 0.f, 1.5f, 0.f, + 0.f, 0.f, 0.f, 1.f + }; + + m_renderParams.depthStencilView = m_dsv; + m_renderParams.renderTargetView = m_rtv; + + auto texture = NvFlowSDFGenShape(m_sdfGen, m_context); + + NvFlowVolumeRenderTexture3D(m_volumeRender, m_context, texture, &m_renderParams); +#endif + + m_flowGridActor.draw(&m_flowContext, projection, view); + + m_flowContext.drawEnd(); +} + +void SceneSDFTest::release() +{ + m_projectile.release(); + + m_flowGridActor.release(); + + NvFlowReleaseShapeSDF(m_shape); + + NvFlowReleaseSDFGen(m_sdfGen); + + m_flowContext.release(); + + MeshRelease(m_mesh); + MeshContextRelease(m_meshContext); +} + +void SceneSDFTest::imgui(int xIn, int yIn, int wIn, int hIn) +{ + SceneFluid::imgui(xIn, yIn, wIn, hIn); + + if (m_shouldLoadPreset) + { + imguiserLoadC(Preset0::g_root, sizeof(Preset0::g_root)); + m_shouldLoadPreset = false; + } +} + +// ************************** Scene Custom Lighting ****************************** + +#include "computeContext.h" + +namespace +{ + // Need BYTE defined for shader bytecode + typedef unsigned char BYTE; + #include "customLightingCS.hlsl.h" +} + +void SceneCustomLighting::init(AppGraphCtx* context, int winw, int winh) +{ + SceneSDFTest::init(context, winw, winh); + + auto gridExport = NvFlowGridProxyGetGridExport(m_flowGridActor.m_gridProxy, m_flowContext.m_renderContext); + + NvFlowGridImportDesc importDesc = {}; + importDesc.gridExport = gridExport; + + m_import = NvFlowCreateGridImport(m_flowContext.m_renderContext, &importDesc); + + // create compute resources + m_computeContext = ComputeContextNvFlowContextCreate(m_flowContext.m_renderContext); + + ComputeShaderDesc shaderDesc = {}; + shaderDesc.cs = g_customLightingCS; + shaderDesc.cs_length = sizeof(g_customLightingCS); + m_computeShader = ComputeShaderCreate(m_computeContext, &shaderDesc); + + ComputeConstantBufferDesc cbDesc = {}; + cbDesc.sizeInBytes = 1024 * sizeof(float); + m_computeConstantBuffer = ComputeConstantBufferCreate(m_computeContext, &cbDesc); +} + +void SceneCustomLighting::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + ComputeContextNvFlowContextUpdate(m_computeContext, m_flowContext.m_renderContext); + + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + if (shouldUpdate) + { + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + NvFlowShapeDesc shapeDesc; + shapeDesc.sdf.sdfOffset = 0u; // m_shape; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeSDF; + m_emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &m_emitParams, 1u); + + NvFlowShapeSDF* sdfs[] = { m_shape }; + NvFlowGridUpdateEmitSDFs(m_flowGridActor.m_grid, sdfs, 1u); + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + } + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + + m_time += dt; + } + m_flowContext.updateEnd(); +} + +void SceneCustomLighting::preDraw() +{ + m_flowContext.preDrawBegin(); + + //auto gridView = NvFlowGridGetGridView(m_grid, m_context); + + AppGraphCtxProfileBegin(m_appctx, "UpdateGridView"); + + NvFlowGridProxyFlushParams flushParams = {}; + flushParams.gridContext = m_flowContext.m_gridContext; + flushParams.gridCopyContext = m_flowContext.m_gridCopyContext; + flushParams.renderCopyContext = m_flowContext.m_renderCopyContext; + NvFlowGridProxyFlush(m_flowGridActor.m_gridProxy, &flushParams); + + auto gridExport = NvFlowGridProxyGetGridExport(m_flowGridActor.m_gridProxy, m_flowContext.m_renderContext); + + AppGraphCtxProfileEnd(m_appctx, "UpdateGridView"); + + AppGraphCtxProfileBegin(m_appctx, "CustomLighting"); + + // Only layer 0 for the moment + NvFlowUint layerIdx = 0u; + + NvFlowGridExportHandle exportHandle = NvFlowGridExportGetHandle(gridExport, m_flowContext.m_renderContext, eNvFlowGridTextureChannelDensity); + NvFlowGridExportLayeredView exportLayeredView; + NvFlowGridExportGetLayeredView(exportHandle, &exportLayeredView); + NvFlowGridExportLayerView exportLayerView; + NvFlowGridExportGetLayerView(exportHandle, layerIdx, &exportLayerView); + + NvFlowGridImportParams importParams = {}; + importParams.gridExport = gridExport; + importParams.channel = eNvFlowGridTextureChannelDensity; + importParams.importMode = eNvFlowGridImportModePoint; + NvFlowGridImportHandle importHandle = NvFlowGridImportGetHandle(m_import, m_flowContext.m_renderContext, &importParams); + NvFlowGridImportLayeredView importLayeredView; + NvFlowGridImportGetLayeredView(importHandle, &importLayeredView); + NvFlowGridImportLayerView importLayerView; + NvFlowGridImportGetLayerView(importHandle, layerIdx, &importLayerView); + + // convert resource from NvFlow types to ComputeResource types + { + auto updateResource = [&](ComputeResource*& computeResouce, NvFlowResource*& flowResource) + { + if (computeResouce) { + ComputeResourceNvFlowUpdate(m_computeContext, computeResouce, m_flowContext.m_renderContext, flowResource); + } + else { + computeResouce = ComputeResourceNvFlowCreate(m_computeContext, m_flowContext.m_renderContext, flowResource); + } + }; + auto updateResourceRW = [&](ComputeResourceRW*& computeResouceRW, NvFlowResourceRW*& flowResourceRW) + { + if (computeResouceRW) { + ComputeResourceRWNvFlowUpdate(m_computeContext, computeResouceRW, m_flowContext.m_renderContext, flowResourceRW); + } + else { + computeResouceRW = ComputeResourceRWNvFlowCreate(m_computeContext, m_flowContext.m_renderContext, flowResourceRW); + } + }; + updateResource(m_exportBlockList, exportLayerView.mapping.blockList); + updateResource(m_exportBlockTable, exportLayerView.mapping.blockTable); + updateResource(m_exportData, exportLayerView.data); + updateResource(m_importBlockList, importLayerView.mapping.blockList); + updateResource(m_importBlockTable, importLayerView.mapping.blockTable); + updateResourceRW(m_importDataRW, importLayerView.dataRW); + } + + // dispatch custom lighting operation + { + struct Light + { + NvFlowFloat4 location; + NvFlowFloat4 intensity; + NvFlowFloat4 bias; + NvFlowFloat4 falloff; + }; + + struct ComputeShaderParams + { + NvFlowShaderLinearParams exportParams; + NvFlowShaderLinearParams importParams; + + Light light[3]; + }; + + auto mapped = (ComputeShaderParams*)ComputeConstantBufferMap(m_computeContext, m_computeConstantBuffer); + + mapped->exportParams = exportLayeredView.mapping.shaderParams; + mapped->importParams = importLayeredView.mapping.shaderParams; + + if (m_time >= DirectX::XM_2PI) + { + m_time -= DirectX::XM_2PI; + } + const float radius = 0.025f; + const float a = radius * cosf(m_time); + const float b = radius * sinf(m_time); + + mapped->light[0].location = { a, b, 0.f, 1.f }; + mapped->light[0].intensity = { 1.25f, 0.f, 0.f, 1.f }; + mapped->light[0].bias = { 0.1f, 0.1f, 0.1f, 0.1f }; + mapped->light[0].falloff = { 200.f, 200.f, 200.f, 0.f }; + mapped->light[1].location = { 0.f, a, b, 1.f }; + mapped->light[1].intensity = { 0.f, 1.25f, 0.f, 1.f }; + mapped->light[1].bias = { 0.1f, 0.1f, 0.1f, 0.1f }; + mapped->light[1].falloff = { 200.f, 200.f, 200.f, 0.f }; + mapped->light[2].location = { b, 0.f, a, 1.f }; + mapped->light[2].intensity = { 0.f, 0.f, 1.1f, 1.f }; + mapped->light[2].bias = { 0.1f, 0.1f, 0.1f, 0.1f }; + mapped->light[2].falloff = { 200.f, 200.f, 200.f, 0.f }; + + ComputeConstantBufferUnmap(m_computeContext, m_computeConstantBuffer); + + ComputeDispatchParams dparams = {}; + dparams.shader = m_computeShader; + dparams.constantBuffer = m_computeConstantBuffer; + dparams.gridDim[0] = (importLayerView.mapping.numBlocks * importLayeredView.mapping.shaderParams.blockDim.x + 7) / 8; + dparams.gridDim[1] = (importLayeredView.mapping.shaderParams.blockDim.y + 7) / 8; + dparams.gridDim[2] = (importLayeredView.mapping.shaderParams.blockDim.z + 7) / 8; + dparams.resources[0] = m_exportBlockList; + dparams.resources[1] = m_exportBlockTable; + dparams.resources[2] = m_exportData; + dparams.resources[3] = m_importBlockList; + dparams.resources[4] = m_importBlockTable; + dparams.resourcesRW[0] = m_importDataRW; + + ComputeContextDispatch(m_computeContext, &dparams); + } + + AppGraphCtxProfileEnd(m_appctx, "CustomLighting"); + + AppGraphCtxProfileBegin(m_appctx, "CustomImport"); + + // override original gridExport + gridExport = NvFlowGridImportGetGridExport(m_import, m_flowContext.m_renderContext); + + AppGraphCtxProfileEnd(m_appctx, "CustomImport"); + + m_flowGridActor.m_gridExportOverride = gridExport; + m_flowGridActor.m_renderParamsOverride = m_flowGridActor.m_renderParams; + + m_flowContext.preDrawEnd(); +} + +void SceneCustomLighting::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + m_projectile.draw(projection, view); + + m_flowContext.drawBegin(); + + m_flowGridActor.draw(&m_flowContext, projection, view); + + m_flowContext.drawEnd(); +} + +void SceneCustomLighting::release() +{ + NvFlowReleaseGridImport(m_import); + + // release compute resources + ComputeConstantBufferRelease(m_computeConstantBuffer); + ComputeShaderRelease(m_computeShader); + ComputeContextRelease(m_computeContext); + + ComputeResourceRelease(m_exportBlockList); + ComputeResourceRelease(m_exportBlockTable); + ComputeResourceRelease(m_exportData); + ComputeResourceRelease(m_importBlockList); + ComputeResourceRelease(m_importBlockTable); + ComputeResourceRWRelease(m_importDataRW); + + m_exportBlockList = nullptr; + m_exportBlockTable = nullptr; + m_exportData = nullptr; + m_importBlockList = nullptr; + m_importBlockTable = nullptr; + m_importDataRW = nullptr; + + SceneSDFTest::release(); +} + +void SceneCustomLighting::imgui(int xIn, int yIn, int wIn, int hIn) +{ + bool shouldLoadPreset = m_shouldLoadPreset; + m_shouldLoadPreset = false; + SceneSDFTest::imgui(xIn, yIn, wIn, hIn); + m_shouldLoadPreset = shouldLoadPreset; + if (m_shouldLoadPreset) + { + imguiserLoadC(Preset1::g_root, sizeof(Preset1::g_root)); + m_shouldLoadPreset = false; + } +} + +void SceneCustomLighting::initParams() +{ + SceneSDFTest::initParams(); +}
\ No newline at end of file diff --git a/demo/DemoApp/sceneSimpleFlame.cpp b/demo/DemoApp/sceneSimpleFlame.cpp new file mode 100644 index 0000000..60b134b --- /dev/null +++ b/demo/DemoApp/sceneSimpleFlame.cpp @@ -0,0 +1,1156 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <stdio.h> +#include <string.h> + +#include "loader.h" +#include "imgui.h" +#include "imguiser.h" + +namespace PresetFlame +{ +#include "presetFlame.h" +} + +#include "scene.h" + +#include <SDL.h> + +void SceneSimpleFlame::initParams() +{ + m_flowGridActor.initParams(AppGraphCtxDedicatedVideoMemory(m_appctx)); + + // set emitter defaults + NvFlowGridEmitParamsDefaults(&m_emitParams); + + // configure emitter params + m_emitParams.bounds.x.x = 0.25f; + m_emitParams.bounds.y.y = 0.25f; + m_emitParams.bounds.z.z = 0.25f; + m_emitParams.velocityLinear.y = 8.f; + m_emitParams.fuel = 1.9f; + m_emitParams.smoke = 0.5f; + + m_shouldLoadPreset = true; +} + +void SceneSimpleFlame::init(AppGraphCtx* appctx, int winw, int winh) +{ + m_appctx = appctx; + + if (!m_shouldReset || m_isFirstRun) + { + initParams(); + m_isFirstRun = false; + } + + m_flowContext.init(appctx); + + m_flowGridActor.init(&m_flowContext, appctx); + + // more compute resources + NvFlowShapeSDFDesc shapeDesc; + NvFlowShapeSDFDescDefaults(&shapeDesc); + m_shape = NvFlowCreateShapeSDF(m_flowContext.m_gridContext, &shapeDesc); + + // generate sphere SDF + const float radius = 0.8f; + auto mappedData = NvFlowShapeSDFMap(m_shape, m_flowContext.m_gridContext); + if (mappedData.data) + { + for (NvFlowUint k = 0; k < mappedData.dim.z; k++) + for (NvFlowUint j = 0; j < mappedData.dim.y; j++) + for (NvFlowUint i = 0; i < mappedData.dim.x; i++) + { + float& val = mappedData.data[k * mappedData.depthPitch + j * mappedData.rowPitch + i]; + + float x = 2.f * (float(i) + 0.5f) / float(mappedData.dim.x) - 1.f; + float y = 2.f * (float(j) + 0.5f) / float(mappedData.dim.y) - 1.f; + float z = 2.f * (float(k) + 0.5f) / float(mappedData.dim.z) - 1.f; + + float d = sqrtf(x*x + y*y + z*z); + float v = d - radius; + + val = v; + } + NvFlowShapeSDFUnmap(m_shape, m_flowContext.m_gridContext); + } + + // create default color map + { + const int numPoints = 5; + const CurvePoint pts[numPoints] = { + {0.f, 0.f,0.f,0.f,0.f}, + {0.05f, 0.f,0.f,0.f,0.5f}, + {0.6f, 213.f / 255.f,100.f / 255.f,30.f / 255.f,0.8f}, + {0.85f, 255.f / 255.f,240.f / 255.f,0.f,0.8f}, + {1.f, 1.f,1.f,1.f,0.7f} + }; + + auto& colorMap = m_flowGridActor.m_colorMap; + colorMap.initColorMap(m_flowContext.m_renderContext, pts, numPoints, (colorMap.m_curvePointsDefault.size() == 0)); + } + + m_projectile.init(m_appctx, m_flowContext.m_gridContext); + + resize(winw, winh); +} + +void SceneSimpleFlame::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + // emit + { + NvFlowShapeDesc shapeDesc; + shapeDesc.sphere.radius = 0.8f; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeSphere; + m_emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &m_emitParams, 1u); + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + } + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +void SceneSimpleFlame::preDraw() +{ + m_flowContext.preDrawBegin(); + + m_flowGridActor.preDraw(&m_flowContext); + + m_flowContext.preDrawEnd(); +} + +void SceneSimpleFlame::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + m_projectile.draw(projection, view); + + m_flowContext.drawBegin(); + + m_flowGridActor.draw(&m_flowContext, projection, view); + + m_flowContext.drawEnd(); +} + +void SceneSimpleFlame::release() +{ + m_projectile.release(); + + m_flowGridActor.release(); + + NvFlowReleaseShapeSDF(m_shape); + + m_flowContext.release(); +} + +void SceneSimpleFlame::imgui(int xIn, int yIn, int wIn, int hIn) +{ + SceneFluid::imgui(xIn, yIn, wIn, hIn); + + if (m_shouldLoadPreset) + { + imguiserLoadC(PresetFlame::g_root, sizeof(PresetFlame::g_root)); + m_shouldLoadPreset = false; + } +} + +// *************************** SceneSimpleFlameDouble ********************** + +void SceneSimpleFlameDouble::init(AppGraphCtx* context, int winw, int winh) +{ + SceneSimpleFlame::init(context, winw, winh); + + NvFlowGridMaterialParams materialParams = {}; + NvFlowGridMaterialParamsDefaults(&materialParams); + + m_materialA = NvFlowGridCreateMaterial(m_flowGridActor.m_grid, &materialParams); + + materialParams.vorticityStrength = 5.f; + materialParams.vorticityVelocityMask = 0.f; + materialParams.velocity.macCormackBlendFactor = 0.f; + materialParams.smoke.macCormackBlendFactor = 0.75f; + materialParams.buoyancyPerTemp *= 5.f; + + m_materialB = NvFlowGridCreateMaterial(m_flowGridActor.m_grid, &materialParams); + + m_flowGridActor.m_renderMaterialMat0Params.material = m_materialA; + m_flowGridActor.m_renderMaterialMat1Params.material = m_materialB; +} + +void SceneSimpleFlameDouble::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + // emit + { + NvFlowShapeDesc shapeDesc; + shapeDesc.sphere.radius = 0.8f; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeSphere; + m_emitParams.deltaTime = dt; + + m_emitParamsA = m_emitParams; + m_emitParamsA.material = m_materialA; + m_emitParamsA.bounds.w.x = +0.25f; + m_emitParamsA.localToWorld = m_emitParamsA.bounds; + m_emitParamsA.velocityLinear.x = -8.f; + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &m_emitParamsA, 1u); + + m_emitParamsB = m_emitParams; + m_emitParamsB.material = m_materialB; + m_emitParamsB.bounds.w.x = -0.25f; + m_emitParamsB.localToWorld = m_emitParamsB.bounds; + m_emitParamsB.velocityLinear.x = +8.f; + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &m_emitParamsB, 1u); + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + } + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +void SceneSimpleFlameDouble::preDraw() +{ + SceneSimpleFlame::preDraw(); +} + +void SceneSimpleFlameDouble::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + SceneSimpleFlame::draw(projection, view); +} + +void SceneSimpleFlameDouble::release() +{ + SceneSimpleFlame::release(); +} + +void SceneSimpleFlameDouble::imgui(int x, int y, int w, int h) +{ + SceneSimpleFlame::imgui(x, y, w, h); +} + +void SceneSimpleFlameDouble::initParams() +{ + m_flowGridActor.initParams(AppGraphCtxDedicatedVideoMemory(m_appctx)); + + // set emitter defaults + NvFlowGridEmitParamsDefaults(&m_emitParams); + + // configure emitter params + m_emitParams.bounds.x.x = 0.25f; + m_emitParams.bounds.y.y = 0.25f; + m_emitParams.bounds.z.z = 0.25f; + m_emitParams.velocityLinear.y = 8.f; + m_emitParams.fuel = 1.9f; + m_emitParams.smoke = 0.5f; + + m_shouldLoadPreset = true; +} + +// *************************** SceneSimpleFlameFuelMap ********************** + +void SceneSimpleFlameFuelMap::init(AppGraphCtx* context, int winw, int winh) +{ + SceneSimpleFlame::init(context, winw, winh); + + m_flowGridActor.m_renderMaterialMat0Params.material = NvFlowGridGetDefaultMaterial(m_flowGridActor.m_grid); + + m_flowGridActor.m_renderMaterialMat0Params.colorMapCompMask = { 0.f, 4.f, 0.f, 0.f }; + m_flowGridActor.m_renderMaterialMat0Params.alphaCompMask = { 0.f, 1.f, 0.f, 0.f }; + m_flowGridActor.m_renderMaterialMat0Params.alphaBias = 0.f; + + //m_flowGridActor.m_renderMaterialMat1Params.material = m_materialB; +} + +void SceneSimpleFlameFuelMap::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + // emit + { + NvFlowShapeDesc shapeDesc; + shapeDesc.sphere.radius = 0.8f; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeSphere; + m_emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &m_emitParams, 1u); + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + } + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +void SceneSimpleFlameFuelMap::preDraw() +{ + SceneSimpleFlame::preDraw(); +} + +void SceneSimpleFlameFuelMap::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + SceneSimpleFlame::draw(projection, view); +} + +void SceneSimpleFlameFuelMap::release() +{ + SceneSimpleFlame::release(); +} + +void SceneSimpleFlameFuelMap::imgui(int x, int y, int w, int h) +{ + SceneSimpleFlame::imgui(x, y, w, h); +} + +void SceneSimpleFlameFuelMap::initParams() +{ + m_flowGridActor.initParams(AppGraphCtxDedicatedVideoMemory(m_appctx)); + + // set emitter defaults + NvFlowGridEmitParamsDefaults(&m_emitParams); + + // configure emitter params + m_emitParams.bounds.x.x = 0.25f; + m_emitParams.bounds.y.y = 0.25f; + m_emitParams.bounds.z.z = 0.25f; + m_emitParams.velocityLinear.y = 8.f; + m_emitParams.fuel = 1.9f; + m_emitParams.smoke = 0.5f; + + m_shouldLoadPreset = true; +} + +// *************************** SceneSimpleFlameParticleSurface ********************** + +void SceneSimpleFlameParticleSurface::init(AppGraphCtx* context, int winw, int winh) +{ + SceneSimpleFlame::init(context, winw, winh); + + NvFlowParticleSurfaceDesc surfaceDesc = {}; + surfaceDesc.initialLocation = { 0.f, 0.f, 0.f }; + surfaceDesc.halfSize = { 8.f, 8.f, 8.f }; + surfaceDesc.virtualDim = NvFlowDim{512u, 512u, 512u}; + surfaceDesc.residentScale = 0.125f * 0.125f; + surfaceDesc.maxParticles = 64u * 1024u; + + m_particleSurface = NvFlowCreateParticleSurface(m_flowContext.m_gridContext, &surfaceDesc); + + if (!m_visualizeSurface) + { + NvFlowGridEmitCustomRegisterAllocFunc(m_flowGridActor.m_grid, emitCustomAllocFunc, this); + NvFlowGridEmitCustomRegisterEmitFunc(m_flowGridActor.m_grid, eNvFlowGridTextureChannelVelocity, emitCustomEmitVelocityFunc, this); + NvFlowGridEmitCustomRegisterEmitFunc(m_flowGridActor.m_grid, eNvFlowGridTextureChannelDensity, emitCustomEmitDensityFunc, this); + } + + // generate positions + const NvFlowUint r = 32u; + + m_positions.clear(); + m_positions.resize(4u * r * r); + const float scale = 4.f; + const float scaleXInv = scale / float(r); + const float scaleYInv = scale / float(r); + for (NvFlowUint j = 0u; j < r; j++) + { + for (NvFlowUint i = 0u; i < r; i++) + { + float x = scaleXInv * float(i) - scale * 0.5f; + float y = scaleYInv * float(j) - scale * 0.5f; + + m_positions[4 * (j * r + i) + 0u] = x; + m_positions[4 * (j * r + i) + 1u] = 0.f; + m_positions[4 * (j * r + i) + 2u] = y; + m_positions[4 * (j * r + i) + 3u] = 1.f; + } + } + + m_flowGridActor.m_renderMaterialDefaultParams.material = NvFlowGridMaterialHandle{ nullptr, 1u }; + m_flowGridActor.m_renderMaterialMat0Params.material = NvFlowGridGetDefaultMaterial(m_flowGridActor.m_grid); + + m_particleParams.smoothRadius = 16.f; + m_particleParams.surfaceThreshold = 0.001f; + m_particleParams.separableSmoothing = true; +} + +void SceneSimpleFlameParticleSurface::emitCustomAllocFunc(void* userdata, const NvFlowGridEmitCustomAllocParams* params) +{ + ((SceneSimpleFlameParticleSurface*)(userdata))->doEmitCustomAllocFunc(params); +} + +void SceneSimpleFlameParticleSurface::emitCustomEmitVelocityFunc(void* userdata, NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params) +{ + ((SceneSimpleFlameParticleSurface*)(userdata))->doEmitCustomEmitVelocityFunc(dataFrontIdx, params); +} + +void SceneSimpleFlameParticleSurface::emitCustomEmitDensityFunc(void* userdata, NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params) +{ + ((SceneSimpleFlameParticleSurface*)(userdata))->doEmitCustomEmitDensityFunc(dataFrontIdx, params); +} + +void SceneSimpleFlameParticleSurface::doEmitCustomAllocFunc(const NvFlowGridEmitCustomAllocParams* params) +{ + NvFlowParticleSurfaceAllocFunc(m_particleSurface, m_flowContext.m_gridContext, params); +} + +void SceneSimpleFlameParticleSurface::doEmitCustomEmitVelocityFunc(NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params) +{ + NvFlowParticleSurfaceEmitVelocityFunc(m_particleSurface, m_flowContext.m_gridContext, dataFrontIdx, params, &m_surfaceEmitParams); +} + +void SceneSimpleFlameParticleSurface::doEmitCustomEmitDensityFunc(NvFlowUint* dataFrontIdx, const NvFlowGridEmitCustomEmitParams* params) +{ + NvFlowParticleSurfaceEmitDensityFunc(m_particleSurface, m_flowContext.m_gridContext, dataFrontIdx, params, &m_surfaceEmitParams); +} + +void SceneSimpleFlameParticleSurface::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + // update emit params + { + // set surface emit params + const float coupleRate = 0.5f; + m_surfaceEmitParams.deltaTime = dt; + m_surfaceEmitParams.velocityLinear = m_emitParams.velocityLinear; + m_surfaceEmitParams.velocityCoupleRate = NvFlowFloat3{ coupleRate, coupleRate, coupleRate }; + m_surfaceEmitParams.smoke = m_emitParams.smoke; + m_surfaceEmitParams.smokeCoupleRate = coupleRate; + m_surfaceEmitParams.temperature = m_emitParams.temperature; + m_surfaceEmitParams.temperatureCoupleRate = coupleRate; + m_surfaceEmitParams.fuel = m_emitParams.fuel; + m_surfaceEmitParams.fuelCoupleRate = coupleRate; + } + + AppGraphCtxProfileBegin(m_appctx, "ParticleSurface"); + + { + // animate wave surface + { + const NvFlowUint r = 32u; + const float k = 0.125f; + const float timeScale = 4.f; + const float spaceScale = 32.f; + const float pi = 3.14159f; + + const float period = 2.f * pi / (timeScale); + + m_time += dt; + + float offsetX = 0.f; // 3.f * cosf(m_time); + float offsetY = 0.f; // 3.f * sinf(m_time); + + const float scale = 4.f; + const float scaleInv = 1.f / scale; + const float scaleXInv = scale / float(r); + const float scaleYInv = scale / float(r); + for (NvFlowUint j = 0u; j < r; j++) + { + for (NvFlowUint i = 0u; i < r; i++) + { + float x = scaleXInv * float(i) - scale * 0.5f; + float y = scaleYInv * float(j) - scale * 0.5f; + float d = scaleInv * sqrtf(x * x + y * y); + + m_positions[4 * (j * r + i) + 0u] = x + offsetX; + m_positions[4 * (j * r + i) + 2u] = y + offsetY; + m_positions[4 * (j * r + i) + 1u] = k * cosf(-timeScale * m_time + spaceScale * d); + } + } + } + + NvFlowParticleSurfaceData particleData = {}; + particleData.positions = &m_positions[0u]; + particleData.positionStride = 4 * sizeof(float); + particleData.numParticles = NvFlowUint(m_positions.size() / 4u); + + NvFlowParticleSurfaceUpdateParticles(m_particleSurface, m_flowContext.m_gridContext, &particleData); + + NvFlowParticleSurfaceUpdateSurface(m_particleSurface, m_flowContext.m_gridContext, &m_particleParams); + } + + AppGraphCtxProfileEnd(m_appctx, "ParticleSurface"); + + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + // emit + { + /* + NvFlowShapeDesc shapeDesc; + shapeDesc.sphere.radius = 0.8f; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeSphere; + m_emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &m_emitParams, 1u); + */ + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + } + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +void SceneSimpleFlameParticleSurface::preDraw() +{ + SceneSimpleFlame::preDraw(); +} + +void SceneSimpleFlameParticleSurface::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + m_projectile.draw(projection, view); + + m_flowContext.drawBegin(); + + if (!m_visualizeSurface) + { + m_flowGridActor.draw(&m_flowContext, projection, view); + } + else + { + AppGraphCtxProfileBegin(m_appctx, "Render"); + + auto m_renderParams = m_flowGridActor.m_renderParams; + + memcpy(&m_renderParams.projectionMatrix, &projection, sizeof(m_renderParams.projectionMatrix)); + memcpy(&m_renderParams.viewMatrix, &view, sizeof(m_renderParams.viewMatrix)); + + m_renderParams.depthStencilView = m_flowContext.m_dsv; + m_renderParams.renderTargetView = m_flowContext.m_rtv; + + auto gridExport = NvFlowParticleSurfaceDebugGridExport(m_particleSurface, m_flowContext.m_renderContext); + + NvFlowVolumeRenderGridExport(m_flowGridActor.m_volumeRender, m_flowContext.m_renderContext, gridExport, &m_renderParams); + + AppGraphCtxProfileEnd(m_appctx, "Render"); + } + + m_flowContext.drawEnd(); +} + +void SceneSimpleFlameParticleSurface::release() +{ + SceneSimpleFlame::release(); + + NvFlowReleaseParticleSurface(m_particleSurface); +} + +void SceneSimpleFlameParticleSurface::imgui(int x, int y, int w, int h) +{ + SceneSimpleFlame::imgui(x, y, w, h); +} + +void SceneSimpleFlameParticleSurface::imguiFluidRenderExtra() +{ + imguiLabel("Particle Surface"); + if (imguiserCheck("SurfaceVis", m_visualizeSurface, true)) + { + m_visualizeSurface = !m_visualizeSurface; + m_shouldReset = true; + } + imguiserSlider("Smooth Radius", &m_particleParams.smoothRadius, 1.f, 16.f, 1.f, true); + imguiserSlider("Threshold", &m_particleParams.surfaceThreshold, 0.001f, 0.01f, 0.001f, true); + if (imguiserCheck("SeparableSmooth", m_particleParams.separableSmoothing, true)) + { + m_particleParams.separableSmoothing = !m_particleParams.separableSmoothing; + } +} + +void SceneSimpleFlameParticleSurface::initParams() +{ + m_flowGridActor.initParams(AppGraphCtxDedicatedVideoMemory(m_appctx)); + + // set emitter defaults + NvFlowGridEmitParamsDefaults(&m_emitParams); + + // configure emitter params + m_emitParams.bounds.x.x = 0.25f; + m_emitParams.bounds.y.y = 0.25f; + m_emitParams.bounds.z.z = 0.25f; + m_emitParams.velocityLinear.y = -1.f; + m_emitParams.fuel = 0.2f; + m_emitParams.smoke = 0.1f; + m_emitParams.temperature = 8.f; + + m_flowGridActor.m_materialParams.coolingRate = 3.f; + + m_shouldLoadPreset = true; +} + +// *************************** SceneDynamicCoupleRate ********************** + +void SceneDynamicCoupleRate::initParams() +{ + SceneSimpleFlame::initParams(); + m_emitParams.allocationPredict = 0.3f; +} + +float SceneDynamicCoupleRate::positionFunc(float theta) +{ + return 2.f * cosf(theta); +} + +float SceneDynamicCoupleRate::velocityFunc(float theta, float rate) +{ + return -2.f * rate * sinf(theta); +} + +void SceneDynamicCoupleRate::doUpdate(float dt) +{ + const float pi2 = 2.f * 3.14159265f; + + theta += pi2 * rate * dt; + + if (theta > pi2) theta -= pi2; + + // get position and velocity + float position = positionFunc(theta); + float velocity = velocityFunc(theta, pi2 * rate); + + // update emitter bounds + m_emitParams.bounds.x.x = 0.25f * emitterScale; + m_emitParams.bounds.y.y = 0.25f * emitterScale; + m_emitParams.bounds.z.z = 0.25f * emitterScale; + + // modulate couple rate as a function of velocity and emitter width + const float defaultCoupleRate = 0.5f; + + float emitWidth = m_emitParams.bounds.x.x; + + float coupleRate = fmaxf(coupleRateScale * fabsf(velocity) / emitWidth, defaultCoupleRate); + + m_emitParams.smokeCoupleRate = coupleRate; + m_emitParams.temperatureCoupleRate = coupleRate; + m_emitParams.fuelCoupleRate = coupleRate; + m_emitParams.velocityCoupleRate = { coupleRate, coupleRate, coupleRate }; + + m_emitParams.bounds.w.x = position; + m_emitParams.velocityLinear.x = velocity; + + m_emitParams.predictVelocityWeight = 1.f; + m_emitParams.predictVelocity.x = velocity; + m_emitParams.predictVelocity.y = 0.f; + m_emitParams.predictVelocity.z = 0.f; + + SceneSimpleFlame::doUpdate(dt); +} + +void SceneDynamicCoupleRate::imguiFluidEmitterExtra() +{ + imguiSeparatorLine(); + imguiLabel("Dynamic Couple Rate"); + + imguiserSlider("Anim Cycle Time", &rate, 0.f, 0.5f, 0.01f, true); + imguiserSlider("Couple Rate Scale", &coupleRateScale, 0.f, 1.0f, 0.01f, true); + imguiserSlider("Emitter Scale", &emitterScale, 0.5f, 2.0f, 0.01f, true); +} + +// *************************** SceneSimpleFlameMesh ************************ + +void SceneSimpleFlameMesh::initParams() +{ + SceneSimpleFlame::initParams(); + + NvFlowGridEmitParamsDefaults(&m_teapotEmitParams); + + m_teapotEmitParams.allocationScale = { 0.f, 0.f, 0.f }; + + m_teapotEmitParams.maxActiveDist = -0.08f; + m_teapotEmitParams.slipThickness = 0.25f; + m_teapotEmitParams.slipFactor = 0.9f; +} + +void SceneSimpleFlameMesh::init(AppGraphCtx* context, int winw, int winh) +{ + using namespace DirectX; + + m_meshContext = MeshInteropContextCreate(context); + m_mesh = MeshCreate(m_meshContext); + + MeshLoadFromFile(m_mesh, m_meshPath); + + SceneSimpleFlame::init(context, winw, winh); + + NvFlowSDFGenDesc sdfDesc; + sdfDesc.resolution = { 128u, 128u, 128u }; + + m_sdfGen = NvFlowCreateSDFGen(m_flowContext.m_gridContext, &sdfDesc); + + MeshData meshData; + MeshGetData(m_mesh, &meshData); + + NvFlowSDFGenReset(m_sdfGen, m_flowContext.m_gridContext); + + XMMATRIX modelMatrix = XMMatrixMultiply( + XMMatrixScaling(m_sdfScale.x, m_sdfScale.y, m_sdfScale.z), + XMMatrixTranslation(0.f, 0.f, 0.f) + ); + + NvFlowSDFGenMeshParams meshParams; + meshParams.numVertices = meshData.numVertices; + meshParams.positions = meshData.positions; + meshParams.positionStride = meshData.positionStride; + meshParams.normals = meshData.normals; + meshParams.normalStride = meshData.normalStride; + meshParams.numIndices = meshData.numIndices; + meshParams.indices = meshData.indices; + XMStoreFloat4x4((XMFLOAT4X4*)&meshParams.modelMatrix, modelMatrix); + meshParams.renderTargetView = m_flowContext.m_multiGPUActive ? nullptr : m_flowContext.m_rtv; + meshParams.depthStencilView = m_flowContext.m_multiGPUActive ? nullptr : m_flowContext.m_dsv; + + NvFlowSDFGenVoxelize(m_sdfGen, m_flowContext.m_gridContext, &meshParams); + + NvFlowSDFGenUpdate(m_sdfGen, m_flowContext.m_gridContext); + + // create shape from SDF + m_teapotShape = NvFlowCreateShapeSDFFromTexture3D( + m_flowContext.m_gridContext, + NvFlowSDFGenShape(m_sdfGen, m_flowContext.m_gridContext) + ); +} + +void SceneSimpleFlameMesh::release() +{ + MeshRelease(m_mesh); + MeshContextRelease(m_meshContext); + NvFlowReleaseShapeSDF(m_teapotShape); + NvFlowReleaseSDFGen(m_sdfGen); + SceneSimpleFlame::release(); +} + +void SceneSimpleFlameMesh::doUpdate(float dt) +{ + NvFlowGridEmitParams& emitParams = m_teapotEmitParams; + emitParams.bounds.x.x = m_emitterScale.x; + emitParams.bounds.y.y = m_emitterScale.y; + emitParams.bounds.z.z = m_emitterScale.z; + emitParams.bounds.w.x = m_emitterOffset.x; + emitParams.bounds.w.y = m_emitterOffset.y; + emitParams.bounds.w.z = m_emitterOffset.z; + + emitParams.velocityCoupleRate = { 1000.f, 1000.f, 1000.f }; + + emitParams.temperature = 0.f; + emitParams.temperatureCoupleRate = 10.f; + + emitParams.fuel = 0.f; + emitParams.fuelCoupleRate = 10.f; + + emitParams.smoke = 0.f; + emitParams.smokeCoupleRate = 10.f; + + NvFlowShapeDesc shapeDesc; + shapeDesc.sdf.sdfOffset = 0u; // m_teapotShape; + + emitParams.localToWorld = emitParams.bounds; + emitParams.shapeType = eNvFlowShapeTypeSDF; + emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &emitParams, 1u); + + NvFlowShapeSDF* sdfs[] = { m_teapotShape }; + NvFlowGridUpdateEmitSDFs(m_flowGridActor.m_grid, sdfs, 1u); + + // animate emitter + if (m_animate) + { + m_time += dt; + + const float rate = 2.f; + const float period = 2.f * 3.14159265f / rate; + if (m_time > period) m_time -= period; + + m_emitParams.bounds.w.x = 0.15f * sinf(rate * m_time); + m_emitParams.bounds.w.z = 0.f; + } + else + { + m_emitParams.bounds.w.x = 0.f; + m_emitParams.bounds.w.z = 0.f; + + m_time = 0.f; + } + + SceneSimpleFlame::doUpdate(dt); +} + +void SceneSimpleFlameMesh::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + MeshInteropContextUpdate(m_meshContext, m_appctx); + + MeshDrawParams meshDrawParams; + meshDrawParams.renderMode = MESH_RENDER_SOLID; + meshDrawParams.projection = projection; + meshDrawParams.view = view; + meshDrawParams.model = DirectX::XMMatrixMultiply( + DirectX::XMMatrixScaling(m_emitterScale.x * m_sdfScale.x, m_emitterScale.y * m_sdfScale.y, m_emitterScale.z * m_sdfScale.z), + DirectX::XMMatrixTranslation(m_emitterOffset.x, m_emitterOffset.y, m_emitterOffset.z) + ); + + if (m_shouldDrawMesh) + { + MeshDraw(m_mesh, &meshDrawParams); + } + + SceneSimpleFlame::draw(projection, view); +} + +void SceneSimpleFlameMesh::imguiFluidRenderExtra() +{ + if (imguiserCheck("Draw Mesh", m_shouldDrawMesh, true)) + { + m_shouldDrawMesh = !m_shouldDrawMesh; + } +} + +void SceneSimpleFlameMesh::imguiFluidEmitterExtra() +{ + if (imguiserCheck("Animate", m_animate, true)) + { + m_animate = !m_animate; + } + imguiSeparatorLine(); + imguiLabel("Teapot"); + imguiserBeginGroup("Teapot", nullptr); + + imguiserSlider("Max Emit Dist", &m_teapotEmitParams.maxActiveDist, -1.f, 1.f, 0.01f, true); + imguiserSlider("Min Emit Dist", &m_teapotEmitParams.minActiveDist, -1.f, 1.f, 0.01f, true); + imguiserSlider("Slip Thickness", &m_teapotEmitParams.slipThickness, 0.f, 1.f, 0.01f, true); + imguiserSlider("Slip Factor", &m_teapotEmitParams.slipFactor, 0.f, 1.f, 0.01f, true); + imguiserSlider("Fuel Release Temp", &m_teapotEmitParams.fuelReleaseTemp, 0.f, 1.f, 0.01f, true); + imguiserSlider("Fuel Release", &m_teapotEmitParams.fuelRelease, 0.f, 10.f, 0.1f, true); + + imguiserEndGroup(); +} + +// *************************** SceneSimpleFlameCulling ************************ + +void SceneSimpleFlameCulling::initParams() +{ + SceneSimpleFlame::initParams(); + + m_emitParams.allocationScale = { 2.f, 2.f, 2.f }; + m_emitParams.allocationPredict = 0.4f; +} + +void SceneSimpleFlameCulling::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + { + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + // main emitter + { + NvFlowShapeDesc shapeDesc; + shapeDesc.box.halfSize = { 0.8f, 0.8f, 0.8f }; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeBox; + m_emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &m_emitParams, 1u); + } + + // grid of emitters + { + const int r = m_emitGridR; + const float scale = 0.125f; + + NvFlowShapeDesc shapeDesc; + shapeDesc.sphere.radius = 0.8f; + + NvFlowGridEmitParams emitParams; + + NvFlowGridEmitParamsDefaults(&emitParams); + + emitParams.bounds.x.x = 0.25f; + emitParams.bounds.y.y = 0.25f; + emitParams.bounds.z.z = 0.25f; + + emitParams.maxActiveDist = -0.08f; + emitParams.slipThickness = 0.25f; + emitParams.slipFactor = 0.9f; + + emitParams.velocityCoupleRate = { 1000.f, 1000.f, 1000.f }; + + emitParams.temperature = 0.f; + emitParams.temperatureCoupleRate = 10.f; + + emitParams.fuel = 0.f; + emitParams.fuelCoupleRate = 10.f; + + emitParams.smoke = 0.f; + emitParams.smokeCoupleRate = 10.f; + + emitParams.allocationScale = { 1.f, 1.f, 1.f }; + emitParams.allocationPredict = 0.f; + + for (int j = -r; j <= r; j++) + { + for (int i = -r; i <= r; i++) + { + if (i == 0 && j == 0) continue; + + emitParams.bounds.w.x = scale * float(i); + emitParams.bounds.w.y = 0.f; + emitParams.bounds.w.z = scale * float(j); + + emitParams.localToWorld = emitParams.bounds; + emitParams.shapeType = eNvFlowShapeTypeSphere; + emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &emitParams, 1u); + } + } + } + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + } + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +void SceneSimpleFlameCulling::imguiFluidEmitterExtra() +{ + imguiSeparatorLine(); + imguiLabel("Culling"); + imguiserBeginGroup("Culling", nullptr); + + float r = float(m_emitGridR); + imguiserSlider("Emit Grid R", &r, 0.f, 16.f, 1.f, true); + m_emitGridR = NvFlowUint(r); + + imguiserEndGroup(); +} + +// *************************** SceneSimpleFlameConvex ************************ + +void SceneSimpleFlameConvex::initParams() +{ + SceneSimpleFlame::initParams(); + + m_emitParams.minActiveDist = -0.3f; + m_emitParams.fuel = 2.5f; + + m_flowGridActor.m_materialParams.smoke.damping = 0.5f; + m_flowGridActor.m_materialParams.smoke.fade = 0.5f; +} + +void SceneSimpleFlameConvex::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + { + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + NvFlowShapeDesc shapeDesc[8]; + const float a = 0.866f; + const float b = 0.5f; + const float d = 4.f * m_size; + shapeDesc[0].plane = { +1.f, 0.f, 0.f, d }; + shapeDesc[1].plane = { -1.f, 0.f, 0.f, d }; + shapeDesc[2].plane = { +b, 0.f, +a, d }; + shapeDesc[3].plane = { +b, 0.f, -a, d }; + shapeDesc[4].plane = { -b, 0.f, +a, d }; + shapeDesc[5].plane = { -b, 0.f, -a, d }; + shapeDesc[6].plane = { 0.f, +1.f, 0.f, 0.8f }; + shapeDesc[7].plane = { 0.f, -1.f, 0.f, 0.8f }; + + m_emitParams.bounds.x.x = m_size + 0.25f; + //m_emitParams.bounds.y.y = m_barLength; + m_emitParams.bounds.z.z = m_size + 0.25f; + + m_emitParams.localToWorld = NvFlowFloat4x4{ + 0.25f, 0.f, 0.f, 0.f, + 0.f, 0.25f, 0.f, 0.f, + 0.f, 0.f, 0.25f, 0.f, + m_emitParams.bounds.w.x, m_emitParams.bounds.w.y, m_emitParams.bounds.w.z, 1.f + }; + m_emitParams.shapeType = eNvFlowShapeTypePlane; + m_emitParams.shapeDistScale = m_distanceScale; + m_emitParams.shapeRangeOffset = 0u; + m_emitParams.shapeRangeSize = 8u; + m_emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, shapeDesc, 8u, &m_emitParams, 1u); + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + } + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +void SceneSimpleFlameConvex::imguiFluidEmitterExtra() +{ + imguiSeparatorLine(); + imguiLabel("Bar"); + imguiserBeginGroup("Bar", nullptr); + + imguiserSlider("Size", &m_size, 0.f, 4.f, 0.1f, true); + imguiserSlider("Distance Scale", &m_distanceScale, 0.1f, 3.f, 0.025f, true); + + imguiserEndGroup(); +} + +// *************************** SceneSimpleFlameCapsule ************************ + +void SceneSimpleFlameCapsule::initParams() +{ + SceneSimpleFlame::initParams(); + + m_emitParams.minActiveDist = -0.3f; + m_emitParams.fuel = 2.5f; + + m_flowGridActor.m_materialParams.smoke.damping = 0.5f; + m_flowGridActor.m_materialParams.smoke.fade = 0.5f; +} + +void SceneSimpleFlameCapsule::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + if (shouldUpdate) + { + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + NvFlowShapeDesc shapeDesc[1]; + shapeDesc[0].capsule.radius = m_capsuleRadius; + shapeDesc[0].capsule.length = m_capsuleLength; + + // generate bounds based on radius and length + const float boundInflate = 0.25f; + float xbound = 2.f * m_capsuleRadius + m_capsuleLength + boundInflate; + float yzbound = 2.f * m_capsuleRadius + boundInflate; + m_emitParams.bounds.x.x = 0.5f * xbound; + m_emitParams.bounds.y.y = 0.5f * yzbound; + m_emitParams.bounds.z.z = 0.5f * yzbound; + + m_emitParams.localToWorld = NvFlowFloat4x4{ + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + m_emitParams.bounds.w.x, m_emitParams.bounds.w.y, m_emitParams.bounds.w.z, 1.f + }; + + m_emitParams.shapeType = eNvFlowShapeTypeCapsule; + m_emitParams.shapeDistScale = m_distanceScale; + m_emitParams.deltaTime = dt; + + if (m_boxMode) + { + m_emitParams.shapeType = eNvFlowShapeTypeBox; + shapeDesc[0].box.halfSize.x = 0.5f * m_capsuleLength + m_capsuleRadius; + shapeDesc[0].box.halfSize.y = m_capsuleRadius; + shapeDesc[0].box.halfSize.z = 0.5f * m_capsuleRadius; + } + + NvFlowGridEmit(m_flowGridActor.m_grid, shapeDesc, 1u, &m_emitParams, 1u); + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + } + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +void SceneSimpleFlameCapsule::imguiFluidEmitterExtra() +{ + imguiSeparatorLine(); + imguiLabel("Bar"); + imguiserBeginGroup("Bar", nullptr); + + imguiserSlider("Capsule Radius", &m_capsuleRadius, 0.f, 1.f, 0.1f, true); + imguiserSlider("Capsule Length", &m_capsuleLength, 0.f, 3.f, 0.1f, true); + imguiserSlider("Distance Scale", &m_distanceScale, 0.1f, 5.f, 0.025f, true); + + if (imguiserCheck("Box mode", m_boxMode, true)) + { + m_boxMode = !m_boxMode; + } + + imguiserEndGroup(); +}
\ No newline at end of file diff --git a/demo/DemoApp/sceneSimpleSmoke.cpp b/demo/DemoApp/sceneSimpleSmoke.cpp new file mode 100644 index 0000000..da5440d --- /dev/null +++ b/demo/DemoApp/sceneSimpleSmoke.cpp @@ -0,0 +1,399 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include <stdio.h> +#include <string.h> + +#include "loader.h" +#include "imgui.h" +#include "imguiser.h" + +namespace PresetSmoke +{ +#include "presetSmoke.h" +} +namespace PresetFireBall +{ +#include "PresetFireBall.h" +} + +#include "scene.h" + +#include <SDL.h> + +void SceneSimpleSmoke::initParams() +{ + m_flowGridActor.initParams(AppGraphCtxDedicatedVideoMemory(m_appctx)); + + // set emitter defaults + NvFlowGridEmitParamsDefaults(&m_emitParams); + + m_emitParams.bounds.x.x = 0.25f; + m_emitParams.bounds.y.y = 0.25f; + m_emitParams.bounds.z.z = 0.25f; + m_emitParams.velocityLinear.y = 8.f; + m_emitParams.fuel = 1.9f; + m_emitParams.smoke = 0.5f; + + m_emitParams.allocationPredict = 0.3f; + + // grid actor overrides + m_flowGridActor.m_renderParams.renderMode = eNvFlowVolumeRenderMode_colormap; + m_flowGridActor.m_renderMaterialDefaultParams.intensityCompMask = { 0.f, 0.f, 1.f, 0.f }; + m_flowGridActor.m_renderMaterialDefaultParams.intensityBias = 0.f; + m_flowGridActor.m_gridParams.gravity = NvFlowFloat3{ 0.f, -1.f, 0.f }; + + m_flowGridActor.m_enableVolumeShadow = true; + + m_shouldLoadPreset = true; +} + +void SceneSimpleSmoke::init(AppGraphCtx* appctx, int winw, int winh) +{ + m_appctx = appctx; + + if (!m_shouldReset || m_isFirstRun) + { + initParams(); + m_isFirstRun = false; + } + + if (m_flowGridActor.m_enableVolumeShadow) + { + m_flowGridActor.m_renderMaterialDefaultParams.intensityCompMask = { 0.f, 0.f, 1.f, 0.f }; + m_flowGridActor.m_renderMaterialDefaultParams.intensityBias = 0.f; + } + else + { + m_flowGridActor.m_renderMaterialDefaultParams.intensityCompMask = { 0.f, 0.f, 0.f, 0.f }; + m_flowGridActor.m_renderMaterialDefaultParams.intensityBias = 1.f; + } + + m_flowContext.init(appctx); + + m_flowGridActor.init(&m_flowContext, appctx); + + // create default color map + { + const int numPoints = 5; + const CurvePoint pts[numPoints] = { + { 0.f, 0.f,0.f,0.f,0.f }, + { 0.05f, 0.f,0.f,0.f,0.5f }, + { 0.6f, 213.f / 255.f,100.f / 255.f,30.f / 255.f,0.8f }, + { 0.85f, 255.f / 255.f,240.f / 255.f,0.f,0.8f }, + { 1.f, 1.f,1.f,1.f,0.7f } + }; + + auto& colorMap = m_flowGridActor.m_colorMap; + colorMap.initColorMap(m_flowContext.m_renderContext, pts, numPoints, (colorMap.m_curvePointsDefault.size() == 0)); + } + + m_projectile.init(m_appctx, m_flowContext.m_gridContext); + + resize(winw, winh); +} + +NvFlowFloat3 SceneSimpleSmoke::positionFunc(float theta) +{ + return NvFlowFloat3{ + 3.f * cosf(theta), + 0.f, + 3.f * sinf(theta) + }; +} + +NvFlowFloat3 SceneSimpleSmoke::velocityFunc(float theta, float rate) +{ + return NvFlowFloat3{ + -3.f * rate * sinf(theta), + 0.f, + +3.f * rate * cosf(theta) + }; +} + +void SceneSimpleSmoke::doUpdate(float dt) +{ + bool shouldUpdate = m_flowContext.updateBegin(); + if (shouldUpdate) + { + AppGraphCtxProfileBegin(m_appctx, "Simulate"); + + m_flowGridActor.updatePreEmit(&m_flowContext, dt); + + NvFlowShapeDesc shapeDesc; + shapeDesc.sphere.radius = 0.8f; + + if (m_animate) + { + const float pi2 = 2.f * 3.14159265f; + const float emitterScale = 1.f; + + theta += pi2 * rate * dt; + + if (theta > pi2) theta -= pi2; + + // get position and velocity + NvFlowFloat3 position = positionFunc(theta); + NvFlowFloat3 velocity = velocityFunc(theta, pi2 * rate); + + // update emitter bounds + m_emitParams.bounds.x.x = 0.25f * emitterScale; + m_emitParams.bounds.y.y = 0.25f * emitterScale; + m_emitParams.bounds.z.z = 0.25f * emitterScale; + + // modulate couple rate as a function of velocity and emitter width + const float defaultCoupleRate = 0.5f; + + float emitWidth = m_emitParams.bounds.x.x; + + float velMagn = sqrtf(velocity.x*velocity.x + velocity.y*velocity.y + velocity.z*velocity.z); + float coupleRate = fmaxf(coupleRateScale * fabsf(velMagn) / emitWidth, defaultCoupleRate); + + m_emitParams.smokeCoupleRate = coupleRate; + m_emitParams.temperatureCoupleRate = coupleRate; + m_emitParams.fuelCoupleRate = coupleRate; + m_emitParams.velocityCoupleRate = { coupleRate, coupleRate, coupleRate }; + + m_emitParams.bounds.w.x = position.x; + m_emitParams.bounds.w.y = position.y; + m_emitParams.bounds.w.z = position.z; + m_emitParams.velocityLinear.x = velocity.x; + //m_emitParams.velocityLinear.y = velocity.y; + m_emitParams.velocityLinear.z = velocity.z; + + m_emitParams.predictVelocityWeight = 1.f; + m_emitParams.predictVelocity.x = velocity.x; + //m_emitParams.predictVelocity.y = velocity.y; + m_emitParams.predictVelocity.z = velocity.z; + } + else if (m_animate != m_animateOld) + { + float coupleRate = 0.5f; + + m_emitParams.smokeCoupleRate = coupleRate; + m_emitParams.temperatureCoupleRate = coupleRate; + m_emitParams.fuelCoupleRate = coupleRate; + m_emitParams.velocityCoupleRate = { coupleRate, coupleRate, coupleRate }; + + m_emitParams.bounds.w.x = 0.f; + m_emitParams.velocityLinear.x = 0.f; + + m_emitParams.predictVelocityWeight = 0.f; + m_emitParams.predictVelocity.x = 0.f; + m_emitParams.predictVelocity.y = 0.f; + m_emitParams.predictVelocity.z = 0.f; + } + m_animateOld = m_animate; + + m_emitParams.localToWorld = m_emitParams.bounds; + m_emitParams.shapeType = eNvFlowShapeTypeSphere; + m_emitParams.deltaTime = dt; + + NvFlowGridEmit(m_flowGridActor.m_grid, &shapeDesc, 1u, &m_emitParams, 1u); + + m_projectile.update(m_flowContext.m_gridContext, m_flowGridActor.m_grid, dt); + + m_flowGridActor.updatePostEmit(&m_flowContext, dt, shouldUpdate, m_shouldGridReset); + + m_shouldGridReset = false; + + AppGraphCtxProfileEnd(m_appctx, "Simulate"); + } + m_flowContext.updateEnd(); +} + +void SceneSimpleSmoke::preDraw() +{ + m_flowContext.preDrawBegin(); + + m_flowGridActor.preDraw(&m_flowContext); + + m_flowContext.preDrawEnd(); +} + +void SceneSimpleSmoke::imguiFluidEmitterExtra() +{ + if (imguiserCheck("Animate", m_animate, true)) + { + m_animate = !m_animate; + } +} + +void SceneSimpleSmoke::imguiFluidRenderExtra() +{ +} + +void SceneSimpleSmoke::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + m_projectile.draw(projection, view); + + m_flowContext.drawBegin(); + + m_flowGridActor.draw(&m_flowContext, projection, view); + + m_flowContext.drawEnd(); +} + +void SceneSimpleSmoke::release() +{ + m_projectile.release(); + + m_flowGridActor.release(); + + m_flowContext.release(); +} + +void SceneSimpleSmoke::imgui(int xIn, int yIn, int wIn, int hIn) +{ + SceneFluid::imgui(xIn, yIn, wIn, hIn); + + if (m_shouldLoadPreset) + { + imguiserLoadC(PresetSmoke::g_root, sizeof(PresetSmoke::g_root)); + m_shouldLoadPreset = false; + } +} + +// ******************************* SceneSimpleFlameBall ************************* + +void SceneSimpleFlameBall::initParams() +{ + SceneSimpleFlame::initParams(); + + m_flowGridActor.m_gridDesc.lowLatencyMapping = true; + m_flowGridActor.m_memoryLimit = 4.f; + + m_flowGridActor.m_materialParams.smoke.allocWeight = 1.f; + m_flowGridActor.m_materialParams.smoke.allocThreshold = 0.02f; + + m_flowGridActor.m_gridParams.gravity = { 0.f, -0.5f, 0.f }; + + m_flowGridActor.m_gridParams.bigEffectMode = true; + + m_flowGridActor.m_materialParams.smoke.damping = 0.3f; + m_flowGridActor.m_materialParams.smoke.fade = 0.65f; + m_flowGridActor.m_materialParams.vorticityStrength = 20.f; + + m_emitParams.fuel = 2.0f; + m_emitParams.temperature = 3.f; + m_emitParams.smoke = 0.5f; + + m_emitParams.bounds.x.x = m_radius; + m_emitParams.bounds.y.y = m_radius; + m_emitParams.bounds.z.z = m_radius; + + m_emitParams.bounds.w.y = -2.f; + + m_emitParams.allocationScale = { 1.f, 1.f, 1.f }; + m_emitParams.allocationPredict = 0.05f; + + // grid actor overrides + m_flowGridActor.m_renderParams.renderMode = eNvFlowVolumeRenderMode_colormap; + m_flowGridActor.m_renderMaterialDefaultParams.intensityCompMask = { 0.f, 0.f, 1.f, 0.f }; + m_flowGridActor.m_renderMaterialDefaultParams.intensityBias = 0.f; + + m_flowGridActor.m_shadowBlendCompMask = { -2.f, 0.f, 0.f, 0.f }; + m_flowGridActor.m_shadowBlendBias = 1.f; + + m_flowGridActor.m_enableVolumeShadow = true; + + m_shouldLoadPreset = true; +} + +void SceneSimpleFlameBall::init(AppGraphCtx* context, int winw, int winh) +{ + SceneSimpleFlame::init(context, winw, winh); + + if (m_flowGridActor.m_enableVolumeShadow) + { + m_flowGridActor.m_renderMaterialDefaultParams.intensityCompMask = { 0.f, 0.f, 1.f, 0.f }; + m_flowGridActor.m_renderMaterialDefaultParams.intensityBias = 0.f; + } + else + { + m_flowGridActor.m_renderMaterialDefaultParams.intensityCompMask = { 0.f, 0.f, 0.f, 0.f }; + m_flowGridActor.m_renderMaterialDefaultParams.intensityBias = 1.f; + } +} + +void SceneSimpleFlameBall::doUpdate(float dt) +{ + time += dt; + + m_emitParams.bounds.x.x = m_radius; + m_emitParams.bounds.y.y = m_radius; + m_emitParams.bounds.z.z = m_radius; + + if (time < 0.25f) + { + m_emitParams.fuelCoupleRate = 0.f; + m_emitParams.velocityCoupleRate = { 0.f, 0.f, 0.f }; + m_emitParams.smokeCoupleRate = 0.f; + m_emitParams.temperatureCoupleRate = 0.f; + //m_emitParams.allocationScale = { 1.f, 1.f, 1.f }; + } + else if (time < 0.75f) + { + const float coupleRate = 5.f; + m_emitParams.fuelCoupleRate = coupleRate; + m_emitParams.velocityCoupleRate = { coupleRate, coupleRate, coupleRate }; + m_emitParams.smokeCoupleRate = coupleRate; + m_emitParams.temperatureCoupleRate = coupleRate; + //m_emitParams.allocationScale = { 1.f, 1.f, 1.f }; + } + else if (time < 4.f) + { + m_emitParams.fuelCoupleRate = 0.f; + m_emitParams.velocityCoupleRate = { 0.f, 0.f, 0.f }; + m_emitParams.smokeCoupleRate = 0.f; + m_emitParams.temperatureCoupleRate = 0.f; + //m_emitParams.allocationScale = { 0.f, 0.f, 0.f }; + } + else + { + time = 0.f; + } + + SceneSimpleFlame::doUpdate(dt); +} + +void SceneSimpleFlameBall::draw(DirectX::CXMMATRIX projection, DirectX::CXMMATRIX view) +{ + SceneSimpleFlame::draw(projection, view); +} + +void SceneSimpleFlameBall::release() +{ + SceneSimpleFlame::release(); +} + +void SceneSimpleFlameBall::imguiFluidEmitterExtra() +{ + imguiserSlider("Radius", &m_radius, 0.1f, 2.f, 0.05f, true); +} + +void SceneSimpleFlameBall::imguiFluidRenderExtra() +{ +} + +void SceneSimpleFlameBall::imguiFluidSimExtra() +{ +} + +void SceneSimpleFlameBall::imgui(int xIn, int yIn, int wIn, int hIn) +{ + SceneFluid::imgui(xIn, yIn, wIn, hIn); + + if (m_shouldLoadPreset) + { + imguiserLoadC(PresetFireBall::g_root, sizeof(PresetFireBall::g_root)); + m_shouldLoadPreset = false; + } +}
\ No newline at end of file diff --git a/demo/DemoApp/stb_truetype.h b/demo/DemoApp/stb_truetype.h new file mode 100644 index 0000000..be40bcb --- /dev/null +++ b/demo/DemoApp/stb_truetype.h @@ -0,0 +1,1839 @@ +// stb_truetype.h - v0.3 - public domain - 2009 Sean Barrett / RAD Game Tools +// +// This library processes TrueType files: +// parse files +// extract glyph metrics +// extract glyph shapes +// render glyphs to one-channel bitmaps with antialiasing (box filter) +// +// Todo: +// non-MS cmaps +// crashproof on bad data +// hinting +// subpixel positioning when rendering bitmap +// cleartype-style AA +// +// ADDITIONAL CONTRIBUTORS +// +// Mikko Mononen: compound shape support, more cmap formats +// +// VERSIONS +// +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (STB) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// +// USAGE +// +// Include this file in whatever places neeed to refer to it. In ONE C/C++ +// file, write: +// #define STB_TRUETYPE_IMPLEMENTATION +// before the #include of this file. This expands out the actual +// implementation into that C/C++ file. +// +// Look at the header-file sections below for the API, but here's a quick skim: +// +// Simple 3D API (don't ship this, but it's fine for tools and quick start, +// and you can cut and paste from it to move to more advanced) +// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture +// stbtt_GetBakedQuad() -- compute quad to draw for a given char +// +// "Load" a font file from a memory buffer (you have to keep the buffer loaded) +// stbtt_InitFont() +// stbtt_GetFontOffsetForIndex() -- use for TTC font collections +// +// Render a unicode codepoint to a bitmap +// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap +// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide +// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be +// +// Character advance/positioning +// stbtt_GetCodepointHMetrics() +// stbtt_GetFontVMetrics() +// +// NOTES +// +// The system uses the raw data found in the .ttf file without changing it +// and without building auxiliary data structures. This is a bit inefficient +// on little-endian systems (the data is big-endian), but assuming you're +// caching the bitmaps or glyph shapes this shouldn't be a big deal. +// +// It appears to be very hard to programmatically determine what font a +// given file is in a general way. I provide an API for this, but I don't +// recommend it. +// +// +// SOURCE STATISTICS (based on v0.3, 1800 LOC) +// +// Documentation & header file 350 LOC \___ 500 LOC documentation +// Sample code 140 LOC / +// Truetype parsing 580 LOC ---- 600 LOC TrueType +// Software rasterization 240 LOC \ . +// Curve tesselation 120 LOC \__ 500 LOC Bitmap creation +// Bitmap management 70 LOC / +// Baked bitmap interface 70 LOC / +// Font name matching & access 150 LOC ---- 150 +// C runtime library abstraction 60 LOC ---- 60 + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// SAMPLE PROGRAMS +//// +// +// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless +// +#if 0 +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1 << 20]; +unsigned char temp_bitmap[512 * 512]; + +stbtt_chardata cdata[96]; // ASCII 32..126 is 95 glyphs +GLstbtt_uint ftex; + +void my_stbtt_initfont(void) +{ + fread(ttf_buffer, 1, 1 << 20, fopen("c:/windows/fonts/times.ttf", "rb")); + stbtt_BakeFontBitmap(data, 0, 32.0, temp_bitmap, 512, 512, 32, 96, cdata); // no guarantee this fits! + // can free ttf_buffer at this point + glGenTextures(1, &ftex); + glBindTexture(GL_TEXTURE_2D, ftex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512, 512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); + // can free temp_bitmap at this point + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +} + +void my_stbtt_print(float x, float y, char *text) +{ + // assume orthographic projection with units = screen pixels, origin at top left + glBindTexture(GL_TEXTURE_2D, ftex); + glBegin(GL_QUADS); + while (*text) { + if (*text >= 32 && *text < 128) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad(cdata, 512, 512, *text - 32, &x, &y, &q, 1);//1=opengl,0=old d3d + glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y0); + glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y0); + glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y1); + glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y1); + } + ++text; + } + glEnd(); +} +#endif +// +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program (this compiles): get a single bitmap, print as ASCII art +// +#if 0 +#include <stdio.h> +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1 << 25]; + +int main(int argc, char **argv) +{ + stbtt_fontinfo font; + unsigned char *bitmap; + int w, h, i, j, c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); + + fread(ttf_buffer, 1, 1 << 25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); + + stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer, 0)); + bitmap = stbtt_GetCodepointBitmap(&font, 0, stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0, 0); + + for (j = 0; j < h; ++j) { + for (i = 0; i < w; ++i) + putchar(" .:ioVM@"[bitmap[j*w + i] >> 5]); + putchar('\n'); + } + return 0; +} +#endif +// +// Output: +// +// .ii. +// @@@@@@. +// V@Mio@@o +// :i. V@V +// :oM@@M +// :@@@MM@M +// @@o o@M +// :@@. M@M +// @@@o@@@@ +// :M@@V:@@. +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program: print "Hello World!" banner, with bugs +// +#if 0 +int main(int arg, char **argv) +{ + unsigned char screen[20][79]; + int i, j, pos = 0; + float scale; + char *text = "Heljo World!"; + + fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); + stbtt_InitFont(&font, buffer, 0); + + scale = stbtt_ScaleForPixelHeight(&font, 16); + memset(screen, 0, sizeof(screen)); + + while (*text) { + int advance, lsb, x0, y0, x1, y1, newpos, baseline = 13; + stbtt_GetCodepointHMetrics(&font, *text, &advance, &lsb); + stbtt_GetCodepointBitmapBox(&font, *text, scale, scale, &x0, &y0, &x1, &y1); + newpos = pos + (int)(lsb * scale) + x0; + stbtt_MakeCodepointBitmap(&font, &screen[baseline + y0][newpos], x1 - x0, y1 - y0, 79, scale, scale, *text); + // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong + // because this API is really for baking character bitmaps into textures + pos += (int)(advance * scale); + ++text; + } + + for (j = 0; j < 20; ++j) { + for (i = 0; i < 79; ++i) + putchar(" .:ioVM@"[screen[j][i] >> 5]); + putchar('\n'); + } + + return 0; +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// INTEGRATION WITH RUNTIME LIBRARIES +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION +// #define your own (u)stbtt_int8/16/32 before including to override this +#ifndef stbtt_uint8 +typedef unsigned char stbtt_uint8; +typedef signed char stbtt_int8; +typedef unsigned short stbtt_uint16; +typedef signed short stbtt_int16; +typedef unsigned int stbtt_uint32; +typedef signed int stbtt_int32; +#endif + +typedef char stbtt__check_size32[sizeof(stbtt_int32) == 4 ? 1 : -1]; +typedef char stbtt__check_size16[sizeof(stbtt_int16) == 2 ? 1 : -1]; + +// #define your own STBTT_sort() to override this to avoid qsort +#ifndef STBTT_sort +#include <stdlib.h> +#define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func) +#endif + +// #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h +#ifndef STBTT_ifloor +#include <math.h> +#define STBTT_ifloor(x) ((int) floor(x)) +#define STBTT_iceil(x) ((int) ceil(x)) +#endif + +// #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h +#ifndef STBTT_malloc +#include <malloc.h> +#define STBTT_malloc(x,u) malloc(x) +#define STBTT_free(x,u) free(x) +#endif + +#ifndef STBTT_assert +#include <assert.h> +#define STBTT_assert(x) assert(x) +#endif + +#ifndef STBTT_strlen +#include <string.h> +#define STBTT_strlen(x) strlen(x) +#endif + +#ifndef STBTT_memcpy +#include <memory.h> +#define STBTT_memcpy memcpy +#define STBTT_memset memset +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// INTERFACE +//// +//// + +#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ +#define __STB_INCLUDE_STB_TRUETYPE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + ////////////////////////////////////////////////////////////////////////////// + // + // TEXTURE BAKING API + // + // If you use this API, you only have to call two functions ever. + // + + typedef struct + { + unsigned short x0, y0, x1, y1; // coordinates of bbox in bitmap + float xoff, yoff, xadvance; + } stbtt_bakedchar; + + extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long + // if return is positive, the first unused row of the bitmap + // if return is negative, returns the negative of the number of characters that fit + // if return is 0, no characters fit and no rows were used + // This uses a very crappy packing. + + typedef struct + { + float x0, y0, s0, t0; // top-left + float x1, y1, s1, t1; // bottom-right + } stbtt_aligned_quad; + + extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier + // Call GetBakedQuad with char_index = 'character - first_char', and it + // creates the quad you need to draw and advances the current position. + // It's inefficient; you might want to c&p it and optimize it. + + + ////////////////////////////////////////////////////////////////////////////// + // + // FONT LOADING + // + // + + extern int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); + // Each .ttf file may have more than one font. Each has a sequential index + // number starting from 0. Call this function to get the font offset for a + // given index; it returns -1 if the index is out of range. A regular .ttf + // file will only define one font and it always be at offset 0, so it will + // return '0' for index 0, and -1 for all other indices. You can just skip + // this step if you know it's that kind of font. + + + // The following structure is defined publically so you can declare one on + // the stack or as a global or etc. + typedef struct + { + void *userdata; + unsigned char *data; // pointer to .ttf file + int fontstart; // offset of start of font + + int numGlyphs; // number of glyphs, needed for range checking + + int loca, head, glyf, hhea, hmtx; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph + } stbtt_fontinfo; + + extern int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); + // Given an offset into the file that defines a font, this function builds + // the necessary cached info for the rest of the system. You must allocate + // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't + // need to do anything special to free it, because the contents are a pure + // cache with no additional data structures. Returns 0 on failure. + + + ////////////////////////////////////////////////////////////////////////////// + // + // CHARACTER TO GLYPH-INDEX CONVERSIOn + + int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); + // If you're going to perform multiple operations on the same character + // and you want a speed-up, call this function with the character you're + // going to process, then use glyph-based functions instead of the + // codepoint-based functions. + + + ////////////////////////////////////////////////////////////////////////////// + // + // CHARACTER PROPERTIES + // + + extern float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); + // computes a scale factor to produce a font whose "height" is 'pixels' tall. + // Height is measured as the distance from the highest ascender to the lowest + // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics + // and computing: + // scale = pixels / (ascent - descent) + // so if you prefer to measure height by the ascent only, use a similar calculation. + + extern void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); + // ascent is the coordinate above the baseline the font extends; descent + // is the coordinate below the baseline the font extends (i.e. it is typically negative) + // lineGap is the spacing between one row's descent and the next row's ascent... + // so you should advance the vertical position by "*ascent - *descent + *lineGap" + // these are expressed in unscaled coordinates + + extern void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); + // leftSideBearing is the offset from the current horizontal position to the left edge of the character + // advanceWidth is the offset from the current horizontal position to the next horizontal position + // these are expressed in unscaled coordinates + + extern int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); + // an additional amount to add to the 'advance' value between ch1 and ch2 + // @TODO; for now always returns 0! + + extern int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); + // Gets the bounding box of the visible part of the glyph, in unscaled coordinates + + extern void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); + extern int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); + extern int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + // as above, but takes one or more glyph indices for greater efficiency + + + ////////////////////////////////////////////////////////////////////////////// + // + // GLYPH SHAPES (you probably don't need these, but they have to go before + // the bitmaps for C declaration-order reasons) + // + +#ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum { + STBTT_vmove = 1, + STBTT_vline, + STBTT_vcurve + }; +#endif + +#ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) +#define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x, y, cx, cy; + unsigned char type, padding; + } stbtt_vertex; +#endif + + extern int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); + extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); + // returns # of vertices and fills *vertices with the pointer to them + // these are expressed in "unscaled" coordinates + + extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); + // frees the data allocated above + + ////////////////////////////////////////////////////////////////////////////// + // + // BITMAP RENDERING + // + + extern void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); + // frees the bitmap allocated below + + extern unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); + // allocates a large-enough single-channel 8bpp bitmap and renders the + // specified character/glyph at the specified scale into it, with + // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). + // *width & *height are filled out with the width & height of the bitmap, + // which is stored left-to-right, top-to-bottom. + // + // xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + + extern void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); + // the same as above, but you pass in storage for the bitmap in the form + // of 'output', with row spacing of 'out_stride' bytes. the bitmap is + // clipped to out_w/out_h bytes. call the next function to get the + // height and width and positioning info + + extern void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); + // get the bbox of the bitmap centered around the glyph origin; so the + // bitmap width is ix1-ix0, height is iy1-iy0, and location to place + // the bitmap top left is (leftSideBearing*scale,iy0). + // (Note that the bitmap uses y-increases-down, but the shape uses + // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + + extern unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); + extern void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); + extern void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); + + //extern void stbtt_get_true_bbox(stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); + + // @TODO: don't expose this structure + typedef struct + { + int w, h, stride; + unsigned char *pixels; + } stbtt__bitmap; + + extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata); + + ////////////////////////////////////////////////////////////////////////////// + // + // Finding the right font... + // + // You should really just solve this offline, keep your own tables + // of what font is what, and don't try to get it out of the .ttf file. + // That's because getting it out of the .ttf file is really hard, because + // the names in the file can appear in many possible encodings, in many + // possible languages, and e.g. if you need a case-insensitive comparison, + // the details of that depend on the encoding & language in a complex way + // (actually underspecified in truetype, but also gigantic). + // + // But you can use the provided functions in two possible ways: + // stbtt_FindMatchingFont() will use *case-sensitive* comparisons on + // unicode-encoded names to try to find the font you want; + // you can run this before calling stbtt_InitFont() + // + // stbtt_GetFontNameString() lets you get any of the various strings + // from the file yourself and do your own comparisons on them. + // You have to have called stbtt_InitFont() first. + + + extern int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); + // returns the offset (not index) of the font that matches, or -1 if none + // if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". + // if you use any other flag, use a font name like "Arial"; this checks + // the 'macStyle' header field; i don't know if fonts set this consistently +#define STBTT_MACSTYLE_DONTCARE 0 +#define STBTT_MACSTYLE_BOLD 1 +#define STBTT_MACSTYLE_ITALIC 2 +#define STBTT_MACSTYLE_UNDERSCORE 4 +#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + + extern int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); + // returns 1/0 whether the first string interpreted as utf8 is identical to + // the second string interpreted as big-endian utf16... useful for strings from next func + + extern char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); + // returns the string (which may be big-endian double byte, e.g. for unicode) + // and puts the length in bytes in *length. + // + // some of the values for the IDs are below; for more see the truetype spec: + // http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html + // http://www.microsoft.com/typography/otspec/name.htm + + enum { // platformID + STBTT_PLATFORM_ID_UNICODE = 0, + STBTT_PLATFORM_ID_MAC = 1, + STBTT_PLATFORM_ID_ISO = 2, + STBTT_PLATFORM_ID_MICROSOFT = 3 + }; + + enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 = 0, + STBTT_UNICODE_EID_UNICODE_1_1 = 1, + STBTT_UNICODE_EID_ISO_10646 = 2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP = 3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL = 4, + }; + + enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL = 0, + STBTT_MS_EID_UNICODE_BMP = 1, + STBTT_MS_EID_SHIFTJIS = 2, + STBTT_MS_EID_UNICODE_FULL = 10, + }; + + enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN = 0, STBTT_MAC_EID_ARABIC = 4, + STBTT_MAC_EID_JAPANESE = 1, STBTT_MAC_EID_HEBREW = 5, + STBTT_MAC_EID_CHINESE_TRAD = 2, STBTT_MAC_EID_GREEK = 6, + STBTT_MAC_EID_KOREAN = 3, STBTT_MAC_EID_RUSSIAN = 7, + }; + + enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH = 0x0409, STBTT_MS_LANG_ITALIAN = 0x0410, + STBTT_MS_LANG_CHINESE = 0x0804, STBTT_MS_LANG_JAPANESE = 0x0411, + STBTT_MS_LANG_DUTCH = 0x0413, STBTT_MS_LANG_KOREAN = 0x0412, + STBTT_MS_LANG_FRENCH = 0x040c, STBTT_MS_LANG_RUSSIAN = 0x0419, + STBTT_MS_LANG_GERMAN = 0x0407, STBTT_MS_LANG_SPANISH = 0x0409, + STBTT_MS_LANG_HEBREW = 0x040d, STBTT_MS_LANG_SWEDISH = 0x041D, + }; + + enum { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH = 0, STBTT_MAC_LANG_JAPANESE = 11, + STBTT_MAC_LANG_ARABIC = 12, STBTT_MAC_LANG_KOREAN = 23, + STBTT_MAC_LANG_DUTCH = 4, STBTT_MAC_LANG_RUSSIAN = 32, + STBTT_MAC_LANG_FRENCH = 1, STBTT_MAC_LANG_SPANISH = 6, + STBTT_MAC_LANG_GERMAN = 2, STBTT_MAC_LANG_SWEDISH = 5, + STBTT_MAC_LANG_HEBREW = 10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED = 33, + STBTT_MAC_LANG_ITALIAN = 3, STBTT_MAC_LANG_CHINESE_TRAD = 19, + }; + +#ifdef __cplusplus +} +#endif + +#endif // __STB_INCLUDE_STB_TRUETYPE_H__ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// IMPLEMENTATION +//// +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +////////////////////////////////////////////////////////////////////////// +// +// accessors to parse data from file +// + +// on platforms that don't allow misaligned reads, if we want to allow +// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE + +#define ttBYTE(p) (* (stbtt_uint8 *) (p)) +#define ttCHAR(p) (* (stbtt_int8 *) (p)) +#define ttFixed(p) ttLONG(p) + +#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE) + +#define ttUSHORT(p) (* (stbtt_uint16 *) (p)) +#define ttSHORT(p) (* (stbtt_int16 *) (p)) +#define ttULONG(p) (* (stbtt_uint32 *) (p)) +#define ttLONG(p) (* (stbtt_int32 *) (p)) + +#else + +stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0] * 256 + p[1]; } +stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0] * 256 + p[1]; } +stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; } +stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; } + +#endif + +#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) +#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + +static int stbtt__isfont(const stbtt_uint8 *font) +{ + // check the version number + if (stbtt_tag(font, "1")) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0, 1, 0, 0)) return 1; // OpenType 1.0 + return 0; +} + +// @OPTIMIZE: binary search +static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) +{ + stbtt_int32 num_tables = ttUSHORT(data + fontstart + 4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + for (i = 0; i < num_tables; ++i) { + stbtt_uint32 loc = tabledir + 16 * i; + if (stbtt_tag(data + loc + 0, tag)) + return ttULONG(data + loc + 8); + } + return 0; +} + +int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index) +{ + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) + return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection + 4) == 0x00010000 || ttULONG(font_collection + 4) == 0x00020000) { + stbtt_int32 n = ttLONG(font_collection + 8); + if (index >= n) + return -1; + return ttULONG(font_collection + 12 + index * 14); + } + } + return -1; +} + +int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart) +{ + stbtt_uint8 *data = (stbtt_uint8 *)data2; + stbtt_uint32 cmap, t; + stbtt_int32 i, numTables; + + info->data = data; + info->fontstart = fontstart; + + cmap = stbtt__find_table(data, fontstart, "cmap"); + info->loca = stbtt__find_table(data, fontstart, "loca"); + info->head = stbtt__find_table(data, fontstart, "head"); + info->glyf = stbtt__find_table(data, fontstart, "glyf"); + info->hhea = stbtt__find_table(data, fontstart, "hhea"); + info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); + if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) + return 0; + + t = stbtt__find_table(data, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data + t + 4); + else + info->numGlyphs = 0xffff; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i = 0; i < numTables; ++i) { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch (ttUSHORT(data + encoding_record)) { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data + encoding_record + 2)) { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data + encoding_record + 4); + break; + } + break; + } + } + if (info->index_map == 0) + return 0; + + info->indexToLocFormat = ttUSHORT(data + info->head + 50); + return 1; +} + +int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +{ + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes - 6) + return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } + else if (format == 6) { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32)unicode_codepoint >= first && (stbtt_uint32)unicode_codepoint < first + count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first) * 2); + return 0; + } + else if (format == 2) { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } + else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data + index_map + 6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data + index_map + 8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data + index_map + 10); + stbtt_uint16 rangeShift = ttUSHORT(data + index_map + 12) >> 1; + stbtt_uint16 item, offset, start, end; + + (void)end; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) + return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift * 2)) + search += rangeShift * 2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) { + stbtt_uint16 start, end; + searchRange >>= 1; + start = ttUSHORT(data + search + 2 + segcount * 2 + 2); + end = ttUSHORT(data + search + 2); + start = ttUSHORT(data + search + searchRange * 2 + segcount * 2 + 2); + end = ttUSHORT(data + search + searchRange * 2); + if (unicode_codepoint > end) + search += searchRange * 2; + --entrySelector; + + (void)start; + } + search += 2; + + item = (stbtt_uint16)((search - endCount) >> 1); + + STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2 * item)); + start = ttUSHORT(data + index_map + 14 + segcount * 2 + 2 + 2 * item); + end = ttUSHORT(data + index_map + 14 + 2 + 2 * item); + if (unicode_codepoint < start) + return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount * 6 + 2 + 2 * item); + if (offset == 0) + return unicode_codepoint + ttSHORT(data + index_map + 14 + segcount * 4 + 2 + 2 * item); + + return ttUSHORT(data + offset + (unicode_codepoint - start) * 2 + index_map + 14 + segcount * 6 + 2 + 2 * item); + } + else if (format == 12) { + stbtt_uint16 ngroups = ttUSHORT(data + index_map + 6); + stbtt_int32 low, high; + low = 0; high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low <= high) { + stbtt_int32 mid = low + ((high - low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data + index_map + 16 + mid * 12); + stbtt_uint32 end_char = ttULONG(data + index_map + 16 + mid * 12 + 4); + if ((stbtt_uint32)unicode_codepoint < start_char) + high = mid - 1; + else if ((stbtt_uint32)unicode_codepoint > end_char) + low = mid + 1; + else { + stbtt_uint32 start_glyph = ttULONG(data + index_map + 16 + mid * 12 + 8); + return start_glyph + unicode_codepoint - start_char; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; +} + +int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) +{ + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); +} + +static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int16 x, stbtt_int16 y, stbtt_int16 cx, stbtt_int16 cy) +{ + v->type = type; + v->x = x; + v->y = y; + v->cx = cx; + v->cy = cy; +} + +static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) +{ + int g1, g2; + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + + if (info->indexToLocFormat == 0) { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } + else { + g1 = info->glyf + ttULONG(info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG(info->data + info->loca + glyph_index * 4 + 4); + } + + return g1 == g2 ? -1 : g1; // if length is 0, return -1 +} + +int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + return 1; +} + +int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +{ + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info, codepoint), x0, y0, x1, y1); +} + +int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + stbtt_int16 numberOfContours; + stbtt_uint8 *endPtsOfContours; + stbtt_uint8 *data = info->data; + stbtt_vertex *vertices = 0; + int num_vertices = 0; + int g = stbtt__GetGlyfOffset(info, glyph_index); + + *pvertices = NULL; + + if (g < 0) return 0; + + numberOfContours = ttSHORT(data + g); + + if (numberOfContours > 0) { + stbtt_uint8 flags = 0, flagcount; + stbtt_int32 ins, i, j = 0, m, n, next_move, was_off = 0, off; + stbtt_int16 x, y, cx, cy, sx, sy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; + + n = 1 + ttUSHORT(endPtsOfContours + numberOfContours * 2 - 2); + + m = n + numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *)STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) + return 0; + + next_move = 0; + flagcount = 0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i = 0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } + else + --flagcount; + vertices[off + i].type = flags; + } + + // now load x coordinates + x = 0; + for (i = 0; i < n; ++i) { + flags = vertices[off + i].type; + if (flags & 2) { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } + else { + if (!(flags & 16)) { + x = x + (stbtt_int16)(points[0] * 256 + points[1]); + points += 2; + } + } + vertices[off + i].x = x; + } + + // now load y coordinates + y = 0; + for (i = 0; i < n; ++i) { + flags = vertices[off + i].type; + if (flags & 4) { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } + else { + if (!(flags & 32)) { + y = y + (stbtt_int16)(points[0] * 256 + points[1]); + points += 2; + } + } + vertices[off + i].y = y; + } + + // now convert them to our format + num_vertices = 0; + sx = sy = cx = cy = 0; + for (i = 0; i < n; ++i) { + flags = vertices[off + i].type; + x = (stbtt_int16)vertices[off + i].x; + y = (stbtt_int16)vertices[off + i].y; + if (next_move == i) { + // when we get to the end, we have to close the shape explicitly + if (i != 0) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx, sy, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, sx, sy, 0, 0); + } + + // now start the new one + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove, x, y, 0, 0); + next_move = 1 + ttUSHORT(endPtsOfContours + j * 2); + ++j; + was_off = 0; + sx = x; + sy = y; + } + else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx + x) >> 1, (cy + y) >> 1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } + else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x, y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x, y, 0, 0); + was_off = 0; + } + } + } + if (i != 0) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx, sy, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, sx, sy, 0, 0); + } + } + else if (numberOfContours == -1) { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + num_vertices = 0; + vertices = 0; + while (more) { + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + stbtt_vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = { 1,0,0,1,0,0 }, m, n; + + flags = ttSHORT(comp); comp += 2; + gidx = ttSHORT(comp); comp += 2; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + mtx[4] = ttSHORT(comp); comp += 2; + mtx[5] = ttSHORT(comp); comp += 2; + } + else { + mtx[4] = ttCHAR(comp); comp += 1; + mtx[5] = ttCHAR(comp); comp += 1; + } + } + else { + // @TODO handle matching point + STBTT_assert(0); + } + if (flags & (1 << 3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp) / 16384.0f; comp += 2; + mtx[1] = mtx[2] = 0; + } + else if (flags & (1 << 6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp) / 16384.0f; comp += 2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp) / 16384.0f; comp += 2; + } + else if (flags & (1 << 7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp) / 16384.0f; comp += 2; + mtx[1] = ttSHORT(comp) / 16384.0f; comp += 2; + mtx[2] = ttSHORT(comp) / 16384.0f; comp += 2; + mtx[3] = ttSHORT(comp) / 16384.0f; comp += 2; + } + + // Find transformation scales. + m = (float)sqrt(mtx[0] * mtx[0] + mtx[1] * mtx[1]); + n = (float)sqrt(mtx[2] * mtx[2] + mtx[3] * mtx[3]); + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + if (comp_num_verts > 0) { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + stbtt_vertex_type x, y; + x = v->x; y = v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0] * x + mtx[2] * y + mtx[4])); + v->y = (stbtt_vertex_type)(n * (mtx[1] * x + mtx[3] * y + mtx[5])); + x = v->cx; y = v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0] * x + mtx[2] * y + mtx[4])); + v->cy = (stbtt_vertex_type)(n * (mtx[1] * x + mtx[3] * y + mtx[5])); + } + // Append vertices. + tmp = (stbtt_vertex*)STBTT_malloc((num_vertices + comp_num_verts)*sizeof(stbtt_vertex), info->userdata); + if (!tmp) { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0) memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + memcpy(tmp + num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1 << 5); + } + } + else if (numberOfContours < 0) { + // @TODO other compound variations? + STBTT_assert(0); + } + else { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; +} + +void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +{ + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data + info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4 * glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4 * glyph_index + 2); + } + else { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4 * (numOfLongHorMetrics - 1)); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4 * numOfLongHorMetrics + 2 * (glyph_index - numOfLongHorMetrics)); + } +} + +int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo * /*info*/, int /*glyph1*/, int /*glyph2*/) +{ + return 0; +} + +int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo * /*info*/, int /*ch1*/, int /*ch2*/) +{ + return 0; +} + +void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +{ + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info, codepoint), advanceWidth, leftSideBearing); +} + +void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +{ + if (ascent) *ascent = ttSHORT(info->data + info->hhea + 4); + if (descent) *descent = ttSHORT(info->data + info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data + info->hhea + 8); +} + +float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float)height / fheight; +} + +void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +{ + STBTT_free(v, info->userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// antialiasing software rasterizer +// + +void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0, y0, x1, y1; + if (!stbtt_GetGlyphBox(font, glyph, &x0, &y0, &x1, &y1)) + x0 = y0 = x1 = y1 = 0; // e.g. space character + // now move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x); + if (iy0) *iy0 = -STBTT_iceil(y1 * scale_y); + if (ix1) *ix1 = STBTT_iceil(x1 * scale_x); + if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y); +} + +void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBox(font, stbtt_FindGlyphIndex(font, codepoint), scale_x, scale_y, ix0, iy0, ix1, iy1); +} + +typedef struct stbtt__edge { + float x0, y0, x1, y1; + int invert; +} stbtt__edge; + +typedef struct stbtt__active_edge +{ + int x, dx; + float ey; + struct stbtt__active_edge *next; + int valid; +} stbtt__active_edge; + +#define FIXSHIFT 10 +#define FIX (1 << FIXSHIFT) +#define FIXMASK (FIX-1) + +static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *)STBTT_malloc(sizeof(*z), userdata); // @TODO: make a pool of these!!! + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(e->y0 <= start_point); + if (!z) return z; + // round dx down to avoid going too far + if (dxdy < 0) + z->dx = -STBTT_ifloor(FIX * -dxdy); + else + z->dx = STBTT_ifloor(FIX * dxdy); + z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0))); + z->x -= off_x * FIX; + z->ey = e->y1; + z->next = 0; + z->valid = e->invert ? 1 : -1; + return z; +} + +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) +{ + // non-zero winding fill + int x0 = 0, w = 0; + + while (e) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->valid; + } + else { + int x1 = e->x; w += e->valid; + // if we went to zero, we need to draw + if (w == 0) { + int i = x0 >> FIXSHIFT; + int j = x1 >> FIXSHIFT; + + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8)((x1 - x0) * max_weight >> FIXSHIFT); + } + else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = scanline[i] + (stbtt_uint8)(((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8)(((x1 & FIXMASK) * max_weight) >> FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8)max_weight; + } + } + } + } + + e = e->next; + } +} + +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__active_edge *active = NULL; + int y, j = 0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *)STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float)vsubsample + 1; + + while (j < result->h) { + STBTT_memset(scanline, 0, result->w); + for (s = 0; s < vsubsample; ++s) { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y) { + *step = z->next; // delete from list + STBTT_assert(z->valid); + z->valid = 0; + STBTT_free(z, userdata); + } + else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for (;;) { + int changed = 0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) { + if (e->y1 > scan_y) { + stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata); + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } + else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + ++e; + } + + // now process all active edges in XOR fashion + if (active) + stbtt__fill_active_edges(scanline, result->w, active, max_weight); + + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } + + while (active) { + stbtt__active_edge *z = active; + active = active->next; + STBTT_free(z, userdata); + } + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} + +static int stbtt__edge_compare(const void *p, const void *q) +{ + stbtt__edge *a = (stbtt__edge *)p; + stbtt__edge *b = (stbtt__edge *)q; + + if (a->y0 < b->y0) return -1; + if (a->y0 > b->y0) return 1; + return 0; +} + +typedef struct +{ + float x, y; +} stbtt__point; + +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n, i, j, k, m; + int vsubsample = result->h < 8 ? 15 : 5; + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i = 0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *)STBTT_malloc(sizeof(*e) * (n + 1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m = 0; + for (i = 0; i < windings; ++i) { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i] - 1; + for (k = 0; k < wcount[i]; j = k++) { + int a = k, b = j; + // skip the edge if horizontal + if (p[j].y == p[k].y) + continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { + e[n].invert = 1; + a = j, b = k; + } + e[n].x0 = p[a].x * scale_x; + e[n].y0 = p[a].y * y_scale_inv * vsubsample; + e[n].x1 = p[b].x * scale_x; + e[n].y1 = p[b].y * y_scale_inv * vsubsample; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); +} + +static void stbtt__add_point(stbtt__point *points, int n, float x, float y) +{ + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; +} + +// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2 * x1 + x2) / 4; + float my = (y0 + 2 * y1 + y2) / 4; + // versus directly drawn line + float dx = (x0 + x2) / 2 - mx; + float dy = (y0 + y2) / 2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx*dx + dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0, y0, (x0 + x1) / 2.0f, (y0 + y1) / 2.0f, mx, my, objspace_flatness_squared, n + 1); + stbtt__tesselate_curve(points, num_points, mx, my, (x1 + x2) / 2.0f, (y1 + y2) / 2.0f, x2, y2, objspace_flatness_squared, n + 1); + } + else { + stbtt__add_point(points, *num_points, x2, y2); + *num_points = *num_points + 1; + } + return 1; +} + +// returns number of contours +stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +{ + stbtt__point *points = 0; + int num_points = 0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i, n = 0, start = 0, pass; + + // count how many "moves" there are to get the contour count + for (i = 0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) + ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *)STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass = 0; pass < 2; ++pass) { + float x = 0, y = 0; + if (pass == 1) { + points = (stbtt__point *)STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n = -1; + for (i = 0; i < num_verts; ++i) { + switch (vertices[i].type) { + case STBTT_vmove: + // start the next contour + if (n >= 0) + (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vline: + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vcurve: + stbtt__tesselate_curve(points, &num_points, x, y, + vertices[i].cx, vertices[i].cy, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } + + return points; +error: + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count, *winding_lengths; + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, x_off, y_off, invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } +} + +void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + int ix0, iy0, ix1, iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) return NULL; + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0, &iy0, &ix1, &iy1); + + // now we get the size + gbm.w = (ix1 - ix0); + gbm.h = (iy1 - iy0); + gbm.pixels = NULL; // in case we error + + if (width) *width = gbm.w; + if (height) *height = gbm.h; + if (xoff) *xoff = ix0; + if (yoff) *yoff = iy0; + + if (gbm.w && gbm.h) { + gbm.pixels = (unsigned char *)STBTT_malloc(gbm.w * gbm.h, info->userdata); + if (gbm.pixels) { + gbm.stride = gbm.w; + + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0, iy0, 1, info->userdata); + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} + +void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +{ + int ix0, iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + stbtt__bitmap gbm; + + stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0, &iy0, 0, 0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; + + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0, iy0, 1, info->userdata); + + STBTT_free(vertices, info->userdata); +} + +unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmap(info, scale_x, scale_y, stbtt_FindGlyphIndex(info, codepoint), width, height, xoff, yoff); +} + +void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +{ + stbtt_MakeGlyphBitmap(info, output, out_w, out_h, out_stride, scale_x, scale_y, stbtt_FindGlyphIndex(info, codepoint)); +} + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-SHITTY packing to keep source code small + +extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x, y, bottom_y, i; + stbtt_fontinfo f; + stbtt_InitFont(&f, data, offset); + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + x = y = 1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i = 0; i < num_chars; ++i) { + int advance, lsb, x0, y0, x1, y1, gw, gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale, scale, &x0, &y0, &x1, &y1); + gw = x1 - x0; + gh = y1 - y0; + if (x + gw + 1 >= pw) + y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x + gw < pw); + STBTT_assert(y + gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels + x + y*pw, gw, gh, pw, scale, scale, g); + chardata[i].x0 = (stbtt_int16)x; + chardata[i].y0 = (stbtt_int16)y; + chardata[i].x1 = (stbtt_int16)(x + gw); + chardata[i].y1 = (stbtt_int16)(y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float)x0; + chardata[i].yoff = (float)y0; + x = x + gw + 2; + if (y + gh + 2 > bottom_y) + bottom_y = y + gh + 2; + } + return bottom_y; +} + +void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +{ + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5); + + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * ipw; + q->s1 = b->x1 * iph; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// font name matching -- recommended not to use this +// + +// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +{ + stbtt_int32 i = 0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) { + stbtt_uint16 ch = s2[0] * 256 + s2[1]; + if (ch < 0x80) { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } + else if (ch < 0x800) { + if (i + 1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } + else if (ch >= 0xd800 && ch < 0xdc00) { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2] * 256 + s2[3]; + if (i + 3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c)& 0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } + else if (ch >= 0xdc00 && ch < 0xe000) { + return -1; + } + else { + if (i + 2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch)& 0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; +} + +int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*)s1, len1, (stbtt_uint8*)s2, len2); +} + +// returns results in whatever encoding you request... but note that 2-byte encodings +// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare +char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +{ + stbtt_int32 i, count, stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc + nm + 2); + stringOffset = nm + ttUSHORT(fc + nm + 4); + for (i = 0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc + loc + 0) && encodingID == ttUSHORT(fc + loc + 2) + && languageID == ttUSHORT(fc + loc + 4) && nameID == ttUSHORT(fc + loc + 6)) { + *length = ttUSHORT(fc + loc + 8); + return (char *)(fc + stringOffset + ttUSHORT(fc + loc + 10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc + nm + 2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc + nm + 4); + + for (i = 0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc + loc + 6); + if (id == target_id) { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc + loc + 0), encoding = ttUSHORT(fc + loc + 2), language = ttUSHORT(fc + loc + 4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { + stbtt_int32 slen = ttUSHORT(fc + loc + 8), off = ttUSHORT(fc + loc + 10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc + stringOffset + off, slen); + if (matchlen >= 0) { + // check for target_id+1 immediately following, with same encoding & language + if (i + 1 < count && ttUSHORT(fc + loc + 12 + 6) == next_id && ttUSHORT(fc + loc + 12) == platform && ttUSHORT(fc + loc + 12 + 2) == encoding && ttUSHORT(fc + loc + 12 + 4) == language) { + stbtt_int32 slen = ttUSHORT(fc + loc + 12 + 8), off = ttUSHORT(fc + loc + 12 + 10); + if (slen == 0) { + if (matchlen == nlen) + return 1; + } + else if (matchlen < nlen && name[matchlen] == ' ') { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian((char*)(name + matchlen), nlen - matchlen, (char*)(fc + stringOffset + off), slen)) + return 1; + } + } + else { + // if nothing immediately following + if (matchlen == nlen) + return 1; + } + } + } + + // @TODO handle other encodings + } + } + return 0; +} + +static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) +{ + stbtt_int32 nlen = STBTT_strlen((char *)name); + stbtt_uint32 nm, hd; + if (!stbtt__isfont(fc + offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) { + hd = stbtt__find_table(fc, offset, "head"); + if ((ttUSHORT(fc + hd + 44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return 0; + + if (flags) { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + else { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; +} + +int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags) +{ + stbtt_int32 i; + for (i = 0;; ++i) { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0) return off; + if (stbtt__matches((stbtt_uint8 *)font_collection, off, (stbtt_uint8*)name_utf8, flags)) + return off; + } +} + +#endif // STB_TRUETYPE_IMPLEMENTATION
\ No newline at end of file diff --git a/demo/DemoAppD3D11/DemoAppD3D11.vcxproj b/demo/DemoAppD3D11/DemoAppD3D11.vcxproj new file mode 100644 index 0000000..b3b19b3 --- /dev/null +++ b/demo/DemoAppD3D11/DemoAppD3D11.vcxproj @@ -0,0 +1,269 @@ +<?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="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Condition="'$(Platform)'=='Win32'"> + <PlatformName>win32</PlatformName> + </PropertyGroup> + <PropertyGroup Condition="'$(Platform)'=='x64'"> + <PlatformName>win64</PlatformName> + </PropertyGroup> + <ItemGroup> + <ClCompile Include="appD3D11Ctx.cpp" /> + <ClCompile Include="computeContextD3D11.cpp" /> + <ClCompile Include="imguiGraphD3D11.cpp" /> + <ClCompile Include="imguiInteropD3D11.cpp" /> + <ClCompile Include="meshD3D11.cpp" /> + <ClCompile Include="meshInteropD3D11.cpp" /> + <ClCompile Include="NvFlowInteropD3D11.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="appD3D11Ctx.h" /> + <ClInclude Include="computeContextD3D11.h" /> + <ClInclude Include="imguiGraphD3D11.h" /> + <ClInclude Include="meshD3D11.h" /> + </ItemGroup> + <ItemGroup> + <FxCompile Include="..\Shaders\imguiPS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType> + </FxCompile> + <FxCompile Include="..\Shaders\imguiVS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Vertex</ShaderType> + </FxCompile> + <FxCompile Include="..\Shaders\meshPS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType> + </FxCompile> + <FxCompile Include="..\Shaders\meshVS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Vertex</ShaderType> + </FxCompile> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{A8C5329D-82CC-4D1A-971C-243B65AA3D7B}</ProjectGuid> + <RootNamespace>DemoAppD3D11</RootNamespace> + <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup 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" /> + </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)'=='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|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|x64'"> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlowContextD3D11;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win64;$(SolutionDir)external\SDL2\lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlowContextD3D11;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win64;$(SolutionDir)external\SDL2\lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlowContextD3D11;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win32;$(SolutionDir)external\SDL2\lib\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86</LibraryPath> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlowContextD3D11;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win32;$(SolutionDir)external\SDL2\lib\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86</LibraryPath> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <FxCompile> + <EntryPointName>%(Filename)</EntryPointName> + </FxCompile> + <FxCompile> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <FxCompile> + <VariableName> + </VariableName> + </FxCompile> + <FxCompile> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + </FxCompile> + <FxCompile> + <ObjectFileOutput /> + </FxCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <FxCompile> + <EntryPointName>%(Filename)</EntryPointName> + </FxCompile> + <FxCompile> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <FxCompile> + <VariableName> + </VariableName> + </FxCompile> + <FxCompile> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + </FxCompile> + <FxCompile> + <ObjectFileOutput /> + </FxCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <FxCompile> + <EntryPointName>%(Filename)</EntryPointName> + </FxCompile> + <FxCompile> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <FxCompile> + <VariableName> + </VariableName> + </FxCompile> + <FxCompile> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + </FxCompile> + <FxCompile> + <ObjectFileOutput /> + </FxCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <FxCompile> + <EntryPointName>%(Filename)</EntryPointName> + </FxCompile> + <FxCompile> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <FxCompile> + <VariableName> + </VariableName> + </FxCompile> + <FxCompile> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + </FxCompile> + <FxCompile> + <ObjectFileOutput /> + </FxCompile> + </ItemDefinitionGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/demo/DemoAppD3D11/DemoAppD3D11.vcxproj.filters b/demo/DemoAppD3D11/DemoAppD3D11.vcxproj.filters new file mode 100644 index 0000000..469e1e0 --- /dev/null +++ b/demo/DemoAppD3D11/DemoAppD3D11.vcxproj.filters @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Shaders"> + <UniqueIdentifier>{154d623a-ffac-4ddd-a878-c4dc912a750d}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="appD3D11Ctx.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="imguiGraphD3D11.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="meshD3D11.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="NvFlowInteropD3D11.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="meshInteropD3D11.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="imguiInteropD3D11.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="computeContextD3D11.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="appD3D11Ctx.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="imguiGraphD3D11.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="meshD3D11.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="computeContextD3D11.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <FxCompile Include="..\Shaders\imguiPS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + <FxCompile Include="..\Shaders\imguiVS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + <FxCompile Include="..\Shaders\meshPS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + <FxCompile Include="..\Shaders\meshVS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/demo/DemoAppD3D11/NvFlowInteropD3D11.cpp b/demo/DemoAppD3D11/NvFlowInteropD3D11.cpp new file mode 100644 index 0000000..23aaf9c --- /dev/null +++ b/demo/DemoAppD3D11/NvFlowInteropD3D11.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <d3d11.h> + +#include "../DemoApp/NvFlowInterop.h" + +#include "NvFlowContextD3D11.h" +#include "appD3D11Ctx.h" + +NvFlowContext* NvFlowInteropCreateContext(AppGraphCtx* appctx) +{ + NvFlowContextDescD3D11 desc = {}; + desc.device = appctx->m_device; + desc.deviceContext = appctx->m_deviceContext; + return NvFlowCreateContextD3D11(NV_FLOW_VERSION, &desc); +} + +NvFlowDepthStencilView* NvFlowInteropCreateDepthStencilView(AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + NvFlowDepthStencilViewDescD3D11 desc = {}; + desc.dsv = appctx->m_dsv; + desc.srv = appctx->m_depthSRV; + desc.viewport = appctx->m_viewport; + return NvFlowCreateDepthStencilViewD3D11(flowctx, &desc); +} + +NvFlowRenderTargetView* NvFlowInteropCreateRenderTargetView(AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + NvFlowRenderTargetViewDescD3D11 desc = {}; + desc.rtv = appctx->m_rtv; + desc.viewport = appctx->m_viewport; + return NvFlowCreateRenderTargetViewD3D11(flowctx, &desc); +} + +void NvFlowInteropUpdateContext(NvFlowContext* context, AppGraphCtx* appctx) +{ + NvFlowContextDescD3D11 desc = {}; + desc.device = appctx->m_device; + desc.deviceContext = appctx->m_deviceContext; + NvFlowUpdateContextD3D11(context, &desc); +} + +void NvFlowInteropUpdateDepthStencilView(NvFlowDepthStencilView* view, AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + NvFlowDepthStencilViewDescD3D11 desc = {}; + desc.dsv = appctx->m_dsv; + desc.srv = appctx->m_depthSRV; + desc.viewport = appctx->m_viewport; + NvFlowUpdateDepthStencilViewD3D11(flowctx, view, &desc); +} + +void NvFlowInteropUpdateRenderTargetView(NvFlowRenderTargetView* view, AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + NvFlowRenderTargetViewDescD3D11 desc = {}; + desc.rtv = appctx->m_rtv; + desc.viewport = appctx->m_viewport; + NvFlowUpdateRenderTargetViewD3D11(flowctx, view, &desc); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D11/appD3D11Ctx.cpp b/demo/DemoAppD3D11/appD3D11Ctx.cpp new file mode 100644 index 0000000..959614c --- /dev/null +++ b/demo/DemoAppD3D11/appD3D11Ctx.cpp @@ -0,0 +1,766 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +//direct3d headers +#include <d3d11.h> +#include <dxgi.h> + +// include the Direct3D Library file +#pragma comment (lib, "d3d11.lib") +#pragma comment (lib, "DXGI.lib") + +#include "appD3D11Ctx.h" + +#include <stdio.h> + +#include <SDL.h> +#include <SDL_video.h> +#include <SDL_syswm.h> + +namespace +{ + // COM object release utilities + template <class T> + void inline COMRelease(T& t) + { + if (t) t->Release(); + t = nullptr; + } + + template <class T> + void inline COMRelease(T& t, UINT arraySize) + { + for (UINT i = 0; i < arraySize; i++) + { + if (t[i]) t[i]->Release(); + t[i] = nullptr; + } + } +} + +AppGraphProfiler* appGraphCreateProfiler(AppGraphCtx* ctx); +void appGraphProfilerFrameBegin(AppGraphProfiler* profiler); +void appGraphProfilerFrameEnd(AppGraphProfiler* profiler); +void appGraphProfilerEnable(AppGraphProfiler* profiler, bool enabled); +void appGraphProfilerBegin(AppGraphProfiler* profiler, const char* label); +void appGraphProfilerEnd(AppGraphProfiler* profiler, const char* label); +bool appGraphProfilerGet(AppGraphProfiler* profiler, const char** plabel, float* cpuTime, float* gpuTime, int index); +void appGraphReleaseProfiler(AppGraphProfiler* profiler); + +void AppGraphCtxInitRenderTarget(AppGraphCtx* context, SDL_Window* window, bool fullscreen); + +AppGraphCtx::AppGraphCtx() +{ + m_profiler = appGraphCreateProfiler(this); +} + +AppGraphCtx::~AppGraphCtx() +{ + AppGraphCtxReleaseRenderTarget(this); + + COMRelease(m_device); + COMRelease(m_deviceContext); + COMRelease(m_depthState); + + appGraphReleaseProfiler(m_profiler); + m_profiler = nullptr; +} + +AppGraphCtx* AppGraphCtxCreate(int deviceID) +{ + AppGraphCtx* context = new AppGraphCtx; + + HRESULT hr = S_OK; + + // enumerate devices + IDXGIFactory1* pFactory = NULL; + CreateDXGIFactory1(IID_PPV_ARGS(&pFactory)); + IDXGIAdapter1* pAdapterTemp = NULL; + IDXGIAdapter1* pAdapter = NULL; + DXGI_ADAPTER_DESC1 adapterDesc; + int adapterIdx = 0; + while (S_OK == pFactory->EnumAdapters1(adapterIdx, &pAdapterTemp)) + { + pAdapterTemp->GetDesc1(&adapterDesc); + + context->m_dedicatedVideoMemory = (size_t)adapterDesc.DedicatedVideoMemory; + + if (deviceID == adapterIdx) + { + pAdapter = pAdapterTemp; + break; + } + else + { + pAdapterTemp->Release(); + } + adapterIdx++; + } + + D3D_DRIVER_TYPE driverTypes[] = + { + D3D_DRIVER_TYPE_UNKNOWN, + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + D3D_DRIVER_TYPE_REFERENCE, + }; + UINT numDriverTypes = 4; + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + UINT numFeatureLevels = 4; + + UINT createDeviceFlags = 0; +#ifdef _DEBUG + createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; +#endif + + for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) + { + D3D_FEATURE_LEVEL featureLevel; + D3D_DRIVER_TYPE driverType = driverTypes[driverTypeIndex]; + hr = D3D11CreateDevice(pAdapter, driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, + D3D11_SDK_VERSION, &context->m_device, &featureLevel, &context->m_deviceContext); + if (SUCCEEDED(hr)) + { + break; + } + } + if (FAILED(hr)) + { + delete context; + return nullptr; + } + + // cleanup adapter and factory + COMRelease(pAdapter); + COMRelease(pFactory); + + // create depth state + D3D11_DEPTH_STENCIL_DESC depthStateDesc = {}; + depthStateDesc.DepthEnable = TRUE; + depthStateDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStateDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; + + if (hr = context->m_device->CreateDepthStencilState(&depthStateDesc, &context->m_depthState)) + { + delete context; + return nullptr; + } + + return context; +} + +bool AppGraphCtxUpdateSize(AppGraphCtx* context, SDL_Window* window, bool fullscreen) +{ + // TODO: fix iflip fullscreen support + fullscreen = false; + + bool sizeChanged = false; + + // sync with window + { + HWND hWnd = nullptr; + // get Windows handle to this SDL window + SDL_SysWMinfo winInfo; + SDL_VERSION(&winInfo.version); + if (SDL_GetWindowWMInfo(window, &winInfo)) + { + if (winInfo.subsystem == SDL_SYSWM_WINDOWS) + { + hWnd = winInfo.info.win.window; + } + } + context->m_hWnd = hWnd; + context->m_fullscreen = fullscreen; + + HRESULT hr = S_OK; + + RECT rc; + GetClientRect(context->m_hWnd, &rc); + UINT width = rc.right - rc.left; + UINT height = rc.bottom - rc.top; + + if (context->m_winW != width || context->m_winH != height) + { + context->m_winW = width; + context->m_winH = height; + sizeChanged = true; + context->m_valid = (context->m_winW != 0 && context->m_winH != 0); + } + } + + if (sizeChanged) + { + AppGraphCtxReleaseRenderTarget(context); + } + if (sizeChanged && context->m_valid) + { + AppGraphCtxInitRenderTarget(context, window, fullscreen); + } + + return context->m_valid; +} + +void AppGraphCtxInitRenderTarget(AppGraphCtx* context, SDL_Window* window, bool fullscreen) +{ + HWND hWnd = nullptr; + // get Windows handle to this SDL window + SDL_SysWMinfo winInfo; + SDL_VERSION(&winInfo.version); + if (SDL_GetWindowWMInfo(window, &winInfo)) + { + if (winInfo.subsystem == SDL_SYSWM_WINDOWS) + { + hWnd = winInfo.info.win.window; + } + } + context->m_hWnd = hWnd; + context->m_fullscreen = fullscreen; + + HRESULT hr = S_OK; + + // enumerate devices + IDXGIFactory1* pFactory = NULL; + CreateDXGIFactory1(IID_PPV_ARGS(&pFactory)); + + // create the swap chain + for (int i = 0; i < 2; i++) + { + DXGI_SWAP_CHAIN_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.BufferCount = 1; + desc.BufferDesc.Width = context->m_winW; + desc.BufferDesc.Height = context->m_winH; + desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.BufferDesc.RefreshRate.Numerator = 0; + desc.BufferDesc.RefreshRate.Denominator = 0; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // DXGI_SWAP_EFFECT_FLIP_DISCARD; + desc.OutputWindow = context->m_hWnd; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Windowed = TRUE; // m_fullscreen ? FALSE : TRUE; + desc.Flags = 0u; + + if (hr = pFactory->CreateSwapChain(context->m_device, &desc, (IDXGISwapChain**)&context->m_swapChain)) + { + COMRelease(context->m_swapChain); + context->m_fullscreen = false; + continue; + } + + if (!context->m_fullscreen) + { + + } + else + { + hr = context->m_swapChain->SetFullscreenState(true, nullptr); + if (hr != S_OK) + { + COMRelease(context->m_swapChain); + context->m_fullscreen = false; + continue; + } + DXGI_SWAP_CHAIN_DESC desc = {}; + context->m_swapChain->GetDesc(&desc); + context->m_swapChain->ResizeBuffers(1, context->m_winW, context->m_winH, desc.BufferDesc.Format, desc.Flags); + } + break; + } + + // configure scissor and viewport + { + context->m_viewport.Width = float(context->m_winW); + context->m_viewport.Height = float(context->m_winH); + context->m_viewport.MaxDepth = 1.f; + } + + COMRelease(pFactory); + + // Create a render target view + ID3D11Texture2D* pBackBuffer = NULL; + hr = context->m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); + if (FAILED(hr)) + { + return; + } + + hr = context->m_device->CreateRenderTargetView(pBackBuffer, NULL, &context->m_rtv); + pBackBuffer->Release(); + if (FAILED(hr)) + { + return; + } + + context->m_deviceContext->OMSetRenderTargets(1, &context->m_rtv, NULL); + + // viewport + context->m_deviceContext->RSSetViewports(1, &context->m_viewport); + + { + D3D11_TEXTURE2D_DESC texDesc = {}; + texDesc.Width = context->m_winW; + texDesc.Height = context->m_winH; + texDesc.MipLevels = 1; + texDesc.ArraySize = 1; + texDesc.Format = DXGI_FORMAT_R32_TYPELESS; // DXGI_FORMAT_R24G8_TYPELESS + texDesc.SampleDesc.Count = 1; + texDesc.SampleDesc.Quality = 0u; + texDesc.Usage = D3D11_USAGE_DEFAULT; + texDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; + texDesc.CPUAccessFlags = 0; + texDesc.MiscFlags = 0; + + if (hr = context->m_device->CreateTexture2D(&texDesc, nullptr, &context->m_depthStencil)) + { + return; + } + + D3D11_DEPTH_STENCIL_VIEW_DESC viewDesc = {}; + viewDesc.Format = DXGI_FORMAT_D32_FLOAT; + viewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + viewDesc.Flags = 0u; + viewDesc.Texture2D.MipSlice = 0; + + if (hr = context->m_device->CreateDepthStencilView(context->m_depthStencil, &viewDesc, &context->m_dsv)) + { + return; + } + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Format = DXGI_FORMAT_R32_FLOAT; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + srvDesc.Texture2D.MostDetailedMip = 0; + + if (hr = context->m_device->CreateShaderResourceView(context->m_depthStencil, &srvDesc, &context->m_depthSRV)) + { + return; + } + } +} + +void AppGraphCtxReleaseRenderTarget(AppGraphCtx* context) +{ + if (context->m_swapChain == nullptr) + { + return; + } + + BOOL bFullscreen = FALSE; + context->m_swapChain->GetFullscreenState(&bFullscreen, nullptr); + if (bFullscreen == TRUE) context->m_swapChain->SetFullscreenState(FALSE, nullptr); + + COMRelease(context->m_swapChain); + COMRelease(context->m_rtv); + COMRelease(context->m_depthStencil); + COMRelease(context->m_dsv); + COMRelease(context->m_depthSRV); + + context->m_valid = false; + context->m_winW = 0u; + context->m_winH = 0u; +} + +void AppGraphCtxRelease(AppGraphCtx* context) +{ + if (context == nullptr) return; + + delete context; +} + +void AppGraphCtxFrameStart(AppGraphCtx* context, float clearColor[4]) +{ + appGraphProfilerFrameBegin(context->m_profiler); + + context->m_deviceContext->RSSetViewports(1, &context->m_viewport); + context->m_deviceContext->RSSetScissorRects(0, nullptr); + + context->m_deviceContext->OMSetRenderTargets(1, &context->m_rtv, context->m_dsv); + + context->m_deviceContext->ClearRenderTargetView(context->m_rtv, clearColor); + context->m_deviceContext->ClearDepthStencilView(context->m_dsv, D3D11_CLEAR_DEPTH, 1.f, 0u); + + context->m_deviceContext->OMSetDepthStencilState(context->m_depthState, 0u); +} + +void AppGraphCtxFramePresent(AppGraphCtx* context, bool fullsync) +{ + context->m_swapChain->Present(0, 0); + + appGraphProfilerFrameEnd(context->m_profiler); +} + +void AppGraphCtxWaitForFrames(AppGraphCtx* context, unsigned int maxFramesInFlight) +{ + // TODO: Implement +} + +void AppGraphCtxProfileEnable(AppGraphCtx* context, bool enabled) +{ + appGraphProfilerEnable(context->m_profiler, enabled); +} + +void AppGraphCtxProfileBegin(AppGraphCtx* context, const char* label) +{ + appGraphProfilerBegin(context->m_profiler, label); +} + +void AppGraphCtxProfileEnd(AppGraphCtx* context, const char* label) +{ + appGraphProfilerEnd(context->m_profiler, label); +} + +bool AppGraphCtxProfileGet(AppGraphCtx* context, const char** plabel, float* cpuTime, float* gpuTime, int index) +{ + return appGraphProfilerGet(context->m_profiler, plabel, cpuTime, gpuTime, index); +} + +// ******************************* Profiler ********************************* + +namespace +{ + struct TimerCPU + { + LARGE_INTEGER oldCount; + LARGE_INTEGER count; + LARGE_INTEGER freq; + TimerCPU() + { + QueryPerformanceCounter(&count); + QueryPerformanceFrequency(&freq); + oldCount = count; + } + double getDeltaTime() + { + QueryPerformanceCounter(&count); + double dt = double(count.QuadPart - oldCount.QuadPart) / double(freq.QuadPart); + oldCount = count; + return dt; + } + }; + + struct TimerGPU + { + ID3D11Query* m_begin = nullptr; + ID3D11Query* m_end = nullptr; + + TimerGPU() {} + ~TimerGPU() + { + COMRelease(m_begin); + COMRelease(m_end); + } + }; + + struct Timer + { + TimerCPU m_cpu; + TimerGPU m_gpu; + + const char* m_label = nullptr; + float m_cpuTime = 0.f; + float m_gpuTime = 0.f; + + Timer() {} + ~Timer() {} + }; + + struct TimerValue + { + const char* m_label = nullptr; + float m_cpuTime = 0.f; + float m_gpuTime = 0.f; + + struct Stat + { + float m_time = 0.f; + float m_maxTime = 0.f; + float m_maxTimeAge = 0.f; + + float m_smoothTime = 0.f; + float m_smoothTimeSum = 0.f; + float m_smoothTimeCount = 0.f; + + Stat() {} + void push(float time) + { + m_time = time; + + if (m_time > m_maxTime) + { + m_maxTime = m_time; + m_maxTimeAge = 0.f; + } + + if (fabsf(m_time - m_maxTime) < 0.25f * m_maxTime) + { + m_smoothTimeSum += m_time; + m_smoothTimeCount += 1.f; + m_smoothTimeSum *= 0.98f; + m_smoothTimeCount *= 0.98f; + m_smoothTime = m_smoothTimeSum / m_smoothTimeCount; + } + } + + float pull(float frameTime) + { + m_maxTimeAge += frameTime; + + if (m_maxTimeAge > 1.f) + { + m_maxTimeAge = 0.f; + m_maxTime = m_time; + m_smoothTimeSum = 0.f; + m_smoothTimeCount = 0.f; + } + return m_smoothTime; + } + }; + + Stat m_cpu; + Stat m_gpu; + + void push(float cpuTime, float gpuTime) + { + m_cpu.push(cpuTime); + m_gpu.push(gpuTime); + } + + void pull(float frameTime) + { + m_cpuTime = m_cpu.pull(frameTime); + m_gpuTime = m_gpu.pull(frameTime); + } + }; +} + +struct AppGraphProfiler +{ + AppGraphCtx* m_context; + + int m_state = 0; + bool m_enabled = false; + + TimerCPU m_frameTimer; + float m_frameTime = 0.f; + + ID3D11Query* m_disjoint = nullptr; + + static const int m_timersCap = 64; + Timer m_timers[m_timersCap]; + int m_timersSize = 0; + + TimerValue m_timerValues[m_timersCap]; + int m_timerValuesSize = 0; + + AppGraphProfiler(AppGraphCtx* context); + ~AppGraphProfiler(); +}; + +AppGraphProfiler::AppGraphProfiler(AppGraphCtx* context) : m_context(context) +{ +} + +AppGraphProfiler::~AppGraphProfiler() +{ + COMRelease(m_disjoint); +} + +AppGraphProfiler* appGraphCreateProfiler(AppGraphCtx* ctx) +{ + return new AppGraphProfiler(ctx); +} + +void appGraphReleaseProfiler(AppGraphProfiler* profiler) +{ + delete profiler; +} + +void appGraphProfilerFrameBegin(AppGraphProfiler* p) +{ + p->m_frameTime = (float)p->m_frameTimer.getDeltaTime(); + + if (p->m_state == 0 && p->m_enabled) + { + auto device = p->m_context->m_device; + auto deviceContext = p->m_context->m_deviceContext; + + if (p->m_disjoint == nullptr) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; + queryDesc.MiscFlags = 0u; + device->CreateQuery(&queryDesc, &p->m_disjoint); + } + + deviceContext->Begin(p->m_disjoint); + + p->m_timersSize = 0; + + p->m_state = 1; + } +} + +void appGraphProfilerFrameEnd(AppGraphProfiler* p) +{ + if (p->m_state == 1) + { + auto deviceContext = p->m_context->m_deviceContext; + + deviceContext->End(p->m_disjoint); + + p->m_state = 2; + } +} + +void appGraphProfilerEnable(AppGraphProfiler* p, bool enabled) +{ + p->m_enabled = enabled; +} + +void appGraphProfilerBegin(AppGraphProfiler* p, const char* label) +{ + if (p->m_state == 1 && p->m_timersSize < p->m_timersCap) + { + auto& timer = p->m_timers[p->m_timersSize++]; + timer.m_label = label; + timer.m_cpu.getDeltaTime(); + + auto device = p->m_context->m_device; + auto deviceContext = p->m_context->m_deviceContext; + + if (timer.m_gpu.m_begin == nullptr) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.MiscFlags = 0u; + queryDesc.Query = D3D11_QUERY_TIMESTAMP; + device->CreateQuery(&queryDesc, &timer.m_gpu.m_begin); + device->CreateQuery(&queryDesc, &timer.m_gpu.m_end); + } + + deviceContext->End(timer.m_gpu.m_begin); + } +} + +void appGraphProfilerEnd(AppGraphProfiler* p, const char* label) +{ + if (p->m_state == 1) + { + Timer* timer = nullptr; + for (int i = 0; i < p->m_timersSize; i++) + { + if (strcmp(p->m_timers[i].m_label, label) == 0) + { + timer = &p->m_timers[i]; + break; + } + } + if (timer) + { + auto deviceContext = p->m_context->m_deviceContext; + + deviceContext->End(timer->m_gpu.m_end); + + timer->m_cpuTime = (float)timer->m_cpu.getDeltaTime(); + } + } +} + +bool appGraphProfilerFlush(AppGraphProfiler* p) +{ + if (p->m_state == 2) + { + auto deviceContext = p->m_context->m_deviceContext; + + // check disjoint for completion + if (deviceContext->GetData(p->m_disjoint, nullptr, 0u, 0u) != S_OK) + { + return false; + } + + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT tsDisjoint; + deviceContext->GetData(p->m_disjoint, &tsDisjoint, sizeof(tsDisjoint), 0u); + if (tsDisjoint.Disjoint) + { + return false; + } + + for (int i = 0; i < p->m_timersSize; i++) + { + Timer& timer = p->m_timers[i]; + + UINT64 tsBegin, tsEnd; + if (deviceContext->GetData(timer.m_gpu.m_begin, &tsBegin, sizeof(UINT64), 0) != S_OK) + { + return false; + } + if (deviceContext->GetData(timer.m_gpu.m_end, &tsEnd, sizeof(UINT64), 0) != S_OK) + { + return false; + } + + timer.m_gpuTime = float(tsEnd - tsBegin) / float(tsDisjoint.Frequency); + + // update TimerValue + int j = 0; + for (; j < p->m_timerValuesSize; j++) + { + TimerValue& value = p->m_timerValues[j]; + if (strcmp(value.m_label, timer.m_label) == 0) + { + value.push(timer.m_cpuTime, timer.m_gpuTime); + break; + } + } + if (j >= p->m_timerValuesSize && p->m_timerValuesSize < p->m_timersCap) + { + TimerValue& value = p->m_timerValues[p->m_timerValuesSize++]; + value.m_label = timer.m_label; + value.push(timer.m_cpuTime, timer.m_gpuTime); + } + } + + p->m_state = 0; + } + return false; +} + +bool appGraphProfilerGet(AppGraphProfiler* p, const char** plabel, float* cpuTime, float* gpuTime, int index) +{ + appGraphProfilerFlush(p); + { + if (index < p->m_timerValuesSize) + { + TimerValue& timer = p->m_timerValues[index]; + + timer.pull(p->m_frameTime); + + if (plabel) *plabel = timer.m_label; + if (cpuTime) *cpuTime = timer.m_cpuTime; + if (gpuTime) *gpuTime = timer.m_gpuTime; + + return true; + } + } + return false; +} + +size_t AppGraphCtxDedicatedVideoMemory(AppGraphCtx* context) +{ + return context->m_dedicatedVideoMemory; +}
\ No newline at end of file diff --git a/demo/DemoAppD3D11/appD3D11Ctx.h b/demo/DemoAppD3D11/appD3D11Ctx.h new file mode 100644 index 0000000..578413c --- /dev/null +++ b/demo/DemoAppD3D11/appD3D11Ctx.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +#include "../DemoApp/appGraphCtx.h" + +struct AppGraphProfiler; + +struct AppGraphCtx +{ + HWND m_hWnd = nullptr; + + int m_winW = 0; + int m_winH = 0; + bool m_fullscreen = false; + bool m_valid = false; + + size_t m_dedicatedVideoMemory = 0u; + + // D3D11 objects + D3D11_VIEWPORT m_viewport = {}; + ID3D11Device* m_device = nullptr; + ID3D11DeviceContext* m_deviceContext = nullptr; + IDXGISwapChain* m_swapChain = nullptr; + ID3D11RenderTargetView* m_rtv = nullptr; + ID3D11Texture2D* m_depthStencil = nullptr; + ID3D11DepthStencilView* m_dsv = nullptr; + ID3D11ShaderResourceView* m_depthSRV = nullptr; + ID3D11DepthStencilState* m_depthState = nullptr; + + AppGraphProfiler* m_profiler = nullptr; + + AppGraphCtx(); + ~AppGraphCtx(); +};
\ No newline at end of file diff --git a/demo/DemoAppD3D11/computeContextD3D11.cpp b/demo/DemoAppD3D11/computeContextD3D11.cpp new file mode 100644 index 0000000..2f25f95 --- /dev/null +++ b/demo/DemoAppD3D11/computeContextD3D11.cpp @@ -0,0 +1,343 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include <d3d11.h> + +#include "computeContextD3D11.h" + +// ************************** Compute Context Implementation ****************** + +template <class T> +void inline COMRelease(T& t) +{ + if (t) t->Release(); + t = nullptr; +} + +struct ComputeContext +{ + ComputeContextDesc m_desc = {}; + + ID3D11SamplerState* m_sampler0 = nullptr; + ID3D11SamplerState* m_sampler1 = nullptr; + ID3D11SamplerState* m_sampler2 = nullptr; + ID3D11SamplerState* m_sampler3 = nullptr; + ID3D11SamplerState* m_sampler4 = nullptr; + ID3D11SamplerState* m_sampler5 = nullptr; + + ComputeContext(const ComputeContextDesc* desc) + { + m_desc = *desc; + + auto createSampler = [&](D3D11_FILTER filter, D3D11_TEXTURE_ADDRESS_MODE mode) + { + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = filter; + samplerDesc.AddressU = mode; + samplerDesc.AddressV = mode; + samplerDesc.AddressW = mode; + samplerDesc.MipLODBias = 0; + samplerDesc.MaxAnisotropy = 0; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.BorderColor[0] = 0.f; + samplerDesc.BorderColor[1] = 0.f; + samplerDesc.BorderColor[2] = 0.f; + samplerDesc.BorderColor[3] = 0.f; + samplerDesc.MinLOD = 0.f; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + ID3D11SamplerState* sampler = nullptr; + m_desc.device->CreateSamplerState(&samplerDesc, &sampler); + return sampler; + }; + + m_sampler0 = createSampler(D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT, D3D11_TEXTURE_ADDRESS_BORDER); + m_sampler1 = createSampler(D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_BORDER); + m_sampler2 = createSampler(D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT, D3D11_TEXTURE_ADDRESS_WRAP); + m_sampler3 = createSampler(D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_WRAP); + m_sampler4 = createSampler(D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT, D3D11_TEXTURE_ADDRESS_CLAMP); + m_sampler5 = createSampler(D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_CLAMP); + } + ~ComputeContext() + { + COMRelease(m_sampler0); + COMRelease(m_sampler1); + COMRelease(m_sampler2); + COMRelease(m_sampler3); + COMRelease(m_sampler4); + COMRelease(m_sampler5); + } +}; + +struct ComputeShader +{ + ID3D11ComputeShader* m_shader = nullptr; + ComputeShader(ID3D11ComputeShader* shader) + { + m_shader = shader; + } + ~ComputeShader() + { + COMRelease(m_shader); + } +}; + +struct ComputeConstantBuffer +{ + ID3D11Buffer* m_buffer; + ComputeConstantBuffer(ID3D11Buffer* buffer) + { + m_buffer = buffer; + } + ~ComputeConstantBuffer() + { + COMRelease(m_buffer); + } +}; + +struct ComputeResource +{ +protected: + ID3D11ShaderResourceView* m_srv = nullptr; +public: + void update(const ComputeResourceDesc* desc) + { + m_srv = desc->srv; + } + + ComputeResource(const ComputeResourceDesc* desc) + { + update(desc); + } + + ID3D11ShaderResourceView* SRV() + { + return m_srv; + } +}; + +struct ComputeResourceRW : public ComputeResource +{ +protected: + ID3D11UnorderedAccessView* m_uav; +public: + void update(const ComputeResourceRWDesc* descRW) + { + m_uav = descRW->uav; + ComputeResource::update(&descRW->resource); + } + + ComputeResourceRW(const ComputeResourceRWDesc* descRW): + ComputeResource(&descRW->resource) + { + m_uav = descRW->uav; + } + + ID3D11UnorderedAccessView* UAV() + { + return m_uav; + } +}; + +// ************* API functions **************** + +ComputeContext* ComputeContextCreate(ComputeContextDesc* desc) +{ + return new ComputeContext(desc); +} + +void ComputeContextUpdate(ComputeContext* context, ComputeContextDesc* desc) +{ + context->m_desc = *desc; +} + +void ComputeContextRelease(ComputeContext* context) +{ + delete context; +} + +ComputeShader* ComputeShaderCreate(ComputeContext* context, const ComputeShaderDesc* desc) +{ + ID3D11ComputeShader* computeShader = nullptr; + context->m_desc.device->CreateComputeShader(desc->cs, desc->cs_length, nullptr, &computeShader); + return new ComputeShader(computeShader); +} + +void ComputeShaderRelease(ComputeShader* shader) +{ + delete shader; +} + +ComputeConstantBuffer* ComputeConstantBufferCreate(ComputeContext* context, const ComputeConstantBufferDesc* desc) +{ + ID3D11Buffer* constantBuffer = nullptr; + { + D3D11_BUFFER_DESC bufDesc; + bufDesc.ByteWidth = desc->sizeInBytes; + bufDesc.Usage = D3D11_USAGE_DYNAMIC; + bufDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufDesc.MiscFlags = 0; + + context->m_desc.device->CreateBuffer(&bufDesc, nullptr, &constantBuffer); + } + return new ComputeConstantBuffer(constantBuffer); +} + +void ComputeConstantBufferRelease(ComputeConstantBuffer* constantBuffer) +{ + delete constantBuffer; +} + +void* ComputeConstantBufferMap(ComputeContext* context, ComputeConstantBuffer* constantBuffer) +{ + D3D11_MAPPED_SUBRESOURCE mapped = {}; + context->m_desc.deviceContext->Map(constantBuffer->m_buffer, 0u, D3D11_MAP_WRITE_DISCARD, 0u, &mapped); + return mapped.pData; +} + +void ComputeConstantBufferUnmap(ComputeContext* context, ComputeConstantBuffer* constantBuffer) +{ + context->m_desc.deviceContext->Unmap(constantBuffer->m_buffer, 0u); +} + +ComputeResource* ComputeResourceCreate(ComputeContext* context, const ComputeResourceDesc* desc) +{ + return new ComputeResource(desc); +} + +void ComputeResourceUpdate(ComputeContext* context, ComputeResource* resource, const ComputeResourceDesc* desc) +{ + resource->update(desc); +} + +void ComputeResourceRelease(ComputeResource* resource) +{ + delete resource; +} + +ComputeResourceRW* ComputeResourceRWCreate(ComputeContext* context, const ComputeResourceRWDesc* desc) +{ + return new ComputeResourceRW(desc); +} + +void ComputeResourceRWUpdate(ComputeContext* context, ComputeResourceRW* resourceRW, const ComputeResourceRWDesc* desc) +{ + resourceRW->update(desc); +} + +void ComputeResourceRWRelease(ComputeResourceRW* resourceRW) +{ + delete resourceRW; +} + +ComputeResource* ComputeResourceRWGetResource(ComputeResourceRW* resourceRW) +{ + return static_cast<ComputeResource*>(resourceRW); +} + +void ComputeContextDispatch(ComputeContext* context, const ComputeDispatchParams* params) +{ + auto& deviceContext = context->m_desc.deviceContext; + + if (params->shader) deviceContext->CSSetShader(params->shader->m_shader, nullptr, 0u); + + ID3D11ShaderResourceView* srvs[ComputeDispatchMaxResources] = { nullptr }; + ID3D11UnorderedAccessView* uavs[ComputeDispatchMaxResourcesRW] = { nullptr }; + for (unsigned int i = 0u; i < ComputeDispatchMaxResources; i++) + { + if (params->resources[i]) srvs[i] = params->resources[i]->SRV(); + } + for (unsigned int i = 0u; i < ComputeDispatchMaxResourcesRW; i++) + { + if (params->resourcesRW[i]) uavs[i] = params->resourcesRW[i]->UAV(); + } + deviceContext->CSSetShaderResources(0u, ComputeDispatchMaxResources, srvs); + deviceContext->CSSetUnorderedAccessViews(0u, ComputeDispatchMaxResourcesRW, uavs, nullptr); + + if (params->constantBuffer) deviceContext->CSSetConstantBuffers(0u, 1u, ¶ms->constantBuffer->m_buffer); + + ID3D11SamplerState* samplers[] = { + context->m_sampler0, context->m_sampler1, context->m_sampler2, + context->m_sampler3, context->m_sampler4, context->m_sampler5 + }; + deviceContext->CSSetSamplers(0u, 6u, samplers); + + deviceContext->Dispatch(params->gridDim[0u], params->gridDim[1u], params->gridDim[2u]); + + ID3D11ShaderResourceView* nullsrvs[ComputeDispatchMaxResources] = { nullptr }; + ID3D11UnorderedAccessView* nulluavs[ComputeDispatchMaxResourcesRW] = { nullptr }; + deviceContext->CSSetShaderResources(0, ComputeDispatchMaxResources, nullsrvs); + deviceContext->CSSetUnorderedAccessViews(0, ComputeDispatchMaxResourcesRW, nulluavs, nullptr); +} + +// ******************************* NvFlow Interoperation **************************************** + +#include "NvFlow.h" +#include "NvFlowContextD3D11.h" + +inline void updateComputeContextDesc(NvFlowContext* flowContext, ComputeContextDesc* desc) +{ + NvFlowContextDescD3D11 srcDesc = {}; + NvFlowUpdateContextDescD3D11(flowContext, &srcDesc); + desc->device = srcDesc.device; + desc->deviceContext = srcDesc.deviceContext; +} + +ComputeContext* ComputeContextNvFlowContextCreate(NvFlowContext* flowContext) +{ + ComputeContextDesc desc = {}; + updateComputeContextDesc(flowContext, &desc); + return ComputeContextCreate(&desc); +} + +void ComputeContextNvFlowContextUpdate(ComputeContext* computeContext, NvFlowContext* flowContext) +{ + ComputeContextDesc desc = {}; + updateComputeContextDesc(flowContext, &desc); + ComputeContextUpdate(computeContext, &desc); +} + +ComputeResource* ComputeResourceNvFlowCreate(ComputeContext* context, NvFlowContext* flowContext, NvFlowResource* flowResource) +{ + NvFlowResourceViewDescD3D11 flowViewDesc = {}; + NvFlowUpdateResourceViewDescD3D11(flowContext, flowResource, &flowViewDesc); + ComputeResourceDesc desc = {}; + desc.srv = flowViewDesc.srv; + return ComputeResourceCreate(context, &desc); +} + +void ComputeResourceNvFlowUpdate(ComputeContext* context, ComputeResource* resource, NvFlowContext* flowContext, NvFlowResource* flowResource) +{ + NvFlowResourceViewDescD3D11 flowViewDesc = {}; + NvFlowUpdateResourceViewDescD3D11(flowContext, flowResource, &flowViewDesc); + ComputeResourceDesc desc = {}; + desc.srv = flowViewDesc.srv; + ComputeResourceUpdate(context, resource, &desc); +} + +ComputeResourceRW* ComputeResourceRWNvFlowCreate(ComputeContext* context, NvFlowContext* flowContext, NvFlowResourceRW* flowResourceRW) +{ + NvFlowResourceRWViewDescD3D11 flowViewDesc = {}; + NvFlowUpdateResourceRWViewDescD3D11(flowContext, flowResourceRW, &flowViewDesc); + ComputeResourceRWDesc desc = {}; + desc.resource.srv = flowViewDesc.resourceView.srv; + desc.uav = flowViewDesc.uav; + return ComputeResourceRWCreate(context, &desc); +} + +void ComputeResourceRWNvFlowUpdate(ComputeContext* context, ComputeResourceRW* resourceRW, NvFlowContext* flowContext, NvFlowResourceRW* flowResourceRW) +{ + NvFlowResourceRWViewDescD3D11 flowViewDesc = {}; + NvFlowUpdateResourceRWViewDescD3D11(flowContext, flowResourceRW, &flowViewDesc); + ComputeResourceRWDesc desc = {}; + desc.resource.srv = flowViewDesc.resourceView.srv; + desc.uav = flowViewDesc.uav; + ComputeResourceRWUpdate(context, resourceRW, &desc); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D11/computeContextD3D11.h b/demo/DemoAppD3D11/computeContextD3D11.h new file mode 100644 index 0000000..43ad5b1 --- /dev/null +++ b/demo/DemoAppD3D11/computeContextD3D11.h @@ -0,0 +1,30 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#pragma once + +#include "../DemoApp/computeContext.h" + +struct ComputeContextDesc +{ + ID3D11Device* device; + ID3D11DeviceContext* deviceContext; +}; + +struct ComputeResourceDesc +{ + ID3D11ShaderResourceView* srv; +}; + +struct ComputeResourceRWDesc +{ + ComputeResourceDesc resource; + ID3D11UnorderedAccessView* uav; +};
\ No newline at end of file diff --git a/demo/DemoAppD3D11/imguiGraphD3D11.cpp b/demo/DemoAppD3D11/imguiGraphD3D11.cpp new file mode 100644 index 0000000..a654cf2 --- /dev/null +++ b/demo/DemoAppD3D11/imguiGraphD3D11.cpp @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include "imguiGraphD3D11.h" + +//direct3d headers +#include <d3d11.h> + +#include "imguiVS.hlsl.h" +#include "imguiPS.hlsl.h" + +namespace +{ + template <class T> + void inline COMRelease(T& t) + { + if (t) t->Release(); + t = nullptr; + } +} + +namespace +{ + ID3D11Device* m_device = nullptr; + ID3D11DeviceContext* m_deviceContext = nullptr; + int m_winW = 0; + int m_winH = 0; + + uint32_t m_maxVertices = 0; + + struct Vertex + { + float x, y; + float u, v; + uint8_t rgba[4]; + }; + + ID3D11RasterizerState* m_rasterizerState = nullptr; + ID3D11SamplerState* m_samplerState = nullptr; + ID3D11InputLayout* m_inputLayout = nullptr; + ID3D11BlendState* m_blendState = nullptr; + ID3D11VertexShader* m_imguiVS = nullptr; + ID3D11PixelShader* m_imguiPS = nullptr; + ID3D11Buffer* m_constantBuffer = nullptr; + ID3D11Buffer* m_vertexBuffer = nullptr; + Vertex* m_vertexBufferData = nullptr; + + struct Scissor + { + int beginIdx; + int stopIdx; + int x; + int y; + int width; + int height; + }; + Scissor m_stateScissor = {}; + + ID3D11Texture2D* m_texture = nullptr; + ID3D11ShaderResourceView* m_textureSRV = nullptr; + + Vertex m_stateVert; + uint32_t m_stateVertIdx = 0u; + + struct Params + { + float projection[16]; + + float padding[64 - 16]; + }; +} + +void imguiGraphContextDestroy() +{ + COMRelease(m_rasterizerState); + COMRelease(m_samplerState); + COMRelease(m_inputLayout); + COMRelease(m_blendState); + COMRelease(m_imguiVS); + COMRelease(m_imguiPS); + COMRelease(m_constantBuffer); + COMRelease(m_vertexBuffer); +} + +void imguiGraphContextInit(const ImguiGraphDesc* desc) +{ + m_device = desc->device; + m_deviceContext = desc->deviceContext; + m_winW = desc->winW; + m_winH = desc->winH; + + m_maxVertices = desc->maxVertices; + + // create the rastersizer state + { + D3D11_RASTERIZER_DESC desc = {}; + desc.FillMode = D3D11_FILL_SOLID; + desc.CullMode = D3D11_CULL_BACK; + desc.FrontCounterClockwise = TRUE; // This is non-default + desc.DepthBias = 0; + desc.DepthBiasClamp = 0.f; + desc.SlopeScaledDepthBias = 0.f; + desc.DepthClipEnable = TRUE; + desc.ScissorEnable = TRUE; // This is non-default + desc.MultisampleEnable = FALSE; + desc.AntialiasedLineEnable = FALSE; + + m_device->CreateRasterizerState(&desc, &m_rasterizerState); + } + + // create the sampler state + { + D3D11_SAMPLER_DESC sampler = {}; + sampler.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + sampler.AddressU = D3D11_TEXTURE_ADDRESS_BORDER; + sampler.AddressV = D3D11_TEXTURE_ADDRESS_BORDER; + sampler.AddressW = D3D11_TEXTURE_ADDRESS_BORDER; + sampler.MipLODBias = 0; + sampler.MaxAnisotropy = 0; + sampler.ComparisonFunc = D3D11_COMPARISON_NEVER; + //sampler.BorderColor = D3D11_BORDER_COLOR_TRANSPARENT_BLACK; + sampler.MinLOD = 0.f; + sampler.MaxLOD = D3D11_FLOAT32_MAX; + + m_device->CreateSamplerState(&sampler, &m_samplerState); + } + + // create the input layout + { + D3D11_INPUT_ELEMENT_DESC inputElementDescs[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + m_device->CreateInputLayout(inputElementDescs, 3, g_imguiVS, sizeof(g_imguiVS), &m_inputLayout); + } + + // create the blend state + { + D3D11_BLEND_DESC blendDesc = {}; + blendDesc.AlphaToCoverageEnable = false; + blendDesc.IndependentBlendEnable = false; + blendDesc.RenderTarget[0].BlendEnable = true; + blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; + blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; + blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + + m_device->CreateBlendState(&blendDesc, &m_blendState); + } + + // create the shaders + m_device->CreateVertexShader(g_imguiVS, sizeof(g_imguiVS), nullptr, &m_imguiVS); + m_device->CreatePixelShader(g_imguiPS, sizeof(g_imguiPS), nullptr, &m_imguiPS); + + // create a constant buffer + { + Params params = { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f + }; + + D3D11_BUFFER_DESC bufDesc; + bufDesc.ByteWidth = sizeof(params); + bufDesc.Usage = D3D11_USAGE_DYNAMIC; + bufDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufDesc.MiscFlags = 0; + + D3D11_SUBRESOURCE_DATA data = {}; + data.pSysMem = ¶ms; + + m_device->CreateBuffer(&bufDesc, &data, &m_constantBuffer); + } + + // create a vertex buffer + { + UINT bufferSize = (UINT)(m_maxVertices) * sizeof(Vertex); + + D3D11_BUFFER_DESC bufDesc; + bufDesc.ByteWidth = bufferSize; + bufDesc.Usage = D3D11_USAGE_DYNAMIC; + bufDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufDesc.MiscFlags = 0; + + m_device->CreateBuffer(&bufDesc, nullptr, &m_vertexBuffer); + } +} + +void imguiGraphContextUpdate(const ImguiGraphDesc* desc) +{ + m_device = desc->device; + m_deviceContext = desc->deviceContext; + m_winW = desc->winW; + m_winH = desc->winH; +} + +void imguiGraphRecordBegin() +{ + Params params = { + 2.f / float(m_winW), 0.f, 0.f, -1.f, + 0.f, 2.f / float(m_winH), 0.f, -1.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f + }; + + ID3D11DeviceContext* context = m_deviceContext; + + // update constant buffer + { + D3D11_MAPPED_SUBRESOURCE mappedResource = {}; + if (S_OK == context->Map(m_constantBuffer, 0u, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)) + { + memcpy(mappedResource.pData, ¶ms, sizeof(Params)); + + context->Unmap(m_constantBuffer, 0u); + } + } + + // clear state + m_stateVert = Vertex{ 0.f, 0.f, -1.f, -1.f, 0,0,0,0 }; + m_stateVertIdx = 0u; + + m_stateScissor = Scissor { 0, 0, 0, 0, m_winW, m_winH }; + + // configure for triangle renderering + context->VSSetShader(m_imguiVS, nullptr, 0u); + context->PSSetShader(m_imguiPS, nullptr, 0u); + + context->IASetInputLayout(m_inputLayout); + context->OMSetBlendState(m_blendState, nullptr, 0xFFFFFFFF); + context->PSSetSamplers(0, 1, &m_samplerState); + + context->VSSetConstantBuffers(0, 1, &m_constantBuffer); + + context->PSSetShaderResources(0, 1, &m_textureSRV); + + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + context->RSSetState(m_rasterizerState); + + // trigger allocation of new vertex buffer as needed + { + D3D11_MAPPED_SUBRESOURCE mappedResource = {}; + if (S_OK == context->Map(m_vertexBuffer, 0u, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)) + { + context->Unmap(m_vertexBuffer, 0u); + } + } + + UINT vertexStride = sizeof(Vertex); + UINT offset = 0u; + context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vertexStride, &offset); + + // map allocated vertex buffer + { + D3D11_MAPPED_SUBRESOURCE mappedResource = {}; + if (S_OK == context->Map(m_vertexBuffer, 0u, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource)) + { + m_vertexBufferData = (Vertex*)mappedResource.pData; + } + else + { + m_vertexBufferData = nullptr; + } + } +} + +static void imguiGraphFlush() +{ + ID3D11DeviceContext* context = m_deviceContext; + + // unmap vertex buffer + context->Unmap(m_vertexBuffer, 0u); + + Scissor& p = m_stateScissor; + if (p.beginIdx < p.stopIdx) + { + int winH = m_winH; + D3D11_RECT rect; + rect.left = p.x; + rect.right = p.x + p.width; + rect.top = (winH) - (p.y + p.height); + rect.bottom = (winH) - (p.y); + context->RSSetScissorRects(1, &rect); + + UINT vertexCount = (p.stopIdx - p.beginIdx); + UINT startIndex = p.beginIdx; + context->DrawInstanced(vertexCount, 1, startIndex, 0); + } + + // map allocated vertex buffer + { + D3D11_MAPPED_SUBRESOURCE mappedResource = {}; + if (S_OK == context->Map(m_vertexBuffer, 0u, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource)) + { + m_vertexBufferData = (Vertex*)mappedResource.pData; + } + else + { + m_vertexBufferData = nullptr; + } + } +} + +void imguiGraphRecordEnd() +{ + ID3D11DeviceContext* context = m_deviceContext; + + context->OMSetBlendState(nullptr,nullptr,0xFFFFFFFF); + + // unmap vertex buffer + context->Unmap(m_vertexBuffer, 0u); + + // restore scissor + Scissor& p = m_stateScissor; + int winH = m_winH; + D3D11_RECT rect; + rect.left = p.x; + rect.right = p.x + p.width; + rect.top = (winH) - (p.y + p.height); + rect.bottom = (winH) - (p.y); + context->RSSetScissorRects(1, &rect); + + context->RSSetState(nullptr); +} + +void imguiGraphEnableScissor(int x, int y, int width, int height) +{ + // mark end of last region + m_stateScissor.stopIdx = m_stateVertIdx; + + imguiGraphFlush(); + + m_stateScissor.beginIdx = m_stateVertIdx; + m_stateScissor.stopIdx = m_stateVertIdx; + m_stateScissor.x = x; + m_stateScissor.y = y; + m_stateScissor.width = width; + m_stateScissor.height = height; +} + +void imguiGraphDisableScissor() +{ + if (m_stateVertIdx == 0) return; + + // mark end of last region + m_stateScissor.stopIdx = m_stateVertIdx; + + imguiGraphFlush(); + + m_stateScissor.beginIdx = m_stateVertIdx; + m_stateScissor.stopIdx = m_stateVertIdx; + m_stateScissor.x = 0; + m_stateScissor.y = 0; + m_stateScissor.width = m_winW; + m_stateScissor.height = m_winH; +} + +void imguiGraphVertex2f(float x, float y) +{ + float v[2] = { x,y }; + imguiGraphVertex2fv(v); +} + +void imguiGraphVertex2fv(const float* v) +{ + // update state + m_stateVert.x = v[0]; + m_stateVert.y = v[1]; + + Vertex* vdata = m_vertexBufferData; + + // push vertex + if ((m_stateVertIdx) < m_maxVertices) + { + vdata[m_stateVertIdx++] = m_stateVert; + } +} + +void imguiGraphTexCoord2f(float u, float v) +{ + m_stateVert.u = u; + m_stateVert.v = v; +} + +void imguiGraphColor4ub(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) +{ + m_stateVert.rgba[0] = red; + m_stateVert.rgba[1] = green; + m_stateVert.rgba[2] = blue; + m_stateVert.rgba[3] = alpha; +} + +void imguiGraphColor4ubv(const uint8_t* v) +{ + m_stateVert.rgba[0] = v[0]; + m_stateVert.rgba[1] = v[1]; + m_stateVert.rgba[2] = v[2]; + m_stateVert.rgba[3] = v[3]; +} + +void imguiGraphFontTextureEnable() +{ + +} + +void imguiGraphFontTextureDisable() +{ + m_stateVert.u = -1.f; + m_stateVert.v = -1.f; +} + +void imguiGraphFontTextureInit(unsigned char* data) +{ + ID3D11DeviceContext* context = m_deviceContext; + + // create texture + { + UINT width = 512; + UINT height = 512; + + D3D11_TEXTURE2D_DESC texDesc = {}; + texDesc.Width = width; + texDesc.Height = height; + texDesc.MipLevels = 1; + texDesc.ArraySize = 1; + texDesc.Format = DXGI_FORMAT_R8_UNORM; + texDesc.SampleDesc.Count = 1; + texDesc.SampleDesc.Quality = 0u; + texDesc.Usage = D3D11_USAGE_IMMUTABLE; + texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + texDesc.CPUAccessFlags = 0; + texDesc.MiscFlags = 0; + + D3D11_SUBRESOURCE_DATA initData = {}; + initData.pSysMem = data; + initData.SysMemPitch = width; + + if (m_device->CreateTexture2D(&texDesc, &initData, &m_texture)) + { + return; + } + + if (m_device->CreateShaderResourceView(m_texture, nullptr, &m_textureSRV)) + { + return; + } + } + +} + +void imguiGraphFontTextureRelease() +{ + COMRelease(m_texture); + COMRelease(m_textureSRV); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D11/imguiGraphD3D11.h b/demo/DemoAppD3D11/imguiGraphD3D11.h new file mode 100644 index 0000000..54e022f --- /dev/null +++ b/demo/DemoAppD3D11/imguiGraphD3D11.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#ifndef IMGUI_GRAPH_D3D11_H +#define IMGUI_GRAPH_D3D11_H + +#include <stdint.h> + +#include "../DemoApp/imguiGraph.h" + +struct ID3D11Device; +struct ID3D11DeviceContext; + +struct ImguiGraphDesc +{ + ID3D11Device* device = nullptr; + ID3D11DeviceContext* deviceContext = nullptr; + int winW; + int winH; + + uint32_t maxVertices = 64 * 4096u; + + ImguiGraphDesc() {} +}; + +#endif
\ No newline at end of file diff --git a/demo/DemoAppD3D11/imguiInteropD3D11.cpp b/demo/DemoAppD3D11/imguiInteropD3D11.cpp new file mode 100644 index 0000000..9989aeb --- /dev/null +++ b/demo/DemoAppD3D11/imguiInteropD3D11.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +//direct3d headers +#include <d3d11.h> + +// include the Direct3D Library file +#pragma comment (lib, "d3d11.lib") + +#include "../DemoApp/imguiInterop.h" + +#include "appD3D11Ctx.h" +#include "imguiGraphD3D11.h" + +bool imguiInteropGraphInit(imguiGraphInit_t func, const char* fontpath, AppGraphCtx* appctx) +{ + ImguiGraphDesc desc; + desc.device = appctx->m_device; + desc.deviceContext = appctx->m_deviceContext; + desc.winW = appctx->m_winW; + desc.winH = appctx->m_winH; + + return func(fontpath, &desc); +} + +void imguiInteropGraphUpdate(imguiGraphUpdate_t func, AppGraphCtx* appctx) +{ + ImguiGraphDesc desc; + desc.device = appctx->m_device; + desc.deviceContext = appctx->m_deviceContext; + desc.winW = appctx->m_winW; + desc.winH = appctx->m_winH; + + return func(&desc); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D11/imguiPS.hlsl.h b/demo/DemoAppD3D11/imguiPS.hlsl.h new file mode 100644 index 0000000..d6fb74c --- /dev/null +++ b/demo/DemoAppD3D11/imguiPS.hlsl.h @@ -0,0 +1,195 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// texSampler sampler NA NA s0 1 +// tex texture float 2d t0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v1.xy +dcl_input_ps linear v2.xyzw +dcl_output o0.xyzw +dcl_temps 1 +ge r0.x, v1.x, l(0.000000) +if_nz r0.x + sample_l_indexable(texture2d)(float,float,float,float) r0.x, v1.xyxx, t0.xyzw, s0, l(0.000000) + mul r0.x, r0.x, v2.w +else + mov r0.x, v2.w +endif +mov r0.yzw, v2.xxyz +mov o0.xyzw, r0.yzwx +ret +// Approximately 10 instruction slots used +#endif + +const BYTE g_imguiPS[] = +{ + 68, 88, 66, 67, 254, 30, + 194, 112, 35, 29, 114, 31, + 28, 188, 13, 85, 22, 84, + 219, 9, 1, 0, 0, 0, + 80, 3, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 240, 0, 0, 0, 100, 1, + 0, 0, 152, 1, 0, 0, + 180, 2, 0, 0, 82, 68, + 69, 70, 180, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 255, 255, 0, 1, 0, 0, + 139, 0, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 124, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 135, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 116, 101, + 120, 83, 97, 109, 112, 108, + 101, 114, 0, 116, 101, 120, + 0, 77, 105, 99, 114, 111, + 115, 111, 102, 116, 32, 40, + 82, 41, 32, 72, 76, 83, + 76, 32, 83, 104, 97, 100, + 101, 114, 32, 67, 111, 109, + 112, 105, 108, 101, 114, 32, + 49, 48, 46, 49, 0, 171, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 79, 83, 73, 84, + 73, 79, 78, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 65, 82, + 71, 69, 84, 0, 171, 171, + 83, 72, 69, 88, 20, 1, + 0, 0, 80, 0, 0, 0, + 69, 0, 0, 0, 106, 8, + 0, 1, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 98, 16, 0, 3, 242, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 29, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 16, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 72, 0, 0, 141, 194, 0, + 0, 128, 67, 85, 21, 0, + 18, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 58, 16, 16, 0, 2, 0, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 58, 16, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 54, 0, 0, 5, 226, 0, + 16, 0, 0, 0, 0, 0, + 6, 25, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 242, 32, 16, 0, 0, 0, + 0, 0, 150, 3, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/demo/DemoAppD3D11/imguiVS.hlsl.h b/demo/DemoAppD3D11/imguiVS.hlsl.h new file mode 100644 index 0000000..6c7ed54 --- /dev/null +++ b/demo/DemoAppD3D11/imguiVS.hlsl.h @@ -0,0 +1,246 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer params +// { +// +// float4x4 transform; // Offset: 0 Size: 64 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// params cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xy 0 NONE float xy +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// SV_InstanceID 0 x 3 INSTID uint +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[4], immediateIndexed +dcl_input v0.xy +dcl_input v1.xy +dcl_input v2.xyzw +dcl_output_siv o0.xyzw, position +dcl_output o1.xy +dcl_output o2.xyzw +dcl_temps 1 +mov r0.xy, v0.xyxx +mov r0.z, l(1.000000) +dp3 o0.x, r0.xyzx, cb0[0].xywx +dp3 o0.y, r0.xyzx, cb0[1].xywx +dp3 o0.z, r0.xyzx, cb0[2].xywx +dp3 o0.w, r0.xyzx, cb0[3].xywx +mov o1.xy, v1.xyxx +mov o2.xyzw, v2.xyzw +ret +// Approximately 9 instruction slots used +#endif + +const BYTE g_imguiVS[] = +{ + 68, 88, 66, 67, 6, 20, + 203, 172, 109, 190, 55, 177, + 9, 228, 94, 38, 104, 254, + 183, 14, 1, 0, 0, 0, + 52, 4, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 64, 1, 0, 0, 216, 1, + 0, 0, 76, 2, 0, 0, + 152, 3, 0, 0, 82, 68, + 69, 70, 4, 1, 0, 0, + 1, 0, 0, 0, 100, 0, + 0, 0, 1, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 254, 255, 0, 1, 0, 0, + 220, 0, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 112, 97, 114, 97, + 109, 115, 0, 171, 92, 0, + 0, 0, 1, 0, 0, 0, + 124, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 0, + 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 2, 0, + 0, 0, 184, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 116, 114, 97, 110, + 115, 102, 111, 114, 109, 0, + 102, 108, 111, 97, 116, 52, + 120, 52, 0, 171, 3, 0, + 3, 0, 4, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 174, 0, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 144, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 104, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, + 113, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 3, 0, 0, + 122, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 15, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 80, 79, 83, 73, 84, 73, + 79, 78, 0, 84, 69, 88, + 67, 79, 79, 82, 68, 0, + 67, 79, 76, 79, 82, 0, + 83, 86, 95, 73, 110, 115, + 116, 97, 110, 99, 101, 73, + 68, 0, 171, 171, 79, 83, + 71, 78, 108, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 80, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 92, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 12, + 0, 0, 101, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 67, + 79, 76, 79, 82, 0, 171, + 83, 72, 69, 88, 68, 1, + 0, 0, 80, 0, 1, 0, + 81, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 2, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 2, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 54, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 16, 0, + 0, 8, 18, 32, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 131, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 8, 34, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 131, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 16, 0, 0, 8, + 66, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 131, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 16, 0, + 0, 8, 130, 32, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 131, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 5, 50, 32, + 16, 0, 1, 0, 0, 0, + 70, 16, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 242, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 2, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 9, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/demo/DemoAppD3D11/meshD3D11.cpp b/demo/DemoAppD3D11/meshD3D11.cpp new file mode 100644 index 0000000..2b119bb --- /dev/null +++ b/demo/DemoAppD3D11/meshD3D11.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +//direct3d headers +#include <d3d11.h> + +// include the Direct3D Library file +#pragma comment (lib, "d3d11.lib") + +#include <math.h> + +#include "meshD3D11.h" + +#include "meshVS.hlsl.h" +#include "meshPS.hlsl.h" + +namespace +{ + template <class T> + void inline COMRelease(T& t) + { + if (t) t->Release(); + t = nullptr; + } +} + +struct MeshContext +{ + ID3D11Device* m_device = nullptr; + ID3D11DeviceContext* m_deviceContext = nullptr; + + ID3D11InputLayout* m_inputLayout = nullptr; + ID3D11VertexShader* m_meshVS = nullptr; + ID3D11PixelShader* m_meshPS = nullptr; + ID3D11Buffer* m_constantBuffer = nullptr; + ID3D11RasterizerState* m_rasterizerStateRH = nullptr; + + MeshContext() {} + ~MeshContext() + { + COMRelease(m_inputLayout); + COMRelease(m_meshVS); + COMRelease(m_meshPS); + COMRelease(m_constantBuffer); + COMRelease(m_rasterizerStateRH); + } +}; + +struct MeshIndexBuffer +{ + ID3D11Buffer* m_buffer = nullptr; + MeshUint m_numElements = 0u; + + MeshIndexBuffer() {} + ~MeshIndexBuffer() + { + COMRelease(m_buffer); + } +}; + +struct MeshVertexBuffer +{ + ID3D11Buffer* m_buffer = nullptr; + MeshUint m_numElements = 0u; + + MeshVertexBuffer() {} + ~MeshVertexBuffer() + { + COMRelease(m_buffer); + } +}; + +MeshContext* MeshContextCreate(const MeshContextDesc* desc) +{ + MeshContext* context = new MeshContext; + + context->m_device = desc->device; + context->m_deviceContext = desc->context; + + // create the input layout + { + D3D11_INPUT_ELEMENT_DESC inputElementDescs[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } + }; + + context->m_device->CreateInputLayout(inputElementDescs, 2, g_meshVS, sizeof(g_meshVS), &context->m_inputLayout); + } + + // create the shaders + context->m_device->CreateVertexShader(g_meshVS, sizeof(g_meshVS), nullptr, &context->m_meshVS); + context->m_device->CreatePixelShader(g_meshPS, sizeof(g_meshPS), nullptr, &context->m_meshPS); + + // create a constant buffer + { + D3D11_BUFFER_DESC bufDesc; + bufDesc.ByteWidth = 64 * sizeof(float); + bufDesc.Usage = D3D11_USAGE_DYNAMIC; + bufDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufDesc.MiscFlags = 0; + + context->m_device->CreateBuffer(&bufDesc, nullptr, &context->m_constantBuffer); + } + + // create the rastersizer state + { + D3D11_RASTERIZER_DESC desc = {}; + desc.FillMode = D3D11_FILL_SOLID; + desc.CullMode = D3D11_CULL_BACK; + desc.FrontCounterClockwise = TRUE; // This is non-default + desc.DepthBias = 0; + desc.DepthBiasClamp = 0.f; + desc.SlopeScaledDepthBias = 0.f; + desc.DepthClipEnable = TRUE; + desc.ScissorEnable = FALSE; + desc.MultisampleEnable = FALSE; + desc.AntialiasedLineEnable = FALSE; + + context->m_device->CreateRasterizerState(&desc, &context->m_rasterizerStateRH); + } + + return context; +} + +void MeshContextUpdate(MeshContext* context, const MeshContextDesc* desc) +{ + context->m_device = desc->device; + context->m_deviceContext = desc->context; +} + +void MeshContextRelease(MeshContext* context) +{ + if (context == nullptr) return; + + delete context; +} + +MeshIndexBuffer* MeshIndexBufferCreate(MeshContext* context, MeshUint* indices, MeshUint numIndices) +{ + MeshIndexBuffer* buffer = new MeshIndexBuffer; + + buffer->m_numElements = numIndices; + // create an index buffer + { + UINT bufferSize = (UINT)(numIndices) * sizeof(UINT); + + D3D11_BUFFER_DESC bufDesc; + bufDesc.ByteWidth = bufferSize; + bufDesc.Usage = D3D11_USAGE_IMMUTABLE; + bufDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufDesc.CPUAccessFlags = DXGI_CPU_ACCESS_NONE; + bufDesc.MiscFlags = 0; + + D3D11_SUBRESOURCE_DATA data = {}; + data.pSysMem = indices; + + context->m_device->CreateBuffer(&bufDesc, &data, &buffer->m_buffer); + } + + return buffer; +} + +void MeshIndexBufferRelease(MeshIndexBuffer* buffer) +{ + if (buffer == nullptr) return; + + delete buffer; +} + +MeshVertexBuffer* MeshVertexBufferCreate(MeshContext* context, MeshVertex* vertices, MeshUint numVertices) +{ + MeshVertexBuffer* buffer = new MeshVertexBuffer; + + buffer->m_numElements = numVertices; + // create a vertex buffer + { + UINT bufferSize = (UINT)(numVertices * sizeof(MeshVertex)); + + D3D11_BUFFER_DESC bufDesc; + bufDesc.ByteWidth = bufferSize; + bufDesc.Usage = D3D11_USAGE_IMMUTABLE; + bufDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufDesc.CPUAccessFlags = DXGI_CPU_ACCESS_NONE; + bufDesc.MiscFlags = 0; + + D3D11_SUBRESOURCE_DATA data = {}; + data.pSysMem = vertices; + + context->m_device->CreateBuffer(&bufDesc, &data, &buffer->m_buffer); + } + + return buffer; +} + +void MeshVertexBufferRelease(MeshVertexBuffer* buffer) +{ + if (buffer == nullptr) return; + + delete buffer; +} + +void MeshContextDraw(MeshContext* context, const MeshContextDrawParams* params) +{ + using namespace DirectX; + + XMMATRIX matrix = XMMatrixTranspose(XMMatrixMultiply(XMMatrixMultiply( + params->params->model, + params->params->view), + params->params->projection) + ); + + ID3D11DeviceContext* deviceContext = context->m_deviceContext; + + // update constant buffer + { + D3D11_MAPPED_SUBRESOURCE mappedResource = {}; + if (S_OK == deviceContext->Map(context->m_constantBuffer, 0u, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)) + { + XMStoreFloat4x4((XMFLOAT4X4*)(mappedResource.pData), matrix); + + deviceContext->Unmap(context->m_constantBuffer, 0u); + } + } + + deviceContext->VSSetShader(context->m_meshVS, nullptr, 0u); + deviceContext->PSSetShader(context->m_meshPS, nullptr, 0u); + + deviceContext->IASetInputLayout(context->m_inputLayout); + + deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + deviceContext->VSSetConstantBuffers(0, 1, &context->m_constantBuffer); + + UINT vertexStride = sizeof(MeshVertex); + UINT offset = 0u; + deviceContext->IASetVertexBuffers(0, 1, ¶ms->vertexBuffer->m_buffer, &vertexStride, &offset); + deviceContext->IASetIndexBuffer(params->indexBuffer->m_buffer, DXGI_FORMAT_R32_UINT, 0u); + + float depthSign = DirectX::XMVectorGetW(params->params->projection.r[2]); + if (depthSign < 0.f) + { + deviceContext->RSSetState(context->m_rasterizerStateRH); + } + + deviceContext->DrawIndexed((UINT)params->indexBuffer->m_numElements, 0, 0); + + if (depthSign < 0.f) + { + deviceContext->RSSetState(nullptr); + } +}
\ No newline at end of file diff --git a/demo/DemoAppD3D11/meshD3D11.h b/demo/DemoAppD3D11/meshD3D11.h new file mode 100644 index 0000000..86efe6b --- /dev/null +++ b/demo/DemoAppD3D11/meshD3D11.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +#include "../DemoApp/mesh.h" + +struct MeshContextDesc +{ + ID3D11Device* device; + ID3D11DeviceContext* context; +};
\ No newline at end of file diff --git a/demo/DemoAppD3D11/meshInteropD3D11.cpp b/demo/DemoAppD3D11/meshInteropD3D11.cpp new file mode 100644 index 0000000..5ab9a90 --- /dev/null +++ b/demo/DemoAppD3D11/meshInteropD3D11.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +//direct3d headers +#include <d3d11.h> + +// include the Direct3D Library file +#pragma comment (lib, "d3d11.lib") + +#include "../DemoApp/meshInterop.h" + +#include "appD3D11Ctx.h" +#include "meshD3D11.h" + +MeshContext* MeshInteropContextCreate(AppGraphCtx* appctx) +{ + MeshContextDesc desc = {}; + desc.device = appctx->m_device; + desc.context = appctx->m_deviceContext; + + return MeshContextCreate(&desc); +} + +void MeshInteropContextUpdate(MeshContext* context, AppGraphCtx* appctx) +{ + MeshContextDesc desc = {}; + desc.device = appctx->m_device; + desc.context = appctx->m_deviceContext; + + return MeshContextUpdate(context, &desc); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D11/meshPS.hlsl.h b/demo/DemoAppD3D11/meshPS.hlsl.h new file mode 100644 index 0000000..fcef532 --- /dev/null +++ b/demo/DemoAppD3D11/meshPS.hlsl.h @@ -0,0 +1,205 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float +// NORMAL 0 xyz 1 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_input_ps linear v1.xyz +dcl_output o0.xyzw +dcl_temps 1 +dp3 r0.x, v1.xyzx, l(0.570000, 0.570000, 0.570000, 0.000000) +max r0.x, r0.x, l(0.000000) +mad r0.x, r0.x, l(0.400000), l(0.100000) +dp3 r0.y, v1.xyzx, l(-0.570000, 0.570000, 0.570000, 0.000000) +max r0.y, r0.y, l(0.000000) +mad r0.x, r0.y, l(0.400000), r0.x +dp3 r0.y, v1.xyzx, l(0.570000, 0.570000, -0.570000, 0.000000) +max r0.y, r0.y, l(0.000000) +mad r0.x, r0.y, l(0.400000), r0.x +dp3 r0.y, v1.xzyx, l(-0.570000, -0.570000, 0.570000, 0.000000) +max r0.y, r0.y, l(0.000000) +mad o0.xyz, r0.yyyy, l(0.400000, 0.400000, 0.400000, 0.000000), r0.xxxx +mov o0.w, l(1.000000) +ret +// Approximately 14 instruction slots used +#endif + +const BYTE g_meshPS[] = +{ + 68, 88, 66, 67, 253, 169, + 122, 175, 25, 228, 25, 139, + 94, 18, 195, 68, 91, 159, + 92, 156, 1, 0, 0, 0, + 188, 3, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 160, 0, 0, 0, 244, 0, + 0, 0, 40, 1, 0, 0, + 32, 3, 0, 0, 82, 68, + 69, 70, 100, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 255, 255, 0, 1, 0, 0, + 60, 0, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 76, 0, 0, 0, + 2, 0, 0, 0, 8, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 7, 7, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 78, 79, 82, 77, + 65, 76, 0, 171, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 65, 82, 71, 69, 84, 0, + 171, 171, 83, 72, 69, 88, + 240, 1, 0, 0, 80, 0, + 0, 0, 124, 0, 0, 0, + 106, 8, 0, 1, 98, 16, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 16, 0, 0, 10, 18, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 133, 235, 17, 63, 133, 235, + 17, 63, 133, 235, 17, 63, + 0, 0, 0, 0, 52, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 205, 204, 204, 62, + 1, 64, 0, 0, 205, 204, + 204, 61, 16, 0, 0, 10, + 34, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 133, 235, 17, 191, + 133, 235, 17, 63, 133, 235, + 17, 63, 0, 0, 0, 0, + 52, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 10, 0, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 10, 34, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 133, 235, + 17, 63, 133, 235, 17, 63, + 133, 235, 17, 191, 0, 0, + 0, 0, 52, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 205, 204, 204, 62, 10, 0, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 10, 34, 0, + 16, 0, 0, 0, 0, 0, + 134, 17, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 133, 235, 17, 191, 133, 235, + 17, 191, 133, 235, 17, 63, + 0, 0, 0, 0, 52, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 114, 32, 16, 0, 0, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 205, 204, 204, 62, + 205, 204, 204, 62, 205, 204, + 204, 62, 0, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 14, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/demo/DemoAppD3D11/meshVS.hlsl.h b/demo/DemoAppD3D11/meshVS.hlsl.h new file mode 100644 index 0000000..e2c1466 --- /dev/null +++ b/demo/DemoAppD3D11/meshVS.hlsl.h @@ -0,0 +1,223 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer params +// { +// +// float4x4 projection; // Offset: 0 Size: 64 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// params cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xyz 0 NONE float xyz +// NORMAL 0 xyz 1 NONE float xyz +// SV_InstanceID 0 x 2 INSTID uint +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[4], immediateIndexed +dcl_input v0.xyz +dcl_input v1.xyz +dcl_output_siv o0.xyzw, position +dcl_output o1.xyz +dcl_temps 1 +mov r0.xyz, v0.xyzx +mov r0.w, l(1.000000) +dp4 o0.x, r0.xyzw, cb0[0].xyzw +dp4 o0.y, r0.xyzw, cb0[1].xyzw +dp4 o0.z, r0.xyzw, cb0[2].xyzw +dp4 o0.w, r0.xyzw, cb0[3].xyzw +mov o1.xyz, v1.xyzx +ret +// Approximately 8 instruction slots used +#endif + +const BYTE g_meshVS[] = +{ + 68, 88, 66, 67, 146, 57, + 84, 204, 22, 172, 14, 230, + 119, 17, 66, 227, 109, 150, + 21, 41, 1, 0, 0, 0, + 200, 3, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 64, 1, 0, 0, 184, 1, + 0, 0, 12, 2, 0, 0, + 44, 3, 0, 0, 82, 68, + 69, 70, 4, 1, 0, 0, + 1, 0, 0, 0, 100, 0, + 0, 0, 1, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 254, 255, 0, 1, 0, 0, + 220, 0, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 112, 97, 114, 97, + 109, 115, 0, 171, 92, 0, + 0, 0, 1, 0, 0, 0, + 124, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 0, + 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 2, 0, + 0, 0, 184, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 112, 114, 111, 106, + 101, 99, 116, 105, 111, 110, + 0, 102, 108, 111, 97, 116, + 52, 120, 52, 0, 3, 0, + 3, 0, 4, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 175, 0, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 112, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 80, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 7, 7, 0, 0, + 89, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 7, 7, 0, 0, + 96, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 80, 79, 83, 73, 84, 73, + 79, 78, 0, 78, 79, 82, + 77, 65, 76, 0, 83, 86, + 95, 73, 110, 115, 116, 97, + 110, 99, 101, 73, 68, 0, + 171, 171, 79, 83, 71, 78, + 76, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 7, 8, 0, 0, + 83, 86, 95, 80, 79, 83, + 73, 84, 73, 79, 78, 0, + 78, 79, 82, 77, 65, 76, + 0, 171, 83, 72, 69, 88, + 24, 1, 0, 0, 80, 0, + 1, 0, 70, 0, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 114, 32, + 16, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 54, 0, 0, 5, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 17, 0, 0, 8, 18, 32, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 54, 0, 0, 5, + 114, 32, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/demo/DemoAppD3D12/DemoAppD3D12.vcxproj b/demo/DemoAppD3D12/DemoAppD3D12.vcxproj new file mode 100644 index 0000000..9ddc20a --- /dev/null +++ b/demo/DemoAppD3D12/DemoAppD3D12.vcxproj @@ -0,0 +1,269 @@ +<?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="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Condition="'$(Platform)'=='Win32'"> + <PlatformName>win32</PlatformName> + </PropertyGroup> + <PropertyGroup Condition="'$(Platform)'=='x64'"> + <PlatformName>win64</PlatformName> + </PropertyGroup> + <ItemGroup> + <ClCompile Include="appD3D12Ctx.cpp" /> + <ClCompile Include="computeContextD3D12.cpp" /> + <ClCompile Include="imguiGraphD3D12.cpp" /> + <ClCompile Include="imguiInteropD3D12.cpp" /> + <ClCompile Include="meshD3D12.cpp" /> + <ClCompile Include="meshInteropD3D12.cpp" /> + <ClCompile Include="NvFlowInteropD3D12.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="appD3D12Ctx.h" /> + <ClInclude Include="computeContextD3D12.h" /> + <ClInclude Include="imguiGraphD3D12.h" /> + <ClInclude Include="meshD3D12.h" /> + </ItemGroup> + <ItemGroup> + <FxCompile Include="..\Shaders\imguiPS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType> + </FxCompile> + <FxCompile Include="..\Shaders\imguiVS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Vertex</ShaderType> + </FxCompile> + <FxCompile Include="..\Shaders\meshPS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType> + </FxCompile> + <FxCompile Include="..\Shaders\meshVS.hlsl"> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType> + <ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Vertex</ShaderType> + </FxCompile> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{BCBFA7E1-C9CE-4326-A5E3-3A93416BBD90}</ProjectGuid> + <RootNamespace>DemoAppD3D12</RootNamespace> + <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + <UseOfMfc>Static</UseOfMfc> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup 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" /> + </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)'=='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|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|x64'"> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlowContextD3D12;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win64;$(SolutionDir)external\SDL2\lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlowContextD3D12;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win64;$(SolutionDir)external\SDL2\lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlowContextD3D12;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win32;$(SolutionDir)external\SDL2\lib\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86</LibraryPath> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <IncludePath>$(SolutionDir)\include;$(SolutionDir)\NvFlowContextD3D12;$(SolutionDir)\NvFlow;$(SolutionDir)\NvFlowContext;$(SolutionDir)external\SDL2\include;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath> + <LibraryPath>$(SolutionDir)lib\win32;$(SolutionDir)external\SDL2\lib\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86</LibraryPath> + <OutDir>$(SolutionDir)bin\$(PlatformName)\</OutDir> + <IntDir>interm\$(Configuration)_$(PlatformName)\</IntDir> + <TargetName>$(ProjectName)$(Configuration)_$(PlatformName)</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <FxCompile> + <EntryPointName>%(Filename)</EntryPointName> + </FxCompile> + <FxCompile> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <FxCompile> + <VariableName> + </VariableName> + </FxCompile> + <FxCompile> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + </FxCompile> + <FxCompile> + <ObjectFileOutput /> + </FxCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <FxCompile> + <EntryPointName>%(Filename)</EntryPointName> + </FxCompile> + <FxCompile> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <FxCompile> + <VariableName> + </VariableName> + </FxCompile> + <FxCompile> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + </FxCompile> + <FxCompile> + <ObjectFileOutput /> + </FxCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <FxCompile> + <EntryPointName>%(Filename)</EntryPointName> + </FxCompile> + <FxCompile> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <FxCompile> + <VariableName> + </VariableName> + </FxCompile> + <FxCompile> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + </FxCompile> + <FxCompile> + <ObjectFileOutput /> + </FxCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalDependencies>NvFlowLib$(Configuration)_$(PlatformName).lib;SDL2.lib;SDL2main.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> + <FxCompile> + <EntryPointName>%(Filename)</EntryPointName> + </FxCompile> + <FxCompile> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <FxCompile> + <VariableName> + </VariableName> + </FxCompile> + <FxCompile> + <HeaderFileOutput>$(ProjectDir)%(Filename).hlsl.h</HeaderFileOutput> + </FxCompile> + <FxCompile> + <ObjectFileOutput /> + </FxCompile> + </ItemDefinitionGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/demo/DemoAppD3D12/DemoAppD3D12.vcxproj.filters b/demo/DemoAppD3D12/DemoAppD3D12.vcxproj.filters new file mode 100644 index 0000000..fcb8c61 --- /dev/null +++ b/demo/DemoAppD3D12/DemoAppD3D12.vcxproj.filters @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Shaders"> + <UniqueIdentifier>{154d623a-ffac-4ddd-a878-c4dc912a750d}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="appD3D12Ctx.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="imguiGraphD3D12.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="meshD3D12.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="NvFlowInteropD3D12.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="meshInteropD3D12.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="imguiInteropD3D12.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="computeContextD3D12.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="appD3D12Ctx.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="imguiGraphD3D12.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="meshD3D12.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="computeContextD3D12.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <FxCompile Include="..\Shaders\imguiPS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + <FxCompile Include="..\Shaders\imguiVS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + <FxCompile Include="..\Shaders\meshPS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + <FxCompile Include="..\Shaders\meshVS.hlsl"> + <Filter>Shaders</Filter> + </FxCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/demo/DemoAppD3D12/NvFlowInteropD3D12.cpp b/demo/DemoAppD3D12/NvFlowInteropD3D12.cpp new file mode 100644 index 0000000..ce79bcc --- /dev/null +++ b/demo/DemoAppD3D12/NvFlowInteropD3D12.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include <d3d12.h> + +#include "../DemoApp/NvFlowInterop.h" + +#include "NvFlowContextD3D12.h" +#include "appD3D12Ctx.h" + +NvFlowDescriptorReserveHandleD3D12 NvFlowInteropReserveDescriptors(void* userdata, NvFlowUint numDescriptors, NvFlowUint64 lastFenceCompleted, NvFlowUint64 nextFenceValue) +{ + auto appctx = static_cast<AppGraphCtx*>(userdata); + auto srcHandle = appctx->m_dynamicHeapCbvSrvUav.reserveDescriptors(numDescriptors, lastFenceCompleted, nextFenceValue); + NvFlowDescriptorReserveHandleD3D12 handle = {}; + handle.heap = srcHandle.heap; + handle.descriptorSize = srcHandle.descriptorSize; + handle.cpuHandle = srcHandle.cpuHandle; + handle.gpuHandle = srcHandle.gpuHandle; + return handle; +} + +void NvFlowInteropUpdateContextDesc(NvFlowContextDescD3D12* desc, AppGraphCtx* appctx) +{ + desc->device = appctx->m_device; + desc->commandQueue = appctx->m_commandQueue; + desc->commandQueueFence = appctx->m_fence; + desc->commandList = appctx->m_commandList; + desc->lastFenceCompleted = appctx->m_lastFenceComplete; + desc->nextFenceValue = appctx->m_thisFrameFenceID; + + desc->dynamicHeapCbvSrvUav.userdata = appctx; + desc->dynamicHeapCbvSrvUav.reserveDescriptors = NvFlowInteropReserveDescriptors; +} + +NvFlowContext* NvFlowInteropCreateContext(AppGraphCtx* appctx) +{ + NvFlowContextDescD3D12 desc = {}; + NvFlowInteropUpdateContextDesc(&desc, appctx); + return NvFlowCreateContextD3D12(NV_FLOW_VERSION, &desc); +} + +NvFlowDepthStencilView* NvFlowInteropCreateDepthStencilView(AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + NvFlowDepthStencilViewDescD3D12 desc = {}; + desc.dsvHandle = appctx->m_current_dsvHandle; + desc.dsvDesc = appctx->m_current_dsvDesc; + desc.srvHandle = appctx->m_current_depth_srvHandle; + desc.srvDesc = appctx->m_current_depth_srvDesc; + desc.resource = appctx->m_depthStencil; + desc.currentState = D3D12_RESOURCE_STATE_DEPTH_WRITE; + desc.viewport = appctx->m_viewport; + return NvFlowCreateDepthStencilViewD3D12(flowctx, &desc); +} + +NvFlowRenderTargetView* NvFlowInteropCreateRenderTargetView(AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + NvFlowRenderTargetViewDescD3D12 desc = {}; + desc.rtvHandle = appctx->m_current_rtvHandle; + desc.rtvDesc = appctx->m_current_rtvDesc; + desc.resource = appctx->m_current_renderTarget; + desc.currentState = D3D12_RESOURCE_STATE_RENDER_TARGET; + desc.viewport = appctx->m_viewport; + desc.scissor = appctx->m_scissorRect; + return NvFlowCreateRenderTargetViewD3D12(flowctx, &desc); +} + +void NvFlowInteropUpdateContext(NvFlowContext* context, AppGraphCtx* appctx) +{ + NvFlowContextDescD3D12 desc = {}; + NvFlowInteropUpdateContextDesc(&desc, appctx); + NvFlowUpdateContextD3D12(context, &desc); +} + +void NvFlowInteropUpdateDepthStencilView(NvFlowDepthStencilView* view, AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + NvFlowDepthStencilViewDescD3D12 desc = {}; + desc.dsvHandle = appctx->m_current_dsvHandle; + desc.dsvDesc = appctx->m_current_dsvDesc; + desc.srvHandle = appctx->m_current_depth_srvHandle; + desc.srvDesc = appctx->m_current_depth_srvDesc; + desc.resource = appctx->m_depthStencil; + desc.currentState = D3D12_RESOURCE_STATE_DEPTH_WRITE; + desc.viewport = appctx->m_viewport; + NvFlowUpdateDepthStencilViewD3D12(flowctx, view, &desc); +} + +void NvFlowInteropUpdateRenderTargetView(NvFlowRenderTargetView* view, AppGraphCtx* appctx, NvFlowContext* flowctx) +{ + NvFlowRenderTargetViewDescD3D12 desc = {}; + desc.rtvHandle = appctx->m_current_rtvHandle; + desc.rtvDesc = appctx->m_current_rtvDesc; + desc.resource = appctx->m_current_renderTarget; + desc.currentState = D3D12_RESOURCE_STATE_RENDER_TARGET; + desc.viewport = appctx->m_viewport; + desc.scissor = appctx->m_scissorRect; + NvFlowUpdateRenderTargetViewD3D12(flowctx, view, &desc); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D12/appD3D12Ctx.cpp b/demo/DemoAppD3D12/appD3D12Ctx.cpp new file mode 100644 index 0000000..8d1d7ff --- /dev/null +++ b/demo/DemoAppD3D12/appD3D12Ctx.cpp @@ -0,0 +1,1097 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +//direct3d headers +#include <d3d12.h> +#include <dxgi1_4.h> + +// include the Direct3D Library file +#pragma comment (lib, "d3d12.lib") +#pragma comment (lib, "DXGI.lib") + +#include "appD3D12Ctx.h" + +#include <stdio.h> + +#include <SDL.h> +#include <SDL_video.h> +#include <SDL_syswm.h> + +namespace +{ + // COM object release utilities + template <class T> + void inline COMRelease(T& t) + { + if (t) t->Release(); + t = nullptr; + } + + template <class T> + void inline COMRelease(T& t, UINT arraySize) + { + for (UINT i = 0; i < arraySize; i++) + { + if (t[i]) t[i]->Release(); + t[i] = nullptr; + } + } +} + +AppGraphProfiler* appGraphCreateProfiler(AppGraphCtx* ctx); +void appGraphProfilerFrameBegin(AppGraphProfiler* profiler); +void appGraphProfilerFrameEnd(AppGraphProfiler* profiler); +void appGraphProfilerEnable(AppGraphProfiler* profiler, bool enabled); +void appGraphProfilerBegin(AppGraphProfiler* profiler, const char* label); +void appGraphProfilerEnd(AppGraphProfiler* profiler, const char* label); +bool appGraphProfilerGet(AppGraphProfiler* profiler, const char** plabel, float* cpuTime, float* gpuTime, int index); +void appGraphReleaseProfiler(AppGraphProfiler* profiler); + +void AppGraphCtxInitRenderTarget(AppGraphCtx* context, SDL_Window* window, bool fullscreen); + +AppGraphCtx::AppGraphCtx() +{ + m_profiler = appGraphCreateProfiler(this); +} + +AppGraphCtx::~AppGraphCtx() +{ + AppGraphCtxReleaseRenderTarget(this); + + COMRelease(m_device); + COMRelease(m_commandQueue); + COMRelease(m_rtvHeap); + COMRelease(m_dsvHeap); + COMRelease(m_depthSrvHeap); + COMRelease(m_commandAllocators, m_frameCount); + + COMRelease(m_fence); + CloseHandle(m_fenceEvent); + + COMRelease(m_commandList); + + m_dynamicHeapCbvSrvUav.release(); + + appGraphReleaseProfiler(m_profiler); + m_profiler = nullptr; +} + +AppGraphCtx* AppGraphCtxCreate(int deviceID) +{ + AppGraphCtx* context = new AppGraphCtx; + + HRESULT hr = S_OK; + +#if defined(_DEBUG) + // Enable the D3D12 debug layer. + { + ID3D12Debug* debugController; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) + { + debugController->EnableDebugLayer(); + } + COMRelease(debugController); + } +#endif + + UINT debugFlags = 0; +#ifdef _DEBUG + debugFlags |= DXGI_CREATE_FACTORY_DEBUG; +#endif + + // enumerate devices + IDXGIFactory4* pFactory = NULL; + CreateDXGIFactory2(debugFlags, IID_PPV_ARGS(&pFactory)); + IDXGIAdapter1* pAdapterTemp = NULL; + IDXGIAdapter1* pAdapter = NULL; + DXGI_ADAPTER_DESC1 adapterDesc; + int adapterIdx = 0; + while (S_OK == pFactory->EnumAdapters1(adapterIdx, &pAdapterTemp)) + { + pAdapterTemp->GetDesc1(&adapterDesc); + + context->m_dedicatedVideoMemory = (size_t)adapterDesc.DedicatedVideoMemory; + + if (deviceID == adapterIdx) + { + pAdapter = pAdapterTemp; + break; + } + else + { + pAdapterTemp->Release(); + } + adapterIdx++; + } + + // create device + if (hr = D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void**)&context->m_device)) + { + delete context; + return nullptr; + } + + // to disable annoying warning +#if 0 + context->m_device->SetStablePowerState(TRUE); +#endif + + // create command queue + { + D3D12_COMMAND_QUEUE_DESC desc; + desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + desc.NodeMask = 0; + + if (hr = context->m_device->CreateCommandQueue(&desc, IID_PPV_ARGS(&context->m_commandQueue))) + { + delete context; + return nullptr; + } + } + + // cleanup adapter and factory + COMRelease(pAdapter); + COMRelease(pFactory); + + // create RTV descriptor heap + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = context->m_renderTargetCount; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + if (hr = context->m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&context->m_rtvHeap))) + { + delete context; + return nullptr; + } + context->m_rtvDescriptorSize = context->m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + } + + // create DSV descriptor heap + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = 1; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + if (hr = context->m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&context->m_dsvHeap))) + { + delete context; + return nullptr; + } + } + + // create depth SRV descriptor heap + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = 1; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + if (hr = context->m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&context->m_depthSrvHeap))) + { + delete context; + return nullptr; + } + } + + // Create per frame resources + { + for (UINT idx = 0; idx < context->m_frameCount; idx++) + { + if (hr = context->m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&context->m_commandAllocators[idx]))) + { + delete context; + return nullptr; + } + } + } + + // create dynamic heap + { + context->m_dynamicHeapCbvSrvUav.init(context->m_device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 256u * 1024u); + } + + // Create command list and close it + { + if (hr = context->m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, + context->m_commandAllocators[context->m_frameIndex], nullptr, IID_PPV_ARGS(&context->m_commandList)) + ) + { + delete context; + return nullptr; + } + context->m_commandList->Close(); + } + + // create synchronization objects + { + if (hr = context->m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&context->m_fence))) + { + delete context; + return nullptr; + } + + context->m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (context->m_fenceEvent == nullptr) + { + delete context; + return nullptr; + } + } + + return context; +} + +bool AppGraphCtxUpdateSize(AppGraphCtx* context, SDL_Window* window, bool fullscreen) +{ + // TODO: fix iflip fullscreen support + fullscreen = false; + + bool sizeChanged = false; + + // sync with window + { + HWND hWnd = nullptr; + // get Windows handle to this SDL window + SDL_SysWMinfo winInfo; + SDL_VERSION(&winInfo.version); + if (SDL_GetWindowWMInfo(window, &winInfo)) + { + if (winInfo.subsystem == SDL_SYSWM_WINDOWS) + { + hWnd = winInfo.info.win.window; + } + } + context->m_hWnd = hWnd; + context->m_fullscreen = fullscreen; + + HRESULT hr = S_OK; + + RECT rc; + GetClientRect(context->m_hWnd, &rc); + UINT width = rc.right - rc.left; + UINT height = rc.bottom - rc.top; + + if (context->m_winW != width || context->m_winH != height) + { + context->m_winW = width; + context->m_winH = height; + sizeChanged = true; + context->m_valid = (context->m_winW != 0 && context->m_winH != 0); + } + } + + if (sizeChanged) + { + AppGraphCtxReleaseRenderTarget(context); + } + if (sizeChanged && context->m_valid) + { + AppGraphCtxInitRenderTarget(context, window, fullscreen); + } + + return context->m_valid; +} + +void AppGraphCtxInitRenderTarget(AppGraphCtx* context, SDL_Window* window, bool fullscreen) +{ + HWND hWnd = nullptr; + // get Windows handle to this SDL window + SDL_SysWMinfo winInfo; + SDL_VERSION(&winInfo.version); + if (SDL_GetWindowWMInfo(window, &winInfo)) + { + if (winInfo.subsystem == SDL_SYSWM_WINDOWS) + { + hWnd = winInfo.info.win.window; + } + } + context->m_hWnd = hWnd; + context->m_fullscreen = fullscreen; + + HRESULT hr = S_OK; + + UINT debugFlags = 0; +#ifdef _DEBUG + debugFlags |= DXGI_CREATE_FACTORY_DEBUG; +#endif + + // enumerate devices + IDXGIFactory4* pFactory = NULL; + CreateDXGIFactory2(debugFlags, IID_PPV_ARGS(&pFactory)); + + // create the swap chain + for (int i = 0; i < 2; i++) + { + DXGI_SWAP_CHAIN_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.BufferCount = context->m_renderTargetCount; + desc.BufferDesc.Width = context->m_winW; + desc.BufferDesc.Height = context->m_winH; + desc.BufferDesc.Format = context->m_rtv_format; // DXGI_FORMAT_R8G8B8A8_UNORM; + desc.BufferDesc.RefreshRate.Numerator = 0; + desc.BufferDesc.RefreshRate.Denominator = 0; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + desc.OutputWindow = context->m_hWnd; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Windowed = TRUE; // m_fullscreen ? FALSE : TRUE; + desc.Flags = context->m_fullscreen ? 0u : DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + + context->m_current_rtvDesc.Format = context->m_rtv_format; + context->m_current_rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + context->m_current_rtvDesc.Texture2D.MipSlice = 0u; + context->m_current_rtvDesc.Texture2D.PlaneSlice = 0u; + + if (hr = pFactory->CreateSwapChain(context->m_commandQueue, &desc, (IDXGISwapChain**)&context->m_swapChain)) + { + COMRelease(context->m_swapChain); + context->m_fullscreen = false; + continue; + } + + if (!context->m_fullscreen) + { + context->m_swapChainWaitableObject = context->m_swapChain->GetFrameLatencyWaitableObject(); + context->m_swapChain->SetMaximumFrameLatency(context->m_renderTargetCount - 2); + } + else + { + hr = context->m_swapChain->SetFullscreenState(true, nullptr); + if (hr != S_OK) + { + COMRelease(context->m_swapChain); + context->m_fullscreen = false; + continue; + } + DXGI_SWAP_CHAIN_DESC desc = {}; + context->m_swapChain->GetDesc(&desc); + context->m_swapChain->ResizeBuffers(context->m_renderTargetCount, context->m_winW, context->m_winH, desc.BufferDesc.Format, desc.Flags); + } + + context->m_frameIndex = context->m_swapChain->GetCurrentBackBufferIndex(); + break; + } + + // configure scissor and viewport + { + context->m_viewport.Width = float(context->m_winW); + context->m_viewport.Height = float(context->m_winH); + context->m_viewport.MaxDepth = 1.f; + + context->m_scissorRect.right = context->m_winW; + context->m_scissorRect.bottom = context->m_winH; + } + + COMRelease(pFactory); + + // create per render target resources + { + D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = context->m_rtvHeap->GetCPUDescriptorHandleForHeapStart(); + + for (UINT idx = 0; idx < context->m_renderTargetCount; idx++) + { + if (hr = context->m_swapChain->GetBuffer(idx, IID_PPV_ARGS(&context->m_renderTargets[idx]))) + { + return; + } + context->m_device->CreateRenderTargetView(context->m_renderTargets[idx], nullptr, rtvHandle); + rtvHandle.ptr += context->m_rtvDescriptorSize; + } + } + + // create the depth stencil + { + 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 = 0u; + heapProps.VisibleNodeMask = 0u; + + D3D12_RESOURCE_DESC texDesc = {}; + texDesc.MipLevels = 1u; + texDesc.Format = context->m_depth_format; // DXGI_FORMAT_R32_TYPELESS; // DXGI_FORMAT_R24G8_TYPELESS + texDesc.Width = context->m_winW; + texDesc.Height = context->m_winH; + texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL /*| D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE*/; + texDesc.DepthOrArraySize = 1u; + texDesc.SampleDesc.Count = 1u; + texDesc.SampleDesc.Quality = 0u; + texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + + D3D12_CLEAR_VALUE clearValue; + clearValue.Format = context->m_dsv_format; // DXGI_FORMAT_D32_FLOAT; + clearValue.DepthStencil.Depth = 1.f; + clearValue.DepthStencil.Stencil = 0; + + if (hr = context->m_device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &texDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &clearValue, + IID_PPV_ARGS(&context->m_depthStencil) + )) + { + return; + } + + // create the depth stencil view + D3D12_DEPTH_STENCIL_VIEW_DESC viewDesc = {}; + viewDesc.Format = context->m_dsv_format; // DXGI_FORMAT_D32_FLOAT; + viewDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + viewDesc.Flags = D3D12_DSV_FLAG_NONE; + viewDesc.Texture2D.MipSlice = 0; + + context->m_current_dsvDesc = viewDesc; + + context->m_device->CreateDepthStencilView(context->m_depthStencil, &viewDesc, context->m_dsvHeap->GetCPUDescriptorHandleForHeapStart()); + + // create the depth SRV + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Format = context->m_depth_srv_format; // DXGI_FORMAT_R32_FLOAT; + srvDesc.Texture2D.MipLevels = 1; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.ResourceMinLODClamp = 0.f; + + context->m_current_depth_srvDesc = srvDesc; + + D3D12_CPU_DESCRIPTOR_HANDLE srvHandle = context->m_depthSrvHeap->GetCPUDescriptorHandleForHeapStart(); + context->m_device->CreateShaderResourceView(context->m_depthStencil, &srvDesc, srvHandle); + } +} + +void AppGraphCtxReleaseRenderTarget(AppGraphCtx* context) +{ + if (context->m_swapChain == nullptr) + { + return; + } + + // need to make sure the pipeline is flushed + for (UINT i = 0; i < context->m_frameCount; i++) + { + // check dependencies + UINT64 fenceCompleted = context->m_fence->GetCompletedValue(); + if (fenceCompleted < context->m_fenceValues[i]) + { + context->m_fence->SetEventOnCompletion(context->m_fenceValues[i], context->m_fenceEvent); + WaitForSingleObjectEx(context->m_fenceEvent, INFINITE, FALSE); + } + } + + BOOL bFullscreen = FALSE; + context->m_swapChain->GetFullscreenState(&bFullscreen, nullptr); + if (bFullscreen == TRUE) context->m_swapChain->SetFullscreenState(FALSE, nullptr); + + COMRelease(context->m_swapChain); + COMRelease(context->m_renderTargets, context->m_renderTargetCount); + COMRelease(context->m_depthStencil); + + context->m_valid = false; + context->m_winW = 0u; + context->m_winH = 0u; +} + +void AppGraphCtxRelease(AppGraphCtx* context) +{ + if (context == nullptr) return; + + delete context; +} + +void AppGraphCtxFrameStart(AppGraphCtx* context, float clearColor[4]) +{ + // Get back render target index + context->m_renderTargetIndex = context->m_swapChain->GetCurrentBackBufferIndex(); + + // check dependencies + UINT64 fenceCompleted = context->m_fence->GetCompletedValue(); + if (fenceCompleted < context->m_fenceValues[context->m_frameIndex]) + { + context->m_fence->SetEventOnCompletion(context->m_fenceValues[context->m_frameIndex], context->m_fenceEvent); + WaitForSingleObjectEx(context->m_fenceEvent, INFINITE, FALSE); + } + + // The fence ID associated with completion of this frame + context->m_thisFrameFenceID = context->m_frameID + 1; + context->m_lastFenceComplete = context->m_fence->GetCompletedValue(); + + // reset this frame's command allocator + context->m_commandAllocators[context->m_frameIndex]->Reset(); + + // reset command list with this frame's allocator + context->m_commandList->Reset(context->m_commandAllocators[context->m_frameIndex], nullptr); + + appGraphProfilerFrameBegin(context->m_profiler); + + context->m_commandList->RSSetViewports(1, &context->m_viewport); + context->m_commandList->RSSetScissorRects(1, &context->m_scissorRect); + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = context->m_renderTargets[context->m_renderTargetIndex]; + barrier.Transition.Subresource = 0u; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + context->m_commandList->ResourceBarrier(1, &barrier); + + D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = context->m_rtvHeap->GetCPUDescriptorHandleForHeapStart(); + rtvHandle.ptr += context->m_renderTargetIndex * context->m_rtvDescriptorSize; + + D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = context->m_dsvHeap->GetCPUDescriptorHandleForHeapStart(); + context->m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle); + + context->m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); + context->m_commandList->ClearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH, 1.f, 0, 0, nullptr); + + /// to simplify interop implementation + context->m_current_renderTarget = context->m_renderTargets[context->m_renderTargetIndex]; + context->m_current_rtvHandle = rtvHandle; + context->m_current_dsvHandle = dsvHandle; + context->m_current_depth_srvHandle = context->m_depthSrvHeap->GetCPUDescriptorHandleForHeapStart(); +} + +void AppGraphCtxFramePresent(AppGraphCtx* context, bool fullsync) +{ + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = context->m_renderTargets[context->m_renderTargetIndex]; + barrier.Transition.Subresource = 0u; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + context->m_commandList->ResourceBarrier(1, &barrier); + + context->m_commandList->Close(); + + // submit command list + ID3D12CommandList* cmdLists[] = { context->m_commandList }; + context->m_commandQueue->ExecuteCommandLists(1, cmdLists); + + // check if now is good time to present + bool shouldPresent = context->m_fullscreen ? true : WaitForSingleObjectEx(context->m_swapChainWaitableObject, 0, TRUE) != WAIT_TIMEOUT; + if (shouldPresent) + { + context->m_swapChain->Present(0, 0); + context->m_renderTargetID++; + } + + appGraphProfilerFrameEnd(context->m_profiler); + + // signal for this frame id + context->m_frameID++; + context->m_fenceValues[context->m_frameIndex] = context->m_frameID; + context->m_commandQueue->Signal(context->m_fence, context->m_frameID); + + // increment frame index after signal + context->m_frameIndex = (context->m_frameIndex + 1) % context->m_frameCount; + + if (fullsync) + { + // check dependencies + for (int frameIndex = 0; frameIndex < context->m_frameCount; frameIndex++) + { + UINT64 fenceCompleted = context->m_fence->GetCompletedValue(); + if (fenceCompleted < context->m_fenceValues[frameIndex]) + { + context->m_fence->SetEventOnCompletion(context->m_fenceValues[frameIndex], context->m_fenceEvent); + WaitForSingleObjectEx(context->m_fenceEvent, INFINITE, FALSE); + } + } + } +} + +void AppGraphCtxWaitForFrames(AppGraphCtx* context, unsigned int maxFramesInFlight) +{ + unsigned int framesActive = maxFramesInFlight; + while (framesActive >= maxFramesInFlight) + { + // reset count each cycle, and get latest fence value + framesActive = 0u; + UINT64 fenceCompleted = context->m_fence->GetCompletedValue(); + + // determine how many frames are in flight + for (int frameIndex = 0; frameIndex < context->m_frameCount; frameIndex++) + { + if (fenceCompleted < context->m_fenceValues[frameIndex]) + { + framesActive++; + } + } + + if (framesActive >= maxFramesInFlight) + { + // find the active frame with the lowest fence ID + UINT64 minFenceID = 0; + unsigned int minFrameIdx = 0; + for (int frameIndex = 0; frameIndex < context->m_frameCount; frameIndex++) + { + if (fenceCompleted < context->m_fenceValues[frameIndex]) + { + if (minFenceID == 0) + { + minFenceID = context->m_fenceValues[frameIndex]; + minFrameIdx = frameIndex; + } + else if (context->m_fenceValues[frameIndex] < minFenceID) + { + minFenceID = context->m_fenceValues[frameIndex]; + minFrameIdx = frameIndex; + } + } + } + // Wait for min frame + { + unsigned int frameIndex = minFrameIdx; + fenceCompleted = context->m_fence->GetCompletedValue(); + if (fenceCompleted < context->m_fenceValues[frameIndex]) + { + context->m_fence->SetEventOnCompletion(context->m_fenceValues[frameIndex], context->m_fenceEvent); + WaitForSingleObjectEx(context->m_fenceEvent, INFINITE, FALSE); + } + } + } + } +} + +void AppGraphCtxProfileEnable(AppGraphCtx* context, bool enabled) +{ + appGraphProfilerEnable(context->m_profiler, enabled); +} + +void AppGraphCtxProfileBegin(AppGraphCtx* context, const char* label) +{ + appGraphProfilerBegin(context->m_profiler, label); +} + +void AppGraphCtxProfileEnd(AppGraphCtx* context, const char* label) +{ + appGraphProfilerEnd(context->m_profiler, label); +} + +bool AppGraphCtxProfileGet(AppGraphCtx* context, const char** plabel, float* cpuTime, float* gpuTime, int index) +{ + return appGraphProfilerGet(context->m_profiler, plabel, cpuTime, gpuTime, index); +} + +// ******************************* Dynamic descriptor heap ****************************** + +void AppDynamicDescriptorHeapD3D12::init(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE heapType, UINT minHeapSize) +{ + m_device = device; + m_heapSize = minHeapSize; + m_startSlot = 0u; + m_descriptorSize = m_device->GetDescriptorHandleIncrementSize(heapType); + + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = m_heapSize; + desc.Type = heapType; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_heap)); +} + +void AppDynamicDescriptorHeapD3D12::release() +{ + m_device = nullptr; + COMRelease(m_heap); + m_descriptorSize = 0u; + m_startSlot = 0u; + m_heapSize = 0u; +} + +AppDescriptorReserveHandleD3D12 AppDynamicDescriptorHeapD3D12::reserveDescriptors(UINT numDescriptors, UINT64 lastFenceCompleted, UINT64 nextFenceValue) +{ + UINT endSlot = m_startSlot + numDescriptors; + if (endSlot >= m_heapSize) + { + m_startSlot = 0u; + endSlot = numDescriptors; + } + D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle; + D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle; + cpuHandle = m_heap->GetCPUDescriptorHandleForHeapStart(); + cpuHandle.ptr += m_startSlot * m_descriptorSize; + gpuHandle = m_heap->GetGPUDescriptorHandleForHeapStart(); + gpuHandle.ptr += m_startSlot * m_descriptorSize; + + // advance start slot + m_startSlot = endSlot; + + AppDescriptorReserveHandleD3D12 handle = {}; + handle.heap = m_heap; + handle.descriptorSize = m_descriptorSize; + handle.cpuHandle = cpuHandle; + handle.gpuHandle = gpuHandle; + return handle; +} + +// ******************************* Profiler ********************************* + +namespace +{ + struct TimerCPU + { + LARGE_INTEGER oldCount; + LARGE_INTEGER count; + LARGE_INTEGER freq; + TimerCPU() + { + QueryPerformanceCounter(&count); + QueryPerformanceFrequency(&freq); + oldCount = count; + } + double getDeltaTime() + { + QueryPerformanceCounter(&count); + double dt = double(count.QuadPart - oldCount.QuadPart) / double(freq.QuadPart); + oldCount = count; + return dt; + } + }; + + struct TimerGPU + { + ID3D12QueryHeap* m_queryHeap = nullptr; + ID3D12Resource* m_queryReadback = nullptr; + UINT64 m_queryFrequency = 0; + UINT64 m_queryReadbackFenceVal = ~0llu; + + TimerGPU() {} + ~TimerGPU() + { + COMRelease(m_queryHeap); + COMRelease(m_queryReadback); + } + }; + + struct Timer + { + TimerCPU m_cpu; + TimerGPU m_gpu; + + const char* m_label = nullptr; + float m_cpuTime = 0.f; + float m_gpuTime = 0.f; + + Timer() {} + ~Timer() {} + }; + + struct TimerValue + { + const char* m_label = nullptr; + float m_cpuTime = 0.f; + float m_gpuTime = 0.f; + + struct Stat + { + float m_time = 0.f; + float m_maxTime = 0.f; + float m_maxTimeAge = 0.f; + + float m_smoothTime = 0.f; + float m_smoothTimeSum = 0.f; + float m_smoothTimeCount = 0.f; + + Stat() {} + void push(float time) + { + m_time = time; + + if (m_time > m_maxTime) + { + m_maxTime = m_time; + m_maxTimeAge = 0.f; + } + + if (fabsf(m_time - m_maxTime) < 0.25f * m_maxTime) + { + m_smoothTimeSum += m_time; + m_smoothTimeCount += 1.f; + m_smoothTimeSum *= 0.98f; + m_smoothTimeCount *= 0.98f; + m_smoothTime = m_smoothTimeSum / m_smoothTimeCount; + } + } + + float pull(float frameTime) + { + m_maxTimeAge += frameTime; + + if (m_maxTimeAge > 1.f) + { + m_maxTimeAge = 0.f; + m_maxTime = m_time; + m_smoothTimeSum = 0.f; + m_smoothTimeCount = 0.f; + } + return m_smoothTime; + } + }; + + Stat m_cpu; + Stat m_gpu; + + void push(float cpuTime, float gpuTime) + { + m_cpu.push(cpuTime); + m_gpu.push(gpuTime); + } + + void pull(float frameTime) + { + m_cpuTime = m_cpu.pull(frameTime); + m_gpuTime = m_gpu.pull(frameTime); + } + }; + + struct HeapPropsReadback : public D3D12_HEAP_PROPERTIES + { + HeapPropsReadback() + { + Type = D3D12_HEAP_TYPE_READBACK; + CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + CreationNodeMask = 0u; + VisibleNodeMask = 0u; + } + }; + struct ResourceDescBuffer : public D3D12_RESOURCE_DESC + { + ResourceDescBuffer(UINT64 size) + { + Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + Alignment = 0u; + Width = size; + Height = 1u; + DepthOrArraySize = 1u; + MipLevels = 1; + Format = DXGI_FORMAT_UNKNOWN; + SampleDesc.Count = 1u; + SampleDesc.Quality = 0u; + Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + Flags = D3D12_RESOURCE_FLAG_NONE; + } + }; +} + +struct AppGraphProfiler +{ + AppGraphCtx* m_context; + + int m_state = 0; + bool m_enabled = false; + + TimerCPU m_frameTimer; + float m_frameTime = 0.f; + + static const int m_timersCap = 64; + Timer m_timers[m_timersCap]; + int m_timersSize = 0; + + TimerValue m_timerValues[m_timersCap]; + int m_timerValuesSize = 0; + + AppGraphProfiler(AppGraphCtx* context); + ~AppGraphProfiler(); +}; + +AppGraphProfiler::AppGraphProfiler(AppGraphCtx* context) : m_context(context) +{ +} + +AppGraphProfiler::~AppGraphProfiler() +{ +} + +AppGraphProfiler* appGraphCreateProfiler(AppGraphCtx* ctx) +{ + return new AppGraphProfiler(ctx); +} + +void appGraphReleaseProfiler(AppGraphProfiler* profiler) +{ + delete profiler; +} + +void appGraphProfilerFrameBegin(AppGraphProfiler* p) +{ + p->m_frameTime = (float)p->m_frameTimer.getDeltaTime(); + + if (p->m_state == 0 && p->m_enabled) + { + p->m_timersSize = 0; + + p->m_state = 1; + } +} + +void appGraphProfilerFrameEnd(AppGraphProfiler* p) +{ + if (p->m_state == 1) + { + p->m_state = 2; + } +} + +void appGraphProfilerEnable(AppGraphProfiler* p, bool enabled) +{ + p->m_enabled = enabled; +} + +void appGraphProfilerBegin(AppGraphProfiler* p, const char* label) +{ + if (p->m_state == 1 && p->m_timersSize < p->m_timersCap) + { + auto& timer = p->m_timers[p->m_timersSize++]; + timer.m_label = label; + timer.m_cpu.getDeltaTime(); + + auto device = p->m_context->m_device; + + if (timer.m_gpu.m_queryHeap == nullptr) + { + D3D12_QUERY_HEAP_DESC queryDesc = {}; + queryDesc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP; + queryDesc.Count = 2; + queryDesc.NodeMask = 0; + + device->CreateQueryHeap(&queryDesc, IID_PPV_ARGS(&timer.m_gpu.m_queryHeap)); + + HeapPropsReadback readbackProps; + ResourceDescBuffer resDesc(2 * sizeof(UINT64)); + resDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + + device->CreateCommittedResource(&readbackProps, D3D12_HEAP_FLAG_NONE, + &resDesc, D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, IID_PPV_ARGS(&timer.m_gpu.m_queryReadback)); + } + + p->m_context->m_commandQueue->GetTimestampFrequency(&timer.m_gpu.m_queryFrequency); + + p->m_context->m_commandList->EndQuery(timer.m_gpu.m_queryHeap, D3D12_QUERY_TYPE_TIMESTAMP, 0); + } +} + +void appGraphProfilerEnd(AppGraphProfiler* p, const char* label) +{ + if (p->m_state == 1) + { + Timer* timer = nullptr; + for (int i = 0; i < p->m_timersSize; i++) + { + if (strcmp(p->m_timers[i].m_label, label) == 0) + { + timer = &p->m_timers[i]; + break; + } + } + if (timer) + { + p->m_context->m_commandList->EndQuery(timer->m_gpu.m_queryHeap, D3D12_QUERY_TYPE_TIMESTAMP, 1); + + p->m_context->m_commandList->ResolveQueryData(timer->m_gpu.m_queryHeap, D3D12_QUERY_TYPE_TIMESTAMP, 0, 2, timer->m_gpu.m_queryReadback, 0u); + + timer->m_gpu.m_queryReadbackFenceVal = p->m_context->m_thisFrameFenceID; + + timer->m_cpuTime = (float)timer->m_cpu.getDeltaTime(); + } + } +} + +bool appGraphProfilerFlush(AppGraphProfiler* p) +{ + if (p->m_state == 2) + { + for (int i = 0; i < p->m_timersSize; i++) + { + Timer& timer = p->m_timers[i]; + + if (timer.m_gpu.m_queryReadbackFenceVal > p->m_context->m_lastFenceComplete) + { + return false; + } + + UINT64 tsBegin, tsEnd; + { + void* data; + // Read range is nullptr, meaning full read access + D3D12_RANGE readRange; + readRange.Begin = 0u; + readRange.End = 2 * sizeof(UINT64); + timer.m_gpu.m_queryReadback->Map(0u, &readRange, &data); + if (data) + { + auto mapped = (UINT64*)data; + tsBegin = mapped[0]; + tsEnd = mapped[1]; + + D3D12_RANGE writeRange{}; + timer.m_gpu.m_queryReadback->Unmap(0u, &writeRange); + } + } + + timer.m_gpuTime = float(tsEnd - tsBegin) / float(timer.m_gpu.m_queryFrequency); + + // update TimerValue + int j = 0; + for (; j < p->m_timerValuesSize; j++) + { + TimerValue& value = p->m_timerValues[j]; + if (strcmp(value.m_label, timer.m_label) == 0) + { + value.push(timer.m_cpuTime, timer.m_gpuTime); + break; + } + } + if (j >= p->m_timerValuesSize && p->m_timerValuesSize < p->m_timersCap) + { + TimerValue& value = p->m_timerValues[p->m_timerValuesSize++]; + value.m_label = timer.m_label; + value.push(timer.m_cpuTime, timer.m_gpuTime); + } + } + + p->m_state = 0; + } + return false; +} + +bool appGraphProfilerGet(AppGraphProfiler* p, const char** plabel, float* cpuTime, float* gpuTime, int index) +{ + appGraphProfilerFlush(p); + { + if (index < p->m_timerValuesSize) + { + TimerValue& timer = p->m_timerValues[index]; + + timer.pull(p->m_frameTime); + + if (plabel) *plabel = timer.m_label; + if (cpuTime) *cpuTime = timer.m_cpuTime; + if (gpuTime) *gpuTime = timer.m_gpuTime; + + return true; + } + } + return false; +} + +size_t AppGraphCtxDedicatedVideoMemory(AppGraphCtx* context) +{ + return context->m_dedicatedVideoMemory; +}
\ No newline at end of file diff --git a/demo/DemoAppD3D12/appD3D12Ctx.h b/demo/DemoAppD3D12/appD3D12Ctx.h new file mode 100644 index 0000000..f6d2ba3 --- /dev/null +++ b/demo/DemoAppD3D12/appD3D12Ctx.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#ifndef APP_D3D12_CTX_H +#define APP_D3D12_CTX_H + +#include "../DemoApp/appGraphCtx.h" + +struct IDXGISwapChain3; + +struct AppGraphProfiler; + +struct AppDescriptorReserveHandleD3D12 +{ + ID3D12DescriptorHeap* heap; + UINT descriptorSize; + D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle; + D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle; +}; + +struct AppDynamicDescriptorHeapD3D12 +{ + ID3D12Device* m_device = nullptr; + ID3D12DescriptorHeap* m_heap = nullptr; + UINT m_descriptorSize = 0u; + UINT m_startSlot = 0u; + UINT m_heapSize = 0u; + + void init(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE heapType, UINT minHeapSize); + void release(); + AppDescriptorReserveHandleD3D12 reserveDescriptors(UINT numDescriptors, UINT64 lastFenceCompleted, UINT64 nextFenceValue); + + AppDynamicDescriptorHeapD3D12() {} + ~AppDynamicDescriptorHeapD3D12() { release(); } +}; + +struct AppGraphCtx +{ + HWND m_hWnd = nullptr; + + int m_winW = 0; + int m_winH = 0; + bool m_fullscreen = false; + bool m_valid = false; + + size_t m_dedicatedVideoMemory = 0u; + + // D3D12 non-replicated objects + D3D12_VIEWPORT m_viewport = {}; + D3D12_RECT m_scissorRect = {}; + ID3D12Device* m_device = nullptr; + ID3D12CommandQueue* m_commandQueue = nullptr; + + // D3D12 render target pipeline + static const UINT m_renderTargetCount = 6u; + UINT m_renderTargetIndex = 0u; + UINT64 m_renderTargetID = 0u; + IDXGISwapChain3* m_swapChain = nullptr; + HANDLE m_swapChainWaitableObject = nullptr; + ID3D12DescriptorHeap* m_rtvHeap = nullptr; + UINT m_rtvDescriptorSize = 0u; + ID3D12Resource* m_renderTargets[m_renderTargetCount] = {}; + + ID3D12Resource* m_depthStencil = nullptr; + ID3D12DescriptorHeap* m_dsvHeap = nullptr; + ID3D12DescriptorHeap* m_depthSrvHeap = nullptr; + + // D3D12 frame pipeline objects + static const UINT m_frameCount = 8u; + UINT m_frameIndex = 0u; + UINT64 m_frameID = 0u; + ID3D12CommandAllocator* m_commandAllocators[m_frameCount] = {}; + + // D3D12 synchronization objects + ID3D12Fence* m_fence = nullptr; + HANDLE m_fenceEvent = 0u; + UINT64 m_fenceValues[m_frameCount] = {}; + + // fence values for library synchronization + UINT64 m_lastFenceComplete = 1u; + UINT64 m_thisFrameFenceID = 2u; + + // D3D12 per asset objects + ID3D12GraphicsCommandList* m_commandList = nullptr; + ID3D12Resource* m_current_renderTarget = nullptr; + D3D12_CPU_DESCRIPTOR_HANDLE m_current_rtvHandle; + D3D12_RENDER_TARGET_VIEW_DESC m_current_rtvDesc; + D3D12_CPU_DESCRIPTOR_HANDLE m_current_dsvHandle; + D3D12_DEPTH_STENCIL_VIEW_DESC m_current_dsvDesc; + D3D12_CPU_DESCRIPTOR_HANDLE m_current_depth_srvHandle; + D3D12_SHADER_RESOURCE_VIEW_DESC m_current_depth_srvDesc; + + DXGI_FORMAT m_rtv_format = DXGI_FORMAT_R8G8B8A8_UNORM; + DXGI_FORMAT m_dsv_format = DXGI_FORMAT_D32_FLOAT; + DXGI_FORMAT m_depth_srv_format = DXGI_FORMAT_R32_FLOAT; + DXGI_FORMAT m_depth_format = DXGI_FORMAT_R32_TYPELESS; + + AppDynamicDescriptorHeapD3D12 m_dynamicHeapCbvSrvUav; + + AppGraphProfiler* m_profiler = nullptr; + + AppGraphCtx(); + ~AppGraphCtx(); +}; + +#endif
\ No newline at end of file diff --git a/demo/DemoAppD3D12/computeContextD3D12.cpp b/demo/DemoAppD3D12/computeContextD3D12.cpp new file mode 100644 index 0000000..f6cf26e --- /dev/null +++ b/demo/DemoAppD3D12/computeContextD3D12.cpp @@ -0,0 +1,759 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#include <d3d12.h> + +#include "computeContextD3D12.h" + +#include <vector> + +// ************************** Compute Context Implementation ****************** + +typedef unsigned int ComputeUint; +typedef unsigned long long ComputeUint64; + +namespace +{ + template<class T> + struct VectorCached + { + std::vector<T> m_data; + + ComputeUint m_size = 0u; + + ComputeUint allocateBack() + { + m_size++; + m_data.resize(m_size); + return m_size - 1; + } + + T& operator[](unsigned int idx) + { + return m_data[idx]; + } + }; + + template <class BufferData> + struct VersionedBuffer + { + BufferData* map(ComputeUint64 lastFenceCompleted, ComputeUint64 nextFenceValue); + void unmap(ComputeUint64 lastFenceCompleted, ComputeUint64 nextFenceValue); + + struct Buffer + { + ComputeUint64 releaseFenceValue = ~0llu; + BufferData bufferData; + + Buffer() : bufferData() {} + }; + + VectorCached<Buffer> m_buffers; + ComputeUint m_frontIdx = 0u; + ComputeUint m_mappedIdx = 0u; + + BufferData* front(); + + ComputeUint64 currentFrame = 0u; + + VersionedBuffer(); + ~VersionedBuffer(); + }; + + template <class BufferData> + VersionedBuffer<BufferData>::VersionedBuffer() + { + } + + template <class BufferData> + VersionedBuffer<BufferData>::~VersionedBuffer() + { + } + + template <class BufferData> + BufferData* VersionedBuffer<BufferData>::front() + { + return &m_buffers[m_frontIdx].bufferData; + } + + template <class BufferData> + BufferData* VersionedBuffer<BufferData>::map(ComputeUint64 lastFenceCompleted, ComputeUint64 nextFenceValue) + { + // search for available buffer + ComputeUint numBuffers = m_buffers.m_size; + ComputeUint index = m_frontIdx + 1; + for (; index < numBuffers; index++) + { + if (m_buffers[index].releaseFenceValue <= lastFenceCompleted) + { + break; + } + } + if (index == numBuffers) + { + for (index = 0u; index < m_frontIdx; index++) + { + if (m_buffers[index].releaseFenceValue <= lastFenceCompleted) + { + break; + } + } + } + if (index == m_frontIdx || numBuffers == 0u) + { + index = m_buffers.allocateBack(); + } + m_mappedIdx = index; + return &m_buffers[index].bufferData; + } + + template <class BufferData> + void VersionedBuffer<BufferData>::unmap(ComputeUint64 lastFenceCompleted, ComputeUint64 nextFenceValue) + { + // mark front obsolete + if (m_frontIdx != m_mappedIdx) m_buffers[m_frontIdx].releaseFenceValue = nextFenceValue; + // set new front + m_frontIdx = m_mappedIdx; + } +} + +namespace +{ + struct HeapPropsUpload : public D3D12_HEAP_PROPERTIES + { + HeapPropsUpload() + { + Type = D3D12_HEAP_TYPE_UPLOAD; + CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + CreationNodeMask = 0u; + VisibleNodeMask = 0u; + } + }; + struct ResourceDescBuffer : public D3D12_RESOURCE_DESC + { + ResourceDescBuffer(UINT64 size) + { + Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + Alignment = 0u; + Width = size; + Height = 1u; + DepthOrArraySize = 1u; + MipLevels = 1; + Format = DXGI_FORMAT_UNKNOWN; + SampleDesc.Count = 1u; + SampleDesc.Quality = 0u; + Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + Flags = D3D12_RESOURCE_FLAG_NONE; + } + }; + struct DescriptorRange : public D3D12_DESCRIPTOR_RANGE + { + void init(D3D12_DESCRIPTOR_RANGE_TYPE type, UINT baseRegister, UINT numDescriptors) + { + RangeType = type; + NumDescriptors = numDescriptors; + BaseShaderRegister = baseRegister; + RegisterSpace = 0u; + OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + } + }; + struct RootParameter : public D3D12_ROOT_PARAMETER + { + void initRootConstant(D3D12_SHADER_VISIBILITY visibility, UINT shaderReg) + { + ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + Descriptor.ShaderRegister = shaderReg; + Descriptor.RegisterSpace = 0u; + ShaderVisibility = visibility; + } + void initTable(D3D12_DESCRIPTOR_RANGE* range, D3D12_SHADER_VISIBILITY visibility) + { + ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + DescriptorTable.NumDescriptorRanges = 1; + DescriptorTable.pDescriptorRanges = range; + ShaderVisibility = visibility; + } + }; + struct StaticSamplerDesc : public D3D12_STATIC_SAMPLER_DESC + { + void init(UINT shaderRegister, D3D12_FILTER filter, D3D12_TEXTURE_ADDRESS_MODE addressMode) + { + Filter = filter; + AddressU = addressMode; + AddressV = addressMode; + AddressW = addressMode; + MipLODBias = 0; + MaxAnisotropy = 0; + ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + MinLOD = 0.f; + MaxLOD = D3D12_FLOAT32_MAX; + ShaderRegister = shaderRegister; + RegisterSpace = 0; + ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + } + }; + struct ComputeRootSignature + { + static const int numRanges = 2; + static const int numParams = 3; //4; + static const int numSamplers = 6; + + DescriptorRange ranges[numRanges]; + RootParameter params[numParams]; + StaticSamplerDesc samplers[numSamplers]; + D3D12_ROOT_SIGNATURE_DESC desc; + + ComputeRootSignature() + { + ranges[0].init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0u, ComputeDispatchMaxResources); + ranges[1].init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0u, ComputeDispatchMaxResourcesRW); + + params[0].initRootConstant(D3D12_SHADER_VISIBILITY_ALL, 0u); + params[1].initTable(&ranges[0], D3D12_SHADER_VISIBILITY_ALL); + params[2].initTable(&ranges[1], D3D12_SHADER_VISIBILITY_ALL); + //params[3].initRootConstant(D3D12_SHADER_VISIBILITY_ALL, 1u); + + samplers[0].init(0, D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_BORDER); + samplers[1].init(1, D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_BORDER); + samplers[2].init(2, D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_WRAP); + samplers[3].init(3, D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_WRAP); + samplers[4].init(4, D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_CLAMP); + samplers[5].init(5, D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_CLAMP); + + desc.NumParameters = numParams; + desc.pParameters = params; + desc.NumStaticSamplers = numSamplers; + desc.pStaticSamplers = samplers; + desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + } + }; +}; + +template <class T> +void inline COMRelease(T& t) +{ + if (t) t->Release(); + t = nullptr; +} + +struct ComputeContextUserData +{ + virtual void Release() = 0; +}; + +struct ComputeContext +{ + ComputeContextDesc m_desc = {}; + + ID3D12RootSignature* m_rootSignatureCompute = nullptr; + ID3D12DescriptorHeap* m_nullHeap = nullptr; + D3D12_CPU_DESCRIPTOR_HANDLE m_nullUAV; + D3D12_CPU_DESCRIPTOR_HANDLE m_nullSRV; + + ComputeContextUserData* m_computeUserdata = nullptr; + + ComputeContext(const ComputeContextDesc* desc) + { + m_desc = *desc; + + auto createRootSignature = [&](D3D12_ROOT_SIGNATURE_DESC* desc, ID3D12RootSignature** root) + { + ID3DBlob* signature = nullptr; + ID3DBlob* error = nullptr; + HRESULT hr = S_OK; + if (hr = D3D12SerializeRootSignature(desc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)) + { + return hr; + } + if (hr = m_desc.device->CreateRootSignature(0u, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(root))) + { + return hr; + } + COMRelease(signature); + COMRelease(error); + return HRESULT(0); + }; + { + ComputeRootSignature desc; + createRootSignature(&desc.desc, &m_rootSignatureCompute); + } + + // create CPU descriptor heap + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = 2u; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + m_desc.device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_nullHeap)); + } + + // create null UAV + { + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + uavDesc.Format = DXGI_FORMAT_R32_UINT; + uavDesc.Buffer.FirstElement = 0u; + uavDesc.Buffer.NumElements = 256u; + + m_nullUAV = m_nullHeap->GetCPUDescriptorHandleForHeapStart(); + m_desc.device->CreateUnorderedAccessView(nullptr, nullptr, &uavDesc, m_nullUAV); + } + + // create null SRV + { + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + srvDesc.Texture2D.MipLevels = 1; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.ResourceMinLODClamp = 0.0f; + + m_nullSRV = m_nullHeap->GetCPUDescriptorHandleForHeapStart(); + m_nullSRV.ptr += m_desc.device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + m_desc.device->CreateShaderResourceView(nullptr, &srvDesc, m_nullSRV); + } + } + ~ComputeContext() + { + COMRelease(m_rootSignatureCompute); + COMRelease(m_nullHeap); + COMRelease(m_computeUserdata); + } +}; + +struct ComputeShader +{ + ID3D12PipelineState* m_shader = nullptr; + ComputeShader(ID3D12PipelineState* shader) + { + m_shader = shader; + } + ~ComputeShader() + { + COMRelease(m_shader); + } +}; + +struct ComputeConstantBuffer +{ + ComputeConstantBufferDesc m_desc = {}; + + struct BufferData + { + ID3D12Resource* m_buffer = nullptr; + void* m_mappedData = nullptr; + + BufferData() {} + }; + VersionedBuffer<BufferData> m_buffers; + + ComputeConstantBuffer(ComputeContext* context, const ComputeConstantBufferDesc* desc) + { + m_desc = *desc; + + // map and unmap to trigger initial allocation + ComputeConstantBufferMap(context, this); + ComputeConstantBufferUnmap(context, this); + } + ~ComputeConstantBuffer() + { + for (ComputeUint i = 0; i < m_buffers.m_buffers.m_size; i++) + { + COMRelease(m_buffers.m_buffers[i].bufferData.m_buffer); + } + } +}; + +struct ComputeResource +{ +protected: + D3D12_CPU_DESCRIPTOR_HANDLE m_srv; + ID3D12Resource* m_resource; + D3D12_RESOURCE_STATES* m_currentState; +public: + void update(const ComputeResourceDesc* desc) + { + m_srv = desc->srv; + m_resource = desc->resource; + m_currentState = desc->currentState; + } + + ComputeResource(const ComputeResourceDesc* desc) + { + update(desc); + } + + D3D12_CPU_DESCRIPTOR_HANDLE SRV() + { + return m_srv; + } + + ID3D12Resource* resource() + { + return m_resource; + } + + D3D12_RESOURCE_STATES* currentState() + { + return m_currentState; + } +}; + +struct ComputeResourceRW : public ComputeResource +{ +protected: + D3D12_CPU_DESCRIPTOR_HANDLE m_uav; +public: + void update(const ComputeResourceRWDesc* descRW) + { + m_uav = descRW->uav; + ComputeResource::update(&descRW->resource); + } + + ComputeResourceRW(const ComputeResourceRWDesc* descRW) : + ComputeResource(&descRW->resource) + { + m_uav = descRW->uav; + } + + D3D12_CPU_DESCRIPTOR_HANDLE UAV() + { + return m_uav; + } +}; + +// ************* API functions **************** + +ComputeContext* ComputeContextCreate(ComputeContextDesc* desc) +{ + return new ComputeContext(desc); +} + +void ComputeContextUpdate(ComputeContext* context, ComputeContextDesc* desc) +{ + context->m_desc = *desc; +} + +void ComputeContextRelease(ComputeContext* context) +{ + delete context; +} + +ComputeShader* ComputeShaderCreate(ComputeContext* context, const ComputeShaderDesc* desc) +{ + ID3D12PipelineState* computeShader = nullptr; + + D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = context->m_rootSignatureCompute; + psoDesc.CS.pShaderBytecode = desc->cs; + psoDesc.CS.BytecodeLength = desc->cs_length; + + context->m_desc.device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&computeShader)); + + return new ComputeShader(computeShader); +} + +void ComputeShaderRelease(ComputeShader* shader) +{ + delete shader; +} + +ComputeConstantBuffer* ComputeConstantBufferCreate(ComputeContext* context, const ComputeConstantBufferDesc* desc) +{ + return new ComputeConstantBuffer(context, desc); +} + +void ComputeConstantBufferRelease(ComputeConstantBuffer* constantBuffer) +{ + delete constantBuffer; +} + +void* ComputeConstantBufferMap(ComputeContext* context, ComputeConstantBuffer* constantBuffer) +{ + auto bufferData = constantBuffer->m_buffers.map(context->m_desc.lastFenceCompleted, context->m_desc.nextFenceValue); + + if (bufferData->m_buffer == nullptr) + { + HeapPropsUpload heapProps; + ResourceDescBuffer resDesc(constantBuffer->m_desc.sizeInBytes); + + context->m_desc.device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, + &resDesc, D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, IID_PPV_ARGS(&bufferData->m_buffer)); + + UINT8* pdata = nullptr; + D3D12_RANGE readRange = {}; + bufferData->m_buffer->Map(0, &readRange, (void**)&pdata); + + bufferData->m_mappedData = pdata; + } + return bufferData->m_mappedData; +} + +void ComputeConstantBufferUnmap(ComputeContext* context, ComputeConstantBuffer* constantBuffer) +{ + constantBuffer->m_buffers.unmap(context->m_desc.lastFenceCompleted, context->m_desc.nextFenceValue); +} + +ComputeResource* ComputeResourceCreate(ComputeContext* context, const ComputeResourceDesc* desc) +{ + return new ComputeResource(desc); +} + +void ComputeResourceUpdate(ComputeContext* context, ComputeResource* resource, const ComputeResourceDesc* desc) +{ + resource->update(desc); +} + +void ComputeResourceRelease(ComputeResource* resource) +{ + delete resource; +} + +ComputeResourceRW* ComputeResourceRWCreate(ComputeContext* context, const ComputeResourceRWDesc* desc) +{ + return new ComputeResourceRW(desc); +} + +void ComputeResourceRWUpdate(ComputeContext* context, ComputeResourceRW* resourceRW, const ComputeResourceRWDesc* desc) +{ + resourceRW->update(desc); +} + +void ComputeResourceRWRelease(ComputeResourceRW* resourceRW) +{ + delete resourceRW; +} + +ComputeResource* ComputeResourceRWGetResource(ComputeResourceRW* resourceRW) +{ + return static_cast<ComputeResource*>(resourceRW); +} + +void ComputeContextDispatch(ComputeContext* context, const ComputeDispatchParams* params) +{ + auto& commandList = context->m_desc.commandList; + + commandList->SetComputeRootSignature(context->m_rootSignatureCompute); + if (params->shader) commandList->SetPipelineState(params->shader->m_shader); + + auto handles = context->m_desc.dynamicHeapCbvSrvUav.reserveDescriptors(context->m_desc.dynamicHeapCbvSrvUav.userdata, + ComputeDispatchMaxResources + ComputeDispatchMaxResourcesRW, + context->m_desc.lastFenceCompleted, context->m_desc.nextFenceValue + ); + + commandList->SetDescriptorHeaps(1u, &handles.heap); + + for (ComputeUint i = 0u; i < ComputeDispatchMaxResources; i++) + { + auto r = params->resources[i]; + D3D12_CPU_DESCRIPTOR_HANDLE srcHandle = r ? r->SRV() : context->m_nullSRV; + context->m_desc.device->CopyDescriptorsSimple(1u, handles.cpuHandle, srcHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + handles.cpuHandle.ptr += handles.descriptorSize; + } + for (ComputeUint i = 0u; i < ComputeDispatchMaxResourcesRW; i++) + { + auto rw = params->resourcesRW[i]; + D3D12_CPU_DESCRIPTOR_HANDLE srcHandle = rw ? rw->UAV() : context->m_nullUAV; + context->m_desc.device->CopyDescriptorsSimple(1u, handles.cpuHandle, srcHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + handles.cpuHandle.ptr += handles.descriptorSize; + } + + commandList->SetComputeRootDescriptorTable(1u, handles.gpuHandle); + handles.gpuHandle.ptr += handles.descriptorSize * ComputeDispatchMaxResources; + commandList->SetComputeRootDescriptorTable(2u, handles.gpuHandle); + + if (params->constantBuffer) + { + auto cbv = params->constantBuffer->m_buffers.front()->m_buffer; + commandList->SetComputeRootConstantBufferView(0u, cbv->GetGPUVirtualAddress()); + } + + ComputeUint barrierIdx = 0u; + D3D12_RESOURCE_BARRIER barrier[ComputeDispatchMaxResources + ComputeDispatchMaxResourcesRW]; + for (ComputeUint i = 0u; i < ComputeDispatchMaxResources; i++) + { + auto r = params->resources[i]; + if (r) + { + if (!((*r->currentState()) & D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)) + { + D3D12_RESOURCE_BARRIER& bar = barrier[barrierIdx++]; + bar.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + bar.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + bar.Transition.pResource = r->resource(); + bar.Transition.Subresource = 0u; + bar.Transition.StateBefore = *r->currentState(); + bar.Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + + *r->currentState() = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + } + } + } + for (ComputeUint i = 0u; i < ComputeDispatchMaxResourcesRW; i++) + { + auto rw = params->resourcesRW[i]; + if (rw) + { + if ((*rw->currentState()) == D3D12_RESOURCE_STATE_UNORDERED_ACCESS) + { + D3D12_RESOURCE_BARRIER& bar = barrier[barrierIdx++]; + bar.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + bar.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + bar.UAV.pResource = rw->resource(); + } + else + { + D3D12_RESOURCE_BARRIER& bar = barrier[barrierIdx++]; + bar.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + bar.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + bar.Transition.pResource = rw->resource(); + bar.Transition.Subresource = 0u; + bar.Transition.StateBefore = *rw->currentState(); + bar.Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + + *rw->currentState() = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + } + } + } + + commandList->ResourceBarrier(barrierIdx, barrier); + + commandList->Dispatch(params->gridDim[0], params->gridDim[1], params->gridDim[2]); +} + +// ******************************* NvFlow Interoperation **************************************** + +#include "NvFlow.h" +#include "NvFlowContextD3D12.h" + +struct ComputeContextUserDataNvFlow : public ComputeContextUserData +{ + NvFlowDynamicDescriptorHeapD3D12 flowHeap = {}; + + void Release() override + { + delete this; + } +}; + +ComputeDescriptorReserveHandleD3D12 ComputeReserveDescriptors(void* userdata, UINT numDescriptors, UINT64 lastFenceCompleted, UINT64 nextFenceValue) +{ + auto data = static_cast<ComputeContextUserDataNvFlow*>(userdata); + auto srcHandle = data->flowHeap.reserveDescriptors(data->flowHeap.userdata, numDescriptors, lastFenceCompleted, nextFenceValue); + ComputeDescriptorReserveHandleD3D12 handle = {}; + handle.heap = srcHandle.heap; + handle.descriptorSize = srcHandle.descriptorSize; + handle.cpuHandle = srcHandle.cpuHandle; + handle.gpuHandle = srcHandle.gpuHandle; + return handle; +} + +ComputeContext* ComputeContextNvFlowContextCreate(NvFlowContext* flowContext) +{ + ComputeContextDesc desc = {}; + NvFlowContextDescD3D12 srcDesc = {}; + NvFlowUpdateContextDescD3D12(flowContext, &srcDesc); + + desc.device = srcDesc.device; + desc.commandQueue = srcDesc.commandQueue; + desc.commandQueueFence = srcDesc.commandQueueFence; + desc.commandList = srcDesc.commandList; + desc.lastFenceCompleted = srcDesc.lastFenceCompleted; + desc.nextFenceValue = srcDesc.nextFenceValue; + + auto computeUserdata = new ComputeContextUserDataNvFlow; + computeUserdata->flowHeap.userdata = srcDesc.dynamicHeapCbvSrvUav.userdata; + computeUserdata->flowHeap.reserveDescriptors = srcDesc.dynamicHeapCbvSrvUav.reserveDescriptors; + + desc.dynamicHeapCbvSrvUav.userdata = computeUserdata; + desc.dynamicHeapCbvSrvUav.reserveDescriptors = ComputeReserveDescriptors; + + auto computeContext = ComputeContextCreate(&desc); + + computeContext->m_computeUserdata = computeUserdata; + + return computeContext; +} + +void ComputeContextNvFlowContextUpdate(ComputeContext* computeContext, NvFlowContext* flowContext) +{ + ComputeContextDesc desc = {}; + NvFlowContextDescD3D12 srcDesc = {}; + NvFlowUpdateContextDescD3D12(flowContext, &srcDesc); + + desc.device = srcDesc.device; + desc.commandQueue = srcDesc.commandQueue; + desc.commandQueueFence = srcDesc.commandQueueFence; + desc.commandList = srcDesc.commandList; + desc.lastFenceCompleted = srcDesc.lastFenceCompleted; + desc.nextFenceValue = srcDesc.nextFenceValue; + + auto computeUserdata = static_cast<ComputeContextUserDataNvFlow*>(computeContext->m_computeUserdata); + computeUserdata->flowHeap.userdata = srcDesc.dynamicHeapCbvSrvUav.userdata; + computeUserdata->flowHeap.reserveDescriptors = srcDesc.dynamicHeapCbvSrvUav.reserveDescriptors; + + desc.dynamicHeapCbvSrvUav.userdata = computeUserdata; + desc.dynamicHeapCbvSrvUav.reserveDescriptors = ComputeReserveDescriptors; + + ComputeContextUpdate(computeContext, &desc); +} + +inline void updateComputeResourceDesc(NvFlowResourceViewDescD3D12* flowViewDesc, ComputeResourceDesc* desc) +{ + desc->srv = flowViewDesc->srvHandle; + desc->resource = flowViewDesc->resource; + desc->currentState = flowViewDesc->currentState; +} + +ComputeResource* ComputeResourceNvFlowCreate(ComputeContext* context, NvFlowContext* flowContext, NvFlowResource* flowResource) +{ + NvFlowResourceViewDescD3D12 flowViewDesc = {}; + NvFlowUpdateResourceViewDescD3D12(flowContext, flowResource, &flowViewDesc); + ComputeResourceDesc desc = {}; + updateComputeResourceDesc(&flowViewDesc, &desc); + return ComputeResourceCreate(context, &desc); +} + +void ComputeResourceNvFlowUpdate(ComputeContext* context, ComputeResource* resource, NvFlowContext* flowContext, NvFlowResource* flowResource) +{ + NvFlowResourceViewDescD3D12 flowViewDesc = {}; + NvFlowUpdateResourceViewDescD3D12(flowContext, flowResource, &flowViewDesc); + ComputeResourceDesc desc = {}; + updateComputeResourceDesc(&flowViewDesc, &desc); + ComputeResourceUpdate(context, resource, &desc); +} + +inline void updateComputeResourceRWDesc(NvFlowResourceRWViewDescD3D12* flowViewDesc, ComputeResourceRWDesc* desc) +{ + updateComputeResourceDesc(&flowViewDesc->resourceView, &desc->resource); + desc->uav = flowViewDesc->uavHandle; +} + +ComputeResourceRW* ComputeResourceRWNvFlowCreate(ComputeContext* context, NvFlowContext* flowContext, NvFlowResourceRW* flowResourceRW) +{ + NvFlowResourceRWViewDescD3D12 flowViewDesc = {}; + NvFlowUpdateResourceRWViewDescD3D12(flowContext, flowResourceRW, &flowViewDesc); + ComputeResourceRWDesc desc = {}; + updateComputeResourceRWDesc(&flowViewDesc, &desc); + return ComputeResourceRWCreate(context, &desc); +} + +void ComputeResourceRWNvFlowUpdate(ComputeContext* context, ComputeResourceRW* resourceRW, NvFlowContext* flowContext, NvFlowResourceRW* flowResourceRW) +{ + NvFlowResourceRWViewDescD3D12 flowViewDesc = {}; + NvFlowUpdateResourceRWViewDescD3D12(flowContext, flowResourceRW, &flowViewDesc); + ComputeResourceRWDesc desc = {}; + updateComputeResourceRWDesc(&flowViewDesc, &desc); + ComputeResourceRWUpdate(context, resourceRW, &desc); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D12/computeContextD3D12.h b/demo/DemoAppD3D12/computeContextD3D12.h new file mode 100644 index 0000000..0acb489 --- /dev/null +++ b/demo/DemoAppD3D12/computeContextD3D12.h @@ -0,0 +1,52 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#pragma once + +#include "../DemoApp/computeContext.h" + +struct ComputeDescriptorReserveHandleD3D12 +{ + ID3D12DescriptorHeap* heap; + UINT descriptorSize; + D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle; + D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle; +}; + +struct ComputeDynamicDescriptorHeapD3D12 +{ + void* userdata; + ComputeDescriptorReserveHandleD3D12(*reserveDescriptors)(void* userdata, UINT numDescriptors, UINT64 lastFenceCompleted, UINT64 nextFenceValue); +}; + +struct ComputeContextDesc +{ + ID3D12Device* device; + ID3D12CommandQueue* commandQueue; + ID3D12Fence* commandQueueFence; + ID3D12GraphicsCommandList* commandList; + UINT64 lastFenceCompleted; + UINT64 nextFenceValue; + + ComputeDynamicDescriptorHeapD3D12 dynamicHeapCbvSrvUav; +}; + +struct ComputeResourceDesc +{ + D3D12_CPU_DESCRIPTOR_HANDLE srv; + ID3D12Resource* resource; + D3D12_RESOURCE_STATES* currentState; +}; + +struct ComputeResourceRWDesc +{ + ComputeResourceDesc resource; + D3D12_CPU_DESCRIPTOR_HANDLE uav; +};
\ No newline at end of file diff --git a/demo/DemoAppD3D12/imguiGraphD3D12.cpp b/demo/DemoAppD3D12/imguiGraphD3D12.cpp new file mode 100644 index 0000000..9b5f74a --- /dev/null +++ b/demo/DemoAppD3D12/imguiGraphD3D12.cpp @@ -0,0 +1,662 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +//direct3d headers +#include <d3d12.h> + +#include "imguiGraphD3D12.h" + +#include "imguiVS.hlsl.h" +#include "imguiPS.hlsl.h" + +namespace +{ + template <class T> + void inline COMRelease(T& t) + { + if (t) t->Release(); + t = nullptr; + } +} + +namespace +{ + ImguiGraphDesc m_desc = {}; + + struct Vertex + { + float x, y; + float u, v; + uint8_t rgba[4]; + }; + + ID3D12RootSignature* m_rootSignature = nullptr; + ID3D12PipelineState* m_pipelineState = nullptr; + ID3D12Resource* m_constantBuffer = nullptr; + UINT8* m_constantBufferData = nullptr; + ID3D12Resource* m_vertexBuffer = nullptr; + Vertex* m_vertexBufferData = nullptr; + D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView = {}; + + struct Scissor + { + int beginIdx; + int stopIdx; + int x; + int y; + int width; + int height; + }; + Scissor m_stateScissor = {}; + + ID3D12Resource* m_textureUploadHeap = nullptr; + ID3D12Resource* m_texture = nullptr; + + ID3D12DescriptorHeap* m_srvUavHeapCPU = nullptr; + ID3D12DescriptorHeap* m_srvUavHeapGPU = nullptr; + + Vertex m_stateVert; + uint32_t m_stateVertIdx = 0u; + + struct Params + { + float projection[16]; + + float padding[64 - 16]; + }; + static const int frameCount = 4; + int frameIndex = 0; +} + +void imguiGraphContextInit(const ImguiGraphDesc* desc) +{ + m_desc = *desc; + + // create the root signature + { + D3D12_DESCRIPTOR_RANGE ranges[1]; + ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + ranges[0].NumDescriptors = 1u; + ranges[0].BaseShaderRegister = 0u; + ranges[0].RegisterSpace = 0u; + ranges[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + D3D12_ROOT_PARAMETER params[2]; + params[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + params[0].Descriptor.ShaderRegister = 0u; + params[0].Descriptor.RegisterSpace = 0u; + params[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + params[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + params[1].DescriptorTable.NumDescriptorRanges = 1; + params[1].DescriptorTable.pDescriptorRanges = ranges; + params[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + D3D12_STATIC_SAMPLER_DESC sampler = {}; + sampler.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; + sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER; + sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER; + sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER; + sampler.MipLODBias = 0; + sampler.MaxAnisotropy = 0; + sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + sampler.MinLOD = 0.f; + sampler.MaxLOD = D3D12_FLOAT32_MAX; + sampler.ShaderRegister = 0; + sampler.RegisterSpace = 0; + sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + D3D12_ROOT_SIGNATURE_DESC desc; + desc.NumParameters = 2; + desc.pParameters = params; + desc.NumStaticSamplers = 1u; + desc.pStaticSamplers = &sampler; + desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + + ID3DBlob* signature = nullptr; + ID3DBlob* error = nullptr; + HRESULT hr = S_OK; + if (hr = D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)) + { + return; + } + if (hr = m_desc.device->CreateRootSignature(0u, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature))) + { + return; + } + COMRelease(signature); + COMRelease(error); + } + + // create the pipeline state object + { + D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + const bool wireFrame = false; + + D3D12_RASTERIZER_DESC rasterDesc; + if (wireFrame) + { + rasterDesc.FillMode = D3D12_FILL_MODE_WIREFRAME; + rasterDesc.CullMode = D3D12_CULL_MODE_NONE; + } + else + { + rasterDesc.FillMode = D3D12_FILL_MODE_SOLID; + rasterDesc.CullMode = D3D12_CULL_MODE_BACK; + } + rasterDesc.FrontCounterClockwise = TRUE; // FALSE; + rasterDesc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + rasterDesc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + rasterDesc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + rasterDesc.ForcedSampleCount = 0; + rasterDesc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + + D3D12_BLEND_DESC blendDesc; + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = FALSE; + { + const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = + { + TRUE,FALSE, + D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, + D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL, + }; + for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) + blendDesc.RenderTarget[i] = defaultRenderTargetBlendDesc; + } + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout.NumElements = 3; + psoDesc.InputLayout.pInputElementDescs = inputElementDescs; + psoDesc.pRootSignature = m_rootSignature; + psoDesc.VS.pShaderBytecode = g_imguiVS; + psoDesc.VS.BytecodeLength = sizeof(g_imguiVS); + psoDesc.PS.pShaderBytecode = g_imguiPS; + psoDesc.PS.BytecodeLength = sizeof(g_imguiPS); + psoDesc.RasterizerState = rasterDesc; + psoDesc.BlendState = blendDesc; + psoDesc.DepthStencilState.DepthEnable = FALSE; + psoDesc.DepthStencilState.StencilEnable = FALSE; + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + psoDesc.SampleDesc.Count = 1; + HRESULT hr = S_OK; + if (hr = m_desc.device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState))) + { + return; + } + } + + // create a constant buffer + { + Params params = { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f + }; + + HRESULT hr = S_OK; + + D3D12_HEAP_PROPERTIES heapProps = {}; + heapProps.Type = D3D12_HEAP_TYPE_UPLOAD; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 0u; + heapProps.VisibleNodeMask = 0u; + + D3D12_RESOURCE_DESC desc = {}; + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Alignment = 0u; + desc.Width = frameCount*sizeof(params); + desc.Height = 1u; + desc.DepthOrArraySize = 1u; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1u; + desc.SampleDesc.Quality = 0u; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + + if (hr = m_desc.device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, IID_PPV_ARGS(&m_constantBuffer))) + { + return; + } + + UINT8* pdata; + D3D12_RANGE readRange = {}; + if (hr = m_constantBuffer->Map(0, &readRange, (void**)&pdata)) + { + return; + } + else + { + memcpy(pdata, ¶ms, sizeof(params)); + m_constantBufferData = pdata; + //m_constantBuffer->Unmap(0, nullptr); // leave mapped + } + } + + // create a vertex buffer + { + HRESULT hr = S_OK; + + UINT bufferSize = (UINT)(m_desc.maxVertices * frameCount) * sizeof(Vertex); + + D3D12_HEAP_PROPERTIES heapProps = {}; + heapProps.Type = D3D12_HEAP_TYPE_UPLOAD; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 0u; + heapProps.VisibleNodeMask = 0u; + + D3D12_RESOURCE_DESC desc = {}; + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Alignment = 0u; + desc.Width = bufferSize; + desc.Height = 1u; + desc.DepthOrArraySize = 1u; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1u; + desc.SampleDesc.Quality = 0u; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + + if (hr = m_desc.device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, IID_PPV_ARGS(&m_vertexBuffer))) + { + return; + } + + UINT8* pdata; + D3D12_RANGE readRange = {}; + if (hr = m_vertexBuffer->Map(0, &readRange, (void**)&pdata)) + { + return; + } + else + { + m_vertexBufferData = (Vertex*)pdata; + //m_vertexBufferUpload->Unmap(0, nullptr); + } + + m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); + m_vertexBufferView.StrideInBytes = sizeof(Vertex); + m_vertexBufferView.SizeInBytes = bufferSize; + } +} + +void imguiGraphContextUpdate(const ImguiGraphDesc* desc) +{ + m_desc = *desc; +} + +void imguiGraphContextDestroy() +{ + COMRelease(m_rootSignature); + COMRelease(m_pipelineState); + COMRelease(m_constantBuffer); + COMRelease(m_vertexBuffer); +} + +void imguiGraphRecordBegin() +{ + frameIndex = (frameIndex + 1) % frameCount; + + Params params = { + 2.f / float(m_desc.winW), 0.f, 0.f, -1.f, + 0.f, 2.f / float(m_desc.winH), 0.f, -1.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f + }; + + memcpy(m_constantBufferData + frameIndex*sizeof(Params), ¶ms, sizeof(Params)); + + // clear state + m_stateVert = Vertex{ 0.f, 0.f, -1.f, -1.f, 0,0,0,0 }; + m_stateVertIdx = 0u; + + m_stateScissor = Scissor { 0, 0, 0, 0, m_desc.winW, m_desc.winH }; + + // configure for triangle renderering + ID3D12GraphicsCommandList* commandList = m_desc.commandList; + + D3D12_CPU_DESCRIPTOR_HANDLE srvHandleCPU; + D3D12_GPU_DESCRIPTOR_HANDLE srvHandleGPU; + ID3D12DescriptorHeap* heap = nullptr; + if (m_desc.dynamicHeapCbvSrvUav.reserveDescriptors) + { + auto handle = m_desc.dynamicHeapCbvSrvUav.reserveDescriptors(m_desc.dynamicHeapCbvSrvUav.userdata, + 1u, m_desc.lastFenceCompleted, m_desc.nextFenceValue); + heap = handle.heap; + srvHandleCPU = handle.cpuHandle; + srvHandleGPU = handle.gpuHandle; + } + else + { + if (m_srvUavHeapGPU == nullptr) + { + D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; + srvHeapDesc.NumDescriptors = 1; + srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + m_desc.device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_srvUavHeapGPU)); + } + heap = m_srvUavHeapGPU; + srvHandleCPU = m_srvUavHeapGPU->GetCPUDescriptorHandleForHeapStart(); + srvHandleGPU = m_srvUavHeapGPU->GetGPUDescriptorHandleForHeapStart(); + } + + commandList->SetDescriptorHeaps(1, &heap); + + m_desc.device->CopyDescriptorsSimple(1u, srvHandleCPU, m_srvUavHeapCPU->GetCPUDescriptorHandleForHeapStart(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + commandList->SetGraphicsRootSignature(m_rootSignature); + commandList->SetPipelineState(m_pipelineState); + + D3D12_GPU_VIRTUAL_ADDRESS cbvHandle = m_constantBuffer->GetGPUVirtualAddress(); + commandList->SetGraphicsRootConstantBufferView(0, cbvHandle + frameIndex * sizeof(Params)); + + commandList->SetGraphicsRootDescriptorTable(1, srvHandleGPU); + + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView); +} + +static void imguiGraphFlush() +{ + ID3D12GraphicsCommandList* commandList = m_desc.commandList; + + Scissor& p = m_stateScissor; + if (p.beginIdx < p.stopIdx) + { + int winH = m_desc.winH; + D3D12_RECT rect; + rect.left = p.x; + rect.right = p.x + p.width; + rect.top = (winH) - (p.y + p.height); + rect.bottom = (winH) - (p.y); + commandList->RSSetScissorRects(1, &rect); + + UINT vertexCount = (p.stopIdx - p.beginIdx); + UINT startIndex = p.beginIdx + frameIndex * m_desc.maxVertices; + commandList->DrawInstanced(vertexCount, 1, startIndex, 0); + } +} + +void imguiGraphRecordEnd() +{ + ID3D12GraphicsCommandList* commandList = m_desc.commandList; + + // no need to hold onto this + COMRelease(m_textureUploadHeap); + + // restore scissor + Scissor& p = m_stateScissor; + int winH = m_desc.winH; + D3D12_RECT rect; + rect.left = p.x; + rect.right = p.x + p.width; + rect.top = (winH) - (p.y + p.height); + rect.bottom = (winH) - (p.y); + commandList->RSSetScissorRects(1, &rect); +} + +void imguiGraphEnableScissor(int x, int y, int width, int height) +{ + // mark end of last region + m_stateScissor.stopIdx = m_stateVertIdx; + + imguiGraphFlush(); + + m_stateScissor.beginIdx = m_stateVertIdx; + m_stateScissor.stopIdx = m_stateVertIdx; + m_stateScissor.x = x; + m_stateScissor.y = y; + m_stateScissor.width = width; + m_stateScissor.height = height; +} + +void imguiGraphDisableScissor() +{ + if (m_stateVertIdx == 0) return; + + // mark end of last region + m_stateScissor.stopIdx = m_stateVertIdx; + + imguiGraphFlush(); + + m_stateScissor.beginIdx = m_stateVertIdx; + m_stateScissor.stopIdx = m_stateVertIdx; + m_stateScissor.x = 0; + m_stateScissor.y = 0; + m_stateScissor.width = m_desc.winW; + m_stateScissor.height = m_desc.winH; +} + +void imguiGraphVertex2f(float x, float y) +{ + float v[2] = { x,y }; + imguiGraphVertex2fv(v); +} + +void imguiGraphVertex2fv(const float* v) +{ + // update state + m_stateVert.x = v[0]; + m_stateVert.y = v[1]; + + Vertex* vdata = &m_vertexBufferData[frameIndex * m_desc.maxVertices]; + + // push vertex + if ((m_stateVertIdx) < m_desc.maxVertices) + { + vdata[m_stateVertIdx++] = m_stateVert; + } +} + +void imguiGraphTexCoord2f(float u, float v) +{ + m_stateVert.u = u; + m_stateVert.v = v; +} + +void imguiGraphColor4ub(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) +{ + m_stateVert.rgba[0] = red; + m_stateVert.rgba[1] = green; + m_stateVert.rgba[2] = blue; + m_stateVert.rgba[3] = alpha; +} + +void imguiGraphColor4ubv(const uint8_t* v) +{ + m_stateVert.rgba[0] = v[0]; + m_stateVert.rgba[1] = v[1]; + m_stateVert.rgba[2] = v[2]; + m_stateVert.rgba[3] = v[3]; +} + +void imguiGraphFontTextureEnable() +{ + +} + +void imguiGraphFontTextureDisable() +{ + m_stateVert.u = -1.f; + m_stateVert.v = -1.f; +} + +void imguiGraphFontTextureInit(unsigned char* data) +{ + ID3D12GraphicsCommandList* commandList = m_desc.commandList; + + // Create the texture + { + UINT width = 512; + UINT height = 512; + + 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 = 0u; + heapProps.VisibleNodeMask = 0u; + + D3D12_RESOURCE_DESC texDesc = {}; + texDesc.MipLevels = 1u; + texDesc.Format = DXGI_FORMAT_R8_UNORM; + texDesc.Width = width; + texDesc.Height = height; + texDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + texDesc.DepthOrArraySize = 1u; + texDesc.SampleDesc.Count = 1u; + texDesc.SampleDesc.Quality = 0u; + texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + + if (m_desc.device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &texDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&m_texture) + )) + { + return; + } + + // get footprint information + D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint = {}; + UINT64 uploadHeapSize = 0u; + m_desc.device->GetCopyableFootprints(&texDesc, 0u, 1u, 0u, &footprint, nullptr, nullptr, &uploadHeapSize); + + heapProps.Type = D3D12_HEAP_TYPE_UPLOAD; + D3D12_RESOURCE_DESC bufferDesc = texDesc; + bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + bufferDesc.Alignment = 0u; + bufferDesc.Width = uploadHeapSize; + bufferDesc.Height = 1u; + bufferDesc.DepthOrArraySize = 1u; + bufferDesc.MipLevels = 1; + bufferDesc.Format = DXGI_FORMAT_UNKNOWN; + bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + bufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + + if (m_desc.device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &bufferDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&m_textureUploadHeap) + )) + { + return; + } + + // map upload heap, and convert rgb bitmap to rgba + UINT8* pdata; + D3D12_RANGE readRange = {}; + if (m_textureUploadHeap->Map(0, &readRange, (void**)&pdata)) + { + return; + } + else + { + UINT8* dst = pdata; + UINT elements = width*height; + UINT8* src = data; + for (UINT j = 0; j < height; j++) + { + for (UINT i = 0; i < width; i++) + { + UINT idx = j * (footprint.Footprint.RowPitch) + i; + + UINT8 a = src[j * width + i]; + dst[idx] = a; + } + } + + m_textureUploadHeap->Unmap(0, nullptr); + } + + // add copy from upload heap to default heap to command list + D3D12_TEXTURE_COPY_LOCATION dstCopy = {}; + D3D12_TEXTURE_COPY_LOCATION srcCopy = {}; + dstCopy.pResource = m_texture; + dstCopy.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dstCopy.SubresourceIndex = 0u; + srcCopy.pResource = m_textureUploadHeap; + srcCopy.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + srcCopy.PlacedFootprint = footprint; + commandList->CopyTextureRegion(&dstCopy, 0, 0, 0, &srcCopy, nullptr); + + D3D12_RESOURCE_BARRIER barrier[1] = {}; + auto textureBarrier = [&barrier](UINT idx, ID3D12Resource* texture) + { + barrier[idx].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier[idx].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier[idx].Transition.pResource = texture; + barrier[idx].Transition.Subresource = 0u; + barrier[idx].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier[idx].Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + }; + textureBarrier(0, m_texture); + commandList->ResourceBarrier(1, barrier); + + // create an SRV heap and descriptor for the texture + D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; + srvHeapDesc.NumDescriptors = 1; + srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + if (m_desc.device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_srvUavHeapCPU))) + { + return; + } + + D3D12_CPU_DESCRIPTOR_HANDLE srvUavHandle = m_srvUavHeapCPU->GetCPUDescriptorHandleForHeapStart(); + + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Format = texDesc.Format; + srvDesc.Texture2D.MipLevels = 1; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.ResourceMinLODClamp = 0.f; + + m_desc.device->CreateShaderResourceView(m_texture, &srvDesc, srvUavHandle); + } + +} + +void imguiGraphFontTextureRelease() +{ + COMRelease(m_texture); + COMRelease(m_textureUploadHeap); + COMRelease(m_srvUavHeapCPU); + COMRelease(m_srvUavHeapGPU); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D12/imguiGraphD3D12.h b/demo/DemoAppD3D12/imguiGraphD3D12.h new file mode 100644 index 0000000..7eeb538 --- /dev/null +++ b/demo/DemoAppD3D12/imguiGraphD3D12.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#ifndef IMGUI_GRAPH_D3D12_H +#define IMGUI_GRAPH_D3D12_H + +#include <stdint.h> + +#include "../DemoApp/imguiGraph.h" + +struct ImguiDescriptorReserveHandleD3D12 +{ + ID3D12DescriptorHeap* heap; + UINT descriptorSize; + D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle; + D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle; +}; + +struct ImguiDynamicDescriptorHeapD3D12 +{ + void* userdata; + ImguiDescriptorReserveHandleD3D12(*reserveDescriptors)(void* userdata, UINT numDescriptors, UINT64 lastFenceCompleted, UINT64 nextFenceValue); +}; + +struct ImguiGraphDesc +{ + ID3D12Device* device = nullptr; + ID3D12GraphicsCommandList* commandList = nullptr; + UINT64 lastFenceCompleted; + UINT64 nextFenceValue; + int winW; + int winH; + + uint32_t maxVertices = 64 * 4096u; + + ImguiDynamicDescriptorHeapD3D12 dynamicHeapCbvSrvUav = {}; + + ImguiGraphDesc() {} +}; + +#endif
\ No newline at end of file diff --git a/demo/DemoAppD3D12/imguiInteropD3D12.cpp b/demo/DemoAppD3D12/imguiInteropD3D12.cpp new file mode 100644 index 0000000..322e1b5 --- /dev/null +++ b/demo/DemoAppD3D12/imguiInteropD3D12.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + + //direct3d headers +#include <d3d12.h> + +// include the Direct3D Library file +#pragma comment (lib, "d3d12.lib") + +#include "../DemoApp/imguiInterop.h" + +#include "appD3D12Ctx.h" +#include "imguiGraphD3D12.h" + +ImguiDescriptorReserveHandleD3D12 imguiInteropReserveDescriptors(void* userdata, UINT numDescriptors, UINT64 lastFenceCompleted, UINT64 nextFenceValue) +{ + auto appctx = static_cast<AppGraphCtx*>(userdata); + auto srcHandle = appctx->m_dynamicHeapCbvSrvUav.reserveDescriptors(numDescriptors, lastFenceCompleted, nextFenceValue); + ImguiDescriptorReserveHandleD3D12 handle = {}; + handle.heap = srcHandle.heap; + handle.descriptorSize = srcHandle.descriptorSize; + handle.cpuHandle = srcHandle.cpuHandle; + handle.gpuHandle = srcHandle.gpuHandle; + return handle; +} + +void imguiInteropUpdateDesc(ImguiGraphDesc& desc, AppGraphCtx* appctx) +{ + desc.device = appctx->m_device; + desc.commandList = appctx->m_commandList; + desc.lastFenceCompleted = appctx->m_lastFenceComplete; + desc.nextFenceValue = appctx->m_thisFrameFenceID; + desc.winW = appctx->m_winW; + desc.winH = appctx->m_winH; + desc.dynamicHeapCbvSrvUav.userdata = appctx; + desc.dynamicHeapCbvSrvUav.reserveDescriptors = imguiInteropReserveDescriptors; +} + +bool imguiInteropGraphInit(imguiGraphInit_t func, const char* fontpath, AppGraphCtx* appctx) +{ + ImguiGraphDesc desc; + imguiInteropUpdateDesc(desc, appctx); + + return func(fontpath, &desc); +} + +void imguiInteropGraphUpdate(imguiGraphUpdate_t func, AppGraphCtx* appctx) +{ + ImguiGraphDesc desc; + imguiInteropUpdateDesc(desc, appctx); + + return func(&desc); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D12/imguiPS.hlsl.h b/demo/DemoAppD3D12/imguiPS.hlsl.h new file mode 100644 index 0000000..d6fb74c --- /dev/null +++ b/demo/DemoAppD3D12/imguiPS.hlsl.h @@ -0,0 +1,195 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// texSampler sampler NA NA s0 1 +// tex texture float 2d t0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v1.xy +dcl_input_ps linear v2.xyzw +dcl_output o0.xyzw +dcl_temps 1 +ge r0.x, v1.x, l(0.000000) +if_nz r0.x + sample_l_indexable(texture2d)(float,float,float,float) r0.x, v1.xyxx, t0.xyzw, s0, l(0.000000) + mul r0.x, r0.x, v2.w +else + mov r0.x, v2.w +endif +mov r0.yzw, v2.xxyz +mov o0.xyzw, r0.yzwx +ret +// Approximately 10 instruction slots used +#endif + +const BYTE g_imguiPS[] = +{ + 68, 88, 66, 67, 254, 30, + 194, 112, 35, 29, 114, 31, + 28, 188, 13, 85, 22, 84, + 219, 9, 1, 0, 0, 0, + 80, 3, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 240, 0, 0, 0, 100, 1, + 0, 0, 152, 1, 0, 0, + 180, 2, 0, 0, 82, 68, + 69, 70, 180, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 255, 255, 0, 1, 0, 0, + 139, 0, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 124, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 135, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 116, 101, + 120, 83, 97, 109, 112, 108, + 101, 114, 0, 116, 101, 120, + 0, 77, 105, 99, 114, 111, + 115, 111, 102, 116, 32, 40, + 82, 41, 32, 72, 76, 83, + 76, 32, 83, 104, 97, 100, + 101, 114, 32, 67, 111, 109, + 112, 105, 108, 101, 114, 32, + 49, 48, 46, 49, 0, 171, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 79, 83, 73, 84, + 73, 79, 78, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 65, 82, + 71, 69, 84, 0, 171, 171, + 83, 72, 69, 88, 20, 1, + 0, 0, 80, 0, 0, 0, + 69, 0, 0, 0, 106, 8, + 0, 1, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 98, 16, 0, 3, 242, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 29, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 16, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 72, 0, 0, 141, 194, 0, + 0, 128, 67, 85, 21, 0, + 18, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 58, 16, 16, 0, 2, 0, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 58, 16, 16, 0, 2, 0, + 0, 0, 21, 0, 0, 1, + 54, 0, 0, 5, 226, 0, + 16, 0, 0, 0, 0, 0, + 6, 25, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 242, 32, 16, 0, 0, 0, + 0, 0, 150, 3, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/demo/DemoAppD3D12/imguiVS.hlsl.h b/demo/DemoAppD3D12/imguiVS.hlsl.h new file mode 100644 index 0000000..6c7ed54 --- /dev/null +++ b/demo/DemoAppD3D12/imguiVS.hlsl.h @@ -0,0 +1,246 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer params +// { +// +// float4x4 transform; // Offset: 0 Size: 64 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// params cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xy 0 NONE float xy +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// SV_InstanceID 0 x 3 INSTID uint +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[4], immediateIndexed +dcl_input v0.xy +dcl_input v1.xy +dcl_input v2.xyzw +dcl_output_siv o0.xyzw, position +dcl_output o1.xy +dcl_output o2.xyzw +dcl_temps 1 +mov r0.xy, v0.xyxx +mov r0.z, l(1.000000) +dp3 o0.x, r0.xyzx, cb0[0].xywx +dp3 o0.y, r0.xyzx, cb0[1].xywx +dp3 o0.z, r0.xyzx, cb0[2].xywx +dp3 o0.w, r0.xyzx, cb0[3].xywx +mov o1.xy, v1.xyxx +mov o2.xyzw, v2.xyzw +ret +// Approximately 9 instruction slots used +#endif + +const BYTE g_imguiVS[] = +{ + 68, 88, 66, 67, 6, 20, + 203, 172, 109, 190, 55, 177, + 9, 228, 94, 38, 104, 254, + 183, 14, 1, 0, 0, 0, + 52, 4, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 64, 1, 0, 0, 216, 1, + 0, 0, 76, 2, 0, 0, + 152, 3, 0, 0, 82, 68, + 69, 70, 4, 1, 0, 0, + 1, 0, 0, 0, 100, 0, + 0, 0, 1, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 254, 255, 0, 1, 0, 0, + 220, 0, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 112, 97, 114, 97, + 109, 115, 0, 171, 92, 0, + 0, 0, 1, 0, 0, 0, + 124, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 0, + 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 2, 0, + 0, 0, 184, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 116, 114, 97, 110, + 115, 102, 111, 114, 109, 0, + 102, 108, 111, 97, 116, 52, + 120, 52, 0, 171, 3, 0, + 3, 0, 4, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 174, 0, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 144, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 104, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, + 113, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 3, 0, 0, + 122, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 15, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 80, 79, 83, 73, 84, 73, + 79, 78, 0, 84, 69, 88, + 67, 79, 79, 82, 68, 0, + 67, 79, 76, 79, 82, 0, + 83, 86, 95, 73, 110, 115, + 116, 97, 110, 99, 101, 73, + 68, 0, 171, 171, 79, 83, + 71, 78, 108, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 80, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 92, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 12, + 0, 0, 101, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 67, + 79, 76, 79, 82, 0, 171, + 83, 72, 69, 88, 68, 1, + 0, 0, 80, 0, 1, 0, + 81, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 2, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 2, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 54, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 16, 0, + 0, 8, 18, 32, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 131, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 8, 34, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 131, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 16, 0, 0, 8, + 66, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 131, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 16, 0, + 0, 8, 130, 32, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 131, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 5, 50, 32, + 16, 0, 1, 0, 0, 0, + 70, 16, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 242, 32, 16, 0, 2, 0, + 0, 0, 70, 30, 16, 0, + 2, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 9, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/demo/DemoAppD3D12/meshD3D12.cpp b/demo/DemoAppD3D12/meshD3D12.cpp new file mode 100644 index 0000000..3b04436 --- /dev/null +++ b/demo/DemoAppD3D12/meshD3D12.cpp @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +//direct3d headers +#include <d3d12.h> + +// include the Direct3D Library file +#pragma comment (lib, "d3d12.lib") + +#include <math.h> + +#include <SDL.h> + +#include "meshD3D12.h" + +#include "meshVS.hlsl.h" +#include "meshPS.hlsl.h" + +namespace +{ + template <class T> + void inline COMRelease(T& t) + { + if (t) t->Release(); + t = nullptr; + } +} + +struct MeshConstantHeap +{ + MeshConstantHeap* m_next = nullptr; + MeshContext* m_meshContext = nullptr; + + ID3D12Resource* m_constantBuffer = nullptr; + UINT8* m_constantBufferData = nullptr; + + int m_allocIdx = 0; + int m_size; + + MeshConstantHeap(MeshContext* meshContext, int size); + ~MeshConstantHeap() + { + COMRelease(m_constantBuffer); + delete m_next; + } + + void reset() + { + m_allocIdx = 0; + if (m_next) + { + m_next->reset(); + } + } + + UINT8* allocate(int size) + { + UINT8* ret = nullptr; + size = 256 * ((size + 255) / 256); + if (m_allocIdx + size <= m_size) + { + ret = m_constantBufferData + m_allocIdx; + m_allocIdx += size; + } + if (ret == nullptr) + { + if (m_next) + { + return m_next->allocate(size); + } + else + { + m_next = new MeshConstantHeap(m_meshContext, m_size); + return m_next->allocate(size); + } + } + return ret; + } + + D3D12_GPU_VIRTUAL_ADDRESS getVirtualAddress(UINT8* cpuAddress) + { + size_t offset = cpuAddress - m_constantBufferData; + if (offset < m_size) + { + return m_constantBuffer->GetGPUVirtualAddress() + offset; + } + else + { + if (m_next) + { + return m_next->getVirtualAddress(cpuAddress); + } + else + { + return 0u; + } + } + } +}; + +struct MeshContext +{ + ID3D12Device* m_device = nullptr; + ID3D12GraphicsCommandList* m_commandList = nullptr; + + ID3D12RootSignature* m_rootSignature = nullptr; + ID3D12PipelineState* m_pipelineStateLH = nullptr; + ID3D12PipelineState* m_pipelineStateRH = nullptr; + + MeshConstantHeap* m_constantHeap = nullptr; + + MeshContext() {} + ~MeshContext() + { + COMRelease(m_rootSignature); + COMRelease(m_pipelineStateLH); + COMRelease(m_pipelineStateRH); + if (m_constantHeap) + { + delete m_constantHeap; + m_constantHeap = nullptr; + } + } +}; + +struct MeshIndexBuffer +{ + ID3D12Resource* m_buffer = nullptr; + MeshUint m_numElements = 0u; + D3D12_INDEX_BUFFER_VIEW m_view = {}; + + ID3D12Resource* m_upload = nullptr; + + MeshIndexBuffer() {} + ~MeshIndexBuffer() + { + COMRelease(m_buffer); + COMRelease(m_upload); + } +}; + +struct MeshVertexBuffer +{ + ID3D12Resource* m_buffer = nullptr; + MeshUint m_numElements = 0u; + D3D12_VERTEX_BUFFER_VIEW m_view = {}; + + ID3D12Resource* m_upload = nullptr; + + MeshVertexBuffer() {} + ~MeshVertexBuffer() + { + COMRelease(m_buffer); + COMRelease(m_upload); + } +}; + +MeshConstantHeap::MeshConstantHeap(MeshContext* meshContext, int size) : m_meshContext(meshContext) +{ + // create a constant buffer + { + HRESULT hr = S_OK; + + D3D12_HEAP_PROPERTIES heapProps = {}; + heapProps.Type = D3D12_HEAP_TYPE_UPLOAD; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 0u; + heapProps.VisibleNodeMask = 0u; + + m_size = 256 * ((size + 255) / 256); + + D3D12_RESOURCE_DESC desc = {}; + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Alignment = 0u; + desc.Width = m_size; + desc.Height = 1u; + desc.DepthOrArraySize = 1u; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1u; + desc.SampleDesc.Quality = 0u; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + + if (hr = meshContext->m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, IID_PPV_ARGS(&m_constantBuffer))) + { + } + + UINT8* pdata; + D3D12_RANGE readRange = {}; + if (hr = m_constantBuffer->Map(0, &readRange, (void**)&pdata)) + { + } + else + { + m_constantBufferData = pdata; + //m_constantBuffer->Unmap(0, nullptr); // leave mapped + } + } +} + +MeshContext* MeshContextCreate(const MeshContextDesc* desc) +{ + MeshContext* context = new MeshContext; + + context->m_device = desc->device; + context->m_commandList = desc->commandList; + + // create the root signature + { + D3D12_ROOT_PARAMETER params[1]; + params[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + params[0].Descriptor.ShaderRegister = 0u; + params[0].Descriptor.RegisterSpace = 0u; + params[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + D3D12_ROOT_SIGNATURE_DESC desc; + desc.NumParameters = 1; + desc.pParameters = params; + desc.NumStaticSamplers = 0u; + desc.pStaticSamplers = nullptr; + desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + + ID3DBlob* signature = nullptr; + ID3DBlob* error = nullptr; + HRESULT hr = S_OK; + if (hr = D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)) + { + delete context; + return nullptr; + } + if (hr = context->m_device->CreateRootSignature(0u, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&context->m_rootSignature))) + { + delete context; + return nullptr; + } + COMRelease(signature); + COMRelease(error); + } + + // create the pipeline state object + { + D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } + }; + + const bool wireFrame = false; + + D3D12_RASTERIZER_DESC rasterDesc; + if (wireFrame) + { + rasterDesc.FillMode = D3D12_FILL_MODE_WIREFRAME; + rasterDesc.CullMode = D3D12_CULL_MODE_NONE; + } + else + { + rasterDesc.FillMode = D3D12_FILL_MODE_SOLID; + rasterDesc.CullMode = D3D12_CULL_MODE_BACK; + } + rasterDesc.FrontCounterClockwise = FALSE; + rasterDesc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + rasterDesc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + rasterDesc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + rasterDesc.ForcedSampleCount = 0; + rasterDesc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + + D3D12_BLEND_DESC blendDesc; + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = FALSE; + { + const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = + { + FALSE,FALSE, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL, + }; + for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) + blendDesc.RenderTarget[i] = defaultRenderTargetBlendDesc; + } + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout.NumElements = 2; + psoDesc.InputLayout.pInputElementDescs = inputElementDescs; + psoDesc.pRootSignature = context->m_rootSignature; + psoDesc.VS.pShaderBytecode = g_meshVS; + psoDesc.VS.BytecodeLength = sizeof(g_meshVS); + psoDesc.PS.pShaderBytecode = g_meshPS; + psoDesc.PS.BytecodeLength = sizeof(g_meshPS); + psoDesc.RasterizerState = rasterDesc; + psoDesc.BlendState = blendDesc; + psoDesc.DepthStencilState.DepthEnable = TRUE; + psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; + psoDesc.DepthStencilState.StencilEnable = FALSE; + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; + psoDesc.SampleDesc.Count = 1; + HRESULT hr = S_OK; + + if (hr = context->m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&context->m_pipelineStateLH))) + { + delete context; + return nullptr; + } + + psoDesc.RasterizerState.FrontCounterClockwise = TRUE; + + if (hr = context->m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&context->m_pipelineStateRH))) + { + delete context; + return nullptr; + } + } + + // create constant heap + { + context->m_constantHeap = new MeshConstantHeap(context, 4096u); + } + + return context; +} + +void MeshContextUpdate(MeshContext* context, const MeshContextDesc* desc) +{ + context->m_device = desc->device; + context->m_commandList = desc->commandList; + + context->m_constantHeap->reset(); +} + +void MeshContextRelease(MeshContext* context) +{ + if (context == nullptr) return; + + delete context; +} + +MeshIndexBuffer* MeshIndexBufferCreate(MeshContext* context, MeshUint* indices, MeshUint numIndices) +{ + MeshIndexBuffer* buffer = new MeshIndexBuffer; + + buffer->m_numElements = numIndices; + // create an index buffer + { + HRESULT hr = S_OK; + + UINT bufferSize = (UINT)(numIndices) * sizeof(UINT); + + D3D12_HEAP_PROPERTIES heapProps = {}; + heapProps.Type = D3D12_HEAP_TYPE_UPLOAD; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 0u; + heapProps.VisibleNodeMask = 0u; + + D3D12_RESOURCE_DESC desc = {}; + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Alignment = 0u; + desc.Width = bufferSize; + desc.Height = 1u; + desc.DepthOrArraySize = 1u; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1u; + desc.SampleDesc.Quality = 0u; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + + if (hr = context->m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, IID_PPV_ARGS(&buffer->m_upload))) + { + delete buffer; + return nullptr; + } + + UINT8* pdata; + D3D12_RANGE readRange = {}; + if (hr = buffer->m_upload->Map(0, &readRange, (void**)&pdata)) + { + delete buffer; + return nullptr; + } + else + { + memcpy(pdata, indices, numIndices * sizeof(UINT)); + + buffer->m_upload->Unmap(0, nullptr); + } + + // create a GPU memory buffer + heapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + if (hr = context->m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, IID_PPV_ARGS(&buffer->m_buffer))) + { + delete buffer; + return nullptr; + } + + // copy from upload to new buffer + context->m_commandList->CopyBufferRegion(buffer->m_buffer, 0, buffer->m_upload, 0, bufferSize); + + D3D12_RESOURCE_BARRIER barrier[1]; + barrier[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier[0].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier[0].Transition.pResource = buffer->m_buffer; + barrier[0].Transition.Subresource = 0u; + barrier[0].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier[0].Transition.StateAfter = D3D12_RESOURCE_STATE_INDEX_BUFFER; + context->m_commandList->ResourceBarrier(1, barrier); + + bufferSize = (UINT)(numIndices) * sizeof(UINT); + buffer->m_view.BufferLocation = buffer->m_buffer->GetGPUVirtualAddress(); + buffer->m_view.SizeInBytes = bufferSize; + buffer->m_view.Format = DXGI_FORMAT_R32_UINT; + } + + return buffer; +} + +void MeshIndexBufferRelease(MeshIndexBuffer* buffer) +{ + if (buffer == nullptr) return; + + delete buffer; +} + +MeshVertexBuffer* MeshVertexBufferCreate(MeshContext* context, MeshVertex* vertices, MeshUint numVertices) +{ + MeshVertexBuffer* buffer = new MeshVertexBuffer; + + buffer->m_numElements = numVertices; + // create a vertex buffer + { + HRESULT hr = S_OK; + + UINT bufferSize = (UINT)(numVertices * sizeof(MeshVertex)); + + D3D12_HEAP_PROPERTIES heapProps = {}; + heapProps.Type = D3D12_HEAP_TYPE_UPLOAD; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 0u; + heapProps.VisibleNodeMask = 0u; + + D3D12_RESOURCE_DESC desc = {}; + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Alignment = 0u; + desc.Width = bufferSize; + desc.Height = 1u; + desc.DepthOrArraySize = 1u; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1u; + desc.SampleDesc.Quality = 0u; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + + if (hr = context->m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, IID_PPV_ARGS(&buffer->m_upload))) + { + delete buffer; + return nullptr; + } + + UINT8* pdata; + D3D12_RANGE readRange = {}; + if (hr = buffer->m_upload->Map(0, &readRange, (void**)&pdata)) + { + delete buffer; + return nullptr; + } + else + { + memcpy(pdata, vertices, numVertices * sizeof(MeshVertex)); + + buffer->m_upload->Unmap(0, nullptr); + } + + // create a GPU memory buffer + heapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + if (hr = context->m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, IID_PPV_ARGS(&buffer->m_buffer))) + { + delete buffer; + return nullptr; + } + + // copy from upload to new buffer + context->m_commandList->CopyBufferRegion(buffer->m_buffer, 0, buffer->m_upload, 0, bufferSize); + + D3D12_RESOURCE_BARRIER barrier[1]; + barrier[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier[0].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier[0].Transition.pResource = buffer->m_buffer; + barrier[0].Transition.Subresource = 0u; + barrier[0].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier[0].Transition.StateAfter = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; + context->m_commandList->ResourceBarrier(1, barrier); + + bufferSize = (UINT)(numVertices * sizeof(MeshVertex)); + buffer->m_view.BufferLocation = buffer->m_buffer->GetGPUVirtualAddress(); + buffer->m_view.StrideInBytes = 6 * sizeof(float); + buffer->m_view.SizeInBytes = bufferSize; + } + + return buffer; +} + +void MeshVertexBufferRelease(MeshVertexBuffer* buffer) +{ + if (buffer == nullptr) return; + + delete buffer; +} + +void MeshContextDraw(MeshContext* context, const MeshContextDrawParams* params) +{ + using namespace DirectX; + + XMMATRIX matrix = XMMatrixTranspose(XMMatrixMultiply(XMMatrixMultiply( + params->params->model, + params->params->view), + params->params->projection + )); + + UINT8* constantBufferData = context->m_constantHeap->allocate(256); + + if (constantBufferData == nullptr) + { + return; + } + + XMStoreFloat4x4((XMFLOAT4X4*)(constantBufferData), matrix); + + ID3D12GraphicsCommandList* commandList = context->m_commandList; + + commandList->SetGraphicsRootSignature(context->m_rootSignature); + + float depthSign = DirectX::XMVectorGetW(params->params->projection.r[2]); + if (depthSign < 0.f) + { + commandList->SetPipelineState(context->m_pipelineStateRH); + } + else + { + commandList->SetPipelineState(context->m_pipelineStateLH); + } + + D3D12_GPU_VIRTUAL_ADDRESS cbvHandle = context->m_constantHeap->getVirtualAddress(constantBufferData); + commandList->SetGraphicsRootConstantBufferView(0, cbvHandle); + + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + commandList->IASetVertexBuffers(0, 1, ¶ms->vertexBuffer->m_view); + commandList->IASetIndexBuffer(¶ms->indexBuffer->m_view); + + commandList->DrawIndexedInstanced((UINT)params->indexBuffer->m_numElements, 1, 0, 0, 0); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D12/meshD3D12.h b/demo/DemoAppD3D12/meshD3D12.h new file mode 100644 index 0000000..4bd0fab --- /dev/null +++ b/demo/DemoAppD3D12/meshD3D12.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +#include "../DemoApp/mesh.h" + +struct MeshContextDesc +{ + ID3D12Device* device; + ID3D12GraphicsCommandList* commandList; +};
\ No newline at end of file diff --git a/demo/DemoAppD3D12/meshInteropD3D12.cpp b/demo/DemoAppD3D12/meshInteropD3D12.cpp new file mode 100644 index 0000000..19c034d --- /dev/null +++ b/demo/DemoAppD3D12/meshInteropD3D12.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +//direct3d headers +#include <d3d12.h> + +// include the Direct3D Library file +#pragma comment (lib, "d3d12.lib") + +#include "../DemoApp/meshInterop.h" + +#include "appD3D12Ctx.h" +#include "meshD3D12.h" + +MeshContext* MeshInteropContextCreate(AppGraphCtx* appctx) +{ + MeshContextDesc desc = {}; + desc.device = appctx->m_device; + desc.commandList = appctx->m_commandList; + + return MeshContextCreate(&desc); +} + +void MeshInteropContextUpdate(MeshContext* context, AppGraphCtx* appctx) +{ + MeshContextDesc desc = {}; + desc.device = appctx->m_device; + desc.commandList = appctx->m_commandList; + + return MeshContextUpdate(context, &desc); +}
\ No newline at end of file diff --git a/demo/DemoAppD3D12/meshPS.hlsl.h b/demo/DemoAppD3D12/meshPS.hlsl.h new file mode 100644 index 0000000..fcef532 --- /dev/null +++ b/demo/DemoAppD3D12/meshPS.hlsl.h @@ -0,0 +1,205 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float +// NORMAL 0 xyz 1 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_input_ps linear v1.xyz +dcl_output o0.xyzw +dcl_temps 1 +dp3 r0.x, v1.xyzx, l(0.570000, 0.570000, 0.570000, 0.000000) +max r0.x, r0.x, l(0.000000) +mad r0.x, r0.x, l(0.400000), l(0.100000) +dp3 r0.y, v1.xyzx, l(-0.570000, 0.570000, 0.570000, 0.000000) +max r0.y, r0.y, l(0.000000) +mad r0.x, r0.y, l(0.400000), r0.x +dp3 r0.y, v1.xyzx, l(0.570000, 0.570000, -0.570000, 0.000000) +max r0.y, r0.y, l(0.000000) +mad r0.x, r0.y, l(0.400000), r0.x +dp3 r0.y, v1.xzyx, l(-0.570000, -0.570000, 0.570000, 0.000000) +max r0.y, r0.y, l(0.000000) +mad o0.xyz, r0.yyyy, l(0.400000, 0.400000, 0.400000, 0.000000), r0.xxxx +mov o0.w, l(1.000000) +ret +// Approximately 14 instruction slots used +#endif + +const BYTE g_meshPS[] = +{ + 68, 88, 66, 67, 253, 169, + 122, 175, 25, 228, 25, 139, + 94, 18, 195, 68, 91, 159, + 92, 156, 1, 0, 0, 0, + 188, 3, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 160, 0, 0, 0, 244, 0, + 0, 0, 40, 1, 0, 0, + 32, 3, 0, 0, 82, 68, + 69, 70, 100, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 255, 255, 0, 1, 0, 0, + 60, 0, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 76, 0, 0, 0, + 2, 0, 0, 0, 8, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 68, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 7, 7, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 78, 79, 82, 77, + 65, 76, 0, 171, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 65, 82, 71, 69, 84, 0, + 171, 171, 83, 72, 69, 88, + 240, 1, 0, 0, 80, 0, + 0, 0, 124, 0, 0, 0, + 106, 8, 0, 1, 98, 16, + 0, 3, 114, 16, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 16, 0, 0, 10, 18, 0, + 16, 0, 0, 0, 0, 0, + 70, 18, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 133, 235, 17, 63, 133, 235, + 17, 63, 133, 235, 17, 63, + 0, 0, 0, 0, 52, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 205, 204, 204, 62, + 1, 64, 0, 0, 205, 204, + 204, 61, 16, 0, 0, 10, + 34, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 133, 235, 17, 191, + 133, 235, 17, 63, 133, 235, + 17, 63, 0, 0, 0, 0, + 52, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 10, 0, 16, 0, + 0, 0, 0, 0, 16, 0, + 0, 10, 34, 0, 16, 0, + 0, 0, 0, 0, 70, 18, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 133, 235, + 17, 63, 133, 235, 17, 63, + 133, 235, 17, 191, 0, 0, + 0, 0, 52, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 205, 204, 204, 62, 10, 0, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 10, 34, 0, + 16, 0, 0, 0, 0, 0, + 134, 17, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 133, 235, 17, 191, 133, 235, + 17, 191, 133, 235, 17, 63, + 0, 0, 0, 0, 52, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 12, + 114, 32, 16, 0, 0, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 205, 204, 204, 62, + 205, 204, 204, 62, 205, 204, + 204, 62, 0, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 14, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/demo/DemoAppD3D12/meshVS.hlsl.h b/demo/DemoAppD3D12/meshVS.hlsl.h new file mode 100644 index 0000000..e2c1466 --- /dev/null +++ b/demo/DemoAppD3D12/meshVS.hlsl.h @@ -0,0 +1,223 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer params +// { +// +// float4x4 projection; // Offset: 0 Size: 64 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// params cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xyz 0 NONE float xyz +// NORMAL 0 xyz 1 NONE float xyz +// SV_InstanceID 0 x 2 INSTID uint +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float xyzw +// NORMAL 0 xyz 1 NONE float xyz +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[4], immediateIndexed +dcl_input v0.xyz +dcl_input v1.xyz +dcl_output_siv o0.xyzw, position +dcl_output o1.xyz +dcl_temps 1 +mov r0.xyz, v0.xyzx +mov r0.w, l(1.000000) +dp4 o0.x, r0.xyzw, cb0[0].xyzw +dp4 o0.y, r0.xyzw, cb0[1].xyzw +dp4 o0.z, r0.xyzw, cb0[2].xyzw +dp4 o0.w, r0.xyzw, cb0[3].xyzw +mov o1.xyz, v1.xyzx +ret +// Approximately 8 instruction slots used +#endif + +const BYTE g_meshVS[] = +{ + 68, 88, 66, 67, 146, 57, + 84, 204, 22, 172, 14, 230, + 119, 17, 66, 227, 109, 150, + 21, 41, 1, 0, 0, 0, + 200, 3, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 64, 1, 0, 0, 184, 1, + 0, 0, 12, 2, 0, 0, + 44, 3, 0, 0, 82, 68, + 69, 70, 4, 1, 0, 0, + 1, 0, 0, 0, 100, 0, + 0, 0, 1, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 254, 255, 0, 1, 0, 0, + 220, 0, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 112, 97, 114, 97, + 109, 115, 0, 171, 92, 0, + 0, 0, 1, 0, 0, 0, + 124, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 0, + 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 2, 0, + 0, 0, 184, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 112, 114, 111, 106, + 101, 99, 116, 105, 111, 110, + 0, 102, 108, 111, 97, 116, + 52, 120, 52, 0, 3, 0, + 3, 0, 4, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 175, 0, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 112, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 80, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 7, 7, 0, 0, + 89, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 7, 7, 0, 0, + 96, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 1, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 80, 79, 83, 73, 84, 73, + 79, 78, 0, 78, 79, 82, + 77, 65, 76, 0, 83, 86, + 95, 73, 110, 115, 116, 97, + 110, 99, 101, 73, 68, 0, + 171, 171, 79, 83, 71, 78, + 76, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 68, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 7, 8, 0, 0, + 83, 86, 95, 80, 79, 83, + 73, 84, 73, 79, 78, 0, + 78, 79, 82, 77, 65, 76, + 0, 171, 83, 72, 69, 88, + 24, 1, 0, 0, 80, 0, + 1, 0, 70, 0, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 0, 0, + 0, 0, 95, 0, 0, 3, + 114, 16, 16, 0, 1, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 114, 32, + 16, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 54, 0, 0, 5, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 18, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 17, 0, 0, 8, 18, 32, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 8, + 34, 32, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 17, 0, + 0, 8, 66, 32, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 17, 0, 0, 8, 130, 32, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 54, 0, 0, 5, + 114, 32, 16, 0, 1, 0, + 0, 0, 70, 18, 16, 0, + 1, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/demo/Shaders/customEmitAllocCS.hlsl b/demo/Shaders/customEmitAllocCS.hlsl new file mode 100644 index 0000000..930ef4f --- /dev/null +++ b/demo/Shaders/customEmitAllocCS.hlsl @@ -0,0 +1,34 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#define THREAD_DIM_X 8 +#define THREAD_DIM_Y 8 +#define THREAD_DIM_Z 8 + +typedef uint4 NvFlowUint4; + +cbuffer params : register(b0) +{ + NvFlowUint4 minMaskIdx; + NvFlowUint4 maxMaskIdx; +}; + +RWTexture3D<uint> maskUAV : register(u0); + +[numthreads(THREAD_DIM_X, THREAD_DIM_Y, THREAD_DIM_Z)] +void customEmitAllocCS(uint3 tidx : SV_DispatchThreadID) +{ + int3 maskIdx = tidx + minMaskIdx.xyz; + + if (all(maskIdx >= int3(minMaskIdx.xyz)) && all(maskIdx < int3(maxMaskIdx.xyz))) + { + maskUAV[maskIdx] = 1u; + } +}
\ No newline at end of file diff --git a/demo/Shaders/customEmitEmit2CS.hlsl b/demo/Shaders/customEmitEmit2CS.hlsl new file mode 100644 index 0000000..4616b87 --- /dev/null +++ b/demo/Shaders/customEmitEmit2CS.hlsl @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#define THREAD_DIM_X 8 +#define THREAD_DIM_Y 8 +#define THREAD_DIM_Z 8 + +typedef uint4 NvFlowUint4; +typedef float4 NvFlowFloat4; + +/// Begin Samplers supplied by ComputeContext +SamplerState borderSampler : register(s0); +SamplerState borderPointSampler : register(s1); +SamplerState wrapSampler : register(s2); +SamplerState wrapPointSampler : register(s3); +SamplerState clampSampler : register(s4); +SamplerState clampPointSampler : register(s5); +/// End Samplers supplied by ComputeContext + +#include "../DemoApp/flowShaderParams.h" + +cbuffer params : register(b0) +{ + NvFlowShaderPointParams customEmitParams; + + NvFlowUint4 minVidx; + NvFlowUint4 maxVidx; + NvFlowFloat4 targetValue; + NvFlowFloat4 blendRate; +}; + +Buffer<uint> blockList : register(t0); +Texture3D<uint> blockTable : register(t1); +Texture3D<float4> dataSRV : register(t2); +RWTexture3D<float4> dataUAV : register(u0); + +NV_FLOW_DISPATCH_ID_TO_VIRTUAL(blockList, customEmitParams); + +NV_FLOW_VIRTUAL_TO_REAL(VirtualToReal, blockTable, customEmitParams); + +[numthreads(THREAD_DIM_X, THREAD_DIM_Y, THREAD_DIM_Z)] +void customEmitEmit2CS(uint3 tidx : SV_DispatchThreadID) +{ + int3 vidx = DispatchIDToVirtual(tidx); + + //int3 vidx = tidx.xyz + minVidx.xyz; + + int3 ridx = VirtualToReal(vidx); + + float4 value = dataSRV[ridx]; + + if (all(vidx >= int3(minVidx.xyz)) && all(vidx < int3(maxVidx.xyz))) + { + value = (1.f.xxxx - blendRate) * value + blendRate * targetValue; + value = (1.f.xxxx - blendRate) * value + blendRate * targetValue; + } + + dataUAV[ridx] = value; +}
\ No newline at end of file diff --git a/demo/Shaders/customEmitEmitCS.hlsl b/demo/Shaders/customEmitEmitCS.hlsl new file mode 100644 index 0000000..c9adbb9 --- /dev/null +++ b/demo/Shaders/customEmitEmitCS.hlsl @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#define THREAD_DIM_X 8 +#define THREAD_DIM_Y 8 +#define THREAD_DIM_Z 8 + +typedef uint4 NvFlowUint4; +typedef float4 NvFlowFloat4; + +/// Begin Samplers supplied by ComputeContext +SamplerState borderSampler : register(s0); +SamplerState borderPointSampler : register(s1); +SamplerState wrapSampler : register(s2); +SamplerState wrapPointSampler : register(s3); +SamplerState clampSampler : register(s4); +SamplerState clampPointSampler : register(s5); +/// End Samplers supplied by ComputeContext + +#include "../DemoApp/flowShaderParams.h" + +cbuffer params : register(b0) +{ + NvFlowShaderPointParams customEmitParams; + + NvFlowUint4 minVidx; + NvFlowUint4 maxVidx; + NvFlowFloat4 targetValue; + NvFlowFloat4 blendRate; +}; + +Buffer<uint> blockList : register(t0); +Texture3D<uint> blockTable : register(t1); +Texture3D<float4> dataSRV : register(t2); +RWTexture3D<float4> dataUAV : register(u0); + +NV_FLOW_DISPATCH_ID_TO_VIRTUAL(blockList, customEmitParams); + +NV_FLOW_VIRTUAL_TO_REAL(VirtualToReal, blockTable, customEmitParams); + +[numthreads(THREAD_DIM_X, THREAD_DIM_Y, THREAD_DIM_Z)] +void customEmitEmitCS(uint3 tidx : SV_DispatchThreadID) +{ + //int3 vidx = DispatchIDToVirtual(tidx); + + int3 vidx = tidx.xyz + minVidx.xyz; + + if (all(vidx >= int3(minVidx.xyz)) && all(vidx < int3(maxVidx.xyz))) + { + int3 ridx = VirtualToReal(vidx); + + float4 value = dataSRV[ridx]; + + value = (1.f.xxxx - blendRate) * value + blendRate * targetValue; + + dataUAV[ridx] = value; + } +}
\ No newline at end of file diff --git a/demo/Shaders/customLightingCS.hlsl b/demo/Shaders/customLightingCS.hlsl new file mode 100644 index 0000000..d9f95ee --- /dev/null +++ b/demo/Shaders/customLightingCS.hlsl @@ -0,0 +1,87 @@ +/* +* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#define THREAD_DIM_X 8 +#define THREAD_DIM_Y 8 +#define THREAD_DIM_Z 8 + +/// Begin Samplers supplied by ComputeContext +SamplerState borderSampler : register(s0); +SamplerState borderPointSampler : register(s1); +SamplerState wrapSampler : register(s2); +SamplerState wrapPointSampler : register(s3); +SamplerState clampSampler : register(s4); +SamplerState clampPointSampler : register(s5); +/// End Samplers supplied by ComputeContext + +typedef uint4 NvFlowUint4; +typedef float4 NvFlowFloat4; + +#include "../DemoApp/flowShaderParams.h" + +struct Light +{ + float4 location; + float4 intensity; + float4 bias; + float4 falloff; +}; + +cbuffer params : register(b0) +{ + NvFlowShaderLinearParams exportParams; + NvFlowShaderLinearParams importParams; + + Light light[3]; +}; + +Buffer<uint> exportBlockList : register(t0); +Texture3D<uint> exportBlockTable : register(t1); +Texture3D<float4> exportData : register(t2); + +Buffer<uint> importBlockList : register(t3); +Texture3D<uint> importBlockTable : register(t4); +RWTexture3D<float4> importDataRW : register(u0); + +NV_FLOW_DISPATCH_ID_TO_VIRTUAL(importBlockList, importParams); + +NV_FLOW_VIRTUAL_TO_REAL_LINEAR(VirtualToRealExport, exportBlockTable, exportParams); +NV_FLOW_VIRTUAL_TO_REAL(VirtualToRealImport, importBlockTable, importParams); + +float4 applyLight(uniform Light light, float3 vidxNorm) +{ + float3 offset = vidxNorm.xyz - light.location.xyz; + float dist2 = dot(offset.xyz, offset.xyz); + return light.intensity * light.bias / (light.bias + light.falloff * dist2); +} + +[numthreads(THREAD_DIM_X, THREAD_DIM_Y, THREAD_DIM_Z)] +void customLightingCS(uint3 tidx : SV_DispatchThreadID) +{ + int3 vidx = DispatchIDToVirtual(tidx); + float3 vidxf = float3(vidx)+0.5f.xxx; + + float3 vidxNorm = 2.f * vidxf * exportParams.vdimInv.xyz - 1.f; + + float3 ridxExport = VirtualToRealExport(vidxf); + float4 value = exportData.SampleLevel(borderSampler,exportParams.dimInv.xyz * ridxExport,0); + float temp = value.x; + + float4 color = float4(0.1f * temp, 0.1f * temp, 0.1f * temp, 0.25f); + + color += applyLight(light[0], vidxNorm); + color += applyLight(light[1], vidxNorm); + color += applyLight(light[2], vidxNorm); + + color.w *= 0.25f * max(temp - 0.25f, 0.f); + + int3 ridxImport = VirtualToRealImport(vidx); + importDataRW[ridxImport] = color; +}
\ No newline at end of file diff --git a/demo/Shaders/imguiPS.hlsl b/demo/Shaders/imguiPS.hlsl new file mode 100644 index 0000000..f51a21b --- /dev/null +++ b/demo/Shaders/imguiPS.hlsl @@ -0,0 +1,22 @@ + +struct Input +{ + float4 position : SV_POSITION; + float2 texCoord : TEXCOORD; + float4 color : COLOR; +}; + +Texture2D<float> tex : register(t0); +SamplerState texSampler : register(s0); + +float4 imguiPS(Input input) : SV_TARGET +{ + float4 color = input.color; + + if (input.texCoord.x >= 0.f) + { + color.a *= tex.SampleLevel(texSampler, input.texCoord, 0.f); + } + + return color; +}
\ No newline at end of file diff --git a/demo/Shaders/imguiVS.hlsl b/demo/Shaders/imguiVS.hlsl new file mode 100644 index 0000000..6116ee1 --- /dev/null +++ b/demo/Shaders/imguiVS.hlsl @@ -0,0 +1,31 @@ + +cbuffer params : register(b0) +{ + float4x4 transform; +}; + +struct Input +{ + float2 position : POSITION; + float2 texCoord : TEXCOORD; + float4 color : COLOR; +}; + +struct Output +{ + float4 position : SV_POSITION; + float2 texCoord : TEXCOORD; + float4 color : COLOR; +}; + +Output imguiVS(Input input, uint instance : SV_InstanceID) +{ + Output output; + + output.position = mul(float4(input.position, 0.f, 1.f), transform); + + output.texCoord = input.texCoord.xy; // float2(input.texCoord.x, 1.f - input.texCoord.y); + output.color = input.color; + + return output; +}
\ No newline at end of file diff --git a/demo/Shaders/meshPS.hlsl b/demo/Shaders/meshPS.hlsl new file mode 100644 index 0000000..6df4ebe --- /dev/null +++ b/demo/Shaders/meshPS.hlsl @@ -0,0 +1,21 @@ + +struct Input +{ + float4 position : SV_POSITION; + float3 normal : NORMAL; +}; + +float4 meshPS(Input input) : SV_TARGET +{ + float color = 0.1f; + + color += 0.4f * max(0.f,dot(input.normal, float3(0.57f, 0.57f, 0.57f))); + + color += 0.4f * max(0.f, dot(input.normal, float3(-0.57f, 0.57f, 0.57f))); + + color += 0.4f * max(0.f, dot(input.normal, float3(0.57f, 0.57f, -0.57f))); + + color += 0.4f * max(0.f, dot(input.normal, float3(-0.57f, 0.57f, -0.57f))); + + return float4(color.xxx, 1.0f); +}
\ No newline at end of file diff --git a/demo/Shaders/meshVS.hlsl b/demo/Shaders/meshVS.hlsl new file mode 100644 index 0000000..969cbeb --- /dev/null +++ b/demo/Shaders/meshVS.hlsl @@ -0,0 +1,31 @@ + +cbuffer params : register(b0) +{ + float4x4 projection; +}; + +struct Input +{ + float3 position : POSITION; + float3 normal : NORMAL; +}; + +struct Output +{ + float4 position : SV_POSITION; + float3 normal : NORMAL; +}; + +Output meshVS( Input input, uint instance : SV_InstanceID ) +{ + Output output; + output.position = mul(float4(input.position,1.f),projection); + output.normal = input.normal; + + //output.position.z *= -1.f; + //output.position.z += 0.5f; + + //output.position.y -= 1.f * float(instance) + 0.1f; + + return output; +}
\ No newline at end of file |