DirectX11 由 Reflect Shader 创建 InputLayout

    其实ID3D11ShaderReflection原本就能获取HLSL文件信息·由获取到的信息创建InputLayout其实是比较容易的·

  Reflection接口由函数D3DReflect创建·需要四个参数·分别是编译着色器时得到的 缓冲指针 · 缓冲大小 · GUID(也就是IID_ID3D11ShaderReflection) 和 ID3D11ShaderReflection接口·

    获得ID3D11ShaderReflection接口后·调用GetInputParameterDesc获得D3D11_SIGNATURE_PARAMETER_DESC结构体·然后依照信息填充D3D11_INPUT_ELEMENT_DESC就可以了·

以下是填充部分:

		D3D11_SHADER_DESC t_ShaderDesc;
		t_ShaderReflection->GetDesc(&t_ShaderDesc);

		std::vector<D3D11_INPUT_ELEMENT_DESC> t_InputElementDescVec;                                         //用什么存放实际上无所谓
		unsigned int t_ByteOffset = 0;

		for(int i = 0; i != t_ShaderDesc.InputParameters; ++i){
			D3D11_SIGNATURE_PARAMETER_DESC t_SP_DESC;
			t_ShaderReflection->GetInputParameterDesc(i, &t_SP_DESC);

			D3D11_INPUT_ELEMENT_DESC t_InputElementDesc;
			t_InputElementDesc.SemanticName = t_SP_DESC.SemanticName;
			t_InputElementDesc.SemanticIndex = t_SP_DESC.SemanticIndex;
			t_InputElementDesc.InputSlot = 0;
			t_InputElementDesc.AlignedByteOffset = t_ByteOffset;
			t_InputElementDesc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
			t_InputElementDesc.InstanceDataStepRate = 0;

			if( t_SP_DESC.Mask == 1 ){
				if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_UINT32 ){ 
					t_InputElementDesc.Format = DXGI_FORMAT_R32_UINT;
				}
				else if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_SINT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32_SINT;
				}
				else if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32_FLOAT;
				}
				t_ByteOffset += 4;
			}
			else if( t_SP_DESC.Mask <= 3 ){
				if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_UINT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32G32_UINT;
				}
				else if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_SINT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32G32_SINT;
				}
				else if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32G32_FLOAT;
				}
				t_ByteOffset += 8;
			}
			else if( t_SP_DESC.Mask <= 7 ){
				if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_UINT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32G32B32_UINT;
				}
				else if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_SINT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32G32B32_SINT;
				}
				else if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
				}
				t_ByteOffset += 12;
			}
			else if( t_SP_DESC.Mask <= 15 ){
				if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_UINT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32G32B32A32_UINT;
				}
				else if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_SINT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32G32B32A32_SINT;
				}
				else if ( t_SP_DESC.ComponentType == D3D_REGISTER_COMPONENT_FLOAT32 ){
					t_InputElementDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
				}
				t_ByteOffset += 16;
			}

			t_InputElementDescVec.push_back(t_InputElementDesc);
		}

 这样就可以获得所有D3D11_INPUT_ELEMENT_DESC信息·然后将t_InputElementDescVec作为参数调用CreateInputLayout创建ID3D11InputLayout就可以了·

注意下ComponentType要和Mask合起来判断Format就行了·

posted @ 2013-10-30 12:06  macom  阅读(913)  评论(0编辑  收藏  举报