bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

テクスチャ管理

テクスチャを管理するクラスを作ってみた。
キャッシュに残っていれば使う。
参照カウンターが0になったらキャッシュを消す。

#ifndef __cTextureManager_h__
#define __cTextureManager_h__

#include <d3d11.h>
#include <d3dx11.h>
#include <string>
#include <map>

class cTextureManager
{
private:
	struct sCache
	{
		int m_RefCount;
		ID3D11ShaderResourceView* m_Resource;
	};
	typedef std::map<std::string, sCache*> TextureCache;

public:
	static cTextureManager& GetInstance()
	{
		static cTextureManager s_Instance;
		return s_Instance;
	}

private:
	cTextureManager() { }
	cTextureManager(const cTextureManager& rhs);
	cTextureManager& operator=(const cTextureManager& rhs);

public:
	ID3D11ShaderResourceView* getTextureResourceView(ID3D11Device* device,const std::string& filename);
	HRESULT removeTextureResourceView(ID3D11ShaderResourceView* resource);
	void exit();

	void dump();

protected:
	TextureCache m_TextureCache;
};

#define g_texture_manager cTextureManager::GetInstance()

#endif	// __cTextureManager_h__
#include "cTextureManager.h"
#include "ShaderUtility.h"


ID3D11ShaderResourceView* cTextureManager::getTextureResourceView(ID3D11Device* device, const std::string& filename)
{
	TextureCache::iterator it;
	it = m_TextureCache.find(filename);
	
	// キャッシュにヒット
	if(it != m_TextureCache.end()) {
		std::string key = it->first;
		sCache* value = it->second;
		int refCnt = ++value->m_RefCount;	// 参照カウントを増やす
		ID3D11ShaderResourceView* pRV = value->m_Resource;
		printf("cTextureManager already regist %s : %p, refCnt = %d\n", key.c_str(), pRV, refCnt);
		return pRV;
	}

	ID3D11ShaderResourceView* pRV = NULL;
	// キャッシュにないのでロード
	HRESULT hr = D3DX11CreateShaderResourceViewFromFileA( device, filename.c_str(), NULL, NULL, &pRV, NULL );
	if(FAILED(hr)) {
		printf("cant load %s\n", filename.c_str());
		return NULL;
	}
	sCache* pCache = new sCache;
	pCache->m_RefCount = 1;
	pCache->m_Resource = pRV;
	m_TextureCache.insert(std::pair<std::string, sCache*>(filename, pCache));
	printf("cTextureManager regist %s : %p\n", filename.c_str(), pRV);

	return pRV;
}

HRESULT cTextureManager::removeTextureResourceView(ID3D11ShaderResourceView* resource)
{
	TextureCache::iterator it = m_TextureCache.begin();
	TextureCache::iterator end = m_TextureCache.end();
	sCache* pCache = NULL;
	ID3D11ShaderResourceView* pRV = NULL;

	while(it != end) {
		pCache = it->second;
		pRV = pCache->m_Resource;
		if(resource == pRV) {
			if(--pCache->m_RefCount <= 0) {
				printf("cTextureManager remove %s, %p\n", it->first.c_str(), pRV);
				pRV->Release();
				delete pCache;
				m_TextureCache.erase(it);
				return S_OK;
			}
			printf("cTextureManager descrease RefCount %d\n", pCache->m_RefCount);
		}
		++it;
	}
	return E_FAIL;
}

void cTextureManager::exit()
{
	TextureCache::iterator it = m_TextureCache.begin();
	TextureCache::iterator end = m_TextureCache.end();
	sCache* pCache = NULL;
	ID3D11ShaderResourceView* pRV = NULL;

	while(it != end) {
		pCache = it->second;
		if(pCache) {
			printf("cTextureManager::exit %s : %p, %d\n", it->first.c_str(), pCache->m_Resource, pCache->m_RefCount);
			pRV = pCache->m_Resource;
			if(pRV) {
				pRV->Release();
			}
			delete pCache;
		}
		++it;
	}
}

void cTextureManager::dump()
{
	TextureCache::iterator it = m_TextureCache.begin();
	TextureCache::iterator end = m_TextureCache.end();
	sCache* pCache = NULL;

	printf("cTextureManager cache dump ------------------\n");
	while(it != end) {
		pCache = it->second;
		printf("%s : %p, %d\n", it->first.c_str(), pCache->m_Resource, pCache->m_RefCount);
		++it;
	}
	printf("---------------------------------------------\n");
}