Merge branch 'GLSL-master'
Merge an endless story. The branch name is a lie, it was started as glsl, but now it is a complete reworked opengl3 backend. It just began with simple changes which aren't supported on osx. They either support ogl2 OR ogl3 core, but mixing isn't allowed. As the branch name says, the vicious circle starts with GLSL, but just implementing one wasn't possible either: - OSX supports only GLSL100 which doesn't support our shaders. - Vertex Array Objects are needed for ogl3, but not supported on ogl2 - immediate mode isn't supported any more, so we must implement vertex buffers - uniform buffers are recommended as else we would need tons glUniform - postprocessing shaders have to be converted to glsl - lots of smaller outdated issues and bug fixes :-) Thanks at all for testing and at Sonic for converting all of our shaders to glsl130 And sorry for all upcoming bugs...
This commit is contained in:
@@ -21,11 +21,8 @@
|
||||
#include "Common.h"
|
||||
#include <fstream>
|
||||
|
||||
// Increment this every time you change shader generation code.
|
||||
enum
|
||||
{
|
||||
LINEAR_DISKCACHE_VER = 6979
|
||||
};
|
||||
// defined in Version.cpp
|
||||
extern const char *scm_rev_git_str;
|
||||
|
||||
// On disk format:
|
||||
//header{
|
||||
@@ -187,13 +184,15 @@ private:
|
||||
{
|
||||
Header()
|
||||
: id(*(u32*)"DCAC")
|
||||
, ver(LINEAR_DISKCACHE_VER)
|
||||
, key_t_size(sizeof(K))
|
||||
, value_t_size(sizeof(V))
|
||||
{}
|
||||
{
|
||||
memcpy(ver, scm_rev_git_str, 40);
|
||||
}
|
||||
|
||||
const u32 id, ver;
|
||||
const u32 id;
|
||||
const u16 key_t_size, value_t_size;
|
||||
char ver[40];
|
||||
|
||||
} m_header;
|
||||
|
||||
|
||||
@@ -117,6 +117,8 @@ struct Rectangle
|
||||
Rectangle(T theLeft, T theTop, T theRight, T theBottom)
|
||||
: left(theLeft), top(theTop), right(theRight), bottom(theBottom)
|
||||
{ }
|
||||
|
||||
bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; }
|
||||
|
||||
T GetWidth() const { return abs(right - left); }
|
||||
T GetHeight() const { return abs(bottom - top); }
|
||||
|
||||
@@ -50,3 +50,5 @@ const char *netplay_dolphin_ver = SCM_DESC_STR " M" NP_ARCH;
|
||||
#else
|
||||
const char *netplay_dolphin_ver = SCM_DESC_STR " L" NP_ARCH;
|
||||
#endif
|
||||
|
||||
const char *scm_rev_git_str = SCM_REV_STR;
|
||||
|
||||
@@ -103,6 +103,7 @@ public:
|
||||
virtual void Video_Prepare() = 0;
|
||||
virtual void Video_EnterLoop() = 0;
|
||||
virtual void Video_ExitLoop() = 0;
|
||||
virtual void Video_Cleanup() = 0; // called from gl/d3d thread
|
||||
|
||||
virtual void Video_BeginField(u32, FieldType, u32, u32) = 0;
|
||||
virtual void Video_EndField() = 0;
|
||||
|
||||
@@ -322,6 +322,9 @@ void CpuThread()
|
||||
CCPU::Run();
|
||||
|
||||
g_bStarted = false;
|
||||
|
||||
if (!_CoreParameter.bCPUThread)
|
||||
g_video_backend->Video_Cleanup();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -350,6 +353,9 @@ void FifoPlayerThread()
|
||||
}
|
||||
|
||||
g_bStarted = false;
|
||||
|
||||
if(!_CoreParameter.bCPUThread)
|
||||
g_video_backend->Video_Cleanup();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -476,6 +482,9 @@ void EmuThread()
|
||||
g_cpu_thread.join();
|
||||
|
||||
INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str());
|
||||
|
||||
if(_CoreParameter.bCPUThread)
|
||||
g_video_backend->Video_Cleanup();
|
||||
|
||||
VolumeHandler::EjectVolume();
|
||||
FileMon::Close();
|
||||
|
||||
@@ -95,11 +95,7 @@ else()
|
||||
if(WIN32)
|
||||
set(SRCS ${SRCS} Src/GLInterface/GLW.cpp)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
if(USE_WX)
|
||||
set(SRCS ${SRCS} Src/GLInterface/WX.cpp)
|
||||
else()
|
||||
set(SRCS ${SRCS} Src/GLInterface/AGL.cpp)
|
||||
endif()
|
||||
set(SRCS ${SRCS} Src/GLInterface/AGL.cpp)
|
||||
else()
|
||||
set(SRCS ${SRCS} Src/GLInterface/GLX.cpp
|
||||
Src/GLInterface/X11_Util.cpp)
|
||||
|
||||
@@ -136,7 +136,6 @@
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win32\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
@@ -151,7 +150,6 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
@@ -168,7 +166,6 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win32\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
@@ -183,7 +180,6 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win32\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
@@ -200,7 +196,6 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
@@ -217,7 +212,6 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||
echo Copying External .dlls
|
||||
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\OpenAL\Win64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||
</Command>
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
#include <GLInterface/InterfaceBase.h>
|
||||
#elif defined(USE_EGL) && USE_EGL
|
||||
#include "GLInterface/EGL_X11.h"
|
||||
#elif defined(USE_WX) && USE_WX
|
||||
#include "GLInterface/WX.h"
|
||||
#elif defined(__APPLE__)
|
||||
#include "GLInterface/AGL.h"
|
||||
#elif defined(_WIN32)
|
||||
@@ -51,12 +49,8 @@ typedef struct {
|
||||
std::thread xEventThread;
|
||||
int x, y;
|
||||
unsigned int width, height;
|
||||
#elif defined(USE_WX) && USE_WX
|
||||
wxGLCanvas *glCanvas;
|
||||
wxGLContext *glCtxt;
|
||||
wxPanel *panel;
|
||||
#elif defined(__APPLE__)
|
||||
NSWindow *cocoaWin;
|
||||
NSView *cocoaWin;
|
||||
NSOpenGLContext *cocoaCtx;
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
int screen;
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "RenderBase.h"
|
||||
#include "ConfigManager.h"
|
||||
|
||||
#include <wx/panel.h>
|
||||
|
||||
#include "VertexShaderManager.h"
|
||||
#include "../GLInterface.h"
|
||||
#include "AGL.h"
|
||||
@@ -32,7 +34,7 @@ void cInterfaceAGL::Swap()
|
||||
// Show the current FPS
|
||||
void cInterfaceAGL::UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
[GLWin.cocoaWin setTitle: [NSString stringWithUTF8String: text]];
|
||||
[[GLWin.cocoaWin window] setTitle: [NSString stringWithUTF8String: text]];
|
||||
}
|
||||
|
||||
// Create rendering window.
|
||||
@@ -48,7 +50,7 @@ bool cInterfaceAGL::Create(void *&window_handle)
|
||||
|
||||
NSRect size;
|
||||
NSUInteger style = NSMiniaturizableWindowMask;
|
||||
NSOpenGLPixelFormatAttribute attr[2] = { NSOpenGLPFADoubleBuffer, 0 };
|
||||
NSOpenGLPixelFormatAttribute attr[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, NSOpenGLPFAAccelerated, 0 };
|
||||
NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc]
|
||||
initWithAttributes: attr];
|
||||
if (fmt == nil) {
|
||||
@@ -72,8 +74,7 @@ bool cInterfaceAGL::Create(void *&window_handle)
|
||||
style |= NSResizableWindowMask | NSTitledWindowMask;
|
||||
}
|
||||
|
||||
GLWin.cocoaWin = [[NSWindow alloc] initWithContentRect: size
|
||||
styleMask: style backing: NSBackingStoreBuffered defer: NO];
|
||||
GLWin.cocoaWin = (NSView*)(((wxPanel*)window_handle)->GetHandle());;
|
||||
if (GLWin.cocoaWin == nil) {
|
||||
ERROR_LOG(VIDEO, "failed to create window");
|
||||
return NULL;
|
||||
@@ -84,8 +85,8 @@ bool cInterfaceAGL::Create(void *&window_handle)
|
||||
[GLWin.cocoaWin setLevel: CGShieldingWindowLevel()];
|
||||
}
|
||||
|
||||
[GLWin.cocoaCtx setView: [GLWin.cocoaWin contentView]];
|
||||
[GLWin.cocoaWin makeKeyAndOrderFront: nil];
|
||||
[GLWin.cocoaCtx setView: GLWin.cocoaWin];
|
||||
[[GLWin.cocoaWin window] makeKeyAndOrderFront: nil];
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -94,12 +95,12 @@ bool cInterfaceAGL::MakeCurrent()
|
||||
{
|
||||
int width, height;
|
||||
|
||||
width = [[GLWin.cocoaWin contentView] frame].size.width;
|
||||
height = [[GLWin.cocoaWin contentView] frame].size.height;
|
||||
if (width == s_backbuffer_width && height == s_backbuffer_height)
|
||||
return;
|
||||
width = [GLWin.cocoaWin frame].size.width;
|
||||
height = [GLWin.cocoaWin frame].size.height;
|
||||
//if (width == s_backbuffer_width && height == s_backbuffer_height)
|
||||
// return true;
|
||||
|
||||
[GLWin.cocoaCtx setView: [GLWin.cocoaWin contentView]];
|
||||
[GLWin.cocoaCtx setView: GLWin.cocoaWin];
|
||||
[GLWin.cocoaCtx update];
|
||||
[GLWin.cocoaCtx makeCurrentContext];
|
||||
s_backbuffer_width = width;
|
||||
@@ -110,7 +111,6 @@ bool cInterfaceAGL::MakeCurrent()
|
||||
// Close backend
|
||||
void cInterfaceAGL::Shutdown()
|
||||
{
|
||||
[GLWin.cocoaWin close];
|
||||
[GLWin.cocoaCtx clearDrawable];
|
||||
[GLWin.cocoaCtx release];
|
||||
}
|
||||
|
||||
@@ -69,8 +69,6 @@ bool cInterfaceGLX::Create(void *&window_handle)
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
GLX_SAMPLE_BUFFERS_ARB, g_Config.iMultisampleMode != MULTISAMPLE_OFF?1:0,
|
||||
GLX_SAMPLES_ARB, g_Config.iMultisampleMode != MULTISAMPLE_OFF?1:0,
|
||||
None };
|
||||
|
||||
int attrListDefault[] = {
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "Host.h"
|
||||
#include "RenderBase.h"
|
||||
|
||||
#include "VertexShaderManager.h"
|
||||
#include "../GLInterface.h"
|
||||
#include "WX.h"
|
||||
|
||||
void cInterfaceWX::SwapInterval(int Interval)
|
||||
{
|
||||
// WX interface only used on Apple
|
||||
#ifdef __APPLE__
|
||||
#if defined USE_WX && USE_WX
|
||||
NSOpenGLContext *ctx = GLWin.glCtxt->GetWXGLContext();
|
||||
#else
|
||||
NSOpenGLContext *ctx = GLWin.cocoaCtx;
|
||||
#endif
|
||||
[ctx setValues: &Interval forParameter: NSOpenGLCPSwapInterval];
|
||||
#endif
|
||||
}
|
||||
|
||||
void cInterfaceWX::Swap()
|
||||
{
|
||||
GLWin.glCanvas->SwapBuffers();
|
||||
}
|
||||
|
||||
void cInterfaceWX::UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
// Handled by Host_UpdateTitle()
|
||||
}
|
||||
|
||||
// Create rendering window.
|
||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
||||
bool cInterfaceWX::Create(void *&window_handle)
|
||||
{
|
||||
int _tx, _ty, _twidth, _theight;
|
||||
Host_GetRenderWindowSize(_tx, _ty, _twidth, _theight);
|
||||
|
||||
// Control window size and picture scaling
|
||||
s_backbuffer_width = _twidth;
|
||||
s_backbuffer_height = _theight;
|
||||
|
||||
GLWin.panel = (wxPanel *)window_handle;
|
||||
GLWin.glCanvas = new wxGLCanvas(GLWin.panel, wxID_ANY, NULL,
|
||||
wxPoint(0, 0), wxSize(_twidth, _theight));
|
||||
GLWin.glCanvas->Show(true);
|
||||
if (GLWin.glCtxt == NULL) // XXX dirty hack
|
||||
GLWin.glCtxt = new wxGLContext(GLWin.glCanvas);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cInterfaceWX::MakeCurrent()
|
||||
{
|
||||
return GLWin.glCanvas->SetCurrent(*GLWin.glCtxt);
|
||||
}
|
||||
|
||||
// Update window width, size and etc. Called from Render.cpp
|
||||
void cInterfaceWX::Update()
|
||||
{
|
||||
int width, height;
|
||||
|
||||
GLWin.panel->GetSize(&width, &height);
|
||||
if (width == s_backbuffer_width && height == s_backbuffer_height)
|
||||
return;
|
||||
|
||||
GLWin.glCanvas->SetFocus();
|
||||
GLWin.glCanvas->SetSize(0, 0, width, height);
|
||||
GLWin.glCtxt->SetCurrent(*GLWin.glCanvas);
|
||||
s_backbuffer_width = width;
|
||||
s_backbuffer_height = height;
|
||||
}
|
||||
|
||||
// Close backend
|
||||
void cInterfaceWX::Shutdown()
|
||||
{
|
||||
GLWin.glCanvas->Hide();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#ifndef _INTERFACEWX_H_
|
||||
#define _INTERFACEWX_H_
|
||||
|
||||
#if defined HAVE_X11 && HAVE_X11
|
||||
#include <GL/glxew.h>
|
||||
#include <GL/gl.h>
|
||||
#elif defined __APPLE__
|
||||
#include <GL/glew.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif
|
||||
|
||||
#if defined USE_WX && USE_WX
|
||||
#include "wx/wx.h"
|
||||
#include "wx/glcanvas.h"
|
||||
#endif
|
||||
|
||||
#include "InterfaceBase.h"
|
||||
|
||||
class cInterfaceWX : public cInterfaceBase
|
||||
{
|
||||
public:
|
||||
void SwapInterval(int Interval);
|
||||
void Swap();
|
||||
void UpdateFPSDisplay(const char *Text);
|
||||
bool Create(void *&window_handle);
|
||||
bool MakeCurrent();
|
||||
void Shutdown();
|
||||
|
||||
void Update();
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif
|
||||
|
||||
// Nvidia drivers >= v302 will check if the application exports a global
|
||||
// variable named NvOptimusEnablement to know if it should run the app in high
|
||||
// performance graphics mode or using the IGP.
|
||||
@@ -232,6 +236,17 @@ bool DolphinApp::OnInit()
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
if (floor(NSAppKitVersionNumber) < NSAppKitVersionNumber10_7)
|
||||
{
|
||||
PanicAlertT("Hi,\n\nDolphin requires OS X 10.7 or greater.\n"
|
||||
"Unfortunately you're running an old version of OS X.\n"
|
||||
"The last Dolphin version to support OS X 10.6 is Dolphin 3.5\n"
|
||||
"Please upgrade to 10.7 or greater to use the newest Dolphin version.\n\n"
|
||||
"Sayonara!\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!wxSetWorkingDirectory(StrToWxStr(File::GetExeDirectory())))
|
||||
|
||||
@@ -82,6 +82,7 @@ wxString af_desc = wxTRANSLATE("Enable anisotropic filtering.\nEnhances visual q
|
||||
wxString aa_desc = wxTRANSLATE("Reduces the amount of aliasing caused by rasterizing 3D graphics.\nThis makes the rendered picture look less blocky.\nHeavily decreases emulation speed and sometimes causes issues.\n\nIf unsure, select None.");
|
||||
wxString scaled_efb_copy_desc = wxTRANSLATE("Greatly increases quality of textures generated using render to texture effects.\nRaising the internal resolution will improve the effect of this setting.\nSlightly decreases performance and possibly causes issues (although unlikely).\n\nIf unsure, leave this checked.");
|
||||
wxString pixel_lighting_desc = wxTRANSLATE("Calculate lighting of 3D graphics per-pixel rather than per vertex.\nDecreases emulation speed by some percent (depending on your GPU).\nThis usually is a safe enhancement, but might cause issues sometimes.\n\nIf unsure, leave this unchecked.");
|
||||
wxString hacked_buffer_upload_desc = wxTRANSLATE("Use a hacked upload strategy to stream vertices.\nThis usually speed up, but is forbidden by OpenGL specification and may causes heavy glitches.\n\nIf unsure, leave this unchecked.");
|
||||
wxString force_filtering_desc = wxTRANSLATE("Force texture filtering even if the emulated game explicitly disabled it.\nImproves texture quality slightly but causes glitches in some games.\n\nIf unsure, leave this unchecked.");
|
||||
wxString _3d_vision_desc = wxTRANSLATE("Enable 3D effects via stereoscopy using Nvidia 3D Vision technology if it's supported by your GPU.\nPossibly causes issues.\nRequires fullscreen to work.\n\nIf unsure, leave this unchecked.");
|
||||
wxString internal_res_desc = wxTRANSLATE("Specifies the resolution used to render at. A high resolution will improve visual quality a lot but is also quite heavy on performance and might cause glitches in certain games.\n\"Multiple of 640x528\" is a bit slower than \"Window Size\" but yields less issues. Generally speaking, the lower the internal resolution is, the better your performance will be.\n\nIf unsure, select 640x528.");
|
||||
@@ -486,13 +487,17 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
|
||||
// - other hacks
|
||||
{
|
||||
wxGridSizer* const szr_other = new wxGridSizer(2, 5, 5);
|
||||
|
||||
SettingCheckBox* hacked_buffer_upload_cb;
|
||||
szr_other->Add(CreateCheckBox(page_hacks, _("Cache Display Lists"), wxGetTranslation(dlc_desc), vconfig.bDlistCachingEnable));
|
||||
szr_other->Add(CreateCheckBox(page_hacks, _("Disable Fog"), wxGetTranslation(disable_fog_desc), vconfig.bDisableFog));
|
||||
szr_other->Add(CreateCheckBox(page_hacks, _("Skip Dest. Alpha Pass"), wxGetTranslation(disable_alphapass_desc), vconfig.bDstAlphaPass));
|
||||
szr_other->Add(CreateCheckBox(page_hacks, _("OpenCL Texture Decoder"), wxGetTranslation(opencl_desc), vconfig.bEnableOpenCL));
|
||||
szr_other->Add(CreateCheckBox(page_hacks, _("OpenMP Texture Decoder"), wxGetTranslation(omp_desc), vconfig.bOMPDecoder));
|
||||
szr_other->Add(hacked_buffer_upload_cb = CreateCheckBox(page_hacks, _("Hacked Buffer Upload"), wxGetTranslation(hacked_buffer_upload_desc), vconfig.bHackedBufferUpload));
|
||||
|
||||
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
||||
hacked_buffer_upload_cb->Disable();
|
||||
|
||||
wxStaticBoxSizer* const group_other = new wxStaticBoxSizer(wxVERTICAL, page_hacks, _("Other"));
|
||||
group_other->Add(szr_other, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_hacks->Add(group_other, 0, wxEXPAND | wxALL, 5);
|
||||
@@ -564,7 +569,6 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
|
||||
szr_misc->Add(cb_prog_scan);
|
||||
}
|
||||
|
||||
|
||||
wxStaticBoxSizer* const group_misc = new wxStaticBoxSizer(wxVERTICAL, page_advanced, _("Misc"));
|
||||
szr_advanced->Add(group_misc, 0, wxEXPAND | wxALL, 5);
|
||||
group_misc->Add(szr_misc, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
|
||||
@@ -236,7 +236,7 @@ bool GetConfig(const int &type)
|
||||
case CONFIG_DISABLEFOG:
|
||||
return g_ActiveConfig.bDisableFog;
|
||||
case CONFIG_SHOWEFBREGIONS:
|
||||
return false;
|
||||
return g_ActiveConfig.bShowEFBCopyRegions;
|
||||
default:
|
||||
PanicAlert("GetConfig Error: Unknown Config Type!");
|
||||
return false;
|
||||
@@ -248,6 +248,7 @@ u8 *GetPointer(const u32 &address)
|
||||
return Memory::GetPointer(address);
|
||||
}
|
||||
|
||||
// Never used. All backends call SetSamplerState in VertexManager::Flush
|
||||
void SetTextureMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetSamplerState(bp.address & 3, (bp.address & 0xE0) == 0xA0);
|
||||
|
||||
@@ -225,6 +225,8 @@ void BPWritten(const BPCmd& bp)
|
||||
{
|
||||
PRIM_LOG("constalpha: alp=%d, en=%d", bpmem.dstalpha.alpha, bpmem.dstalpha.enable);
|
||||
PixelShaderManager::SetDestAlpha(bpmem.dstalpha);
|
||||
if(bp.changes & 0x100)
|
||||
SetBlendMode();
|
||||
break;
|
||||
}
|
||||
// This is called when the game is done drawing the new frame (eg: like in DX: Begin(); Draw(); End();)
|
||||
@@ -459,6 +461,8 @@ void BPWritten(const BPCmd& bp)
|
||||
g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel
|
||||
g_renderer->SetBlendMode(true);
|
||||
OnPixelFormatChange();
|
||||
if(bp.changes & 3)
|
||||
SetBlendMode(); // dual source could be activated by changing to PIXELFMT_RGBA6_Z24
|
||||
break;
|
||||
|
||||
case BPMEM_MIPMAP_STRIDE: // MipMap Stride Channel
|
||||
@@ -576,8 +580,6 @@ void BPWritten(const BPCmd& bp)
|
||||
// ------------------------
|
||||
case BPMEM_TX_SETMODE0: // (0x90 for linear)
|
||||
case BPMEM_TX_SETMODE0_4:
|
||||
// Shouldn't need to call this here, we call it for each active texture right before rendering
|
||||
SetTextureMode(bp);
|
||||
break;
|
||||
|
||||
case BPMEM_TX_SETMODE1:
|
||||
@@ -719,14 +721,6 @@ void BPReload()
|
||||
SetBlendMode();
|
||||
SetColorMask();
|
||||
OnPixelFormatChange();
|
||||
{
|
||||
BPCmd bp = {BPMEM_TX_SETMODE0, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_TX_SETMODE0])};
|
||||
SetTextureMode(bp);
|
||||
}
|
||||
{
|
||||
BPCmd bp = {BPMEM_TX_SETMODE0_4, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_TX_SETMODE0_4])};
|
||||
SetTextureMode(bp);
|
||||
}
|
||||
{
|
||||
BPCmd bp = {BPMEM_FIELDMASK, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_FIELDMASK])};
|
||||
SetInterlacingMode(bp);
|
||||
|
||||
@@ -163,13 +163,9 @@ void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHe
|
||||
|
||||
// keep stale XFB data from being used
|
||||
ReplaceVirtualXFB();
|
||||
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
// Copy EFB data to XFB and restore render target again
|
||||
vxfb->xfbSource->CopyEFB(Gamma);
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
FramebufferManagerBase::VirtualXFBListType::iterator FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
||||
|
||||
@@ -47,13 +47,13 @@ char *GenerateLightShader(char *p, int index, const LitChannel& chan, const char
|
||||
// atten disabled
|
||||
switch (chan.diffusefunc) {
|
||||
case LIGHTDIF_NONE:
|
||||
WRITE(p, "lacc.%s += %s.lights[%d].col.%s;\n", swizzle, lightsName, index, swizzle);
|
||||
WRITE(p, "lacc.%s += %s[%d].%s;\n", swizzle, lightsName, index * 5, swizzle);
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
case LIGHTDIF_CLAMP:
|
||||
WRITE(p, "ldir = normalize(%s.lights[%d].pos.xyz - pos.xyz);\n", lightsName, index);
|
||||
WRITE(p, "lacc.%s += %sdot(ldir, _norm0)) * %s.lights[%d].col.%s;\n",
|
||||
swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", lightsName, index, swizzle);
|
||||
WRITE(p, "ldir = normalize(%s[%d + 3].xyz - pos.xyz);\n", lightsName, index * 5);
|
||||
WRITE(p, "lacc.%s += %sdot(ldir, _norm0)) * %s[%d].%s;\n",
|
||||
swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", lightsName, index * 5, swizzle);
|
||||
break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
@@ -62,32 +62,32 @@ char *GenerateLightShader(char *p, int index, const LitChannel& chan, const char
|
||||
|
||||
if (chan.attnfunc == 3)
|
||||
{ // spot
|
||||
WRITE(p, "ldir = %s.lights[%d].pos.xyz - pos.xyz;\n", lightsName, index);
|
||||
WRITE(p, "ldir = %s[%d + 3].xyz - pos.xyz;\n", lightsName, index * 5);
|
||||
WRITE(p, "dist2 = dot(ldir, ldir);\n"
|
||||
"dist = sqrt(dist2);\n"
|
||||
"ldir = ldir / dist;\n"
|
||||
"attn = max(0.0f, dot(ldir, %s.lights[%d].dir.xyz));\n", lightsName, index);
|
||||
WRITE(p, "attn = max(0.0f, dot(%s.lights[%d].cosatt.xyz, float3(1.0f, attn, attn*attn))) / dot(%s.lights[%d].distatt.xyz, float3(1.0f,dist,dist2));\n", lightsName, index, lightsName, index);
|
||||
"attn = max(0.0f, dot(ldir, %s[%d + 4].xyz));\n", lightsName, index * 5);
|
||||
WRITE(p, "attn = max(0.0f, dot(%s[%d + 1].xyz, float3(1.0f, attn, attn*attn))) / dot(%s[%d + 2].xyz, float3(1.0f,dist,dist2));\n", lightsName, index * 5, lightsName, index * 5);
|
||||
}
|
||||
else if (chan.attnfunc == 1)
|
||||
{ // specular
|
||||
WRITE(p, "ldir = normalize(%s.lights[%d].pos.xyz);\n", lightsName, index);
|
||||
WRITE(p, "attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, %s.lights[%d].dir.xyz)) : 0.0f;\n", lightsName, index);
|
||||
WRITE(p, "attn = max(0.0f, dot(%s.lights[%d].cosatt.xyz, float3(1,attn,attn*attn))) / dot(%s.lights[%d].distatt.xyz, float3(1,attn,attn*attn));\n", lightsName, index, lightsName, index);
|
||||
WRITE(p, "ldir = normalize(%s[%d + 3].xyz);\n", lightsName, index * 5);
|
||||
WRITE(p, "attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, %s[%d + 4].xyz)) : 0.0f;\n", lightsName, index * 5);
|
||||
WRITE(p, "attn = max(0.0f, dot(%s[%d + 1].xyz, float3(1,attn,attn*attn))) / dot(%s[%d + 2].xyz, float3(1,attn,attn*attn));\n", lightsName, index * 5, lightsName, index * 5);
|
||||
}
|
||||
|
||||
switch (chan.diffusefunc)
|
||||
{
|
||||
case LIGHTDIF_NONE:
|
||||
WRITE(p, "lacc.%s += attn * %s.lights[%d].col.%s;\n", swizzle, lightsName, index, swizzle);
|
||||
WRITE(p, "lacc.%s += attn * %s[%d].%s;\n", swizzle, lightsName, index * 5, swizzle);
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
case LIGHTDIF_CLAMP:
|
||||
WRITE(p, "lacc.%s += attn * %sdot(ldir, _norm0)) * %s.lights[%d].col.%s;\n",
|
||||
WRITE(p, "lacc.%s += attn * %sdot(ldir, _norm0)) * %s[%d].%s;\n",
|
||||
swizzle,
|
||||
chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(",
|
||||
lightsName,
|
||||
index,
|
||||
index * 5,
|
||||
swizzle);
|
||||
break;
|
||||
default: _assert_(0);
|
||||
@@ -120,7 +120,7 @@ char *GenerateLightingShader(char *p, int components, const char* materialsName,
|
||||
WRITE(p, "mat = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
|
||||
}
|
||||
else // from color
|
||||
WRITE(p, "mat = %s.C%d;\n", materialsName, j+2);
|
||||
WRITE(p, "mat = %s[%d];\n", materialsName, j+2);
|
||||
|
||||
if (color.enablelighting) {
|
||||
if (color.ambsource) { // from vertex
|
||||
@@ -132,7 +132,7 @@ char *GenerateLightingShader(char *p, int components, const char* materialsName,
|
||||
WRITE(p, "lacc = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
|
||||
}
|
||||
else // from color
|
||||
WRITE(p, "lacc = %s.C%d;\n", materialsName, j);
|
||||
WRITE(p, "lacc = %s[%d];\n", materialsName, j);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -149,7 +149,7 @@ char *GenerateLightingShader(char *p, int components, const char* materialsName,
|
||||
else WRITE(p, "mat.w = 1.0f;\n");
|
||||
}
|
||||
else // from color
|
||||
WRITE(p, "mat.w = %s.C%d.w;\n", materialsName, j+2);
|
||||
WRITE(p, "mat.w = %s[%d].w;\n", materialsName, j+2);
|
||||
}
|
||||
|
||||
if (alpha.enablelighting)
|
||||
@@ -163,7 +163,7 @@ char *GenerateLightingShader(char *p, int components, const char* materialsName,
|
||||
WRITE(p, "lacc.w = 0.0f;\n");
|
||||
}
|
||||
else // from color
|
||||
WRITE(p, "lacc.w = %s.C%d.w;\n", materialsName, j);
|
||||
WRITE(p, "lacc.w = %s[%d].w;\n", materialsName, j);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
virtual void SetupVertexPointers() = 0;
|
||||
virtual void EnableComponents(u32 components) {}
|
||||
|
||||
int GetVertexStride() const { return vertex_stride; }
|
||||
u32 GetVertexStride() const { return vertex_stride; }
|
||||
|
||||
// TODO: move this under private:
|
||||
u32 m_components; // VB_HAS_X. Bitmask telling what vertex components are present.
|
||||
|
||||
@@ -394,7 +394,7 @@ static void Decode()
|
||||
|
||||
// Display lists get added directly into the FIFO stream
|
||||
if (g_bRecordFifoData && cmd_byte != GX_CMD_CALL_DL)
|
||||
FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, g_pVideoData - opcodeStart);
|
||||
FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, u32(g_pVideoData - opcodeStart));
|
||||
}
|
||||
|
||||
static void DecodeSemiNop()
|
||||
@@ -477,7 +477,7 @@ static void DecodeSemiNop()
|
||||
}
|
||||
|
||||
if (g_bRecordFifoData && cmd_byte != GX_CMD_CALL_DL)
|
||||
FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, g_pVideoData - opcodeStart);
|
||||
FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, u32(g_pVideoData - opcodeStart));
|
||||
}
|
||||
|
||||
void OpcodeDecoder_Init()
|
||||
|
||||
@@ -173,7 +173,7 @@ void GetPixelShaderId(PIXELSHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 compo
|
||||
*ptr++ = components;
|
||||
}
|
||||
|
||||
uid->num_values = ptr - uid->values;
|
||||
uid->num_values = int(ptr - uid->values);
|
||||
}
|
||||
|
||||
void GetSafePixelShaderId(PIXELSHADERUIDSAFE *uid, DSTALPHA_MODE dstAlphaMode, u32 components)
|
||||
@@ -205,7 +205,7 @@ void GetSafePixelShaderId(PIXELSHADERUIDSAFE *uid, DSTALPHA_MODE dstAlphaMode, u
|
||||
|
||||
*ptr++ = bpmem.tevindref.hex; // 31
|
||||
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numtevstages+1u; ++i) // up to 16 times
|
||||
for (u32 i = 0; i < bpmem.genMode.numtevstages+1u; ++i) // up to 16 times
|
||||
{
|
||||
*ptr++ = bpmem.combiners[i].colorC.hex; // 32+5*i
|
||||
*ptr++ = bpmem.combiners[i].alphaC.hex; // 33+5*i
|
||||
@@ -440,8 +440,8 @@ static const char *tevRasTable[] =
|
||||
"ERROR13", //2
|
||||
"ERROR14", //3
|
||||
"ERROR15", //4
|
||||
"alphabump", // use bump alpha
|
||||
"(alphabump*(255.0f/248.0f))", //normalized
|
||||
"float4(alphabump,alphabump,alphabump,alphabump)", // use bump alpha
|
||||
"(float4(alphabump,alphabump,alphabump,alphabump)*(255.0f/248.0f))", //normalized
|
||||
"float4(0.0f, 0.0f, 0.0f, 0.0f)", // zero
|
||||
};
|
||||
|
||||
@@ -485,6 +485,24 @@ static void BuildSwapModeTable()
|
||||
}
|
||||
}
|
||||
|
||||
const char* WriteRegister(API_TYPE ApiType, const char *prefix, const u32 num)
|
||||
{
|
||||
if (ApiType == API_OPENGL)
|
||||
return ""; // Nothing to do here
|
||||
static char result[64];
|
||||
sprintf(result, " : register(%s%d)", prefix, num);
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *WriteLocation(API_TYPE ApiType)
|
||||
{
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
return "";
|
||||
static char result[64];
|
||||
sprintf(result, "uniform ");
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components)
|
||||
{
|
||||
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
|
||||
@@ -510,138 +528,216 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
|
||||
nIndirectStagesUsed |= 1 << bpmem.tevind[i].bt;
|
||||
}
|
||||
}
|
||||
// Declare samplers
|
||||
|
||||
if(ApiType != API_D3D11)
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
WRITE(p, "uniform sampler2D ");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p, "sampler ");
|
||||
}
|
||||
|
||||
bool bfirst = true;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
WRITE(p, "%s samp%d : register(s%d)", bfirst?"":",", i, i);
|
||||
bfirst = false;
|
||||
}
|
||||
WRITE(p, ";\n");
|
||||
if(ApiType == API_D3D11)
|
||||
{
|
||||
WRITE(p, "Texture2D ");
|
||||
bfirst = true;
|
||||
// A function here
|
||||
// Fmod implementation gleaned from Nvidia
|
||||
// At http://http.developer.nvidia.com/Cg/fmod.html
|
||||
WRITE(p, "float fmod( float x, float y )\n");
|
||||
WRITE(p, "{\n");
|
||||
WRITE(p, "\tfloat z = fract( abs( x / y) ) * abs( y );\n");
|
||||
WRITE(p, "\treturn (x < 0) ? -z : z;\n");
|
||||
WRITE(p, "}\n");
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
WRITE(p, "%s Tex%d : register(t%d)", bfirst?"":",", i, i);
|
||||
bfirst = false;
|
||||
}
|
||||
WRITE(p, ";\n");
|
||||
}
|
||||
|
||||
WRITE(p, "\n");
|
||||
|
||||
WRITE(p, "uniform float4 " I_COLORS"[4] : register(c%d);\n", C_COLORS);
|
||||
WRITE(p, "uniform float4 " I_KCOLORS"[4] : register(c%d);\n", C_KCOLORS);
|
||||
WRITE(p, "uniform float4 " I_ALPHA"[1] : register(c%d);\n", C_ALPHA);
|
||||
WRITE(p, "uniform float4 " I_TEXDIMS"[8] : register(c%d);\n", C_TEXDIMS);
|
||||
WRITE(p, "uniform float4 " I_ZBIAS"[2] : register(c%d);\n", C_ZBIAS);
|
||||
WRITE(p, "uniform float4 " I_INDTEXSCALE"[2] : register(c%d);\n", C_INDTEXSCALE);
|
||||
WRITE(p, "uniform float4 " I_INDTEXMTX"[6] : register(c%d);\n", C_INDTEXMTX);
|
||||
WRITE(p, "uniform float4 " I_FOG"[3] : register(c%d);\n", C_FOG);
|
||||
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
WRITE(p,"typedef struct { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; } Light;\n");
|
||||
WRITE(p,"typedef struct { Light lights[8]; } s_" I_PLIGHTS";\n");
|
||||
WRITE(p, "uniform s_" I_PLIGHTS" " I_PLIGHTS" : register(c%d);\n", C_PLIGHTS);
|
||||
WRITE(p, "typedef struct { float4 C0, C1, C2, C3; } s_" I_PMATERIALS";\n");
|
||||
WRITE(p, "uniform s_" I_PMATERIALS" " I_PMATERIALS" : register(c%d);\n", C_PMATERIALS);
|
||||
}
|
||||
|
||||
WRITE(p, "void main(\n");
|
||||
if(ApiType != API_D3D11)
|
||||
{
|
||||
WRITE(p, " out float4 ocol0 : COLOR0,%s%s\n in float4 rawpos : %s,\n",
|
||||
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : COLOR1," : "",
|
||||
per_pixel_depth ? "\n out float depth : DEPTH," : "",
|
||||
ApiType & API_OPENGL ? "WPOS" : ApiType & API_D3D9_SM20 ? "POSITION" : "VPOS");
|
||||
WRITE(p, "uniform sampler2D samp%d;\n", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p, " out float4 ocol0 : SV_Target0,%s%s\n in float4 rawpos : SV_Position,\n",
|
||||
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "",
|
||||
per_pixel_depth ? "\n out float depth : SV_Depth," : "");
|
||||
}
|
||||
|
||||
WRITE(p, " in float4 colors_0 : COLOR0,\n");
|
||||
WRITE(p, " in float4 colors_1 : COLOR1");
|
||||
|
||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||
if (numTexgen < 7)
|
||||
{
|
||||
for (int i = 0; i < numTexgen; ++i)
|
||||
WRITE(p, ",\n in float3 uv%d : TEXCOORD%d", i, i);
|
||||
WRITE(p, ",\n in float4 clipPos : TEXCOORD%d", numTexgen);
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
WRITE(p, ",\n in float4 Normal : TEXCOORD%d", numTexgen + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// wpos is in w of first 4 texcoords
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
// Declare samplers
|
||||
if (ApiType != API_D3D11)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
WRITE(p, ",\n in float4 uv%d : TEXCOORD%d", i, i);
|
||||
WRITE(p, "uniform sampler2D ");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
WRITE(p, ",\n in float%d uv%d : TEXCOORD%d", i < 4 ? 4 : 3 , i, i);
|
||||
WRITE(p, "sampler ");
|
||||
}
|
||||
|
||||
bool bfirst = true;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
WRITE(p, "%s samp%d %s", bfirst?"":",", i, WriteRegister(ApiType, "s", i));
|
||||
bfirst = false;
|
||||
}
|
||||
WRITE(p, ";\n");
|
||||
if (ApiType == API_D3D11)
|
||||
{
|
||||
WRITE(p, "Texture2D ");
|
||||
bfirst = true;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
WRITE(p, "%s Tex%d : register(t%d)", bfirst?"":",", i, i);
|
||||
bfirst = false;
|
||||
}
|
||||
WRITE(p, ";\n");
|
||||
}
|
||||
}
|
||||
|
||||
WRITE(p, "\n");
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
WRITE(p, "layout(std140) uniform PSBlock {\n");
|
||||
|
||||
WRITE(p, "\t%sfloat4 " I_COLORS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_COLORS));
|
||||
WRITE(p, "\t%sfloat4 " I_KCOLORS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_KCOLORS));
|
||||
WRITE(p, "\t%sfloat4 " I_ALPHA"[1] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_ALPHA));
|
||||
WRITE(p, "\t%sfloat4 " I_TEXDIMS"[8] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_TEXDIMS));
|
||||
WRITE(p, "\t%sfloat4 " I_ZBIAS"[2] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_ZBIAS));
|
||||
WRITE(p, "\t%sfloat4 " I_INDTEXSCALE"[2] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_INDTEXSCALE));
|
||||
WRITE(p, "\t%sfloat4 " I_INDTEXMTX"[6] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_INDTEXMTX));
|
||||
WRITE(p, "\t%sfloat4 " I_FOG"[3] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_FOG));
|
||||
|
||||
// For pixel lighting
|
||||
WRITE(p, "\t%sfloat4 " I_PLIGHTS"[40] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_PLIGHTS));
|
||||
WRITE(p, "\t%sfloat4 " I_PMATERIALS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_PMATERIALS));
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
WRITE(p, "};\n");
|
||||
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
WRITE(p, "out float4 ocol0;\n");
|
||||
if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
|
||||
WRITE(p, "out float4 ocol1;\n");
|
||||
|
||||
if (per_pixel_depth)
|
||||
WRITE(p, "#define depth gl_FragDepth\n");
|
||||
WRITE(p, "float4 rawpos = gl_FragCoord;\n");
|
||||
|
||||
WRITE(p, "VARYIN float4 colors_02;\n");
|
||||
WRITE(p, "VARYIN float4 colors_12;\n");
|
||||
WRITE(p, "float4 colors_0 = colors_02;\n");
|
||||
WRITE(p, "float4 colors_1 = colors_12;\n");
|
||||
|
||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||
// Let's set up attributes
|
||||
if (xfregs.numTexGen.numTexGens < 7)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
WRITE(p, "VARYIN float3 uv%d_2;\n", i);
|
||||
WRITE(p, "float3 uv%d = uv%d_2;\n", i, i);
|
||||
}
|
||||
WRITE(p, "VARYIN float4 clipPos_2;\n");
|
||||
WRITE(p, "float4 clipPos = clipPos_2;\n");
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
WRITE(p, "VARYIN float4 Normal_2;\n");
|
||||
WRITE(p, "float4 Normal = Normal_2;\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// wpos is in w of first 4 texcoords
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
WRITE(p, "VARYIN float4 uv%d_2;\n", i);
|
||||
WRITE(p, "float4 uv%d = uv%d_2;\n", i, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
{
|
||||
WRITE(p, "VARYIN float%d uv%d_2;\n", i < 4 ? 4 : 3 , i);
|
||||
WRITE(p, "float%d uv%d = uv%d_2;\n", i < 4 ? 4 : 3 , i, i);
|
||||
}
|
||||
}
|
||||
WRITE(p, "float4 clipPos;\n");
|
||||
}
|
||||
WRITE(p, "void main()\n{\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p, "void main(\n");
|
||||
if (ApiType != API_D3D11)
|
||||
{
|
||||
WRITE(p, " out float4 ocol0 : COLOR0,%s%s\n in float4 rawpos : %s,\n",
|
||||
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : COLOR1," : "",
|
||||
per_pixel_depth ? "\n out float depth : DEPTH," : "",
|
||||
ApiType & API_D3D9_SM20 ? "POSITION" : "VPOS");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p, " out float4 ocol0 : SV_Target0,%s%s\n in float4 rawpos : SV_Position,\n",
|
||||
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "",
|
||||
per_pixel_depth ? "\n out float depth : SV_Depth," : "");
|
||||
}
|
||||
|
||||
WRITE(p, " in float4 colors_0 : COLOR0,\n");
|
||||
WRITE(p, " in float4 colors_1 : COLOR1");
|
||||
|
||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||
if (numTexgen < 7)
|
||||
{
|
||||
for (int i = 0; i < numTexgen; ++i)
|
||||
WRITE(p, ",\n in float3 uv%d : TEXCOORD%d", i, i);
|
||||
WRITE(p, ",\n in float4 clipPos : TEXCOORD%d", numTexgen);
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
WRITE(p, ",\n in float4 Normal : TEXCOORD%d", numTexgen + 1);
|
||||
WRITE(p, " ) {\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// wpos is in w of first 4 texcoords
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
WRITE(p, ",\n in float4 uv%d : TEXCOORD%d", i, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
WRITE(p, ",\n in float%d uv%d : TEXCOORD%d", i < 4 ? 4 : 3 , i, i);
|
||||
}
|
||||
WRITE(p, " ) {\n");
|
||||
WRITE(p, "\tfloat4 clipPos = float4(0.0f, 0.0f, 0.0f, 0.0f);");
|
||||
}
|
||||
}
|
||||
WRITE(p, " ) {\n");
|
||||
|
||||
WRITE(p, " float4 c0 = " I_COLORS"[1], c1 = " I_COLORS"[2], c2 = " I_COLORS"[3], prev = float4(0.0f, 0.0f, 0.0f, 0.0f), textemp = float4(0.0f, 0.0f, 0.0f, 0.0f), rastemp = float4(0.0f, 0.0f, 0.0f, 0.0f), konsttemp = float4(0.0f, 0.0f, 0.0f, 0.0f);\n"
|
||||
" float3 comp16 = float3(1.0f, 255.0f, 0.0f), comp24 = float3(1.0f, 255.0f, 255.0f*255.0f);\n"
|
||||
" float4 alphabump=float4(0.0f,0.0f,0.0f,0.0f);\n"
|
||||
" float alphabump=0.0f;\n"
|
||||
" float3 tevcoord=float3(0.0f, 0.0f, 0.0f);\n"
|
||||
" float2 wrappedcoord=float2(0.0f,0.0f), tempcoord=float2(0.0f,0.0f);\n"
|
||||
" float4 cc0=float4(0.0f,0.0f,0.0f,0.0f), cc1=float4(0.0f,0.0f,0.0f,0.0f);\n"
|
||||
" float4 cc2=float4(0.0f,0.0f,0.0f,0.0f), cprev=float4(0.0f,0.0f,0.0f,0.0f);\n"
|
||||
" float4 crastemp=float4(0.0f,0.0f,0.0f,0.0f),ckonsttemp=float4(0.0f,0.0f,0.0f,0.0f);\n\n");
|
||||
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
if (xfregs.numTexGen.numTexGens < 7)
|
||||
{
|
||||
WRITE(p,"float3 _norm0 = normalize(Normal.xyz);\n\n");
|
||||
WRITE(p,"float3 pos = float3(clipPos.x,clipPos.y,Normal.w);\n");
|
||||
WRITE(p,"\tfloat3 _norm0 = normalize(Normal.xyz);\n\n");
|
||||
WRITE(p,"\tfloat3 pos = float3(clipPos.x,clipPos.y,Normal.w);\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p," float3 _norm0 = normalize(float3(uv4.w,uv5.w,uv6.w));\n\n");
|
||||
WRITE(p,"float3 pos = float3(uv0.w,uv1.w,uv7.w);\n");
|
||||
WRITE(p,"\tfloat3 _norm0 = normalize(float3(uv4.w,uv5.w,uv6.w));\n\n");
|
||||
WRITE(p,"\tfloat3 pos = float3(uv0.w,uv1.w,uv7.w);\n");
|
||||
}
|
||||
|
||||
|
||||
WRITE(p, "float4 mat, lacc;\n"
|
||||
"float3 ldir, h;\n"
|
||||
"float dist, dist2, attn;\n");
|
||||
WRITE(p, "\tfloat4 mat, lacc;\n"
|
||||
"\tfloat3 ldir, h;\n"
|
||||
"\tfloat dist, dist2, attn;\n");
|
||||
|
||||
p = GenerateLightingShader(p, components, I_PMATERIALS, I_PLIGHTS, "colors_", "colors_");
|
||||
}
|
||||
|
||||
if (numTexgen < 7)
|
||||
WRITE(p, "clipPos = float4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n");
|
||||
WRITE(p, "\tclipPos = float4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n");
|
||||
else
|
||||
WRITE(p, "float4 clipPos = float4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n");
|
||||
WRITE(p, "\tclipPos = float4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n");
|
||||
|
||||
// HACK to handle cases where the tex gen is not enabled
|
||||
if (numTexgen == 0)
|
||||
{
|
||||
WRITE(p, "float3 uv0 = float3(0.0f, 0.0f, 0.0f);\n");
|
||||
WRITE(p, "\tfloat3 uv0 = float3(0.0f, 0.0f, 0.0f);\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -650,8 +746,8 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
|
||||
// optional perspective divides
|
||||
if (xfregs.texMtxInfo[i].projection == XF_TEXPROJ_STQ)
|
||||
{
|
||||
WRITE(p, "if (uv%d.z)", i);
|
||||
WRITE(p, " uv%d.xy = uv%d.xy / uv%d.z;\n", i, i, i);
|
||||
WRITE(p, "\tif (uv%d.z != 0.0f)", i);
|
||||
WRITE(p, "\t\tuv%d.xy = uv%d.xy / uv%d.z;\n", i, i, i);
|
||||
}
|
||||
|
||||
WRITE(p, "uv%d.xy = uv%d.xy * " I_TEXDIMS"[%d].zw;\n", i, i, i);
|
||||
@@ -659,16 +755,16 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
|
||||
}
|
||||
|
||||
// indirect texture map lookup
|
||||
for(u32 i = 0; i < bpmem.genMode.numindstages; ++i)
|
||||
for (u32 i = 0; i < bpmem.genMode.numindstages; ++i)
|
||||
{
|
||||
if (nIndirectStagesUsed & (1<<i))
|
||||
{
|
||||
int texcoord = bpmem.tevindref.getTexCoord(i);
|
||||
|
||||
if (texcoord < numTexgen)
|
||||
WRITE(p, "tempcoord = uv%d.xy * " I_INDTEXSCALE"[%d].%s;\n", texcoord, i/2, (i&1)?"zw":"xy");
|
||||
WRITE(p, "\ttempcoord = uv%d.xy * " I_INDTEXSCALE"[%d].%s;\n", texcoord, i/2, (i&1)?"zw":"xy");
|
||||
else
|
||||
WRITE(p, "tempcoord = float2(0.0f, 0.0f);\n");
|
||||
WRITE(p, "\ttempcoord = float2(0.0f, 0.0f);\n");
|
||||
|
||||
char buffer[32];
|
||||
sprintf(buffer, "float3 indtex%d", i);
|
||||
@@ -689,26 +785,26 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
|
||||
for (int i = 0; i < numStages; i++)
|
||||
WriteStage(p, i, ApiType); //build the equation for this stage
|
||||
|
||||
if(numStages)
|
||||
if (numStages)
|
||||
{
|
||||
// The results of the last texenv stage are put onto the screen,
|
||||
// regardless of the used destination register
|
||||
if(bpmem.combiners[numStages - 1].colorC.dest != 0)
|
||||
{
|
||||
bool retrieveFromAuxRegister = !RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].ColorNeedOverflowControl && RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].AuxStored;
|
||||
WRITE(p, "prev.rgb = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevCOutputTable[bpmem.combiners[numStages - 1].colorC.dest]);
|
||||
WRITE(p, "\tprev.rgb = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevCOutputTable[bpmem.combiners[numStages - 1].colorC.dest]);
|
||||
RegisterStates[0].ColorNeedOverflowControl = RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].ColorNeedOverflowControl;
|
||||
}
|
||||
if(bpmem.combiners[numStages - 1].alphaC.dest != 0)
|
||||
{
|
||||
bool retrieveFromAuxRegister = !RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AlphaNeedOverflowControl && RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AuxStored;
|
||||
WRITE(p, "prev.a = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevAOutputTable[bpmem.combiners[numStages - 1].alphaC.dest]);
|
||||
WRITE(p, "\tprev.a = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevAOutputTable[bpmem.combiners[numStages - 1].alphaC.dest]);
|
||||
RegisterStates[0].AlphaNeedOverflowControl = RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AlphaNeedOverflowControl;
|
||||
}
|
||||
}
|
||||
// emulation of unsigned 8 overflow when casting if needed
|
||||
if(RegisterStates[0].AlphaNeedOverflowControl || RegisterStates[0].ColorNeedOverflowControl)
|
||||
WRITE(p, "prev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
|
||||
WRITE(p, "\tprev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
|
||||
|
||||
AlphaTest::TEST_RESULT Pretest = bpmem.alpha_test.TestResult();
|
||||
if (Pretest == AlphaTest::UNDETERMINED)
|
||||
@@ -741,11 +837,11 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
|
||||
}
|
||||
|
||||
if (dstAlphaMode == DSTALPHA_ALPHA_PASS)
|
||||
WRITE(p, " ocol0 = float4(prev.rgb, " I_ALPHA"[0].a);\n");
|
||||
WRITE(p, "\tocol0 = float4(prev.rgb, " I_ALPHA"[0].a);\n");
|
||||
else
|
||||
{
|
||||
WriteFog(p);
|
||||
WRITE(p, " ocol0 = prev;\n");
|
||||
WRITE(p, "\tocol0 = prev;\n");
|
||||
}
|
||||
|
||||
// On D3D11, use dual-source color blending to perform dst alpha in a
|
||||
@@ -753,9 +849,9 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType
|
||||
if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
|
||||
{
|
||||
// Colors will be blended against the alpha from ocol1...
|
||||
WRITE(p, " ocol1 = ocol0;\n");
|
||||
WRITE(p, "\tocol1 = prev;\n");
|
||||
// ...and the alpha from ocol0 will be written to the framebuffer.
|
||||
WRITE(p, " ocol0.a = " I_ALPHA"[0].a;\n");
|
||||
WRITE(p, "\tocol0.a = " I_ALPHA"[0].a;\n");
|
||||
}
|
||||
|
||||
WRITE(p, "}\n");
|
||||
@@ -864,10 +960,10 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
|
||||
WRITE(p, "float2 indtevtrans%d = " I_INDTEXMTX"[%d].ww * uv%d.xy * indtevcrd%d.yy;\n", n, mtxidx, texcoord, n);
|
||||
}
|
||||
else
|
||||
WRITE(p, "float2 indtevtrans%d = 0;\n", n);
|
||||
WRITE(p, "float2 indtevtrans%d = float2(0.0f);\n", n);
|
||||
}
|
||||
else
|
||||
WRITE(p, "float2 indtevtrans%d = 0;\n", n);
|
||||
WRITE(p, "float2 indtevtrans%d = float2(0.0f);\n", n);
|
||||
|
||||
// ---------
|
||||
// Wrapping
|
||||
@@ -913,10 +1009,10 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
|
||||
|
||||
if (bpmem.tevorders[n/2].getEnable(n&1))
|
||||
{
|
||||
if(!bHasIndStage)
|
||||
if (!bHasIndStage)
|
||||
{
|
||||
// calc tevcord
|
||||
if(bHasTexCoord)
|
||||
if (bHasTexCoord)
|
||||
WRITE(p, "tevcoord.xy = uv%d.xy;\n", texcoord);
|
||||
else
|
||||
WRITE(p, "tevcoord.xy = float2(0.0f, 0.0f);\n");
|
||||
@@ -936,7 +1032,7 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
|
||||
int kc = bpmem.tevksel[n / 2].getKC(n & 1);
|
||||
int ka = bpmem.tevksel[n / 2].getKA(n & 1);
|
||||
WRITE(p, "konsttemp = float4(%s, %s);\n", tevKSelTableC[kc], tevKSelTableA[ka]);
|
||||
if(kc > 7 || ka > 7)
|
||||
if (kc > 7 || ka > 7)
|
||||
{
|
||||
WRITE(p, "ckonsttemp = frac(konsttemp * (255.0f/256.0f)) * (256.0f/255.0f);\n");
|
||||
}
|
||||
@@ -1035,7 +1131,7 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
|
||||
if (cc.shift > TEVSCALE_1)
|
||||
WRITE(p, "%s*(", tevScaleTable[cc.shift]);
|
||||
|
||||
if(!(cc.d == TEVCOLORARG_ZERO && cc.op == TEVOP_ADD))
|
||||
if (!(cc.d == TEVCOLORARG_ZERO && cc.op == TEVOP_ADD))
|
||||
WRITE(p, "%s%s", tevCInputTable[cc.d], tevOpTable[cc.op]);
|
||||
|
||||
if (cc.a == cc.b)
|
||||
@@ -1085,7 +1181,7 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
|
||||
if (ac.shift > TEVSCALE_1)
|
||||
WRITE(p, "%s*(", tevScaleTable[ac.shift]);
|
||||
|
||||
if(!(ac.d == TEVALPHAARG_ZERO && ac.op == TEVOP_ADD))
|
||||
if (!(ac.d == TEVALPHAARG_ZERO && ac.op == TEVOP_ADD))
|
||||
WRITE(p, "%s.a%s", tevAInputTable[ac.d], tevOpTable[ac.op]);
|
||||
|
||||
if (ac.a == ac.b)
|
||||
@@ -1101,7 +1197,7 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType)
|
||||
|
||||
WRITE(p, "%s",tevBiasTable[ac.bias]);
|
||||
|
||||
if (ac.shift>0)
|
||||
if (ac.shift > 0)
|
||||
WRITE(p, ")");
|
||||
|
||||
}
|
||||
@@ -1126,7 +1222,7 @@ void SampleTexture(char *&p, const char *destination, const char *texcoords, con
|
||||
if (ApiType == API_D3D11)
|
||||
WRITE(p, "%s=Tex%d.Sample(samp%d,%s.xy * " I_TEXDIMS"[%d].xy).%s;\n", destination, texmap,texmap, texcoords, texmap, texswap);
|
||||
else
|
||||
WRITE(p, "%s=tex2D(samp%d,%s.xy * " I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap);
|
||||
WRITE(p, "%s=%s(samp%d,%s.xy * " I_TEXDIMS"[%d].xy).%s;\n", destination, ApiType == API_OPENGL ? "texture" : "tex2D", texmap, texcoords, texmap, texswap);
|
||||
}
|
||||
|
||||
static const char *tevAlphaFuncsTable[] =
|
||||
@@ -1157,8 +1253,9 @@ static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode
|
||||
I_ALPHA"[0].g"
|
||||
};
|
||||
|
||||
|
||||
// using discard then return works the same in cg and dx9 but not in dx11
|
||||
WRITE(p, "if(!( ");
|
||||
WRITE(p, "\tif(!( ");
|
||||
|
||||
int compindex = bpmem.alpha_test.comp0;
|
||||
WRITE(p, tevAlphaFuncsTable[compindex],alphaRef[0]);//lookup the first component from the alpha function table
|
||||
@@ -1169,9 +1266,9 @@ static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode
|
||||
WRITE(p, tevAlphaFuncsTable[compindex],alphaRef[1]);//lookup the second component from the alpha function table
|
||||
WRITE(p, ")) {\n");
|
||||
|
||||
WRITE(p, "ocol0 = 0;\n");
|
||||
WRITE(p, "\t\tocol0 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
|
||||
if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
|
||||
WRITE(p, "ocol1 = 0;\n");
|
||||
WRITE(p, "\t\tocol1 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
|
||||
if(per_pixel_depth)
|
||||
WRITE(p, "depth = 1.f;\n");
|
||||
|
||||
@@ -1187,9 +1284,9 @@ static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode
|
||||
// we don't have a choice.
|
||||
if (!(bpmem.zcontrol.early_ztest && bpmem.zmode.updateenable))
|
||||
{
|
||||
WRITE(p, "discard;\n");
|
||||
WRITE(p, "\t\tdiscard;\n");
|
||||
if (ApiType != API_D3D11)
|
||||
WRITE(p, "return;\n");
|
||||
WRITE(p, "\t\treturn;\n");
|
||||
}
|
||||
|
||||
WRITE(p, "}\n");
|
||||
@@ -1201,52 +1298,51 @@ static const char *tevFogFuncsTable[] =
|
||||
"", //?
|
||||
"", //Linear
|
||||
"", //?
|
||||
" fog = 1.0f - pow(2.0f, -8.0f * fog);\n", //exp
|
||||
" fog = 1.0f - pow(2.0f, -8.0f * fog * fog);\n", //exp2
|
||||
" fog = pow(2.0f, -8.0f * (1.0f - fog));\n", //backward exp
|
||||
" fog = 1.0f - fog;\n fog = pow(2.0f, -8.0f * fog * fog);\n" //backward exp2
|
||||
"\tfog = 1.0f - pow(2.0f, -8.0f * fog);\n", //exp
|
||||
"\tfog = 1.0f - pow(2.0f, -8.0f * fog * fog);\n", //exp2
|
||||
"\tfog = pow(2.0f, -8.0f * (1.0f - fog));\n", //backward exp
|
||||
"\tfog = 1.0f - fog;\n fog = pow(2.0f, -8.0f * fog * fog);\n" //backward exp2
|
||||
};
|
||||
|
||||
static void WriteFog(char *&p)
|
||||
{
|
||||
if(bpmem.fog.c_proj_fsel.fsel == 0)return;//no Fog
|
||||
if (bpmem.fog.c_proj_fsel.fsel == 0)
|
||||
return; // no Fog
|
||||
|
||||
if (bpmem.fog.c_proj_fsel.proj == 0)
|
||||
{
|
||||
// perspective
|
||||
// ze = A/(B - (Zs >> B_SHF)
|
||||
WRITE (p, " float ze = " I_FOG"[1].x / (" I_FOG"[1].y - (zCoord / " I_FOG"[1].w));\n");
|
||||
WRITE (p, "\tfloat ze = " I_FOG"[1].x / (" I_FOG"[1].y - (zCoord / " I_FOG"[1].w));\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// orthographic
|
||||
// ze = a*Zs (here, no B_SHF)
|
||||
WRITE (p, " float ze = " I_FOG"[1].x * zCoord;\n");
|
||||
WRITE (p, "\tfloat ze = " I_FOG"[1].x * zCoord;\n");
|
||||
}
|
||||
|
||||
// x_adjust = sqrt((x-center)^2 + k^2)/k
|
||||
// ze *= x_adjust
|
||||
//this is complitly teorical as the real hard seems to use a table intead of calculate the values.
|
||||
if(bpmem.fogRange.Base.Enabled)
|
||||
if (bpmem.fogRange.Base.Enabled)
|
||||
{
|
||||
WRITE (p, " float x_adjust = (2.0f * (clipPos.x / " I_FOG"[2].y)) - 1.0f - " I_FOG"[2].x;\n");
|
||||
WRITE (p, " x_adjust = sqrt(x_adjust * x_adjust + " I_FOG"[2].z * " I_FOG"[2].z) / " I_FOG"[2].z;\n");
|
||||
WRITE (p, " ze *= x_adjust;\n");
|
||||
WRITE (p, "\tfloat x_adjust = (2.0f * (clipPos.x / " I_FOG"[2].y)) - 1.0f - " I_FOG"[2].x;\n");
|
||||
WRITE (p, "\tx_adjust = sqrt(x_adjust * x_adjust + " I_FOG"[2].z * " I_FOG"[2].z) / " I_FOG"[2].z;\n");
|
||||
WRITE (p, "\tze *= x_adjust;\n");
|
||||
}
|
||||
|
||||
WRITE (p, " float fog = saturate(ze - " I_FOG"[1].z);\n");
|
||||
WRITE (p, "\tfloat fog = saturate(ze - " I_FOG"[1].z);\n");
|
||||
|
||||
if(bpmem.fog.c_proj_fsel.fsel > 3)
|
||||
if (bpmem.fog.c_proj_fsel.fsel > 3)
|
||||
{
|
||||
WRITE(p, "%s", tevFogFuncsTable[bpmem.fog.c_proj_fsel.fsel]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(bpmem.fog.c_proj_fsel.fsel != 2)
|
||||
if (bpmem.fog.c_proj_fsel.fsel != 2)
|
||||
WARN_LOG(VIDEO, "Unknown Fog Type! %08x", bpmem.fog.c_proj_fsel.fsel);
|
||||
}
|
||||
|
||||
WRITE(p, " prev.rgb = lerp(prev.rgb," I_FOG"[0].rgb,fog);\n");
|
||||
|
||||
|
||||
WRITE(p, "\tprev.rgb = lerp(prev.rgb, " I_FOG"[0].rgb, fog);\n");
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#define I_INDTEXSCALE "cindscale"
|
||||
#define I_INDTEXMTX "cindmtx"
|
||||
#define I_FOG "cfog"
|
||||
#define I_PLIGHTS "cLights"
|
||||
#define I_PMATERIALS "cmtrl"
|
||||
#define I_PLIGHTS "cPLights"
|
||||
#define I_PMATERIALS "cPmtrl"
|
||||
|
||||
#define C_COLORMATRIX 0 // 0
|
||||
#define C_COLORS 0 // 0
|
||||
@@ -47,6 +47,19 @@
|
||||
#define PIXELSHADERUID_MAX_VALUES 70
|
||||
#define PIXELSHADERUID_MAX_VALUES_SAFE 115
|
||||
|
||||
// Annoying sure, can be removed once we get up to GLSL ~1.3
|
||||
const s_svar PSVar_Loc[] = { {I_COLORS, C_COLORS, 4 },
|
||||
{I_KCOLORS, C_KCOLORS, 4 },
|
||||
{I_ALPHA, C_ALPHA, 1 },
|
||||
{I_TEXDIMS, C_TEXDIMS, 8 },
|
||||
{I_ZBIAS , C_ZBIAS, 2 },
|
||||
{I_INDTEXSCALE , C_INDTEXSCALE, 2 },
|
||||
{I_INDTEXMTX, C_INDTEXMTX, 6 },
|
||||
{I_FOG, C_FOG, 3 },
|
||||
{I_PLIGHTS, C_PLIGHTS, 40 },
|
||||
{I_PMATERIALS, C_PMATERIALS, 4 },
|
||||
};
|
||||
|
||||
// DO NOT make anything in this class virtual.
|
||||
template<bool safe>
|
||||
class _PIXELSHADERUID
|
||||
|
||||
@@ -85,6 +85,8 @@ void PixelShaderManager::Shutdown()
|
||||
|
||||
void PixelShaderManager::SetConstants()
|
||||
{
|
||||
if (g_ActiveConfig.backend_info.APIType == API_OPENGL && !g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
Dirty();
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (s_nColorsChanged[i])
|
||||
|
||||
@@ -831,9 +831,5 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
|
||||
|
||||
entry->frameCount = frameCount;
|
||||
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat);
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "PixelShaderGen.h"
|
||||
#include "BPMemory.h"
|
||||
#include "RenderBase.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
#define WRITE p+=sprintf
|
||||
|
||||
@@ -66,19 +67,31 @@ u16 GetEncodedSampleCount(u32 format)
|
||||
}
|
||||
}
|
||||
|
||||
const char* WriteRegister(API_TYPE ApiType, const char *prefix, const u32 num)
|
||||
{
|
||||
if (ApiType == API_OPENGL)
|
||||
return ""; // Once we switch to GLSL 1.3 we can do something here
|
||||
static char result[64];
|
||||
sprintf(result, " : register(%s%d)", prefix, num);
|
||||
return result;
|
||||
}
|
||||
|
||||
// block dimensions : widthStride, heightStride
|
||||
// texture dims : width, height, x offset, y offset
|
||||
void WriteSwizzler(char*& p, u32 format, API_TYPE ApiType)
|
||||
{
|
||||
WRITE(p, "uniform float4 blkDims : register(c%d);\n", C_COLORMATRIX);
|
||||
WRITE(p, "uniform float4 textureDims : register(c%d);\n", C_COLORMATRIX + 1);
|
||||
// [0] left, top, right, bottom of source rectangle within source texture
|
||||
// [1] width and height of destination texture in pixels
|
||||
// Two were merged for GLSL
|
||||
WRITE(p, "uniform float4 " I_COLORS"[2] %s;\n", WriteRegister(ApiType, "c", C_COLORS));
|
||||
|
||||
float blkW = (float)TexDecoder_GetBlockWidthInTexels(format);
|
||||
float blkW = (float)TexDecoder_GetBlockWidthInTexels(format);
|
||||
float blkH = (float)TexDecoder_GetBlockHeightInTexels(format);
|
||||
float samples = (float)GetEncodedSampleCount(format);
|
||||
if(ApiType == API_OPENGL)
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
WRITE(p,"uniform samplerRECT samp0 : register(s0);\n");
|
||||
WRITE(p, "#define samp0 samp9\n");
|
||||
WRITE(p, "uniform sampler2DRect samp0;\n");
|
||||
}
|
||||
else if (ApiType & API_D3D9)
|
||||
{
|
||||
@@ -91,18 +104,27 @@ void WriteSwizzler(char*& p, u32 format, API_TYPE ApiType)
|
||||
}
|
||||
|
||||
|
||||
WRITE(p,"void main(\n");
|
||||
if(ApiType != API_D3D11)
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
WRITE(p," out float4 ocol0 : COLOR0,\n");
|
||||
WRITE(p, " out float4 ocol0;\n");
|
||||
WRITE(p, " in float2 uv0;\n");
|
||||
WRITE(p, "void main()\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p," out float4 ocol0 : SV_Target,\n");
|
||||
WRITE(p,"void main(\n");
|
||||
if (ApiType != API_D3D11)
|
||||
{
|
||||
WRITE(p," out float4 ocol0 : COLOR0,\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p," out float4 ocol0 : SV_Target,\n");
|
||||
}
|
||||
WRITE(p," in float2 uv0 : TEXCOORD0)\n");
|
||||
}
|
||||
|
||||
WRITE(p," in float2 uv0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
WRITE(p, "{\n"
|
||||
" float2 sampleUv;\n"
|
||||
" float2 uv1 = floor(uv0);\n");
|
||||
|
||||
@@ -113,7 +135,7 @@ void WriteSwizzler(char*& p, u32 format, API_TYPE ApiType)
|
||||
WRITE(p, " float yl = floor(uv1.y / %f);\n", blkH);
|
||||
WRITE(p, " float yb = yl * %f;\n", blkH);
|
||||
WRITE(p, " float yoff = uv1.y - yb;\n");
|
||||
WRITE(p, " float xp = uv1.x + (yoff * textureDims.x);\n");
|
||||
WRITE(p, " float xp = uv1.x + (yoff * " I_COLORS"[1].x);\n");
|
||||
WRITE(p, " float xel = floor(xp / %f);\n", blkW);
|
||||
WRITE(p, " float xb = floor(xel / %f);\n", blkH);
|
||||
WRITE(p, " float xoff = xel - (xb * %f);\n", blkH);
|
||||
@@ -121,34 +143,37 @@ void WriteSwizzler(char*& p, u32 format, API_TYPE ApiType)
|
||||
WRITE(p, " sampleUv.x = xib + (xb * %f);\n", blkW);
|
||||
WRITE(p, " sampleUv.y = yb + xoff;\n");
|
||||
|
||||
WRITE(p, " sampleUv = sampleUv * blkDims.xy;\n");
|
||||
WRITE(p, " sampleUv = sampleUv * " I_COLORS"[0].xy;\n");
|
||||
|
||||
if(ApiType == API_OPENGL)
|
||||
WRITE(p," sampleUv.y = textureDims.y - sampleUv.y;\n");
|
||||
if (ApiType == API_OPENGL)
|
||||
WRITE(p," sampleUv.y = " I_COLORS"[1].y - sampleUv.y;\n");
|
||||
|
||||
WRITE(p, " sampleUv = sampleUv + textureDims.zw;\n");
|
||||
WRITE(p, " sampleUv = sampleUv + " I_COLORS"[1].zw;\n");
|
||||
|
||||
if(ApiType != API_OPENGL)
|
||||
if (ApiType != API_OPENGL)
|
||||
{
|
||||
WRITE(p, " sampleUv = sampleUv + float2(0.0f,1.0f);\n");// still to determine the reason for this
|
||||
WRITE(p, " sampleUv = sampleUv / blkDims.zw;\n");
|
||||
WRITE(p, " sampleUv = sampleUv / " I_COLORS"[0].zw;\n");
|
||||
}
|
||||
}
|
||||
|
||||
// block dimensions : widthStride, heightStride
|
||||
// texture dims : width, height, x offset, y offset
|
||||
void Write32BitSwizzler(char*& p, u32 format, API_TYPE ApiType)
|
||||
{
|
||||
WRITE(p, "uniform float4 blkDims : register(c%d);\n", C_COLORMATRIX);
|
||||
WRITE(p, "uniform float4 textureDims : register(c%d);\n", C_COLORMATRIX + 1);
|
||||
{
|
||||
// [0] left, top, right, bottom of source rectangle within source texture
|
||||
// [1] width and height of destination texture in pixels
|
||||
// Two were merged for GLSL
|
||||
WRITE(p, "uniform float4 " I_COLORS"[2] %s;\n", WriteRegister(ApiType, "c", C_COLORS));
|
||||
|
||||
float blkW = (float)TexDecoder_GetBlockWidthInTexels(format);
|
||||
float blkW = (float)TexDecoder_GetBlockWidthInTexels(format);
|
||||
float blkH = (float)TexDecoder_GetBlockHeightInTexels(format);
|
||||
|
||||
// 32 bit textures (RGBA8 and Z24) are store in 2 cache line increments
|
||||
if(ApiType == API_OPENGL)
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
WRITE(p,"uniform samplerRECT samp0 : register(s0);\n");
|
||||
WRITE(p, "#define samp0 samp9\n");
|
||||
WRITE(p, "uniform sampler2DRect samp0;\n");
|
||||
}
|
||||
else if (ApiType & API_D3D9)
|
||||
{
|
||||
@@ -160,26 +185,35 @@ void Write32BitSwizzler(char*& p, u32 format, API_TYPE ApiType)
|
||||
WRITE(p, "Texture2D Tex0 : register(t0);\n");
|
||||
}
|
||||
|
||||
|
||||
WRITE(p,"void main(\n");
|
||||
if(ApiType != API_D3D11)
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
WRITE(p," out float4 ocol0 : COLOR0,\n");
|
||||
WRITE(p, " out float4 ocol0;\n");
|
||||
WRITE(p, " in float2 uv0;\n");
|
||||
WRITE(p, "void main()\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p," out float4 ocol0 : SV_Target,\n");
|
||||
WRITE(p,"void main(\n");
|
||||
if(ApiType != API_D3D11)
|
||||
{
|
||||
WRITE(p," out float4 ocol0 : COLOR0,\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p," out float4 ocol0 : SV_Target,\n");
|
||||
}
|
||||
WRITE(p," in float2 uv0 : TEXCOORD0)\n");
|
||||
}
|
||||
|
||||
WRITE(p," in float2 uv0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
|
||||
WRITE(p, "{\n"
|
||||
" float2 sampleUv;\n"
|
||||
" float2 uv1 = floor(uv0);\n");
|
||||
|
||||
WRITE(p, " float yl = floor(uv1.y / %f);\n", blkH);
|
||||
WRITE(p, " float yb = yl * %f;\n", blkH);
|
||||
WRITE(p, " float yoff = uv1.y - yb;\n");
|
||||
WRITE(p, " float xp = uv1.x + (yoff * textureDims.x);\n");
|
||||
WRITE(p, " float xp = uv1.x + (yoff * " I_COLORS"[1].x);\n");
|
||||
WRITE(p, " float xel = floor(xp / 2);\n");
|
||||
WRITE(p, " float xb = floor(xel / %f);\n", blkH);
|
||||
WRITE(p, " float xoff = xel - (xb * %f);\n", blkH);
|
||||
@@ -188,21 +222,20 @@ void Write32BitSwizzler(char*& p, u32 format, API_TYPE ApiType)
|
||||
WRITE(p, " float xl = floor(x2 / %f);\n", blkW);
|
||||
WRITE(p, " float xib = x2 - (xl * %f);\n", blkW);
|
||||
WRITE(p, " float halfxb = floor(xb / 2);\n");
|
||||
|
||||
|
||||
WRITE(p, " sampleUv.x = xib + (halfxb * %f);\n", blkW);
|
||||
WRITE(p, " sampleUv.y = yb + xoff;\n");
|
||||
WRITE(p, " sampleUv = sampleUv * blkDims.xy;\n");
|
||||
WRITE(p, " sampleUv = sampleUv * " I_COLORS"[0].xy;\n");
|
||||
|
||||
if(ApiType == API_OPENGL)
|
||||
WRITE(p," sampleUv.y = textureDims.y - sampleUv.y;\n");
|
||||
if (ApiType == API_OPENGL)
|
||||
WRITE(p," sampleUv.y = " I_COLORS"[1].y - sampleUv.y;\n");
|
||||
|
||||
WRITE(p, " sampleUv = sampleUv + textureDims.zw;\n");
|
||||
WRITE(p, " sampleUv = sampleUv + " I_COLORS"[1].zw;\n");
|
||||
|
||||
if(ApiType != API_OPENGL)
|
||||
if (ApiType != API_OPENGL)
|
||||
{
|
||||
WRITE(p, " sampleUv = sampleUv + float2(0.0f,1.0f);\n");// still to determine the reason for this
|
||||
WRITE(p, " sampleUv = sampleUv / blkDims.zw;\n");
|
||||
WRITE(p, " sampleUv = sampleUv / " I_COLORS"[0].zw;\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,14 +247,14 @@ void WriteSampleColor(char*& p, const char* colorComp, const char* dest, API_TYP
|
||||
else if (ApiType == API_D3D11)
|
||||
texSampleOpName = "tex0.Sample";
|
||||
else
|
||||
texSampleOpName = "texRECT";
|
||||
texSampleOpName = "texture2DRect";
|
||||
|
||||
// the increment of sampleUv.x is delayed, so we perform it here. see WriteIncrementSampleX.
|
||||
const char* texSampleIncrementUnit;
|
||||
if(ApiType != API_OPENGL)
|
||||
texSampleIncrementUnit = "blkDims.x / blkDims.z";
|
||||
if (ApiType != API_OPENGL)
|
||||
texSampleIncrementUnit = I_COLORS"[0].x / " I_COLORS"[0].z";
|
||||
else
|
||||
texSampleIncrementUnit = "blkDims.x";
|
||||
texSampleIncrementUnit = I_COLORS"[0].x";
|
||||
|
||||
WRITE(p, " %s = %s(samp0, sampleUv + float2(%d * (%s), 0)).%s;\n",
|
||||
dest, texSampleOpName, s_incrementSampleXCount, texSampleIncrementUnit, colorComp);
|
||||
@@ -229,7 +262,7 @@ void WriteSampleColor(char*& p, const char* colorComp, const char* dest, API_TYP
|
||||
|
||||
void WriteColorToIntensity(char*& p, const char* src, const char* dest)
|
||||
{
|
||||
if(!IntensityConstantAdded)
|
||||
if (!IntensityConstantAdded)
|
||||
{
|
||||
WRITE(p, " float4 IntensityConst = float4(0.257f,0.504f,0.098f,0.0625f);\n");
|
||||
IntensityConstantAdded = true;
|
||||
@@ -263,7 +296,7 @@ void WriteToBitDepth(char*& p, u8 depth, const char* src, const char* dest)
|
||||
WRITE(p, " %s = floor(%s * %ff);\n", dest, src, result);
|
||||
}
|
||||
|
||||
void WriteEncoderEnd(char* p)
|
||||
void WriteEncoderEnd(char* p, API_TYPE ApiType)
|
||||
{
|
||||
WRITE(p, "}\n");
|
||||
IntensityConstantAdded = false;
|
||||
@@ -272,65 +305,65 @@ void WriteEncoderEnd(char* p)
|
||||
|
||||
void WriteI8Encoder(char* p, API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_TF_I8,ApiType);
|
||||
WriteSwizzler(p, GX_TF_I8, ApiType);
|
||||
WRITE(p, " float3 texSample;\n");
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "ocol0.b");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "ocol0.g");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "ocol0.r");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "ocol0.a");
|
||||
|
||||
WRITE(p, " ocol0.rgba += IntensityConst.aaaa;\n"); // see WriteColorToIntensity
|
||||
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteI4Encoder(char* p, API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_TF_I4,ApiType);
|
||||
WriteSwizzler(p, GX_TF_I4, ApiType);
|
||||
WRITE(p, " float3 texSample;\n");
|
||||
WRITE(p, " float4 color0;\n");
|
||||
WRITE(p, " float4 color1;\n");
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "color0.b");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "color1.b");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "color0.g");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "color1.g");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "color0.r");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "color1.r");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "color0.a");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgb", "texSample", ApiType);
|
||||
WriteColorToIntensity(p, "texSample", "color1.a");
|
||||
|
||||
WRITE(p, " color0.rgba += IntensityConst.aaaa;\n");
|
||||
@@ -340,51 +373,51 @@ void WriteI4Encoder(char* p, API_TYPE ApiType)
|
||||
WriteToBitDepth(p, 4, "color1", "color1");
|
||||
|
||||
WRITE(p, " ocol0 = (color0 * 16.0f + color1) / 255.0f;\n");
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteIA8Encoder(char* p,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_TF_IA8,ApiType);
|
||||
WriteSwizzler(p, GX_TF_IA8, ApiType);
|
||||
WRITE(p, " float4 texSample;\n");
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
WRITE(p, " ocol0.b = texSample.a;\n");
|
||||
WriteColorToIntensity(p, "texSample", "ocol0.g");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
WRITE(p, " ocol0.r = texSample.a;\n");
|
||||
WriteColorToIntensity(p, "texSample", "ocol0.a");
|
||||
|
||||
WRITE(p, " ocol0.ga += IntensityConst.aa;\n");
|
||||
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteIA4Encoder(char* p,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_TF_IA4,ApiType);
|
||||
WriteSwizzler(p, GX_TF_IA4, ApiType);
|
||||
WRITE(p, " float4 texSample;\n");
|
||||
WRITE(p, " float4 color0;\n");
|
||||
WRITE(p, " float4 color1;\n");
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
WRITE(p, " color0.b = texSample.a;\n");
|
||||
WriteColorToIntensity(p, "texSample", "color1.b");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
WRITE(p, " color0.g = texSample.a;\n");
|
||||
WriteColorToIntensity(p, "texSample", "color1.g");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
WRITE(p, " color0.r = texSample.a;\n");
|
||||
WriteColorToIntensity(p, "texSample", "color1.r");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
WRITE(p, " color0.a = texSample.a;\n");
|
||||
WriteColorToIntensity(p, "texSample", "color1.a");
|
||||
|
||||
@@ -394,20 +427,19 @@ void WriteIA4Encoder(char* p,API_TYPE ApiType)
|
||||
WriteToBitDepth(p, 4, "color1", "color1");
|
||||
|
||||
WRITE(p, " ocol0 = (color0 * 16.0f + color1) / 255.0f;\n");
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteRGB565Encoder(char* p,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_TF_RGB565,ApiType);
|
||||
WriteSwizzler(p, GX_TF_RGB565, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgb", "float3 texSample0",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, "rgb", "float3 texSample1",ApiType);
|
||||
|
||||
WRITE(p, " float2 texRs = {texSample0.r, texSample1.r};\n");
|
||||
WRITE(p, " float2 texGs = {texSample0.g, texSample1.g};\n");
|
||||
WRITE(p, " float2 texBs = {texSample0.b, texSample1.b};\n");
|
||||
WriteSampleColor(p, "rgb", "float3 texSample0", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
WriteSampleColor(p, "rgb", "float3 texSample1", ApiType);
|
||||
WRITE(p, " float2 texRs = float2(texSample0.r, texSample1.r);\n");
|
||||
WRITE(p, " float2 texGs = float2(texSample0.g, texSample1.g);\n");
|
||||
WRITE(p, " float2 texBs = float2(texSample0.b, texSample1.b);\n");
|
||||
|
||||
WriteToBitDepth(p, 6, "texGs", "float2 gInt");
|
||||
WRITE(p, " float2 gUpper = floor(gInt / 8.0f);\n");
|
||||
@@ -419,19 +451,19 @@ void WriteRGB565Encoder(char* p,API_TYPE ApiType)
|
||||
WRITE(p, " ocol0.ga = ocol0.ga + gLower * 32.0f;\n");
|
||||
|
||||
WRITE(p, " ocol0 = ocol0 / 255.0f;\n");
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteRGB5A3Encoder(char* p,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_TF_RGB5A3,ApiType);
|
||||
WriteSwizzler(p, GX_TF_RGB5A3, ApiType);
|
||||
|
||||
WRITE(p, " float4 texSample;\n");
|
||||
WRITE(p, " float color0;\n");
|
||||
WRITE(p, " float gUpper;\n");
|
||||
WRITE(p, " float gLower;\n");
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
|
||||
// 0.8784 = 224 / 255 which is the maximum alpha value that can be represented in 3 bits
|
||||
WRITE(p, "if(texSample.a > 0.878f) {\n");
|
||||
@@ -458,9 +490,9 @@ void WriteRGB5A3Encoder(char* p,API_TYPE ApiType)
|
||||
WRITE(p, "}\n");
|
||||
|
||||
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
|
||||
WRITE(p, "if(texSample.a > 0.878f) {\n");
|
||||
|
||||
@@ -486,38 +518,38 @@ void WriteRGB5A3Encoder(char* p,API_TYPE ApiType)
|
||||
WRITE(p, "}\n");
|
||||
|
||||
WRITE(p, " ocol0 = ocol0 / 255.0f;\n");
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteRGBA4443Encoder(char* p,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_TF_RGB5A3,ApiType);
|
||||
WriteSwizzler(p, GX_TF_RGB5A3, ApiType);
|
||||
|
||||
WRITE(p, " float4 texSample;\n");
|
||||
WRITE(p, " float4 color0;\n");
|
||||
WRITE(p, " float4 color1;\n");
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
WriteToBitDepth(p, 3, "texSample.a", "color0.b");
|
||||
WriteToBitDepth(p, 4, "texSample.r", "color1.b");
|
||||
WriteToBitDepth(p, 4, "texSample.g", "color0.g");
|
||||
WriteToBitDepth(p, 4, "texSample.b", "color1.g");
|
||||
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
WriteToBitDepth(p, 3, "texSample.a", "color0.r");
|
||||
WriteToBitDepth(p, 4, "texSample.r", "color1.r");
|
||||
WriteToBitDepth(p, 4, "texSample.g", "color0.a");
|
||||
WriteToBitDepth(p, 4, "texSample.b", "color1.a");
|
||||
|
||||
WRITE(p, " ocol0 = (color0 * 16.0f + color1) / 255.0f;\n");
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteRGBA8Encoder(char* p,API_TYPE ApiType)
|
||||
{
|
||||
Write32BitSwizzler(p, GX_TF_RGBA8,ApiType);
|
||||
Write32BitSwizzler(p, GX_TF_RGBA8, ApiType);
|
||||
|
||||
WRITE(p, " float cl1 = xb - (halfxb * 2);\n");
|
||||
WRITE(p, " float cl0 = 1.0f - cl1;\n");
|
||||
@@ -526,15 +558,15 @@ void WriteRGBA8Encoder(char* p,API_TYPE ApiType)
|
||||
WRITE(p, " float4 color0;\n");
|
||||
WRITE(p, " float4 color1;\n");
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
WRITE(p, " color0.b = texSample.a;\n");
|
||||
WRITE(p, " color0.g = texSample.r;\n");
|
||||
WRITE(p, " color1.b = texSample.g;\n");
|
||||
WRITE(p, " color1.g = texSample.b;\n");
|
||||
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "rgba", "texSample",ApiType);
|
||||
WriteSampleColor(p, "rgba", "texSample", ApiType);
|
||||
WRITE(p, " color0.r = texSample.a;\n");
|
||||
WRITE(p, " color0.a = texSample.r;\n");
|
||||
WRITE(p, " color1.r = texSample.g;\n");
|
||||
@@ -542,86 +574,86 @@ void WriteRGBA8Encoder(char* p,API_TYPE ApiType)
|
||||
|
||||
WRITE(p, " ocol0 = (cl0 * color0) + (cl1 * color1);\n");
|
||||
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteC4Encoder(char* p, const char* comp,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_CTF_R4,ApiType);
|
||||
WriteSwizzler(p, GX_CTF_R4, ApiType);
|
||||
WRITE(p, " float4 color0;\n");
|
||||
WRITE(p, " float4 color1;\n");
|
||||
|
||||
WriteSampleColor(p, comp, "color0.b",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "color0.b", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "color1.b",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "color1.b", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "color0.g",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "color0.g", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "color1.g",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "color1.g", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "color0.r",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "color0.r", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "color1.r",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "color1.r", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "color0.a",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "color0.a", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "color1.a",ApiType);
|
||||
WriteSampleColor(p, comp, "color1.a", ApiType);
|
||||
|
||||
WriteToBitDepth(p, 4, "color0", "color0");
|
||||
WriteToBitDepth(p, 4, "color1", "color1");
|
||||
|
||||
WRITE(p, " ocol0 = (color0 * 16.0f + color1) / 255.0f;\n");
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteC8Encoder(char* p, const char* comp,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_CTF_R8,ApiType);
|
||||
WriteSwizzler(p, GX_CTF_R8, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "ocol0.b",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "ocol0.b", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "ocol0.g",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "ocol0.g", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "ocol0.r",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "ocol0.r", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "ocol0.a",ApiType);
|
||||
WriteSampleColor(p, comp, "ocol0.a", ApiType);
|
||||
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteCC4Encoder(char* p, const char* comp,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_CTF_RA4,ApiType);
|
||||
WriteSwizzler(p, GX_CTF_RA4, ApiType);
|
||||
WRITE(p, " float2 texSample;\n");
|
||||
WRITE(p, " float4 color0;\n");
|
||||
WRITE(p, " float4 color1;\n");
|
||||
|
||||
WriteSampleColor(p, comp, "texSample",ApiType);
|
||||
WriteSampleColor(p, comp, "texSample", ApiType);
|
||||
WRITE(p, " color0.b = texSample.x;\n");
|
||||
WRITE(p, " color1.b = texSample.y;\n");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "texSample",ApiType);
|
||||
WriteSampleColor(p, comp, "texSample", ApiType);
|
||||
WRITE(p, " color0.g = texSample.x;\n");
|
||||
WRITE(p, " color1.g = texSample.y;\n");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "texSample",ApiType);
|
||||
WriteSampleColor(p, comp, "texSample", ApiType);
|
||||
WRITE(p, " color0.r = texSample.x;\n");
|
||||
WRITE(p, " color1.r = texSample.y;\n");
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "texSample",ApiType);
|
||||
WriteSampleColor(p, comp, "texSample", ApiType);
|
||||
WRITE(p, " color0.a = texSample.x;\n");
|
||||
WRITE(p, " color1.a = texSample.y;\n");
|
||||
|
||||
@@ -629,55 +661,55 @@ void WriteCC4Encoder(char* p, const char* comp,API_TYPE ApiType)
|
||||
WriteToBitDepth(p, 4, "color1", "color1");
|
||||
|
||||
WRITE(p, " ocol0 = (color0 * 16.0f + color1) / 255.0f;\n");
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteCC8Encoder(char* p, const char* comp, API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_CTF_RA8,ApiType);
|
||||
WriteSwizzler(p, GX_CTF_RA8, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "ocol0.bg",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, comp, "ocol0.bg", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, comp, "ocol0.ra",ApiType);
|
||||
WriteSampleColor(p, comp, "ocol0.ra", ApiType);
|
||||
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteZ8Encoder(char* p, const char* multiplier,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_CTF_Z8M,ApiType);
|
||||
WriteSwizzler(p, GX_CTF_Z8M, ApiType);
|
||||
|
||||
WRITE(p, " float depth;\n");
|
||||
|
||||
WriteSampleColor(p, "b", "depth",ApiType);
|
||||
WriteSampleColor(p, "b", "depth", ApiType);
|
||||
WRITE(p, "ocol0.b = frac(depth * %s);\n", multiplier);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "b", "depth",ApiType);
|
||||
WriteSampleColor(p, "b", "depth", ApiType);
|
||||
WRITE(p, "ocol0.g = frac(depth * %s);\n", multiplier);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "b", "depth",ApiType);
|
||||
WriteSampleColor(p, "b", "depth", ApiType);
|
||||
WRITE(p, "ocol0.r = frac(depth * %s);\n", multiplier);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "b", "depth",ApiType);
|
||||
WriteSampleColor(p, "b", "depth", ApiType);
|
||||
WRITE(p, "ocol0.a = frac(depth * %s);\n", multiplier);
|
||||
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteZ16Encoder(char* p,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_TF_Z16,ApiType);
|
||||
WriteSwizzler(p, GX_TF_Z16, ApiType);
|
||||
|
||||
WRITE(p, " float depth;\n");
|
||||
WRITE(p, " float3 expanded;\n");
|
||||
|
||||
// byte order is reversed
|
||||
|
||||
WriteSampleColor(p, "b", "depth",ApiType);
|
||||
WriteSampleColor(p, "b", "depth", ApiType);
|
||||
|
||||
WRITE(p, " depth *= 16777215.0f;\n");
|
||||
WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
|
||||
@@ -687,9 +719,9 @@ void WriteZ16Encoder(char* p,API_TYPE ApiType)
|
||||
WRITE(p, " ocol0.b = expanded.g / 255;\n");
|
||||
WRITE(p, " ocol0.g = expanded.r / 255;\n");
|
||||
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "b", "depth",ApiType);
|
||||
WriteSampleColor(p, "b", "depth", ApiType);
|
||||
|
||||
WRITE(p, " depth *= 16777215.0f;\n");
|
||||
WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
|
||||
@@ -699,19 +731,19 @@ void WriteZ16Encoder(char* p,API_TYPE ApiType)
|
||||
WRITE(p, " ocol0.r = expanded.g / 255;\n");
|
||||
WRITE(p, " ocol0.a = expanded.r / 255;\n");
|
||||
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteZ16LEncoder(char* p,API_TYPE ApiType)
|
||||
{
|
||||
WriteSwizzler(p, GX_CTF_Z16L,ApiType);
|
||||
WriteSwizzler(p, GX_CTF_Z16L, ApiType);
|
||||
|
||||
WRITE(p, " float depth;\n");
|
||||
WRITE(p, " float3 expanded;\n");
|
||||
|
||||
// byte order is reversed
|
||||
|
||||
WriteSampleColor(p, "b", "depth",ApiType);
|
||||
WriteSampleColor(p, "b", "depth", ApiType);
|
||||
|
||||
WRITE(p, " depth *= 16777215.0f;\n");
|
||||
WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
|
||||
@@ -723,9 +755,9 @@ void WriteZ16LEncoder(char* p,API_TYPE ApiType)
|
||||
WRITE(p, " ocol0.b = expanded.b / 255;\n");
|
||||
WRITE(p, " ocol0.g = expanded.g / 255;\n");
|
||||
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
|
||||
WriteSampleColor(p, "b", "depth",ApiType);
|
||||
WriteSampleColor(p, "b", "depth", ApiType);
|
||||
|
||||
WRITE(p, " depth *= 16777215.0f;\n");
|
||||
WRITE(p, " expanded.r = floor(depth / (256 * 256));\n");
|
||||
@@ -737,12 +769,12 @@ void WriteZ16LEncoder(char* p,API_TYPE ApiType)
|
||||
WRITE(p, " ocol0.r = expanded.b;\n");
|
||||
WRITE(p, " ocol0.a = expanded.g;\n");
|
||||
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
void WriteZ24Encoder(char* p, API_TYPE ApiType)
|
||||
{
|
||||
Write32BitSwizzler(p, GX_TF_Z24X8,ApiType);
|
||||
Write32BitSwizzler(p, GX_TF_Z24X8, ApiType);
|
||||
|
||||
WRITE(p, " float cl = xb - (halfxb * 2);\n");
|
||||
|
||||
@@ -751,19 +783,19 @@ void WriteZ24Encoder(char* p, API_TYPE ApiType)
|
||||
WRITE(p, " float3 expanded0;\n");
|
||||
WRITE(p, " float3 expanded1;\n");
|
||||
|
||||
WriteSampleColor(p, "b", "depth0",ApiType);
|
||||
WriteIncrementSampleX(p,ApiType);
|
||||
WriteSampleColor(p, "b", "depth1",ApiType);
|
||||
WriteSampleColor(p, "b", "depth0", ApiType);
|
||||
WriteIncrementSampleX(p, ApiType);
|
||||
WriteSampleColor(p, "b", "depth1", ApiType);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
WRITE(p, " depth%i *= 16777215.0f;\n", i);
|
||||
WRITE(p, " depth%i *= 16777215.0f;\n", i);
|
||||
|
||||
WRITE(p, " expanded%i.r = floor(depth%i / (256 * 256));\n", i, i);
|
||||
WRITE(p, " depth%i -= expanded%i.r * 256 * 256;\n", i, i);
|
||||
WRITE(p, " expanded%i.g = floor(depth%i / 256);\n", i, i);
|
||||
WRITE(p, " depth%i -= expanded%i.g * 256;\n", i, i);
|
||||
WRITE(p, " expanded%i.b = depth%i;\n", i, i);
|
||||
WRITE(p, " expanded%i.r = floor(depth%i / (256 * 256));\n", i, i);
|
||||
WRITE(p, " depth%i -= expanded%i.r * 256 * 256;\n", i, i);
|
||||
WRITE(p, " expanded%i.g = floor(depth%i / 256);\n", i, i);
|
||||
WRITE(p, " depth%i -= expanded%i.g * 256;\n", i, i);
|
||||
WRITE(p, " expanded%i.b = depth%i;\n", i, i);
|
||||
}
|
||||
|
||||
WRITE(p, " if(cl > 0.5f) {\n");
|
||||
@@ -780,7 +812,7 @@ void WriteZ24Encoder(char* p, API_TYPE ApiType)
|
||||
WRITE(p, " ocol0.a = expanded1.r / 255;\n");
|
||||
WRITE(p, " }\n");
|
||||
|
||||
WriteEncoderEnd(p);
|
||||
WriteEncoderEnd(p, ApiType);
|
||||
}
|
||||
|
||||
const char *GenerateEncodingShader(u32 format,API_TYPE ApiType)
|
||||
@@ -790,76 +822,76 @@ const char *GenerateEncodingShader(u32 format,API_TYPE ApiType)
|
||||
|
||||
char *p = text;
|
||||
|
||||
switch(format)
|
||||
switch (format)
|
||||
{
|
||||
case GX_TF_I4:
|
||||
WriteI4Encoder(p,ApiType);
|
||||
WriteI4Encoder(p, ApiType);
|
||||
break;
|
||||
case GX_TF_I8:
|
||||
WriteI8Encoder(p,ApiType);
|
||||
WriteI8Encoder(p, ApiType);
|
||||
break;
|
||||
case GX_TF_IA4:
|
||||
WriteIA4Encoder(p,ApiType);
|
||||
WriteIA4Encoder(p, ApiType);
|
||||
break;
|
||||
case GX_TF_IA8:
|
||||
WriteIA8Encoder(p,ApiType);
|
||||
WriteIA8Encoder(p, ApiType);
|
||||
break;
|
||||
case GX_TF_RGB565:
|
||||
WriteRGB565Encoder(p,ApiType);
|
||||
WriteRGB565Encoder(p, ApiType);
|
||||
break;
|
||||
case GX_TF_RGB5A3:
|
||||
WriteRGB5A3Encoder(p,ApiType);
|
||||
WriteRGB5A3Encoder(p, ApiType);
|
||||
break;
|
||||
case GX_TF_RGBA8:
|
||||
WriteRGBA8Encoder(p,ApiType);
|
||||
WriteRGBA8Encoder(p, ApiType);
|
||||
break;
|
||||
case GX_CTF_R4:
|
||||
WriteC4Encoder(p, "r",ApiType);
|
||||
WriteC4Encoder(p, "r", ApiType);
|
||||
break;
|
||||
case GX_CTF_RA4:
|
||||
WriteCC4Encoder(p, "ar",ApiType);
|
||||
WriteCC4Encoder(p, "ar", ApiType);
|
||||
break;
|
||||
case GX_CTF_RA8:
|
||||
WriteCC8Encoder(p, "ar",ApiType);
|
||||
WriteCC8Encoder(p, "ar", ApiType);
|
||||
break;
|
||||
case GX_CTF_A8:
|
||||
WriteC8Encoder(p, "a",ApiType);
|
||||
WriteC8Encoder(p, "a", ApiType);
|
||||
break;
|
||||
case GX_CTF_R8:
|
||||
WriteC8Encoder(p, "r",ApiType);
|
||||
WriteC8Encoder(p, "r", ApiType);
|
||||
break;
|
||||
case GX_CTF_G8:
|
||||
WriteC8Encoder(p, "g",ApiType);
|
||||
WriteC8Encoder(p, "g", ApiType);
|
||||
break;
|
||||
case GX_CTF_B8:
|
||||
WriteC8Encoder(p, "b",ApiType);
|
||||
WriteC8Encoder(p, "b", ApiType);
|
||||
break;
|
||||
case GX_CTF_RG8:
|
||||
WriteCC8Encoder(p, "rg",ApiType);
|
||||
WriteCC8Encoder(p, "rg", ApiType);
|
||||
break;
|
||||
case GX_CTF_GB8:
|
||||
WriteCC8Encoder(p, "gb",ApiType);
|
||||
WriteCC8Encoder(p, "gb", ApiType);
|
||||
break;
|
||||
case GX_TF_Z8:
|
||||
WriteC8Encoder(p, "b",ApiType);
|
||||
WriteC8Encoder(p, "b", ApiType);
|
||||
break;
|
||||
case GX_TF_Z16:
|
||||
WriteZ16Encoder(p,ApiType);
|
||||
WriteZ16Encoder(p, ApiType);
|
||||
break;
|
||||
case GX_TF_Z24X8:
|
||||
WriteZ24Encoder(p,ApiType);
|
||||
WriteZ24Encoder(p, ApiType);
|
||||
break;
|
||||
case GX_CTF_Z4:
|
||||
WriteC4Encoder(p, "b",ApiType);
|
||||
WriteC4Encoder(p, "b", ApiType);
|
||||
break;
|
||||
case GX_CTF_Z8M:
|
||||
WriteZ8Encoder(p, "256.0f",ApiType);
|
||||
WriteZ8Encoder(p, "256.0f", ApiType);
|
||||
break;
|
||||
case GX_CTF_Z8L:
|
||||
WriteZ8Encoder(p, "65536.0f" ,ApiType);
|
||||
WriteZ8Encoder(p, "65536.0f" , ApiType);
|
||||
break;
|
||||
case GX_CTF_Z16L:
|
||||
WriteZ16LEncoder(p,ApiType);
|
||||
WriteZ16LEncoder(p, ApiType);
|
||||
break;
|
||||
default:
|
||||
PanicAlert("Unknown texture copy format: 0x%x\n", format);
|
||||
|
||||
@@ -44,8 +44,10 @@
|
||||
#include "XFMemory.h"
|
||||
extern float GC_ALIGNED16(g_fProjectionMatrix[16]);
|
||||
#ifndef _M_GENERIC
|
||||
#ifndef __APPLE__
|
||||
#define USE_JIT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define COMPILED_CODE_SIZE 4096
|
||||
|
||||
|
||||
@@ -131,38 +131,43 @@ static char text[16384];
|
||||
|
||||
#define WRITE p+=sprintf
|
||||
|
||||
char* GenerateVSOutputStruct(char* p, u32 components, API_TYPE api_type)
|
||||
char* GenerateVSOutputStruct(char* p, u32 components, API_TYPE ApiType)
|
||||
{
|
||||
// GLSL makes this ugly
|
||||
// TODO: Make pretty
|
||||
WRITE(p, "struct VS_OUTPUT {\n");
|
||||
WRITE(p, " float4 pos : POSITION;\n");
|
||||
WRITE(p, " float4 colors_0 : COLOR0;\n");
|
||||
WRITE(p, " float4 colors_1 : COLOR1;\n");
|
||||
WRITE(p, " float4 pos %s POSITION;\n", ApiType == API_OPENGL ? ";//" : ":");
|
||||
WRITE(p, " float4 colors_0 %s COLOR0;\n", ApiType == API_OPENGL ? ";//" : ":");
|
||||
WRITE(p, " float4 colors_1 %s COLOR1;\n", ApiType == API_OPENGL ? ";//" : ":");
|
||||
|
||||
if (xfregs.numTexGen.numTexGens < 7) {
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
WRITE(p, " float3 tex%d : TEXCOORD%d;\n", i, i);
|
||||
WRITE(p, " float4 clipPos : TEXCOORD%d;\n", xfregs.numTexGen.numTexGens);
|
||||
WRITE(p, " float3 tex%d %s TEXCOORD%d;\n", i, ApiType == API_OPENGL ? ";//" : ":", i);
|
||||
WRITE(p, " float4 clipPos %s TEXCOORD%d;\n", ApiType == API_OPENGL ? ";//" : ":", xfregs.numTexGen.numTexGens);
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
WRITE(p, " float4 Normal : TEXCOORD%d;\n", xfregs.numTexGen.numTexGens + 1);
|
||||
WRITE(p, " float4 Normal %s TEXCOORD%d;\n", ApiType == API_OPENGL ? ";//" : ":", xfregs.numTexGen.numTexGens + 1);
|
||||
} else {
|
||||
// clip position is in w of first 4 texcoords
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
WRITE(p, " float4 tex%d : TEXCOORD%d;\n", i, i);
|
||||
WRITE(p, " float4 tex%d %s TEXCOORD%d;\n", i, ApiType == API_OPENGL? ";//" : ":", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
WRITE(p, " float%d tex%d : TEXCOORD%d;\n", i < 4 ? 4 : 3 , i, i);
|
||||
WRITE(p, " float%d tex%d %s TEXCOORD%d;\n", i < 4 ? 4 : 3 , i, ApiType == API_OPENGL ? ";//" : ":", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
WRITE(p, "};\n");
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
|
||||
extern const char* WriteRegister(API_TYPE ApiType, const char *prefix, const u32 num);
|
||||
extern const char *WriteLocation(API_TYPE ApiType);
|
||||
|
||||
const char *GenerateVertexShaderCode(u32 components, API_TYPE ApiType)
|
||||
{
|
||||
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
|
||||
text[sizeof(text) - 1] = 0x7C; // canary
|
||||
@@ -170,7 +175,7 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
|
||||
_assert_(bpmem.genMode.numtexgens == xfregs.numTexGen.numTexGens);
|
||||
_assert_(bpmem.genMode.numcolchans == xfregs.numChan.numColorChans);
|
||||
|
||||
bool is_d3d = (api_type & API_D3D9 || api_type == API_D3D11);
|
||||
bool is_d3d = (ApiType & API_D3D9 || ApiType == API_D3D11);
|
||||
u32 lightMask = 0;
|
||||
if (xfregs.numChan.numColorChans > 0)
|
||||
lightMask |= xfregs.color[0].GetFullLightMask() | xfregs.alpha[0].GetFullLightMask();
|
||||
@@ -179,91 +184,134 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
|
||||
|
||||
char *p = text;
|
||||
WRITE(p, "//Vertex Shader: comp:%x, \n", components);
|
||||
WRITE(p, "typedef struct { float4 T0, T1, T2; float4 N0, N1, N2; } s_" I_POSNORMALMATRIX";\n"
|
||||
"typedef struct { float4 t; } FLT4;\n"
|
||||
"typedef struct { FLT4 T[24]; } s_" I_TEXMATRICES";\n"
|
||||
"typedef struct { FLT4 T[64]; } s_" I_TRANSFORMMATRICES";\n"
|
||||
"typedef struct { FLT4 T[32]; } s_" I_NORMALMATRICES";\n"
|
||||
"typedef struct { FLT4 T[64]; } s_" I_POSTTRANSFORMMATRICES";\n"
|
||||
"typedef struct { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; } Light;\n"
|
||||
"typedef struct { Light lights[8]; } s_" I_LIGHTS";\n"
|
||||
"typedef struct { float4 C0, C1, C2, C3; } s_" I_MATERIALS";\n"
|
||||
"typedef struct { float4 T0, T1, T2, T3; } s_" I_PROJECTION";\n"
|
||||
);
|
||||
|
||||
p = GenerateVSOutputStruct(p, components, api_type);
|
||||
|
||||
// uniforms
|
||||
|
||||
WRITE(p, "uniform s_" I_TRANSFORMMATRICES" " I_TRANSFORMMATRICES" : register(c%d);\n", C_TRANSFORMMATRICES);
|
||||
WRITE(p, "uniform s_" I_TEXMATRICES" " I_TEXMATRICES" : register(c%d);\n", C_TEXMATRICES); // also using tex matrices
|
||||
WRITE(p, "uniform s_" I_NORMALMATRICES" " I_NORMALMATRICES" : register(c%d);\n", C_NORMALMATRICES);
|
||||
WRITE(p, "uniform s_" I_POSNORMALMATRIX" " I_POSNORMALMATRIX" : register(c%d);\n", C_POSNORMALMATRIX);
|
||||
WRITE(p, "uniform s_" I_POSTTRANSFORMMATRICES" " I_POSTTRANSFORMMATRICES" : register(c%d);\n", C_POSTTRANSFORMMATRICES);
|
||||
WRITE(p, "uniform s_" I_LIGHTS" " I_LIGHTS" : register(c%d);\n", C_LIGHTS);
|
||||
WRITE(p, "uniform s_" I_MATERIALS" " I_MATERIALS" : register(c%d);\n", C_MATERIALS);
|
||||
WRITE(p, "uniform s_" I_PROJECTION" " I_PROJECTION" : register(c%d);\n", C_PROJECTION);
|
||||
WRITE(p, "uniform float4 " I_DEPTHPARAMS" : register(c%d);\n", C_DEPTHPARAMS);
|
||||
|
||||
WRITE(p, "VS_OUTPUT main(\n");
|
||||
|
||||
// inputs
|
||||
if (components & VB_HAS_NRM0)
|
||||
WRITE(p, " float3 rawnorm0 : NORMAL0,\n");
|
||||
if (components & VB_HAS_NRM1) {
|
||||
if (is_d3d)
|
||||
WRITE(p, " float3 rawnorm1 : NORMAL1,\n");
|
||||
else
|
||||
WRITE(p, " float3 rawnorm1 : ATTR%d,\n", SHADER_NORM1_ATTRIB);
|
||||
}
|
||||
if (components & VB_HAS_NRM2) {
|
||||
if (is_d3d)
|
||||
WRITE(p, " float3 rawnorm2 : NORMAL2,\n");
|
||||
else
|
||||
WRITE(p, " float3 rawnorm2 : ATTR%d,\n", SHADER_NORM2_ATTRIB);
|
||||
}
|
||||
if (components & VB_HAS_COL0)
|
||||
WRITE(p, " float4 color0 : COLOR0,\n");
|
||||
if (components & VB_HAS_COL1)
|
||||
WRITE(p, " float4 color1 : COLOR1,\n");
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
|
||||
if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
|
||||
WRITE(p, " float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i);
|
||||
}
|
||||
if (components & VB_HAS_POSMTXIDX) {
|
||||
if (is_d3d)
|
||||
// uniforms
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
WRITE(p, "layout(std140) uniform VSBlock {\n");
|
||||
|
||||
WRITE(p, "%sfloat4 " I_POSNORMALMATRIX"[6] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_POSNORMALMATRIX));
|
||||
WRITE(p, "%sfloat4 " I_PROJECTION"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_PROJECTION));
|
||||
WRITE(p, "%sfloat4 " I_MATERIALS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_MATERIALS));
|
||||
WRITE(p, "%sfloat4 " I_LIGHTS"[40] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_LIGHTS));
|
||||
WRITE(p, "%sfloat4 " I_TEXMATRICES"[24] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_TEXMATRICES)); // also using tex matrices
|
||||
WRITE(p, "%sfloat4 " I_TRANSFORMMATRICES"[64] %s;\n", WriteLocation(ApiType),WriteRegister(ApiType, "c", C_TRANSFORMMATRICES));
|
||||
WRITE(p, "%sfloat4 " I_NORMALMATRICES"[32] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_NORMALMATRICES));
|
||||
WRITE(p, "%sfloat4 " I_POSTTRANSFORMMATRICES"[64] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_POSTTRANSFORMMATRICES));
|
||||
WRITE(p, "%sfloat4 " I_DEPTHPARAMS" %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_DEPTHPARAMS));
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
WRITE(p, "};\n");
|
||||
|
||||
|
||||
p = GenerateVSOutputStruct(p, components, ApiType);
|
||||
|
||||
if(ApiType == API_OPENGL)
|
||||
{
|
||||
WRITE(p, "ATTRIN float4 rawpos; // ATTR%d,\n", SHADER_POSITION_ATTRIB);
|
||||
if (components & VB_HAS_POSMTXIDX)
|
||||
WRITE(p, "ATTRIN int posmtx; // ATTR%d,\n", SHADER_POSMTX_ATTRIB);
|
||||
if (components & VB_HAS_NRM0)
|
||||
WRITE(p, "ATTRIN float3 rawnorm0; // ATTR%d,\n", SHADER_NORM0_ATTRIB);
|
||||
if (components & VB_HAS_NRM1)
|
||||
WRITE(p, "ATTRIN float3 rawnorm1; // ATTR%d,\n", SHADER_NORM1_ATTRIB);
|
||||
if (components & VB_HAS_NRM2)
|
||||
WRITE(p, "ATTRIN float3 rawnorm2; // ATTR%d,\n", SHADER_NORM2_ATTRIB);
|
||||
|
||||
if (components & VB_HAS_COL0)
|
||||
WRITE(p, "ATTRIN float4 color0; // ATTR%d,\n", SHADER_COLOR0_ATTRIB);
|
||||
if (components & VB_HAS_COL1)
|
||||
WRITE(p, "ATTRIN float4 color1; // ATTR%d,\n", SHADER_COLOR1_ATTRIB);
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
|
||||
if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
|
||||
WRITE(p, "ATTRIN float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, SHADER_TEXTURE0_ATTRIB + i);
|
||||
}
|
||||
|
||||
// Let's set up attributes
|
||||
if (xfregs.numTexGen.numTexGens < 7)
|
||||
{
|
||||
WRITE(p, " float4 blend_indices : BLENDINDICES,\n");
|
||||
for (int i = 0; i < 8; ++i)
|
||||
WRITE(p, "VARYOUT float3 uv%d_2;\n", i);
|
||||
WRITE(p, "VARYOUT float4 clipPos_2;\n");
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
WRITE(p, "VARYOUT float4 Normal_2;\n");
|
||||
}
|
||||
else
|
||||
WRITE(p, " float fposmtx : ATTR%d,\n", SHADER_POSMTX_ATTRIB);
|
||||
{
|
||||
// wpos is in w of first 4 texcoords
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
WRITE(p, "VARYOUT float4 uv%d_2;\n", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
WRITE(p, "VARYOUT float%d uv%d_2;\n", i < 4 ? 4 : 3 , i);
|
||||
}
|
||||
}
|
||||
WRITE(p, "VARYOUT float4 colors_02;\n");
|
||||
WRITE(p, "VARYOUT float4 colors_12;\n");
|
||||
|
||||
WRITE(p, "void main()\n{\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p, "VS_OUTPUT main(\n");
|
||||
|
||||
// inputs
|
||||
if (components & VB_HAS_NRM0)
|
||||
WRITE(p, " float3 rawnorm0 : NORMAL0,\n");
|
||||
if (components & VB_HAS_NRM1) {
|
||||
if (is_d3d)
|
||||
WRITE(p, " float3 rawnorm1 : NORMAL1,\n");
|
||||
else
|
||||
WRITE(p, " float3 rawnorm1 : ATTR%d,\n", SHADER_NORM1_ATTRIB);
|
||||
}
|
||||
if (components & VB_HAS_NRM2) {
|
||||
if (is_d3d)
|
||||
WRITE(p, " float3 rawnorm2 : NORMAL2,\n");
|
||||
else
|
||||
WRITE(p, " float3 rawnorm2 : ATTR%d,\n", SHADER_NORM2_ATTRIB);
|
||||
}
|
||||
if (components & VB_HAS_COL0)
|
||||
WRITE(p, " float4 color0 : COLOR0,\n");
|
||||
if (components & VB_HAS_COL1)
|
||||
WRITE(p, " float4 color1 : COLOR1,\n");
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
|
||||
if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
|
||||
WRITE(p, " float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i);
|
||||
}
|
||||
if (components & VB_HAS_POSMTXIDX) {
|
||||
if (is_d3d)
|
||||
WRITE(p, " float4 blend_indices : BLENDINDICES,\n");
|
||||
else
|
||||
WRITE(p, " float fposmtx : ATTR%d,\n", SHADER_POSMTX_ATTRIB);
|
||||
}
|
||||
WRITE(p, " float4 rawpos : POSITION) {\n");
|
||||
}
|
||||
WRITE(p, " float4 rawpos : POSITION) {\n");
|
||||
WRITE(p, "VS_OUTPUT o;\n");
|
||||
|
||||
// transforms
|
||||
if (components & VB_HAS_POSMTXIDX)
|
||||
{
|
||||
if (api_type & API_D3D9)
|
||||
if (ApiType & API_D3D9)
|
||||
{
|
||||
WRITE(p, "int4 indices = D3DCOLORtoUBYTE4(blend_indices);\n");
|
||||
WRITE(p, "int posmtx = indices.x;\n");
|
||||
}
|
||||
else if (api_type == API_D3D11)
|
||||
else if (ApiType == API_D3D11)
|
||||
{
|
||||
WRITE(p, "int posmtx = blend_indices.x * 255.0f;\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p, "int posmtx = fposmtx;\n");
|
||||
}
|
||||
|
||||
WRITE(p, "float4 pos = float4(dot(" I_TRANSFORMMATRICES".T[posmtx].t, rawpos), dot(" I_TRANSFORMMATRICES".T[posmtx+1].t, rawpos), dot(" I_TRANSFORMMATRICES".T[posmtx+2].t, rawpos), 1);\n");
|
||||
WRITE(p, "float4 pos = float4(dot(" I_TRANSFORMMATRICES"[posmtx], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+1], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+2], rawpos), 1);\n");
|
||||
|
||||
if (components & VB_HAS_NRMALL) {
|
||||
WRITE(p, "int normidx = posmtx >= 32 ? (posmtx-32) : posmtx;\n");
|
||||
WRITE(p, "float3 N0 = " I_NORMALMATRICES".T[normidx].t.xyz, N1 = " I_NORMALMATRICES".T[normidx+1].t.xyz, N2 = " I_NORMALMATRICES".T[normidx+2].t.xyz;\n");
|
||||
WRITE(p, "float3 N0 = " I_NORMALMATRICES"[normidx].xyz, N1 = " I_NORMALMATRICES"[normidx+1].xyz, N2 = " I_NORMALMATRICES"[normidx+2].xyz;\n");
|
||||
}
|
||||
|
||||
if (components & VB_HAS_NRM0)
|
||||
@@ -275,13 +323,13 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p, "float4 pos = float4(dot(" I_POSNORMALMATRIX".T0, rawpos), dot(" I_POSNORMALMATRIX".T1, rawpos), dot(" I_POSNORMALMATRIX".T2, rawpos), 1.0f);\n");
|
||||
WRITE(p, "float4 pos = float4(dot(" I_POSNORMALMATRIX"[0], rawpos), dot(" I_POSNORMALMATRIX"[1], rawpos), dot(" I_POSNORMALMATRIX"[2], rawpos), 1.0f);\n");
|
||||
if (components & VB_HAS_NRM0)
|
||||
WRITE(p, "float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX".N0.xyz, rawnorm0), dot(" I_POSNORMALMATRIX".N1.xyz, rawnorm0), dot(" I_POSNORMALMATRIX".N2.xyz, rawnorm0)));\n");
|
||||
WRITE(p, "float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm0), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm0), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm0)));\n");
|
||||
if (components & VB_HAS_NRM1)
|
||||
WRITE(p, "float3 _norm1 = float3(dot(" I_POSNORMALMATRIX".N0.xyz, rawnorm1), dot(" I_POSNORMALMATRIX".N1.xyz, rawnorm1), dot(" I_POSNORMALMATRIX".N2.xyz, rawnorm1));\n");
|
||||
WRITE(p, "float3 _norm1 = float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm1), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm1), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm1));\n");
|
||||
if (components & VB_HAS_NRM2)
|
||||
WRITE(p, "float3 _norm2 = float3(dot(" I_POSNORMALMATRIX".N0.xyz, rawnorm2), dot(" I_POSNORMALMATRIX".N1.xyz, rawnorm2), dot(" I_POSNORMALMATRIX".N2.xyz, rawnorm2));\n");
|
||||
WRITE(p, "float3 _norm2 = float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm2), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm2), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm2));\n");
|
||||
}
|
||||
|
||||
if (!(components & VB_HAS_NRM0))
|
||||
@@ -289,13 +337,13 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
|
||||
|
||||
|
||||
|
||||
WRITE(p, "o.pos = float4(dot(" I_PROJECTION".T0, pos), dot(" I_PROJECTION".T1, pos), dot(" I_PROJECTION".T2, pos), dot(" I_PROJECTION".T3, pos));\n");
|
||||
WRITE(p, "o.pos = float4(dot(" I_PROJECTION"[0], pos), dot(" I_PROJECTION"[1], pos), dot(" I_PROJECTION"[2], pos), dot(" I_PROJECTION"[3], pos));\n");
|
||||
|
||||
WRITE(p, "float4 mat, lacc;\n"
|
||||
"float3 ldir, h;\n"
|
||||
"float dist, dist2, attn;\n");
|
||||
|
||||
if(xfregs.numChan.numColorChans == 0)
|
||||
if (xfregs.numChan.numColorChans == 0)
|
||||
{
|
||||
if (components & VB_HAS_COL0)
|
||||
WRITE(p, "o.colors_0 = color0;\n");
|
||||
@@ -306,7 +354,7 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
|
||||
// TODO: This probably isn't necessary if pixel lighting is enabled.
|
||||
p = GenerateLightingShader(p, components, I_MATERIALS, I_LIGHTS, "color", "o.colors_");
|
||||
|
||||
if(xfregs.numChan.numColorChans < 2)
|
||||
if (xfregs.numChan.numColorChans < 2)
|
||||
{
|
||||
if (components & VB_HAS_COL1)
|
||||
WRITE(p, "o.colors_1 = color1;\n");
|
||||
@@ -368,7 +416,7 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
|
||||
|
||||
if (components & (VB_HAS_NRM1|VB_HAS_NRM2)) {
|
||||
// transform the light dir into tangent space
|
||||
WRITE(p, "ldir = normalize(" I_LIGHTS".lights[%d].pos.xyz - pos.xyz);\n", texinfo.embosslightshift);
|
||||
WRITE(p, "ldir = normalize(" I_LIGHTS"[%d + 3].xyz - pos.xyz);\n", texinfo.embosslightshift);
|
||||
WRITE(p, "o.tex%d.xyz = o.tex%d.xyz + float3(dot(ldir, _norm1), dot(ldir, _norm2), 0.0f);\n", i, texinfo.embosssourceshift);
|
||||
}
|
||||
else
|
||||
@@ -388,18 +436,20 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
|
||||
break;
|
||||
case XF_TEXGEN_REGULAR:
|
||||
default:
|
||||
if (components & (VB_HAS_TEXMTXIDX0<<i)) {
|
||||
if (components & (VB_HAS_TEXMTXIDX0<<i))
|
||||
{
|
||||
WRITE(p, "int tmp = int(tex%d.z);\n", i);
|
||||
if (texinfo.projection == XF_TEXPROJ_STQ)
|
||||
WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z].t), dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z+1].t), dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z+2].t));\n", i, i, i, i);
|
||||
WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES"[tmp]), dot(coord, " I_TRANSFORMMATRICES"[tmp+1]), dot(coord, " I_TRANSFORMMATRICES"[tmp+2]));\n", i);
|
||||
else {
|
||||
WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z].t), dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z+1].t), 1);\n", i, i, i);
|
||||
WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES"[tmp]), dot(coord, " I_TRANSFORMMATRICES"[tmp+1]), 1);\n", i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (texinfo.projection == XF_TEXPROJ_STQ)
|
||||
WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES".T[%d].t), dot(coord, " I_TEXMATRICES".T[%d].t), dot(coord, " I_TEXMATRICES".T[%d].t));\n", i, 3*i, 3*i+1, 3*i+2);
|
||||
WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]));\n", i, 3*i, 3*i+1, 3*i+2);
|
||||
else
|
||||
WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES".T[%d].t), dot(coord, " I_TEXMATRICES".T[%d].t), 1);\n", i, 3*i, 3*i+1);
|
||||
WRITE(p, "o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]), 1);\n", i, 3*i, 3*i+1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -408,9 +458,9 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
|
||||
const PostMtxInfo& postInfo = xfregs.postMtxInfo[i];
|
||||
|
||||
int postidx = postInfo.index;
|
||||
WRITE(p, "float4 P0 = " I_POSTTRANSFORMMATRICES".T[%d].t;\n"
|
||||
"float4 P1 = " I_POSTTRANSFORMMATRICES".T[%d].t;\n"
|
||||
"float4 P2 = " I_POSTTRANSFORMMATRICES".T[%d].t;\n",
|
||||
WRITE(p, "float4 P0 = " I_POSTTRANSFORMMATRICES"[%d];\n"
|
||||
"float4 P1 = " I_POSTTRANSFORMMATRICES"[%d];\n"
|
||||
"float4 P2 = " I_POSTTRANSFORMMATRICES"[%d];\n",
|
||||
postidx&0x3f, (postidx+1)&0x3f, (postidx+2)&0x3f);
|
||||
|
||||
if (texGenSpecialCase) {
|
||||
@@ -494,15 +544,49 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
|
||||
//seems to get rather complicated
|
||||
}
|
||||
|
||||
if (api_type & API_D3D9)
|
||||
if (ApiType & API_D3D9)
|
||||
{
|
||||
// D3D9 is addressing pixel centers instead of pixel boundaries in clip space.
|
||||
// Thus we need to offset the final position by half a pixel
|
||||
WRITE(p, "o.pos = o.pos + float4(" I_DEPTHPARAMS".z, " I_DEPTHPARAMS".w, 0.f, 0.f);\n");
|
||||
}
|
||||
|
||||
WRITE(p, "return o;\n}\n");
|
||||
if(ApiType == API_OPENGL)
|
||||
{
|
||||
// Bit ugly here
|
||||
// TODO: Make pretty
|
||||
// Will look better when we bind uniforms in GLSL 1.3
|
||||
// clipPos/w needs to be done in pixel shader, not here
|
||||
|
||||
if (xfregs.numTexGen.numTexGens < 7) {
|
||||
for (unsigned int i = 0; i < 8; ++i)
|
||||
if(i < xfregs.numTexGen.numTexGens)
|
||||
WRITE(p, " uv%d_2.xyz = o.tex%d;\n", i, i);
|
||||
else
|
||||
WRITE(p, " uv%d_2.xyz = float3(0.0f, 0.0f, 0.0f);\n", i);
|
||||
WRITE(p, " clipPos_2 = o.clipPos;\n");
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
WRITE(p, " Normal_2 = o.Normal;\n");
|
||||
} else {
|
||||
// clip position is in w of first 4 texcoords
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
WRITE(p, " uv%d_2 = o.tex%d;\n", i, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
WRITE(p, " uv%d_2%s = o.tex%d;\n", i, i < 4 ? ".xyzw" : ".xyz" , i);
|
||||
}
|
||||
}
|
||||
WRITE(p, "colors_02 = o.colors_0;\n");
|
||||
WRITE(p, "colors_12 = o.colors_1;\n");
|
||||
WRITE(p, "gl_Position = o.pos;\n");
|
||||
WRITE(p, "}\n");
|
||||
}
|
||||
else
|
||||
WRITE(p, "return o;\n}\n");
|
||||
|
||||
if (text[sizeof(text) - 1] != 0x7C)
|
||||
PanicAlert("VertexShader generator - buffer too small, canary has been eaten!");
|
||||
|
||||
@@ -21,9 +21,24 @@
|
||||
#include "XFMemory.h"
|
||||
#include "VideoCommon.h"
|
||||
|
||||
#define SHADER_POSMTX_ATTRIB 1
|
||||
#define SHADER_NORM1_ATTRIB 6
|
||||
#define SHADER_NORM2_ATTRIB 7
|
||||
// TODO should be reordered
|
||||
#define SHADER_POSITION_ATTRIB 0
|
||||
#define SHADER_POSMTX_ATTRIB 1
|
||||
#define SHADER_NORM0_ATTRIB 2
|
||||
#define SHADER_NORM1_ATTRIB 3
|
||||
#define SHADER_NORM2_ATTRIB 4
|
||||
#define SHADER_COLOR0_ATTRIB 5
|
||||
#define SHADER_COLOR1_ATTRIB 6
|
||||
|
||||
#define SHADER_TEXTURE0_ATTRIB 8
|
||||
#define SHADER_TEXTURE1_ATTRIB 9
|
||||
#define SHADER_TEXTURE2_ATTRIB 10
|
||||
#define SHADER_TEXTURE3_ATTRIB 11
|
||||
#define SHADER_TEXTURE4_ATTRIB 12
|
||||
#define SHADER_TEXTURE5_ATTRIB 13
|
||||
#define SHADER_TEXTURE6_ATTRIB 14
|
||||
#define SHADER_TEXTURE7_ATTRIB 15
|
||||
|
||||
|
||||
|
||||
// shader variables
|
||||
@@ -46,8 +61,17 @@
|
||||
#define C_NORMALMATRICES (C_TRANSFORMMATRICES + 64)
|
||||
#define C_POSTTRANSFORMMATRICES (C_NORMALMATRICES + 32)
|
||||
#define C_DEPTHPARAMS (C_POSTTRANSFORMMATRICES + 64)
|
||||
#define C_VENVCONST_END (C_DEPTHPARAMS + 4)
|
||||
|
||||
#define C_VENVCONST_END (C_DEPTHPARAMS + 1)
|
||||
const s_svar VSVar_Loc[] = { {I_POSNORMALMATRIX, C_POSNORMALMATRIX, 6 },
|
||||
{I_PROJECTION , C_PROJECTION, 4 },
|
||||
{I_MATERIALS, C_MATERIALS, 4 },
|
||||
{I_LIGHTS, C_LIGHTS, 40 },
|
||||
{I_TEXMATRICES, C_TEXMATRICES, 24 },
|
||||
{I_TRANSFORMMATRICES , C_TRANSFORMMATRICES, 64 },
|
||||
{I_NORMALMATRICES , C_NORMALMATRICES, 32 },
|
||||
{I_POSTTRANSFORMMATRICES, C_POSTTRANSFORMMATRICES, 64 },
|
||||
{I_DEPTHPARAMS, C_DEPTHPARAMS, 1 },
|
||||
};
|
||||
template<bool safe>
|
||||
class _VERTEXSHADERUID
|
||||
{
|
||||
|
||||
@@ -194,6 +194,8 @@ void VertexShaderManager::Dirty()
|
||||
// TODO: A cleaner way to control the matricies without making a mess in the parameters field
|
||||
void VertexShaderManager::SetConstants()
|
||||
{
|
||||
if (g_ActiveConfig.backend_info.APIType == API_OPENGL && !g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
Dirty();
|
||||
if (nTransformMatricesChanged[0] >= 0)
|
||||
{
|
||||
int startn = nTransformMatricesChanged[0] / 4;
|
||||
|
||||
@@ -102,8 +102,7 @@ typedef enum
|
||||
API_D3D9_SM20 = 4,
|
||||
API_D3D9 = 6,
|
||||
API_D3D11 = 8,
|
||||
API_GLSL = 16,
|
||||
API_NONE = 32
|
||||
API_NONE = 16
|
||||
} API_TYPE;
|
||||
|
||||
inline u32 RGBA8ToRGBA6ToRGBA8(u32 src)
|
||||
@@ -149,5 +148,11 @@ inline unsigned int GetPow2(unsigned int val)
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
struct s_svar
|
||||
{
|
||||
const char *name;
|
||||
const unsigned int reg;
|
||||
const unsigned int size;
|
||||
};
|
||||
|
||||
#endif // _VIDEOCOMMON_H
|
||||
|
||||
@@ -76,6 +76,7 @@ void VideoConfig::Load(const char *ini_file)
|
||||
iniFile.Get("Settings", "AnaglyphStereoSeparation", &iAnaglyphStereoSeparation, 200);
|
||||
iniFile.Get("Settings", "AnaglyphFocalAngle", &iAnaglyphFocalAngle, 0);
|
||||
iniFile.Get("Settings", "EnablePixelLighting", &bEnablePixelLighting, 0);
|
||||
iniFile.Get("Settings", "HackedBufferUpload", &bHackedBufferUpload, 0);
|
||||
|
||||
iniFile.Get("Settings", "MSAA", &iMultisampleMode, 0);
|
||||
iniFile.Get("Settings", "EFBScale", &iEFBScale, 2); // native
|
||||
@@ -134,6 +135,7 @@ void VideoConfig::GameIniLoad(const char *ini_file)
|
||||
iniFile.GetIfExists("Video_Settings", "AnaglyphStereoSeparation", &iAnaglyphStereoSeparation);
|
||||
iniFile.GetIfExists("Video_Settings", "AnaglyphFocalAngle", &iAnaglyphFocalAngle);
|
||||
iniFile.GetIfExists("Video_Settings", "EnablePixelLighting", &bEnablePixelLighting);
|
||||
iniFile.GetIfExists("Video_Settings", "HackedBufferUpload", &bHackedBufferUpload);
|
||||
iniFile.GetIfExists("Video_Settings", "MSAA", &iMultisampleMode);
|
||||
iniFile.GetIfExists("Video_Settings", "EFBScale", &iEFBScale); // integral
|
||||
iniFile.GetIfExists("Video_Settings", "DstAlphaPass", &bDstAlphaPass);
|
||||
@@ -172,6 +174,7 @@ void VideoConfig::VerifyValidity()
|
||||
if (!backend_info.bSupports3DVision) b3DVision = false;
|
||||
if (!backend_info.bSupportsFormatReinterpretation) bEFBEmulateFormatChanges = false;
|
||||
if (!backend_info.bSupportsPixelLighting) bEnablePixelLighting = false;
|
||||
if (backend_info.APIType != API_OPENGL) backend_info.bSupportsGLSLUBO = false;
|
||||
}
|
||||
|
||||
void VideoConfig::Save(const char *ini_file)
|
||||
@@ -202,7 +205,7 @@ void VideoConfig::Save(const char *ini_file)
|
||||
iniFile.Set("Settings", "AnaglyphStereoSeparation", iAnaglyphStereoSeparation);
|
||||
iniFile.Set("Settings", "AnaglyphFocalAngle", iAnaglyphFocalAngle);
|
||||
iniFile.Set("Settings", "EnablePixelLighting", bEnablePixelLighting);
|
||||
|
||||
iniFile.Set("Settings", "HackedBufferUpload", bHackedBufferUpload);
|
||||
|
||||
iniFile.Set("Settings", "ShowEFBCopyRegions", bShowEFBCopyRegions);
|
||||
iniFile.Set("Settings", "MSAA", iMultisampleMode);
|
||||
|
||||
@@ -133,6 +133,7 @@ struct VideoConfig
|
||||
bool bZTPSpeedHack; // The Legend of Zelda: Twilight Princess
|
||||
bool bUseBBox;
|
||||
bool bEnablePixelLighting;
|
||||
bool bHackedBufferUpload;
|
||||
|
||||
int iLog; // CONF_ bits
|
||||
int iSaveTargetId; // TODO: Should be dropped
|
||||
@@ -162,6 +163,12 @@ struct VideoConfig
|
||||
bool bSupportsDualSourceBlend; // only supported by D3D11 and OpenGL
|
||||
bool bSupportsFormatReinterpretation;
|
||||
bool bSupportsPixelLighting;
|
||||
|
||||
bool bSupportsGLSLUBO;
|
||||
bool bSupportsGLSLCache;
|
||||
bool bSupportsGLPinnedMemory;
|
||||
bool bSupportsGLSync;
|
||||
bool bSupportsGLBaseVertex;
|
||||
} backend_info;
|
||||
|
||||
// Utility
|
||||
|
||||
@@ -208,6 +208,8 @@ void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
|
||||
|
||||
void XFBSource::CopyEFB(float Gamma)
|
||||
{
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
// Copy EFB data to XFB and restore render target again
|
||||
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight);
|
||||
|
||||
@@ -222,6 +224,8 @@ void XFBSource::CopyEFB(float Gamma)
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(),
|
||||
FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
} // namespace DX11
|
||||
@@ -41,39 +41,39 @@ namespace DX11
|
||||
// TODO: Find sensible values for these two
|
||||
const UINT IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16) * 8;
|
||||
const UINT VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
|
||||
const UINT MAXVBUFFER_COUNT = 2;
|
||||
const UINT MAX_VBUFFER_COUNT = 2;
|
||||
|
||||
void VertexManager::CreateDeviceObjects()
|
||||
{
|
||||
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(IBUFFER_SIZE,
|
||||
D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
|
||||
m_vertexDrawOffset = 0;
|
||||
m_triangleDrawIndex = 0;
|
||||
m_lineDrawIndex = 0;
|
||||
m_pointDrawIndex = 0;
|
||||
m_indexBuffers = new PID3D11Buffer[MAXVBUFFER_COUNT];
|
||||
m_vertexBuffers = new PID3D11Buffer[MAXVBUFFER_COUNT];
|
||||
for (m_activeIndexBuffer = 0; m_activeIndexBuffer < MAXVBUFFER_COUNT; m_activeIndexBuffer++)
|
||||
m_vertex_draw_offset = 0;
|
||||
m_triangle_draw_index = 0;
|
||||
m_line_draw_index = 0;
|
||||
m_point_draw_index = 0;
|
||||
m_index_buffers = new PID3D11Buffer[MAX_VBUFFER_COUNT];
|
||||
m_vertex_buffers = new PID3D11Buffer[MAX_VBUFFER_COUNT];
|
||||
for (m_current_index_buffer = 0; m_current_index_buffer < MAX_VBUFFER_COUNT; m_current_index_buffer++)
|
||||
{
|
||||
m_indexBuffers[m_activeIndexBuffer] = NULL;
|
||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_indexBuffers[m_activeIndexBuffer])),
|
||||
m_index_buffers[m_current_index_buffer] = NULL;
|
||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_index_buffers[m_current_index_buffer])),
|
||||
"Failed to create index buffer.");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_indexBuffers[m_activeIndexBuffer], "index buffer of VertexManager");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_index_buffers[m_current_index_buffer], "index buffer of VertexManager");
|
||||
}
|
||||
bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufdesc.ByteWidth = VBUFFER_SIZE;
|
||||
for (m_activeVertexBuffer = 0; m_activeVertexBuffer < MAXVBUFFER_COUNT; m_activeVertexBuffer++)
|
||||
for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
|
||||
{
|
||||
m_vertexBuffers[m_activeVertexBuffer] = NULL;
|
||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_vertexBuffers[m_activeVertexBuffer])),
|
||||
m_vertex_buffers[m_current_vertex_buffer] = NULL;
|
||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_vertex_buffers[m_current_vertex_buffer])),
|
||||
"Failed to create vertex buffer.");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_vertexBuffers[m_activeVertexBuffer], "Vertex buffer of VertexManager");
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_vertex_buffers[m_current_vertex_buffer], "Vertex buffer of VertexManager");
|
||||
}
|
||||
m_activeVertexBuffer = 0;
|
||||
m_activeIndexBuffer = 0;
|
||||
m_indexBufferCursor = IBUFFER_SIZE;
|
||||
m_vertexBufferCursor = VBUFFER_SIZE;
|
||||
m_current_vertex_buffer = 0;
|
||||
m_current_index_buffer = 0;
|
||||
m_index_buffer_cursor = IBUFFER_SIZE;
|
||||
m_vertex_buffer_cursor = VBUFFER_SIZE;
|
||||
m_lineShader.Init();
|
||||
m_pointShader.Init();
|
||||
}
|
||||
@@ -82,10 +82,10 @@ void VertexManager::DestroyDeviceObjects()
|
||||
{
|
||||
m_pointShader.Shutdown();
|
||||
m_lineShader.Shutdown();
|
||||
for (m_activeVertexBuffer = 0; m_activeVertexBuffer < MAXVBUFFER_COUNT; m_activeVertexBuffer++)
|
||||
for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
|
||||
{
|
||||
SAFE_RELEASE(m_vertexBuffers[m_activeVertexBuffer]);
|
||||
SAFE_RELEASE(m_indexBuffers[m_activeVertexBuffer]);
|
||||
SAFE_RELEASE(m_vertex_buffers[m_current_vertex_buffer]);
|
||||
SAFE_RELEASE(m_index_buffers[m_current_vertex_buffer]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -100,47 +100,47 @@ VertexManager::~VertexManager()
|
||||
DestroyDeviceObjects();
|
||||
}
|
||||
|
||||
void VertexManager::LoadBuffers()
|
||||
void VertexManager::PrepareDrawBuffers()
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
|
||||
UINT vSize = UINT(s_pCurBufferPointer - s_pBaseBufferPointer);
|
||||
D3D11_MAP MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
|
||||
if (m_vertexBufferCursor + vSize >= VBUFFER_SIZE)
|
||||
if (m_vertex_buffer_cursor + vSize >= VBUFFER_SIZE)
|
||||
{
|
||||
// Wrap around
|
||||
m_activeVertexBuffer = (m_activeVertexBuffer + 1) % MAXVBUFFER_COUNT;
|
||||
m_vertexBufferCursor = 0;
|
||||
m_current_vertex_buffer = (m_current_vertex_buffer + 1) % MAX_VBUFFER_COUNT;
|
||||
m_vertex_buffer_cursor = 0;
|
||||
MapType = D3D11_MAP_WRITE_DISCARD;
|
||||
}
|
||||
|
||||
D3D::context->Map(m_vertexBuffers[m_activeVertexBuffer], 0, MapType, 0, &map);
|
||||
D3D::context->Map(m_vertex_buffers[m_current_vertex_buffer], 0, MapType, 0, &map);
|
||||
|
||||
memcpy((u8*)map.pData + m_vertexBufferCursor, s_pBaseBufferPointer, vSize);
|
||||
D3D::context->Unmap(m_vertexBuffers[m_activeVertexBuffer], 0);
|
||||
m_vertexDrawOffset = m_vertexBufferCursor;
|
||||
m_vertexBufferCursor += vSize;
|
||||
memcpy((u8*)map.pData + m_vertex_buffer_cursor, s_pBaseBufferPointer, vSize);
|
||||
D3D::context->Unmap(m_vertex_buffers[m_current_vertex_buffer], 0);
|
||||
m_vertex_draw_offset = m_vertex_buffer_cursor;
|
||||
m_vertex_buffer_cursor += vSize;
|
||||
|
||||
UINT iCount = IndexGenerator::GetTriangleindexLen() +
|
||||
IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
|
||||
MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
|
||||
if (m_indexBufferCursor + iCount >= (IBUFFER_SIZE / sizeof(u16)))
|
||||
if (m_index_buffer_cursor + iCount >= (IBUFFER_SIZE / sizeof(u16)))
|
||||
{
|
||||
// Wrap around
|
||||
m_activeIndexBuffer = (m_activeIndexBuffer + 1) % MAXVBUFFER_COUNT;
|
||||
m_indexBufferCursor = 0;
|
||||
m_current_index_buffer = (m_current_index_buffer + 1) % MAX_VBUFFER_COUNT;
|
||||
m_index_buffer_cursor = 0;
|
||||
MapType = D3D11_MAP_WRITE_DISCARD;
|
||||
}
|
||||
D3D::context->Map(m_indexBuffers[m_activeIndexBuffer], 0, MapType, 0, &map);
|
||||
D3D::context->Map(m_index_buffers[m_current_index_buffer], 0, MapType, 0, &map);
|
||||
|
||||
m_triangleDrawIndex = m_indexBufferCursor;
|
||||
m_lineDrawIndex = m_triangleDrawIndex + IndexGenerator::GetTriangleindexLen();
|
||||
m_pointDrawIndex = m_lineDrawIndex + IndexGenerator::GetLineindexLen();
|
||||
memcpy((u16*)map.pData + m_triangleDrawIndex, GetTriangleIndexBuffer(), sizeof(u16) * IndexGenerator::GetTriangleindexLen());
|
||||
memcpy((u16*)map.pData + m_lineDrawIndex, GetLineIndexBuffer(), sizeof(u16) * IndexGenerator::GetLineindexLen());
|
||||
memcpy((u16*)map.pData + m_pointDrawIndex, GetPointIndexBuffer(), sizeof(u16) * IndexGenerator::GetPointindexLen());
|
||||
D3D::context->Unmap(m_indexBuffers[m_activeIndexBuffer], 0);
|
||||
m_indexBufferCursor += iCount;
|
||||
m_triangle_draw_index = m_index_buffer_cursor;
|
||||
m_line_draw_index = m_triangle_draw_index + IndexGenerator::GetTriangleindexLen();
|
||||
m_point_draw_index = m_line_draw_index + IndexGenerator::GetLineindexLen();
|
||||
memcpy((u16*)map.pData + m_triangle_draw_index, GetTriangleIndexBuffer(), sizeof(u16) * IndexGenerator::GetTriangleindexLen());
|
||||
memcpy((u16*)map.pData + m_line_draw_index, GetLineIndexBuffer(), sizeof(u16) * IndexGenerator::GetLineindexLen());
|
||||
memcpy((u16*)map.pData + m_point_draw_index, GetPointIndexBuffer(), sizeof(u16) * IndexGenerator::GetPointindexLen());
|
||||
D3D::context->Unmap(m_index_buffers[m_current_index_buffer], 0);
|
||||
m_index_buffer_cursor += iCount;
|
||||
}
|
||||
|
||||
static const float LINE_PT_TEX_OFFSETS[8] = {
|
||||
@@ -149,13 +149,13 @@ static const float LINE_PT_TEX_OFFSETS[8] = {
|
||||
|
||||
void VertexManager::Draw(UINT stride)
|
||||
{
|
||||
D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffers[m_activeVertexBuffer], &stride, &m_vertexDrawOffset);
|
||||
D3D::context->IASetIndexBuffer(m_indexBuffers[m_activeIndexBuffer], DXGI_FORMAT_R16_UINT, 0);
|
||||
D3D::context->IASetVertexBuffers(0, 1, &m_vertex_buffers[m_current_vertex_buffer], &stride, &m_vertex_draw_offset);
|
||||
D3D::context->IASetIndexBuffer(m_index_buffers[m_current_index_buffer], DXGI_FORMAT_R16_UINT, 0);
|
||||
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
{
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
D3D::context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangleDrawIndex, 0);
|
||||
D3D::context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangle_draw_index, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
// Disable culling for lines and points
|
||||
@@ -177,7 +177,7 @@ void VertexManager::Draw(UINT stride)
|
||||
texOffset, vpWidth, vpHeight, texOffsetEnable))
|
||||
{
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
|
||||
D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_lineDrawIndex, 0);
|
||||
D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_line_draw_index, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
|
||||
D3D::context->GSSetShader(NULL, NULL, 0);
|
||||
@@ -199,7 +199,7 @@ void VertexManager::Draw(UINT stride)
|
||||
texOffset, vpWidth, vpHeight, texOffsetEnable))
|
||||
{
|
||||
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
|
||||
D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_pointDrawIndex, 0);
|
||||
D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_point_draw_index, 0);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
|
||||
D3D::context->GSSetShader(NULL, NULL, 0);
|
||||
@@ -265,7 +265,7 @@ void VertexManager::vFlush()
|
||||
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
|
||||
return;
|
||||
}
|
||||
LoadBuffers();
|
||||
PrepareDrawBuffers();
|
||||
unsigned int stride = g_nativeVertexFmt->GetVertexStride();
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
g_renderer->ApplyState(useDstAlpha);
|
||||
|
||||
@@ -37,22 +37,22 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
void LoadBuffers();
|
||||
void Draw(UINT stride);
|
||||
void PrepareDrawBuffers();
|
||||
void Draw(u32 stride);
|
||||
// temp
|
||||
void vFlush();
|
||||
|
||||
UINT m_indexBufferCursor;
|
||||
UINT m_vertexBufferCursor;
|
||||
UINT m_vertexDrawOffset;
|
||||
UINT m_triangleDrawIndex;
|
||||
UINT m_lineDrawIndex;
|
||||
UINT m_pointDrawIndex;
|
||||
UINT m_activeVertexBuffer;
|
||||
UINT m_activeIndexBuffer;
|
||||
u32 m_vertex_buffer_cursor;
|
||||
u32 m_vertex_draw_offset;
|
||||
u32 m_index_buffer_cursor;
|
||||
u32 m_current_vertex_buffer;
|
||||
u32 m_current_index_buffer;
|
||||
u32 m_triangle_draw_index;
|
||||
u32 m_line_draw_index;
|
||||
u32 m_point_draw_index;
|
||||
typedef ID3D11Buffer* PID3D11Buffer;
|
||||
PID3D11Buffer* m_indexBuffers;
|
||||
PID3D11Buffer* m_vertexBuffers;
|
||||
PID3D11Buffer* m_index_buffers;
|
||||
PID3D11Buffer* m_vertex_buffers;
|
||||
|
||||
LineGeometryShader m_lineShader;
|
||||
PointGeometryShader m_pointShader;
|
||||
|
||||
@@ -15,6 +15,7 @@ class VideoBackend : public VideoBackendHardware
|
||||
std::string GetName();
|
||||
|
||||
void Video_Prepare();
|
||||
void Video_Cleanup();
|
||||
|
||||
void ShowConfig(void* parent);
|
||||
|
||||
|
||||
@@ -208,6 +208,7 @@ void VideoBackend::Shutdown()
|
||||
{
|
||||
s_BackendInitialized = false;
|
||||
|
||||
// TODO: should be in Video_Cleanup
|
||||
if (g_renderer)
|
||||
{
|
||||
s_efbAccessRequested = FALSE;
|
||||
@@ -236,4 +237,7 @@ void VideoBackend::Shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
void VideoBackend::Video_Cleanup() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ 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;
|
||||
@@ -83,10 +84,23 @@ static DWORD m_SamplerStates[MaxSamplerSize][MaxSamplerTypes];
|
||||
static bool m_SamplerStatesSet[MaxSamplerSize][MaxSamplerTypes];
|
||||
static bool m_SamplerStatesChanged[MaxSamplerSize][MaxSamplerTypes];
|
||||
|
||||
LPDIRECT3DBASETEXTURE9 m_Textures[16];
|
||||
LPDIRECT3DVERTEXDECLARATION9 m_VtxDecl;
|
||||
LPDIRECT3DPIXELSHADER9 m_PixelShader;
|
||||
LPDIRECT3DVERTEXSHADER9 m_VertexShader;
|
||||
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[] = {
|
||||
@@ -170,9 +184,9 @@ void EnableAlphaToCoverage()
|
||||
{
|
||||
// Each vendor has their own specific little hack.
|
||||
if (GetCurAdapter().ident.VendorId == VENDOR_ATI)
|
||||
D3D::SetRenderState(D3DRS_POINTSIZE, (D3DFORMAT)MAKEFOURCC('A', '2', 'M', '1'));
|
||||
SetRenderState(D3DRS_POINTSIZE, (D3DFORMAT)MAKEFOURCC('A', '2', 'M', '1'));
|
||||
else
|
||||
D3D::SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
|
||||
SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
|
||||
}
|
||||
|
||||
void InitPP(int adapter, int f, int aa_mode, D3DPRESENT_PARAMETERS *pp)
|
||||
@@ -215,14 +229,14 @@ void InitPP(int adapter, int f, int aa_mode, D3DPRESENT_PARAMETERS *pp)
|
||||
|
||||
void Enumerate()
|
||||
{
|
||||
numAdapters = D3D::D3D->GetAdapterCount();
|
||||
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::D3D->GetAdapterIdentifier(i, 0, &a.ident);
|
||||
D3D->GetAdapterIdentifier(i, 0, &a.ident);
|
||||
bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA;
|
||||
|
||||
// Add SuperSamples modes
|
||||
@@ -233,17 +247,17 @@ void Enumerate()
|
||||
//disable them will they are not implemnted
|
||||
/*
|
||||
DWORD qlevels = 0;
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
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::D3D->CheckDeviceMultiSampleType(
|
||||
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::D3D->CheckDeviceMultiSampleType(
|
||||
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));
|
||||
@@ -251,7 +265,7 @@ void Enumerate()
|
||||
if (isNvidia)
|
||||
{
|
||||
// CSAA support
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels))
|
||||
{
|
||||
if (qlevels > 2)
|
||||
@@ -262,7 +276,7 @@ void Enumerate()
|
||||
a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
|
||||
}
|
||||
}
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
if (D3DERR_NOTAVAILABLE != D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
|
||||
{
|
||||
if (qlevels > 2)
|
||||
@@ -296,11 +310,11 @@ void Enumerate()
|
||||
{
|
||||
strcpy(a.aa_levels[0].name, "(Not supported on this device)");
|
||||
}
|
||||
int numModes = D3D::D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
|
||||
int numModes = D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
|
||||
for (int m = 0; m < numModes; m++)
|
||||
{
|
||||
D3DDISPLAYMODE mode;
|
||||
D3D::D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
|
||||
D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
|
||||
|
||||
int found = -1;
|
||||
for (int x = 0; x < (int)a.resolutions.size(); x++)
|
||||
@@ -440,8 +454,8 @@ HRESULT Create(int adapter, HWND wnd, int _resolution, int aa_mode, bool auto_de
|
||||
dev->GetRenderTarget(0, &back_buffer);
|
||||
if (dev->GetDepthStencilSurface(&back_buffer_z) == D3DERR_NOTFOUND)
|
||||
back_buffer_z = NULL;
|
||||
D3D::SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE );
|
||||
D3D::SetRenderState(D3DRS_FILLMODE, g_Config.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
|
||||
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));
|
||||
@@ -452,6 +466,15 @@ HRESULT Create(int adapter, HWND wnd, int _resolution, int aa_mode, bool auto_de
|
||||
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;
|
||||
}
|
||||
@@ -516,7 +539,7 @@ bool CheckDepthStencilSupport(D3DFORMAT target_format, D3DFORMAT depth_format)
|
||||
D3DFORMAT GetSupportedDepthTextureFormat()
|
||||
{
|
||||
for (int i = 0; i < sizeof(DepthFormats)/sizeof(D3DFORMAT); ++i)
|
||||
if (D3D::CheckTextureSupport(D3DUSAGE_DEPTHSTENCIL, DepthFormats[i]))
|
||||
if (CheckTextureSupport(D3DUSAGE_DEPTHSTENCIL, DepthFormats[i]))
|
||||
return DepthFormats[i];
|
||||
|
||||
return D3DFMT_UNKNOWN;
|
||||
@@ -525,7 +548,7 @@ D3DFORMAT GetSupportedDepthTextureFormat()
|
||||
D3DFORMAT GetSupportedDepthSurfaceFormat(D3DFORMAT target_format)
|
||||
{
|
||||
for (int i = 0; i < sizeof(DepthFormats)/sizeof(D3DFORMAT); ++i)
|
||||
if (D3D::CheckDepthStencilSupport(target_format, DepthFormats[i]))
|
||||
if (CheckDepthStencilSupport(target_format, DepthFormats[i]))
|
||||
return DepthFormats[i];
|
||||
|
||||
return D3DFMT_UNKNOWN;
|
||||
@@ -533,13 +556,13 @@ D3DFORMAT GetSupportedDepthSurfaceFormat(D3DFORMAT target_format)
|
||||
|
||||
const char *VertexShaderVersionString()
|
||||
{
|
||||
int version = ((D3D::caps.VertexShaderVersion >> 8) & 0xFF);
|
||||
int version = ((caps.VertexShaderVersion >> 8) & 0xFF);
|
||||
return vsVersions[std::min(4, version)];
|
||||
}
|
||||
|
||||
const char *PixelShaderVersionString()
|
||||
{
|
||||
int version = ((D3D::caps.PixelShaderVersion >> 8) & 0xFF);
|
||||
int version = ((caps.PixelShaderVersion >> 8) & 0xFF);
|
||||
return psVersions[std::min(4, version)];
|
||||
}
|
||||
|
||||
@@ -653,14 +676,14 @@ void ApplyCachedState()
|
||||
for (int type = 0; type < MaxSamplerTypes; type++)
|
||||
{
|
||||
if(m_SamplerStatesSet[sampler][type])
|
||||
D3D::dev->SetSamplerState(sampler, (D3DSAMPLERSTATETYPE)type, m_SamplerStates[sampler][type]);
|
||||
dev->SetSamplerState(sampler, (D3DSAMPLERSTATETYPE)type, m_SamplerStates[sampler][type]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int rs = 0; rs < MaxRenderStates; rs++)
|
||||
{
|
||||
if (m_RenderStatesSet[rs])
|
||||
D3D::dev->SetRenderState((D3DRENDERSTATETYPE)rs, m_RenderStates[rs]);
|
||||
dev->SetRenderState((D3DRENDERSTATETYPE)rs, m_RenderStates[rs]);
|
||||
}
|
||||
|
||||
// We don't bother restoring these so let's just wipe the state copy
|
||||
@@ -671,6 +694,13 @@ void ApplyCachedState()
|
||||
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)
|
||||
@@ -678,7 +708,7 @@ void SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture)
|
||||
if (m_Textures[Stage] != pTexture)
|
||||
{
|
||||
m_Textures[Stage] = pTexture;
|
||||
D3D::dev->SetTexture(Stage, pTexture);
|
||||
dev->SetTexture(Stage, pTexture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -686,7 +716,7 @@ void RefreshRenderState(D3DRENDERSTATETYPE State)
|
||||
{
|
||||
if(m_RenderStatesSet[State] && m_RenderStatesChanged[State])
|
||||
{
|
||||
D3D::dev->SetRenderState(State, m_RenderStates[State]);
|
||||
dev->SetRenderState(State, m_RenderStates[State]);
|
||||
m_RenderStatesChanged[State] = false;
|
||||
}
|
||||
}
|
||||
@@ -698,7 +728,7 @@ void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value)
|
||||
m_RenderStates[State] = Value;
|
||||
m_RenderStatesSet[State] = true;
|
||||
m_RenderStatesChanged[State] = false;
|
||||
D3D::dev->SetRenderState(State, Value);
|
||||
dev->SetRenderState(State, Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,7 +737,7 @@ void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value)
|
||||
if (m_RenderStates[State] != Value || !m_RenderStatesSet[State])
|
||||
{
|
||||
m_RenderStatesChanged[State] = m_RenderStatesSet[State];
|
||||
D3D::dev->SetRenderState(State, Value);
|
||||
dev->SetRenderState(State, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -722,7 +752,7 @@ void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Valu
|
||||
m_TextureStageStates[Stage][Type] = Value;
|
||||
m_TextureStageStatesSet[Stage][Type]=true;
|
||||
m_TextureStageStatesChanged[Stage][Type]=false;
|
||||
D3D::dev->SetTextureStageState(Stage, Type, Value);
|
||||
dev->SetTextureStageState(Stage, Type, Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -730,7 +760,7 @@ void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type)
|
||||
{
|
||||
if(m_TextureStageStatesSet[Stage][Type] && m_TextureStageStatesChanged[Stage][Type])
|
||||
{
|
||||
D3D::dev->SetTextureStageState(Stage, Type, m_TextureStageStates[Stage][Type]);
|
||||
dev->SetTextureStageState(Stage, Type, m_TextureStageStates[Stage][Type]);
|
||||
m_TextureStageStatesChanged[Stage][Type] = false;
|
||||
}
|
||||
}
|
||||
@@ -740,7 +770,7 @@ void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD V
|
||||
if (m_TextureStageStates[Stage][Type] != Value || !m_TextureStageStatesSet[Stage][Type])
|
||||
{
|
||||
m_TextureStageStatesChanged[Stage][Type] = m_TextureStageStatesSet[Stage][Type];
|
||||
D3D::dev->SetTextureStageState(Stage, Type, Value);
|
||||
dev->SetTextureStageState(Stage, Type, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -755,7 +785,7 @@ void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
|
||||
m_SamplerStates[Sampler][Type] = Value;
|
||||
m_SamplerStatesSet[Sampler][Type] = true;
|
||||
m_SamplerStatesChanged[Sampler][Type] = false;
|
||||
D3D::dev->SetSamplerState(Sampler, Type, Value);
|
||||
dev->SetSamplerState(Sampler, Type, Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,7 +793,7 @@ void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type)
|
||||
{
|
||||
if(m_SamplerStatesSet[Sampler][Type] && m_SamplerStatesChanged[Sampler][Type])
|
||||
{
|
||||
D3D::dev->SetSamplerState(Sampler, Type, m_SamplerStates[Sampler][Type]);
|
||||
dev->SetSamplerState(Sampler, Type, m_SamplerStates[Sampler][Type]);
|
||||
m_SamplerStatesChanged[Sampler][Type] = false;
|
||||
}
|
||||
}
|
||||
@@ -773,7 +803,7 @@ 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];
|
||||
D3D::dev->SetSamplerState(Sampler, Type, Value);
|
||||
dev->SetSamplerState(Sampler, Type, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -783,67 +813,155 @@ void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
|
||||
|
||||
void RefreshVertexDeclaration()
|
||||
{
|
||||
if (m_VtxDecl)
|
||||
if (m_VtxDeclChanged)
|
||||
{
|
||||
D3D::dev->SetVertexDeclaration(m_VtxDecl);
|
||||
dev->SetVertexDeclaration(m_VtxDecl);
|
||||
m_VtxDeclChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl)
|
||||
{
|
||||
if (!decl) {
|
||||
m_VtxDecl = NULL;
|
||||
return;
|
||||
}
|
||||
if (decl != m_VtxDecl)
|
||||
{
|
||||
D3D::dev->SetVertexDeclaration(decl);
|
||||
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_VertexShader)
|
||||
if (m_VertexShaderChanged)
|
||||
{
|
||||
D3D::dev->SetVertexShader(m_VertexShader);
|
||||
dev->SetVertexShader(m_VertexShader);
|
||||
m_VertexShaderChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader)
|
||||
{
|
||||
if (!shader) {
|
||||
m_VertexShader = NULL;
|
||||
return;
|
||||
}
|
||||
if (shader != m_VertexShader)
|
||||
{
|
||||
D3D::dev->SetVertexShader(shader);
|
||||
dev->SetVertexShader(shader);
|
||||
m_VertexShader = shader;
|
||||
m_VertexShaderChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshPixelShader()
|
||||
{
|
||||
if (m_PixelShader)
|
||||
if (m_PixelShaderChanged)
|
||||
{
|
||||
D3D::dev->SetPixelShader(m_PixelShader);
|
||||
dev->SetPixelShader(m_PixelShader);
|
||||
m_PixelShaderChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader)
|
||||
{
|
||||
if (!shader) {
|
||||
m_PixelShader = NULL;
|
||||
return;
|
||||
}
|
||||
if (shader != m_PixelShader)
|
||||
{
|
||||
D3D::dev->SetPixelShader(shader);
|
||||
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
|
||||
|
||||
|
||||
@@ -100,12 +100,23 @@ 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();
|
||||
|
||||
|
||||
@@ -198,6 +198,8 @@ const int TS[6][2] =
|
||||
void RestoreShaders()
|
||||
{
|
||||
D3D::SetTexture(0, 0);
|
||||
D3D::RefreshStreamSource(0);
|
||||
D3D::RefreshIndices();
|
||||
D3D::RefreshVertexDeclaration();
|
||||
D3D::RefreshPixelShader();
|
||||
D3D::RefreshVertexShader();
|
||||
@@ -217,9 +219,9 @@ void CD3DFont::SetRenderStates()
|
||||
{
|
||||
D3D::SetTexture(0, m_pTexture);
|
||||
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
|
||||
D3D::ChangePixelShader(0);
|
||||
D3D::ChangeVertexShader(0);
|
||||
D3D::ChangeVertexDeclaration(0);
|
||||
dev->SetFVF(D3DFVF_FONT2DVERTEX);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
@@ -236,7 +238,7 @@ int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, flo
|
||||
return 0;
|
||||
|
||||
SetRenderStates();
|
||||
dev->SetStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
|
||||
D3D::ChangeStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
|
||||
|
||||
float vpWidth = 1;
|
||||
float vpHeight = 1;
|
||||
@@ -389,9 +391,10 @@ void drawShadedTexQuad(IDirect3DTexture9 *texture,
|
||||
{ 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}
|
||||
};
|
||||
dev->SetVertexShader(Vshader);
|
||||
dev->SetPixelShader(PShader);
|
||||
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();
|
||||
@@ -424,9 +427,10 @@ void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
|
||||
{ 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}
|
||||
};
|
||||
dev->SetVertexShader(Vshader);
|
||||
dev->SetPixelShader(PShader);
|
||||
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();
|
||||
@@ -442,8 +446,9 @@ void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2)
|
||||
{ x1, y1, 0.f, 1.f, Color },
|
||||
{ x2, y1, 0.f, 1.f, Color },
|
||||
};
|
||||
dev->SetVertexShader(VertexShaderCache::GetClearVertexShader());
|
||||
dev->SetPixelShader(PixelShaderCache::GetClearProgram());
|
||||
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();
|
||||
@@ -457,8 +462,9 @@ void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVer
|
||||
{ 1.0f, -1.0f, z, 1.0f, Color},
|
||||
{-1.0f, -1.0f, z, 1.0f, Color}
|
||||
};
|
||||
dev->SetVertexShader(Vshader);
|
||||
dev->SetPixelShader(PShader);
|
||||
D3D::ChangeVertexShader(Vshader);
|
||||
D3D::ChangePixelShader(PShader);
|
||||
D3D::ChangeVertexDeclaration(0);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
|
||||
@@ -187,6 +187,8 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c
|
||||
|
||||
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);
|
||||
@@ -229,6 +231,8 @@ void XFBSource::CopyEFB(float Gamma)
|
||||
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||
|
||||
Rendersurf->Release();
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
} // namespace DX9
|
||||
|
||||
@@ -67,6 +67,7 @@ static int s_fps = 0;
|
||||
static u32 s_blendMode;
|
||||
static u32 s_LastAA;
|
||||
static bool IS_AMD;
|
||||
static float m_fMaxPointSize;
|
||||
|
||||
static char *st;
|
||||
|
||||
@@ -187,6 +188,9 @@ Renderer::Renderer()
|
||||
D3D::BeginFrame();
|
||||
D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, true);
|
||||
D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width,s_backbuffer_height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL );
|
||||
D3D::SetRenderState(D3DRS_POINTSCALEENABLE,false);
|
||||
m_fMaxPointSize = D3D::GetCaps().MaxPointSize;
|
||||
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
@@ -1280,7 +1284,15 @@ void Renderer::SetLineWidth()
|
||||
// We can't change line width in D3D unless we use ID3DXLine
|
||||
float fratio = xfregs.viewport.wd != 0 ? Renderer::EFBToScaledXf(1.f) : 1.0f;
|
||||
float psize = bpmem.lineptwidth.linesize * fratio / 6.0f;
|
||||
//little hack to compensate scalling problems in dx9 must be taken out when scalling is fixed.
|
||||
psize *= 2.0f;
|
||||
if (psize > m_fMaxPointSize)
|
||||
{
|
||||
psize = m_fMaxPointSize;
|
||||
}
|
||||
D3D::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize));
|
||||
D3D::SetRenderState(D3DRS_POINTSIZE_MIN, *((DWORD*)&psize));
|
||||
D3D::SetRenderState(D3DRS_POINTSIZE_MAX, *((DWORD*)&psize));
|
||||
}
|
||||
|
||||
void Renderer::SetSamplerState(int stage, int texindex)
|
||||
|
||||
@@ -82,6 +82,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||
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();
|
||||
@@ -179,6 +181,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||
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,
|
||||
|
||||
@@ -44,7 +44,7 @@ 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 MAXVBUFFER_COUNT = 2;
|
||||
const u32 MAX_VBUFFER_COUNT = 2;
|
||||
|
||||
inline void DumpBadShaders()
|
||||
{
|
||||
@@ -67,88 +67,88 @@ inline void DumpBadShaders()
|
||||
|
||||
void VertexManager::CreateDeviceObjects()
|
||||
{
|
||||
NumVBuffers = 0;
|
||||
VBuffers = NULL;
|
||||
IBuffers = NULL;
|
||||
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
|
||||
CurrentVBufferSize = (VBUFFER_SIZE > devicevMaxBufferSize) ? devicevMaxBufferSize : VBUFFER_SIZE;
|
||||
CurrentIBufferSize = (IBUFFER_SIZE > DeviceCaps.MaxVertexIndex) ? DeviceCaps.MaxVertexIndex : IBUFFER_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 (CurrentIBufferSize < MAXIBUFFERSIZE || CurrentVBufferSize < MAXVBUFFERSIZE) return;
|
||||
if (m_index_buffer_size < MAXIBUFFERSIZE || m_vertex_buffer_size < MAXVBUFFERSIZE) return;
|
||||
|
||||
VBuffers = new LPDIRECT3DVERTEXBUFFER9[MAXVBUFFER_COUNT];
|
||||
IBuffers = new LPDIRECT3DINDEXBUFFER9[MAXVBUFFER_COUNT];
|
||||
m_vertex_buffers = new LPDIRECT3DVERTEXBUFFER9[MAX_VBUFFER_COUNT];
|
||||
m_index_buffers = new LPDIRECT3DINDEXBUFFER9[MAX_VBUFFER_COUNT];
|
||||
|
||||
bool Fail = false;
|
||||
for (CurrentVBuffer = 0; CurrentVBuffer < MAXVBUFFER_COUNT; CurrentVBuffer++)
|
||||
for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
|
||||
{
|
||||
VBuffers[CurrentVBuffer] = NULL;
|
||||
IBuffers[CurrentVBuffer] = NULL;
|
||||
m_vertex_buffers[m_current_vertex_buffer] = NULL;
|
||||
m_index_buffers[m_current_vertex_buffer] = NULL;
|
||||
}
|
||||
for (CurrentVBuffer = 0; CurrentVBuffer < MAXVBUFFER_COUNT; CurrentVBuffer++)
|
||||
for (m_current_vertex_buffer = 0; m_current_vertex_buffer < MAX_VBUFFER_COUNT; m_current_vertex_buffer++)
|
||||
{
|
||||
if(FAILED( D3D::dev->CreateVertexBuffer( CurrentVBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &VBuffers[CurrentVBuffer], NULL ) ) )
|
||||
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( CurrentIBufferSize * sizeof(u16), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &IBuffers[CurrentVBuffer], NULL ) ) )
|
||||
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;
|
||||
}
|
||||
}
|
||||
NumVBuffers = CurrentVBuffer;
|
||||
CurrentVBuffer = 0;
|
||||
CurrentIBuffer = 0;
|
||||
CurrentIBufferIndex = CurrentIBufferSize;
|
||||
CurrentVBufferIndex = CurrentVBufferSize;
|
||||
|
||||
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)
|
||||
{
|
||||
NumVBuffers--;
|
||||
if (NumVBuffers < 2)
|
||||
m_buffers_count--;
|
||||
if (m_buffers_count < 2)
|
||||
{
|
||||
//Error creating Vertex buffers. clean and fall to Vertex arrays
|
||||
NumVBuffers = MAXVBUFFER_COUNT;
|
||||
m_buffers_count = MAX_VBUFFER_COUNT;
|
||||
DestroyDeviceObjects();
|
||||
}
|
||||
}
|
||||
}
|
||||
void VertexManager::DestroyDeviceObjects()
|
||||
{
|
||||
D3D::dev->SetStreamSource( 0, NULL, 0, 0);
|
||||
D3D::dev->SetIndices(NULL);
|
||||
for (int i = 0; i < MAXVBUFFER_COUNT; i++)
|
||||
D3D::SetStreamSource( 0, NULL, 0, 0);
|
||||
D3D::SetIndices(NULL);
|
||||
for (int i = 0; i < MAX_VBUFFER_COUNT; i++)
|
||||
{
|
||||
if(VBuffers)
|
||||
if(m_vertex_buffers)
|
||||
{
|
||||
if (VBuffers[i])
|
||||
if (m_vertex_buffers[i])
|
||||
{
|
||||
VBuffers[i]->Release();
|
||||
VBuffers[i] = NULL;
|
||||
m_vertex_buffers[i]->Release();
|
||||
m_vertex_buffers[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (IBuffers[i])
|
||||
if (m_index_buffers[i])
|
||||
{
|
||||
IBuffers[i]->Release();
|
||||
IBuffers[i] = NULL;
|
||||
m_index_buffers[i]->Release();
|
||||
m_index_buffers[i] = NULL;
|
||||
}
|
||||
}
|
||||
if(VBuffers)
|
||||
delete [] VBuffers;
|
||||
if(IBuffers)
|
||||
delete [] IBuffers;
|
||||
VBuffers = NULL;
|
||||
IBuffers = 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::PrepareVBuffers(int stride)
|
||||
void VertexManager::PrepareDrawBuffers(u32 stride)
|
||||
{
|
||||
if (!NumVBuffers)
|
||||
if (!m_buffers_count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -158,34 +158,33 @@ void VertexManager::PrepareVBuffers(int stride)
|
||||
int TdataSize = IndexGenerator::GetTriangleindexLen();
|
||||
int LDataSize = IndexGenerator::GetLineindexLen();
|
||||
int PDataSize = IndexGenerator::GetPointindexLen();
|
||||
int IndexDataSize = TdataSize + LDataSize + PDataSize;
|
||||
int IndexDataSize = TdataSize + LDataSize;
|
||||
DWORD LockMode = D3DLOCK_NOOVERWRITE;
|
||||
|
||||
if (CurrentVBufferIndex > CurrentVBufferSize - datasize)
|
||||
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;
|
||||
CurrentVBufferIndex = 0;
|
||||
CurrentVBuffer = (CurrentVBuffer + 1) % NumVBuffers;
|
||||
}
|
||||
|
||||
if(FAILED(VBuffers[CurrentVBuffer]->Lock(CurrentVBufferIndex, datasize,(VOID**)(&pVertices), LockMode)))
|
||||
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);
|
||||
VBuffers[CurrentVBuffer]->Unlock();
|
||||
m_vertex_buffers[m_current_vertex_buffer]->Unlock();
|
||||
|
||||
LockMode = D3DLOCK_NOOVERWRITE;
|
||||
|
||||
if (CurrentIBufferIndex > CurrentIBufferSize - IndexDataSize)
|
||||
if (m_index_buffer_cursor > m_index_buffer_size - IndexDataSize)
|
||||
{
|
||||
LockMode = D3DLOCK_DISCARD;
|
||||
CurrentIBufferIndex = 0;
|
||||
CurrentIBuffer = (CurrentIBuffer + 1) % NumVBuffers;
|
||||
}
|
||||
m_index_buffer_cursor = 0;
|
||||
m_current_index_buffer = (m_current_index_buffer + 1) % m_buffers_count;
|
||||
}
|
||||
|
||||
if(FAILED(IBuffers[CurrentIBuffer]->Lock(CurrentIBufferIndex * sizeof(u16), IndexDataSize * sizeof(u16), (VOID**)(&pIndices), LockMode )))
|
||||
if(FAILED(m_index_buffers[m_current_index_buffer]->Lock(m_index_buffer_cursor * sizeof(u16), IndexDataSize * sizeof(u16), (VOID**)(&pIndices), LockMode )))
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
return;
|
||||
@@ -200,72 +199,88 @@ void VertexManager::PrepareVBuffers(int stride)
|
||||
memcpy(pIndices, GetLineIndexBuffer(), LDataSize * sizeof(u16));
|
||||
pIndices += LDataSize;
|
||||
}
|
||||
if(PDataSize)
|
||||
{
|
||||
memcpy(pIndices, GetPointIndexBuffer(), PDataSize * sizeof(u16));
|
||||
}
|
||||
IBuffers[CurrentIBuffer]->Unlock();
|
||||
D3D::dev->SetStreamSource( 0, VBuffers[CurrentVBuffer], CurrentVBufferIndex, stride);
|
||||
if(CurrentIBufferIndex == 0)
|
||||
m_index_buffers[m_current_index_buffer]->Unlock();
|
||||
if(m_current_stride != stride || m_vertex_buffer_cursor == 0)
|
||||
{
|
||||
D3D::dev->SetIndices(IBuffers[CurrentIBuffer]);
|
||||
m_current_stride = stride;
|
||||
D3D::SetStreamSource( 0, m_vertex_buffers[m_current_vertex_buffer], 0, stride);
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::DrawVB(int stride)
|
||||
{
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
if (m_index_buffer_cursor == 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitive(
|
||||
D3DPT_TRIANGLELIST,
|
||||
0,
|
||||
0,
|
||||
IndexGenerator::GetNumVerts(),
|
||||
CurrentIBufferIndex,
|
||||
IndexGenerator::GetNumTriangles())))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumLines() > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitive(
|
||||
D3DPT_LINELIST,
|
||||
0,
|
||||
0,
|
||||
IndexGenerator::GetNumVerts(),
|
||||
CurrentIBufferIndex + IndexGenerator::GetTriangleindexLen(),
|
||||
IndexGenerator::GetNumLines())))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumPoints() > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitive(
|
||||
D3DPT_POINTLIST,
|
||||
0,
|
||||
0,
|
||||
IndexGenerator::GetNumVerts(),
|
||||
CurrentIBufferIndex + IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen(),
|
||||
IndexGenerator::GetNumPoints())))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
D3D::SetIndices(m_index_buffers[m_current_index_buffer]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VertexManager::DrawVA(int stride)
|
||||
{
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
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 the points one by one
|
||||
for (int i = 0; i < points; i++)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawPrimitive(
|
||||
D3DPT_POINTLIST,
|
||||
basevertex + GetPointIndexBuffer()[i],
|
||||
1)))
|
||||
{
|
||||
DumpBadShaders();
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numDrawCalls);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumTriangles(),
|
||||
0, numverts, triangles,
|
||||
GetTriangleIndexBuffer(),
|
||||
D3DFMT_INDEX16,
|
||||
s_pBaseBufferPointer,
|
||||
@@ -275,11 +290,11 @@ void VertexManager::DrawVA(int stride)
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumLines() > 0)
|
||||
if (lines > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_LINELIST,
|
||||
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumLines(),
|
||||
0, numverts, lines,
|
||||
GetLineIndexBuffer(),
|
||||
D3DFMT_INDEX16,
|
||||
s_pBaseBufferPointer,
|
||||
@@ -289,11 +304,11 @@ void VertexManager::DrawVA(int stride)
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (IndexGenerator::GetNumPoints() > 0)
|
||||
if (points > 0)
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
D3DPT_POINTLIST,
|
||||
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumPoints(),
|
||||
0, numverts, points,
|
||||
GetPointIndexBuffer(),
|
||||
D3DFMT_INDEX16,
|
||||
s_pBaseBufferPointer,
|
||||
@@ -345,7 +360,7 @@ void VertexManager::vFlush()
|
||||
// set global constants
|
||||
VertexShaderManager::SetConstants();
|
||||
PixelShaderManager::SetConstants();
|
||||
int stride = g_nativeVertexFmt->GetVertexStride();
|
||||
u32 stride = g_nativeVertexFmt->GetVertexStride();
|
||||
if (!PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
|
||||
@@ -357,9 +372,16 @@ void VertexManager::vFlush()
|
||||
goto shader_fail;
|
||||
|
||||
}
|
||||
PrepareVBuffers(stride);
|
||||
PrepareDrawBuffers(stride);
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
if(NumVBuffers){ DrawVB(stride);} else { DrawVA(stride);}
|
||||
if(m_buffers_count)
|
||||
{
|
||||
DrawVertexBuffer(stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawVertexArray(stride);
|
||||
}
|
||||
|
||||
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
|
||||
bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
@@ -372,16 +394,23 @@ void VertexManager::vFlush()
|
||||
}
|
||||
// update alpha only
|
||||
g_renderer->ApplyState(true);
|
||||
if(NumVBuffers){ DrawVB(stride);} else { DrawVA(stride);}
|
||||
if(m_buffers_count)
|
||||
{
|
||||
DrawVertexBuffer(stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawVertexArray(stride);
|
||||
}
|
||||
g_renderer->RestoreState();
|
||||
}
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
|
||||
|
||||
shader_fail:
|
||||
if(NumVBuffers)
|
||||
if(m_buffers_count)
|
||||
{
|
||||
CurrentIBufferIndex += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
|
||||
CurrentVBufferIndex += IndexGenerator::GetNumVerts() * stride;
|
||||
m_index_buffer_cursor += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
|
||||
m_vertex_buffer_cursor += IndexGenerator::GetNumVerts() * stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,18 +34,19 @@ public:
|
||||
void CreateDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
private:
|
||||
u32 CurrentVBufferIndex;
|
||||
u32 CurrentVBufferSize;
|
||||
u32 CurrentIBufferIndex;
|
||||
u32 CurrentIBufferSize;
|
||||
u32 NumVBuffers;
|
||||
u32 CurrentVBuffer;
|
||||
u32 CurrentIBuffer;
|
||||
LPDIRECT3DVERTEXBUFFER9 *VBuffers;
|
||||
LPDIRECT3DINDEXBUFFER9 *IBuffers;
|
||||
void PrepareVBuffers(int stride);
|
||||
void DrawVB(int stride);
|
||||
void DrawVA(int stride);
|
||||
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();
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ class VideoBackend : public VideoBackendHardware
|
||||
std::string GetName();
|
||||
|
||||
void Video_Prepare();
|
||||
void Video_Cleanup();
|
||||
|
||||
void ShowConfig(void* parent);
|
||||
|
||||
|
||||
@@ -191,6 +191,7 @@ void VideoBackend::Shutdown()
|
||||
{
|
||||
s_BackendInitialized = false;
|
||||
|
||||
// TODO: should be in Video_Cleanup
|
||||
if (g_renderer)
|
||||
{
|
||||
s_efbAccessRequested = FALSE;
|
||||
@@ -219,4 +220,7 @@ void VideoBackend::Shutdown()
|
||||
D3D::Shutdown();
|
||||
}
|
||||
|
||||
void VideoBackend::Video_Cleanup() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,8 +5,11 @@ set(SRCS Src/FramebufferManager.cpp
|
||||
Src/PerfQuery.cpp
|
||||
Src/PixelShaderCache.cpp
|
||||
Src/PostProcessing.cpp
|
||||
Src/ProgramShaderCache.cpp
|
||||
Src/RasterFont.cpp
|
||||
Src/Render.cpp
|
||||
Src/SamplerCache.cpp
|
||||
Src/StreamBuffer.cpp
|
||||
Src/TextureCache.cpp
|
||||
Src/TextureConverter.cpp
|
||||
Src/VertexShaderCache.cpp
|
||||
@@ -34,12 +37,6 @@ if(wxWidgets_FOUND)
|
||||
set(LIBS ${LIBS} ${wxWidgets_LIBRARIES})
|
||||
endif(wxWidgets_FOUND)
|
||||
|
||||
if(WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(LIBS ${LIBS} Cg CgGL)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
list(APPEND LIBS "${CMAKE_SOURCE_DIR}/Externals/Cg/Cg.framework")
|
||||
endif()
|
||||
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(LIBS ${LIBS} clrun)
|
||||
endif()
|
||||
|
||||
@@ -121,8 +121,8 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
<Lib />
|
||||
@@ -133,8 +133,8 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
<Lib />
|
||||
@@ -147,8 +147,8 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
<Lib />
|
||||
@@ -161,8 +161,8 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glu32.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
<Lib />
|
||||
@@ -175,8 +175,8 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
<Lib />
|
||||
@@ -189,8 +189,8 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>opengl32.lib;cg.lib;cgGL.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;..\..\..\Externals\Cg64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glu32.lib;glew64s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\GLew;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<OutputFile>..\..\..\Binary\$(PlatformName)\Plugins\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
<Lib />
|
||||
@@ -203,8 +203,11 @@
|
||||
<ClCompile Include="Src\PerfQuery.cpp" />
|
||||
<ClCompile Include="Src\PixelShaderCache.cpp" />
|
||||
<ClCompile Include="Src\PostProcessing.cpp" />
|
||||
<ClCompile Include="Src\ProgramShaderCache.cpp" />
|
||||
<ClCompile Include="Src\RasterFont.cpp" />
|
||||
<ClCompile Include="Src\Render.cpp" />
|
||||
<ClCompile Include="Src\SamplerCache.cpp" />
|
||||
<ClCompile Include="Src\StreamBuffer.cpp" />
|
||||
<ClCompile Include="Src\stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
@@ -224,15 +227,16 @@
|
||||
<ClInclude Include="Src\GLUtil.h" />
|
||||
<ClInclude Include="Src\main.h" />
|
||||
<ClInclude Include="Src\PerfQuery.h" />
|
||||
<ClInclude Include="Src\PixelShaderCache.h" />
|
||||
<ClInclude Include="Src\PostProcessing.h" />
|
||||
<ClInclude Include="Src\ProgramShaderCache.h" />
|
||||
<ClInclude Include="Src\RasterFont.h" />
|
||||
<ClInclude Include="Src\Render.h" />
|
||||
<ClInclude Include="Src\SamplerCache.h" />
|
||||
<ClInclude Include="Src\StreamBuffer.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>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -27,9 +27,15 @@
|
||||
<ClCompile Include="Src\PostProcessing.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\ProgramShaderCache.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\Render.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\StreamBuffer.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\TextureCache.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
@@ -60,10 +66,10 @@
|
||||
<ClInclude Include="Src\FramebufferManager.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\PixelShaderCache.h">
|
||||
<ClInclude Include="Src\PostProcessing.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\PostProcessing.h">
|
||||
<ClInclude Include="Src\ProgramShaderCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\Render.h">
|
||||
@@ -72,9 +78,6 @@
|
||||
<ClInclude Include="Src\TextureCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\VertexShaderCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\PerfQuery.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
@@ -96,4 +99,4 @@
|
||||
<UniqueIdentifier>{aaa16061-dca9-4155-be44-f77538e839fc}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "FramebufferManager.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
#include "TextureConverter.h"
|
||||
#include "Render.h"
|
||||
@@ -25,8 +26,6 @@
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp. ugly.
|
||||
|
||||
int FramebufferManager::m_targetWidth;
|
||||
int FramebufferManager::m_targetHeight;
|
||||
int FramebufferManager::m_msaaSamples;
|
||||
@@ -41,7 +40,7 @@ GLuint FramebufferManager::m_resolvedFramebuffer;
|
||||
GLuint FramebufferManager::m_resolvedColorTexture;
|
||||
GLuint FramebufferManager::m_resolvedDepthTexture;
|
||||
|
||||
GLuint FramebufferManager::m_xfbFramebuffer; // Only used in MSAA mode
|
||||
GLuint FramebufferManager::m_xfbFramebuffer;
|
||||
|
||||
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
|
||||
{
|
||||
@@ -52,7 +51,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
|
||||
m_resolvedColorTexture = 0;
|
||||
m_resolvedDepthTexture = 0;
|
||||
m_xfbFramebuffer = 0;
|
||||
|
||||
|
||||
m_targetWidth = targetWidth;
|
||||
m_targetHeight = targetHeight;
|
||||
|
||||
@@ -72,7 +71,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
|
||||
|
||||
// Create EFB target.
|
||||
|
||||
glGenFramebuffersEXT(1, &m_efbFramebuffer);
|
||||
glGenFramebuffers(1, &m_efbFramebuffer);
|
||||
|
||||
if (m_msaaSamples <= 1)
|
||||
{
|
||||
@@ -83,20 +82,20 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
|
||||
m_efbColor = glObj[0];
|
||||
m_efbDepth = glObj[1];
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbColor);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, m_efbColor);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbDepth);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, m_efbDepth);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, 0);
|
||||
|
||||
// Bind target textures to the EFB framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
|
||||
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, m_efbColor, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_RECTANGLE, m_efbDepth, 0);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
}
|
||||
@@ -109,67 +108,67 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
|
||||
// Create EFB target renderbuffers.
|
||||
|
||||
GLuint glObj[2];
|
||||
glGenRenderbuffersEXT(2, glObj);
|
||||
glGenRenderbuffers(2, glObj);
|
||||
m_efbColor = glObj[0];
|
||||
m_efbDepth = glObj[1];
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_efbColor);
|
||||
if (m_msaaCoverageSamples)
|
||||
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
||||
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
||||
else
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_efbDepth);
|
||||
if (m_msaaCoverageSamples)
|
||||
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
|
||||
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
|
||||
else
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
// Bind target renderbuffers to EFB framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
|
||||
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_efbColor);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_efbDepth);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_efbColor);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_efbDepth);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
|
||||
// Create resolved targets for transferring multisampled EFB to texture.
|
||||
|
||||
glGenFramebuffersEXT(1, &m_resolvedFramebuffer);
|
||||
glGenFramebuffers(1, &m_resolvedFramebuffer);
|
||||
|
||||
glGenTextures(2, glObj);
|
||||
m_resolvedColorTexture = glObj[0];
|
||||
m_resolvedDepthTexture = glObj[1];
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, m_resolvedColorTexture);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, m_resolvedDepthTexture);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, 0);
|
||||
|
||||
// Bind resolved textures to resolved framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer);
|
||||
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, m_resolvedColorTexture, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_RECTANGLE, m_resolvedDepthTexture, 0);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
|
||||
// Return to EFB framebuffer.
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
|
||||
}
|
||||
|
||||
// Create XFB framebuffer; targets will be created elsewhere.
|
||||
|
||||
glGenFramebuffersEXT(1, &m_xfbFramebuffer);
|
||||
|
||||
glGenFramebuffers(1, &m_xfbFramebuffer);
|
||||
|
||||
// EFB framebuffer is currently bound, make sure to clear its alpha value to 1.f
|
||||
glViewport(0, 0, m_targetWidth, m_targetHeight);
|
||||
glScissor(0, 0, m_targetWidth, m_targetHeight);
|
||||
@@ -180,7 +179,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
GLuint glObj[3];
|
||||
|
||||
@@ -189,7 +188,7 @@ FramebufferManager::~FramebufferManager()
|
||||
glObj[0] = m_efbFramebuffer;
|
||||
glObj[1] = m_resolvedFramebuffer;
|
||||
glObj[2] = m_xfbFramebuffer;
|
||||
glDeleteFramebuffersEXT(3, glObj);
|
||||
glDeleteFramebuffers(3, glObj);
|
||||
m_efbFramebuffer = 0;
|
||||
m_xfbFramebuffer = 0;
|
||||
|
||||
@@ -204,7 +203,7 @@ FramebufferManager::~FramebufferManager()
|
||||
if (m_msaaSamples <= 1)
|
||||
glDeleteTextures(2, glObj);
|
||||
else
|
||||
glDeleteRenderbuffersEXT(2, glObj);
|
||||
glDeleteRenderbuffers(2, glObj);
|
||||
m_efbColor = 0;
|
||||
m_efbDepth = 0;
|
||||
}
|
||||
@@ -224,16 +223,16 @@ GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
|
||||
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
|
||||
|
||||
// Resolve.
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
||||
glBlitFramebufferEXT(
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer);
|
||||
glBlitFramebuffer(
|
||||
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
|
||||
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST
|
||||
);
|
||||
|
||||
// Return to EFB.
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
|
||||
|
||||
return m_resolvedColorTexture;
|
||||
}
|
||||
@@ -254,16 +253,16 @@ GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc)
|
||||
targetRc.ClampLL(0, 0, m_targetWidth, m_targetHeight);
|
||||
|
||||
// Resolve.
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
||||
glBlitFramebufferEXT(
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer);
|
||||
glBlitFramebuffer(
|
||||
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
|
||||
targetRc.left, targetRc.top, targetRc.right, targetRc.bottom,
|
||||
GL_DEPTH_BUFFER_BIT, GL_NEAREST
|
||||
);
|
||||
|
||||
// Return to EFB.
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
|
||||
|
||||
return m_resolvedDepthTexture;
|
||||
}
|
||||
@@ -284,7 +283,7 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c
|
||||
|
||||
void FramebufferManager::SetFramebuffer(GLuint fb)
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb != 0 ? fb : GetEFBFramebuffer());
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb != 0 ? fb : GetEFBFramebuffer());
|
||||
}
|
||||
|
||||
// Apply AA if enabled
|
||||
@@ -298,106 +297,60 @@ GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_r
|
||||
return GetEFBDepthTexture(source_rect);
|
||||
}
|
||||
|
||||
XFBSource::~XFBSource()
|
||||
{
|
||||
glDeleteRenderbuffers(1, &renderbuf);
|
||||
}
|
||||
|
||||
|
||||
void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||
const MathUtil::Rectangle<float> &drawrc, int width, int height) const
|
||||
{
|
||||
// Texture map xfbSource->texture onto the main buffer
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(sourcerc.left, sourcerc.bottom);
|
||||
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0);
|
||||
glVertex2f(drawrc.left, drawrc.bottom);
|
||||
|
||||
glTexCoord2f(sourcerc.left, sourcerc.top);
|
||||
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1);
|
||||
glVertex2f(drawrc.left, drawrc.top);
|
||||
|
||||
glTexCoord2f(sourcerc.right, sourcerc.top);
|
||||
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1);
|
||||
glVertex2f(drawrc.right, drawrc.top);
|
||||
|
||||
glTexCoord2f(sourcerc.right, sourcerc.bottom);
|
||||
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0);
|
||||
glVertex2f(drawrc.right, drawrc.bottom);
|
||||
glEnd();
|
||||
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuf);
|
||||
glBlitFramebuffer(sourcerc.left, sourcerc.bottom, sourcerc.right, sourcerc.top,
|
||||
drawrc.left, drawrc.bottom, drawrc.right, drawrc.top,
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
|
||||
{
|
||||
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, texture);
|
||||
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, renderbuf);
|
||||
}
|
||||
|
||||
void XFBSource::CopyEFB(float Gamma)
|
||||
{
|
||||
// Copy EFB data to XFB and restore render target again
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetEFBFramebuffer());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer());
|
||||
|
||||
#if 0
|
||||
if (m_msaaSamples <= 1)
|
||||
#else
|
||||
if (!s_bHaveFramebufferBlit)
|
||||
#endif
|
||||
{
|
||||
// Just copy the EFB directly.
|
||||
// Bind texture.
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuf);
|
||||
GL_REPORT_FBO_ERROR();
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
|
||||
glBlitFramebuffer(
|
||||
0, 0, texWidth, texHeight,
|
||||
0, 0, texWidth, texHeight,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST
|
||||
);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, texWidth, texHeight, 0);
|
||||
// Return to EFB.
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// OpenGL cannot copy directly from a multisampled framebuffer, so use
|
||||
// EXT_framebuffer_blit.
|
||||
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
|
||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, FramebufferManager::GetXFBFramebuffer());
|
||||
|
||||
// Bind texture.
|
||||
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texture, 0);
|
||||
GL_REPORT_FBO_ERROR();
|
||||
|
||||
glBlitFramebufferEXT(
|
||||
0, 0, texWidth, texHeight,
|
||||
0, 0, texWidth, texHeight,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST
|
||||
);
|
||||
|
||||
// Unbind texture.
|
||||
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
|
||||
|
||||
// Return to EFB.
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferManager::GetEFBFramebuffer());
|
||||
}
|
||||
}
|
||||
|
||||
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||
{
|
||||
GLuint texture;
|
||||
GLuint renderbuf;
|
||||
|
||||
glGenTextures(1, &texture);
|
||||
glGenRenderbuffers(1, &renderbuf);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, renderbuf);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, target_width, target_height);
|
||||
|
||||
#if 0// XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible.
|
||||
if (m_msaaSamples > 1)
|
||||
#else
|
||||
if (s_bHaveFramebufferBlit)
|
||||
#endif
|
||||
{
|
||||
// In MSAA mode, allocate the texture image here. In non-MSAA mode,
|
||||
// the image will be allocated by glCopyTexImage2D (later).
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, target_width, target_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
}
|
||||
|
||||
return new XFBSource(texture);
|
||||
return new XFBSource(renderbuf);
|
||||
}
|
||||
|
||||
void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc)
|
||||
|
||||
@@ -57,15 +57,15 @@ namespace OGL {
|
||||
|
||||
struct XFBSource : public XFBSourceBase
|
||||
{
|
||||
XFBSource(GLuint tex) : texture(tex) {}
|
||||
~XFBSource() { glDeleteTextures(1, &texture); }
|
||||
XFBSource(GLuint rbuf) : renderbuf(rbuf) {}
|
||||
~XFBSource();
|
||||
|
||||
void CopyEFB(float Gamma);
|
||||
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||
void Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||
const MathUtil::Rectangle<float> &drawrc, int width, int height) const;
|
||||
|
||||
const GLuint texture;
|
||||
const GLuint renderbuf;
|
||||
};
|
||||
|
||||
class FramebufferManager : public FramebufferManagerBase
|
||||
|
||||
@@ -55,8 +55,6 @@ void InitInterface()
|
||||
GLInterface = new cInterfaceBase;
|
||||
#elif defined(USE_EGL) && USE_EGL
|
||||
GLInterface = new cInterfaceEGL;
|
||||
#elif defined(USE_WX) && USE_WX
|
||||
GLInterface = new cInterfaceWX;
|
||||
#elif defined(__APPLE__)
|
||||
GLInterface = new cInterfaceAGL;
|
||||
#elif defined(_WIN32)
|
||||
@@ -72,14 +70,14 @@ GLuint OpenGL_CompileProgram ( const char* vertexShader, const char* fragmentSha
|
||||
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
|
||||
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
GLuint programID = glCreateProgram();
|
||||
GLint Result = GL_FALSE;
|
||||
char stringBuffer[1024];
|
||||
GLsizei stringBufferUsage = 0;
|
||||
|
||||
// compile vertex shader
|
||||
glShaderSource(vertexShaderID, 1, &vertexShader, NULL);
|
||||
glCompileShader(vertexShaderID);
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL)
|
||||
GLint Result = GL_FALSE;
|
||||
char stringBuffer[1024];
|
||||
GLsizei stringBufferUsage = 0;
|
||||
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &Result);
|
||||
glGetShaderInfoLog(vertexShaderID, 1024, &stringBufferUsage, stringBuffer);
|
||||
if(Result && stringBufferUsage) {
|
||||
@@ -159,32 +157,26 @@ void OpenGL_ReportARBProgramError()
|
||||
bool OpenGL_ReportFBOError(const char *function, const char *file, int line)
|
||||
{
|
||||
#ifndef USE_GLES
|
||||
unsigned int fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
if (fbo_status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
unsigned int fbo_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (fbo_status != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
const char *error = "-";
|
||||
const char *error = "unknown error";
|
||||
switch (fbo_status)
|
||||
{
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
error = "INCOMPLETE_ATTACHMENT_EXT";
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
||||
error = "INCOMPLETE_ATTACHMENT";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
error = "INCOMPLETE_MISSING_ATTACHMENT_EXT";
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
||||
error = "INCOMPLETE_MISSING_ATTACHMENT";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
error = "INCOMPLETE_DIMENSIONS_EXT";
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
|
||||
error = "INCOMPLETE_DRAW_BUFFER";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
||||
error = "INCOMPLETE_FORMATS_EXT";
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
|
||||
error = "INCOMPLETE_READ_BUFFER";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
error = "INCOMPLETE_DRAW_BUFFER_EXT";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
error = "INCOMPLETE_READ_BUFFER_EXT";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
error = "UNSUPPORTED_EXT";
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED:
|
||||
error = "UNSUPPORTED";
|
||||
break;
|
||||
}
|
||||
ERROR_LOG(VIDEO, "%s:%d: (%s) OpenGL FBO error - %s\n",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#define TEX2D GL_TEXTURE_2D
|
||||
#define PREC "highp"
|
||||
#define TEXTYPE "sampler2D"
|
||||
#define TEXFUNC "texture2D"
|
||||
#define TEXFUNC "texture"
|
||||
#else
|
||||
#define TEX2D GL_TEXTURE_RECTANGLE_ARB
|
||||
#define PREC
|
||||
@@ -69,20 +69,16 @@ bool OpenGL_ReportFBOError(const char *function, const char *file, int line);
|
||||
#define GL_REPORT_PROGRAM_ERROR() (void)0
|
||||
#endif
|
||||
|
||||
#if (defined __APPLE__ || defined __linux__ || defined _WIN32) && !(defined _M_ARM)
|
||||
#include <Cg/cg.h>
|
||||
#include <Cg/cgGL.h>
|
||||
#define HAVE_CG 1
|
||||
extern CGcontext g_cgcontext;
|
||||
extern CGprofile g_cgvProf, g_cgfProf;
|
||||
// this should be removed in future, but as long as glsl is unstable, we should really read this messages
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
#define DEBUG_GLSL 1
|
||||
#else
|
||||
#define DEBUG_GLSL 0
|
||||
#endif
|
||||
|
||||
// XXX: Dual-source blending in OpenGL does not work correctly yet. To make it
|
||||
// work, we may need to use glBindFragDataLocation. To use that, we need to
|
||||
// use GLSL shaders across the whole pipeline. Yikes!
|
||||
//#define USE_DUAL_SOURCE_BLEND
|
||||
|
||||
// TODO: should be removed if we use glsl a lot
|
||||
#define DEBUG_GLSL
|
||||
// Isn't defined if we aren't using GLEW 1.6
|
||||
#ifndef GL_ONE_MINUS_SRC1_ALPHA
|
||||
#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
|
||||
#endif
|
||||
|
||||
#endif // _GLINIT_H_
|
||||
|
||||
@@ -19,54 +19,16 @@
|
||||
#include "x64Emitter.h"
|
||||
#include "x64ABI.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "ProgramShaderCache.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
#include "CPMemory.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "VertexManager.h"
|
||||
|
||||
#define COMPILED_CODE_SIZE 4096
|
||||
|
||||
// TODO: this guy is never initialized
|
||||
u32 s_prevcomponents; // previous state set
|
||||
/*
|
||||
#ifdef _WIN32
|
||||
#ifdef _M_IX86
|
||||
#define USE_JIT
|
||||
#endif
|
||||
#endif
|
||||
*/
|
||||
// Note the use of CallCdeclFunction3I etc.
|
||||
// This is a horrible hack that is necessary because in 64-bit mode, Opengl32.dll is based way, way above the 32-bit
|
||||
// address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we
|
||||
// want to grab the function pointers from the import table instead.
|
||||
|
||||
// This problem does not apply to glew functions, only core opengl32 functions.
|
||||
|
||||
// Here's some global state. We only use this to keep track of what we've sent to the OpenGL state
|
||||
// machine.
|
||||
|
||||
#ifdef USE_JIT
|
||||
DECLARE_IMPORT(glNormalPointer);
|
||||
DECLARE_IMPORT(glVertexPointer);
|
||||
DECLARE_IMPORT(glColorPointer);
|
||||
DECLARE_IMPORT(glTexCoordPointer);
|
||||
#endif
|
||||
|
||||
class GLVertexFormat : public NativeVertexFormat
|
||||
{
|
||||
u8 *m_compiledCode;
|
||||
PortableVertexDeclaration vtx_decl;
|
||||
|
||||
public:
|
||||
GLVertexFormat();
|
||||
~GLVertexFormat();
|
||||
|
||||
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
|
||||
virtual void SetupVertexPointers();
|
||||
virtual void EnableComponents(u32 components);
|
||||
};
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
@@ -75,23 +37,14 @@ NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
|
||||
return new GLVertexFormat();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GLVertexFormat::GLVertexFormat()
|
||||
{
|
||||
#ifdef USE_JIT
|
||||
m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false);
|
||||
if (m_compiledCode)
|
||||
memset(m_compiledCode, 0, COMPILED_CODE_SIZE);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
GLVertexFormat::~GLVertexFormat()
|
||||
{
|
||||
#ifdef USE_JIT
|
||||
FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE);
|
||||
m_compiledCode = 0;
|
||||
#endif
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
}
|
||||
|
||||
inline GLuint VarToGL(VarType t)
|
||||
@@ -104,183 +57,56 @@ inline GLuint VarToGL(VarType t)
|
||||
|
||||
void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
|
||||
{
|
||||
s_prevcomponents = 0;
|
||||
|
||||
vertex_stride = _vtx_decl.stride;
|
||||
using namespace Gen;
|
||||
this->vtx_decl = _vtx_decl;
|
||||
vertex_stride = vtx_decl.stride;
|
||||
|
||||
// We will not allow vertex components causing uneven strides.
|
||||
if (_vtx_decl.stride & 3)
|
||||
PanicAlert("Uneven vertex stride: %i", _vtx_decl.stride);
|
||||
|
||||
#ifdef USE_JIT
|
||||
Gen::XEmitter emit(m_compiledCode);
|
||||
// Alright, we have our vertex declaration. Compile some crazy code to set it quickly using GL.
|
||||
emit.ABI_EmitPrologue(6);
|
||||
if (vertex_stride & 3)
|
||||
PanicAlert("Uneven vertex stride: %i", vertex_stride);
|
||||
|
||||
emit.CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, _vtx_decl.stride, 0);
|
||||
VertexManager *vm = (OGL::VertexManager*)g_vertex_manager;
|
||||
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
// the element buffer is bound directly to the vao, so we must it set for every vao
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vm->m_index_buffers);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers);
|
||||
|
||||
if (_vtx_decl.num_normals >= 1)
|
||||
{
|
||||
emit.CallCdeclFunction3_I(glNormalPointer, VarToGL(_vtx_decl.normal_gl_type), _vtx_decl.stride, _vtx_decl.normal_offset[0]);
|
||||
if (_vtx_decl.num_normals == 3) {
|
||||
emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[1]);
|
||||
emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[2]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (_vtx_decl.color_offset[i] != -1)
|
||||
{
|
||||
if (i == 0)
|
||||
emit.CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]);
|
||||
else
|
||||
emit.CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (_vtx_decl.texcoord_offset[i] != -1)
|
||||
{
|
||||
int id = GL_TEXTURE0 + i;
|
||||
#ifdef _M_X64
|
||||
#ifdef _MSC_VER
|
||||
emit.MOV(32, R(RCX), Imm32(id));
|
||||
#else
|
||||
emit.MOV(32, R(RDI), Imm32(id));
|
||||
#endif
|
||||
#else
|
||||
emit.ABI_AlignStack(1 * 4);
|
||||
emit.PUSH(32, Imm32(id));
|
||||
#endif
|
||||
emit.CALL((void *)glClientActiveTexture);
|
||||
#ifndef _M_X64
|
||||
#ifdef _WIN32
|
||||
// don't inc stack on windows, stdcall
|
||||
#else
|
||||
emit.ABI_RestoreStack(1 * 4);
|
||||
#endif
|
||||
#endif
|
||||
emit.CallCdeclFunction4_I(
|
||||
glTexCoordPointer, _vtx_decl.texcoord_size[i], VarToGL(_vtx_decl.texcoord_gl_type[i]),
|
||||
_vtx_decl.stride, _vtx_decl.texcoord_offset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (_vtx_decl.posmtx_offset != -1)
|
||||
emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, _vtx_decl.stride, _vtx_decl.posmtx_offset);
|
||||
|
||||
emit.ABI_EmitEpilogue(6);
|
||||
|
||||
if (emit.GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE)
|
||||
Crash();
|
||||
|
||||
#endif
|
||||
this->vtx_decl = _vtx_decl;
|
||||
}
|
||||
|
||||
void GLVertexFormat::SetupVertexPointers() {
|
||||
// Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to
|
||||
// get around type checking errors, and call it.
|
||||
#ifdef USE_JIT
|
||||
((void (*)())(void*)m_compiledCode)();
|
||||
#else
|
||||
glVertexPointer(3, GL_FLOAT, vtx_decl.stride, VertexManager::s_pBaseBufferPointer);
|
||||
if (vtx_decl.num_normals >= 1) {
|
||||
glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[0]));
|
||||
if (vtx_decl.num_normals == 3) {
|
||||
glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[1]));
|
||||
glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[2]));
|
||||
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 3, GL_FLOAT, GL_FALSE, vtx_decl.stride, (u8*)NULL);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (vtx_decl.num_normals > i) {
|
||||
glEnableVertexAttribArray(SHADER_NORM0_ATTRIB+i);
|
||||
glVertexAttribPointer(SHADER_NORM0_ATTRIB+i, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (u8*)NULL + vtx_decl.normal_offset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (vtx_decl.color_offset[i] != -1) {
|
||||
if (i == 0)
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
|
||||
else {
|
||||
glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
|
||||
}
|
||||
glEnableVertexAttribArray(SHADER_COLOR0_ATTRIB+i);
|
||||
glVertexAttribPointer(SHADER_COLOR0_ATTRIB+i, 4, GL_UNSIGNED_BYTE, GL_TRUE, vtx_decl.stride, (u8*)NULL + vtx_decl.color_offset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (vtx_decl.texcoord_offset[i] != -1) {
|
||||
int id = GL_TEXTURE0 + i;
|
||||
glClientActiveTexture(id);
|
||||
glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]),
|
||||
vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.texcoord_offset[i]));
|
||||
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB+i);
|
||||
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB+i, vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]),
|
||||
GL_FALSE, vtx_decl.stride, (u8*)NULL + vtx_decl.texcoord_offset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (vtx_decl.posmtx_offset != -1) {
|
||||
glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.posmtx_offset));
|
||||
glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
|
||||
glVertexAttribIPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, vtx_decl.stride, (u8*)NULL + vtx_decl.posmtx_offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
vm->m_last_vao = VAO;
|
||||
}
|
||||
|
||||
void GLVertexFormat::SetupVertexPointers() {
|
||||
}
|
||||
|
||||
void GLVertexFormat::EnableComponents(u32 components)
|
||||
{
|
||||
if (s_prevcomponents != components)
|
||||
{
|
||||
VertexManager::Flush();
|
||||
|
||||
// matrices
|
||||
if ((components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX))
|
||||
{
|
||||
if (components & VB_HAS_POSMTXIDX)
|
||||
glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
|
||||
else
|
||||
glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB);
|
||||
}
|
||||
|
||||
// normals
|
||||
if ((components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0))
|
||||
{
|
||||
if (components & VB_HAS_NRM0)
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
else
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
if ((components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1))
|
||||
{
|
||||
if (components & VB_HAS_NRM1) {
|
||||
glEnableVertexAttribArray(SHADER_NORM1_ATTRIB);
|
||||
glEnableVertexAttribArray(SHADER_NORM2_ATTRIB);
|
||||
}
|
||||
else {
|
||||
glDisableVertexAttribArray(SHADER_NORM1_ATTRIB);
|
||||
glDisableVertexAttribArray(SHADER_NORM2_ATTRIB);
|
||||
}
|
||||
}
|
||||
|
||||
// color
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if ((components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i)))
|
||||
{
|
||||
if (components & (VB_HAS_COL0 << i))
|
||||
glEnableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
|
||||
else
|
||||
glDisableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
// tex
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i)))
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0 + i);
|
||||
if (components & (VB_HAS_UV0 << i))
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
else
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
s_prevcomponents = components;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,347 +27,88 @@
|
||||
#include "Common.h"
|
||||
#include "Render.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "ProgramShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "OnScreenDisplay.h"
|
||||
#include "StringUtil.h"
|
||||
#include "FileUtil.h"
|
||||
#include "Debugger.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
static int s_nMaxPixelInstructions;
|
||||
static GLuint s_ColorMatrixProgram = 0;
|
||||
static GLuint s_DepthMatrixProgram = 0;
|
||||
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
|
||||
PIXELSHADERUID PixelShaderCache::s_curuid;
|
||||
bool PixelShaderCache::s_displayCompileAlert;
|
||||
GLuint PixelShaderCache::CurrentShader;
|
||||
bool PixelShaderCache::ShaderEnabled;
|
||||
|
||||
PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry = NULL;
|
||||
PIXELSHADERUID PixelShaderCache::last_uid;
|
||||
|
||||
GLuint PixelShaderCache::GetDepthMatrixProgram()
|
||||
void SetPSConstant4fvByName(const char * name, unsigned int offset, const float *f, const unsigned int count = 1)
|
||||
{
|
||||
return s_DepthMatrixProgram;
|
||||
}
|
||||
|
||||
GLuint PixelShaderCache::GetColorMatrixProgram()
|
||||
{
|
||||
return s_ColorMatrixProgram;
|
||||
}
|
||||
|
||||
void PixelShaderCache::Init()
|
||||
{
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
ShaderEnabled = true;
|
||||
CurrentShader = 0;
|
||||
last_entry = NULL;
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
s_displayCompileAlert = true;
|
||||
|
||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions);
|
||||
|
||||
if(s_nMaxPixelInstructions == 0) // Some combination of drivers and hardware returns zero for some reason.
|
||||
s_nMaxPixelInstructions = 4096;
|
||||
if (strstr((const char*)glGetString(GL_VENDOR), "Humper") != NULL) s_nMaxPixelInstructions = 4096;
|
||||
#if CG_VERSION_NUM == 2100
|
||||
if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
|
||||
ProgramShaderCache::PCacheEntry tmp = ProgramShaderCache::GetShaderProgram();
|
||||
for (int a = 0; a < NUM_UNIFORMS; ++a)
|
||||
{
|
||||
s_nMaxPixelInstructions = 4096;
|
||||
}
|
||||
#endif
|
||||
|
||||
int maxinst, maxattribs;
|
||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&maxinst);
|
||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, (GLint *)&maxattribs);
|
||||
INFO_LOG(VIDEO, "pixel max_alu=%d, max_inst=%d, max_attrib=%d", s_nMaxPixelInstructions, maxinst, maxattribs);
|
||||
|
||||
char pmatrixprog[2048];
|
||||
sprintf(pmatrixprog, "!!ARBfp1.0"
|
||||
"TEMP R0;\n"
|
||||
"TEMP R1;\n"
|
||||
"PARAM K0 = { 0.5, 0.5, 0.5, 0.5};\n"
|
||||
"TEX R0, fragment.texcoord[0], texture[0], RECT;\n"
|
||||
"MUL R0, R0, program.env[%d];\n"
|
||||
"ADD R0, R0, K0;\n"
|
||||
"FLR R0, R0;\n"
|
||||
"MUL R0, R0, program.env[%d];\n"
|
||||
"DP4 R1.x, R0, program.env[%d];\n"
|
||||
"DP4 R1.y, R0, program.env[%d];\n"
|
||||
"DP4 R1.z, R0, program.env[%d];\n"
|
||||
"DP4 R1.w, R0, program.env[%d];\n"
|
||||
"ADD result.color, R1, program.env[%d];\n"
|
||||
"END\n",C_COLORMATRIX+5,C_COLORMATRIX+6, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+2, C_COLORMATRIX+3, C_COLORMATRIX+4);
|
||||
glGenProgramsARB(1, &s_ColorMatrixProgram);
|
||||
SetCurrentShader(s_ColorMatrixProgram);
|
||||
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);
|
||||
|
||||
GLenum err = GL_REPORT_ERROR();
|
||||
if (err != GL_NO_ERROR) {
|
||||
ERROR_LOG(VIDEO, "Failed to create color matrix fragment program");
|
||||
glDeleteProgramsARB(1, &s_ColorMatrixProgram);
|
||||
s_ColorMatrixProgram = 0;
|
||||
}
|
||||
|
||||
sprintf(pmatrixprog, "!!ARBfp1.0\n"
|
||||
"TEMP R0;\n"
|
||||
"TEMP R1;\n"
|
||||
"TEMP R2;\n"
|
||||
//16777215/16777216*256, 1/255, 256, 0
|
||||
"PARAM K0 = { 255.99998474121, 0.003921568627451, 256.0, 0.0};\n"
|
||||
"PARAM K1 = { 15.0, 0.066666666666, 0.0, 0.0};\n"
|
||||
//sample the depth value
|
||||
"TEX R2, fragment.texcoord[0], texture[0], RECT;\n"
|
||||
|
||||
//scale from [0*16777216..1*16777216] to
|
||||
//[0*16777215..1*16777215], multiply by 256
|
||||
"MUL R0, R2.x, K0.x;\n" // *16777215/16777216*256
|
||||
|
||||
//It is easy to get bad results due to low precision
|
||||
//here, for example converting like this:
|
||||
//MUL R0,R0,{ 65536, 256, 1, 16777216 }
|
||||
//FRC R0,R0
|
||||
//gives {?, 128/255, 254/255, ?} for depth value 254/255
|
||||
//on some gpus
|
||||
|
||||
"FLR R0.x,R0;\n" //bits 31..24
|
||||
|
||||
"SUB R0.yzw,R0,R0.x;\n" //subtract bits 31..24 from rest
|
||||
"MUL R0.yzw,R0,K0.z;\n" // *256
|
||||
"FLR R0.y,R0;\n" //bits 23..16
|
||||
|
||||
"SUB R0.zw,R0,R0.y;\n" //subtract bits 23..16 from rest
|
||||
"MUL R0.zw,R0,K0.z;\n" // *256
|
||||
"FLR R0.z,R0;\n" //bits 15..8
|
||||
|
||||
"MOV R0.w,R0.x;\n" //duplicate bit 31..24
|
||||
|
||||
"MUL R0,R0,K0.y;\n" // /255
|
||||
|
||||
"MUL R0.w,R0,K1.x;\n" // *15
|
||||
"FLR R0.w,R0;\n" //bits 31..28
|
||||
"MUL R0.w,R0,K1.y;\n" // /15
|
||||
|
||||
"DP4 R1.x, R0, program.env[%d];\n"
|
||||
"DP4 R1.y, R0, program.env[%d];\n"
|
||||
"DP4 R1.z, R0, program.env[%d];\n"
|
||||
"DP4 R1.w, R0, program.env[%d];\n"
|
||||
"ADD result.color, R1, program.env[%d];\n"
|
||||
"END\n", C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+2, C_COLORMATRIX+3, C_COLORMATRIX+4);
|
||||
glGenProgramsARB(1, &s_DepthMatrixProgram);
|
||||
SetCurrentShader(s_DepthMatrixProgram);
|
||||
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);
|
||||
|
||||
err = GL_REPORT_ERROR();
|
||||
if (err != GL_NO_ERROR) {
|
||||
ERROR_LOG(VIDEO, "Failed to create depth matrix fragment program");
|
||||
glDeleteProgramsARB(1, &s_DepthMatrixProgram);
|
||||
s_DepthMatrixProgram = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PixelShaderCache::Shutdown()
|
||||
{
|
||||
glDeleteProgramsARB(1, &s_ColorMatrixProgram);
|
||||
s_ColorMatrixProgram = 0;
|
||||
glDeleteProgramsARB(1, &s_DepthMatrixProgram);
|
||||
s_DepthMatrixProgram = 0;
|
||||
PSCache::iterator iter = PixelShaders.begin();
|
||||
for (; iter != PixelShaders.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
PixelShaders.clear();
|
||||
}
|
||||
|
||||
FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(&uid, dstAlphaMode, components);
|
||||
|
||||
// Check if the shader is already set
|
||||
if (last_entry)
|
||||
{
|
||||
if (uid == last_uid)
|
||||
if (!strcmp(name, UniformNames[a]))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
ValidatePixelShaderIDs(API_OPENGL, last_entry->safe_uid, last_entry->shader.strprog, dstAlphaMode, components);
|
||||
return &last_entry->shader;
|
||||
if (tmp.shader.UniformLocations[a] == -1)
|
||||
return;
|
||||
else
|
||||
{
|
||||
glUniform4fv(tmp.shader.UniformLocations[a] + offset, count, f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last_uid = uid;
|
||||
|
||||
PSCache::iterator iter = PixelShaders.find(uid);
|
||||
if (iter != PixelShaders.end())
|
||||
{
|
||||
PSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
ValidatePixelShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, dstAlphaMode, components);
|
||||
return &last_entry->shader;
|
||||
}
|
||||
|
||||
// Make an entry in the table
|
||||
PSCacheEntry& newentry = PixelShaders[uid];
|
||||
last_entry = &newentry;
|
||||
const char *code = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components);
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging && code)
|
||||
{
|
||||
GetSafePixelShaderId(&newentry.safe_uid, dstAlphaMode, components);
|
||||
newentry.shader.strprog = code;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
|
||||
|
||||
SaveData(szTemp, code);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!code || !CompilePixelShader(newentry.shader, code)) {
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
return &last_entry->shader;
|
||||
}
|
||||
|
||||
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
|
||||
{
|
||||
GLenum err = GL_REPORT_ERROR();
|
||||
if (err != GL_NO_ERROR)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "glError %08x before PS!", err);
|
||||
}
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
char stropt[128];
|
||||
sprintf(stropt, "MaxLocalParams=224,NumInstructionSlots=%d", s_nMaxPixelInstructions);
|
||||
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
|
||||
CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
|
||||
|
||||
// handle errors
|
||||
if (!cgIsProgram(tempprog))
|
||||
{
|
||||
cgDestroyProgram(tempprog);
|
||||
|
||||
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 << pstrprogram;
|
||||
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 (%d):\n%s",
|
||||
szTemp,
|
||||
g_cgfProf,
|
||||
cgGetLastListing(g_cgcontext));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// handle warnings
|
||||
if (cgGetError() != CG_NO_ERROR)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext));
|
||||
WARN_LOG(VIDEO, "%s", pstrprogram);
|
||||
}
|
||||
|
||||
// This looks evil - we modify the program through the const char * we got from cgGetProgramString!
|
||||
// It SHOULD not have any nasty side effects though - but you never know...
|
||||
char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
|
||||
char *plocal = strstr(pcompiledprog, "program.local");
|
||||
while (plocal != NULL)
|
||||
{
|
||||
const char *penv = " program.env";
|
||||
memcpy(plocal, penv, 13);
|
||||
plocal = strstr(plocal+13, "program.local");
|
||||
}
|
||||
|
||||
glGenProgramsARB(1, &ps.glprogid);
|
||||
SetCurrentShader(ps.glprogid);
|
||||
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
|
||||
|
||||
err = GL_REPORT_ERROR();
|
||||
if (err != GL_NO_ERROR)
|
||||
{
|
||||
GLint error_pos, native_limit;
|
||||
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
|
||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native_limit);
|
||||
// Error occur
|
||||
if (error_pos != -1) {
|
||||
const char *program_error = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
|
||||
char line[256];
|
||||
strncpy(line, (const char *)pcompiledprog + error_pos, 255);
|
||||
line[255] = 0;
|
||||
ERROR_LOG(VIDEO, "Error at %i: %s", error_pos, program_error);
|
||||
ERROR_LOG(VIDEO, "Line dump: \n%s", line);
|
||||
} else if (native_limit != -1) {
|
||||
ERROR_LOG(VIDEO, "Hit limit? %i", native_limit);
|
||||
// TODO
|
||||
}
|
||||
ERROR_LOG(VIDEO, "%s", pstrprogram);
|
||||
ERROR_LOG(VIDEO, "%s", pcompiledprog);
|
||||
}
|
||||
|
||||
cgDestroyProgram(tempprog);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Disable Fragment programs and reset the selected Program
|
||||
void PixelShaderCache::DisableShader()
|
||||
{
|
||||
if(ShaderEnabled)
|
||||
{
|
||||
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
ShaderEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
//bind a program if is diferent from the binded oone
|
||||
void PixelShaderCache::SetCurrentShader(GLuint Shader)
|
||||
{
|
||||
if(!ShaderEnabled)
|
||||
{
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
ShaderEnabled = true;
|
||||
}
|
||||
if(CurrentShader != Shader)
|
||||
{
|
||||
if(Shader != 0)
|
||||
CurrentShader = Shader;
|
||||
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, CurrentShader);
|
||||
}
|
||||
}
|
||||
|
||||
// Renderer functions
|
||||
void Renderer::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
float f[4] = { f1, f2, f3, f4 };
|
||||
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
|
||||
float const f[4] = {f1, f2, f3, f4};
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
ProgramShaderCache::SetMultiPSConstant4fv(const_number, f, 1);
|
||||
return;
|
||||
}
|
||||
for (unsigned int a = 0; a < 10; ++a)
|
||||
{
|
||||
if (const_number >= PSVar_Loc[a].reg && const_number < (PSVar_Loc[a].reg + PSVar_Loc[a].size))
|
||||
{
|
||||
unsigned int offset = const_number - PSVar_Loc[a].reg;
|
||||
SetPSConstant4fvByName(PSVar_Loc[a].name, offset, f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetPSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
ProgramShaderCache::SetMultiPSConstant4fv(const_number, f, 1);
|
||||
return;
|
||||
}
|
||||
for (unsigned int a = 0; a < 10; ++a)
|
||||
{
|
||||
if (const_number >= PSVar_Loc[a].reg && const_number < (PSVar_Loc[a].reg + PSVar_Loc[a].size))
|
||||
{
|
||||
unsigned int offset = const_number - PSVar_Loc[a].reg;
|
||||
SetPSConstant4fvByName(PSVar_Loc[a].name, offset, f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++,f+=4)
|
||||
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number + i, f);
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
ProgramShaderCache::SetMultiPSConstant4fv(const_number, f, count);
|
||||
return;
|
||||
}
|
||||
for (unsigned int a = 0; a < 10; ++a)
|
||||
{
|
||||
if (const_number >= PSVar_Loc[a].reg && const_number < (PSVar_Loc[a].reg + PSVar_Loc[a].size))
|
||||
{
|
||||
unsigned int offset = const_number - PSVar_Loc[a].reg;
|
||||
SetPSConstant4fvByName(PSVar_Loc[a].name, offset, f, count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OGL
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _PIXELSHADERCACHE_H_
|
||||
#define _PIXELSHADERCACHE_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "BPMemory.h"
|
||||
#include "PixelShaderGen.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
struct FRAGMENTSHADER
|
||||
{
|
||||
FRAGMENTSHADER() : glprogid(0) { }
|
||||
void Destroy()
|
||||
{
|
||||
if (glprogid)
|
||||
{
|
||||
glDeleteProgramsARB(1, &glprogid);
|
||||
glprogid = 0;
|
||||
}
|
||||
}
|
||||
GLuint glprogid; // opengl program id
|
||||
std::string strprog;
|
||||
};
|
||||
|
||||
class PixelShaderCache
|
||||
{
|
||||
struct PSCacheEntry
|
||||
{
|
||||
FRAGMENTSHADER shader;
|
||||
PSCacheEntry() {}
|
||||
~PSCacheEntry() {}
|
||||
void Destroy()
|
||||
{
|
||||
shader.Destroy();
|
||||
}
|
||||
PIXELSHADERUIDSAFE safe_uid;
|
||||
};
|
||||
|
||||
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
|
||||
|
||||
static PSCache PixelShaders;
|
||||
|
||||
static PIXELSHADERUID s_curuid; // the current pixel shader uid (progressively changed as memory is written)
|
||||
|
||||
static bool s_displayCompileAlert;
|
||||
|
||||
static GLuint CurrentShader;
|
||||
static PSCacheEntry* last_entry;
|
||||
static PIXELSHADERUID last_uid;
|
||||
|
||||
static bool ShaderEnabled;
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
static FRAGMENTSHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components);
|
||||
static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram);
|
||||
|
||||
static GLuint GetColorMatrixProgram();
|
||||
|
||||
static GLuint GetDepthMatrixProgram();
|
||||
|
||||
static void SetCurrentShader(GLuint Shader);
|
||||
|
||||
static void DisableShader();
|
||||
};
|
||||
|
||||
} // namespace OGL
|
||||
|
||||
#endif // _PIXELSHADERCACHE_H_
|
||||
@@ -20,7 +20,8 @@
|
||||
#include "VideoConfig.h"
|
||||
#include "GLUtil.h"
|
||||
#include "PostProcessing.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "ProgramShaderCache.h"
|
||||
#include "FramebufferManager.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
@@ -29,16 +30,72 @@ namespace PostProcessing
|
||||
{
|
||||
|
||||
static std::string s_currentShader;
|
||||
static FRAGMENTSHADER s_shader;
|
||||
static SHADER s_shader;
|
||||
static bool s_enable;
|
||||
|
||||
static u32 s_width;
|
||||
static u32 s_height;
|
||||
static GLuint s_fbo;
|
||||
static GLuint s_texture;
|
||||
static GLuint s_vao;
|
||||
static GLuint s_vbo;
|
||||
|
||||
static GLuint s_uniform_resolution;
|
||||
|
||||
static char s_vertex_shader[] =
|
||||
"in vec2 rawpos;\n"
|
||||
"in vec2 tex0;\n"
|
||||
"out vec2 uv0;\n"
|
||||
"void main(void) {\n"
|
||||
" gl_Position = vec4(rawpos,0,1);\n"
|
||||
" uv0 = tex0;\n"
|
||||
"}\n";
|
||||
|
||||
void Init()
|
||||
{
|
||||
s_currentShader = "";
|
||||
s_enable = 0;
|
||||
s_width = 0;
|
||||
s_height = 0;
|
||||
|
||||
glGenFramebuffers(1, &s_fbo);
|
||||
glGenTextures(1, &s_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, s_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); // disable mipmaps
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, s_fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, s_texture, 0);
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
|
||||
glGenBuffers(1, &s_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_vbo);
|
||||
GLfloat vertices[] = {
|
||||
-1.f, -1.f, 0.f, 0.f,
|
||||
-1.f, 1.f, 0.f, 1.f,
|
||||
1.f, -1.f, 1.f, 0.f,
|
||||
1.f, 1.f, 1.f, 1.f
|
||||
};
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glGenVertexArrays(1, &s_vao);
|
||||
glBindVertexArray( s_vao );
|
||||
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, NULL);
|
||||
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
s_shader.Destroy();
|
||||
|
||||
glDeleteFramebuffers(1, &s_vbo);
|
||||
glDeleteTextures(1, &s_texture);
|
||||
|
||||
glDeleteBuffers(1, &s_vbo);
|
||||
glDeleteVertexArrays(1, &s_vao);
|
||||
}
|
||||
|
||||
void ReloadShader()
|
||||
@@ -46,45 +103,83 @@ void ReloadShader()
|
||||
s_currentShader = "";
|
||||
}
|
||||
|
||||
bool ApplyShader()
|
||||
void BindTargetFramebuffer ()
|
||||
{
|
||||
if (s_currentShader != File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt")
|
||||
{
|
||||
// Set immediately to prevent endless recompiles on failure.
|
||||
if (!g_ActiveConfig.sPostProcessingShader.empty())
|
||||
s_currentShader = File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt";
|
||||
else
|
||||
s_currentShader.clear();
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_enable ? s_fbo : 0);
|
||||
}
|
||||
|
||||
s_shader.Destroy();
|
||||
void BlitToScreen()
|
||||
{
|
||||
if(!s_enable) return;
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glViewport(0, 0, s_width, s_height);
|
||||
|
||||
glBindVertexArray(s_vao);
|
||||
s_shader.Bind();
|
||||
|
||||
glUniform4f(s_uniform_resolution, (float)s_width, (float)s_height, 1.0f/(float)s_width, 1.0f/(float)s_height);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+9);
|
||||
glBindTexture(GL_TEXTURE_2D, s_texture);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
/* glBindFramebuffer(GL_READ_FRAMEBUFFER, s_fbo);
|
||||
|
||||
glBlitFramebuffer(rc.left, rc.bottom, rc.right, rc.top,
|
||||
rc.left, rc.bottom, rc.right, rc.top,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);*/
|
||||
}
|
||||
|
||||
if (!s_currentShader.empty())
|
||||
{
|
||||
std::string code;
|
||||
if (File::ReadFileToString(true, s_currentShader.c_str(), code))
|
||||
{
|
||||
if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str()))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
void Update ( u32 width, u32 height )
|
||||
{
|
||||
ApplyShader();
|
||||
|
||||
if (s_shader.glprogid != 0)
|
||||
{
|
||||
PixelShaderCache::SetCurrentShader(s_shader.glprogid);
|
||||
return true;
|
||||
if(s_enable && (width != s_width || height != s_height)) {
|
||||
s_width = width;
|
||||
s_height = height;
|
||||
|
||||
// alloc texture for framebuffer
|
||||
glActiveTexture(GL_TEXTURE0+9);
|
||||
glBindTexture(GL_TEXTURE_2D, s_texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
PixelShaderCache::DisableShader();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ApplyShader()
|
||||
{
|
||||
// shader didn't changed
|
||||
if (s_currentShader == g_ActiveConfig.sPostProcessingShader) return;
|
||||
s_currentShader = g_ActiveConfig.sPostProcessingShader;
|
||||
s_enable = false;
|
||||
s_shader.Destroy();
|
||||
|
||||
// shader disabled
|
||||
if (g_ActiveConfig.sPostProcessingShader == "") return;
|
||||
|
||||
// so need to compile shader
|
||||
|
||||
// loading shader code
|
||||
std::string code;
|
||||
std::string path = File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".txt";
|
||||
if(!File::ReadFileToString(true, path.c_str(), code)) {
|
||||
ERROR_LOG(VIDEO, "post-processing shader not found: %s", path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// and compile it
|
||||
if (!ProgramShaderCache::CompileShader(s_shader, s_vertex_shader, code.c_str())) {
|
||||
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// read uniform locations
|
||||
s_uniform_resolution = glGetUniformLocation(s_shader.glprogid, "resolution");
|
||||
|
||||
// successful
|
||||
s_enable = true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -30,9 +30,13 @@ namespace PostProcessing
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void BindTargetFramebuffer();
|
||||
void BlitToScreen();
|
||||
void Update(u32 width, u32 height);
|
||||
|
||||
void ReloadShader();
|
||||
// Returns false if no shader was applied.
|
||||
bool ApplyShader();
|
||||
|
||||
void ApplyShader();
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -0,0 +1,551 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "ProgramShaderCache.h"
|
||||
#include "MathUtil.h"
|
||||
#include "StreamBuffer.h"
|
||||
#include "Debugger.h"
|
||||
#include "Statistics.h"
|
||||
#include "ImageWrite.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
static const u32 UBO_LENGTH = 32*1024*1024;
|
||||
|
||||
GLintptr ProgramShaderCache::s_vs_data_offset;
|
||||
u8 *ProgramShaderCache::s_ubo_buffer;
|
||||
u32 ProgramShaderCache::s_ubo_buffer_size;
|
||||
bool ProgramShaderCache::s_ubo_dirty;
|
||||
|
||||
static StreamBuffer *s_buffer;
|
||||
|
||||
LinearDiskCache<SHADERUID, u8> g_program_disk_cache;
|
||||
static GLuint CurrentProgram = 0;
|
||||
ProgramShaderCache::PCache ProgramShaderCache::pshaders;
|
||||
ProgramShaderCache::PCacheEntry* ProgramShaderCache::last_entry;
|
||||
SHADERUID ProgramShaderCache::last_uid;
|
||||
|
||||
static char s_glsl_header[1024] = "";
|
||||
|
||||
const char *UniformNames[NUM_UNIFORMS] =
|
||||
{
|
||||
// PIXEL SHADER UNIFORMS
|
||||
I_COLORS,
|
||||
I_KCOLORS,
|
||||
I_ALPHA,
|
||||
I_TEXDIMS,
|
||||
I_ZBIAS ,
|
||||
I_INDTEXSCALE ,
|
||||
I_INDTEXMTX,
|
||||
I_FOG,
|
||||
I_PLIGHTS,
|
||||
I_PMATERIALS,
|
||||
// VERTEX SHADER UNIFORMS
|
||||
I_POSNORMALMATRIX,
|
||||
I_PROJECTION ,
|
||||
I_MATERIALS,
|
||||
I_LIGHTS,
|
||||
I_TEXMATRICES,
|
||||
I_TRANSFORMMATRICES ,
|
||||
I_NORMALMATRICES ,
|
||||
I_POSTTRANSFORMMATRICES,
|
||||
I_DEPTHPARAMS,
|
||||
};
|
||||
|
||||
void SHADER::SetProgramVariables()
|
||||
{
|
||||
// glsl shader must be bind to set samplers
|
||||
Bind();
|
||||
|
||||
// Bind UBO
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
GLint PSBlock_id = glGetUniformBlockIndex(glprogid, "PSBlock");
|
||||
GLint VSBlock_id = glGetUniformBlockIndex(glprogid, "VSBlock");
|
||||
|
||||
if(PSBlock_id != -1)
|
||||
glUniformBlockBinding(glprogid, PSBlock_id, 1);
|
||||
if(VSBlock_id != -1)
|
||||
glUniformBlockBinding(glprogid, VSBlock_id, 2);
|
||||
}
|
||||
|
||||
// We cache our uniform locations for now
|
||||
// Once we move up to a newer version of GLSL, ~1.30
|
||||
// We can remove this
|
||||
|
||||
// (Sonicadvance): For some reason this fails on my hardware
|
||||
//glGetUniformIndices(glprogid, NUM_UNIFORMS, UniformNames, UniformLocations);
|
||||
// Got to do it this crappy way.
|
||||
UniformLocations[0] = glGetUniformLocation(glprogid, UniformNames[0]);
|
||||
if (!g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
for (int a = 1; a < NUM_UNIFORMS; ++a)
|
||||
UniformLocations[a] = glGetUniformLocation(glprogid, UniformNames[a]);
|
||||
|
||||
// Bind Texture Sampler
|
||||
for (int a = 0; a <= 9; ++a)
|
||||
{
|
||||
char name[8];
|
||||
snprintf(name, 8, "samp%d", a);
|
||||
|
||||
// Still need to get sampler locations since we aren't binding them statically in the shaders
|
||||
int loc = glGetUniformLocation(glprogid, name);
|
||||
if (loc != -1)
|
||||
glUniform1i(loc, a);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SHADER::SetProgramBindings()
|
||||
{
|
||||
if (g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
|
||||
{
|
||||
// So we do support extended blending
|
||||
// So we need to set a few more things here.
|
||||
// Bind our out locations
|
||||
glBindFragDataLocationIndexed(glprogid, 0, 0, "ocol0");
|
||||
glBindFragDataLocationIndexed(glprogid, 0, 1, "ocol1");
|
||||
}
|
||||
else
|
||||
glBindFragDataLocation(glprogid, 0, "ocol0");
|
||||
|
||||
// Need to set some attribute locations
|
||||
glBindAttribLocation(glprogid, SHADER_POSITION_ATTRIB, "rawpos");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_POSMTX_ATTRIB, "fposmtx");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_COLOR0_ATTRIB, "color0");
|
||||
glBindAttribLocation(glprogid, SHADER_COLOR1_ATTRIB, "color1");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_NORM0_ATTRIB, "rawnorm0");
|
||||
glBindAttribLocation(glprogid, SHADER_NORM1_ATTRIB, "rawnorm1");
|
||||
glBindAttribLocation(glprogid, SHADER_NORM2_ATTRIB, "rawnorm2");
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
char attrib_name[8];
|
||||
snprintf(attrib_name, 8, "tex%d", i);
|
||||
glBindAttribLocation(glprogid, SHADER_TEXTURE0_ATTRIB+i, attrib_name);
|
||||
}
|
||||
}
|
||||
|
||||
void SHADER::Bind()
|
||||
{
|
||||
if(CurrentProgram != glprogid)
|
||||
{
|
||||
glUseProgram(glprogid);
|
||||
CurrentProgram = glprogid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ProgramShaderCache::SetMultiPSConstant4fv(unsigned int offset, const float *f, unsigned int count)
|
||||
{
|
||||
s_ubo_dirty = true;
|
||||
memcpy(s_ubo_buffer+(offset*4*sizeof(float)), f, count*4*sizeof(float));
|
||||
}
|
||||
|
||||
void ProgramShaderCache::SetMultiVSConstant4fv(unsigned int offset, const float *f, unsigned int count)
|
||||
{
|
||||
s_ubo_dirty = true;
|
||||
memcpy(s_ubo_buffer+(offset*4*sizeof(float))+s_vs_data_offset, f, count*4*sizeof(float));
|
||||
}
|
||||
|
||||
void ProgramShaderCache::UploadConstants()
|
||||
{
|
||||
if(s_ubo_dirty) {
|
||||
s_buffer->Alloc(s_ubo_buffer_size);
|
||||
size_t offset = s_buffer->Upload(s_ubo_buffer, s_ubo_buffer_size);
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, 1, s_buffer->getBuffer(), offset, s_vs_data_offset);
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, 2, s_buffer->getBuffer(), offset + s_vs_data_offset, s_ubo_buffer_size - s_vs_data_offset);
|
||||
s_ubo_dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint ProgramShaderCache::GetCurrentProgram(void)
|
||||
{
|
||||
return CurrentProgram;
|
||||
}
|
||||
|
||||
SHADER* ProgramShaderCache::SetShader ( DSTALPHA_MODE dstAlphaMode, u32 components )
|
||||
{
|
||||
SHADERUID uid;
|
||||
GetShaderId(&uid, dstAlphaMode, components);
|
||||
|
||||
// Check if the shader is already set
|
||||
if (last_entry)
|
||||
{
|
||||
if (uid == last_uid)
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
ValidateShaderIDs(last_entry, dstAlphaMode, components);
|
||||
last_entry->shader.Bind();
|
||||
return &last_entry->shader;
|
||||
}
|
||||
}
|
||||
|
||||
last_uid = uid;
|
||||
|
||||
// Check if shader is already in cache
|
||||
PCache::iterator iter = pshaders.find(uid);
|
||||
if (iter != pshaders.end())
|
||||
{
|
||||
PCacheEntry *entry = &iter->second;
|
||||
last_entry = entry;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
ValidateShaderIDs(entry, dstAlphaMode, components);
|
||||
last_entry->shader.Bind();
|
||||
return &last_entry->shader;
|
||||
}
|
||||
|
||||
// Make an entry in the table
|
||||
PCacheEntry& newentry = pshaders[uid];
|
||||
last_entry = &newentry;
|
||||
newentry.in_cache = 0;
|
||||
|
||||
const char *vcode = GenerateVertexShaderCode(components, API_OPENGL);
|
||||
const char *pcode = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components);
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
GetSafeShaderId(&newentry.safe_uid, dstAlphaMode, components);
|
||||
newentry.shader.strvprog = vcode;
|
||||
newentry.shader.strpprog = pcode;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS) {
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
|
||||
SaveData(szTemp, vcode);
|
||||
sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
|
||||
SaveData(szTemp, pcode);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!CompileShader(newentry.shader, vcode, pcode)) {
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, pshaders.size());
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
|
||||
last_entry->shader.Bind();
|
||||
return &last_entry->shader;
|
||||
}
|
||||
|
||||
bool ProgramShaderCache::CompileShader ( SHADER& shader, const char* vcode, const char* pcode )
|
||||
{
|
||||
GLuint vsid = CompileSingleShader(GL_VERTEX_SHADER, vcode);
|
||||
GLuint psid = CompileSingleShader(GL_FRAGMENT_SHADER, pcode);
|
||||
|
||||
if(!vsid || !psid)
|
||||
{
|
||||
glDeleteShader(vsid);
|
||||
glDeleteShader(psid);
|
||||
return false;
|
||||
}
|
||||
|
||||
GLuint pid = shader.glprogid = glCreateProgram();;
|
||||
|
||||
glAttachShader(pid, vsid);
|
||||
glAttachShader(pid, psid);
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLCache)
|
||||
glProgramParameteri(pid, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
||||
|
||||
shader.SetProgramBindings();
|
||||
|
||||
glLinkProgram(pid);
|
||||
|
||||
// original shaders aren't needed any more
|
||||
glDeleteShader(vsid);
|
||||
glDeleteShader(psid);
|
||||
|
||||
GLint linkStatus;
|
||||
glGetProgramiv(pid, GL_LINK_STATUS, &linkStatus);
|
||||
GLsizei length = 0;
|
||||
glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &length);
|
||||
if (linkStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
|
||||
{
|
||||
GLsizei charsWritten;
|
||||
GLchar* infoLog = new GLchar[length];
|
||||
glGetProgramInfoLog(pid, length, &charsWritten, infoLog);
|
||||
ERROR_LOG(VIDEO, "Program info log:\n%s", infoLog);
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sp_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), pid);
|
||||
std::ofstream file;
|
||||
OpenFStream(file, szTemp, std::ios_base::out);
|
||||
file << infoLog << s_glsl_header << vcode << s_glsl_header << pcode;
|
||||
file.close();
|
||||
delete [] infoLog;
|
||||
}
|
||||
if (linkStatus != GL_TRUE)
|
||||
{
|
||||
// Compile failed
|
||||
ERROR_LOG(VIDEO, "Program linking failed; see info log");
|
||||
|
||||
// Don't try to use this shader
|
||||
glDeleteProgram(pid);
|
||||
return false;
|
||||
}
|
||||
|
||||
shader.SetProgramVariables();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLuint ProgramShaderCache::CompileSingleShader (GLuint type, const char* code )
|
||||
{
|
||||
GLuint result = glCreateShader(type);
|
||||
|
||||
const char *src[] = {s_glsl_header, code};
|
||||
|
||||
glShaderSource(result, 2, src, NULL);
|
||||
glCompileShader(result);
|
||||
GLint compileStatus;
|
||||
glGetShaderiv(result, GL_COMPILE_STATUS, &compileStatus);
|
||||
GLsizei length = 0;
|
||||
glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length);
|
||||
if (compileStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
|
||||
{
|
||||
GLsizei charsWritten;
|
||||
GLchar* infoLog = new GLchar[length];
|
||||
glGetShaderInfoLog(result, length, &charsWritten, infoLog);
|
||||
ERROR_LOG(VIDEO, "PS Shader info log:\n%s", infoLog);
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%sps_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), result);
|
||||
std::ofstream file;
|
||||
OpenFStream(file, szTemp, std::ios_base::out);
|
||||
file << infoLog << s_glsl_header << code;
|
||||
file.close();
|
||||
delete[] infoLog;
|
||||
}
|
||||
if (compileStatus != GL_TRUE)
|
||||
{
|
||||
// Compile failed
|
||||
ERROR_LOG(VIDEO, "Shader compilation failed; see info log");
|
||||
|
||||
// Don't try to use this shader
|
||||
glDeleteShader(result);
|
||||
return 0;
|
||||
}
|
||||
(void)GL_REPORT_ERROR();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ProgramShaderCache::GetShaderId ( SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 components )
|
||||
{
|
||||
GetPixelShaderId(&uid->puid, dstAlphaMode, components);
|
||||
GetVertexShaderId(&uid->vuid, components);
|
||||
}
|
||||
|
||||
void ProgramShaderCache::GetSafeShaderId ( SHADERUIDSAFE* uid, DSTALPHA_MODE dstAlphaMode, u32 components )
|
||||
{
|
||||
GetSafePixelShaderId(&uid->puid, dstAlphaMode, components);
|
||||
GetSafeVertexShaderId(&uid->vuid, components);
|
||||
}
|
||||
|
||||
void ProgramShaderCache::ValidateShaderIDs ( PCacheEntry *entry, DSTALPHA_MODE dstAlphaMode, u32 components )
|
||||
{
|
||||
ValidateVertexShaderIDs(API_OPENGL, entry->safe_uid.vuid, entry->shader.strvprog, components);
|
||||
ValidatePixelShaderIDs(API_OPENGL, entry->safe_uid.puid, entry->shader.strpprog, dstAlphaMode, components);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ProgramShaderCache::PCacheEntry ProgramShaderCache::GetShaderProgram(void)
|
||||
{
|
||||
return *last_entry;
|
||||
}
|
||||
|
||||
void ProgramShaderCache::Init(void)
|
||||
{
|
||||
// We have to get the UBO alignment here because
|
||||
// if we generate a buffer that isn't aligned
|
||||
// then the UBO will fail.
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
GLint Align;
|
||||
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &Align);
|
||||
|
||||
GLintptr const ps_data_size = ROUND_UP(C_PENVCONST_END * sizeof(float) * 4, Align);
|
||||
GLintptr const vs_data_size = ROUND_UP(C_VENVCONST_END * sizeof(float) * 4, Align);
|
||||
s_vs_data_offset = ps_data_size;
|
||||
s_ubo_buffer_size = ps_data_size + vs_data_size;
|
||||
|
||||
// We multiply by *4*4 because we need to get down to basic machine units.
|
||||
// So multiply by four to get how many floats we have from vec4s
|
||||
// Then once more to get bytes
|
||||
s_buffer = new StreamBuffer(GL_UNIFORM_BUFFER, UBO_LENGTH);
|
||||
|
||||
s_ubo_buffer = new u8[s_ubo_buffer_size];
|
||||
memset(s_ubo_buffer, 0, s_ubo_buffer_size);
|
||||
s_ubo_dirty = true;
|
||||
}
|
||||
|
||||
// Read our shader cache, only if supported
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLCache)
|
||||
{
|
||||
GLint Supported;
|
||||
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &Supported);
|
||||
if(!Supported)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "GL_ARB_get_program_binary is supported, but no binary format is known. So disable shader cache.");
|
||||
g_ActiveConfig.backend_info.bSupportsGLSLCache = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
|
||||
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str());
|
||||
|
||||
char cache_filename[MAX_PATH];
|
||||
sprintf(cache_filename, "%sogl-%s-shaders.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
|
||||
|
||||
ProgramShaderCacheInserter inserter;
|
||||
g_program_disk_cache.OpenAndRead(cache_filename, inserter);
|
||||
}
|
||||
SETSTAT(stats.numPixelShadersAlive, pshaders.size());
|
||||
}
|
||||
|
||||
CreateHeader();
|
||||
|
||||
CurrentProgram = 0;
|
||||
last_entry = NULL;
|
||||
}
|
||||
|
||||
void ProgramShaderCache::Shutdown(void)
|
||||
{
|
||||
// store all shaders in cache on disk
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLCache)
|
||||
{
|
||||
PCache::iterator iter = pshaders.begin();
|
||||
for (; iter != pshaders.end(); ++iter)
|
||||
{
|
||||
if(iter->second.in_cache) continue;
|
||||
|
||||
GLint binary_size;
|
||||
glGetProgramiv(iter->second.shader.glprogid, GL_PROGRAM_BINARY_LENGTH, &binary_size);
|
||||
if(!binary_size) continue;
|
||||
|
||||
u8 *data = new u8[binary_size+sizeof(GLenum)];
|
||||
u8 *binary = data + sizeof(GLenum);
|
||||
GLenum *prog_format = (GLenum*)data;
|
||||
glGetProgramBinary(iter->second.shader.glprogid, binary_size, NULL, prog_format, binary);
|
||||
|
||||
g_program_disk_cache.Append(iter->first, data, binary_size+sizeof(GLenum));
|
||||
delete [] data;
|
||||
}
|
||||
|
||||
g_program_disk_cache.Sync();
|
||||
g_program_disk_cache.Close();
|
||||
}
|
||||
|
||||
glUseProgram(0);
|
||||
|
||||
PCache::iterator iter = pshaders.begin();
|
||||
for (; iter != pshaders.end(); ++iter)
|
||||
iter->second.Destroy();
|
||||
pshaders.clear();
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
delete s_buffer;
|
||||
s_buffer = 0;
|
||||
delete [] s_ubo_buffer;
|
||||
s_ubo_buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ProgramShaderCache::CreateHeader ( void )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Intel Windows driver has a issue:
|
||||
// their glsl doesn't know about the ubo extension, so we can't load it.
|
||||
// but as version 140, ubo is in core and don't have to be loaded in glsl.
|
||||
// as sandy do ogl3.1, glsl 140 is supported, so force it in this way.
|
||||
// TODO: remove this again when the issue is fixed:
|
||||
// see http://communities.intel.com/thread/36084
|
||||
char *vendor = (char*)glGetString(GL_VENDOR);
|
||||
bool glsl140_hack = strcmp(vendor, "Intel") == 0;
|
||||
#elif __APPLE__
|
||||
// as apple doesn't support glsl130 at all, we also have to use glsl140
|
||||
bool glsl140_hack = true;
|
||||
#else
|
||||
bool glsl140_hack = false;
|
||||
#endif
|
||||
|
||||
snprintf(s_glsl_header, sizeof(s_glsl_header),
|
||||
"#version %s\n"
|
||||
"%s\n" // tex_rect
|
||||
"%s\n" // ubo
|
||||
|
||||
"\n"// A few required defines and ones that will make our lives a lot easier
|
||||
"#define ATTRIN in\n"
|
||||
"#define ATTROUT out\n"
|
||||
"#define VARYIN in\n"
|
||||
"#define VARYOUT out\n"
|
||||
|
||||
// Silly differences
|
||||
"#define float2 vec2\n"
|
||||
"#define float3 vec3\n"
|
||||
"#define float4 vec4\n"
|
||||
|
||||
// hlsl to glsl function translation
|
||||
"#define frac(x) fract(x)\n"
|
||||
"#define saturate(x) clamp(x, 0.0f, 1.0f)\n"
|
||||
"#define lerp(x, y, z) mix(x, y, z)\n"
|
||||
|
||||
|
||||
, glsl140_hack ? "140" : "130"
|
||||
, glsl140_hack ? "#define texture2DRect texture" : "#extension GL_ARB_texture_rectangle : enable"
|
||||
, g_ActiveConfig.backend_info.bSupportsGLSLUBO && !glsl140_hack ? "#extension GL_ARB_uniform_buffer_object : enable" : "// ubo disabled"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void ProgramShaderCache::ProgramShaderCacheInserter::Read ( const SHADERUID& key, const u8* value, u32 value_size )
|
||||
{
|
||||
const u8 *binary = value+sizeof(GLenum);
|
||||
GLenum *prog_format = (GLenum*)value;
|
||||
GLint binary_size = value_size-sizeof(GLenum);
|
||||
|
||||
PCacheEntry entry;
|
||||
entry.in_cache = 1;
|
||||
entry.shader.glprogid = glCreateProgram();
|
||||
glProgramBinary(entry.shader.glprogid, *prog_format, binary, binary_size);
|
||||
|
||||
GLint success;
|
||||
glGetProgramiv(entry.shader.glprogid, GL_LINK_STATUS, &success);
|
||||
|
||||
if (success)
|
||||
{
|
||||
pshaders[key] = entry;
|
||||
entry.shader.SetProgramVariables();
|
||||
}
|
||||
else
|
||||
glDeleteProgram(entry.shader.glprogid);
|
||||
}
|
||||
|
||||
|
||||
} // namespace OGL
|
||||
@@ -0,0 +1,135 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef PROGRAM_SHADER_CACHE_H_
|
||||
#define PROGRAM_SHADER_CACHE_H_
|
||||
|
||||
#include "GLUtil.h"
|
||||
|
||||
#include "PixelShaderGen.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
#include "LinearDiskCache.h"
|
||||
#include "ConfigManager.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
template<bool safe>
|
||||
class _SHADERUID
|
||||
{
|
||||
public:
|
||||
_VERTEXSHADERUID<safe> vuid;
|
||||
_PIXELSHADERUID<safe> puid;
|
||||
|
||||
_SHADERUID() {}
|
||||
|
||||
_SHADERUID(const _SHADERUID& r) : vuid(r.vuid), puid(r.puid) {}
|
||||
|
||||
bool operator <(const _SHADERUID& r) const
|
||||
{
|
||||
if(puid < r.puid) return true;
|
||||
if(r.puid < puid) return false;
|
||||
if(vuid < r.vuid) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator ==(const _SHADERUID& r) const
|
||||
{
|
||||
return puid == r.puid && vuid == r.vuid;
|
||||
}
|
||||
};
|
||||
typedef _SHADERUID<false> SHADERUID;
|
||||
typedef _SHADERUID<true> SHADERUIDSAFE;
|
||||
|
||||
|
||||
const int NUM_UNIFORMS = 19;
|
||||
extern const char *UniformNames[NUM_UNIFORMS];
|
||||
|
||||
struct SHADER
|
||||
{
|
||||
SHADER() : glprogid(0) { }
|
||||
void Destroy()
|
||||
{
|
||||
glDeleteProgram(glprogid);
|
||||
glprogid = 0;
|
||||
}
|
||||
GLuint glprogid; // opengl program id
|
||||
|
||||
std::string strvprog, strpprog;
|
||||
GLint UniformLocations[NUM_UNIFORMS];
|
||||
|
||||
void SetProgramVariables();
|
||||
void SetProgramBindings();
|
||||
void Bind();
|
||||
};
|
||||
|
||||
class ProgramShaderCache
|
||||
{
|
||||
public:
|
||||
|
||||
struct PCacheEntry
|
||||
{
|
||||
SHADER shader;
|
||||
SHADERUIDSAFE safe_uid;
|
||||
bool in_cache;
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
shader.Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
static PCacheEntry GetShaderProgram(void);
|
||||
static GLuint GetCurrentProgram(void);
|
||||
static SHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components);
|
||||
static void GetShaderId(SHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 components);
|
||||
static void GetSafeShaderId(SHADERUIDSAFE *uid, DSTALPHA_MODE dstAlphaMode, u32 components);
|
||||
static void ValidateShaderIDs(PCacheEntry *entry, DSTALPHA_MODE dstAlphaMode, u32 components);
|
||||
|
||||
static bool CompileShader(SHADER &shader, const char* vcode, const char* pcode);
|
||||
static GLuint CompileSingleShader(GLuint type, const char *code);
|
||||
|
||||
static void SetMultiPSConstant4fv(unsigned int offset, const float *f, unsigned int count);
|
||||
static void SetMultiVSConstant4fv(unsigned int offset, const float *f, unsigned int count);
|
||||
static void UploadConstants();
|
||||
|
||||
static void Init(void);
|
||||
static void Shutdown(void);
|
||||
static void CreateHeader(void);
|
||||
|
||||
private:
|
||||
class ProgramShaderCacheInserter : public LinearDiskCacheReader<SHADERUID, u8>
|
||||
{
|
||||
public:
|
||||
void Read(const SHADERUID &key, const u8 *value, u32 value_size);
|
||||
};
|
||||
|
||||
typedef std::map<SHADERUID, PCacheEntry> PCache;
|
||||
|
||||
static PCache pshaders;
|
||||
static PCacheEntry* last_entry;
|
||||
static SHADERUID last_uid;
|
||||
|
||||
static GLintptr s_vs_data_offset;
|
||||
static u8 *s_ubo_buffer;
|
||||
static u32 s_ubo_buffer_size;
|
||||
static bool s_ubo_dirty;
|
||||
};
|
||||
|
||||
} // namespace OGL
|
||||
#endif
|
||||
@@ -17,12 +17,18 @@
|
||||
|
||||
#include "GLUtil.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "RasterFont.h"
|
||||
#include "ProgramShaderCache.h"
|
||||
// globals
|
||||
|
||||
const GLubyte rasters[][13] = {
|
||||
namespace OGL {
|
||||
|
||||
static const u32 char_width = 8;
|
||||
static const u32 char_height = 13;
|
||||
static const u32 char_offset = 32;
|
||||
static const u32 char_count = 95;
|
||||
|
||||
const u8 rasters[char_count][char_height] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
|
||||
@@ -120,104 +126,159 @@ const GLubyte rasters[][13] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
|
||||
};
|
||||
|
||||
static const char *s_vertexShaderSrc =
|
||||
"uniform vec2 charSize;\n"
|
||||
"in vec2 rawpos;\n"
|
||||
"in vec2 tex0;\n"
|
||||
"out vec2 uv0;\n"
|
||||
"void main(void) {\n"
|
||||
" gl_Position = vec4(rawpos,0,1);\n"
|
||||
" uv0 = tex0 * charSize;\n"
|
||||
"}\n";
|
||||
|
||||
static const char *s_fragmentShaderSrc =
|
||||
"uniform sampler2D samp8;\n"
|
||||
"uniform vec4 color;\n"
|
||||
"in vec2 uv0;\n"
|
||||
"out vec4 ocol0;\n"
|
||||
"void main(void) {\n"
|
||||
" ocol0 = texture(samp8,uv0) * color;\n"
|
||||
"}\n";
|
||||
|
||||
static SHADER s_shader;
|
||||
|
||||
RasterFont::RasterFont()
|
||||
{
|
||||
// set GL modes
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
// create the raster font
|
||||
fontOffset = glGenLists(128);
|
||||
for (int i = 32; i < 127; i++) {
|
||||
glNewList(i + fontOffset, GL_COMPILE);
|
||||
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
|
||||
glEndList();
|
||||
// generate the texture
|
||||
glGenTextures(1, &texture);
|
||||
glActiveTexture(GL_TEXTURE0+8);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
u32* texture_data = new u32[char_width*char_count*char_height];
|
||||
for(u32 y=0; y<char_height; y++) {
|
||||
for(u32 c=0; c<char_count; c++) {
|
||||
for(u32 x=0; x<char_width; x++) {
|
||||
bool pixel = rasters[c][y] & (1<<(char_width-x-1));
|
||||
texture_data[char_width*char_count*y+char_width*c+x] = pixel ? -1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
temp_buffer = new char[TEMP_BUFFER_SIZE];
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, char_width*char_count, char_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
|
||||
delete [] texture_data;
|
||||
|
||||
// generate shader
|
||||
ProgramShaderCache::CompileShader(s_shader, s_vertexShaderSrc, s_fragmentShaderSrc);
|
||||
|
||||
// bound uniforms
|
||||
glUniform2f(glGetUniformLocation(s_shader.glprogid,"charSize"), 1.0f / GLfloat(char_count), 1.0f);
|
||||
uniform_color_id = glGetUniformLocation(s_shader.glprogid,"color");
|
||||
glUniform4f(uniform_color_id, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
cached_color = -1;
|
||||
|
||||
// generate VBO & VAO
|
||||
glGenBuffers(1, &VBO);
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBindVertexArray(VAO);
|
||||
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, NULL);
|
||||
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
|
||||
}
|
||||
|
||||
RasterFont::~RasterFont()
|
||||
{
|
||||
glDeleteLists(fontOffset, 128);
|
||||
delete [] temp_buffer;
|
||||
glDeleteTextures(1, &texture);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
s_shader.Destroy();
|
||||
}
|
||||
|
||||
void RasterFont::printString(const char *s, double x, double y, double z)
|
||||
void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight, u32 color)
|
||||
{
|
||||
int length = (int)strlen(s);
|
||||
if (!length)
|
||||
return;
|
||||
if (length >= TEMP_BUFFER_SIZE)
|
||||
length = TEMP_BUFFER_SIZE - 1;
|
||||
|
||||
// Sanitize string to avoid GL errors.
|
||||
char *s2 = temp_buffer;
|
||||
memcpy(s2, s, length);
|
||||
s2[length] = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (s2[i] < 32 || s2[i] > 126)
|
||||
s2[i] = '!';
|
||||
}
|
||||
|
||||
// go to the right spot
|
||||
glRasterPos3d(x, y, z);
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
glPushAttrib (GL_LIST_BIT);
|
||||
glListBase(fontOffset);
|
||||
glCallLists((GLsizei)strlen(s2), GL_UNSIGNED_BYTE, (GLubyte *) s2);
|
||||
GL_REPORT_ERRORD();
|
||||
glPopAttrib();
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)
|
||||
{
|
||||
int length = (int)strlen(s);
|
||||
int x = (int)(screen_width/2.0 - (length/2.0)*char_width);
|
||||
printString(s, x, y, z);
|
||||
}
|
||||
|
||||
void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight)
|
||||
{
|
||||
double x = start_x;
|
||||
double y = start_y;
|
||||
char temp[1024];
|
||||
char *t = temp;
|
||||
while (*text)
|
||||
{
|
||||
if (*text == '\n')
|
||||
{
|
||||
*t = 0;
|
||||
printString(temp, x, y, z);
|
||||
y -= char_height * 2.0f / bbHeight;
|
||||
size_t length = strlen(text);
|
||||
GLfloat *vertices = new GLfloat[length*6*4];
|
||||
|
||||
int usage = 0;
|
||||
GLfloat delta_x = GLfloat(2*char_width)/GLfloat(bbWidth);
|
||||
GLfloat delta_y = GLfloat(2*char_height)/GLfloat(bbHeight);
|
||||
GLfloat border_x = 2.0/GLfloat(bbWidth);
|
||||
GLfloat border_y = 4.0/GLfloat(bbHeight);
|
||||
|
||||
GLfloat x = GLfloat(start_x);
|
||||
GLfloat y = GLfloat(start_y);
|
||||
|
||||
for(size_t i=0; i<length; i++) {
|
||||
u8 c = text[i];
|
||||
|
||||
if(c == '\n') {
|
||||
x = start_x;
|
||||
t = temp;
|
||||
y -= delta_y + border_y;
|
||||
continue;
|
||||
}
|
||||
else if (*text == '\r')
|
||||
{
|
||||
t = temp;
|
||||
|
||||
// do not print spaces, they can be skipped easyly
|
||||
if(c == ' ') {
|
||||
x += delta_x + border_x;
|
||||
continue;
|
||||
}
|
||||
else if (*text == '\t')
|
||||
{
|
||||
//todo: add tabs every something like 4*char_width
|
||||
*t = 0;
|
||||
int cpos = (int)strlen(temp);
|
||||
int newpos = (cpos + 4) & (~3);
|
||||
printString(temp, x, y, z);
|
||||
x = start_x + (char_width*newpos) * 2.0f / bbWidth;
|
||||
t = temp;
|
||||
*t++ = ' ';
|
||||
}
|
||||
else
|
||||
*t++ = *text;
|
||||
|
||||
text++;
|
||||
|
||||
if(c < char_offset || c >= char_count+char_offset) continue;
|
||||
|
||||
vertices[usage++] = x;
|
||||
vertices[usage++] = y;
|
||||
vertices[usage++] = GLfloat(c-char_offset);
|
||||
vertices[usage++] = 0.0f;
|
||||
|
||||
vertices[usage++] = x+delta_x;
|
||||
vertices[usage++] = y;
|
||||
vertices[usage++] = GLfloat(c-char_offset+1);
|
||||
vertices[usage++] = 0.0f;
|
||||
|
||||
vertices[usage++] = x+delta_x;
|
||||
vertices[usage++] = y+delta_y;
|
||||
vertices[usage++] = GLfloat(c-char_offset+1);
|
||||
vertices[usage++] = 1.0f;
|
||||
|
||||
vertices[usage++] = x;
|
||||
vertices[usage++] = y;
|
||||
vertices[usage++] = GLfloat(c-char_offset);
|
||||
vertices[usage++] = 0.0f;
|
||||
|
||||
vertices[usage++] = x+delta_x;
|
||||
vertices[usage++] = y+delta_y;
|
||||
vertices[usage++] = GLfloat(c-char_offset+1);
|
||||
vertices[usage++] = 1.0f;
|
||||
|
||||
vertices[usage++] = x;
|
||||
vertices[usage++] = y+delta_y;
|
||||
vertices[usage++] = GLfloat(c-char_offset);
|
||||
vertices[usage++] = 1.0f;
|
||||
|
||||
x += delta_x + border_x;
|
||||
}
|
||||
|
||||
// ????
|
||||
if (t != text)
|
||||
{
|
||||
*t = 0;
|
||||
printString(temp, x, y, z);
|
||||
|
||||
if(!usage) {
|
||||
delete [] vertices;
|
||||
return;
|
||||
}
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, usage*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
|
||||
|
||||
delete [] vertices;
|
||||
|
||||
s_shader.Bind();
|
||||
|
||||
if(color != cached_color) {
|
||||
glUniform4f(uniform_color_id, GLfloat((color>>16)&0xff)/255.f,GLfloat((color>>8)&0xff)/255.f,GLfloat((color>>0)&0xff)/255.f,GLfloat((color>>24)&0xff)/255.f);
|
||||
cached_color = color;
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+8);
|
||||
glDrawArrays(GL_TRIANGLES, 0, usage/4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,25 +18,24 @@
|
||||
#ifndef _RASTERFONT_H_
|
||||
#define _RASTERFONT_H_
|
||||
|
||||
namespace OGL {
|
||||
|
||||
class RasterFont {
|
||||
public:
|
||||
RasterFont();
|
||||
~RasterFont(void);
|
||||
static int debug;
|
||||
|
||||
// some useful constants
|
||||
enum {char_width = 10};
|
||||
enum {char_height = 15};
|
||||
|
||||
// and the happy helper functions
|
||||
void printString(const char *s, double x, double y, double z=0.0);
|
||||
void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
|
||||
|
||||
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
|
||||
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight, u32 color);
|
||||
private:
|
||||
int fontOffset;
|
||||
char *temp_buffer;
|
||||
enum {TEMP_BUFFER_SIZE = 64 * 1024};
|
||||
|
||||
u32 VBO;
|
||||
u32 VAO;
|
||||
u32 texture;
|
||||
u32 uniform_color_id;
|
||||
u32 cached_color;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _RASTERFONT_H_
|
||||
|
||||
@@ -44,9 +44,8 @@
|
||||
#include "RasterFont.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "DLCache.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "ProgramShaderCache.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexLoaderManager.h"
|
||||
#include "VertexLoader.h"
|
||||
@@ -64,6 +63,8 @@
|
||||
#include "BPFunctions.h"
|
||||
#include "FPSCounter.h"
|
||||
#include "ConfigManager.h"
|
||||
#include "VertexManager.h"
|
||||
#include "SamplerCache.h"
|
||||
|
||||
#include "main.h" // Local
|
||||
#ifdef _WIN32
|
||||
@@ -95,11 +96,6 @@ typedef struct
|
||||
} ScrStrct;
|
||||
#endif
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
CGcontext g_cgcontext;
|
||||
CGprofile g_cgvProf;
|
||||
CGprofile g_cgfProf;
|
||||
#endif
|
||||
|
||||
int OSDInternalW, OSDInternalH;
|
||||
|
||||
@@ -108,17 +104,18 @@ namespace OGL
|
||||
|
||||
// Declarations and definitions
|
||||
// ----------------------------
|
||||
int s_fps=0;
|
||||
static int s_fps = 0;
|
||||
static GLuint s_ShowEFBCopyRegions_VBO = 0;
|
||||
static GLuint s_ShowEFBCopyRegions_VAO = 0;
|
||||
static SHADER s_ShowEFBCopyRegions;
|
||||
|
||||
|
||||
RasterFont* s_pfont = NULL;
|
||||
static RasterFont* s_pfont = NULL;
|
||||
|
||||
// 1 for no MSAA. Use s_MSAASamples > 1 to check for MSAA.
|
||||
static int s_MSAASamples = 1;
|
||||
static int s_MSAACoverageSamples = 0;
|
||||
static int s_LastMultisampleMode = 0;
|
||||
|
||||
bool s_bHaveFramebufferBlit = false; // export to FramebufferManager.cpp
|
||||
static bool s_bHaveCoverageMSAA = false;
|
||||
static u32 s_blendMode;
|
||||
|
||||
@@ -127,29 +124,14 @@ static std::thread scrshotThread;
|
||||
#endif
|
||||
|
||||
// EFB cache related
|
||||
const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks.
|
||||
const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up
|
||||
const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE;
|
||||
static const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks.
|
||||
static const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up
|
||||
static const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE;
|
||||
static bool s_efbCacheValid[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT];
|
||||
static std::vector<u32> s_efbCache[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; // 2 for PEEK_Z and PEEK_COLOR
|
||||
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
|
||||
{
|
||||
DEBUG_LOG(VIDEO, "Cg error: %s", cgGetErrorString(err));
|
||||
const char* listing = cgGetLastListing(g_cgcontext);
|
||||
if (listing != NULL)
|
||||
DEBUG_LOG(VIDEO, " last listing: %s", listing);
|
||||
}
|
||||
#endif
|
||||
|
||||
int GetNumMSAASamples(int MSAAMode)
|
||||
{
|
||||
// required for MSAA
|
||||
if (!s_bHaveFramebufferBlit)
|
||||
return 1;
|
||||
|
||||
switch (MSAAMode)
|
||||
{
|
||||
case MULTISAMPLE_OFF:
|
||||
@@ -200,39 +182,23 @@ Renderer::Renderer()
|
||||
OSDInternalH = 0;
|
||||
|
||||
s_fps=0;
|
||||
s_ShowEFBCopyRegions_VBO = 0;
|
||||
s_blendMode = 0;
|
||||
|
||||
InitFPSCounter();
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
g_cgcontext = cgCreateContext();
|
||||
cgGetError();
|
||||
cgSetErrorHandler(HandleCgError, NULL);
|
||||
#endif
|
||||
|
||||
// Look for required extensions.
|
||||
const char *ptoken = (const char*)glGetString(GL_EXTENSIONS);
|
||||
if (!ptoken)
|
||||
{
|
||||
PanicAlert("Your OpenGL Driver seems to be not working.\n"
|
||||
"Please make sure your drivers are up-to-date and\n"
|
||||
"that your video hardware is OpenGL 2.x compatible.");
|
||||
return; // TODO: fail
|
||||
}
|
||||
|
||||
INFO_LOG(VIDEO, "Supported OpenGL Extensions:");
|
||||
INFO_LOG(VIDEO, "%s", ptoken); // write to the log file
|
||||
INFO_LOG(VIDEO, "\n");
|
||||
|
||||
const char* gl_vendor = (const char*)glGetString(GL_VENDOR);
|
||||
const char* gl_renderer = (const char*)glGetString(GL_RENDERER);
|
||||
const char* gl_version = (const char*)glGetString(GL_VERSION);
|
||||
|
||||
OSD::AddMessage(StringFromFormat("Video Info: %s, %s, %s",
|
||||
glGetString(GL_VENDOR),
|
||||
glGetString(GL_RENDERER),
|
||||
glGetString(GL_VERSION)).c_str(), 5000);
|
||||
gl_vendor,
|
||||
gl_renderer,
|
||||
gl_version).c_str(), 5000);
|
||||
|
||||
bool bSuccess = true;
|
||||
GLint numvertexattribs = 0;
|
||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &numvertexattribs);
|
||||
if (numvertexattribs < 11)
|
||||
if (numvertexattribs < 16)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "GPU: OGL ERROR: Number of attributes %d not enough.\n"
|
||||
"GPU: Does your video card support OpenGL 2.x?",
|
||||
@@ -241,19 +207,15 @@ Renderer::Renderer()
|
||||
}
|
||||
|
||||
// Init extension support.
|
||||
#ifdef __APPLE__
|
||||
glewExperimental = 1;
|
||||
#endif
|
||||
if (glewInit() != GLEW_OK)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "glewInit() failed! Does your video card support OpenGL 2.x?");
|
||||
return; // TODO: fail
|
||||
}
|
||||
|
||||
if (!GLEW_EXT_framebuffer_object)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "GPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets.\n"
|
||||
"GPU: Does your video card support OpenGL 2.x?");
|
||||
bSuccess = false;
|
||||
}
|
||||
|
||||
if (!GLEW_EXT_secondary_color)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_EXT_secondary_color.\n"
|
||||
@@ -261,9 +223,60 @@ Renderer::Renderer()
|
||||
bSuccess = false;
|
||||
}
|
||||
|
||||
s_bHaveFramebufferBlit = strstr(ptoken, "GL_EXT_framebuffer_blit") != NULL;
|
||||
s_bHaveCoverageMSAA = strstr(ptoken, "GL_NV_framebuffer_multisample_coverage") != NULL;
|
||||
if (!GLEW_ARB_framebuffer_object)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "GPU: ERROR: Need GL_ARB_framebufer_object for multiple render targets.\n"
|
||||
"GPU: Does your video card support OpenGL 3.0?");
|
||||
bSuccess = false;
|
||||
}
|
||||
|
||||
if (!GLEW_ARB_vertex_array_object)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_vertex_array_object.\n"
|
||||
"GPU: Does your video card support OpenGL 3.0?");
|
||||
bSuccess = false;
|
||||
}
|
||||
|
||||
if (!GLEW_ARB_map_buffer_range)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_map_buffer_range.\n"
|
||||
"GPU: Does your video card support OpenGL 3.0?");
|
||||
bSuccess = false;
|
||||
}
|
||||
|
||||
if (!GLEW_ARB_sampler_objects)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_sampler_objects.");
|
||||
bSuccess = false;
|
||||
}
|
||||
|
||||
s_bHaveCoverageMSAA = GLEW_NV_framebuffer_multisample_coverage;
|
||||
|
||||
g_Config.backend_info.bSupportsDualSourceBlend = GLEW_ARB_blend_func_extended;
|
||||
g_Config.backend_info.bSupportsGLSLUBO = GLEW_ARB_uniform_buffer_object;
|
||||
g_Config.backend_info.bSupportsGLPinnedMemory = GLEW_AMD_pinned_memory;
|
||||
g_Config.backend_info.bSupportsGLSync = GLEW_ARB_sync;
|
||||
g_Config.backend_info.bSupportsGLSLCache = GLEW_ARB_get_program_binary;
|
||||
g_Config.backend_info.bSupportsGLBaseVertex = GLEW_ARB_draw_elements_base_vertex;
|
||||
|
||||
if(g_Config.backend_info.bSupportsGLSLUBO && (
|
||||
// hd3000 get corruption, hd4000 also and a big slowdown
|
||||
!strcmp(gl_vendor, "Intel Open Source Technology Center") && (!strcmp(gl_version, "3.0 Mesa 9.0.0") || !strcmp(gl_version, "3.0 Mesa 9.0.1") || !strcmp(gl_version, "3.0 Mesa 9.0.2") || !strcmp(gl_version, "3.0 Mesa 9.0.3") || !strcmp(gl_version, "3.0 Mesa 9.1.0") )
|
||||
)) {
|
||||
g_Config.backend_info.bSupportsGLSLUBO = false;
|
||||
ERROR_LOG(VIDEO, "buggy driver detected. Disable UBO");
|
||||
}
|
||||
|
||||
UpdateActiveConfig();
|
||||
OSD::AddMessage(StringFromFormat("Missing Extensions: %s%s%s%s%s%s",
|
||||
g_ActiveConfig.backend_info.bSupportsDualSourceBlend ? "" : "DualSourceBlend ",
|
||||
g_ActiveConfig.backend_info.bSupportsGLSLUBO ? "" : "UniformBuffer ",
|
||||
g_ActiveConfig.backend_info.bSupportsGLPinnedMemory ? "" : "PinnedMemory ",
|
||||
g_ActiveConfig.backend_info.bSupportsGLSLCache ? "" : "ShaderCache ",
|
||||
g_ActiveConfig.backend_info.bSupportsGLBaseVertex ? "" : "BaseVertex ",
|
||||
g_ActiveConfig.backend_info.bSupportsGLSync ? "" : "Sync "
|
||||
).c_str(), 5000);
|
||||
|
||||
s_LastMultisampleMode = g_ActiveConfig.iMultisampleMode;
|
||||
s_MSAASamples = GetNumMSAASamples(s_LastMultisampleMode);
|
||||
s_MSAACoverageSamples = GetNumMSAACoverageSamples(s_LastMultisampleMode);
|
||||
@@ -289,9 +302,6 @@ Renderer::Renderer()
|
||||
if (GL_REPORT_ERROR() != GL_NO_ERROR)
|
||||
bSuccess = false;
|
||||
|
||||
if (glDrawBuffers == NULL && !GLEW_ARB_draw_buffers)
|
||||
glDrawBuffers = glDrawBuffersARB;
|
||||
|
||||
if (!GLEW_ARB_texture_non_power_of_two)
|
||||
WARN_LOG(VIDEO, "ARB_texture_non_power_of_two not supported.");
|
||||
|
||||
@@ -315,90 +325,17 @@ Renderer::Renderer()
|
||||
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
|
||||
s_MSAASamples, s_MSAACoverageSamples);
|
||||
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||
|
||||
if (GL_REPORT_ERROR() != GL_NO_ERROR)
|
||||
bSuccess = false;
|
||||
|
||||
s_pfont = new RasterFont();
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
// load the effect, find the best profiles (if any)
|
||||
if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "arbvp1 not supported");
|
||||
return; // TODO: fail
|
||||
}
|
||||
|
||||
if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "arbfp1 not supported");
|
||||
return; // TODO: fail
|
||||
}
|
||||
|
||||
g_cgvProf = cgGLGetLatestProfile(CG_GL_VERTEX);
|
||||
g_cgfProf = cgGLGetLatestProfile(CG_GL_FRAGMENT);
|
||||
if (strstr((const char*)glGetString(GL_VENDOR), "Humper") == NULL)
|
||||
{
|
||||
#if CG_VERSION_NUM == 2100
|
||||
// A bug was introduced in Cg2.1's handling of very large profile option values
|
||||
// so this will not work on ATI. ATI returns MAXINT = 2147483647 (0x7fffffff)
|
||||
// which is correct in OpenGL but Cg fails to handle it properly. As a result
|
||||
// -1 is used by Cg resulting (signedness incorrect) and compilation fails.
|
||||
if (strstr((const char*)glGetString(GL_VENDOR), "ATI") == NULL)
|
||||
#endif
|
||||
{
|
||||
cgGLSetOptimalOptions(g_cgvProf);
|
||||
cgGLSetOptimalOptions(g_cgfProf);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_CG
|
||||
|
||||
int nenvvertparams, nenvfragparams, naddrregisters[2];
|
||||
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,
|
||||
GL_MAX_PROGRAM_ENV_PARAMETERS_ARB,
|
||||
(GLint *)&nenvvertparams);
|
||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
|
||||
GL_MAX_PROGRAM_ENV_PARAMETERS_ARB,
|
||||
(GLint *)&nenvfragparams);
|
||||
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,
|
||||
GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB,
|
||||
(GLint *)&naddrregisters[0]);
|
||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
|
||||
GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB,
|
||||
(GLint *)&naddrregisters[1]);
|
||||
DEBUG_LOG(VIDEO, "Max program env parameters: vert=%d, frag=%d",
|
||||
nenvvertparams, nenvfragparams);
|
||||
DEBUG_LOG(VIDEO, "Max program address register parameters: vert=%d, frag=%d",
|
||||
naddrregisters[0], naddrregisters[1]);
|
||||
|
||||
if (nenvvertparams < 238)
|
||||
ERROR_LOG(VIDEO, "Not enough vertex shader environment constants!!");
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
INFO_LOG(VIDEO, "Max buffer sizes: %d %d",
|
||||
cgGetProgramBufferMaxSize(g_cgvProf),
|
||||
cgGetProgramBufferMaxSize(g_cgfProf));
|
||||
#ifndef _DEBUG
|
||||
cgGLSetDebugMode(GL_FALSE);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
glStencilFunc(GL_ALWAYS, 0, 0);
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
|
||||
glViewport(0, 0, GetTargetWidth(), GetTargetHeight()); // Reset The Current Viewport
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClearDepth(1.0f);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
|
||||
@@ -407,39 +344,14 @@ Renderer::Renderer()
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
glScissor(0, 0, GetTargetWidth(), GetTargetHeight());
|
||||
glBlendColorEXT(0, 0, 0, 0.5f);
|
||||
glBlendColor(0, 0, 0, 0.5f);
|
||||
glClearDepth(1.0f);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// legacy multitexturing: select texture channel only.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
UpdateActiveConfig();
|
||||
|
||||
//return GL_REPORT_ERROR() == GL_NO_ERROR && bSuccess;
|
||||
return;
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
{
|
||||
g_Config.bRunning = false;
|
||||
UpdateActiveConfig();
|
||||
delete s_pfont;
|
||||
s_pfont = 0;
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
if (g_cgcontext)
|
||||
{
|
||||
cgDestroyContext(g_cgcontext);
|
||||
g_cgcontext = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
if (scrshotThread.joinable())
|
||||
@@ -449,6 +361,49 @@ Renderer::~Renderer()
|
||||
delete g_framebuffer_manager;
|
||||
}
|
||||
|
||||
void Renderer::Shutdown()
|
||||
{
|
||||
g_Config.bRunning = false;
|
||||
UpdateActiveConfig();
|
||||
|
||||
glDeleteBuffers(1, &s_ShowEFBCopyRegions_VBO);
|
||||
glDeleteVertexArrays(1, &s_ShowEFBCopyRegions_VAO);
|
||||
s_ShowEFBCopyRegions_VBO = 0;
|
||||
|
||||
delete s_pfont;
|
||||
s_pfont = 0;
|
||||
s_ShowEFBCopyRegions.Destroy();
|
||||
}
|
||||
|
||||
void Renderer::Init()
|
||||
{
|
||||
s_pfont = new RasterFont();
|
||||
|
||||
ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions,
|
||||
"in vec2 rawpos;\n"
|
||||
"in vec3 color0;\n"
|
||||
"out vec4 c;\n"
|
||||
"void main(void) {\n"
|
||||
" gl_Position = vec4(rawpos,0,1);\n"
|
||||
" c = vec4(color0, 1.0);\n"
|
||||
"}\n",
|
||||
"in vec4 c;\n"
|
||||
"out vec4 ocol0;\n"
|
||||
"void main(void) {\n"
|
||||
" ocol0 = c;\n"
|
||||
"}\n");
|
||||
|
||||
// creating buffers
|
||||
glGenBuffers(1, &s_ShowEFBCopyRegions_VBO);
|
||||
glGenVertexArrays(1, &s_ShowEFBCopyRegions_VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_ShowEFBCopyRegions_VBO);
|
||||
glBindVertexArray( s_ShowEFBCopyRegions_VAO );
|
||||
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*5, NULL);
|
||||
glEnableVertexAttribArray(SHADER_COLOR0_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_COLOR0_ATTRIB, 3, GL_FLOAT, 0, sizeof(GLfloat)*5, (GLfloat*)NULL+2);
|
||||
}
|
||||
|
||||
// Create On-Screen-Messages
|
||||
void Renderer::DrawDebugInfo()
|
||||
{
|
||||
@@ -477,9 +432,15 @@ void Renderer::DrawDebugInfo()
|
||||
// Set Line Size
|
||||
glLineWidth(3.0f);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
// 2*Coords + 3*Color
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_ShowEFBCopyRegions_VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, stats.efb_regions.size() * sizeof(GLfloat) * (2+3)*2*6, NULL, GL_STREAM_DRAW);
|
||||
GLfloat *Vertices = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
||||
|
||||
// Draw EFB copy regions rectangles
|
||||
int a = 0;
|
||||
GLfloat color[3] = {0.0f, 1.0f, 1.0f};
|
||||
|
||||
for (std::vector<EFBRectangle>::const_iterator it = stats.efb_regions.begin();
|
||||
it != stats.efb_regions.end(); ++it)
|
||||
{
|
||||
@@ -490,22 +451,94 @@ void Renderer::DrawDebugInfo()
|
||||
GLfloat x2 = (GLfloat) -1.0f + ((GLfloat)it->right / halfWidth);
|
||||
GLfloat y2 = (GLfloat) 1.0f - ((GLfloat)it->bottom / halfHeight);
|
||||
|
||||
// Draw shadow of rect
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
glVertex2f(x, y - 0.01); glVertex2f(x2, y - 0.01);
|
||||
glVertex2f(x, y2 - 0.01); glVertex2f(x2, y2 - 0.01);
|
||||
glVertex2f(x + 0.005, y); glVertex2f(x + 0.005, y2);
|
||||
glVertex2f(x2 + 0.005, y); glVertex2f(x2 + 0.005, y2);
|
||||
|
||||
// Draw rect
|
||||
glColor3f(0.0f, 1.0f, 1.0f);
|
||||
glVertex2f(x, y); glVertex2f(x2, y);
|
||||
glVertex2f(x, y2); glVertex2f(x2, y2);
|
||||
glVertex2f(x, y); glVertex2f(x, y2);
|
||||
glVertex2f(x2, y); glVertex2f(x2, y2);
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
|
||||
Vertices[a++] = x2;
|
||||
Vertices[a++] = y;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
Vertices[a++] = x;
|
||||
Vertices[a++] = y2;
|
||||
Vertices[a++] = color[0];
|
||||
Vertices[a++] = color[1];
|
||||
Vertices[a++] = color[2];
|
||||
|
||||
// TO DO: build something nicer here
|
||||
GLfloat temp = color[0];
|
||||
color[0] = color[1];
|
||||
color[1] = color[2];
|
||||
color[2] = temp;
|
||||
}
|
||||
|
||||
glEnd();
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
|
||||
s_ShowEFBCopyRegions.Bind();
|
||||
glBindVertexArray( s_ShowEFBCopyRegions_VAO );
|
||||
glDrawArrays(GL_LINES, 0, stats.efb_regions.size() * 2*6);
|
||||
|
||||
// Restore Line Size
|
||||
glLineWidth(lSize);
|
||||
@@ -533,20 +566,12 @@ void Renderer::RenderText(const char *text, int left, int top, u32 color)
|
||||
const int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth();
|
||||
const int nBackbufferHeight = (int)GLInterface->GetBackBufferHeight();
|
||||
|
||||
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
|
||||
((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
s_pfont->printMultilineText(text,
|
||||
left * 2.0f / (float)nBackbufferWidth - 1,
|
||||
1 - top * 2.0f / (float)nBackbufferHeight,
|
||||
0, nBackbufferWidth, nBackbufferHeight);
|
||||
0, nBackbufferWidth, nBackbufferHeight, color);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||
@@ -672,7 +697,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||
{
|
||||
// Resolve our rectangle.
|
||||
FramebufferManager::GetEFBDepthTexture(efbPixelRc);
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer());
|
||||
}
|
||||
|
||||
u32* depthMap = new u32[targetPixelRcWidth * targetPixelRcHeight];
|
||||
@@ -721,7 +746,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||
{
|
||||
// Resolve our rectangle.
|
||||
FramebufferManager::GetEFBColorTexture(efbPixelRc);
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer());
|
||||
}
|
||||
|
||||
u32* colorMap = new u32[targetPixelRcWidth * targetPixelRcHeight];
|
||||
@@ -857,9 +882,13 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
|
||||
|
||||
void Renderer::SetBlendMode(bool forceUpdate)
|
||||
{
|
||||
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;
|
||||
|
||||
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
|
||||
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
|
||||
bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
const GLenum glSrcFactors[8] =
|
||||
{
|
||||
GL_ZERO,
|
||||
@@ -885,11 +914,13 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
||||
|
||||
// blend mode bit mask
|
||||
// 0 - blend enable
|
||||
// 1 - dst alpha enabled
|
||||
// 2 - reverse subtract enable (else add)
|
||||
// 3-5 - srcRGB function
|
||||
// 6-8 - dstRGB function
|
||||
|
||||
u32 newval = bpmem.blendmode.subtract << 2;
|
||||
u32 newval = useDualSource << 1;
|
||||
newval |= bpmem.blendmode.subtract << 2;
|
||||
|
||||
if (bpmem.blendmode.subtract)
|
||||
newval |= 0x0049; // enable blending src 1 dst 1
|
||||
@@ -902,33 +933,23 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
||||
|
||||
u32 changes = forceUpdate ? 0xFFFFFFFF : newval ^ s_blendMode;
|
||||
|
||||
#ifdef USE_DUAL_SOURCE_BLEND
|
||||
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate
|
||||
&& bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
bool useDualSource = useDstAlpha && GLEW_ARB_blend_func_extended;
|
||||
#endif
|
||||
|
||||
if (changes & 1)
|
||||
// blend enable change
|
||||
(newval & 1) ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
|
||||
if (changes & 4)
|
||||
{
|
||||
#ifdef USE_DUAL_SOURCE_BLEND
|
||||
// subtract enable change
|
||||
GLenum equation = newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
|
||||
GLenum equationAlpha = useDualSource ? GL_FUNC_ADD : equation;
|
||||
|
||||
glBlendEquationSeparate(equation, equationAlpha);
|
||||
#else
|
||||
glBlendEquation(newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (changes & 0x1F8)
|
||||
if (changes & 0x1FA)
|
||||
{
|
||||
GLenum srcFactor = glSrcFactors[(newval >> 3) & 7];
|
||||
GLenum dstFactor = glDestFactors[(newval >> 6) & 7];
|
||||
#ifdef USE_DUAL_SOURCE_BLEND
|
||||
GLenum srcFactorAlpha = srcFactor;
|
||||
GLenum dstFactorAlpha = dstFactor;
|
||||
if (useDualSource)
|
||||
@@ -946,12 +967,9 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
||||
else if (dstFactor == GL_ONE_MINUS_SRC_ALPHA)
|
||||
dstFactor = GL_ONE_MINUS_SRC1_ALPHA;
|
||||
}
|
||||
|
||||
|
||||
// blend RGB change
|
||||
glBlendFuncSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha);
|
||||
#else
|
||||
glBlendFunc(srcFactor, dstFactor);
|
||||
#endif
|
||||
}
|
||||
|
||||
s_blendMode = newval;
|
||||
@@ -990,6 +1008,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
|
||||
ResetAPIState();
|
||||
|
||||
PostProcessing::Update(s_backbuffer_width, s_backbuffer_height);
|
||||
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
|
||||
TargetRectangle flipped_trc = GetTargetRectangle();
|
||||
|
||||
@@ -997,38 +1016,20 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
int tmp = flipped_trc.top;
|
||||
flipped_trc.top = flipped_trc.bottom;
|
||||
flipped_trc.bottom = tmp;
|
||||
|
||||
// Textured triangles are necessary because of post-processing shaders
|
||||
|
||||
// Disable all other stages
|
||||
for (int i = 1; i < 8; ++i)
|
||||
OGL::TextureCache::DisableStage(i);
|
||||
|
||||
// Update GLViewPort
|
||||
glViewport(flipped_trc.left, flipped_trc.bottom, flipped_trc.GetWidth(), flipped_trc.GetHeight());
|
||||
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// Copy the framebuffer to screen.
|
||||
|
||||
// Texture map s_xfbTexture onto the main buffer
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
// Use linear filtering.
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
// We must call ApplyShader here even if no post proc is selected - it takes
|
||||
// care of disabling it in that case. It returns false in case of no post processing.
|
||||
bool applyShader = PostProcessing::ApplyShader();
|
||||
|
||||
const XFBSourceBase* xfbSource = NULL;
|
||||
|
||||
if(g_ActiveConfig.bUseXFB)
|
||||
{
|
||||
// Render to the real/postprocessing buffer now.
|
||||
PostProcessing::BindTargetFramebuffer();
|
||||
|
||||
// draw each xfb source
|
||||
// Render to the real buffer now.
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer());
|
||||
|
||||
for (u32 i = 0; i < xfbCount; ++i)
|
||||
{
|
||||
@@ -1038,10 +1039,10 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
|
||||
if (g_ActiveConfig.bUseRealXFB)
|
||||
{
|
||||
drawRc.top = 1;
|
||||
drawRc.bottom = -1;
|
||||
drawRc.left = -1;
|
||||
drawRc.right = 1;
|
||||
drawRc.top = flipped_trc.top;
|
||||
drawRc.bottom = flipped_trc.bottom;
|
||||
drawRc.left = flipped_trc.left;
|
||||
drawRc.right = flipped_trc.right;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1049,12 +1050,12 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
int xfbHeight = xfbSource->srcHeight;
|
||||
int xfbWidth = xfbSource->srcWidth;
|
||||
int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbWidth * 2);
|
||||
|
||||
drawRc.top = 1.0f - (2.0f * (hOffset) / (float)fbHeight);
|
||||
drawRc.bottom = 1.0f - (2.0f * (hOffset + xfbHeight) / (float)fbHeight);
|
||||
drawRc.left = -(xfbWidth / (float)fbWidth);
|
||||
drawRc.right = (xfbWidth / (float)fbWidth);
|
||||
|
||||
|
||||
drawRc.top = flipped_trc.bottom + (hOffset + xfbHeight) * flipped_trc.GetHeight() / fbHeight;
|
||||
drawRc.bottom = flipped_trc.bottom + hOffset * flipped_trc.GetHeight() / fbHeight;
|
||||
drawRc.left = flipped_trc.left + (flipped_trc.GetWidth() - xfbWidth * flipped_trc.GetWidth() / fbWidth)/2;
|
||||
drawRc.right = flipped_trc.left + (flipped_trc.GetWidth() + xfbWidth * flipped_trc.GetWidth() / fbWidth)/2;
|
||||
|
||||
// The following code disables auto stretch. Kept for reference.
|
||||
// scale draw area for a 1 to 1 pixel mapping with the draw target
|
||||
//float vScale = (float)fbHeight / (float)flipped_trc.GetHeight();
|
||||
@@ -1074,62 +1075,30 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
sourceRc.bottom = xfbSource->sourceRc.bottom;
|
||||
|
||||
xfbSource->Draw(sourceRc, drawRc, 0, 0);
|
||||
|
||||
// We must call ApplyShader here even if no post proc is selected.
|
||||
// It takes care of disabling it in that case. It returns false in
|
||||
// case of no post processing.
|
||||
if (applyShader)
|
||||
PixelShaderCache::DisableShader();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TargetRectangle targetRc = ConvertEFBRectangle(rc);
|
||||
GLuint read_texture = FramebufferManager::ResolveAndGetRenderTarget(rc);
|
||||
// Render to the real buffer now.
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
|
||||
if (applyShader)
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(targetRc.left, targetRc.bottom);
|
||||
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0);
|
||||
glVertex2f(-1, -1);
|
||||
|
||||
glTexCoord2f(targetRc.left, targetRc.top);
|
||||
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1);
|
||||
glVertex2f(-1, 1);
|
||||
|
||||
glTexCoord2f(targetRc.right, targetRc.top);
|
||||
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1);
|
||||
glVertex2f( 1, 1);
|
||||
|
||||
glTexCoord2f(targetRc.right, targetRc.bottom);
|
||||
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0);
|
||||
glVertex2f( 1, -1);
|
||||
glEnd();
|
||||
PixelShaderCache::DisableShader();
|
||||
}
|
||||
else
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(targetRc.left, targetRc.bottom);
|
||||
glVertex2f(-1, -1);
|
||||
|
||||
glTexCoord2f(targetRc.left, targetRc.top);
|
||||
glVertex2f(-1, 1);
|
||||
|
||||
glTexCoord2f(targetRc.right, targetRc.top);
|
||||
glVertex2f( 1, 1);
|
||||
|
||||
glTexCoord2f(targetRc.right, targetRc.bottom);
|
||||
glVertex2f( 1, -1);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// for msaa mode, we must resolve the efb content to non-msaa
|
||||
FramebufferManager::ResolveAndGetRenderTarget(rc);
|
||||
|
||||
// Render to the real/postprocessing buffer now. (resolve have changed this in msaa mode)
|
||||
PostProcessing::BindTargetFramebuffer();
|
||||
|
||||
// always the non-msaa fbo
|
||||
GLuint fb = s_MSAASamples>1?FramebufferManager::GetResolvedFramebuffer():FramebufferManager::GetEFBFramebuffer();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
|
||||
glBlitFramebuffer(targetRc.left, targetRc.bottom, targetRc.right, targetRc.top,
|
||||
flipped_trc.left, flipped_trc.bottom, flipped_trc.right, flipped_trc.top,
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
}
|
||||
|
||||
PostProcessing::BlitToScreen();
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
OGL::TextureCache::DisableStage(0);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
// Save screenshot
|
||||
if (s_bScreenshot)
|
||||
@@ -1280,7 +1249,6 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
delete g_framebuffer_manager;
|
||||
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
|
||||
s_MSAASamples, s_MSAACoverageSamples);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1288,18 +1256,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
s_fps = UpdateFPSCounter();
|
||||
// ---------------------------------------------------------------------
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
DrawDebugText();
|
||||
DrawDebugInfo();
|
||||
DrawDebugText();
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// Get the status of the Blend mode
|
||||
GLboolean blend_enabled = glIsEnabled(GL_BLEND);
|
||||
glDisable(GL_BLEND);
|
||||
OSD::DrawMessages();
|
||||
if (blend_enabled)
|
||||
glEnable(GL_BLEND);
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// Copy the rendered frame to the real window
|
||||
@@ -1358,8 +1324,6 @@ void Renderer::ResetAPIState()
|
||||
{
|
||||
// Gets us to a reasonably sane state where it's possible to do things like
|
||||
// image copies with textured quads, etc.
|
||||
VertexShaderCache::DisableShader();
|
||||
PixelShaderCache::DisableShader();
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
@@ -1380,9 +1344,12 @@ void Renderer::RestoreAPIState()
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, g_ActiveConfig.bWireFrame ? GL_LINE : GL_FILL);
|
||||
|
||||
VertexShaderCache::SetCurrentShader(0);
|
||||
PixelShaderCache::SetCurrentShader(0);
|
||||
|
||||
VertexManager *vm = (OGL::VertexManager*)g_vertex_manager;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vm->m_vertex_buffers);
|
||||
vm->m_last_vao = 0;
|
||||
|
||||
TextureCache::SetStage();
|
||||
}
|
||||
|
||||
void Renderer::SetGenerationMode()
|
||||
@@ -1480,7 +1447,11 @@ void Renderer::SetLineWidth()
|
||||
|
||||
void Renderer::SetSamplerState(int stage, int texindex)
|
||||
{
|
||||
// TODO
|
||||
auto const& tex = bpmem.tex[texindex];
|
||||
auto const& tm0 = tex.texMode0[stage];
|
||||
auto const& tm1 = tex.texMode1[stage];
|
||||
|
||||
g_sampler_cache->SetSamplerState((texindex * 4) + stage, tm0, tm1);
|
||||
}
|
||||
|
||||
void Renderer::SetInterlacingMode()
|
||||
|
||||
@@ -14,6 +14,9 @@ class Renderer : public ::Renderer
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
void SetColorMask();
|
||||
void SetBlendMode(bool forceUpdate);
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "SamplerCache.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
SamplerCache *g_sampler_cache;
|
||||
|
||||
SamplerCache::SamplerCache()
|
||||
: m_last_max_anisotropy()
|
||||
{}
|
||||
|
||||
SamplerCache::~SamplerCache()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void SamplerCache::SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1)
|
||||
{
|
||||
// TODO: can this go somewhere else?
|
||||
if (m_last_max_anisotropy != g_ActiveConfig.iMaxAnisotropy)
|
||||
{
|
||||
m_last_max_anisotropy = g_ActiveConfig.iMaxAnisotropy;
|
||||
Clear();
|
||||
}
|
||||
|
||||
Params params(tm0, tm1);
|
||||
|
||||
// take equivalent forced linear when bForceFiltering
|
||||
if (g_ActiveConfig.bForceFiltering)
|
||||
{
|
||||
params.tm0.min_filter |= 0x4;
|
||||
params.tm0.mag_filter |= 0x1;
|
||||
}
|
||||
|
||||
// TODO: Should keep a circular buffer for each stage of recently used samplers.
|
||||
|
||||
auto& active_sampler = m_active_samplers[stage];
|
||||
if (active_sampler.first != params || !active_sampler.second.sampler_id)
|
||||
{
|
||||
// Active sampler does not match parameters (or is invalid), bind the proper one.
|
||||
active_sampler.first = params;
|
||||
active_sampler.second = GetEntry(params);
|
||||
glBindSampler(stage, active_sampler.second.sampler_id);
|
||||
}
|
||||
}
|
||||
|
||||
auto SamplerCache::GetEntry(const Params& params) -> Value&
|
||||
{
|
||||
auto& val = m_cache[params];
|
||||
if (!val.sampler_id)
|
||||
{
|
||||
// Sampler not found in cache, create it.
|
||||
glGenSamplers(1, &val.sampler_id);
|
||||
SetParameters(val.sampler_id, params);
|
||||
|
||||
// TODO: Maybe kill old samplers if the cache gets huge. It doesn't seem to get huge though.
|
||||
//ERROR_LOG(VIDEO, "Sampler cache size is now %ld.", m_cache.size());
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void SamplerCache::SetParameters(GLuint sampler_id, const Params& params)
|
||||
{
|
||||
static const GLint min_filters[8] =
|
||||
{
|
||||
GL_NEAREST,
|
||||
GL_NEAREST_MIPMAP_NEAREST,
|
||||
GL_NEAREST_MIPMAP_LINEAR,
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_LINEAR_MIPMAP_NEAREST,
|
||||
GL_LINEAR_MIPMAP_LINEAR,
|
||||
GL_LINEAR,
|
||||
};
|
||||
|
||||
static const GLint wrap_settings[4] =
|
||||
{
|
||||
GL_CLAMP_TO_EDGE,
|
||||
GL_REPEAT,
|
||||
GL_MIRRORED_REPEAT,
|
||||
GL_REPEAT,
|
||||
};
|
||||
|
||||
auto& tm0 = params.tm0;
|
||||
auto& tm1 = params.tm1;
|
||||
|
||||
glSamplerParameteri(sampler_id, GL_TEXTURE_MIN_FILTER, min_filters[tm0.min_filter % ARRAYSIZE(min_filters)]);
|
||||
glSamplerParameteri(sampler_id, GL_TEXTURE_MAG_FILTER, tm0.mag_filter ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_S, wrap_settings[tm0.wrap_s]);
|
||||
glSamplerParameteri(sampler_id, GL_TEXTURE_WRAP_T, wrap_settings[tm0.wrap_t]);
|
||||
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, tm0.lod_bias / 32.f);
|
||||
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, tm1.min_lod / 16.f);
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, tm1.max_lod / 16.f);
|
||||
|
||||
if (g_ActiveConfig.iMaxAnisotropy > 0)
|
||||
glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
||||
}
|
||||
|
||||
void SamplerCache::Clear()
|
||||
{
|
||||
for (auto it = m_cache.begin(); it != m_cache.end(); ++it)
|
||||
{
|
||||
glDeleteSamplers(1, &it->second.sampler_id);
|
||||
}
|
||||
m_cache.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
#ifndef INCLUDE_SAMPLER_CACHE_H_
|
||||
#define INCLUDE_SAMPLER_CACHE_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "Render.h"
|
||||
#include "GLUtil.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
class SamplerCache : NonCopyable
|
||||
{
|
||||
public:
|
||||
SamplerCache();
|
||||
~SamplerCache();
|
||||
|
||||
void SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1);
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
struct Params
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
TexMode0 tm0;
|
||||
TexMode1 tm1;
|
||||
};
|
||||
|
||||
u64 hex;
|
||||
};
|
||||
|
||||
Params()
|
||||
: hex()
|
||||
{}
|
||||
|
||||
Params(const TexMode0& _tm0, const TexMode1& _tm1)
|
||||
: tm0(_tm0)
|
||||
, tm1(_tm1)
|
||||
{
|
||||
static_assert(sizeof(Params) == 8, "Assuming I can treat this as a 64bit int.");
|
||||
}
|
||||
|
||||
bool operator<(const Params& other) const
|
||||
{
|
||||
return hex < other.hex;
|
||||
}
|
||||
|
||||
bool operator!=(const Params& other) const
|
||||
{
|
||||
return hex != other.hex;
|
||||
}
|
||||
};
|
||||
|
||||
struct Value
|
||||
{
|
||||
Value()
|
||||
: sampler_id()
|
||||
{}
|
||||
|
||||
GLuint sampler_id;
|
||||
};
|
||||
|
||||
void SetParameters(GLuint sampler_id, const Params& params);
|
||||
Value& GetEntry(const Params& params);
|
||||
|
||||
std::map<Params, Value> m_cache;
|
||||
std::pair<Params, Value> m_active_samplers[8];
|
||||
|
||||
int m_last_max_anisotropy;
|
||||
};
|
||||
|
||||
extern SamplerCache *g_sampler_cache;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,228 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Globals.h"
|
||||
#include "GLUtil.h"
|
||||
#include "StreamBuffer.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
static const u32 SYNC_POINTS = 16;
|
||||
static const u32 ALIGN_PINNED_MEMORY = 4096;
|
||||
|
||||
StreamBuffer::StreamBuffer(u32 type, size_t size, StreamType uploadType)
|
||||
: m_uploadtype(uploadType), m_buffertype(type), m_size(size)
|
||||
{
|
||||
glGenBuffers(1, &m_buffer);
|
||||
|
||||
bool nvidia = !strcmp((const char*)glGetString(GL_VENDOR), "NVIDIA Corporation");
|
||||
|
||||
if(m_uploadtype == STREAM_DETECT)
|
||||
{
|
||||
if(!g_Config.backend_info.bSupportsGLBaseVertex)
|
||||
m_uploadtype = BUFFERSUBDATA;
|
||||
else if(g_Config.backend_info.bSupportsGLSync && g_Config.backend_info.bSupportsGLPinnedMemory)
|
||||
m_uploadtype = PINNED_MEMORY;
|
||||
else if(g_Config.backend_info.bSupportsGLSync && g_Config.bHackedBufferUpload)
|
||||
m_uploadtype = MAP_AND_RISK;
|
||||
else if(nvidia)
|
||||
m_uploadtype = BUFFERSUBDATA;
|
||||
else if(g_Config.backend_info.bSupportsGLSync)
|
||||
m_uploadtype = MAP_AND_SYNC;
|
||||
else
|
||||
m_uploadtype = MAP_AND_ORPHAN;
|
||||
}
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
StreamBuffer::~StreamBuffer()
|
||||
{
|
||||
Shutdown();
|
||||
glDeleteBuffers(1, &m_buffer);
|
||||
}
|
||||
|
||||
#define SLOT(x) (x)*SYNC_POINTS/m_size
|
||||
|
||||
void StreamBuffer::Alloc ( size_t size, u32 stride )
|
||||
{
|
||||
size_t m_iterator_aligned = m_iterator;
|
||||
if(m_iterator_aligned && stride) {
|
||||
m_iterator_aligned--;
|
||||
m_iterator_aligned = m_iterator_aligned - (m_iterator_aligned % stride) + stride;
|
||||
}
|
||||
size_t iter_end = m_iterator_aligned + size;
|
||||
|
||||
switch(m_uploadtype) {
|
||||
case MAP_AND_ORPHAN:
|
||||
if(iter_end >= m_size) {
|
||||
glBufferData(m_buffertype, m_size, NULL, GL_STREAM_DRAW);
|
||||
m_iterator_aligned = 0;
|
||||
}
|
||||
break;
|
||||
case MAP_AND_SYNC:
|
||||
case PINNED_MEMORY:
|
||||
|
||||
// insert waiting slots for used memory
|
||||
for(u32 i=SLOT(m_used_iterator); i<SLOT(m_iterator); i++)
|
||||
{
|
||||
fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
}
|
||||
m_used_iterator = m_iterator;
|
||||
|
||||
// wait for new slots to end of buffer
|
||||
for(u32 i=SLOT(m_free_iterator)+1; i<=SLOT(iter_end) && i < SYNC_POINTS; i++)
|
||||
{
|
||||
glClientWaitSync(fences[i], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
|
||||
glDeleteSync(fences[i]);
|
||||
}
|
||||
m_free_iterator = iter_end;
|
||||
|
||||
// if buffer is full
|
||||
if(iter_end >= m_size) {
|
||||
|
||||
// insert waiting slots in unused space at the end of the buffer
|
||||
for(u32 i=SLOT(m_used_iterator); i < SYNC_POINTS; i++)
|
||||
fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
// move to the start
|
||||
m_used_iterator = m_iterator_aligned = m_iterator = 0; // offset 0 is always aligned
|
||||
iter_end = size;
|
||||
|
||||
// wait for space at the start
|
||||
for(u32 i=0; i<=SLOT(iter_end); i++)
|
||||
{
|
||||
glClientWaitSync(fences[i], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
|
||||
glDeleteSync(fences[i]);
|
||||
}
|
||||
m_free_iterator = iter_end;
|
||||
}
|
||||
|
||||
break;
|
||||
case MAP_AND_RISK:
|
||||
if(iter_end >= m_size) {
|
||||
m_iterator_aligned = 0;
|
||||
}
|
||||
break;
|
||||
case BUFFERSUBDATA:
|
||||
m_iterator_aligned = 0;
|
||||
break;
|
||||
case STREAM_DETECT:
|
||||
break;
|
||||
}
|
||||
m_iterator = m_iterator_aligned;
|
||||
}
|
||||
|
||||
size_t StreamBuffer::Upload ( u8* data, size_t size )
|
||||
{
|
||||
switch(m_uploadtype) {
|
||||
case MAP_AND_SYNC:
|
||||
case MAP_AND_ORPHAN:
|
||||
pointer = (u8*)glMapBufferRange(m_buffertype, m_iterator, size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
if(pointer) {
|
||||
memcpy(pointer, data, size);
|
||||
glUnmapBuffer(m_buffertype);
|
||||
} else {
|
||||
ERROR_LOG(VIDEO, "buffer mapping failed");
|
||||
}
|
||||
break;
|
||||
case PINNED_MEMORY:
|
||||
case MAP_AND_RISK:
|
||||
if(pointer)
|
||||
memcpy(pointer+m_iterator, data, size);
|
||||
break;
|
||||
case BUFFERSUBDATA:
|
||||
glBufferSubData(m_buffertype, m_iterator, size, data);
|
||||
break;
|
||||
case STREAM_DETECT:
|
||||
break;
|
||||
}
|
||||
size_t ret = m_iterator;
|
||||
m_iterator += size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void StreamBuffer::Init()
|
||||
{
|
||||
m_iterator = 0;
|
||||
m_used_iterator = 0;
|
||||
m_free_iterator = 0;
|
||||
|
||||
switch(m_uploadtype) {
|
||||
case MAP_AND_SYNC:
|
||||
fences = new GLsync[SYNC_POINTS];
|
||||
for(u32 i=0; i<SYNC_POINTS; i++)
|
||||
fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
case MAP_AND_ORPHAN:
|
||||
case BUFFERSUBDATA:
|
||||
glBindBuffer(m_buffertype, m_buffer);
|
||||
glBufferData(m_buffertype, m_size, NULL, GL_STREAM_DRAW);
|
||||
break;
|
||||
case PINNED_MEMORY:
|
||||
fences = new GLsync[SYNC_POINTS];
|
||||
for(u32 i=0; i<SYNC_POINTS; i++)
|
||||
fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
pointer = (u8*)AllocateAlignedMemory(ROUND_UP(m_size,ALIGN_PINNED_MEMORY), ALIGN_PINNED_MEMORY );
|
||||
glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_buffer);
|
||||
glBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_size, pointer, GL_STREAM_COPY);
|
||||
glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
|
||||
glBindBuffer(m_buffertype, m_buffer);
|
||||
break;
|
||||
case MAP_AND_RISK:
|
||||
glBindBuffer(m_buffertype, m_buffer);
|
||||
glBufferData(m_buffertype, m_size, NULL, GL_STREAM_DRAW);
|
||||
pointer = (u8*)glMapBuffer(m_buffertype, GL_WRITE_ONLY);
|
||||
glUnmapBuffer(m_buffertype);
|
||||
if(!pointer)
|
||||
ERROR_LOG(VIDEO, "buffer allocation failed");
|
||||
|
||||
case STREAM_DETECT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void StreamBuffer::Shutdown()
|
||||
{
|
||||
switch(m_uploadtype) {
|
||||
case MAP_AND_SYNC:
|
||||
for(u32 i=0; i<SYNC_POINTS; i++)
|
||||
glDeleteSync(fences[i]);
|
||||
delete [] fences;
|
||||
break;
|
||||
|
||||
case MAP_AND_RISK:
|
||||
case MAP_AND_ORPHAN:
|
||||
case BUFFERSUBDATA:
|
||||
break;
|
||||
case PINNED_MEMORY:
|
||||
for(u32 i=0; i<SYNC_POINTS; i++)
|
||||
glDeleteSync(fences[i]);
|
||||
delete [] fences;
|
||||
glBindBuffer(m_buffertype, 0);
|
||||
glFinish(); // ogl pipeline must be flushed, else this buffer can be in use
|
||||
FreeAlignedMemory(pointer);
|
||||
break;
|
||||
case STREAM_DETECT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#ifndef STREAMBUFFER_H
|
||||
#define STREAMBUFFER_H
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "FramebufferManager.h"
|
||||
#include "GLUtil.h"
|
||||
|
||||
// glew < 1.8 doesn't support pinned memory
|
||||
#ifndef GLEW_AMD_pinned_memory
|
||||
#define GLEW_AMD_pinned_memory glewIsSupported("GL_AMD_pinned_memory")
|
||||
#define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160
|
||||
#endif
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
enum StreamType {
|
||||
STREAM_DETECT,
|
||||
MAP_AND_ORPHAN,
|
||||
MAP_AND_SYNC,
|
||||
MAP_AND_RISK,
|
||||
PINNED_MEMORY,
|
||||
BUFFERSUBDATA
|
||||
};
|
||||
|
||||
class StreamBuffer {
|
||||
|
||||
public:
|
||||
StreamBuffer(u32 type, size_t size, StreamType uploadType = STREAM_DETECT);
|
||||
~StreamBuffer();
|
||||
|
||||
void Alloc(size_t size, u32 stride = 0);
|
||||
size_t Upload(u8 *data, size_t size);
|
||||
|
||||
u32 getBuffer() { return m_buffer; }
|
||||
|
||||
private:
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
StreamType m_uploadtype;
|
||||
u32 m_buffer;
|
||||
u32 m_buffertype;
|
||||
size_t m_size;
|
||||
u8 *pointer;
|
||||
size_t m_iterator;
|
||||
size_t m_used_iterator;
|
||||
size_t m_free_iterator;
|
||||
GLsync *fences;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // STREAMBUFFER_H
|
||||
@@ -42,7 +42,7 @@
|
||||
#include "HW/Memmap.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "ProgramShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "Render.h"
|
||||
#include "Statistics.h"
|
||||
@@ -56,6 +56,24 @@
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
static SHADER s_ColorMatrixProgram;
|
||||
static SHADER s_DepthMatrixProgram;
|
||||
static GLuint s_ColorMatrixUniform;
|
||||
static GLuint s_DepthMatrixUniform;
|
||||
static u32 s_ColorCbufid;
|
||||
static u32 s_DepthCbufid;
|
||||
|
||||
static u32 s_Textures[8];
|
||||
static u32 s_ActiveTexture;
|
||||
static u32 s_NextStage;
|
||||
|
||||
struct VBOCache {
|
||||
GLuint vbo;
|
||||
GLuint vao;
|
||||
TargetRectangle targetSource;
|
||||
};
|
||||
static std::map<u64,VBOCache> s_VBO;
|
||||
|
||||
static u32 s_TempFramebuffer = 0;
|
||||
|
||||
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level)
|
||||
@@ -63,8 +81,11 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width
|
||||
int width = std::max(virtual_width >> level, 1);
|
||||
int height = std::max(virtual_height >> level, 1);
|
||||
std::vector<u32> data(width * height);
|
||||
glActiveTexture(GL_TEXTURE0+9);
|
||||
glBindTexture(textarget, tex);
|
||||
glGetTexImage(textarget, level, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]);
|
||||
glBindTexture(textarget, 0);
|
||||
TextureCache::SetStage();
|
||||
|
||||
const GLenum err = GL_REPORT_ERROR();
|
||||
if (GL_NO_ERROR != err)
|
||||
@@ -80,6 +101,9 @@ TextureCache::TCacheEntry::~TCacheEntry()
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
for(int i=0; i<8; i++)
|
||||
if(s_Textures[i] == texture)
|
||||
s_Textures[i] = 0;
|
||||
glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
}
|
||||
@@ -93,14 +117,17 @@ TextureCache::TCacheEntry::TCacheEntry()
|
||||
|
||||
void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// TODO: is this already done somewhere else?
|
||||
TexMode0 &tm0 = bpmem.tex[stage >> 2].texMode0[stage & 3];
|
||||
TexMode1 &tm1 = bpmem.tex[stage >> 2].texMode1[stage & 3];
|
||||
SetTextureParameters(tm0, tm1);
|
||||
if (s_Textures[stage] != texture)
|
||||
{
|
||||
if (s_ActiveTexture != stage)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + stage);
|
||||
s_ActiveTexture = stage;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
s_Textures[stage] = texture;
|
||||
}
|
||||
}
|
||||
|
||||
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
|
||||
@@ -129,13 +156,13 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||
PanicAlert("Invalid PC texture format %i", pcfmt);
|
||||
case PC_TEX_FMT_BGRA32:
|
||||
gl_format = GL_BGRA;
|
||||
gl_iformat = 4;
|
||||
gl_iformat = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case PC_TEX_FMT_RGBA32:
|
||||
gl_format = GL_RGBA;
|
||||
gl_iformat = 4;
|
||||
gl_iformat = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
@@ -177,7 +204,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||
entry.gl_type = gl_type;
|
||||
entry.pcfmt = pcfmt;
|
||||
|
||||
entry.bHaveMipMaps = tex_levels != 1;
|
||||
entry.m_tex_levels = tex_levels;
|
||||
|
||||
entry.Load(width, height, expanded_width, 0);
|
||||
|
||||
@@ -187,19 +214,33 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
//glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
//GL_REPORT_ERRORD();
|
||||
if (s_ActiveTexture != s_NextStage)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + s_NextStage);
|
||||
s_ActiveTexture = s_NextStage;
|
||||
}
|
||||
|
||||
if (s_Textures[s_NextStage] != texture)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
s_Textures[s_NextStage] = texture;
|
||||
}
|
||||
|
||||
// TODO: sloppy, just do this on creation?
|
||||
if (level == 0)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_tex_levels - 1);
|
||||
}
|
||||
|
||||
if (pcfmt != PC_TEX_FMT_DXT1)
|
||||
{
|
||||
if (expanded_width != width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp);
|
||||
|
||||
if (expanded_width != width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -214,31 +255,26 @@ TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(
|
||||
unsigned int scaled_tex_w, unsigned int scaled_tex_h)
|
||||
{
|
||||
TCacheEntry *const entry = new TCacheEntry;
|
||||
glActiveTexture(GL_TEXTURE0+9);
|
||||
glBindTexture(GL_TEXTURE_2D, entry->texture);
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
const GLenum
|
||||
gl_format = GL_RGBA,
|
||||
gl_iformat = 4,
|
||||
gl_iformat = GL_RGBA,
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
entry->m_tex_levels = 1;
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, scaled_tex_w, scaled_tex_h, 0, gl_format, gl_type, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
SetStage();
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (GL_REPORT_ERROR() != GL_NO_ERROR)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -247,8 +283,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
||||
const float *colmat)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
// Make sure to resolve anything we need to read from.
|
||||
const GLuint read_texture = (srcFormat == PIXELFMT_Z24) ?
|
||||
FramebufferManager::ResolveAndGetDepthTarget(srcRect) :
|
||||
@@ -259,38 +295,85 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||
if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture)
|
||||
{
|
||||
if (s_TempFramebuffer == 0)
|
||||
glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
|
||||
glGenFramebuffers(1, (GLuint*)&s_TempFramebuffer);
|
||||
|
||||
FramebufferManager::SetFramebuffer(s_TempFramebuffer);
|
||||
// Bind texture to temporary framebuffer
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
||||
GL_REPORT_FBO_ERROR();
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+9);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, read_texture);
|
||||
|
||||
glViewport(0, 0, virtual_width, virtual_height);
|
||||
|
||||
PixelShaderCache::SetCurrentShader((srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram());
|
||||
PixelShaderManager::SetColorMatrix(colmat); // set transformation
|
||||
if(srcFormat == PIXELFMT_Z24) {
|
||||
s_DepthMatrixProgram.Bind();
|
||||
if(s_DepthCbufid != cbufid)
|
||||
glUniform4fv(s_DepthMatrixUniform, 5, colmat);
|
||||
s_DepthCbufid = cbufid;
|
||||
} else {
|
||||
s_ColorMatrixProgram.Bind();
|
||||
if(s_ColorCbufid != cbufid)
|
||||
glUniform4fv(s_ColorMatrixUniform, 7, colmat);
|
||||
s_ColorCbufid = cbufid;
|
||||
}
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// should be unique enough, if not, vbo will "only" be uploaded to much
|
||||
u64 targetSourceHash = u64(targetSource.left)<<48 | u64(targetSource.top)<<32 | u64(targetSource.right)<<16 | u64(targetSource.bottom);
|
||||
std::map<u64, VBOCache>::iterator vbo_it = s_VBO.find(targetSourceHash);
|
||||
|
||||
if(vbo_it == s_VBO.end()) {
|
||||
VBOCache item;
|
||||
item.targetSource.bottom = -1;
|
||||
item.targetSource.top = -1;
|
||||
item.targetSource.left = -1;
|
||||
item.targetSource.right = -1;
|
||||
glGenBuffers(1, &item.vbo);
|
||||
glGenVertexArrays(1, &item.vao);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, item.vbo);
|
||||
glBindVertexArray(item.vao);
|
||||
|
||||
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
|
||||
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
|
||||
|
||||
vbo_it = s_VBO.insert(std::pair<u64,VBOCache>(targetSourceHash, item)).first;
|
||||
}
|
||||
if(!(vbo_it->second.targetSource == targetSource)) {
|
||||
GLfloat vertices[] = {
|
||||
-1.f, 1.f,
|
||||
(GLfloat)targetSource.left, (GLfloat)targetSource.bottom,
|
||||
-1.f, -1.f,
|
||||
(GLfloat)targetSource.left, (GLfloat)targetSource.top,
|
||||
1.f, -1.f,
|
||||
(GLfloat)targetSource.right, (GLfloat)targetSource.top,
|
||||
1.f, 1.f,
|
||||
(GLfloat)targetSource.right, (GLfloat)targetSource.bottom
|
||||
};
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_it->second.vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, 4*4*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
|
||||
|
||||
vbo_it->second.targetSource = targetSource;
|
||||
}
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.bottom); glVertex2f(-1, 1);
|
||||
glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.top ); glVertex2f(-1, -1);
|
||||
glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.top ); glVertex2f( 1, -1);
|
||||
glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.bottom); glVertex2f( 1, 1);
|
||||
glEnd();
|
||||
glBindVertexArray(vbo_it->second.vao);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// Unbind texture from temporary framebuffer
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
|
||||
if (false == g_ActiveConfig.bCopyEFBToTexture)
|
||||
@@ -318,7 +401,6 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
DisableStage(0);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
@@ -328,63 +410,95 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||
SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
||||
count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0);
|
||||
}
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1)
|
||||
TextureCache::TextureCache()
|
||||
{
|
||||
const GLint c_MinLinearFilter[8] =
|
||||
{
|
||||
GL_NEAREST,
|
||||
GL_NEAREST_MIPMAP_NEAREST,
|
||||
GL_NEAREST_MIPMAP_LINEAR,
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_LINEAR_MIPMAP_NEAREST,
|
||||
GL_LINEAR_MIPMAP_LINEAR,
|
||||
GL_LINEAR,
|
||||
};
|
||||
const GLint c_WrapSettings[4] =
|
||||
{
|
||||
GL_CLAMP_TO_EDGE,
|
||||
GL_REPEAT,
|
||||
GL_MIRRORED_REPEAT,
|
||||
GL_REPEAT,
|
||||
};
|
||||
const char *pColorMatrixProg =
|
||||
"uniform sampler2DRect samp9;\n"
|
||||
"uniform vec4 colmat[7];\n"
|
||||
"in vec2 uv0;\n"
|
||||
"out vec4 ocol0;\n"
|
||||
"\n"
|
||||
"void main(){\n"
|
||||
" vec4 texcol = texture2DRect(samp9, uv0);\n"
|
||||
" texcol = round(texcol * colmat[5]) * colmat[6];\n"
|
||||
" ocol0 = texcol * mat4(colmat[0], colmat[1], colmat[2], colmat[3]) + colmat[4];\n"
|
||||
"}\n";
|
||||
|
||||
int filt = newmode.min_filter;
|
||||
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
|
||||
filt += 4; // take equivalent forced linear
|
||||
const char *pDepthMatrixProg =
|
||||
"uniform sampler2DRect samp9;\n"
|
||||
"uniform vec4 colmat[5];\n"
|
||||
"in vec2 uv0;\n"
|
||||
"out vec4 ocol0;\n"
|
||||
"\n"
|
||||
"void main(){\n"
|
||||
" vec4 texcol = texture2DRect(samp9, uv0);\n"
|
||||
" vec4 EncodedDepth = fract((texcol.r * (16777215.0f/16777216.0f)) * vec4(1.0f,256.0f,256.0f*256.0f,1.0f));\n"
|
||||
" texcol = round(EncodedDepth * (16777216.0f/16777215.0f) * vec4(255.0f,255.0f,255.0f,15.0f)) / vec4(255.0f,255.0f,255.0f,15.0f);\n"
|
||||
" ocol0 = texcol * mat4(colmat[0], colmat[1], colmat[2], colmat[3]) + colmat[4];"
|
||||
"}\n";
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod / 16.f);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod / 16.f);
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (s32)newmode.lod_bias / 32.0f);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]);
|
||||
|
||||
// TODO: Reset anisotrop when changed to 1
|
||||
if (g_Config.iMaxAnisotropy >= 1)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
(float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
||||
|
||||
const char *VProgram =
|
||||
"in vec2 rawpos;\n"
|
||||
"in vec2 tex0;\n"
|
||||
"out vec2 uv0;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" uv0 = tex0;\n"
|
||||
" gl_Position = vec4(rawpos,0,1);\n"
|
||||
"}\n";
|
||||
|
||||
ProgramShaderCache::CompileShader(s_ColorMatrixProgram, VProgram, pColorMatrixProg);
|
||||
ProgramShaderCache::CompileShader(s_DepthMatrixProgram, VProgram, pDepthMatrixProg);
|
||||
|
||||
s_ColorMatrixUniform = glGetUniformLocation(s_ColorMatrixProgram.glprogid, "colmat");
|
||||
s_DepthMatrixUniform = glGetUniformLocation(s_DepthMatrixProgram.glprogid, "colmat");
|
||||
s_ColorCbufid = -1;
|
||||
s_DepthCbufid = -1;
|
||||
|
||||
s_ActiveTexture = -1;
|
||||
s_NextStage = -1;
|
||||
for(int i=0; i<8; i++)
|
||||
s_Textures[i] = -1;
|
||||
}
|
||||
|
||||
|
||||
TextureCache::~TextureCache()
|
||||
{
|
||||
if (s_TempFramebuffer)
|
||||
s_ColorMatrixProgram.Destroy();
|
||||
s_DepthMatrixProgram.Destroy();
|
||||
|
||||
for(std::map<u64, VBOCache>::iterator it = s_VBO.begin(); it != s_VBO.end(); it++) {
|
||||
glDeleteBuffers(1, &it->second.vbo);
|
||||
glDeleteVertexArrays(1, &it->second.vao);
|
||||
}
|
||||
s_VBO.clear();
|
||||
|
||||
if (s_TempFramebuffer)
|
||||
{
|
||||
glDeleteFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
|
||||
s_TempFramebuffer = 0;
|
||||
}
|
||||
glDeleteFramebuffers(1, (GLuint*)&s_TempFramebuffer);
|
||||
s_TempFramebuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::DisableStage(unsigned int stage)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + stage);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
}
|
||||
|
||||
void TextureCache::SetStage ()
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + s_ActiveTexture);
|
||||
}
|
||||
|
||||
void TextureCache::SetNextStage ( unsigned int stage )
|
||||
{
|
||||
s_NextStage = stage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,10 @@ namespace OGL
|
||||
class TextureCache : public ::TextureCache
|
||||
{
|
||||
public:
|
||||
TextureCache();
|
||||
static void DisableStage(unsigned int stage);
|
||||
static void SetStage();
|
||||
static void SetNextStage(unsigned int stage);
|
||||
|
||||
private:
|
||||
struct TCacheEntry : TCacheEntryBase
|
||||
@@ -45,7 +48,7 @@ private:
|
||||
int gl_iformat;
|
||||
int gl_type;
|
||||
|
||||
bool bHaveMipMaps;
|
||||
int m_tex_levels;
|
||||
|
||||
//TexMode0 mode; // current filter and clamp modes that texture is set to
|
||||
//TexMode1 mode1; // current filter and clamp modes that texture is set to
|
||||
@@ -63,9 +66,6 @@ private:
|
||||
|
||||
void Bind(unsigned int stage);
|
||||
bool Save(const char filename[], unsigned int level);
|
||||
|
||||
private:
|
||||
void SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1);
|
||||
};
|
||||
|
||||
~TextureCache();
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "TextureConverter.h"
|
||||
#include "TextureConversionShader.h"
|
||||
#include "TextureCache.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "ProgramShaderCache.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "FramebufferManager.h"
|
||||
#include "Globals.h"
|
||||
@@ -50,64 +50,73 @@ static GLuint s_dstRenderBuffer = 0; // for encoding to RAM
|
||||
const int renderBufferWidth = 1024;
|
||||
const int renderBufferHeight = 1024;
|
||||
|
||||
static FRAGMENTSHADER s_rgbToYuyvProgram;
|
||||
static FRAGMENTSHADER s_yuyvToRgbProgram;
|
||||
static SHADER s_rgbToYuyvProgram;
|
||||
static SHADER s_yuyvToRgbProgram;
|
||||
|
||||
// Not all slots are taken - but who cares.
|
||||
const u32 NUM_ENCODING_PROGRAMS = 64;
|
||||
static FRAGMENTSHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS];
|
||||
static SHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS];
|
||||
|
||||
void CreateRgbToYuyvProgram()
|
||||
static GLuint s_encode_VBO = 0;
|
||||
static GLuint s_encode_VAO = 0;
|
||||
static GLuint s_decode_VBO = 0;
|
||||
static GLuint s_decode_VAO = 0;
|
||||
static TargetRectangle s_cached_sourceRc;
|
||||
static int s_cached_srcWidth = 0;
|
||||
static int s_cached_srcHeight = 0;
|
||||
|
||||
static const char *VProgram =
|
||||
"in vec2 rawpos;\n"
|
||||
"in vec2 tex0;\n"
|
||||
"out vec2 uv0;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" uv0 = tex0;\n"
|
||||
" gl_Position = vec4(rawpos,0,1);\n"
|
||||
"}\n";
|
||||
|
||||
void CreatePrograms()
|
||||
{
|
||||
// Output is BGRA because that is slightly faster than RGBA.
|
||||
const char *FProgram =
|
||||
"uniform samplerRECT samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
" float2 uv1 = float2(uv0.x + 1.0f, uv0.y);\n"
|
||||
" float3 c0 = texRECT(samp0, uv0).rgb;\n"
|
||||
" float3 c1 = texRECT(samp0, uv1).rgb;\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";
|
||||
const char *FProgramRgbToYuyv =
|
||||
"uniform sampler2DRect samp9;\n"
|
||||
"in vec2 uv0;\n"
|
||||
"out vec4 ocol0;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec3 c0 = texture2DRect(samp9, uv0).rgb;\n"
|
||||
" vec3 c1 = texture2DRect(samp9, uv0 + vec2(1.0, 0.0)).rgb;\n"
|
||||
" vec3 c01 = (c0 + c1) * 0.5;\n"
|
||||
" vec3 y_const = vec3(0.257,0.504,0.098);\n"
|
||||
" vec3 u_const = vec3(-0.148,-0.291,0.439);\n"
|
||||
" vec3 v_const = vec3(0.439,-0.368,-0.071);\n"
|
||||
" vec4 const3 = vec4(0.0625,0.5,0.0625f,0.5);\n"
|
||||
" ocol0 = vec4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n"
|
||||
"}\n";
|
||||
|
||||
if (!PixelShaderCache::CompilePixelShader(s_rgbToYuyvProgram, FProgram))
|
||||
ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program.");
|
||||
const char *FProgramYuyvToRgb =
|
||||
"uniform sampler2DRect samp9;\n"
|
||||
"in vec2 uv0;\n"
|
||||
"out vec4 ocol0;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 c0 = texture2DRect(samp9, uv0).rgba;\n"
|
||||
" float f = step(0.5, fract(uv0.x));\n"
|
||||
" float y = mix(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 = vec4(yComp + (1.596f * vComp),\n"
|
||||
" yComp - (0.813f * vComp) - (0.391f * uComp),\n"
|
||||
" yComp + (2.018f * uComp),\n"
|
||||
" 1.0f);\n"
|
||||
"}\n";
|
||||
|
||||
ProgramShaderCache::CompileShader(s_rgbToYuyvProgram, VProgram, FProgramRgbToYuyv);
|
||||
ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgram, FProgramYuyvToRgb);
|
||||
}
|
||||
|
||||
void CreateYuyvToRgbProgram()
|
||||
{
|
||||
const char *FProgram =
|
||||
"uniform samplerRECT samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
" float4 c0 = texRECT(samp0, uv0).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";
|
||||
|
||||
if (!PixelShaderCache::CompilePixelShader(s_yuyvToRgbProgram, FProgram))
|
||||
ERROR_LOG(VIDEO, "Failed to create YUYV to RGB fragment program.");
|
||||
}
|
||||
|
||||
FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
|
||||
SHADER &GetOrCreateEncodingShader(u32 format)
|
||||
{
|
||||
if (format > NUM_ENCODING_PROGRAMS)
|
||||
{
|
||||
@@ -117,7 +126,7 @@ FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
|
||||
|
||||
if (s_encodingPrograms[format].glprogid == 0)
|
||||
{
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(format,API_OPENGL);
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(format, API_OPENGL);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader)
|
||||
@@ -130,20 +139,43 @@ FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!PixelShaderCache::CompilePixelShader(s_encodingPrograms[format], shader)) {
|
||||
ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
|
||||
}
|
||||
ProgramShaderCache::CompileShader(s_encodingPrograms[format], VProgram, shader);
|
||||
}
|
||||
return s_encodingPrograms[format];
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
glGenFramebuffersEXT(1, &s_texConvFrameBuffer);
|
||||
glGenFramebuffers(1, &s_texConvFrameBuffer);
|
||||
|
||||
glGenBuffers(1, &s_encode_VBO );
|
||||
glGenVertexArrays(1, &s_encode_VAO );
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_encode_VBO );
|
||||
glBindVertexArray( s_encode_VAO );
|
||||
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
|
||||
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
|
||||
s_cached_sourceRc.top = -1;
|
||||
s_cached_sourceRc.bottom = -1;
|
||||
s_cached_sourceRc.left = -1;
|
||||
s_cached_sourceRc.right = -1;
|
||||
|
||||
glGenBuffers(1, &s_decode_VBO );
|
||||
glGenVertexArrays(1, &s_decode_VAO );
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO );
|
||||
glBindVertexArray( s_decode_VAO );
|
||||
s_cached_srcWidth = -1;
|
||||
s_cached_srcHeight = -1;
|
||||
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
|
||||
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
|
||||
|
||||
glGenRenderbuffersEXT(1, &s_dstRenderBuffer);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, renderBufferWidth, renderBufferHeight);
|
||||
glGenRenderbuffers(1, &s_dstRenderBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, s_dstRenderBuffer);
|
||||
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, renderBufferWidth, renderBufferHeight);
|
||||
|
||||
s_srcTextureWidth = 0;
|
||||
s_srcTextureHeight = 0;
|
||||
@@ -152,16 +184,20 @@ void Init()
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
CreateRgbToYuyvProgram();
|
||||
CreateYuyvToRgbProgram();
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
|
||||
CreatePrograms();
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
glDeleteTextures(1, &s_srcTexture);
|
||||
glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer);
|
||||
glDeleteFramebuffersEXT(1, &s_texConvFrameBuffer);
|
||||
glDeleteRenderbuffers(1, &s_dstRenderBuffer);
|
||||
glDeleteFramebuffers(1, &s_texConvFrameBuffer);
|
||||
glDeleteBuffers(1, &s_encode_VBO );
|
||||
glDeleteVertexArrays(1, &s_encode_VAO );
|
||||
glDeleteBuffers(1, &s_decode_VBO );
|
||||
glDeleteVertexArrays(1, &s_decode_VAO );
|
||||
|
||||
s_rgbToYuyvProgram.Destroy();
|
||||
s_yuyvToRgbProgram.Destroy();
|
||||
@@ -174,8 +210,8 @@ void Shutdown()
|
||||
s_texConvFrameBuffer = 0;
|
||||
}
|
||||
|
||||
void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight, int readStride,
|
||||
void EncodeToRamUsingShader(GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight, int readStride,
|
||||
bool toTexture, bool linearFilter)
|
||||
{
|
||||
|
||||
@@ -184,42 +220,52 @@ void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const Tar
|
||||
// attach render buffer as color destination
|
||||
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, s_dstRenderBuffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, s_dstRenderBuffer);
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
for (int i = 1; i < 8; ++i)
|
||||
TextureCache::DisableStage(i);
|
||||
|
||||
// set source texture
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
|
||||
glActiveTexture(GL_TEXTURE0+9);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, srcTexture);
|
||||
|
||||
if (linearFilter)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
glViewport(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight);
|
||||
|
||||
PixelShaderCache::SetCurrentShader(shader.glprogid);
|
||||
GL_REPORT_ERRORD();
|
||||
if(!(s_cached_sourceRc == sourceRc)) {
|
||||
GLfloat vertices[] = {
|
||||
-1.f, -1.f,
|
||||
(float)sourceRc.left, (float)sourceRc.top,
|
||||
-1.f, 1.f,
|
||||
(float)sourceRc.left, (float)sourceRc.bottom,
|
||||
1.f, 1.f,
|
||||
(float)sourceRc.right, (float)sourceRc.bottom,
|
||||
1.f, -1.f,
|
||||
(float)sourceRc.right, (float)sourceRc.top
|
||||
};
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_encode_VBO );
|
||||
glBufferData(GL_ARRAY_BUFFER, 4*4*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
|
||||
|
||||
s_cached_sourceRc = sourceRc;
|
||||
}
|
||||
|
||||
// Draw...
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f((float)sourceRc.left, (float)sourceRc.top); glVertex2f(-1,-1);
|
||||
glTexCoord2f((float)sourceRc.left, (float)sourceRc.bottom); glVertex2f(-1,1);
|
||||
glTexCoord2f((float)sourceRc.right, (float)sourceRc.bottom); glVertex2f(1,1);
|
||||
glTexCoord2f((float)sourceRc.right, (float)sourceRc.top); glVertex2f(1,-1);
|
||||
glEnd();
|
||||
glBindVertexArray( s_encode_VAO );
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// .. and then read back the results.
|
||||
@@ -266,9 +312,7 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
|
||||
if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
|
||||
format |= _GX_TF_CTF;
|
||||
|
||||
FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format);
|
||||
if (texconv_shader.glprogid == 0)
|
||||
return 0;
|
||||
SHADER& texconv_shader = GetOrCreateEncodingShader(format);
|
||||
|
||||
u8 *dest_ptr = Memory::GetPointer(address);
|
||||
|
||||
@@ -285,14 +329,18 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
|
||||
// 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(EFB_HEIGHT - source.top - expandedHeight),
|
||||
Renderer::EFBToScaledXf(sampleStride),
|
||||
Renderer::EFBToScaledYf(sampleStride));
|
||||
|
||||
float params[] = {
|
||||
Renderer::EFBToScaledXf(sampleStride), Renderer::EFBToScaledYf(sampleStride),
|
||||
0.0f, 0.0f,
|
||||
(float)expandedWidth, (float)Renderer::EFBToScaledY(expandedHeight)-1,
|
||||
(float)Renderer::EFBToScaledX(source.left), (float)Renderer::EFBToScaledY(EFB_HEIGHT - source.top - expandedHeight)
|
||||
};
|
||||
|
||||
texconv_shader.Bind();
|
||||
glUniform4fv(texconv_shader.UniformLocations[C_COLORS], 2, params);
|
||||
|
||||
TargetRectangle scaledSource;
|
||||
scaledSource.top = 0;
|
||||
@@ -305,7 +353,7 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
|
||||
|
||||
int readStride = (expandedWidth * cacheBytes) /
|
||||
TexDecoder_GetBlockWidthInTexels(format);
|
||||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource,
|
||||
EncodeToRamUsingShader(source_texture, scaledSource,
|
||||
dest_ptr, expandedWidth / samples, expandedHeight, readStride,
|
||||
true, bScaleByHalf > 0 && !bFromZBuffer);
|
||||
return size_in_bytes; // TODO: D3D11 is calculating this value differently!
|
||||
@@ -315,10 +363,12 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
|
||||
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight)
|
||||
{
|
||||
g_renderer->ResetAPIState();
|
||||
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
|
||||
|
||||
s_rgbToYuyvProgram.Bind();
|
||||
|
||||
EncodeToRamUsingShader(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
TextureCache::DisableStage(0);
|
||||
g_renderer->RestoreAPIState();
|
||||
GL_REPORT_ERRORD();
|
||||
@@ -326,7 +376,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des
|
||||
|
||||
|
||||
// Should be scale free.
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture)
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destRenderbuf)
|
||||
{
|
||||
u8* srcAddr = Memory::GetPointer(xfbAddr);
|
||||
if (!srcAddr)
|
||||
@@ -342,51 +392,60 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
|
||||
// switch to texture converter frame buffer
|
||||
// attach destTexture as color destination
|
||||
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, destRenderbuf);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
|
||||
for (int i = 1; i < 8; ++i)
|
||||
TextureCache::DisableStage(i);
|
||||
|
||||
// activate source texture
|
||||
// set srcAddr as data for source texture
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture);
|
||||
glActiveTexture(GL_TEXTURE0+9);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, s_srcTexture);
|
||||
|
||||
// TODO: make this less slow. (How?)
|
||||
if((GLsizei)s_srcTextureWidth == (GLsizei)srcFmtWidth && (GLsizei)s_srcTextureHeight == (GLsizei)srcHeight)
|
||||
if ((GLsizei)s_srcTextureWidth == (GLsizei)srcFmtWidth && (GLsizei)s_srcTextureHeight == (GLsizei)srcHeight)
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,0,0,s_srcTextureWidth, s_srcTextureHeight,
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0,0,0,s_srcTextureWidth, s_srcTextureHeight,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)srcFmtWidth, (GLsizei)srcHeight,
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA8, (GLsizei)srcFmtWidth, (GLsizei)srcHeight,
|
||||
0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
|
||||
s_srcTextureWidth = (GLsizei)srcFmtWidth;
|
||||
s_srcTextureHeight = (GLsizei)srcHeight;
|
||||
}
|
||||
|
||||
glViewport(0, 0, srcWidth, srcHeight);
|
||||
|
||||
PixelShaderCache::SetCurrentShader(s_yuyvToRgbProgram.glprogid);
|
||||
s_yuyvToRgbProgram.Bind();
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f((float)srcFmtWidth, (float)srcHeight); glVertex2f(1,-1);
|
||||
glTexCoord2f((float)srcFmtWidth, 0); glVertex2f(1,1);
|
||||
glTexCoord2f(0, 0); glVertex2f(-1,1);
|
||||
glTexCoord2f(0, (float)srcHeight); glVertex2f(-1,-1);
|
||||
glEnd();
|
||||
|
||||
if(s_cached_srcHeight != srcHeight || s_cached_srcWidth != srcWidth) {
|
||||
GLfloat vertices[] = {
|
||||
1.f, -1.f,
|
||||
(float)srcFmtWidth, (float)srcHeight,
|
||||
1.f, 1.f,
|
||||
(float)srcFmtWidth, 0.f,
|
||||
-1.f, 1.f,
|
||||
0.f, 0.f,
|
||||
-1.f, -1.f,
|
||||
0.f, (float)srcHeight
|
||||
};
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO );
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*4, vertices, GL_STREAM_DRAW);
|
||||
|
||||
s_cached_srcHeight = srcHeight;
|
||||
s_cached_srcWidth = srcWidth;
|
||||
}
|
||||
|
||||
glBindVertexArray( s_decode_VAO );
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// reset state
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
|
||||
TextureCache::DisableStage(0);
|
||||
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ void Shutdown();
|
||||
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight);
|
||||
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destRenderbuf);
|
||||
|
||||
// returns size of the encoded data (in bytes)
|
||||
int EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
@@ -29,10 +29,9 @@
|
||||
#include "ImageWrite.h"
|
||||
#include "BPMemory.h"
|
||||
#include "TextureCache.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "ProgramShaderCache.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexManager.h"
|
||||
@@ -40,6 +39,7 @@
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "FileUtil.h"
|
||||
#include "Debugger.h"
|
||||
#include "StreamBuffer.h"
|
||||
#include "PerfQueryBase.h"
|
||||
|
||||
#include "main.h"
|
||||
@@ -49,53 +49,112 @@ extern NativeVertexFormat *g_nativeVertexFmt;
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
//This are the initially requeted size for the buffers expresed in bytes
|
||||
const u32 MAX_IBUFFER_SIZE = 2*1024*1024;
|
||||
const u32 MAX_VBUFFER_SIZE = 16*1024*1024;
|
||||
|
||||
//static GLint max_Index_size = 0;
|
||||
|
||||
//static GLuint s_vboBuffers[MAXVBOBUFFERCOUNT] = {0};
|
||||
//static int s_nCurVBOIndex = 0; // current free buffer
|
||||
static StreamBuffer *s_vertexBuffer;
|
||||
static StreamBuffer *s_indexBuffer;
|
||||
static u32 s_baseVertex;
|
||||
static u32 s_offset[3];
|
||||
|
||||
VertexManager::VertexManager()
|
||||
{
|
||||
// TODO: doesn't seem to be used anywhere
|
||||
CreateDeviceObjects();
|
||||
}
|
||||
|
||||
//glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*)&max_Index_size);
|
||||
//
|
||||
//if (max_Index_size > MAXIBUFFERSIZE)
|
||||
// max_Index_size = MAXIBUFFERSIZE;
|
||||
//
|
||||
//GL_REPORT_ERRORD();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
GL_REPORT_ERRORD();
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
}
|
||||
|
||||
void VertexManager::CreateDeviceObjects()
|
||||
{
|
||||
s_vertexBuffer = new StreamBuffer(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
|
||||
m_vertex_buffers = s_vertexBuffer->getBuffer();
|
||||
s_indexBuffer = new StreamBuffer(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE);
|
||||
m_index_buffers = s_indexBuffer->getBuffer();
|
||||
|
||||
|
||||
m_CurrentVertexFmt = NULL;
|
||||
m_last_vao = 0;
|
||||
}
|
||||
|
||||
void VertexManager::DestroyDeviceObjects()
|
||||
{
|
||||
GL_REPORT_ERRORD();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0 );
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0 );
|
||||
GL_REPORT_ERROR();
|
||||
|
||||
delete s_vertexBuffer;
|
||||
delete s_indexBuffer;
|
||||
GL_REPORT_ERROR();
|
||||
}
|
||||
|
||||
void VertexManager::Draw()
|
||||
void VertexManager::PrepareDrawBuffers(u32 stride)
|
||||
{
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride;
|
||||
u32 triangle_index_size = IndexGenerator::GetTriangleindexLen();
|
||||
u32 line_index_size = IndexGenerator::GetLineindexLen();
|
||||
u32 point_index_size = IndexGenerator::GetPointindexLen();
|
||||
u32 index_size = (triangle_index_size+line_index_size+point_index_size) * sizeof(u16);
|
||||
|
||||
s_vertexBuffer->Alloc(vertex_data_size, stride);
|
||||
u32 offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size);
|
||||
s_baseVertex = offset / stride;
|
||||
|
||||
s_indexBuffer->Alloc(index_size);
|
||||
if(triangle_index_size)
|
||||
{
|
||||
glDrawElements(GL_TRIANGLES, IndexGenerator::GetTriangleindexLen(), GL_UNSIGNED_SHORT, GetTriangleIndexBuffer());
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
s_offset[0] = s_indexBuffer->Upload((u8*)GetTriangleIndexBuffer(), triangle_index_size * sizeof(u16));
|
||||
}
|
||||
if (IndexGenerator::GetNumLines() > 0)
|
||||
if(line_index_size)
|
||||
{
|
||||
glDrawElements(GL_LINES, IndexGenerator::GetLineindexLen(), GL_UNSIGNED_SHORT, GetLineIndexBuffer());
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
s_offset[1] = s_indexBuffer->Upload((u8*)GetLineIndexBuffer(), line_index_size * sizeof(u16));
|
||||
}
|
||||
if (IndexGenerator::GetNumPoints() > 0)
|
||||
if(point_index_size)
|
||||
{
|
||||
glDrawElements(GL_POINTS, IndexGenerator::GetPointindexLen(), GL_UNSIGNED_SHORT, GetPointIndexBuffer());
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
s_offset[2] = s_indexBuffer->Upload((u8*)GetPointIndexBuffer(), point_index_size * sizeof(u16));
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::Draw(u32 stride)
|
||||
{
|
||||
u32 triangle_index_size = IndexGenerator::GetTriangleindexLen();
|
||||
u32 line_index_size = IndexGenerator::GetLineindexLen();
|
||||
u32 point_index_size = IndexGenerator::GetPointindexLen();
|
||||
if(g_Config.backend_info.bSupportsGLBaseVertex) {
|
||||
if (triangle_index_size > 0)
|
||||
{
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (line_index_size > 0)
|
||||
{
|
||||
glDrawElementsBaseVertex(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1], s_baseVertex);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (point_index_size > 0)
|
||||
{
|
||||
glDrawElementsBaseVertex(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2], s_baseVertex);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
} else {
|
||||
if (triangle_index_size > 0)
|
||||
{
|
||||
glDrawElements(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (line_index_size > 0)
|
||||
{
|
||||
glDrawElements(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1]);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
if (point_index_size > 0)
|
||||
{
|
||||
glDrawElements(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2]);
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,13 +190,15 @@ void VertexManager::vFlush()
|
||||
|
||||
(void)GL_REPORT_ERROR();
|
||||
|
||||
//glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]);
|
||||
//glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - s_pBaseBufferPointer, s_pBaseBufferPointer, GL_STREAM_DRAW);
|
||||
GL_REPORT_ERRORD();
|
||||
GLVertexFormat *nativeVertexFmt = (GLVertexFormat*)g_nativeVertexFmt;
|
||||
u32 stride = nativeVertexFmt->GetVertexStride();
|
||||
|
||||
if(m_last_vao != nativeVertexFmt->VAO) {
|
||||
glBindVertexArray(nativeVertexFmt->VAO);
|
||||
m_last_vao = nativeVertexFmt->VAO;
|
||||
}
|
||||
|
||||
// setup the pointers
|
||||
if (g_nativeVertexFmt)
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
PrepareDrawBuffers(stride);
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
u32 usedtextures = 0;
|
||||
@@ -150,11 +211,12 @@ void VertexManager::vFlush()
|
||||
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
|
||||
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
if (usedtextures & (1 << i))
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
TextureCache::SetNextStage(i);
|
||||
g_renderer->SetSamplerState(i % 4, i / 4);
|
||||
FourTexUnits &tex = bpmem.tex[i >> 2];
|
||||
TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i,
|
||||
(tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5,
|
||||
@@ -175,62 +237,64 @@ void VertexManager::vFlush()
|
||||
}
|
||||
}
|
||||
|
||||
// set global constants
|
||||
VertexShaderManager::SetConstants();
|
||||
PixelShaderManager::SetConstants();
|
||||
|
||||
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate
|
||||
&& bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
|
||||
#ifdef USE_DUAL_SOURCE_BLEND
|
||||
bool dualSourcePossible = GLEW_ARB_blend_func_extended;
|
||||
// Makes sure we can actually do Dual source blending
|
||||
bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
|
||||
|
||||
// finally bind
|
||||
FRAGMENTSHADER* ps;
|
||||
if (dualSourcePossible)
|
||||
{
|
||||
if (useDstAlpha)
|
||||
{
|
||||
// If host supports GL_ARB_blend_func_extended, we can do dst alpha in
|
||||
// the same pass as regular rendering.
|
||||
g_renderer->SetBlendMode(true);
|
||||
ps = PixelShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components);
|
||||
ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_renderer->SetBlendMode(true);
|
||||
ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
|
||||
ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
|
||||
ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
|
||||
}
|
||||
#else
|
||||
bool dualSourcePossible = false;
|
||||
FRAGMENTSHADER* ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
|
||||
#endif
|
||||
VERTEXSHADER* vs = VertexShaderCache::SetShader(g_nativeVertexFmt->m_components);
|
||||
if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid); // Lego Star Wars crashes here.
|
||||
if (vs) VertexShaderCache::SetCurrentShader(vs->glprogid);
|
||||
|
||||
// set global constants
|
||||
VertexShaderManager::SetConstants();
|
||||
PixelShaderManager::SetConstants();
|
||||
ProgramShaderCache::UploadConstants();
|
||||
|
||||
// setup the pointers
|
||||
if (g_nativeVertexFmt)
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
|
||||
Draw();
|
||||
Draw(stride);
|
||||
g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
|
||||
//ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.early_ztest ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT));
|
||||
|
||||
// run through vertex groups again to set alpha
|
||||
if (useDstAlpha && !dualSourcePossible)
|
||||
{
|
||||
ps = PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components);
|
||||
if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid);
|
||||
|
||||
ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components);
|
||||
if (!g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
// Need to set these again, if we don't support UBO
|
||||
VertexShaderManager::SetConstants();
|
||||
PixelShaderManager::SetConstants();
|
||||
}
|
||||
|
||||
// only update alpha
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
Draw();
|
||||
Draw(stride);
|
||||
|
||||
// restore color mask
|
||||
g_renderer->SetColorMask();
|
||||
|
||||
@@ -238,22 +302,21 @@ void VertexManager::vFlush()
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
|
||||
|
||||
//s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers);
|
||||
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
|
||||
{
|
||||
// save the shaders
|
||||
ProgramShaderCache::PCacheEntry prog = ProgramShaderCache::GetShaderProgram();
|
||||
char strfile[255];
|
||||
sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
|
||||
std::ofstream fps;
|
||||
OpenFStream(fps, strfile, std::ios_base::out);
|
||||
fps << ps->strprog.c_str();
|
||||
fps << prog.shader.strpprog.c_str();
|
||||
sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
|
||||
std::ofstream fvs;
|
||||
OpenFStream(fvs, strfile, std::ios_base::out);
|
||||
fvs << vs->strprog.c_str();
|
||||
fvs << prog.shader.strvprog.c_str();
|
||||
}
|
||||
|
||||
if (g_ActiveConfig.iLog & CONF_SAVETARGETS)
|
||||
|
||||
@@ -24,6 +24,19 @@
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
class GLVertexFormat : public NativeVertexFormat
|
||||
{
|
||||
PortableVertexDeclaration vtx_decl;
|
||||
|
||||
public:
|
||||
GLVertexFormat();
|
||||
~GLVertexFormat();
|
||||
|
||||
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
|
||||
virtual void SetupVertexPointers();
|
||||
|
||||
GLuint VAO;
|
||||
};
|
||||
|
||||
// Handles the OpenGL details of drawing lots of vertices quickly.
|
||||
// Other functionality is moving out.
|
||||
@@ -31,14 +44,20 @@ class VertexManager : public ::VertexManager
|
||||
{
|
||||
public:
|
||||
VertexManager();
|
||||
|
||||
~VertexManager();
|
||||
NativeVertexFormat* CreateNativeVertexFormat();
|
||||
void CreateDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
|
||||
// NativeVertexFormat use this
|
||||
GLuint m_vertex_buffers;
|
||||
GLuint m_index_buffers;
|
||||
GLuint m_last_vao;
|
||||
private:
|
||||
void Draw();
|
||||
// temp
|
||||
void Draw(u32 stride);
|
||||
void vFlush();
|
||||
void PrepareDrawBuffers(u32 stride);
|
||||
NativeVertexFormat *m_CurrentVertexFmt;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "Render.h"
|
||||
#include "VertexShaderGen.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "ProgramShaderCache.h"
|
||||
#include "VertexManager.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "XFMemory.h"
|
||||
@@ -37,237 +37,104 @@
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||
GLuint VertexShaderCache::CurrentShader;
|
||||
bool VertexShaderCache::ShaderEnabled;
|
||||
|
||||
VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry = NULL;
|
||||
VERTEXSHADERUID VertexShaderCache::last_uid;
|
||||
|
||||
static int s_nMaxVertexInstructions;
|
||||
|
||||
|
||||
void VertexShaderCache::Init()
|
||||
void SetVSConstant4fvByName(const char * name, unsigned int offset, const float *f, const unsigned int count = 1)
|
||||
{
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
ShaderEnabled = true;
|
||||
CurrentShader = 0;
|
||||
last_entry = NULL;
|
||||
|
||||
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);
|
||||
if (strstr((const char*)glGetString(GL_VENDOR), "Humper") != NULL) s_nMaxVertexInstructions = 4096;
|
||||
#if CG_VERSION_NUM == 2100
|
||||
if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
|
||||
ProgramShaderCache::PCacheEntry tmp = ProgramShaderCache::GetShaderProgram();
|
||||
for (int a = 0; a < NUM_UNIFORMS; ++a)
|
||||
{
|
||||
s_nMaxVertexInstructions = 4096;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void VertexShaderCache::Shutdown()
|
||||
{
|
||||
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter)
|
||||
iter->second.Destroy();
|
||||
vshaders.clear();
|
||||
}
|
||||
|
||||
|
||||
VERTEXSHADER* VertexShaderCache::SetShader(u32 components)
|
||||
{
|
||||
VERTEXSHADERUID uid;
|
||||
GetVertexShaderId(&uid, components);
|
||||
if (last_entry)
|
||||
{
|
||||
if (uid == last_uid)
|
||||
if (!strcmp(name, UniformNames[a]))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
ValidateVertexShaderIDs(API_OPENGL, vshaders[uid].safe_uid, vshaders[uid].shader.strprog, components);
|
||||
return &last_entry->shader;
|
||||
if (tmp.shader.UniformLocations[a] == -1)
|
||||
return;
|
||||
else
|
||||
{
|
||||
glUniform4fv(tmp.shader.UniformLocations[a] + offset, count, f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last_uid = uid;
|
||||
|
||||
VSCache::iterator iter = vshaders.find(uid);
|
||||
if (iter != vshaders.end())
|
||||
{
|
||||
VSCacheEntry &entry = iter->second;
|
||||
last_entry = &entry;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
ValidateVertexShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, components);
|
||||
return &last_entry->shader;
|
||||
}
|
||||
|
||||
// Make an entry in the table
|
||||
VSCacheEntry& entry = vshaders[uid];
|
||||
last_entry = &entry;
|
||||
const char *code = GenerateVertexShaderCode(components, API_OPENGL);
|
||||
GetSafeVertexShaderId(&entry.safe_uid, components);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
|
||||
|
||||
SaveData(szTemp, code);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) {
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
return &last_entry->shader;
|
||||
}
|
||||
|
||||
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
|
||||
{
|
||||
// Reset GL error before compiling shaders. Yeah, we need to investigate the causes of these.
|
||||
GLenum err = GL_REPORT_ERROR();
|
||||
if (err != GL_NO_ERROR)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "glError %08x before VS!", err);
|
||||
}
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
char stropt[64];
|
||||
sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions);
|
||||
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
|
||||
CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgvProf, "main", opts);
|
||||
if (!cgIsProgram(tempprog)) {
|
||||
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 << pstrprogram;
|
||||
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 (%d):\n%s",
|
||||
szTemp,
|
||||
g_cgfProf,
|
||||
cgGetLastListing(g_cgcontext));
|
||||
|
||||
cgDestroyProgram(tempprog);
|
||||
ERROR_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
|
||||
ERROR_LOG(VIDEO, "%s", pstrprogram);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cgGetError() != CG_NO_ERROR)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
|
||||
WARN_LOG(VIDEO, "%s", pstrprogram);
|
||||
}
|
||||
|
||||
// This looks evil - we modify the program through the const char * we got from cgGetProgramString!
|
||||
// It SHOULD not have any nasty side effects though - but you never know...
|
||||
char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
|
||||
char *plocal = strstr(pcompiledprog, "program.local");
|
||||
while (plocal != NULL) {
|
||||
const char* penv = " program.env";
|
||||
memcpy(plocal, penv, 13);
|
||||
plocal = strstr(plocal + 13, "program.local");
|
||||
}
|
||||
glGenProgramsARB(1, &vs.glprogid);
|
||||
SetCurrentShader(vs.glprogid);
|
||||
|
||||
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
|
||||
err = GL_REPORT_ERROR();
|
||||
if (err != GL_NO_ERROR) {
|
||||
ERROR_LOG(VIDEO, "%s", pstrprogram);
|
||||
ERROR_LOG(VIDEO, "%s", pcompiledprog);
|
||||
}
|
||||
|
||||
cgDestroyProgram(tempprog);
|
||||
#endif
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
vs.strprog = pstrprogram;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VertexShaderCache::DisableShader()
|
||||
{
|
||||
if (ShaderEnabled)
|
||||
{
|
||||
glDisable(GL_VERTEX_PROGRAM_ARB);
|
||||
ShaderEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VertexShaderCache::SetCurrentShader(GLuint Shader)
|
||||
{
|
||||
if (!ShaderEnabled)
|
||||
{
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
ShaderEnabled= true;
|
||||
}
|
||||
if (CurrentShader != Shader)
|
||||
{
|
||||
if(Shader != 0)
|
||||
CurrentShader = Shader;
|
||||
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, const_number, f1, f2, f3, f4);
|
||||
float const buf[4] = {f1, f2, f3, f4};
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
ProgramShaderCache::SetMultiVSConstant4fv(const_number, buf, 1);
|
||||
return;
|
||||
}
|
||||
for (unsigned int a = 0; a < 9; ++a)
|
||||
{
|
||||
if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
|
||||
{
|
||||
unsigned int offset = const_number - VSVar_Loc[a].reg;
|
||||
SetVSConstant4fvByName(VSVar_Loc[a].name, offset, buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetVSConstant4fv(unsigned int const_number, const float *f)
|
||||
{
|
||||
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
ProgramShaderCache::SetMultiVSConstant4fv(const_number, f, 1);
|
||||
return;
|
||||
}
|
||||
for (unsigned int a = 0; a < 9; ++a)
|
||||
{
|
||||
if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
|
||||
{
|
||||
unsigned int offset = const_number - VSVar_Loc[a].reg;
|
||||
SetVSConstant4fvByName(VSVar_Loc[a].name, offset, f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
if(GLEW_EXT_gpu_program_parameters)
|
||||
{
|
||||
glProgramEnvParameters4fvEXT(GL_VERTEX_PROGRAM_ARB, const_number, count, f);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++,f+=4)
|
||||
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, f);
|
||||
}
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
ProgramShaderCache::SetMultiVSConstant4fv(const_number, f, count);
|
||||
return;
|
||||
}
|
||||
for (unsigned int a = 0; a < 9; ++a)
|
||||
{
|
||||
if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
|
||||
{
|
||||
unsigned int offset = const_number - VSVar_Loc[a].reg;
|
||||
SetVSConstant4fvByName(VSVar_Loc[a].name, offset, f, count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
{
|
||||
if(GLEW_EXT_gpu_program_parameters)
|
||||
float buf[4 * C_VENVCONST_END];
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
float buf[4 * C_VENVCONST_END];
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
buf[4*i ] = *f++;
|
||||
buf[4*i+1] = *f++;
|
||||
buf[4*i+2] = *f++;
|
||||
buf[4*i+3] = 0.f;
|
||||
}
|
||||
glProgramEnvParameters4fvEXT(GL_VERTEX_PROGRAM_ARB, const_number, count, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
float buf[4];
|
||||
buf[0] = *f++;
|
||||
buf[1] = *f++;
|
||||
buf[2] = *f++;
|
||||
buf[3] = 0.f;
|
||||
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, buf);
|
||||
}
|
||||
}
|
||||
buf[4*i ] = *f++;
|
||||
buf[4*i+1] = *f++;
|
||||
buf[4*i+2] = *f++;
|
||||
buf[4*i+3] = 0.f;
|
||||
}
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
{
|
||||
ProgramShaderCache::SetMultiVSConstant4fv(const_number, buf, count);
|
||||
return;
|
||||
}
|
||||
for (unsigned int a = 0; a < 9; ++a)
|
||||
{
|
||||
if (const_number >= VSVar_Loc[a].reg && const_number < ( VSVar_Loc[a].reg + VSVar_Loc[a].size))
|
||||
{
|
||||
unsigned int offset = const_number - VSVar_Loc[a].reg;
|
||||
SetVSConstant4fvByName(VSVar_Loc[a].name, offset, buf, count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OGL
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _VERTEXSHADERCACHE_H_
|
||||
#define _VERTEXSHADERCACHE_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "BPMemory.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
|
||||
struct VERTEXSHADER
|
||||
{
|
||||
VERTEXSHADER() : glprogid(0) {}
|
||||
GLuint glprogid; // opengl program id
|
||||
|
||||
std::string strprog;
|
||||
};
|
||||
|
||||
class VertexShaderCache
|
||||
{
|
||||
struct VSCacheEntry
|
||||
{
|
||||
VERTEXSHADER shader;
|
||||
VERTEXSHADERUIDSAFE safe_uid;
|
||||
VSCacheEntry() {}
|
||||
void Destroy() {
|
||||
// printf("Destroying vs %i\n", shader.glprogid);
|
||||
glDeleteProgramsARB(1, &shader.glprogid);
|
||||
shader.glprogid = 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
|
||||
|
||||
static VSCache vshaders;
|
||||
|
||||
static VSCacheEntry* last_entry;
|
||||
static VERTEXSHADERUID last_uid;
|
||||
|
||||
static GLuint CurrentShader;
|
||||
static bool ShaderEnabled;
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
static VERTEXSHADER* SetShader(u32 components);
|
||||
static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
|
||||
|
||||
static void SetCurrentShader(GLuint Shader);
|
||||
static void DisableShader();
|
||||
|
||||
};
|
||||
|
||||
} // namespace OGL
|
||||
|
||||
#endif // _VERTEXSHADERCACHE_H_
|
||||
@@ -15,6 +15,7 @@ class VideoBackend : public VideoBackendHardware
|
||||
std::string GetName();
|
||||
|
||||
void Video_Prepare();
|
||||
void Video_Cleanup();
|
||||
|
||||
void ShowConfig(void* parent);
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ Make AA apply instantly during gameplay if possible
|
||||
#include "LogManager.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "EmuWindow.h"
|
||||
@@ -79,10 +80,9 @@ Make AA apply instantly during gameplay if possible
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexLoaderManager.h"
|
||||
#include "VertexManager.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "PixelShaderManager.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "VertexShaderManager.h"
|
||||
#include "ProgramShaderCache.h"
|
||||
#include "CommandProcessor.h"
|
||||
#include "PixelEngine.h"
|
||||
#include "TextureConverter.h"
|
||||
@@ -92,6 +92,7 @@ Make AA apply instantly during gameplay if possible
|
||||
#include "FramebufferManager.h"
|
||||
#include "Core.h"
|
||||
#include "Host.h"
|
||||
#include "SamplerCache.h"
|
||||
#include "PerfQuery.h"
|
||||
|
||||
#include "VideoState.h"
|
||||
@@ -108,32 +109,34 @@ std::string VideoBackend::GetName()
|
||||
|
||||
void GetShaders(std::vector<std::string> &shaders)
|
||||
{
|
||||
shaders.clear();
|
||||
if (File::IsDirectory(File::GetUserPath(D_SHADERS_IDX)))
|
||||
{
|
||||
File::FSTEntry entry;
|
||||
File::ScanDirectoryTree(File::GetUserPath(D_SHADERS_IDX), entry);
|
||||
for (u32 i = 0; i < entry.children.size(); i++)
|
||||
{
|
||||
std::string name = entry.children[i].virtualName.c_str();
|
||||
if (!strcasecmp(name.substr(name.size() - 4).c_str(), ".txt"))
|
||||
name = name.substr(0, name.size() - 4);
|
||||
shaders.push_back(name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
File::CreateDir(File::GetUserPath(D_SHADERS_IDX).c_str());
|
||||
}
|
||||
shaders.clear();
|
||||
if (File::IsDirectory(File::GetUserPath(D_SHADERS_IDX)))
|
||||
{
|
||||
File::FSTEntry entry;
|
||||
File::ScanDirectoryTree(File::GetUserPath(D_SHADERS_IDX), entry);
|
||||
for (u32 i = 0; i < entry.children.size(); i++)
|
||||
{
|
||||
std::string name = entry.children[i].virtualName.c_str();
|
||||
if (!strcasecmp(name.substr(name.size() - 4).c_str(), ".txt")) {
|
||||
name = name.substr(0, name.size() - 4);
|
||||
shaders.push_back(name);
|
||||
}
|
||||
}
|
||||
std::sort(shaders.begin(), shaders.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
File::CreateDir(File::GetUserPath(D_SHADERS_IDX).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void InitBackendInfo()
|
||||
{
|
||||
g_Config.backend_info.APIType = API_OPENGL;
|
||||
g_Config.backend_info.bUseRGBATextures = false;
|
||||
g_Config.backend_info.bUseRGBATextures = true;
|
||||
g_Config.backend_info.bUseMinimalMipCount = false;
|
||||
g_Config.backend_info.bSupports3DVision = false;
|
||||
g_Config.backend_info.bSupportsDualSourceBlend = false; // supported, but broken
|
||||
//g_Config.backend_info.bSupportsDualSourceBlend = true; // is gpu depenend and must be set in renderer
|
||||
g_Config.backend_info.bSupportsFormatReinterpretation = false;
|
||||
g_Config.backend_info.bSupportsPixelLighting = true;
|
||||
|
||||
@@ -191,18 +194,18 @@ void VideoBackend::Video_Prepare()
|
||||
CommandProcessor::Init();
|
||||
PixelEngine::Init();
|
||||
|
||||
g_texture_cache = new TextureCache;
|
||||
|
||||
BPInit();
|
||||
g_vertex_manager = new VertexManager;
|
||||
g_perf_query = new PerfQuery;
|
||||
Fifo_Init(); // must be done before OpcodeDecoder_Init()
|
||||
OpcodeDecoder_Init();
|
||||
VertexShaderCache::Init();
|
||||
VertexShaderManager::Init();
|
||||
PixelShaderCache::Init();
|
||||
PixelShaderManager::Init();
|
||||
ProgramShaderCache::Init();
|
||||
PostProcessing::Init();
|
||||
g_texture_cache = new TextureCache();
|
||||
g_sampler_cache = new SamplerCache();
|
||||
Renderer::Init();
|
||||
GL_REPORT_ERRORD();
|
||||
VertexLoaderManager::Init();
|
||||
TextureConverter::Init();
|
||||
@@ -217,7 +220,11 @@ void VideoBackend::Video_Prepare()
|
||||
void VideoBackend::Shutdown()
|
||||
{
|
||||
s_BackendInitialized = false;
|
||||
GLInterface->Shutdown();
|
||||
}
|
||||
|
||||
void VideoBackend::Video_Cleanup() {
|
||||
|
||||
if (g_renderer)
|
||||
{
|
||||
s_efbAccessRequested = false;
|
||||
@@ -227,24 +234,26 @@ void VideoBackend::Shutdown()
|
||||
DLCache::Shutdown();
|
||||
#endif
|
||||
Fifo_Shutdown();
|
||||
PostProcessing::Shutdown();
|
||||
|
||||
// The following calls are NOT Thread Safe
|
||||
// And need to be called from the video thread
|
||||
Renderer::Shutdown();
|
||||
TextureConverter::Shutdown();
|
||||
VertexLoaderManager::Shutdown();
|
||||
VertexShaderCache::Shutdown();
|
||||
delete g_sampler_cache;
|
||||
g_sampler_cache = NULL;
|
||||
delete g_texture_cache;
|
||||
g_texture_cache = NULL;
|
||||
PostProcessing::Shutdown();
|
||||
ProgramShaderCache::Shutdown();
|
||||
VertexShaderManager::Shutdown();
|
||||
PixelShaderManager::Shutdown();
|
||||
PixelShaderCache::Shutdown();
|
||||
delete g_vertex_manager;
|
||||
delete g_texture_cache;
|
||||
g_vertex_manager = NULL;
|
||||
OpcodeDecoder_Shutdown();
|
||||
delete g_renderer;
|
||||
g_renderer = NULL;
|
||||
g_texture_cache = NULL;
|
||||
}
|
||||
GLInterface->Shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ static GLuint program;
|
||||
|
||||
// Rasterfont isn't compatible with GLES
|
||||
#ifndef USE_GLES
|
||||
RasterFont* s_pfont = NULL;
|
||||
OGL::RasterFont* s_pfont = NULL;
|
||||
#endif
|
||||
|
||||
void SWRenderer::Init()
|
||||
@@ -87,7 +87,7 @@ void SWRenderer::Prepare()
|
||||
CreateShaders();
|
||||
// TODO: Enable for GLES once RasterFont supports GLES
|
||||
#ifndef USE_GLES
|
||||
s_pfont = new RasterFont();
|
||||
s_pfont = new OGL::RasterFont();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
#endif
|
||||
GL_REPORT_ERRORD();
|
||||
@@ -98,12 +98,11 @@ void SWRenderer::RenderText(const char* pstr, int left, int top, u32 color)
|
||||
#ifndef USE_GLES
|
||||
int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth();
|
||||
int nBackbufferHeight = (int)GLInterface->GetBackBufferHeight();
|
||||
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
|
||||
((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
|
||||
|
||||
s_pfont->printMultilineText(pstr,
|
||||
left * 2.0f / (float)nBackbufferWidth - 1,
|
||||
1 - top * 2.0f / (float)nBackbufferHeight,
|
||||
0, nBackbufferWidth, nBackbufferHeight);
|
||||
0, nBackbufferWidth, nBackbufferHeight, color);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -159,18 +159,26 @@ void VideoSoftware::EmuStateChange(EMUSTATE_CHANGE newState)
|
||||
|
||||
void VideoSoftware::Shutdown()
|
||||
{
|
||||
// TODO: should be in Video_Cleanup
|
||||
HwRasterizer::Shutdown();
|
||||
SWRenderer::Shutdown();
|
||||
|
||||
GLInterface->Shutdown();
|
||||
}
|
||||
|
||||
void VideoSoftware::Video_Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
// This is called after Video_Initialize() from the Core
|
||||
void VideoSoftware::Video_Prepare()
|
||||
{
|
||||
GLInterface->MakeCurrent();
|
||||
// Init extension support.
|
||||
// Required for WGL SwapInterval
|
||||
#ifndef USE_GLES
|
||||
#ifdef __APPLE__
|
||||
glewExperimental = 1;
|
||||
#endif
|
||||
if (glewInit() != GLEW_OK) {
|
||||
ERROR_LOG(VIDEO, "glewInit() failed!Does your video card support OpenGL 2.x?");
|
||||
return;
|
||||
|
||||
@@ -21,6 +21,7 @@ class VideoSoftware : public VideoBackend
|
||||
void ShowConfig(void* parent);
|
||||
|
||||
void Video_Prepare();
|
||||
void Video_Cleanup();
|
||||
|
||||
void Video_EnterLoop();
|
||||
void Video_ExitLoop();
|
||||
|
||||
@@ -102,22 +102,6 @@
|
||||
obj:/usr/lib/libasound.so.2.0.0
|
||||
fun:snd_pcm_open_named_slave
|
||||
}
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Cond
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
fun:cgCreateProgram
|
||||
}
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Cond
|
||||
@@ -149,27 +133,4 @@
|
||||
obj:/usr/lib/libasound.so.2.0.0
|
||||
obj:*
|
||||
}
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Cond
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
fun:cgCreateProgram
|
||||
fun:_ZN15PixelShaderMngr18CompilePixelShaderER14FRAGMENTSHADERPKc
|
||||
}
|
||||
{
|
||||
<insert a suppression name here>
|
||||
Memcheck:Cond
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:/usr/lib/libCg.so
|
||||
obj:*
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\Cg;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;glew32s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;opengl32.lib;glew32s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup />
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\Cg64;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;glew64s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;opengl32.lib;glew64s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup />
|
||||
|
||||
Reference in New Issue
Block a user