Understanding Shader Programming

三世轮回 提交于 2019-12-08 02:50:08

问题


I am trying to understand shader programming, but at this point, documentation wont help me further.

1] Does the data type & size of the buffers have to match?

In the DX tutorial 4 from the DX SDK, they have a struct:

struct SimpleVertex{
    XMFLOAT3 Pos;
    XMFLOAT4 Color;
};

While in their shader file, they define:

struct VS_OUTPUT{
    float4 Pos : SV_POSITION;
    float4 Color : COLOR0;
};

They define Pos as a vector of 3 in one file, while it is 4 in another. How is this correct? I thought the size of the data have to match.

2] To create another constant buffer, is this the steps I need to do?

// Make in shader file
cbuffer LightBuffer : register(b0){
    float3 lDir;
    float4 lColor;
}

// Make in C++ file
struct LightBuffer{
    XMFLOAT3 Direction;
    XMFLOAT4 Color;
};

    ...

LightBuffer lb;
lb.Direction=XMFLOAT3(-1.0f, -10.0f, 4.0f); // Make an instance of it
lb.Color=XMFLOAT4(0.35f, 0.5f, 1.0f, 1.0f);

    ...

ID3D11Buffer* lightBuffer=NULL; // Declare in global scope

D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage=D3D11_USAGE_DEFAULT;
bd.ByteWidth=sizeof(LightBuffer);
bd.BindFlags=D3D11_BIND_CONSTANT_BUFFER;

hr=graphics->deviceInterface->CreateBuffer(&bd, NULL, &lightBuffer);

graphics->deviceContext->UpdateSubresource(lightBuffer, 0, NULL, &lb, 0, 0);

graphics->deviceContext->PSSetConstantBuffers(0, 1, &lightBuffer);

These are the steps I did, which was similar to the constant buffer in the tutorial. It ends up producing nothing.

I found out by accident that if I change the type of LightBuffer::XMFLOAT3 Direction to XMFLOAT4, it works. What am I not understanding? Why cant I have the type I wish?

Thanks for reading.


回答1:


1-As you can see from the struct's name, it is not the input but the output of the vertex shader. Vertex shader should output position variable as 4 floats(homogeneus coordinates). So somewhere in the shader file, there should be an operation which expands the vector to a float4 variable(something like "float4(inputPos, 1.0);").

2-It's probably an alignment issue. GPU's are designed to work with 4D vectors. While using constant buffers, try to create your structures with matrices first, 4D variables second, 3D variables third, and so on. Or you can add extra unused padding bytes like you said you did. If you have too much non-4D vectors, you can pack them in one slot with 'packoffset' keyword for not wasting GPU registers. Detailed explanation is here: http://msdn.microsoft.com/en-us/library/windows/desktop/bb509581(v=vs.85).aspx




回答2:


  1. SimpleVertex is the C++ side structure defining the input vertex layout. VS_OUTPUT is the hlsl side structure defining the vertex shader output / pixel shader input. The layout of SimpleVertex corresponds to the vertex shader input which is the arguments to the vertex shader function VS(float4 Pos : POSITION, float4 Color: COLOR). In D3D11 you use an ID3D11InputLayout object (on the C++ side) to describe how the input vertex layout (SimpleVertex structure) should be bound to the vertex shader inputs. If you search in the C++ source code for the tutorial for InputLayout you will see where this is created.
  2. You need to account for alignment with constant buffers. Constant buffer members are aligned on float4 boundaries but C++ structs are not so when you use an XMFLOAT3 for direction your XMFLOAT4 color doesn't line up with the layout your constant buffer defines in hlsl.


来源:https://stackoverflow.com/questions/12889619/understanding-shader-programming

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!