d3d11 triangle rendering failure despite everything being properly initialized

60 views Asked by At

learning how to use d3d11, using ComPtrs, no error checks is on purpose cause i just used breakpoints to see if everything waas being initialized which it was but nothing was being drawn to the window, debug flag flags no error or warnings, don't know how to spot the problem cause as far as i can tell everything is alright, just wanna see a triangle on the screen with under 200-250 line code, please help me solve this issue please.

#include <Windows.h>
#include <d3d11_1.h>
#include <wrl/client.h>
#include <d3dcompiler.h>
#pragma comment(lib, "d3dcompiler")
#pragma comment(lib, "d3d11")
#pragma comment(lib, "dxgi")

#define check(a) if(FAILED(a)) std::cout << "HRES ERROR!" << std::endl;

#define VSFile L"shader.sh"
#define FSFile L"shader.sh"

#include <iostream>
struct position {
    float x, y;
};
struct color {
    float r, g, b;
};

struct vertex {

    position pos;
    color col;

};

const vertex vertices[] = {


    {-1.0f,  1.0f,  0.0f, 1.0f, 0.0f},
    { 1.0f, -1.0f,  0.0f, 0.0f, 1.0f},
    {-1.0f, -1.0f,  1.0f, 0.0f, 0.0f},

};

int other(HINSTANCE hInstance);

LRESULT CALLBACK proc(HWND wnd, UINT msg, WPARAM wpr, LPARAM lpr) {
        switch (msg) {
        case WM_DESTROY: PostQuitMessage(0); break;
        default: return DefWindowProc(wnd, msg, wpr, lpr);
        }
        return 0;
    }
int main()
{
    
    WNDCLASS wc = {};
    wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB((255/2), (255 / 2), (255 / 2)));
    wc.lpfnWndProc = proc;
    wc.lpszClassName = L"class name";
    
    RegisterClass(&wc);

    RECT wndrect = {
        .left = 0, .top = 0,
        .right = 800, .bottom = 500
    };
    AdjustWindowRect(&wndrect, WS_OVERLAPPEDWINDOW, false);
    int width = wndrect.right - wndrect.left;
    int height = wndrect.bottom - wndrect.top;

    HWND hwnd = CreateWindow(wc.lpszClassName, L"window name", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, nullptr, nullptr, nullptr, nullptr);

    UnregisterClass(wc.lpszClassName, nullptr);

    Microsoft::WRL::ComPtr<IDXGIFactory1> factory = nullptr; 
    Microsoft::WRL::ComPtr<ID3D11Device> device = nullptr; 
    Microsoft::WRL::ComPtr<ID3D11DeviceContext> context = nullptr; {

        check(CreateDXGIFactory1(IID_PPV_ARGS(&factory)));
        Microsoft::WRL::ComPtr<IDXGIAdapter> adapter = nullptr;
        factory->EnumAdapters(0, adapter.GetAddressOf());
        check(D3D11CreateDevice(adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, 0, D3D11_CREATE_DEVICE_DEBUG, 0, 0, D3D11_SDK_VERSION, device.GetAddressOf(), 0, context.GetAddressOf()));
        DXGI_ADAPTER_DESC desc; check(adapter->GetDesc(&desc));
        std::wcout << desc.Description << std::endl;
    }
    Microsoft::WRL::ComPtr<ID3D11Buffer> vertex_buffer = nullptr; {

        D3D11_BUFFER_DESC desc = {}; {
            desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
            desc.ByteWidth = sizeof(vertices);
            desc.MiscFlags = 0;
            desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
            desc.StructureByteStride = sizeof(vertex);
            desc.Usage = D3D11_USAGE_DYNAMIC;
        }
                                                            
        D3D11_SUBRESOURCE_DATA data = {}; {

            data.pSysMem = &vertices;

        }
        check(device->CreateBuffer(&desc, &data, &vertex_buffer));
    }
    Microsoft::WRL::ComPtr<ID3D11VertexShader> vertex_shader = nullptr;
    Microsoft::WRL::ComPtr<ID3DBlob> vs = nullptr; {

        check(D3DCompileFromFile(VSFile, NULL, NULL, "vs_main", "vs_5_0", 0, 0, vs.GetAddressOf(), NULL));
        check(device->CreateVertexShader(vs->GetBufferPointer(), vs->GetBufferSize(), NULL, vertex_shader.GetAddressOf()));

    }
    Microsoft::WRL::ComPtr<ID3D11PixelShader> pixel_shader = nullptr; {

        Microsoft::WRL::ComPtr<ID3DBlob> ps = nullptr;
        Microsoft::WRL::ComPtr<ID3DBlob> errorBlob = nullptr;
        check(D3DCompileFromFile(FSFile, NULL, NULL, "fs_main", "ps_5_0", 0, 0, ps.GetAddressOf(), errorBlob.GetAddressOf()));
        check(device->CreatePixelShader(ps->GetBufferPointer(), ps->GetBufferSize(), NULL, pixel_shader.GetAddressOf()));
    }
    Microsoft::WRL::ComPtr<IDXGISwapChain> swapchain = nullptr; {

        DXGI_SWAP_CHAIN_DESC desc = {}; {

            desc.Windowed = 1;
            desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
            desc.OutputWindow = hwnd;
            desc.SampleDesc.Count = 1;
            desc.BufferCount = 2;
            desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            desc.BufferDesc.RefreshRate = {120, 1};
            desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

        }
                                        
        check(factory->CreateSwapChain(device.Get(), &desc, swapchain.GetAddressOf()));

    }
    Microsoft::WRL::ComPtr <ID3D11RenderTargetView> RTV = nullptr; {

        D3D11_RENDER_TARGET_VIEW_DESC desc = {}; {

            desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
            desc.Texture2D.MipSlice = 0;
        }
        Microsoft::WRL::ComPtr<ID3D11Texture2D> back_buffer = nullptr; 
        check(swapchain->GetBuffer(0, IID_PPV_ARGS(back_buffer.GetAddressOf())));
        check(device->CreateRenderTargetView(back_buffer.Get(), &desc, &RTV));
        
    }
    Microsoft::WRL::ComPtr<ID3D11InputLayout> layout = nullptr; {

        const D3D11_INPUT_ELEMENT_DESC desc[] = {
        
            {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
            {"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, sizeof(position) , D3D11_INPUT_PER_VERTEX_DATA, 0}
        };
        check(device->CreateInputLayout(desc, ARRAYSIZE(desc), vs->GetBufferPointer(), vs->GetBufferSize(), layout.GetAddressOf()));
    }
    { UINT32 stride = sizeof(vertex); UINT offset = 0;
        context->IASetVertexBuffers(0, 1, vertex_buffer.GetAddressOf(), &stride, &offset);
        context->IASetInputLayout(layout.Get());
        context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

        context->VSSetShader(vertex_shader.Get(), NULL, 0);
        context->PSSetShader(pixel_shader.Get(), NULL, 0);
        
        context->OMSetRenderTargets(1, RTV.GetAddressOf(), nullptr);
    }

    ShowWindow(hwnd, SW_SHOW);

    MSG msg = {};
    while (msg.message != WM_QUIT) {

        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg); DispatchMessageW(&msg);
        }

        RECT winRect;
        GetClientRect(hwnd, &winRect);
        D3D11_VIEWPORT port[] = { 
            {.TopLeftX = 0, .TopLeftY = 0, 
            .Width = (FLOAT)(winRect.right - winRect.left), 
            .Height = (FLOAT)(winRect.bottom - winRect.top), 
            .MinDepth = 0, .MaxDepth = 1 } 
        }; context->RSSetViewports(1, port);

        float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
        context->ClearRenderTargetView(RTV.Get(), clearColor);
        context->Draw(3, 0);
        swapchain->Present(1, 0);

    }
    return 0;
}

