Исключение: устройство имеет значение nullptr. нарушение прав чтения в D3D11 - PullRequest
1 голос
/ 27 апреля 2020

каждый.

Я написал небольшую 3D-сцену два года go, это всего 1700 строк исходного кода (исключая файлы .h). Теперь, вернувшись на GitHub и запустив свое приложение, я обнаружил довольно интересную ошибку в режиме отладки. Debbuger выдает мне исключение при вызове CreateBuffer для буфера вершин:

auto result = device->CreateBuffer(&vertex_buffer_desc, &vertex_data, &vertex_buffer);
        if(FAILED(result))
            return false;

По сути, отладчик говорит, что (d3d11) устройство - это nullptr, чего не может быть, потому что при работе в режиме без отладки все работает нормально , Но когда я определяю UINT create_device_flag = D3D11_CREATE_DEVICE_DEBUG; перед созданием устройства, я получаю это исключение: нарушение прав чтения. устройство является nullptr. Несколько дней спустя я все еще не могу выяснить, в чем дело, потому что порядок, в котором определены указатели, правильный.

Вот Main. cpp:

#include <StdAfx.h>

#include <Window.h>
#include <FPSCamera.h>

#include <DirectInput8.h>
#include <D3D11Renderer.h>

#include <Terrain.h>
#include <TerrainShader.h>

using namespace bm;

int __stdcall WinMain(HINSTANCE, HINSTANCE, char*, int)
{
    auto resource_directory_name = L"..\\..\\..\\Resource\\"s;
    auto terrain_name = L"terrain"s;

    auto dds_file_extension = L".dds"s;
    auto hlsl_file_extension = L".hlsl"s;

    std::wstring resources[] = {resource_directory_name + L"heightmap.bmp"s,
                                resource_directory_name + terrain_name + dds_file_extension,
                                resource_directory_name + terrain_name + L"_bump"s + dds_file_extension,
                                resource_directory_name + terrain_name + L"_vs"s + hlsl_file_extension,
                                resource_directory_name + terrain_name + L"_ps"s + hlsl_file_extension};

    constexpr auto ENABLE_FULLSCREEN = false;
    constexpr auto ENABLE_VSYNC = false;

    constexpr auto SCREEN_WIDTH = 1366;
    constexpr auto SCREEN_HEIGHT = 768;

    auto window = std::make_shared<bm::Window>(SCREEN_WIDTH, SCREEN_HEIGHT, ENABLE_FULLSCREEN);
    window->registerClass();
    window->create();

    auto d3d11_renderer = std::make_shared<bm::D3D11Renderer>(SCREEN_WIDTH, SCREEN_HEIGHT, ENABLE_FULLSCREEN, window->getHandle(), ENABLE_VSYNC);

    // Exception is thrown in the following ponter, but d3d11 device should be already initialized.
    auto terrain = std::make_shared<bm::Terrain>(d3d11_renderer->getDevice(), resources[0].c_str(), resources[1].c_str(), resources[2].c_str());
    auto terrain_shader = std::make_shared<bm::TerrainShader>(d3d11_renderer->getDevice(), resources[3].c_str(), resources[4].c_str());

    auto fps_camera = std::make_shared<bm::FPSCamera>(static_cast<float>(SCREEN_WIDTH),  static_cast<float>(SCREEN_HEIGHT));
    fps_camera->setPosition(500.f, 75.f, 400.f);
    fps_camera->setRotation(20.f, 30.f, 0.f); // in degree.

    auto direct_input_8 = std::make_shared<bm::DirectInput8>(window->getHandle());

    constexpr float CLEAR_COLOR[] = {0.84f, 0.84f, 1.f, 1.f};

    while(window->update())
    {
        direct_input_8->update(fps_camera->getMoveLeftRight(), fps_camera->getMoveBackForward(), fps_camera->getYaw(), fps_camera->getPitch());
        fps_camera->update();

        d3d11_renderer->clearScreen(CLEAR_COLOR);

        terrain->render(d3d11_renderer->getDeviceContext());

        terrain_shader->render(d3d11_renderer->getDeviceContext(),
                               terrain->getIndexCount(),
                               fps_camera->getWorld(),
                               fps_camera->getView(),
                               fps_camera->getProjection(),
                               {0.82f, 0.82f, 0.82f, 1.0f},
                               {-0.0f, -1.0f, 0.0f},
                               terrain->getColorTexture(),
                               terrain->getNormalMapTexture());

        d3d11_renderer->swapBuffers();
    }

    return 0;
}

PS И я знаю, что на сайте есть статья 6-летней давности: CreateBuffer выдает "Место чтения нарушения доступа" Но это вряд ли что-то объясняет, так как у меня нет глобальных переменных и указателей. Я хотел бы исправить свою старую ошибку, поэтому я буду рад указать что-нибудь, если нужно.

1 Ответ

0 голосов
/ 28 апреля 2020

Извините, но это весь код абстракции, поэтому мы не можем увидеть реальное место, куда вы звоните D3D11CreateDevice.

При этом описанный вами симптом звучит так, как будто вы не имеете права Уровень отладки устройства SDK установлен в вашей операционной системе. Скорее всего, вы также не можете проверить FAILED HRESULT из D3D11CreateDevice.

DWORD createDeviceFlags = 0;
#ifdef _DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
D3D_FEATURE_LEVEL fl;
HRESULT hr = D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_HARDWARE,
    nullptr, createDeviceFlags, nullptr,
    0, D3D11_SDK_VERSION, &device, &fl, &context );
if (FAILED(hr))
    ...

В системе без установленного слоя SDK отладочного устройства это будет невозможно в _DEBUG.

В Windows 8.x или Windows 10 при установке устаревшего DirectX SDK 1013 * не устанавливается ни одна отладочная среда .

Для Windows 8.x вы можете получить Direct3D 11 Debug Runtime, установив Windows 8.x SDK или Windows 10 SDK.

Для Windows 10 вы получите Direct3D Debug Runtime, установив Windows дополнительная функция с именем Графические инструменты . Для Windows 10 это спецификация версии c, поэтому убедитесь, что она включена, и она соответствует вашей версии. См. это сообщение в блоге

См. Анатомия Direct3D 11 Создание устройства

...