📄 densematrixongpu.cpp
字号:
// DenseMatrixOnGPU.cpp: implementation of the DenseMatrixOnGPU class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "shadow.h"
#include "DenseMatrixOnGPU.h"
#include <math.h>
#include "CommonHW.h"
#include "InitOpenGL.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
///////////////////////////////////////////////////////////////////////////////////////
/// Class: CDenseMatrixOnGPU
///////////////////////////////////////////////////////////////////////////////////////
CDenseMatrixOnGPU::CDenseMatrixOnGPU()
{
_iTexID = NULL;
_iWholeTexID = 0;
_bInitialized = false;
MaxTexNum = 0;
LeftNum = 0;
_bFloat = g_Float;
_iChannelsNum = g_ChannelsNum;
}
CDenseMatrixOnGPU::~CDenseMatrixOnGPU()
{
glDeleteTextures(1, &_iWholeTexID);
//////Release the memory on CPU
if(_iTexID != NULL)
{
glDeleteTextures(MaxTexNum, _iTexID);
//delete[] _iTexID;
//_iTexID = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////////////////
/// Arrange the matrix M into N 2D textures in diagonal way
/// M[DimSize][DimSize] ----->
/// Matrix is square
////////////////////////////////////////////////////////////////////////////////////////////
void CDenseMatrixOnGPU::SetData(float *M, int DimSize)
{
int i,j,k;
//// M has N*N elements, here Total Elements Number = _iDim*_iDim
_iDim = DimSize;
GLuint iInternalFormat;
GLuint iFormat;
////Organize all elements into _iDim diagonal entries.
////And then generate _iDim Textures(_iHeight*_iWidth)
////----->fInputMatrix[_iDim][_iHeight*_iWidth]
float **fInputMatrix = NULL;
if( _iChannelsNum == 1)
{
//// Determine the format of texture according to specifications
if(_bFloat == true )
{
iInternalFormat = GL_FLOAT_R32_NV;
iFormat = GL_RED;
}
else
{
iInternalFormat = GL_LUMINANCE;
iFormat = GL_RED;
}
//// Previous Method: Texture resolution = res*res (NOTE: square)
//// Last Modified Date: 2003/10/23
//// ------To get appropriate Texture Size to reduce reduction
//// Texture size = Height*Width
CalOptTexRSize(_iDim, _iHeight, _iWidth);
fInputMatrix = new float*[_iDim];
for(i=0; i<_iDim; i++)
{
fInputMatrix[i] = new float[_iHeight * _iWidth];
memset(fInputMatrix[i], 0, sizeof(float)* _iHeight * _iWidth);
}
if(fInputMatrix == NULL)
{
AfxMessageBox("Error to allocate memory in CDenseMatrixOnGPU::SetData!");
return ;
}
if(M != NULL)
{
/////Fill the textures with accordingly matrix elements which arranged in diagonal
for(i=0; i<_iDim; i++)
{
for(j=0; j<_iDim; j++)
{
////////Transfer the Matrix into a set of Diagonal vectors
k = j*_iDim + (i+j)%_iDim;
fInputMatrix[i][j] = M[k];
}
}
}
}
else///// 4 Channels
{
if(_bFloat == true )
{
iInternalFormat = GL_FLOAT_RGBA32_NV;
iFormat = GL_RGBA;
}
else
{
iInternalFormat = GL_RGBA8;
iFormat = GL_RGBA;
}
CalOptTexRGBASize(_iDim, _iHeight, _iWidth);
fInputMatrix = new float*[_iDim];
for(i=0; i<_iDim; i++)
{
fInputMatrix[i] = new float[_iHeight * _iWidth * 4];
memset(fInputMatrix[i], 0, sizeof(float)* _iHeight * _iWidth * 4);
}
if(fInputMatrix == NULL)
{
AfxMessageBox("Error to allocate memory in CDenseMatrixOnGPU::SetData!");
return ;
}
if( M != NULL)
{
/////Fill the textures with accordingly matrix elements which arranged in diagonal
for(i=0; i<_iDim; i++)
{
for(j=0; j<_iDim; j++)
{
////////Transfer the Matrix into a set of Diagonal vectors
k = j*_iDim + (i+j)%_iDim;
fInputMatrix[i][j] = M[k];
}
}
}
}
/*
if(IsPowerOfTwo(_iWidth) && IsPowerOfTwo(_iHeight) && _bFloat == false)
{
_iTextureTarget = GL_TEXTURE_2D;
}
else
_iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
*/
_iTextureTarget = g_TextureTarget;
////Generate Textures IDs
if(_iTexID != NULL)
{
delete[] _iTexID;
_iTexID = NULL;
}
MaxTexNum = _iDim;
_iTexID = new unsigned int[MaxTexNum];
if(_iTexID == NULL)
{
AfxMessageBox("Error to allocate memory in CDenseMatrixOnGPU::SetData!");
return;
}
glGenTextures(MaxTexNum, _iTexID);
for(i=0; i<MaxTexNum; i++)
{
glBindTexture(_iTextureTarget, _iTexID[i]);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameterf(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(_iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight, 0, iFormat, GL_FLOAT, fInputMatrix[i] );
}
for(i=0; i<MaxTexNum; i++)
{
delete[] fInputMatrix[i];
fInputMatrix[i] = NULL;
}
delete[] fInputMatrix;
fInputMatrix = NULL;
_bInitialized = true;
return;
}
////////////////////////////////////////////////////////////////////////////////////////////
/// Arrange the matrix M into ONLY one 2D texture for Matrix Multiplication operation
/// ONE Channel
/// M[_iHeight][_iWidth] -----> M[m][n]
/// M --------------> 0 1 2 3
/// 4 5 6 7
/// FOUR channels
/// M --------------> 0 1 2 3 -----> into 4 blocks
/// 4 5 6 7 Ar Bg
/// 8 9 10 11 Cb Da
/// 12 13 14 15
/// NOTE: try this matrix into 4 blocks, then use RGBA 4 components to store it
/// SO: this matrix's size must be EVEN
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
void CDenseMatrixOnGPU::SetData(float *M, int m, int n)
{
int i,j,k;
GLuint iInternalFormat;
GLuint iFormat;
float *fInputMatrix = NULL;
if( _iChannelsNum == 1)
{
//// Determine the format of texture according to specifications
if(_bFloat == true )
{
iInternalFormat = GL_FLOAT_R32_NV;
iFormat = GL_RED;
}
else
{
iInternalFormat = GL_LUMINANCE;
iFormat = GL_RED;
}
//// M has m*n elements, so the texture is Height*Width;
_iHeight = m;
_iWidth = n;
//// Here just use ONE component (RED)
if(M != NULL)
{
fInputMatrix = new float[_iWidth*_iHeight];
if(fInputMatrix == NULL)
{
AfxMessageBox("Error to allocate memory in CDenseMatrixOnGPU::SetData!");
return;
}
/////Fill the textures with accordingly matrix elements
for(i=0; i<_iHeight; i++)
{
for(j=0; j<_iWidth; j++)
{
////
fInputMatrix[i*_iWidth + j] = M[i*_iWidth + j];
}
}
}
}
else////4 channels
{
if(_bFloat == true )
{
iInternalFormat = GL_FLOAT_RGBA32_NV;
iFormat = GL_RGBA;
}
else
{
iInternalFormat = GL_RGBA8;
iFormat = GL_RGBA;
}
/// Determine m and n are or not EVEN
if(m != n)
{
AfxMessageBox("This matrix must be squre in SetData for Matrix Multiplication operation!");
return;
}
if(m%2 != 0)
{
AfxMessageBox("To such size of Matrix, this program can not organize it into 4 channels!");
return;
}
//// M has m*n elements, so the texture is Height*Width;
_iHeight = m/2;
_iWidth = n/2;
//// use 4 component (RGBA)
if(M != NULL)
{
fInputMatrix = new float[_iWidth * _iHeight * 4];
if(fInputMatrix == NULL)
{
AfxMessageBox("Error to allocate memory in CDenseMatrixOnGPU::SetData!");
return;
}
/////Fill the textures with accordingly matrix elements
k = 0;
for(i=0; i<_iHeight; i++)
{
for(j=0; j<_iWidth; j++)
{
//// R
fInputMatrix[(i*_iWidth + j)*4] = M[i*n + j];
//// G
fInputMatrix[(i*_iWidth + j)*4+1] = M[i*n + j + _iWidth];
//// B
fInputMatrix[(i*_iWidth + j)*4+2] = M[(i+_iHeight)*n + j];
//// A
fInputMatrix[(i*_iWidth + j)*4+3] = M[(i+_iHeight)*n + j + _iWidth];
}
}
}
}
/*
if(IsPowerOfTwo(_iWidth) && IsPowerOfTwo(_iHeight) && _bFloat == false)
{
_iTextureTarget = GL_TEXTURE_2D;
}
else
_iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
*/
_iTextureTarget = g_TextureTarget;
////Generate Textures ID
glGenTextures(1, &_iWholeTexID);
glBindTexture(_iTextureTarget, _iWholeTexID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
////Keep the original data in array
glTexParameterf(_iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(_iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(_iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(_iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D( _iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight, 0, iFormat, GL_FLOAT, fInputMatrix);
delete[] fInputMatrix;
fInputMatrix = NULL;
_bInitialized = true;
return;
}
///////////////////////////////////////////////////////////////////////////////////////
/// Retrieve the data from the texture
/// FOR matrix * vector
/// NOTE: all values are clamped to [0,1] if not FLOAT supported
/// ONE channel or FOUR channels in diagonal mode
////////////////////////////////////////////////////////////////////////////////////////////
float* CDenseMatrixOnGPU::GetData(int &DimSize)
{
int i,k,l;
DimSize = _iDim;
float *fOutputMatrix = NULL;
fOutputMatrix = new float[DimSize*DimSize];
if(fOutputMatrix == NULL)
{
AfxMessageBox("Error to allocate memory in CDenseMatrixOnGPU::GetData!");
return NULL;
}
memset(fOutputMatrix, 0, sizeof(float) * DimSize * DimSize);
float *fOutputTex = NULL;
if( _iChannelsNum == 1)
{
fOutputTex = new float[_iHeight * _iWidth];
if(fOutputTex == NULL)
{
AfxMessageBox("Error to allocate memory in CDenseMatrixOnGPU::GetData!");
return NULL;
}
memset(fOutputTex, 0, sizeof(float) * _iHeight * _iWidth);
for(l=0; l<MaxTexNum; l++)
{
glBindTexture(_iTextureTarget, _iTexID[l]);
glGetTexImage(_iTextureTarget, 0, GL_RED, GL_FLOAT, fOutputTex);
/////Here re-arrange so many textures into A Correct Matrix
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -