directx-11vertex-shader.net-8.0silk

Primitive do not show up on screen


I have no idea why my code will not make a RED RECTANGLE appears on GREEN BACKGROUND.

<Program.cs>

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.


/////////////////////////////////////////////////////// PLEASE READ! ///////////////////////////////////////////////////
// This provides a basic example of using our Direct3D 11 bindings in their current form. These bindings are still    //
// improving over time, and as a result the content of this example may change.                                       //
// Notably:                                                                                                           //
// TODO remove Unsafe.NullRef once we've updated the bindings to not require it                                       //
// TODO investigate making the D3DPrimitiveTopology enum more user friendly                                           //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

using System.Text;
using System.Runtime.CompilerServices;
using Silk.NET.Core.Native;
using Silk.NET.Direct3D.Compilers;
using Silk.NET.Direct3D11;
using Silk.NET.DXGI;
using Silk.NET.Input;
using Silk.NET.Maths;
using Silk.NET.Windowing;
using SilkNetTest3;

var backgroundColour = new[] { 0.0f, 1.0f, 0.0f, 1.0f };
var shapeColor = new Vector4D<float>(1, 0, 0, 1);


VertexPositionColor[] vertices =
    [
        new VertexPositionColor(new Vector2D<float>(0.5f, 0.5f), shapeColor),
        new VertexPositionColor(new Vector2D<float>(0.5f, -0.5f), shapeColor),
        new VertexPositionColor(new Vector2D<float>(-0.5f, -0.5f), shapeColor),
        new VertexPositionColor(new Vector2D<float>(-0.5f, 0.5f), shapeColor)

    ];

uint[] indices =
[
    0, 1, 3,
    1, 2, 3
];

// Create a window.
var options = WindowOptions.Default;
options.Size = new Vector2D<int>(800, 600);
options.Title = "Learn Direct3D11 with Silk.NET";
options.API = GraphicsAPI.None; // <-- This bit is important, as your window will be configured for OpenGL by default.
var window = Window.Create(options);

// Load the DXGI and Direct3D11 libraries for later use.
// Given this is not tied to the window, this doesn't need to be done in the OnLoad event.
DXGI dxgi = null!;
D3D11 d3d11 = null!;
D3DCompiler compiler = null!;

// These variables are initialized within the Load event.
ComPtr<IDXGIFactory2> factory = default;
ComPtr<IDXGISwapChain1> swapchain = default;
ComPtr<ID3D11Device> device = default;
ComPtr<ID3D11DeviceContext> deviceContext = default;
ComPtr<ID3D11Buffer> vertexBuffer = default;
ComPtr<ID3D11Buffer> indexBuffer = default;
ComPtr<ID3D11VertexShader> vertexShader = default;
ComPtr<ID3D11PixelShader> pixelShader = default;
ComPtr<ID3D11InputLayout> inputLayout = default;

//ComPtr<ID3D11Texture2D> renderTexture = default;
//ComPtr<ID3D11RenderTargetView> renderTextureRTV = default;
//ComPtr<ID3D11ShaderResourceView> renderTextureSRV = default;

BasicShaders basicShaders = null;

// Assign events.
window.Load += OnLoad;
window.Update += OnUpdate;
window.Render += OnRender;
window.FramebufferResize += OnFramebufferResize;

// Run the window.
window.Run();

// Clean up any resources.
factory.Dispose();
swapchain.Dispose();
device.Dispose();
deviceContext.Dispose();
vertexBuffer.Dispose();
indexBuffer.Dispose();
vertexShader.Dispose();
pixelShader.Dispose();
inputLayout.Dispose();
compiler.Dispose();
d3d11.Dispose();
dxgi.Dispose();

//dispose the window, and its internal resources
window.Dispose();

unsafe void OnLoad()
{
    //Whether or not to force use of DXVK on platforms where native DirectX implementations are available
    const bool forceDxvk = false;

    dxgi = DXGI.GetApi(window, forceDxvk);
    d3d11 = D3D11.GetApi(window, forceDxvk);
    compiler = D3DCompiler.GetApi();

    // Set-up input context.
    var input = window.CreateInput();
    foreach (var keyboard in input.Keyboards)
    {
        keyboard.KeyDown += OnKeyDown;
    }

    // Create our D3D11 logical device.
    SilkMarshal.ThrowHResult
    (
        d3d11.CreateDevice
        (
            default(ComPtr<IDXGIAdapter>),
            D3DDriverType.Hardware,
            Software: default,
            (uint)CreateDeviceFlag.Debug,
            null,
            0,
            D3D11.SdkVersion,
            ref device,
            null,
            ref deviceContext
        )
    );

    //This is not supported under DXVK 
    //TODO: PR a stub into DXVK for this maybe?
    if (OperatingSystem.IsWindows())
    {
        // Log debug messages for this device (given that we've enabled the debug flag). Don't do this in release code!
        device.SetInfoQueueCallback(msg => Console.WriteLine(SilkMarshal.PtrToString((nint)msg.PDescription)));
    }

    // Create our swapchain.
    var swapChainDesc = new SwapChainDesc1
    {
        BufferCount = 2, // double buffered
        Format = Format.FormatB8G8R8A8Unorm,
        BufferUsage = DXGI.UsageRenderTargetOutput,
        SwapEffect = SwapEffect.FlipDiscard,
        SampleDesc = new SampleDesc(1, 0)
    };

    // Create our DXGI factory to allow us to create a swapchain. 
    factory = dxgi.CreateDXGIFactory<IDXGIFactory2>();

    // Create the swapchain.
    SilkMarshal.ThrowHResult
    (
        factory.CreateSwapChainForHwnd
        (
            device,
            window.Native!.DXHandle!.Value,
            in swapChainDesc,
            null,
            ref Unsafe.NullRef<IDXGIOutput>(),
            ref swapchain
        )
    );

    // ==============>

    vertexBuffer = BufferHelper.Create(device, vertices.Length * sizeof(VertexPositionColor), BindFlag.VertexBuffer,  0);
    indexBuffer = BufferHelper.Create(device, indices.Length * sizeof(uint), BindFlag.IndexBuffer, 0);

    // Load shaders
    basicShaders = new BasicShaders();
    basicShaders.Load(device);

    // ===============>

    // Define rasterizer
    var rsDesc = new RasterizerDesc()
    {
        FillMode = FillMode.Solid,
        CullMode = CullMode.None,
        FrontCounterClockwise = false,
        DepthBias = 0,
        DepthBiasClamp = 0,
        SlopeScaledDepthBias = 0,
        DepthClipEnable = false,
        // ScissorEnable = true require defining of scissors
        ScissorEnable = false,
        MultisampleEnable = true,
        AntialiasedLineEnable = true,
    };

    // Create Rasterizer
    ComPtr<ID3D11RasterizerState> rs = default;

    SilkMarshal.ThrowHResult(device.CreateRasterizerState(rsDesc, ref rs));


    // Set Rasterizer State
    deviceContext.RSSetState(rs);
}

