DX and GL Geometry shaders added

Added the dx and gl geometry shader compile codes.
This commit is contained in:
marauder2k7 2024-03-06 13:51:50 +00:00
parent 808e2f4200
commit 4a6fbd5811
6 changed files with 312 additions and 239 deletions

View file

@ -39,12 +39,12 @@ class GFXGLShaderConstHandle : public GFXShaderConstHandle
{
friend class GFXGLShader;
public:
public:
GFXGLShaderConstHandle( GFXGLShader *shader );
GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum );
virtual ~GFXGLShaderConstHandle();
void reinit( const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum );
const String& getName() const { return mDesc.name; }
@ -52,7 +52,7 @@ public:
U32 getArraySize() const { return mDesc.arraySize; }
U32 getSize() const;
void setValid( bool valid ) { mValid = valid; }
void setValid( bool valid ) { mValid = valid; }
/// @warning This will always return the value assigned when the shader was
/// initialized. If the value is later changed this method won't reflect that.
S32 getSamplerRegister() const { return mSamplerNum; }
@ -62,7 +62,7 @@ public:
U32 mOffset;
U32 mSize;
GLuint mLocation;
S32 mSamplerNum;
S32 mSamplerNum;
bool mInstancingConstant;
};
@ -75,7 +75,7 @@ GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader )
static U32 shaderConstTypeSize(GFXShaderConstType type)
{
switch(type)
switch(type)
{
case GFXSCT_Float:
case GFXSCT_Int:
@ -107,7 +107,7 @@ static U32 shaderConstTypeSize(GFXShaderConstType type)
}
}
GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum )
GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum )
: mShader(shader), mInstancingConstant(false)
{
reinit(desc, loc, samplerNum);
@ -120,7 +120,7 @@ void GFXGLShaderConstHandle::reinit( const GFXShaderConstDesc& desc, GLuint loc,
mSamplerNum = samplerNum;
mOffset = 0;
mInstancingConstant = false;
U32 elemSize = shaderConstTypeSize(mDesc.constType);
AssertFatal(elemSize, "GFXGLShaderConst::GFXGLShaderConst - elemSize is 0");
mSize = mDesc.arraySize * elemSize;
@ -169,7 +169,7 @@ void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const Con
AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
U8 *buf = mBuffer + _glHandle->mOffset;
if(_glHandle->mInstancingConstant)
if(_glHandle->mInstancingConstant)
buf = mInstPtr + _glHandle->mOffset;
dMemcpy(buf, &param, sizeof(ConstType));
@ -204,7 +204,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const LinearColor
{
internalSet(handle, fv);
}
void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 fv)
{
internalSet(handle, fv);
@ -258,7 +258,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArra
internalSet(handle, fv);
}
void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv)
void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv)
{
internalSet(handle, fv);
}
@ -292,7 +292,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& ma
GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
AssertFatal(!_glHandle->mInstancingConstant || matType == GFXSCT_Float4x4, "GFXGLShaderConstBuffer::set - Only support GFXSCT_Float4x4 for instancing");
switch(matType)
{
case GFXSCT_Float2x2:
@ -316,15 +316,15 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& ma
dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, (sizeof(F32) * 12));// matrix with end row chopped off
break;
case GFXSCT_Float4x4:
{
{
if(_glHandle->mInstancingConstant)
{
MatrixF transposed;
MatrixF transposed;
mat.transposeTo(transposed);
dMemcpy( mInstPtr + _glHandle->mOffset, (const F32*)transposed, sizeof(MatrixF) );
return;
}
dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, sizeof(MatrixF));
break;
}
@ -340,7 +340,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* ma
AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" );
GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
AssertFatal(!_glHandle->mInstancingConstant, "GFXGLShaderConstBuffer::set - Instancing not supported for matrix arrays");
switch (matrixType) {
@ -385,6 +385,7 @@ void GFXGLShaderConstBuffer::onShaderReload( GFXGLShader *shader )
GFXGLShader::GFXGLShader(GFXGLDevice* device) :
mVertexShader(0),
mPixelShader(0),
mGeometryShader(0),
mProgram(0),
mDevice(device),
mConstBufferSize(0),
@ -397,7 +398,7 @@ GFXGLShader::~GFXGLShader()
clearShaders();
for(HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++)
delete i->value;
delete[] mConstBuffer;
}
@ -406,10 +407,12 @@ void GFXGLShader::clearShaders()
glDeleteProgram(mProgram);
glDeleteShader(mVertexShader);
glDeleteShader(mPixelShader);
glDeleteShader(mGeometryShader);
mProgram = 0;
mVertexShader = 0;
mPixelShader = 0;
mGeometryShader = 0;
}
bool GFXGLShader::_init()
@ -422,44 +425,57 @@ bool GFXGLShader::_init()
clearShaders();
mProgram = glCreateProgram();
// Set the macros and add the global ones.
Vector<GFXShaderMacro> macros;
macros.merge( mMacros );
macros.merge( smGlobalMacros );
macros.increment();
macros.last().name = "TORQUE_SM";
macros.last().value = 40;
macros.increment();
macros.last().name = "TORQUE_VERTEX_SHADER";
macros.last().value = "";
// Default to true so we're "successful" if a vertex/pixel shader wasn't specified.
bool compiledVertexShader = true;
bool compiledPixelShader = true;
// Compile the vertex and pixel shaders if specified.
if(!mVertexFile.isEmpty())
compiledVertexShader = initShader(mVertexFile, true, macros);
bool compiledGeometryShader = true;
// Compile the vertex and pixel shaders if specified.
if (!mVertexFile.isEmpty())
{
compiledVertexShader = initShader(mVertexFile, GFXShaderStage::VERTEX_SHADER, macros);
if (!compiledVertexShader)
return false;
}
if (!mPixelFile.isEmpty())
{
macros.last().name = "TORQUE_PIXEL_SHADER";
compiledPixelShader = initShader(mPixelFile, GFXShaderStage::PIXEL_SHADER, macros);
if (!compiledPixelShader)
return false;
}
if (!mGeometryFile.isEmpty())
{
macros.last().name = "TORQUE_GEOMETRY_SHADER";
compiledGeometryShader = initShader(mPixelFile, GFXShaderStage::GEOMETRY_SHADER, macros);
if (!compiledGeometryShader)
return false;
}
macros.last().name = "TORQUE_PIXEL_SHADER";
if(!mPixelFile.isEmpty())
compiledPixelShader = initShader(mPixelFile, false, macros);
// If either shader was present and failed to compile, bail.
if(!compiledVertexShader || !compiledPixelShader)
return false;
// Link it!
glLinkProgram( mProgram );
GLint activeAttribs = 0;
glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs );
GLint maxLength;
glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
FrameTemp<GLchar> tempData(maxLength+1);
*tempData.address() = '\0';
// Check atributes
@ -467,11 +483,11 @@ bool GFXGLShader::_init()
{
GLint size;
GLenum type;
glGetActiveAttrib(mProgram, i, maxLength + 1, NULL, &size, &type, tempData.address());
StringTableEntry argName = StringTable->insert(tempData.address());
CHECK_AARG(Torque::GL_VertexAttrib_Position, vPosition);
CHECK_AARG(Torque::GL_VertexAttrib_Normal, vNormal);
CHECK_AARG(Torque::GL_VertexAttrib_Color, vColor);
@ -502,13 +518,13 @@ bool GFXGLShader::_init()
glBindFragDataLocation(mProgram, i, buffer);
}
// Link it again!
glLinkProgram( mProgram );
GLint linkStatus;
glGetProgramiv( mProgram, GL_LINK_STATUS, &linkStatus );
// Dump the info log to the console
U32 logLength = 0;
glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, (GLint*)&logLength);
@ -517,7 +533,7 @@ bool GFXGLShader::_init()
FrameAllocatorMarker fam;
char* log = (char*)fam.alloc( logLength );
glGetProgramInfoLog( mProgram, logLength, NULL, log );
if ( linkStatus == GL_FALSE )
{
if ( smLogErrors )
@ -539,16 +555,16 @@ bool GFXGLShader::_init()
if ( linkStatus == GL_FALSE )
return false;
initConstantDescs();
initConstantDescs();
initHandles();
// Notify Buffers we might have changed in size.
// If this was our first init then we won't have any activeBuffers
// Notify Buffers we might have changed in size.
// If this was our first init then we won't have any activeBuffers
// to worry about unnecessarily calling.
Vector<GFXShaderConstBuffer*>::iterator biter = mActiveBuffers.begin();
for ( ; biter != mActiveBuffers.end(); biter++ )
for ( ; biter != mActiveBuffers.end(); biter++ )
((GFXGLShaderConstBuffer*)(*biter))->onShaderReload( this );
return true;
}
@ -565,23 +581,23 @@ void GFXGLShader::initConstantDescs()
maxNameLength++;
FrameTemp<GLchar> uniformName(maxNameLength);
for(U32 i = 0; i < numUniforms; i++)
{
GLint size;
GLenum type;
glGetActiveUniform(mProgram, i, maxNameLength, NULL, &size, &type, uniformName);
GFXShaderConstDesc desc;
desc.name = String((char*)uniformName);
// Remove array brackets from the name
desc.name = desc.name.substr(0, desc.name.find('['));
// Insert $ to match D3D behavior of having a $ prepended to parameters to main.
desc.name.insert(0, '$');
desc.arraySize = size;
switch(type)
{
case GL_FLOAT:
@ -641,24 +657,24 @@ void GFXGLShader::initConstantDescs()
// If we don't recognize the constant don't add its description.
continue;
}
mConstants.push_back(desc);
}
}
void GFXGLShader::initHandles()
{
{
// Mark all existing handles as invalid.
// Those that are found when parsing the descriptions will then be marked valid again.
for ( HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter )
(iter->value)->setValid( false );
for ( HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter )
(iter->value)->setValid( false );
mValidHandles.clear();
// Loop through all ConstantDescriptions,
// Loop through all ConstantDescriptions,
// if they aren't in the HandleMap add them, if they are reinitialize them.
for ( U32 i = 0; i < mConstants.size(); i++ )
{
GFXShaderConstDesc &desc = mConstants[i];
GFXShaderConstDesc &desc = mConstants[i];
// Index element 1 of the name to skip the '$' we inserted earier.
GLint loc = glGetUniformLocation(mProgram, &desc.name.c_str()[1]);
@ -678,11 +694,11 @@ void GFXGLShader::initHandles()
}
if ( handle != mHandles.end() )
{
handle->value->reinit( desc, loc, sampler );
}
else
handle->value->reinit( desc, loc, sampler );
}
else
{
mHandles[desc.name] = new GFXGLShaderConstHandle( this, desc, loc, sampler );
mHandles[desc.name] = new GFXGLShaderConstHandle( this, desc, loc, sampler );
}
}
@ -703,10 +719,10 @@ void GFXGLShader::initHandles()
mConstBufferSize += handle->getSize();
}
}
mConstBuffer = new U8[mConstBufferSize];
dMemset(mConstBuffer, 0, mConstBufferSize);
// Set our program so uniforms are assigned properly.
mDevice->setShader(this, false);
@ -736,15 +752,15 @@ void GFXGLShader::initHandles()
for ( U32 i=0; i < mInstancingFormat->getElementCount(); i++ )
{
const GFXVertexElement &element = mInstancingFormat->getElement( i );
String constName = String::ToString( "$%s", element.getSemantic().c_str() );
HandleMap::Iterator handle = mHandles.find(constName);
HandleMap::Iterator handle = mHandles.find(constName);
if ( handle != mHandles.end() )
{
{
AssertFatal(0, "");
}
else
}
else
{
GFXShaderConstDesc desc;
desc.name = constName;
@ -759,7 +775,7 @@ void GFXGLShader::initHandles()
desc.constType = GFXSCT_Float;
break;
}
GFXGLShaderConstHandle *h = new GFXGLShaderConstHandle( this, desc, -1, -1 );
h->mInstancingConstant = true;
h->mOffset = offset;
@ -801,7 +817,7 @@ GFXShaderConstHandle* GFXGLShader::getShaderConstHandle(const String& name)
GFXGLShaderConstHandle* handle = new GFXGLShaderConstHandle( this );
handle->setValid(false);
mHandles[ name ] = handle;
return handle;
}
}
@ -826,11 +842,11 @@ void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer)
if(handle->mInstancingConstant)
continue;
// Don't set if the value has not be changed.
if(dMemcmp(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()) == 0)
continue;
// Copy new value into our const buffer and set in GL.
dMemcpy(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize());
@ -872,7 +888,7 @@ void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer)
break;
case GFXSCT_Float4x3:
// NOTE: To save a transpose here we could store the matrix transposed (i.e. column major) in the constant buffer.
// See _mesa_uniform_matrix in the mesa source for the correct transpose algorithm for a 4x3 matrix.
// See _mesa_uniform_matrix in the mesa source for the correct transpose algorithm for a 4x3 matrix.
glUniformMatrix4x3fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
break;
case GFXSCT_Float4x4:
@ -919,7 +935,7 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s )
//dStrncpy( buffer, linePragma.c_str(), linePragmaLen );
s->read(shaderLen, buffer);
buffer[shaderLen] = 0;
char* p = dStrstr(buffer, "#include");
while(p)
{
@ -944,12 +960,12 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s )
// First try it as a local file.
Torque::Path includePath = Torque::Path::Join(path.getPath(), '/', includeFile);
includePath = Torque::Path::CompressPath(includePath);
FileStream includeStream;
if ( !includeStream.open( includePath, Torque::FS::File::Read ) )
{
// Try again assuming the path is absolute
// Try again assuming the path is absolute
// and/or relative.
includePath = String( includeFile );
includePath = Torque::Path::CompressPath(includePath);
@ -958,7 +974,7 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s )
AssertISV(false, avar("failed to open include '%s'.", includePath.getFullPath().c_str()));
if ( smLogErrors )
Con::errorf( "GFXGLShader::_handleIncludes - Failed to open include '%s'.",
Con::errorf( "GFXGLShader::_handleIncludes - Failed to open include '%s'.",
includePath.getFullPath().c_str() );
// Fail... don't return the buffer.
@ -968,17 +984,17 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s )
}
char* includedText = _handleIncludes(includePath, &includeStream);
// If a sub-include fails... cleanup and return.
if ( !includedText )
{
dFree(buffer);
return NULL;
}
// TODO: Disabled till this is fixed correctly.
//
// Count the number of lines in the file
// Count the number of lines in the file
// before the include.
/*
U32 includeLine = 0;
@ -1002,7 +1018,7 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s )
// Add a new line pragma to restore the proper
// file and line number after the include.
//sItx += String::ToString( "\r\n#line %d \r\n", includeLine );
dFree(includedText);
manip.insert(q-buffer, sItx);
char* manipBuf = dStrdup(manip.c_str());
@ -1012,18 +1028,18 @@ char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s )
}
p = dStrstr(p, "#include");
}
return buffer;
}
bool GFXGLShader::_loadShaderFromStream( GLuint shader,
const Torque::Path &path,
FileStream *s,
bool GFXGLShader::_loadShaderFromStream( GLuint shader,
const Torque::Path &path,
FileStream *s,
const Vector<GFXShaderMacro> &macros )
{
Vector<char*> buffers;
Vector<U32> lengths;
// The GLSL version declaration must go first!
const char *versionDecl = "#version 330\n";
buffers.push_back( dStrdup( versionDecl ) );
@ -1052,16 +1068,16 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader,
buffers.push_back( dStrdup( define.c_str() ) );
lengths.push_back( define.length() );
}
// Now finally add the shader source.
U32 shaderLen = s->getStreamSize();
char *buffer = _handleIncludes(path, s);
if ( !buffer )
return false;
buffers.push_back(buffer);
lengths.push_back(shaderLen);
glShaderSource(shader, buffers.size(), (const GLchar**)const_cast<const char**>(buffers.address()), NULL);
#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
@ -1084,19 +1100,40 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader,
return true;
}
bool GFXGLShader::initShader( const Torque::Path &file,
bool isVertex,
bool GFXGLShader::initShader( const Torque::Path &file,
GFXShaderStage stage,
const Vector<GFXShaderMacro> &macros )
{
PROFILE_SCOPE(GFXGLShader_CompileShader);
GLuint activeShader = glCreateShader(isVertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER);
if(isVertex)
GLuint activeShader;
switch (stage)
{
case VERTEX_SHADER:
activeShader = glCreateShader(GL_VERTEX_SHADER);
mVertexShader = activeShader;
else
break;
case PIXEL_SHADER:
activeShader = glCreateShader(GL_FRAGMENT_SHADER);
mPixelShader = activeShader;
break;
case GEOMETRY_SHADER:
activeShader = glCreateShader(GL_GEOMETRY_SHADER);
mGeometryShader = activeShader;
break;
case DOMAIN_SHADER:
break;
case HULL_SHADER:
break;
case COMPUTE_SHADER:
break;
default:
break;
}
glAttachShader(mProgram, activeShader);
// Ok it's not in the shader gen manager, so ask Torque for it
FileStream stream;
if ( !stream.open( file, Torque::FS::File::Read ) )
@ -1104,12 +1141,12 @@ bool GFXGLShader::initShader( const Torque::Path &file,
AssertISV(false, avar("GFXGLShader::initShader - failed to open shader '%s'.", file.getFullPath().c_str()));
if ( smLogErrors )
Con::errorf( "GFXGLShader::initShader - Failed to open shader file '%s'.",
Con::errorf( "GFXGLShader::initShader - Failed to open shader file '%s'.",
file.getFullPath().c_str() );
return false;
}
if (!_loadShaderFromStream(activeShader, file, &stream, macros))
{
if (smLogErrors)
@ -1122,7 +1159,7 @@ bool GFXGLShader::initShader( const Torque::Path &file,
// Dump the info log to the console
U32 logLength = 0;
glGetShaderiv(activeShader, GL_INFO_LOG_LENGTH, (GLint*)&logLength);
if ( logLength )
{
FrameAllocatorMarker fam;
@ -1164,6 +1201,6 @@ const String GFXGLShader::describeSelf() const
ret = String::ToString(" Program: %i", mProgram);
ret += String::ToString(" Vertex Path: %s", mVertexFile.getFullPath().c_str());
ret += String::ToString(" Pixel Path: %s", mPixelFile.getFullPath().c_str());
return ret;
}