質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
DirectX

DirectX(ダイレクトエックス)は、 マイクロソフトが開発したゲーム・マルチメディア処理用のAPIの集合です。

Q&A

0回答

2921閲覧

DirectX12 エラー

SOlsenT

総合スコア0

DirectX

DirectX(ダイレクトエックス)は、 マイクロソフトが開発したゲーム・マルチメディア処理用のAPIの集合です。

0グッド

0クリップ

投稿2020/05/26 08:18

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
今私はDirectX12の勉強をしています。
初期化処理を作っていたら以下のようなエラーがでて困っています。
どなたかご教授お願い致します。

発生している問題・エラーメッセージ

D3D12 ERROR: ID3D12CommandQueue::ExecuteCommandLists: A command list, which writes to a swapchain back buffer, may only be executed when that back buffer is the back buffer that will be presented during the next call to Present*. Such a back buffer is also referred to as the "current back buffer".

該当のソースコード

C++

1#include <Windows.h> 2#include <tchar.h> 3#include <vector> 4 5#include <d3d12.h> 6#include <dxgi1_6.h> 7 8#pragma comment(lib,"d3d12.lib") 9#pragma comment(lib,"dxgi.lib") 10 11#ifdef _DEBUG 12#include <iostream> 13#endif 14 15using namespace std; 16 17#define window_width 1280 18#define window_height 720 19 20/* 21@brief コンソール画面にフォーマット付き文字列を表示 22@param format フォーマット(%dとか%fとかの) 23@param 可変長引数 24@remarks この関数はデバック用です。デバック時にしか動作しません 25*/ 26 27// デバックレイヤー 28void EnableDebugLayer() 29{ 30 ID3D12Debug* debugLayer = nullptr; 31 32 auto result = D3D12GetDebugInterface(IID_PPV_ARGS(&debugLayer)); 33 34 // デバックレイヤーを有効化 35 debugLayer->EnableDebugLayer(); 36 // 有効化したらインターフェイスを解放 37 debugLayer->Release(); 38} 39 40void DebugOutputFormatString(const char* format, ...) 41{ 42#ifdef _DEBUG 43 va_list valist; 44 va_start(valist, format); 45 vprintf(format, valist); 46 va_end(valist); 47#endif 48} 49 50// 書かないといけない関数 51LRESULT WindowProcedure(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 52{ 53 // ウィンドウが破壊されたら呼ばれる 54 if (msg == WM_DESTROY) 55 { 56 // OSに対して「このアプリは終わる」と伝える 57 PostQuitMessage(0); 58 59 return 0; 60 } 61 62 // 既定の処理を行う 63 return DefWindowProc(hwnd, msg, wparam, lparam); 64} 65 66#ifdef _DEBUG 67int main() 68{ 69 // ウィンドウクラスの生成&登録 70 WNDCLASSEX w = {}; 71 72 w.cbSize = sizeof(WNDCLASSEX); 73 w.lpfnWndProc = (WNDPROC)WindowProcedure; // コールバック関数の指定 74 w.lpszClassName = _T("DX12Sample"); // アプリケーションクラス名(適当でいい) 75 w.hInstance = GetModuleHandle(nullptr); // ハンドルの取得 76 77 // アプリケーションクラス(ウィンドウクラスの指定をOSに伝える) 78 RegisterClassEx(&w); 79 80 // ウィンドサイズを決める 81 RECT wrc = { 0,0,window_width,window_height }; 82 83 // 関数を使ってウィンドウのサイズを補正する 84 AdjustWindowRect(&wrc, WS_OVERLAPPEDWINDOW, false); 85 86 // ウィンドウオブジェクトの作成 87 HWND hwnd = CreateWindow 88 ( 89 w.lpszClassName, // クラス名指定 90 _T("DX12テスト"), // タイトルバーの文字 91 WS_OVERLAPPEDWINDOW, // タイトルバーと境界線があるウィンドウ 92 CW_USEDEFAULT, // 表示x座標はOSにお任せ 93 CW_USEDEFAULT, // 表示y座標はOSにお任せ 94 wrc.right - wrc.left, // ウィンドウ幅 95 wrc.bottom - wrc.top, // ウィンドウ高 96 nullptr, // 親ウィンドウハンドル 97 nullptr, // メニューハンドル 98 w.hInstance, // 呼び出しアプリケーションハンドル 99 nullptr // 追加パラメーター 100 ); 101 102 // ウィンドウ表示 103 ShowWindow(hwnd, SW_SHOW); 104 105 106 107 // デバックレイヤーを有効化 108#ifdef _DEBUG 109 EnableDebugLayer(); 110#endif 111 112 113 114 // ============================ 115 // DirectX12初期化 116 ID3D12Device* _dev = nullptr; 117 IDXGIFactory6* _dxgiFactory = nullptr; 118 IDXGISwapChain3* _swapchain = nullptr; 119 120 // Direct3Dデバイスの初期化 121 D3D_FEATURE_LEVEL levels[] = 122 { 123 D3D_FEATURE_LEVEL_12_1, 124 D3D_FEATURE_LEVEL_12_0, 125 D3D_FEATURE_LEVEL_11_1, 126 D3D_FEATURE_LEVEL_11_0, 127 }; 128 D3D_FEATURE_LEVEL featureLevel; 129 130#ifdef _DEBUG 131 auto result = CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(&_dxgiFactory)); 132#else 133 auto result = CreateDXGIFactory1(IID_PPV_ARGS(&_dxgiFactory)); 134#endif 135 136 // 利用可能なアダプターを列挙し、列挙されたアダプターをstd::vectorに入れる 137 std::vector<IDXGIAdapter*>adapters; 138 139 // ここに特定の名前を持つアダプターオブジェクトが入る 140 IDXGIAdapter* tmpAdapter = nullptr; 141 142 for (int i = 0; _dxgiFactory->EnumAdapters(i, &tmpAdapter) != DXGI_ERROR_NOT_FOUND; ++i) 143 { 144 adapters.push_back(tmpAdapter); 145 } 146 147 for (auto adpt : adapters) 148 { 149 DXGI_ADAPTER_DESC adesc = {}; 150 151 // アダプターの説明オブジェクト取得 152 adpt->GetDesc(&adesc); 153 154 std::wstring strDesc = adesc.Description; 155 156 // 探したいアダプターの名前を確認 157 if (strDesc.find(L"Radeon") != std::string::npos) 158 { 159 tmpAdapter = adpt; 160 161 break; 162 } 163 } 164 165 // 生成可能なバージョンが見つかったら打ち切り 166 for (auto lv : levels) 167 { 168 if (D3D12CreateDevice(tmpAdapter, lv, IID_PPV_ARGS(&_dev)) == S_OK) 169 { 170 featureLevel = lv; 171 172 break; 173 } 174 } 175 // ↑ではだめだったら終了 176 if (_dev == nullptr) { return 0; } 177 178 179 180 // コマンドリストを使用するためにはコマンドアロケーターが必要なのでそれぞれを宣言する 181 ID3D12CommandAllocator* _cmdAllocator = nullptr; 182 ID3D12GraphicsCommandList* _cmdList = nullptr; 183 184 result = _dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&_cmdAllocator)); 185 result = _dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, _cmdAllocator, nullptr, IID_PPV_ARGS(&_cmdList)); 186 187 // コマンドキュー 188 ID3D12CommandQueue* _cmdQueue = nullptr; 189 190 D3D12_COMMAND_QUEUE_DESC cmdQueueDesc = {}; 191 // タイムアウトなし 192 cmdQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; 193 // アダプターを1つしか使わない時は0でよい 194 cmdQueueDesc.NodeMask = 0; 195 // プライオリティは特になし 196 cmdQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; 197 // コマンドリストと合わせる 198 cmdQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; 199 200 // キュー生成 201 result = _dev->CreateCommandQueue(&cmdQueueDesc, IID_PPV_ARGS(&_cmdQueue)); 202 203 /* 204 コマンドリストは対応した形式で命令をためるためのインターフェイス 205 コマンドアロケーターは命令の内容をためるメモリ領域 206 コマンドキューはためた命令を順次実行するためのもの 207 */ 208 209 210 211 // スワップチェーン生成 212 DXGI_SWAP_CHAIN_DESC1 swapchainDesc = {}; 213 214 swapchainDesc.Width = window_width; 215 swapchainDesc.Height = window_height; 216 swapchainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 217 swapchainDesc.Stereo = false; 218 swapchainDesc.SampleDesc.Count = 1; 219 swapchainDesc.SampleDesc.Quality = 0; 220 swapchainDesc.BufferUsage = DXGI_USAGE_BACK_BUFFER; 221 swapchainDesc.BufferCount = 2; 222 swapchainDesc.Scaling = DXGI_SCALING_STRETCH; // バックバッファーは伸び縮み可能 223 swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // フリップ後は速やかに破棄 224 swapchainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // 特になし 225 swapchainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // ウィンドウ⇔フルスクリーン切り替え可能 226 227 result = _dxgiFactory->CreateSwapChainForHwnd 228 ( 229 _cmdQueue, 230 hwnd, 231 &swapchainDesc, 232 nullptr, 233 nullptr, 234 (IDXGISwapChain1**)&_swapchain 235 ); 236 237 // レンダーターゲットビュー 238 D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {}; 239 240 heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; // レンダーターゲットビューなのでRTV 241 heapDesc.NodeMask = 0; 242 heapDesc.NumDescriptors = 2; // 表裏の2つ 243 heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; // 特に指定なし 244 245 ID3D12DescriptorHeap* rtvHeaps = nullptr; 246 247 result = _dev->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&rtvHeaps)); 248 249 // スワップチェーン上のバッファとデスクリプタを関連づける 250 DXGI_SWAP_CHAIN_DESC swcDesc = {}; 251 252 result = _swapchain->GetDesc(&swcDesc); 253 254 std::vector<ID3D12Resource*>_backBuffers(swcDesc.BufferCount); 255 256 D3D12_CPU_DESCRIPTOR_HANDLE handle = rtvHeaps->GetCPUDescriptorHandleForHeapStart(); 257 258 for (int idx = 0; idx < swcDesc.BufferCount; ++idx) 259 { 260 result = _swapchain->GetBuffer(idx, IID_PPV_ARGS(&_backBuffers[idx])); 261 _dev->CreateRenderTargetView(_backBuffers[idx], nullptr, handle); 262 263 handle.ptr += _dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); 264 } 265 266 267 268 // フェンス(GPU側の処理が完了したかどうか知るための仕組み) 269 ID3D12Fence* _fence = nullptr; 270 UINT64 _fenceVal = 0; 271 272 result = _dev->CreateFence(_fenceVal, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&_fence)); 273 274 _cmdQueue->Signal(_fence, ++_fenceVal); 275 276 if (_fence->GetCompletedValue() != _fenceVal) 277 { 278 // イベントハンドルの取得 279 auto event = CreateEvent(nullptr, false, false, nullptr); 280 281 _fence->SetEventOnCompletion(_fenceVal, event); 282 283 // イベントが発生するまで待ち続ける 284 WaitForSingleObject(event, INFINITE); 285 286 // イベントハンドルを閉じる 287 CloseHandle(event); 288 } 289 290 291 292 MSG msg = {}; 293 294 while (true) 295 { 296 if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) 297 { 298 TranslateMessage(&msg); 299 DispatchMessage(&msg); 300 } 301 302 // アプリケーションが終わる時にmessageがWM_QUITになる 303 if (msg.message == WM_QUIT) { break; } 304 305 306 307 // スワップチェーンを動作させる 308 /* 309 1、コマンドアロケーターとコマンドリストをクリア(アロケーターをリセットすればいい) 310 2、レンダーターゲットをバックバッファにセット 311 3、レンダーターゲットを指定色でクリア 312 4、レンダーターゲットをクローズ 313 5、たまったコマンドをコマンドリストに投げる 314 6、スワップチェーンのフリップ処理(Present命令) 315 */ 316 // 1 317 result = _cmdAllocator->Reset(); 318 319 // 2 320 auto bbldx = _swapchain->GetCurrentBackBufferIndex(); 321 322 auto rtvH = rtvHeaps->GetCPUDescriptorHandleForHeapStart(); 323 rtvH.ptr += bbldx * _dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); 324 325 326 327 // リソースバリアの設定 328 D3D12_RESOURCE_BARRIER BarrierDesc = {}; 329 330 BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; // 遷移 331 BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; // 特に指定なし 332 BarrierDesc.Transition.pResource = _backBuffers[bbldx]; // バックバッファーリソース 333 BarrierDesc.Transition.Subresource = 0; 334 BarrierDesc.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; // 直前はPRESENT状態 335 BarrierDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; // 今からレンダーターゲット状態 336 337 _cmdList->ResourceBarrier(1, &BarrierDesc); // バリア指定実行 338 339 340 341 _cmdList->OMSetRenderTargets(1, &rtvH, true, nullptr); 342 343 // 3 344 // 画面クリア 345 float clearColor[] = { 1.0f,1.0f,0.0f,1.0f }; // 黄色 346 347 _cmdList->ClearRenderTargetView(rtvH, clearColor, 0, nullptr); 348 349 // 4 350 // 命令のクローズ 351 _cmdList->Close(); 352 353 // 5 354 // コマンドリストの実行 355 ID3D12CommandList* cmdlists[] = { _cmdList }; 356 357 _cmdQueue->ExecuteCommandLists(1, cmdlists); 358 359 // キューのクリア 360 _cmdAllocator->Reset(); 361 // 再びコマンドリストを再びためる準備 362 _cmdList->Reset(_cmdAllocator, nullptr); 363 364 365 366 BarrierDesc.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; // 直前はPRESENT状態 367 BarrierDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; // 今からレンダーターゲット状態 368 369 _cmdList->ResourceBarrier(1, &BarrierDesc); // バリア指定実行 370 371 372 373 // 6 374 // フリップ 375 _swapchain->Present(1, 0); 376 } 377 378 // クラスは使わないので登録解除する 379 UnregisterClass(w.lpszClassName, w.hInstance); 380 381#else 382int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) 383{ 384#endif 385 386 DebugOutputFormatString("Show window test."); 387 getchar(); 388 389 return 0; 390}

試したこと

このエラーについて調べたらこのエラーは対処できない?できなことが出てきました

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問