⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 densematrixongpu.cpp

📁 PDE simulator on GPU.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -