Ошибка при создании пиксельного шейдера: "Exception thrown: read access violation. **PS** was nullptr"

Рейтинг: 0Ответов: 0Опубликовано: 09.01.2023

Я изучаю DirectX с помощью ресурса www.directxtutorial.com. Я полностью выполнил все шаги для отображения треугольника на экране, но при попытке запуска готовой программы возникает эта ошибка. В тексте ошибки говорится, что переменная PS, в котором должно хранится бинарный код скомпилированного пиксельного шейдера, — пустой (nullptr). Снимок ошибки

В моём случае, код пиксельного и вершинного шейдеров хранятся в одном файле. Может ли это быть причиной ошибки? Почему не указывается ошибка сначала на вершинный шейдер (так как он создаётся первым)?

Вот полный код программы и шейдеров (ошибка в методе InitPipeline):

#include <iostream>
#include <Windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>

#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")

IDXGISwapChain* swapchain;
ID3D11RenderTargetView* backbuffer;
ID3D11Device* dev;
ID3D11DeviceContext* devcon;

ID3D11Buffer* pVBuffer;
ID3D11InputLayout* pLayout;
ID3D11VertexShader* pVS;
ID3D11PixelShader* pPS;

struct VERTEX
{
    FLOAT X, Y, Z;
    D3DXCOLOR Color;
};

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void InitD3D(HWND hWnd);
void InitPipeline();
void InitGraphics();
void RenderFrame();
void CleanD3D();

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hWnd;
    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(WNDCLASSEX));
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = L"WindowClass1";

    RegisterClassEx(&wc);

    hWnd = CreateWindowEx(NULL,
                            L"WindowClass1",
                            L"My Game",
                            WS_OVERLAPPEDWINDOW,
                            300,
                            300,
                            500,
                            400,
                            NULL,
                            NULL,
                            hInstance,
                            NULL);

    ShowWindow(hWnd, nCmdShow);

    InitD3D(hWnd);
    RenderFrame();

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    CleanD3D();
    return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
    {
        PostQuitMessage(0);
        return 0;
    } break;
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

void InitD3D(HWND hWnd)
{
    DXGI_SWAP_CHAIN_DESC scd;
    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
    scd.BufferCount = 1;
    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    scd.OutputWindow = hWnd;
    scd.SampleDesc.Count = 4;
    scd.Windowed = TRUE;

    D3D11CreateDeviceAndSwapChain(NULL,
                                D3D_DRIVER_TYPE_HARDWARE,
                                NULL,
                                NULL,
                                NULL,
                                NULL,
                                D3D11_SDK_VERSION,
                                &scd,
                                &swapchain,
                                &dev,
                                NULL,
                                &devcon);

    ID3D11Texture2D* pBackBuffer;
    swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
    dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
    pBackBuffer->Release();
    devcon->OMSetRenderTargets(1, &backbuffer, NULL);

    D3D11_VIEWPORT viewport;
    ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    viewport.Width = 800;
    viewport.Height = 600;
    devcon->RSSetViewports(1, &viewport);

    InitPipeline();
    InitGraphics();
}

void InitPipeline()
{
    ID3D10Blob* VS, * PS;
    D3DX11CompileFromFile(L"shaders.shader", 0, 0, "VShader", "vs_4_0", 0, 0, 0, &VS, 0, 0);
    D3DX11CompileFromFile(L"shaders.shader", 0, 0, "PShader", "vs_4_0", 0, 0, 0, &PS, 0, 0);

    dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
    dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

    devcon->VSSetShader(pVS, 0, 0);
    devcon->PSSetShader(pPS, 0, 0);

    D3D11_INPUT_ELEMENT_DESC ied[] =
    {
        {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
        {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}
    };
    dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
    devcon->IASetInputLayout(pLayout);
}

void InitGraphics()
{
    VERTEX OurVertices[] =
    {
        {0, 0.5f, 0, D3DXCOLOR{1.0f, 0, 0, 1.0f}},
        {0.45f, -0.5f, 0, D3DXCOLOR{0, 1.0f, 0, 1.0f}},
        {-0.45f, -0.5f, 0, D3DXCOLOR{0, 0, 1.0f, 1.0f}}
    };
    // create a buffer in the video adapter
    D3D11_BUFFER_DESC bd;
    ZeroMemory(&bd, sizeof(D3D11_BUFFER_DESC));
    bd.Usage = D3D11_USAGE_DYNAMIC;
    bd.ByteWidth = sizeof(VERTEX) * 3;
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    dev->CreateBuffer(&bd, NULL, &pVBuffer);
    // fill the buffer
    D3D11_MAPPED_SUBRESOURCE ms;
    devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
    memcpy(ms.pData, OurVertices, sizeof(OurVertices));
    devcon->Unmap(pVBuffer, NULL);
}

void RenderFrame()
{
    devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR{0, 0.2f, 0.4f, 1.0f});

    UINT stride = sizeof(VERTEX);
    UINT offset = 0;
    devcon->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);
    devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    devcon->Draw(3, 0);
    swapchain->Present(0, 0);
}

void CleanD3D()
{
    swapchain->Release();
    dev->Release();
    devcon->Release();
    pVBuffer->Release();
    pVS->Release();
    pPS->Release();
}
struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = position;
    output.color = color;

    return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

Попробуйте, пожалуйста, запустить данную программу на вашей машине. У Вас тоже возникает данная ошибка?

ИЗМЕНЕНО: Я прочитал текст ошибки метода компиляции пиксельного шейдера:

введите сюда описание изображения

Как теперь исправить программу?

Ответы

Ответов пока нет.