zzogl: GLSL is working again for AMD gpu. Nvidia test is welcome

* properly release shader in release mode
* set stream format every time an array buffer is bound


git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5219 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut 2012-05-21 06:43:28 +00:00
parent 2db7ddaaa3
commit cdeaa5e03c
6 changed files with 117 additions and 79 deletions

View File

@ -165,10 +165,14 @@ class GSVertexBufferStateOGL {
GLuint m_va;
GLenum m_topology;
// DEBUG
vector<GSInputLayoutOGL> layout_store;
public:
GSVertexBufferStateOGL(size_t stride, GSInputLayoutOGL* layout, uint32 layout_nbr)
{
glGenVertexArrays(1, &m_va);
layout_store.clear();
m_vb = new GSBufferOGL(GL_ARRAY_BUFFER, stride);
m_ib = new GSBufferOGL(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32));
@ -188,23 +192,39 @@ public:
m_vb->bind();
}
void set_internal_format()
{
for (vector<GSInputLayoutOGL>::iterator it = layout_store.begin(); it != layout_store.end(); it++)
set_internal_format(*it);
}
void set_internal_format(GSInputLayoutOGL& layout) {
// Note this function need both a vertex array object and a GL_ARRAY_BUFFER buffer
glEnableVertexAttribArray(layout.index);
switch (layout.type) {
case GL_UNSIGNED_SHORT:
case GL_UNSIGNED_INT:
case GL_SHORT:
case GL_INT:
// Rule: when shader use integral (not normalized) you must use glVertexAttribIPointer (note the extra I)
if (layout.normalize == false)
glVertexAttribIPointer(layout.index, layout.size, layout.type, layout.stride, layout.offset);
else
glVertexAttribPointer(layout.index, layout.size, layout.type, layout.normalize, layout.stride, layout.offset);
break;
default:
glVertexAttribPointer(layout.index, layout.size, layout.type, layout.normalize, layout.stride, layout.offset);
break;
}
}
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:
case GL_SHORT:
case GL_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;
}
// DEBUG
layout_store.push_back(layout[i]);
set_internal_format(layout[i]);
}
}

View File

@ -84,6 +84,9 @@ static __forceinline void GL_STENCILFUNC_SET()
glStencilFunc(s_stencilfunc, s_stencilref, s_stencilmask);
}
#ifdef GLSL4_API
#include "ZZoglShaders.h"
#endif
// sets the data stream
static __forceinline void SET_STREAM()
{
@ -92,6 +95,8 @@ static __forceinline void SET_STREAM()
glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12);
glTexCoordPointer(3, GL_FLOAT, sizeof(VertexGPU), (void*)16);
glVertexPointer(4, GL_SHORT, sizeof(VertexGPU), (void*)0);
#else
vertex_array->set_internal_format();
#endif
}

View File

@ -40,7 +40,6 @@ typedef void (APIENTRYP _PFNSWAPINTERVAL)(int);
map<string, GLbyte> mapGLExtensions;
extern bool LoadEffects();
extern bool ZZshLoadExtraEffects();
extern FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed);
@ -575,10 +574,9 @@ bool ZZCreate(int _width, int _height)
GL_REPORT_ERROR();
#ifdef GLSL4_API
// FIXME maybe GL_UNSIGNED_SHORT could be better than GL_SHORT
GSInputLayoutOGL vert_format[] =
{
{0 , 4 , GL_SHORT , GL_FALSE , sizeof(VertexGPU) , (const GLvoid*)(0) } , // vertex
{0 , 2 , GL_SHORT , GL_FALSE , sizeof(VertexGPU) , (const GLvoid*)(0) } , // vertex
{1 , 4 , GL_UNSIGNED_BYTE , GL_TRUE , sizeof(VertexGPU) , (const GLvoid*)(8) } , // color
{2 , 4 , GL_UNSIGNED_BYTE , GL_TRUE , sizeof(VertexGPU) , (const GLvoid*)(12) } , // z value. FIXME WTF 4 unsigned byte, why not a full integer
{3 , 3 , GL_FLOAT , GL_FALSE , sizeof(VertexGPU) , (const GLvoid*)(16) } , // tex coord
@ -596,7 +594,7 @@ bool ZZCreate(int _width, int _height)
glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[i]);
glBufferData(GL_ARRAY_BUFFER, 0x100*sizeof(VertexGPU), NULL, GL_STREAM_DRAW);
#ifdef GLSL4_API
vertex_array->set_internal_format(vert_format, 4);
vertex_array->set_internal_format();
#endif
}
vb_buffer_allocated = true; // mark the buffer allocated
@ -680,7 +678,7 @@ bool ZZCreate(int _width, int _height)
glGenBuffers(1, &vboRect);
glBindBuffer(GL_ARRAY_BUFFER, vboRect);
#ifdef GLSL4_API
vertex_array->set_internal_format(vert_format, 4);
vertex_array->set_internal_format();
#endif
vector<VertexGPU> verts(4);

