gsdx ogl:

* allow to switch renderer with F9
* skip first frame in stat of the replayer
* drop msaa. Fxaa and internal resolution will do the job
* move texture attachment from texture object into device object (allow to keep sanely the state)
* split the write buffer and attachment setup
* completely split sampler and texture input setup
* redo GSDeviceOGL::CopyOffscreen to avoid an extra copy.



git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5704 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut 2013-07-19 19:25:50 +00:00
parent 92487e2618
commit d3e1e4da0d
10 changed files with 200 additions and 458 deletions

View File

@ -429,9 +429,17 @@ EXPORT_C_(int) GSopen2(void** dsp, uint32 flags)
case 0: renderer = 1; break; // DX9: HW to SW
case 4: renderer = 3; break; // DX11: SW to HW
case 3: renderer = 4; break; // DX11: HW to SW
case 13: renderer = 12; break; // OGL: SW to HW
case 12: renderer = 13; break; // OGL: HW to SW
default: renderer = best_sw_renderer; // If wasn't using DX (e.g. SDL), use best SW renderer.
}
#endif
#ifdef _LINUX
switch(renderer) {
case 13: renderer = 12; break; // OGL: SW to HW
case 12: renderer = 13; break; // OGL: HW to SW
}
#endif
}
@ -1594,15 +1602,18 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
finished--;
}
if (theApp.GetConfig("linux_replay", 1) > 1) {
// Print some nice stats
float n = (float)theApp.GetConfig("linux_replay", 1);
// Skip first frame (shader compilation populate the result)
// it divides by 10 the standard deviation...
float n = (float)theApp.GetConfig("linux_replay", 1) - 1.0f;
float mean = 0;
float sd = 0;
for (auto i = stats.begin(); i != stats.end(); i++) {
for (auto i = stats.begin()+1; i != stats.end(); i++) {
mean += *i;
}
mean = mean/n;
for (auto i = stats.begin(); i != stats.end(); i++) {
for (auto i = stats.begin()+1; i != stats.end(); i++) {
sd += pow((*i)-mean, 2);
}
sd = sqrt(sd/n);
@ -1611,6 +1622,7 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
fprintf(stderr, "Standard deviation: %fms\n", sd);
fprintf(stderr, "Mean by frame: %fms (%ffps)\n", mean/(float)frame_number, 1000.0f*frame_number/mean);
fprintf(stderr, "Standard deviatin by frame: %fms\n", sd/(float)frame_number);
}
for(auto i = packets.begin(); i != packets.end(); i++)
{

View File

@ -24,10 +24,6 @@
#include "res/glsl_source.h"
// TODO performance cost to investigate
// Texture attachment/glDrawBuffer. For the moment it set every draw and potentially multiple time (first time in clear, second time in rendering)
// Attachment 1 is only used with the GL_16UI format
//#define LOUD_DEBUGGING
//#define PRINT_FRAME_NUMBER
//#define ONLY_LINES
@ -54,8 +50,6 @@ GSDeviceOGL::GSDeviceOGL()
, m_vb_sr(NULL)
, m_shader(NULL)
{
m_msaa = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_MSAA", 0) : 0;
memset(&m_merge_obj, 0, sizeof(m_merge_obj));
memset(&m_interlace, 0, sizeof(m_interlace));
memset(&m_convert, 0, sizeof(m_convert));
@ -143,7 +137,7 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int for
{
// A wrapper to call GSTextureOGL, with the different kind of parameter
GSTextureOGL* t = NULL;
t = new GSTextureOGL(type, w, h, msaa, format, m_fbo_read);
t = new GSTextureOGL(type, w, h, format, m_fbo_read);
switch(type)
{
@ -152,7 +146,7 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int for
break;
case GSTexture::DepthStencil:
ClearDepth(t, 0);
//FIXME might be need to clear the stencil too
// No need to clear the stencil now.
break;
}
return t;
@ -160,16 +154,7 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int for
GSTexture* GSDeviceOGL::FetchSurface(int type, int w, int h, bool msaa, int format)
{
// FIXME: keep DX code. Do not know how work msaa but not important for the moment
// Current config give only 0 or 1
#if 0
if(m_msaa < 2) {
msaa = false;
}
#endif
msaa = false;
return GSDevice::FetchSurface(type, w, h, msaa, format);
return GSDevice::FetchSurface(type, w, h, false, format);
}
bool GSDeviceOGL::Create(GSWnd* wnd)
@ -180,9 +165,6 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
if (!GLLoader::check_gl_supported_extension()) return false;
}
// FIXME disable it when code is ready
// glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
m_window = wnd;
// ****************************************************************
@ -281,7 +263,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
#endif
// ****************************************************************
// fxaa (bonus)
// fxaa
// ****************************************************************
std::string fxaa_macro = "#define FXAA_GLSL_130 1\n";
if (GLLoader::found_GL_ARB_gpu_shader5) {
@ -320,59 +302,6 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
GSVector4i rect = wnd->GetClientRect();
Reset(rect.z, rect.w);
#if 0
HRESULT hr = E_FAIL;
DXGI_SWAP_CHAIN_DESC scd;
D3D11_BUFFER_DESC bd;
D3D11_SAMPLER_DESC sd;
D3D11_DEPTH_STENCIL_DESC dsd;
D3D11_RASTERIZER_DESC rd;
D3D11_BLEND_DESC bsd;
memset(&scd, 0, sizeof(scd));
scd.BufferCount = 2;
scd.BufferDesc.Width = 1;
scd.BufferDesc.Height = 1;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
//scd.BufferDesc.RefreshRate.Numerator = 60;
//scd.BufferDesc.RefreshRate.Denominator = 1;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = (HWND)m_wnd->GetHandle();
scd.SampleDesc.Count = 1;
scd.SampleDesc.Quality = 0;
// Always start in Windowed mode. According to MS, DXGI just "prefers" this, and it's more or less
// required if we want to add support for dual displays later on. The fullscreen/exclusive flip
// will be issued after all other initializations are complete.
scd.Windowed = TRUE;
// NOTE : D3D11_CREATE_DEVICE_SINGLETHREADED
// This flag is safe as long as the DXGI's internal message pump is disabled or is on the
// same thread as the GS window (which the emulator makes sure of, if it utilizes a
// multithreaded GS). Setting the flag is a nice and easy 5% speedup on GS-intensive scenes.
uint32 flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
#ifdef DEBUG
flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_FEATURE_LEVEL level;
const D3D_FEATURE_LEVEL levels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, levels, countof(levels), D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &level, &m_ctx);
// hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, flags, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &level, &m_ctx);
#endif
return true;
}
@ -385,7 +314,7 @@ bool GSDeviceOGL::Reset(int w, int h)
// Opengl allocate the backbuffer with the window. The render is done in the backbuffer when
// there isn't any FBO. Only a dummy texture is created to easily detect when the rendering is done
// in the backbuffer
m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, false, 0, m_fbo_read);
m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, 0, m_fbo_read);
return true;
}
@ -458,7 +387,9 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c)
gl_ClearBufferfv(GL_COLOR, 0, c.v);
} else {
OMSetFBO(m_fbo);
static_cast<GSTextureOGL*>(t)->Attach(GL_COLOR_ATTACHMENT0);
// FIXME useful
OMSetWriteBuffer();
OMAttachRt(t);
gl_ClearBufferfv(GL_COLOR, 0, c.v);
}
@ -474,7 +405,9 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c)
void GSDeviceOGL::ClearDepth(GSTexture* t, float c)
{
OMSetFBO(m_fbo);
static_cast<GSTextureOGL*>(t)->Attach(GL_DEPTH_STENCIL_ATTACHMENT);
// FIXME useful
OMSetWriteBuffer();
OMAttachDs(t);
glDisable(GL_SCISSOR_TEST);
if (m_state.dss != NULL && m_state.dss->IsMaskEnable()) {
@ -490,7 +423,9 @@ void GSDeviceOGL::ClearDepth(GSTexture* t, float c)
void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c)
{
OMSetFBO(m_fbo);
static_cast<GSTextureOGL*>(t)->Attach(GL_DEPTH_STENCIL_ATTACHMENT);
// FIXME useful
OMSetWriteBuffer();
OMAttachDs(t);
GLint color = c;
glDisable(GL_SCISSOR_TEST);
@ -608,48 +543,19 @@ GSTexture* GSDeviceOGL::CreateOffscreen(int w, int h, int format)
// blit a texture into an offscreen buffer
GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format)
{
GSTexture* dst = NULL;
ASSERT(src);
ASSERT(format == GL_RGBA8 || format == GL_R16UI);
if(format == 0) format = GL_RGBA8;
if(format != GL_RGBA8 && format != GL_R16UI)
{
ASSERT(0);
if(format != GL_RGBA8 && format != GL_R16UI) return NULL;
return NULL;
}
// FIXME: It is possible to bypass completely offscreen-buffer on opengl but it needs some re-thinking of the code.
// For the moment mimic dx11
GSTexture* rt = CreateRenderTarget(w, h, false, format);
if(rt)
{
GSTexture* dst = CreateOffscreen(w, h, format);
GSVector4 dr(0, 0, w, h);
if(GSTexture* src2 = src->IsMSAA() ? Resolve(src) : src)
{
StretchRect(src2, sr, rt, dr, m_convert.ps[format == GL_R16UI ? 1 : 0]);
if(src2 != src) Recycle(src2);
}
GSVector4i dor(0, 0, w, h);
dst = CreateOffscreen(w, h, format);
if (dst) CopyRect(rt, dst, dor);
#if 0
if(dst)
{
m_ctx->CopyResource(*(GSTexture11*)dst, *(GSTexture11*)rt);
}
#endif
Recycle(rt);
}
StretchRect(src, sr, dst, dr, m_convert.ps[format == GL_R16UI ? 1 : 0]);
return dst;
//return rt;
}
// Copy a sub part of a texture into another
@ -658,32 +564,23 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w
// From a sub-part to a full texture
void GSDeviceOGL::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
{
if(!st || !dt)
{
ASSERT(0);
return;
}
ASSERT(st && dt);
// FIXME: the extension was integrated in opengl 4.3 (now we need driver that support OGL4.3)
// FIXME check those function work as expected
// void CopyImageSubDataNV(
// uint32 srcName, enum srcTarget, int srcLevel, int srcX, int srcY, int srcZ,
// uint32 dstName, enum dstTarget, int dstLevel, int dstX, int dstY, int dstZ,
// sizei width, sizei height, sizei depth);
if (GLLoader::found_GL_NV_copy_image) {
#ifndef ENABLE_GLES
gl_CopyImageSubDataNV( static_cast<GSTextureOGL*>(st)->GetID(), static_cast<GSTextureOGL*>(st)->GetTarget(),
gl_CopyImageSubDataNV( static_cast<GSTextureOGL*>(st)->GetID(), GL_TEXTURE_2D,
0, r.x, r.y, 0,
static_cast<GSTextureOGL*>(dt)->GetID(), static_cast<GSTextureOGL*>(dt)->GetTarget(),
static_cast<GSTextureOGL*>(dt)->GetID(), GL_TEXTURE_2D,
0, r.x, r.y, 0,
r.width(), r.height(), 1);
#endif
} else if (GLLoader::found_GL_ARB_copy_image) {
// Would need an update of GL definition. For the moment it isn't supported by driver anyway.
#if 0
gl_CopyImageSubData( static_cast<GSTextureOGL*>(st)->GetID(), static_cast<GSTextureOGL*>(st)->GetTarget(),
gl_CopyImageSubData( static_cast<GSTextureOGL*>(st)->GetID(), GL_TEXTURE_2D,
0, r.x, r.y, 0,
static_cast<GSTextureOGL*>(dt)->GetID(), static_cast<GSTextureOGL*>(dt)->GetTarget(),
static_cast<GSTextureOGL*>(dt)->GetID(), GL_TEXTURE_2D,
0, r.x, r.y, 0,
r.width(), r.height(), 1);
#endif
@ -694,17 +591,14 @@ void GSDeviceOGL::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
st_ogl->AttachRead(GL_COLOR_ATTACHMENT0);
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, static_cast<GSTextureOGL*>(st_ogl)->GetID(), 0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
dt_ogl->EnableUnit(6);
glCopyTexSubImage2D(dt_ogl->GetTarget(), 0, r.x, r.y, r.x, r.y, r.width(), r.height());
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.x, r.y, r.width(), r.height());
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
#if 0
D3D11_BOX box = {r.left, r.top, 0, r.right, r.bottom, 1};
m_ctx->CopySubresourceRegion(*(GSTexture11*)dt, 0, 0, 0, 0, *(GSTexture11*)st, 0, &box);
#endif
}
void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
@ -801,8 +695,8 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
// ps
// ************************************
PSSetShaderResources(st, NULL);
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt, 0);
PSSetShaderResource(0, st);
PSSetSamplerState(0, linear ? m_convert.ln : m_convert.pt);
m_shader->PS(ps);
// ************************************
@ -815,8 +709,6 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
// ************************************
EndScene();
PSSetShaderResources(NULL, NULL);
}
void GSDeviceOGL::DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c)
@ -896,7 +788,7 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
{
#ifdef ENABLE_OGL_STENCIL_DEBUG
const GSVector2i& size = rt->GetSize();
GSTexture* t = CreateRenderTarget(size.x, size.y, rt->IsMSAA());
GSTexture* t = CreateRenderTarget(size.x, size.y, false);
#else
GSTexture* t = NULL;
#endif
@ -928,10 +820,8 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
// ps
GSTexture* rt2 = rt->IsMSAA() ? Resolve(rt) : rt;
PSSetShaderResources(rt2, NULL);
PSSetSamplerState(m_convert.pt, 0);
PSSetShaderResource(0, rt);
PSSetSamplerState(0, m_convert.pt);
m_shader->PS(m_convert.ps[datm ? 2 : 3]);
//
@ -943,31 +833,9 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
EndScene();
#ifdef ENABLE_OGL_STENCIL_DEBUG
// FIXME invalidate data
Recycle(t);
#endif
if(rt2 != rt) Recycle(rt2);
}
// copy a multisample texture to a non-texture multisample. On opengl you need 2 FBO with different level of
// sample and then do a blit. Headach expected to for the moment just drop MSAA...
GSTexture* GSDeviceOGL::Resolve(GSTexture* t)
{
ASSERT(t != NULL && t->IsMSAA());
#if 0
if(GSTexture* dst = CreateRenderTarget(t->GetWidth(), t->GetHeight(), false, t->GetFormat()))
{
dst->SetScale(t->GetScale());
m_ctx->ResolveSubresource(*(GSTexture11*)dst, 0, *(GSTexture11*)t, 0, (DXGI_FORMAT)t->GetFormat());
return dst;
}
return NULL;
#endif
return NULL;
}
void GSDeviceOGL::EndScene()
@ -1018,53 +886,54 @@ void GSDeviceOGL::IASetPrimitiveTopology(GLenum topology)
m_state.vb->SetTopology(topology);
}
void GSDeviceOGL::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
void GSDeviceOGL::PSSetShaderResource(const int i, GSTexture* sr)
{
PSSetShaderResource(0, sr0);
PSSetShaderResource(1, sr1);
//PSSetShaderResource(2, NULL);
ASSERT(sr);
static_cast<GSTextureOGL*>(sr)->EnableUnit(i);
}
void GSDeviceOGL::PSSetShaderResource(int i, GSTexture* sr)
void GSDeviceOGL::PSSetSamplerState(const int i, GLuint ss)
{
GSTextureOGL* srv = static_cast<GSTextureOGL*>(sr);
if (m_state.ps_srv[i] != srv)
{
m_state.ps_srv[i] = srv;
if (srv != NULL)
m_state.ps_srv[i]->EnableUnit(i);
if (m_state.ps_ss[i] != ss) {
m_state.ps_ss[i] = ss;
gl_BindSampler(i, ss);
}
}
void GSDeviceOGL::PSSetSamplerState(GLuint ss0, GLuint ss1, GLuint ss2)
void GSDeviceOGL::OMAttachRt(GSTexture* rt)
{
if (m_state.ps_ss[0] != ss0) {
m_state.ps_ss[0] = ss0;
gl_BindSampler(0, ss0);
}
if (m_state.ps_ss[1] != ss1) {
m_state.ps_ss[1] = ss1;
gl_BindSampler(1, ss1);
if (m_state.rt != rt) {
m_state.rt = rt;
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, static_cast<GSTextureOGL*>(rt)->GetID(), 0);
}
}
void GSDeviceOGL::OMSetFBO(GLuint fbo, GLenum buffer)
void GSDeviceOGL::OMAttachDs(GSTexture* ds)
{
if (m_state.ds != ds) {
m_state.ds = ds;
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, static_cast<GSTextureOGL*>(ds)->GetID(), 0);
}
}
void GSDeviceOGL::OMSetFBO(GLuint fbo)
{
if (m_state.fbo != fbo) {
m_state.fbo = fbo;
gl_BindFramebuffer(GL_FRAMEBUFFER, fbo);
// FIXME DEBUG
//if (fbo) fprintf(stderr, "FB status %x\n", gl_CheckFramebufferStatus(GL_FRAMEBUFFER));
}
}
// Note if m_fbo is 0, standard GL_BACK will be used instead
if (m_fbo && m_state.draw != buffer) {
void GSDeviceOGL::OMSetWriteBuffer(GLenum buffer)
{
// Note if fbo is 0, standard GL_BACK will be used instead
if (m_state.fbo && m_state.draw != buffer) {
m_state.draw = buffer;
GLenum target[1] = {buffer};
gl_DrawBuffers(1, target);
}
}
void GSDeviceOGL::OMSetDepthStencilState(GSDepthStencilOGL* dss, uint8 sref)
@ -1093,16 +962,18 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto
if (rt == NULL || !static_cast<GSTextureOGL*>(rt)->IsBackbuffer()) {
if (rt) {
OMSetFBO(m_fbo);
static_cast<GSTextureOGL*>(rt)->Attach(GL_COLOR_ATTACHMENT0);
OMSetWriteBuffer();
OMAttachRt(rt);
} else {
// Note: NULL rt is only used in DATE so far. Color writing is disabled
// on the blend setup
OMSetFBO(m_fbo, GL_NONE);
OMSetFBO(m_fbo);
OMSetWriteBuffer(GL_NONE);
}
// Note: it must be done after OMSetFBO
if (ds)
static_cast<GSTextureOGL*>(ds)->Attach(GL_DEPTH_STENCIL_ATTACHMENT);
OMAttachDs(ds);
} else {
// Render in the backbuffer

View File

@ -43,7 +43,6 @@ class GSBlendStateOGL {
bool m_g_msk;
bool m_a_msk;
bool constant_factor;
float debug_factor;
public:
@ -104,7 +103,6 @@ public:
if (m_enable) {
glEnable(GL_BLEND);
if (HasConstantFactor()) {
debug_factor = factor;
gl_BlendColor(factor, factor, factor, 0);
}
@ -114,38 +112,6 @@ public:
glDisable(GL_BLEND);
}
}
char* NameOfParam(GLenum p)
{
switch (p) {
case GL_FUNC_ADD: return "ADD";
case GL_FUNC_SUBTRACT: return "SUB";
case GL_FUNC_REVERSE_SUBTRACT: return "REV SUB";
case GL_ONE: return "ONE";
case GL_ZERO: return "ZERO";
#ifndef ENABLE_GLES
case GL_SRC1_ALPHA: return "SRC1 ALPHA";
case GL_ONE_MINUS_SRC1_ALPHA: return "1 - SRC1 ALPHA";
#endif
case GL_SRC_ALPHA: return "SRC ALPHA";
case GL_ONE_MINUS_DST_ALPHA: return "1 - DST ALPHA";
case GL_DST_ALPHA: return "DST ALPHA";
case GL_DST_COLOR: return "DST COLOR";
case GL_ONE_MINUS_SRC_ALPHA: return "1 - SRC ALPHA";
case GL_CONSTANT_COLOR: return "CST";
case GL_ONE_MINUS_CONSTANT_COLOR: return "1 - CST";
default: return "UKN";
}
return "UKN";
}
void debug()
{
if (!m_enable) return;
fprintf(stderr,"Blend op: %s; src:%s; dst:%s\n", NameOfParam(m_equation_RGB), NameOfParam(m_func_sRGB), NameOfParam(m_func_dRGB));
if (HasConstantFactor()) fprintf(stderr, "Blend constant: %f\n", debug_factor);
fprintf(stderr,"Mask. R:%d B:%d G:%d A:%d\n", m_r_msk, m_b_msk, m_g_msk, m_a_msk);
}
};
class GSDepthStencilOGL {
@ -161,21 +127,6 @@ class GSDepthStencilOGL {
const GLuint m_stencil_spass_dfail_op;
GLuint m_stencil_spass_dpass_op;
char* NameOfParam(GLenum p)
{
switch(p) {
case GL_NEVER: return "NEVER";
case GL_ALWAYS: return "ALWAYS";
case GL_GEQUAL: return "GEQUAL";
case GL_GREATER: return "GREATER";
case GL_KEEP: return "KEEP";
case GL_EQUAL: return "EQUAL";
case GL_REPLACE: return "REPLACE";
default: return "UKN";
}
return "UKN";
}
public:
GSDepthStencilOGL() : m_depth_enable(false)
@ -188,7 +139,11 @@ public:
, m_stencil_sfail_op(GL_KEEP)
, m_stencil_spass_dfail_op(GL_KEEP)
, m_stencil_spass_dpass_op(GL_KEEP)
{}
{
// Only needed once since m_stencil_mask is constant
// Control which stencil bitplane are written
glStencilMask(m_stencil_mask);
}
void EnableDepth() { m_depth_enable = true; }
void EnableStencil() { m_stencil_enable = true; }
@ -213,27 +168,10 @@ public:
// Note: here the mask control which bitplane is considered by the operation
glStencilFunc(m_stencil_func, m_stencil_ref, m_stencil_mask);
glStencilOp(m_stencil_sfail_op, m_stencil_spass_dfail_op, m_stencil_spass_dpass_op);
// FIXME only needed once since m_stencil_mask is constant
// Control which stencil bitplane are written
glStencilMask(m_stencil_mask);
} else
glDisable(GL_STENCIL_TEST);
}
void debug() { debug_depth(); debug_stencil(); }
void debug_depth()
{
if (!m_depth_enable) return;
fprintf(stderr, "Depth %s. Mask %x\n", NameOfParam(m_depth_func), m_depth_mask);
}
void debug_stencil()
{
if (!m_stencil_enable) return;
fprintf(stderr, "Stencil %s. Both pass op %s\n", NameOfParam(m_stencil_func), NameOfParam(m_stencil_spass_dpass_op));
}
bool IsMaskEnable() { return m_depth_mask != GL_FALSE; }
};
@ -540,26 +478,17 @@ class GSDeviceOGL : public GSDevice
struct {
GSVertexBufferStateOGL* vb;
GLuint vs; // program
GSUniformBufferOGL* cb; // uniform current buffer
GLuint gs; // program
// FIXME texture binding. Maybe not equivalent for the state but the best I could find.
GSTextureOGL* ps_srv[3];
// ID3D11ShaderResourceView* ps_srv[3];
GLuint ps; // program
GSUniformBufferOGL* cb;
GLuint ps_ss[3]; // sampler
GSVector2i viewport;
GSVector4i scissor;
GSDepthStencilOGL* dss;
GSBlendStateOGL* bs;
float bf;
// FIXME texture attachment in the FBO
// ID3D11RenderTargetView* rtv;
// ID3D11DepthStencilView* dsv;
GSTextureOGL* rtv;
GSTextureOGL* dsv;
float bf; // blend factor
GLuint fbo;
GLenum draw;
GSTexture* rt; // render target
GSTexture* ds; // Depth-Stencil
} m_state;
GSShaderOGL* m_shader;
@ -580,7 +509,6 @@ class GSDeviceOGL : public GSDevice
VSConstantBuffer m_vs_cb_cache;
PSConstantBuffer m_ps_cb_cache;
protected:
GSTexture* CreateSurface(int type, int w, int h, bool msaa, int format);
GSTexture* FetchSurface(int type, int w, int h, bool msaa, int format);
@ -589,6 +517,11 @@ class GSDeviceOGL : public GSDevice
void DoFXAA(GSTexture* st, GSTexture* dt);
void DoShadeBoost(GSTexture* st, GSTexture* dt);
void OMAttachRt(GSTexture* rt);
void OMAttachDs(GSTexture* ds);
void OMSetFBO(GLuint fbo);
void OMSetWriteBuffer(GLenum buffer = GL_COLOR_ATTACHMENT0);
public:
GSDeviceOGL();
virtual ~GSDeviceOGL();
@ -629,8 +562,6 @@ class GSDeviceOGL : public GSDevice
void SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm);
GSTexture* Resolve(GSTexture* t);
void EndScene();
void IASetPrimitiveTopology(GLenum topology);
@ -642,11 +573,9 @@ class GSDeviceOGL : public GSDevice
void SetUniformBuffer(GSUniformBufferOGL* cb);
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
void PSSetShaderResource(int i, GSTexture* sr);
void PSSetSamplerState(GLuint ss0, GLuint ss1, GLuint ss2 = 0);
void PSSetShaderResource(const int i, GSTexture* sr);
void PSSetSamplerState(const int i, GLuint ss);
void OMSetFBO(GLuint fbo, GLenum buffer = GL_COLOR_ATTACHMENT0);
void OMSetDepthStencilState(GSDepthStencilOGL* dss, uint8 sref);
void OMSetBlendState(GSBlendStateOGL* bs, float bf);
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL);
@ -665,6 +594,8 @@ class GSDeviceOGL : public GSDevice
void SetupIA(const void* vertex, int vertex_count, const uint32* index, int index_count, int prim);
void SetupVS(VSSelector sel, const VSConstantBuffer* cb);
void SetupGS(GSSelector sel);
void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel);
void SetupPS(PSSelector sel, const PSConstantBuffer* cb);
void SetupSampler(PSSelector sel, PSSamplerSelector ssel);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);
};

