public static void Init([NativeTypeName("D3D12_ROOT_SIGNATURE_DESC &")] out D3D12_ROOT_SIGNATURE_DESC desc, uint numParameters, [NativeTypeName("const D3D12_ROOT_PARAMETER *")] D3D12_ROOT_PARAMETER *_pParameters, uint numStaticSamplers = 0, [NativeTypeName("const D3D12_STATIC_SAMPLER_DESC *")] D3D12_STATIC_SAMPLER_DESC *_pStaticSamplers = null, D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_NONE)
 {
     desc.NumParameters     = numParameters;
     desc.pParameters       = _pParameters;
     desc.NumStaticSamplers = numStaticSamplers;
     desc.pStaticSamplers   = _pStaticSamplers;
     desc.Flags             = flags;
 }
Beispiel #2
0
    protected override unsafe ID3D12RootSignature *CreateRootSignature()
    {
        using ComPtr <ID3DBlob> signature = null;
        using ComPtr <ID3DBlob> error     = null;

        var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC {
            Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT
        };

        ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, signature.GetAddressOf(), error.GetAddressOf()));

        ID3D12RootSignature *rootSignature;

        ThrowIfFailed(D3DDevice->CreateRootSignature(nodeMask: 0, signature.Get()->GetBufferPointer(), signature.Get()->GetBufferSize(), __uuidof <ID3D12RootSignature>(), (void **)&rootSignature));

        return(rootSignature);
    }
Beispiel #3
0
        /// <summary>
        /// Creates a new <see cref="RootSignature"/>
        /// </summary>
        /// <param name="device">The <see cref="ID3D12Device"/> used to create the root signature</param>
        /// <param name="rootParameters">The <see cref="RootParameter"/>s in the signature</param>
        /// <param name="staticSamplers">The <see cref="StaticSampler"/>s in the signature</param>
        /// <returns>A new <see cref="RootSignature"/></returns>
        public static RootSignature Create(ID3D12Device *device, ReadOnlyMemory <RootParameter> rootParameters, ReadOnlyMemory <StaticSampler> staticSamplers)
        {
            using var rootParams = RentedArray <D3D12_ROOT_PARAMETER> .Create(rootParameters.Length);

            using var samplers = RentedArray <D3D12_STATIC_SAMPLER_DESC> .Create(staticSamplers.Length);

            TranslateStaticSamplers(staticSamplers, samplers.Value);

            fixed(D3D12_ROOT_PARAMETER *pRootParams = rootParams.Value)
            fixed(D3D12_STATIC_SAMPLER_DESC * pSamplerDesc = samplers.Value)
            {
                var desc = new D3D12_ROOT_SIGNATURE_DESC
                {
                    NumParameters     = (uint)rootParams.Value.Length,
                    pParameters       = pRootParams,
                    NumStaticSamplers = (uint)samplers.Value.Length,
                    pStaticSamplers   = pSamplerDesc,
                    Flags             = D3D12_ROOT_SIGNATURE_FLAGS.D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT // TODO provide finer grained control
                };

                ID3DBlob *pBlob  = default;
                ID3DBlob *pError = default;
                int       hr     = Windows.D3D12SerializeRootSignature(
                    &desc,
                    D3D_ROOT_SIGNATURE_VERSION.D3D_ROOT_SIGNATURE_VERSION_1,
                    &pBlob,
                    &pError
                    );

                if (Windows.FAILED(hr))
                {
                    ThrowHelper.ErrorWithBlob(hr, pError);
                }

                using ComPtr <ID3D12RootSignature> rootSig = default;
                Guard.ThrowIfFailed(device->CreateRootSignature(
                                        0 /* TODO: MULTI-GPU */,
                                        pBlob->GetBufferPointer(),
                                        pBlob->GetBufferSize(),
                                        rootSig.Guid,
                                        ComPtr.GetVoidAddressOf(&rootSig)
                                        ));

                return(new RootSignature(rootSig.Move(), rootParameters, staticSamplers));
            }
        }
