more seperation
This commit is contained in:
@@ -104,6 +104,8 @@ set(APP_SOURCES
|
||||
"${APP_DIR}/runtime/RuntimeHost.h"
|
||||
"${APP_DIR}/runtime/HealthTelemetry.cpp"
|
||||
"${APP_DIR}/runtime/HealthTelemetry.h"
|
||||
"${APP_DIR}/runtime/RuntimeCoordinator.cpp"
|
||||
"${APP_DIR}/runtime/RuntimeCoordinator.h"
|
||||
"${APP_DIR}/runtime/RuntimeSnapshotProvider.cpp"
|
||||
"${APP_DIR}/runtime/RuntimeSnapshotProvider.h"
|
||||
"${APP_DIR}/runtime/RuntimeClock.cpp"
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LoopThroughWithOpenGLCompositing", "LoopThroughWithOpenGLCompositing.vcxproj", "{92C79085-CA51-4008-95DB-5403D2E19885}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{92C79085-CA51-4008-95DB-5403D2E19885}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{92C79085-CA51-4008-95DB-5403D2E19885}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{92C79085-CA51-4008-95DB-5403D2E19885}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{92C79085-CA51-4008-95DB-5403D2E19885}.Debug|x64.Build.0 = Debug|x64
|
||||
{92C79085-CA51-4008-95DB-5403D2E19885}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{92C79085-CA51-4008-95DB-5403D2E19885}.Release|Win32.Build.0 = Release|Win32
|
||||
{92C79085-CA51-4008-95DB-5403D2E19885}.Release|x64.ActiveCfg = Release|x64
|
||||
{92C79085-CA51-4008-95DB-5403D2E19885}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,299 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{92C79085-CA51-4008-95DB-5403D2E19885}</ProjectGuid>
|
||||
<RootNamespace>LoopThroughWithOpenGLCompositing</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>12.0.21005.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>.;control;gl;gl\pipeline;gl\renderer;gl\shader;platform;runtime;shader;videoio;videoio\decklink;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>opengl32.lib;Glu32.lib;Ws2_32.lib;Crypt32.lib;Advapi32.lib;Gdiplus.lib;Ole32.lib;Windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>.;control;gl;gl\pipeline;gl\renderer;gl\shader;platform;runtime;shader;videoio;videoio\decklink;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>opengl32.lib;Glu32.lib;Ws2_32.lib;Crypt32.lib;Advapi32.lib;Gdiplus.lib;Ole32.lib;Windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>.;control;gl;gl\pipeline;gl\renderer;gl\shader;platform;runtime;shader;videoio;videoio\decklink;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>opengl32.lib;Glu32.lib;Ws2_32.lib;Crypt32.lib;Advapi32.lib;Gdiplus.lib;Ole32.lib;Windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>.;control;gl;gl\pipeline;gl\renderer;gl\shader;platform;runtime;shader;videoio;videoio\decklink;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>opengl32.lib;Glu32.lib;Ws2_32.lib;Crypt32.lib;Advapi32.lib;Gdiplus.lib;Ole32.lib;Windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="control\ControlServer.cpp" />
|
||||
<ClCompile Include="control\ControlServices.cpp" />
|
||||
<ClCompile Include="control\OscServer.cpp" />
|
||||
<ClCompile Include="control\RuntimeControlBridge.cpp" />
|
||||
<ClCompile Include="control\RuntimeServices.cpp" />
|
||||
<ClCompile Include="gl\renderer\GLExtensions.cpp" />
|
||||
<ClCompile Include="gl\shader\GlobalParamsBuffer.cpp" />
|
||||
<ClCompile Include="gl\shader\GlShaderSources.cpp" />
|
||||
<ClCompile Include="LoopThroughWithOpenGLCompositing.cpp" />
|
||||
<ClCompile Include="gl\OpenGLComposite.cpp" />
|
||||
<ClCompile Include="gl\OpenGLCompositeRuntimeControls.cpp" />
|
||||
<ClCompile Include="gl\RenderEngine.cpp" />
|
||||
<ClCompile Include="gl\pipeline\OpenGLRenderPass.cpp" />
|
||||
<ClCompile Include="gl\pipeline\OpenGLRenderPipeline.cpp" />
|
||||
<ClCompile Include="gl\pipeline\ShaderFeedbackBuffers.cpp" />
|
||||
<ClCompile Include="gl\renderer\OpenGLRenderer.cpp" />
|
||||
<ClCompile Include="gl\renderer\RenderTargetPool.cpp" />
|
||||
<ClCompile Include="gl\pipeline\OpenGLVideoIOBridge.cpp" />
|
||||
<ClCompile Include="gl\shader\OpenGLShaderPrograms.cpp" />
|
||||
<ClCompile Include="gl\pipeline\PngScreenshotWriter.cpp" />
|
||||
<ClCompile Include="gl\shader\ShaderProgramCompiler.cpp" />
|
||||
<ClCompile Include="gl\shader\ShaderBuildQueue.cpp" />
|
||||
<ClCompile Include="gl\shader\ShaderTextureBindings.cpp" />
|
||||
<ClCompile Include="gl\shader\TextRasterizer.cpp" />
|
||||
<ClCompile Include="gl\shader\TextureAssetLoader.cpp" />
|
||||
<ClCompile Include="gl\pipeline\TemporalHistoryBuffers.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="videoio\decklink\DeckLinkAPI_i.c" />
|
||||
<ClCompile Include="videoio\decklink\DeckLinkDisplayMode.cpp" />
|
||||
<ClCompile Include="videoio\decklink\DeckLinkFrameTransfer.cpp" />
|
||||
<ClCompile Include="videoio\decklink\DeckLinkSession.cpp" />
|
||||
<ClCompile Include="videoio\decklink\DeckLinkVideoIOFormat.cpp" />
|
||||
<ClCompile Include="runtime\HealthTelemetry.cpp" />
|
||||
<ClCompile Include="runtime\RuntimeClock.cpp" />
|
||||
<ClCompile Include="runtime\RuntimeHost.cpp" />
|
||||
<ClCompile Include="runtime\RuntimeJson.cpp" />
|
||||
<ClCompile Include="runtime\RuntimeParameterUtils.cpp" />
|
||||
<ClCompile Include="runtime\RuntimeSnapshotProvider.cpp" />
|
||||
<ClCompile Include="runtime\RuntimeStore.cpp" />
|
||||
<ClCompile Include="shader\ShaderCompiler.cpp" />
|
||||
<ClCompile Include="shader\ShaderPackageRegistry.cpp" />
|
||||
<ClCompile Include="videoio\VideoBackend.cpp" />
|
||||
<ClCompile Include="videoio\VideoIOFormat.cpp" />
|
||||
<ClCompile Include="videoio\VideoPlayoutScheduler.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="control\ControlServer.h" />
|
||||
<ClInclude Include="control\ControlServices.h" />
|
||||
<ClInclude Include="control\OscServer.h" />
|
||||
<ClInclude Include="control\RuntimeControlBridge.h" />
|
||||
<ClInclude Include="control\RuntimeServices.h" />
|
||||
<ClInclude Include="gl\renderer\GLExtensions.h" />
|
||||
<ClInclude Include="gl\shader\GlobalParamsBuffer.h" />
|
||||
<ClInclude Include="gl\renderer\GlRenderConstants.h" />
|
||||
<ClInclude Include="gl\renderer\GlScopedObjects.h" />
|
||||
<ClInclude Include="gl\shader\GlShaderSources.h" />
|
||||
<ClInclude Include="LoopThroughWithOpenGLCompositing.h" />
|
||||
<ClInclude Include="gl\OpenGLComposite.h" />
|
||||
<ClInclude Include="gl\RenderEngine.h" />
|
||||
<ClInclude Include="gl\pipeline\OpenGLRenderPass.h" />
|
||||
<ClInclude Include="gl\pipeline\OpenGLRenderPipeline.h" />
|
||||
<ClInclude Include="gl\pipeline\RenderPassDescriptor.h" />
|
||||
<ClInclude Include="gl\pipeline\ShaderFeedbackBuffers.h" />
|
||||
<ClInclude Include="gl\renderer\OpenGLRenderer.h" />
|
||||
<ClInclude Include="gl\renderer\RenderTargetPool.h" />
|
||||
<ClInclude Include="gl\pipeline\OpenGLVideoIOBridge.h" />
|
||||
<ClInclude Include="gl\shader\OpenGLShaderPrograms.h" />
|
||||
<ClInclude Include="gl\pipeline\PngScreenshotWriter.h" />
|
||||
<ClInclude Include="gl\shader\ShaderProgramCompiler.h" />
|
||||
<ClInclude Include="gl\shader\ShaderBuildQueue.h" />
|
||||
<ClInclude Include="gl\shader\ShaderTextureBindings.h" />
|
||||
<ClInclude Include="gl\shader\Std140Buffer.h" />
|
||||
<ClInclude Include="gl\shader\TextRasterizer.h" />
|
||||
<ClInclude Include="gl\shader\TextureAssetLoader.h" />
|
||||
<ClInclude Include="gl\pipeline\TemporalHistoryBuffers.h" />
|
||||
<ClInclude Include="platform\NativeHandles.h" />
|
||||
<ClInclude Include="platform\NativeSockets.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="runtime\HealthTelemetry.h" />
|
||||
<ClInclude Include="runtime\RuntimeClock.h" />
|
||||
<ClInclude Include="runtime\RuntimeHost.h" />
|
||||
<ClInclude Include="runtime\RuntimeJson.h" />
|
||||
<ClInclude Include="runtime\RuntimeParameterUtils.h" />
|
||||
<ClInclude Include="runtime\RuntimeSnapshotProvider.h" />
|
||||
<ClInclude Include="runtime\RuntimeStore.h" />
|
||||
<ClInclude Include="shader\ShaderCompiler.h" />
|
||||
<ClInclude Include="shader\ShaderPackageRegistry.h" />
|
||||
<ClInclude Include="shader\ShaderTypes.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="videoio\decklink\DeckLinkAPI_h.h" />
|
||||
<ClInclude Include="videoio\decklink\DeckLinkDisplayMode.h" />
|
||||
<ClInclude Include="videoio\decklink\DeckLinkFrameTransfer.h" />
|
||||
<ClInclude Include="videoio\decklink\DeckLinkSession.h" />
|
||||
<ClInclude Include="videoio\decklink\DeckLinkVideoIOFormat.h" />
|
||||
<ClInclude Include="videoio\VideoBackend.h" />
|
||||
<ClInclude Include="videoio\VideoIOFormat.h" />
|
||||
<ClInclude Include="videoio\VideoIOTypes.h" />
|
||||
<ClInclude Include="videoio\VideoPlayoutScheduler.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="LoopThroughWithOpenGLCompositing.ico" />
|
||||
<Image Include="small.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="video_effect.slang" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="LoopThroughWithOpenGLCompositing.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="..\..\3rdParty\Blackmagic DeckLink SDK 16.0\Win\include\DeckLinkAPI.idl" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,338 +0,0 @@
|
||||
<?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;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</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="DeckLink API">
|
||||
<UniqueIdentifier>{1eab21d6-58f8-49e0-929b-8a4482e04756}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="control\ControlServer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="control\ControlServices.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="control\OscServer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="control\RuntimeControlBridge.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\renderer\GLExtensions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\shader\GlobalParamsBuffer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\shader\GlShaderSources.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LoopThroughWithOpenGLCompositing.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\OpenGLComposite.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\OpenGLCompositeRuntimeControls.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\RenderEngine.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\pipeline\OpenGLRenderPass.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\pipeline\OpenGLRenderPipeline.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\pipeline\ShaderFeedbackBuffers.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\renderer\OpenGLRenderer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\renderer\RenderTargetPool.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\shader\OpenGLShaderPrograms.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\pipeline\PngScreenshotWriter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\shader\ShaderProgramCompiler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\shader\ShaderBuildQueue.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\shader\ShaderTextureBindings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\shader\TextRasterizer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\shader\TextureAssetLoader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\pipeline\TemporalHistoryBuffers.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\pipeline\OpenGLVideoIOBridge.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="videoio\decklink\DeckLinkAPI_i.c">
|
||||
<Filter>DeckLink API</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="control\RuntimeServices.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="videoio\decklink\DeckLinkDisplayMode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="videoio\decklink\DeckLinkFrameTransfer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="videoio\decklink\DeckLinkSession.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="videoio\decklink\DeckLinkVideoIOFormat.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="runtime\HealthTelemetry.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="runtime\RuntimeClock.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="runtime\RuntimeHost.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="runtime\RuntimeJson.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="runtime\RuntimeParameterUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="runtime\RuntimeSnapshotProvider.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="runtime\RuntimeStore.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="shader\ShaderCompiler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="shader\ShaderPackageRegistry.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="videoio\VideoBackend.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="videoio\VideoIOFormat.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="videoio\VideoPlayoutScheduler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="control\ControlServer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="control\ControlServices.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="control\OscServer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="control\RuntimeControlBridge.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\renderer\GLExtensions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\shader\GlobalParamsBuffer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\renderer\GlRenderConstants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\renderer\GlScopedObjects.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\shader\GlShaderSources.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LoopThroughWithOpenGLCompositing.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\OpenGLComposite.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\RenderEngine.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\pipeline\OpenGLRenderPass.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\pipeline\OpenGLRenderPipeline.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\pipeline\RenderPassDescriptor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\pipeline\ShaderFeedbackBuffers.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\renderer\OpenGLRenderer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\renderer\RenderTargetPool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\shader\OpenGLShaderPrograms.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\pipeline\PngScreenshotWriter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\shader\ShaderProgramCompiler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\shader\ShaderBuildQueue.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\shader\ShaderTextureBindings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\shader\Std140Buffer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\shader\TextRasterizer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\shader\TextureAssetLoader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\pipeline\TemporalHistoryBuffers.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gl\pipeline\OpenGLVideoIOBridge.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="platform\NativeHandles.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="platform\NativeSockets.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="runtime\HealthTelemetry.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="runtime\RuntimeHost.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="runtime\RuntimeJson.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="runtime\RuntimeParameterUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="runtime\RuntimeSnapshotProvider.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="runtime\RuntimeStore.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="shader\ShaderCompiler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="shader\ShaderPackageRegistry.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="shader\ShaderTypes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="control\RuntimeServices.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="videoio\decklink\DeckLinkSession.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="videoio\decklink\DeckLinkVideoIOFormat.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="videoio\decklink\DeckLinkAPI_h.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="videoio\decklink\DeckLinkDisplayMode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="videoio\decklink\DeckLinkFrameTransfer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="videoio\VideoBackend.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="runtime\RuntimeClock.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="videoio\VideoIOFormat.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="videoio\VideoIOTypes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="videoio\VideoPlayoutScheduler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="LoopThroughWithOpenGLCompositing.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="small.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="LoopThroughWithOpenGLCompositing.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="..\..\include\DeckLinkAPI.idl">
|
||||
<Filter>DeckLink API</Filter>
|
||||
</Midl>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="video_effect.slang">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -101,9 +101,10 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
|
||||
mRuntimeHost = std::make_unique<RuntimeHost>();
|
||||
mRuntimeStore = std::make_unique<RuntimeStore>(*mRuntimeHost);
|
||||
mRuntimeSnapshotProvider = std::make_unique<RuntimeSnapshotProvider>(*mRuntimeHost);
|
||||
mRuntimeCoordinator = std::make_unique<RuntimeCoordinator>(*mRuntimeStore);
|
||||
mRenderEngine = std::make_unique<RenderEngine>(
|
||||
*mRuntimeHost,
|
||||
*mRuntimeSnapshotProvider,
|
||||
mRuntimeHost->GetHealthTelemetry(),
|
||||
pMutex,
|
||||
hGLDC,
|
||||
hGLRC,
|
||||
@@ -202,7 +203,11 @@ bool OpenGLComposite::InitVideoIO()
|
||||
}
|
||||
if (!mVideoBackend->HasInputDevice() && mRuntimeHost)
|
||||
{
|
||||
mRuntimeHost->SetSignalStatus(false, mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight(), mVideoBackend->InputDisplayModeName());
|
||||
mRuntimeHost->GetHealthTelemetry().ReportSignalStatus(
|
||||
false,
|
||||
mVideoBackend->InputFrameWidth(),
|
||||
mVideoBackend->InputFrameHeight(),
|
||||
mVideoBackend->InputDisplayModeName());
|
||||
}
|
||||
|
||||
if (!mVideoBackend->ConfigureOutput(videoModes.output, mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured(), initFailureReason))
|
||||
@@ -227,27 +232,15 @@ void OpenGLComposite::paintGL(bool force)
|
||||
{
|
||||
if (IsIconic(hGLWnd))
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned previewFps = mRuntimeStore ? mRuntimeStore->GetConfiguredPreviewFps() : 30u;
|
||||
if (previewFps == 0)
|
||||
return;
|
||||
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
const auto minimumInterval = std::chrono::microseconds(1000000 / (previewFps == 0 ? 1u : previewFps));
|
||||
if (mLastPreviewPresentTime != std::chrono::steady_clock::time_point() &&
|
||||
now - mLastPreviewPresentTime < minimumInterval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mRenderEngine->TryPresentToWindow(mVideoBackend->OutputFrameWidth(), mVideoBackend->OutputFrameHeight()))
|
||||
if (!mRenderEngine->TryPresentPreview(force, previewFps, mVideoBackend->OutputFrameWidth(), mVideoBackend->OutputFrameHeight()))
|
||||
{
|
||||
ValidateRect(hGLWnd, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
mLastPreviewPresentTime = std::chrono::steady_clock::now();
|
||||
ValidateRect(hGLWnd, NULL);
|
||||
}
|
||||
|
||||
@@ -336,7 +329,7 @@ bool OpenGLComposite::InitOpenGLState()
|
||||
MessageBoxA(NULL, compilerErrorMessage, "OpenGL shader failed to load or compile", MB_OK);
|
||||
return false;
|
||||
}
|
||||
mCachedLayerRenderStates = mRenderEngine->CommittedLayerStates();
|
||||
mRuntimeStore->SetCompileStatus(true, "Shader layers compiled successfully.");
|
||||
mUseCommittedLayerStates = false;
|
||||
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
@@ -367,15 +360,8 @@ bool OpenGLComposite::Stop()
|
||||
|
||||
bool OpenGLComposite::ReloadShader(bool preserveFeedbackState)
|
||||
{
|
||||
mPreserveFeedbackOnNextShaderBuild = preserveFeedbackState;
|
||||
if (mRuntimeHost)
|
||||
{
|
||||
mRuntimeStore->SetCompileStatus(true, "Shader rebuild queued.");
|
||||
mRuntimeStore->ClearReloadRequest();
|
||||
}
|
||||
RequestShaderBuild();
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->RequestShaderReload(preserveFeedbackState));
|
||||
}
|
||||
|
||||
bool OpenGLComposite::RequestScreenshot(std::string& error)
|
||||
@@ -442,7 +428,7 @@ void OpenGLComposite::renderEffect()
|
||||
|
||||
const auto applyOscOverlays = [&](std::vector<RuntimeRenderState>& states, bool allowCommit)
|
||||
{
|
||||
if (states.empty() || mOscOverlayStates.empty() || !mRuntimeHost)
|
||||
if (states.empty() || mOscOverlayStates.empty())
|
||||
return;
|
||||
|
||||
const double smoothing = ClampOscAlpha(mRuntimeStore ? mRuntimeStore->GetConfiguredOscSmoothing() : 0.0);
|
||||
@@ -576,66 +562,12 @@ void OpenGLComposite::renderEffect()
|
||||
|
||||
const bool hasInputSource = mVideoBackend->HasInputSource();
|
||||
std::vector<RuntimeRenderState> layerStates;
|
||||
if (mUseCommittedLayerStates)
|
||||
{
|
||||
layerStates = mRenderEngine->CommittedLayerStates();
|
||||
applyOscOverlays(layerStates, false);
|
||||
if (mRuntimeSnapshotProvider)
|
||||
mRuntimeSnapshotProvider->RefreshDynamicRenderStateFields(layerStates);
|
||||
}
|
||||
else if (mRuntimeSnapshotProvider)
|
||||
{
|
||||
const unsigned renderWidth = mVideoBackend->InputFrameWidth();
|
||||
const unsigned renderHeight = mVideoBackend->InputFrameHeight();
|
||||
const RuntimeSnapshotVersions versions = mRuntimeSnapshotProvider->GetVersions();
|
||||
const bool renderStateCacheValid =
|
||||
!mCachedLayerRenderStates.empty() &&
|
||||
mCachedRenderStateVersion == versions.renderStateVersion &&
|
||||
mCachedRenderStateWidth == renderWidth &&
|
||||
mCachedRenderStateHeight == renderHeight;
|
||||
|
||||
if (renderStateCacheValid)
|
||||
{
|
||||
RuntimeRenderStateSnapshot renderSnapshot;
|
||||
renderSnapshot.outputWidth = renderWidth;
|
||||
renderSnapshot.outputHeight = renderHeight;
|
||||
renderSnapshot.versions.renderStateVersion = mCachedRenderStateVersion;
|
||||
renderSnapshot.versions.parameterStateVersion = mCachedParameterStateVersion;
|
||||
renderSnapshot.states = mCachedLayerRenderStates;
|
||||
|
||||
applyOscOverlays(renderSnapshot.states, true);
|
||||
if (mCachedParameterStateVersion != versions.parameterStateVersion &&
|
||||
mRuntimeSnapshotProvider->TryRefreshSnapshotParameters(renderSnapshot))
|
||||
{
|
||||
mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion;
|
||||
applyOscOverlays(renderSnapshot.states, true);
|
||||
}
|
||||
|
||||
mCachedLayerRenderStates = renderSnapshot.states;
|
||||
layerStates = renderSnapshot.states;
|
||||
mRuntimeSnapshotProvider->RefreshDynamicRenderStateFields(layerStates);
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeRenderStateSnapshot renderSnapshot;
|
||||
if (mRuntimeSnapshotProvider->TryGetRenderStateSnapshot(renderWidth, renderHeight, renderSnapshot))
|
||||
{
|
||||
mCachedLayerRenderStates = renderSnapshot.states;
|
||||
mCachedRenderStateVersion = renderSnapshot.versions.renderStateVersion;
|
||||
mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion;
|
||||
mCachedRenderStateWidth = renderSnapshot.outputWidth;
|
||||
mCachedRenderStateHeight = renderSnapshot.outputHeight;
|
||||
applyOscOverlays(mCachedLayerRenderStates, true);
|
||||
layerStates = mCachedLayerRenderStates;
|
||||
}
|
||||
else
|
||||
{
|
||||
applyOscOverlays(mCachedLayerRenderStates, true);
|
||||
layerStates = mCachedLayerRenderStates;
|
||||
mRuntimeSnapshotProvider->RefreshDynamicRenderStateFields(layerStates);
|
||||
}
|
||||
}
|
||||
}
|
||||
mRenderEngine->ResolveRenderLayerStates(
|
||||
mUseCommittedLayerStates.load(),
|
||||
mVideoBackend->InputFrameWidth(),
|
||||
mVideoBackend->InputFrameHeight(),
|
||||
applyOscOverlays,
|
||||
layerStates);
|
||||
const unsigned historyCap = mRuntimeStore ? mRuntimeStore->GetConfiguredMaxTemporalHistoryFrames() : 0;
|
||||
mRenderEngine->RenderLayerStack(
|
||||
hasInputSource,
|
||||
@@ -657,20 +589,9 @@ void OpenGLComposite::ProcessScreenshotRequest()
|
||||
if (width == 0 || height == 0)
|
||||
return;
|
||||
|
||||
std::vector<unsigned char> bottomUpPixels;
|
||||
if (!mRenderEngine->ReadOutputFrameRgba(width, height, bottomUpPixels))
|
||||
std::vector<unsigned char> topDownPixels;
|
||||
if (!mRenderEngine->CaptureOutputFrameRgbaTopDown(width, height, topDownPixels))
|
||||
return;
|
||||
std::vector<unsigned char> topDownPixels(bottomUpPixels.size());
|
||||
|
||||
const std::size_t rowBytes = static_cast<std::size_t>(width) * 4;
|
||||
for (unsigned y = 0; y < height; ++y)
|
||||
{
|
||||
const unsigned sourceY = height - 1 - y;
|
||||
std::copy(
|
||||
bottomUpPixels.begin() + static_cast<std::ptrdiff_t>(sourceY * rowBytes),
|
||||
bottomUpPixels.begin() + static_cast<std::ptrdiff_t>((sourceY + 1) * rowBytes),
|
||||
topDownPixels.begin() + static_cast<std::ptrdiff_t>(y * rowBytes));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -707,14 +628,13 @@ std::filesystem::path OpenGLComposite::BuildScreenshotPath() const
|
||||
|
||||
bool OpenGLComposite::ProcessRuntimePollResults()
|
||||
{
|
||||
if (!mRuntimeHost || !mRuntimeServices)
|
||||
if (!mRuntimeServices)
|
||||
return true;
|
||||
|
||||
const RuntimePollEvents events = mRuntimeServices->ConsumePollEvents();
|
||||
if (events.failed)
|
||||
{
|
||||
mRuntimeStore->SetCompileStatus(false, events.error);
|
||||
broadcastRuntimeState();
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandleRuntimePollFailure(events.error));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -728,29 +648,23 @@ bool OpenGLComposite::ProcessRuntimePollResults()
|
||||
return true;
|
||||
|
||||
char compilerErrorMessage[1024] = {};
|
||||
if (!mRenderEngine->CommitPreparedLayerPrograms(readyBuild, mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
if (!mRenderEngine->ApplyPreparedShaderBuild(
|
||||
readyBuild,
|
||||
mVideoBackend->InputFrameWidth(),
|
||||
mVideoBackend->InputFrameHeight(),
|
||||
mRuntimeCoordinator && mRuntimeCoordinator->PreserveFeedbackOnNextShaderBuild(),
|
||||
sizeof(compilerErrorMessage),
|
||||
compilerErrorMessage))
|
||||
{
|
||||
mRuntimeStore->SetCompileStatus(false, compilerErrorMessage);
|
||||
mUseCommittedLayerStates = true;
|
||||
mPreserveFeedbackOnNextShaderBuild = false;
|
||||
broadcastRuntimeState();
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandlePreparedShaderBuildFailure(compilerErrorMessage));
|
||||
return false;
|
||||
}
|
||||
|
||||
mUseCommittedLayerStates = false;
|
||||
mCachedLayerRenderStates = mRenderEngine->CommittedLayerStates();
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
if (!mPreserveFeedbackOnNextShaderBuild)
|
||||
mRenderEngine->ResetShaderFeedbackState();
|
||||
mPreserveFeedbackOnNextShaderBuild = false;
|
||||
broadcastRuntimeState();
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandlePreparedShaderBuildSuccess());
|
||||
return true;
|
||||
}
|
||||
|
||||
mRuntimeStore->SetCompileStatus(true, "Shader rebuild queued.");
|
||||
mPreserveFeedbackOnNextShaderBuild = false;
|
||||
RequestShaderBuild();
|
||||
broadcastRuntimeState();
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->HandleRuntimeReloadRequest());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -759,24 +673,81 @@ void OpenGLComposite::RequestShaderBuild()
|
||||
if (!mShaderBuildQueue || !mVideoBackend)
|
||||
return;
|
||||
|
||||
mUseCommittedLayerStates = true;
|
||||
if (mRuntimeHost)
|
||||
mRuntimeStore->ClearReloadRequest();
|
||||
mShaderBuildQueue->RequestBuild(mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight());
|
||||
}
|
||||
|
||||
bool OpenGLComposite::ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error)
|
||||
{
|
||||
if (!result.accepted)
|
||||
{
|
||||
if (error)
|
||||
*error = result.errorMessage;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result.compileStatusChanged && mRuntimeStore)
|
||||
mRuntimeStore->SetCompileStatus(result.compileStatusSucceeded, result.compileStatusMessage);
|
||||
|
||||
if (result.clearReloadRequest && mRuntimeStore)
|
||||
mRuntimeStore->ClearReloadRequest();
|
||||
|
||||
switch (result.committedStateMode)
|
||||
{
|
||||
case RuntimeCoordinatorCommittedStateMode::UseCommittedStates:
|
||||
mUseCommittedLayerStates = true;
|
||||
break;
|
||||
case RuntimeCoordinatorCommittedStateMode::UseLiveSnapshots:
|
||||
mUseCommittedLayerStates = false;
|
||||
break;
|
||||
case RuntimeCoordinatorCommittedStateMode::Unchanged:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.clearTransientOscState)
|
||||
{
|
||||
mOscOverlayStates.clear();
|
||||
if (mRuntimeServices)
|
||||
mRuntimeServices->ClearOscState();
|
||||
}
|
||||
|
||||
ApplyRuntimeCoordinatorRenderReset(result.renderResetScope);
|
||||
|
||||
if (result.shaderBuildRequested)
|
||||
RequestShaderBuild();
|
||||
|
||||
if (result.runtimeStateBroadcastRequired)
|
||||
broadcastRuntimeState();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLComposite::ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderResetScope resetScope)
|
||||
{
|
||||
if (!mRenderEngine)
|
||||
return;
|
||||
|
||||
switch (resetScope)
|
||||
{
|
||||
case RuntimeCoordinatorRenderResetScope::TemporalHistoryOnly:
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
break;
|
||||
case RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback:
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
mRenderEngine->ResetShaderFeedbackState();
|
||||
break;
|
||||
case RuntimeCoordinatorRenderResetScope::None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLComposite::broadcastRuntimeState()
|
||||
{
|
||||
if (mRuntimeServices)
|
||||
mRuntimeServices->BroadcastState();
|
||||
}
|
||||
|
||||
void OpenGLComposite::resetTemporalHistoryState()
|
||||
{
|
||||
mRenderEngine->ResetTemporalHistoryState();
|
||||
mRenderEngine->ResetShaderFeedbackState();
|
||||
}
|
||||
|
||||
bool OpenGLComposite::CheckOpenGLExtensions()
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <comutil.h>
|
||||
|
||||
#include "GLExtensions.h"
|
||||
#include "RuntimeCoordinator.h"
|
||||
#include "RuntimeHost.h"
|
||||
#include "RuntimeSnapshotProvider.h"
|
||||
#include "RuntimeStore.h"
|
||||
@@ -91,30 +92,25 @@ private:
|
||||
|
||||
std::unique_ptr<RuntimeHost> mRuntimeHost;
|
||||
std::unique_ptr<RuntimeStore> mRuntimeStore;
|
||||
std::unique_ptr<RuntimeCoordinator> mRuntimeCoordinator;
|
||||
std::unique_ptr<RuntimeSnapshotProvider> mRuntimeSnapshotProvider;
|
||||
std::unique_ptr<RenderEngine> mRenderEngine;
|
||||
std::unique_ptr<ShaderBuildQueue> mShaderBuildQueue;
|
||||
std::unique_ptr<RuntimeServices> mRuntimeServices;
|
||||
std::unique_ptr<VideoBackend> mVideoBackend;
|
||||
std::vector<RuntimeRenderState> mCachedLayerRenderStates;
|
||||
uint64_t mCachedRenderStateVersion = 0;
|
||||
uint64_t mCachedParameterStateVersion = 0;
|
||||
unsigned mCachedRenderStateWidth = 0;
|
||||
unsigned mCachedRenderStateHeight = 0;
|
||||
std::map<std::string, OscOverlayState> mOscOverlayStates;
|
||||
std::atomic<bool> mUseCommittedLayerStates;
|
||||
std::atomic<bool> mScreenshotRequested;
|
||||
std::chrono::steady_clock::time_point mLastPreviewPresentTime;
|
||||
bool mPreserveFeedbackOnNextShaderBuild = false;
|
||||
|
||||
bool InitOpenGLState();
|
||||
void renderEffect();
|
||||
bool ProcessRuntimePollResults();
|
||||
void RequestShaderBuild();
|
||||
bool ApplyRuntimeCoordinatorResult(const RuntimeCoordinatorResult& result, std::string* error = nullptr);
|
||||
void ApplyRuntimeCoordinatorRenderReset(RuntimeCoordinatorRenderResetScope resetScope);
|
||||
void ProcessScreenshotRequest();
|
||||
std::filesystem::path BuildScreenshotPath() const;
|
||||
void broadcastRuntimeState();
|
||||
void resetTemporalHistoryState();
|
||||
};
|
||||
|
||||
#endif // __OPENGL_COMPOSITE_H__
|
||||
|
||||
@@ -38,62 +38,38 @@ std::string OpenGLComposite::GetOscAddress() const
|
||||
|
||||
bool OpenGLComposite::AddLayer(const std::string& shaderId, std::string& error)
|
||||
{
|
||||
if (!mRuntimeStore->CreateStoredLayer(shaderId, error))
|
||||
return false;
|
||||
|
||||
ReloadShader(true);
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->AddLayer(shaderId), &error);
|
||||
}
|
||||
|
||||
bool OpenGLComposite::RemoveLayer(const std::string& layerId, std::string& error)
|
||||
{
|
||||
if (!mRuntimeStore->DeleteStoredLayer(layerId, error))
|
||||
return false;
|
||||
|
||||
ReloadShader(true);
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->RemoveLayer(layerId), &error);
|
||||
}
|
||||
|
||||
bool OpenGLComposite::MoveLayer(const std::string& layerId, int direction, std::string& error)
|
||||
{
|
||||
if (!mRuntimeStore->MoveStoredLayer(layerId, direction, error))
|
||||
return false;
|
||||
|
||||
ReloadShader(true);
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->MoveLayer(layerId, direction), &error);
|
||||
}
|
||||
|
||||
bool OpenGLComposite::MoveLayerToIndex(const std::string& layerId, std::size_t targetIndex, std::string& error)
|
||||
{
|
||||
if (!mRuntimeStore->MoveStoredLayerToIndex(layerId, targetIndex, error))
|
||||
return false;
|
||||
|
||||
ReloadShader(true);
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->MoveLayerToIndex(layerId, targetIndex), &error);
|
||||
}
|
||||
|
||||
bool OpenGLComposite::SetLayerBypass(const std::string& layerId, bool bypassed, std::string& error)
|
||||
{
|
||||
if (!mRuntimeStore->SetStoredLayerBypassState(layerId, bypassed, error))
|
||||
return false;
|
||||
|
||||
ReloadShader();
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SetLayerBypass(layerId, bypassed), &error);
|
||||
}
|
||||
|
||||
bool OpenGLComposite::SetLayerShader(const std::string& layerId, const std::string& shaderId, std::string& error)
|
||||
{
|
||||
if (!mRuntimeStore->SetStoredLayerShaderSelection(layerId, shaderId, error))
|
||||
return false;
|
||||
|
||||
ReloadShader();
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SetLayerShader(layerId, shaderId), &error);
|
||||
}
|
||||
|
||||
bool OpenGLComposite::UpdateLayerParameterJson(const std::string& layerId, const std::string& parameterId, const std::string& valueJson, std::string& error)
|
||||
@@ -102,11 +78,8 @@ bool OpenGLComposite::UpdateLayerParameterJson(const std::string& layerId, const
|
||||
if (!ParseJson(valueJson, parsedValue, error))
|
||||
return false;
|
||||
|
||||
if (!mRuntimeStore->SetStoredParameterValue(layerId, parameterId, parsedValue, error))
|
||||
return false;
|
||||
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->UpdateLayerParameter(layerId, parameterId, parsedValue), &error);
|
||||
}
|
||||
|
||||
bool OpenGLComposite::UpdateLayerParameterByControlKeyJson(const std::string& layerKey, const std::string& parameterKey, const std::string& valueJson, std::string& error)
|
||||
@@ -115,42 +88,24 @@ bool OpenGLComposite::UpdateLayerParameterByControlKeyJson(const std::string& la
|
||||
if (!ParseJson(valueJson, parsedValue, error))
|
||||
return false;
|
||||
|
||||
if (!mRuntimeStore->SetStoredParameterValueByControlKey(layerKey, parameterKey, parsedValue, error))
|
||||
return false;
|
||||
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->UpdateLayerParameterByControlKey(layerKey, parameterKey, parsedValue), &error);
|
||||
}
|
||||
|
||||
bool OpenGLComposite::ResetLayerParameters(const std::string& layerId, std::string& error)
|
||||
{
|
||||
if (!mRuntimeStore->ResetStoredLayerParameterValues(layerId, error))
|
||||
return false;
|
||||
|
||||
mOscOverlayStates.clear();
|
||||
if (mRuntimeServices)
|
||||
mRuntimeServices->ClearOscState();
|
||||
resetTemporalHistoryState();
|
||||
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->ResetLayerParameters(layerId), &error);
|
||||
}
|
||||
|
||||
bool OpenGLComposite::SaveStackPreset(const std::string& presetName, std::string& error)
|
||||
{
|
||||
if (!mRuntimeStore->SaveStackPresetSnapshot(presetName, error))
|
||||
return false;
|
||||
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->SaveStackPreset(presetName), &error);
|
||||
}
|
||||
|
||||
bool OpenGLComposite::LoadStackPreset(const std::string& presetName, std::string& error)
|
||||
{
|
||||
if (!mRuntimeStore->LoadStackPresetSnapshot(presetName, error))
|
||||
return false;
|
||||
|
||||
ReloadShader();
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
return mRuntimeCoordinator &&
|
||||
ApplyRuntimeCoordinatorResult(mRuntimeCoordinator->LoadStackPreset(presetName), &error);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
#include <gl/gl.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
RenderEngine::RenderEngine(
|
||||
RuntimeHost& runtimeHost,
|
||||
RuntimeSnapshotProvider& runtimeSnapshotProvider,
|
||||
HealthTelemetry& healthTelemetry,
|
||||
CRITICAL_SECTION& mutex,
|
||||
HDC hdc,
|
||||
HGLRC hglrc,
|
||||
@@ -13,8 +16,9 @@ RenderEngine::RenderEngine(
|
||||
PreviewPaintCallback previewPaint) :
|
||||
mRenderer(),
|
||||
mRenderPass(mRenderer),
|
||||
mRenderPipeline(mRenderer, runtimeHost, std::move(renderEffect), std::move(screenshotReady), std::move(previewPaint)),
|
||||
mShaderPrograms(mRenderer, runtimeHost, runtimeSnapshotProvider),
|
||||
mRenderPipeline(mRenderer, runtimeSnapshotProvider, healthTelemetry, std::move(renderEffect), std::move(screenshotReady), std::move(previewPaint)),
|
||||
mShaderPrograms(mRenderer, runtimeSnapshotProvider),
|
||||
mRuntimeSnapshotProvider(runtimeSnapshotProvider),
|
||||
mMutex(mutex),
|
||||
mHdc(hdc),
|
||||
mHglrc(hglrc)
|
||||
@@ -65,6 +69,28 @@ bool RenderEngine::CommitPreparedLayerPrograms(const PreparedShaderBuild& prepar
|
||||
return mShaderPrograms.CommitPreparedLayerPrograms(preparedBuild, inputFrameWidth, inputFrameHeight, errorMessageSize, errorMessage);
|
||||
}
|
||||
|
||||
bool RenderEngine::ApplyPreparedShaderBuild(
|
||||
const PreparedShaderBuild& preparedBuild,
|
||||
unsigned inputFrameWidth,
|
||||
unsigned inputFrameHeight,
|
||||
bool preserveFeedbackState,
|
||||
int errorMessageSize,
|
||||
char* errorMessage)
|
||||
{
|
||||
if (!CommitPreparedLayerPrograms(preparedBuild, inputFrameWidth, inputFrameHeight, errorMessageSize, errorMessage))
|
||||
return false;
|
||||
|
||||
mCachedLayerRenderStates = mShaderPrograms.CommittedLayerStates();
|
||||
mCachedRenderStateVersion = preparedBuild.renderSnapshot.versions.renderStateVersion;
|
||||
mCachedParameterStateVersion = preparedBuild.renderSnapshot.versions.parameterStateVersion;
|
||||
mCachedRenderStateWidth = preparedBuild.renderSnapshot.outputWidth;
|
||||
mCachedRenderStateHeight = preparedBuild.renderSnapshot.outputHeight;
|
||||
ResetTemporalHistoryState();
|
||||
if (!preserveFeedbackState)
|
||||
ResetShaderFeedbackState();
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::vector<RuntimeRenderState>& RenderEngine::CommittedLayerStates() const
|
||||
{
|
||||
return mShaderPrograms.CommittedLayerStates();
|
||||
@@ -85,12 +111,27 @@ void RenderEngine::ResizeView(int width, int height)
|
||||
mRenderer.ResizeView(width, height);
|
||||
}
|
||||
|
||||
bool RenderEngine::TryPresentToWindow(unsigned outputFrameWidth, unsigned outputFrameHeight)
|
||||
bool RenderEngine::TryPresentPreview(bool force, unsigned previewFps, unsigned outputFrameWidth, unsigned outputFrameHeight)
|
||||
{
|
||||
if (!force)
|
||||
{
|
||||
if (previewFps == 0)
|
||||
return false;
|
||||
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
const auto minimumInterval = std::chrono::microseconds(1000000 / (previewFps == 0 ? 1u : previewFps));
|
||||
if (mLastPreviewPresentTime != std::chrono::steady_clock::time_point() &&
|
||||
now - mLastPreviewPresentTime < minimumInterval)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!TryEnterCriticalSection(&mMutex))
|
||||
return false;
|
||||
|
||||
mRenderer.PresentToWindow(mHdc, outputFrameWidth, outputFrameHeight);
|
||||
mLastPreviewPresentTime = std::chrono::steady_clock::now();
|
||||
LeaveCriticalSection(&mMutex);
|
||||
return true;
|
||||
}
|
||||
@@ -133,6 +174,76 @@ bool RenderEngine::RenderOutputFrame(const RenderPipelineFrameContext& context,
|
||||
return rendered;
|
||||
}
|
||||
|
||||
bool RenderEngine::ResolveRenderLayerStates(
|
||||
bool useCommittedLayerStates,
|
||||
unsigned renderWidth,
|
||||
unsigned renderHeight,
|
||||
OverlayApplier overlayApplier,
|
||||
std::vector<RuntimeRenderState>& layerStates)
|
||||
{
|
||||
layerStates.clear();
|
||||
if (useCommittedLayerStates)
|
||||
{
|
||||
layerStates = mShaderPrograms.CommittedLayerStates();
|
||||
if (overlayApplier)
|
||||
overlayApplier(layerStates, false);
|
||||
mRuntimeSnapshotProvider.RefreshDynamicRenderStateFields(layerStates);
|
||||
return true;
|
||||
}
|
||||
|
||||
const RuntimeSnapshotVersions versions = mRuntimeSnapshotProvider.GetVersions();
|
||||
const bool renderStateCacheValid =
|
||||
!mCachedLayerRenderStates.empty() &&
|
||||
mCachedRenderStateVersion == versions.renderStateVersion &&
|
||||
mCachedRenderStateWidth == renderWidth &&
|
||||
mCachedRenderStateHeight == renderHeight;
|
||||
|
||||
if (renderStateCacheValid)
|
||||
{
|
||||
RuntimeRenderStateSnapshot renderSnapshot;
|
||||
renderSnapshot.outputWidth = renderWidth;
|
||||
renderSnapshot.outputHeight = renderHeight;
|
||||
renderSnapshot.versions.renderStateVersion = mCachedRenderStateVersion;
|
||||
renderSnapshot.versions.parameterStateVersion = mCachedParameterStateVersion;
|
||||
renderSnapshot.states = mCachedLayerRenderStates;
|
||||
|
||||
if (overlayApplier)
|
||||
overlayApplier(renderSnapshot.states, true);
|
||||
if (mCachedParameterStateVersion != versions.parameterStateVersion &&
|
||||
mRuntimeSnapshotProvider.TryRefreshSnapshotParameters(renderSnapshot))
|
||||
{
|
||||
mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion;
|
||||
if (overlayApplier)
|
||||
overlayApplier(renderSnapshot.states, true);
|
||||
}
|
||||
|
||||
mCachedLayerRenderStates = renderSnapshot.states;
|
||||
layerStates = renderSnapshot.states;
|
||||
mRuntimeSnapshotProvider.RefreshDynamicRenderStateFields(layerStates);
|
||||
return true;
|
||||
}
|
||||
|
||||
RuntimeRenderStateSnapshot renderSnapshot;
|
||||
if (mRuntimeSnapshotProvider.TryGetRenderStateSnapshot(renderWidth, renderHeight, renderSnapshot))
|
||||
{
|
||||
mCachedLayerRenderStates = renderSnapshot.states;
|
||||
mCachedRenderStateVersion = renderSnapshot.versions.renderStateVersion;
|
||||
mCachedParameterStateVersion = renderSnapshot.versions.parameterStateVersion;
|
||||
mCachedRenderStateWidth = renderSnapshot.outputWidth;
|
||||
mCachedRenderStateHeight = renderSnapshot.outputHeight;
|
||||
if (overlayApplier)
|
||||
overlayApplier(mCachedLayerRenderStates, true);
|
||||
layerStates = mCachedLayerRenderStates;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (overlayApplier)
|
||||
overlayApplier(mCachedLayerRenderStates, true);
|
||||
layerStates = mCachedLayerRenderStates;
|
||||
mRuntimeSnapshotProvider.RefreshDynamicRenderStateFields(layerStates);
|
||||
return !layerStates.empty();
|
||||
}
|
||||
|
||||
void RenderEngine::RenderLayerStack(
|
||||
bool hasInputSource,
|
||||
const std::vector<RuntimeRenderState>& layerStates,
|
||||
@@ -178,3 +289,23 @@ bool RenderEngine::ReadOutputFrameRgba(unsigned width, unsigned height, std::vec
|
||||
LeaveCriticalSection(&mMutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderEngine::CaptureOutputFrameRgbaTopDown(unsigned width, unsigned height, std::vector<unsigned char>& topDownPixels)
|
||||
{
|
||||
std::vector<unsigned char> bottomUpPixels;
|
||||
if (!ReadOutputFrameRgba(width, height, bottomUpPixels))
|
||||
return false;
|
||||
|
||||
topDownPixels.resize(bottomUpPixels.size());
|
||||
const std::size_t rowBytes = static_cast<std::size_t>(width) * 4;
|
||||
for (unsigned y = 0; y < height; ++y)
|
||||
{
|
||||
const unsigned sourceY = height - 1 - y;
|
||||
std::copy(
|
||||
bottomUpPixels.begin() + static_cast<std::ptrdiff_t>(sourceY * rowBytes),
|
||||
bottomUpPixels.begin() + static_cast<std::ptrdiff_t>((sourceY + 1) * rowBytes),
|
||||
topDownPixels.begin() + static_cast<std::ptrdiff_t>(y * rowBytes));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
#include "OpenGLRenderPipeline.h"
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "OpenGLShaderPrograms.h"
|
||||
#include "RuntimeHost.h"
|
||||
#include "HealthTelemetry.h"
|
||||
#include "RuntimeSnapshotProvider.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -19,10 +21,11 @@ public:
|
||||
using RenderEffectCallback = std::function<void()>;
|
||||
using ScreenshotCallback = std::function<void()>;
|
||||
using PreviewPaintCallback = std::function<void()>;
|
||||
using OverlayApplier = std::function<void(std::vector<RuntimeRenderState>& states, bool allowCommit)>;
|
||||
|
||||
RenderEngine(
|
||||
RuntimeHost& runtimeHost,
|
||||
RuntimeSnapshotProvider& runtimeSnapshotProvider,
|
||||
HealthTelemetry& healthTelemetry,
|
||||
CRITICAL_SECTION& mutex,
|
||||
HDC hdc,
|
||||
HGLRC hglrc,
|
||||
@@ -43,14 +46,27 @@ public:
|
||||
std::string& error);
|
||||
bool CompileLayerPrograms(unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage);
|
||||
bool CommitPreparedLayerPrograms(const PreparedShaderBuild& preparedBuild, unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage);
|
||||
bool ApplyPreparedShaderBuild(
|
||||
const PreparedShaderBuild& preparedBuild,
|
||||
unsigned inputFrameWidth,
|
||||
unsigned inputFrameHeight,
|
||||
bool preserveFeedbackState,
|
||||
int errorMessageSize,
|
||||
char* errorMessage);
|
||||
|
||||
const std::vector<RuntimeRenderState>& CommittedLayerStates() const;
|
||||
void ResetTemporalHistoryState();
|
||||
void ResetShaderFeedbackState();
|
||||
void ResizeView(int width, int height);
|
||||
bool TryPresentToWindow(unsigned outputFrameWidth, unsigned outputFrameHeight);
|
||||
bool TryPresentPreview(bool force, unsigned previewFps, unsigned outputFrameWidth, unsigned outputFrameHeight);
|
||||
bool TryUploadInputFrame(const VideoIOFrame& inputFrame, const VideoIOState& videoState);
|
||||
bool RenderOutputFrame(const RenderPipelineFrameContext& context, VideoIOOutputFrame& outputFrame);
|
||||
bool ResolveRenderLayerStates(
|
||||
bool useCommittedLayerStates,
|
||||
unsigned renderWidth,
|
||||
unsigned renderHeight,
|
||||
OverlayApplier overlayApplier,
|
||||
std::vector<RuntimeRenderState>& layerStates);
|
||||
void RenderLayerStack(
|
||||
bool hasInputSource,
|
||||
const std::vector<RuntimeRenderState>& layerStates,
|
||||
@@ -60,13 +76,21 @@ public:
|
||||
VideoIOPixelFormat inputPixelFormat,
|
||||
unsigned historyCap);
|
||||
bool ReadOutputFrameRgba(unsigned width, unsigned height, std::vector<unsigned char>& bottomUpPixels);
|
||||
bool CaptureOutputFrameRgbaTopDown(unsigned width, unsigned height, std::vector<unsigned char>& topDownPixels);
|
||||
|
||||
private:
|
||||
OpenGLRenderer mRenderer;
|
||||
OpenGLRenderPass mRenderPass;
|
||||
OpenGLRenderPipeline mRenderPipeline;
|
||||
OpenGLShaderPrograms mShaderPrograms;
|
||||
RuntimeSnapshotProvider& mRuntimeSnapshotProvider;
|
||||
CRITICAL_SECTION& mMutex;
|
||||
HDC mHdc;
|
||||
HGLRC mHglrc;
|
||||
std::vector<RuntimeRenderState> mCachedLayerRenderStates;
|
||||
uint64_t mCachedRenderStateVersion = 0;
|
||||
uint64_t mCachedParameterStateVersion = 0;
|
||||
unsigned mCachedRenderStateWidth = 0;
|
||||
unsigned mCachedRenderStateHeight = 0;
|
||||
std::chrono::steady_clock::time_point mLastPreviewPresentTime;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "OpenGLRenderPipeline.h"
|
||||
|
||||
#include "HealthTelemetry.h"
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "RuntimeHost.h"
|
||||
#include "RuntimeSnapshotProvider.h"
|
||||
#include "VideoIOFormat.h"
|
||||
|
||||
#include <cstring>
|
||||
@@ -11,12 +12,14 @@
|
||||
|
||||
OpenGLRenderPipeline::OpenGLRenderPipeline(
|
||||
OpenGLRenderer& renderer,
|
||||
RuntimeHost& runtimeHost,
|
||||
RuntimeSnapshotProvider& runtimeSnapshotProvider,
|
||||
HealthTelemetry& healthTelemetry,
|
||||
RenderEffectCallback renderEffect,
|
||||
OutputReadyCallback outputReady,
|
||||
PaintCallback paint) :
|
||||
mRenderer(renderer),
|
||||
mRuntimeHost(runtimeHost),
|
||||
mRuntimeSnapshotProvider(runtimeSnapshotProvider),
|
||||
mHealthTelemetry(healthTelemetry),
|
||||
mRenderEffect(renderEffect),
|
||||
mOutputReady(outputReady),
|
||||
mPaint(paint)
|
||||
@@ -47,8 +50,8 @@ bool OpenGLRenderPipeline::RenderFrame(const RenderPipelineFrameContext& context
|
||||
|
||||
const auto renderEndTime = std::chrono::steady_clock::now();
|
||||
const double renderMilliseconds = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(renderEndTime - renderStartTime).count();
|
||||
mRuntimeHost.GetHealthTelemetry().TryRecordPerformanceStats(state.frameBudgetMilliseconds, renderMilliseconds);
|
||||
mRuntimeHost.TryAdvanceFrame();
|
||||
mHealthTelemetry.TryRecordPerformanceStats(state.frameBudgetMilliseconds, renderMilliseconds);
|
||||
mRuntimeSnapshotProvider.TryAdvanceFrame();
|
||||
|
||||
ReadOutputFrame(state, outputFrame);
|
||||
if (mPaint)
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
#include <vector>
|
||||
|
||||
class OpenGLRenderer;
|
||||
class RuntimeHost;
|
||||
class HealthTelemetry;
|
||||
class RuntimeSnapshotProvider;
|
||||
|
||||
struct RenderPipelineFrameContext
|
||||
{
|
||||
@@ -25,7 +26,8 @@ public:
|
||||
|
||||
OpenGLRenderPipeline(
|
||||
OpenGLRenderer& renderer,
|
||||
RuntimeHost& runtimeHost,
|
||||
RuntimeSnapshotProvider& runtimeSnapshotProvider,
|
||||
HealthTelemetry& healthTelemetry,
|
||||
RenderEffectCallback renderEffect,
|
||||
OutputReadyCallback outputReady,
|
||||
PaintCallback paint);
|
||||
@@ -53,7 +55,8 @@ private:
|
||||
void ReadOutputFrame(const VideoIOState& state, VideoIOOutputFrame& outputFrame);
|
||||
|
||||
OpenGLRenderer& mRenderer;
|
||||
RuntimeHost& mRuntimeHost;
|
||||
RuntimeSnapshotProvider& mRuntimeSnapshotProvider;
|
||||
HealthTelemetry& mHealthTelemetry;
|
||||
RenderEffectCallback mRenderEffect;
|
||||
OutputReadyCallback mOutputReady;
|
||||
PaintCallback mPaint;
|
||||
|
||||
@@ -1,81 +1,25 @@
|
||||
#include "OpenGLVideoIOBridge.h"
|
||||
|
||||
#include "HealthTelemetry.h"
|
||||
#include "RenderEngine.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
OpenGLVideoIOBridge::OpenGLVideoIOBridge(
|
||||
VideoIODevice& videoIO,
|
||||
RenderEngine& renderEngine,
|
||||
HealthTelemetry& healthTelemetry) :
|
||||
mVideoIO(videoIO),
|
||||
mRenderEngine(renderEngine),
|
||||
mHealthTelemetry(healthTelemetry)
|
||||
OpenGLVideoIOBridge::OpenGLVideoIOBridge(RenderEngine& renderEngine) :
|
||||
mRenderEngine(renderEngine)
|
||||
{
|
||||
}
|
||||
|
||||
void OpenGLVideoIOBridge::RecordFramePacing(VideoIOCompletionResult completionResult)
|
||||
void OpenGLVideoIOBridge::UploadInputFrame(const VideoIOFrame& inputFrame, const VideoIOState& state)
|
||||
{
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (mLastPlayoutCompletionTime != std::chrono::steady_clock::time_point())
|
||||
{
|
||||
mCompletionIntervalMilliseconds = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(now - mLastPlayoutCompletionTime).count();
|
||||
if (mSmoothedCompletionIntervalMilliseconds <= 0.0)
|
||||
mSmoothedCompletionIntervalMilliseconds = mCompletionIntervalMilliseconds;
|
||||
else
|
||||
mSmoothedCompletionIntervalMilliseconds = mSmoothedCompletionIntervalMilliseconds * 0.9 + mCompletionIntervalMilliseconds * 0.1;
|
||||
if (mCompletionIntervalMilliseconds > mMaxCompletionIntervalMilliseconds)
|
||||
mMaxCompletionIntervalMilliseconds = mCompletionIntervalMilliseconds;
|
||||
}
|
||||
mLastPlayoutCompletionTime = now;
|
||||
|
||||
if (completionResult == VideoIOCompletionResult::DisplayedLate)
|
||||
++mLateFrameCount;
|
||||
else if (completionResult == VideoIOCompletionResult::Dropped)
|
||||
++mDroppedFrameCount;
|
||||
else if (completionResult == VideoIOCompletionResult::Flushed)
|
||||
++mFlushedFrameCount;
|
||||
|
||||
mHealthTelemetry.TryRecordFramePacingStats(
|
||||
mCompletionIntervalMilliseconds,
|
||||
mSmoothedCompletionIntervalMilliseconds,
|
||||
mMaxCompletionIntervalMilliseconds,
|
||||
mLateFrameCount,
|
||||
mDroppedFrameCount,
|
||||
mFlushedFrameCount);
|
||||
}
|
||||
|
||||
void OpenGLVideoIOBridge::VideoFrameArrived(const VideoIOFrame& inputFrame)
|
||||
{
|
||||
const VideoIOState& state = mVideoIO.State();
|
||||
mHealthTelemetry.TryReportSignalStatus(!inputFrame.hasNoInputSource, state.inputFrameSize.width, state.inputFrameSize.height, state.inputDisplayModeName);
|
||||
|
||||
if (inputFrame.hasNoInputSource || inputFrame.bytes == nullptr)
|
||||
return; // don't transfer texture when there's no input
|
||||
|
||||
mRenderEngine.TryUploadInputFrame(inputFrame, state);
|
||||
}
|
||||
|
||||
void OpenGLVideoIOBridge::PlayoutFrameCompleted(const VideoIOCompletion& completion)
|
||||
void OpenGLVideoIOBridge::RenderScheduledFrame(const VideoIOState& state, const VideoIOCompletion& completion, VideoIOOutputFrame& outputFrame)
|
||||
{
|
||||
RecordFramePacing(completion.result);
|
||||
|
||||
VideoIOOutputFrame outputFrame;
|
||||
if (!mVideoIO.BeginOutputFrame(outputFrame))
|
||||
return;
|
||||
const VideoIOState& state = mVideoIO.State();
|
||||
RenderPipelineFrameContext frameContext;
|
||||
frameContext.videoState = state;
|
||||
frameContext.completion = completion;
|
||||
|
||||
mRenderEngine.RenderOutputFrame(frameContext, outputFrame);
|
||||
|
||||
mVideoIO.EndOutputFrame(outputFrame);
|
||||
|
||||
mVideoIO.AccountForCompletionResult(completion.result);
|
||||
|
||||
// Schedule the next frame for playout after the GL bridge is released so
|
||||
// input uploads are not blocked by non-GL output bookkeeping.
|
||||
mVideoIO.ScheduleOutputFrame(outputFrame);
|
||||
}
|
||||
|
||||
@@ -2,34 +2,16 @@
|
||||
|
||||
#include "OpenGLRenderPipeline.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
|
||||
class HealthTelemetry;
|
||||
class RenderEngine;
|
||||
|
||||
class OpenGLVideoIOBridge
|
||||
{
|
||||
public:
|
||||
OpenGLVideoIOBridge(
|
||||
VideoIODevice& videoIO,
|
||||
RenderEngine& renderEngine,
|
||||
HealthTelemetry& healthTelemetry);
|
||||
explicit OpenGLVideoIOBridge(RenderEngine& renderEngine);
|
||||
|
||||
void VideoFrameArrived(const VideoIOFrame& inputFrame);
|
||||
void PlayoutFrameCompleted(const VideoIOCompletion& completion);
|
||||
void UploadInputFrame(const VideoIOFrame& inputFrame, const VideoIOState& state);
|
||||
void RenderScheduledFrame(const VideoIOState& state, const VideoIOCompletion& completion, VideoIOOutputFrame& outputFrame);
|
||||
|
||||
private:
|
||||
void RecordFramePacing(VideoIOCompletionResult completionResult);
|
||||
|
||||
VideoIODevice& mVideoIO;
|
||||
RenderEngine& mRenderEngine;
|
||||
HealthTelemetry& mHealthTelemetry;
|
||||
std::chrono::steady_clock::time_point mLastPlayoutCompletionTime;
|
||||
double mCompletionIntervalMilliseconds = 0.0;
|
||||
double mSmoothedCompletionIntervalMilliseconds = 0.0;
|
||||
double mMaxCompletionIntervalMilliseconds = 0.0;
|
||||
uint64_t mLateFrameCount = 0;
|
||||
uint64_t mDroppedFrameCount = 0;
|
||||
uint64_t mFlushedFrameCount = 0;
|
||||
};
|
||||
|
||||
@@ -29,12 +29,11 @@ std::size_t RequiredTemporaryRenderTargets(const std::vector<OpenGLRenderer::Lay
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLShaderPrograms::OpenGLShaderPrograms(OpenGLRenderer& renderer, RuntimeHost& runtimeHost, RuntimeSnapshotProvider& runtimeSnapshotProvider) :
|
||||
OpenGLShaderPrograms::OpenGLShaderPrograms(OpenGLRenderer& renderer, RuntimeSnapshotProvider& runtimeSnapshotProvider) :
|
||||
mRenderer(renderer),
|
||||
mRuntimeHost(runtimeHost),
|
||||
mRuntimeSnapshotProvider(runtimeSnapshotProvider),
|
||||
mGlobalParamsBuffer(renderer),
|
||||
mCompiler(renderer, runtimeHost, mTextureBindings)
|
||||
mCompiler(renderer, runtimeSnapshotProvider, mTextureBindings)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ bool OpenGLShaderPrograms::CompileLayerPrograms(unsigned inputFrameWidth, unsign
|
||||
mRuntimeSnapshotProvider.GetRenderStateSnapshot(inputFrameWidth, inputFrameHeight);
|
||||
const std::vector<RuntimeRenderState>& layerStates = renderSnapshot.states;
|
||||
std::string temporalError;
|
||||
const unsigned historyCap = mRuntimeHost.GetMaxTemporalHistoryFrames();
|
||||
const unsigned historyCap = mRuntimeSnapshotProvider.GetMaxTemporalHistoryFrames();
|
||||
if (!mRenderer.TemporalHistory().ValidateTextureUnitBudget(layerStates, historyCap, temporalError))
|
||||
{
|
||||
CopyErrorMessage(temporalError, errorMessageSize, errorMessage);
|
||||
@@ -92,9 +91,6 @@ bool OpenGLShaderPrograms::CompileLayerPrograms(unsigned inputFrameWidth, unsign
|
||||
mRenderer.ReplaceLayerPrograms(newPrograms);
|
||||
mCommittedLayerStates = renderSnapshot.states;
|
||||
|
||||
mRuntimeHost.SetCompileStatus(true, "Shader layers compiled successfully.");
|
||||
mRuntimeHost.ClearReloadRequest();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -107,7 +103,7 @@ bool OpenGLShaderPrograms::CommitPreparedLayerPrograms(const PreparedShaderBuild
|
||||
}
|
||||
|
||||
std::string temporalError;
|
||||
const unsigned historyCap = mRuntimeHost.GetMaxTemporalHistoryFrames();
|
||||
const unsigned historyCap = mRuntimeSnapshotProvider.GetMaxTemporalHistoryFrames();
|
||||
if (!mRenderer.TemporalHistory().ValidateTextureUnitBudget(preparedBuild.renderSnapshot.states, historyCap, temporalError))
|
||||
{
|
||||
CopyErrorMessage(temporalError, errorMessageSize, errorMessage);
|
||||
@@ -155,9 +151,6 @@ bool OpenGLShaderPrograms::CommitPreparedLayerPrograms(const PreparedShaderBuild
|
||||
mRenderer.ReplaceLayerPrograms(newPrograms);
|
||||
mCommittedLayerStates = preparedBuild.renderSnapshot.states;
|
||||
|
||||
mRuntimeHost.SetCompileStatus(true, "Shader layers compiled successfully.");
|
||||
mRuntimeHost.ClearReloadRequest();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "GlobalParamsBuffer.h"
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "RuntimeHost.h"
|
||||
#include "RuntimeSnapshotProvider.h"
|
||||
#include "ShaderBuildQueue.h"
|
||||
#include "ShaderTypes.h"
|
||||
@@ -16,7 +15,7 @@ class OpenGLShaderPrograms
|
||||
public:
|
||||
using LayerProgram = OpenGLRenderer::LayerProgram;
|
||||
|
||||
OpenGLShaderPrograms(OpenGLRenderer& renderer, RuntimeHost& runtimeHost, RuntimeSnapshotProvider& runtimeSnapshotProvider);
|
||||
OpenGLShaderPrograms(OpenGLRenderer& renderer, RuntimeSnapshotProvider& runtimeSnapshotProvider);
|
||||
|
||||
bool CompileLayerPrograms(unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage);
|
||||
bool CommitPreparedLayerPrograms(const PreparedShaderBuild& preparedBuild, unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage);
|
||||
@@ -33,7 +32,6 @@ public:
|
||||
|
||||
private:
|
||||
OpenGLRenderer& mRenderer;
|
||||
RuntimeHost& mRuntimeHost;
|
||||
RuntimeSnapshotProvider& mRuntimeSnapshotProvider;
|
||||
ShaderTextureBindings mTextureBindings;
|
||||
GlobalParamsBuffer mGlobalParamsBuffer;
|
||||
|
||||
@@ -19,9 +19,9 @@ void CopyErrorMessage(const std::string& message, int errorMessageSize, char* er
|
||||
}
|
||||
}
|
||||
|
||||
ShaderProgramCompiler::ShaderProgramCompiler(OpenGLRenderer& renderer, RuntimeHost& runtimeHost, ShaderTextureBindings& textureBindings) :
|
||||
ShaderProgramCompiler::ShaderProgramCompiler(OpenGLRenderer& renderer, RuntimeSnapshotProvider& runtimeSnapshotProvider, ShaderTextureBindings& textureBindings) :
|
||||
mRenderer(renderer),
|
||||
mRuntimeHost(runtimeHost),
|
||||
mRuntimeSnapshotProvider(runtimeSnapshotProvider),
|
||||
mTextureBindings(textureBindings)
|
||||
{
|
||||
}
|
||||
@@ -31,7 +31,7 @@ bool ShaderProgramCompiler::CompileLayerProgram(const RuntimeRenderState& state,
|
||||
std::vector<ShaderPassBuildSource> passSources;
|
||||
std::string loadError;
|
||||
|
||||
if (!mRuntimeHost.BuildLayerPassFragmentShaderSources(state.layerId, passSources, loadError))
|
||||
if (!mRuntimeSnapshotProvider.BuildLayerPassFragmentShaderSources(state.layerId, passSources, loadError))
|
||||
{
|
||||
CopyErrorMessage(loadError, errorMessageSize, errorMessage);
|
||||
return false;
|
||||
@@ -117,7 +117,7 @@ bool ShaderProgramCompiler::CompilePreparedLayerProgram(const RuntimeRenderState
|
||||
passProgram.passId = passSource.passId;
|
||||
passProgram.inputNames = passSource.inputNames;
|
||||
passProgram.outputName = passSource.outputName;
|
||||
passProgram.shaderTextureBase = mTextureBindings.ResolveShaderTextureBase(state, mRuntimeHost.GetMaxTemporalHistoryFrames());
|
||||
passProgram.shaderTextureBase = mTextureBindings.ResolveShaderTextureBase(state, mRuntimeSnapshotProvider.GetMaxTemporalHistoryFrames());
|
||||
passProgram.textureBindings.swap(textureBindings);
|
||||
passProgram.textBindings.swap(textBindings);
|
||||
|
||||
@@ -125,7 +125,7 @@ bool ShaderProgramCompiler::CompilePreparedLayerProgram(const RuntimeRenderState
|
||||
if (globalParamsIndex != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(newProgram.get(), globalParamsIndex, kGlobalParamsBindingPoint);
|
||||
|
||||
const unsigned historyCap = mRuntimeHost.GetMaxTemporalHistoryFrames();
|
||||
const unsigned historyCap = mRuntimeSnapshotProvider.GetMaxTemporalHistoryFrames();
|
||||
glUseProgram(newProgram.get());
|
||||
mTextureBindings.AssignLayerSamplerUniforms(newProgram.get(), state, passProgram, historyCap);
|
||||
glUseProgram(0);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "RuntimeHost.h"
|
||||
#include "RuntimeSnapshotProvider.h"
|
||||
#include "ShaderTextureBindings.h"
|
||||
|
||||
#include <string>
|
||||
@@ -13,7 +13,7 @@ public:
|
||||
using LayerProgram = OpenGLRenderer::LayerProgram;
|
||||
using PassProgram = OpenGLRenderer::LayerProgram::PassProgram;
|
||||
|
||||
ShaderProgramCompiler(OpenGLRenderer& renderer, RuntimeHost& runtimeHost, ShaderTextureBindings& textureBindings);
|
||||
ShaderProgramCompiler(OpenGLRenderer& renderer, RuntimeSnapshotProvider& runtimeSnapshotProvider, ShaderTextureBindings& textureBindings);
|
||||
|
||||
bool CompileLayerProgram(const RuntimeRenderState& state, LayerProgram& layerProgram, int errorMessageSize, char* errorMessage);
|
||||
bool CompilePreparedLayerProgram(const RuntimeRenderState& state, const std::vector<ShaderPassBuildSource>& passSources, LayerProgram& layerProgram, int errorMessageSize, char* errorMessage);
|
||||
@@ -22,6 +22,6 @@ public:
|
||||
|
||||
private:
|
||||
OpenGLRenderer& mRenderer;
|
||||
RuntimeHost& mRuntimeHost;
|
||||
RuntimeSnapshotProvider& mRuntimeSnapshotProvider;
|
||||
ShaderTextureBindings& mTextureBindings;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "RuntimeCoordinator.h"
|
||||
|
||||
#include "RuntimeStore.h"
|
||||
|
||||
RuntimeCoordinator::RuntimeCoordinator(RuntimeStore& runtimeStore) :
|
||||
mRuntimeStore(runtimeStore)
|
||||
{
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::AddLayer(const std::string& shaderId)
|
||||
{
|
||||
std::string error;
|
||||
return ApplyStoreMutation(mRuntimeStore.CreateStoredLayer(shaderId, error), error, true, true);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::RemoveLayer(const std::string& layerId)
|
||||
{
|
||||
std::string error;
|
||||
return ApplyStoreMutation(mRuntimeStore.DeleteStoredLayer(layerId, error), error, true, true);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::MoveLayer(const std::string& layerId, int direction)
|
||||
{
|
||||
std::string error;
|
||||
return ApplyStoreMutation(mRuntimeStore.MoveStoredLayer(layerId, direction, error), error, true, true);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::MoveLayerToIndex(const std::string& layerId, std::size_t targetIndex)
|
||||
{
|
||||
std::string error;
|
||||
return ApplyStoreMutation(mRuntimeStore.MoveStoredLayerToIndex(layerId, targetIndex, error), error, true, true);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::SetLayerBypass(const std::string& layerId, bool bypassed)
|
||||
{
|
||||
std::string error;
|
||||
return ApplyStoreMutation(mRuntimeStore.SetStoredLayerBypassState(layerId, bypassed, error), error, true, false);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::SetLayerShader(const std::string& layerId, const std::string& shaderId)
|
||||
{
|
||||
std::string error;
|
||||
return ApplyStoreMutation(mRuntimeStore.SetStoredLayerShaderSelection(layerId, shaderId, error), error, true, false);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameter(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue)
|
||||
{
|
||||
std::string error;
|
||||
return ApplyStoreMutation(mRuntimeStore.SetStoredParameterValue(layerId, parameterId, newValue, error), error, false, false);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue)
|
||||
{
|
||||
std::string error;
|
||||
return ApplyStoreMutation(mRuntimeStore.SetStoredParameterValueByControlKey(layerKey, parameterKey, newValue, error), error, false, false);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::ResetLayerParameters(const std::string& layerId)
|
||||
{
|
||||
std::string error;
|
||||
RuntimeCoordinatorResult result = ApplyStoreMutation(mRuntimeStore.ResetStoredLayerParameterValues(layerId, error), error, false, false);
|
||||
if (!result.accepted)
|
||||
return result;
|
||||
|
||||
result.clearTransientOscState = true;
|
||||
result.renderResetScope = RuntimeCoordinatorRenderResetScope::TemporalHistoryAndFeedback;
|
||||
return result;
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::SaveStackPreset(const std::string& presetName)
|
||||
{
|
||||
std::string error;
|
||||
return ApplyStoreMutation(mRuntimeStore.SaveStackPresetSnapshot(presetName, error), error, false, false);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::LoadStackPreset(const std::string& presetName)
|
||||
{
|
||||
std::string error;
|
||||
return ApplyStoreMutation(mRuntimeStore.LoadStackPresetSnapshot(presetName, error), error, true, false);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::RequestShaderReload(bool preserveFeedbackState)
|
||||
{
|
||||
return BuildQueuedReloadResult(preserveFeedbackState);
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::HandleRuntimePollFailure(const std::string& error)
|
||||
{
|
||||
RuntimeCoordinatorResult result;
|
||||
result.accepted = true;
|
||||
result.runtimeStateBroadcastRequired = true;
|
||||
result.compileStatusChanged = true;
|
||||
result.compileStatusSucceeded = false;
|
||||
result.compileStatusMessage = error;
|
||||
return result;
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildFailure(const std::string& error)
|
||||
{
|
||||
mPreserveFeedbackOnNextShaderBuild = false;
|
||||
|
||||
RuntimeCoordinatorResult result;
|
||||
result.accepted = true;
|
||||
result.runtimeStateBroadcastRequired = true;
|
||||
result.compileStatusChanged = true;
|
||||
result.compileStatusSucceeded = false;
|
||||
result.compileStatusMessage = error;
|
||||
result.committedStateMode = RuntimeCoordinatorCommittedStateMode::UseCommittedStates;
|
||||
return result;
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::HandlePreparedShaderBuildSuccess()
|
||||
{
|
||||
RuntimeCoordinatorResult result;
|
||||
result.accepted = true;
|
||||
result.runtimeStateBroadcastRequired = true;
|
||||
result.compileStatusChanged = true;
|
||||
result.compileStatusSucceeded = true;
|
||||
result.compileStatusMessage = "Shader layers compiled successfully.";
|
||||
result.committedStateMode = RuntimeCoordinatorCommittedStateMode::UseLiveSnapshots;
|
||||
mPreserveFeedbackOnNextShaderBuild = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::HandleRuntimeReloadRequest()
|
||||
{
|
||||
return BuildQueuedReloadResult(false);
|
||||
}
|
||||
|
||||
bool RuntimeCoordinator::PreserveFeedbackOnNextShaderBuild() const
|
||||
{
|
||||
return mPreserveFeedbackOnNextShaderBuild;
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::ApplyStoreMutation(bool succeeded, const std::string& errorMessage, bool reloadRequired, bool preserveFeedbackState)
|
||||
{
|
||||
if (!succeeded)
|
||||
{
|
||||
RuntimeCoordinatorResult result;
|
||||
result.accepted = false;
|
||||
result.errorMessage = errorMessage;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (reloadRequired)
|
||||
return BuildQueuedReloadResult(preserveFeedbackState);
|
||||
|
||||
return BuildAcceptedNoReloadResult();
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::BuildQueuedReloadResult(bool preserveFeedbackState)
|
||||
{
|
||||
mPreserveFeedbackOnNextShaderBuild = preserveFeedbackState;
|
||||
|
||||
RuntimeCoordinatorResult result;
|
||||
result.accepted = true;
|
||||
result.runtimeStateBroadcastRequired = true;
|
||||
result.shaderBuildRequested = true;
|
||||
result.compileStatusChanged = true;
|
||||
result.compileStatusSucceeded = true;
|
||||
result.compileStatusMessage = "Shader rebuild queued.";
|
||||
result.clearReloadRequest = true;
|
||||
result.committedStateMode = RuntimeCoordinatorCommittedStateMode::UseCommittedStates;
|
||||
return result;
|
||||
}
|
||||
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::BuildAcceptedNoReloadResult() const
|
||||
{
|
||||
RuntimeCoordinatorResult result;
|
||||
result.accepted = true;
|
||||
result.runtimeStateBroadcastRequired = true;
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include "RuntimeJson.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
class RuntimeStore;
|
||||
|
||||
enum class RuntimeCoordinatorCommittedStateMode
|
||||
{
|
||||
Unchanged,
|
||||
UseCommittedStates,
|
||||
UseLiveSnapshots
|
||||
};
|
||||
|
||||
enum class RuntimeCoordinatorRenderResetScope
|
||||
{
|
||||
None,
|
||||
TemporalHistoryOnly,
|
||||
TemporalHistoryAndFeedback
|
||||
};
|
||||
|
||||
struct RuntimeCoordinatorResult
|
||||
{
|
||||
bool accepted = false;
|
||||
bool runtimeStateBroadcastRequired = false;
|
||||
bool shaderBuildRequested = false;
|
||||
bool clearTransientOscState = false;
|
||||
bool compileStatusChanged = false;
|
||||
bool compileStatusSucceeded = false;
|
||||
bool clearReloadRequest = false;
|
||||
RuntimeCoordinatorCommittedStateMode committedStateMode = RuntimeCoordinatorCommittedStateMode::Unchanged;
|
||||
RuntimeCoordinatorRenderResetScope renderResetScope = RuntimeCoordinatorRenderResetScope::None;
|
||||
std::string compileStatusMessage;
|
||||
std::string errorMessage;
|
||||
};
|
||||
|
||||
class RuntimeCoordinator
|
||||
{
|
||||
public:
|
||||
explicit RuntimeCoordinator(RuntimeStore& runtimeStore);
|
||||
|
||||
RuntimeCoordinatorResult AddLayer(const std::string& shaderId);
|
||||
RuntimeCoordinatorResult RemoveLayer(const std::string& layerId);
|
||||
RuntimeCoordinatorResult MoveLayer(const std::string& layerId, int direction);
|
||||
RuntimeCoordinatorResult MoveLayerToIndex(const std::string& layerId, std::size_t targetIndex);
|
||||
RuntimeCoordinatorResult SetLayerBypass(const std::string& layerId, bool bypassed);
|
||||
RuntimeCoordinatorResult SetLayerShader(const std::string& layerId, const std::string& shaderId);
|
||||
RuntimeCoordinatorResult UpdateLayerParameter(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue);
|
||||
RuntimeCoordinatorResult UpdateLayerParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue);
|
||||
RuntimeCoordinatorResult ResetLayerParameters(const std::string& layerId);
|
||||
RuntimeCoordinatorResult SaveStackPreset(const std::string& presetName);
|
||||
RuntimeCoordinatorResult LoadStackPreset(const std::string& presetName);
|
||||
|
||||
RuntimeCoordinatorResult RequestShaderReload(bool preserveFeedbackState = false);
|
||||
RuntimeCoordinatorResult HandleRuntimePollFailure(const std::string& error);
|
||||
RuntimeCoordinatorResult HandlePreparedShaderBuildFailure(const std::string& error);
|
||||
RuntimeCoordinatorResult HandlePreparedShaderBuildSuccess();
|
||||
RuntimeCoordinatorResult HandleRuntimeReloadRequest();
|
||||
bool PreserveFeedbackOnNextShaderBuild() const;
|
||||
|
||||
private:
|
||||
RuntimeCoordinatorResult ApplyStoreMutation(bool succeeded, const std::string& errorMessage, bool reloadRequired, bool preserveFeedbackState);
|
||||
RuntimeCoordinatorResult BuildQueuedReloadResult(bool preserveFeedbackState);
|
||||
RuntimeCoordinatorResult BuildAcceptedNoReloadResult() const;
|
||||
|
||||
RuntimeStore& mRuntimeStore;
|
||||
bool mPreserveFeedbackOnNextShaderBuild = false;
|
||||
};
|
||||
@@ -12,6 +12,11 @@ bool RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources(const std::str
|
||||
return mRuntimeHost.BuildLayerPassFragmentShaderSources(layerId, passSources, error);
|
||||
}
|
||||
|
||||
unsigned RuntimeSnapshotProvider::GetMaxTemporalHistoryFrames() const
|
||||
{
|
||||
return mRuntimeHost.GetMaxTemporalHistoryFrames();
|
||||
}
|
||||
|
||||
RuntimeSnapshotVersions RuntimeSnapshotProvider::GetVersions() const
|
||||
{
|
||||
RuntimeSnapshotVersions versions;
|
||||
@@ -35,6 +40,16 @@ RuntimeRenderFrameContext RuntimeSnapshotProvider::GetFrameContext() const
|
||||
return frameContext;
|
||||
}
|
||||
|
||||
void RuntimeSnapshotProvider::AdvanceFrame()
|
||||
{
|
||||
mRuntimeHost.AdvanceFrame();
|
||||
}
|
||||
|
||||
bool RuntimeSnapshotProvider::TryAdvanceFrame()
|
||||
{
|
||||
return mRuntimeHost.TryAdvanceFrame();
|
||||
}
|
||||
|
||||
RuntimeRenderStateSnapshot RuntimeSnapshotProvider::GetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const
|
||||
{
|
||||
for (;;)
|
||||
|
||||
@@ -35,8 +35,11 @@ public:
|
||||
explicit RuntimeSnapshotProvider(RuntimeHost& runtimeHost);
|
||||
|
||||
bool BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error) const;
|
||||
unsigned GetMaxTemporalHistoryFrames() const;
|
||||
RuntimeSnapshotVersions GetVersions() const;
|
||||
RuntimeRenderFrameContext GetFrameContext() const;
|
||||
void AdvanceFrame();
|
||||
bool TryAdvanceFrame();
|
||||
RuntimeRenderStateSnapshot GetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const;
|
||||
bool TryGetRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const;
|
||||
bool TryRefreshSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const;
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
|
||||
#include "DeckLinkSession.h"
|
||||
#include "OpenGLVideoIOBridge.h"
|
||||
#include "RenderEngine.h"
|
||||
#include "HealthTelemetry.h"
|
||||
#include "RenderEngine.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
VideoBackend::VideoBackend(RenderEngine& renderEngine, HealthTelemetry& healthTelemetry) :
|
||||
mHealthTelemetry(healthTelemetry),
|
||||
mVideoIODevice(std::make_unique<DeckLinkSession>()),
|
||||
mBridge(std::make_unique<OpenGLVideoIOBridge>(*mVideoIODevice, renderEngine, healthTelemetry))
|
||||
mBridge(std::make_unique<OpenGLVideoIOBridge>(renderEngine))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,7 +38,7 @@ bool VideoBackend::SelectPreferredFormats(const VideoFormatSelection& videoModes
|
||||
bool VideoBackend::ConfigureInput(const VideoFormat& inputVideoMode, std::string& error)
|
||||
{
|
||||
return mVideoIODevice->ConfigureInput(
|
||||
[this](const VideoIOFrame& frame) { mBridge->VideoFrameArrived(frame); },
|
||||
[this](const VideoIOFrame& frame) { HandleInputFrame(frame); },
|
||||
inputVideoMode,
|
||||
error);
|
||||
}
|
||||
@@ -43,7 +46,7 @@ bool VideoBackend::ConfigureInput(const VideoFormat& inputVideoMode, std::string
|
||||
bool VideoBackend::ConfigureOutput(const VideoFormat& outputVideoMode, bool externalKeyingEnabled, std::string& error)
|
||||
{
|
||||
return mVideoIODevice->ConfigureOutput(
|
||||
[this](const VideoIOCompletion& completion) { mBridge->PlayoutFrameCompleted(completion); },
|
||||
[this](const VideoIOCompletion& completion) { HandleOutputFrameCompletion(completion); },
|
||||
outputVideoMode,
|
||||
externalKeyingEnabled,
|
||||
error);
|
||||
@@ -173,3 +176,63 @@ void VideoBackend::SetStatusMessage(const std::string& message)
|
||||
{
|
||||
mVideoIODevice->SetStatusMessage(message);
|
||||
}
|
||||
|
||||
void VideoBackend::HandleInputFrame(const VideoIOFrame& frame)
|
||||
{
|
||||
const VideoIOState& state = mVideoIODevice->State();
|
||||
mHealthTelemetry.TryReportSignalStatus(!frame.hasNoInputSource, state.inputFrameSize.width, state.inputFrameSize.height, state.inputDisplayModeName);
|
||||
|
||||
if (mBridge)
|
||||
mBridge->UploadInputFrame(frame, state);
|
||||
}
|
||||
|
||||
void VideoBackend::HandleOutputFrameCompletion(const VideoIOCompletion& completion)
|
||||
{
|
||||
RecordFramePacing(completion.result);
|
||||
|
||||
VideoIOOutputFrame outputFrame;
|
||||
if (!BeginOutputFrame(outputFrame))
|
||||
return;
|
||||
|
||||
const VideoIOState& state = mVideoIODevice->State();
|
||||
if (mBridge)
|
||||
mBridge->RenderScheduledFrame(state, completion, outputFrame);
|
||||
|
||||
EndOutputFrame(outputFrame);
|
||||
AccountForCompletionResult(completion.result);
|
||||
|
||||
// Schedule the next frame after render work is complete so device-side
|
||||
// bookkeeping stays with the backend seam and the bridge stays render-only.
|
||||
ScheduleOutputFrame(outputFrame);
|
||||
}
|
||||
|
||||
void VideoBackend::RecordFramePacing(VideoIOCompletionResult completionResult)
|
||||
{
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (mLastPlayoutCompletionTime != std::chrono::steady_clock::time_point())
|
||||
{
|
||||
mCompletionIntervalMilliseconds = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(now - mLastPlayoutCompletionTime).count();
|
||||
if (mSmoothedCompletionIntervalMilliseconds <= 0.0)
|
||||
mSmoothedCompletionIntervalMilliseconds = mCompletionIntervalMilliseconds;
|
||||
else
|
||||
mSmoothedCompletionIntervalMilliseconds = mSmoothedCompletionIntervalMilliseconds * 0.9 + mCompletionIntervalMilliseconds * 0.1;
|
||||
if (mCompletionIntervalMilliseconds > mMaxCompletionIntervalMilliseconds)
|
||||
mMaxCompletionIntervalMilliseconds = mCompletionIntervalMilliseconds;
|
||||
}
|
||||
mLastPlayoutCompletionTime = now;
|
||||
|
||||
if (completionResult == VideoIOCompletionResult::DisplayedLate)
|
||||
++mLateFrameCount;
|
||||
else if (completionResult == VideoIOCompletionResult::Dropped)
|
||||
++mDroppedFrameCount;
|
||||
else if (completionResult == VideoIOCompletionResult::Flushed)
|
||||
++mFlushedFrameCount;
|
||||
|
||||
mHealthTelemetry.TryRecordFramePacingStats(
|
||||
mCompletionIntervalMilliseconds,
|
||||
mSmoothedCompletionIntervalMilliseconds,
|
||||
mMaxCompletionIntervalMilliseconds,
|
||||
mLateFrameCount,
|
||||
mDroppedFrameCount,
|
||||
mFlushedFrameCount);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "VideoIOTypes.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -50,6 +52,18 @@ public:
|
||||
void SetStatusMessage(const std::string& message);
|
||||
|
||||
private:
|
||||
void HandleInputFrame(const VideoIOFrame& frame);
|
||||
void HandleOutputFrameCompletion(const VideoIOCompletion& completion);
|
||||
void RecordFramePacing(VideoIOCompletionResult completionResult);
|
||||
|
||||
HealthTelemetry& mHealthTelemetry;
|
||||
std::unique_ptr<VideoIODevice> mVideoIODevice;
|
||||
std::unique_ptr<OpenGLVideoIOBridge> mBridge;
|
||||
std::chrono::steady_clock::time_point mLastPlayoutCompletionTime;
|
||||
double mCompletionIntervalMilliseconds = 0.0;
|
||||
double mSmoothedCompletionIntervalMilliseconds = 0.0;
|
||||
double mMaxCompletionIntervalMilliseconds = 0.0;
|
||||
uint64_t mLateFrameCount = 0;
|
||||
uint64_t mDroppedFrameCount = 0;
|
||||
uint64_t mFlushedFrameCount = 0;
|
||||
};
|
||||
|
||||
@@ -417,11 +417,21 @@ double DeckLinkSession::FrameBudgetMilliseconds() const
|
||||
return mScheduler.FrameBudgetMilliseconds();
|
||||
}
|
||||
|
||||
bool DeckLinkSession::BeginOutputFrame(VideoIOOutputFrame& frame)
|
||||
bool DeckLinkSession::AcquireNextOutputVideoFrame(CComPtr<IDeckLinkMutableVideoFrame>& outputVideoFrame)
|
||||
{
|
||||
CComPtr<IDeckLinkMutableVideoFrame> outputVideoFrame = outputVideoFrameQueue.front();
|
||||
if (outputVideoFrameQueue.empty())
|
||||
return false;
|
||||
|
||||
outputVideoFrame = outputVideoFrameQueue.front();
|
||||
outputVideoFrameQueue.push_back(outputVideoFrame);
|
||||
outputVideoFrameQueue.pop_front();
|
||||
return outputVideoFrame != nullptr;
|
||||
}
|
||||
|
||||
bool DeckLinkSession::PopulateOutputFrame(IDeckLinkMutableVideoFrame* outputVideoFrame, VideoIOOutputFrame& frame)
|
||||
{
|
||||
if (outputVideoFrame == nullptr)
|
||||
return false;
|
||||
|
||||
CComPtr<IDeckLinkVideoBuffer> outputVideoFrameBuffer;
|
||||
if (outputVideoFrame->QueryInterface(IID_IDeckLinkVideoBuffer, (void**)&outputVideoFrameBuffer) != S_OK)
|
||||
@@ -438,11 +448,44 @@ bool DeckLinkSession::BeginOutputFrame(VideoIOOutputFrame& frame)
|
||||
frame.width = mState.outputFrameSize.width;
|
||||
frame.height = mState.outputFrameSize.height;
|
||||
frame.pixelFormat = mState.outputPixelFormat;
|
||||
frame.nativeFrame = outputVideoFrame.p;
|
||||
frame.nativeFrame = outputVideoFrame;
|
||||
frame.nativeBuffer = outputVideoFrameBuffer.Detach();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeckLinkSession::ScheduleFrame(IDeckLinkMutableVideoFrame* outputVideoFrame)
|
||||
{
|
||||
const VideoIOScheduleTime scheduleTime = mScheduler.NextScheduleTime();
|
||||
return outputVideoFrame != nullptr &&
|
||||
output->ScheduleVideoFrame(outputVideoFrame, scheduleTime.streamTime, scheduleTime.duration, scheduleTime.timeScale) == S_OK;
|
||||
}
|
||||
|
||||
bool DeckLinkSession::ScheduleBlackFrame(IDeckLinkMutableVideoFrame* outputVideoFrame)
|
||||
{
|
||||
if (outputVideoFrame == nullptr)
|
||||
return false;
|
||||
|
||||
CComPtr<IDeckLinkVideoBuffer> outputVideoFrameBuffer;
|
||||
if (outputVideoFrame->QueryInterface(IID_IDeckLinkVideoBuffer, (void**)&outputVideoFrameBuffer) != S_OK)
|
||||
return false;
|
||||
|
||||
if (outputVideoFrameBuffer->StartAccess(bmdBufferAccessWrite) != S_OK)
|
||||
return false;
|
||||
|
||||
void* pFrame = nullptr;
|
||||
outputVideoFrameBuffer->GetBytes((void**)&pFrame);
|
||||
memset(pFrame, 0, outputVideoFrame->GetRowBytes() * mState.outputFrameSize.height);
|
||||
|
||||
outputVideoFrameBuffer->EndAccess(bmdBufferAccessWrite);
|
||||
return ScheduleFrame(outputVideoFrame);
|
||||
}
|
||||
|
||||
bool DeckLinkSession::BeginOutputFrame(VideoIOOutputFrame& frame)
|
||||
{
|
||||
CComPtr<IDeckLinkMutableVideoFrame> outputVideoFrame;
|
||||
return AcquireNextOutputVideoFrame(outputVideoFrame) && PopulateOutputFrame(outputVideoFrame, frame);
|
||||
}
|
||||
|
||||
void DeckLinkSession::EndOutputFrame(VideoIOOutputFrame& frame)
|
||||
{
|
||||
IDeckLinkVideoBuffer* outputVideoFrameBuffer = static_cast<IDeckLinkVideoBuffer*>(frame.nativeBuffer);
|
||||
@@ -463,11 +506,7 @@ void DeckLinkSession::AccountForCompletionResult(VideoIOCompletionResult complet
|
||||
bool DeckLinkSession::ScheduleOutputFrame(const VideoIOOutputFrame& frame)
|
||||
{
|
||||
IDeckLinkMutableVideoFrame* outputVideoFrame = static_cast<IDeckLinkMutableVideoFrame*>(frame.nativeFrame);
|
||||
const VideoIOScheduleTime scheduleTime = mScheduler.NextScheduleTime();
|
||||
if (outputVideoFrame == nullptr || output->ScheduleVideoFrame(outputVideoFrame, scheduleTime.streamTime, scheduleTime.duration, scheduleTime.timeScale) != S_OK)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return ScheduleFrame(outputVideoFrame);
|
||||
}
|
||||
|
||||
bool DeckLinkSession::Start()
|
||||
@@ -486,31 +525,13 @@ bool DeckLinkSession::Start()
|
||||
|
||||
for (unsigned i = 0; i < kPrerollFrameCount; i++)
|
||||
{
|
||||
CComPtr<IDeckLinkMutableVideoFrame> outputVideoFrame = outputVideoFrameQueue.front();
|
||||
outputVideoFrameQueue.push_back(outputVideoFrame);
|
||||
outputVideoFrameQueue.pop_front();
|
||||
|
||||
CComPtr<IDeckLinkVideoBuffer> outputVideoFrameBuffer;
|
||||
if (outputVideoFrame->QueryInterface(IID_IDeckLinkVideoBuffer, (void**)&outputVideoFrameBuffer) != S_OK)
|
||||
CComPtr<IDeckLinkMutableVideoFrame> outputVideoFrame;
|
||||
if (!AcquireNextOutputVideoFrame(outputVideoFrame))
|
||||
{
|
||||
MessageBoxA(NULL, "Could not query the preroll output frame buffer.", "DeckLink start failed", MB_OK | MB_ICONERROR);
|
||||
MessageBoxA(NULL, "Could not acquire a preroll output frame.", "DeckLink start failed", MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outputVideoFrameBuffer->StartAccess(bmdBufferAccessWrite) != S_OK)
|
||||
{
|
||||
MessageBoxA(NULL, "Could not write to the preroll output frame buffer.", "DeckLink start failed", MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
void* pFrame = nullptr;
|
||||
outputVideoFrameBuffer->GetBytes((void**)&pFrame);
|
||||
memset(pFrame, 0, outputVideoFrame->GetRowBytes() * mState.outputFrameSize.height);
|
||||
|
||||
outputVideoFrameBuffer->EndAccess(bmdBufferAccessWrite);
|
||||
|
||||
const VideoIOScheduleTime scheduleTime = mScheduler.NextScheduleTime();
|
||||
if (output->ScheduleVideoFrame(outputVideoFrame, scheduleTime.streamTime, scheduleTime.duration, scheduleTime.timeScale) != S_OK)
|
||||
if (!ScheduleBlackFrame(outputVideoFrame))
|
||||
{
|
||||
MessageBoxA(NULL, "Could not schedule a preroll output frame.", "DeckLink start failed", MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
@@ -599,23 +620,23 @@ void DeckLinkSession::HandlePlayoutFrameCompleted(IDeckLinkVideoFrame*, BMDOutpu
|
||||
return;
|
||||
|
||||
VideoIOCompletion completion;
|
||||
completion.result = TranslateCompletionResult(completionResult);
|
||||
mOutputFrameCallback(completion);
|
||||
}
|
||||
|
||||
VideoIOCompletionResult DeckLinkSession::TranslateCompletionResult(BMDOutputFrameCompletionResult completionResult)
|
||||
{
|
||||
switch (completionResult)
|
||||
{
|
||||
case bmdOutputFrameDisplayedLate:
|
||||
completion.result = VideoIOCompletionResult::DisplayedLate;
|
||||
break;
|
||||
return VideoIOCompletionResult::DisplayedLate;
|
||||
case bmdOutputFrameDropped:
|
||||
completion.result = VideoIOCompletionResult::Dropped;
|
||||
break;
|
||||
return VideoIOCompletionResult::Dropped;
|
||||
case bmdOutputFrameFlushed:
|
||||
completion.result = VideoIOCompletionResult::Flushed;
|
||||
break;
|
||||
return VideoIOCompletionResult::Flushed;
|
||||
case bmdOutputFrameCompleted:
|
||||
completion.result = VideoIOCompletionResult::Completed;
|
||||
break;
|
||||
return VideoIOCompletionResult::Completed;
|
||||
default:
|
||||
completion.result = VideoIOCompletionResult::Unknown;
|
||||
break;
|
||||
return VideoIOCompletionResult::Unknown;
|
||||
}
|
||||
mOutputFrameCallback(completion);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,12 @@ public:
|
||||
void HandlePlayoutFrameCompleted(IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult completionResult);
|
||||
|
||||
private:
|
||||
bool AcquireNextOutputVideoFrame(CComPtr<IDeckLinkMutableVideoFrame>& outputVideoFrame);
|
||||
bool PopulateOutputFrame(IDeckLinkMutableVideoFrame* outputVideoFrame, VideoIOOutputFrame& frame);
|
||||
bool ScheduleFrame(IDeckLinkMutableVideoFrame* outputVideoFrame);
|
||||
bool ScheduleBlackFrame(IDeckLinkMutableVideoFrame* outputVideoFrame);
|
||||
static VideoIOCompletionResult TranslateCompletionResult(BMDOutputFrameCompletionResult completionResult);
|
||||
|
||||
CComPtr<CaptureDelegate> captureDelegate;
|
||||
CComPtr<PlayoutDelegate> playoutDelegate;
|
||||
CComPtr<IDeckLinkInput> input;
|
||||
|
||||
Reference in New Issue
Block a user