// the shader (shaders.sh)

// Input structure representing a single vertex
struct VertexInput {
    float2 Position : POSITION;
    float3 Color : COLOR;
};

// Output structure to be passed to the pixel shader
struct VertexOutput {
    float4 Position : SV_POSITION;
    float3 Color : COLOR;
};

// The main vertex shader function
VertexOutput vs_main(VertexInput input) {
    VertexOutput output;

    // Transform the vertex position to clip space
    output.Position = float4(input.Position, 0.0f, 1.0f);

    // Pass the vertex color to the pixel shader
    output.Color = input.Color;

    return output;
}

float4 fs_main(VertexOutput input) : SV_TARGET
{

    return float4(input.Color, 1.0f);

}

edit : an update, an error occured, the OMSetRenderTargets function is setting the RTV to null, don't know why though, msdn says it will set to null if i "try to set the same subresource to multiple render target slot", which i was not so dunno what that is about.

edit2 : another update, error is now fixed i was putting in an invalid argument, so now it doesn't set the RTV to null but the program still doesn't draw anything so, the main issue still persists.

1

There are 1 answers

0
user7860670 On

Addressof operator at context->OMSetRenderTargets(1, &RTV, nullptr); does not do what you think it does. It releases stored interface and returns a pointer to (now null) internal pointer. This method should be used when you want to obtain an interface from method taking a pointer to pointer to that interface and overwriting it, such as
device->CreateRenderTargetView(back_buffer.Get(),0, &RTV);.

Here you should use GetAddressOf method that returns a pointer to internal pointer without releasing the held interface:

context->OMSetRenderTargets(1, RTV.GetAddressOf(), nullptr);

or store a pointer(s) at the temporary array:

::std::array views{RTV.Get()};
context->OMSetRenderTargets(views.size(), views.data(), nullptr);

Also "no error checks is on purpose" is a way to shoot yourself in the foot.