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