mirror of https://github.com/PCSX2/pcsx2.git
gsdx ogl:
* split GSDeviceOGl header. Will allow easy sharing with zzogl. * fix some gcc warning zzogl: * import Uniform buffer and Vertex array from GSdx git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5207 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
2f9e35e5ae
commit
b665499a6b
|
@ -224,7 +224,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
// ****************************************************************
|
||||
CompileShaderFromSource("convert.glsl", "vs_main", GL_VERTEX_SHADER, &m_convert.vs);
|
||||
CompileShaderFromSource("convert.glsl", "gs_main", GL_GEOMETRY_SHADER, &m_convert.gs);
|
||||
for(int i = 0; i < countof(m_convert.ps); i++)
|
||||
for(uint i = 0; i < countof(m_convert.ps); i++)
|
||||
CompileShaderFromSource("convert.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_convert.ps[i]);
|
||||
|
||||
// Note the following object are initialized to 0 so disabled.
|
||||
|
@ -252,7 +252,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
glSamplerParameteri(m_convert.ln, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(m_convert.ln, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
// FIXME which value for GL_TEXTURE_MIN_LOD
|
||||
glSamplerParameteri(m_convert.ln, GL_TEXTURE_MAX_LOD, FLT_MAX);
|
||||
glSamplerParameterf(m_convert.ln, GL_TEXTURE_MAX_LOD, FLT_MAX);
|
||||
// FIXME: seems there is 2 possibility in opengl
|
||||
// DX: sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
// glSamplerParameteri(m_convert.ln, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
|
@ -268,7 +268,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
glSamplerParameteri(m_convert.pt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(m_convert.pt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
// FIXME which value for GL_TEXTURE_MIN_LOD
|
||||
glSamplerParameteri(m_convert.pt, GL_TEXTURE_MAX_LOD, FLT_MAX);
|
||||
glSamplerParameterf(m_convert.pt, GL_TEXTURE_MAX_LOD, FLT_MAX);
|
||||
// FIXME: seems there is 2 possibility in opengl
|
||||
// DX: sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
// glSamplerParameteri(m_convert.pt, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
|
@ -284,7 +284,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
// ****************************************************************
|
||||
m_merge_obj.cb = new GSUniformBufferOGL(1, sizeof(MergeConstantBuffer));
|
||||
|
||||
for(int i = 0; i < countof(m_merge_obj.ps); i++)
|
||||
for(uint i = 0; i < countof(m_merge_obj.ps); i++)
|
||||
CompileShaderFromSource("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_merge_obj.ps[i]);
|
||||
|
||||
m_merge_obj.bs = new GSBlendStateOGL();
|
||||
|
@ -296,7 +296,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
// ****************************************************************
|
||||
m_interlace.cb = new GSUniformBufferOGL(2, sizeof(InterlaceConstantBuffer));
|
||||
|
||||
for(int i = 0; i < countof(m_interlace.ps); i++)
|
||||
for(uint i = 0; i < countof(m_interlace.ps); i++)
|
||||
CompileShaderFromSource("interlace.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_interlace.ps[i]);
|
||||
// ****************************************************************
|
||||
// Shade boost
|
||||
|
@ -1167,8 +1167,6 @@ void GSDeviceOGL::OMSetFBO(GLuint fbo, GLenum buffer)
|
|||
|
||||
void GSDeviceOGL::OMSetDepthStencilState(GSDepthStencilOGL* dss, uint8 sref)
|
||||
{
|
||||
uint ref = sref;
|
||||
|
||||
if(m_state.dss != dss) {
|
||||
m_state.dss = dss;
|
||||
m_state.sref = sref;
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "GSDevice.h"
|
||||
#include "GSTextureOGL.h"
|
||||
#include "GSdx.h"
|
||||
#include "GSVertexArrayOGL.h"
|
||||
#include "GSUniformBufferOGL.h"
|
||||
|
||||
class GSBlendStateOGL {
|
||||
// Note: You can also select the index of the draw buffer for which to set the blend setting
|
||||
|
@ -228,281 +230,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class GSUniformBufferOGL {
|
||||
GLuint buffer; // data object
|
||||
GLuint index; // GLSL slot
|
||||
uint size; // size of the data
|
||||
const GLenum target;
|
||||
|
||||
public:
|
||||
GSUniformBufferOGL(GLuint index, uint size) : index(index)
|
||||
, size(size)
|
||||
,target(GL_UNIFORM_BUFFER)
|
||||
{
|
||||
glGenBuffers(1, &buffer);
|
||||
bind();
|
||||
allocate();
|
||||
attach();
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindBuffer(target, buffer);
|
||||
}
|
||||
|
||||
void allocate()
|
||||
{
|
||||
glBufferData(target, size, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
void attach()
|
||||
{
|
||||
glBindBufferBase(target, index, buffer);
|
||||
}
|
||||
|
||||
void upload(const void* src)
|
||||
{
|
||||
uint32 flags = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
uint8* dst = (uint8*) glMapBufferRange(target, 0, size, flags);
|
||||
memcpy(dst, src, size);
|
||||
glUnmapBuffer(target);
|
||||
}
|
||||
|
||||
~GSUniformBufferOGL() {
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
};
|
||||
|
||||
struct GSInputLayoutOGL {
|
||||
GLuint index;
|
||||
GLint size;
|
||||
GLenum type;
|
||||
GLboolean normalize;
|
||||
GLsizei stride;
|
||||
const GLvoid* offset;
|
||||
};
|
||||
|
||||
class GSVertexBufferStateOGL {
|
||||
class GSBufferOGL {
|
||||
size_t m_stride;
|
||||
size_t m_start;
|
||||
size_t m_count;
|
||||
size_t m_limit;
|
||||
GLenum m_target;
|
||||
GLuint m_buffer;
|
||||
size_t m_default_size;
|
||||
|
||||
public:
|
||||
GSBufferOGL(GLenum target, size_t stride) :
|
||||
m_stride(stride)
|
||||
, m_start(0)
|
||||
, m_count(0)
|
||||
, m_limit(0)
|
||||
, m_target(target)
|
||||
{
|
||||
glGenBuffers(1, &m_buffer);
|
||||
// Opengl works best with 1-4MB buffer.
|
||||
m_default_size = 2 * 1024 * 1024 / m_stride;
|
||||
}
|
||||
|
||||
~GSBufferOGL() { glDeleteBuffers(1, &m_buffer); }
|
||||
|
||||
void allocate() { allocate(m_default_size); }
|
||||
|
||||
void allocate(size_t new_limit)
|
||||
{
|
||||
m_start = 0;
|
||||
m_limit = new_limit;
|
||||
glBufferData(m_target, m_limit * m_stride, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindBuffer(m_target, m_buffer);
|
||||
}
|
||||
|
||||
void upload(const void* src, uint32 count)
|
||||
{
|
||||
// Upload the data to the buffer
|
||||
void* dst;
|
||||
if (Map(&dst, count)) {
|
||||
// FIXME which one to use
|
||||
// GSVector4i::storent(dst, src, m_count * m_stride);
|
||||
memcpy(dst, src, m_stride*m_count);
|
||||
Unmap();
|
||||
}
|
||||
}
|
||||
|
||||
bool Map(void** pointer, uint32 count ) {
|
||||
#ifdef OGL_DEBUG
|
||||
GLint b_size = -1;
|
||||
glGetBufferParameteriv(m_target, GL_BUFFER_SIZE, &b_size);
|
||||
|
||||
if (b_size <= 0) return false;
|
||||
#endif
|
||||
|
||||
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>(m_count * 3 / 2, m_default_size));
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
// Upload the data to the buffer
|
||||
*pointer = (uint8*) glMapBufferRange(m_target, m_stride*m_start, m_stride*m_count, map_flags);
|
||||
//fprintf(stderr, "Map %x from %d to %d\n", *pointer, m_start, m_start+m_count);
|
||||
#ifdef OGL_DEBUG
|
||||
if (*pointer == NULL) {
|
||||
fprintf(stderr, "CRITICAL ERROR map failed for vb!!!\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void Unmap() { glUnmapBuffer(m_target); }
|
||||
|
||||
void EndScene()
|
||||
{
|
||||
m_start += m_count;
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
void Draw(GLenum mode)
|
||||
{
|
||||
glDrawArrays(mode, m_start, m_count);
|
||||
}
|
||||
|
||||
void Draw(GLenum mode, GLint basevertex)
|
||||
{
|
||||
glDrawElementsBaseVertex(mode, m_count, GL_UNSIGNED_INT, (void*)(m_start * m_stride), basevertex);
|
||||
}
|
||||
|
||||
void Draw(GLenum mode, GLint basevertex, int offset, int count)
|
||||
{
|
||||
glDrawElementsBaseVertex(mode, count, GL_UNSIGNED_INT, (void*)((m_start + offset) * m_stride), basevertex);
|
||||
}
|
||||
|
||||
size_t GetStart() { return m_start; }
|
||||
|
||||
void debug()
|
||||
{
|
||||
fprintf(stderr, "data buffer: start %d, count %d\n", m_start, m_count);
|
||||
}
|
||||
|
||||
} *m_vb, *m_ib;
|
||||
|
||||
GLuint m_va;
|
||||
GLenum m_topology;
|
||||
|
||||
public:
|
||||
GSVertexBufferStateOGL(size_t stride, GSInputLayoutOGL* layout, uint32 layout_nbr)
|
||||
{
|
||||
glGenVertexArrays(1, &m_va);
|
||||
|
||||
m_vb = new GSBufferOGL(GL_ARRAY_BUFFER, stride);
|
||||
m_ib = new GSBufferOGL(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32));
|
||||
|
||||
bind();
|
||||
// Note: index array are part of the VA state so it need to be bind only once.
|
||||
m_ib->bind();
|
||||
|
||||
m_vb->allocate();
|
||||
m_ib->allocate();
|
||||
set_internal_format(layout, layout_nbr);
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindVertexArray(m_va);
|
||||
m_vb->bind();
|
||||
}
|
||||
|
||||
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
|
||||
glEnableVertexAttribArray(layout[i].index);
|
||||
switch (layout[i].type) {
|
||||
case GL_UNSIGNED_SHORT:
|
||||
case GL_UNSIGNED_INT:
|
||||
// Rule: when shader use integral (not normalized) you must use glVertexAttribIPointer (note the extra I)
|
||||
glVertexAttribIPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].stride, layout[i].offset);
|
||||
break;
|
||||
default:
|
||||
glVertexAttribPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].normalize, layout[i].stride, layout[i].offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndScene()
|
||||
{
|
||||
m_vb->EndScene();
|
||||
m_ib->EndScene();
|
||||
}
|
||||
|
||||
void DrawPrimitive() { m_vb->Draw(m_topology); }
|
||||
|
||||
void DrawIndexedPrimitive() { m_ib->Draw(m_topology, m_vb->GetStart() ); }
|
||||
|
||||
void DrawIndexedPrimitive(int offset, int count) { m_ib->Draw(m_topology, m_vb->GetStart(), offset, count ); }
|
||||
|
||||
void SetTopology(GLenum topology) { m_topology = topology; }
|
||||
|
||||
void UploadVB(const void* vertices, size_t count) { m_vb->upload(vertices, count); }
|
||||
|
||||
void UploadIB(const void* index, size_t count) { m_ib->upload(index, count); }
|
||||
|
||||
bool MapVB(void **pointer, size_t count) { return m_vb->Map(pointer, count); }
|
||||
|
||||
void UnmapVB() { m_vb->Unmap(); }
|
||||
|
||||
~GSVertexBufferStateOGL()
|
||||
{
|
||||
glDeleteVertexArrays(1, &m_va);
|
||||
}
|
||||
|
||||
void debug()
|
||||
{
|
||||
string topo;
|
||||
switch (m_topology) {
|
||||
case GL_POINTS:
|
||||
topo = "point";
|
||||
break;
|
||||
case GL_LINES:
|
||||
topo = "line";
|
||||
break;
|
||||
case GL_TRIANGLES:
|
||||
topo = "triangle";
|
||||
break;
|
||||
case GL_TRIANGLE_STRIP:
|
||||
topo = "triangle strip";
|
||||
break;
|
||||
}
|
||||
m_vb->debug();
|
||||
m_ib->debug();
|
||||
fprintf(stderr, "primitives of %s\n", topo.c_str());
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class GSDeviceOGL : public GSDevice
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -38,7 +38,7 @@ void GSDeviceOGL::CreateTextureFX()
|
|||
glSamplerParameteri(m_rt_ss, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(m_rt_ss, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
// FIXME which value for GL_TEXTURE_MIN_LOD
|
||||
glSamplerParameteri(m_rt_ss, GL_TEXTURE_MAX_LOD, FLT_MAX);
|
||||
glSamplerParameterf(m_rt_ss, GL_TEXTURE_MAX_LOD, FLT_MAX);
|
||||
// FIXME: seems there is 2 possibility in opengl
|
||||
// DX: sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
// glSamplerParameteri(m_rt_ss, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
|
@ -225,7 +225,7 @@ void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerS
|
|||
glSamplerParameteri(ss0, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
// FIXME which value for GL_TEXTURE_MIN_LOD
|
||||
glSamplerParameteri(m_rt_ss, GL_TEXTURE_MAX_LOD, FLT_MAX);
|
||||
glSamplerParameterf(m_rt_ss, GL_TEXTURE_MAX_LOD, FLT_MAX);
|
||||
// FIXME: seems there is 2 possibility in opengl
|
||||
// DX: sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
// glSamplerParameteri(m_rt_ss, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2011 Gregory hainaut
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
*
|
||||
* 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; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class GSUniformBufferOGL {
|
||||
GLuint buffer; // data object
|
||||
GLuint index; // GLSL slot
|
||||
uint size; // size of the data
|
||||
const GLenum target;
|
||||
|
||||
public:
|
||||
GSUniformBufferOGL(GLuint index, uint size) : index(index)
|
||||
, size(size)
|
||||
,target(GL_UNIFORM_BUFFER)
|
||||
{
|
||||
glGenBuffers(1, &buffer);
|
||||
bind();
|
||||
allocate();
|
||||
attach();
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindBuffer(target, buffer);
|
||||
}
|
||||
|
||||
void allocate()
|
||||
{
|
||||
glBufferData(target, size, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
void attach()
|
||||
{
|
||||
glBindBufferBase(target, index, buffer);
|
||||
}
|
||||
|
||||
void upload(const void* src)
|
||||
{
|
||||
uint32 flags = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
uint8* dst = (uint8*) glMapBufferRange(target, 0, size, flags);
|
||||
memcpy(dst, src, size);
|
||||
glUnmapBuffer(target);
|
||||
}
|
||||
|
||||
~GSUniformBufferOGL() {
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2011 Gregory hainaut
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
*
|
||||
* 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; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct GSInputLayoutOGL {
|
||||
GLuint index;
|
||||
GLint size;
|
||||
GLenum type;
|
||||
GLboolean normalize;
|
||||
GLsizei stride;
|
||||
const GLvoid* offset;
|
||||
};
|
||||
|
||||
class GSVertexBufferStateOGL {
|
||||
class GSBufferOGL {
|
||||
size_t m_stride;
|
||||
size_t m_start;
|
||||
size_t m_count;
|
||||
size_t m_limit;
|
||||
GLenum m_target;
|
||||
GLuint m_buffer;
|
||||
size_t m_default_size;
|
||||
|
||||
public:
|
||||
GSBufferOGL(GLenum target, size_t stride) :
|
||||
m_stride(stride)
|
||||
, m_start(0)
|
||||
, m_count(0)
|
||||
, m_limit(0)
|
||||
, m_target(target)
|
||||
{
|
||||
glGenBuffers(1, &m_buffer);
|
||||
// Opengl works best with 1-4MB buffer.
|
||||
m_default_size = 2 * 1024 * 1024 / m_stride;
|
||||
}
|
||||
|
||||
~GSBufferOGL() { glDeleteBuffers(1, &m_buffer); }
|
||||
|
||||
void allocate() { allocate(m_default_size); }
|
||||
|
||||
void allocate(size_t new_limit)
|
||||
{
|
||||
m_start = 0;
|
||||
m_limit = new_limit;
|
||||
glBufferData(m_target, m_limit * m_stride, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindBuffer(m_target, m_buffer);
|
||||
}
|
||||
|
||||
void upload(const void* src, uint32 count)
|
||||
{
|
||||
// Upload the data to the buffer
|
||||
void* dst;
|
||||
if (Map(&dst, count)) {
|
||||
// FIXME which one to use
|
||||
// GSVector4i::storent(dst, src, m_count * m_stride);
|
||||
memcpy(dst, src, m_stride*m_count);
|
||||
Unmap();
|
||||
}
|
||||
}
|
||||
|
||||
bool Map(void** pointer, uint32 count ) {
|
||||
#ifdef OGL_DEBUG
|
||||
GLint b_size = -1;
|
||||
glGetBufferParameteriv(m_target, GL_BUFFER_SIZE, &b_size);
|
||||
|
||||
if (b_size <= 0) return false;
|
||||
#endif
|
||||
|
||||
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>(m_count * 3 / 2, m_default_size));
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
// Upload the data to the buffer
|
||||
*pointer = (uint8*) glMapBufferRange(m_target, m_stride*m_start, m_stride*m_count, map_flags);
|
||||
//fprintf(stderr, "Map %x from %d to %d\n", *pointer, m_start, m_start+m_count);
|
||||
#ifdef OGL_DEBUG
|
||||
if (*pointer == NULL) {
|
||||
fprintf(stderr, "CRITICAL ERROR map failed for vb!!!\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void Unmap() { glUnmapBuffer(m_target); }
|
||||
|
||||
void EndScene()
|
||||
{
|
||||
m_start += m_count;
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
void Draw(GLenum mode)
|
||||
{
|
||||
glDrawArrays(mode, m_start, m_count);
|
||||
}
|
||||
|
||||
void Draw(GLenum mode, GLint basevertex)
|
||||
{
|
||||
glDrawElementsBaseVertex(mode, m_count, GL_UNSIGNED_INT, (void*)(m_start * m_stride), basevertex);
|
||||
}
|
||||
|
||||
void Draw(GLenum mode, GLint basevertex, int offset, int count)
|
||||
{
|
||||
glDrawElementsBaseVertex(mode, count, GL_UNSIGNED_INT, (void*)((m_start + offset) * m_stride), basevertex);
|
||||
}
|
||||
|
||||
size_t GetStart() { return m_start; }
|
||||
|
||||
void debug()
|
||||
{
|
||||
fprintf(stderr, "data buffer: start %d, count %d\n", m_start, m_count);
|
||||
}
|
||||
|
||||
} *m_vb, *m_ib;
|
||||
|
||||
GLuint m_va;
|
||||
GLenum m_topology;
|
||||
|
||||
public:
|
||||
GSVertexBufferStateOGL(size_t stride, GSInputLayoutOGL* layout, uint32 layout_nbr)
|
||||
{
|
||||
glGenVertexArrays(1, &m_va);
|
||||
|
||||
m_vb = new GSBufferOGL(GL_ARRAY_BUFFER, stride);
|
||||
m_ib = new GSBufferOGL(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32));
|
||||
|
||||
bind();
|
||||
// Note: index array are part of the VA state so it need to be bind only once.
|
||||
m_ib->bind();
|
||||
|
||||
m_vb->allocate();
|
||||
m_ib->allocate();
|
||||
set_internal_format(layout, layout_nbr);
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindVertexArray(m_va);
|
||||
m_vb->bind();
|
||||
}
|
||||
|
||||
void set_internal_format(GSInputLayoutOGL* layout, uint32 layout_nbr)
|
||||
{
|
||||
for (uint i = 0; i < layout_nbr; i++) {
|
||||
// Note this function need both a vertex array object and a GL_ARRAY_BUFFER buffer
|
||||
glEnableVertexAttribArray(layout[i].index);
|
||||
switch (layout[i].type) {
|
||||
case GL_UNSIGNED_SHORT:
|
||||
case GL_UNSIGNED_INT:
|
||||
// Rule: when shader use integral (not normalized) you must use glVertexAttribIPointer (note the extra I)
|
||||
glVertexAttribIPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].stride, layout[i].offset);
|
||||
break;
|
||||
default:
|
||||
glVertexAttribPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].normalize, layout[i].stride, layout[i].offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndScene()
|
||||
{
|
||||
m_vb->EndScene();
|
||||
m_ib->EndScene();
|
||||
}
|
||||
|
||||
void DrawPrimitive() { m_vb->Draw(m_topology); }
|
||||
|
||||
void DrawIndexedPrimitive() { m_ib->Draw(m_topology, m_vb->GetStart() ); }
|
||||
|
||||
void DrawIndexedPrimitive(int offset, int count) { m_ib->Draw(m_topology, m_vb->GetStart(), offset, count ); }
|
||||
|
||||
void SetTopology(GLenum topology) { m_topology = topology; }
|
||||
|
||||
void UploadVB(const void* vertices, size_t count) { m_vb->upload(vertices, count); }
|
||||
|
||||
void UploadIB(const void* index, size_t count) { m_ib->upload(index, count); }
|
||||
|
||||
bool MapVB(void **pointer, size_t count) { return m_vb->Map(pointer, count); }
|
||||
|
||||
void UnmapVB() { m_vb->Unmap(); }
|
||||
|
||||
~GSVertexBufferStateOGL()
|
||||
{
|
||||
glDeleteVertexArrays(1, &m_va);
|
||||
}
|
||||
|
||||
void debug()
|
||||
{
|
||||
string topo;
|
||||
switch (m_topology) {
|
||||
case GL_POINTS:
|
||||
topo = "point";
|
||||
break;
|
||||
case GL_LINES:
|
||||
topo = "line";
|
||||
break;
|
||||
case GL_TRIANGLES:
|
||||
topo = "triangle";
|
||||
break;
|
||||
case GL_TRIANGLE_STRIP:
|
||||
topo = "triangle strip";
|
||||
break;
|
||||
}
|
||||
m_vb->debug();
|
||||
m_ib->debug();
|
||||
fprintf(stderr, "primitives of %s\n", topo.c_str());
|
||||
|
||||
}
|
||||
};
|
|
@ -230,7 +230,7 @@ void GLWindow::CreateContextGL()
|
|||
{
|
||||
#if defined(OGL4_LOG) || defined(GLSL4_API)
|
||||
// We need to define a debug context. So we need at a 3.0 context (if not 3.2 actually)
|
||||
CreateContextGL(4, 2);
|
||||
CreateContextGL(3, 3);
|
||||
#else
|
||||
// FIXME there was some issue with previous context creation on Geforce7. Code was rewritten
|
||||
// for GSdx unfortunately it was not tested on Geforce7 so keep the 2.0 context for now.
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2011 Gregory hainaut
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
*
|
||||
* 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; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// Note: it is same code that was developed for GSdx plugin
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef GLSL4_API
|
||||
class GSUniformBufferOGL {
|
||||
GLuint buffer; // data object
|
||||
GLuint index; // GLSL slot
|
||||
uint size; // size of the data
|
||||
const GLenum target;
|
||||
|
||||
public:
|
||||
GSUniformBufferOGL(GLuint index, uint size) : index(index)
|
||||
, size(size)
|
||||
,target(GL_UNIFORM_BUFFER)
|
||||
{
|
||||
glGenBuffers(1, &buffer);
|
||||
bind();
|
||||
allocate();
|
||||
attach();
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindBuffer(target, buffer);
|
||||
}
|
||||
|
||||
void allocate()
|
||||
{
|
||||
glBufferData(target, size, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
void attach()
|
||||
{
|
||||
glBindBufferBase(target, index, buffer);
|
||||
}
|
||||
|
||||
void upload(const void* src)
|
||||
{
|
||||
uint32 flags = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
uint8* dst = (uint8*) glMapBufferRange(target, 0, size, flags);
|
||||
memcpy(dst, src, size);
|
||||
glUnmapBuffer(target);
|
||||
}
|
||||
|
||||
~GSUniformBufferOGL() {
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2011 Gregory hainaut
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
*
|
||||
* 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; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// Note: it is same code that was developed for GSdx plugin
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef GLSL4_API
|
||||
struct GSInputLayoutOGL {
|
||||
GLuint index;
|
||||
GLint size;
|
||||
GLenum type;
|
||||
GLboolean normalize;
|
||||
GLsizei stride;
|
||||
const GLvoid* offset;
|
||||
};
|
||||
|
||||
class GSVertexBufferStateOGL {
|
||||
class GSBufferOGL {
|
||||
size_t m_stride;
|
||||
size_t m_start;
|
||||
size_t m_count;
|
||||
size_t m_limit;
|
||||
GLenum m_target;
|
||||
GLuint m_buffer;
|
||||
size_t m_default_size;
|
||||
|
||||
public:
|
||||
GSBufferOGL(GLenum target, size_t stride) :
|
||||
m_stride(stride)
|
||||
, m_start(0)
|
||||
, m_count(0)
|
||||
, m_limit(0)
|
||||
, m_target(target)
|
||||
{
|
||||
glGenBuffers(1, &m_buffer);
|
||||
// Opengl works best with 1-4MB buffer.
|
||||
m_default_size = 2 * 1024 * 1024 / m_stride;
|
||||
}
|
||||
|
||||
~GSBufferOGL() { glDeleteBuffers(1, &m_buffer); }
|
||||
|
||||
void allocate() { allocate(m_default_size); }
|
||||
|
||||
void allocate(size_t new_limit)
|
||||
{
|
||||
m_start = 0;
|
||||
m_limit = new_limit;
|
||||
glBufferData(m_target, m_limit * m_stride, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindBuffer(m_target, m_buffer);
|
||||
}
|
||||
|
||||
void upload(const void* src, uint32 count)
|
||||
{
|
||||
// Upload the data to the buffer
|
||||
void* dst;
|
||||
if (Map(&dst, count)) {
|
||||
// FIXME which one to use
|
||||
// GSVector4i::storent(dst, src, m_count * m_stride);
|
||||
memcpy(dst, src, m_stride*m_count);
|
||||
Unmap();
|
||||
}
|
||||
}
|
||||
|
||||
bool Map(void** pointer, uint32 count ) {
|
||||
#ifdef OGL_DEBUG
|
||||
GLint b_size = -1;
|
||||
glGetBufferParameteriv(m_target, GL_BUFFER_SIZE, &b_size);
|
||||
|
||||
if (b_size <= 0) return false;
|
||||
#endif
|
||||
|
||||
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>(m_count * 3 / 2, m_default_size));
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
// Upload the data to the buffer
|
||||
*pointer = (uint8*) glMapBufferRange(m_target, m_stride*m_start, m_stride*m_count, map_flags);
|
||||
//fprintf(stderr, "Map %x from %d to %d\n", *pointer, m_start, m_start+m_count);
|
||||
#ifdef OGL_DEBUG
|
||||
if (*pointer == NULL) {
|
||||
fprintf(stderr, "CRITICAL ERROR map failed for vb!!!\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void Unmap() { glUnmapBuffer(m_target); }
|
||||
|
||||
void EndScene()
|
||||
{
|
||||
m_start += m_count;
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
void Draw(GLenum mode)
|
||||
{
|
||||
glDrawArrays(mode, m_start, m_count);
|
||||
}
|
||||
|
||||
void Draw(GLenum mode, GLint basevertex)
|
||||
{
|
||||
glDrawElementsBaseVertex(mode, m_count, GL_UNSIGNED_INT, (void*)(m_start * m_stride), basevertex);
|
||||
}
|
||||
|
||||
void Draw(GLenum mode, GLint basevertex, int offset, int count)
|
||||
{
|
||||
glDrawElementsBaseVertex(mode, count, GL_UNSIGNED_INT, (void*)((m_start + offset) * m_stride), basevertex);
|
||||
}
|
||||
|
||||
size_t GetStart() { return m_start; }
|
||||
|
||||
void debug()
|
||||
{
|
||||
fprintf(stderr, "data buffer: start %d, count %d\n", m_start, m_count);
|
||||
}
|
||||
|
||||
} *m_vb, *m_ib;
|
||||
|
||||
GLuint m_va;
|
||||
GLenum m_topology;
|
||||
|
||||
public:
|
||||
GSVertexBufferStateOGL(size_t stride, GSInputLayoutOGL* layout, uint32 layout_nbr)
|
||||
{
|
||||
glGenVertexArrays(1, &m_va);
|
||||
|
||||
m_vb = new GSBufferOGL(GL_ARRAY_BUFFER, stride);
|
||||
m_ib = new GSBufferOGL(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32));
|
||||
|
||||
bind();
|
||||
// Note: index array are part of the VA state so it need to be bind only once.
|
||||
m_ib->bind();
|
||||
|
||||
m_vb->allocate();
|
||||
m_ib->allocate();
|
||||
set_internal_format(layout, layout_nbr);
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindVertexArray(m_va);
|
||||
m_vb->bind();
|
||||
}
|
||||
|
||||
void set_internal_format(GSInputLayoutOGL* layout, uint32 layout_nbr)
|
||||
{
|
||||
for (uint i = 0; i < layout_nbr; i++) {
|
||||
// Note this function need both a vertex array object and a GL_ARRAY_BUFFER buffer
|
||||
glEnableVertexAttribArray(layout[i].index);
|
||||
switch (layout[i].type) {
|
||||
case GL_UNSIGNED_SHORT:
|
||||
case GL_UNSIGNED_INT:
|
||||
// Rule: when shader use integral (not normalized) you must use glVertexAttribIPointer (note the extra I)
|
||||
glVertexAttribIPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].stride, layout[i].offset);
|
||||
break;
|
||||
default:
|
||||
glVertexAttribPointer(layout[i].index, layout[i].size, layout[i].type, layout[i].normalize, layout[i].stride, layout[i].offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EndScene()
|
||||
{
|
||||
m_vb->EndScene();
|
||||
m_ib->EndScene();
|
||||
}
|
||||
|
||||
void DrawPrimitive() { m_vb->Draw(m_topology); }
|
||||
|
||||
void DrawIndexedPrimitive() { m_ib->Draw(m_topology, m_vb->GetStart() ); }
|
||||
|
||||
void DrawIndexedPrimitive(int offset, int count) { m_ib->Draw(m_topology, m_vb->GetStart(), offset, count ); }
|
||||
|
||||
void SetTopology(GLenum topology) { m_topology = topology; }
|
||||
|
||||
void UploadVB(const void* vertices, size_t count) { m_vb->upload(vertices, count); }
|
||||
|
||||
void UploadIB(const void* index, size_t count) { m_ib->upload(index, count); }
|
||||
|
||||
bool MapVB(void **pointer, size_t count) { return m_vb->Map(pointer, count); }
|
||||
|
||||
void UnmapVB() { m_vb->Unmap(); }
|
||||
|
||||
~GSVertexBufferStateOGL()
|
||||
{
|
||||
glDeleteVertexArrays(1, &m_va);
|
||||
}
|
||||
|
||||
void debug()
|
||||
{
|
||||
string topo;
|
||||
switch (m_topology) {
|
||||
case GL_POINTS:
|
||||
topo = "point";
|
||||
break;
|
||||
case GL_LINES:
|
||||
topo = "line";
|
||||
break;
|
||||
case GL_TRIANGLES:
|
||||
topo = "triangle";
|
||||
break;
|
||||
case GL_TRIANGLE_STRIP:
|
||||
topo = "triangle strip";
|
||||
break;
|
||||
}
|
||||
m_vb->debug();
|
||||
m_ib->debug();
|
||||
fprintf(stderr, "primitives of %s\n", topo.c_str());
|
||||
|
||||
}
|
||||
};
|
||||
#endif
|
|
@ -72,6 +72,16 @@ extern "C" u32 CALLBACK PS2EgetLibVersion2(u32 type);
|
|||
extern "C" char* CALLBACK PS2EgetLibName(void);
|
||||
#endif
|
||||
|
||||
// Allow easy copy/past between GSdx and zzogl
|
||||
typedef unsigned char uint8;
|
||||
typedef signed char int8;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed short int16;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed int int32;
|
||||
typedef unsigned long long uint64;
|
||||
typedef signed long long int64;
|
||||
|
||||
#include "ZZoglMath.h"
|
||||
#include "Profile.h"
|
||||
#include "GSDump.h"
|
||||
|
|
|
@ -59,6 +59,10 @@ inline bool ZZshActiveParameter(ZZshParameter param) {return (param !=NULL); }
|
|||
|
||||
#endif // end NVIDIA cg-toolkit API
|
||||
|
||||
#ifdef GLSL4_API
|
||||
#include "GSUniformBufferOGL.h"
|
||||
#endif
|
||||
|
||||
#ifdef GLSL_API
|
||||
|
||||
enum ZZshPARAMTYPE {
|
||||
|
@ -118,53 +122,6 @@ enum {
|
|||
ZZSH_CTX_ALL = 2
|
||||
};
|
||||
|
||||
class GSUniformBufferOGL {
|
||||
GLuint buffer; // data object
|
||||
GLuint index; // GLSL slot
|
||||
uint size; // size of the data
|
||||
const GLenum target;
|
||||
|
||||
public:
|
||||
GSUniformBufferOGL(GLuint index, uint size) : index(index)
|
||||
, size(size)
|
||||
,target(GL_UNIFORM_BUFFER)
|
||||
{
|
||||
glGenBuffers(1, &buffer);
|
||||
bind();
|
||||
allocate();
|
||||
attach();
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
glBindBuffer(target, buffer);
|
||||
}
|
||||
|
||||
void allocate()
|
||||
{
|
||||
glBufferData(target, size, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
void attach()
|
||||
{
|
||||
glBindBufferBase(target, index, buffer);
|
||||
}
|
||||
|
||||
void upload(const void* src)
|
||||
{
|
||||
u32 flags = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
u8* dst = (u8*) glMapBufferRange(target, 0, size, flags);
|
||||
memcpy(dst, src, size);
|
||||
glUnmapBuffer(target);
|
||||
}
|
||||
|
||||
~GSUniformBufferOGL() {
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Note A nice template could be better
|
||||
// Warning order is important for buffer (see GLSL)
|
||||
// Note must be keep POD (so you can map it to GLSL)
|
||||
|
|
|
@ -93,9 +93,6 @@ ZZshProgram ZZshMainProgram;
|
|||
char* ZZshSource; // Shader's source data.
|
||||
off_t ZZshSourceSize;
|
||||
|
||||
extern char* EFFECT_NAME; // All this variables used for testing and set manually
|
||||
extern char* EFFECT_DIR;
|
||||
|
||||
bool g_bCRTCBilinear = true;
|
||||
|
||||
float4 g_vdepth, vlogz;
|
||||
|
@ -109,37 +106,23 @@ VERTEXSHADER pvsBitBlt;
|
|||
inline bool LoadEffects();
|
||||
extern bool s_bWriteDepth;
|
||||
|
||||
struct SHADERHEADER
|
||||
{
|
||||
unsigned int index, offset, size; // if highest bit of index is set, pixel shader
|
||||
};
|
||||
map<int, SHADERHEADER*> mapShaderResources;
|
||||
|
||||
// Debug variable, store name of the function that call the shader.
|
||||
const char* ShaderCallerName = "";
|
||||
const char* ShaderHandleName = "";
|
||||
|
||||
int NumActiveUniforms, NumGlobalUniforms;
|
||||
ZZshParamInfo UniformsIndex[MAX_ACTIVE_UNIFORMS] = {qZero};
|
||||
const char* ShaderNames[MAX_ACTIVE_SHADERS] = {""};
|
||||
ZZshShaderType ShaderTypes[MAX_ACTIVE_SHADERS] = {ZZ_SH_NONE};
|
||||
|
||||
ZZshProgram CompiledPrograms[MAX_ACTIVE_SHADERS][MAX_ACTIVE_SHADERS] = {{0}};
|
||||
const char* TextureUnits[NUMBER_OF_SAMPLERS] =
|
||||
{"g_sMemory[0]", "g_sMemory[1]", "g_sSrcFinal", "g_sBitwiseANDX", "g_sBitwiseANDY", "g_sInterlace", \
|
||||
"g_sCLUT", "g_sBlocks", "g_sBilinearBlocks", "g_sConv16to32", "g_sConv32to16"};
|
||||
ZZshPARAMTYPE TextureTypes[NUMBER_OF_SAMPLERS] =
|
||||
{ZZ_TEXTURE_RECT, ZZ_TEXTURE_RECT, ZZ_TEXTURE_RECT, ZZ_TEXTURE_RECT, ZZ_TEXTURE_RECT, ZZ_TEXTURE_RECT, \
|
||||
ZZ_TEXTURE_2D, ZZ_TEXTURE_2D, ZZ_TEXTURE_2D, ZZ_TEXTURE_2D, ZZ_TEXTURE_3D} ;
|
||||
|
||||
#ifdef GLSL4_API
|
||||
// new for GLSL4
|
||||
GSUniformBufferOGL *constant_buffer;
|
||||
GSUniformBufferOGL *common_buffer;
|
||||
GSUniformBufferOGL *vertex_buffer;
|
||||
GSUniformBufferOGL *fragment_buffer;
|
||||
|
||||
COMMONSHADER g_cs;
|
||||
#endif
|
||||
|
||||
//------------------ Code
|
||||
|
||||
|
@ -162,28 +145,6 @@ void HandleCgError(ZZshContext ctx, ZZshError err, void* appdata)
|
|||
*/
|
||||
}
|
||||
|
||||
float ZeroFloat4[4] = {0};
|
||||
|
||||
inline void SettleFloat(float* f, const float* v) {
|
||||
f[0] = v[0];
|
||||
f[1] = v[1];
|
||||
f[2] = v[2];
|
||||
f[3] = v[3];
|
||||
}
|
||||
|
||||
inline ZZshParamInfo ParamInfo(const char* ShName, ZZshPARAMTYPE type, const float fvalue[], GLuint sampler, GLint texid, bool Constant, bool Settled) {
|
||||
ZZshParamInfo x;
|
||||
x.ShName = new char[MAX_UNIFORM_NAME_SIZE];
|
||||
x.ShName = ShName;
|
||||
x.type = type;
|
||||
SettleFloat(x.fvalue, fvalue);
|
||||
x.sampler = sampler;
|
||||
x.texid = texid;
|
||||
x.Constant = Constant;
|
||||
x.Settled = Settled;
|
||||
return x;
|
||||
}
|
||||
|
||||
bool ZZshStartUsingShaders() {
|
||||
|
||||
ZZLog::Error_Log("Creating effects.");
|
||||
|
@ -331,25 +292,6 @@ void ZZshDefaultOneColor( FRAGMENTSHADER& ptr ) {
|
|||
const GLchar * EmptyVertex = "void main(void) {gl_Position = ftransform();}";
|
||||
const GLchar * EmptyFragment = "void main(void) {gl_FragColor = gl_Color;}";
|
||||
|
||||
inline ZZshProgram UseEmptyProgram(const char* name, GLenum shaderType) {
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
if (shaderType == GL_VERTEX_SHADER)
|
||||
glShaderSource(shader, 1, &EmptyVertex, NULL);
|
||||
else
|
||||
glShaderSource(shader, 1, &EmptyFragment, NULL);
|
||||
|
||||
glCompileShader(shader);
|
||||
ZZshProgram prog = glCreateProgram();
|
||||
glAttachShader(prog, shader);
|
||||
glLinkProgram(prog);
|
||||
if( !glIsProgram(prog) || glGetError() != GL_NO_ERROR ) {
|
||||
ZZLog::Error_Log("Failed to load empty shader for %s:", name);
|
||||
return -1;
|
||||
}
|
||||
ZZLog::Error_Log("Used Empty program for %s... Ok.",name);
|
||||
return prog;
|
||||
}
|
||||
|
||||
ZZshShaderType ZZshGetShaderType(const char* name) {
|
||||
if (strncmp(name, "TextureFog", 10) == 0) return ZZ_SH_TEXTURE_FOG;
|
||||
if (strncmp(name, "Texture", 7) == 0) return ZZ_SH_TEXTURE;
|
||||
|
@ -381,10 +323,10 @@ inline bool GetCompilationLog(GLuint shader) {
|
|||
if (CompileStatus == GL_TRUE)
|
||||
return true;
|
||||
|
||||
int* lenght, infologlength;
|
||||
int lenght, infologlength;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologlength);
|
||||
char* InfoLog = new char[infologlength];
|
||||
glGetShaderInfoLog(shader, infologlength, lenght, InfoLog);
|
||||
glGetShaderInfoLog(shader, infologlength, &lenght, InfoLog);
|
||||
ZZLog::Error_Log("Compiling... %d:\t %s", shader, InfoLog);
|
||||
|
||||
return false;
|
||||
|
@ -413,6 +355,10 @@ inline bool CompileShader(ZZshProgram& shader, const char* DefineString, const c
|
|||
}
|
||||
|
||||
inline bool LoadShaderFromFile(ZZshShader& shader, const char* DefineString, const char* name, GLenum ShaderType) { // Linux specific, as I presume
|
||||
|
||||
// Emit annotation for apitrace
|
||||
// if (GLEW_GREMEDY_string_marker) glStringMarkerGREMEDY(0, DefineString);
|
||||
|
||||
if (!CompileShader(shader, DefineString, name, ShaderType)) {
|
||||
ZZLog::Error_Log("Failed to compile shader for %s: ", name);
|
||||
return false;
|
||||
|
@ -454,10 +400,10 @@ static bool ValidateProgram(ZZshProgram Prog) {
|
|||
|
||||
if (!isValid) {
|
||||
glValidateProgram(Prog);
|
||||
int* lenght, infologlength;
|
||||
int lenght, infologlength;
|
||||
glGetProgramiv(Prog, GL_INFO_LOG_LENGTH, &infologlength);
|
||||
char* InfoLog = new char[infologlength];
|
||||
glGetProgramInfoLog(Prog, infologlength, lenght, InfoLog);
|
||||
glGetProgramInfoLog(Prog, infologlength, &lenght, InfoLog);
|
||||
ZZLog::Error_Log("Validation %d... %d:\t %s", Prog, infologlength, InfoLog);
|
||||
}
|
||||
return (isValid != 0);
|
||||
|
@ -542,8 +488,14 @@ void ZZshSetPixelShader(ZZshShaderLink prog) {
|
|||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef GLSL4_API
|
||||
static void init_shader() {
|
||||
// TODO:
|
||||
// Note it would be more clever to allocate buffer inside SHADER class
|
||||
// Add a dirty flags to avoid to upload twice same data...
|
||||
// You need to attach() properly the uniform buffer;
|
||||
// Note: don't put GSUniformBuffer creation inside constructor of static object (context won't
|
||||
// be set to call gl command)
|
||||
|
||||
// Warning put same order than GLSL
|
||||
constant_buffer = new GSUniformBufferOGL(0, sizeof(ConstantUniform));
|
||||
common_buffer = new GSUniformBufferOGL(1, sizeof(GlobalUniform));
|
||||
|
@ -565,55 +517,13 @@ static void PutParametersInProgam(VERTEXSHADER* vs, FRAGMENTSHADER* ps, int cont
|
|||
fragment_buffer->bind();
|
||||
fragment_buffer->upload((void*)&ps->uniform_buffer[context]);
|
||||
|
||||
// FIXME DEBUG
|
||||
#ifdef _DEBUG
|
||||
GLint cb_idx = glGetUniformBlockIndex(ZZshMainProgram, "constant_buffer");
|
||||
GLint co_idx = glGetUniformBlockIndex(ZZshMainProgram, "common_buffer");
|
||||
GLint fb_idx = glGetUniformBlockIndex(ZZshMainProgram, "fragment_buffer");
|
||||
GLint vb_idx = glGetUniformBlockIndex(ZZshMainProgram, "vertex_buffer");
|
||||
|
||||
GLint debug;
|
||||
|
||||
ZZLog::Error_Log("NEW !!!");
|
||||
if (cb_idx != GL_INVALID_INDEX) {
|
||||
glGetActiveUniformBlockiv(ZZshMainProgram, cb_idx, GL_UNIFORM_BLOCK_BINDING, &debug);
|
||||
ZZLog::Error_Log("cb active : %d", debug);
|
||||
glGetActiveUniformBlockiv(ZZshMainProgram, cb_idx, GL_UNIFORM_BLOCK_DATA_SIZE, &debug);
|
||||
ZZLog::Error_Log("size : %d", debug);
|
||||
}
|
||||
|
||||
if (co_idx != GL_INVALID_INDEX) {
|
||||
glGetActiveUniformBlockiv(ZZshMainProgram, co_idx, GL_UNIFORM_BLOCK_BINDING, &debug);
|
||||
ZZLog::Error_Log("co active : %d", debug);
|
||||
glGetActiveUniformBlockiv(ZZshMainProgram, co_idx, GL_UNIFORM_BLOCK_DATA_SIZE, &debug);
|
||||
ZZLog::Error_Log("size : %d", debug);
|
||||
}
|
||||
|
||||
if (vb_idx != GL_INVALID_INDEX) {
|
||||
glGetActiveUniformBlockiv(ZZshMainProgram, vb_idx, GL_UNIFORM_BLOCK_BINDING, &debug);
|
||||
ZZLog::Error_Log("vb active : %d", debug);
|
||||
glGetActiveUniformBlockiv(ZZshMainProgram, vb_idx, GL_UNIFORM_BLOCK_DATA_SIZE, &debug);
|
||||
ZZLog::Error_Log("size : %d", debug);
|
||||
}
|
||||
|
||||
if (fb_idx != GL_INVALID_INDEX) {
|
||||
glGetActiveUniformBlockiv(ZZshMainProgram, fb_idx, GL_UNIFORM_BLOCK_BINDING, &debug);
|
||||
ZZLog::Error_Log("fb active : %d", debug);
|
||||
glGetActiveUniformBlockiv(ZZshMainProgram, fb_idx, GL_UNIFORM_BLOCK_DATA_SIZE, &debug);
|
||||
ZZLog::Error_Log("size : %d", debug);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_cs.enable_texture();
|
||||
ps->enable_texture(context);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void SetupFragmentProgramParameters(FRAGMENTSHADER* pf, int context, int type)
|
||||
{
|
||||
// uniform parameters
|
||||
GLint p;
|
||||
pf->prog.link = (void*)pf; // Setting autolink
|
||||
pf->prog.isFragment = true; // Setting autolink
|
||||
pf->ShaderType = ShaderTypes[pf->Shader];
|
||||
|
@ -628,7 +538,6 @@ static void SetupFragmentProgramParameters(FRAGMENTSHADER* pf, int context, int
|
|||
|
||||
void SetupVertexProgramParameters(VERTEXSHADER* pf, int context)
|
||||
{
|
||||
GLint p;
|
||||
pf->prog.link = (void*)pf; // Setting autolink
|
||||
pf->prog.isFragment = false; // Setting autolink
|
||||
pf->ShaderType = ShaderTypes[pf->Shader];
|
||||
|
@ -637,12 +546,12 @@ void SetupVertexProgramParameters(VERTEXSHADER* pf, int context)
|
|||
}
|
||||
|
||||
//const int GLSL_VERSION = 130; // Sampler2DRect appear in 1.3
|
||||
const int GLSL_VERSION = 420;
|
||||
const int GLSL_VERSION = 330;
|
||||
|
||||
// We use strictly compilation from source for GSLS
|
||||
static __forceinline void GlslHeaderString(char* header_string, const char* name, const char* depth)
|
||||
{
|
||||
sprintf(header_string, "#version %d\n#define %s main\n%s\n", GLSL_VERSION, name, depth);
|
||||
sprintf(header_string, "#version %d compatibility\n#define %s main\n%s\n", GLSL_VERSION, name, depth);
|
||||
}
|
||||
|
||||
static __forceinline bool LOAD_VS(char* DefineString, const char* name, VERTEXSHADER& vertex, int shaderver, ZZshProfile context, const char* depth)
|
||||
|
@ -702,7 +611,6 @@ bool ZZshLoadExtraEffects() {
|
|||
pvs[i] = pvsStore[i].prog;
|
||||
|
||||
if (!LOAD_VS(DefineString, "BitBltVS", pvsBitBlt, cgvProf, 0, "")) bLoadSuccess = false;
|
||||
GLint p;
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
if (!LOAD_PS(DefineString, "RegularPS", ppsRegular[0], cgfProf, 0, "")) bLoadSuccess = false;
|
||||
|
@ -755,13 +663,10 @@ bool ZZshLoadExtraEffects() {
|
|||
|
||||
const static char* g_pPsTexWrap[] = { "#define REPEAT 1\n", "#define CLAMP 1\n", "#define REGION_REPEAT 1\n", "" };
|
||||
|
||||
static ZZshShader LoadShaderFromType(const char* srcdir, const char* srcfile, int type, int texfilter, int texwrap, int fog, int writedepth, int testaem, int exactcolor, int ps, int context) {
|
||||
static ZZshShader LoadShaderFromType(int type, int texfilter, int texwrap, int fog, int writedepth, int testaem, int exactcolor, int ps, int context) {
|
||||
|
||||
assert( texwrap < NUM_TEXWRAPS);
|
||||
assert( type < NUM_TYPES );
|
||||
//ZZLog::Error_Log("\n");
|
||||
|
||||
ZZshProgram prog;
|
||||
|
||||
char* name = new char[MAX_SHADER_NAME_SIZE];
|
||||
sprintf(name, "Texture%s%d_%sPS", fog?"Fog":"", texfilter, g_pTexTypes[type]);
|
||||
|
@ -818,7 +723,7 @@ FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testae
|
|||
{
|
||||
return pf;
|
||||
}
|
||||
pf->Shader = LoadShaderFromType(EFFECT_DIR, EFFECT_NAME, type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, g_nPixelShaderVer, context);
|
||||
pf->Shader = LoadShaderFromType(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, g_nPixelShaderVer, context);
|
||||
|
||||
if (ZZshExistProgram(pf)) {
|
||||
SetupFragmentProgramParameters(pf, context, type);
|
||||
|
@ -840,4 +745,4 @@ FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testae
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#endif // GLSL_API
|
||||
#endif // GLSL4_API
|
||||
|
|
|
@ -5,7 +5,12 @@
|
|||
// fixes kh textures
|
||||
|
||||
#extension ARB_texture_rectangle: require
|
||||
#define GL_compatibility_profile 1
|
||||
#extension GL_ARB_shading_language_420pack: require
|
||||
#extension GL_ARB_separate_shader_objects : require
|
||||
// Set with version
|
||||
// #define GL_compatibility_profile 1
|
||||
|
||||
|
||||
#define PERSPECTIVE_CORRECT_TEX
|
||||
|
||||
// When writting GLSL code we should change variables in code according to denominator
|
||||
|
|
Loading…
Reference in New Issue