Beispiel #4
0
        // Load the sample assets.
        private void LoadAssets()
        {
            Guid      iid;
            ID3DBlob *signature    = null;
            ID3DBlob *error        = null;
            ID3DBlob *vertexShader = null;
            ID3DBlob *pixelShader  = null;

            try
            {
                // Create an empty root signature.
                {
                    var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC {
                        Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT
                    };

                    ThrowIfFailed(nameof(D3D12SerializeRootSignature), D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));

                    fixed(ID3D12RootSignature **rootSignature = &_rootSignature)
                    {
                        iid = IID_ID3D12RootSignature;
                        ThrowIfFailed(nameof(ID3D12Device.CreateRootSignature), _device->CreateRootSignature(nodeMask: 0, signature->GetBufferPointer(), signature->GetBufferSize(), &iid, (void **)rootSignature));
                    }
                }

                // Create the pipeline state, which includes compiling and loading shaders.
                {
                    var compileFlags = 0u;

#if DEBUG
                    // Enable better shader debugging with the graphics debugging tools.
                    compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
                    fixed(char *fileName = GetAssetFullPath(@"D3D12\Assets\Shaders\HelloTriangle.hlsl"))
                    {
                        var entryPoint = 0x00006E69614D5356;    // VSMain
                        var target     = 0x0000305F355F7376;    // vs_5_0

                        ThrowIfFailed(nameof(D3DCompileFromFile), D3DCompileFromFile((ushort *)fileName, pDefines: null, pInclude: null, (sbyte *)&entryPoint, (sbyte *)&target, compileFlags, Flags2: 0, &vertexShader, ppErrorMsgs: null));

                        entryPoint = 0x00006E69614D5350;        // PSMain
                        target     = 0x0000305F355F7370;        // ps_5_0
                        ThrowIfFailed(nameof(D3DCompileFromFile), D3DCompileFromFile((ushort *)fileName, pDefines: null, pInclude: null, (sbyte *)&entryPoint, (sbyte *)&target, compileFlags, Flags2: 0, &pixelShader, ppErrorMsgs: null));
                    }

                    // Define the vertex input layout.
                    const int InputElementDescsCount = 2;

                    var semanticName0 = stackalloc ulong[2] {
                        0x4E4F495449534F50,     // POSITION
                        0x0000000000000000,
                    };

                    var semanticName1 = stackalloc ulong[1] {
                        0x000000524F4C4F43,     // COLOR
                    };

                    var inputElementDescs = stackalloc D3D12_INPUT_ELEMENT_DESC[InputElementDescsCount] {
                        new D3D12_INPUT_ELEMENT_DESC {
                            SemanticName   = (sbyte *)semanticName0,
                            Format         = DXGI_FORMAT_R32G32B32_FLOAT,
                            InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
                        },
                        new D3D12_INPUT_ELEMENT_DESC {
                            SemanticName      = (sbyte *)semanticName1,
                            Format            = DXGI_FORMAT_R32G32B32A32_FLOAT,
                            AlignedByteOffset = 12,
                            InputSlotClass    = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
                        },
                    };

                    // Describe and create the graphics pipeline state object (PSO).
                    var psoDesc = new D3D12_GRAPHICS_PIPELINE_STATE_DESC {
                        InputLayout = new D3D12_INPUT_LAYOUT_DESC {
                            pInputElementDescs = inputElementDescs,
                            NumElements        = InputElementDescsCount,
                        },
                        pRootSignature        = _rootSignature,
                        VS                    = new D3D12_SHADER_BYTECODE(vertexShader),
                        PS                    = new D3D12_SHADER_BYTECODE(pixelShader),
                        RasterizerState       = D3D12_RASTERIZER_DESC.DEFAULT,
                        BlendState            = D3D12_BLEND_DESC.DEFAULT,
                        DepthStencilState     = D3D12_DEPTH_STENCIL_DESC.DEFAULT,
                        SampleMask            = uint.MaxValue,
                        PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
                        NumRenderTargets      = 1,
                        SampleDesc            = new DXGI_SAMPLE_DESC(count: 1, quality: 0),
                    };
                    psoDesc.DepthStencilState.DepthEnable = FALSE;
                    psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;

                    fixed(ID3D12PipelineState **pipelineState = &_pipelineState)
                    {
                        iid = IID_ID3D12PipelineState;
                        ThrowIfFailed(nameof(ID3D12Device.CreateGraphicsPipelineState), _device->CreateGraphicsPipelineState(&psoDesc, &iid, (void **)pipelineState));
                    }
                }

                // Create the command list.
                fixed(ID3D12GraphicsCommandList **commandList = &_commandList)
                {
                    iid = IID_ID3D12GraphicsCommandList;
                    ThrowIfFailed(nameof(ID3D12Device.CreateCommandList), _device->CreateCommandList(nodeMask: 0, D3D12_COMMAND_LIST_TYPE_DIRECT, _commandAllocator, _pipelineState, &iid, (void **)commandList));
                }

                // Command lists are created in the recording state, but there is nothing
                // to record yet. The main loop expects it to be closed, so close it now.
                ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), _commandList->Close());

                // Create the vertex buffer.
                {
                    // Define the geometry for a triangle.
                    const int TriangleVerticesCount = 3;
                    var       triangleVertices      = stackalloc Vertex[TriangleVerticesCount] {
                        new Vertex {
                            Position = new Vector3(0.0f, 0.25f * AspectRatio, 0.0f),
                            Color    = new Vector4(1.0f, 0.0f, 0.0f, 1.0f)
                        },
                        new Vertex {
                            Position = new Vector3(0.25f, -0.25f * AspectRatio, 0.0f),
                            Color    = new Vector4(0.0f, 1.0f, 0.0f, 1.0f)
                        },
                        new Vertex {
                            Position = new Vector3(-0.25f, -0.25f * AspectRatio, 0.0f),
                            Color    = new Vector4(0.0f, 0.0f, 1.0f, 1.0f)
                        },
                    };

                    var vertexBufferSize = (uint)sizeof(Vertex) * TriangleVerticesCount;

                    // Note: using upload heaps to transfer static data like vert buffers is not
                    // recommended. Every time the GPU needs it, the upload heap will be marshalled
                    // over. Please read up on Default Heap usage. An upload heap is used here for
                    // code simplicity and because there are very few verts to actually transfer.
                    fixed(ID3D12Resource **vertexBuffer = &_vertexBuffer)
                    {
                        var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
                        var bufferDesc     = D3D12_RESOURCE_DESC.Buffer(vertexBufferSize);

                        iid = IID_ID3D12Resource;
                        ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), _device->CreateCommittedResource(
                                          &heapProperties,
                                          D3D12_HEAP_FLAG_NONE,
                                          &bufferDesc,
                                          D3D12_RESOURCE_STATE_GENERIC_READ,
                                          pOptimizedClearValue: null,
                                          &iid,
                                          (void **)vertexBuffer
                                          ));
                    }

                    // Copy the triangle data to the vertex buffer.
                    var readRange = new D3D12_RANGE();

                    byte *pVertexDataBegin;
                    ThrowIfFailed(nameof(ID3D12Resource.Map), _vertexBuffer->Map(Subresource: 0, &readRange, (void **)&pVertexDataBegin));
                    Unsafe.CopyBlock(pVertexDataBegin, triangleVertices, vertexBufferSize);
                    _vertexBuffer->Unmap(0, null);

                    // Initialize the vertex buffer view.
                    _vertexBufferView.BufferLocation = _vertexBuffer->GetGPUVirtualAddress();
                    _vertexBufferView.StrideInBytes  = (uint)sizeof(Vertex);
                    _vertexBufferView.SizeInBytes    = vertexBufferSize;
                }

                // Create and record the bundle.
                {
                    fixed(ID3D12GraphicsCommandList **ppBundle = &_bundle)
                    {
                        iid = IID_ID3D12GraphicsCommandList;
                        ThrowIfFailed(nameof(ID3D12Device.CreateCommandList), _device->CreateCommandList(nodeMask: 0, D3D12_COMMAND_LIST_TYPE_BUNDLE, _bundleAllocator, _pipelineState, &iid, (void **)ppBundle));
                    }

                    _bundle->SetGraphicsRootSignature(_rootSignature);
                    _bundle->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

                    fixed(D3D12_VERTEX_BUFFER_VIEW *vertexBufferView = &_vertexBufferView)
                    {
                        _bundle->IASetVertexBuffers(StartSlot: 0, 1, vertexBufferView);
                    }

                    _bundle->DrawInstanced(3, 1, 0, 0);
                    ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), _bundle->Close());
                }

                // Create synchronization objects and wait until assets have been uploaded to the GPU.
                {
                    fixed(ID3D12Fence **fence = &_fence)
                    {
                        iid = IID_ID3D12Fence;
                        ThrowIfFailed(nameof(ID3D12Device.CreateFence), _device->CreateFence(0, D3D12_FENCE_FLAG_NONE, &iid, (void **)fence));
                        _fenceValue = 1;
                    }

                    // Create an event handle to use for frame synchronization.
                    _fenceEvent = CreateEventW(lpEventAttributes: null, bManualReset: FALSE, bInitialState: FALSE, lpName: null);
                    if (_fenceEvent == null)
                    {
                        var hr = Marshal.GetHRForLastWin32Error();
                        Marshal.ThrowExceptionForHR(hr);
                    }

                    // Wait for the command list to execute; we are reusing the same command
                    // list in our main loop but for now, we just want to wait for setup to
                    // complete before continuing.
                    WaitForPreviousFrame();
                }
            }
            finally
            {
                if (signature != null)
                {
                    signature->Release();
                }

                if (error != null)
                {
                    error->Release();
                }

                if (vertexShader != null)
                {
                    vertexShader->Release();
                }

                if (pixelShader != null)
                {
                    pixelShader->Release();
                }
            }
        }
