bool GFXD3D9ShaderBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer) { PROFILE_SCOPE(GFXD3D9ShaderBufferLayout_setMatrix); if (pd.constType == GFXSCT_Float4x4) { // Special case, we can just blast this guy. AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!"); if (dMemcmp(basePointer+pd.offset, data, size) != 0) { dMemcpy(basePointer+pd.offset, data, size); return true; } return false; } else { PROFILE_SCOPE(GFXD3D9ShaderBufferLayout_setMatrix_not4x4); // Figure out how big of a chunk we are copying. We're going to copy 4 columns by N rows of data U32 csize; switch (pd.constType) { case GFXSCT_Float2x2 : csize = 32; break; case GFXSCT_Float3x3 : csize = 48; break; default: AssertFatal(false, "Unhandled case!"); return false; break; } // Loop through and copy bool ret = false; U8* currDestPointer = basePointer+pd.offset; const U8* currSourcePointer = static_cast<const U8*>(data); const U8* endData = currSourcePointer + size; while (currSourcePointer < endData) { if (dMemcmp(currDestPointer, currSourcePointer, csize) != 0) { dMemcpy(currDestPointer, currSourcePointer, csize); ret = true; } currDestPointer += csize; currSourcePointer += sizeof(MatrixF); } return ret; } }
void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer) { for(Vector<GFXGLShaderConstHandle*>::iterator i = mValidHandles.begin(); i != mValidHandles.end(); ++i) { GFXGLShaderConstHandle* handle = *i; AssertFatal(handle, "GFXGLShader::setConstantsFromBuffer - Null handle"); 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()); switch(handle->mDesc.constType) { case GFXSCT_Float: glUniform1fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Float2: glUniform2fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Float3: glUniform3fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Float4: glUniform4fv(handle->mLocation, handle->mDesc.arraySize, (GLfloat*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Int: case GFXSCT_Sampler: case GFXSCT_SamplerCube: glUniform1iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Int2: glUniform2iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Int3: glUniform3iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Int4: glUniform4iv(handle->mLocation, handle->mDesc.arraySize, (GLint*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Float2x2: glUniformMatrix2fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Float3x3: glUniformMatrix3fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset)); break; case GFXSCT_Float4x4: glUniformMatrix4fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset)); break; default: AssertFatal(0,""); break; } } }
bool GenericConstBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer) { PROFILE_SCOPE(GenericConstBufferLayout_setMatrix); // We're generic, so just copy the full MatrixF in AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!"); // Matrices are an annoying case because of the alignment issues. There are alignment issues in the matrix itself, and then potential inter matrices alignment issues. // So GL and DX will need to derive their own GenericConstBufferLayout classes and override this method to deal with that stuff. For GenericConstBuffer, copy the whole // 4x4 matrix regardless of the target case. if (dMemcmp(basePointer+pd.offset, data, size) != 0) { dMemcpy(basePointer+pd.offset, data, size); return true; } return false; }
bool GenericConstBufferLayout::set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer) { PROFILE_SCOPE(GenericConstBufferLayout_set); // Shader compilers like to optimize float4x4 uniforms into float3x3s. // So long as the real paramater is a matrix of-some-type and the data // passed in is a MatrixF ( which is will be ), we DO NOT have a // mismatched const type. AssertFatal( pd.constType == constType || ( ( pd.constType == GFXSCT_Float2x2 || pd.constType == GFXSCT_Float3x3 || pd.constType == GFXSCT_Float4x4 ) && ( constType == GFXSCT_Float2x2 || constType == GFXSCT_Float3x3 || constType == GFXSCT_Float4x4 ) ), "Mismatched const type!" ); // This "cute" bit of code allows us to support 2x3 and 3x3 matrices in shader constants but use our MatrixF class. Yes, a hack. -BTR switch (pd.constType) { case GFXSCT_Float2x2 : case GFXSCT_Float3x3 : case GFXSCT_Float4x4 : return setMatrix(pd, constType, size, data, basePointer); break; default : break; } AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!"); // Ok, we only set data if it's different than the data we already have, this maybe more expensive than just setting the data, but // we'll have to do some timings to see. For example, the lighting shader constants rarely change, but we can't assume that at the // renderInstMgr level, but we can check down here. -BTR if (dMemcmp(basePointer+pd.offset, data, size) != 0) { dMemcpy(basePointer+pd.offset, data, size); return true; } return false; }