Shader Resource Struct / Hash Table
이전 글에서 해당 Resource 등록 과정에 대해 써놓았는데 내부적으로 사용하는 방식을 정리하려한다.
굳이 왜 해당 Resource에 대응하는 Class를 선언하여 Key값을 검색하는데에 사용하는가? 에 대한 의문이 들 수도 있는데
일단 이전에 사용하던 string Key값을 이용한 검색은 잘못된 Key를 입력했을 경우 RunTime에 반환이 잘못되거나 에러가 뜨는 상황이 자주 발생하여 실수를 최소화 하고싶어 이와 같은 방식으로 모든 Resource 관리를 변경하였다.
이제 내부 코드를 순차적으로 정리해보자.
/*
# HashClass Create Define
* ClassName -> Struct Name
* ResourceType -> Struct Resource Type (eResourceType)
*/
#define CREATE_HASH_CLASS(ClassName, ResourceType) \
struct ClassName : public HashClass<ClassName> \
{ \
static eResourceType GetType() { return ResourceType; } \
};
/*
# Resource Push HashTable Define
* ClassName -> Struct Name
* ResourceType -> Struct Resource Type (eResourceType)
*/
#define RESOURCE_PUSH(ClassName, ResourceType) static bool push_##ClassName = ShaderResourceHashTable::Get()->Push(ResourceType, #ClassName, typeid(ClassName).hash_code());
/*
# Resource Push HashTable Overlap Check Define
* ResourceMask -> Resource Define Mask
*/
#define RESOURCE_DEFINE(ResourceMask) static bool overlap_##ResourceMask = ShaderResourceHashTable::Get()->DefineCheck(ResourceMask);
// Template을 통해 들어오는 Class가 HashClass를 상속 받았는지 체크..
template<typename T>
using Enable_Check = typename std::enable_if<std::is_base_of<HashClass<T>, T>::value, bool>::type;
- CREATE_HASH_CLASS : Resource의 Base Macro. 매개변수로 들어오는 토큰 기준으로 해당 Struct 생성.
- RESOURCE_PUSH : Resource Struct Hash Code 등록 Macro.
- RESOURCE_DEFINE : Hash Code 등록 시 매번 Find 하는것을 막기 위해 현재 상태 업데이트하기 위한 Macro.
- Enable_Check : 위의 Macro를 통해 등록한 Resource를 찾을 경우 해당 Resource Struct가 들어올때만 체크하기 위해 사용.
/// <summary>
/// ConstantBuffer Resource Struct
/// </summary>
///
/// - Shader 내부의 ConstantBuffer Resource와 1:1 대응하는 Struct
/// - Shader에서 설정한 레지스터 번호와 버퍼가 일치하는 한개의 Constant Buffer
/// - D3DCompiler에서 현재 Shader에서 ConstantBuffer을 선언해 두어도 사용하지 않으면
/// Register Slot에 올리지 않는다..
///
/// - 주의점
/// 1) 현재 struct의 이름과 변수 순서는 Shader 내부의 ConstantBuffer와 일치해야한다 (Struct Name을 통해 Constant Buffer를 찾기 때문)
///////////////////////////////////////////////////////////////////////////////////////////
// Deferred Constant Buffer
///////////////////////////////////////////////////////////////////////////////////////////
CONSTANT_BUFFER(cbMeshObject)
struct CB_MeshObject : public cbMeshObject
{
DirectX::SimpleMath::Matrix gWorld;
DirectX::SimpleMath::Matrix gWorldView;
DirectX::SimpleMath::Matrix gWorldViewProj;
DirectX::SimpleMath::Matrix gTexTransform;
DirectX::SimpleMath::Matrix gShadowTransform;
};
...
/// Resource Hash 재등록 방지 Define
RESOURCE_DEFINE(DEFINE_CB)
- Constant Buffer의 경우 해당 Buffer와 동일한 크기의 구조체가 필요하므로 상속받아 사용.
#define DEFINE_CB 0x00000001
#define DEFINE_SS 0x00000010
#define DEFINE_SRV 0x00000100
#define DEFINE_UAV 0x00001000
///
/// 2021/11/08 1:22
/// SeoKyuHwang
///
/// # ShaderResourceHashTable Class
///
/// - ShaderResource Struct 기준 Hash Code 키값으로 설정하기 위한 Class..
/// - Shader Reflect Load 시 Description과 비교하기 위해 필요..
/// - Resource Struct 선언과 동시에 Hash Table에 올리기 위해 Define 활용..
/// - Define을 통해 해당 Resource Struct 선언과 동시에 Hash Table에 등록..
class ShaderResourceHashTable
{
public:
static ShaderResourceHashTable* Get();
static ShaderResourceHashTable* instance;
public:
// ConstantBuffer Hash Table..
std::unordered_map<std::string, Hash_Code> g_CBuffer_HashTable;
// Sampler Hash Table..
std::unordered_map<std::string, Hash_Code> g_Sampler_HashTable;
// ShaderResourceView Hash Table..
std::unordered_map<std::string, Hash_Code> g_SRV_HashTable;
// UnorderedAccessView Hash Table..
std::unordered_map<std::string, Hash_Code> g_UAV_HashTable;
public:
// Hash Code Push 함수..
bool Push(eResourceType type, std::string name, Hash_Code hash_code);
// 해당 Hash Code 반환 함수..
size_t FindHashCode(eResourceType type, std::string cBufName);
bool DefineCheck(Define_Mask nowDefine);
// Hash Table Reset 함수..
void Destroy();
private:
// Hash Code Push Check 함수..
bool CheckHashCode(std::unordered_map<std::string, Hash_Code>& table, std::string name, Hash_Code hash_code);
Define_Mask DEFINE_MASK = 0x00000000;
};
bool ShaderResourceHashTable::Push(eResourceType type, std::string name, Hash_Code hash_code)
{
// 해당 Resource Type에 따른 Hash Code 등록..
switch (type)
{
case eResourceType::CB:
{
if (DEFINE_MASK & DEFINE_CB)
return false;
else
return CheckHashCode(g_CBuffer_HashTable, name, hash_code);
}
case eResourceType::SS:
{
if (DEFINE_MASK & DEFINE_SS)
return false;
else
return CheckHashCode(g_Sampler_HashTable, name, hash_code);
}
case eResourceType::SRV:
{
if (DEFINE_MASK & DEFINE_SRV)
return false;
else
return CheckHashCode(g_SRV_HashTable, name, hash_code);
}
case eResourceType::UAV:
{
if (DEFINE_MASK & DEFINE_UAV)
return false;
else
return CheckHashCode(g_UAV_HashTable, name, hash_code);
}
default:
break;
}
return true;
}
size_t ShaderResourceHashTable::FindHashCode(eResourceType type, std::string cBufName)
{
std::unordered_map<std::string, Hash_Code>::iterator cHash;
// Resource Type에 따른 Hash Code 반환..
switch (type)
{
case eResourceType::CB:
{
cHash = g_CBuffer_HashTable.find(cBufName);
if (cHash == g_CBuffer_HashTable.end())
{
return 0;
}
}
break;
case eResourceType::SS:
{
cHash = g_Sampler_HashTable.find(cBufName);
if (cHash == g_Sampler_HashTable.end())
{
return 0;
}
}
break;
case eResourceType::SRV:
{
cHash = g_SRV_HashTable.find(cBufName);
if (cHash == g_SRV_HashTable.end())
{
return 0;
}
}
break;
case eResourceType::UAV:
{
cHash = g_UAV_HashTable.find(cBufName);
if (cHash == g_UAV_HashTable.end())
{
return 0;
}
}
break;
default:
return 0;
}
return cHash->second;
}
bool ShaderResourceHashTable::DefineCheck(Define_Mask nowDefine)
{
DEFINE_MASK |= nowDefine;
return true;
}
bool ShaderResourceHashTable::CheckHashCode(std::unordered_map<std::string, Hash_Code>& table, std::string name, Hash_Code hash_code)
{
// 해당 Resource가 등록된 상태가 아니라면 Hash_Code 등록..
if (table.find(name) == table.end())
{
table.insert(std::make_pair(name, hash_code));
}
return true;
}
- 해당 선언한 Struct의 Name과 Hash_Code가 올라갈 Hash Table List Class.
이어서 다음글에서 해당 Hash Table과 Struct를 이용한 Resource 등록에 관한 정리를 해야겠다.
'Shader' 카테고리의 다른 글
[Shader / HLSL] Shader Reflection & Define Macro Resource Hash Table 을 이용한 Resource 동기화 (0) | 2022.01.17 |
---|---|
[Shader / HLSL] Shader Reflection & Define Macro를 이용한 Resource 관리 (3) (0) | 2021.12.19 |
[Shader / HLSL] Shader Reflection & Define Macro를 이용한 Resource 관리 (1) (0) | 2021.12.19 |
[Shader / HLSL] RunTime Compile Shader / Shader Macro (0) | 2021.12.19 |
[Shader / HLSL] Shader Reflection (0) | 2021.12.18 |