port from perforce
This commit is contained in:
328
aiwaz/Aiwaz/Resources/Texture/Texture.cpp
Normal file
328
aiwaz/Aiwaz/Resources/Texture/Texture.cpp
Normal file
@@ -0,0 +1,328 @@
|
||||
#include "stdafx.h"
|
||||
#include "IEngine.h"
|
||||
#include "IResourceFactory.h"
|
||||
#include "Texture.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
Texture::Texture(IEngine& argEngine)
|
||||
: ShaderParameterCollection(argEngine, 3)
|
||||
, m_ShaderResourceView(NULL)
|
||||
, m_TextureResource(NULL)
|
||||
, m_TextureBuffer(NULL)
|
||||
, m_Texture(NULL)
|
||||
, m_TextureWidth(0)
|
||||
, m_TextureHeight(0)
|
||||
, m_TextureFormat(DataFormat::Unknown)
|
||||
, m_LockedTexture(false)
|
||||
, m_LockedArrayElement(0)
|
||||
, m_TextureBindingName("Diffuse")
|
||||
, m_TextureArraySize(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
this->Uninitialize();
|
||||
m_Engine.get_ResourceFactory().DeleteTexture(*const_cast<Texture*>(this), true);
|
||||
}
|
||||
|
||||
|
||||
void Texture::Uninitialize()
|
||||
{
|
||||
m_FileName = L"";
|
||||
m_LockedTexture = false;
|
||||
m_TextureWidth = 0;
|
||||
m_TextureHeight = 0;
|
||||
m_TextureArraySize = 0;
|
||||
m_TextureFormat = DataFormat::Unknown;
|
||||
|
||||
if (m_ShaderResourceView != NULL)
|
||||
m_ShaderResourceView->Release();
|
||||
m_ShaderResourceView = NULL;
|
||||
|
||||
if (m_Texture != NULL)
|
||||
m_Texture->Release();
|
||||
m_Texture = NULL;
|
||||
m_TextureResource = NULL;
|
||||
|
||||
if (m_TextureBuffer != NULL)
|
||||
m_TextureBuffer->Release();
|
||||
m_TextureBuffer = NULL;
|
||||
}
|
||||
|
||||
|
||||
void Texture::set_BindingName(const string8& argName)
|
||||
{
|
||||
if (!m_TextureBindingName.empty())
|
||||
this->RemoveParameter(m_TextureBindingName);
|
||||
|
||||
m_TextureBindingName = argName;
|
||||
|
||||
if (m_ShaderResourceView == NULL)
|
||||
return;
|
||||
|
||||
if (!m_TextureBindingName.empty() && m_ShaderResourceView != NULL)
|
||||
this->SetParameter(argName, *const_cast<Texture*>(this));
|
||||
}
|
||||
|
||||
void Texture::LoadFromFile(const string16& argFileName, DataAccessType::Enumeration argAccessType)
|
||||
{
|
||||
this->Uninitialize();
|
||||
|
||||
D3DX10_IMAGE_LOAD_INFO loadInfo;
|
||||
loadInfo.Width = D3DX10_DEFAULT;
|
||||
loadInfo.Height = D3DX10_DEFAULT;
|
||||
loadInfo.Depth = D3DX10_DEFAULT;
|
||||
loadInfo.FirstMipLevel = D3DX10_DEFAULT;
|
||||
loadInfo.MipLevels = D3DX10_DEFAULT;
|
||||
loadInfo.BindFlags = D3DX10_DEFAULT;
|
||||
loadInfo.MiscFlags = D3DX10_DEFAULT;
|
||||
loadInfo.Format = DXGI_FORMAT(D3DX10_DEFAULT);
|
||||
loadInfo.Filter = D3DX10_DEFAULT;
|
||||
loadInfo.MipFilter = D3DX10_DEFAULT;
|
||||
loadInfo.pSrcInfo = NULL;
|
||||
|
||||
if (argAccessType == DataAccessType::Static)
|
||||
{
|
||||
loadInfo.Usage = D3D10_USAGE(D3DX10_DEFAULT);
|
||||
loadInfo.CpuAccessFlags = D3DX10_DEFAULT;
|
||||
}
|
||||
else if (argAccessType == DataAccessType::CpuReadOnly)
|
||||
{
|
||||
loadInfo.BindFlags = 0;
|
||||
loadInfo.Usage = D3D10_USAGE_STAGING;
|
||||
loadInfo.CpuAccessFlags = D3D10_CPU_ACCESS_WRITE | D3D10_CPU_ACCESS_READ;
|
||||
}
|
||||
else if (argAccessType == DataAccessType::Dynamic)
|
||||
{
|
||||
loadInfo.Usage = D3D10_USAGE_DYNAMIC;
|
||||
loadInfo.CpuAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
}
|
||||
|
||||
IFile* textureFile = m_Engine.get_FileSystem().Open(argFileName);
|
||||
if (textureFile == NULL)
|
||||
throw L"Unable to open texture file.";
|
||||
|
||||
|
||||
ID3D10Device& device = m_Engine.get_DX10Device();
|
||||
if (S_OK != ::D3DX10CreateTextureFromMemory(&device,
|
||||
textureFile->get_Buffer(),
|
||||
textureFile->get_BufferLength(),
|
||||
&loadInfo,
|
||||
NULL,
|
||||
&m_TextureResource,
|
||||
NULL
|
||||
))
|
||||
{
|
||||
this->Uninitialize();
|
||||
throw L"Texture: Unable to load texture.";
|
||||
}
|
||||
|
||||
D3DX10_IMAGE_INFO loadedImageInfo;
|
||||
D3DX10GetImageInfoFromMemory(textureFile->get_Buffer(), textureFile->get_BufferLength(), NULL, &loadedImageInfo, NULL);
|
||||
|
||||
delete textureFile;
|
||||
|
||||
if (argAccessType != DataAccessType::CpuReadOnly)
|
||||
{
|
||||
D3D10_SHADER_RESOURCE_VIEW_DESC texViewDesc;
|
||||
ZeroMemory(&texViewDesc, sizeof(texViewDesc));
|
||||
texViewDesc.Format = loadedImageInfo.Format;
|
||||
texViewDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
|
||||
texViewDesc.Texture2DArray.MostDetailedMip = 0;
|
||||
texViewDesc.Texture2DArray.MipLevels = loadedImageInfo.MipLevels;
|
||||
|
||||
if (S_OK != device.CreateShaderResourceView(m_TextureResource, &texViewDesc, &m_ShaderResourceView))
|
||||
{
|
||||
this->Uninitialize();
|
||||
throw L"Texture: Unable to create resource view.";
|
||||
}
|
||||
}
|
||||
|
||||
m_Texture = (ID3D10Texture2D*)m_TextureResource;
|
||||
m_FileName = argFileName;
|
||||
m_TextureWidth = loadedImageInfo.Width;
|
||||
m_TextureHeight = loadedImageInfo.Height;
|
||||
m_TextureFormat = (DataFormat::Enumeration)loadedImageInfo.Format;
|
||||
m_TextureArraySize = 0;
|
||||
|
||||
this->set_BindingName(this->get_BindingName());
|
||||
}
|
||||
|
||||
|
||||
void Texture::CreateTexture(const CreateTextureDescriptor& argDesc)
|
||||
{
|
||||
this->CreateTexture(argDesc.Width, argDesc.Height, argDesc.MipLevels, argDesc.Elements, argDesc.Format, argDesc.InitialData_, argDesc.AccessType, false, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
LockedTextureData Texture::LockTextureBuffer(DataAccessMode::Enumeration argAccessMode, uint32 argArrayElement)
|
||||
{
|
||||
LockedTextureData outData = { NULL, 0 };
|
||||
if (m_Texture == NULL)
|
||||
throw L"Texture: Access forbidden until resource has been initialized.";
|
||||
|
||||
if (m_LockedTexture)
|
||||
throw L"Texture: Only one access to the texture buffer at one time possible.";
|
||||
|
||||
if (argArrayElement >= m_TextureArraySize && m_TextureArraySize != 0 && argArrayElement != 0)
|
||||
throw L"Texture: Access element index out of range.";
|
||||
|
||||
D3D10_MAPPED_TEXTURE2D mapped;
|
||||
if (S_OK != m_Texture->Map(D3D10CalcSubresource(0, argArrayElement, 1), (D3D10_MAP)argAccessMode, 0, &mapped))
|
||||
throw L"TextureResource: Access to the texture buffer was not successfull.";
|
||||
|
||||
outData.Data = mapped.pData;
|
||||
outData.RowPitch = mapped.RowPitch;
|
||||
|
||||
m_LockedTexture = true;
|
||||
m_LockedArrayElement = argArrayElement;
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
|
||||
void Texture::UnlockTextureBuffer()
|
||||
{
|
||||
if (m_Texture == NULL)
|
||||
throw L"Texture: Access forbidden until resource has been initialized.";
|
||||
|
||||
if (!m_LockedTexture)
|
||||
throw L"Texture: No access was done ending the access to the texture buffer is not possible.";
|
||||
|
||||
m_Texture->Unmap(D3D10CalcSubresource(0, m_LockedArrayElement, 1));
|
||||
|
||||
m_LockedTexture = false;
|
||||
}
|
||||
|
||||
|
||||
void Texture::CreateRenderTargetTexture(uint32 argWidth, uint32 argHeight, DataFormat::Enumeration argFormat, uint32 argMultiSampleCount, uint32 argMultiSampleQuality)
|
||||
{
|
||||
this->CreateTexture(argWidth, argHeight, 1, 0, argFormat, NULL, DataAccessType::Static, true, argMultiSampleCount, argMultiSampleQuality);
|
||||
}
|
||||
|
||||
|
||||
void Texture::CreateTexture(uint32 argWidth, uint32 argHeight, uint32 argMipLevels, uint32 argElements, DataFormat::Enumeration argFormat, TextureInitialData* ar_InitialData_, DataAccessType::Enumeration argAccessType, bool argRenderTarget, uint32 argMultiSampleCount, uint32 argMultiSampleQuality)
|
||||
{
|
||||
this->Uninitialize();
|
||||
|
||||
ID3D10Device& device = m_Engine.get_DX10Device();
|
||||
|
||||
if (argElements > 512)
|
||||
throw L"Texture: TextureArrays must not exceed the maximum element count of 512.";
|
||||
|
||||
if (argElements > 0 && ar_InitialData_ == NULL)
|
||||
throw L"TextureResource: TextureArrays must provide a initial data set.";
|
||||
|
||||
// calculate the needed amount of mipmap levels
|
||||
uint32 mipMapLevels = 1;
|
||||
for (uint32 tmp = std::min<uint32>(argHeight, argWidth); tmp > 1; tmp /= 2, ++mipMapLevels);
|
||||
mipMapLevels = std::max<uint32>(1, std::min<uint32>(mipMapLevels, argMipLevels == 0 ? mipMapLevels : argMipLevels));
|
||||
|
||||
// initialize the initiate data (this includes fake mipmap levels)
|
||||
D3D10_SUBRESOURCE_DATA* subResourceData = NULL;
|
||||
if (ar_InitialData_ != NULL)
|
||||
{
|
||||
subResourceData = new D3D10_SUBRESOURCE_DATA[std::max<uint32>(1, argElements) * mipMapLevels];
|
||||
uint32 maxI = std::max<uint32>(1, argElements);
|
||||
|
||||
for (uint32 i = 0; i < maxI; ++i)
|
||||
for (uint32 k = 0; k < mipMapLevels; ++k)
|
||||
{
|
||||
subResourceData[i * mipMapLevels + k].pSysMem = ar_InitialData_[i].Data;
|
||||
subResourceData[i * mipMapLevels + k].SysMemSlicePitch = 0;
|
||||
|
||||
// use fake mipmap sizes when we are processing mipmaps, so we do not allocate unnecessary memory
|
||||
// due the post calculation step for the mipmaps
|
||||
if (k > 0)
|
||||
subResourceData[i * mipMapLevels + k].SysMemPitch = 1;
|
||||
else
|
||||
subResourceData[i * mipMapLevels + k].SysMemPitch = ar_InitialData_[i].Pitch;
|
||||
}
|
||||
}
|
||||
|
||||
// create the resource
|
||||
D3D10_TEXTURE2D_DESC texDesc;
|
||||
ZeroMemory(&texDesc, sizeof(texDesc));
|
||||
texDesc.Width = argWidth;
|
||||
texDesc.Height = argHeight;
|
||||
texDesc.MipLevels = mipMapLevels;
|
||||
texDesc.ArraySize = std::max<uint32>(1, argElements);
|
||||
texDesc.Format = (DXGI_FORMAT)argFormat;
|
||||
texDesc.SampleDesc.Count = argMultiSampleCount;
|
||||
texDesc.SampleDesc.Quality = argMultiSampleQuality;
|
||||
|
||||
if (argAccessType == DataAccessType::Static)
|
||||
{
|
||||
texDesc.Usage = D3D10_USAGE_DEFAULT;
|
||||
texDesc.CPUAccessFlags = 0;
|
||||
}
|
||||
else if (argAccessType == DataAccessType::Dynamic)
|
||||
{
|
||||
texDesc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
texDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
}
|
||||
|
||||
if (argAccessType != DataAccessType::CpuReadOnly)
|
||||
texDesc.BindFlags = ((mipMapLevels > 1 || argRenderTarget) ? D3D10_BIND_RENDER_TARGET : 0) | D3D10_BIND_SHADER_RESOURCE;
|
||||
if (mipMapLevels > 1)
|
||||
texDesc.MiscFlags = D3D10_RESOURCE_MISC_GENERATE_MIPS;
|
||||
|
||||
if (S_OK != device.CreateTexture2D(&texDesc, subResourceData, &m_Texture))
|
||||
{
|
||||
if (subResourceData != NULL)
|
||||
delete subResourceData;
|
||||
|
||||
this->Uninitialize();
|
||||
throw L"Texture: Unable to create plain texture.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (subResourceData != NULL)
|
||||
delete [] subResourceData;
|
||||
|
||||
m_TextureResource = m_Texture;
|
||||
|
||||
// update the mipmapchain
|
||||
if (mipMapLevels > 1)
|
||||
{
|
||||
if (S_OK != ::D3DX10FilterTexture(m_Texture, 0, D3DX10_DEFAULT))
|
||||
throw L"Texture: Unable to filter texture (mipmaps).";
|
||||
else
|
||||
m_Texture->GetDesc(&texDesc);
|
||||
}
|
||||
|
||||
// create the resource view when possible
|
||||
if (argAccessType != DataAccessType::CpuReadOnly)
|
||||
{
|
||||
D3D10_SHADER_RESOURCE_VIEW_DESC texViewDesc;
|
||||
ZeroMemory(&texViewDesc, sizeof(texViewDesc));
|
||||
texViewDesc.Format = texDesc.Format;
|
||||
texViewDesc.Buffer.ElementWidth = argElements;
|
||||
|
||||
if (argElements > 0)
|
||||
texViewDesc.ViewDimension = argMultiSampleCount == 1 ? D3D10_SRV_DIMENSION_TEXTURE2DARRAY : D3D10_SRV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
else
|
||||
texViewDesc.ViewDimension = argMultiSampleCount == 1 ? D3D10_SRV_DIMENSION_TEXTURE2D : D3D10_SRV_DIMENSION_TEXTURE2DMS;
|
||||
|
||||
texViewDesc.Texture2DArray.MostDetailedMip = 0;
|
||||
texViewDesc.Texture2DArray.MipLevels = texDesc.MipLevels;
|
||||
texViewDesc.Texture2DArray.ArraySize = argElements;
|
||||
|
||||
if (S_OK != device.CreateShaderResourceView(m_TextureResource, &texViewDesc, &m_ShaderResourceView))
|
||||
{
|
||||
this->Uninitialize();
|
||||
throw L"TextureResource: Unable to create resource view.";
|
||||
}
|
||||
}
|
||||
|
||||
// finalize
|
||||
m_TextureWidth = argWidth;
|
||||
m_TextureHeight = argHeight;
|
||||
m_TextureFormat = argFormat;
|
||||
m_TextureArraySize = argElements;
|
||||
|
||||
this->set_BindingName(this->get_BindingName());
|
||||
}
|
||||
57
aiwaz/Aiwaz/Resources/Texture/Texture.h
Normal file
57
aiwaz/Aiwaz/Resources/Texture/Texture.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include "ITexture.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "../ShaderParameterCollection/ShaderParameterCollection.h"
|
||||
#include "../../Commands/CommandUserBase.h"
|
||||
|
||||
|
||||
class Texture
|
||||
: public ITexture
|
||||
, public ShaderParameterCollection
|
||||
{
|
||||
public:
|
||||
Texture(IEngine& argEngine);
|
||||
virtual ~Texture();
|
||||
|
||||
virtual void Uninitialize();
|
||||
|
||||
// ITexture
|
||||
virtual string8 get_BindingName() const { return m_TextureBindingName; }
|
||||
virtual void set_BindingName(const string8& argName);
|
||||
virtual string16 get_FileName() const { return m_FileName; }
|
||||
virtual uint32 get_TextureWidth() const{ return m_TextureWidth; }
|
||||
virtual uint32 get_TextureHeight() const { return m_TextureHeight; }
|
||||
virtual uint32 get_TextureArraySize() const { return m_TextureArraySize; }
|
||||
virtual DataFormat::Enumeration get_TextureFormat() const{ return m_TextureFormat; }
|
||||
|
||||
virtual void LoadFromFile(const string16& argFileName, DataAccessType::Enumeration argAccessType = DataAccessType::Static);
|
||||
virtual void CreateTexture(const CreateTextureDescriptor& argDesc);
|
||||
virtual LockedTextureData LockTextureBuffer(DataAccessMode::Enumeration argAccessMode, uint32 argArrayElement = 0);
|
||||
virtual void UnlockTextureBuffer();
|
||||
virtual void CreateRenderTargetTexture(uint32 argWidth, uint32 argHeight, DataFormat::Enumeration argFormat, uint32 argMultiSampleCount, uint32 argMultiSampleQuality);
|
||||
virtual ID3D10ShaderResourceView* get_ResourceViewFromTexture() const { return m_ShaderResourceView; }
|
||||
virtual ID3D10Texture2D* get_Texture2D() const { return m_Texture; }
|
||||
|
||||
protected:
|
||||
// ICommandUser
|
||||
virtual string8 get_UserName() const { return "Texture"; }
|
||||
|
||||
protected:
|
||||
void CreateTexture(uint32 argWidth, uint32 argHeight, uint32 argMipLevels, uint32 m_Elements, DataFormat::Enumeration argFormat, TextureInitialData* ar_InitialData_, DataAccessType::Enumeration argAccessType, bool argRenderTarget, uint32 argMultiSampleCount, uint32 argMultiSampleQuality);
|
||||
|
||||
private:
|
||||
ID3D10Buffer* m_TextureBuffer;
|
||||
ID3D10Resource* m_TextureResource;
|
||||
ID3D10ShaderResourceView* m_ShaderResourceView;
|
||||
ID3D10Texture2D* m_Texture;
|
||||
string16 m_FileName;
|
||||
uint32 m_TextureWidth;
|
||||
uint32 m_TextureHeight;
|
||||
uint32 m_TextureArraySize;
|
||||
DataFormat::Enumeration m_TextureFormat;
|
||||
|
||||
bool m_LockedTexture;
|
||||
uint32 m_LockedArrayElement;
|
||||
string8 m_TextureBindingName;
|
||||
};
|
||||
Reference in New Issue
Block a user