diff --git a/CMakeLists.txt b/CMakeLists.txt index 219101e82..92d8184ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,6 +129,7 @@ add_definitions(-DAMBER_ENGINE_DAWN=$) add_definitions(-DAMBER_ENABLE_SPIRV_TOOLS=$) add_definitions(-DAMBER_ENABLE_SHADERC=$) add_definitions(-DAMBER_ENABLE_DXC=$) +add_definitions(-DAMBER_ENABLE_CLSPV=$) set(CMAKE_DEBUG_POSTFIX "") diff --git a/docs/amber_script.md b/docs/amber_script.md index 6e0bd3548..cbe5c737f 100644 --- a/docs/amber_script.md +++ b/docs/amber_script.md @@ -85,7 +85,7 @@ types, but in that case must only provide a single shader type in the module. * `HLSL`  (with dxc or glslang if dxc disabled) -- future * `SPIRV-ASM` (with spirv-as) * `SPIRV-HEX` (decoded straight to SPIR-V) - * `OPENCL-C` (with clspv)  --- potentially? -- future + * `OPENCL-C` (with clspv) ```groovy # Creates a passthrough vertex shader. The shader passes the vec4 at input diff --git a/include/amber/shader_info.h b/include/amber/shader_info.h index d01644171..713b18c49 100644 --- a/include/amber/shader_info.h +++ b/include/amber/shader_info.h @@ -27,6 +27,7 @@ enum ShaderFormat { kShaderFormatHlsl, kShaderFormatSpirvAsm, kShaderFormatSpirvHex, + kShaderFormatOpenCLC, }; enum ShaderType { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff1a15e8b..03d183afa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,6 +55,10 @@ if (${AMBER_ENABLE_DXC}) list(APPEND AMBER_SOURCES dxc_helper.cc) endif() +if (${AMBER_ENABLE_CLSPV}) + list(APPEND AMBER_SOURCES clspv_helper.cc) +endif() + add_library(libamber ${AMBER_SOURCES}) amber_default_compile_options(libamber) target_include_directories(libamber PRIVATE "${CMAKE_BINARY_DIR}") @@ -76,6 +80,17 @@ if (${AMBER_ENABLE_DXC}) ) endif() +if (${AMBER_ENABLE_CLSPV}) + target_include_directories(libamber PRIVATE + "${PROJECT_SOURCE_DIR}/third_party/clspv/include" + ) + + target_link_libraries(libamber + clspv_core + clspv_passes + ) +endif() + if (${AMBER_ENABLE_SPIRV_TOOLS}) target_link_libraries(libamber SPIRV-Tools) endif() diff --git a/src/amberscript/parser.cc b/src/amberscript/parser.cc index 2c1fc05e0..412f33fab 100644 --- a/src/amberscript/parser.cc +++ b/src/amberscript/parser.cc @@ -187,6 +187,8 @@ Result Parser::ToShaderFormat(const std::string& str, ShaderFormat* fmt) { *fmt = kShaderFormatSpirvAsm; else if (str == "SPIRV-HEX") *fmt = kShaderFormatSpirvHex; + else if (str == "OPENCL-C") + *fmt = kShaderFormatOpenCLC; else return Result("unknown shader format: " + str); return {}; diff --git a/src/amberscript/parser_shader_test.cc b/src/amberscript/parser_shader_test.cc index 47f3c1d39..f9fd95725 100644 --- a/src/amberscript/parser_shader_test.cc +++ b/src/amberscript/parser_shader_test.cc @@ -340,5 +340,29 @@ END)"; EXPECT_EQ("7: duplicate shader name provided", r.Error()); } +TEST_F(AmberScriptParserTest, OpenCLCKernel) { + std::string in = R"( +SHADER compute my_shader OPENCL-C +# shader +END +)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_TRUE(r.IsSuccess()); +} + +TEST_F(AmberScriptParserTest, OpenCLCMultiKernel) { + std::string in = R"( +SHADER multi my_shader OPENCL-C +# shader +END +)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_TRUE(r.IsSuccess()); +} + } // namespace amberscript } // namespace amber diff --git a/src/clspv_helper.cc b/src/clspv_helper.cc new file mode 100644 index 000000000..056b5d511 --- /dev/null +++ b/src/clspv_helper.cc @@ -0,0 +1,35 @@ +// Copyright 2019 The Amber Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/clspv_helper.h" + +#include "clspv/Compiler.h" + +namespace amber { +namespace clspvhelper { + +Result Compile(const std::string& src_str, + std::vector* generated_binary) { + // TODO(alan-baker): Parse the descriptor map. + std::vector entries; + if (clspv::CompileFromSourceString(src_str, "", "", generated_binary, + &entries)) { + return Result("Clspv compile failed"); + } + + return Result(); +} + +} // namespace clspvhelper +} // namespace amber diff --git a/src/clspv_helper.h b/src/clspv_helper.h new file mode 100644 index 000000000..367253213 --- /dev/null +++ b/src/clspv_helper.h @@ -0,0 +1,34 @@ +// Copyright 2019 The Amber Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_CLSPV_HELPER_H_ +#define SRC_CLSPV_HELPER_H_ + +#include +#include + +#include "amber/result.h" + +namespace amber { +namespace clspvhelper { + +// Passes the OpenCL C source code to Clspv. +// Returns the generated SPIR-V binary via |generated_binary| argument. +Result Compile(const std::string& src_str, + std::vector* generated_binary); + +} // namespace clspvhelper +} // namespace amber + +#endif // SRC_CLSPV_HELPER_H_ diff --git a/src/shader_compiler.cc b/src/shader_compiler.cc index 674da4acb..a0c737e09 100644 --- a/src/shader_compiler.cc +++ b/src/shader_compiler.cc @@ -38,6 +38,10 @@ #include "src/dxc_helper.h" #endif // AMBER_ENABLE_DXC +#ifdef AMBER_ENABLE_CLSPV +#include "src/clspv_helper.h" +#endif // AMBER_ENABLE_CLSPV + namespace amber { ShaderCompiler::ShaderCompiler() = default; @@ -116,6 +120,13 @@ std::pair> ShaderCompiler::Compile( } #endif // AMBER_ENABLE_SPIRV_TOOLS +#if AMBER_ENABLE_CLSPV + } else if (shader->GetFormat() == kShaderFormatOpenCLC) { + Result r = CompileOpenCLC(shader, &results); + if (!r.IsSuccess()) + return {r, {}}; +#endif // AMBER_ENABLE_CLSPV + } else { return {Result("Invalid shader format"), results}; } @@ -218,4 +229,16 @@ Result ShaderCompiler::CompileHlsl(const Shader*, } #endif // AMBER_ENABLE_DXC +#if AMBER_ENABLE_CLSPV +Result ShaderCompiler::CompileOpenCLC(const Shader* shader, + std::vector* result) const { + return clspvhelper::Compile(shader->GetData(), result); +} +#else +Result ShaderCompiler::CompileOpenCLC(const Shader*, + std::vector*) const { + return {}; +} +#endif // AMBER_ENABLE_CLSPV + } // namespace amber diff --git a/src/shader_compiler.h b/src/shader_compiler.h index 3c0067d4f..52fd0272b 100644 --- a/src/shader_compiler.h +++ b/src/shader_compiler.h @@ -44,6 +44,8 @@ class ShaderCompiler { Result ParseHex(const std::string& data, std::vector* result) const; Result CompileGlsl(const Shader* shader, std::vector* result) const; Result CompileHlsl(const Shader* shader, std::vector* result) const; + Result CompileOpenCLC(const Shader* shader, + std::vector* result) const; std::string spv_env_; }; diff --git a/tests/cases/opencl_c_copy.amber b/tests/cases/opencl_c_copy.amber new file mode 100644 index 000000000..343b6b443 --- /dev/null +++ b/tests/cases/opencl_c_copy.amber @@ -0,0 +1,35 @@ +#!amber +# Copyright 2019 The Amber Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +SHADER compute my_shader OPENCL-C +kernel void foo(global int* in, global int* out) { + *out = *in; +} +END + +BUFFER in_buf DATA_TYPE uint32 DATA + 9 +END +BUFFER out_buf DATA_TYPE uint32 SIZE 1 FILL 0 + +PIPELINE compute my_pipeline + ATTACH my_shader ENTRY_POINT foo + BIND BUFFER in_buf AS storage DESCRIPTOR_SET 0 BINDING 0 + BIND BUFFER out_buf AS storage DESCRIPTOR_SET 0 BINDING 1 +END + +RUN my_pipeline 1 1 1 + +EXPECT out_buf EQ_BUFFER in_buf