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