One of the new features of D3D11.1 was the offline shader compilation and the debugging utilities. I decided to try this out on Visual Studio 2012.
The shader compilation is pretty good. The only thing is you have write each shader separately and build them in separate files (unless you use effects). For each file you have to specify the shader model, entry point, which shader type etc by right clicking on the file and choosing properties. The good thing is once all that is done, only thing remaining is to load the shader binary into a blob at runtime, and rest is the same. You can also specify where the compiled shader binaries should go.
One way to design the shaders now is to put only the entry points in separate files and put all the functions, constant buffers, samplers in a common file. This way, you can avoid recoding the same functions.
Unfortunately i was not able to check out the debugging utilities as I had the express version, and the utilities are only available in the Retail versions :(.
Log of all my real time graphics experiments, goof ups and journey to create the perfect virtual world.
Friday, December 28, 2012
Shader Reflection using ID3D11ShaderReflection
Merry Christmas and a Happy New Year to all!!
It's been some time since i wrote my last blog. There's been a lot of work lately and I haven't been able to dedicate any time to my hobby engine and to this blog. Now that I'm on vacation, I got to spend some time with the engine.With my new laptop, Windows 8 with DirectX 11.1 and some work experience , I decided to rewrite my whole engine from scratch, and see if I could design a better engine.
One of the first thoughts about the old engine was that the shader system was kind of clunky. With all the hard-coded resource bindings (like constant buffers, textures etc), I was not able to get far with the existing system. So I decided to spend a little time to investigate how to manage the shader system better. After some investigation I came across "Shader Reflection" mentioned on the Microsoft site and on a few blogs. After playing around with it, I found that it's possible to analyze the entire shader from within the engine and it was the perfect solution to the problem.
So, what is shader Reflection? According to http://msdn.microsoft.com/en-us/library/windows/desktop/ff476590(v=vs.85).aspx, "ID3D11ShaderReflection" is basically an interface to access shader information. This means that you can figure out the following:
1. Constant Buffer Information ( constants used, register bindings etc)
2. Texture Sampler Information
3. Instruction Counts for Performance measuring
4. Input Layout Generation
and a whole lot more.
Here's the line that gets the shader reflection:
HRESULT hr = D3DReflect( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), IID_ID3D11ShaderReflection, (void**) &ppShaderReflection );
where pBlob is ID3DBlob* which gets loaded from a file or created during runtime by compiling a shader.
So now that I had access to this information, figuring out the details of the shader was so simple. I was able to dynamically generate the input layout and set up the constant buffer information. Now it's possible for different shaders to access the same constant buffer information, without storing separate buffer information for each one of them (from engine side). Plus, at the point of binding, I could figure out which register the constant buffer is used and then bind the information to that register itself. All this without any sort of hard-coding !!
For Input Layout Information:
http://takinginitiative.net/2011/12/11/directx-1011-basic-shader-reflection-automatic-input-layout-creation/
Here's a code snippet on how to access the constant buffer information:
D3D11_SHADER_DESC shaderDesc;
pShaderReflection->GetDesc(&shaderDesc);
HRESULT hr;
for(UINT i=0; i< shaderDesc.ConstantBuffers; i++)
{
D3D11_SHADER_BUFFER_DESC bufferDesc;
ID3D11ShaderReflectionConstantBuffer* pConstantBuffer = m_pShaderReflection->GetConstantBufferByIndex(i);
//This has the buffer description
hr = pConstantBuffer->GetDesc(&bufferDesc);
//Access to register binding
D3D11_SHADER_INPUT_BIND_DESC bindDesc;
hr = pShaderReflection->GetResourceBindingDescByName(bufferDesc.Name, &bindDesc);
for(UINT j=0; j< bufferDesc.Variables; j++)
{
ID3D11ShaderReflectionVariable* pVariable = pConstantBuffer->GetVariableByIndex(j);
//Access to variable information
D3D11_SHADER_VARIABLE_DESC variableDesc;
pVariable->GetDesc(&variableDesc);
}
}
So, when the shader is bound, all the constant buffers it uses, will get updated with the new information and they will get bound to the right register. Right now I've been playing only with the constant buffer information, but i presume that the texture samplers will also be the same. I'll keep posting on any more details about shader reflection.
So if you're looking into writing a more flexible shader system, I'd suggest you to look into this whole interface. If you have any questions regarding the design of my new engine, or this interface, feel free to post on this blog.
Following are some links that helped me out:
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476590(v=vs.85).aspx
http://members.gamedev.net/JasonZ/Heiroglyph/D3D11ShaderReflection.pdf
It's been some time since i wrote my last blog. There's been a lot of work lately and I haven't been able to dedicate any time to my hobby engine and to this blog. Now that I'm on vacation, I got to spend some time with the engine.With my new laptop, Windows 8 with DirectX 11.1 and some work experience , I decided to rewrite my whole engine from scratch, and see if I could design a better engine.
One of the first thoughts about the old engine was that the shader system was kind of clunky. With all the hard-coded resource bindings (like constant buffers, textures etc), I was not able to get far with the existing system. So I decided to spend a little time to investigate how to manage the shader system better. After some investigation I came across "Shader Reflection" mentioned on the Microsoft site and on a few blogs. After playing around with it, I found that it's possible to analyze the entire shader from within the engine and it was the perfect solution to the problem.
So, what is shader Reflection? According to http://msdn.microsoft.com/en-us/library/windows/desktop/ff476590(v=vs.85).aspx, "ID3D11ShaderReflection" is basically an interface to access shader information. This means that you can figure out the following:
1. Constant Buffer Information ( constants used, register bindings etc)
2. Texture Sampler Information
3. Instruction Counts for Performance measuring
4. Input Layout Generation
and a whole lot more.
Here's the line that gets the shader reflection:
HRESULT hr = D3DReflect( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), IID_ID3D11ShaderReflection, (void**) &ppShaderReflection );
where pBlob is ID3DBlob* which gets loaded from a file or created during runtime by compiling a shader.
So now that I had access to this information, figuring out the details of the shader was so simple. I was able to dynamically generate the input layout and set up the constant buffer information. Now it's possible for different shaders to access the same constant buffer information, without storing separate buffer information for each one of them (from engine side). Plus, at the point of binding, I could figure out which register the constant buffer is used and then bind the information to that register itself. All this without any sort of hard-coding !!
For Input Layout Information:
http://takinginitiative.net/2011/12/11/directx-1011-basic-shader-reflection-automatic-input-layout-creation/
Here's a code snippet on how to access the constant buffer information:
D3D11_SHADER_DESC shaderDesc;
pShaderReflection->GetDesc(&shaderDesc);
HRESULT hr;
for(UINT i=0; i< shaderDesc.ConstantBuffers; i++)
{
D3D11_SHADER_BUFFER_DESC bufferDesc;
ID3D11ShaderReflectionConstantBuffer* pConstantBuffer = m_pShaderReflection->GetConstantBufferByIndex(i);
//This has the buffer description
hr = pConstantBuffer->GetDesc(&bufferDesc);
//Access to register binding
D3D11_SHADER_INPUT_BIND_DESC bindDesc;
hr = pShaderReflection->GetResourceBindingDescByName(bufferDesc.Name, &bindDesc);
for(UINT j=0; j< bufferDesc.Variables; j++)
{
ID3D11ShaderReflectionVariable* pVariable = pConstantBuffer->GetVariableByIndex(j);
//Access to variable information
D3D11_SHADER_VARIABLE_DESC variableDesc;
pVariable->GetDesc(&variableDesc);
}
}
So, when the shader is bound, all the constant buffers it uses, will get updated with the new information and they will get bound to the right register. Right now I've been playing only with the constant buffer information, but i presume that the texture samplers will also be the same. I'll keep posting on any more details about shader reflection.
So if you're looking into writing a more flexible shader system, I'd suggest you to look into this whole interface. If you have any questions regarding the design of my new engine, or this interface, feel free to post on this blog.
Following are some links that helped me out:
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476590(v=vs.85).aspx
http://members.gamedev.net/JasonZ/Heiroglyph/D3D11ShaderReflection.pdf
Saturday, June 23, 2012
Animations using Instancing and Compute Shaders
The concept of Instancing was brought about in DX9, where using the same mesh you could render it again. Compute shaders was brought about when DX11 was introduced as a way to use the GPU to process non-graphics computations.
I decided that I wanted to use these features for animating my meshes. Instancing was useful because I wanted to render the same mesh in different places without using different draw calls for each mesh. And Compute shaders was very useful for computing the positions of the bones. In this case, I wanted to perform the bone computations for all the meshes in the same scene at the same time.
The use of unordered access buffers in the compute shaders made it possible for me to define a structure for the update of bones. I used this to update the bones of all the meshes.
And the use of structured buffers in the pixel shaders made it possible to read the data in anyway we wanted it to be.
In this case, I used the instance ID of the mesh to index into the bones buffer. And with GPU Skinning, the meshes are all animated
So with the combination of compute shaders for the update of skeletons, and instancing to render all the meshes alongwith their animations, I was able to animate and render 101 meshes with just one update and one draw call.
Following is a video of the result.
One major drawback for this method is that we have to load all the keyframes into the GPU when performing the Update for the skeleton.
I decided that I wanted to use these features for animating my meshes. Instancing was useful because I wanted to render the same mesh in different places without using different draw calls for each mesh. And Compute shaders was very useful for computing the positions of the bones. In this case, I wanted to perform the bone computations for all the meshes in the same scene at the same time.
The use of unordered access buffers in the compute shaders made it possible for me to define a structure for the update of bones. I used this to update the bones of all the meshes.
And the use of structured buffers in the pixel shaders made it possible to read the data in anyway we wanted it to be.
In this case, I used the instance ID of the mesh to index into the bones buffer. And with GPU Skinning, the meshes are all animated
So with the combination of compute shaders for the update of skeletons, and instancing to render all the meshes alongwith their animations, I was able to animate and render 101 meshes with just one update and one draw call.
Following is a video of the result.
Basic Animations
I started off constructing my basic engine. This involved setting up of the keyboard, camera handling, creation of various buffers, rendertargets etc. This was like the standard way of creating the engine.
I wanted to learn about how animations are done in graphics. So I started looking at various examples that involved animation a model based on some clip and keyframe animation and I came across the simple format from Microsoft - X Format.
http://paulbourke.net/dataformats/directx/ is a good reference for the .X Format.
Step 1: Load and render the mesh from .X file:
This step will help us see what the mesh will look like in a T-Pose.
Step 2: Load the skeleton from the .X file:
This step will load the skeleton the from the file which will be used to skin the skeleton
Step 3: Perform GPU Skinning and use weights from .X file:
A shader performs this step.
Step 4: Load the animation clips and apply movement data to the skeleton
Once this step is done, then the skeleton will be animated, which in turns animates the model. The principles of Articulated figures is used in this step.
Here is a snapshot of what the model and the skeleton looks like:
I should give credit to Microsoft for providing this model from their DirectX SDK.
Step 5: Now I use the keyboard input to identify what animation clip to play. For Eg: if i press "Up" it plays the walk animation. If no key is pressed, it plays the idle animation.
Only issue here is that the skeleton would suddenly start the next animation which results in a "pop" in the movement.
One way to get rid of this pop is to perform a Linear Interpolation (lerp) for some time between both the animations, during the transition. This results in a much smoother change, and looks much better. Below is a video of that demonstration.
This was my first step :). More to come soon.
I wanted to learn about how animations are done in graphics. So I started looking at various examples that involved animation a model based on some clip and keyframe animation and I came across the simple format from Microsoft - X Format.
http://paulbourke.net/dataformats/directx/ is a good reference for the .X Format.
Step 1: Load and render the mesh from .X file:
This step will help us see what the mesh will look like in a T-Pose.
Step 2: Load the skeleton from the .X file:
This step will load the skeleton the from the file which will be used to skin the skeleton
Step 3: Perform GPU Skinning and use weights from .X file:
A shader performs this step.
Step 4: Load the animation clips and apply movement data to the skeleton
Once this step is done, then the skeleton will be animated, which in turns animates the model. The principles of Articulated figures is used in this step.
Here is a snapshot of what the model and the skeleton looks like:
I should give credit to Microsoft for providing this model from their DirectX SDK.
Step 5: Now I use the keyboard input to identify what animation clip to play. For Eg: if i press "Up" it plays the walk animation. If no key is pressed, it plays the idle animation.
Only issue here is that the skeleton would suddenly start the next animation which results in a "pop" in the movement.
One way to get rid of this pop is to perform a Linear Interpolation (lerp) for some time between both the animations, during the transition. This results in a much smoother change, and looks much better. Below is a video of that demonstration.
Friday, June 22, 2012
So far...
I had already started working on my DX11 engine a while back (starting a year ago) and I have made some advancements in my engine. It's still very much the beginning stage, but I will try my best to make it look like what you folks have seen on Unreal Engine 4, Square Enix's new engine, etc.
My focus is actually not on the engine, but just trying to learn how to implement various techniques. I will be posting up various topics on parts of my engine, and a recap of what I've done so far.
My focus is actually not on the engine, but just trying to learn how to implement various techniques. I will be posting up various topics on parts of my engine, and a recap of what I've done so far.
Thursday, June 21, 2012
Launch Blog
Hey everyone,
I have decided to start my own blog about my experiments and journey with real time graphics. I want to share my experience with everyone on such interesting topics. Please provide any feedback on my experiments, or my writing about them :)
I have decided to start my own blog about my experiments and journey with real time graphics. I want to share my experience with everyone on such interesting topics. Please provide any feedback on my experiments, or my writing about them :)
Subscribe to:
Posts (Atom)