まめ - たんたんめん

備忘録 C# / WPF 多め

ConstantBufferを定義したヘッダをHLSLとC++共通化する

C++ 側と hlsl 側のcbuffer定義を一致させておくことで多重変更を防ぎます。
また、hlslでは#pragma onceは利用できなかったりするので注意してください。

マクロベースの文字列の1:1置換で対応させます。

用意したヘッダ

#ifndef _HLSL_TYPE_
#define _HLSL_TYPE_
    #ifdef TS_FRAMEWORK
        
        #define TS_HLSL_CBUFFER struct
        #define TS_HLSL_TBUFFER struct

        #define TS_HLSL_FLOAT2 TS::Vector2
        #define TS_HLSL_FLOAT3 TS::Vector3
        #define TS_HLSL_FLOAT4 TS::Vector4

        #define TS_HLSL_MATRIX TS::Matrix4

        template<unsigned N = 0> struct ts_cbuffer_register { unsigned RegisterIndex() { return N; } };

        #define TS_HLSL_REGISTER_B(register_id) : public ts_cbuffer_register<register_id>
        #define TS_HLSL_SEMANTICS(semantics_name)
        #define TS_HLSL_PACKOFFSET(offset_name)

    #else // hlsl

        #define TS_HLSL_CBUFFER cbuffer
        #define TS_HLSL_TBUFFER tbuffer

        #define TS_HLSL_FLOAT2 float2
        #define TS_HLSL_FLOAT3 float3
        #define TS_HLSL_FLOAT4 float4

        #define TS_HLSL_MATRIX float4x4

        #define TS_HLSL_REGISTER_B(register_id)   : register(b##register_id)
        #define TS_HLSL_SEMANTICS(semantics_name) : semantics_name
        #define TS_HLSL_PACKOFFSET(offset_name)   : packoffset(offset_name)
    #endif
#endif

実際の定義

#ifndef _STRUCTURE_RESOURCE
#define _STRUCTURE_RESOURCE
#include "HlslType.h"

TS_HLSL_CBUFFER CameraCbuffer 
TS_HLSL_REGISTER_B(0)
{
    TS_HLSL_MATRIX u_ViewMatrix;
    TS_HLSL_MATRIX u_ProjectionMatrix;
    TS_HLSL_MATRIX u_InvViewMatrix;
    TS_HLSL_MATRIX u_InvProjectionMatrix;
};

TS_HLSL_CBUFFER TransformCBuffer 
TS_HLSL_REGISTER_B(1)
{
    TS_HLSL_MATRIX u_WorldMatrix;
};

#endif
<||

展開されるhlsl コード
>|cpp|
cbuffer CameraCbuffer : register(b0)
{
    float4x4 u_ViewMatrix;
    float4x4 u_ProjectionMatrix;
    float4x4 u_InvViewMatrix;
    float4x4 u_InvProjectionMatrix;
};

展開されるCPPヘッダ

struct CameraCbuffer : public ts_cbuffer_register<0>
{
    TS::Matrix4 u_ViewMatrix;
    TS::Matrix4 u_ProjectionMatrix;
    TS::Matrix4 u_InvViewMatrix;
    TS::Matrix4 u_InvProjectionMatrix;
};

C++側ではTS_HLSL_REGISTER_B(0)で継承を利用したレジスタIDの取得を行えるようにしています。

    CameraCbuffer cbuffer;
    cbuffer.RegisterIndex(); // レジスタのインデックスを取得できる

最近はあまりシェーダを書いていません...。