[Shader / HLSL] Shader Reflection

2021. 12. 18. 04:52·Shader

Shader Reflection

 

DirectX 11 Shader Reflection

- ID3D11ShaderReflection

  -> 해당 struct를 통해 Shader Reflection 실행.

- ID3D11ShaderReflectionConstantBuffer

  -> 해당 struct를 통해 ConstantBuffer Index를 기준으로 정보를 가져온다.

- D3D11_SHADER_DESC

  -> 해당 struct를 통해 ID3D11ShaderReflection에서 Shader 정보를 가져온다.

- D3D11_SHADER_BUFFER_DESC

  -> 해당 struct를 통해 ID3D11ShaderReflectionConstantBuffer에서 Constant Buffer 정보를 가져온다.

- D3D11_SHADER_INPUT_BIND_DESC

  -> 해당 struct를 통해 Binding 된 Resource Name을 기준으로 정보를 가져온다.

 

Shader Reflection 이점

- 경험상 Effect11을 사용 할 때 Input Layout 실수가 너무 잦아 애를 많이 먹었었다. 하지만 해당 Shader Reflection을

  통해 Input Layout을 Shader Load시 설정할 수 있어 일일히 Input Layout과 대응하는 구조체를 만들어 설정해 줄

  필요가 없어진다.

- Effect 기준 해당 Constant Buffer나 Resource에 관한 Update를 일일히 함수로 지정해주어야 했는데, 그렇게 되면

  Shader가 늘어날수록 Class를 일일히 설정해주는게 귀찮았다. 하지만 Shader Reflection을 통해 해당 Resource의

  Bind Point(Register Slot)을 알 수 있고, 해당 Register Slot으로 Resource를 설정 해주게 되면 매번 설정할 필요가

  없어진다.

 

ID3DBlob* shaderBlob = nullptr;
ID3D11ShaderReflection* pReflector = nullptr;
    
...
    
// Create Reflector..
D3DReflect(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&pReflector);
	
// Shader Refection
D3D11_SHADER_DESC shaderDesc;
pReflector->GetDesc(&shaderDesc);

/// Input Layout Reflection
// Shader Input Layout..
std::vector<D3D11_INPUT_ELEMENT_DESC> inputLayoutDesc;
for (unsigned inputIndex = 0; inputIndex < shaderDesc.InputParameters; inputIndex++)
{
	D3D11_SIGNATURE_PARAMETER_DESC paramDesc;
	pReflector->GetInputParameterDesc(inputIndex, &paramDesc);
	
	// Shader Input Data를 기반으로 생성..
	D3D11_INPUT_ELEMENT_DESC elementDesc;
	elementDesc.SemanticName = paramDesc.SemanticName;
	elementDesc.SemanticIndex = paramDesc.SemanticIndex;
	elementDesc.InputSlot = 0;
	elementDesc.AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
	elementDesc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
	elementDesc.InstanceDataStepRate = 0;

	// Shader Data 기반으로 DXGI format 설정..
	if (paramDesc.Mask == 1)
	{
		if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_UINT32) elementDesc.Format = DXGI_FORMAT_R32_UINT;
		else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_SINT32) elementDesc.Format = DXGI_FORMAT_R32_SINT;
		else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32) elementDesc.Format = DXGI_FORMAT_R32_FLOAT;
	}
	else if (paramDesc.Mask <= 3)
	{
		if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_UINT32) elementDesc.Format = DXGI_FORMAT_R32G32_UINT;
		else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_SINT32) elementDesc.Format = DXGI_FORMAT_R32G32_SINT;
		else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32) elementDesc.Format = DXGI_FORMAT_R32G32_FLOAT;
	}
	else if (paramDesc.Mask <= 7)
	{
		if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_UINT32) elementDesc.Format = DXGI_FORMAT_R32G32B32_UINT;
		else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_SINT32) elementDesc.Format = DXGI_FORMAT_R32G32B32_SINT;
		else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32) elementDesc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
	}
	else if (paramDesc.Mask <= 15)
	{
		if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_UINT32) elementDesc.Format = DXGI_FORMAT_R32G32B32A32_UINT;
		else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_SINT32) elementDesc.Format = DXGI_FORMAT_R32G32B32A32_SINT;
		else if (paramDesc.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32) elementDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
	}

	// 현 InputLayout 데이터 삽입..
	inputLayoutDesc.push_back(elementDesc);
}

// Shader InputLayout 생성..
HR(g_Device->CreateInputLayout(&inputLayoutDesc[0], (UINT)inputLayoutDesc.size(), shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), &m_InputLayout));

/// ConstantBuffer Reflection
// Pixel Shader ConstantBuffer..
for (unsigned int cbindex = 0; cbindex < shaderDesc.ConstantBuffers; cbindex++)
{
	ID3D11ShaderReflectionConstantBuffer* cBuffer = pReflector->GetConstantBufferByIndex(cbindex);
	D3D11_SHADER_BUFFER_DESC bufferDesc;

	if (SUCCEEDED(cBuffer->GetDesc(&bufferDesc)))
	{
		ID3D11Buffer* cBuffer = nullptr;
		CD3D11_BUFFER_DESC cBufferDesc(bufferDesc.Size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);

		D3D11_SHADER_INPUT_BIND_DESC bindDesc;
		pReflector->GetResourceBindingDescByName(bufferDesc.Name, &bindDesc);

		// 해당 Constant Buffer 생성..
		HR(g_Device->CreateBuffer(&cBufferDesc, nullptr, &cBuffer));

		// Constant Buffer Register Slot Number..
		cbuffer_register_slot = bindDesc.BindPoint;

		...
            
	}
}
    
