ShaderTesterImpl.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. #ifndef WIN32_LEAN_AND_MEAN
  2. #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers.
  3. #endif
  4. #define UNICODE
  5. #include <windows.h>
  6. #include <d3d12.h>
  7. #include <dxgi1_4.h>
  8. #include <D3Dcompiler.h>
  9. #include <DirectXMath.h>
  10. #include "dxc\Support\d3dx12.h"
  11. #include <string>
  12. #include <wrl.h>
  13. #include <shellapi.h>
  14. #include "DXSampleHelper.h"
  15. #include <iostream>
  16. #include <fstream>
  17. #include <vector>
  18. #include <map>
  19. using namespace DirectX;
  20. using Microsoft::WRL::ComPtr;
  21. #include "ShaderTesterImpl.h"
  22. #include <atlbase.h>
  23. #include "dxc/dxcapi.h"
  24. #include "dxc/Support/dxcapi.use.h"
  25. static dxc::DxcDllSupport g_DxcDllHelper;
  26. #define VERIFY_SUCCEEDED(expr) { HRESULT Result = expr; if (FAILED(Result)) { assert(0 && #expr " failed: Result=%08x"); } }
  27. #ifndef DXIL_FOURCC
  28. #define DXIL_FOURCC(ch0, ch1, ch2, ch3) ( \
  29. (uint32_t)(uint8_t)(ch0) | (uint32_t)(uint8_t)(ch1) << 8 | \
  30. (uint32_t)(uint8_t)(ch2) << 16 | (uint32_t)(uint8_t)(ch3) << 24 \
  31. )
  32. #endif
  33. HRESULT D3DCompileToDxilFromFile(LPCWSTR pShaderTextFilePath, LPCWSTR pEntryPoint, LPCWSTR pTargetProfile, const DxcDefine *pDefines, UINT32 defineCount, ID3DBlob **ppBlob, IDxcBlobEncoding** ppErrorBlob)
  34. {
  35. VERIFY_SUCCEEDED(g_DxcDllHelper.Initialize());
  36. CComPtr<IDxcCompiler> pCompiler;
  37. CComPtr<IDxcLibrary> pLibrary;
  38. CComPtr<IDxcBlobEncoding> pTextBlob(nullptr);
  39. CComPtr<IDxcOperationResult> pResult;
  40. CComPtr<IDxcIncludeHandler> dxcIncludeHandler;
  41. VERIFY_SUCCEEDED(g_DxcDllHelper.CreateInstance(CLSID_DxcCompiler, &pCompiler));
  42. VERIFY_SUCCEEDED(g_DxcDllHelper.CreateInstance(CLSID_DxcLibrary, &pLibrary));
  43. VERIFY_SUCCEEDED(pLibrary->CreateIncludeHandler(&dxcIncludeHandler));
  44. UINT32 codePage(0);
  45. VERIFY_SUCCEEDED(pLibrary->CreateBlobFromFile(pShaderTextFilePath, &codePage, &pTextBlob));
  46. VERIFY_SUCCEEDED(pCompiler->Compile(pTextBlob, pShaderTextFilePath, pEntryPoint, pTargetProfile, nullptr, 0, pDefines, defineCount, dxcIncludeHandler, &pResult));
  47. HRESULT resultCode;
  48. VERIFY_SUCCEEDED(pResult->GetStatus(&resultCode));
  49. VERIFY_SUCCEEDED(pResult->GetErrorBuffer(ppErrorBlob));
  50. //VERIFY_SUCCEEDED(resultCode);
  51. if (SUCCEEDED(resultCode))
  52. {
  53. VERIFY_SUCCEEDED(pResult->GetResult((IDxcBlob **)ppBlob));
  54. }
  55. return resultCode;
  56. }
  57. // A more recent Windows SDK than currently required is needed for these.
  58. typedef HRESULT(WINAPI *D3D12EnableExperimentalFeaturesFn)(
  59. UINT NumFeatures,
  60. __in_ecount(NumFeatures) const IID* pIIDs,
  61. __in_ecount_opt(NumFeatures) void* pConfigurationStructs,
  62. __in_ecount_opt(NumFeatures) UINT* pConfigurationStructSizes);
  63. static const GUID D3D12ExperimentalShaderModelsID = { /* 76f5573e-f13a-40f5-b297-81ce9e18933f */
  64. 0x76f5573e,
  65. 0xf13a,
  66. 0x40f5,
  67. { 0xb2, 0x97, 0x81, 0xce, 0x9e, 0x18, 0x93, 0x3f }
  68. };
  69. static HRESULT EnableExperimentalShaderModels()
  70. {
  71. #if 1
  72. HMODULE hRuntime = LoadLibraryW(L"d3d12.dll");
  73. if (hRuntime == NULL)
  74. {
  75. return HRESULT_FROM_WIN32(GetLastError());
  76. }
  77. D3D12EnableExperimentalFeaturesFn pD3D12EnableExperimentalFeatures =
  78. (D3D12EnableExperimentalFeaturesFn)GetProcAddress(hRuntime, "D3D12EnableExperimentalFeatures");
  79. if (pD3D12EnableExperimentalFeatures == nullptr)
  80. {
  81. std::cerr << "Unable to enable experimental shader models\n";
  82. FreeLibrary(hRuntime);
  83. return HRESULT_FROM_WIN32(GetLastError());
  84. }
  85. HRESULT hr = pD3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModelsID, nullptr, nullptr);
  86. //FreeLibrary(hRuntime);
  87. return hr;
  88. #else
  89. HRESULT hr = D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModelsID, nullptr, nullptr);
  90. #endif
  91. }
  92. void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter, const std::wstring& namePrefix)
  93. {
  94. ComPtr<IDXGIAdapter1> adapter;
  95. *ppAdapter = nullptr;
  96. for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, &adapter); ++adapterIndex)
  97. {
  98. DXGI_ADAPTER_DESC1 desc;
  99. adapter->GetDesc1(&desc);
  100. if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
  101. {
  102. // Don't select the Basic Render Driver adapter.
  103. // If you want a software adapter, pass in "/warp" on the command line.
  104. continue;
  105. }
  106. // Check to see if the adapter supports Direct3D 12, but don't create the
  107. // actual device yet.
  108. if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_12_0, _uuidof(ID3D12Device), nullptr)) &&
  109. std::wstring(desc.Description).find(namePrefix) != std::wstring::npos)
  110. {
  111. break;
  112. }
  113. }
  114. *ppAdapter = adapter.Detach();
  115. }
  116. void ReadFileToBuffer(const std::wstring& path, std::vector<char>& buffer)
  117. {
  118. std::fstream fs(path, std::ios::binary | std::ios::in);
  119. if (fs.fail())
  120. {
  121. std::wcerr << L"Could not open file " << path << L"\n";
  122. exit(1);
  123. }
  124. fs.seekg(0, std::ios::end);
  125. std::streampos size = fs.tellg();
  126. fs.seekg(0, std::ios::beg);
  127. buffer.resize(size, 0);
  128. if (size)
  129. fs.read(buffer.data(), buffer.size());
  130. }
  131. ShaderTester* ShaderTester::New(const std::wstring& filename)
  132. {
  133. return new ShaderTesterImpl(filename);
  134. }
  135. ShaderTester* ShaderTester::New(void* blob)
  136. {
  137. return new ShaderTesterImpl((ID3DBlob*)blob);
  138. }
  139. ShaderTesterImpl::ShaderTesterImpl(const std::wstring& filename)
  140. : m_filename(filename)
  141. {}
  142. ShaderTesterImpl::ShaderTesterImpl(ID3DBlob* blob)
  143. : m_blob(blob)
  144. {}
  145. ShaderTesterImpl::~ShaderTesterImpl()
  146. {
  147. CloseHandle(m_fenceEvent);
  148. }
  149. void ShaderTesterImpl::init()
  150. {
  151. initDevice();
  152. initResources();
  153. initPipeline();
  154. initExecution();
  155. }
  156. void ShaderTesterImpl::initDevice()
  157. {
  158. ThrowIfFailed(EnableExperimentalShaderModels());
  159. #if defined(_DEBUG)
  160. // Enable the D3D12 debug layer.
  161. {
  162. ComPtr<ID3D12Debug> debugController;
  163. if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
  164. {
  165. debugController->EnableDebugLayer();
  166. }
  167. }
  168. #endif
  169. ComPtr<IDXGIFactory4> factory;
  170. ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory)));
  171. if (m_namePrefix == L"WARP")
  172. {
  173. ComPtr<IDXGIAdapter> warpAdapter;
  174. ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)));
  175. ThrowIfFailed(D3D12CreateDevice(
  176. warpAdapter.Get(),
  177. D3D_FEATURE_LEVEL_12_0,
  178. IID_PPV_ARGS(&m_device)
  179. ));
  180. }
  181. else
  182. {
  183. ComPtr<IDXGIAdapter1> hardwareAdapter;
  184. GetHardwareAdapter(factory.Get(), &hardwareAdapter, m_namePrefix);
  185. ThrowIfFailed(D3D12CreateDevice(
  186. hardwareAdapter.Get(),
  187. D3D_FEATURE_LEVEL_12_0,
  188. IID_PPV_ARGS(&m_device)
  189. ));
  190. }
  191. {
  192. D3D12_FEATURE_DATA_SHADER_MODEL shaderModel = { D3D_SHADER_MODEL_6_0 };
  193. if (FAILED(m_device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shaderModel, sizeof(shaderModel))) || shaderModel.HighestShaderModel < D3D_SHADER_MODEL_6_0)
  194. {
  195. std::cerr << "SM6_0 not supported.\n";
  196. }
  197. }
  198. }
  199. void ShaderTesterImpl::initResources()
  200. {
  201. // Create the compute resources
  202. {
  203. CD3DX12_HEAP_PROPERTIES heapProps;
  204. CD3DX12_RESOURCE_DESC resDesc;
  205. UINT64 bufferSizeInBytes = m_bufferSize * sizeof(int);
  206. ThrowIfFailed(m_device->CreateCommittedResource(
  207. &(heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT)),
  208. D3D12_HEAP_FLAG_NONE,
  209. &(resDesc = CD3DX12_RESOURCE_DESC::Buffer(bufferSizeInBytes, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)),
  210. D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
  211. nullptr,
  212. IID_PPV_ARGS(&m_input)));
  213. NAME_D3D12_OBJECT(m_input);
  214. ThrowIfFailed(m_device->CreateCommittedResource(
  215. &(heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT)),
  216. D3D12_HEAP_FLAG_NONE,
  217. &(resDesc = CD3DX12_RESOURCE_DESC::Buffer(bufferSizeInBytes, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)),
  218. D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
  219. nullptr,
  220. IID_PPV_ARGS(&m_output)));
  221. NAME_D3D12_OBJECT(m_output);
  222. ThrowIfFailed(m_device->CreateCommittedResource(
  223. &(heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT)),
  224. D3D12_HEAP_FLAG_NONE,
  225. &(resDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(int), D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)),
  226. D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
  227. nullptr,
  228. IID_PPV_ARGS(&m_one)));
  229. NAME_D3D12_OBJECT(m_one);
  230. ThrowIfFailed(m_device->CreateCommittedResource(
  231. &(heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD)),
  232. D3D12_HEAP_FLAG_NONE,
  233. &(resDesc = CD3DX12_RESOURCE_DESC::Buffer(bufferSizeInBytes)),
  234. D3D12_RESOURCE_STATE_GENERIC_READ,
  235. nullptr,
  236. IID_PPV_ARGS(&m_uploadInput)));
  237. NAME_D3D12_OBJECT(m_uploadInput);
  238. ThrowIfFailed(m_device->CreateCommittedResource(
  239. &(heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD)),
  240. D3D12_HEAP_FLAG_NONE,
  241. &(resDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(int))),
  242. D3D12_RESOURCE_STATE_GENERIC_READ,
  243. nullptr,
  244. IID_PPV_ARGS(&m_uploadOne)));
  245. NAME_D3D12_OBJECT(m_uploadOne);
  246. ThrowIfFailed(m_device->CreateCommittedResource(
  247. &(heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK)),
  248. D3D12_HEAP_FLAG_NONE,
  249. &(resDesc = CD3DX12_RESOURCE_DESC::Buffer(bufferSizeInBytes)),
  250. D3D12_RESOURCE_STATE_COPY_DEST,
  251. nullptr,
  252. IID_PPV_ARGS(&m_readback)));
  253. NAME_D3D12_OBJECT(m_readback);
  254. }
  255. // Create a UAV heap.
  256. {
  257. D3D12_DESCRIPTOR_HEAP_DESC uavHeapDesc = {};
  258. uavHeapDesc.NumDescriptors = 3;
  259. uavHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  260. uavHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  261. ThrowIfFailed(m_device->CreateDescriptorHeap(&uavHeapDesc, IID_PPV_ARGS(&m_uavHeap)));
  262. m_uavDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  263. }
  264. // Create compute UAVs
  265. {
  266. D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
  267. uavDesc.Format = DXGI_FORMAT_UNKNOWN;
  268. uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
  269. uavDesc.Buffer.FirstElement = 0;
  270. uavDesc.Buffer.NumElements = m_bufferSize;
  271. uavDesc.Buffer.StructureByteStride = sizeof(int);
  272. uavDesc.Buffer.CounterOffsetInBytes = 0;
  273. uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
  274. CD3DX12_CPU_DESCRIPTOR_HANDLE uavHandle(m_uavHeap->GetCPUDescriptorHandleForHeapStart(), 0, m_uavDescriptorSize);
  275. m_device->CreateUnorderedAccessView(m_input.Get(), nullptr, &uavDesc, uavHandle);
  276. uavHandle.Offset(1, m_uavDescriptorSize);
  277. m_device->CreateUnorderedAccessView(m_output.Get(), nullptr, &uavDesc, uavHandle);
  278. uavHandle.Offset(1, m_uavDescriptorSize);
  279. uavDesc.Buffer.NumElements = 1;
  280. m_device->CreateUnorderedAccessView(m_one.Get(), nullptr, &uavDesc, uavHandle);
  281. }
  282. }
  283. void ShaderTesterImpl::initPipeline()
  284. {
  285. // Compute root signature.
  286. {
  287. CD3DX12_ROOT_PARAMETER1 rootParameters[2];
  288. CD3DX12_DESCRIPTOR_RANGE1 uavs(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 3, 0);
  289. rootParameters[0].InitAsDescriptorTable(1, &uavs); // register u0 : input
  290. // register u1 : output
  291. // register u2 : one
  292. rootParameters[1].InitAsConstants(1, 0); // register b0 : initialStateId
  293. CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC computeRootSignatureDesc;
  294. computeRootSignatureDesc.Init_1_1(_countof(rootParameters), rootParameters);
  295. ComPtr<ID3DBlob> signature;
  296. ComPtr<ID3DBlob> error;
  297. ThrowIfFailed(D3DX12SerializeVersionedRootSignature(&computeRootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
  298. ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_computeRootSignature)));
  299. NAME_D3D12_OBJECT(m_computeRootSignature);
  300. }
  301. // Create compute pipeline
  302. {
  303. //#if defined(_DEBUG)
  304. // // Enable better shader debugging with the graphics debugging tools.
  305. // UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
  306. //#else
  307. // UINT compileFlags = 0;
  308. //#endif
  309. // Load and compile shaders.
  310. //ComPtr<ID3DBlob> computeShader;
  311. //ThrowIfFailed(D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "CSMain", "cs_6_0", compileFlags, 0, &computeShader, nullptr));
  312. CD3DX12_SHADER_BYTECODE bytecode;
  313. std::vector<char> computeShaderBuffer;
  314. ComPtr<ID3DBlob> computeShaderBlob;
  315. if (m_blob)
  316. {
  317. bytecode = CD3DX12_SHADER_BYTECODE(m_blob.Get());
  318. }
  319. else if (m_filename.find(L".cso") != std::wstring::npos)
  320. {
  321. ReadFileToBuffer(m_filename, computeShaderBuffer);
  322. bytecode = CD3DX12_SHADER_BYTECODE(computeShaderBuffer.data(), computeShaderBuffer.size());
  323. }
  324. else
  325. {
  326. HRESULT DxilResult(S_OK);
  327. ComPtr<IDxcBlobEncoding> errors;
  328. DxilResult = D3DCompileToDxilFromFile(m_filename.c_str(), L"CSMain", L"cs_6_0", nullptr, 0, &computeShaderBlob, &errors);
  329. if (!SUCCEEDED(DxilResult)) { OutputDebugStringA((LPCSTR)errors->GetBufferPointer()); }
  330. ThrowIfFailed(DxilResult);
  331. bytecode = CD3DX12_SHADER_BYTECODE(computeShaderBlob.Get());
  332. }
  333. // Describe and create the compute pipeline state object (PSO).
  334. D3D12_COMPUTE_PIPELINE_STATE_DESC computePsoDesc = {};
  335. computePsoDesc.pRootSignature = m_computeRootSignature.Get();
  336. computePsoDesc.CS = bytecode;
  337. ThrowIfFailed(m_device->CreateComputePipelineState(&computePsoDesc, IID_PPV_ARGS(&m_computeState)));
  338. NAME_D3D12_OBJECT(m_computeState);
  339. }
  340. }
  341. void ShaderTesterImpl::initExecution()
  342. {
  343. // Describe and create the command queue.
  344. D3D12_COMMAND_QUEUE_DESC queueDesc = {};
  345. queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
  346. queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
  347. ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)));
  348. ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator)));
  349. // Create the command list.
  350. ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator.Get(), nullptr, IID_PPV_ARGS(&m_commandList)));
  351. // Command lists are created in the recording state, but there is nothing
  352. // to record yet. The main loop expects it to be closed, so close it now.
  353. ThrowIfFailed(m_commandList->Close());
  354. // Create synchronization objects
  355. {
  356. ThrowIfFailed(m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)));
  357. m_fenceValue = 1;
  358. // Create an event handle to use for frame synchronization.
  359. m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  360. if (m_fenceEvent == nullptr)
  361. {
  362. ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
  363. }
  364. }
  365. }
  366. void ShaderTesterImpl::setDevice(const std::wstring& namePrefix)
  367. {
  368. m_namePrefix = namePrefix;
  369. }
  370. void ShaderTesterImpl::runShader(int initialShaderId, const std::vector<int>& input, std::vector<int>& output)
  371. {
  372. if (!m_device)
  373. init();
  374. //////////////////////////////////////////////////////////////////////////
  375. // Dispatch compute shader
  376. //////////////////////////////////////////////////////////////////////////
  377. // Command list allocators can only be reset when the associated
  378. // command lists have finished execution on the GPU; apps should use
  379. // fences to determine GPU execution progress.
  380. ThrowIfFailed(m_commandAllocator->Reset());
  381. // However, when ExecuteCommandList() is called on a particular command
  382. // list, that command list can then be reset at any time and must be before
  383. // re-recording.
  384. ThrowIfFailed(m_commandList->Reset(m_commandAllocator.Get(), nullptr));
  385. m_commandList->SetPipelineState(m_computeState.Get());
  386. m_commandList->SetComputeRootSignature(m_computeRootSignature.Get());
  387. ID3D12DescriptorHeap* ppHeaps[] = { m_uavHeap.Get() };
  388. m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
  389. CD3DX12_GPU_DESCRIPTOR_HANDLE uavHandle(m_uavHeap->GetGPUDescriptorHandleForHeapStart(), 0, m_uavDescriptorSize);
  390. m_commandList->SetComputeRootDescriptorTable(0, uavHandle);
  391. m_commandList->SetComputeRoot32BitConstant(1, initialShaderId, 0);
  392. // Upload some data
  393. CD3DX12_RANGE readRange(0, 0);
  394. int* pUpload = nullptr;
  395. m_uploadInput->Map(0, &readRange, (void**)&pUpload);
  396. pUpload[0] = 0;
  397. memcpy(pUpload + 1, input.data(), input.size() * sizeof(int));
  398. m_uploadInput->Unmap(0, nullptr);
  399. m_uploadOne->Map(0, &readRange, (void**)&pUpload);
  400. pUpload[0] = 1;
  401. m_uploadOne->Unmap(0, nullptr);
  402. // Copy it to the input buffer
  403. CD3DX12_RESOURCE_BARRIER bar;
  404. m_commandList->ResourceBarrier(1, &(bar = CD3DX12_RESOURCE_BARRIER::Transition(m_input.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST)));
  405. m_commandList->CopyResource(m_input.Get(), m_uploadInput.Get());
  406. m_commandList->ResourceBarrier(1, &(bar = CD3DX12_RESOURCE_BARRIER::Transition(m_input.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)));
  407. m_commandList->ResourceBarrier(1, &(bar = CD3DX12_RESOURCE_BARRIER::Transition(m_one.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST)));
  408. m_commandList->CopyResource(m_one.Get(), m_uploadOne.Get());
  409. m_commandList->ResourceBarrier(1, &(bar = CD3DX12_RESOURCE_BARRIER::Transition(m_one.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)));
  410. m_commandList->Dispatch(1, 1, 1);
  411. m_commandList->ResourceBarrier(1, &(bar = CD3DX12_RESOURCE_BARRIER::Transition(m_output.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE)));
  412. m_commandList->CopyResource(m_readback.Get(), m_output.Get());
  413. m_commandList->ResourceBarrier(1, &(bar = CD3DX12_RESOURCE_BARRIER::Transition(m_output.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)));
  414. ThrowIfFailed(m_commandList->Close());
  415. // Execute the command list.
  416. ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
  417. m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
  418. //////////////////////////////////////////////////////////////////////////
  419. // Synchronize
  420. //////////////////////////////////////////////////////////////////////////
  421. // Signal and increment the fence value.
  422. const UINT64 oldFenceValue = m_fenceValue;
  423. ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), oldFenceValue));
  424. m_fenceValue++;
  425. // Wait until the previous frame is finished.
  426. if (m_fence->GetCompletedValue() < oldFenceValue)
  427. {
  428. ThrowIfFailed(m_fence->SetEventOnCompletion(oldFenceValue, m_fenceEvent));
  429. WaitForSingleObject(m_fenceEvent, INFINITE);
  430. }
  431. //////////////////////////////////////////////////////////////////////////
  432. // Readback
  433. //////////////////////////////////////////////////////////////////////////
  434. {
  435. int* pReadback = nullptr;
  436. CD3DX12_RANGE readRange(0, m_bufferSize);
  437. m_readback->Map(0, &readRange, (void**)&pReadback);
  438. output.assign(pReadback, pReadback + m_bufferSize);
  439. CD3DX12_RANGE writeRange(0, 0);
  440. m_readback->Unmap(0, &writeRange);
  441. }
  442. }
  443. void ShaderTesterImpl::printLog(int* log)
  444. {
  445. int *pos = log;
  446. int count = pos[0];
  447. std::cout << count << ": ";
  448. pos++;
  449. for (int i = 0; i < count; ++i)
  450. std::cout << pos[i] << " ";
  451. std::cout << "\n";
  452. }