Advertisement

Questions about D3D12_INPUT_ELEMENT_DESC

Started by August 17, 2018 03:40 PM
5 comments, last by Adam Miles 6 years, 5 months ago

Is there some reason to use multiple buffers attached to different Input Slots, over using a single buffer separating the data using AlignedByteOffset?

When there is much data per vertex, should I use DrawIndexedInstanced method instead of DrawInstanced method?

How is it different to use my custom Semantic Names like "VERTICESPOS" over "POSITION"?

For the Normals, Tangets and Bitangets, should i name them like: NORMAL0, NORMAL1 and NORMAL2, or like NORMAL, TANGENT and BINORMAL, and why?

Just in order to understand this better, what is the difference between supplying vertices positions under the semantic name POSITION and the semantic name TEXCOORD?

When there is only one semantic data in a buffer, should I use AlignedByteOffset of 1 for DXGI_FORMAT_RxGxBx_xxx, or I should let D3D12_APPEND_ALIGNED_ELEMENT to handle it for me? Its name suggests Aligning...

The semantic names of non-system-value inputs to the vertex shader don't have any meaning. It's holdover from DX9 that a lot of apps use POSITION or TEXCOORD, where the names did actually matter.

AlignedByteOffset of 1 probably won't work, unless your data is a single byte. The 'aligned' in the name means that the value needs to be aligned to the size of the element you're trying to read. So for a 4-byte value, a value of 0, 4, or 8 is valid, but 1 is not. Unless you're intentionally leaving space for data that a different input layout will reference (e.g. a shadow pass only needs one value, but the same vertex buffer will also be used for real rendering with more data), you should just use the APPEND_ALIGNED_ELEMENT value.

I'll let someone else comment on best practices.

Advertisement

There is good reason to have deinterleaved vertex buffers (so multiple vertex buffers on multiple input slots). Let's say that you have two render passes for a mesh, one is using a simple shader that only uses the positions, while the other render pass wants position, texcoord, normal. If you have separate vertex buffers, then you can bind only the positions vertex buffer to the simple render pass, and achieve better performance because more vertices will fit into cache. Your engine code can mix-and match vertex buffers very easily in general and allows some nice tricks.

You should always prefer DrawIndexed instead of just regular Draw when you have more than just a couple vertices to draw. This can trigger a behaviour where the vertex shader can skip processing vertices whose indices were already executed and still inside the cache.

For vertex shaders, the input semantic names have no meaning apart from reflection information. With shader reflection API, you can retrieve semantics and maybe do some engine-specific logic on them. Also, it is good to have meaningful semantic names, because if you enable the debug layer, it will output semantic names in the error messages if there are mismatching input/outputs in different shader stages.

For output semantics, you have semantics that start with SV_, meaning system-value semantics, which will bring special meaning and fixed function behaviour. 

You can always use D3D12_APPEND_ALIGNED_ELEMENT when your real data type size matches the size of the DXGI_FORMAT description provided to the input description. Otherwise, you can supply a custom size and the hardware will have to read from your buffers with that stride instead of the stride specified by the DXGI_FORMAT.

@turanszkij So, if i send vertex position data with a semantic name TEXCOORD it would not clamp my positions between 0.0 and 1.0, or scale them to fit in that range or something? I have POSITION for that, so i would not use TEXCOORD for positions, but I ask in order to understand it better.

39 minutes ago, turanszkij said:

This can trigger a behaviour where the vertex shader can skip processing vertices whose indices were already executed and still inside the cache.

Great!!

16 hours ago, NikiTo said:

@turanszkij So, if i send vertex position data with a semantic name TEXCOORD it would not clamp my positions between 0.0 and 1.0, or scale them to fit in that range or something? I have POSITION for that, so i would not use TEXCOORD for positions, but I ask in order to understand it better.

I'm not completely sure that I understood the question. Your vertex buffer input will not be clamped. The output from vertex shader to pixel shader will be clipped outside [-1; 1] range for SV_Position, because it specifies clip space positions. TEXCOORD semantic has absolutely no meaning, so no extra clamping will be done.

17 hours ago, turanszkij said:

For vertex shaders, the input semantic names have no meaning apart from reflection information. With shader reflection API, you can retrieve semantics and maybe do some engine-specific logic on them. Also, it is good to have meaningful semantic names, because if you enable the debug layer, it will output semantic names in the error messages if there are mismatching input/outputs in different shader stages.

That makes it sound like there isn't still a good reason that the semantics still exist. They're still required for binding the Input Layout to the Vertex Shader. A struct declared in a shader needs to markup the members of that struct such that the driver/hardware know which member corresponds to which element in the input layout. A VS_INPUT struct can declare its elements in any order and even omit elements that may be included in the input layout, the mapping from the Input Layout to the VS Input is handled by the input semantic names and without them some other system would need to be added to achieve this.

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

This topic is closed to new replies.

Advertisement