Beispiel #5
0
        private Pointer <ID3D12RootSignature> CreateD3D12RootSignature()
        {
            ThrowIfDisposedOrDisposing(_state, nameof(D3D12GraphicsPipelineSignature));

            ID3DBlob *rootSignatureBlob      = null;
            ID3DBlob *rootSignatureErrorBlob = null;

            try
            {
                ID3D12RootSignature *d3d12RootSignature;

                var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC {
                    Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT,
                };

                var resources       = Resources;
                var resourcesLength = resources.Length;

                var rootParametersLength = 0;
                var staticSamplersLength = 0;

                var rootParametersIndex    = 0;
                var constantShaderRegister = 0;
                var textureShaderRegister  = 0;
                var staticSamplersIndex    = 0;

                for (var inputIndex = 0; inputIndex < resourcesLength; inputIndex++)
                {
                    rootParametersLength++;

                    if (resources[inputIndex].Kind == GraphicsPipelineResourceKind.Texture)
                    {
                        staticSamplersLength++;
                    }
                }

                var rootParameters   = stackalloc D3D12_ROOT_PARAMETER[rootParametersLength];
                var staticSamplers   = stackalloc D3D12_STATIC_SAMPLER_DESC[staticSamplersLength];
                var descriptorRanges = stackalloc D3D12_DESCRIPTOR_RANGE[staticSamplersLength];

                for (var inputIndex = 0; inputIndex < resourcesLength; inputIndex++)
                {
                    var input = resources[inputIndex];

                    switch (input.Kind)
                    {
                    case GraphicsPipelineResourceKind.ConstantBuffer:
                    {
                        var shaderVisibility = GetD3D12ShaderVisiblity(input.ShaderVisibility);
                        rootParameters[rootParametersIndex].InitAsConstantBufferView(unchecked ((uint)constantShaderRegister), registerSpace: 0, shaderVisibility);

                        constantShaderRegister++;
                        rootParametersIndex++;
                        break;
                    }

                    case GraphicsPipelineResourceKind.Texture:
                    {
                        descriptorRanges[staticSamplersIndex] = new D3D12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, numDescriptors: 1, baseShaderRegister: unchecked ((uint)textureShaderRegister));
                        var shaderVisibility = GetD3D12ShaderVisiblity(input.ShaderVisibility);

                        rootParameters[rootParametersIndex].InitAsDescriptorTable(1, &descriptorRanges[staticSamplersIndex], shaderVisibility);
                        staticSamplers[staticSamplersIndex] = new D3D12_STATIC_SAMPLER_DESC(
                            shaderRegister: unchecked ((uint)staticSamplersIndex),
                            shaderVisibility: shaderVisibility
                            );

                        textureShaderRegister++;
                        rootParametersIndex++;
                        staticSamplersIndex++;
                        break;
                    }

                    default:
                    {
                        break;
                    }
                    }
                }

                rootSignatureDesc.NumParameters = unchecked ((uint)rootParametersLength);
                rootSignatureDesc.pParameters   = rootParameters;

                rootSignatureDesc.NumStaticSamplers = unchecked ((uint)staticSamplersLength);
                rootSignatureDesc.pStaticSamplers   = staticSamplers;

                ThrowExternalExceptionIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &rootSignatureErrorBlob), nameof(D3D12SerializeRootSignature));

                var iid = IID_ID3D12RootSignature;
                ThrowExternalExceptionIfFailed(Device.D3D12Device->CreateRootSignature(0, rootSignatureBlob->GetBufferPointer(), rootSignatureBlob->GetBufferSize(), &iid, (void **)&d3d12RootSignature), nameof(ID3D12Device.CreateRootSignature));

                return(d3d12RootSignature);
            }
            finally
            {
                ReleaseIfNotNull(rootSignatureErrorBlob);
                ReleaseIfNotNull(rootSignatureBlob);
            }
        private Pointer <ID3D12RootSignature> CreateD3D12RootSignature()
        {
            _state.ThrowIfDisposedOrDisposing();

            ID3DBlob *rootSignatureBlob      = null;
            ID3DBlob *rootSignatureErrorBlob = null;

            try
            {
                ID3D12RootSignature *d3d12RootSignature;

                var rootParameters = Array.Empty <D3D12_ROOT_PARAMETER>();

                var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC {
                    Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT,
                };

                var resources       = Resources;
                var resourcesLength = resources.Length;

                var rootParametersIndex    = 0;
                var constantShaderRegister = 0;

                if (resourcesLength != 0)
                {
                    rootParameters = new D3D12_ROOT_PARAMETER[resourcesLength];

                    for (var inputIndex = 0; inputIndex < resourcesLength; inputIndex++)
                    {
                        var input = resources[inputIndex];

                        switch (input.Kind)
                        {
                        case GraphicsPipelineResourceKind.ConstantBuffer:
                        {
                            var shaderVisibility = GetD3D12ShaderVisiblity(input.ShaderVisibility);
                            rootParameters[rootParametersIndex].InitAsConstantBufferView(unchecked ((uint)constantShaderRegister), registerSpace: 0, shaderVisibility);

                            constantShaderRegister++;
                            rootParametersIndex++;
                            break;
                        }

                        default:
                        {
                            break;
                        }
                        }
                    }
                }

                fixed(D3D12_ROOT_PARAMETER *pRootParameters = rootParameters)
                {
                    rootSignatureDesc.NumParameters = unchecked ((uint)rootParameters.Length);
                    rootSignatureDesc.pParameters   = pRootParameters;

                    ThrowExternalExceptionIfFailed(nameof(D3D12SerializeRootSignature), D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &rootSignatureErrorBlob));
                }

                var iid = IID_ID3D12RootSignature;
                ThrowExternalExceptionIfFailed(nameof(ID3D12Device.CreateRootSignature), D3D12GraphicsDevice.D3D12Device->CreateRootSignature(0, rootSignatureBlob->GetBufferPointer(), rootSignatureBlob->GetBufferSize(), &iid, (void **)&d3d12RootSignature));

                return(d3d12RootSignature);
            }
            finally
            {
                ReleaseIfNotNull(rootSignatureErrorBlob);
                ReleaseIfNotNull(rootSignatureBlob);
            }