View File

@ -486,6 +486,11 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
ps_ssel.tau = (context->CLAMP.WMS + 3) >> 1;
ps_ssel.tav = (context->CLAMP.WMT + 3) >> 1;
ps_ssel.ltf = bilinear && simple_sample;
dev->SetupSampler(ps_sel, ps_ssel);
dev->PSSetShaderResource(0, tex->m_texture);
if (tex->m_palette)
dev->PSSetShaderResource(1, tex->m_palette);
}
else
{
@ -497,8 +502,6 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
GSVector4i scissor = GSVector4i(GSVector4(rtscale).xyxy() * context->scissor.in).rintersect(GSVector4i(rtsize).zwxy());
dev->OMSetRenderTargets(rt, ds, &scissor);
dev->PSSetShaderResource(0, tex ? tex->m_texture : NULL);
dev->PSSetShaderResource(1, tex ? tex->m_palette : NULL);
uint8 afix = context->ALPHA.FIX;
@ -507,7 +510,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
dev->SetupOM(om_dssel, om_bsel, afix);
dev->SetupVS(vs_sel, &vs_cb);
dev->SetupGS(gs_sel);
dev->SetupPS(ps_sel, &ps_cb, ps_ssel);
dev->SetupPS(ps_sel, &ps_cb);
// draw
@ -524,7 +527,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
ps_selneg.colclip = 2;
dev->SetupOM(om_dssel, om_bselneg, afix);
dev->SetupPS(ps_selneg, &ps_cb, ps_ssel);
dev->SetupPS(ps_selneg, &ps_cb);
dev->DrawIndexedPrimitive();
dev->SetupOM(om_dssel, om_bsel, afix);
@ -539,7 +542,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
ps_sel.atst = iatst[ps_sel.atst];
dev->SetupPS(ps_sel, &ps_cb, ps_ssel);
dev->SetupPS(ps_sel, &ps_cb);
bool z = om_dssel.zwe;
bool r = om_bsel.wr;
@ -577,7 +580,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
ps_selneg.colclip = 2;
dev->SetupOM(om_dssel, om_bselneg, afix);
dev->SetupPS(ps_selneg, &ps_cb, ps_ssel);
dev->SetupPS(ps_selneg, &ps_cb);
dev->DrawIndexedPrimitive();
}

View File

@ -318,6 +318,8 @@ std::string GSShaderOGL::GenGlslHeader(const std::string& entry, GLenum type, co
GLuint GSShaderOGL::Compile(const std::string& glsl_file, const std::string& entry, GLenum type, const char* glsl_h_code, const std::string& macro_sel)
{
ASSERT(glsl_h_code != NULL);
GLuint program = 0;
#ifndef ENABLE_GLES
@ -331,26 +333,22 @@ GLuint GSShaderOGL::Compile(const std::string& glsl_file, const std::string& ent
const char* sources[2];
std::string header = GenGlslHeader(entry, type, macro_sel);
int shader_nb = 1;
#if 0
sources[0] = header.c_str();
if (glsl_h_code)
sources[1] = glsl_h_code;
else
sources[1] = '\0';
shader_nb++;
#else
sources[0] = header.append(glsl_h_code).c_str();
#endif
if (m_sso) {
#ifndef ENABLE_GLES
#if 0
const GLchar* ShaderSource[1];
ShaderSource[0] = header.append(glsl_h_code).c_str();
program = gl_CreateShaderProgramv(type, 1, &ShaderSource[0]);
#else
program = gl_CreateShaderProgramv(type, 2, sources);
#endif
program = gl_CreateShaderProgramv(type, shader_nb, sources);
#endif
} else {
program = gl_CreateShader(type);
gl_ShaderSource(program, 2, sources, NULL);
gl_ShaderSource(program, shader_nb, sources, NULL);
gl_CompileShader(program);
}

View File

@ -32,7 +32,7 @@ void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
{
if(t->m_type != RenderTarget)
{
assert(0);
ASSERT(0);
return;
}
@ -96,6 +96,7 @@ void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
offscreen->Unmap();
}
// FIXME invalidate data
m_renderer->m_dev->Recycle(offscreen);
}
}

View File

@ -151,7 +151,7 @@ void GSDeviceOGL::SetupGS(GSSelector sel)
m_shader->GS(gs);
}
void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel)
void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb)
{
// *************************************************************
// Static
@ -174,25 +174,18 @@ void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerS
m_ps_cb->upload(cb);
}
GLuint ss0, ss1;
ss0 = ss1 = 0;
if(sel.tfx != 4)
m_shader->PS(ps);
}
void GSDeviceOGL::SetupSampler(PSSelector sel, PSSamplerSelector ssel)
{
if(!(sel.fmt < 3 && sel.wms < 3 && sel.wmt < 3))
{
ssel.ltf = 0;
}
ss0 = m_ps_ss[ssel];
if(sel.fmt >= 3)
{
ss1 = m_palette_ss;
}
}
PSSetSamplerState(ss0, ss1, 0);
m_shader->PS(ps);
PSSetSamplerState(0, m_ps_ss[ssel]);
PSSetSamplerState(1, m_palette_ss);
}
void GSDeviceOGL::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix)