/// Shader Resource Reflection
// Shader Resource..
for (unsigned int rsindex = 0; rsindex < shaderDesc.BoundResources; rsindex++)
{
	D3D11_SHADER_INPUT_BIND_DESC bindDesc;
	pReflector->GetResourceBindingDesc(rsindex, &bindDesc);

	// Resource Type에 맞는 해당 List에 삽입..
	switch (bindDesc.Type)
	{
	case D3D_SIT_TEXTURE:
	{
		// Texture Resource 삽입..
	}
	break;
	case D3D_SIT_SAMPLER:
	{
		// Sampler Resource 삽입..
	}
	break;
	default:
	break;
	}
}

Shader Reflection을 통한 Shader Data 설정.

 

/// <summary>
/// ShaderBase Class
/// </summary>
/// 
/// - 모든 Shader Class의 Base Class
/// - Vertex, Pixel, Compute Shader의 기본적으로 사용하는 Resource를 포함한 Base Class
/// 
class ShaderBase : public IShader
{
public:
	ShaderBase(SHADER_TYPE shaderType) : m_ShaderType(shaderType) {}

public:
	virtual void LoadShader(std::string fileName, const char* entry_point, const char* shader_model, const D3D_SHADER_MACRO* pDefines) abstract;
	virtual void Update() abstract;
	virtual void Release();

	// Shader SamplerState 설정..
	void SetSamplerState(Hash_Code hash_code, ID3D11SamplerState* sampler);

	// Shader ConstantBuffer Resource Update..
	template<typename T>
	void ConstantBufferCopy(T* cBuffer);

	template<typename T>
	void ConstantBufferUpdate(T* cBuffer);

	// Shader ShaderResourceView 설정..
	template<typename T>
	void SetShaderResourceView(ID3D11ShaderResourceView* srv);

public:
	// 현재 Shader Type 반환 함수..
	SHADER_TYPE GetType();

protected:
	void CreateShader(const wchar_t* wPath, const D3D_SHADER_MACRO* pDefines, LPCSTR entry_point, LPCSTR shader_model, ID3DBlob** ppShader);

protected:
	// 연속된 메모리 공간에 있는 ConstantBuffer List..
	std::vector<Microsoft::WRL::ComPtr<ID3D11Buffer>> m_ConstantBuffers;

	// 연속된 메모리 공간에 있는 SamplerState List..
	std::vector<Microsoft::WRL::ComPtr<ID3D11SamplerState>> m_SamplerStates;

	// 연속된 메모리 공간에 있는 ShaderResourceView List..
	std::vector<Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>> m_ShaderResourceViews;

	// PixelShader ConstantBuffer List..
	std::unordered_map<Hash_Code, ConstantBuffer*> m_ConstantBufferList;

	// PixelShader SamplerState List..
	std::unordered_map<Hash_Code, SamplerBuffer*> m_SamplerList;

	// PixelShader ShaderResourceView List..
	std::unordered_map<Hash_Code, ShaderResourceBuffer*> m_SRVList;

private:
	// 현재 Shader Type..
	SHADER_TYPE m_ShaderType;
};

Shader Base Class를 통해 Shader Resource Update.

'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 관리 (2)  (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' 카테고리의 다른 글
  • [Shader / HLSL] Shader Reflection & Define Macro를 이용한 Resource 관리 (3)
  • [Shader / HLSL] Shader Reflection & Define Macro를 이용한 Resource 관리 (2)
  • [Shader / HLSL] Shader Reflection & Define Macro를 이용한 Resource 관리 (1)
  • [Shader / HLSL] RunTime Compile Shader / Shader Macro
KyuHwang
KyuHwang
  • KyuHwang
    DirectX Engine
    KyuHwang
  • 전체
    오늘
    어제
    • 분류 전체보기 (50)
      • C++ (4)
      • CS (0)
      • Graphics (32)
      • DLL (2)
      • Shader (7)
      • Project (4)
      • ETC (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • YouTube
  • 공지사항

  • 인기 글

  • 태그

    DLL Interface
    Explicit Linking
    DirectX 2D
    shader
    Shader Resource 관리
    RunTime Compile Shader
    std::is_base_of
    Return Type Operator
    Alpha Blending
    C ++
    Project
    animation retargeting
    Shader Reflection
    Win API
    Shader Macro
    dll
    texture block compression
    hlsl
    Hash Code
    Define Macro
    Directx11
    Define Function
    animation constraint
    Order Independent Transparency
    bc format
    Implicit Linking
    nvtt
    std::enable_if
    mobile format
    rigging chain
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
KyuHwang
[Shader / HLSL] Shader Reflection
상단으로

티스토리툴바