mesa/src/microsoft/clc/compute_test.h

356 lines
11 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdexcept>
#include <directx/d3d12.h>
#include <dxgi1_4.h>
#include <gtest/gtest.h>
#include <wrl.h>
#include "clc_compiler.h"
using std::runtime_error;
using Microsoft::WRL::ComPtr;
inline D3D12_CPU_DESCRIPTOR_HANDLE
offset_cpu_handle(D3D12_CPU_DESCRIPTOR_HANDLE handle, UINT offset)
{
handle.ptr += offset;
return handle;
}
inline size_t
align(size_t value, unsigned alignment)
{
assert(alignment > 0);
return ((value + (alignment - 1)) / alignment) * alignment;
}
class ComputeTest : public ::testing::Test {
protected:
struct Shader {
std::shared_ptr<struct clc_binary> obj;
std::shared_ptr<struct clc_parsed_spirv> metadata;
std::shared_ptr<struct clc_dxil_object> dxil;
};
static void
enable_d3d12_debug_layer();
static IDXGIFactory4 *
get_dxgi_factory();
static IDXGIAdapter1 *
choose_adapter(IDXGIFactory4 *factory);
static ID3D12Device *
create_device(IDXGIAdapter1 *adapter);
struct Resources {
void add(ComPtr<ID3D12Resource> res,
D3D12_DESCRIPTOR_RANGE_TYPE type,
unsigned spaceid,
unsigned resid)
{
descs.push_back(res);
if(!ranges.empty() &&
ranges.back().RangeType == type &&
ranges.back().RegisterSpace == spaceid &&
ranges.back().BaseShaderRegister + ranges.back().NumDescriptors == resid) {
ranges.back().NumDescriptors++;
return;
}
D3D12_DESCRIPTOR_RANGE1 range;
range.RangeType = type;
range.NumDescriptors = 1;
range.BaseShaderRegister = resid;
range.RegisterSpace = spaceid;
range.OffsetInDescriptorsFromTableStart = descs.size() - 1;
range.Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS;
ranges.push_back(range);
}
std::vector<D3D12_DESCRIPTOR_RANGE1> ranges;
std::vector<ComPtr<ID3D12Resource>> descs;
};
ComPtr<ID3D12RootSignature>
create_root_signature(const Resources &resources);
ComPtr<ID3D12PipelineState>
create_pipeline_state(ComPtr<ID3D12RootSignature> &root_sig,
const struct clc_dxil_object &dxil);
ComPtr<ID3D12Resource>
create_buffer(int size, D3D12_HEAP_TYPE heap_type);
ComPtr<ID3D12Resource>
create_upload_buffer_with_data(const void *data, size_t size);
ComPtr<ID3D12Resource>
create_sized_buffer_with_data(size_t buffer_size, const void *data,
size_t data_size);
ComPtr<ID3D12Resource>
create_buffer_with_data(const void *data, size_t size)
{
return create_sized_buffer_with_data(size, data, size);
}
void
get_buffer_data(ComPtr<ID3D12Resource> res,
void *buf, size_t size);
void
resource_barrier(ComPtr<ID3D12Resource> &res,
D3D12_RESOURCE_STATES state_before,
D3D12_RESOURCE_STATES state_after);
void
execute_cmdlist();
void
create_uav_buffer(ComPtr<ID3D12Resource> res,
size_t width, size_t byte_stride,
D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle);
void create_cbv(ComPtr<ID3D12Resource> res, size_t size,
D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle);
ComPtr<ID3D12Resource>
add_uav_resource(Resources &resources, unsigned spaceid, unsigned resid,
const void *data = NULL, size_t num_elems = 0,
size_t elem_size = 0);
ComPtr<ID3D12Resource>
add_cbv_resource(Resources &resources, unsigned spaceid, unsigned resid,
const void *data, size_t size);
void
SetUp() override;
void
TearDown() override;
Shader
compile(const std::vector<const char *> &sources,
const std::vector<const char *> &compile_args = {},
bool create_library = false);
Shader
link(const std::vector<Shader> &sources,
bool create_library = false);
Shader
assemble(const char *source);
void
configure(Shader &shader,
const struct clc_runtime_kernel_conf *conf);
void
validate(Shader &shader);
template <typename T>
Shader
specialize(Shader &shader, uint32_t id, T const& val)
{
Shader new_shader;
new_shader.obj = std::shared_ptr<clc_binary>(new clc_binary{}, [](clc_binary *spirv)
{
clc_free_spirv(spirv);
delete spirv;
});
if (!shader.metadata)
configure(shader, NULL);
clc_spirv_specialization spec;
spec.id = id;
memcpy(&spec.value, &val, sizeof(val));
clc_spirv_specialization_consts consts;
consts.specializations = &spec;
consts.num_specializations = 1;
if (!clc_specialize_spirv(shader.obj.get(), shader.metadata.get(), &consts, new_shader.obj.get()))
throw runtime_error("failed to specialize");
configure(new_shader, NULL);
return new_shader;
}
enum ShaderArgDirection {
SHADER_ARG_INPUT = 1,
SHADER_ARG_OUTPUT = 2,
SHADER_ARG_INOUT = SHADER_ARG_INPUT | SHADER_ARG_OUTPUT,
};
class RawShaderArg {
public:
RawShaderArg(enum ShaderArgDirection dir) : dir(dir) { }
virtual size_t get_elem_size() const = 0;
virtual size_t get_num_elems() const = 0;
virtual const void *get_data() const = 0;
virtual void *get_data() = 0;
enum ShaderArgDirection get_direction() { return dir; }
private:
enum ShaderArgDirection dir;
};
class NullShaderArg : public RawShaderArg {
public:
NullShaderArg() : RawShaderArg(SHADER_ARG_INPUT) { }
size_t get_elem_size() const override { return 0; }
size_t get_num_elems() const override { return 0; }
const void *get_data() const override { return NULL; }
void *get_data() override { return NULL; }
};
template <typename T>
class ShaderArg : public std::vector<T>, public RawShaderArg
{
public:
ShaderArg(const T &v, enum ShaderArgDirection dir = SHADER_ARG_INOUT) :
std::vector<T>({ v }), RawShaderArg(dir) { }
ShaderArg(const std::vector<T> &v, enum ShaderArgDirection dir = SHADER_ARG_INOUT) :
std::vector<T>(v), RawShaderArg(dir) { }
ShaderArg(const std::initializer_list<T> v, enum ShaderArgDirection dir = SHADER_ARG_INOUT) :
std::vector<T>(v), RawShaderArg(dir) { }
ShaderArg<T>& operator =(const T &v)
{
this->clear();
this->push_back(v);
return *this;
}
operator T&() { return this->at(0); }
operator const T&() const { return this->at(0); }
ShaderArg<T>& operator =(const std::vector<T> &v)
{
*this = v;
return *this;
}
ShaderArg<T>& operator =(std::initializer_list<T> v)
{
*this = v;
return *this;
}
size_t get_elem_size() const override { return sizeof(T); }
size_t get_num_elems() const override { return this->size(); }
const void *get_data() const override { return this->data(); }
void *get_data() override { return this->data(); }
};
struct CompileArgs
{
unsigned x, y, z;
std::vector<const char *> compiler_command_line;
clc_work_properties_data work_props;
};
private:
void gather_args(std::vector<RawShaderArg *> &args) { }
template <typename T, typename... Rest>
void gather_args(std::vector<RawShaderArg *> &args, T &arg, Rest&... rest)
{
args.push_back(&arg);
gather_args(args, rest...);
}
void run_shader_with_raw_args(Shader shader,
const CompileArgs &compile_args,
const std::vector<RawShaderArg *> &args);
protected:
template <typename... Args>
void run_shader(Shader shader,
const CompileArgs &compile_args,
Args&... args)
{
std::vector<RawShaderArg *> raw_args;
gather_args(raw_args, args...);
run_shader_with_raw_args(shader, compile_args, raw_args);
}
template <typename... Args>
void run_shader(const std::vector<const char *> &sources,
unsigned x, unsigned y, unsigned z,
Args&... args)
{
std::vector<RawShaderArg *> raw_args;
gather_args(raw_args, args...);
CompileArgs compile_args = { x, y, z };
run_shader_with_raw_args(compile(sources), compile_args, raw_args);
}
template <typename... Args>
void run_shader(const std::vector<const char *> &sources,
const CompileArgs &compile_args,
Args&... args)
{
std::vector<RawShaderArg *> raw_args;
gather_args(raw_args, args...);
run_shader_with_raw_args(
compile(sources, compile_args.compiler_command_line),
compile_args, raw_args);
}
template <typename... Args>
void run_shader(const char *source,
unsigned x, unsigned y, unsigned z,
Args&... args)
{
std::vector<RawShaderArg *> raw_args;
gather_args(raw_args, args...);
CompileArgs compile_args = { x, y, z };
run_shader_with_raw_args(compile({ source }), compile_args, raw_args);
}
IDXGIFactory4 *factory;
IDXGIAdapter1 *adapter;
ID3D12Device *dev;
ID3D12Fence *cmdqueue_fence;
ID3D12CommandQueue *cmdqueue;
ID3D12CommandAllocator *cmdalloc;
ID3D12GraphicsCommandList *cmdlist;
ID3D12DescriptorHeap *uav_heap;
struct clc_libclc *compiler_ctx;
UINT uav_heap_incr;
int fence_value;
HANDLE event;
static PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE D3D12SerializeVersionedRootSignature;
};