View File

@ -24,15 +24,12 @@
#include "GSTextureOGL.h"
static GLuint g_state_texture_unit = -1;
static GLuint g_state_texture_id[7] = {0, 0, 0, 0, 0, 0, 0};
static GLuint g_color0 = 0;
static GLuint g_color1 = 0;
static GLuint g_depth = 0;
// FIXME: check if it possible to always use those setup by default
// glPixelStorei(GL_PACK_ALIGNMENT, 1);
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint fbo_read)
GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read)
: m_pbo_id(0),
m_pbo_size(0)
{
@ -62,15 +59,14 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
m_size.y = max(1,h);
m_format = format;
m_type = type;
m_msaa = msaa;
m_fbo_read = fbo_read;
m_texture_id = 0;
// Generate the buffer
switch (m_type) {
case GSTexture::Offscreen:
//FIXME I not sure we need a pixel buffer object. It seems more a texture
// gl_GenBuffers(1, &m_texture_id);
// m_texture_target = GL_PIXEL_UNPACK_BUFFER;
// ASSERT(0);
// Note there is also a buffer texture!!!
// http://www.opengl.org/wiki/Buffer_Texture
@ -81,11 +77,8 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
case GSTexture::RenderTarget:
case GSTexture::DepthStencil:
glGenTextures(1, &m_texture_id);
m_texture_target = GL_TEXTURE_2D;
break;
case GSTexture::Backbuffer:
m_texture_target = 0;
m_texture_id = 0;
break;
default:
break;
@ -93,16 +86,6 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
// Extra buffer to handle various pixel transfer
gl_GenBuffers(1, &m_pbo_id);
#if 0
uint32 msaa_level;
if (m_msaa) {
// FIXME which level of MSAA
msaa_level = 1;
} else {
msaa_level = 0;
}
#endif
// Allocate the buffer
switch (m_type) {
case GSTexture::Offscreen:
@ -117,19 +100,12 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo_id);
gl_BufferData(GL_PIXEL_PACK_BUFFER, m_pbo_size, NULL, GL_STREAM_DRAW);
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
ASSERT(!m_msaa);
case GSTexture::DepthStencil:
case GSTexture::RenderTarget:
case GSTexture::Texture:
EnableUnit(3);
if (m_msaa) {
ASSERT(m_texture_target == GL_TEXTURE_2D_MULTISAMPLE);
// Require a recent GL4.3 extension
//gl_TexStorage2DMultisample(m_texture_target, msaa_level, m_format, m_size.x, m_size.y, false);
} else {
gl_TexStorage2D(m_texture_target, 1, m_format, m_size.x, m_size.y);
}
gl_TexStorage2D(GL_TEXTURE_2D, 1, m_format, m_size.x, m_size.y);
break;
default: break;
}
@ -146,45 +122,9 @@ GSTextureOGL::~GSTextureOGL()
glDeleteTextures(1, &m_texture_id);
}
void GSTextureOGL::Attach(GLenum attachment)
{
switch(attachment) {
case GL_COLOR_ATTACHMENT0:
if (g_color0 != m_texture_id) {
g_color0 = m_texture_id;
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
}
break;
case GL_COLOR_ATTACHMENT1:
if (g_color1 != m_texture_id) {
g_color1 = m_texture_id;
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
}
break;
case GL_DEPTH_STENCIL_ATTACHMENT:
if (g_depth != m_texture_id) {
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
g_depth = m_texture_id;
}
break;
default:
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
break;
}
// FIXME DEBUG
//fprintf(stderr, "FB status %x\n", gl_CheckFramebufferStatus(GL_FRAMEBUFFER));
}
void GSTextureOGL::AttachRead(GLenum attachment)
{
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
glReadBuffer(attachment);
}
bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
{
if (m_type == GSTexture::DepthStencil || m_type == GSTexture::Offscreen) ASSERT(0);
ASSERT(m_type != GSTexture::DepthStencil && m_type != GSTexture::Offscreen);
// FIXME warning order of the y axis
// FIXME I'm not confident with GL_UNSIGNED_BYTE type
@ -234,7 +174,7 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
}
#endif
glTexSubImage2D(m_texture_target, 0, r.x, r.y, r.width(), r.height(), format, type, data);
glTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.width(), r.height(), format, type, data);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // Restore default behavior
@ -253,25 +193,26 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
#endif
}
void GSTextureOGL::EnableUnit(uint32 unit)
void GSTextureOGL::EnableUnit(const uint32 unit)
{
/* Not a real texture */
if (IsBackbuffer()) {
return;
}
ASSERT(!IsBackbuffer());
if (g_state_texture_unit != unit) {
gl_ActiveTexture(GL_TEXTURE0 + unit);
g_state_texture_unit = unit;
}
if (g_state_texture_id[unit] != m_texture_id) {
g_state_texture_id[unit] = m_texture_id;
glBindTexture(m_texture_target, m_texture_id);
glBindTexture(GL_TEXTURE_2D, m_texture_id);
}
}
bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
{
if (m_type != GSTexture::Offscreen) return false;
// The function allow to modify the texture from the CPU
// Set m.bits <- pointer to the data
// Set m.pitch <- size of a row
@ -279,11 +220,11 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
//
// gl_MapBuffer — map a buffer object's data store
// Can be used on GL_PIXEL_UNPACK_BUFFER or GL_TEXTURE_BUFFER
if (m_type == GSTexture::Offscreen) {
// Bind the texture to the read framebuffer to avoid any disturbance
EnableUnit(5);
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_target, m_texture_id, 0);
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
// FIXME It might be possible to only read a subrange of the texture based on r object
@ -317,9 +258,7 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
return false;
}
}
return false;
#if 0
if(m_texture && m_desc.Usage == D3D11_USAGE_STAGING)
{
@ -465,7 +404,7 @@ bool GSTextureOGL::Save(const string& fn, bool dds)
} else if(IsDss()) {
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_texture_target, m_texture_id, 0);
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_texture_id, 0);
glReadPixels(0, 0, m_size.x, m_size.y, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image);
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
@ -473,7 +412,7 @@ bool GSTextureOGL::Save(const string& fn, bool dds)
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
EnableUnit(6);
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_target, m_texture_id, 0);
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
if (m_format == GL_RGBA8)

