Search code examples
shaderdirectx-11

Shader does not get Vertex data except position, texcoord, normal


i want to read bone's weight but shader can't read data

this is my vertex type

struct SkinnedMesh
{

XMFLOAT3 Position;
XMFLOAT2 Texture;
XMFLOAT3 Normal;
XMFLOAT3 Weight;
UINT BoneIndices[4];
};

this is initialize shader description

// Create the vertex input layout description.
polygonLayout[0].SemanticName = "POSITION";
polygonLayout[0].SemanticIndex = 0;
polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[0].InputSlot = 0;
polygonLayout[0].AlignedByteOffset = 0;
polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[0].InstanceDataStepRate = 0;

polygonLayout[1].SemanticName = "TEXCOORD";
polygonLayout[1].SemanticIndex = 0;
polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT;
polygonLayout[1].InputSlot = 0;
polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[1].InstanceDataStepRate = 0;

polygonLayout[2].SemanticName = "NORMAL";
polygonLayout[2].SemanticIndex = 0;
polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[2].InputSlot = 0;
polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[2].InstanceDataStepRate = 0;

polygonLayout[3].SemanticName = "BLENDWEIGHT";
polygonLayout[3].SemanticIndex = 0;
polygonLayout[3].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[3].InputSlot = 0;
polygonLayout[3].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[3].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[3].InstanceDataStepRate = 0;

polygonLayout[4].SemanticName = "BLENDINDICES";
polygonLayout[4].SemanticIndex = 0;
polygonLayout[4].Format = DXGI_FORMAT_R32G32B32A32_UINT;
polygonLayout[4].InputSlot = 0;
polygonLayout[4].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[4].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[4].InstanceDataStepRate = 0;

numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);

// Create the vertex input layout.8
if (FAILED(_Device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &Layout)))
{
    MSG_BOX("Failed to create vertex input layout.");
    return E_FAIL;
}
return S_OK;

this is hlsl code

struct SkinnedInput
{
    float3 Position : POSITION;   
    float2 Tex : TEXCOORD;          
    float3 Normal : NORMAL;
    float4 Weights : WEIGHT;
    uint4 BoneIndices : BLENDINDICES;  
};

struct SkinnedOutput
{
    float4 Position : SV_POSITION;
    float2 Tex : TEXCOORD;
    float3 Normal : NORMAL;
};

SkinnedOutput main(SkinnedInput _Input)
{
    SkinnedOutput Out = (SkinnedOutput) 0;

    float weight[4];
    //weight[0] = _Input.Weights.x;
    //weight[1] = _Input.Weights.y;
    //weight[2] = _Input.Weights.z;
    //weight[3] = _Input.Weights.w;

    Out.Position = mul(float4(_Input.Position, 1.f), WorldMatrix);
    Out.Position = mul(Out.Position, ViewMatrix);
    Out.Position = mul(Out.Position, ProjectionMatrix);

    Out.Tex = _Input.Tex;

    Out.Normal = normalize(mul(float4(_Input.Normal, 0.f), WorldMatrix));

    
    return Out;

}

when i debug hlsl, there is no data in weights and boneindices. I've read int values ​​other than weights and boneindicies, but I can't read them

Even if I change the data order and read it, only position, texcoord, and normal are read

Anyone know about this?

i changed struct and layout decs

struct SkinnedMesh
{
    XMFLOAT3 Position;
    XMFLOAT2 Texture;
    XMFLOAT3 Normal;
    XMFLOAT4 Weight;
    XMUINT4 BoneIndices;
};

D3D11_INPUT_ELEMENT_DESC polygonLayout[] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "BLENDWEIGHT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "BLENDINDICES", 0, DXGI_FORMAT_R32G32B32A32_UINT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } };

But result is same..


Solution

  • This is a case of compiler/runtime optimization.

    Since in your shader you do not use blend weights at all, the data will eventually not be fetched.

    To test it properly, you could make something like :

    struct SkinnedOutput
    {
        float4 Position : SV_POSITION;
        float2 Tex : TEXCOORD;
        float3 Normal : NORMAL;
        float4 Weights : WEIGHT;
    };
    

    And make sure to assign it:

     Out.Weights = _Input.Weights;
    

    It is visible when checking shader disassembly, your input declaration is :

    // Input signature:
    //
    // Name                 Index   Mask Register SysValue  Format   Used
    // -------------------- ----- ------ -------- -------- ------- ------
    // POSITION                 0   xyz         0     NONE   float   xyz 
    // TEXCOORD                 0   xy          1     NONE   float   xy  
    // NORMAL                   0   xyz         2     NONE   float   xyz 
    // WEIGHT                   0   xyzw        3     NONE   float       
    // BLENDINDICES             0   xyzw        4     NONE    uint  
    

    Note that the used flag is empty, so when you check variable declarations :

    vs_5_0
    dcl_globalFlags refactoringAllowed
    dcl_constantbuffer CB0[12], immediateIndexed
    dcl_input v0.xyz
    dcl_input v1.xy
    dcl_input v2.xyz
    dcl_output_siv o0.xyzw, position
    dcl_output o1.xy
    dcl_output o2.xyz
    dcl_temps 2
    

    you can see that the shader only declares v0 (position), v1 (uv), v2 (texcoords), unused ones are not declared at all.

    Note that the compiler is very aggressive into removing unused code, so even if you uncomment :

    float weight[4];
    weight[0] = _Input.Weights.x;
    weight[1] = _Input.Weights.y;
    weight[2] = _Input.Weights.z;
    weight[3] = _Input.Weights.w;
    

    But weight does not write into an output, it will also be removed.