void ShaderReflection::Reflect(ID3D10Blob* shader) { ID3D11ShaderReflection* reflector = 0; D3D11_SIGNATURE_PARAMETER_DESC input, output; D3D11_SHADER_INPUT_BIND_DESC resource; //Bind point is the register location D3DReflect(shader->GetBufferPointer(), shader->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&reflector); reflector->GetDesc(&shaderDesc); inputParams.paramCount = shaderDesc.InputParameters; inputParams.params = new D3D11_SIGNATURE_PARAMETER_DESC[inputParams.paramCount]; for(u32 i = 0; i < shaderDesc.InputParameters; ++i) { reflector->GetInputParameterDesc(i, &input); inputParams.params[i] = input; } outputParams.paramCount = shaderDesc.OutputParameters; outputParams.params = new D3D11_SIGNATURE_PARAMETER_DESC[outputParams.paramCount]; for(u32 i = 0; i < shaderDesc.OutputParameters; ++i) { reflector->GetOutputParameterDesc(i, &output); outputParams.params[i] = output; } for(u32 i = 0; i < shaderDesc.BoundResources; ++i) { reflector->GetResourceBindingDesc(i, &resource); if(resource.Type == D3D_SIT_CBUFFER) { ProcessCbuffer(reflector->GetConstantBufferByName(resource.Name)); } else if(resource.Type == D3D_SIT_SAMPLER) { } else if(resource.Type == D3D_SIT_TEXTURE) { } else {} } }
void ezShaderCompilerHLSL::ReflectShaderStage(ezShaderProgramData& inout_Data, ezGALShaderStage::Enum Stage) { ID3D11ShaderReflection* pReflector = nullptr; auto byteCode = inout_Data.m_StageBinary[Stage].GetByteCode(); D3DReflect(byteCode.GetData(), byteCode.GetCount(), IID_ID3D11ShaderReflection, (void**)&pReflector); D3D11_SHADER_DESC shaderDesc; pReflector->GetDesc(&shaderDesc); for (ezUInt32 r = 0; r < shaderDesc.BoundResources; ++r) { D3D11_SHADER_INPUT_BIND_DESC shaderInputBindDesc; pReflector->GetResourceBindingDesc(r, &shaderInputBindDesc); // ezLog::Info("Bound Resource: '{0}' at slot {1} (Count: {2}, Flags: {3})", sibd.Name, sibd.BindPoint, sibd.BindCount, sibd.uFlags); ezShaderResourceBinding shaderResourceBinding; shaderResourceBinding.m_Type = ezShaderResourceBinding::Unknown; shaderResourceBinding.m_iSlot = shaderInputBindDesc.BindPoint; shaderResourceBinding.m_sName.Assign(shaderInputBindDesc.Name); if (shaderInputBindDesc.Type == D3D_SIT_TEXTURE) { switch (shaderInputBindDesc.Dimension) { case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1D: shaderResourceBinding.m_Type = ezShaderResourceBinding::Texture1D; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1DARRAY: shaderResourceBinding.m_Type = ezShaderResourceBinding::Texture1DArray; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2D: shaderResourceBinding.m_Type = ezShaderResourceBinding::Texture2D; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DARRAY: shaderResourceBinding.m_Type = ezShaderResourceBinding::Texture2DArray; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DMS: shaderResourceBinding.m_Type = ezShaderResourceBinding::Texture2DMS; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DMSARRAY: shaderResourceBinding.m_Type = ezShaderResourceBinding::Texture2DMSArray; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE3D: shaderResourceBinding.m_Type = ezShaderResourceBinding::Texture3D; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURECUBE: shaderResourceBinding.m_Type = ezShaderResourceBinding::TextureCube; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURECUBEARRAY: shaderResourceBinding.m_Type = ezShaderResourceBinding::TextureCubeArray; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_BUFFER: shaderResourceBinding.m_Type = ezShaderResourceBinding::GenericBuffer; break; default: EZ_ASSERT_NOT_IMPLEMENTED; break; } } else if (shaderInputBindDesc.Type == D3D_SIT_UAV_RWTYPED) { switch (shaderInputBindDesc.Dimension) { case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1D: shaderResourceBinding.m_Type = ezShaderResourceBinding::RWTexture1D; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE1DARRAY: shaderResourceBinding.m_Type = ezShaderResourceBinding::RWTexture1DArray; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2D: shaderResourceBinding.m_Type = ezShaderResourceBinding::RWTexture2D; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_TEXTURE2DARRAY: shaderResourceBinding.m_Type = ezShaderResourceBinding::RWTexture2DArray; break; case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_BUFFER: case D3D_SRV_DIMENSION::D3D_SRV_DIMENSION_BUFFEREX: shaderResourceBinding.m_Type = ezShaderResourceBinding::RWBuffer; break; default: EZ_ASSERT_NOT_IMPLEMENTED; break; } } else if (shaderInputBindDesc.Type == D3D_SIT_UAV_RWSTRUCTURED) shaderResourceBinding.m_Type = ezShaderResourceBinding::RWStructuredBuffer; else if (shaderInputBindDesc.Type == D3D_SIT_UAV_RWBYTEADDRESS) shaderResourceBinding.m_Type = ezShaderResourceBinding::RWRawBuffer; else if (shaderInputBindDesc.Type == D3D_SIT_UAV_APPEND_STRUCTURED) shaderResourceBinding.m_Type = ezShaderResourceBinding::RWAppendBuffer; else if (shaderInputBindDesc.Type == D3D_SIT_UAV_CONSUME_STRUCTURED) shaderResourceBinding.m_Type = ezShaderResourceBinding::RWConsumeBuffer; else if (shaderInputBindDesc.Type == D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER) shaderResourceBinding.m_Type = ezShaderResourceBinding::RWStructuredBufferWithCounter; else if (shaderInputBindDesc.Type == D3D_SIT_CBUFFER) { shaderResourceBinding.m_Type = ezShaderResourceBinding::ConstantBuffer; shaderResourceBinding.m_pLayout = ReflectConstantBufferLayout(inout_Data.m_StageBinary[Stage], pReflector->GetConstantBufferByName(shaderInputBindDesc.Name)); } else if (shaderInputBindDesc.Type == D3D_SIT_SAMPLER) { shaderResourceBinding.m_Type = ezShaderResourceBinding::Sampler; if (ezStringUtils::EndsWith(shaderInputBindDesc.Name, "_AutoSampler")) { ezStringBuilder sb = shaderInputBindDesc.Name; sb.Shrink(0, ezStringUtils::GetStringElementCount("_AutoSampler")); shaderResourceBinding.m_sName.Assign(sb.GetData()); } } else { shaderResourceBinding.m_Type = ezShaderResourceBinding::GenericBuffer; } if (shaderResourceBinding.m_Type != ezShaderResourceBinding::Unknown) { inout_Data.m_StageBinary[Stage].AddShaderResourceBinding(shaderResourceBinding); } } pReflector->Release(); }
// Requires the compiled shaders (.cso files) DXShader::DXShader( string vertexPath, string fragmentPath ) { HRESULT result; ID3DBlob* shaderCompileErrors; // Layout description, must match layout in vertex shader const int numLayoutElements = 3; const D3D11_INPUT_ELEMENT_DESC vLayout[] = { /*POS*/ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, /*UV*/ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, /*NORMAL*/ { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; // ---- Load Vertex Shader ID3DBlob* vsb; wstring wVertexPath( vertexPath.begin(), vertexPath.end() ); ShaderInclude include( File( vertexPath ).GetDirectory() ); //D3DReadFileToBlob( wVertexPath.c_str(), &vsb ); result = D3DCompileFromFile( wVertexPath.c_str(), NULL, &include, "main", "vs_5_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, &vsb, &shaderCompileErrors ); if( FAILED(result) ) { OutputController::PrintMessage( OutputType::Error, "Error compiling vertex shader\n" + vertexPath ); OutputController::PrintMessage( OutputType::Error, (char*)(shaderCompileErrors->GetBufferPointer()) ); } result = AdapterController::Get()->GetDevice().dx->CreateVertexShader( vsb->GetBufferPointer(), vsb->GetBufferSize(), NULL, &vertexShader ); if( FAILED(result) ) { OutputController::PrintMessage( OutputType::Error, "Failed to create vertex shader." ); } // Create Input Layout result = AdapterController::Get()->GetDevice().dx->CreateInputLayout( vLayout, numLayoutElements,//ARRAYSIZE(vertexLayout), vsb->GetBufferPointer(), vsb->GetBufferSize(), &vertexLayout ); if( FAILED(result) ) { OutputController::PrintMessage( OutputType::Error, "Failed to create input layout." ); } // ---- Load Pixel Shader ID3DBlob* psb; wstring wPixelPath( fragmentPath.begin(), fragmentPath.end() ); //D3DReadFileToBlob( wPixelPath.c_str(), &psb ); result = D3DCompileFromFile( wPixelPath.c_str(), NULL, &include, "main", "ps_5_0", D3DCOMPILE_ENABLE_STRICTNESS, 0, &psb, &shaderCompileErrors ); if( FAILED(result) ) { OutputController::PrintMessage( OutputType::Error, "Error compiling fragment shader\n" + fragmentPath ); OutputController::PrintMessage( OutputType::Error, (gChar*)(shaderCompileErrors->GetBufferPointer()) ); } result = AdapterController::Get()->GetDevice().dx->CreatePixelShader( psb->GetBufferPointer(), psb->GetBufferSize(), NULL, &pixelShader ); if( FAILED(result) ) { OutputController::PrintMessage( OutputType::Error, "Failed to create fragment shader." ); } // get constant buffer variables ID3D11ShaderReflection* vsReflection = nullptr; D3D11Reflect( vsb->GetBufferPointer(), vsb->GetBufferSize(), &vsReflection ); D3D11_SHADER_BUFFER_DESC vsShaderBufferDesc; vsReflection->GetConstantBufferByName( "uniforms" )->GetDesc( &vsShaderBufferDesc ); vsShaderBufferDesc.Name; UINT numVariables = vsShaderBufferDesc.Variables; ID3D11ShaderReflectionVariable* var2 = vsReflection->GetConstantBufferByName( "uniforms" )->GetVariableByIndex( 2 ); D3D11_SHADER_VARIABLE_DESC var2Desc; var2->GetDesc( &var2Desc ); var2Desc.Name; var2Desc.Size; ID3D11ShaderReflectionType* var2Type = var2->GetType(); var2Type->GetMemberTypeByIndex(0); // ---- Create Sampler State D3D11_SAMPLER_DESC samplerDesc; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.MipLODBias = 0.0f; samplerDesc.MaxAnisotropy = 1; samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; samplerDesc.BorderColor[0] = 0; samplerDesc.BorderColor[1] = 0; samplerDesc.BorderColor[2] = 0; samplerDesc.BorderColor[3] = 0; samplerDesc.MinLOD = 0; samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; result = AdapterController::Get()->GetDevice().dx->CreateSamplerState( &samplerDesc, &samplerState ); if( FAILED(result) ) { OutputController::PrintMessage( OutputType::Error, "Failed to create sampler state." ); } // release unneeded buffers ReleaseCOMobjMacro( psb ); ReleaseCOMobjMacro( vsb ); ReleaseCOMobjMacro( shaderCompileErrors ); // TEMPORARY BUFFER TO BE REMOVED FROM C++ SIDE auto buf = new ConstBuffer; buf->totalSize = 0; buf->AddProperty( "modelViewProj", sizeof(Matrix4) ); buf->AddProperty( "rotationMatrix", sizeof(Matrix4) ); buf->AddProperty( "ambientLight", AmbientLight::size ); buf->AddProperty( "dirLight", DirectionalLight::size ); RegisterConstBuffer( "uniforms", buf ); delete buf; }
//------------------------------------------------------------------------------- // @ IvConstantTableD3D11::Create() //------------------------------------------------------------------------------- // Get the constant table for this shader //------------------------------------------------------------------------------- IvConstantTableD3D11* IvConstantTableD3D11::Create(ID3D11Device* device, ID3DBlob* code) { ID3D11ShaderReflection* pReflector = nullptr; D3DReflect(code->GetBufferPointer(), code->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&pReflector); // first get constant table IvConstantTableD3D11* table = new IvConstantTableD3D11(); ID3D11ShaderReflectionConstantBuffer* globalConstants = pReflector->GetConstantBufferByName("$Globals"); D3D11_SHADER_BUFFER_DESC constantBufferDesc = { 0 }; HRESULT hr = globalConstants->GetDesc(&constantBufferDesc); if (FAILED(hr)) { // no constants in this shader goto get_textures; } table->mBacking = new char[constantBufferDesc.Size]; table->mBackingSize = constantBufferDesc.Size; if (nullptr == table->mBacking) { delete table; pReflector->Release(); return nullptr; } for (unsigned int i = 0; i < constantBufferDesc.Variables; ++i) { ID3D11ShaderReflectionVariable* var = globalConstants->GetVariableByIndex(i); D3D11_SHADER_VARIABLE_DESC varDesc; if (FAILED(var->GetDesc(&varDesc))) { delete table; pReflector->Release(); return nullptr; } ID3D11ShaderReflectionType* type = var->GetType(); D3D11_SHADER_TYPE_DESC typeDesc; if (FAILED(type->GetDesc(&typeDesc))) { delete table; pReflector->Release(); return nullptr; } IvConstantDesc constantDesc; constantDesc.mOffset = table->mBacking + varDesc.StartOffset; if (typeDesc.Class == D3D_SVC_SCALAR && typeDesc.Type == D3D_SVT_FLOAT) { constantDesc.mType = IvUniformType::kFloatUniform; } else if (typeDesc.Class == D3D_SVC_VECTOR && typeDesc.Type == D3D_SVT_FLOAT && typeDesc.Columns == 3) { constantDesc.mType = IvUniformType::kFloat3Uniform; } else if (typeDesc.Class == D3D_SVC_VECTOR && typeDesc.Type == D3D_SVT_FLOAT && typeDesc.Columns == 4) { constantDesc.mType = IvUniformType::kFloat4Uniform; } else if ((typeDesc.Class == D3D_SVC_MATRIX_ROWS || typeDesc.Class == D3D_SVC_MATRIX_COLUMNS) && typeDesc.Type == D3D_SVT_FLOAT && typeDesc.Rows == 4 && typeDesc.Columns == 4) { constantDesc.mType = IvUniformType::kFloatMatrix44Uniform; } else { // unsupported uniform type delete table; pReflector->Release(); return nullptr; } constantDesc.mCount = typeDesc.Elements != 0 ? typeDesc.Elements : 1; table->mConstants[varDesc.Name] = constantDesc; } D3D11_BUFFER_DESC cbDesc; cbDesc.ByteWidth = constantBufferDesc.Size; cbDesc.Usage = D3D11_USAGE_DYNAMIC; cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; cbDesc.MiscFlags = 0; cbDesc.StructureByteStride = 0; if (FAILED(device->CreateBuffer(&cbDesc, nullptr, &table->mBuffer))) { delete table; pReflector->Release(); return nullptr; } get_textures: // now get any textures and samplers D3D11_SHADER_DESC shaderDesc = { 0 }; hr = pReflector->GetDesc(&shaderDesc); if (FAILED(hr)) { pReflector->Release(); return table; } int resourceCount = shaderDesc.BoundResources; for (int i = 0; i < resourceCount; ++i) { D3D11_SHADER_INPUT_BIND_DESC bindingDesc = { 0 }; pReflector->GetResourceBindingDesc(i, &bindingDesc); if (bindingDesc.Type == D3D_SIT_TEXTURE && bindingDesc.ReturnType == D3D_RETURN_TYPE_FLOAT && bindingDesc.Dimension == D3D_SRV_DIMENSION_TEXTURE2D && bindingDesc.NumSamples == -1 && bindingDesc.BindCount == 1) { IvConstantDesc& constantDesc = table->mConstants[bindingDesc.Name]; constantDesc.mType = IvUniformType::kTextureUniform; constantDesc.mTextureSlot = bindingDesc.BindPoint; } else if (bindingDesc.Type == D3D_SIT_SAMPLER && bindingDesc.BindCount == 1) { char strippedName[256]; const char* samplerKeyword = strstr(bindingDesc.Name, "Sampler"); strncpy(strippedName, bindingDesc.Name, samplerKeyword - bindingDesc.Name); strippedName[samplerKeyword - bindingDesc.Name] = '\0'; IvConstantDesc& constantDesc = table->mConstants[strippedName]; constantDesc.mType = IvUniformType::kTextureUniform; constantDesc.mSamplerSlot = bindingDesc.BindPoint; } else if (bindingDesc.Type == D3D_SIT_CBUFFER && !_strnicmp(bindingDesc.Name, "$Globals", 8)) { // ignore this, we handled it above } else { // unsupported resource type delete table; pReflector->Release(); return nullptr; } } pReflector->Release(); return table; }