mirror of
https://github.com/libretro/pcsx2.git
synced 2024-11-28 20:00:44 +00:00
GSdx-ogl: happy new years commit :)
* move all vertex buffer stuff into the class * Bypass FIFO2 because of multithread issue with OGL(temporary workaround until we found a nicer solutions) git-svn-id: http://pcsx2.googlecode.com/svn/branches/gsdx-ogl@5035 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
9ca65c9cc6
commit
2f4e2d8b6b
@ -396,11 +396,28 @@ EXPORT_C GSwriteCSR(uint32 csr)
|
||||
|
||||
EXPORT_C GSreadFIFO(uint8* mem)
|
||||
{
|
||||
#ifdef _LINUX
|
||||
// FIXME: double check which thread call this function
|
||||
// See fifo2 issue below
|
||||
if (theApp.GetConfig("renderer", 0) == 12) {
|
||||
fprintf(stderr, "Disable FIFO1 on opengl\n");
|
||||
}
|
||||
#endif
|
||||
s_gs->ReadFIFO(mem, 1);
|
||||
}
|
||||
|
||||
EXPORT_C GSreadFIFO2(uint8* mem, uint32 size)
|
||||
{
|
||||
#ifdef _LINUX
|
||||
// FIXME called from EE core thread not MTGS which cause
|
||||
// invalidate data for opengl
|
||||
if (theApp.GetConfig("renderer", 0) == 12) {
|
||||
#ifdef OGL_DEBUG
|
||||
fprintf(stderr, "Disable FIFO2 on opengl\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
s_gs->ReadFIFO(mem, size);
|
||||
}
|
||||
|
||||
|
@ -226,12 +226,12 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
||||
// ****************************************************************
|
||||
// Vertex buffer state
|
||||
// ****************************************************************
|
||||
GSInputLayout il_convert[2] =
|
||||
GSInputLayoutOGL il_convert[2] =
|
||||
{
|
||||
{0, 4, GL_FLOAT, GL_FALSE, sizeof(GSVertexPT1), (const GLvoid*)offsetof(struct GSVertexPT1, p) },
|
||||
{1, 2, GL_FLOAT, GL_FALSE, sizeof(GSVertexPT1), (const GLvoid*)offsetof(struct GSVertexPT1, t) },
|
||||
};
|
||||
m_vb_sr = new GSVertexBufferState(sizeof(GSVertexPT1), il_convert, countof(il_convert));
|
||||
m_vb_sr = new GSVertexBufferStateOGL(sizeof(GSVertexPT1), il_convert, countof(il_convert));
|
||||
|
||||
// ****************************************************************
|
||||
// convert
|
||||
@ -546,7 +546,7 @@ void GSDeviceOGL::DrawPrimitive()
|
||||
}
|
||||
#endif
|
||||
|
||||
glDrawArrays(m_state.topology, m_state.vb_state->start, m_state.vb_state->count);
|
||||
m_state.vb_state->draw_arrays(m_state.topology);
|
||||
|
||||
// DUMP OUTPUT
|
||||
#ifdef DUMP_START
|
||||
@ -964,8 +964,7 @@ GSTexture* GSDeviceOGL::Resolve(GSTexture* t)
|
||||
|
||||
void GSDeviceOGL::EndScene()
|
||||
{
|
||||
m_state.vb_state->start += m_state.vb_state->count;
|
||||
m_state.vb_state->count = 0;
|
||||
m_state.vb_state->draw_done();
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetUniformBuffer(GSUniformBufferOGL* cb)
|
||||
@ -976,7 +975,7 @@ void GSDeviceOGL::SetUniformBuffer(GSUniformBufferOGL* cb)
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::IASetVertexState(GSVertexBufferState* vb_state)
|
||||
void GSDeviceOGL::IASetVertexState(GSVertexBufferStateOGL* vb_state)
|
||||
{
|
||||
if (m_state.vb_state != vb_state) {
|
||||
m_state.vb_state = vb_state;
|
||||
@ -986,33 +985,7 @@ void GSDeviceOGL::IASetVertexState(GSVertexBufferState* vb_state)
|
||||
|
||||
void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t count)
|
||||
{
|
||||
// Note: For an explanation of the map flag
|
||||
// see http://www.opengl.org/wiki/Buffer_Object_Streaming
|
||||
uint32 map_flags = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
|
||||
|
||||
GSVertexBufferState* vb = m_state.vb_state;
|
||||
vb->count = count;
|
||||
|
||||
// Current GPU buffer is really too small need to realocate a new one
|
||||
if (count > vb->limit) {
|
||||
vb->allocate(std::max<int>(count * 3 / 2, 60000));
|
||||
|
||||
} else if (count > (vb->limit - vb->start) ) {
|
||||
// Not enough left free room. Just go back at the beginning
|
||||
vb->start = 0;
|
||||
|
||||
// Tell the driver that it can orphan previous buffer and restart from a scratch buffer.
|
||||
// Technically the buffer will not be accessible by the application anymore but the
|
||||
// GL will effectively remove it when draws call are finised.
|
||||
map_flags |= GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
} else {
|
||||
// Tell the driver that it doesn't need to contain any valid buffer data, and that you promise to write the entire range you map
|
||||
map_flags |= GL_MAP_INVALIDATE_RANGE_BIT;
|
||||
}
|
||||
|
||||
vb->upload(vertices, map_flags);
|
||||
// FIXME: disable it when code is working
|
||||
CheckDebugLog();
|
||||
m_state.vb_state->upload(vertices, count);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::IASetPrimitiveTopology(GLenum topology)
|
||||
|
@ -128,7 +128,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct GSInputLayout {
|
||||
struct GSInputLayoutOGL {
|
||||
GLuint index;
|
||||
GLint size;
|
||||
GLenum type;
|
||||
@ -137,51 +137,73 @@ struct GSInputLayout {
|
||||
const GLvoid* offset;
|
||||
};
|
||||
|
||||
struct GSVertexBufferState {
|
||||
size_t stride;
|
||||
size_t start;
|
||||
size_t count;
|
||||
size_t limit;
|
||||
GLuint vb;
|
||||
GLuint va;
|
||||
|
||||
GSVertexBufferState(size_t stride, GSInputLayout* layout, uint32 layout_nbr) : stride(stride)
|
||||
, count(0)
|
||||
{
|
||||
glGenBuffers(1, &vb);
|
||||
glGenVertexArrays(1, &va);
|
||||
bind();
|
||||
allocate(60000); // Opengl works best with 1-4MB buffer. 60k element seems a good value.
|
||||
set_internal_format(layout, layout_nbr);
|
||||
}
|
||||
class GSVertexBufferStateOGL {
|
||||
size_t m_stride;
|
||||
size_t m_start;
|
||||
size_t m_count;
|
||||
size_t m_limit;
|
||||
GLuint m_vb;
|
||||
GLuint m_va;
|
||||
const GLenum m_target;
|
||||
|
||||
void allocate(size_t new_limit)
|
||||
{
|
||||
start = 0;
|
||||
limit = new_limit;
|
||||
glBufferData(GL_ARRAY_BUFFER, limit * stride, NULL, GL_STREAM_DRAW);
|
||||
m_start = 0;
|
||||
m_limit = new_limit;
|
||||
glBufferData(m_target, m_limit * m_stride, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
public:
|
||||
GSVertexBufferStateOGL(size_t stride, GSInputLayoutOGL* layout, uint32 layout_nbr)
|
||||
: m_stride(stride)
|
||||
, m_count(0)
|
||||
, m_target(GL_ARRAY_BUFFER)
|
||||
{
|
||||
glGenBuffers(1, &m_vb);
|
||||
glGenVertexArrays(1, &m_va);
|
||||
bind();
|
||||
allocate(60000); // Opengl works best with 1-4MB buffer. 60k element seems a good value. Note stride is 32
|
||||
set_internal_format(layout, layout_nbr);
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindVertexArray(va);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vb);
|
||||
glBindVertexArray(m_va);
|
||||
glBindBuffer(m_target, m_vb);
|
||||
}
|
||||
|
||||
void upload(const void* src, uint32 flags)
|
||||
void upload(const void* src, uint32 count)
|
||||
{
|
||||
uint8* dst = (uint8*) glMapBufferRange(GL_ARRAY_BUFFER, stride*start, stride*count, flags);
|
||||
#ifdef OGL_DEBUG
|
||||
if (dst == NULL) {
|
||||
fprintf(stderr, "CRITICAL ERROR map failed for vb !!!\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
memcpy(dst, src, stride*count);
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
m_count = count;
|
||||
|
||||
// Note: For an explanation of the map flag
|
||||
// see http://www.opengl.org/wiki/Buffer_Object_Streaming
|
||||
uint32 map_flags = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
|
||||
|
||||
// Current GPU buffer is really too small need to allocate a new one
|
||||
if (m_count > m_limit) {
|
||||
allocate(std::max<int>(count * 3 / 2, 60000));
|
||||
|
||||
} else if (m_count > (m_limit - m_start) ) {
|
||||
// Not enough left free room. Just go back at the beginning
|
||||
m_start = 0;
|
||||
|
||||
// Tell the driver that it can orphan previous buffer and restart from a scratch buffer.
|
||||
// Technically the buffer will not be accessible by the application anymore but the
|
||||
// GL will effectively remove it when draws call are finised.
|
||||
map_flags |= GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
} else {
|
||||
// Tell the driver that it doesn't need to contain any valid buffer data, and that you promise to write the entire range you map
|
||||
map_flags |= GL_MAP_INVALIDATE_RANGE_BIT;
|
||||
}
|
||||
|
||||
void set_internal_format(GSInputLayout* layout, uint32 layout_nbr)
|
||||
// Upload the data to the buffer
|
||||
uint8* dst = (uint8*) glMapBufferRange(m_target, m_stride*m_start, m_stride*m_count, map_flags);
|
||||
memcpy(dst, src, m_stride*m_count);
|
||||
glUnmapBuffer(m_target);
|
||||
}
|
||||
|
||||
void set_internal_format(GSInputLayoutOGL* layout, uint32 layout_nbr)
|
||||
{
|
||||
for (int i = 0; i < layout_nbr; i++) {
|
||||
// Note this function need both a vertex array object and a GL_ARRAY_BUFFER buffer
|
||||
@ -199,10 +221,21 @@ struct GSVertexBufferState {
|
||||
}
|
||||
}
|
||||
|
||||
~GSVertexBufferState()
|
||||
void draw_arrays(GLenum topology)
|
||||
{
|
||||
glDeleteBuffers(1, &vb);
|
||||
glDeleteVertexArrays(1, &va);
|
||||
glDrawArrays(topology, m_start, m_count);
|
||||
}
|
||||
|
||||
void draw_done()
|
||||
{
|
||||
m_start += m_count;
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
~GSVertexBufferStateOGL()
|
||||
{
|
||||
glDeleteBuffers(1, &m_vb);
|
||||
glDeleteVertexArrays(1, &m_va);
|
||||
}
|
||||
};
|
||||
|
||||
@ -451,8 +484,8 @@ class GSDeviceOGL : public GSDevice
|
||||
GLuint m_pipeline; // pipeline to attach program shader
|
||||
GLuint m_fbo; // frame buffer container
|
||||
|
||||
GSVertexBufferState* m_vb; // vb_state for HW renderer
|
||||
GSVertexBufferState* m_vb_sr; // vb_state for StretchRect
|
||||
GSVertexBufferStateOGL* m_vb; // vb_state for HW renderer
|
||||
GSVertexBufferStateOGL* m_vb_sr; // vb_state for StretchRect
|
||||
|
||||
struct {
|
||||
GLuint ps[2]; // program object
|
||||
@ -488,7 +521,7 @@ class GSDeviceOGL : public GSDevice
|
||||
|
||||
struct
|
||||
{
|
||||
GSVertexBufferState* vb_state;
|
||||
GSVertexBufferStateOGL* vb_state;
|
||||
GLenum topology; // (ie GL_TRIANGLES...)
|
||||
GLuint vs; // program
|
||||
GSUniformBufferOGL* cb; // uniform current buffer
|
||||
@ -604,7 +637,7 @@ class GSDeviceOGL : public GSDevice
|
||||
|
||||
void IASetPrimitiveTopology(GLenum topology);
|
||||
void IASetVertexBuffer(const void* vertices, size_t count);
|
||||
void IASetVertexState(GSVertexBufferState* vb_state);
|
||||
void IASetVertexState(GSVertexBufferStateOGL* vb_state);
|
||||
|
||||
void SetUniformBuffer(GSUniformBufferOGL* cb);
|
||||
|
||||
|
@ -61,7 +61,7 @@ void GSDeviceOGL::CreateTextureFX()
|
||||
//float4 c : COLOR0;
|
||||
//float4 f : COLOR1;
|
||||
|
||||
GSInputLayout vert_format[6] =
|
||||
GSInputLayoutOGL vert_format[6] =
|
||||
{
|
||||
// FIXME
|
||||
{0 , 2 , GL_FLOAT , GL_FALSE , sizeof(GSVertexHW11) , (const GLvoid*)(0) } ,
|
||||
@ -72,7 +72,7 @@ void GSDeviceOGL::CreateTextureFX()
|
||||
// note: there is a 32 bits pad
|
||||
{5 , 4 , GL_UNSIGNED_BYTE , GL_TRUE , sizeof(GSVertexHW11) , (const GLvoid*)(28) } ,
|
||||
};
|
||||
m_vb = new GSVertexBufferState(sizeof(GSVertexHW11), vert_format, countof(vert_format));
|
||||
m_vb = new GSVertexBufferStateOGL(sizeof(GSVertexHW11), vert_format, countof(vert_format));
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetupIA(const void* vertices, int count, GLenum prim)
|
||||
|
@ -175,8 +175,20 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
|
||||
// pitch could be different of width*element_size
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch>>2);
|
||||
// FIXME : it crash on colin mcrae rally 3 (others game too) when the size is 16
|
||||
//if (m_size.x != 16)
|
||||
//fprintf(stderr, "Texture %dx%d with a pitch of %d\n", m_size.x, m_size.y, pitch >>2);
|
||||
//fprintf(stderr, "Box (%d,%d)x(%d,%d)\n", r.x, r.y, r.width(), r.height());
|
||||
|
||||
glTexSubImage2D(m_texture_target, 0, r.x, r.y, r.width(), r.height(), GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
#if 0
|
||||
//if (m_size.x != 16)
|
||||
if (r.width() > 16 && r.height() > 16)
|
||||
glTexSubImage2D(m_texture_target, 0, r.x, r.y, r.width(), r.height(), GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
else {
|
||||
fprintf(stderr, "skip texture upload\n");
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // Restore default behavior
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // Restore default behavior
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user