View File

@ -26,14 +26,13 @@
class GSTextureOGL : public GSTexture
{
private:
GLenum m_texture_target; // texture target: 2D, rectangle etc...
GLuint m_texture_id; // the texture id
uint32 m_pbo_id;
int m_pbo_size;
GLuint m_fbo_read;
public:
explicit GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint fbo_read);
explicit GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read);
virtual ~GSTextureOGL();
bool Update(const GSVector4i& r, const void* data, int pitch);
@ -42,13 +41,10 @@ class GSTextureOGL : public GSTexture
bool Save(const string& fn, bool dds = false);
void Save(const string& fn, const void* image, uint32 pitch);
void EnableUnit(uint32 unit);
void Attach(GLenum attachment);
void AttachRead(GLenum attachment);
void EnableUnit(const uint32 unit);
bool IsBackbuffer() { return (m_type == GSTexture::Backbuffer); }
bool IsDss() { return (m_type == GSTexture::DepthStencil); }
GLuint GetID() { return m_texture_id; }
GLenum GetTarget() { return m_texture_target; }
};

View File

@ -25,12 +25,10 @@ class GSUniformBufferOGL {
GLuint buffer; // data object
GLuint index; // GLSL slot
uint32 size; // size of the data
const GLenum target;
public:
GSUniformBufferOGL(GLuint index, uint32 size) : index(index)
, size(size)
,target(GL_UNIFORM_BUFFER)
{
gl_GenBuffers(1, &buffer);
bind();
@ -40,17 +38,17 @@ public:
void bind()
{
gl_BindBuffer(target, buffer);
gl_BindBuffer(GL_UNIFORM_BUFFER, buffer);
}
void allocate()
{
gl_BufferData(target, size, NULL, GL_STREAM_DRAW);
gl_BufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STREAM_DRAW);
}
void attach()
{
gl_BindBufferBase(target, index, buffer);
gl_BindBufferBase(GL_UNIFORM_BUFFER, index, buffer);
}
void upload(const void* src)
@ -58,7 +56,7 @@ public:
// glMapBufferRange allow to set various parameter but the call is
// synchronous whereas glBufferSubData could be asynchronous.
// TODO: investigate the extension ARB_invalidate_subdata
gl_BufferSubData(target, 0, size, src);
gl_BufferSubData(GL_UNIFORM_BUFFER, 0, size, src);
}
~GSUniformBufferOGL() {