void OnUpdate(double deltaSeconds)
{
    // Here all of the updates to program state ahead of rendering (e.g. physics) should be done. We don't have anything
    // to do here at the moment, so we've left it blank.
}

unsafe void OnFramebufferResize(Vector2D<int> newSize)
{
    // If the window resizes, we need to be sure to update the swapchain's back buffers.
    SilkMarshal.ThrowHResult
    (
        swapchain.ResizeBuffers(0, (uint)newSize.X, (uint)newSize.Y, Format.FormatB8G8R8A8Unorm, 0)
    );
}

unsafe void OnRender(double deltaSeconds)
{
    // Obtain the framebuffer for the swapchain's backbuffer.
    using var framebuffer = swapchain.GetBuffer<ID3D11Texture2D>(0);

    // Create a view over the render target.
    ComPtr<ID3D11RenderTargetView> renderTargetView = default;
    SilkMarshal.ThrowHResult(device.CreateRenderTargetView(framebuffer, null, ref renderTargetView));

    // Clear the render target to be all black ahead of rendering.
    deviceContext.ClearRenderTargetView(renderTargetView, ref backgroundColour[0]);

    // Update the rasterizer state with the current viewport.
    var viewport = new Viewport(0, 0, window.FramebufferSize.X, window.FramebufferSize.Y, 0, 1);
    deviceContext.RSSetViewports(1, in viewport);



    // Tell the output merger about our render target view.
    deviceContext.OMSetRenderTargets(1, ref renderTargetView, ref Unsafe.NullRef<ID3D11DepthStencilView>());

    // Update the input assembler to use our shader input layout, and associated vertex & index buffers.
    deviceContext.IASetPrimitiveTopology(D3DPrimitiveTopology.D3DPrimitiveTopologyTrianglelist);

    uint vertexStride = (uint)sizeof(VertexPositionColor);
    uint vertexOffset = 0U;

    deviceContext.IASetVertexBuffers(0, 1, vertexBuffer, in vertexStride, in vertexOffset);
    deviceContext.IASetIndexBuffer(indexBuffer, Format.FormatR32Uint, 0);

    // Bind our shaders. 
    basicShaders.BasicColorShader.ApplyShader();

    // Draw the quad.
    deviceContext.DrawIndexed(6, 0, 0);
    //deviceContext.Draw(3, 0);

    // Present the drawn image.
    swapchain.Present(1, 0);

    // Clean up any resources created in this method.
    renderTargetView.Dispose();
}

void OnKeyDown(IKeyboard keyboard, Key key, int scancode)
{
    // Check to close the window on escape.
    if (key == Key.Escape)
    {
        window.Close();
    }
}

I dropped whole project on github: https://github.com/Kordi3112/SilkNetTest3chrome---settings-searchEngines

I used: https://github.com/dotnet/Silk.NET/tree/main/examples/CSharp/Direct3D11%20Tutorials/Tutorial%201.2%20-%20Hello%20quad as a template, and made some classes to improve code visibility.

Template works fine

When I modify pixel shader and instead of returning of "input.col" (Color data from pixel shader) i type "return float4(1, 0, 0, 1)" and still nothing will show. Its seems as a problem with vertex buffer or input layout.


Solution

  • You allocate a vertex buffer and an index buffer, but you never copies data in them.

    So you want to replace these lines:

    vertexBuffer = BufferHelper.Create(device, vertices.Length * sizeof(VertexPositionColor), BindFlag.VertexBuffer,  0);
    indexBuffer = BufferHelper.Create(device, indices.Length * sizeof(uint), BindFlag.IndexBuffer, 0);
    

    by this, using vertices and indices data:

    vertexBuffer = BufferHelper.Create(device, vertices, vertices.Length * sizeof(VertexPositionColor), BindFlag.VertexBuffer, 0);
    indexBuffer = BufferHelper.Create(device, indices, indices.Length * sizeof(uint), BindFlag.IndexBuffer, 0);
    

    so they'll end up in this code:

    unsafe
    {
        // use the buffer data
        fixed (T* pData = data)
        {
            var subresourceData = new SubresourceData
            {
                PSysMem = pData
            };
    
            SilkMarshal.ThrowHResult(device.CreateBuffer(in bufferDesc, in subresourceData, ref buffer));
        }
    }