Repository: shader-slang/slang
File: tools/render-test/render-test-main.cpp (C++)

Code before:
                // TODO: In the future we should be more flexible and support matching
                // available attributes from arbitrary models/streams with the shader's
                // requirements.
                //
                const InputElementDesc allInputElements[] = {
                    {"A", 0, Format::RGB32Float, offsetof(Vertex, position)},
                    {"A", 1, Format::RGB32Float, offsetof(Vertex, color)},
                    {"A", 2, Format::RG32Float, offsetof(Vertex, uv)},
                    {"A", 3, Format::RGBA32Float, offsetof(Vertex, customData0)},
                    {"A", 4, Format::RGBA32Float, offsetof(Vertex, customData1)},
                    {"A", 5, Format::RGBA32Float, offsetof(Vertex, customData2)},
                    {"A", 6, Format::RGBA32Float, offsetof(Vertex, customData3)},
                };


                slang::IComponentType* slangProgram = m_compilationOutput.output.slangProgram;
                SLANG_ASSERT(slangProgram);
                if (nullptr == slangProgram)
                {
                    return SLANG_FAIL;
                }

                List<InputElementDesc> inputElements = filterInputElements(
                    allInputElements,
                    SLANG_COUNT_OF(allInputElements),
                    slangProgram->getLayout());


                ComPtr<IInputLayout> inputLayout;
                SLANG_RETURN_ON_FAIL(device->createInputLayout(
                    sizeof(Vertex),
                    inputElements.getBuffer(),
                    inputElements.getCount(),
                    inputLayout.writeRef()));

                BufferDesc vertexBufferDesc;
                vertexBufferDesc.size = kVertexCount * sizeof(Vertex);
                vertexBufferDesc.memoryType = MemoryType::DeviceLocal;
                vertexBufferDesc.usage = BufferUsage::VertexBuffer;
                vertexBufferDesc.defaultState = ResourceState::VertexBuffer;

                SLANG_RETURN_ON_FAIL(
                    device->createBuffer(vertexBufferDesc, kVertexData, m_vertexBuffer.writeRef()));

                ColorTargetDesc colorTarget;
                colorTarget.format = Format::RGBA8Unorm;
                RenderPipelineDesc desc;
                desc.program = m_shaderProgram;
                desc.inputLayout = inputLayout;
                desc.targets = &colorTarget;
                desc.targetCount = 1;

Review comment (bug):
Thanks for the fix. 
I guess the `output.slangProgram` could be nullptr in some cases.
I suggested not filtering if so, using the previous logic.

```suggestion
                if (nullptr == slangProgram)
                {
                    inputElements.addRange(allInputElements, SLANG_COUNT_OF(allInputElements));
                }
                else
                {
                    inputElements = filterInputElements(
                        allInputElements,
                        SLANG_COUNT_OF(allInputElements),
                        slangProgram->getLayout());
                } 
```

Code after:
                // TODO: In the future we should be more flexible and support matching
                // available attributes from arbitrary models/streams with the shader's
                // requirements.
                //
                const InputElementDesc allInputElements[] = {
                    {"A", 0, Format::RGB32Float, offsetof(Vertex, position)},
                    {"A", 1, Format::RGB32Float, offsetof(Vertex, color)},
                    {"A", 2, Format::RG32Float, offsetof(Vertex, uv)},
                    {"A", 3, Format::RGBA32Float, offsetof(Vertex, customData0)},
                    {"A", 4, Format::RGBA32Float, offsetof(Vertex, customData1)},
                    {"A", 5, Format::RGBA32Float, offsetof(Vertex, customData2)},
                    {"A", 6, Format::RGBA32Float, offsetof(Vertex, customData3)},
                };

                List<InputElementDesc> inputElements;
                if (slang::IComponentType* slangProgram = m_compilationOutput.output.slangProgram)
                {
                    inputElements = filterInputElements(
                        allInputElements,
                        SLANG_COUNT_OF(allInputElements),
                        slangProgram->getLayout());
                }
                else
                {
                    inputElements.addRange(allInputElements, SLANG_COUNT_OF(allInputElements));
                }

                ComPtr<IInputLayout> inputLayout;
                SLANG_RETURN_ON_FAIL(device->createInputLayout(
                    sizeof(Vertex),
                    inputElements.getBuffer(),
                    inputElements.getCount(),
                    inputLayout.writeRef()));

                BufferDesc vertexBufferDesc;
                vertexBufferDesc.size = kVertexCount * sizeof(Vertex);
                vertexBufferDesc.memoryType = MemoryType::DeviceLocal;
                vertexBufferDesc.usage = BufferUsage::VertexBuffer;
                vertexBufferDesc.defaultState = ResourceState::VertexBuffer;

                SLANG_RETURN_ON_FAIL(
                    device->createBuffer(vertexBufferDesc, kVertexData, m_vertexBuffer.writeRef()));

                ColorTargetDesc colorTarget;
                colorTarget.format = Format::RGBA8Unorm;
                RenderPipelineDesc desc;
                desc.program = m_shaderProgram;
                desc.inputLayout = inputLayout;
                desc.targets = &colorTarget;
                desc.targetCount = 1;
                desc.depthStencil.format = Format::D32Float;