View File

@ -137,8 +137,7 @@ struct GlobalUniform {
float linear[2*4];
};
void SettleFloat(uint indice, const float* v) {
assert(indice >= 0);
assert(indice + 3 < sizeof(linear));
assert(indice + 3 < 2*4);
linear[indice+0] = v[0];
linear[indice+1] = v[1];
linear[indice+2] = v[2];
@ -163,8 +162,7 @@ struct ConstantUniform {
float linear[8*4];
};
void SettleFloat(uint indice, const float* v) {
assert(indice >= 0);
assert(indice + 3 < sizeof(linear));
assert(indice + 3 < 8*4);
linear[indice+0] = v[0];
linear[indice+1] = v[1];
linear[indice+2] = v[2];
@ -191,8 +189,7 @@ struct FragmentUniform {
float linear[13*4];
};
void SettleFloat(uint indice, const float* v) {
assert(indice >= 0);
assert(indice + 3 < sizeof(linear));
assert(indice + 3 < 13*4);
linear[indice+0] = v[0];
linear[indice+1] = v[1];
linear[indice+2] = v[2];
@ -209,8 +206,7 @@ struct VertexUniform {
float linear[3*4];
};
void SettleFloat(uint indice, const float* v) {
assert(indice >= 0);
assert(indice + 3 < sizeof(linear) / 4);
assert(indice + 3 < 3*4);
linear[indice+0] = v[0];
linear[indice+1] = v[1];
linear[indice+2] = v[2];
@ -340,8 +336,7 @@ struct SamplerParam {
SamplerParam() : unit(-1), texid(0), target(0) {}
void set_unit(int new_unit = 0) {
assert(new_unit >= 0);
void set_unit(int new_unit) {
assert(new_unit < 10);
unit = new_unit;
target = g_texture_target[new_unit];
@ -359,6 +354,10 @@ struct SamplerParam {
void set_texture(GLuint new_texid) {
texid = new_texid;
}
void release_texture() {
texid = 0;
}
};
struct FRAGMENTSHADER
@ -393,7 +392,7 @@ struct FRAGMENTSHADER
//sBitwiseANDY = 4;
//sInterlace = 5;
//sCLUT = 6;
samplers[sMemory+0].set_unit(0);
samplers[sMemory].set_unit(0);
samplers[sMemory+1].set_unit(0); // Dual context. Use same unit
samplers[sFinal].set_unit(1);
samplers[sBitwiseANDX].set_unit(6);
@ -437,17 +436,26 @@ struct FRAGMENTSHADER
}
void enable_texture() {
samplers[0+context].enable_texture(); // sMemory is dual context
samplers[sMemory+context].enable_texture(); // sMemory is dual context
for (int i = 2; i < 7; i++)
samplers[i].enable_texture();
}
void set_texture(ZZshParameter param, GLuint texid) {
if (param == 0) // sMemory is dual context
samplers[0+context].set_texture(texid);
if (param == sMemory) // sMemory is dual context
samplers[sMemory+context].set_texture(texid);
else
samplers[param].set_texture(texid);
}
void release_prog() {
if(program) {
glDeleteProgram(program);
program = 0;
}
for (uint i = 0; i < 7 ; i++)
samplers[i].release_texture();
}
};
#endif

View File

@ -124,8 +124,8 @@ GSVertexBufferStateOGL *vertex_array;
COMMONSHADER g_cs;
static GLuint s_pipeline = 0;
FRAGMENTSHADER ppsDebug;
FRAGMENTSHADER ppsDebug2;
//FRAGMENTSHADER ppsDebug;
//FRAGMENTSHADER ppsDebug2;
//------------------ Code
@ -392,7 +392,7 @@ inline bool LoadShaderFromFile(ZZshProgram& program, const char* DefineString, c
return false;
}
ZZLog::Error_Log("Used shader for %s... Ok",name);
ZZLog::Error_Log("Compile shader for %s... Ok",name);
return true;
}
@ -422,25 +422,22 @@ void ZZshSetupShader() {
PutParametersAndRun(vs, ps);
}
static void ZZshSetShader(VERTEXSHADER* vs, FRAGMENTSHADER* ps) {
if (vs == NULL || ps == NULL) return;
FRAGMENTSHADER* debug = ps;
glUseProgramStages(s_pipeline, GL_VERTEX_SHADER_BIT, vs->program);
glUseProgramStages(s_pipeline, GL_FRAGMENT_SHADER_BIT, ps->program);
//PutParametersAndRun(vs, ps);
GL_REPORT_ERRORD();
}
void ZZshSetVertexShader(ZZshShaderLink prog) {
g_vsprog = prog;
ZZshSetShader((VERTEXSHADER*)(g_vsprog.link), (FRAGMENTSHADER*)(g_psprog.link)) ;
VERTEXSHADER* vs = (VERTEXSHADER*)g_vsprog.link;
if (!vs) return;
glUseProgramStages(s_pipeline, GL_VERTEX_SHADER_BIT, vs->program);
}
void ZZshSetPixelShader(ZZshShaderLink prog) {
g_psprog = prog;
ZZshSetShader((VERTEXSHADER*)(g_vsprog.link), (FRAGMENTSHADER*)(g_psprog.link)) ;
FRAGMENTSHADER* ps = (FRAGMENTSHADER*)g_psprog.link;
if (!ps) return;
glUseProgramStages(s_pipeline, GL_FRAGMENT_SHADER_BIT, ps->program);
}
//------------------------------------------------------------------------------------------------------------------
@ -482,14 +479,13 @@ void PutParametersInProgram(VERTEXSHADER* vs, FRAGMENTSHADER* ps) {
fragment_buffer->bind();
fragment_buffer->upload((void*)&ps->uniform_buffer[ps->context]);
g_cs.enable_texture();
#ifdef ENABLE_MARKER
char* debug = new char[100];
sprintf(debug, "FS(%d): enable texture", ps->program);
if (GLEW_GREMEDY_string_marker) glStringMarkerGREMEDY(0, debug);
#endif
g_cs.enable_texture();
ps->enable_texture();
}
@ -547,13 +543,8 @@ static __forceinline bool LOAD_PS(char* DefineString, const char* name, FRAGMENT
inline bool LoadEffects()
{
// clear the textures
for(u32 i = 0; i < ArraySize(ppsTexture); ++i) {
SAFE_RELEASE_PROG(ppsTexture[i].prog);
}
#ifndef _DEBUG
memset(ppsTexture, 0, sizeof(ppsTexture));
#endif
for(u32 i = 0; i < ArraySize(ppsTexture); ++i)
ppsTexture[i].release_prog();
return true;
}
@ -623,8 +614,8 @@ bool ZZshLoadExtraEffects() {
if (!LOAD_PS(DefineString, "Convert32to16PS", ppsConvert32to16, cgfProf, 0, "")) bLoadSuccess = false;
// DEBUG
if (!LOAD_PS(DefineString, "ZeroDebugPS", ppsDebug, cgfProf, 0, "")) bLoadSuccess = false;
if (!LOAD_PS(DefineString, "ZeroDebug2PS", ppsDebug2, cgfProf, 0, "")) bLoadSuccess = false;
// if (!LOAD_PS(DefineString, "ZeroDebugPS", ppsDebug, cgfProf, 0, "")) bLoadSuccess = false;
// if (!LOAD_PS(DefineString, "ZeroDebug2PS", ppsDebug2, cgfProf, 0, "")) bLoadSuccess = false;
GL_REPORT_ERRORD();
return true;
@ -656,7 +647,7 @@ static ZZshProgram LoadShaderFromType(int type, int texfilter, int texwrap, int
if (!LoadShaderFromFile(program, DefineString, name, GL_FRAGMENT_SHADER))
return LoadShaderFromFile(program, DefineString, name, GL_FRAGMENT_SHADER, true);
ZZLog::Debug_Log("Used shader for type:%d filter:%d wrap:%d for:%d depth:%d aem:%d color:%d decompression:%d ctx:%d... Ok \n", type, texfilter, texwrap, fog, writedepth, testaem, exactcolor, ps, context);
ZZLog::Debug_Log("Create new shader for type:%d filter:%d wrap:%d for:%d depth:%d aem:%d color:%d decompression:%d ctx:%d... Ok \n", type, texfilter, texwrap, fog, writedepth, testaem, exactcolor, ps, context);
GL_REPORT_ERRORD();
return program;
@ -699,6 +690,7 @@ FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testae
GL_REPORT_ERRORD();
if( glGetError() != GL_NO_ERROR ) {
ZZLog::Check_GL_Error();
ZZLog::Error_Log("Failed to load shader %d,%d,%d,%d.", type, fog, texfilter, 4*clamp.wms+clamp.wmt);
if (pbFailed != NULL ) *pbFailed = true;
return pf;

View File

@ -3,17 +3,17 @@
// ZZ Open GL graphics plugin
// Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com, gregory.hainaut@gmail.com
// Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
//
//
// 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 of the License, 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 this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
@ -89,14 +89,14 @@ struct vertex
// glSecondaryColorPointerEXT -> gl_SecondaryColor (it seems just a way to have another parameter in shader)
// glTexCoordPointer -> gl_MultiTexCoord0 (tex coord)
// glVertexPointer -> gl_Vertex (position)
//
//
// VS Output (to PS)
// gl_Position (must be kept)
// vertex
//
// FS input (from VS)
// vertex
//
//
// FS output
// gl_FragData[0]
// gl_FragData[1]
@ -110,7 +110,7 @@ out gl_PerVertex {
};
layout(location = 0) in ivec2 Vert;
layout(location = 1) in vec4 Color;
layout(location = 1) in vec4 Color;
layout(location = 2) in vec4 SecondaryColor;
layout(location = 3) in vec3 TexCoord;
@ -126,7 +126,6 @@ layout(location = 0) out vertex VSout;
layout(location = 0) in vertex PSin;
// NOTE: Basic s/gl_FragData[X]/FragDataX/ I think
// FIXME: host only do glDrawBuffers of 1 buffers not 2. I think this is a major bug
layout(location = 0) out vec4 FragData0;
layout(location = 1) out vec4 FragData1;
@ -603,6 +602,7 @@ half4 ps2FinalColor(half4 col)
half4 ps2FinalColor(half4 col)
{
return col * g_fOneColor.xxxy + g_fOneColor.zzzw;
//return vec4(1.0f,0.0f,1.0f, 0.8f);
}
#endif
@ -765,7 +765,7 @@ void CRTCTargInterPS() {
void CRTCTargPS() {
float4 c = BilinearFloat16(PSin.tex.xy);
// FIXME DEBUG: to validate tex coord on blit
//vec4 c = vec4(PSin.tex.x/512.0f, PSin.tex.y/512.0f, 0.0, 1.0);
//c = vec4(PSin.tex.x/512.0f, PSin.tex.y/512.0f, 0.0, 1.0);
c.w = g_fc0.w * c.w * g_fOneColor.x + g_fOneColor.y;
FragData0 = c;
}
@ -821,11 +821,12 @@ void ZeroPS() {
}
void ZeroDebugPS() {
FragData0 = vec4(0.0, 1.0, 0.0, 1.0);
FragData0 = vec4(0.0, 1.0, 0.0, 0.5);
//FragData0 = vec4(PSin.position.x, PSin.position.y, 1.0, 0.5);
}
void ZeroDebug2PS() {
FragData0 = vec4(1.0, 0.0, 0.0, 1.0);
FragData0 = vec4(1.0, 0.0, 0.0, 0.5);
}
void BaseTexturePS() {
@ -876,30 +877,37 @@ void Convert32to16PS() {
#ifdef VERTEX_SHADER
float4 OutPosition() {
float4 Position;
Position.xy = Vert.xy * g_fPosXY.xy + g_fPosXY.zw;
Position.z = (log(g_fc0.y + dot(g_fZ, SecondaryColor.zyxw)) * g_fZNorm.x + g_fZNorm.y) * g_fZMin.y + dot(g_fZ, SecondaryColor.zyxw) * g_fZMin.x ;
Position.w = g_fc0.y;
return Position;
float4 position;
position.xy = vec2(Vert.xy) * g_fPosXY.xy + g_fPosXY.zw;
position.z = (log(g_fc0.y + dot(g_fZ, SecondaryColor.zyxw)) * g_fZNorm.x + g_fZNorm.y) * g_fZMin.y + dot(g_fZ, SecondaryColor.zyxw) * g_fZMin.x ;
position.w = g_fc0.y;
return position;
}
// just smooth shadering
void RegularVS() {
gl_Position = OutPosition();
float4 position = OutPosition();
gl_Position = position;
VSout.color = Color;
DOZWRITE(VSout.z = SecondaryColor * g_fZBias.x + g_fZBias.y;)
DOZWRITE(VSout.z.w = g_fc0.y;)
}
// diffuse texture mapping
void TextureVS() {
gl_Position = OutPosition();
float4 position = OutPosition();
gl_Position = position;
VSout.color = Color;
#ifdef PERSPECTIVE_CORRECT_TEX
VSout.tex.xyz = TexCoord.xyz;
#else
VSout.tex.xy = TexCoord.xy/TexCoord.z;
#endif
DOZWRITE(VSout.z = SecondaryColor * g_fZBias.x + g_fZBias.y;)
DOZWRITE(VSout.z.w = g_fc0.y;)
}
@ -907,8 +915,11 @@ void TextureVS() {
void RegularFogVS() {
float4 position = OutPosition();
gl_Position = position;
VSout.color = Color;
VSout.fog = position.z * g_fBilinear.w;
DOZWRITE(VSout.z = SecondaryColor * g_fZBias.x + g_fZBias.y;)
DOZWRITE(VSout.z.w = g_fc0.y;)
}
@ -916,20 +927,24 @@ void RegularFogVS() {
void TextureFogVS() {
float4 position = OutPosition();
gl_Position = position;
VSout.color = Color;
#ifdef PERSPECTIVE_CORRECT_TEX
VSout.tex.xyz = TexCoord.xyz;
#else
VSout.tex.xy = TexCoord.xy/TexCoord.z;
#endif
VSout.fog = position.z * g_fBilinear.w;
DOZWRITE(VSout.z = SecondaryColor * g_fZBias.x + g_fZBias.y;)
DOZWRITE(VSout.z.w = g_fc0.y;)
}
void BitBltVS() {
vec4 position;
position.xy = Vert.xy * g_fBitBltPos.xy + g_fBitBltPos.zw;
position.xy = vec2(Vert.xy) * g_fBitBltPos.xy + g_fBitBltPos.zw;
position.zw = g_fc0.xy;
gl_Position = position;