Remove D3D9 related files.
Cf. issue 6167 for a list of shortcomings that made us decide on removing the backend.
This commit is contained in:
parent
6bdcde9dd6
commit
0d4df39e1f
|
@ -374,9 +374,6 @@ xcopy "$(SolutionDir)..\Externals\msvcrt\$(PlatformName)\*.dll" "$(TargetDir)" /
|
|||
<ProjectReference Include="..\..\Plugins\Plugin_VideoDX11\Plugin_VideoDX11.vcxproj">
|
||||
<Project>{9a4c733c-bade-4ac6-b58a-6e274395e90e}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Plugins\Plugin_VideoDX9\Plugin_VideoDX9.vcxproj">
|
||||
<Project>{dc7d7af4-ce47-49e8-8b63-265cb6233a49}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Plugins\Plugin_VideoOGL\Plugin_VideoOGL.vcxproj">
|
||||
<Project>{1909cd2d-1707-456f-86ca-0df42a727c99}</Project>
|
||||
</ProjectReference>
|
||||
|
@ -408,4 +405,4 @@ xcopy "$(SolutionDir)..\Externals\msvcrt\$(PlatformName)\*.dll" "$(TargetDir)" /
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
// TODO: ugly
|
||||
#ifdef _WIN32
|
||||
#include "../../../Plugins/Plugin_VideoDX9/Src/VideoBackend.h"
|
||||
#include "../../../Plugins/Plugin_VideoDX11/Src/VideoBackend.h"
|
||||
#endif
|
||||
#if !defined(USE_GLES) || USE_GLES3
|
||||
|
@ -43,7 +42,6 @@ void VideoBackend::PopulateList()
|
|||
|
||||
// D3D11 > OGL > D3D9 > SW
|
||||
#ifdef _WIN32
|
||||
g_available_video_backends.push_back(backends[2] = new DX9::VideoBackend);
|
||||
if (IsGteVista())
|
||||
g_available_video_backends.push_back(backends[0] = new DX11::VideoBackend);
|
||||
#endif
|
||||
|
|
|
@ -64,12 +64,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DiscIO", "Core\DiscIO\DiscI
|
|||
{3E1339F5-9311-4122-9442-369702E8FCAD} = {3E1339F5-9311-4122-9442-369702E8FCAD}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoDX9", "Plugins\Plugin_VideoDX9\Plugin_VideoDX9.vcxproj", "{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{3E5C4E02-1BA9-4776-BDBE-E3F91FFA34CF} = {3E5C4E02-1BA9-4776-BDBE-E3F91FFA34CF}
|
||||
{1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE} = {1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoDX11", "Plugins\Plugin_VideoDX11\Plugin_VideoDX11.vcxproj", "{9A4C733C-BADE-4AC6-B58A-6E274395E90E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{3E5C4E02-1BA9-4776-BDBE-E3F91FFA34CF} = {3E5C4E02-1BA9-4776-BDBE-E3F91FFA34CF}
|
||||
|
@ -278,18 +272,6 @@ Global
|
|||
{B6398059-EBB6-4C34-B547-95F365B71FF4}.Release|Win32.Build.0 = Release|Win32
|
||||
{B6398059-EBB6-4C34-B547-95F365B71FF4}.Release|x64.ActiveCfg = Release|x64
|
||||
{B6398059-EBB6-4C34-B547-95F365B71FF4}.Release|x64.Build.0 = Release|x64
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.Debug|x64.Build.0 = Debug|x64
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.DebugFast|Win32.Build.0 = DebugFast|Win32
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.DebugFast|x64.Build.0 = DebugFast|x64
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.Release|Win32.Build.0 = Release|Win32
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.Release|x64.ActiveCfg = Release|x64
|
||||
{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}.Release|x64.Build.0 = Release|x64
|
||||
{9A4C733C-BADE-4AC6-B58A-6E274395E90E}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9A4C733C-BADE-4AC6-B58A-6E274395E90E}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9A4C733C-BADE-4AC6-B58A-6E274395E90E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
|
|
|
@ -1,239 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="DebugFast|Win32">
|
||||
<Configuration>DebugFast</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="DebugFast|x64">
|
||||
<Configuration>DebugFast</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{DC7D7AF4-CE47-49E8-8B63-265CB6233A49}</ProjectGuid>
|
||||
<RootNamespace>Plugin_VideoDX9</RootNamespace>
|
||||
<ProjectName>VideoDX9</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\PrecompiledHeader.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_Debug.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\PrecompiledHeader.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_Debug.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_Release.props" />
|
||||
<Import Project="..\..\VSProps\PrecompiledHeader.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_DebugFast.props" />
|
||||
<Import Project="..\..\VSProps\PrecompiledHeader.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_Release.props" />
|
||||
<Import Project="..\..\VSProps\PrecompiledHeader.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
<Import Project="..\..\VSProps\CodeGen_DebugFast.props" />
|
||||
<Import Project="..\..\VSProps\PrecompiledHeader.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(PlatformName)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<TargetName>$(ProjectName)D</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ForcedIncludeFiles>stdafx.h</ForcedIncludeFiles>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\VideoCommon\VideoCommon.vcxproj">
|
||||
<Project>{3e5c4e02-1ba9-4776-bdbe-e3f91ffa34cf}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\D3DBase.cpp" />
|
||||
<ClCompile Include="Src\D3DShader.cpp" />
|
||||
<ClCompile Include="Src\D3DTexture.cpp" />
|
||||
<ClCompile Include="Src\D3DUtil.cpp" />
|
||||
<ClCompile Include="Src\FramebufferManager.cpp" />
|
||||
<ClCompile Include="Src\main.cpp" />
|
||||
<ClCompile Include="Src\NativeVertexFormat.cpp" />
|
||||
<ClCompile Include="Src\PerfQuery.cpp" />
|
||||
<ClCompile Include="Src\PixelShaderCache.cpp" />
|
||||
<ClCompile Include="Src\Render.cpp" />
|
||||
<ClCompile Include="Src\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)'=='DebugFast|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\TextureCache.cpp" />
|
||||
<ClCompile Include="Src\TextureConverter.cpp" />
|
||||
<ClCompile Include="Src\VertexManager.cpp" />
|
||||
<ClCompile Include="Src\VertexShaderCache.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Src\D3DBase.h" />
|
||||
<ClInclude Include="Src\D3DShader.h" />
|
||||
<ClInclude Include="Src\D3DTexture.h" />
|
||||
<ClInclude Include="Src\D3DUtil.h" />
|
||||
<ClInclude Include="Src\FramebufferManager.h" />
|
||||
<ClInclude Include="Src\Globals.h" />
|
||||
<ClInclude Include="Src\main.h" />
|
||||
<ClInclude Include="Src\PerfQuery.h" />
|
||||
<ClInclude Include="Src\PixelShaderCache.h" />
|
||||
<ClInclude Include="Src\Render.h" />
|
||||
<ClInclude Include="Src\stdafx.h" />
|
||||
<ClInclude Include="Src\TextureCache.h" />
|
||||
<ClInclude Include="Src\TextureConverter.h" />
|
||||
<ClInclude Include="Src\VertexManager.h" />
|
||||
<ClInclude Include="Src\VertexShaderCache.h" />
|
||||
<ClInclude Include="Src\VideoBackend.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,96 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\main.cpp" />
|
||||
<ClCompile Include="Src\stdafx.cpp" />
|
||||
<ClCompile Include="Src\FramebufferManager.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\NativeVertexFormat.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\PixelShaderCache.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\Render.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\TextureCache.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\VertexManager.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\VertexShaderCache.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\D3DBase.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\D3DUtil.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\D3DShader.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\D3DTexture.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\TextureConverter.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\PerfQuery.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Src\Globals.h" />
|
||||
<ClInclude Include="Src\main.h" />
|
||||
<ClInclude Include="Src\stdafx.h" />
|
||||
<ClInclude Include="Src\VideoBackend.h" />
|
||||
<ClInclude Include="Src\FramebufferManager.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\PixelShaderCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\Render.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\TextureCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\VertexManager.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\VertexShaderCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\D3DBase.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\D3DShader.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\D3DTexture.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\D3DUtil.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\TextureConverter.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\PerfQuery.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="D3D">
|
||||
<UniqueIdentifier>{7acd5e48-186b-4788-ab0a-3551205635f8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Render">
|
||||
<UniqueIdentifier>{46f1aa47-0eaf-4c32-bdbb-f61c587cd233}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,955 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "Render.h"
|
||||
#include "XFStructs.h"
|
||||
#include "StringUtil.h"
|
||||
#include "VideoCommon.h"
|
||||
|
||||
D3DXSAVESURFACETOFILEATYPE PD3DXSaveSurfaceToFileA = NULL;
|
||||
D3DXSAVETEXTURETOFILEATYPE PD3DXSaveTextureToFileA = NULL;
|
||||
D3DXCOMPILESHADERTYPE PD3DXCompileShader = NULL;
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
static char vsVersions[5][7] = {"ERROR", "vs_1_4", "vs_2_a", "vs_3_0", "vs_4_0"};
|
||||
static char psVersions[5][7] = {"ERROR", "ps_1_4", "ps_2_a", "ps_3_0", "ps_4_0"};
|
||||
// D3DX
|
||||
HINSTANCE hD3DXDll = NULL;
|
||||
int d3dx_dll_ref = 0;
|
||||
|
||||
typedef IDirect3D9* (WINAPI* DIRECT3DCREATE9)(UINT);
|
||||
DIRECT3DCREATE9 PDirect3DCreate9 = NULL;
|
||||
HINSTANCE hD3DDll = NULL;
|
||||
int d3d_dll_ref = 0;
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
LPDIRECT3D9 D3D = NULL; // Used to create the D3DDevice
|
||||
LPDIRECT3DDEVICE9 dev = NULL; // Our rendering device
|
||||
LPDIRECT3DSURFACE9 back_buffer;
|
||||
LPDIRECT3DSURFACE9 back_buffer_z;
|
||||
D3DCAPS9 caps;
|
||||
HWND hWnd;
|
||||
|
||||
static int multisample;
|
||||
static int resolution;
|
||||
static int xres, yres;
|
||||
static bool auto_depth_stencil = false;
|
||||
|
||||
#define VENDOR_NVIDIA 4318
|
||||
#define VENDOR_ATI 4098
|
||||
#define VENDOR_INTEL 32902
|
||||
|
||||
bool bFrameInProgress = false;
|
||||
|
||||
#define MAX_ADAPTERS 4
|
||||
static Adapter adapters[MAX_ADAPTERS];
|
||||
static int numAdapters;
|
||||
static int cur_adapter;
|
||||
|
||||
// Value caches for state filtering
|
||||
const int MaxStreamSources = 16;
|
||||
const int MaxTextureStages = 9;
|
||||
const int MaxRenderStates = 210 + 46;
|
||||
const int MaxTextureTypes = 33;
|
||||
const int MaxSamplerSize = 13;
|
||||
const int MaxSamplerTypes = 15;
|
||||
static bool m_RenderStatesSet[MaxRenderStates];
|
||||
static DWORD m_RenderStates[MaxRenderStates];
|
||||
static bool m_RenderStatesChanged[MaxRenderStates];
|
||||
|
||||
static DWORD m_TextureStageStates[MaxTextureStages][MaxTextureTypes];
|
||||
static bool m_TextureStageStatesSet[MaxTextureStages][MaxTextureTypes];
|
||||
static bool m_TextureStageStatesChanged[MaxTextureStages][MaxTextureTypes];
|
||||
|
||||
static DWORD m_SamplerStates[MaxSamplerSize][MaxSamplerTypes];
|
||||
static bool m_SamplerStatesSet[MaxSamplerSize][MaxSamplerTypes];
|
||||
static bool m_SamplerStatesChanged[MaxSamplerSize][MaxSamplerTypes];
|
||||
|
||||
static LPDIRECT3DBASETEXTURE9 m_Textures[16];
|
||||
static LPDIRECT3DVERTEXDECLARATION9 m_VtxDecl;
|
||||
static bool m_VtxDeclChanged;
|
||||
static LPDIRECT3DPIXELSHADER9 m_PixelShader;
|
||||
static bool m_PixelShaderChanged;
|
||||
static LPDIRECT3DVERTEXSHADER9 m_VertexShader;
|
||||
static bool m_VertexShaderChanged;
|
||||
struct StreamSourceDescriptor
|
||||
{
|
||||
LPDIRECT3DVERTEXBUFFER9 pStreamData;
|
||||
UINT OffsetInBytes;
|
||||
UINT Stride;
|
||||
};
|
||||
static StreamSourceDescriptor m_stream_sources[MaxStreamSources];
|
||||
static bool m_stream_sources_Changed[MaxStreamSources];
|
||||
static LPDIRECT3DINDEXBUFFER9 m_index_buffer;
|
||||
static bool m_index_buffer_Changed;
|
||||
|
||||
// Z buffer formats to be used for EFB depth surface
|
||||
D3DFORMAT DepthFormats[] = {
|
||||
FOURCC_INTZ,
|
||||
FOURCC_DF24,
|
||||
FOURCC_RAWZ,
|
||||
FOURCC_DF16,
|
||||
D3DFMT_D24X8,
|
||||
D3DFMT_D24X4S4,
|
||||
D3DFMT_D24S8,
|
||||
D3DFMT_D24FS8,
|
||||
D3DFMT_D32, // too much precision, but who cares
|
||||
D3DFMT_D16, // much lower precision, but better than nothing
|
||||
D3DFMT_D15S1,
|
||||
};
|
||||
|
||||
|
||||
void Enumerate();
|
||||
|
||||
int GetNumAdapters() { return numAdapters; }
|
||||
const Adapter &GetAdapter(int i) { return adapters[i]; }
|
||||
const Adapter &GetCurAdapter() { return adapters[cur_adapter]; }
|
||||
|
||||
bool IsATIDevice()
|
||||
{
|
||||
return GetCurAdapter().ident.VendorId == VENDOR_ATI;
|
||||
}
|
||||
bool IsIntelDevice()
|
||||
{
|
||||
return GetCurAdapter().ident.VendorId == VENDOR_INTEL;
|
||||
}
|
||||
|
||||
|
||||
HRESULT Init()
|
||||
{
|
||||
if (d3d_dll_ref++ > 0) return S_OK;
|
||||
|
||||
hD3DDll = LoadLibraryA("d3d9.dll");
|
||||
if (!hD3DDll)
|
||||
{
|
||||
MessageBoxA(NULL, "Failed to load d3d9.dll", "Critical error", MB_OK | MB_ICONERROR);
|
||||
return E_FAIL;
|
||||
}
|
||||
PDirect3DCreate9 = (DIRECT3DCREATE9)GetProcAddress(hD3DDll, "Direct3DCreate9");
|
||||
if (PDirect3DCreate9 == NULL) MessageBoxA(NULL, "GetProcAddress failed for Direct3DCreate9!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
|
||||
// Create the D3D object, which is needed to create the D3DDevice.
|
||||
D3D = PDirect3DCreate9(D3D_SDK_VERSION);
|
||||
if (!D3D)
|
||||
{
|
||||
--d3d_dll_ref;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Init the caps structure using data from the currently selected device
|
||||
int adapter = g_Config.iAdapter;
|
||||
D3D->GetDeviceCaps((adapter >= 0 && adapter < std::min(MAX_ADAPTERS, numAdapters)) ? adapter : D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
|
||||
Enumerate();
|
||||
if(IsIntelDevice()){
|
||||
// Murder the a because Intel doesn't support 2.0a because the 'a' part was a ATI and Nvidia war going on
|
||||
psVersions[2][5] = '0';
|
||||
vsVersions[2][5] = '0';
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
if (!d3d_dll_ref) return;
|
||||
if (--d3d_dll_ref != 0) return;
|
||||
|
||||
if (D3D) D3D->Release();
|
||||
D3D = NULL;
|
||||
|
||||
if (hD3DDll) FreeLibrary(hD3DDll);
|
||||
PDirect3DCreate9 = NULL;
|
||||
}
|
||||
|
||||
void EnableAlphaToCoverage()
|
||||
{
|
||||
// Each vendor has their own specific little hack.
|
||||
if (GetCurAdapter().ident.VendorId == VENDOR_ATI)
|
||||
SetRenderState(D3DRS_POINTSIZE, (D3DFORMAT)MAKEFOURCC('A', '2', 'M', '1'));
|
||||
else
|
||||
SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
|
||||
}
|
||||
|
||||
void InitPP(int adapter, int f, int aa_mode, D3DPRESENT_PARAMETERS *pp)
|
||||
{
|
||||
ZeroMemory(pp, sizeof(D3DPRESENT_PARAMETERS));
|
||||
pp->hDeviceWindow = hWnd;
|
||||
if (auto_depth_stencil)
|
||||
{
|
||||
pp->EnableAutoDepthStencil = TRUE;
|
||||
pp->AutoDepthStencilFormat = D3DFMT_D24S8;
|
||||
} else {
|
||||
pp->EnableAutoDepthStencil = FALSE;
|
||||
pp->AutoDepthStencilFormat = D3DFMT_UNKNOWN;
|
||||
}
|
||||
pp->BackBufferFormat = D3DFMT_X8R8G8B8;
|
||||
if (aa_mode >= (int)adapters[adapter].aa_levels.size())
|
||||
aa_mode = 0;
|
||||
|
||||
pp->MultiSampleType = adapters[adapter].aa_levels[aa_mode].ms_setting;
|
||||
pp->MultiSampleQuality = adapters[adapter].aa_levels[aa_mode].qual_setting;
|
||||
|
||||
pp->Flags = auto_depth_stencil ? D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL : 0;
|
||||
|
||||
if(g_Config.b3DVision)
|
||||
{
|
||||
xres = pp->BackBufferWidth = adapters[adapter].resolutions[f].xres;
|
||||
yres = pp->BackBufferHeight = adapters[adapter].resolutions[f].yres;
|
||||
}
|
||||
else
|
||||
{
|
||||
RECT client;
|
||||
GetClientRect(hWnd, &client);
|
||||
xres = pp->BackBufferWidth = client.right - client.left;
|
||||
yres = pp->BackBufferHeight = client.bottom - client.top;
|
||||
}
|
||||
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp->PresentationInterval = g_Config.IsVSync() ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
pp->Windowed = !g_Config.b3DVision;
|
||||
}
|
||||
|
||||
void Enumerate()
|
||||
{
|
||||
numAdapters = D3D->GetAdapterCount();
|
||||
|
||||
for (int i = 0; i < std::min(MAX_ADAPTERS, numAdapters); i++)
|
||||
{
|
||||
Adapter &a = adapters[i];
|
||||
a.aa_levels.clear();
|
||||
a.resolutions.clear();
|
||||
D3D->GetAdapterIdentifier(i, 0, &a.ident);
|
||||
bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA;
|
||||
|
||||
// Add SuperSamples modes
|
||||
a.aa_levels.push_back(AALevel("None", D3DMULTISAMPLE_NONE, 0));
|
||||
a.aa_levels.push_back(AALevel("4x SSAA", D3DMULTISAMPLE_NONE, 0));
|
||||
a.aa_levels.push_back(AALevel("9x SSAA", D3DMULTISAMPLE_NONE, 0));
|
||||
//Add multisample modes
|
||||
//disable them will they are not implemnted
|
||||
/*
|
||||
DWORD qlevels = 0;
|
||||
if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("2x MSAA", D3DMULTISAMPLE_2_SAMPLES, 0));
|
||||
|
||||
if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("4x MSAA", D3DMULTISAMPLE_4_SAMPLES, 0));
|
||||
|
||||
if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("8x MSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
|
||||
|
||||
if (isNvidia)
|
||||
{
|
||||
// CSAA support
|
||||
if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels))
|
||||
{
|
||||
if (qlevels > 2)
|
||||
{
|
||||
// 8x, 8xQ are available
|
||||
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
|
||||
a.aa_levels.push_back(AALevel("8x CSAA", D3DMULTISAMPLE_4_SAMPLES, 2));
|
||||
a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
|
||||
}
|
||||
}
|
||||
if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
|
||||
{
|
||||
if (qlevels > 2)
|
||||
{
|
||||
// 16x, 16xQ are available
|
||||
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
|
||||
a.aa_levels.push_back(AALevel("16x CSAA", D3DMULTISAMPLE_4_SAMPLES, 4));
|
||||
a.aa_levels.push_back(AALevel("16xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Determine if INTZ is supported. Code from ATI's doc.
|
||||
// http://developer.amd.com/gpu_assets/Advanced%20DX9%20Capabilities%20for%20ATI%20Radeon%20Cards.pdf
|
||||
a.supports_intz = D3D_OK == D3D->CheckDeviceFormat(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
|
||||
D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, FOURCC_INTZ);
|
||||
// Also check for RAWZ (nvidia only, but the only option to get Z24 textures on sub GF8800
|
||||
a.supports_rawz = D3D_OK == D3D->CheckDeviceFormat(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
|
||||
D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, FOURCC_RAWZ);
|
||||
// Might as well check for RESZ and NULL too.
|
||||
a.supports_resz = D3D_OK == D3D->CheckDeviceFormat(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
|
||||
D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, FOURCC_RESZ);
|
||||
a.supports_null = D3D_OK == D3D->CheckDeviceFormat(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
|
||||
D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, FOURCC_NULL);
|
||||
|
||||
if (a.aa_levels.size() == 1)
|
||||
{
|
||||
strcpy(a.aa_levels[0].name, "(Not supported on this device)");
|
||||
}
|
||||
int numModes = D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
|
||||
for (int m = 0; m < numModes; m++)
|
||||
{
|
||||
D3DDISPLAYMODE mode;
|
||||
D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
|
||||
|
||||
int found = -1;
|
||||
for (int x = 0; x < (int)a.resolutions.size(); x++)
|
||||
{
|
||||
if (a.resolutions[x].xres == mode.Width && a.resolutions[x].yres == mode.Height)
|
||||
{
|
||||
found = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Resolution temp;
|
||||
Resolution &r = found==-1 ? temp : a.resolutions[found];
|
||||
|
||||
sprintf(r.name, "%ix%i", mode.Width, mode.Height);
|
||||
r.bitdepths.insert(mode.Format);
|
||||
r.refreshes.insert(mode.RefreshRate);
|
||||
if (found == -1 && mode.Width >= 640 && mode.Height >= 480)
|
||||
{
|
||||
r.xres = mode.Width;
|
||||
r.yres = mode.Height;
|
||||
a.resolutions.push_back(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dynamically picks one of the available d3dx9 dlls and loads it.
|
||||
// we're first trying to load the dll Dolphin was compiled with, otherwise the most up-to-date one
|
||||
HRESULT LoadD3DX9()
|
||||
{
|
||||
if (d3dx_dll_ref++ > 0) return S_OK;
|
||||
|
||||
HRESULT hr = E_FAIL;
|
||||
hD3DXDll = LoadLibraryA(StringFromFormat("d3dx9_%d.dll", D3DX_SDK_VERSION).c_str());
|
||||
if (hD3DXDll != NULL)
|
||||
{
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if that fails, try loading older dlls (no need to look for newer ones)
|
||||
for (unsigned int num = D3DX_SDK_VERSION-1; num >= 24; --num)
|
||||
{
|
||||
hD3DXDll = LoadLibraryA(StringFromFormat("d3dx9_%d.dll", num).c_str());
|
||||
if (hD3DXDll != NULL)
|
||||
{
|
||||
NOTICE_LOG(VIDEO, "Successfully loaded %s. If you're having trouble, try updating your DX runtime first.", StringFromFormat("d3dx9_%d.dll", num).c_str());
|
||||
hr = S_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (FAILED(hr))
|
||||
{
|
||||
MessageBoxA(NULL, "Failed to load any D3DX9 dll, update your DX9 runtime, please", "Critical error", MB_OK | MB_ICONERROR);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
PD3DXCompileShader = (D3DXCOMPILESHADERTYPE)GetProcAddress(hD3DXDll, "D3DXCompileShader");
|
||||
if (PD3DXCompileShader == NULL)
|
||||
{
|
||||
MessageBoxA(NULL, "GetProcAddress failed for D3DXCompileShader!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PD3DXSaveSurfaceToFileA = (D3DXSAVESURFACETOFILEATYPE)GetProcAddress(hD3DXDll, "D3DXSaveSurfaceToFileA");
|
||||
if (PD3DXSaveSurfaceToFileA == NULL)
|
||||
{
|
||||
MessageBoxA(NULL, "GetProcAddress failed for D3DXSaveSurfaceToFileA!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PD3DXSaveTextureToFileA = (D3DXSAVETEXTURETOFILEATYPE)GetProcAddress(hD3DXDll, "D3DXSaveTextureToFileA");
|
||||
if (PD3DXSaveTextureToFileA == NULL)
|
||||
{
|
||||
MessageBoxA(NULL, "GetProcAddress failed for D3DXSaveTextureToFileA!", "Critical error", MB_OK | MB_ICONERROR);
|
||||
goto fail;
|
||||
}
|
||||
return S_OK;
|
||||
|
||||
fail:
|
||||
--d3dx_dll_ref;
|
||||
FreeLibrary(hD3DXDll);
|
||||
PD3DXCompileShader = NULL;
|
||||
PD3DXSaveSurfaceToFileA = NULL;
|
||||
PD3DXSaveTextureToFileA = NULL;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
void UnloadD3DX9()
|
||||
{
|
||||
if (!d3dx_dll_ref) return;
|
||||
if (--d3dx_dll_ref != 0) return;
|
||||
|
||||
FreeLibrary(hD3DXDll);
|
||||
PD3DXCompileShader = NULL;
|
||||
PD3DXSaveSurfaceToFileA = NULL;
|
||||
PD3DXSaveTextureToFileA = NULL;
|
||||
}
|
||||
|
||||
HRESULT Create(int adapter, HWND wnd, int _resolution, int aa_mode, bool auto_depth)
|
||||
{
|
||||
hWnd = wnd;
|
||||
multisample = aa_mode;
|
||||
resolution = _resolution;
|
||||
auto_depth_stencil = auto_depth;
|
||||
cur_adapter = adapter;
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
|
||||
HRESULT hr = LoadD3DX9();
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
InitPP(adapter, resolution, aa_mode, &d3dpp);
|
||||
|
||||
if (FAILED(D3D->CreateDevice(
|
||||
adapter,
|
||||
D3DDEVTYPE_HAL,
|
||||
wnd,
|
||||
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, //doesn't seem to make a difference
|
||||
&d3dpp, &dev)))
|
||||
{
|
||||
if (FAILED(D3D->CreateDevice(
|
||||
adapter,
|
||||
D3DDEVTYPE_HAL,
|
||||
wnd,
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
|
||||
&d3dpp, &dev)))
|
||||
{
|
||||
MessageBox(wnd,
|
||||
_T("Failed to initialize Direct3D."),
|
||||
_T("Dolphin Direct3D Backend"), MB_OK | MB_ICONERROR);
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
dev->GetDeviceCaps(&caps);
|
||||
dev->GetRenderTarget(0, &back_buffer);
|
||||
if (dev->GetDepthStencilSurface(&back_buffer_z) == D3DERR_NOTFOUND)
|
||||
back_buffer_z = NULL;
|
||||
SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE );
|
||||
SetRenderState(D3DRS_FILLMODE, g_Config.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
|
||||
memset(m_Textures, 0, sizeof(m_Textures));
|
||||
memset(m_TextureStageStatesSet, 0, sizeof(m_TextureStageStatesSet));
|
||||
memset(m_RenderStatesSet, 0, sizeof(m_RenderStatesSet));
|
||||
memset(m_SamplerStatesSet, 0, sizeof(m_SamplerStatesSet));
|
||||
memset(m_TextureStageStatesChanged, 0, sizeof(m_TextureStageStatesChanged));
|
||||
memset(m_RenderStatesChanged, 0, sizeof(m_RenderStatesChanged));
|
||||
memset(m_SamplerStatesChanged, 0, sizeof(m_SamplerStatesChanged));
|
||||
m_VtxDecl = NULL;
|
||||
m_PixelShader = NULL;
|
||||
m_VertexShader = NULL;
|
||||
m_index_buffer = NULL;
|
||||
memset(m_stream_sources, 0, sizeof(m_stream_sources));
|
||||
m_index_buffer = NULL;
|
||||
|
||||
m_VtxDeclChanged = false;
|
||||
m_PixelShaderChanged = false;
|
||||
m_VertexShaderChanged = false;
|
||||
memset(m_stream_sources_Changed, 0 , sizeof(m_stream_sources_Changed));
|
||||
m_index_buffer_Changed = false;
|
||||
// Device state would normally be set here
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
UnloadD3DX9();
|
||||
|
||||
if (back_buffer_z)
|
||||
back_buffer_z->Release();
|
||||
back_buffer_z = NULL;
|
||||
if( back_buffer )
|
||||
back_buffer->Release();
|
||||
back_buffer = NULL;
|
||||
|
||||
ULONG references = dev->Release();
|
||||
if (references)
|
||||
ERROR_LOG(VIDEO, "Unreleased references: %i.", references);
|
||||
|
||||
dev = NULL;
|
||||
}
|
||||
|
||||
const D3DCAPS9 &GetCaps()
|
||||
{
|
||||
return caps;
|
||||
}
|
||||
|
||||
// returns true if size was changed
|
||||
bool FixTextureSize(int& width, int& height)
|
||||
{
|
||||
int oldw = width, oldh = height;
|
||||
|
||||
// conditional nonpow2 support should work fine for us
|
||||
if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
|
||||
{
|
||||
// all texture dimensions need to be powers of two
|
||||
width = (int)MakePow2((u32)width);
|
||||
height = (int)MakePow2((u32)height);
|
||||
}
|
||||
if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
|
||||
{
|
||||
width = height = max(width, height);
|
||||
}
|
||||
|
||||
width = min(width, (int)caps.MaxTextureWidth);
|
||||
height = min(height, (int)caps.MaxTextureHeight);
|
||||
|
||||
return (width != oldw) || (height != oldh);
|
||||
}
|
||||
|
||||
// returns true if format is supported
|
||||
bool CheckTextureSupport(DWORD usage, D3DFORMAT tex_format)
|
||||
{
|
||||
return D3D_OK == D3D->CheckDeviceFormat(cur_adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, usage, D3DRTYPE_TEXTURE, tex_format);
|
||||
}
|
||||
|
||||
bool CheckDepthStencilSupport(D3DFORMAT target_format, D3DFORMAT depth_format)
|
||||
{
|
||||
return D3D_OK == D3D->CheckDepthStencilMatch(cur_adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, target_format, depth_format);
|
||||
}
|
||||
|
||||
D3DFORMAT GetSupportedDepthTextureFormat()
|
||||
{
|
||||
for (int i = 0; i < sizeof(DepthFormats)/sizeof(D3DFORMAT); ++i)
|
||||
if (CheckTextureSupport(D3DUSAGE_DEPTHSTENCIL, DepthFormats[i]))
|
||||
return DepthFormats[i];
|
||||
|
||||
return D3DFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
D3DFORMAT GetSupportedDepthSurfaceFormat(D3DFORMAT target_format)
|
||||
{
|
||||
for (int i = 0; i < sizeof(DepthFormats)/sizeof(D3DFORMAT); ++i)
|
||||
if (CheckDepthStencilSupport(target_format, DepthFormats[i]))
|
||||
return DepthFormats[i];
|
||||
|
||||
return D3DFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
const char *VertexShaderVersionString()
|
||||
{
|
||||
int version = ((caps.VertexShaderVersion >> 8) & 0xFF);
|
||||
return vsVersions[std::min(4, version)];
|
||||
}
|
||||
|
||||
const char *PixelShaderVersionString()
|
||||
{
|
||||
int version = ((caps.PixelShaderVersion >> 8) & 0xFF);
|
||||
return psVersions[std::min(4, version)];
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 GetBackBufferSurface()
|
||||
{
|
||||
return back_buffer;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 GetBackBufferDepthSurface()
|
||||
{
|
||||
return back_buffer_z;
|
||||
}
|
||||
|
||||
void ShowD3DError(HRESULT err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case D3DERR_DEVICELOST:
|
||||
PanicAlert("Device Lost");
|
||||
break;
|
||||
case D3DERR_INVALIDCALL:
|
||||
PanicAlert("Invalid Call");
|
||||
break;
|
||||
case D3DERR_DRIVERINTERNALERROR:
|
||||
PanicAlert("Driver Internal Error");
|
||||
break;
|
||||
case D3DERR_OUTOFVIDEOMEMORY:
|
||||
PanicAlert("Out of vid mem");
|
||||
break;
|
||||
default:
|
||||
// MessageBox(0,_T("Other error or success"),_T("ERROR"),0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (dev)
|
||||
{
|
||||
// ForgetCachedState();
|
||||
|
||||
// Can't keep a pointer around to the backbuffer surface when resetting.
|
||||
if (back_buffer_z)
|
||||
back_buffer_z->Release();
|
||||
back_buffer_z = NULL;
|
||||
back_buffer->Release();
|
||||
back_buffer = NULL;
|
||||
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
InitPP(cur_adapter, resolution, multisample, &d3dpp);
|
||||
HRESULT hr = dev->Reset(&d3dpp);
|
||||
ShowD3DError(hr);
|
||||
|
||||
dev->GetRenderTarget(0, &back_buffer);
|
||||
if (dev->GetDepthStencilSurface(&back_buffer_z) == D3DERR_NOTFOUND)
|
||||
back_buffer_z = NULL;
|
||||
ApplyCachedState();
|
||||
}
|
||||
}
|
||||
|
||||
int GetBackBufferWidth()
|
||||
{
|
||||
return xres;
|
||||
}
|
||||
|
||||
int GetBackBufferHeight()
|
||||
{
|
||||
return yres;
|
||||
}
|
||||
|
||||
bool BeginFrame()
|
||||
{
|
||||
if (bFrameInProgress)
|
||||
{
|
||||
PanicAlert("BeginFrame WTF");
|
||||
return false;
|
||||
}
|
||||
bFrameInProgress = true;
|
||||
if (dev)
|
||||
{
|
||||
dev->BeginScene();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void EndFrame()
|
||||
{
|
||||
if (!bFrameInProgress)
|
||||
{
|
||||
PanicAlert("EndFrame WTF");
|
||||
return;
|
||||
}
|
||||
bFrameInProgress = false;
|
||||
dev->EndScene();
|
||||
}
|
||||
|
||||
void Present()
|
||||
{
|
||||
if (dev)
|
||||
{
|
||||
dev->Present(NULL, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyCachedState()
|
||||
{
|
||||
for (int sampler = 0; sampler < 8; sampler++)
|
||||
{
|
||||
for (int type = 0; type < MaxSamplerTypes; type++)
|
||||
{
|
||||
if(m_SamplerStatesSet[sampler][type])
|
||||
dev->SetSamplerState(sampler, (D3DSAMPLERSTATETYPE)type, m_SamplerStates[sampler][type]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int rs = 0; rs < MaxRenderStates; rs++)
|
||||
{
|
||||
if (m_RenderStatesSet[rs])
|
||||
dev->SetRenderState((D3DRENDERSTATETYPE)rs, m_RenderStates[rs]);
|
||||
}
|
||||
|
||||
// We don't bother restoring these so let's just wipe the state copy
|
||||
// so no stale state is around.
|
||||
memset(m_Textures, 0, sizeof(m_Textures));
|
||||
memset(m_TextureStageStatesSet, 0, sizeof(m_TextureStageStatesSet));
|
||||
memset(m_TextureStageStatesChanged, 0, sizeof(m_TextureStageStatesChanged));
|
||||
m_VtxDecl = NULL;
|
||||
m_PixelShader = NULL;
|
||||
m_VertexShader = NULL;
|
||||
memset(m_stream_sources, 0, sizeof(m_stream_sources));
|
||||
m_index_buffer = NULL;
|
||||
m_VtxDeclChanged = false;
|
||||
m_PixelShaderChanged = false;
|
||||
m_VertexShaderChanged = false;
|
||||
memset(m_stream_sources_Changed, 0 , sizeof(m_stream_sources_Changed));
|
||||
m_index_buffer_Changed = false;
|
||||
}
|
||||
|
||||
void SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture)
|
||||
{
|
||||
if (m_Textures[Stage] != pTexture)
|
||||
{
|
||||
m_Textures[Stage] = pTexture;
|
||||
dev->SetTexture(Stage, pTexture);
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshRenderState(D3DRENDERSTATETYPE State)
|
||||
{
|
||||
if(m_RenderStatesSet[State] && m_RenderStatesChanged[State])
|
||||
{
|
||||
dev->SetRenderState(State, m_RenderStates[State]);
|
||||
m_RenderStatesChanged[State] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value)
|
||||
{
|
||||
if (m_RenderStates[State] != Value || !m_RenderStatesSet[State])
|
||||
{
|
||||
m_RenderStates[State] = Value;
|
||||
m_RenderStatesSet[State] = true;
|
||||
m_RenderStatesChanged[State] = false;
|
||||
dev->SetRenderState(State, Value);
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value)
|
||||
{
|
||||
if (m_RenderStates[State] != Value || !m_RenderStatesSet[State])
|
||||
{
|
||||
m_RenderStatesChanged[State] = m_RenderStatesSet[State];
|
||||
dev->SetRenderState(State, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RenderStatesChanged[State] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
|
||||
{
|
||||
if (m_TextureStageStates[Stage][Type] != Value || !m_TextureStageStatesSet[Stage][Type])
|
||||
{
|
||||
m_TextureStageStates[Stage][Type] = Value;
|
||||
m_TextureStageStatesSet[Stage][Type]=true;
|
||||
m_TextureStageStatesChanged[Stage][Type]=false;
|
||||
dev->SetTextureStageState(Stage, Type, Value);
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type)
|
||||
{
|
||||
if(m_TextureStageStatesSet[Stage][Type] && m_TextureStageStatesChanged[Stage][Type])
|
||||
{
|
||||
dev->SetTextureStageState(Stage, Type, m_TextureStageStates[Stage][Type]);
|
||||
m_TextureStageStatesChanged[Stage][Type] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
|
||||
{
|
||||
if (m_TextureStageStates[Stage][Type] != Value || !m_TextureStageStatesSet[Stage][Type])
|
||||
{
|
||||
m_TextureStageStatesChanged[Stage][Type] = m_TextureStageStatesSet[Stage][Type];
|
||||
dev->SetTextureStageState(Stage, Type, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_TextureStageStatesChanged[Stage][Type] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
|
||||
{
|
||||
if (m_SamplerStates[Sampler][Type] != Value || !m_SamplerStatesSet[Sampler][Type])
|
||||
{
|
||||
m_SamplerStates[Sampler][Type] = Value;
|
||||
m_SamplerStatesSet[Sampler][Type] = true;
|
||||
m_SamplerStatesChanged[Sampler][Type] = false;
|
||||
dev->SetSamplerState(Sampler, Type, Value);
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type)
|
||||
{
|
||||
if(m_SamplerStatesSet[Sampler][Type] && m_SamplerStatesChanged[Sampler][Type])
|
||||
{
|
||||
dev->SetSamplerState(Sampler, Type, m_SamplerStates[Sampler][Type]);
|
||||
m_SamplerStatesChanged[Sampler][Type] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
|
||||
{
|
||||
if (m_SamplerStates[Sampler][Type] != Value || !m_SamplerStatesSet[Sampler][Type])
|
||||
{
|
||||
m_SamplerStatesChanged[Sampler][Type] = m_SamplerStatesSet[Sampler][Type];
|
||||
dev->SetSamplerState(Sampler, Type, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_SamplerStatesChanged[Sampler][Type] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshVertexDeclaration()
|
||||
{
|
||||
if (m_VtxDeclChanged)
|
||||
{
|
||||
dev->SetVertexDeclaration(m_VtxDecl);
|
||||
m_VtxDeclChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl)
|
||||
{
|
||||
if (decl != m_VtxDecl)
|
||||
{
|
||||
dev->SetVertexDeclaration(decl);
|
||||
m_VtxDecl = decl;
|
||||
m_VtxDeclChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl)
|
||||
{
|
||||
if (decl != m_VtxDecl) {
|
||||
dev->SetVertexDeclaration(decl);
|
||||
m_VtxDeclChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeVertexShader(LPDIRECT3DVERTEXSHADER9 shader)
|
||||
{
|
||||
if (shader != m_VertexShader)
|
||||
{
|
||||
dev->SetVertexShader(shader);
|
||||
m_VertexShaderChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshVertexShader()
|
||||
{
|
||||
if (m_VertexShaderChanged)
|
||||
{
|
||||
dev->SetVertexShader(m_VertexShader);
|
||||
m_VertexShaderChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader)
|
||||
{
|
||||
if (shader != m_VertexShader)
|
||||
{
|
||||
dev->SetVertexShader(shader);
|
||||
m_VertexShader = shader;
|
||||
m_VertexShaderChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshPixelShader()
|
||||
{
|
||||
if (m_PixelShaderChanged)
|
||||
{
|
||||
dev->SetPixelShader(m_PixelShader);
|
||||
m_PixelShaderChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader)
|
||||
{
|
||||
if (shader != m_PixelShader)
|
||||
{
|
||||
dev->SetPixelShader(shader);
|
||||
m_PixelShader = shader;
|
||||
m_PixelShaderChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ChangePixelShader(LPDIRECT3DPIXELSHADER9 shader)
|
||||
{
|
||||
if (shader != m_PixelShader)
|
||||
{
|
||||
dev->SetPixelShader(shader);
|
||||
m_PixelShaderChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
|
||||
{
|
||||
if (m_stream_sources[StreamNumber].OffsetInBytes != OffsetInBytes
|
||||
|| m_stream_sources[StreamNumber].pStreamData != pStreamData
|
||||
|| m_stream_sources[StreamNumber].Stride != Stride)
|
||||
{
|
||||
m_stream_sources[StreamNumber].OffsetInBytes = OffsetInBytes;
|
||||
m_stream_sources[StreamNumber].pStreamData = pStreamData;
|
||||
m_stream_sources[StreamNumber].Stride = Stride;
|
||||
dev->SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride);
|
||||
m_stream_sources_Changed[StreamNumber] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
|
||||
{
|
||||
if (m_stream_sources[StreamNumber].OffsetInBytes != OffsetInBytes
|
||||
|| m_stream_sources[StreamNumber].pStreamData != pStreamData
|
||||
|| m_stream_sources[StreamNumber].Stride != Stride)
|
||||
{
|
||||
dev->SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride);
|
||||
m_stream_sources_Changed[StreamNumber] = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RefreshStreamSource(UINT StreamNumber)
|
||||
{
|
||||
if (m_PixelShaderChanged)
|
||||
{
|
||||
dev->SetStreamSource(
|
||||
StreamNumber,
|
||||
m_stream_sources[StreamNumber].pStreamData,
|
||||
m_stream_sources[StreamNumber].OffsetInBytes,
|
||||
m_stream_sources[StreamNumber].Stride);
|
||||
m_stream_sources_Changed[StreamNumber] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetIndices(LPDIRECT3DINDEXBUFFER9 pIndexData)
|
||||
{
|
||||
if(pIndexData != m_index_buffer)
|
||||
{
|
||||
m_index_buffer = pIndexData;
|
||||
dev->SetIndices(pIndexData);
|
||||
m_index_buffer_Changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeIndices(LPDIRECT3DINDEXBUFFER9 pIndexData)
|
||||
{
|
||||
if(pIndexData != m_index_buffer)
|
||||
{
|
||||
dev->SetIndices(pIndexData);
|
||||
m_index_buffer_Changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshIndices()
|
||||
{
|
||||
if (m_index_buffer_Changed)
|
||||
{
|
||||
dev->SetIndices(m_index_buffer);
|
||||
m_index_buffer_Changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace DX9
|
|
@ -1,168 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
// From http://developer.amd.com/gpu_assets/Advanced%20DX9%20Capabilities%20for%20ATI%20Radeon%20Cards.pdf
|
||||
// Magic FourCC's to unlock undocumented D3D9 features:
|
||||
|
||||
// Z texture formats
|
||||
#define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')))
|
||||
#define FOURCC_RAWZ ((D3DFORMAT)(MAKEFOURCC('R','A','W','Z')))
|
||||
#define FOURCC_DF24 ((D3DFORMAT)(MAKEFOURCC('D','F','2','4')))
|
||||
#define FOURCC_DF16 ((D3DFORMAT)(MAKEFOURCC('D','F','1','6')))
|
||||
|
||||
// Depth buffer resolve:
|
||||
#define FOURCC_RESZ ((D3DFORMAT)(MAKEFOURCC('R','E','S','Z')))
|
||||
#define RESZ_CODE 0x7fa05000
|
||||
|
||||
// Null render target to do Z-only shadow maps: (probably not useful for Dolphin)
|
||||
#define FOURCC_NULL ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')))
|
||||
|
||||
bool IsATIDevice();
|
||||
bool IsIntelDevice();
|
||||
HRESULT Init();
|
||||
HRESULT Create(int adapter, HWND wnd, int resolution, int aa_mode, bool auto_depth);
|
||||
void Close();
|
||||
void Shutdown();
|
||||
|
||||
// Direct access to the device.
|
||||
extern LPDIRECT3DDEVICE9 dev;
|
||||
extern bool bFrameInProgress;
|
||||
|
||||
void Reset();
|
||||
bool BeginFrame();
|
||||
void EndFrame();
|
||||
void Present();
|
||||
bool CanUseINTZ();
|
||||
|
||||
int GetBackBufferWidth();
|
||||
int GetBackBufferHeight();
|
||||
LPDIRECT3DSURFACE9 GetBackBufferSurface();
|
||||
LPDIRECT3DSURFACE9 GetBackBufferDepthSurface();
|
||||
LPDIRECT3DVERTEXBUFFER9 GetquadVB();
|
||||
LPDIRECT3DVERTEXDECLARATION9 GetBasicvertexDecl();
|
||||
const D3DCAPS9 &GetCaps();
|
||||
const char *PixelShaderVersionString();
|
||||
const char *VertexShaderVersionString();
|
||||
void ShowD3DError(HRESULT err);
|
||||
|
||||
// returns true if size was changed
|
||||
bool FixTextureSize(int& width, int& height);
|
||||
|
||||
// returns true if format is supported
|
||||
bool CheckTextureSupport(DWORD usage, D3DFORMAT tex_format);
|
||||
bool CheckDepthStencilSupport(D3DFORMAT target_format, D3DFORMAT depth_format);
|
||||
|
||||
D3DFORMAT GetSupportedDepthTextureFormat();
|
||||
D3DFORMAT GetSupportedDepthSurfaceFormat(D3DFORMAT target_format);
|
||||
|
||||
// The following are "filtered" versions of the corresponding D3Ddev-> functions.
|
||||
void SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture);
|
||||
void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
|
||||
void RefreshRenderState(D3DRENDERSTATETYPE State);
|
||||
void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value);
|
||||
|
||||
void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
|
||||
void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type);
|
||||
void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
|
||||
|
||||
void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
|
||||
void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type);
|
||||
void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
|
||||
|
||||
void RefreshVertexDeclaration();
|
||||
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
|
||||
void ChangeVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
|
||||
|
||||
void RefreshVertexShader();
|
||||
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
|
||||
void ChangeVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
|
||||
|
||||
void RefreshPixelShader();
|
||||
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader);
|
||||
void ChangePixelShader(LPDIRECT3DPIXELSHADER9 shader);
|
||||
|
||||
void SetStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride);
|
||||
void ChangeStreamSource(UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride);
|
||||
void RefreshStreamSource(UINT StreamNumber);
|
||||
|
||||
void SetIndices(LPDIRECT3DINDEXBUFFER9 pIndexData);
|
||||
void ChangeIndices(LPDIRECT3DINDEXBUFFER9 pIndexData);
|
||||
void RefreshIndices();
|
||||
|
||||
void ApplyCachedState();
|
||||
|
||||
// Utility functions for vendor specific hacks. So far, just the one.
|
||||
void EnableAlphaToCoverage();
|
||||
|
||||
struct Resolution
|
||||
{
|
||||
char name[32];
|
||||
int xres;
|
||||
int yres;
|
||||
std::set<D3DFORMAT> bitdepths;
|
||||
std::set<int> refreshes;
|
||||
};
|
||||
|
||||
struct AALevel
|
||||
{
|
||||
AALevel(const char *n, D3DMULTISAMPLE_TYPE m, int q) {
|
||||
strncpy(name, n, 32);
|
||||
name[31] = '\0';
|
||||
ms_setting = m;
|
||||
qual_setting = q;
|
||||
}
|
||||
char name[32];
|
||||
D3DMULTISAMPLE_TYPE ms_setting;
|
||||
int qual_setting;
|
||||
};
|
||||
|
||||
struct Adapter
|
||||
{
|
||||
D3DADAPTER_IDENTIFIER9 ident;
|
||||
std::vector<Resolution> resolutions;
|
||||
std::vector<AALevel> aa_levels;
|
||||
bool supports_alpha_to_coverage;
|
||||
|
||||
// Magic render targets, see the top of this file.
|
||||
bool supports_intz;
|
||||
bool supports_rawz;
|
||||
bool supports_resz;
|
||||
bool supports_null;
|
||||
};
|
||||
|
||||
const Adapter &GetAdapter(int i);
|
||||
const Adapter &GetCurAdapter();
|
||||
int GetNumAdapters();
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace DX9
|
||||
|
||||
|
||||
// Used to not require the SDK and runtime versions to match:
|
||||
// Linking with d3dx9.lib makes the most recent d3dx9_xx.dll of the
|
||||
// compiler's SDK an actually unnecessary requirement.
|
||||
// Add any d3dx9 functions which you want to use here and load them in LoadD3DX9()
|
||||
typedef HRESULT (WINAPI* D3DXSAVESURFACETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DSURFACE9, CONST PALETTEENTRY*, CONST RECT*);
|
||||
typedef HRESULT (WINAPI* D3DXSAVETEXTURETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DBASETEXTURE9, CONST PALETTEENTRY*);
|
||||
typedef HRESULT (WINAPI* D3DXCOMPILESHADERTYPE)(LPCSTR, UINT, CONST D3DXMACRO*, LPD3DXINCLUDE, LPCSTR, LPCSTR, DWORD, LPD3DXBUFFER*, LPD3DXBUFFER*, LPD3DXCONSTANTTABLE*);
|
||||
|
||||
extern D3DXSAVESURFACETOFILEATYPE PD3DXSaveSurfaceToFileA;
|
||||
extern D3DXSAVETEXTURETOFILEATYPE PD3DXSaveTextureToFileA;
|
||||
extern D3DXCOMPILESHADERTYPE PD3DXCompileShader;
|
|
@ -1,152 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <d3dx9.h>
|
||||
#include <string>
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "D3DShader.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
// bytecode->shader.
|
||||
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len)
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 v_shader;
|
||||
HRESULT hr = D3D::dev->CreateVertexShader((DWORD *)bytecode, &v_shader);
|
||||
if (FAILED(hr))
|
||||
return NULL;
|
||||
|
||||
return v_shader;
|
||||
}
|
||||
|
||||
// code->bytecode.
|
||||
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
|
||||
{
|
||||
LPD3DXBUFFER shaderBuffer = NULL;
|
||||
LPD3DXBUFFER errorBuffer = NULL;
|
||||
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::VertexShaderVersionString(),
|
||||
0, &shaderBuffer, &errorBuffer, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
static int num_failures = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
std::ofstream file;
|
||||
OpenFStream(file, szTemp, std::ios_base::out);
|
||||
file << code;
|
||||
file.close();
|
||||
|
||||
PanicAlert("Failed to compile vertex shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%s):\n%s",
|
||||
szTemp,
|
||||
D3D::VertexShaderVersionString(),
|
||||
(char*)errorBuffer->GetBufferPointer());
|
||||
|
||||
*bytecode = NULL;
|
||||
*bytecodelen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*bytecodelen = shaderBuffer->GetBufferSize();
|
||||
*bytecode = new u8[*bytecodelen];
|
||||
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
return SUCCEEDED(hr) ? true : false;
|
||||
}
|
||||
|
||||
// bytecode->shader
|
||||
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len)
|
||||
{
|
||||
LPDIRECT3DPIXELSHADER9 p_shader;
|
||||
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)bytecode, &p_shader);
|
||||
if (FAILED(hr))
|
||||
return NULL;
|
||||
|
||||
return p_shader;
|
||||
}
|
||||
|
||||
// code->bytecode
|
||||
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
|
||||
{
|
||||
LPD3DXBUFFER shaderBuffer = 0;
|
||||
LPD3DXBUFFER errorBuffer = 0;
|
||||
|
||||
// Someone:
|
||||
// For some reason, I had this kind of errors : "Shader uses texture addressing operations
|
||||
// in a dependency chain that is too complex for the target shader model (ps_2_0) to handle."
|
||||
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::PixelShaderVersionString(),
|
||||
0, &shaderBuffer, &errorBuffer, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
static int num_failures = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
std::ofstream file;
|
||||
OpenFStream(file, szTemp, std::ios_base::out);
|
||||
file << code;
|
||||
file.close();
|
||||
|
||||
PanicAlert("Failed to compile pixel shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%s):\n%s",
|
||||
szTemp,
|
||||
D3D::PixelShaderVersionString(),
|
||||
(char*)errorBuffer->GetBufferPointer());
|
||||
|
||||
*bytecode = NULL;
|
||||
*bytecodelen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*bytecodelen = shaderBuffer->GetBufferSize();
|
||||
*bytecode = new u8[*bytecodelen];
|
||||
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
return SUCCEEDED(hr) ? true : false;
|
||||
}
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len)
|
||||
{
|
||||
u8 *bytecode;
|
||||
int bytecodelen;
|
||||
if (CompileVertexShader(code, len, &bytecode, &bytecodelen))
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 v_shader = CreateVertexShaderFromByteCode(bytecode, len);
|
||||
delete [] bytecode;
|
||||
return v_shader;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char* code, unsigned int len)
|
||||
{
|
||||
u8 *bytecode;
|
||||
int bytecodelen;
|
||||
if (CompilePixelShader(code, len, &bytecode, &bytecodelen))
|
||||
{
|
||||
LPDIRECT3DPIXELSHADER9 p_shader = CreatePixelShaderFromByteCode(bytecode, len);
|
||||
delete [] bytecode;
|
||||
return p_shader;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace DX9
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len);
|
||||
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len);
|
||||
|
||||
// The returned bytecode buffers should be delete[]-d.
|
||||
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
|
||||
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
|
||||
|
||||
// Utility functions
|
||||
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len);
|
||||
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, unsigned int len);
|
||||
}
|
||||
|
||||
} // namespace DX9
|
|
@ -1,406 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
|
||||
#include "CPUDetect.h"
|
||||
|
||||
#if _M_SSE >= 0x401
|
||||
#include <smmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#elif _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__)
|
||||
#include <tmmintrin.h>
|
||||
#endif
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
||||
void ConvertRGBA_BGRA_SSE2(u32 *dst, const int dstPitch, u32 *pIn, const int width, const int height, const int pitch)
|
||||
{
|
||||
// Converts RGBA to BGRA:
|
||||
// TODO: this would be totally unnecessary if we just change the TextureDecoder_RGBA to decode
|
||||
// to BGRA instead.
|
||||
for (int y = 0; y < height; y++, pIn += pitch)
|
||||
{
|
||||
u8 *pIn8 = (u8 *)pIn;
|
||||
u8 *pBits = (u8 *)((u8*)dst + (y * dstPitch));
|
||||
|
||||
// Batch up loads/stores into 16 byte chunks to use SSE2 efficiently:
|
||||
int sse2blocks = (width * 4) / 16;
|
||||
int sse2remainder = (width * 4) & 15;
|
||||
|
||||
// Do conversions in batches of 16 bytes:
|
||||
if (sse2blocks > 0)
|
||||
{
|
||||
// Generate a constant of all FF bytes:
|
||||
const __m128i allFFs128 = _mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128());
|
||||
__m128i *src128 = (__m128i *)pIn8;
|
||||
__m128i *dst128 = (__m128i *)pBits;
|
||||
|
||||
// Increment by 16 bytes at a time:
|
||||
for (int i = 0; i < sse2blocks; ++i, ++dst128, ++src128)
|
||||
{
|
||||
// Load up 4 colors simultaneously:
|
||||
__m128i rgba = _mm_loadu_si128(src128);
|
||||
// Swap the R and B components:
|
||||
// Isolate the B component and shift it left 16 bits:
|
||||
// ABGR
|
||||
const __m128i bMask = _mm_srli_epi32(allFFs128, 24);
|
||||
const __m128i bNew = _mm_slli_epi32(_mm_and_si128(rgba, bMask), 16);
|
||||
// Isolate the R component and shift it right 16 bits:
|
||||
const __m128i rMask = _mm_slli_epi32(bMask, 16);
|
||||
const __m128i rNew = _mm_srli_epi32(_mm_and_si128(rgba, rMask), 16);
|
||||
// Now mask off the old R and B components from the rgba data to get 0g0a:
|
||||
const __m128i _g_a = _mm_or_si128(
|
||||
_mm_and_si128(
|
||||
rgba,
|
||||
_mm_or_si128(
|
||||
_mm_slli_epi32(bMask, 8),
|
||||
_mm_slli_epi32(rMask, 8)
|
||||
)
|
||||
),
|
||||
_mm_or_si128(rNew, bNew)
|
||||
);
|
||||
// Finally, OR up all the individual components to get BGRA:
|
||||
const __m128i bgra = _mm_or_si128(_g_a, _mm_or_si128(rNew, bNew));
|
||||
_mm_storeu_si128(dst128, bgra);
|
||||
}
|
||||
}
|
||||
|
||||
// Take the remainder colors at the end of the row that weren't able to
|
||||
// be included into the last 16 byte chunk:
|
||||
if (sse2remainder > 0)
|
||||
{
|
||||
for (int x = (sse2blocks * 16); x < (width * 4); x += 4)
|
||||
{
|
||||
pBits[x + 0] = pIn8[x + 2];
|
||||
pBits[x + 1] = pIn8[x + 1];
|
||||
pBits[x + 2] = pIn8[x + 0];
|
||||
pBits[x + 3] = pIn8[x + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Memory fence to make sure the stores are good:
|
||||
_mm_mfence();
|
||||
}
|
||||
|
||||
void ConvertRGBA_BGRA_SSSE3(u32 *dst, const int dstPitch, u32 *pIn, const int width, const int height, const int pitch)
|
||||
{
|
||||
__m128i mask = _mm_set_epi8(15, 12, 13, 14, 11, 8, 9, 10, 7, 4, 5, 6, 3, 0, 1, 2);
|
||||
for (int y = 0; y < height; y++, pIn += pitch)
|
||||
{
|
||||
u8 *pIn8 = (u8 *)pIn;
|
||||
u8 *pBits = (u8 *)((u8*)dst + (y * dstPitch));
|
||||
|
||||
// Batch up loads/stores into 16 byte chunks to use SSE2 efficiently:
|
||||
int ssse3blocks = (width * 4) / 16;
|
||||
int ssse3remainder = (width * 4) & 15;
|
||||
|
||||
// Do conversions in batches of 16 bytes:
|
||||
if (ssse3blocks > 0)
|
||||
{
|
||||
__m128i *src128 = (__m128i *)pIn8;
|
||||
__m128i *dst128 = (__m128i *)pBits;
|
||||
|
||||
// Increment by 16 bytes at a time:
|
||||
for (int i = 0; i < ssse3blocks; ++i, ++dst128, ++src128)
|
||||
{
|
||||
_mm_storeu_si128(dst128, _mm_shuffle_epi8(_mm_loadu_si128(src128), mask));
|
||||
}
|
||||
}
|
||||
|
||||
// Take the remainder colors at the end of the row that weren't able to
|
||||
// be included into the last 16 byte chunk:
|
||||
if (ssse3remainder > 0)
|
||||
{
|
||||
for (int x = (ssse3blocks * 16); x < (width * 4); x += 4)
|
||||
{
|
||||
pBits[x + 0] = pIn8[x + 2];
|
||||
pBits[x + 1] = pIn8[x + 1];
|
||||
pBits[x + 2] = pIn8[x + 0];
|
||||
pBits[x + 3] = pIn8[x + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Memory fence to make sure the stores are good:
|
||||
_mm_mfence();
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int levels)
|
||||
{
|
||||
u32* pBuffer = (u32*)buffer;
|
||||
LPDIRECT3DTEXTURE9 pTexture;
|
||||
|
||||
// crazy bitmagic, sorry :)
|
||||
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
|
||||
bool bExpand = false;
|
||||
|
||||
if (fmt == D3DFMT_A8P8) {
|
||||
fmt = D3DFMT_A8L8;
|
||||
bExpand = true;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
if (levels > 0)
|
||||
hr = dev->CreateTexture(width, height, levels, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
else
|
||||
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
int level = 0;
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0);
|
||||
switch (fmt)
|
||||
{
|
||||
case D3DFMT_L8:
|
||||
case D3DFMT_A8:
|
||||
case D3DFMT_A4L4:
|
||||
{
|
||||
const u8 *pIn = buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
{
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A8L8:
|
||||
{
|
||||
if (bExpand) { // I8
|
||||
const u8 *pIn = buffer;
|
||||
// TODO(XK): Find a better way that does not involve either unpacking
|
||||
// or downsampling (i.e. A4L4)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for(int i = 0; i < width * 2; i += 2) {
|
||||
pBits[i] = pIn[i / 2];
|
||||
pBits[i + 1] = pIn[i / 2];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
} else { // IA8
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A8R8G8B8:
|
||||
{
|
||||
if(pitch * 4 == Lock.Pitch && !swap_r_b)
|
||||
{
|
||||
memcpy(Lock.pBits,buffer,Lock.Pitch*height);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32* pIn = pBuffer;
|
||||
if (!swap_r_b) {
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 4);
|
||||
pIn += pitch;
|
||||
}
|
||||
} else {
|
||||
#if _M_SSE >= 0x301
|
||||
// Uses SSSE3 intrinsics to optimize RGBA -> BGRA swizzle:
|
||||
if (cpu_info.bSSSE3) {
|
||||
ConvertRGBA_BGRA_SSSE3((u32 *)Lock.pBits, Lock.Pitch, pIn, width, height, pitch);
|
||||
} else
|
||||
#endif
|
||||
// Uses SSE2 intrinsics to optimize RGBA -> BGRA swizzle:
|
||||
{
|
||||
ConvertRGBA_BGRA_SSE2((u32 *)Lock.pBits, Lock.Pitch, pIn, width, height, pitch);
|
||||
}
|
||||
#if 0
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8 *pIn8 = (u8 *)pIn;
|
||||
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for (int x = 0; x < width * 4; x += 4) {
|
||||
pBits[x + 0] = pIn8[x + 2];
|
||||
pBits[x + 1] = pIn8[x + 1];
|
||||
pBits[x + 2] = pIn8[x + 0];
|
||||
pBits[x + 3] = pIn8[x + 3];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
|
||||
break;
|
||||
default:
|
||||
PanicAlert("D3D: Invalid texture format %i", fmt);
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
return pTexture;
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 pTexture;
|
||||
// crazy bitmagic, sorry :)
|
||||
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
|
||||
bool bExpand = false;
|
||||
HRESULT hr;
|
||||
// TODO(ector): Allow mipmaps for non-pow textures on newer cards?
|
||||
// TODO(ector): Use the game-specified mipmaps?
|
||||
if (!isPow2)
|
||||
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
else
|
||||
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
return pTexture;
|
||||
}
|
||||
|
||||
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level)
|
||||
{
|
||||
u32* pBuffer = (u32*)buffer;
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0);
|
||||
u32* pIn = pBuffer;
|
||||
|
||||
bool bExpand = false;
|
||||
|
||||
if (fmt == D3DFMT_A8P8) {
|
||||
fmt = D3DFMT_A8L8;
|
||||
bExpand = true;
|
||||
}
|
||||
switch (fmt)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
if(pitch * 4 == Lock.Pitch && !swap_r_b)
|
||||
{
|
||||
memcpy(Lock.pBits, pBuffer, Lock.Pitch*height);
|
||||
}
|
||||
else if (!swap_r_b)
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 4);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if _M_SSE >= 0x301
|
||||
// Uses SSSE3 intrinsics to optimize RGBA -> BGRA swizzle:
|
||||
if (cpu_info.bSSSE3) {
|
||||
ConvertRGBA_BGRA_SSSE3((u32 *)Lock.pBits, Lock.Pitch, pIn, width, height, pitch);
|
||||
} else
|
||||
#endif
|
||||
// Uses SSE2 intrinsics to optimize RGBA -> BGRA swizzle:
|
||||
{
|
||||
ConvertRGBA_BGRA_SSE2((u32 *)Lock.pBits, Lock.Pitch, pIn, width, height, pitch);
|
||||
}
|
||||
#if 0
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8 *pIn8 = (u8 *)pIn;
|
||||
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for (int x = 0; x < width * 4; x += 4)
|
||||
{
|
||||
pBits[x + 0] = pIn8[x + 2];
|
||||
pBits[x + 1] = pIn8[x + 1];
|
||||
pBits[x + 2] = pIn8[x + 0];
|
||||
pBits[x + 3] = pIn8[x + 3];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case D3DFMT_L8:
|
||||
case D3DFMT_A8:
|
||||
case D3DFMT_A4L4:
|
||||
{
|
||||
const u8 *pIn = buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
{
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A8L8:
|
||||
{
|
||||
if (bExpand) { // I8
|
||||
const u8 *pIn = buffer;
|
||||
// TODO(XK): Find a better way that does not involve either unpacking
|
||||
// or downsampling (i.e. A4L4)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for(int i = 0; i < width * 2; i += 2) {
|
||||
pBits[i] = pIn[i / 2];
|
||||
pBits[i + 1] = pIn[i / 2];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
} else { // IA8
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
|
||||
break;
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace DX9
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt = D3DFMT_A8R8G8B8, bool swap_r_b = false, int levels = 1);
|
||||
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level = 0);
|
||||
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height);
|
||||
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height);
|
||||
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt);
|
||||
}
|
||||
|
||||
} // namespace DX9
|
|
@ -1,463 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common.h"
|
||||
#include "StringUtil.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "Render.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "VertexShaderCache.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
CD3DFont font;
|
||||
|
||||
#define MAX_NUM_VERTICES 50*6
|
||||
struct FONT2DVERTEX {
|
||||
float x,y,z;
|
||||
float rhw;
|
||||
u32 color;
|
||||
float tu, tv;
|
||||
};
|
||||
|
||||
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
|
||||
|
||||
inline FONT2DVERTEX InitFont2DVertex(float x, float y, u32 color, float tu, float tv)
|
||||
{
|
||||
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
|
||||
return v;
|
||||
}
|
||||
|
||||
CD3DFont::CD3DFont()
|
||||
{
|
||||
m_pTexture = NULL;
|
||||
m_pVB = NULL;
|
||||
}
|
||||
|
||||
enum {m_dwTexWidth = 512, m_dwTexHeight = 512};
|
||||
|
||||
int CD3DFont::Init()
|
||||
{
|
||||
// Create vertex buffer for the letters
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = dev->CreateVertexBuffer(MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
|
||||
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &m_pVB, NULL)))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
|
||||
|
||||
// Prepare to create a bitmap
|
||||
unsigned int* pBitmapBits;
|
||||
BITMAPINFO bmi;
|
||||
ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
|
||||
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
|
||||
// Create a DC and a bitmap for the font
|
||||
HDC hDC = CreateCompatibleDC(NULL);
|
||||
HBITMAP hbmBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&pBitmapBits, NULL, 0);
|
||||
SetMapMode(hDC, MM_TEXT);
|
||||
|
||||
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an
|
||||
// antialiased font, but this is not guaranteed.
|
||||
// We definitely don't want to get it cleartype'd, anyway.
|
||||
int m_dwFontHeight = 24;
|
||||
int nHeight = -MulDiv(m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72);
|
||||
int dwBold = FW_NORMAL; ///FW_BOLD
|
||||
HFONT hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0,
|
||||
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
||||
VARIABLE_PITCH, _T("Tahoma"));
|
||||
if (NULL == hFont)
|
||||
return E_FAIL;
|
||||
|
||||
HGDIOBJ hOldbmBitmap = SelectObject(hDC, hbmBitmap);
|
||||
HGDIOBJ hOldFont = SelectObject(hDC, hFont);
|
||||
|
||||
// Set text properties
|
||||
SetTextColor(hDC, 0xFFFFFF);
|
||||
SetBkColor (hDC, 0);
|
||||
SetTextAlign(hDC, TA_TOP);
|
||||
|
||||
// Loop through all printable characters and output them to the bitmap
|
||||
// Meanwhile, keep track of the corresponding tex coords for each character.
|
||||
int x = 0, y = 0;
|
||||
char str[2] = "\0";
|
||||
for (int c = 0; c < 127 - 32; c++)
|
||||
{
|
||||
str[0] = c + 32;
|
||||
SIZE size;
|
||||
GetTextExtentPoint32A(hDC, str, 1, &size);
|
||||
if ((int)(x+size.cx+1) > m_dwTexWidth)
|
||||
{
|
||||
x = 0;
|
||||
y += size.cy + 1;
|
||||
}
|
||||
|
||||
ExtTextOutA(hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL);
|
||||
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
|
||||
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
|
||||
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
|
||||
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
|
||||
|
||||
x += size.cx + 3; // 3 to work around annoying ij conflict (part of the j ends up with the i)
|
||||
}
|
||||
|
||||
// Create a new texture for the font
|
||||
// possible optimization: store the converted data in a buffer and fill the texture on creation.
|
||||
// That way, we can use a static texture
|
||||
hr = dev->CreateTexture(m_dwTexWidth, m_dwTexHeight, 1, D3DUSAGE_DYNAMIC,
|
||||
D3DFMT_A4R4G4B4, D3DPOOL_DEFAULT, &m_pTexture, NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create font texture");
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Lock the surface and write the alpha values for the set pixels
|
||||
D3DLOCKED_RECT d3dlr;
|
||||
m_pTexture->LockRect(0, &d3dlr, 0, D3DLOCK_DISCARD);
|
||||
int bAlpha; // 4-bit measure of pixel intensity
|
||||
|
||||
for (y = 0; y < m_dwTexHeight; y++)
|
||||
{
|
||||
u16 *pDst16 = (u16*)((u8 *)d3dlr.pBits + y * d3dlr.Pitch);
|
||||
for (x = 0; x < m_dwTexWidth; x++)
|
||||
{
|
||||
bAlpha = ((pBitmapBits[m_dwTexWidth * y + x] & 0xff) >> 4);
|
||||
pDst16[x] = (bAlpha << 12) | 0x0fff;
|
||||
}
|
||||
}
|
||||
|
||||
// Done updating texture, so clean up used objects
|
||||
m_pTexture->UnlockRect(0);
|
||||
|
||||
SelectObject(hDC, hOldbmBitmap);
|
||||
DeleteObject(hbmBitmap);
|
||||
|
||||
SelectObject(hDC, hOldFont);
|
||||
DeleteObject(hFont);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int CD3DFont::Shutdown()
|
||||
{
|
||||
m_pVB->Release();
|
||||
m_pVB = NULL;
|
||||
m_pTexture->Release();
|
||||
m_pTexture = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
const int RS[6][2] =
|
||||
{
|
||||
{D3DRS_ALPHABLENDENABLE, TRUE},
|
||||
{D3DRS_SRCBLEND, D3DBLEND_SRCALPHA},
|
||||
{D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA},
|
||||
{D3DRS_CULLMODE, D3DCULL_NONE},
|
||||
{D3DRS_ZENABLE, FALSE},
|
||||
{D3DRS_FOGENABLE, FALSE},
|
||||
};
|
||||
const int TS[6][2] =
|
||||
{
|
||||
{D3DTSS_COLOROP, D3DTOP_MODULATE},
|
||||
{D3DTSS_COLORARG1, D3DTA_TEXTURE},
|
||||
{D3DTSS_COLORARG2, D3DTA_DIFFUSE },
|
||||
{D3DTSS_ALPHAOP, D3DTOP_MODULATE },
|
||||
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
|
||||
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
|
||||
};
|
||||
|
||||
void RestoreShaders()
|
||||
{
|
||||
D3D::SetTexture(0, 0);
|
||||
D3D::RefreshStreamSource(0);
|
||||
D3D::RefreshIndices();
|
||||
D3D::RefreshVertexDeclaration();
|
||||
D3D::RefreshPixelShader();
|
||||
D3D::RefreshVertexShader();
|
||||
}
|
||||
|
||||
void RestoreRenderStates()
|
||||
{
|
||||
RestoreShaders();
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
D3D::RefreshRenderState((_D3DRENDERSTATETYPE)RS[i][0]);
|
||||
D3D::RefreshTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]));
|
||||
}
|
||||
}
|
||||
|
||||
void CD3DFont::SetRenderStates()
|
||||
{
|
||||
D3D::SetTexture(0, m_pTexture);
|
||||
|
||||
D3D::ChangePixelShader(0);
|
||||
D3D::ChangeVertexShader(0);
|
||||
D3D::ChangeVertexDeclaration(0);
|
||||
dev->SetFVF(D3DFVF_FONT2DVERTEX);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
D3D::ChangeRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS[i][1]);
|
||||
D3D::ChangeTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText)
|
||||
{
|
||||
if (!m_pVB)
|
||||
return 0;
|
||||
|
||||
SetRenderStates();
|
||||
D3D::ChangeStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
|
||||
|
||||
float vpWidth = 1;
|
||||
float vpHeight = 1;
|
||||
|
||||
float sx = x*vpWidth-0.5f;
|
||||
float sy = y*vpHeight-0.5f;
|
||||
|
||||
float fStartX = sx;
|
||||
|
||||
float invLineHeight = 1.0f / ((m_fTexCoords[0][3] - m_fTexCoords[0][1]) * m_dwTexHeight);
|
||||
// Fill vertex buffer
|
||||
FONT2DVERTEX* pVertices;
|
||||
int dwNumTriangles = 0L;
|
||||
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
|
||||
|
||||
const char *oldstrText=strText;
|
||||
//First, let's measure the text
|
||||
float tw=0;
|
||||
float mx=0;
|
||||
float maxx=0;
|
||||
|
||||
while (*strText)
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if (c == ('\n'))
|
||||
mx = 0;
|
||||
if (c < (' '))
|
||||
continue;
|
||||
|
||||
float tx1 = m_fTexCoords[c-32][0];
|
||||
float tx2 = m_fTexCoords[c-32][2];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
w *= (fXScale*vpHeight)*invLineHeight;
|
||||
mx += w + spacing*fXScale*vpWidth;
|
||||
if (mx > maxx) maxx = mx;
|
||||
}
|
||||
|
||||
float offset = -maxx/2;
|
||||
strText = oldstrText;
|
||||
|
||||
float wScale = (fXScale*vpHeight)*invLineHeight;
|
||||
float hScale = (fYScale*vpHeight)*invLineHeight;
|
||||
|
||||
// Let's draw it
|
||||
while (*strText)
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if (c == ('\n'))
|
||||
{
|
||||
sx = fStartX;
|
||||
sy += fYScale*vpHeight;
|
||||
}
|
||||
if (c < (' '))
|
||||
continue;
|
||||
|
||||
c -= 32;
|
||||
float tx1 = m_fTexCoords[c][0];
|
||||
float ty1 = m_fTexCoords[c][1];
|
||||
float tx2 = m_fTexCoords[c][2];
|
||||
float ty2 = m_fTexCoords[c][3];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
float h = (ty2-ty1)*m_dwTexHeight;
|
||||
|
||||
w *= wScale;
|
||||
h *= hScale;
|
||||
|
||||
FONT2DVERTEX v[6];
|
||||
v[0] = InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
|
||||
v[1] = InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
|
||||
v[2] = InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
|
||||
v[3] = InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
|
||||
v[4] = v[2];
|
||||
v[5] = v[1];
|
||||
|
||||
memcpy(pVertices, v, 6*sizeof(FONT2DVERTEX));
|
||||
|
||||
pVertices+=6;
|
||||
dwNumTriangles += 2;
|
||||
|
||||
if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6))
|
||||
{
|
||||
// Unlock, render, and relock the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
|
||||
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
|
||||
dwNumTriangles = 0;
|
||||
}
|
||||
sx += w + spacing*fXScale*vpWidth;
|
||||
}
|
||||
|
||||
// Unlock and render the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
if (dwNumTriangles > 0)
|
||||
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
|
||||
RestoreRenderStates();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* Explanation of texture copying via drawShadedTexQuad and drawShadedTexSubQuad:
|
||||
From MSDN: "When rendering 2D output using pre-transformed vertices,
|
||||
care must be taken to ensure that each texel area correctly corresponds
|
||||
to a single pixel area, otherwise texture distortion can occur."
|
||||
=> We need to subtract 0.5 from the vertex positions to properly map texels to pixels.
|
||||
HOWEVER, the MSDN article talks about D3DFVF_XYZRHW vertices, which bypass the programmable pipeline.
|
||||
Since we're using D3DFVF_XYZW and the programmable pipeline though, the vertex positions
|
||||
are normalized to [-1;+1], i.e. we need to scale the -0.5 offset by the texture dimensions.
|
||||
For example see a texture with a width of 640 pixels:
|
||||
"Expected" coordinate range when using D3DFVF_XYZRHW: [0;640]
|
||||
Normalizing this coordinate range for D3DFVF_XYZW: [0;640]->[-320;320]->[-1;1]
|
||||
i.e. we're subtracting width/2 and dividing by width/2
|
||||
BUT: The actual range when using D3DFVF_XYZRHW needs to be [-0.5;639.5] because of the need for exact texel->pixel mapping.
|
||||
We can still apply the same normalizing procedure though:
|
||||
[-0.5;639.5]->[-320-0.5;320-0.5]->[-1-0.5/320;1-0.5/320]
|
||||
|
||||
So generally speaking the correct coordinate range is [-1-0.5/(w/2);1-0.5/(w/2)]
|
||||
which can be simplified to [-1-1/w;1-1/w].
|
||||
|
||||
Note that while for D3DFVF_XYZRHW the y coordinate of the bottom of the screen is positive,
|
||||
it's negative for D3DFVF_XYZW. This is why we need to _add_ 1/h for the second position component instead of subtracting it.
|
||||
|
||||
For a detailed explanation of this read the MSDN article "Directly Mapping Texels to Pixels (Direct3D 9)".
|
||||
*/
|
||||
void drawShadedTexQuad(IDirect3DTexture9 *texture,
|
||||
const RECT *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader,
|
||||
float Gamma)
|
||||
{
|
||||
float sw = 1.0f /(float) SourceWidth;
|
||||
float sh = 1.0f /(float) SourceHeight;
|
||||
float dw = 1.0f /(float) DestWidth;
|
||||
float dh = 1.0f /(float) DestHeight;
|
||||
float u1=((float)rSource->left) * sw;
|
||||
float u2=((float)rSource->right) * sw;
|
||||
float v1=((float)rSource->top) * sh;
|
||||
float v2=((float)rSource->bottom) * sh;
|
||||
float g = 1.0f/Gamma;
|
||||
|
||||
const struct Q2DVertex { float x,y,z,rhw,u,v,w,h,G; } coords[4] = {
|
||||
{-1.0f - dw,-1.0f + dh, 0.0f,1.0f, u1, v2, sw, sh, g},
|
||||
{-1.0f - dw, 1.0f + dh, 0.0f,1.0f, u1, v1, sw, sh, g},
|
||||
{ 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh, g},
|
||||
{ 1.0f - dw, 1.0f + dh, 0.0f,1.0f, u2, v1, sw, sh, g}
|
||||
};
|
||||
D3D::ChangeVertexShader(Vshader);
|
||||
D3D::ChangePixelShader(PShader);
|
||||
D3D::SetTexture(0, texture);
|
||||
D3D::ChangeVertexDeclaration(0);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE1(2));
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
|
||||
const MathUtil::Rectangle<float> *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
const MathUtil::Rectangle<float> *rDest,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader,
|
||||
float Gamma)
|
||||
{
|
||||
float sw = 1.0f /(float) SourceWidth;
|
||||
float sh = 1.0f /(float) SourceHeight;
|
||||
float dw = 1.0f /(float) DestWidth;
|
||||
float dh = 1.0f /(float) DestHeight;
|
||||
float u1= rSource->left * sw;
|
||||
float u2= rSource->right * sw;
|
||||
float v1= rSource->top * sh;
|
||||
float v2= rSource->bottom * sh;
|
||||
float g = 1.0f/Gamma;
|
||||
|
||||
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,G; } coords[4] = {
|
||||
{ rDest->left - dw , rDest->top + dh, 1.0f,1.0f, u1, v2, sw, sh, g},
|
||||
{ rDest->left - dw , rDest->bottom + dh, 1.0f,1.0f, u1, v1, sw, sh, g},
|
||||
{ rDest->right - dw , rDest->top + dh, 1.0f,1.0f, u2, v2, sw, sh, g},
|
||||
{ rDest->right - dw , rDest->bottom + dh, 1.0f,1.0f, u2, v1, sw, sh, g}
|
||||
};
|
||||
D3D::ChangeVertexShader(Vshader);
|
||||
D3D::ChangePixelShader(PShader);
|
||||
D3D::SetTexture(0, texture);
|
||||
D3D::ChangeVertexDeclaration(0);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE1(2));
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
// Fills a certain area of the current render target with the specified color
|
||||
// Z buffer disabled; destination coordinates normalized to (-1;1)
|
||||
void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2)
|
||||
{
|
||||
struct CQVertex { float x, y, z, rhw; u32 col; } coords[4] = {
|
||||
{ x1, y2, 0.f, 1.f, Color },
|
||||
{ x2, y2, 0.f, 1.f, Color },
|
||||
{ x1, y1, 0.f, 1.f, Color },
|
||||
{ x2, y1, 0.f, 1.f, Color },
|
||||
};
|
||||
D3D::ChangeVertexShader(VertexShaderCache::GetClearVertexShader());
|
||||
D3D::ChangePixelShader(PixelShaderCache::GetClearProgram());
|
||||
D3D::ChangeVertexDeclaration(0);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(CQVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader)
|
||||
{
|
||||
struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = {
|
||||
{-1.0f, 1.0f, z, 1.0f, Color},
|
||||
{ 1.0f, 1.0f, z, 1.0f, Color},
|
||||
{ 1.0f, -1.0f, z, 1.0f, Color},
|
||||
{-1.0f, -1.0f, z, 1.0f, Color}
|
||||
};
|
||||
D3D::ChangeVertexShader(Vshader);
|
||||
D3D::ChangePixelShader(PShader);
|
||||
D3D::ChangeVertexDeclaration(0);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace DX9
|
|
@ -1,79 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include <math.h>
|
||||
#include <MathUtil.h>
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
// Font creation flags
|
||||
#define D3DFONT_BOLD 0x0001
|
||||
#define D3DFONT_ITALIC 0x0002
|
||||
|
||||
// Font rendering flags
|
||||
#define D3DFONT_CENTERED 0x0001
|
||||
|
||||
//a cut-down variant of the DXSDK CD3DFont class
|
||||
class CD3DFont
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 m_pTexture; // The d3d texture for this font
|
||||
LPDIRECT3DVERTEXBUFFER9 m_pVB; // VertexBuffer for rendering text
|
||||
//int m_dwTexWidth; // Texture dimensions
|
||||
//int m_dwTexHeight;
|
||||
float m_fTextScale;
|
||||
float m_fTexCoords[128-32][4];
|
||||
|
||||
public:
|
||||
CD3DFont();
|
||||
// 2D (no longer 3D) text drawing function
|
||||
// Initializing and destroying device-dependent objects
|
||||
void SetRenderStates();
|
||||
int Init();
|
||||
int Shutdown();
|
||||
int DrawTextScaled( float x, float y,
|
||||
float fXScale, float fYScale,
|
||||
float spacing, u32 dwColor,
|
||||
const char* strText);
|
||||
|
||||
|
||||
// Constructor / destructor
|
||||
//~CD3DFont();
|
||||
};
|
||||
|
||||
extern CD3DFont font;
|
||||
|
||||
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1=0, float v1=0, float u2=1, float v2=1);
|
||||
void drawShadedTexQuad(IDirect3DTexture9 *texture,
|
||||
const RECT *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader,
|
||||
float Gamma = 1.0f);
|
||||
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
|
||||
const MathUtil::Rectangle<float> *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
const MathUtil::Rectangle<float> *rDest,
|
||||
int DestWidth,
|
||||
int DestHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader,
|
||||
float Gamma = 1.0f);
|
||||
void drawClearQuad(u32 Color, float z, IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader);
|
||||
void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2);
|
||||
|
||||
void SaveRenderStates();
|
||||
void RestoreRenderStates();
|
||||
}
|
||||
|
||||
} // namespace DX9
|
|
@ -1,225 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "Render.h"
|
||||
#include "FramebufferManager.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "TextureConverter.h"
|
||||
#include "HW/Memmap.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
// TODO: this is probably somewhere else
|
||||
#define SAFE_RELEASE(p) if (p) { (p)->Release(); (p) = NULL; }
|
||||
|
||||
#undef CHECK
|
||||
#define CHECK(hr, Message, ...) if (FAILED(hr)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
|
||||
|
||||
inline void GetSurface(IDirect3DTexture9* texture, IDirect3DSurface9** surface)
|
||||
{
|
||||
if (!texture) return;
|
||||
texture->GetSurfaceLevel(0, surface);
|
||||
}
|
||||
|
||||
FramebufferManager::Efb FramebufferManager::s_efb;
|
||||
|
||||
FramebufferManager::FramebufferManager()
|
||||
{
|
||||
bool depth_textures_supported = true;
|
||||
int target_width = Renderer::GetTargetWidth();
|
||||
int target_height = Renderer::GetTargetHeight();
|
||||
s_efb.color_surface_Format = D3DFMT_A8R8G8B8;
|
||||
|
||||
// EFB color texture - primary render target
|
||||
HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb.color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb.color_texture, NULL);
|
||||
GetSurface(s_efb.color_texture, &s_efb.color_surface);
|
||||
CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
|
||||
// Render buffer for AccessEFB (color data)
|
||||
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb.color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb.colorRead_texture, NULL);
|
||||
GetSurface(s_efb.colorRead_texture, &s_efb.color_ReadBuffer);
|
||||
CHECK(hr, "Create Color Read Texture (hr=%#x)", hr);
|
||||
|
||||
// AccessEFB - Sysmem buffer used to retrieve the pixel data from color_ReadBuffer
|
||||
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb.color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb.color_OffScreenReadBuffer, NULL);
|
||||
CHECK(hr, "Create offscreen color surface (hr=%#x)", hr);
|
||||
|
||||
// Select a Z-buffer texture format with hardware support
|
||||
s_efb.depth_surface_Format = D3D::GetSupportedDepthTextureFormat();
|
||||
if (s_efb.depth_surface_Format == D3DFMT_UNKNOWN)
|
||||
{
|
||||
// workaround for Intel GPUs etc: only create a depth _surface_
|
||||
depth_textures_supported = false;
|
||||
s_efb.depth_surface_Format = D3D::GetSupportedDepthSurfaceFormat(s_efb.color_surface_Format);
|
||||
ERROR_LOG(VIDEO, "No supported depth texture format found, disabling Z peeks for EFB access.");
|
||||
}
|
||||
|
||||
if (depth_textures_supported)
|
||||
{
|
||||
// EFB depth buffer - primary depth buffer
|
||||
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb.depth_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb.depth_texture, NULL);
|
||||
GetSurface(s_efb.depth_texture, &s_efb.depth_surface);
|
||||
CHECK(hr, "Framebuffer depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
|
||||
// Render buffer for AccessEFB (depth data)
|
||||
D3DFORMAT DepthTexFormats[2];
|
||||
DepthTexFormats[0] = D3DFMT_D24X8;
|
||||
// This is expected to work on all hardware
|
||||
DepthTexFormats[1] = D3DFMT_A8R8G8B8;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (D3D::CheckTextureSupport(D3DUSAGE_RENDERTARGET, DepthTexFormats[i]))
|
||||
{
|
||||
s_efb.depth_ReadBuffer_Format = DepthTexFormats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb.depth_ReadBuffer_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb.depthRead_texture, NULL);
|
||||
GetSurface(s_efb.depthRead_texture, &s_efb.depth_ReadBuffer);
|
||||
CHECK(hr, "Create depth read texture (hr=%#x)", hr);
|
||||
|
||||
// AccessEFB - Sysmem buffer used to retrieve the pixel data from depth_ReadBuffer
|
||||
hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb.depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb.depth_OffScreenReadBuffer, NULL);
|
||||
CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr);
|
||||
}
|
||||
else if (s_efb.depth_surface_Format)
|
||||
{
|
||||
// just create a depth surface
|
||||
hr = D3D::dev->CreateDepthStencilSurface(target_width, target_height, s_efb.depth_surface_Format, D3DMULTISAMPLE_NONE, 0, FALSE, &s_efb.depth_surface, NULL);
|
||||
CHECK(hr, "Framebuffer depth surface (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
}
|
||||
|
||||
// ReinterpretPixelData - EFB color data will be copy-converted to this texture and the buffers are swapped then
|
||||
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb.color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb.color_reinterpret_texture, NULL);
|
||||
GetSurface(s_efb.color_reinterpret_texture, &s_efb.color_reinterpret_surface);
|
||||
CHECK(hr, "Create color reinterpret texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
}
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
{
|
||||
SAFE_RELEASE(s_efb.depth_surface);
|
||||
SAFE_RELEASE(s_efb.color_surface);
|
||||
SAFE_RELEASE(s_efb.color_ReadBuffer);
|
||||
SAFE_RELEASE(s_efb.depth_ReadBuffer);
|
||||
SAFE_RELEASE(s_efb.color_OffScreenReadBuffer);
|
||||
SAFE_RELEASE(s_efb.depth_OffScreenReadBuffer);
|
||||
SAFE_RELEASE(s_efb.color_texture);
|
||||
SAFE_RELEASE(s_efb.colorRead_texture);
|
||||
SAFE_RELEASE(s_efb.depth_texture);
|
||||
SAFE_RELEASE(s_efb.depthRead_texture);
|
||||
SAFE_RELEASE(s_efb.color_reinterpret_texture);
|
||||
SAFE_RELEASE(s_efb.color_reinterpret_surface);
|
||||
s_efb.color_surface_Format = D3DFMT_UNKNOWN;
|
||||
s_efb.depth_surface_Format = D3DFMT_UNKNOWN;
|
||||
s_efb.depth_ReadBuffer_Format = D3DFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 tex;
|
||||
D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET,
|
||||
s_efb.color_surface_Format, D3DPOOL_DEFAULT, &tex, NULL);
|
||||
|
||||
return new XFBSource(tex);
|
||||
}
|
||||
|
||||
void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc)
|
||||
{
|
||||
TargetRectangle targetSource;
|
||||
|
||||
targetSource.top = ScaleToVirtualXfbHeight(sourceRc.top, Renderer::GetBackbufferHeight());
|
||||
targetSource.bottom = ScaleToVirtualXfbHeight(sourceRc.bottom, Renderer::GetBackbufferHeight());
|
||||
targetSource.left = ScaleToVirtualXfbWidth(sourceRc.left, Renderer::GetBackbufferWidth());
|
||||
targetSource.right = ScaleToVirtualXfbWidth(sourceRc.right, Renderer::GetBackbufferWidth());
|
||||
|
||||
*width = targetSource.right - targetSource.left;
|
||||
*height = targetSource.bottom - targetSource.top;
|
||||
}
|
||||
|
||||
void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||
const MathUtil::Rectangle<float> &drawrc, int width, int height) const
|
||||
{
|
||||
D3D::drawShadedTexSubQuad(texture, &sourcerc, texWidth, texHeight, &drawrc, width , height,
|
||||
PixelShaderCache::GetColorCopyProgram(0), VertexShaderCache::GetSimpleVertexShader(0));
|
||||
}
|
||||
|
||||
void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
|
||||
{
|
||||
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, texture);
|
||||
}
|
||||
|
||||
void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma)
|
||||
{
|
||||
u8* xfb_in_ram = Memory::GetPointer(xfbAddr);
|
||||
if (!xfb_in_ram)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
|
||||
return;
|
||||
}
|
||||
|
||||
TargetRectangle targetRc = g_renderer->ConvertEFBRectangle(sourceRc);
|
||||
TextureConverter::EncodeToRamYUYV(GetEFBColorTexture(), targetRc, xfb_in_ram, fbWidth, fbHeight,Gamma);
|
||||
}
|
||||
|
||||
void XFBSource::CopyEFB(float Gamma)
|
||||
{
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
// Copy EFB data to XFB and restore render target again
|
||||
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
||||
texture->GetSurfaceLevel(0, &Rendersurf);
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = texWidth;
|
||||
vp.Height = texHeight;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
|
||||
RECT sourcerect;
|
||||
sourcerect.bottom = sourceRc.bottom;
|
||||
sourcerect.left = sourceRc.left;
|
||||
sourcerect.right = sourceRc.right;
|
||||
sourcerect.top = sourceRc.top;
|
||||
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
|
||||
D3D::drawShadedTexQuad(
|
||||
FramebufferManager::GetEFBColorTexture(),
|
||||
&sourcerect,
|
||||
Renderer::GetTargetWidth(),
|
||||
Renderer::GetTargetHeight(),
|
||||
texWidth,
|
||||
texHeight,
|
||||
PixelShaderCache::GetColorCopyProgram( g_ActiveConfig.iMultisampleMode),
|
||||
VertexShaderCache::GetSimpleVertexShader( g_ActiveConfig.iMultisampleMode),
|
||||
Gamma);
|
||||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
D3D::SetTexture(0, NULL);
|
||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||
|
||||
Rendersurf->Release();
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
} // namespace DX9
|
|
@ -1,125 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "FramebufferManagerBase.h"
|
||||
|
||||
// On the GameCube, the game sends a request for the graphics processor to
|
||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||
// called the XFB (External Framebuffer). The size and location of the XFB is
|
||||
// decided at the time of the copy, and the format is always YUYV. The video
|
||||
// interface is given a pointer to the XFB, which will be decoded and
|
||||
// displayed on the TV.
|
||||
//
|
||||
// There are two ways for Dolphin to emulate this:
|
||||
//
|
||||
// Real XFB mode:
|
||||
//
|
||||
// Dolphin will behave like the GameCube and encode the EFB to
|
||||
// a portion of GameCube RAM. The emulated video interface will decode the data
|
||||
// for output to the screen.
|
||||
//
|
||||
// Advantages: Behaves exactly like the GameCube.
|
||||
// Disadvantages: Resolution will be limited.
|
||||
//
|
||||
// Virtual XFB mode:
|
||||
//
|
||||
// When a request is made to copy the EFB to an XFB, Dolphin
|
||||
// will remember the RAM location and size of the XFB in a Virtual XFB list.
|
||||
// The video interface will look up the XFB in the list and use the enhanced
|
||||
// data stored there, if available.
|
||||
//
|
||||
// Advantages: Enables high resolution graphics, better than real hardware.
|
||||
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
||||
// possible but uncommon), the Virtual XFB will not capture this information.
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
struct XFBSource : public XFBSourceBase
|
||||
{
|
||||
XFBSource(LPDIRECT3DTEXTURE9 tex) : texture(tex) {}
|
||||
~XFBSource() { texture->Release(); }
|
||||
|
||||
void Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||
const MathUtil::Rectangle<float> &drawrc, int width, int height) const;
|
||||
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||
void CopyEFB(float Gamma);
|
||||
|
||||
LPDIRECT3DTEXTURE9 const texture;
|
||||
};
|
||||
|
||||
class FramebufferManager : public FramebufferManagerBase
|
||||
{
|
||||
public:
|
||||
FramebufferManager();
|
||||
~FramebufferManager();
|
||||
|
||||
static LPDIRECT3DTEXTURE9 GetEFBColorTexture() { return s_efb.color_texture; }
|
||||
static LPDIRECT3DTEXTURE9 GetEFBDepthTexture() { return s_efb.depth_texture; }
|
||||
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorRTSurface() { return s_efb.color_surface; }
|
||||
static LPDIRECT3DSURFACE9 GetEFBDepthRTSurface() { return s_efb.depth_surface; }
|
||||
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface() { return s_efb.color_OffScreenReadBuffer; }
|
||||
static LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface() { return s_efb.depth_OffScreenReadBuffer; }
|
||||
|
||||
static D3DFORMAT GetEFBDepthRTSurfaceFormat() { return s_efb.depth_surface_Format; }
|
||||
static D3DFORMAT GetEFBColorRTSurfaceFormat() { return s_efb.color_surface_Format; }
|
||||
static D3DFORMAT GetEFBDepthReadSurfaceFormat() { return s_efb.depth_ReadBuffer_Format; }
|
||||
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorReadSurface() { return s_efb.color_ReadBuffer; }
|
||||
static LPDIRECT3DSURFACE9 GetEFBDepthReadSurface() { return s_efb.depth_ReadBuffer; }
|
||||
|
||||
static LPDIRECT3DTEXTURE9 GetEFBColorReinterpretTexture() { return s_efb.color_reinterpret_texture; }
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorReinterpretSurface() { return s_efb.color_reinterpret_surface; }
|
||||
static void SwapReinterpretTexture()
|
||||
{
|
||||
LPDIRECT3DSURFACE9 swapsurf = GetEFBColorReinterpretSurface();
|
||||
LPDIRECT3DTEXTURE9 swaptex = GetEFBColorReinterpretTexture();
|
||||
s_efb.color_reinterpret_surface = GetEFBColorRTSurface();
|
||||
s_efb.color_reinterpret_texture = GetEFBColorTexture();
|
||||
s_efb.color_surface = swapsurf;
|
||||
s_efb.color_texture = swaptex;
|
||||
}
|
||||
|
||||
private:
|
||||
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||
void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc);
|
||||
|
||||
void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma);
|
||||
|
||||
static struct Efb
|
||||
{
|
||||
Efb() : color_texture(NULL), colorRead_texture(NULL), depth_texture(NULL), depthRead_texture(NULL),
|
||||
color_reinterpret_texture(NULL), color_reinterpret_surface(NULL),
|
||||
depth_surface(NULL), color_surface(NULL), color_ReadBuffer(NULL), depth_ReadBuffer(NULL),
|
||||
color_OffScreenReadBuffer(NULL), depth_OffScreenReadBuffer(NULL),
|
||||
color_surface_Format(D3DFMT_UNKNOWN), depth_surface_Format(D3DFMT_UNKNOWN),
|
||||
depth_ReadBuffer_Format(D3DFMT_UNKNOWN) {}
|
||||
|
||||
LPDIRECT3DTEXTURE9 color_texture;//Texture that contains the color data of the render target
|
||||
LPDIRECT3DTEXTURE9 colorRead_texture;//1 pixel texture for temporal data store
|
||||
LPDIRECT3DTEXTURE9 depth_texture;//Texture that contains the depth data of the render target
|
||||
LPDIRECT3DTEXTURE9 depthRead_texture;//4 pixel texture for temporal data store
|
||||
|
||||
LPDIRECT3DTEXTURE9 color_reinterpret_texture;//buffer used for ReinterpretPixelData
|
||||
LPDIRECT3DSURFACE9 color_reinterpret_surface;//corresponding surface
|
||||
|
||||
LPDIRECT3DSURFACE9 depth_surface;//Depth Surface
|
||||
LPDIRECT3DSURFACE9 color_surface;//Color Surface
|
||||
LPDIRECT3DSURFACE9 color_ReadBuffer;//Surface 0 of colorRead_texture
|
||||
LPDIRECT3DSURFACE9 depth_ReadBuffer;//Surface 0 of depthRead_texture
|
||||
LPDIRECT3DSURFACE9 color_OffScreenReadBuffer;//System memory Surface that can be locked to retrieve the data
|
||||
LPDIRECT3DSURFACE9 depth_OffScreenReadBuffer;//System memory Surface that can be locked to retrieve the data
|
||||
|
||||
D3DFORMAT color_surface_Format;//Format of the color Surface
|
||||
D3DFORMAT depth_surface_Format;//Format of the Depth Surface
|
||||
D3DFORMAT depth_ReadBuffer_Format;//Format of the Depth color Read Surface
|
||||
} s_efb;
|
||||
};
|
||||
|
||||
} // namespace DX9
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef _GLOBALS_H_
|
||||
#define _GLOBALS_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
||||
#endif // _GLOBALS_H_
|
|
@ -1,179 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include "x64Emitter.h"
|
||||
#include "x64ABI.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
#include "CPMemory.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "VertexManager.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class D3DVertexFormat : public NativeVertexFormat
|
||||
{
|
||||
LPDIRECT3DVERTEXDECLARATION9 d3d_decl;
|
||||
|
||||
public:
|
||||
D3DVertexFormat() : d3d_decl(NULL) {}
|
||||
~D3DVertexFormat();
|
||||
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
|
||||
virtual void SetupVertexPointers();
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
D3DVERTEXELEMENT9 elements[32];
|
||||
int num_elements;
|
||||
#endif
|
||||
};
|
||||
|
||||
NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
|
||||
{
|
||||
return new D3DVertexFormat();
|
||||
}
|
||||
|
||||
void DX9::VertexManager::GetElements(NativeVertexFormat* format, D3DVERTEXELEMENT9** elems, int* num)
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
*elems = ((D3DVertexFormat*)format)->elements;
|
||||
*num = ((D3DVertexFormat*)format)->num_elements;
|
||||
#else
|
||||
*elems = NULL;
|
||||
*num = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
D3DVertexFormat::~D3DVertexFormat()
|
||||
{
|
||||
if (d3d_decl)
|
||||
{
|
||||
d3d_decl->Release();
|
||||
d3d_decl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
D3DDECLTYPE VarToD3D(VarType t, int size)
|
||||
{
|
||||
if (t < 0 || t > 4) {
|
||||
PanicAlert("VarToD3D: Invalid VarType %i", t);
|
||||
}
|
||||
static const D3DDECLTYPE lookup1[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT1,
|
||||
};
|
||||
static const D3DDECLTYPE lookup2[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_SHORT2N, D3DDECLTYPE_USHORT2N, D3DDECLTYPE_FLOAT2,
|
||||
};
|
||||
static const D3DDECLTYPE lookup3[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT3,
|
||||
};
|
||||
// Sadly, D3D9 has no SBYTE4N. D3D10 does, though.
|
||||
static const D3DDECLTYPE lookup4[5] = {
|
||||
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UBYTE4N, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_USHORT4N, D3DDECLTYPE_FLOAT4,
|
||||
};
|
||||
D3DDECLTYPE retval = D3DDECLTYPE_UNUSED;
|
||||
switch (size)
|
||||
{
|
||||
case 1: retval = lookup1[t]; break;
|
||||
case 2: retval = lookup2[t]; break;
|
||||
case 3: retval = lookup3[t]; break;
|
||||
case 4: retval = lookup4[t]; break;
|
||||
default: break;
|
||||
}
|
||||
if (retval == D3DDECLTYPE_UNUSED) {
|
||||
PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
|
||||
{
|
||||
vertex_stride = _vtx_decl.stride;
|
||||
|
||||
D3DVERTEXELEMENT9 elems[32];
|
||||
memset(elems, 0, sizeof(elems));
|
||||
|
||||
// There's only one stream and it's 0, so the above memset takes care of that - no need to set Stream.
|
||||
// Same for method.
|
||||
|
||||
// So, here we go. First position:
|
||||
int elem_idx = 0;
|
||||
elems[elem_idx].Offset = 0; // Positions are always first, at position 0. Always float3.
|
||||
elems[elem_idx].Type = D3DDECLTYPE_FLOAT3;
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_POSITION;
|
||||
++elem_idx;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (_vtx_decl.normal_offset[i] > 0)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.normal_offset[i];
|
||||
elems[elem_idx].Type = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size);
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_NORMAL;
|
||||
elems[elem_idx].UsageIndex = i;
|
||||
++elem_idx;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (_vtx_decl.color_offset[i] > 0)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.color_offset[i];
|
||||
elems[elem_idx].Type = VarToD3D(_vtx_decl.color_gl_type, 4);
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_COLOR;
|
||||
elems[elem_idx].UsageIndex = i;
|
||||
++elem_idx;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (_vtx_decl.texcoord_offset[i] > 0)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.texcoord_offset[i];
|
||||
elems[elem_idx].Type = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]);
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_TEXCOORD;
|
||||
elems[elem_idx].UsageIndex = i;
|
||||
++elem_idx;
|
||||
}
|
||||
}
|
||||
|
||||
if (_vtx_decl.posmtx_offset != -1)
|
||||
{
|
||||
elems[elem_idx].Offset = _vtx_decl.posmtx_offset;
|
||||
elems[elem_idx].Usage = D3DDECLUSAGE_BLENDINDICES;
|
||||
elems[elem_idx].Type = D3DDECLTYPE_D3DCOLOR;
|
||||
elems[elem_idx].UsageIndex = 0;
|
||||
++elem_idx;
|
||||
}
|
||||
|
||||
// End marker
|
||||
elems[elem_idx].Stream = 0xff;
|
||||
elems[elem_idx].Type = D3DDECLTYPE_UNUSED;
|
||||
++elem_idx;
|
||||
|
||||
if (FAILED(DX9::D3D::dev->CreateVertexDeclaration(elems, &d3d_decl)))
|
||||
{
|
||||
PanicAlert("Failed to create D3D vertex declaration!");
|
||||
return;
|
||||
}
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
memcpy(&elements, elems, sizeof(elems));
|
||||
num_elements = elem_idx;
|
||||
#endif
|
||||
}
|
||||
|
||||
void D3DVertexFormat::SetupVertexPointers()
|
||||
{
|
||||
if (d3d_decl)
|
||||
DX9::D3D::SetVertexDeclaration(d3d_decl);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "Invalid D3D decl");
|
||||
}
|
||||
|
||||
} // namespace DX9
|
|
@ -1,169 +0,0 @@
|
|||
#include "RenderBase.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "PerfQuery.h"
|
||||
|
||||
namespace DX9 {
|
||||
|
||||
PerfQuery::PerfQuery()
|
||||
: m_query_read_pos()
|
||||
, m_query_count()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PerfQuery::~PerfQuery()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PerfQuery::CreateDeviceObjects()
|
||||
{
|
||||
for (int i = 0; i != ArraySize(m_query_buffer); ++i)
|
||||
{
|
||||
D3D::dev->CreateQuery(D3DQUERYTYPE_OCCLUSION, &m_query_buffer[i].query);
|
||||
}
|
||||
ResetQuery();
|
||||
}
|
||||
void PerfQuery::DestroyDeviceObjects()
|
||||
{
|
||||
for (int i = 0; i != ArraySize(m_query_buffer); ++i)
|
||||
{
|
||||
m_query_buffer[i].query->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void PerfQuery::EnableQuery(PerfQueryGroup type)
|
||||
{
|
||||
if (!ShouldEmulate())
|
||||
return;
|
||||
// Is this sane?
|
||||
if (m_query_count > ArraySize(m_query_buffer) / 2)
|
||||
WeakFlush();
|
||||
|
||||
if (ArraySize(m_query_buffer) == m_query_count)
|
||||
{
|
||||
// TODO
|
||||
FlushOne();
|
||||
ERROR_LOG(VIDEO, "Flushed query buffer early!");
|
||||
}
|
||||
|
||||
// start query
|
||||
if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
|
||||
{
|
||||
auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ArraySize(m_query_buffer)];
|
||||
entry.query->Issue(D3DISSUE_BEGIN);
|
||||
entry.query_type = type;
|
||||
++m_query_count;
|
||||
}
|
||||
}
|
||||
|
||||
void PerfQuery::DisableQuery(PerfQueryGroup type)
|
||||
{
|
||||
if (!ShouldEmulate())
|
||||
return;
|
||||
// stop query
|
||||
if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
|
||||
{
|
||||
auto& entry = m_query_buffer[(m_query_read_pos + m_query_count + ArraySize(m_query_buffer)-1) % ArraySize(m_query_buffer)];
|
||||
entry.query->Issue(D3DISSUE_END);
|
||||
}
|
||||
}
|
||||
|
||||
void PerfQuery::ResetQuery()
|
||||
{
|
||||
m_query_count = 0;
|
||||
std::fill_n(m_results, ArraySize(m_results), 0);
|
||||
}
|
||||
|
||||
u32 PerfQuery::GetQueryResult(PerfQueryType type)
|
||||
{
|
||||
if (!ShouldEmulate())
|
||||
return 0;
|
||||
u32 result = 0;
|
||||
|
||||
if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC)
|
||||
{
|
||||
result = m_results[PQG_ZCOMP_ZCOMPLOC];
|
||||
}
|
||||
else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT)
|
||||
{
|
||||
result = m_results[PQG_ZCOMP];
|
||||
}
|
||||
else if (type == PQ_BLEND_INPUT)
|
||||
{
|
||||
result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC];
|
||||
}
|
||||
else if (type == PQ_EFB_COPY_CLOCKS)
|
||||
{
|
||||
result = m_results[PQG_EFB_COPY_CLOCKS];
|
||||
}
|
||||
|
||||
return result / 4;
|
||||
}
|
||||
|
||||
void PerfQuery::FlushOne()
|
||||
{
|
||||
if (!ShouldEmulate())
|
||||
return;
|
||||
auto& entry = m_query_buffer[m_query_read_pos];
|
||||
|
||||
DWORD result = 0;
|
||||
HRESULT hr = S_FALSE;
|
||||
while (hr != S_OK && hr != D3DERR_DEVICELOST)
|
||||
{
|
||||
// TODO: Might cause us to be stuck in an infinite loop!
|
||||
hr = entry.query->GetData(&result, sizeof(result), D3DGETDATA_FLUSH);
|
||||
}
|
||||
|
||||
// NOTE: Reported pixel metrics should be referenced to native resolution
|
||||
m_results[entry.query_type] += (u32)((u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight());
|
||||
|
||||
m_query_read_pos = (m_query_read_pos + 1) % ArraySize(m_query_buffer);
|
||||
--m_query_count;
|
||||
}
|
||||
|
||||
// TODO: could selectively flush things, but I don't think that will do much
|
||||
void PerfQuery::FlushResults()
|
||||
{
|
||||
if (!ShouldEmulate())
|
||||
return;
|
||||
while (!IsFlushed())
|
||||
FlushOne();
|
||||
}
|
||||
|
||||
void PerfQuery::WeakFlush()
|
||||
{
|
||||
if (!ShouldEmulate())
|
||||
return;
|
||||
while (!IsFlushed())
|
||||
{
|
||||
auto& entry = m_query_buffer[m_query_read_pos];
|
||||
|
||||
DWORD result = 0;
|
||||
HRESULT hr = entry.query->GetData(&result, sizeof(result), 0);
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
// NOTE: Reported pixel metrics should be referenced to native resolution
|
||||
m_results[entry.query_type] += (u32)((u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight());
|
||||
|
||||
m_query_read_pos = (m_query_read_pos + 1) % ArraySize(m_query_buffer);
|
||||
--m_query_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PerfQuery::IsFlushed() const
|
||||
{
|
||||
if (!ShouldEmulate())
|
||||
return true;
|
||||
return 0 == m_query_count;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
|
@ -1,47 +0,0 @@
|
|||
#ifndef _PERFQUERY_H_
|
||||
#define _PERFQUERY_H_
|
||||
|
||||
#include "PerfQueryBase.h"
|
||||
|
||||
namespace DX9 {
|
||||
|
||||
class PerfQuery : public PerfQueryBase
|
||||
{
|
||||
public:
|
||||
PerfQuery();
|
||||
~PerfQuery();
|
||||
|
||||
void EnableQuery(PerfQueryGroup type);
|
||||
void DisableQuery(PerfQueryGroup type);
|
||||
void ResetQuery();
|
||||
u32 GetQueryResult(PerfQueryType type);
|
||||
void FlushResults();
|
||||
bool IsFlushed() const;
|
||||
void CreateDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
|
||||
private:
|
||||
struct ActiveQuery
|
||||
{
|
||||
IDirect3DQuery9* query;
|
||||
PerfQueryGroup query_type;
|
||||
};
|
||||
|
||||
void WeakFlush();
|
||||
// Only use when non-empty
|
||||
void FlushOne();
|
||||
|
||||
// when testing in SMS: 64 was too small, 128 was ok
|
||||
static const int PERF_QUERY_BUFFER_SIZE = 512;
|
||||
|
||||
ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE];
|
||||
int m_query_read_pos;
|
||||
|
||||
// TODO: sloppy
|
||||
volatile int m_query_count;
|
||||
volatile u32 m_results[PQG_NUM_MEMBERS];
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _PERFQUERY_H_
|
|
@ -1,449 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <locale.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Hash.h"
|
||||
#include "FileUtil.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
#include "Globals.h"
|
||||
#include "D3DBase.h"
|
||||
#include "D3DShader.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "PixelShaderGen.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "Debugger.h"
|
||||
#include "ConfigManager.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
|
||||
const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry;
|
||||
PixelShaderUid PixelShaderCache::last_uid;
|
||||
UidChecker<PixelShaderUid,PixelShaderCode> PixelShaderCache::pixel_uid_checker;
|
||||
|
||||
static LinearDiskCache<PixelShaderUid, u8> g_ps_disk_cache;
|
||||
static std::set<u32> unique_shaders;
|
||||
|
||||
#define MAX_SSAA_SHADERS 3
|
||||
enum
|
||||
{
|
||||
COPY_TYPE_DIRECT,
|
||||
COPY_TYPE_MATRIXCOLOR,
|
||||
NUM_COPY_TYPES
|
||||
};
|
||||
enum
|
||||
{
|
||||
DEPTH_CONVERSION_TYPE_NONE,
|
||||
DEPTH_CONVERSION_TYPE_ON,
|
||||
NUM_DEPTH_CONVERSION_TYPES
|
||||
};
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 s_CopyProgram[NUM_COPY_TYPES][NUM_DEPTH_CONVERSION_TYPES][MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DPIXELSHADER9 s_ClearProgram = NULL;
|
||||
static LPDIRECT3DPIXELSHADER9 s_rgba6_to_rgb8 = NULL;
|
||||
static LPDIRECT3DPIXELSHADER9 s_rgb8_to_rgba6 = NULL;
|
||||
|
||||
class PixelShaderCacheInserter : public LinearDiskCacheReader<PixelShaderUid, u8>
|
||||
{
|
||||
public:
|
||||
void Read(const PixelShaderUid &key, const u8 *value, u32 value_size)
|
||||
{
|
||||
PixelShaderCache::InsertByteCode(key, value, value_size, false);
|
||||
}
|
||||
};
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram(int SSAAMode)
|
||||
{
|
||||
return s_CopyProgram[COPY_TYPE_MATRIXCOLOR][DEPTH_CONVERSION_TYPE_NONE][SSAAMode % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetDepthMatrixProgram(int SSAAMode, bool depthConversion)
|
||||
{
|
||||
return s_CopyProgram[COPY_TYPE_MATRIXCOLOR][depthConversion ? DEPTH_CONVERSION_TYPE_ON : DEPTH_CONVERSION_TYPE_NONE][SSAAMode % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorCopyProgram(int SSAAMode)
|
||||
{
|
||||
return s_CopyProgram[COPY_TYPE_DIRECT][DEPTH_CONVERSION_TYPE_NONE][SSAAMode % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetClearProgram()
|
||||
{
|
||||
return s_ClearProgram;
|
||||
}
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 s_rgb8 = NULL;
|
||||
static LPDIRECT3DPIXELSHADER9 s_rgba6 = NULL;
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::ReinterpRGBA6ToRGB8()
|
||||
{
|
||||
const char code[] =
|
||||
{
|
||||
"uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
" ocol0 = tex2D(samp0,uv0);\n"
|
||||
" float4 src6 = round(ocol0 * 63.f);\n"
|
||||
" ocol0.r = floor(src6.r*4.f) + floor(src6.g/16.f);\n" // dst8r = (src6r<<2)|(src6g>>4);
|
||||
" ocol0.g = frac(src6.g/16.f)*16.f*16.f + floor(src6.b/4.f);\n" // dst8g = ((src6g&0xF)<<4)|(src6b>>2);
|
||||
" ocol0.b = frac(src6.b/4.f)*4.f*64.f + src6.a;\n" // dst8b = ((src6b&0x3)<<6)|src6a;
|
||||
" ocol0.a = 255.f;\n"
|
||||
" ocol0 /= 255.f;\n"
|
||||
"}\n"
|
||||
};
|
||||
|
||||
if (!s_rgba6_to_rgb8)
|
||||
s_rgba6_to_rgb8 = D3D::CompileAndCreatePixelShader(code, (int)strlen(code));
|
||||
|
||||
return s_rgba6_to_rgb8;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::ReinterpRGB8ToRGBA6()
|
||||
{
|
||||
/* old code here for reference
|
||||
const char code[] =
|
||||
{
|
||||
"uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
" ocol0 = tex2D(samp0,uv0);\n"
|
||||
" float4 src8 = round(ocol0*255.f);\n"
|
||||
" ocol0.r = floor(src8.r/4.f);\n" // dst6r = src8r>>2;
|
||||
" ocol0.g = frac(src8.r/4.f)*4.f*16.f + floor(src8.g/16.f);\n" // dst6g = ((src8r&0x3)<<4)|(src8g>>4);
|
||||
" ocol0.b = frac(src8.g/16.f)*16.f*4.f + floor(src8.b/64.f);\n" // dst6b = ((src8g&0xF)<<2)|(src8b>>6);
|
||||
" ocol0.a = frac(src8.b/64.f)*64.f;\n" // dst6a = src8b&0x3F;
|
||||
" ocol0 /= 63.f;\n"
|
||||
"}\n"
|
||||
};
|
||||
*/
|
||||
const char code[] =
|
||||
{
|
||||
"uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
"in float2 uv0 : TEXCOORD0){\n"
|
||||
"float4 temp1 = float4(1.0f/4.0f,1.0f/16.0f,1.0f/64.0f,0.0f);\n"
|
||||
"float4 temp2 = float4(1.0f,64.0f,255.0f,1.0f/63.0f);\n"
|
||||
"float4 src8 = round(tex2D(samp0,uv0)*temp2.z) * temp1;\n"
|
||||
"ocol0 = (frac(src8.wxyz) * temp2.xyyy + floor(src8)) * temp2.w;\n"
|
||||
"}\n"
|
||||
};
|
||||
if (!s_rgb8_to_rgba6) s_rgb8_to_rgba6 = D3D::CompileAndCreatePixelShader(code, (int)strlen(code));
|
||||
return s_rgb8_to_rgba6;
|
||||
}
|
||||
|
||||
#define WRITE p+=sprintf
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 CreateCopyShader(int copyMatrixType, int depthConversionType, int SSAAMode)
|
||||
{
|
||||
//Used for Copy/resolve the color buffer
|
||||
//Color conversion Programs
|
||||
//Depth copy programs
|
||||
// this should create the same shaders as before (plus some extras added for DF16), just... more manageably than listing the full program for each combination
|
||||
char text[3072];
|
||||
|
||||
locale_t locale = newlocale(LC_NUMERIC_MASK, "C", NULL); // New locale for compilation
|
||||
locale_t old_locale = uselocale(locale); // Apply the locale for this thread
|
||||
text[sizeof(text) - 1] = 0x7C; // canary
|
||||
|
||||
char* p = text;
|
||||
WRITE(p, "// Copy/Color Matrix/Depth Matrix shader (matrix=%d, depth=%d, ssaa=%d)\n", copyMatrixType, depthConversionType, SSAAMode);
|
||||
|
||||
WRITE(p, "uniform sampler samp0 : register(s0);\n");
|
||||
if(copyMatrixType == COPY_TYPE_MATRIXCOLOR)
|
||||
WRITE(p, "uniform float4 cColMatrix[7] : register(c%d);\n", C_COLORMATRIX);
|
||||
WRITE(p, "void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n");
|
||||
|
||||
switch(SSAAMode % MAX_SSAA_SHADERS)
|
||||
{
|
||||
case 0: // 1 Sample
|
||||
WRITE(p, "in float2 uv0 : TEXCOORD0,\n"
|
||||
"in float uv1 : TEXCOORD1){\n"
|
||||
"float4 texcol = tex2D(samp0,uv0.xy);\n");
|
||||
break;
|
||||
case 1: // 4 Samples in 4x SSAA buffer
|
||||
WRITE(p, "in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float uv1 : TEXCOORD1,\n"
|
||||
"in float4 uv2 : TEXCOORD2,\n"
|
||||
"in float4 uv3 : TEXCOORD3){\n"
|
||||
"float4 texcol = (tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz) + tex2D(samp0,uv3.xy) + tex2D(samp0,uv3.wz))*0.25f;\n");
|
||||
break;
|
||||
case 2: // 4 Samples in 9x SSAA buffer
|
||||
WRITE(p, "in float4 uv0 : TEXCOORD0,\n"
|
||||
"in float uv1 : TEXCOORD1,\n"
|
||||
"in float4 uv2 : TEXCOORD2,\n"
|
||||
"in float4 uv3 : TEXCOORD3){\n"
|
||||
"float4 texcol = (tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz) + tex2D(samp0,uv3.xy) + tex2D(samp0,uv3.wz))*0.25f;\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(depthConversionType != DEPTH_CONVERSION_TYPE_NONE)
|
||||
{
|
||||
// Watch out for the fire fumes effect in Metroid it's really sensitive to this,
|
||||
// the lighting in RE0 is also way beyond sensitive since the "good value" is hardcoded and Dolphin is almost always off.
|
||||
WRITE(p, "float4 EncodedDepth = frac(texcol.r * (16777215.f/16777216.f) * float4(1.0f,256.0f,256.0f*256.0f,1.0f));\n"
|
||||
"texcol = floor(EncodedDepth * float4(256.f,256.f,256.f,15.0f)) / float4(255.0f,255.0f,255.0f,15.0f);\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//Apply Gamma Correction
|
||||
WRITE(p, "texcol = pow(texcol,uv1.xxxx);\n");
|
||||
}
|
||||
|
||||
if(copyMatrixType == COPY_TYPE_MATRIXCOLOR)
|
||||
{
|
||||
if(depthConversionType == DEPTH_CONVERSION_TYPE_NONE)
|
||||
WRITE(p, "texcol = round(texcol * cColMatrix[5])*cColMatrix[6];\n");
|
||||
|
||||
WRITE(p, "ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n");
|
||||
}
|
||||
else
|
||||
WRITE(p, "ocol0 = texcol;\n");
|
||||
|
||||
WRITE(p, "}\n");
|
||||
if (text[sizeof(text) - 1] != 0x7C)
|
||||
PanicAlert("PixelShaderCache copy shader generator - buffer too small, canary has been eaten!");
|
||||
|
||||
uselocale(old_locale); // restore locale
|
||||
freelocale(locale);
|
||||
return D3D::CompileAndCreatePixelShader(text, (int)strlen(text));
|
||||
}
|
||||
|
||||
void PixelShaderCache::Init()
|
||||
{
|
||||
last_entry = NULL;
|
||||
|
||||
//program used for clear screen
|
||||
{
|
||||
char pprog[3072];
|
||||
sprintf(pprog, "void main(\n"
|
||||
"out float4 ocol0 : COLOR0,\n"
|
||||
" in float4 incol0 : COLOR0){\n"
|
||||
"ocol0 = incol0;\n"
|
||||
"}\n");
|
||||
s_ClearProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
|
||||
}
|
||||
|
||||
int shaderModel = ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF);
|
||||
int maxConstants = (shaderModel < 3) ? 32 : ((shaderModel < 4) ? 224 : 65536);
|
||||
|
||||
// other screen copy/convert programs
|
||||
for(int copyMatrixType = 0; copyMatrixType < NUM_COPY_TYPES; copyMatrixType++)
|
||||
{
|
||||
for(int depthType = 0; depthType < NUM_DEPTH_CONVERSION_TYPES; depthType++)
|
||||
{
|
||||
for(int ssaaMode = 0; ssaaMode < MAX_SSAA_SHADERS; ssaaMode++)
|
||||
{
|
||||
if(ssaaMode && !s_CopyProgram[copyMatrixType][depthType][ssaaMode-1]
|
||||
|| depthType && !s_CopyProgram[copyMatrixType][depthType-1][ssaaMode]
|
||||
|| copyMatrixType && !s_CopyProgram[copyMatrixType-1][depthType][ssaaMode])
|
||||
{
|
||||
// if it failed at a lower setting, it's going to fail here for the same reason it did there,
|
||||
// so skip this attempt to avoid duplicate error messages.
|
||||
s_CopyProgram[copyMatrixType][depthType][ssaaMode] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_CopyProgram[copyMatrixType][depthType][ssaaMode] = CreateCopyShader(copyMatrixType, depthType, ssaaMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Clear();
|
||||
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str());
|
||||
|
||||
SETSTAT(stats.numPixelShadersCreated, 0);
|
||||
SETSTAT(stats.numPixelShadersAlive, 0);
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sdx9-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
|
||||
PixelShaderCacheInserter inserter;
|
||||
g_ps_disk_cache.OpenAndRead(cache_filename, inserter);
|
||||
|
||||
if (g_Config.bEnableShaderDebugging)
|
||||
Clear();
|
||||
}
|
||||
|
||||
// ONLY to be used during shutdown.
|
||||
void PixelShaderCache::Clear()
|
||||
{
|
||||
for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
PixelShaders.clear();
|
||||
pixel_uid_checker.Invalidate();
|
||||
|
||||
last_entry = NULL;
|
||||
}
|
||||
|
||||
void PixelShaderCache::Shutdown()
|
||||
{
|
||||
for(int copyMatrixType = 0; copyMatrixType < NUM_COPY_TYPES; copyMatrixType++)
|
||||
for(int depthType = 0; depthType < NUM_DEPTH_CONVERSION_TYPES; depthType++)
|
||||
for(int ssaaMode = 0; ssaaMode < MAX_SSAA_SHADERS; ssaaMode++)
|
||||
if(s_CopyProgram[copyMatrixType][depthType][ssaaMode]
|
||||
&& (copyMatrixType == 0 || s_CopyProgram[copyMatrixType][depthType][ssaaMode] != s_CopyProgram[copyMatrixType-1][depthType][ssaaMode]))
|
||||
s_CopyProgram[copyMatrixType][depthType][ssaaMode]->Release();
|
||||
|
||||
for(int copyMatrixType = 0; copyMatrixType < NUM_COPY_TYPES; copyMatrixType++)
|
||||
for(int depthType = 0; depthType < NUM_DEPTH_CONVERSION_TYPES; depthType++)
|
||||
for(int ssaaMode = 0; ssaaMode < MAX_SSAA_SHADERS; ssaaMode++)
|
||||
s_CopyProgram[copyMatrixType][depthType][ssaaMode] = NULL;
|
||||
|
||||
if (s_ClearProgram) s_ClearProgram->Release();
|
||||
s_ClearProgram = NULL;
|
||||
if (s_rgb8_to_rgba6) s_rgb8_to_rgba6->Release();
|
||||
s_rgb8_to_rgba6 = NULL;
|
||||
if (s_rgba6_to_rgb8) s_rgba6_to_rgb8->Release();
|
||||
s_rgba6_to_rgb8 = NULL;
|
||||
|
||||
|
||||
Clear();
|
||||
g_ps_disk_cache.Sync();
|
||||
g_ps_disk_cache.Close();
|
||||
|
||||
unique_shaders.clear();
|
||||
}
|
||||
|
||||
bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
|
||||
{
|
||||
const API_TYPE api = ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF) < 3 ? API_D3D9_SM20 : API_D3D9_SM30;
|
||||
PixelShaderUid uid;
|
||||
GetPixelShaderUid(uid, dstAlphaMode, API_D3D9, components);
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
PixelShaderCode code;
|
||||
GeneratePixelShaderCode(code, dstAlphaMode, API_D3D9, components);
|
||||
pixel_uid_checker.AddToIndexAndCheck(code, uid, "Pixel", "p");
|
||||
}
|
||||
|
||||
// Check if the shader is already set
|
||||
if (last_entry)
|
||||
{
|
||||
if (uid == last_uid)
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
return last_entry->shader != NULL;
|
||||
}
|
||||
}
|
||||
|
||||
last_uid = uid;
|
||||
|
||||
// Check if the shader is already in the cache
|
||||
PSCache::iterator iter;
|
||||
iter = PixelShaders.find(uid);
|
||||
if (iter != PixelShaders.end())
|
||||
{
|
||||
const PSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
if (entry.shader) D3D::SetPixelShader(entry.shader);
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
return (entry.shader != NULL);
|
||||
}
|
||||
|
||||
|
||||
// Need to compile a new shader
|
||||
PixelShaderCode code;
|
||||
GeneratePixelShaderCode(code, dstAlphaMode, api, components);
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
u32 code_hash = HashAdler32((const u8 *)code.GetBuffer(), strlen(code.GetBuffer()));
|
||||
unique_shaders.insert(code_hash);
|
||||
SETSTAT(stats.numUniquePixelShaders, unique_shaders.size());
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS) {
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
|
||||
|
||||
SaveData(szTemp, code.GetBuffer());
|
||||
}
|
||||
#endif
|
||||
|
||||
u8 *bytecode = 0;
|
||||
int bytecodelen = 0;
|
||||
if (!D3D::CompilePixelShader(code.GetBuffer(), (int)strlen(code.GetBuffer()), &bytecode, &bytecodelen)) {
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert the bytecode into the caches
|
||||
g_ps_disk_cache.Append(uid, bytecode, bytecodelen);
|
||||
|
||||
// And insert it into the shader cache.
|
||||
bool success = InsertByteCode(uid, bytecode, bytecodelen, true);
|
||||
delete [] bytecode;
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging && success)
|
||||
{
|
||||
PixelShaders[uid].code = code.GetBuffer();
|
||||
}
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::InsertByteCode(const PixelShaderUid &uid, const u8 *bytecode, int bytecodelen, bool activate)
|
||||
{
|
||||
LPDIRECT3DPIXELSHADER9 shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
|
||||
|
||||
// Make an entry in the table
|
||||
PSCacheEntry newentry;
|
||||
newentry.shader = shader;
|
||||
PixelShaders[uid] = newentry;
|
||||
last_entry = &PixelShaders[uid];
|
||||
|
||||
if (!shader) {
|
||||
// INCSTAT(stats.numPixelShadersFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
|
||||
if (activate)
|
||||
{
|
||||
D3D::SetPixelShader(shader);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Renderer::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
float f[4] = { f1, f2, f3, f4 };
|
||||
DX9::D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void Renderer::SetPSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
DX9::D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void Renderer::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
DX9::D3D::dev->SetPixelShaderConstantF(const_number, f, count);
|
||||
}
|
||||
|
||||
} // namespace DX9
|
|
@ -1,64 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include "LinearDiskCache.h"
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "PixelShaderGen.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
typedef u32 tevhash;
|
||||
|
||||
tevhash GetCurrentTEV();
|
||||
|
||||
class PixelShaderCache
|
||||
{
|
||||
private:
|
||||
struct PSCacheEntry
|
||||
{
|
||||
LPDIRECT3DPIXELSHADER9 shader;
|
||||
bool owns_shader;
|
||||
|
||||
std::string code;
|
||||
|
||||
PSCacheEntry() : shader(NULL), owns_shader(true) {}
|
||||
void Destroy()
|
||||
{
|
||||
if (shader && owns_shader)
|
||||
shader->Release();
|
||||
shader = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<PixelShaderUid, PSCacheEntry> PSCache;
|
||||
|
||||
static PSCache PixelShaders;
|
||||
static const PSCacheEntry *last_entry;
|
||||
static PixelShaderUid last_uid;
|
||||
static UidChecker<PixelShaderUid,PixelShaderCode> pixel_uid_checker;
|
||||
|
||||
static void Clear();
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
static bool SetShader(DSTALPHA_MODE dstAlphaMode, u32 componets);
|
||||
static bool InsertByteCode(const PixelShaderUid &uid, const u8 *bytecode, int bytecodelen, bool activate);
|
||||
static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram(int SSAAMode);
|
||||
static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram(int SSAAMode);
|
||||
static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram(int SSAAMode, bool depthConversion);
|
||||
static LPDIRECT3DPIXELSHADER9 GetClearProgram();
|
||||
static LPDIRECT3DPIXELSHADER9 ReinterpRGBA6ToRGB8();
|
||||
static LPDIRECT3DPIXELSHADER9 ReinterpRGB8ToRGBA6();
|
||||
};
|
||||
|
||||
} // namespace DX9
|
File diff suppressed because it is too large
Load Diff
|
@ -1,63 +0,0 @@
|
|||
|
||||
#ifndef _RENDER_H_
|
||||
#define _RENDER_H_
|
||||
|
||||
#include "RenderBase.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class Renderer : public ::Renderer
|
||||
{
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
void SetColorMask();
|
||||
void SetBlendMode(bool forceUpdate);
|
||||
void SetScissorRect(const TargetRectangle& rc);
|
||||
void SetGenerationMode();
|
||||
void SetDepthMode();
|
||||
void SetLogicOpMode();
|
||||
void SetDitherMode();
|
||||
void SetLineWidth();
|
||||
void SetSamplerState(int stage,int texindex);
|
||||
void SetInterlacingMode();
|
||||
|
||||
void ApplyState(bool bUseDstAlpha);
|
||||
void RestoreState();
|
||||
|
||||
void RenderText(const char* pstr, int left, int top, u32 color);
|
||||
|
||||
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data);
|
||||
|
||||
void ResetAPIState();
|
||||
void RestoreAPIState();
|
||||
|
||||
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc);
|
||||
|
||||
void Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& rc,float Gamma);
|
||||
|
||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
|
||||
|
||||
void ReinterpretPixelData(unsigned int convtype);
|
||||
|
||||
void UpdateViewport(Matrix44& vpCorrection);
|
||||
|
||||
bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);
|
||||
|
||||
static bool CheckForResize();
|
||||
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetPSConstant4fv(unsigned int const_number, const float *f);
|
||||
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
|
||||
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
|
||||
void SetVSConstant4fv(unsigned int const_number, const float *f);
|
||||
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
|
||||
};
|
||||
|
||||
} // namespace DX9
|
||||
|
||||
#endif
|
|
@ -1,236 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Statistics.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "Hash.h"
|
||||
#include "HW/Memmap.h"
|
||||
|
||||
#include "CommonPaths.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "FramebufferManager.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexShaderCache.h"
|
||||
|
||||
#include "Render.h"
|
||||
|
||||
#include "TextureDecoder.h"
|
||||
#include "TextureCache.h"
|
||||
#include "HiresTextures.h"
|
||||
#include "TextureConverter.h"
|
||||
#include "Debugger.h"
|
||||
|
||||
extern int frameCount;
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
TextureCache::TCacheEntry::~TCacheEntry()
|
||||
{
|
||||
texture->Release();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||
{
|
||||
D3D::SetTexture(stage, texture);
|
||||
}
|
||||
|
||||
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
|
||||
{
|
||||
IDirect3DSurface9* surface;
|
||||
HRESULT hr = texture->GetSurfaceLevel(level, &surface);
|
||||
if (FAILED(hr))
|
||||
return false;
|
||||
|
||||
hr = PD3DXSaveSurfaceToFileA(filename, D3DXIFF_PNG, surface, NULL, NULL);
|
||||
surface->Release();
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
||||
const float *colmat)
|
||||
{
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
const LPDIRECT3DTEXTURE9 read_texture = (srcFormat == PIXELFMT_Z24) ?
|
||||
FramebufferManager::GetEFBDepthTexture() :
|
||||
FramebufferManager::GetEFBColorTexture();
|
||||
|
||||
if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture)
|
||||
{
|
||||
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
||||
texture->GetSurfaceLevel(0, &Rendersurf);
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
// Stretch picture with increased internal resolution
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = virtual_width;
|
||||
vp.Height = virtual_height;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT destrect;
|
||||
destrect.bottom = virtual_height;
|
||||
destrect.left = 0;
|
||||
destrect.right = virtual_width;
|
||||
destrect.top = 0;
|
||||
|
||||
PixelShaderManager::SetColorMatrix(colmat); // set transformation
|
||||
TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
|
||||
RECT sourcerect;
|
||||
sourcerect.bottom = targetSource.bottom;
|
||||
sourcerect.left = targetSource.left;
|
||||
sourcerect.right = targetSource.right;
|
||||
sourcerect.top = targetSource.top;
|
||||
|
||||
if (srcFormat == PIXELFMT_Z24)
|
||||
{
|
||||
if (scaleByHalf || g_ActiveConfig.iMultisampleMode)
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
}
|
||||
|
||||
D3DFORMAT bformat = FramebufferManager::GetEFBDepthRTSurfaceFormat();
|
||||
int SSAAMode = g_ActiveConfig.iMultisampleMode;
|
||||
|
||||
D3D::drawShadedTexQuad(read_texture, &sourcerect,
|
||||
Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
|
||||
virtual_width, virtual_height,
|
||||
// TODO: why is D3DFMT_D24X8 singled out here? why not D3DFMT_D24X4S4/D24S8/D24FS8/D32/D16/D15S1 too, or none of them?
|
||||
PixelShaderCache::GetDepthMatrixProgram(SSAAMode, (srcFormat == PIXELFMT_Z24) && bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8),
|
||||
VertexShaderCache::GetSimpleVertexShader(SSAAMode));
|
||||
|
||||
Rendersurf->Release();
|
||||
}
|
||||
|
||||
if (!g_ActiveConfig.bCopyEFBToTexture)
|
||||
{
|
||||
int encoded_size = TextureConverter::EncodeToRamFromTexture(
|
||||
addr,
|
||||
read_texture,
|
||||
Renderer::GetTargetWidth(),
|
||||
Renderer::GetTargetHeight(),
|
||||
srcFormat == PIXELFMT_Z24,
|
||||
isIntensity,
|
||||
dstFormat,
|
||||
scaleByHalf,
|
||||
srcRect);
|
||||
|
||||
u8* dst = Memory::GetPointer(addr);
|
||||
u64 hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||
|
||||
// Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date
|
||||
if (!g_ActiveConfig.bEFBCopyCacheEnable)
|
||||
TextureCache::MakeRangeDynamic(addr,encoded_size);
|
||||
else if (!TextureCache::Find(addr, hash))
|
||||
TextureCache::MakeRangeDynamic(addr,encoded_size);
|
||||
|
||||
this->hash = hash;
|
||||
}
|
||||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
D3D::SetTexture(0, NULL);
|
||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt)
|
||||
{
|
||||
D3DFORMAT d3d_fmt;
|
||||
bool swap_r_b = false;
|
||||
|
||||
switch (pcfmt)
|
||||
{
|
||||
case PC_TEX_FMT_BGRA32:
|
||||
d3d_fmt = D3DFMT_A8R8G8B8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGBA32:
|
||||
d3d_fmt = D3DFMT_A8R8G8B8;
|
||||
swap_r_b = true;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGB565:
|
||||
d3d_fmt = D3DFMT_R5G6B5;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_IA4_AS_IA8:
|
||||
d3d_fmt = D3DFMT_A8L8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_I8:
|
||||
case PC_TEX_FMT_I4_AS_I8:
|
||||
// A hack which means the format is a packed
|
||||
// 8-bit intensity texture. It is unpacked
|
||||
// to A8L8 in D3DTexture.cpp
|
||||
d3d_fmt = D3DFMT_A8P8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_IA8:
|
||||
d3d_fmt = D3DFMT_A8L8;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_DXT1:
|
||||
d3d_fmt = D3DFMT_DXT1;
|
||||
break;
|
||||
}
|
||||
|
||||
TCacheEntry* entry = new TCacheEntry(D3D::CreateTexture2D(temp, width, height, expanded_width, d3d_fmt, swap_r_b, tex_levels));
|
||||
entry->swap_r_b = swap_r_b;
|
||||
entry->d3d_fmt = d3d_fmt;
|
||||
|
||||
entry->Load(width, height, expanded_width, 0);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(
|
||||
unsigned int scaled_tex_w, unsigned int scaled_tex_h)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
D3D::dev->CreateTexture(scaled_tex_w, scaled_tex_h, 1, D3DUSAGE_RENDERTARGET,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
|
||||
|
||||
return new TCacheEntry(texture);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef _TEXTURECACHE_H
|
||||
#define _TEXTURECACHE_H
|
||||
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "VideoCommon.h"
|
||||
#include "BPMemory.h"
|
||||
|
||||
#include "TextureCacheBase.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class TextureCache : public ::TextureCache
|
||||
{
|
||||
private:
|
||||
struct TCacheEntry : TCacheEntryBase
|
||||
{
|
||||
const LPDIRECT3DTEXTURE9 texture;
|
||||
|
||||
D3DFORMAT d3d_fmt;
|
||||
bool swap_r_b;
|
||||
|
||||
TCacheEntry(LPDIRECT3DTEXTURE9 _tex) : texture(_tex) {}
|
||||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int levels);
|
||||
|
||||
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
||||
const float *colmat);
|
||||
|
||||
void Bind(unsigned int stage);
|
||||
bool Save(const char filename[], unsigned int level);
|
||||
};
|
||||
|
||||
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
|
||||
|
||||
TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,462 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// Fast image conversion using OpenGL shaders.
|
||||
// This kind of stuff would be a LOT nicer with OpenCL.
|
||||
|
||||
#include "TextureConverter.h"
|
||||
#include "TextureConversionShader.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "FramebufferManager.h"
|
||||
#include "Globals.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "Render.h"
|
||||
#include "TextureCache.h"
|
||||
#include "Math.h"
|
||||
#include "FileUtil.h"
|
||||
#include "HW/Memmap.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
namespace TextureConverter
|
||||
{
|
||||
struct TransformBuffer
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 FBTexture;
|
||||
LPDIRECT3DSURFACE9 RenderSurface;
|
||||
LPDIRECT3DSURFACE9 ReadSurface;
|
||||
int Width;
|
||||
int Height;
|
||||
};
|
||||
const u32 NUM_TRANSFORM_BUFFERS = 16;
|
||||
static TransformBuffer TrnBuffers[NUM_TRANSFORM_BUFFERS];
|
||||
static u32 WorkingBuffers = 0;
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 s_rgbToYuyvProgram = NULL;
|
||||
static LPDIRECT3DPIXELSHADER9 s_yuyvToRgbProgram = NULL;
|
||||
|
||||
// Not all slots are taken - but who cares.
|
||||
const u32 NUM_ENCODING_PROGRAMS = 64;
|
||||
static LPDIRECT3DPIXELSHADER9 s_encodingPrograms[NUM_ENCODING_PROGRAMS];
|
||||
static bool s_encodingProgramsFailed[NUM_ENCODING_PROGRAMS];
|
||||
|
||||
void CreateRgbToYuyvProgram()
|
||||
{
|
||||
// Output is BGRA because that is slightly faster than RGBA.
|
||||
char* FProgram = new char[2048];
|
||||
sprintf(FProgram,"uniform float4 blkDims : register(c%d);\n"
|
||||
"uniform float4 textureDims : register(c%d);\n"
|
||||
"uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0,\n"
|
||||
" in float uv2 : TEXCOORD1)\n"
|
||||
"{\n"
|
||||
" float2 uv1 = float2((uv0.x + 1.0f)/ blkDims.z, uv0.y / blkDims.w);\n"
|
||||
" float3 c0 = tex2D(samp0, uv0.xy / blkDims.zw).rgb;\n"
|
||||
" float3 c1 = tex2D(samp0, uv1).rgb;\n"
|
||||
" c0 = pow(c0,uv2.xxx);\n"
|
||||
" c1 = pow(c1,uv2.xxx);\n"
|
||||
" float3 y_const = float3(0.257f,0.504f,0.098f);\n"
|
||||
" float3 u_const = float3(-0.148f,-0.291f,0.439f);\n"
|
||||
" float3 v_const = float3(0.439f,-0.368f,-0.071f);\n"
|
||||
" float4 const3 = float4(0.0625f,0.5f,0.0625f,0.5f);\n"
|
||||
" float3 c01 = (c0 + c1) * 0.5f;\n"
|
||||
" ocol0 = float4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n"
|
||||
"}\n",C_COLORMATRIX,C_COLORMATRIX+1);
|
||||
|
||||
s_rgbToYuyvProgram = D3D::CompileAndCreatePixelShader(FProgram, (int)strlen(FProgram));
|
||||
if (!s_rgbToYuyvProgram) {
|
||||
ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program");
|
||||
}
|
||||
delete [] FProgram;
|
||||
}
|
||||
|
||||
void CreateYuyvToRgbProgram()
|
||||
{
|
||||
char* FProgram = new char[2048];
|
||||
sprintf(FProgram,"uniform float4 blkDims : register(c%d);\n"
|
||||
"uniform float4 textureDims : register(c%d);\n"
|
||||
"uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
" float4 c0 = tex2D(samp0, uv0 / blkDims.zw).rgba;\n"
|
||||
" float f = step(0.5, frac(uv0.x));\n"
|
||||
" float y = lerp(c0.b, c0.r, f);\n"
|
||||
" float yComp = 1.164f * (y - 0.0625f);\n"
|
||||
" float uComp = c0.g - 0.5f;\n"
|
||||
" float vComp = c0.a - 0.5f;\n"
|
||||
|
||||
" ocol0 = float4(yComp + (1.596f * vComp),\n"
|
||||
" yComp - (0.813f * vComp) - (0.391f * uComp),\n"
|
||||
" yComp + (2.018f * uComp),\n"
|
||||
" 1.0f);\n"
|
||||
"}\n",C_COLORMATRIX,C_COLORMATRIX+1);
|
||||
s_yuyvToRgbProgram = D3D::CompileAndCreatePixelShader(FProgram, (int)strlen(FProgram));
|
||||
if (!s_yuyvToRgbProgram) {
|
||||
ERROR_LOG(VIDEO, "Failed to create YUYV to RGB fragment program");
|
||||
}
|
||||
delete [] FProgram;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 GetOrCreateEncodingShader(u32 format)
|
||||
{
|
||||
if (format > NUM_ENCODING_PROGRAMS)
|
||||
{
|
||||
PanicAlert("Unknown texture copy format: 0x%x\n", format);
|
||||
return s_encodingPrograms[0];
|
||||
}
|
||||
|
||||
if (!s_encodingPrograms[format])
|
||||
{
|
||||
if(s_encodingProgramsFailed[format])
|
||||
{
|
||||
// we already failed to create a shader for this format,
|
||||
// so instead of re-trying and showing the same error message every frame, just return.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(format,API_D3D9);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader) {
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
|
||||
|
||||
SaveData(szTemp, shader);
|
||||
}
|
||||
#endif
|
||||
s_encodingPrograms[format] = D3D::CompileAndCreatePixelShader(shader, (int)strlen(shader));
|
||||
if (!s_encodingPrograms[format]) {
|
||||
ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
|
||||
s_encodingProgramsFailed[format] = true;
|
||||
}
|
||||
}
|
||||
return s_encodingPrograms[format];
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
for (unsigned int i = 0; i < NUM_ENCODING_PROGRAMS; i++)
|
||||
{
|
||||
s_encodingPrograms[i] = NULL;
|
||||
s_encodingProgramsFailed[i] = false;
|
||||
}
|
||||
for (unsigned int i = 0; i < NUM_TRANSFORM_BUFFERS; i++)
|
||||
{
|
||||
TrnBuffers[i].FBTexture = NULL;
|
||||
TrnBuffers[i].RenderSurface = NULL;
|
||||
TrnBuffers[i].ReadSurface = NULL;
|
||||
TrnBuffers[i].Width = 0;
|
||||
TrnBuffers[i].Height = 0;
|
||||
}
|
||||
CreateRgbToYuyvProgram();
|
||||
CreateYuyvToRgbProgram();
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
if(s_rgbToYuyvProgram)
|
||||
s_rgbToYuyvProgram->Release();
|
||||
s_rgbToYuyvProgram = NULL;
|
||||
if(s_yuyvToRgbProgram)
|
||||
s_yuyvToRgbProgram->Release();
|
||||
s_yuyvToRgbProgram=NULL;
|
||||
|
||||
for (unsigned int i = 0; i < NUM_ENCODING_PROGRAMS; i++)
|
||||
{
|
||||
if(s_encodingPrograms[i])
|
||||
s_encodingPrograms[i]->Release();
|
||||
s_encodingPrograms[i] = NULL;
|
||||
}
|
||||
for (unsigned int i = 0; i < NUM_TRANSFORM_BUFFERS; i++)
|
||||
{
|
||||
if(TrnBuffers[i].RenderSurface != NULL)
|
||||
TrnBuffers[i].RenderSurface->Release();
|
||||
TrnBuffers[i].RenderSurface = NULL;
|
||||
|
||||
if(TrnBuffers[i].ReadSurface != NULL)
|
||||
TrnBuffers[i].ReadSurface->Release();
|
||||
TrnBuffers[i].ReadSurface = NULL;
|
||||
|
||||
if(TrnBuffers[i].FBTexture != NULL)
|
||||
TrnBuffers[i].FBTexture->Release();
|
||||
TrnBuffers[i].FBTexture = NULL;
|
||||
|
||||
TrnBuffers[i].Width = 0;
|
||||
TrnBuffers[i].Height = 0;
|
||||
}
|
||||
WorkingBuffers = 0;
|
||||
}
|
||||
|
||||
void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight, int readStride, bool toTexture, bool linearFilter,float Gamma)
|
||||
{
|
||||
HRESULT hr;
|
||||
u32 index =0;
|
||||
while(index < WorkingBuffers && (TrnBuffers[index].Width != dstWidth || TrnBuffers[index].Height != dstHeight))
|
||||
index++;
|
||||
|
||||
LPDIRECT3DSURFACE9 s_texConvReadSurface = NULL;
|
||||
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
||||
|
||||
if (index >= WorkingBuffers)
|
||||
{
|
||||
if (WorkingBuffers < NUM_TRANSFORM_BUFFERS)
|
||||
WorkingBuffers++;
|
||||
if (index >= WorkingBuffers)
|
||||
index--;
|
||||
if (TrnBuffers[index].RenderSurface != NULL)
|
||||
{
|
||||
TrnBuffers[index].RenderSurface->Release();
|
||||
TrnBuffers[index].RenderSurface = NULL;
|
||||
}
|
||||
if (TrnBuffers[index].ReadSurface != NULL)
|
||||
{
|
||||
TrnBuffers[index].ReadSurface->Release();
|
||||
TrnBuffers[index].ReadSurface = NULL;
|
||||
}
|
||||
if (TrnBuffers[index].FBTexture != NULL)
|
||||
{
|
||||
TrnBuffers[index].FBTexture->Release();
|
||||
TrnBuffers[index].FBTexture = NULL;
|
||||
}
|
||||
TrnBuffers[index].Width = dstWidth;
|
||||
TrnBuffers[index].Height = dstHeight;
|
||||
D3D::dev->CreateTexture(dstWidth, dstHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT, &TrnBuffers[index].FBTexture, NULL);
|
||||
TrnBuffers[index].FBTexture->GetSurfaceLevel(0,&TrnBuffers[index].RenderSurface);
|
||||
D3D::dev->CreateOffscreenPlainSurface(dstWidth, dstHeight, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &TrnBuffers[index].ReadSurface, NULL );
|
||||
}
|
||||
|
||||
s_texConvReadSurface = TrnBuffers[index].ReadSurface;
|
||||
Rendersurf = TrnBuffers[index].RenderSurface;
|
||||
|
||||
hr = D3D::dev->SetDepthStencilSurface(NULL);
|
||||
hr = D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
if (linearFilter)
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
}
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = dstWidth;
|
||||
vp.Height = dstHeight;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
hr = D3D::dev->SetViewport(&vp);
|
||||
RECT SrcRect;
|
||||
SrcRect.top = sourceRc.top;
|
||||
SrcRect.left = sourceRc.left;
|
||||
SrcRect.right = sourceRc.right;
|
||||
SrcRect.bottom = sourceRc.bottom;
|
||||
RECT DstRect;
|
||||
DstRect.top = 0;
|
||||
DstRect.left = 0;
|
||||
DstRect.right = dstWidth;
|
||||
DstRect.bottom = dstHeight;
|
||||
|
||||
|
||||
// Draw...
|
||||
D3D::drawShadedTexQuad(srcTexture,&SrcRect,1,1,dstWidth,dstHeight,shader,VertexShaderCache::GetSimpleVertexShader(0), Gamma);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
// .. and then read back the results.
|
||||
// TODO: make this less slow.
|
||||
|
||||
hr = D3D::dev->GetRenderTargetData(Rendersurf,s_texConvReadSurface);
|
||||
|
||||
D3DLOCKED_RECT drect;
|
||||
hr = s_texConvReadSurface->LockRect(&drect, &DstRect, D3DLOCK_READONLY);
|
||||
|
||||
int srcRowsPerBlockRow = readStride / (dstWidth*4); // 4 bytes per pixel
|
||||
|
||||
int readLoops = dstHeight / srcRowsPerBlockRow;
|
||||
const u8 *Source = (const u8*)drect.pBits;
|
||||
for (int i = 0; i < readLoops; i++)
|
||||
{
|
||||
for (int j = 0; j < srcRowsPerBlockRow; ++j)
|
||||
{
|
||||
memcpy(destAddr + j*dstWidth*4, Source, dstWidth*4);
|
||||
Source += drect.Pitch;
|
||||
}
|
||||
destAddr += bpmem.copyMipMapStrideChannels*32;
|
||||
}
|
||||
|
||||
hr = s_texConvReadSurface->UnlockRect();
|
||||
}
|
||||
|
||||
int EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
|
||||
{
|
||||
u32 format = copyfmt;
|
||||
|
||||
if (bFromZBuffer)
|
||||
{
|
||||
format |= _GX_TF_ZTF;
|
||||
if (copyfmt == 11)
|
||||
format = GX_TF_Z16;
|
||||
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
|
||||
format |= _GX_TF_CTF;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
|
||||
format |= _GX_TF_CTF;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 texconv_shader = GetOrCreateEncodingShader(format);
|
||||
if (!texconv_shader)
|
||||
return 0;
|
||||
|
||||
u8 *dest_ptr = Memory::GetPointer(address);
|
||||
|
||||
int width = (source.right - source.left) >> bScaleByHalf;
|
||||
int height = (source.bottom - source.top) >> bScaleByHalf;
|
||||
|
||||
int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
|
||||
|
||||
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
|
||||
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
|
||||
u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
|
||||
|
||||
// only copy on cache line boundaries
|
||||
// extra pixels are copied but not displayed in the resulting texture
|
||||
s32 expandedWidth = (width + blkW) & (~blkW);
|
||||
s32 expandedHeight = (height + blkH) & (~blkH);
|
||||
|
||||
float sampleStride = bScaleByHalf ? 2.f : 1.f;
|
||||
TextureConversionShader::SetShaderParameters(
|
||||
(float)expandedWidth,
|
||||
(float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
|
||||
(float)Renderer::EFBToScaledX(source.left),
|
||||
(float)Renderer::EFBToScaledY(source.top),
|
||||
Renderer::EFBToScaledXf(sampleStride),
|
||||
Renderer::EFBToScaledYf(sampleStride),
|
||||
(float)SourceW,
|
||||
(float)SourceH);
|
||||
|
||||
TargetRectangle scaledSource;
|
||||
scaledSource.top = 0;
|
||||
scaledSource.bottom = expandedHeight;
|
||||
scaledSource.left = 0;
|
||||
scaledSource.right = expandedWidth / samples;
|
||||
int cacheBytes = 32;
|
||||
if ((format & 0x0f) == 6)
|
||||
cacheBytes = 64;
|
||||
|
||||
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
|
||||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0,1.0f);
|
||||
return size_in_bytes; // TODO: D3D11 is calculating this value differently!
|
||||
}
|
||||
|
||||
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight,float Gamma)
|
||||
{
|
||||
TextureConversionShader::SetShaderParameters(
|
||||
(float)dstWidth,
|
||||
(float)dstHeight,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
(float)Renderer::GetTargetWidth(),
|
||||
(float)Renderer::GetTargetHeight());
|
||||
g_renderer->ResetAPIState();
|
||||
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr,
|
||||
dstWidth / 2, dstHeight, dstWidth * 2, false, false,Gamma);
|
||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
|
||||
// Should be scale free.
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture)
|
||||
{
|
||||
u8* srcAddr = Memory::GetPointer(xfbAddr);
|
||||
if (!srcAddr)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Tried to decode from invalid memory address");
|
||||
return;
|
||||
}
|
||||
|
||||
int srcFmtWidth = srcWidth / 2;
|
||||
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
LPDIRECT3DTEXTURE9 s_srcTexture = D3D::CreateTexture2D(srcAddr, srcFmtWidth, srcHeight, srcFmtWidth, D3DFMT_A8R8G8B8, false);
|
||||
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
||||
destTexture->GetSurfaceLevel(0,&Rendersurf);
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
// Stretch picture with increased internal resolution
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = srcWidth;
|
||||
vp.Height = srcHeight;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT destrect;
|
||||
destrect.bottom = srcHeight;
|
||||
destrect.left = 0;
|
||||
destrect.right = srcWidth;
|
||||
destrect.top = 0;
|
||||
|
||||
RECT sourcerect;
|
||||
sourcerect.bottom = srcHeight;
|
||||
sourcerect.left = 0;
|
||||
sourcerect.right = srcFmtWidth;
|
||||
sourcerect.top = 0;
|
||||
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
|
||||
TextureConversionShader::SetShaderParameters(
|
||||
(float)srcFmtWidth,
|
||||
(float)srcHeight,
|
||||
0.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
(float)srcFmtWidth,
|
||||
(float)srcHeight);
|
||||
D3D::drawShadedTexQuad(
|
||||
s_srcTexture,
|
||||
&sourcerect,
|
||||
1,
|
||||
1,
|
||||
srcWidth,
|
||||
srcHeight,
|
||||
s_yuyvToRgbProgram,
|
||||
VertexShaderCache::GetSimpleVertexShader(0));
|
||||
|
||||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
D3D::SetTexture(0,NULL);
|
||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||
g_renderer->RestoreAPIState();
|
||||
Rendersurf->Release();
|
||||
s_srcTexture->Release();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace DX9
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef _TEXTURECONVERTER_H_
|
||||
#define _TEXTURECONVERTER_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "D3DShader.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
// Converts textures between formats using shaders
|
||||
// TODO: support multiple texture formats
|
||||
namespace TextureConverter
|
||||
{
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight,float Gamma);
|
||||
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
|
||||
|
||||
// returns size of the encoded data (in bytes)
|
||||
int EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
|
||||
}
|
||||
|
||||
} // namespace DX9
|
||||
|
||||
#endif // _TEXTURECONVERTER_H_
|
|
@ -1,418 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "Fifo.h"
|
||||
#include "Statistics.h"
|
||||
#include "VertexManager.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "TextureCache.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Debugger.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
// internal state for loading vertices
|
||||
extern NativeVertexFormat *g_nativeVertexFmt;
|
||||
namespace DX9
|
||||
{
|
||||
//This are the initially requeted size for the buffers expresed in elements
|
||||
const u32 IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16) * 8;
|
||||
const u32 VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
|
||||
const u32 MAX_VBUFFER_COUNT = 2;
|
||||
|
||||
inline void DumpBadShaders()
|
||||
{
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
// TODO: Reimplement!
|
||||
/* std::string error_shaders;
|
||||
error_shaders.append(VertexShaderCache::GetCurrentShaderCode());
|
||||
error_shaders.append(PixelShaderCache::GetCurrentShaderCode());
|
||||
char filename[512] = "bad_shader_combo_0.txt";
|
||||
int which = 0;
|
||||
while (File::Exists(filename))
|
||||
{
|
||||
which++;
|
||||
sprintf(filename, "bad_shader_combo_%i.txt", which);
|
||||
}
|
||||
File::WriteStringToFile(true, error_shaders, filename);
|
||||
PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to %s", filename);*/
|
||||
#endif
|
||||
}
|
||||
|
||||
void VertexManager::CreateDeviceObjects()
|
||||
{
|
||||
m_buffers_count = 0;
|
||||
m_vertex_buffers = NULL;
|
||||
m_index_buffers = NULL;
|
||||
D3DCAPS9 DeviceCaps = D3D::GetCaps();
|
||||
u32 devicevMaxBufferSize = DeviceCaps.MaxPrimitiveCount * 3 * DeviceCaps.MaxStreamStride;
|
||||
//Calculate Device Dependant size
|
||||
m_vertex_buffer_size = (VBUFFER_SIZE > devicevMaxBufferSize) ? devicevMaxBufferSize : VBUFFER_SIZE;
|
||||
m_index_buffer_size = (IBUFFER_SIZE > DeviceCaps.MaxVertexIndex) ? DeviceCaps.MaxVertexIndex : IBUFFER_SIZE;
|
||||
//if device caps are not enough for Vbuffer fall back to vertex arrays
|
||||
if (m_index_buffer_size < MAXIBUFFERSIZE || m_vertex_buffer_size < MAXVBUFFERSIZE) return;
|
||||
|
||||
m_vertex_buffers = new LPDIRECT3DVERTEXBUFFER9[MAX_VBUFFER_COUNT];
|
||||
m_index_buffers = new LPDIRECT3DINDEXBUFFER9[MAX_VBUFFER_COUNT];
|
||||
|
||||
bool Fail = false;
|
||||
for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
|
||||
{
|
||||
m_vertex_buffers[m_current_vertex_buffer] = NULL;
|
||||
m_index_buffers[m_current_vertex_buffer] = NULL;
|
||||
}
|
||||
for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
|
||||
{
|
||||
if(FAILED( D3D::dev->CreateVertexBuffer( m_vertex_buffer_size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_vertex_buffers[m_current_vertex_buffer], NULL ) ) )
|
||||
{
|
||||
Fail = true;
|
||||
break;
|
||||
}
|
||||
if( FAILED( D3D::dev->CreateIndexBuffer( m_index_buffer_size * sizeof(u16), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_index_buffers[m_current_vertex_buffer], NULL ) ) )
|
||||
{
|
||||
Fail = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_buffers_count = m_current_vertex_buffer;
|
||||
m_current_vertex_buffer = 0;
|
||||
m_current_index_buffer = 0;
|
||||
m_index_buffer_cursor = m_index_buffer_size;
|
||||
m_vertex_buffer_cursor = m_vertex_buffer_size;
|
||||
m_current_stride = 0;
|
||||
if (Fail)
|
||||
{
|
||||
m_buffers_count--;
|
||||
if (m_buffers_count < 2)
|
||||
{
|
||||
//Error creating Vertex buffers. clean and fall to Vertex arrays
|
||||
m_buffers_count = MAX_VBUFFER_COUNT;
|
||||
DestroyDeviceObjects();
|
||||
}
|
||||
}
|
||||
}
|
||||
void VertexManager::DestroyDeviceObjects()
|
||||
{
|
||||
D3D::SetStreamSource( 0, NULL, 0, 0);
|
||||
D3D::SetIndices(NULL);
|
||||
for (int i = 0; i < MAX_VBUFFER_COUNT; i++)
|
||||
{
|
||||
if(m_vertex_buffers)
|
||||
{
|
||||
if (m_vertex_buffers[i])
|
||||
{
|
||||
m_vertex_buffers[i]->Release();
|
||||
m_vertex_buffers[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_index_buffers[i])
|
||||
{
|
||||
m_index_buffers[i]->Release();
|
||||
m_index_buffers[i] = NULL;
|
||||
}
|
||||
}
|
||||
if(m_vertex_buffers)
|
||||
delete [] m_vertex_buffers;
|
||||
if(m_index_buffers)
|
||||
delete [] m_index_buffers;
|
||||
m_vertex_buffers = NULL;
|
||||
m_index_buffers = NULL;
|
||||
}
|
||||
|
||||
void VertexManager::PrepareDrawBuffers(u32 stride)
|
||||
{
|
||||
if (!m_buffers_count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
u8* pVertices;
|
||||
u16* pIndices;
|
||||
int datasize = IndexGenerator::GetNumVerts() * stride;
|
||||
int TdataSize = IndexGenerator::GetTriangleindexLen();
|
||||
int LDataSize = IndexGenerator::GetLineindexLen();
|
||||
int IndexDataSize = TdataSize + LDataSize;
|
||||
if(IndexDataSize)
|
||||
{
|
||||
DWORD LockMode = D3DLOCK_NOOVERWRITE;
|
||||
m_vertex_buffer_cursor--;
|
||||
m_vertex_buffer_cursor = m_vertex_buffer_cursor - (m_vertex_buffer_cursor % stride) + stride;
|
||||
if (m_vertex_buffer_cursor > m_vertex_buffer_size - datasize)
|
||||
{
|
||||
LockMode = D3DLOCK_DISCARD;
|
||||
m_vertex_buffer_cursor = 0;
|
||||
m_current_vertex_buffer = (m_current_vertex_buffer + 1) % m_buffers_count;
|
||||
}
|
||||
if(FAILED(m_vertex_buffers[m_current_vertex_buffer]->Lock(m_vertex_buffer_cursor, datasize,(VOID**)(&pVertices), LockMode)))
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
return;
|
||||
}
|
||||
memcpy(pVertices, s_pBaseBufferPointer, datasize);
|
||||
m_vertex_buffers[m_current_vertex_buffer]->Unlock();
|
||||
|
||||
LockMode = D3DLOCK_NOOVERWRITE;
|
||||
if (m_index_buffer_cursor > m_index_buffer_size - IndexDataSize)
|
||||
{
|
||||
LockMode = D3DLOCK_DISCARD;
|
||||
m_index_buffer_cursor = 0;
|
||||
m_current_index_buffer = (m_current_index_buffer + 1) % m_buffers_count;
|
||||
}
|
||||
|
||||
if(FAILED(m_index_buffers[m_current_index_buffer]->Lock(m_index_buffer_cursor * sizeof(u16), IndexDataSize * sizeof(u16), (VOID**)(&pIndices), LockMode )))
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
return;
|
||||
}
|
||||
if(TdataSize)
|
||||
{
|
||||
memcpy(pIndices, GetTriangleIndexBuffer(), TdataSize * sizeof(u16));
|
||||
pIndices += TdataSize;
|
||||
}
|
||||
if(LDataSize)
|
||||
{
|
||||
memcpy(pIndices, GetLineIndexBuffer(), LDataSize * sizeof(u16));
|
||||
pIndices += LDataSize;
|
||||
}
|
||||
m_index_buffers[m_current_index_buffer]->Unlock();
|
||||
}
|
||||
if(m_current_stride != stride || m_vertex_buffer_cursor == 0)
|
||||
{
|
||||
m_current_stride = stride;
|
||||
D3D::SetStreamSource( 0, m_vertex_buffers[m_current_vertex_buffer], 0, m_current_stride);
|
||||
}
|
||||
if (m_index_buffer_cursor == 0)
|
||||
{
|
||||
D3D::SetIndices(m_index_buffers[m_current_index_buffer]);
|
||||
}
|
||||
|
||||
ADDSTAT(stats.thisFrame.bytesVertexStreamed, datasize);
|
||||
ADDSTAT(stats.thisFrame.bytesIndexStreamed, IndexDataSize);
|
||||
}
|
||||
|
||||
void VertexManager::DrawVertexBuffer(int stride)
|
||||
{
|
||||
int triangles = IndexGenerator::GetNumTriangles();
|
||||
int lines = IndexGenerator::GetNumLines();
|
||||
int points = IndexGenerator::GetNumPoints();
|
||||
int numverts = IndexGenerator::GetNumVerts();
|
||||
int StartIndex = m_index_buffer_cursor;
|
||||
int basevertex = m_vertex_buffer_cursor / stride;
|
||||
if (triangles > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitive(
|
||||
D3DPT_TRIANGLELIST,
|
||||
basevertex,
|
||||
0,
|
||||
numverts,
|
||||
StartIndex,
|
||||
triangles)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
StartIndex += IndexGenerator::GetTriangleindexLen();
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (lines > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitive(
|
||||
D3DPT_LINELIST,
|
||||
basevertex,
|
||||
0,
|
||||
numverts,
|
||||
StartIndex,
|
||||
IndexGenerator::GetNumLines())))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
StartIndex += IndexGenerator::GetLineindexLen();
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (points > 0)
|
||||
{
|
||||
//DrawIndexedPrimitive does not support point list so we have to draw them using DrawPrimitive
|
||||
u16* PointIndexBuffer = GetPointIndexBuffer();
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
int count = i + 1;
|
||||
while (count < points && PointIndexBuffer[count - 1] + 1 == PointIndexBuffer[count])
|
||||
{
|
||||
count++;
|
||||
}
|
||||
if (FAILED(D3D::dev->DrawPrimitive(
|
||||
D3DPT_POINTLIST,
|
||||
basevertex + PointIndexBuffer[i],
|
||||
count - i)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numDrawCalls);
|
||||
i = count;
|
||||
} while (i < points);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VertexManager::DrawVertexArray(int stride)
|
||||
{
|
||||
int triangles = IndexGenerator::GetNumTriangles();
|
||||
int lines = IndexGenerator::GetNumLines();
|
||||
int points = IndexGenerator::GetNumPoints();
|
||||
int numverts = IndexGenerator::GetNumVerts();
|
||||
if (triangles > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_TRIANGLELIST,
|
||||
0, numverts, triangles,
|
||||
GetTriangleIndexBuffer(),
|
||||
D3DFMT_INDEX16,
|
||||
s_pBaseBufferPointer,
|
||||
stride)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (lines > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_LINELIST,
|
||||
0, numverts, lines,
|
||||
GetLineIndexBuffer(),
|
||||
D3DFMT_INDEX16,
|
||||
s_pBaseBufferPointer,
|
||||
stride)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (points > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_POINTLIST,
|
||||
0, numverts, points,
|
||||
GetPointIndexBuffer(),
|
||||
D3DFMT_INDEX16,
|
||||
s_pBaseBufferPointer,
|
||||
stride)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::vFlush()
|
||||
{
|
||||
u32 usedtextures = 0;
|
||||
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
|
||||
if (bpmem.tevorders[i / 2].getEnable(i & 1))
|
||||
usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1);
|
||||
|
||||
if (bpmem.genMode.numindstages > 0)
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1; ++i)
|
||||
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
|
||||
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
|
||||
|
||||
for (unsigned int i = 0; i < 8; i++)
|
||||
{
|
||||
if (usedtextures & (1 << i))
|
||||
{
|
||||
g_renderer->SetSamplerState(i & 3, i >> 2);
|
||||
FourTexUnits &tex = bpmem.tex[i >> 2];
|
||||
TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i,
|
||||
(tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5,
|
||||
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
||||
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
||||
tex.texTlut[i&3].tlut_format,
|
||||
(tex.texMode0[i&3].min_filter & 3),
|
||||
(tex.texMode1[i&3].max_lod + 0xf) / 0x10,
|
||||
tex.texImage1[i&3].image_type);
|
||||
|
||||
if (tentry)
|
||||
{
|
||||
// 0s are probably for no manual wrapping needed.
|
||||
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0);
|
||||
}
|
||||
else
|
||||
ERROR_LOG(VIDEO, "Error loading texture");
|
||||
}
|
||||
}
|
||||
|
||||
// set global constants
|
||||
VertexShaderManager::SetConstants();
|
||||
PixelShaderManager::SetConstants(g_nativeVertexFmt->m_components);
|
||||
u32 stride = g_nativeVertexFmt->GetVertexStride();
|
||||
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
|
||||
bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
bool useDualSource = useDstAlpha && g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
|
||||
DSTALPHA_MODE AlphaMode = useDualSource ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE;
|
||||
|
||||
if (!PixelShaderCache::SetShader(AlphaMode ,g_nativeVertexFmt->m_components))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
|
||||
goto shader_fail;
|
||||
}
|
||||
if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set vertex shader\n");});
|
||||
goto shader_fail;
|
||||
|
||||
}
|
||||
PrepareDrawBuffers(stride);
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
|
||||
if(m_buffers_count)
|
||||
{
|
||||
DrawVertexBuffer(stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawVertexArray(stride);
|
||||
}
|
||||
g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
|
||||
if (useDstAlpha && !useDualSource)
|
||||
{
|
||||
if (!PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS, g_nativeVertexFmt->m_components))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
|
||||
goto shader_fail;
|
||||
}
|
||||
// update alpha only
|
||||
g_renderer->ApplyState(true);
|
||||
if(m_buffers_count)
|
||||
{
|
||||
DrawVertexBuffer(stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawVertexArray(stride);
|
||||
}
|
||||
g_renderer->RestoreState();
|
||||
}
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
|
||||
|
||||
shader_fail:
|
||||
if(m_buffers_count)
|
||||
{
|
||||
m_index_buffer_cursor += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
|
||||
m_vertex_buffer_cursor += IndexGenerator::GetNumVerts() * stride;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef _VERTEXMANAGER_H
|
||||
#define _VERTEXMANAGER_H
|
||||
|
||||
#include "CPMemory.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
#include "VertexManagerBase.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class VertexManager : public ::VertexManager
|
||||
{
|
||||
public:
|
||||
NativeVertexFormat* CreateNativeVertexFormat();
|
||||
void GetElements(NativeVertexFormat* format, D3DVERTEXELEMENT9** elems, int* num);
|
||||
void CreateDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
private:
|
||||
u32 m_vertex_buffer_cursor;
|
||||
u32 m_vertex_buffer_size;
|
||||
u32 m_index_buffer_cursor;
|
||||
u32 m_index_buffer_size;
|
||||
u32 m_buffers_count;
|
||||
u32 m_current_vertex_buffer;
|
||||
u32 m_current_stride;
|
||||
u32 m_current_index_buffer;
|
||||
LPDIRECT3DVERTEXBUFFER9 *m_vertex_buffers;
|
||||
LPDIRECT3DINDEXBUFFER9 *m_index_buffers;
|
||||
void PrepareDrawBuffers(u32 stride);
|
||||
void DrawVertexBuffer(int stride);
|
||||
void DrawVertexArray(int stride);
|
||||
// temp
|
||||
void vFlush();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,293 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "LinearDiskCache.h"
|
||||
|
||||
#include "Globals.h"
|
||||
#include "D3DBase.h"
|
||||
#include "D3DShader.h"
|
||||
#include "Statistics.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
#include "Debugger.h"
|
||||
#include "ConfigManager.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry;
|
||||
VertexShaderUid VertexShaderCache::last_uid;
|
||||
UidChecker<VertexShaderUid,VertexShaderCode> VertexShaderCache::vertex_uid_checker;
|
||||
|
||||
#define MAX_SSAA_SHADERS 3
|
||||
|
||||
static LPDIRECT3DVERTEXSHADER9 SimpleVertexShader[MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DVERTEXSHADER9 ClearVertexShader;
|
||||
|
||||
LinearDiskCache<VertexShaderUid, u8> g_vs_disk_cache;
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetSimpleVertexShader(int level)
|
||||
{
|
||||
return SimpleVertexShader[level % MAX_SSAA_SHADERS];
|
||||
}
|
||||
|
||||
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetClearVertexShader()
|
||||
{
|
||||
return ClearVertexShader;
|
||||
}
|
||||
|
||||
// this class will load the precompiled shaders into our cache
|
||||
class VertexShaderCacheInserter : public LinearDiskCacheReader<VertexShaderUid, u8>
|
||||
{
|
||||
public:
|
||||
void Read(const VertexShaderUid &key, const u8 *value, u32 value_size)
|
||||
{
|
||||
VertexShaderCache::InsertByteCode(key, value, value_size, false);
|
||||
}
|
||||
};
|
||||
|
||||
void VertexShaderCache::Init()
|
||||
{
|
||||
char* vProg = new char[2048];
|
||||
sprintf(vProg,"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float2 vTexCoord : TEXCOORD0;\n"
|
||||
"float vTexCoord1 : TEXCOORD1;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float inTEX2 : TEXCOORD2)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0;\n"
|
||||
"OUT.vTexCoord1 = inTEX2;\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
|
||||
SimpleVertexShader[0] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
sprintf(vProg,"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vColor0 : COLOR0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vColor0 = inColor0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
|
||||
ClearVertexShader = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
sprintf(vProg, "struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vTexCoord : TEXCOORD0;\n"
|
||||
"float vTexCoord1 : TEXCOORD1;\n"
|
||||
"float4 vTexCoord2 : TEXCOORD2;\n"
|
||||
"float4 vTexCoord3 : TEXCOORD3;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float inTEX2 : TEXCOORD2)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0.xyyx;\n"
|
||||
"OUT.vTexCoord1 = inTEX2.x;\n"
|
||||
"OUT.vTexCoord2 = inTEX0.xyyx + (float4(-0.495f,-0.495f, 0.495f,-0.495f) * inTEX1.xyyx);\n"
|
||||
"OUT.vTexCoord3 = inTEX0.xyyx + (float4( 0.495f, 0.495f,-0.495f, 0.495f) * inTEX1.xyyx);\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
SimpleVertexShader[1] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
sprintf(vProg, "struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vTexCoord : TEXCOORD0;\n"
|
||||
"float vTexCoord1 : TEXCOORD1;\n"
|
||||
"float4 vTexCoord2 : TEXCOORD2;\n"
|
||||
"float4 vTexCoord3 : TEXCOORD3;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float inTEX2 : TEXCOORD2)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0.xyyx;\n"
|
||||
"OUT.vTexCoord1 = inTEX2.x;\n"
|
||||
"OUT.vTexCoord2 = inTEX0.xyyx + (float4(-0.9f,-0.45f, 0.9f,-0.45f) * inTEX1.xyyx);\n"
|
||||
"OUT.vTexCoord3 = inTEX0.xyyx + (float4( 0.9f, 0.45f,-0.9f, 0.45f) * inTEX1.xyyx);\n"
|
||||
"return OUT;\n"
|
||||
"}\n");
|
||||
SimpleVertexShader[2] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
|
||||
|
||||
Clear();
|
||||
delete [] vProg;
|
||||
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str());
|
||||
|
||||
SETSTAT(stats.numVertexShadersCreated, 0);
|
||||
SETSTAT(stats.numVertexShadersAlive, 0);
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
|
||||
VertexShaderCacheInserter inserter;
|
||||
g_vs_disk_cache.OpenAndRead(cache_filename, inserter);
|
||||
|
||||
if (g_Config.bEnableShaderDebugging)
|
||||
Clear();
|
||||
|
||||
last_entry = NULL;
|
||||
}
|
||||
|
||||
void VertexShaderCache::Clear()
|
||||
{
|
||||
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter)
|
||||
iter->second.Destroy();
|
||||
vshaders.clear();
|
||||
vertex_uid_checker.Invalidate();
|
||||
|
||||
last_entry = NULL;
|
||||
}
|
||||
|
||||
void VertexShaderCache::Shutdown()
|
||||
{
|
||||
for (int i = 0; i < MAX_SSAA_SHADERS; i++)
|
||||
{
|
||||
if (SimpleVertexShader[i])
|
||||
SimpleVertexShader[i]->Release();
|
||||
SimpleVertexShader[i] = NULL;
|
||||
}
|
||||
|
||||
if (ClearVertexShader)
|
||||
ClearVertexShader->Release();
|
||||
ClearVertexShader = NULL;
|
||||
|
||||
Clear();
|
||||
g_vs_disk_cache.Sync();
|
||||
g_vs_disk_cache.Close();
|
||||
}
|
||||
|
||||
bool VertexShaderCache::SetShader(u32 components)
|
||||
{
|
||||
VertexShaderUid uid;
|
||||
GetVertexShaderUid(uid, components, API_D3D9);
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
VertexShaderCode code;
|
||||
GenerateVertexShaderCode(code, components, API_D3D9);
|
||||
vertex_uid_checker.AddToIndexAndCheck(code, uid, "Vertex", "v");
|
||||
}
|
||||
|
||||
if (last_entry)
|
||||
{
|
||||
if (uid == last_uid)
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
return (last_entry->shader != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
last_uid = uid;
|
||||
|
||||
VSCache::iterator iter = vshaders.find(uid);
|
||||
if (iter != vshaders.end())
|
||||
{
|
||||
const VSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
if (entry.shader) D3D::SetVertexShader(entry.shader);
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
return (entry.shader != NULL);
|
||||
}
|
||||
|
||||
VertexShaderCode code;
|
||||
GenerateVertexShaderCode(code, components, API_D3D9);
|
||||
|
||||
u8 *bytecode;
|
||||
int bytecodelen;
|
||||
if (!D3D::CompileVertexShader(code.GetBuffer(), (int)strlen(code.GetBuffer()), &bytecode, &bytecodelen))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
|
||||
return false;
|
||||
}
|
||||
g_vs_disk_cache.Append(uid, bytecode, bytecodelen);
|
||||
|
||||
bool success = InsertByteCode(uid, bytecode, bytecodelen, true);
|
||||
if (g_ActiveConfig.bEnableShaderDebugging && success)
|
||||
{
|
||||
vshaders[uid].code = code.GetBuffer();
|
||||
}
|
||||
delete [] bytecode;
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool VertexShaderCache::InsertByteCode(const VertexShaderUid &uid, const u8 *bytecode, int bytecodelen, bool activate) {
|
||||
LPDIRECT3DVERTEXSHADER9 shader = D3D::CreateVertexShaderFromByteCode(bytecode, bytecodelen);
|
||||
|
||||
// Make an entry in the table
|
||||
VSCacheEntry entry;
|
||||
entry.shader = shader;
|
||||
|
||||
vshaders[uid] = entry;
|
||||
last_entry = &vshaders[uid];
|
||||
if (!shader)
|
||||
return false;
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
if (activate)
|
||||
{
|
||||
D3D::SetVertexShader(shader);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float VSConstantbuffer[4*C_VENVCONST_END];
|
||||
|
||||
void Renderer::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
float* VSConstantbuffer_pointer = &VSConstantbuffer[const_number];
|
||||
VSConstantbuffer_pointer[0] = f1;
|
||||
VSConstantbuffer_pointer[1] = f2;
|
||||
VSConstantbuffer_pointer[2] = f3;
|
||||
VSConstantbuffer_pointer[3] = f4;
|
||||
DX9::D3D::dev->SetVertexShaderConstantF(const_number, VSConstantbuffer_pointer, 1);
|
||||
}
|
||||
|
||||
void Renderer::SetVSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
DX9::D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
|
||||
}
|
||||
|
||||
void Renderer::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
float* VSConstantbuffer_pointer = &VSConstantbuffer[const_number];
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*VSConstantbuffer_pointer++ = *f++;
|
||||
*VSConstantbuffer_pointer++ = *f++;
|
||||
*VSConstantbuffer_pointer++ = *f++;
|
||||
*VSConstantbuffer_pointer++ = 0.f;
|
||||
}
|
||||
DX9::D3D::dev->SetVertexShaderConstantF(const_number, &VSConstantbuffer[const_number], count);
|
||||
}
|
||||
|
||||
void Renderer::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
DX9::D3D::dev->SetVertexShaderConstantF(const_number, f, count);
|
||||
}
|
||||
|
||||
} // namespace DX9
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class VertexShaderCache
|
||||
{
|
||||
private:
|
||||
struct VSCacheEntry
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 shader;
|
||||
|
||||
std::string code;
|
||||
|
||||
VSCacheEntry() : shader(NULL) {}
|
||||
void Destroy()
|
||||
{
|
||||
if (shader)
|
||||
shader->Release();
|
||||
shader = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<VertexShaderUid, VSCacheEntry> VSCache;
|
||||
|
||||
static VSCache vshaders;
|
||||
static const VSCacheEntry *last_entry;
|
||||
static VertexShaderUid last_uid;
|
||||
|
||||
static UidChecker<VertexShaderUid,VertexShaderCode> vertex_uid_checker;
|
||||
|
||||
static void Clear();
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
static bool SetShader(u32 components);
|
||||
static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexShader(int level);
|
||||
static LPDIRECT3DVERTEXSHADER9 GetClearVertexShader();
|
||||
static bool InsertByteCode(const VertexShaderUid &uid, const u8 *bytecode, int bytecodelen, bool activate);
|
||||
|
||||
static std::string GetCurrentShaderCode();
|
||||
};
|
||||
|
||||
} // namespace DX9
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
#ifndef DX9_VIDEO_BACKEND_H_
|
||||
#define DX9_VIDEO_BACKEND_H_
|
||||
|
||||
#include "VideoBackendBase.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
class VideoBackend : public VideoBackendHardware
|
||||
{
|
||||
bool Initialize(void *&);
|
||||
void Shutdown();
|
||||
|
||||
std::string GetName();
|
||||
std::string GetDisplayName();
|
||||
|
||||
void Video_Prepare();
|
||||
void Video_Cleanup();
|
||||
|
||||
void ShowConfig(void* parent);
|
||||
|
||||
void UpdateFPSDisplay(const char*);
|
||||
unsigned int PeekMessages();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,241 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common.h"
|
||||
#include "Atomic.h"
|
||||
#include "Thread.h"
|
||||
#include "LogManager.h"
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
#include "VideoConfigDiag.h"
|
||||
#endif // HAVE_WX
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
#include "Debugger/DebuggerPanel.h"
|
||||
#endif // HAVE_WX
|
||||
|
||||
#include "MainBase.h"
|
||||
#include "main.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "Fifo.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TextureCache.h"
|
||||
#include "BPStructs.h"
|
||||
#include "VertexManager.h"
|
||||
#include "FramebufferManager.h"
|
||||
#include "VertexLoaderManager.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "CommandProcessor.h"
|
||||
#include "PixelEngine.h"
|
||||
#include "OnScreenDisplay.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "EmuWindow.h"
|
||||
#include "VideoState.h"
|
||||
#include "Render.h"
|
||||
#include "DLCache.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "IniFile.h"
|
||||
#include "Core.h"
|
||||
#include "Host.h"
|
||||
|
||||
#include "ConfigManager.h"
|
||||
#include "VideoBackend.h"
|
||||
#include "PerfQuery.h"
|
||||
|
||||
namespace DX9
|
||||
{
|
||||
|
||||
unsigned int VideoBackend::PeekMessages()
|
||||
{
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
return FALSE;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void VideoBackend::UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
TCHAR temp[512];
|
||||
swprintf_s(temp, sizeof(temp)/sizeof(TCHAR), _T("%hs | DX9 | %hs"), scm_rev_str, text);
|
||||
EmuWindow::SetWindowText(temp);
|
||||
}
|
||||
|
||||
std::string VideoBackend::GetName()
|
||||
{
|
||||
return "DX9";
|
||||
}
|
||||
|
||||
std::string VideoBackend::GetDisplayName()
|
||||
{
|
||||
return "Direct3D9 (deprecated)";
|
||||
}
|
||||
|
||||
void InitBackendInfo()
|
||||
{
|
||||
DX9::D3D::Init();
|
||||
D3DCAPS9 device_caps = DX9::D3D::GetCaps();
|
||||
const int shaderModel = ((device_caps.PixelShaderVersion >> 8) & 0xFF);
|
||||
const int maxConstants = (shaderModel < 3) ? 32 : ((shaderModel < 4) ? 224 : 65536);
|
||||
g_Config.backend_info.APIType = shaderModel < 3 ? API_D3D9_SM20 : API_D3D9_SM30;
|
||||
g_Config.backend_info.bUseRGBATextures = false;
|
||||
g_Config.backend_info.bUseMinimalMipCount = true;
|
||||
g_Config.backend_info.bSupports3DVision = true;
|
||||
g_Config.backend_info.bSupportsPrimitiveRestart = false; // D3D9 does not support primitive restart
|
||||
g_Config.backend_info.bSupportsSeparateAlphaFunction = device_caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND;
|
||||
// Dual source blend disabled by default until a proper method to test for support is found
|
||||
g_Config.backend_info.bSupports3DVision = true;
|
||||
OSVERSIONINFO info;
|
||||
ZeroMemory(&info, sizeof(OSVERSIONINFO));
|
||||
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
if (GetVersionEx(&info))
|
||||
{
|
||||
// dual source blending is only supported in windows 7 o newer. sorry xp users
|
||||
// we cannot test for device caps because most drivers just declare the minimun caps
|
||||
// and don't expose their support for some functionalities
|
||||
g_Config.backend_info.bSupportsDualSourceBlend = g_Config.backend_info.bSupportsSeparateAlphaFunction && (info.dwPlatformId == VER_PLATFORM_WIN32_NT) && ((info.dwMajorVersion > 6) || ((info.dwMajorVersion == 6) && info.dwMinorVersion >= 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Config.backend_info.bSupportsDualSourceBlend = false;
|
||||
}
|
||||
g_Config.backend_info.bSupportsFormatReinterpretation = true;
|
||||
g_Config.backend_info.bSupportsPixelLighting = C_PLIGHTS + 40 <= maxConstants && C_PMATERIALS + 4 <= maxConstants;
|
||||
g_Config.backend_info.bSupportsEarlyZ = false;
|
||||
|
||||
// adapters
|
||||
g_Config.backend_info.Adapters.clear();
|
||||
for (int i = 0; i < DX9::D3D::GetNumAdapters(); ++i)
|
||||
g_Config.backend_info.Adapters.push_back(DX9::D3D::GetAdapter(i).ident.Description);
|
||||
|
||||
// aamodes
|
||||
g_Config.backend_info.AAModes.clear();
|
||||
if (g_Config.iAdapter < DX9::D3D::GetNumAdapters())
|
||||
{
|
||||
const DX9::D3D::Adapter &adapter = DX9::D3D::GetAdapter(g_Config.iAdapter);
|
||||
|
||||
for (int i = 0; i < (int)adapter.aa_levels.size(); ++i)
|
||||
g_Config.backend_info.AAModes.push_back(adapter.aa_levels[i].name);
|
||||
}
|
||||
|
||||
// Clear ppshaders string vector
|
||||
g_Config.backend_info.PPShaders.clear();
|
||||
|
||||
DX9::D3D::Shutdown();
|
||||
}
|
||||
|
||||
void VideoBackend::ShowConfig(void* parent)
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
InitBackendInfo();
|
||||
VideoConfigDiag diag((wxWindow*)parent, _trans("Direct3D9"), "gfx_dx9");
|
||||
diag.ShowModal();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool VideoBackend::Initialize(void *&window_handle)
|
||||
{
|
||||
InitializeShared();
|
||||
InitBackendInfo();
|
||||
|
||||
frameCount = 0;
|
||||
|
||||
g_Config.Load((File::GetUserPath(D_CONFIG_IDX) + "gfx_dx9.ini").c_str());
|
||||
g_Config.GameIniLoad();
|
||||
g_Config.UpdateProjectionHack();
|
||||
g_Config.VerifyValidity();
|
||||
// as only some driver/hardware configurations support dual source blending only enable it if is
|
||||
// configured by user
|
||||
g_Config.backend_info.bSupportsDualSourceBlend &= g_Config.bForceDualSourceBlend;
|
||||
UpdateActiveConfig();
|
||||
|
||||
window_handle = (void*)EmuWindow::Create((HWND)window_handle, GetModuleHandle(0), _T("Loading - Please wait."));
|
||||
if (window_handle == NULL)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "An error has occurred while trying to create the window.");
|
||||
return false;
|
||||
}
|
||||
else if (FAILED(DX9::D3D::Init()))
|
||||
{
|
||||
MessageBox(GetActiveWindow(), _T("Unable to initialize Direct3D. Please make sure that you have the latest version of DirectX 9.0c correctly installed."), _T("Fatal Error"), MB_ICONERROR|MB_OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
s_BackendInitialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VideoBackend::Video_Prepare()
|
||||
{
|
||||
// Better be safe...
|
||||
s_efbAccessRequested = FALSE;
|
||||
s_FifoShuttingDown = FALSE;
|
||||
s_swapRequested = FALSE;
|
||||
|
||||
// internal interfaces
|
||||
g_vertex_manager = new VertexManager;
|
||||
g_perf_query = new PerfQuery;
|
||||
g_renderer = new Renderer;
|
||||
g_texture_cache = new TextureCache;
|
||||
// VideoCommon
|
||||
BPInit();
|
||||
Fifo_Init();
|
||||
IndexGenerator::Init();
|
||||
VertexLoaderManager::Init();
|
||||
OpcodeDecoder_Init();
|
||||
VertexShaderManager::Init();
|
||||
PixelShaderManager::Init();
|
||||
CommandProcessor::Init();
|
||||
PixelEngine::Init();
|
||||
DLCache::Init();
|
||||
// Notify the core that the video backend is ready
|
||||
Host_Message(WM_USER_CREATE);
|
||||
}
|
||||
|
||||
void VideoBackend::Shutdown()
|
||||
{
|
||||
s_BackendInitialized = false;
|
||||
|
||||
// TODO: should be in Video_Cleanup
|
||||
if (g_renderer)
|
||||
{
|
||||
s_efbAccessRequested = FALSE;
|
||||
s_FifoShuttingDown = FALSE;
|
||||
s_swapRequested = FALSE;
|
||||
|
||||
// VideoCommon
|
||||
DLCache::Shutdown();
|
||||
Fifo_Shutdown();
|
||||
CommandProcessor::Shutdown();
|
||||
PixelShaderManager::Shutdown();
|
||||
VertexShaderManager::Shutdown();
|
||||
OpcodeDecoder_Shutdown();
|
||||
VertexLoaderManager::Shutdown();
|
||||
|
||||
// internal interfaces
|
||||
PixelShaderCache::Shutdown();
|
||||
VertexShaderCache::Shutdown();
|
||||
delete g_texture_cache;
|
||||
delete g_renderer;
|
||||
delete g_perf_query;
|
||||
delete g_vertex_manager;
|
||||
g_renderer = NULL;
|
||||
g_texture_cache = NULL;
|
||||
}
|
||||
D3D::Shutdown();
|
||||
}
|
||||
|
||||
void VideoBackend::Video_Cleanup() {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "VideoBackend.h"
|
||||
#include "Render.h"
|
||||
#include "MainBase.h"
|
||||
|
||||
#endif
|
|
@ -1,5 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "stdafx.h"
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
#define _WIN32_WINNT 0x501
|
||||
#ifndef _WIN32_IE
|
||||
#define _WIN32_IE 0x0500 // Default value is 0x0400
|
||||
#endif
|
||||
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
Loading…
Reference in New Issue