mirror of https://github.com/PCSX2/pcsx2.git
gsdx-ogl: LINUX-ONLY
* improve vertex management with a vertex array. Decorrelate vertex from strech rec and others func (later for the HW renderer) * fix the crash on nvidia when closing the window * clean some texture management code git-svn-id: http://pcsx2.googlecode.com/svn/branches/gsdx-ogl@4985 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
e6057b765f
commit
daf3c43681
|
@ -57,10 +57,11 @@ GSDeviceOGL::GSDeviceOGL()
|
|||
: m_free_window(false)
|
||||
, m_window(NULL)
|
||||
, m_vb(0)
|
||||
, m_fbo(0)
|
||||
, m_sr_vb_offset(0)
|
||||
, m_pipeline(0)
|
||||
, m_srv_changed(false)
|
||||
, m_ss_changed(false)
|
||||
, m_vb_changed(false)
|
||||
{
|
||||
m_msaa = theApp.GetConfig("msaa", 0);
|
||||
|
||||
|
@ -85,6 +86,8 @@ GSDeviceOGL::~GSDeviceOGL()
|
|||
delete (m_interlace.cb);
|
||||
|
||||
// Clean m_convert
|
||||
glDeleteVertexArrays(1, &m_convert.va);
|
||||
glDeleteBuffers(1, &m_convert.vb);
|
||||
glDeleteProgram(m_convert.vs);
|
||||
for (uint i = 0; i < 2; i++)
|
||||
glDeleteProgram(m_convert.ps[i]);
|
||||
|
@ -176,14 +179,17 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
OMSetFBO(m_fbo);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
OMSetFBO(0);
|
||||
|
||||
// ****************************************************************
|
||||
// convert
|
||||
// ****************************************************************
|
||||
|
||||
// There isn't a default VAO in newer versions of OpenGL, so create one.
|
||||
unsigned int vao = 0;
|
||||
glGenVertexArrays(1,&vao);
|
||||
glBindVertexArray(vao);
|
||||
glGenVertexArrays(1, &m_convert.va);
|
||||
IASetVertexArrray(m_convert.va);
|
||||
|
||||
glGenBuffers(1, &m_convert.vb);
|
||||
IASetVertexBufferBind(m_convert.vb);
|
||||
glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(GSVertexPT1), NULL, GL_STREAM_DRAW);
|
||||
|
||||
GSInputLayout il_convert[2] =
|
||||
{
|
||||
|
@ -191,8 +197,14 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
{1, 2, GL_FLOAT, sizeof(GSVertexPT1), (const GLvoid*)offsetof(struct GSVertexPT1, t) },
|
||||
};
|
||||
|
||||
m_convert.il[0] = il_convert[0];
|
||||
m_convert.il[1] = il_convert[1];
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// Note this function need both a vertex array object and a GL_ARRAY_BUFFER buffer
|
||||
glEnableVertexAttribArray(il_convert[i].index);
|
||||
glVertexAttribPointer(il_convert[i].index, il_convert[i].size, il_convert[i].type, GL_FALSE, il_convert[i].stride, il_convert[i].offset);
|
||||
}
|
||||
// Unbind to avoid issue with the setup of others parameters
|
||||
IASetVertexArrray(0);
|
||||
IASetVertexBufferBind(0);
|
||||
|
||||
CompileShaderFromSource("convert.glsl", "vs_main", GL_VERTEX_SHADER, &m_convert.vs);
|
||||
for(int i = 0; i < countof(m_convert.ps); i++)
|
||||
|
@ -662,17 +674,25 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
|||
return;
|
||||
}
|
||||
|
||||
// ************************************
|
||||
// Init
|
||||
// ************************************
|
||||
|
||||
BeginScene();
|
||||
|
||||
GSVector2i ds = dt->GetSize();
|
||||
|
||||
// ************************************
|
||||
// om
|
||||
// ************************************
|
||||
|
||||
OMSetDepthStencilState(m_convert.dss, 0);
|
||||
OMSetBlendState(bs, 0);
|
||||
OMSetRenderTargets(dt, NULL);
|
||||
|
||||
// ************************************
|
||||
// ia
|
||||
// ************************************
|
||||
|
||||
float left = dr.x * 2 / ds.x - 1.0f;
|
||||
float top = 1.0f - dr.y * 2 / ds.y;
|
||||
|
@ -687,29 +707,44 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
|||
{GSVector4(right, bottom, 0.5f, 1.0f), GSVector2(sr.z, sr.w)},
|
||||
};
|
||||
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
|
||||
IASetInputLayout(m_convert.il, 2);
|
||||
IASetPrimitiveTopology(GL_TRIANGLE_STRIP);
|
||||
IASetVertexArrray(m_convert.va);
|
||||
IASetVertexBufferBind(m_convert.vb);
|
||||
// FIXME it will worth some benchmark.
|
||||
// What is the faster always use the same. Or pack to difference emplacement. I'm afraid
|
||||
// that in all case the GPU will be stall to wait the data
|
||||
// Note maybe create a new buffer can be faster.
|
||||
// m_sr_vb_offset = 0;
|
||||
glBufferSubData(GL_ARRAY_BUFFER, m_sr_vb_offset * 4 * sizeof(GSVertexPT1) , sizeof(GSVertexPT1) * 4, vertices);
|
||||
|
||||
// ************************************
|
||||
// vs
|
||||
// ************************************
|
||||
|
||||
VSSetShader(m_convert.vs, NULL);
|
||||
|
||||
// ************************************
|
||||
// gs
|
||||
// ************************************
|
||||
|
||||
GSSetShader(0);
|
||||
|
||||
// ************************************
|
||||
// ps
|
||||
// ************************************
|
||||
|
||||
PSSetShaderResources(st, NULL);
|
||||
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt, 0);
|
||||
PSSetShader(ps, ps_cb);
|
||||
|
||||
//
|
||||
// ************************************
|
||||
// Draw
|
||||
// ************************************
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, m_sr_vb_offset * 4, 4);
|
||||
m_sr_vb_offset = (m_sr_vb_offset + 1) & 0x3;
|
||||
|
||||
DrawPrimitive();
|
||||
|
||||
//
|
||||
// ************************************
|
||||
// End
|
||||
// ************************************
|
||||
|
||||
EndScene();
|
||||
|
||||
|
@ -784,6 +819,22 @@ GSTexture* GSDeviceOGL::Resolve(GSTexture* t)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void GSDeviceOGL::IASetVertexArrray(GLuint va)
|
||||
{
|
||||
if (m_state.va != va) {
|
||||
glBindVertexArray(va);
|
||||
m_state.va = va;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::IASetVertexBufferBind(GLuint vb)
|
||||
{
|
||||
if (m_state.vb != vb) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vb);
|
||||
m_state.vb = vb;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t stride, size_t count)
|
||||
{
|
||||
ASSERT(m_vertices.count == 0);
|
||||
|
@ -799,15 +850,16 @@ void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t stride, size_t
|
|||
m_vertices.start = 0;
|
||||
m_vertices.count = 0;
|
||||
m_vertices.limit = std::max<int>(count * 3 / 2, 11000);
|
||||
|
||||
m_vertices.stride = stride;
|
||||
}
|
||||
|
||||
if(!m_vb)
|
||||
{
|
||||
glGenBuffers(1, &m_vb);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vb);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_vertices.limit * stride, NULL, GL_STREAM_DRAW);
|
||||
m_vb_changed = true;
|
||||
IASetVertexBufferBind(m_vb);
|
||||
// Allocate the buffer
|
||||
glBufferData(GL_ARRAY_BUFFER, m_vertices.limit * m_vertices.stride, NULL, GL_STREAM_DRAW);
|
||||
//m_vb_changed = true;
|
||||
}
|
||||
|
||||
// append data or go back to the beginning
|
||||
|
@ -815,14 +867,13 @@ void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t stride, size_t
|
|||
if(m_vertices.start + count > m_vertices.limit || stride != m_vertices.stride)
|
||||
m_vertices.start = 0;
|
||||
|
||||
// Allocate the buffer
|
||||
// glBufferSubData
|
||||
// Fill the buffer
|
||||
glBufferSubData(GL_ARRAY_BUFFER, m_vertices.start * stride, count * stride, vertices);
|
||||
|
||||
m_vertices.count = count;
|
||||
m_vertices.stride = stride;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void GSDeviceOGL::IASetInputLayout(GSInputLayout* layout, int layout_nbr)
|
||||
{
|
||||
if(m_state.layout != layout || m_state.layout_nbr != layout_nbr || m_vb_changed)
|
||||
|
@ -842,6 +893,7 @@ void GSDeviceOGL::IASetInputLayout(GSInputLayout* layout, int layout_nbr)
|
|||
m_state.layout_nbr = layout_nbr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GSDeviceOGL::IASetPrimitiveTopology(GLenum topology)
|
||||
{
|
||||
|
|
|
@ -107,6 +107,7 @@ class GSDeviceOGL : public GSDevice
|
|||
GLuint m_vb; // vertex buffer object
|
||||
GLuint m_pipeline; // pipeline to attach program shader
|
||||
GLuint m_fbo; // frame buffer container
|
||||
uint32 m_sr_vb_offset;
|
||||
|
||||
struct {
|
||||
GLuint ps[2]; // program object
|
||||
|
@ -123,7 +124,9 @@ class GSDeviceOGL : public GSDevice
|
|||
// Hum I think this one is useless. As far as I understand
|
||||
// it only get the index name of GLSL-equivalent input attribut
|
||||
// ??? CComPtr<ID3D11InputLayout> il;
|
||||
GSInputLayout il[2]; // description of the vertex array
|
||||
//GSInputLayout il[2]; // description of the vertex array
|
||||
GLuint va; // vertex array object
|
||||
GLuint vb; // vertex buffer
|
||||
GLuint vs; // program object
|
||||
GLuint ps[8]; // program object
|
||||
GLuint ln; // sampler object
|
||||
|
@ -162,12 +165,13 @@ class GSDeviceOGL : public GSDevice
|
|||
// } m_state;
|
||||
struct
|
||||
{
|
||||
GLuint vb;
|
||||
GLuint vb; // vertex buffer
|
||||
// Hum I think those things can be dropped on OGL. It probably need an others architecture (see glVertexAttribPointer)
|
||||
// size_t vb_stride;
|
||||
// ID3D11InputLayout* layout;
|
||||
GSInputLayout* layout;
|
||||
uint32 layout_nbr;
|
||||
//GSInputLayout* layout;
|
||||
//uint32 layout_nbr;
|
||||
GLuint va; // vertex array
|
||||
GLenum topology; // (ie GL_TRIANGLES...)
|
||||
GLuint vs; // program
|
||||
GLuint cb; // uniform current buffer
|
||||
|
@ -195,7 +199,7 @@ class GSDeviceOGL : public GSDevice
|
|||
|
||||
bool m_srv_changed;
|
||||
bool m_ss_changed;
|
||||
bool m_vb_changed;
|
||||
//bool m_vb_changed;
|
||||
|
||||
#if 0
|
||||
CComPtr<ID3D11Device> m_dev;
|
||||
|
@ -271,8 +275,10 @@ class GSDeviceOGL : public GSDevice
|
|||
void CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program);
|
||||
|
||||
void IASetPrimitiveTopology(GLenum topology);
|
||||
void IASetInputLayout(GSInputLayout* layout, int layout_nbr);
|
||||
//void IASetInputLayout(GSInputLayout* layout, int layout_nbr);
|
||||
void IASetVertexBuffer(const void* vertices, size_t stride, size_t count);
|
||||
void IASetVertexBufferBind(GLuint vb);
|
||||
void IASetVertexArrray(GLuint va);
|
||||
|
||||
void VSSetShader(GLuint vs, GSUniformBufferOGL* vs_cb);
|
||||
void GSSetShader(GLuint gs);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "GSTextureOGL.h"
|
||||
static uint g_state_texture_unit = 0;
|
||||
static uint g_state_texture_id = 0;
|
||||
|
||||
GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
|
||||
: m_texture_unit(0),
|
||||
|
@ -93,13 +95,8 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
|
|||
|
||||
// Generate the buffer
|
||||
switch (m_type) {
|
||||
case GSTexture::Texture:
|
||||
case GSTexture::RenderTarget:
|
||||
// FIXME what is the real use case of this texture
|
||||
// Maybe a texture will be better
|
||||
// glGenRenderbuffers(1, &m_texture_id);
|
||||
// m_texture_target = GL_RENDERBUFFER;
|
||||
// Buffer can not be read by shader and must be blit before. I see no point to use a render buffer
|
||||
// when you can directly render on the texture. It said it could be faster...
|
||||
glGenTextures(1, &m_texture_id);
|
||||
m_texture_target = GL_TEXTURE_2D;
|
||||
break;
|
||||
|
@ -107,13 +104,6 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
|
|||
glGenRenderbuffers(1, &m_texture_id);
|
||||
m_texture_target = GL_RENDERBUFFER;
|
||||
break;
|
||||
case GSTexture::Texture:
|
||||
glGenTextures(1, &m_texture_id);
|
||||
// FIXME, do we need rectangle (or better to use 2D texture)
|
||||
m_texture_target = GL_TEXTURE_2D;
|
||||
//m_texture_target = GL_TEXTURE_RECTANGLE;
|
||||
// == For texture, the Unit must be selected
|
||||
break;
|
||||
case GSTexture::Offscreen:
|
||||
//FIXME I not sure we need a pixel buffer object. It seems more a texture
|
||||
// glGenBuffers(1, &m_texture_id);
|
||||
|
@ -156,7 +146,7 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
|
|||
glTexImage2D(m_texture_target, 0, m_format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
assert(0); // TODO Later
|
||||
break;
|
||||
case GSTexture::Offscreen:
|
||||
assert(0);
|
||||
|
@ -252,8 +242,16 @@ void GSTextureOGL::EnableUnit(uint unit)
|
|||
// Howto allocate the texture unit !!!
|
||||
// In worst case the HW renderer seems to use 3 texture unit
|
||||
// For the moment SW renderer only use 1 so don't bother
|
||||
if (g_state_texture_unit != unit) {
|
||||
g_state_texture_unit = unit;
|
||||
glActiveTexture(GL_TEXTURE0 + unit);
|
||||
// When you change the texture unit, texture must be rebinded
|
||||
g_state_texture_id = m_texture_id;
|
||||
glBindTexture(m_texture_target, m_texture_id);
|
||||
} else if (g_state_texture_id != m_texture_id) {
|
||||
g_state_texture_id = m_texture_id;
|
||||
glBindTexture(m_texture_target, m_texture_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -363,8 +363,7 @@ bool GSWnd::Attach(void* handle, bool managed)
|
|||
GLXFBConfig *fbc = glXChooseFBConfig(m_XDisplay, DefaultScreen(m_XDisplay), attrListDbl, &fbcount);
|
||||
if (!fbc || fbcount < 1) return false;
|
||||
|
||||
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
|
||||
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*) "glXCreateContextAttribsARB");
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte*) "glXCreateContextAttribsARB");
|
||||
if (!glXCreateContextAttribsARB) return false;
|
||||
|
||||
// Create a context
|
||||
|
@ -407,7 +406,7 @@ void GSWnd::Detach()
|
|||
m_window = NULL;
|
||||
}
|
||||
} else {
|
||||
glXMakeCurrent(m_XDisplay, m_Xwindow, 0);
|
||||
glXMakeCurrent(m_XDisplay, None, NULL);
|
||||
if (m_context) glXDestroyContext(m_XDisplay, m_context);
|
||||
}
|
||||
if (m_XDisplay) {
|
||||
|
|
|
@ -91,8 +91,6 @@ public:
|
|||
#include "../../3rdparty/SDL-1.3.0-5387/include/SDL.h"
|
||||
#include "../../3rdparty/SDL-1.3.0-5387/include/SDL_syswm.h"
|
||||
|
||||
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, bool, const int*);
|
||||
|
||||
class GSWnd
|
||||
{
|
||||
SDL_Window* m_window;
|
||||
|
|
Loading…
Reference in New Issue