Add Vulkan renderer (unimplemented, clone of OpenGL)
This commit is contained in:
parent
ed3f789c2a
commit
3d06c7c647
|
@ -317,6 +317,10 @@
|
|||
<Project>{E6B436B1-A3CD-4C9A-8F76-5D7154726884}</Project>
|
||||
<Name>BizHawk.Bizware.BizwareGL.SlimDX</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Bizware\BizHawk.Bizware.BizwareGL.Vulkan\BizHawk.Bizware.BizwareGL.Vulkan.csproj">
|
||||
<Project>{538947c1-b7f6-8a0d-c976-41ee5160cfb1}</Project>
|
||||
<Name>BizHawk.Bizware.BizwareGL.Vulkan</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Bizware\BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj">
|
||||
<Project>{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}</Project>
|
||||
<Name>BizHawk.Bizware.BizwareGL</Name>
|
||||
|
|
|
@ -3,6 +3,7 @@ using BizHawk.Bizware.BizwareGL;
|
|||
using BizHawk.Bizware.BizwareGL.Drivers.GdiPlus;
|
||||
using BizHawk.Bizware.BizwareGL.Drivers.OpenTK;
|
||||
using BizHawk.Bizware.BizwareGL.Drivers.SlimDX;
|
||||
using BizHawk.Bizware.BizwareGL.Drivers.Vulkan;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
|
@ -10,12 +11,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
public static IGuiRenderer CreateRenderer(this IGL gl)
|
||||
{
|
||||
if (gl is IGL_TK)
|
||||
{
|
||||
return new GuiRenderer(gl);
|
||||
}
|
||||
|
||||
if (gl is IGL_SlimDX9)
|
||||
if (gl is IGL_Vulkan || gl is IGL_TK || gl is IGL_SlimDX9)
|
||||
{
|
||||
return new GuiRenderer(gl);
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public enum EDispMethod
|
||||
{
|
||||
OpenGL, GdiPlus, SlimDX9
|
||||
OpenGL, GdiPlus, SlimDX9, Vulkan
|
||||
}
|
||||
|
||||
public enum ESoundOutputMethod
|
||||
|
|
|
@ -1830,6 +1830,10 @@
|
|||
<Project>{E6B436B1-A3CD-4C9A-8F76-5D7154726884}</Project>
|
||||
<Name>BizHawk.Bizware.BizwareGL.SlimDX</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Bizware\BizHawk.Bizware.BizwareGL.Vulkan\BizHawk.Bizware.BizwareGL.Vulkan.csproj">
|
||||
<Project>{538947c1-b7f6-8a0d-c976-41ee5160cfb1}</Project>
|
||||
<Name>BizHawk.Bizware.BizwareGL.Vulkan</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Bizware\BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj">
|
||||
<Project>{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}</Project>
|
||||
<Name>BizHawk.Bizware.BizwareGL</Name>
|
||||
|
|
|
@ -160,13 +160,29 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
// setup the GL context manager, needed for coping with multiple opengl cores vs opengl display method
|
||||
GLManager.CreateInstance(GlobalWin.IGL_GL);
|
||||
GlobalWin.GLManager = GLManager.Instance;
|
||||
|
||||
GlobalWin.GLManager = GLManager.Instance;
|
||||
|
||||
//now create the "GL" context for the display method. we can reuse the IGL_TK context if opengl display method is chosen
|
||||
|
||||
REDO_DISPMETHOD:
|
||||
if (Global.Config.DispMethod == Config.EDispMethod.GdiPlus)
|
||||
GlobalWin.GL = new Bizware.BizwareGL.Drivers.GdiPlus.IGL_GdiPlus();
|
||||
else if (Global.Config.DispMethod == Config.EDispMethod.Vulkan)
|
||||
{
|
||||
try
|
||||
{
|
||||
GlobalWin.GL = new Bizware.BizwareGL.Drivers.Vulkan.IGL_Vulkan();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
new ExceptionBox(new Exception("Something in Vulkan init failed, using GDI+ as fallback", ex))
|
||||
.ShowDialog();
|
||||
|
||||
// fallback
|
||||
Global.Config.DispMethod = Config.EDispMethod.GdiPlus;
|
||||
goto REDO_DISPMETHOD;
|
||||
}
|
||||
}
|
||||
else if (Global.Config.DispMethod == Config.EDispMethod.SlimDX9 && !EXE_PROJECT.PlatformLinkedLibSingleton.RunningOnUnix)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -69,8 +69,10 @@
|
|||
this.label10 = new System.Windows.Forms.Label();
|
||||
this.nudPrescale = new System.Windows.Forms.NumericUpDown();
|
||||
this.tpDispMethod = new System.Windows.Forms.TabPage();
|
||||
this.label14 = new System.Windows.Forms.Label();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.groupBox3 = new System.Windows.Forms.GroupBox();
|
||||
this.rbVulkan = new System.Windows.Forms.RadioButton();
|
||||
this.label13 = new System.Windows.Forms.Label();
|
||||
this.cbAlternateVsync = new System.Windows.Forms.CheckBox();
|
||||
this.label8 = new System.Windows.Forms.Label();
|
||||
|
@ -122,7 +124,7 @@
|
|||
//
|
||||
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.btnCancel.Location = new System.Drawing.Point(473, 339);
|
||||
this.btnCancel.Location = new System.Drawing.Point(473, 365);
|
||||
this.btnCancel.Name = "btnCancel";
|
||||
this.btnCancel.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnCancel.TabIndex = 5;
|
||||
|
@ -132,7 +134,7 @@
|
|||
// btnOk
|
||||
//
|
||||
this.btnOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnOk.Location = new System.Drawing.Point(392, 339);
|
||||
this.btnOk.Location = new System.Drawing.Point(392, 365);
|
||||
this.btnOk.Name = "btnOk";
|
||||
this.btnOk.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnOk.TabIndex = 4;
|
||||
|
@ -469,7 +471,7 @@
|
|||
this.tabControl1.Location = new System.Drawing.Point(12, 12);
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(536, 317);
|
||||
this.tabControl1.Size = new System.Drawing.Size(536, 343);
|
||||
this.tabControl1.TabIndex = 17;
|
||||
//
|
||||
// tpAR
|
||||
|
@ -487,7 +489,7 @@
|
|||
this.tpAR.Location = new System.Drawing.Point(4, 22);
|
||||
this.tpAR.Name = "tpAR";
|
||||
this.tpAR.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tpAR.Size = new System.Drawing.Size(528, 291);
|
||||
this.tpAR.Size = new System.Drawing.Size(528, 317);
|
||||
this.tpAR.TabIndex = 0;
|
||||
this.tpAR.Text = "Scaling & Filtering";
|
||||
this.tpAR.UseVisualStyleBackColor = true;
|
||||
|
@ -544,18 +546,27 @@
|
|||
//
|
||||
// tpDispMethod
|
||||
//
|
||||
this.tpDispMethod.Controls.Add(this.label14);
|
||||
this.tpDispMethod.Controls.Add(this.label6);
|
||||
this.tpDispMethod.Controls.Add(this.groupBox3);
|
||||
this.tpDispMethod.Location = new System.Drawing.Point(4, 22);
|
||||
this.tpDispMethod.Name = "tpDispMethod";
|
||||
this.tpDispMethod.Size = new System.Drawing.Size(528, 291);
|
||||
this.tpDispMethod.Size = new System.Drawing.Size(528, 317);
|
||||
this.tpDispMethod.TabIndex = 2;
|
||||
this.tpDispMethod.Text = "Display Method";
|
||||
this.tpDispMethod.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// label14
|
||||
//
|
||||
this.label14.Location = new System.Drawing.Point(31, 260);
|
||||
this.label14.Name = "label14";
|
||||
this.label14.Size = new System.Drawing.Size(359, 18);
|
||||
this.label14.TabIndex = 24;
|
||||
this.label14.Text = " • Experimental, high-performance, and open.\r\n";
|
||||
//
|
||||
// label6
|
||||
//
|
||||
this.label6.Location = new System.Drawing.Point(3, 258);
|
||||
this.label6.Location = new System.Drawing.Point(3, 293);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(359, 23);
|
||||
this.label6.TabIndex = 18;
|
||||
|
@ -563,6 +574,7 @@
|
|||
//
|
||||
// groupBox3
|
||||
//
|
||||
this.groupBox3.Controls.Add(this.rbVulkan);
|
||||
this.groupBox3.Controls.Add(this.label13);
|
||||
this.groupBox3.Controls.Add(this.cbAlternateVsync);
|
||||
this.groupBox3.Controls.Add(this.label8);
|
||||
|
@ -573,10 +585,22 @@
|
|||
this.groupBox3.Controls.Add(this.rbOpenGL);
|
||||
this.groupBox3.Location = new System.Drawing.Point(6, 5);
|
||||
this.groupBox3.Name = "groupBox3";
|
||||
this.groupBox3.Size = new System.Drawing.Size(415, 241);
|
||||
this.groupBox3.Size = new System.Drawing.Size(415, 276);
|
||||
this.groupBox3.TabIndex = 16;
|
||||
this.groupBox3.TabStop = false;
|
||||
//
|
||||
// rbVulkan
|
||||
//
|
||||
this.rbVulkan.AutoSize = true;
|
||||
this.rbVulkan.Checked = true;
|
||||
this.rbVulkan.Location = new System.Drawing.Point(6, 235);
|
||||
this.rbVulkan.Name = "rbVulkan";
|
||||
this.rbVulkan.Size = new System.Drawing.Size(65, 17);
|
||||
this.rbVulkan.TabIndex = 23;
|
||||
this.rbVulkan.TabStop = true;
|
||||
this.rbVulkan.Text = "Vulkan";
|
||||
this.rbVulkan.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// label13
|
||||
//
|
||||
this.label13.Location = new System.Drawing.Point(45, 60);
|
||||
|
@ -602,8 +626,7 @@
|
|||
this.label8.Name = "label8";
|
||||
this.label8.Size = new System.Drawing.Size(359, 27);
|
||||
this.label8.TabIndex = 20;
|
||||
this.label8.Text = " • Best compatibility\r\n • May have trouble with OpenGL-based cores (N64)\r\n" +
|
||||
"";
|
||||
this.label8.Text = " • Best compatibility\r\n • May have trouble with OpenGL-based cores (N64)\r\n";
|
||||
//
|
||||
// rbD3D9
|
||||
//
|
||||
|
@ -645,7 +668,7 @@
|
|||
this.tpMisc.Controls.Add(this.checkSnowyNullEmulator);
|
||||
this.tpMisc.Location = new System.Drawing.Point(4, 22);
|
||||
this.tpMisc.Name = "tpMisc";
|
||||
this.tpMisc.Size = new System.Drawing.Size(528, 291);
|
||||
this.tpMisc.Size = new System.Drawing.Size(528, 317);
|
||||
this.tpMisc.TabIndex = 3;
|
||||
this.tpMisc.Text = "Misc";
|
||||
this.tpMisc.UseVisualStyleBackColor = true;
|
||||
|
@ -704,7 +727,7 @@
|
|||
this.tabPage1.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage1.Size = new System.Drawing.Size(528, 291);
|
||||
this.tabPage1.Size = new System.Drawing.Size(528, 317);
|
||||
this.tabPage1.TabIndex = 4;
|
||||
this.tabPage1.Text = "Window";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
|
@ -897,7 +920,7 @@
|
|||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.btnCancel;
|
||||
this.ClientSize = new System.Drawing.Size(564, 374);
|
||||
this.ClientSize = new System.Drawing.Size(564, 400);
|
||||
this.Controls.Add(this.linkLabel1);
|
||||
this.Controls.Add(this.tabControl1);
|
||||
this.Controls.Add(this.btnCancel);
|
||||
|
@ -908,6 +931,7 @@
|
|||
this.Text = "Display Configuration";
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.tbScanlineIntensity)).EndInit();
|
||||
this.grpFinalFilter.ResumeLayout(false);
|
||||
this.grpFinalFilter.PerformLayout();
|
||||
this.grpARSelection.ResumeLayout(false);
|
||||
|
@ -929,7 +953,6 @@
|
|||
this.groupBox4.PerformLayout();
|
||||
this.groupBox2.ResumeLayout(false);
|
||||
this.groupBox2.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.tbScanlineIntensity)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.trackbarFrameSizeWindowed)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
@ -1009,5 +1032,7 @@
|
|||
private System.Windows.Forms.CheckBox cbFullscreenHacks;
|
||||
private System.Windows.Forms.Button btnDefaults;
|
||||
private System.Windows.Forms.ToolTip toolTip1;
|
||||
private System.Windows.Forms.Label label14;
|
||||
private System.Windows.Forms.RadioButton rbVulkan;
|
||||
}
|
||||
}
|
|
@ -44,6 +44,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
rbOpenGL.Checked = Global.Config.DispMethod == Config.EDispMethod.OpenGL;
|
||||
rbGDIPlus.Checked = Global.Config.DispMethod == Config.EDispMethod.GdiPlus;
|
||||
rbD3D9.Checked = Global.Config.DispMethod == Config.EDispMethod.SlimDX9;
|
||||
rbVulkan.Checked = Global.Config.DispMethod == Config.EDispMethod.Vulkan;
|
||||
|
||||
cbStatusBarWindowed.Checked = Global.Config.DispChrome_StatusBarWindowed;
|
||||
cbCaptionWindowed.Checked = Global.Config.DispChrome_CaptionWindowed;
|
||||
|
@ -97,6 +98,12 @@ namespace BizHawk.Client.EmuHawk
|
|||
label13.Enabled = false;
|
||||
label8.Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disallow Vulkan selection on Windows
|
||||
rbVulkan.Enabled = false;
|
||||
label14.Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void btnOk_Click(object sender, EventArgs e)
|
||||
|
@ -183,6 +190,8 @@ namespace BizHawk.Client.EmuHawk
|
|||
Global.Config.DispMethod = Config.EDispMethod.GdiPlus;
|
||||
if(rbD3D9.Checked)
|
||||
Global.Config.DispMethod = Config.EDispMethod.SlimDX9;
|
||||
if (rbVulkan.Checked)
|
||||
Global.Config.DispMethod = Config.EDispMethod.Vulkan;
|
||||
|
||||
if (oldDisplayMethod != Global.Config.DispMethod)
|
||||
NeedReset = true;
|
||||
|
|
18
BizHawk.sln
18
BizHawk.sln
|
@ -59,6 +59,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Client.MultiHawk",
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Client.ApiHawk", "BizHawk.Client.ApiHawk\BizHawk.Client.ApiHawk.csproj", "{8E2F11F2-3955-4382-8C3A-CEBA1276CAEA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.BizwareGL.Vulkan", "Bizware\BizHawk.Bizware.BizwareGL.Vulkan\BizHawk.Bizware.BizwareGL.Vulkan.csproj", "{538947C1-B7F6-8A0D-C976-41EE5160CFB1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -245,6 +247,18 @@ Global
|
|||
{8E2F11F2-3955-4382-8C3A-CEBA1276CAEA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8E2F11F2-3955-4382-8C3A-CEBA1276CAEA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8E2F11F2-3955-4382-8C3A-CEBA1276CAEA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -263,6 +277,10 @@ Global
|
|||
{E6B436B1-A3CD-4C9A-8F76-5D7154726884} = {0540A9A6-977E-466D-8BD3-1D8590BD5282}
|
||||
{B95649F5-A0AE-41EB-B62B-578A2AFF5E18} = {B51F1139-3D2C-41BE-A762-EF1F9B41EACA}
|
||||
{8E2F11F2-3955-4382-8C3A-CEBA1276CAEA} = {B51F1139-3D2C-41BE-A762-EF1F9B41EACA}
|
||||
{538947C1-B7F6-8A0D-C976-41EE5160CFB1} = {0540A9A6-977E-466D-8BD3-1D8590BD5282}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {6BC2A276-7A5D-41C2-A756-36EB1FF7FBEF}
|
||||
EndGlobalSection
|
||||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
StartupItem = BizHawk.Client.EmuHawk\BizHawk.Client.EmuHawk.csproj
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{538947C1-B7F6-8A0D-C976-41EE5160CFB1}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>BizHawk.Bizware.BizwareGL.Vulkan</RootNamespace>
|
||||
<AssemblyName>BizHawk.Bizware.BizwareGL.Vulkan</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\output\dll\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<!--<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>-->
|
||||
<CodeAnalysisRuleSet Condition=" '$(OS)' == 'Windows_NT' ">MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
|
||||
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<OutputPath>..\..\output\dll\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<!--<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>-->
|
||||
<CodeAnalysisRuleSet Condition=" '$(OS)' == 'Windows_NT' ">MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
|
||||
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="OpenTK, Version=3.0.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\References\OpenTK.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="OpenTK.GLControl, Version=3.0.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\References\OpenTK.GLControl.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BizHawk.Common\BizHawk.Common.csproj">
|
||||
<Project>{866F8D13-0678-4FF9-80A4-A3993FD4D8A3}</Project>
|
||||
<Name>BizHawk.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj">
|
||||
<Project>{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}</Project>
|
||||
<Name>BizHawk.Bizware.BizwareGL</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="GraphicsControl_Vulkan.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="IGL_Vulkan.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,2 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp60</s:String></wpf:ResourceDictionary>
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using BizHawk.Bizware.BizwareGL;
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
|
||||
namespace BizHawk.Bizware.BizwareGL.Drivers.Vulkan
|
||||
{
|
||||
class GLControlWrapper_Vulkan : GLControl, IGraphicsControl
|
||||
{
|
||||
//Note: In order to work around bugs in OpenTK which sometimes do things to a context without making that context active first...
|
||||
//we are going to push and pop the context before doing stuff
|
||||
|
||||
public GLControlWrapper_Vulkan(IGL_Vulkan owner)
|
||||
: base(GraphicsMode.Default, 2, 0, GraphicsContextFlags.Default)
|
||||
{
|
||||
Owner = owner;
|
||||
GLControl = this;
|
||||
}
|
||||
|
||||
global::OpenTK.GLControl GLControl;
|
||||
IGL_Vulkan Owner;
|
||||
|
||||
public Control Control { get { return this; } }
|
||||
|
||||
|
||||
public void SetVsync(bool state)
|
||||
{
|
||||
//IGraphicsContext curr = global::OpenTK.Graphics.GraphicsContext.CurrentContext;
|
||||
GLControl.MakeCurrent();
|
||||
GLControl.VSync = state;
|
||||
//Owner.MakeContextCurrent(curr, Owner.NativeWindowsForContexts[curr]);
|
||||
}
|
||||
|
||||
public void Begin()
|
||||
{
|
||||
if (!GLControl.Context.IsCurrent)
|
||||
Owner.MakeContextCurrent(GLControl.Context, GLControl.WindowInfo);
|
||||
}
|
||||
|
||||
public void End()
|
||||
{
|
||||
Owner.MakeDefaultCurrent();
|
||||
}
|
||||
|
||||
public new void SwapBuffers()
|
||||
{
|
||||
if (!GLControl.Context.IsCurrent)
|
||||
MakeCurrent();
|
||||
base.SwapBuffers();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,883 @@
|
|||
//regarding binding and vertex arrays:
|
||||
//http://stackoverflow.com/questions/8704801/glvertexattribpointer-clarification
|
||||
//http://stackoverflow.com/questions/9536973/oes-vertex-array-object-and-client-state
|
||||
//http://www.opengl.org/wiki/Vertex_Specification
|
||||
|
||||
//etc
|
||||
//glBindAttribLocation (programID, 0, "vertexPosition_modelspace");
|
||||
|
||||
//for future reference: c# tesselators
|
||||
//http://www.opentk.com/node/437 (AGG#, codes on Tao forums)
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using sd = System.Drawing;
|
||||
using sdi = System.Drawing.Imaging;
|
||||
using swf=System.Windows.Forms;
|
||||
|
||||
using BizHawk.Bizware.BizwareGL;
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using otkg = OpenTK.Graphics;
|
||||
|
||||
namespace BizHawk.Bizware.BizwareGL.Drivers.Vulkan
|
||||
{
|
||||
/// <summary>
|
||||
/// OpenTK implementation of the BizwareGL.IGL interface.
|
||||
/// TODO - can we have more than one of these? could be dangerous. such dangerous things to be possibly reconsidered are marked with HAMNUTS
|
||||
/// TODO - if we have any way of making contexts, we also need a way of freeing it, and then we can cleanup our dictionaries
|
||||
/// </summary>
|
||||
public class IGL_Vulkan : IGL
|
||||
{
|
||||
//rendering state
|
||||
Pipeline _CurrPipeline;
|
||||
RenderTarget _CurrRenderTarget;
|
||||
|
||||
static IGL_Vulkan()
|
||||
{
|
||||
//make sure OpenTK initializes without getting wrecked on the SDL check and throwing an exception to annoy our MDA's
|
||||
var toolkitOptions = global::OpenTK.ToolkitOptions.Default;
|
||||
toolkitOptions.Backend = PlatformBackend.PreferNative;
|
||||
global::OpenTK.Toolkit.Init(toolkitOptions);
|
||||
//NOTE: this throws EGL exceptions anyway. I'm going to ignore it and whine about it later
|
||||
}
|
||||
|
||||
public string API { get { return "OPENGL"; } }
|
||||
|
||||
public int Version
|
||||
{
|
||||
get
|
||||
{
|
||||
//doesnt work on older than gl3 maybe
|
||||
//int major, minor;
|
||||
////other overloads may not exist...
|
||||
//GL.GetInteger(GetPName.MajorVersion, out major);
|
||||
//GL.GetInteger(GetPName.MinorVersion, out minor);
|
||||
|
||||
//supposedly the standard dictates that whatever junk is in the version string, some kind of version is at the beginning
|
||||
string version_string = GL.GetString(StringName.Version);
|
||||
var version_parts = version_string.Split('.');
|
||||
int major = int.Parse(version_parts[0]);
|
||||
//getting a minor version out is too hard and not needed now
|
||||
return major * 100;
|
||||
}
|
||||
}
|
||||
|
||||
public IGL_Vulkan(int major_version = 0, int minor_version = 0, bool forward_compatible = false)
|
||||
{
|
||||
//make an 'offscreen context' so we can at least do things without having to create a window
|
||||
OffscreenNativeWindow = new NativeWindow();
|
||||
OffscreenNativeWindow.ClientSize = new sd.Size(8, 8);
|
||||
this.GraphicsContext = new GraphicsContext(GraphicsMode.Default, OffscreenNativeWindow.WindowInfo, major_version, minor_version, forward_compatible ? GraphicsContextFlags.ForwardCompatible : GraphicsContextFlags.Default);
|
||||
MakeDefaultCurrent();
|
||||
|
||||
//this is important for reasons unknown
|
||||
this.GraphicsContext.LoadAll();
|
||||
|
||||
//misc initialization
|
||||
CreateRenderStates();
|
||||
PurgeStateCache();
|
||||
}
|
||||
|
||||
public void BeginScene()
|
||||
{
|
||||
//seems not to be needed...
|
||||
}
|
||||
|
||||
public void EndScene()
|
||||
{
|
||||
//seems not to be needed...
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
//TODO - a lot of analysis here
|
||||
OffscreenNativeWindow.Dispose(); OffscreenNativeWindow = null;
|
||||
GraphicsContext.Dispose(); GraphicsContext = null;
|
||||
}
|
||||
|
||||
public void Clear(ClearBufferMask mask)
|
||||
{
|
||||
GL.Clear((global::OpenTK.Graphics.OpenGL.ClearBufferMask)mask);
|
||||
}
|
||||
public void SetClearColor(sd.Color color)
|
||||
{
|
||||
GL.ClearColor(color);
|
||||
}
|
||||
|
||||
public IGraphicsControl Internal_CreateGraphicsControl()
|
||||
{
|
||||
var glc = new GLControlWrapper_Vulkan(this);
|
||||
glc.CreateControl();
|
||||
|
||||
//now the control's context will be current. annoying! fix it.
|
||||
MakeDefaultCurrent();
|
||||
|
||||
|
||||
return glc;
|
||||
}
|
||||
|
||||
public int GenTexture() { return GL.GenTexture(); }
|
||||
public void FreeTexture(Texture2d tex)
|
||||
{
|
||||
GL.DeleteTexture((int)tex.Opaque);
|
||||
}
|
||||
|
||||
public Shader CreateFragmentShader(bool cg, string source, string entry, bool required)
|
||||
{
|
||||
return CreateShader(cg, ShaderType.FragmentShader, source, entry, required);
|
||||
}
|
||||
public Shader CreateVertexShader(bool cg, string source, string entry, bool required)
|
||||
{
|
||||
return CreateShader(cg, ShaderType.VertexShader, source, entry, required);
|
||||
}
|
||||
|
||||
public IBlendState CreateBlendState(BlendingFactorSrc colorSource, BlendEquationMode colorEquation, BlendingFactorDest colorDest,
|
||||
BlendingFactorSrc alphaSource, BlendEquationMode alphaEquation, BlendingFactorDest alphaDest)
|
||||
{
|
||||
return new CacheBlendState(true, colorSource, colorEquation, colorDest, alphaSource, alphaEquation, alphaDest);
|
||||
}
|
||||
|
||||
public void SetBlendState(IBlendState rsBlend)
|
||||
{
|
||||
var mybs = rsBlend as CacheBlendState;
|
||||
if (mybs.Enabled)
|
||||
{
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.BlendEquationSeparate(mybs.colorEquation, mybs.alphaEquation);
|
||||
GL.BlendFuncSeparate(mybs.colorSource, mybs.colorDest, mybs.alphaSource, mybs.alphaDest);
|
||||
}
|
||||
else GL.Disable(EnableCap.Blend);
|
||||
if (rsBlend == _rsBlendNoneOpaque)
|
||||
{
|
||||
//make sure constant color is set correctly
|
||||
GL.BlendColor(new Color4(255, 255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
public IBlendState BlendNoneCopy { get { return _rsBlendNoneVerbatim; } }
|
||||
public IBlendState BlendNoneOpaque { get { return _rsBlendNoneOpaque; } }
|
||||
public IBlendState BlendNormal { get { return _rsBlendNormal; } }
|
||||
|
||||
class ShaderWrapper
|
||||
{
|
||||
public int sid;
|
||||
public Dictionary<string, string> MapCodeToNative;
|
||||
public Dictionary<string, string> MapNativeToCode;
|
||||
}
|
||||
|
||||
class PipelineWrapper
|
||||
{
|
||||
public int pid;
|
||||
public Shader FragmentShader, VertexShader;
|
||||
public List<int> SamplerLocs;
|
||||
}
|
||||
|
||||
public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required, string memo)
|
||||
{
|
||||
//if the shaders arent available, the pipeline isn't either
|
||||
if (!vertexShader.Available || !fragmentShader.Available)
|
||||
{
|
||||
string errors = string.Format("Vertex Shader:\r\n {0} \r\n-------\r\nFragment Shader:\r\n{1}", vertexShader.Errors, fragmentShader.Errors);
|
||||
if (required)
|
||||
throw new InvalidOperationException("Couldn't build required GL pipeline:\r\n" + errors);
|
||||
var pipeline = new Pipeline(this, null, false, null, null, null);
|
||||
pipeline.Errors = errors;
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
|
||||
var vsw = vertexShader.Opaque as ShaderWrapper;
|
||||
var fsw = fragmentShader.Opaque as ShaderWrapper;
|
||||
var sws = new[] { vsw,fsw };
|
||||
|
||||
bool mapVariables = vsw.MapCodeToNative != null || fsw.MapCodeToNative != null;
|
||||
|
||||
ErrorCode errcode;
|
||||
int pid = GL.CreateProgram();
|
||||
GL.AttachShader(pid, vsw.sid);
|
||||
errcode = GL.GetError();
|
||||
GL.AttachShader(pid, fsw.sid);
|
||||
errcode = GL.GetError();
|
||||
|
||||
//NOT BEING USED NOW: USING SEMANTICS INSTEAD
|
||||
////bind the attribute locations from the vertex layout
|
||||
////as we go, look for attribute mappings (CGC will happily reorder and rename our attribute mappings)
|
||||
////what's more it will _RESIZE_ them but this seems benign..somehow..
|
||||
////WELLLLLLL we wish we could do that by names
|
||||
////but the shaders dont seem to be adequate quality (oddly named attributes.. texCoord vs texCoord1). need to use semantics instead.
|
||||
//foreach (var kvp in vertexLayout.Items)
|
||||
//{
|
||||
// string name = kvp.Value.Name;
|
||||
// //if (mapVariables)
|
||||
// //{
|
||||
// // foreach (var sw in sws)
|
||||
// // {
|
||||
// // if (sw.MapNativeToCode.ContainsKey(name))
|
||||
// // {
|
||||
// // name = sw.MapNativeToCode[name];
|
||||
// // break;
|
||||
// // }
|
||||
// // }
|
||||
// //}
|
||||
|
||||
// if(mapVariables) {
|
||||
// ////proxy for came-from-cgc
|
||||
// //switch (kvp.Value.Usage)
|
||||
// //{
|
||||
// // case AttributeUsage.Position:
|
||||
// //}
|
||||
// }
|
||||
|
||||
// //GL.BindAttribLocation(pid, kvp.Key, name);
|
||||
//}
|
||||
|
||||
|
||||
GL.LinkProgram(pid);
|
||||
errcode = GL.GetError();
|
||||
|
||||
string resultLog = GL.GetProgramInfoLog(pid);
|
||||
|
||||
if (errcode != ErrorCode.NoError)
|
||||
if (required)
|
||||
throw new InvalidOperationException("Error creating pipeline (error returned from glLinkProgram): " + errcode + "\r\n\r\n" + resultLog);
|
||||
else success = false;
|
||||
|
||||
int linkStatus;
|
||||
GL.GetProgram(pid, GetProgramParameterName.LinkStatus, out linkStatus);
|
||||
if (linkStatus == 0)
|
||||
if (required)
|
||||
throw new InvalidOperationException("Error creating pipeline (link status false returned from glLinkProgram): " + "\r\n\r\n" + resultLog);
|
||||
else success = false;
|
||||
|
||||
//need to work on validation. apparently there are some weird caveats to glValidate which make it complicated and possibly excuses (barely) the intel drivers' dysfunctional operation
|
||||
//"A sampler points to a texture unit used by fixed function with an incompatible target"
|
||||
//
|
||||
//info:
|
||||
//http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml
|
||||
//This function mimics the validation operation that OpenGL implementations must perform when rendering commands are issued while programmable shaders are part of current state.
|
||||
//glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state
|
||||
//This function is typically useful only during application development.
|
||||
//
|
||||
//So, this is no big deal. we shouldnt be calling validate right now anyway.
|
||||
//conclusion: glValidate is very complicated and is of virtually no use unless your draw calls are returning errors and you want to know why
|
||||
//GL.ValidateProgram(pid);
|
||||
//errcode = GL.GetError();
|
||||
//resultLog = GL.GetProgramInfoLog(pid);
|
||||
//if (errcode != ErrorCode.NoError)
|
||||
// throw new InvalidOperationException("Error creating pipeline (error returned from glValidateProgram): " + errcode + "\r\n\r\n" + resultLog);
|
||||
//int validateStatus;
|
||||
//GL.GetProgram(pid, GetProgramParameterName.ValidateStatus, out validateStatus);
|
||||
//if (validateStatus == 0)
|
||||
// throw new InvalidOperationException("Error creating pipeline (validateStatus status false returned from glValidateProgram): " + "\r\n\r\n" + resultLog);
|
||||
|
||||
//set the program to active, in case we need to set sampler uniforms on it
|
||||
GL.UseProgram(pid);
|
||||
|
||||
//get all the attributes (not needed)
|
||||
List<AttributeInfo> attributes = new List<AttributeInfo>();
|
||||
int nAttributes;
|
||||
GL.GetProgram(pid, GetProgramParameterName.ActiveAttributes, out nAttributes);
|
||||
for (int i = 0; i < nAttributes; i++)
|
||||
{
|
||||
int size, length;
|
||||
string name = new System.Text.StringBuilder(1024).ToString();
|
||||
ActiveAttribType type;
|
||||
GL.GetActiveAttrib(pid, i, 1024, out length, out size, out type, out name);
|
||||
attributes.Add(new AttributeInfo() { Handle = new IntPtr(i), Name = name });
|
||||
}
|
||||
|
||||
//get all the uniforms
|
||||
List<UniformInfo> uniforms = new List<UniformInfo>();
|
||||
int nUniforms;
|
||||
GL.GetProgram(pid,GetProgramParameterName.ActiveUniforms,out nUniforms);
|
||||
List<int> samplers = new List<int>();
|
||||
|
||||
for (int i = 0; i < nUniforms; i++)
|
||||
{
|
||||
int size, length;
|
||||
ActiveUniformType type;
|
||||
string name = new System.Text.StringBuilder(1024).ToString().ToString();
|
||||
GL.GetActiveUniform(pid, i, 1024, out length, out size, out type, out name);
|
||||
errcode = GL.GetError();
|
||||
int loc = GL.GetUniformLocation(pid, name);
|
||||
|
||||
//translate name if appropriate
|
||||
//not sure how effective this approach will be, due to confusion of vertex and fragment uniforms
|
||||
if (mapVariables)
|
||||
{
|
||||
if (vsw.MapCodeToNative.ContainsKey(name)) name = vsw.MapCodeToNative[name];
|
||||
if (fsw.MapCodeToNative.ContainsKey(name)) name = fsw.MapCodeToNative[name];
|
||||
}
|
||||
|
||||
var ui = new UniformInfo();
|
||||
ui.Name = name;
|
||||
ui.Opaque = loc;
|
||||
|
||||
if (type == ActiveUniformType.Sampler2D)
|
||||
{
|
||||
ui.IsSampler = true;
|
||||
ui.SamplerIndex = samplers.Count;
|
||||
ui.Opaque = loc | (samplers.Count << 24);
|
||||
samplers.Add(loc);
|
||||
}
|
||||
|
||||
uniforms.Add(ui);
|
||||
}
|
||||
|
||||
//deactivate the program, so we dont accidentally use it
|
||||
GL.UseProgram(0);
|
||||
|
||||
if (!vertexShader.Available) success = false;
|
||||
if (!fragmentShader.Available) success = false;
|
||||
|
||||
var pw = new PipelineWrapper() { pid = pid, VertexShader = vertexShader, FragmentShader = fragmentShader, SamplerLocs = samplers };
|
||||
|
||||
return new Pipeline(this, pw, success, vertexLayout, uniforms, memo);
|
||||
}
|
||||
|
||||
public void FreePipeline(Pipeline pipeline)
|
||||
{
|
||||
var pw = pipeline.Opaque as PipelineWrapper;
|
||||
|
||||
//unavailable pipelines will have no opaque
|
||||
if (pw == null)
|
||||
return;
|
||||
|
||||
GL.DeleteProgram(pw.pid);
|
||||
|
||||
pw.FragmentShader.Release();
|
||||
pw.VertexShader.Release();
|
||||
}
|
||||
|
||||
public void Internal_FreeShader(Shader shader)
|
||||
{
|
||||
var sw = shader.Opaque as ShaderWrapper;
|
||||
GL.DeleteShader(sw.sid);
|
||||
}
|
||||
|
||||
public void BindPipeline(Pipeline pipeline)
|
||||
{
|
||||
_CurrPipeline = pipeline;
|
||||
|
||||
if (pipeline == null)
|
||||
{
|
||||
sStatePendingVertexLayout = null;
|
||||
GL.UseProgram(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pipeline.Available) throw new InvalidOperationException("Attempt to bind unavailable pipeline");
|
||||
sStatePendingVertexLayout = pipeline.VertexLayout;
|
||||
|
||||
var pw = pipeline.Opaque as PipelineWrapper;
|
||||
GL.UseProgram(pw.pid);
|
||||
|
||||
//this is dumb and confusing, but we have to bind physical sampler numbers to sampler variables.
|
||||
for (int i = 0; i < pw.SamplerLocs.Count; i++)
|
||||
{
|
||||
GL.Uniform1(pw.SamplerLocs[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public VertexLayout CreateVertexLayout() { return new VertexLayout(this, null); }
|
||||
|
||||
private void BindTexture2d(Texture2d tex)
|
||||
{
|
||||
GL.BindTexture(TextureTarget.Texture2D, (int)tex.Opaque);
|
||||
}
|
||||
|
||||
public void SetTextureWrapMode(Texture2d tex, bool clamp)
|
||||
{
|
||||
BindTexture2d(tex);
|
||||
int mode;
|
||||
if (clamp)
|
||||
{
|
||||
mode = (int)global::OpenTK.Graphics.OpenGL.TextureWrapMode.ClampToEdge;
|
||||
}
|
||||
else
|
||||
mode = (int)global::OpenTK.Graphics.OpenGL.TextureWrapMode.Repeat;
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, mode);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, mode);
|
||||
}
|
||||
|
||||
public unsafe void BindArrayData(void* pData)
|
||||
{
|
||||
MyBindArrayData(sStatePendingVertexLayout, pData);
|
||||
}
|
||||
|
||||
public void DrawArrays(PrimitiveType mode, int first, int count)
|
||||
{
|
||||
GL.DrawArrays((global::OpenTK.Graphics.OpenGL.PrimitiveType)mode, first, count);
|
||||
}
|
||||
|
||||
public void SetPipelineUniform(PipelineUniform uniform, bool value)
|
||||
{
|
||||
GL.Uniform1((int)uniform.Sole.Opaque, value ? 1 : 0);
|
||||
}
|
||||
|
||||
public unsafe void SetPipelineUniformMatrix(PipelineUniform uniform, Matrix4 mat, bool transpose)
|
||||
{
|
||||
//GL.UniformMatrix4((int)uniform.Opaque, 1, transpose, (float*)&mat);
|
||||
GL.Uniform4((int)uniform.Sole.Opaque + 0, 1, (float*)&mat.Row0);
|
||||
GL.Uniform4((int)uniform.Sole.Opaque + 1, 1, (float*)&mat.Row1);
|
||||
GL.Uniform4((int)uniform.Sole.Opaque + 2, 1, (float*)&mat.Row2);
|
||||
GL.Uniform4((int)uniform.Sole.Opaque + 3, 1, (float*)&mat.Row3);
|
||||
}
|
||||
|
||||
public unsafe void SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix4 mat, bool transpose)
|
||||
{
|
||||
fixed(Matrix4* pMat = &mat)
|
||||
GL.UniformMatrix4((int)uniform.Sole.Opaque, 1, transpose, (float*)pMat);
|
||||
}
|
||||
|
||||
public void SetPipelineUniform(PipelineUniform uniform, Vector4 value)
|
||||
{
|
||||
GL.Uniform4((int)uniform.Sole.Opaque, value.X, value.Y, value.Z, value.W);
|
||||
}
|
||||
|
||||
public void SetPipelineUniform(PipelineUniform uniform, Vector2 value)
|
||||
{
|
||||
GL.Uniform2((int)uniform.Sole.Opaque, value.X, value.Y);
|
||||
}
|
||||
|
||||
public void SetPipelineUniform(PipelineUniform uniform, float value)
|
||||
{
|
||||
if (uniform.Owner == null) return; //uniform was optimized out
|
||||
GL.Uniform1((int)uniform.Sole.Opaque, value);
|
||||
}
|
||||
|
||||
public unsafe void SetPipelineUniform(PipelineUniform uniform, Vector4[] values)
|
||||
{
|
||||
fixed (Vector4* pValues = &values[0])
|
||||
GL.Uniform4((int)uniform.Sole.Opaque, values.Length, (float*)pValues);
|
||||
}
|
||||
|
||||
public void SetPipelineUniformSampler(PipelineUniform uniform, Texture2d tex)
|
||||
{
|
||||
int n = ((int)uniform.Sole.Opaque)>>24;
|
||||
|
||||
//set the sampler index into the uniform first
|
||||
if (sActiveTexture != n)
|
||||
{
|
||||
sActiveTexture = n;
|
||||
var selectedUnit = (TextureUnit)((int)TextureUnit.Texture0 + n);
|
||||
GL.ActiveTexture(selectedUnit);
|
||||
}
|
||||
|
||||
//now bind the texture
|
||||
GL.BindTexture(TextureTarget.Texture2D, (int)tex.Opaque);
|
||||
}
|
||||
|
||||
public void TexParameter2d(Texture2d tex, TextureParameterName pname, int param)
|
||||
{
|
||||
BindTexture2d(tex);
|
||||
GL.TexParameter(TextureTarget.Texture2D, (global::OpenTK.Graphics.OpenGL.TextureParameterName)pname, param);
|
||||
}
|
||||
|
||||
public Texture2d LoadTexture(sd.Bitmap bitmap)
|
||||
{
|
||||
using (var bmp = new BitmapBuffer(bitmap, new BitmapLoadOptions()))
|
||||
return (this as IGL).LoadTexture(bmp);
|
||||
}
|
||||
|
||||
public Texture2d LoadTexture(Stream stream)
|
||||
{
|
||||
using(var bmp = new BitmapBuffer(stream,new BitmapLoadOptions()))
|
||||
return (this as IGL).LoadTexture(bmp);
|
||||
}
|
||||
|
||||
public Texture2d CreateTexture(int width, int height)
|
||||
{
|
||||
int id = GenTexture();
|
||||
return new Texture2d(this, id, width, height);
|
||||
}
|
||||
|
||||
public Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height)
|
||||
{
|
||||
return new Texture2d(this as IGL, glTexId.ToInt32(), width, height);
|
||||
}
|
||||
|
||||
public void LoadTextureData(Texture2d tex, BitmapBuffer bmp)
|
||||
{
|
||||
sdi.BitmapData bmp_data = bmp.LockBits();
|
||||
try
|
||||
{
|
||||
GL.BindTexture(TextureTarget.Texture2D, (int)tex.Opaque);
|
||||
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bmp.Width, bmp.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
bmp.UnlockBits(bmp_data);
|
||||
}
|
||||
}
|
||||
|
||||
public void FreeRenderTarget(RenderTarget rt)
|
||||
{
|
||||
rt.Texture2d.Dispose();
|
||||
GL.Ext.DeleteFramebuffer((int)rt.Opaque);
|
||||
}
|
||||
|
||||
public unsafe RenderTarget CreateRenderTarget(int w, int h)
|
||||
{
|
||||
//create a texture for it
|
||||
int texid = GenTexture();
|
||||
Texture2d tex = new Texture2d(this, texid, w, h);
|
||||
GL.BindTexture(TextureTarget.Texture2D,texid);
|
||||
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, w, h, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
||||
tex.SetMagFilter(TextureMagFilter.Nearest);
|
||||
tex.SetMinFilter(TextureMinFilter.Nearest);
|
||||
|
||||
//create the FBO
|
||||
int fbid = GL.Ext.GenFramebuffer();
|
||||
GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, fbid);
|
||||
|
||||
//bind the tex to the FBO
|
||||
GL.Ext.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, texid, 0);
|
||||
|
||||
//do something, I guess say which colorbuffers are used by the framebuffer
|
||||
DrawBuffersEnum* buffers = stackalloc DrawBuffersEnum[1];
|
||||
buffers[0] = DrawBuffersEnum.ColorAttachment0;
|
||||
GL.DrawBuffers(1, buffers);
|
||||
|
||||
if (GL.Ext.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete)
|
||||
throw new InvalidOperationException("Error creating framebuffer (at CheckFramebufferStatus)");
|
||||
|
||||
//since we're done configuring unbind this framebuffer, to return to the default
|
||||
GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
|
||||
|
||||
return new RenderTarget(this, fbid, tex);
|
||||
}
|
||||
|
||||
public void BindRenderTarget(RenderTarget rt)
|
||||
{
|
||||
_CurrRenderTarget = rt;
|
||||
if(rt == null)
|
||||
GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
|
||||
else
|
||||
GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, (int)rt.Opaque);
|
||||
}
|
||||
|
||||
public Texture2d LoadTexture(BitmapBuffer bmp)
|
||||
{
|
||||
Texture2d ret = null;
|
||||
int id = GenTexture();
|
||||
try
|
||||
{
|
||||
ret = new Texture2d(this, id, bmp.Width, bmp.Height);
|
||||
GL.BindTexture(TextureTarget.Texture2D, id);
|
||||
//picking a color order that matches doesnt seem to help, any. maybe my driver is accelerating it, or maybe it isnt a big deal. but its something to study on another day
|
||||
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp.Width, bmp.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
||||
(this as IGL).LoadTextureData(ret, bmp);
|
||||
}
|
||||
catch
|
||||
{
|
||||
GL.DeleteTexture(id);
|
||||
throw;
|
||||
}
|
||||
|
||||
//set default filtering.. its safest to do this always
|
||||
ret.SetFilterNearest();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public unsafe BitmapBuffer ResolveTexture2d(Texture2d tex)
|
||||
{
|
||||
//note - this is dangerous since it changes the bound texture. could we save it?
|
||||
BindTexture2d(tex);
|
||||
var bb = new BitmapBuffer(tex.IntWidth, tex.IntHeight);
|
||||
var bmpdata = bb.LockBits();
|
||||
GL.GetTexImage(TextureTarget.Texture2D, 0, PixelFormat.Bgra, PixelType.UnsignedByte, bmpdata.Scan0);
|
||||
var err = GL.GetError();
|
||||
bb.UnlockBits(bmpdata);
|
||||
return bb;
|
||||
}
|
||||
|
||||
public Texture2d LoadTexture(string path)
|
||||
{
|
||||
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
return (this as IGL).LoadTexture(fs);
|
||||
}
|
||||
|
||||
public Matrix4 CreateGuiProjectionMatrix(int w, int h)
|
||||
{
|
||||
return CreateGuiProjectionMatrix(new sd.Size(w, h));
|
||||
}
|
||||
|
||||
public Matrix4 CreateGuiViewMatrix(int w, int h, bool autoflip)
|
||||
{
|
||||
return CreateGuiViewMatrix(new sd.Size(w, h), autoflip);
|
||||
}
|
||||
|
||||
public Matrix4 CreateGuiProjectionMatrix(sd.Size dims)
|
||||
{
|
||||
Matrix4 ret = Matrix4.Identity;
|
||||
ret.M11 = 2.0f / (float)dims.Width;
|
||||
ret.M22 = 2.0f / (float)dims.Height;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Matrix4 CreateGuiViewMatrix(sd.Size dims, bool autoflip)
|
||||
{
|
||||
Matrix4 ret = Matrix4.Identity;
|
||||
ret.M22 = -1.0f;
|
||||
ret.M41 = -(float)dims.Width * 0.5f;
|
||||
ret.M42 = (float)dims.Height * 0.5f;
|
||||
if (autoflip)
|
||||
{
|
||||
if (_CurrRenderTarget == null) { }
|
||||
else
|
||||
{
|
||||
//flip as long as we're not a final render target
|
||||
ret.M22 = 1.0f;
|
||||
ret.M42 *= -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void SetViewport(int x, int y, int width, int height)
|
||||
{
|
||||
GL.Viewport(x, y, width, height);
|
||||
GL.Scissor(x, y, width, height); //hack for mupen[rice]+intel: at least the rice plugin leaves the scissor rectangle scrambled, and we're trying to run it in the main graphics context for intel
|
||||
//BUT ALSO: new specifications.. viewport+scissor make sense together
|
||||
}
|
||||
|
||||
public void SetViewport(int width, int height)
|
||||
{
|
||||
SetViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
public void SetViewport(sd.Size size)
|
||||
{
|
||||
SetViewport(size.Width, size.Height);
|
||||
}
|
||||
|
||||
public void SetViewport(swf.Control control)
|
||||
{
|
||||
var r = control.ClientRectangle;
|
||||
SetViewport(r.Left, r.Top, r.Width, r.Height);
|
||||
}
|
||||
|
||||
//------------------
|
||||
|
||||
INativeWindow OffscreenNativeWindow;
|
||||
IGraphicsContext GraphicsContext;
|
||||
|
||||
//---------------
|
||||
//my utility methods
|
||||
|
||||
GLControl CastControl(swf.Control swfControl)
|
||||
{
|
||||
GLControl glc = swfControl as GLControl;
|
||||
if (glc == null)
|
||||
throw new ArgumentException("Argument isn't a control created by the IGL interface", "glControl");
|
||||
return glc;
|
||||
}
|
||||
|
||||
Shader CreateShader(bool cg, ShaderType type, string source, string entry, bool required)
|
||||
{
|
||||
var sw = new ShaderWrapper();
|
||||
if (cg)
|
||||
{
|
||||
var cgc = new CGC();
|
||||
var results = cgc.Run(source, entry, type == ShaderType.FragmentShader ? "glslf" : "glslv", false);
|
||||
|
||||
if (!results.Succeeded)
|
||||
{
|
||||
Console.WriteLine("CGC failed");
|
||||
Console.WriteLine(results.Errors);
|
||||
return new Shader(this, null, false);
|
||||
}
|
||||
|
||||
source = results.Code;
|
||||
sw.MapCodeToNative = results.MapCodeToNative;
|
||||
sw.MapNativeToCode = results.MapNativeToCode;
|
||||
}
|
||||
|
||||
int sid = GL.CreateShader(type);
|
||||
bool ok = CompileShaderSimple(sid, source, required);
|
||||
if(!ok)
|
||||
{
|
||||
GL.DeleteShader(sid);
|
||||
sid = 0;
|
||||
}
|
||||
|
||||
sw.sid = sid;
|
||||
|
||||
return new Shader(this, sw, ok);
|
||||
}
|
||||
|
||||
bool CompileShaderSimple(int sid, string source, bool required)
|
||||
{
|
||||
bool success = true;
|
||||
ErrorCode errcode;
|
||||
|
||||
errcode = GL.GetError();
|
||||
if (errcode != ErrorCode.NoError)
|
||||
if (required)
|
||||
throw new InvalidOperationException("Error compiling shader (from previous operation) " + errcode);
|
||||
else success = false;
|
||||
|
||||
GL.ShaderSource(sid, source);
|
||||
|
||||
errcode = GL.GetError();
|
||||
if (errcode != ErrorCode.NoError)
|
||||
if (required)
|
||||
throw new InvalidOperationException("Error compiling shader (ShaderSource) " + errcode);
|
||||
else success = false;
|
||||
|
||||
GL.CompileShader(sid);
|
||||
errcode = GL.GetError();
|
||||
|
||||
string resultLog = GL.GetShaderInfoLog(sid);
|
||||
|
||||
if (errcode != ErrorCode.NoError)
|
||||
{
|
||||
string message = "Error compiling shader (CompileShader) " + errcode + "\r\n\r\n" + resultLog;
|
||||
if (required)
|
||||
throw new InvalidOperationException(message);
|
||||
else
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
int n;
|
||||
GL.GetShader(sid, ShaderParameter.CompileStatus, out n);
|
||||
|
||||
if (n == 0)
|
||||
if (required)
|
||||
throw new InvalidOperationException("Error compiling shader (CompileShader )" + "\r\n\r\n" + resultLog);
|
||||
else success = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void UnbindVertexAttributes()
|
||||
{
|
||||
//HAMNUTS:
|
||||
//its not clear how many bindings we'll have to disable before we can enable the ones we need..
|
||||
//so lets just disable the ones we remember we have bound
|
||||
var currBindings = sVertexAttribEnables;
|
||||
foreach (var index in currBindings)
|
||||
GL.DisableVertexAttribArray(index);
|
||||
currBindings.Clear();
|
||||
}
|
||||
|
||||
unsafe void MyBindArrayData(VertexLayout layout, void* pData)
|
||||
{
|
||||
UnbindVertexAttributes();
|
||||
|
||||
//HAMNUTS (continued)
|
||||
var currBindings = sVertexAttribEnables;
|
||||
sStateCurrentVertexLayout = sStatePendingVertexLayout;
|
||||
|
||||
if (layout == null) return;
|
||||
|
||||
//disable all the client states.. a lot of overhead right now, to be sure
|
||||
GL.DisableClientState(ArrayCap.VertexArray);
|
||||
GL.DisableClientState(ArrayCap.ColorArray);
|
||||
for(int i=0;i<8;i++)
|
||||
GL.DisableVertexAttribArray(i);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
GL.ClientActiveTexture(TextureUnit.Texture0 + i);
|
||||
GL.DisableClientState(ArrayCap.TextureCoordArray);
|
||||
}
|
||||
GL.ClientActiveTexture(TextureUnit.Texture0);
|
||||
|
||||
foreach (var kvp in layout.Items)
|
||||
{
|
||||
if(_CurrPipeline.Memo == "gui")
|
||||
{
|
||||
GL.VertexAttribPointer(kvp.Key, kvp.Value.Components, (VertexAttribPointerType)kvp.Value.AttribType, kvp.Value.Normalized, kvp.Value.Stride, new IntPtr(pData) + kvp.Value.Offset);
|
||||
GL.EnableVertexAttribArray(kvp.Key);
|
||||
currBindings.Add(kvp.Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var pw = _CurrPipeline.Opaque as PipelineWrapper;
|
||||
|
||||
//comment SNACKPANTS
|
||||
switch (kvp.Value.Usage)
|
||||
{
|
||||
case AttributeUsage.Position:
|
||||
GL.EnableClientState(ArrayCap.VertexArray);
|
||||
GL.VertexPointer(kvp.Value.Components,VertexPointerType.Float,kvp.Value.Stride,new IntPtr(pData) + kvp.Value.Offset);
|
||||
break;
|
||||
case AttributeUsage.Texcoord0:
|
||||
GL.ClientActiveTexture(TextureUnit.Texture0);
|
||||
GL.EnableClientState(ArrayCap.TextureCoordArray);
|
||||
GL.TexCoordPointer(kvp.Value.Components, TexCoordPointerType.Float, kvp.Value.Stride, new IntPtr(pData) + kvp.Value.Offset);
|
||||
break;
|
||||
case AttributeUsage.Texcoord1:
|
||||
GL.ClientActiveTexture(TextureUnit.Texture1);
|
||||
GL.EnableClientState(ArrayCap.TextureCoordArray);
|
||||
GL.TexCoordPointer(kvp.Value.Components, TexCoordPointerType.Float, kvp.Value.Stride, new IntPtr(pData) + kvp.Value.Offset);
|
||||
GL.ClientActiveTexture(TextureUnit.Texture0);
|
||||
break;
|
||||
case AttributeUsage.Color0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void MakeDefaultCurrent()
|
||||
{
|
||||
MakeContextCurrent(this.GraphicsContext,OffscreenNativeWindow.WindowInfo);
|
||||
}
|
||||
|
||||
internal void MakeContextCurrent(IGraphicsContext context, global::OpenTK.Platform.IWindowInfo windowInfo)
|
||||
{
|
||||
context.MakeCurrent(windowInfo);
|
||||
PurgeStateCache();
|
||||
}
|
||||
|
||||
void CreateRenderStates()
|
||||
{
|
||||
_rsBlendNoneVerbatim = new CacheBlendState(
|
||||
false,
|
||||
BlendingFactorSrc.One, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero,
|
||||
BlendingFactorSrc.One, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero);
|
||||
|
||||
_rsBlendNoneOpaque = new CacheBlendState(
|
||||
false,
|
||||
BlendingFactorSrc.One, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero,
|
||||
BlendingFactorSrc.ConstantAlpha, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero);
|
||||
|
||||
_rsBlendNormal = new CacheBlendState(
|
||||
true,
|
||||
BlendingFactorSrc.SrcAlpha, BlendEquationMode.FuncAdd, BlendingFactorDest.OneMinusSrcAlpha,
|
||||
BlendingFactorSrc.One, BlendEquationMode.FuncAdd, BlendingFactorDest.Zero);
|
||||
}
|
||||
|
||||
CacheBlendState _rsBlendNoneVerbatim, _rsBlendNoneOpaque, _rsBlendNormal;
|
||||
|
||||
//state caches
|
||||
int sActiveTexture;
|
||||
VertexLayout sStateCurrentVertexLayout;
|
||||
VertexLayout sStatePendingVertexLayout;
|
||||
HashSet<int> sVertexAttribEnables = new HashSet<int>();
|
||||
void PurgeStateCache()
|
||||
{
|
||||
sStateCurrentVertexLayout = null;
|
||||
sStatePendingVertexLayout = null;
|
||||
sVertexAttribEnables.Clear();
|
||||
sActiveTexture = -1;
|
||||
}
|
||||
|
||||
} //class IGL_Vulkan
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
|
||||
namespace BizHawk.Bizware.BizwareGL.Drivers.Vulkan
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles RetroArch's GLSL shader pass format
|
||||
/// This isnt implemented in BizwareGL abstract layer because it relies too much on GLSL peculiarities
|
||||
/// </summary>
|
||||
public class RetroShader : IDisposable
|
||||
{
|
||||
public RetroShader(IGL owner, string source, bool debug = false)
|
||||
{
|
||||
Owner = owner as IGL_TK;
|
||||
|
||||
VertexLayout = owner.CreateVertexLayout();
|
||||
VertexLayout.DefineVertexAttribute("VertexCoord", 0, 4, VertexAttribPointerType.Float, AttributeUsage.Unspecified, false, 40, 0); //VertexCoord
|
||||
VertexLayout.DefineVertexAttribute("ColorShit", 1, 4, VertexAttribPointerType.Float, AttributeUsage.Unspecified, false, 40, 16); //COLOR
|
||||
VertexLayout.DefineVertexAttribute("TexCoord", 2, 2, VertexAttribPointerType.Float, AttributeUsage.Unspecified, false, 40, 32); //TexCoord (is this vec2 or vec4? the glsl converted from cg had vec4 but the cg had vec2...)
|
||||
VertexLayout.Close();
|
||||
|
||||
string vsSource = "#define VERTEX\r\n" + source;
|
||||
string psSource = "#define FRAGMENT\r\n" + source;
|
||||
var vs = Owner.CreateVertexShader(vsSource, debug);
|
||||
var ps = Owner.CreateFragmentShader(psSource, debug);
|
||||
Pipeline = Owner.CreatePipeline(VertexLayout, vs, ps, debug);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Pipeline.Dispose();
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
//lame...
|
||||
Owner.BindPipeline(Pipeline);
|
||||
}
|
||||
|
||||
public unsafe void Run(Texture2d tex, Size InputSize, Size OutputSize, bool flip)
|
||||
{
|
||||
//ack! make sure to set the pipeline before setting
|
||||
Bind();
|
||||
|
||||
Pipeline["InputSize"].Set(new Vector2(InputSize.Width,InputSize.Height));
|
||||
Pipeline["TextureSize"].Set(new Vector2(InputSize.Width, InputSize.Height));
|
||||
Pipeline["OutputSize"].Set(new Vector2(OutputSize.Width, OutputSize.Height));
|
||||
Pipeline["FrameCount"].Set(0); //todo
|
||||
Pipeline["FrameDirection"].Set(1); //todo
|
||||
|
||||
var Projection = Owner.CreateGuiProjectionMatrix(OutputSize);
|
||||
var Modelview = Owner.CreateGuiViewMatrix(OutputSize);
|
||||
Pipeline["MVPMatrix"].Set(Modelview * Projection, false);
|
||||
|
||||
Owner.SetTextureWrapMode(tex, true);
|
||||
|
||||
Pipeline["Texture"].Set(tex);
|
||||
Owner.SetViewport(OutputSize);
|
||||
|
||||
int w = OutputSize.Width;
|
||||
int h = OutputSize.Height;
|
||||
float v0,v1;
|
||||
if (flip) { v0 = 1; v1 = 0; }
|
||||
else { v0 = 0; v1 = 1; }
|
||||
float* pData = stackalloc float[10*4];
|
||||
int i=0;
|
||||
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 1; //topleft vert
|
||||
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //junk
|
||||
pData[i++] = 0; pData[i++] = v0; //texcoord
|
||||
pData[i++] = w; pData[i++] = 0; pData[i++] = 0; pData[i++] = 1; //topright vert
|
||||
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //junk
|
||||
pData[i++] = 1; pData[i++] = v0; //texcoord
|
||||
pData[i++] = 0; pData[i++] = h; pData[i++] = 0; pData[i++] = 1; //bottomleft vert
|
||||
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //junk
|
||||
pData[i++] = 0; pData[i++] = v1; //texcoord
|
||||
pData[i++] = w; pData[i++] = h; pData[i++] = 0; pData[i++] = 1; //bottomright vert
|
||||
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //junk
|
||||
pData[i++] = 1; pData[i++] = v1; //texcoord
|
||||
|
||||
Owner.SetBlendState(Owner.BlendNoneCopy);
|
||||
Owner.BindArrayData(pData);
|
||||
Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
|
||||
}
|
||||
|
||||
|
||||
public IGL_TK Owner { get; private set; }
|
||||
|
||||
VertexLayout VertexLayout;
|
||||
public Pipeline Pipeline;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue