Commit 3b03246c authored by Jesse Natalie's avatar Jesse Natalie
Browse files

microsoft/clc: Add a test for specializing via SPIRV-Tools

parent bb87e3d7
Pipeline #377217 waiting for manual action with stages
in 9 seconds
......@@ -2232,3 +2232,82 @@ TEST_F(ComputeTest, unused_arg)
for (int i = 0; i < 4; ++i)
EXPECT_EQ(dest[i], i + 1);
}
TEST_F(ComputeTest, spec_constant)
{
const char *spirv_asm = R"(
OpCapability Addresses
OpCapability Kernel
OpCapability Int64
%1 = OpExtInstImport "OpenCL.std"
OpMemoryModel Physical64 OpenCL
OpEntryPoint Kernel %2 "main_test" %__spirv_BuiltInGlobalInvocationId
%4 = OpString "kernel_arg_type.main_test.uint*,"
OpSource OpenCL_C 102000
OpName %__spirv_BuiltInGlobalInvocationId "__spirv_BuiltInGlobalInvocationId"
OpName %output "output"
OpName %entry "entry"
OpName %output_addr "output.addr"
OpName %id "id"
OpName %call "call"
OpName %conv "conv"
OpName %idxprom "idxprom"
OpName %arrayidx "arrayidx"
OpName %add "add"
OpName %mul "mul"
OpName %idxprom1 "idxprom1"
OpName %arrayidx2 "arrayidx2"
OpDecorate %__spirv_BuiltInGlobalInvocationId BuiltIn GlobalInvocationId
OpDecorate %__spirv_BuiltInGlobalInvocationId Constant
OpDecorate %id Alignment 4
OpDecorate %output_addr Alignment 8
OpDecorate %uint_1 SpecId 1
%ulong = OpTypeInt 64 0
%uint = OpTypeInt 32 0
%uint_1 = OpSpecConstant %uint 1
%v3ulong = OpTypeVector %ulong 3
%_ptr_Input_v3ulong = OpTypePointer Input %v3ulong
%void = OpTypeVoid
%_ptr_CrossWorkgroup_uint = OpTypePointer CrossWorkgroup %uint
%24 = OpTypeFunction %void %_ptr_CrossWorkgroup_uint
%_ptr_Function__ptr_CrossWorkgroup_uint = OpTypePointer Function %_ptr_CrossWorkgroup_uint
%_ptr_Function_uint = OpTypePointer Function %uint
%__spirv_BuiltInGlobalInvocationId = OpVariable %_ptr_Input_v3ulong Input
%2 = OpFunction %void DontInline %24
%output = OpFunctionParameter %_ptr_CrossWorkgroup_uint
%entry = OpLabel
%output_addr = OpVariable %_ptr_Function__ptr_CrossWorkgroup_uint Function
%id = OpVariable %_ptr_Function_uint Function
OpStore %output_addr %output Aligned 8
%27 = OpLoad %v3ulong %__spirv_BuiltInGlobalInvocationId Aligned 32
%call = OpCompositeExtract %ulong %27 0
%conv = OpUConvert %uint %call
OpStore %id %conv Aligned 4
%28 = OpLoad %_ptr_CrossWorkgroup_uint %output_addr Aligned 8
%29 = OpLoad %uint %id Aligned 4
%idxprom = OpUConvert %ulong %29
%arrayidx = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uint %28 %idxprom
%30 = OpLoad %uint %arrayidx Aligned 4
%31 = OpLoad %uint %id Aligned 4
%add = OpIAdd %uint %31 %uint_1
%mul = OpIMul %uint %30 %add
%32 = OpLoad %_ptr_CrossWorkgroup_uint %output_addr Aligned 8
%33 = OpLoad %uint %id Aligned 4
%idxprom1 = OpUConvert %ulong %33
%arrayidx2 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uint %32 %idxprom1
OpStore %arrayidx2 %mul Aligned 4
OpReturn
OpFunctionEnd)";
Shader shader = assemble(spirv_asm);
Shader spec_shader = specialize(shader, 1, 5);
auto inout = ShaderArg<uint32_t>({ 0x00000001, 0x10000001, 0x00020002, 0x04010203 },
SHADER_ARG_INOUT);
const uint32_t expected[] = {
0x00000005, 0x60000006, 0x000e000e, 0x20081018
};
CompileArgs args = { inout.size(), 1, 1 };
run_shader(spec_shader, args, inout);
for (int i = 0; i < inout.size(); ++i)
EXPECT_EQ(inout[i], expected[i]);
}
......@@ -35,6 +35,8 @@
#include "compute_test.h"
#include "dxcapi.h"
#include <spirv-tools/libspirv.hpp>
using std::runtime_error;
using Microsoft::WRL::ComPtr;
......@@ -850,6 +852,29 @@ ComputeTest::link(const std::vector<Shader> &sources,
return shader;
}
ComputeTest::Shader
ComputeTest::assemble(const char *source)
{
spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
std::vector<uint32_t> binary;
if (!tools.Assemble(source, strlen(source), &binary))
throw runtime_error("failed to assemble");
ComputeTest::Shader shader;
shader.obj = std::shared_ptr<clc_binary>(new clc_binary{}, [](clc_binary *spirv)
{
free(spirv->data);
delete spirv;
});
shader.obj->size = binary.size() * 4;
shader.obj->data = malloc(shader.obj->size);
memcpy(shader.obj->data, binary.data(), shader.obj->size);
configure(shader, NULL);
return shader;
}
void
ComputeTest::configure(Shader &shader,
const struct clc_runtime_kernel_conf *conf)
......
......@@ -167,6 +167,9 @@ protected:
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);
......@@ -174,6 +177,33 @@ protected:
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,
......
......@@ -63,8 +63,8 @@ if dep_dxheaders.found()
clc_compiler_test = executable('clc_compiler_test',
['clc_compiler_test.cpp', 'compute_test.cpp'],
link_with : [libclc_compiler],
dependencies : [idep_gtest, idep_mesautil, idep_libdxil_compiler, dep_dxheaders],
include_directories : [inc_include, inc_src])
dependencies : [idep_gtest, idep_mesautil, idep_libdxil_compiler, dep_dxheaders, dep_spirv_tools],
include_directories : [inc_include, inc_src, inc_spirv])
test('clc_compiler_test', clc_compiler_test, timeout: 180)
endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment