1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <stdio.h> 25bf215546Sopenharmony_ci#include <stdint.h> 26bf215546Sopenharmony_ci#include <stdexcept> 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include <unknwn.h> 29bf215546Sopenharmony_ci#include <directx/d3d12.h> 30bf215546Sopenharmony_ci#include <dxgi1_4.h> 31bf215546Sopenharmony_ci#include <gtest/gtest.h> 32bf215546Sopenharmony_ci#include <wrl.h> 33bf215546Sopenharmony_ci#include <dxguids/dxguids.h> 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include "util/u_debug.h" 36bf215546Sopenharmony_ci#include "clc_compiler.h" 37bf215546Sopenharmony_ci#include "compute_test.h" 38bf215546Sopenharmony_ci#include "dxil_validator.h" 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci#include <spirv-tools/libspirv.hpp> 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#if (defined(_WIN32) && defined(_MSC_VER)) || D3D12_SDK_VERSION < 606 43bf215546Sopenharmony_ciinline D3D12_CPU_DESCRIPTOR_HANDLE 44bf215546Sopenharmony_ciGetCPUDescriptorHandleForHeapStart(ID3D12DescriptorHeap *heap) 45bf215546Sopenharmony_ci{ 46bf215546Sopenharmony_ci return heap->GetCPUDescriptorHandleForHeapStart(); 47bf215546Sopenharmony_ci} 48bf215546Sopenharmony_ciinline D3D12_GPU_DESCRIPTOR_HANDLE 49bf215546Sopenharmony_ciGetGPUDescriptorHandleForHeapStart(ID3D12DescriptorHeap *heap) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci return heap->GetGPUDescriptorHandleForHeapStart(); 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ciinline D3D12_HEAP_PROPERTIES 54bf215546Sopenharmony_ciGetCustomHeapProperties(ID3D12Device *dev, D3D12_HEAP_TYPE type) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci return dev->GetCustomHeapProperties(0, type); 57bf215546Sopenharmony_ci} 58bf215546Sopenharmony_ci#else 59bf215546Sopenharmony_ciinline D3D12_CPU_DESCRIPTOR_HANDLE 60bf215546Sopenharmony_ciGetCPUDescriptorHandleForHeapStart(ID3D12DescriptorHeap *heap) 61bf215546Sopenharmony_ci{ 62bf215546Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE ret; 63bf215546Sopenharmony_ci heap->GetCPUDescriptorHandleForHeapStart(&ret); 64bf215546Sopenharmony_ci return ret; 65bf215546Sopenharmony_ci} 66bf215546Sopenharmony_ciinline D3D12_GPU_DESCRIPTOR_HANDLE 67bf215546Sopenharmony_ciGetGPUDescriptorHandleForHeapStart(ID3D12DescriptorHeap *heap) 68bf215546Sopenharmony_ci{ 69bf215546Sopenharmony_ci D3D12_GPU_DESCRIPTOR_HANDLE ret; 70bf215546Sopenharmony_ci heap->GetGPUDescriptorHandleForHeapStart(&ret); 71bf215546Sopenharmony_ci return ret; 72bf215546Sopenharmony_ci} 73bf215546Sopenharmony_ciinline D3D12_HEAP_PROPERTIES 74bf215546Sopenharmony_ciGetCustomHeapProperties(ID3D12Device *dev, D3D12_HEAP_TYPE type) 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci D3D12_HEAP_PROPERTIES ret; 77bf215546Sopenharmony_ci dev->GetCustomHeapProperties(&ret, 0, type); 78bf215546Sopenharmony_ci return ret; 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci#endif 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ciusing std::runtime_error; 83bf215546Sopenharmony_ciusing Microsoft::WRL::ComPtr; 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_cienum compute_test_debug_flags { 86bf215546Sopenharmony_ci COMPUTE_DEBUG_EXPERIMENTAL_SHADERS = 1 << 0, 87bf215546Sopenharmony_ci COMPUTE_DEBUG_USE_HW_D3D = 1 << 1, 88bf215546Sopenharmony_ci COMPUTE_DEBUG_OPTIMIZE_LIBCLC = 1 << 2, 89bf215546Sopenharmony_ci COMPUTE_DEBUG_SERIALIZE_LIBCLC = 1 << 3, 90bf215546Sopenharmony_ci}; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_cistatic const struct debug_named_value compute_debug_options[] = { 93bf215546Sopenharmony_ci { "experimental_shaders", COMPUTE_DEBUG_EXPERIMENTAL_SHADERS, "Enable experimental shaders" }, 94bf215546Sopenharmony_ci { "use_hw_d3d", COMPUTE_DEBUG_USE_HW_D3D, "Use a hardware D3D device" }, 95bf215546Sopenharmony_ci { "optimize_libclc", COMPUTE_DEBUG_OPTIMIZE_LIBCLC, "Optimize the clc_libclc before using it" }, 96bf215546Sopenharmony_ci { "serialize_libclc", COMPUTE_DEBUG_SERIALIZE_LIBCLC, "Serialize and deserialize the clc_libclc" }, 97bf215546Sopenharmony_ci DEBUG_NAMED_VALUE_END 98bf215546Sopenharmony_ci}; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ciDEBUG_GET_ONCE_FLAGS_OPTION(debug_compute, "COMPUTE_TEST_DEBUG", compute_debug_options, 0) 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_cistatic void warning_callback(void *priv, const char *msg) 103bf215546Sopenharmony_ci{ 104bf215546Sopenharmony_ci fprintf(stderr, "WARNING: %s\n", msg); 105bf215546Sopenharmony_ci} 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_cistatic void error_callback(void *priv, const char *msg) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci fprintf(stderr, "ERROR: %s\n", msg); 110bf215546Sopenharmony_ci} 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_cistatic const struct clc_logger logger = { 113bf215546Sopenharmony_ci NULL, 114bf215546Sopenharmony_ci error_callback, 115bf215546Sopenharmony_ci warning_callback, 116bf215546Sopenharmony_ci}; 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_civoid 119bf215546Sopenharmony_ciComputeTest::enable_d3d12_debug_layer() 120bf215546Sopenharmony_ci{ 121bf215546Sopenharmony_ci HMODULE hD3D12Mod = LoadLibrary("D3D12.DLL"); 122bf215546Sopenharmony_ci if (!hD3D12Mod) { 123bf215546Sopenharmony_ci fprintf(stderr, "D3D12: failed to load D3D12.DLL\n"); 124bf215546Sopenharmony_ci return; 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci typedef HRESULT(WINAPI * PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID riid, 128bf215546Sopenharmony_ci void **ppFactory); 129bf215546Sopenharmony_ci PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(hD3D12Mod, "D3D12GetDebugInterface"); 130bf215546Sopenharmony_ci if (!D3D12GetDebugInterface) { 131bf215546Sopenharmony_ci fprintf(stderr, "D3D12: failed to load D3D12GetDebugInterface from D3D12.DLL\n"); 132bf215546Sopenharmony_ci return; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci ID3D12Debug *debug; 136bf215546Sopenharmony_ci if (FAILED(D3D12GetDebugInterface(__uuidof(ID3D12Debug), (void **)& debug))) { 137bf215546Sopenharmony_ci fprintf(stderr, "D3D12: D3D12GetDebugInterface failed\n"); 138bf215546Sopenharmony_ci return; 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci debug->EnableDebugLayer(); 142bf215546Sopenharmony_ci} 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ciIDXGIFactory4 * 145bf215546Sopenharmony_ciComputeTest::get_dxgi_factory() 146bf215546Sopenharmony_ci{ 147bf215546Sopenharmony_ci static const GUID IID_IDXGIFactory4 = { 148bf215546Sopenharmony_ci 0x1bc6ea02, 0xef36, 0x464f, 149bf215546Sopenharmony_ci { 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a } 150bf215546Sopenharmony_ci }; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci typedef HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID riid, 153bf215546Sopenharmony_ci void **ppFactory); 154bf215546Sopenharmony_ci PFN_CREATE_DXGI_FACTORY CreateDXGIFactory; 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci HMODULE hDXGIMod = LoadLibrary("DXGI.DLL"); 157bf215546Sopenharmony_ci if (!hDXGIMod) 158bf215546Sopenharmony_ci throw runtime_error("Failed to load DXGI.DLL"); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci CreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(hDXGIMod, "CreateDXGIFactory"); 161bf215546Sopenharmony_ci if (!CreateDXGIFactory) 162bf215546Sopenharmony_ci throw runtime_error("Failed to load CreateDXGIFactory from DXGI.DLL"); 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci IDXGIFactory4 *factory = NULL; 165bf215546Sopenharmony_ci HRESULT hr = CreateDXGIFactory(IID_IDXGIFactory4, (void **)&factory); 166bf215546Sopenharmony_ci if (FAILED(hr)) 167bf215546Sopenharmony_ci throw runtime_error("CreateDXGIFactory failed"); 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci return factory; 170bf215546Sopenharmony_ci} 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ciIDXGIAdapter1 * 173bf215546Sopenharmony_ciComputeTest::choose_adapter(IDXGIFactory4 *factory) 174bf215546Sopenharmony_ci{ 175bf215546Sopenharmony_ci IDXGIAdapter1 *ret; 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci if (debug_get_option_debug_compute() & COMPUTE_DEBUG_USE_HW_D3D) { 178bf215546Sopenharmony_ci for (unsigned i = 0; SUCCEEDED(factory->EnumAdapters1(i, &ret)); i++) { 179bf215546Sopenharmony_ci DXGI_ADAPTER_DESC1 desc; 180bf215546Sopenharmony_ci ret->GetDesc1(&desc); 181bf215546Sopenharmony_ci if (!(desc.Flags & D3D_DRIVER_TYPE_SOFTWARE)) 182bf215546Sopenharmony_ci return ret; 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci throw runtime_error("Failed to enum hardware adapter"); 185bf215546Sopenharmony_ci } else { 186bf215546Sopenharmony_ci if (FAILED(factory->EnumWarpAdapter(__uuidof(IDXGIAdapter1), 187bf215546Sopenharmony_ci (void **)& ret))) 188bf215546Sopenharmony_ci throw runtime_error("Failed to enum warp adapter"); 189bf215546Sopenharmony_ci return ret; 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci} 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ciID3D12Device * 194bf215546Sopenharmony_ciComputeTest::create_device(IDXGIAdapter1 *adapter) 195bf215546Sopenharmony_ci{ 196bf215546Sopenharmony_ci typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown *, D3D_FEATURE_LEVEL, REFIID, void **); 197bf215546Sopenharmony_ci PFN_D3D12CREATEDEVICE D3D12CreateDevice; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci HMODULE hD3D12Mod = LoadLibrary("D3D12.DLL"); 200bf215546Sopenharmony_ci if (!hD3D12Mod) 201bf215546Sopenharmony_ci throw runtime_error("failed to load D3D12.DLL"); 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci if (debug_get_option_debug_compute() & COMPUTE_DEBUG_EXPERIMENTAL_SHADERS) { 204bf215546Sopenharmony_ci typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID *, void *, UINT *); 205bf215546Sopenharmony_ci PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures; 206bf215546Sopenharmony_ci D3D12EnableExperimentalFeatures = (PFN_D3D12ENABLEEXPERIMENTALFEATURES) 207bf215546Sopenharmony_ci GetProcAddress(hD3D12Mod, "D3D12EnableExperimentalFeatures"); 208bf215546Sopenharmony_ci if (FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) 209bf215546Sopenharmony_ci throw runtime_error("failed to enable experimental shader models"); 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)GetProcAddress(hD3D12Mod, "D3D12CreateDevice"); 213bf215546Sopenharmony_ci if (!D3D12CreateDevice) 214bf215546Sopenharmony_ci throw runtime_error("failed to load D3D12CreateDevice from D3D12.DLL"); 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci ID3D12Device *dev; 217bf215546Sopenharmony_ci if (FAILED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_12_0, 218bf215546Sopenharmony_ci __uuidof(ID3D12Device), (void **)& dev))) 219bf215546Sopenharmony_ci throw runtime_error("D3D12CreateDevice failed"); 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci return dev; 222bf215546Sopenharmony_ci} 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ciComPtr<ID3D12RootSignature> 225bf215546Sopenharmony_ciComputeTest::create_root_signature(const ComputeTest::Resources &resources) 226bf215546Sopenharmony_ci{ 227bf215546Sopenharmony_ci D3D12_ROOT_PARAMETER1 root_param; 228bf215546Sopenharmony_ci root_param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; 229bf215546Sopenharmony_ci root_param.DescriptorTable.NumDescriptorRanges = resources.ranges.size(); 230bf215546Sopenharmony_ci root_param.DescriptorTable.pDescriptorRanges = resources.ranges.data(); 231bf215546Sopenharmony_ci root_param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci D3D12_ROOT_SIGNATURE_DESC1 root_sig_desc; 234bf215546Sopenharmony_ci root_sig_desc.NumParameters = 1; 235bf215546Sopenharmony_ci root_sig_desc.pParameters = &root_param; 236bf215546Sopenharmony_ci root_sig_desc.NumStaticSamplers = 0; 237bf215546Sopenharmony_ci root_sig_desc.pStaticSamplers = NULL; 238bf215546Sopenharmony_ci root_sig_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci D3D12_VERSIONED_ROOT_SIGNATURE_DESC versioned_desc; 241bf215546Sopenharmony_ci versioned_desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; 242bf215546Sopenharmony_ci versioned_desc.Desc_1_1 = root_sig_desc; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci ID3DBlob *sig, *error; 245bf215546Sopenharmony_ci if (FAILED(D3D12SerializeVersionedRootSignature(&versioned_desc, 246bf215546Sopenharmony_ci &sig, &error))) 247bf215546Sopenharmony_ci throw runtime_error("D3D12SerializeVersionedRootSignature failed"); 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci ComPtr<ID3D12RootSignature> ret; 250bf215546Sopenharmony_ci if (FAILED(dev->CreateRootSignature(0, 251bf215546Sopenharmony_ci sig->GetBufferPointer(), 252bf215546Sopenharmony_ci sig->GetBufferSize(), 253bf215546Sopenharmony_ci __uuidof(ID3D12RootSignature), 254bf215546Sopenharmony_ci (void **)& ret))) 255bf215546Sopenharmony_ci throw runtime_error("CreateRootSignature failed"); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci return ret; 258bf215546Sopenharmony_ci} 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ciComPtr<ID3D12PipelineState> 261bf215546Sopenharmony_ciComputeTest::create_pipeline_state(ComPtr<ID3D12RootSignature> &root_sig, 262bf215546Sopenharmony_ci const struct clc_dxil_object &dxil) 263bf215546Sopenharmony_ci{ 264bf215546Sopenharmony_ci D3D12_COMPUTE_PIPELINE_STATE_DESC pipeline_desc = { root_sig.Get() }; 265bf215546Sopenharmony_ci pipeline_desc.CS.pShaderBytecode = dxil.binary.data; 266bf215546Sopenharmony_ci pipeline_desc.CS.BytecodeLength = dxil.binary.size; 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci ComPtr<ID3D12PipelineState> pipeline_state; 269bf215546Sopenharmony_ci if (FAILED(dev->CreateComputePipelineState(&pipeline_desc, 270bf215546Sopenharmony_ci __uuidof(ID3D12PipelineState), 271bf215546Sopenharmony_ci (void **)& pipeline_state))) 272bf215546Sopenharmony_ci throw runtime_error("Failed to create pipeline state"); 273bf215546Sopenharmony_ci return pipeline_state; 274bf215546Sopenharmony_ci} 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ciComPtr<ID3D12Resource> 277bf215546Sopenharmony_ciComputeTest::create_buffer(int size, D3D12_HEAP_TYPE heap_type) 278bf215546Sopenharmony_ci{ 279bf215546Sopenharmony_ci D3D12_RESOURCE_DESC desc; 280bf215546Sopenharmony_ci desc.Format = DXGI_FORMAT_UNKNOWN; 281bf215546Sopenharmony_ci desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; 282bf215546Sopenharmony_ci desc.Width = size; 283bf215546Sopenharmony_ci desc.Height = 1; 284bf215546Sopenharmony_ci desc.DepthOrArraySize = 1; 285bf215546Sopenharmony_ci desc.MipLevels = 1; 286bf215546Sopenharmony_ci desc.SampleDesc.Count = 1; 287bf215546Sopenharmony_ci desc.SampleDesc.Quality = 0; 288bf215546Sopenharmony_ci desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; 289bf215546Sopenharmony_ci desc.Flags = heap_type == D3D12_HEAP_TYPE_DEFAULT ? D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS : D3D12_RESOURCE_FLAG_NONE; 290bf215546Sopenharmony_ci desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci D3D12_HEAP_PROPERTIES heap_pris = GetCustomHeapProperties(dev, heap_type); 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci ComPtr<ID3D12Resource> res; 295bf215546Sopenharmony_ci if (FAILED(dev->CreateCommittedResource(&heap_pris, 296bf215546Sopenharmony_ci D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON, 297bf215546Sopenharmony_ci NULL, __uuidof(ID3D12Resource), (void **)&res))) 298bf215546Sopenharmony_ci throw runtime_error("CreateCommittedResource failed"); 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci return res; 301bf215546Sopenharmony_ci} 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ciComPtr<ID3D12Resource> 304bf215546Sopenharmony_ciComputeTest::create_upload_buffer_with_data(const void *data, size_t size) 305bf215546Sopenharmony_ci{ 306bf215546Sopenharmony_ci auto upload_res = create_buffer(size, D3D12_HEAP_TYPE_UPLOAD); 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci void *ptr = NULL; 309bf215546Sopenharmony_ci D3D12_RANGE res_range = { 0, (SIZE_T)size }; 310bf215546Sopenharmony_ci if (FAILED(upload_res->Map(0, &res_range, (void **)&ptr))) 311bf215546Sopenharmony_ci throw runtime_error("Failed to map upload-buffer"); 312bf215546Sopenharmony_ci assert(ptr); 313bf215546Sopenharmony_ci memcpy(ptr, data, size); 314bf215546Sopenharmony_ci upload_res->Unmap(0, &res_range); 315bf215546Sopenharmony_ci return upload_res; 316bf215546Sopenharmony_ci} 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ciComPtr<ID3D12Resource> 319bf215546Sopenharmony_ciComputeTest::create_sized_buffer_with_data(size_t buffer_size, 320bf215546Sopenharmony_ci const void *data, 321bf215546Sopenharmony_ci size_t data_size) 322bf215546Sopenharmony_ci{ 323bf215546Sopenharmony_ci auto upload_res = create_upload_buffer_with_data(data, data_size); 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci auto res = create_buffer(buffer_size, D3D12_HEAP_TYPE_DEFAULT); 326bf215546Sopenharmony_ci resource_barrier(res, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST); 327bf215546Sopenharmony_ci cmdlist->CopyBufferRegion(res.Get(), 0, upload_res.Get(), 0, data_size); 328bf215546Sopenharmony_ci resource_barrier(res, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COMMON); 329bf215546Sopenharmony_ci execute_cmdlist(); 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci return res; 332bf215546Sopenharmony_ci} 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_civoid 335bf215546Sopenharmony_ciComputeTest::get_buffer_data(ComPtr<ID3D12Resource> res, 336bf215546Sopenharmony_ci void *buf, size_t size) 337bf215546Sopenharmony_ci{ 338bf215546Sopenharmony_ci auto readback_res = create_buffer(align(size, 4), D3D12_HEAP_TYPE_READBACK); 339bf215546Sopenharmony_ci resource_barrier(res, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_SOURCE); 340bf215546Sopenharmony_ci cmdlist->CopyResource(readback_res.Get(), res.Get()); 341bf215546Sopenharmony_ci resource_barrier(res, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COMMON); 342bf215546Sopenharmony_ci execute_cmdlist(); 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci void *ptr = NULL; 345bf215546Sopenharmony_ci D3D12_RANGE res_range = { 0, size }; 346bf215546Sopenharmony_ci if (FAILED(readback_res->Map(0, &res_range, &ptr))) 347bf215546Sopenharmony_ci throw runtime_error("Failed to map readback-buffer"); 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci memcpy(buf, ptr, size); 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci D3D12_RANGE empty_range = { 0, 0 }; 352bf215546Sopenharmony_ci readback_res->Unmap(0, &empty_range); 353bf215546Sopenharmony_ci} 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_civoid 356bf215546Sopenharmony_ciComputeTest::resource_barrier(ComPtr<ID3D12Resource> &res, 357bf215546Sopenharmony_ci D3D12_RESOURCE_STATES state_before, 358bf215546Sopenharmony_ci D3D12_RESOURCE_STATES state_after) 359bf215546Sopenharmony_ci{ 360bf215546Sopenharmony_ci D3D12_RESOURCE_BARRIER barrier; 361bf215546Sopenharmony_ci barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; 362bf215546Sopenharmony_ci barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; 363bf215546Sopenharmony_ci barrier.Transition.pResource = res.Get(); 364bf215546Sopenharmony_ci barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; 365bf215546Sopenharmony_ci barrier.Transition.StateBefore = state_before; 366bf215546Sopenharmony_ci barrier.Transition.StateAfter = state_after; 367bf215546Sopenharmony_ci cmdlist->ResourceBarrier(1, &barrier); 368bf215546Sopenharmony_ci} 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_civoid 371bf215546Sopenharmony_ciComputeTest::execute_cmdlist() 372bf215546Sopenharmony_ci{ 373bf215546Sopenharmony_ci if (FAILED(cmdlist->Close())) 374bf215546Sopenharmony_ci throw runtime_error("Closing ID3D12GraphicsCommandList failed"); 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci ID3D12CommandList *cmdlists[] = { cmdlist }; 377bf215546Sopenharmony_ci cmdqueue->ExecuteCommandLists(1, cmdlists); 378bf215546Sopenharmony_ci cmdqueue_fence->SetEventOnCompletion(fence_value, event); 379bf215546Sopenharmony_ci cmdqueue->Signal(cmdqueue_fence, fence_value); 380bf215546Sopenharmony_ci fence_value++; 381bf215546Sopenharmony_ci WaitForSingleObject(event, INFINITE); 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci if (FAILED(cmdalloc->Reset())) 384bf215546Sopenharmony_ci throw runtime_error("resetting ID3D12CommandAllocator failed"); 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci if (FAILED(cmdlist->Reset(cmdalloc, NULL))) 387bf215546Sopenharmony_ci throw runtime_error("resetting ID3D12GraphicsCommandList failed"); 388bf215546Sopenharmony_ci} 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_civoid 391bf215546Sopenharmony_ciComputeTest::create_uav_buffer(ComPtr<ID3D12Resource> res, 392bf215546Sopenharmony_ci size_t width, size_t byte_stride, 393bf215546Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle) 394bf215546Sopenharmony_ci{ 395bf215546Sopenharmony_ci D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc; 396bf215546Sopenharmony_ci uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; 397bf215546Sopenharmony_ci uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; 398bf215546Sopenharmony_ci uav_desc.Buffer.FirstElement = 0; 399bf215546Sopenharmony_ci uav_desc.Buffer.NumElements = DIV_ROUND_UP(width * byte_stride, 4); 400bf215546Sopenharmony_ci uav_desc.Buffer.StructureByteStride = 0; 401bf215546Sopenharmony_ci uav_desc.Buffer.CounterOffsetInBytes = 0; 402bf215546Sopenharmony_ci uav_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci dev->CreateUnorderedAccessView(res.Get(), NULL, &uav_desc, cpu_handle); 405bf215546Sopenharmony_ci} 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_civoid 408bf215546Sopenharmony_ciComputeTest::create_cbv(ComPtr<ID3D12Resource> res, size_t size, 409bf215546Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle) 410bf215546Sopenharmony_ci{ 411bf215546Sopenharmony_ci D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc; 412bf215546Sopenharmony_ci cbv_desc.BufferLocation = res ? res->GetGPUVirtualAddress() : 0; 413bf215546Sopenharmony_ci cbv_desc.SizeInBytes = size; 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_ci dev->CreateConstantBufferView(&cbv_desc, cpu_handle); 416bf215546Sopenharmony_ci} 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ciComPtr<ID3D12Resource> 419bf215546Sopenharmony_ciComputeTest::add_uav_resource(ComputeTest::Resources &resources, 420bf215546Sopenharmony_ci unsigned spaceid, unsigned resid, 421bf215546Sopenharmony_ci const void *data, size_t num_elems, 422bf215546Sopenharmony_ci size_t elem_size) 423bf215546Sopenharmony_ci{ 424bf215546Sopenharmony_ci size_t size = align(elem_size * num_elems, 4); 425bf215546Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE handle; 426bf215546Sopenharmony_ci ComPtr<ID3D12Resource> res; 427bf215546Sopenharmony_ci handle = GetCPUDescriptorHandleForHeapStart(uav_heap); 428bf215546Sopenharmony_ci handle = offset_cpu_handle(handle, resources.descs.size() * uav_heap_incr); 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci if (size) { 431bf215546Sopenharmony_ci if (data) 432bf215546Sopenharmony_ci res = create_buffer_with_data(data, size); 433bf215546Sopenharmony_ci else 434bf215546Sopenharmony_ci res = create_buffer(size, D3D12_HEAP_TYPE_DEFAULT); 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci resource_barrier(res, D3D12_RESOURCE_STATE_COMMON, 437bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_UNORDERED_ACCESS); 438bf215546Sopenharmony_ci } 439bf215546Sopenharmony_ci create_uav_buffer(res, num_elems, elem_size, handle); 440bf215546Sopenharmony_ci resources.add(res, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, spaceid, resid); 441bf215546Sopenharmony_ci return res; 442bf215546Sopenharmony_ci} 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ciComPtr<ID3D12Resource> 445bf215546Sopenharmony_ciComputeTest::add_cbv_resource(ComputeTest::Resources &resources, 446bf215546Sopenharmony_ci unsigned spaceid, unsigned resid, 447bf215546Sopenharmony_ci const void *data, size_t size) 448bf215546Sopenharmony_ci{ 449bf215546Sopenharmony_ci unsigned aligned_size = align(size, 256); 450bf215546Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE handle; 451bf215546Sopenharmony_ci ComPtr<ID3D12Resource> res; 452bf215546Sopenharmony_ci handle = GetCPUDescriptorHandleForHeapStart(uav_heap); 453bf215546Sopenharmony_ci handle = offset_cpu_handle(handle, resources.descs.size() * uav_heap_incr); 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci if (size) { 456bf215546Sopenharmony_ci assert(data); 457bf215546Sopenharmony_ci res = create_sized_buffer_with_data(aligned_size, data, size); 458bf215546Sopenharmony_ci } 459bf215546Sopenharmony_ci create_cbv(res, aligned_size, handle); 460bf215546Sopenharmony_ci resources.add(res, D3D12_DESCRIPTOR_RANGE_TYPE_CBV, spaceid, resid); 461bf215546Sopenharmony_ci return res; 462bf215546Sopenharmony_ci} 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_civoid 465bf215546Sopenharmony_ciComputeTest::run_shader_with_raw_args(Shader shader, 466bf215546Sopenharmony_ci const CompileArgs &compile_args, 467bf215546Sopenharmony_ci const std::vector<RawShaderArg *> &args) 468bf215546Sopenharmony_ci{ 469bf215546Sopenharmony_ci if (args.size() < 1) 470bf215546Sopenharmony_ci throw runtime_error("no inputs"); 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci static HMODULE hD3D12Mod = LoadLibrary("D3D12.DLL"); 473bf215546Sopenharmony_ci if (!hD3D12Mod) 474bf215546Sopenharmony_ci throw runtime_error("Failed to load D3D12.DLL"); 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci D3D12SerializeVersionedRootSignature = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)GetProcAddress(hD3D12Mod, "D3D12SerializeVersionedRootSignature"); 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci if (args.size() != shader.dxil->kernel->num_args) 479bf215546Sopenharmony_ci throw runtime_error("incorrect number of inputs"); 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci struct clc_runtime_kernel_conf conf = { 0 }; 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci // Older WARP and some hardware doesn't support int64, so for these tests, unconditionally lower away int64 484bf215546Sopenharmony_ci // A more complex runtime can be smarter about detecting when this needs to be done 485bf215546Sopenharmony_ci conf.lower_bit_size = 64; 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci if (!shader.dxil->metadata.local_size[0]) 488bf215546Sopenharmony_ci conf.local_size[0] = compile_args.x; 489bf215546Sopenharmony_ci else 490bf215546Sopenharmony_ci conf.local_size[0] = shader.dxil->metadata.local_size[0]; 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_ci if (!shader.dxil->metadata.local_size[1]) 493bf215546Sopenharmony_ci conf.local_size[1] = compile_args.y; 494bf215546Sopenharmony_ci else 495bf215546Sopenharmony_ci conf.local_size[1] = shader.dxil->metadata.local_size[1]; 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci if (!shader.dxil->metadata.local_size[2]) 498bf215546Sopenharmony_ci conf.local_size[2] = compile_args.z; 499bf215546Sopenharmony_ci else 500bf215546Sopenharmony_ci conf.local_size[2] = shader.dxil->metadata.local_size[2]; 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci if (compile_args.x % conf.local_size[0] || 503bf215546Sopenharmony_ci compile_args.y % conf.local_size[1] || 504bf215546Sopenharmony_ci compile_args.z % conf.local_size[2]) 505bf215546Sopenharmony_ci throw runtime_error("invalid global size must be a multiple of local size"); 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci std::vector<struct clc_runtime_arg_info> argsinfo(args.size()); 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci conf.args = argsinfo.data(); 510bf215546Sopenharmony_ci conf.support_global_work_id_offsets = 511bf215546Sopenharmony_ci compile_args.work_props.global_offset_x != 0 || 512bf215546Sopenharmony_ci compile_args.work_props.global_offset_y != 0 || 513bf215546Sopenharmony_ci compile_args.work_props.global_offset_z != 0; 514bf215546Sopenharmony_ci conf.support_workgroup_id_offsets = 515bf215546Sopenharmony_ci compile_args.work_props.group_id_offset_x != 0 || 516bf215546Sopenharmony_ci compile_args.work_props.group_id_offset_y != 0 || 517bf215546Sopenharmony_ci compile_args.work_props.group_id_offset_z != 0; 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci for (unsigned i = 0; i < shader.dxil->kernel->num_args; ++i) { 520bf215546Sopenharmony_ci RawShaderArg *arg = args[i]; 521bf215546Sopenharmony_ci size_t size = arg->get_elem_size() * arg->get_num_elems(); 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci switch (shader.dxil->kernel->args[i].address_qualifier) { 524bf215546Sopenharmony_ci case CLC_KERNEL_ARG_ADDRESS_LOCAL: 525bf215546Sopenharmony_ci argsinfo[i].localptr.size = size; 526bf215546Sopenharmony_ci break; 527bf215546Sopenharmony_ci default: 528bf215546Sopenharmony_ci break; 529bf215546Sopenharmony_ci } 530bf215546Sopenharmony_ci } 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci configure(shader, &conf); 533bf215546Sopenharmony_ci validate(shader); 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci std::shared_ptr<struct clc_dxil_object> &dxil = shader.dxil; 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci std::vector<uint8_t> argsbuf(dxil->metadata.kernel_inputs_buf_size); 538bf215546Sopenharmony_ci std::vector<ComPtr<ID3D12Resource>> argres(shader.dxil->kernel->num_args); 539bf215546Sopenharmony_ci clc_work_properties_data work_props = compile_args.work_props; 540bf215546Sopenharmony_ci if (!conf.support_workgroup_id_offsets) { 541bf215546Sopenharmony_ci work_props.group_count_total_x = compile_args.x / conf.local_size[0]; 542bf215546Sopenharmony_ci work_props.group_count_total_y = compile_args.y / conf.local_size[1]; 543bf215546Sopenharmony_ci work_props.group_count_total_z = compile_args.z / conf.local_size[2]; 544bf215546Sopenharmony_ci } 545bf215546Sopenharmony_ci if (work_props.work_dim == 0) 546bf215546Sopenharmony_ci work_props.work_dim = 3; 547bf215546Sopenharmony_ci Resources resources; 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci for (unsigned i = 0; i < dxil->kernel->num_args; ++i) { 550bf215546Sopenharmony_ci RawShaderArg *arg = args[i]; 551bf215546Sopenharmony_ci size_t size = arg->get_elem_size() * arg->get_num_elems(); 552bf215546Sopenharmony_ci void *slot = argsbuf.data() + dxil->metadata.args[i].offset; 553bf215546Sopenharmony_ci 554bf215546Sopenharmony_ci switch (dxil->kernel->args[i].address_qualifier) { 555bf215546Sopenharmony_ci case CLC_KERNEL_ARG_ADDRESS_CONSTANT: 556bf215546Sopenharmony_ci case CLC_KERNEL_ARG_ADDRESS_GLOBAL: { 557bf215546Sopenharmony_ci assert(dxil->metadata.args[i].size == sizeof(uint64_t)); 558bf215546Sopenharmony_ci uint64_t *ptr_slot = (uint64_t *)slot; 559bf215546Sopenharmony_ci if (arg->get_data()) 560bf215546Sopenharmony_ci *ptr_slot = (uint64_t)dxil->metadata.args[i].globconstptr.buf_id << 32; 561bf215546Sopenharmony_ci else 562bf215546Sopenharmony_ci *ptr_slot = ~0ull; 563bf215546Sopenharmony_ci break; 564bf215546Sopenharmony_ci } 565bf215546Sopenharmony_ci case CLC_KERNEL_ARG_ADDRESS_LOCAL: { 566bf215546Sopenharmony_ci assert(dxil->metadata.args[i].size == sizeof(uint64_t)); 567bf215546Sopenharmony_ci uint64_t *ptr_slot = (uint64_t *)slot; 568bf215546Sopenharmony_ci *ptr_slot = dxil->metadata.args[i].localptr.sharedmem_offset; 569bf215546Sopenharmony_ci break; 570bf215546Sopenharmony_ci } 571bf215546Sopenharmony_ci case CLC_KERNEL_ARG_ADDRESS_PRIVATE: { 572bf215546Sopenharmony_ci assert(size == dxil->metadata.args[i].size); 573bf215546Sopenharmony_ci memcpy(slot, arg->get_data(), size); 574bf215546Sopenharmony_ci break; 575bf215546Sopenharmony_ci } 576bf215546Sopenharmony_ci default: 577bf215546Sopenharmony_ci assert(0); 578bf215546Sopenharmony_ci } 579bf215546Sopenharmony_ci } 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_ci for (unsigned i = 0; i < dxil->kernel->num_args; ++i) { 582bf215546Sopenharmony_ci RawShaderArg *arg = args[i]; 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci if (dxil->kernel->args[i].address_qualifier == CLC_KERNEL_ARG_ADDRESS_GLOBAL || 585bf215546Sopenharmony_ci dxil->kernel->args[i].address_qualifier == CLC_KERNEL_ARG_ADDRESS_CONSTANT) { 586bf215546Sopenharmony_ci argres[i] = add_uav_resource(resources, 0, 587bf215546Sopenharmony_ci dxil->metadata.args[i].globconstptr.buf_id, 588bf215546Sopenharmony_ci arg->get_data(), arg->get_num_elems(), 589bf215546Sopenharmony_ci arg->get_elem_size()); 590bf215546Sopenharmony_ci } 591bf215546Sopenharmony_ci } 592bf215546Sopenharmony_ci 593bf215546Sopenharmony_ci if (dxil->metadata.printf.uav_id > 0) 594bf215546Sopenharmony_ci add_uav_resource(resources, 0, dxil->metadata.printf.uav_id, NULL, 1024 * 1024 / 4, 4); 595bf215546Sopenharmony_ci 596bf215546Sopenharmony_ci for (unsigned i = 0; i < dxil->metadata.num_consts; ++i) 597bf215546Sopenharmony_ci add_uav_resource(resources, 0, dxil->metadata.consts[i].uav_id, 598bf215546Sopenharmony_ci dxil->metadata.consts[i].data, 599bf215546Sopenharmony_ci dxil->metadata.consts[i].size / 4, 4); 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci if (argsbuf.size()) 602bf215546Sopenharmony_ci add_cbv_resource(resources, 0, dxil->metadata.kernel_inputs_cbv_id, 603bf215546Sopenharmony_ci argsbuf.data(), argsbuf.size()); 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci add_cbv_resource(resources, 0, dxil->metadata.work_properties_cbv_id, 606bf215546Sopenharmony_ci &work_props, sizeof(work_props)); 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_ci auto root_sig = create_root_signature(resources); 609bf215546Sopenharmony_ci auto pipeline_state = create_pipeline_state(root_sig, *dxil); 610bf215546Sopenharmony_ci 611bf215546Sopenharmony_ci cmdlist->SetDescriptorHeaps(1, &uav_heap); 612bf215546Sopenharmony_ci cmdlist->SetComputeRootSignature(root_sig.Get()); 613bf215546Sopenharmony_ci cmdlist->SetComputeRootDescriptorTable(0, GetGPUDescriptorHandleForHeapStart(uav_heap)); 614bf215546Sopenharmony_ci cmdlist->SetPipelineState(pipeline_state.Get()); 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_ci cmdlist->Dispatch(compile_args.x / conf.local_size[0], 617bf215546Sopenharmony_ci compile_args.y / conf.local_size[1], 618bf215546Sopenharmony_ci compile_args.z / conf.local_size[2]); 619bf215546Sopenharmony_ci 620bf215546Sopenharmony_ci for (auto &range : resources.ranges) { 621bf215546Sopenharmony_ci if (range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV) { 622bf215546Sopenharmony_ci for (unsigned i = range.OffsetInDescriptorsFromTableStart; 623bf215546Sopenharmony_ci i < range.NumDescriptors; i++) { 624bf215546Sopenharmony_ci if (!resources.descs[i].Get()) 625bf215546Sopenharmony_ci continue; 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_ci resource_barrier(resources.descs[i], 628bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 629bf215546Sopenharmony_ci D3D12_RESOURCE_STATE_COMMON); 630bf215546Sopenharmony_ci } 631bf215546Sopenharmony_ci } 632bf215546Sopenharmony_ci } 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci execute_cmdlist(); 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci for (unsigned i = 0; i < args.size(); i++) { 637bf215546Sopenharmony_ci if (!(args[i]->get_direction() & SHADER_ARG_OUTPUT)) 638bf215546Sopenharmony_ci continue; 639bf215546Sopenharmony_ci 640bf215546Sopenharmony_ci assert(dxil->kernel->args[i].address_qualifier == CLC_KERNEL_ARG_ADDRESS_GLOBAL); 641bf215546Sopenharmony_ci get_buffer_data(argres[i], args[i]->get_data(), 642bf215546Sopenharmony_ci args[i]->get_elem_size() * args[i]->get_num_elems()); 643bf215546Sopenharmony_ci } 644bf215546Sopenharmony_ci 645bf215546Sopenharmony_ci ComPtr<ID3D12InfoQueue> info_queue; 646bf215546Sopenharmony_ci dev->QueryInterface(info_queue.ReleaseAndGetAddressOf()); 647bf215546Sopenharmony_ci if (info_queue) 648bf215546Sopenharmony_ci { 649bf215546Sopenharmony_ci EXPECT_EQ(0, info_queue->GetNumStoredMessages()); 650bf215546Sopenharmony_ci for (unsigned i = 0; i < info_queue->GetNumStoredMessages(); ++i) { 651bf215546Sopenharmony_ci SIZE_T message_size = 0; 652bf215546Sopenharmony_ci info_queue->GetMessageA(i, nullptr, &message_size); 653bf215546Sopenharmony_ci D3D12_MESSAGE* message = (D3D12_MESSAGE*)malloc(message_size); 654bf215546Sopenharmony_ci info_queue->GetMessageA(i, message, &message_size); 655bf215546Sopenharmony_ci FAIL() << message->pDescription; 656bf215546Sopenharmony_ci free(message); 657bf215546Sopenharmony_ci } 658bf215546Sopenharmony_ci } 659bf215546Sopenharmony_ci} 660bf215546Sopenharmony_ci 661bf215546Sopenharmony_civoid 662bf215546Sopenharmony_ciComputeTest::SetUp() 663bf215546Sopenharmony_ci{ 664bf215546Sopenharmony_ci static struct clc_libclc *compiler_ctx_g = nullptr; 665bf215546Sopenharmony_ci 666bf215546Sopenharmony_ci if (!compiler_ctx_g) { 667bf215546Sopenharmony_ci clc_libclc_dxil_options options = { }; 668bf215546Sopenharmony_ci options.optimize = (debug_get_option_debug_compute() & COMPUTE_DEBUG_OPTIMIZE_LIBCLC) != 0; 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci compiler_ctx_g = clc_libclc_new_dxil(&logger, &options); 671bf215546Sopenharmony_ci if (!compiler_ctx_g) 672bf215546Sopenharmony_ci throw runtime_error("failed to create CLC compiler context"); 673bf215546Sopenharmony_ci 674bf215546Sopenharmony_ci if (debug_get_option_debug_compute() & COMPUTE_DEBUG_SERIALIZE_LIBCLC) { 675bf215546Sopenharmony_ci void *serialized = nullptr; 676bf215546Sopenharmony_ci size_t serialized_size = 0; 677bf215546Sopenharmony_ci clc_libclc_serialize(compiler_ctx_g, &serialized, &serialized_size); 678bf215546Sopenharmony_ci if (!serialized) 679bf215546Sopenharmony_ci throw runtime_error("failed to serialize CLC compiler context"); 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_ci clc_free_libclc(compiler_ctx_g); 682bf215546Sopenharmony_ci compiler_ctx_g = nullptr; 683bf215546Sopenharmony_ci 684bf215546Sopenharmony_ci compiler_ctx_g = clc_libclc_deserialize(serialized, serialized_size); 685bf215546Sopenharmony_ci if (!compiler_ctx_g) 686bf215546Sopenharmony_ci throw runtime_error("failed to deserialize CLC compiler context"); 687bf215546Sopenharmony_ci 688bf215546Sopenharmony_ci clc_libclc_free_serialized(serialized); 689bf215546Sopenharmony_ci } 690bf215546Sopenharmony_ci } 691bf215546Sopenharmony_ci compiler_ctx = compiler_ctx_g; 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci enable_d3d12_debug_layer(); 694bf215546Sopenharmony_ci 695bf215546Sopenharmony_ci factory = get_dxgi_factory(); 696bf215546Sopenharmony_ci if (!factory) 697bf215546Sopenharmony_ci throw runtime_error("failed to create DXGI factory"); 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_ci adapter = choose_adapter(factory); 700bf215546Sopenharmony_ci if (!adapter) 701bf215546Sopenharmony_ci throw runtime_error("failed to choose adapter"); 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci dev = create_device(adapter); 704bf215546Sopenharmony_ci if (!dev) 705bf215546Sopenharmony_ci throw runtime_error("failed to create device"); 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci if (FAILED(dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, 708bf215546Sopenharmony_ci __uuidof(cmdqueue_fence), 709bf215546Sopenharmony_ci (void **)&cmdqueue_fence))) 710bf215546Sopenharmony_ci throw runtime_error("failed to create fence\n"); 711bf215546Sopenharmony_ci 712bf215546Sopenharmony_ci D3D12_COMMAND_QUEUE_DESC queue_desc; 713bf215546Sopenharmony_ci queue_desc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE; 714bf215546Sopenharmony_ci queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; 715bf215546Sopenharmony_ci queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; 716bf215546Sopenharmony_ci queue_desc.NodeMask = 0; 717bf215546Sopenharmony_ci if (FAILED(dev->CreateCommandQueue(&queue_desc, 718bf215546Sopenharmony_ci __uuidof(cmdqueue), 719bf215546Sopenharmony_ci (void **)&cmdqueue))) 720bf215546Sopenharmony_ci throw runtime_error("failed to create command queue"); 721bf215546Sopenharmony_ci 722bf215546Sopenharmony_ci if (FAILED(dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COMPUTE, 723bf215546Sopenharmony_ci __uuidof(cmdalloc), (void **)&cmdalloc))) 724bf215546Sopenharmony_ci throw runtime_error("failed to create command allocator"); 725bf215546Sopenharmony_ci 726bf215546Sopenharmony_ci if (FAILED(dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COMPUTE, 727bf215546Sopenharmony_ci cmdalloc, NULL, __uuidof(cmdlist), (void **)&cmdlist))) 728bf215546Sopenharmony_ci throw runtime_error("failed to create command list"); 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci D3D12_DESCRIPTOR_HEAP_DESC heap_desc; 731bf215546Sopenharmony_ci heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; 732bf215546Sopenharmony_ci heap_desc.NumDescriptors = 1000; 733bf215546Sopenharmony_ci heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; 734bf215546Sopenharmony_ci heap_desc.NodeMask = 0; 735bf215546Sopenharmony_ci if (FAILED(dev->CreateDescriptorHeap(&heap_desc, 736bf215546Sopenharmony_ci __uuidof(uav_heap), (void **)&uav_heap))) 737bf215546Sopenharmony_ci throw runtime_error("failed to create descriptor heap"); 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_ci uav_heap_incr = dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); 740bf215546Sopenharmony_ci 741bf215546Sopenharmony_ci event = CreateEvent(NULL, FALSE, FALSE, NULL); 742bf215546Sopenharmony_ci if (!event) 743bf215546Sopenharmony_ci throw runtime_error("Failed to create event"); 744bf215546Sopenharmony_ci fence_value = 1; 745bf215546Sopenharmony_ci} 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_civoid 748bf215546Sopenharmony_ciComputeTest::TearDown() 749bf215546Sopenharmony_ci{ 750bf215546Sopenharmony_ci CloseHandle(event); 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci uav_heap->Release(); 753bf215546Sopenharmony_ci cmdlist->Release(); 754bf215546Sopenharmony_ci cmdalloc->Release(); 755bf215546Sopenharmony_ci cmdqueue->Release(); 756bf215546Sopenharmony_ci cmdqueue_fence->Release(); 757bf215546Sopenharmony_ci dev->Release(); 758bf215546Sopenharmony_ci adapter->Release(); 759bf215546Sopenharmony_ci factory->Release(); 760bf215546Sopenharmony_ci} 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ciPFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE ComputeTest::D3D12SerializeVersionedRootSignature; 763bf215546Sopenharmony_ci 764bf215546Sopenharmony_cibool 765bf215546Sopenharmony_civalidate_module(const struct clc_dxil_object &dxil) 766bf215546Sopenharmony_ci{ 767bf215546Sopenharmony_ci struct dxil_validator *val = dxil_create_validator(NULL); 768bf215546Sopenharmony_ci char *err; 769bf215546Sopenharmony_ci bool res = dxil_validate_module(val, dxil.binary.data, 770bf215546Sopenharmony_ci dxil.binary.size, &err); 771bf215546Sopenharmony_ci if (!res && err) 772bf215546Sopenharmony_ci fprintf(stderr, "D3D12: validation failed: %s", err); 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_ci dxil_destroy_validator(val); 775bf215546Sopenharmony_ci return res; 776bf215546Sopenharmony_ci} 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_cistatic void 779bf215546Sopenharmony_cidump_blob(const char *path, const struct clc_dxil_object &dxil) 780bf215546Sopenharmony_ci{ 781bf215546Sopenharmony_ci FILE *fp = fopen(path, "wb"); 782bf215546Sopenharmony_ci if (fp) { 783bf215546Sopenharmony_ci fwrite(dxil.binary.data, 1, dxil.binary.size, fp); 784bf215546Sopenharmony_ci fclose(fp); 785bf215546Sopenharmony_ci printf("D3D12: wrote '%s'...\n", path); 786bf215546Sopenharmony_ci } 787bf215546Sopenharmony_ci} 788bf215546Sopenharmony_ci 789bf215546Sopenharmony_ciComputeTest::Shader 790bf215546Sopenharmony_ciComputeTest::compile(const std::vector<const char *> &sources, 791bf215546Sopenharmony_ci const std::vector<const char *> &compile_args, 792bf215546Sopenharmony_ci bool create_library) 793bf215546Sopenharmony_ci{ 794bf215546Sopenharmony_ci struct clc_compile_args args = { 795bf215546Sopenharmony_ci }; 796bf215546Sopenharmony_ci args.args = compile_args.data(); 797bf215546Sopenharmony_ci args.num_args = (unsigned)compile_args.size(); 798bf215546Sopenharmony_ci ComputeTest::Shader shader; 799bf215546Sopenharmony_ci 800bf215546Sopenharmony_ci std::vector<Shader> shaders; 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_ci args.source.name = "obj.cl"; 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_ci for (unsigned i = 0; i < sources.size(); i++) { 805bf215546Sopenharmony_ci args.source.value = sources[i]; 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_ci clc_binary spirv{}; 808bf215546Sopenharmony_ci if (!clc_compile_c_to_spirv(&args, &logger, &spirv)) 809bf215546Sopenharmony_ci throw runtime_error("failed to compile object!"); 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_ci Shader shader; 812bf215546Sopenharmony_ci shader.obj = std::shared_ptr<clc_binary>(new clc_binary(spirv), [](clc_binary *spirv) 813bf215546Sopenharmony_ci { 814bf215546Sopenharmony_ci clc_free_spirv(spirv); 815bf215546Sopenharmony_ci delete spirv; 816bf215546Sopenharmony_ci }); 817bf215546Sopenharmony_ci shaders.push_back(shader); 818bf215546Sopenharmony_ci } 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci if (shaders.size() == 1 && create_library) 821bf215546Sopenharmony_ci return shaders[0]; 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci return link(shaders, create_library); 824bf215546Sopenharmony_ci} 825bf215546Sopenharmony_ci 826bf215546Sopenharmony_ciComputeTest::Shader 827bf215546Sopenharmony_ciComputeTest::link(const std::vector<Shader> &sources, 828bf215546Sopenharmony_ci bool create_library) 829bf215546Sopenharmony_ci{ 830bf215546Sopenharmony_ci std::vector<const clc_binary*> objs; 831bf215546Sopenharmony_ci for (auto& source : sources) 832bf215546Sopenharmony_ci objs.push_back(&*source.obj); 833bf215546Sopenharmony_ci 834bf215546Sopenharmony_ci struct clc_linker_args link_args = {}; 835bf215546Sopenharmony_ci link_args.in_objs = objs.data(); 836bf215546Sopenharmony_ci link_args.num_in_objs = (unsigned)objs.size(); 837bf215546Sopenharmony_ci link_args.create_library = create_library; 838bf215546Sopenharmony_ci clc_binary spirv{}; 839bf215546Sopenharmony_ci if (!clc_link_spirv(&link_args, &logger, &spirv)) 840bf215546Sopenharmony_ci throw runtime_error("failed to link objects!"); 841bf215546Sopenharmony_ci 842bf215546Sopenharmony_ci ComputeTest::Shader shader; 843bf215546Sopenharmony_ci shader.obj = std::shared_ptr<clc_binary>(new clc_binary(spirv), [](clc_binary *spirv) 844bf215546Sopenharmony_ci { 845bf215546Sopenharmony_ci clc_free_spirv(spirv); 846bf215546Sopenharmony_ci delete spirv; 847bf215546Sopenharmony_ci }); 848bf215546Sopenharmony_ci if (!link_args.create_library) 849bf215546Sopenharmony_ci configure(shader, NULL); 850bf215546Sopenharmony_ci 851bf215546Sopenharmony_ci return shader; 852bf215546Sopenharmony_ci} 853bf215546Sopenharmony_ci 854bf215546Sopenharmony_ciComputeTest::Shader 855bf215546Sopenharmony_ciComputeTest::assemble(const char *source) 856bf215546Sopenharmony_ci{ 857bf215546Sopenharmony_ci spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_0); 858bf215546Sopenharmony_ci std::vector<uint32_t> binary; 859bf215546Sopenharmony_ci if (!tools.Assemble(source, strlen(source), &binary)) 860bf215546Sopenharmony_ci throw runtime_error("failed to assemble"); 861bf215546Sopenharmony_ci 862bf215546Sopenharmony_ci ComputeTest::Shader shader; 863bf215546Sopenharmony_ci shader.obj = std::shared_ptr<clc_binary>(new clc_binary{}, [](clc_binary *spirv) 864bf215546Sopenharmony_ci { 865bf215546Sopenharmony_ci free(spirv->data); 866bf215546Sopenharmony_ci delete spirv; 867bf215546Sopenharmony_ci }); 868bf215546Sopenharmony_ci shader.obj->size = binary.size() * 4; 869bf215546Sopenharmony_ci shader.obj->data = malloc(shader.obj->size); 870bf215546Sopenharmony_ci memcpy(shader.obj->data, binary.data(), shader.obj->size); 871bf215546Sopenharmony_ci 872bf215546Sopenharmony_ci configure(shader, NULL); 873bf215546Sopenharmony_ci 874bf215546Sopenharmony_ci return shader; 875bf215546Sopenharmony_ci} 876bf215546Sopenharmony_ci 877bf215546Sopenharmony_civoid 878bf215546Sopenharmony_ciComputeTest::configure(Shader &shader, 879bf215546Sopenharmony_ci const struct clc_runtime_kernel_conf *conf) 880bf215546Sopenharmony_ci{ 881bf215546Sopenharmony_ci if (!shader.metadata) { 882bf215546Sopenharmony_ci shader.metadata = std::shared_ptr<clc_parsed_spirv>(new clc_parsed_spirv{}, [](clc_parsed_spirv *metadata) 883bf215546Sopenharmony_ci { 884bf215546Sopenharmony_ci clc_free_parsed_spirv(metadata); 885bf215546Sopenharmony_ci delete metadata; 886bf215546Sopenharmony_ci }); 887bf215546Sopenharmony_ci if (!clc_parse_spirv(shader.obj.get(), NULL, shader.metadata.get())) 888bf215546Sopenharmony_ci throw runtime_error("failed to parse spirv!"); 889bf215546Sopenharmony_ci } 890bf215546Sopenharmony_ci 891bf215546Sopenharmony_ci std::unique_ptr<clc_dxil_object> dxil(new clc_dxil_object{}); 892bf215546Sopenharmony_ci if (!clc_spirv_to_dxil(compiler_ctx, shader.obj.get(), shader.metadata.get(), "main_test", conf, nullptr, &logger, dxil.get())) 893bf215546Sopenharmony_ci throw runtime_error("failed to compile kernel!"); 894bf215546Sopenharmony_ci shader.dxil = std::shared_ptr<clc_dxil_object>(dxil.release(), [](clc_dxil_object *dxil) 895bf215546Sopenharmony_ci { 896bf215546Sopenharmony_ci clc_free_dxil_object(dxil); 897bf215546Sopenharmony_ci delete dxil; 898bf215546Sopenharmony_ci }); 899bf215546Sopenharmony_ci} 900bf215546Sopenharmony_ci 901bf215546Sopenharmony_civoid 902bf215546Sopenharmony_ciComputeTest::validate(ComputeTest::Shader &shader) 903bf215546Sopenharmony_ci{ 904bf215546Sopenharmony_ci dump_blob("unsigned.cso", *shader.dxil); 905bf215546Sopenharmony_ci if (!validate_module(*shader.dxil)) 906bf215546Sopenharmony_ci throw runtime_error("failed to validate module!"); 907bf215546Sopenharmony_ci 908bf215546Sopenharmony_ci dump_blob("signed.cso", *shader.dxil); 909bf215546Sopenharmony_ci} 910