cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
set(sources demo.cpp)
add_executable(demo ${sources})
-target_link_libraries(demo vulkan_cpu_spirv vulkan_cpu_util vulkan_cpu_spirv_to_llvm)
+target_link_libraries(demo vulkan_cpu_spirv vulkan_cpu_util vulkan_cpu_pipeline vulkan_cpu_vulkan)
#include "spirv/parser.h"
#include "util/optional.h"
#include "util/string_view.h"
-#include "spirv_to_llvm/spirv_to_llvm.h"
-#include "llvm_wrapper/llvm_wrapper.h"
+#include "pipeline/pipeline.h"
+#include "vulkan/vulkan.h"
namespace vulkan_cpu
{
auto file = load_file(filename);
if(file)
{
- {
- dump_words(*file);
- std::cerr << std::endl;
- spirv::Dump_callbacks dump_callbacks;
- try
- {
- spirv::parse(dump_callbacks, file->data(), file->size());
- }
- catch(spirv::Parser_error &e)
- {
- std::cerr << dump_callbacks.ss.str() << std::endl;
- std::cerr << "error: " << e.what();
- return 1;
- }
- std::cerr << dump_callbacks.ss.str() << std::endl;
- }
- auto llvm_target_machine = llvm_wrapper::Target_machine::create_native_target_machine();
- auto llvm_context = llvm_wrapper::Context::create();
- std::uint64_t next_module_id = 1;
- spirv_to_llvm::Converted_module converted_module;
+ dump_words(*file);
+ std::cerr << std::endl;
try
{
- converted_module = spirv_to_llvm::spirv_to_llvm(llvm_context.get(),
- llvm_target_machine.get(),
- file->data(),
- file->size(),
- next_module_id++,
- spirv::Execution_model::vertex,
- "main");
+ VkShaderModuleCreateInfo shader_module_create_info = {
+ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .codeSize = file->size() * sizeof(spirv::Word),
+ .pCode = file->data(),
+ };
+ auto shader_module = pipeline::Shader_module_handle::make(shader_module_create_info);
+ VkPipelineLayoutCreateInfo pipeline_layout_create_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .setLayoutCount = 0,
+ .pSetLayouts = nullptr,
+ .pushConstantRangeCount = 0,
+ .pPushConstantRanges = nullptr,
+ };
+ auto pipeline_layout =
+ pipeline::Pipeline_layout_handle::make(pipeline_layout_create_info);
+ constexpr std::size_t subpass_count = 1;
+ VkSubpassDescription subpass_descriptions[subpass_count] = {
+ {
+ .flags = 0,
+ .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
+ .inputAttachmentCount = 0,
+ .pInputAttachments = nullptr,
+ .colorAttachmentCount = 0,
+ .pColorAttachments = nullptr,
+ .pResolveAttachments = nullptr,
+ .pDepthStencilAttachment = nullptr,
+ .preserveAttachmentCount = 0,
+ .pPreserveAttachments = nullptr,
+ },
+ };
+ VkRenderPassCreateInfo render_pass_create_info = {
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .attachmentCount = 0,
+ .pAttachments = nullptr,
+ .subpassCount = subpass_count,
+ .pSubpasses = subpass_descriptions,
+ .dependencyCount = 0,
+ .pDependencies = nullptr,
+ };
+ auto render_pass = pipeline::Render_pass_handle::make(render_pass_create_info);
+ constexpr std::size_t stage_count = 1;
+ VkPipelineShaderStageCreateInfo stages[stage_count] = {
+ {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .stage = VK_SHADER_STAGE_VERTEX_BIT,
+ .module = pipeline::to_handle(shader_module.get()),
+ .pName = "main",
+ .pSpecializationInfo = nullptr,
+ },
+ };
+ VkPipelineVertexInputStateCreateInfo pipeline_vertex_input_state_create_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .vertexBindingDescriptionCount = 0,
+ .pVertexBindingDescriptions = nullptr,
+ .vertexAttributeDescriptionCount = 0,
+ .pVertexAttributeDescriptions = nullptr,
+ };
+ VkPipelineInputAssemblyStateCreateInfo pipeline_input_assembly_state_create_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
+ .primitiveRestartEnable = false,
+ };
+ VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_create_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .depthClampEnable = false,
+ .rasterizerDiscardEnable = true,
+ .polygonMode = VK_POLYGON_MODE_FILL,
+ .cullMode = VK_CULL_MODE_BACK_BIT,
+ .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
+ .depthBiasEnable = false,
+ .depthBiasConstantFactor = 0,
+ .depthBiasClamp = 0,
+ .depthBiasSlopeFactor = 0,
+ .lineWidth = 1,
+ };
+ VkGraphicsPipelineCreateInfo graphics_pipeline_create_info = {
+ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .stageCount = stage_count,
+ .pStages = stages,
+ .pVertexInputState = &pipeline_vertex_input_state_create_info,
+ .pInputAssemblyState = &pipeline_input_assembly_state_create_info,
+ .pTessellationState = nullptr,
+ .pViewportState = nullptr,
+ .pRasterizationState = &pipeline_rasterization_state_create_info,
+ .pMultisampleState = nullptr,
+ .pDepthStencilState = nullptr,
+ .pColorBlendState = nullptr,
+ .pDynamicState = nullptr,
+ .layout = pipeline::to_handle(pipeline_layout.get()),
+ .renderPass = pipeline::to_handle(render_pass.get()),
+ .subpass = 0,
+ .basePipelineHandle = VK_NULL_HANDLE,
+ .basePipelineIndex = -1,
+ };
+ auto graphics_pipeline =
+ pipeline::Graphics_pipeline::make(nullptr, graphics_pipeline_create_info);
+ std::cerr << "vertex_shader_output_struct_size: "
+ << graphics_pipeline->get_vertex_shader_output_struct_size() << std::endl;
+ constexpr std::uint32_t vertex_start_index = 0;
+ constexpr std::uint32_t vertex_end_index = 3;
+ constexpr std::uint32_t instance_id = 0;
+ constexpr std::size_t vertex_count = vertex_end_index - vertex_start_index;
+ std::unique_ptr<unsigned char[]> output_buffer(
+ new unsigned char[graphics_pipeline->get_vertex_shader_output_struct_size()
+ * vertex_count]);
+ auto vertex_shader_function = graphics_pipeline->get_vertex_shader_function();
+ vertex_shader_function(
+ vertex_start_index, vertex_end_index, instance_id, output_buffer.get());
+ std::cerr << "shader completed" << std::endl;
}
- catch(spirv::Parser_error &e)
+ catch(std::runtime_error &e)
{
- std::cerr << "error: " << e.what();
+ std::cerr << "error: " << e.what() << std::endl;
return 1;
}
- std::cerr << "Translation to LLVM succeeded." << std::endl;
- ::LLVMDumpModule(converted_module.module.get());
- bool failed =
- ::LLVMVerifyModule(converted_module.module.get(), ::LLVMPrintMessageAction, nullptr);
- if(failed)
- return 1;
- auto orc_jit_stack = llvm_wrapper::Orc_jit_stack::create(std::move(llvm_target_machine));
- orc_jit_stack.add_eagerly_compiled_ir(
- std::move(converted_module.module),
- [](const char *symbol_name, [[gnu::unused]] void *user_data) noexcept->std::uint64_t
- {
- std::cerr << "resolving symbol: " << symbol_name << std::endl;
- void *symbol = nullptr;
- return reinterpret_cast<std::uintptr_t>(symbol);
- },
- nullptr);
- auto function = reinterpret_cast<void *>(
- orc_jit_stack.get_symbol_address(converted_module.entry_function_name.c_str()));
- std::cerr << "entry point: " << converted_module.entry_function_name << ": " << reinterpret_cast<void *>(function)
- << std::endl;
}
else
{
*
*/
#include "pipeline.h"
+#include "spirv_to_llvm/spirv_to_llvm.h"
+#include "llvm_wrapper/llvm_wrapper.h"
+#include "vulkan/util.h"
#include <stdexcept>
+#include <cassert>
+#include <vector>
+#include <iostream>
namespace vulkan_cpu
{
namespace pipeline
{
+class Pipeline_cache
+{
+};
+
+void Api_object_deleter<Pipeline_cache>::operator()(Pipeline_cache *pipeline_cache) const noexcept
+{
+ delete pipeline_cache;
+}
+
+class Render_pass
+{
+};
+
+void Api_object_deleter<Render_pass>::operator()(Render_pass *render_pass) const noexcept
+{
+ delete render_pass;
+}
+
+template <>
+Render_pass_handle Render_pass_handle::make(const VkRenderPassCreateInfo &render_pass_create_info)
+{
+#warning finish implementing Render_pass_handle::make
+ return Render_pass_handle(new Render_pass());
+}
+
+class Pipeline_layout
+{
+};
+
+void Api_object_deleter<Pipeline_layout>::operator()(Pipeline_layout *pipeline_layout) const
+ noexcept
+{
+ delete pipeline_layout;
+}
+
+template <>
+Pipeline_layout_handle Pipeline_layout_handle::make(
+ const VkPipelineLayoutCreateInfo &pipeline_layout_create_info)
+{
+#warning finish implementing Pipeline_layout_handle::make
+ return Pipeline_layout_handle(new Pipeline_layout());
+}
+
+struct Graphics_pipeline::Implementation
+{
+ spirv_to_llvm::Jit_symbol_resolver jit_symbol_resolver;
+ llvm_wrapper::Orc_jit_stack jit_stack;
+ llvm_wrapper::Context llvm_context = llvm_wrapper::Context::create();
+ std::uint64_t next_module_id = 1;
+ std::uint64_t make_module_id() noexcept
+ {
+ return next_module_id++;
+ }
+};
+
std::unique_ptr<Graphics_pipeline> Graphics_pipeline::make(
Pipeline_cache *pipeline_cache, const VkGraphicsPipelineCreateInfo &create_info)
{
+ assert(create_info.sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
+ auto *render_pass = Render_pass_handle::from_handle(create_info.renderPass);
+ assert(render_pass);
+ auto *pipeline_layout = Pipeline_layout_handle::from_handle(create_info.layout);
+ assert(pipeline_layout);
+ if(create_info.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT)
+ {
+#warning implement creating derived pipelines
+ throw std::runtime_error("creating derived pipelines is not implemented");
+ }
+ auto implementation = std::make_shared<Implementation>();
+ auto llvm_target_machine = llvm_wrapper::Target_machine::create_native_target_machine();
+ std::vector<spirv_to_llvm::Converted_module> compiled_shaders;
+ compiled_shaders.reserve(create_info.stageCount);
+ for(std::size_t i = 0; i < create_info.stageCount; i++)
+ {
+ auto &stage_info = create_info.pStages[i];
+ auto execution_models =
+ vulkan::get_execution_models_from_shader_stage_flags(stage_info.stage);
+ assert(execution_models.size() == 1);
+ auto execution_model = *execution_models.begin();
+ auto *shader_module = Shader_module_handle::from_handle(stage_info.module);
+ assert(shader_module);
+ {
+ spirv::Dump_callbacks dump_callbacks;
+ try
+ {
+ spirv::parse(dump_callbacks, shader_module->words(), shader_module->word_count());
+ }
+ catch(spirv::Parser_error &e)
+ {
+ std::cerr << dump_callbacks.ss.str() << std::endl;
+ throw;
+ }
+ std::cerr << dump_callbacks.ss.str() << std::endl;
+ }
+ auto compiled_shader = spirv_to_llvm::spirv_to_llvm(implementation->llvm_context.get(),
+ llvm_target_machine.get(),
+ shader_module->words(),
+ shader_module->word_count(),
+ implementation->make_module_id(),
+ execution_model,
+ stage_info.pName);
+ std::cerr << "Translation to LLVM succeeded." << std::endl;
+ ::LLVMDumpModule(compiled_shader.module.get());
+ bool failed =
+ ::LLVMVerifyModule(compiled_shader.module.get(), ::LLVMPrintMessageAction, nullptr);
+ if(failed)
+ throw std::runtime_error("LLVM module verification failed");
+ compiled_shaders.push_back(std::move(compiled_shader));
+ }
+ auto data_layout = llvm_target_machine.create_target_data_layout();
+ implementation->jit_stack = llvm_wrapper::Orc_jit_stack::create(std::move(llvm_target_machine));
+ Vertex_shader_function vertex_shader_function = nullptr;
+ std::size_t vertex_shader_output_struct_size = 0;
+ for(auto &compiled_shader : compiled_shaders)
+ {
+ vertex_shader_output_struct_size = implementation->jit_stack.add_eagerly_compiled_ir(
+ std::move(compiled_shader.module),
+ &spirv_to_llvm::Jit_symbol_resolver::resolve,
+ static_cast<void *>(&implementation->jit_symbol_resolver));
+ auto shader_entry_point_address = implementation->jit_stack.get_symbol_address(
+ compiled_shader.entry_function_name.c_str());
+ std::cerr << "shader entry: " << compiled_shader.entry_function_name << ": "
+ << reinterpret_cast<void *>(shader_entry_point_address) << std::endl;
+ assert(shader_entry_point_address);
+ switch(compiled_shader.execution_model)
+ {
+ case spirv::Execution_model::fragment:
+#warning finish implementing Graphics_pipeline::make
+ throw std::runtime_error("creating fragment shaders is not implemented");
+ case spirv::Execution_model::geometry:
+#warning finish implementing Graphics_pipeline::make
+ throw std::runtime_error("creating geometry shaders is not implemented");
+ case spirv::Execution_model::gl_compute:
+ case spirv::Execution_model::kernel:
+ throw std::runtime_error("can't create compute shaders from Graphics_pipeline::make");
+ case spirv::Execution_model::tessellation_control:
+ case spirv::Execution_model::tessellation_evaluation:
+#warning finish implementing Graphics_pipeline::make
+ throw std::runtime_error("creating tessellation shaders is not implemented");
+ case spirv::Execution_model::vertex:
+ {
+ vertex_shader_function =
+ reinterpret_cast<Vertex_shader_function>(shader_entry_point_address);
+ vertex_shader_output_struct_size = ::LLVMABISizeOfType(
+ data_layout.get(), compiled_shader.outputs_struct->get_or_make_type().type);
+#warning finish implementing Graphics_pipeline::make
+ continue;
+ }
+ }
+ throw std::runtime_error("unknown shader kind");
+ }
#warning finish implementing Graphics_pipeline::make
- throw std::runtime_error("Graphics_pipeline::make is not implemented");
+ if(!vertex_shader_function)
+ throw std::runtime_error("graphics pipeline doesn't have vertex shader");
+ return std::unique_ptr<Graphics_pipeline>(new Graphics_pipeline(
+ std::move(implementation), vertex_shader_function, vertex_shader_output_struct_size));
}
}
}
#include <cstdint>
#include <utility>
#include <cassert>
+#include <cstring>
#include "llvm_wrapper/llvm_wrapper.h"
#include "vulkan/vulkan.h"
+#include "spirv/spirv.h"
namespace vulkan_cpu
{
namespace pipeline
{
-class Pipeline_cache;
-
-class Pipeline_cache_handle
+template <typename T>
+struct Api_object_deleter
{
-private:
- static void destroy(Pipeline_cache *value) noexcept;
+ void operator()(T *) const noexcept = delete;
+ typedef void Vulkan_handle;
+ typedef void Create_info;
+};
-public:
- explicit Pipeline_cache_handle(Pipeline_cache *value) noexcept : value(value)
- {
- }
- constexpr Pipeline_cache_handle() noexcept : value(nullptr)
- {
- }
- Pipeline_cache_handle(Pipeline_cache_handle &&rt) noexcept : value(rt.value)
- {
- rt.value = nullptr;
- }
- Pipeline_cache_handle &operator=(Pipeline_cache_handle rt) noexcept
- {
- swap(rt);
- return *this;
- }
- ~Pipeline_cache_handle() noexcept
- {
- if(value)
- destroy(value);
- }
- void swap(Pipeline_cache_handle &rt) noexcept
- {
- using std::swap;
- swap(value, rt.value);
- }
- static Pipeline_cache *from_handle(VkPipelineCache pipeline_cache) noexcept
+template <typename Object_>
+struct Api_object_handle : public std::unique_ptr<Object_, Api_object_deleter<Object_>>
+{
+ typedef typename Api_object_deleter<Object_>::Vulkan_handle Vulkan_handle;
+ typedef typename Api_object_deleter<Object_>::Create_info Create_info;
+ typedef Object_ Object;
+ using std::unique_ptr<Object_, Api_object_deleter<Object_>>::unique_ptr;
+ static Object *from_handle(Vulkan_handle vulkan_handle) noexcept
{
- return reinterpret_cast<Pipeline_cache *>(pipeline_cache);
+ return reinterpret_cast<Object *>(vulkan_handle);
}
- static Pipeline_cache_handle move_from_handle(VkPipelineCache pipeline_cache) noexcept
+ static Api_object_handle move_from_handle(Vulkan_handle vulkan_handle) noexcept
{
- return Pipeline_cache_handle(from_handle(pipeline_cache));
+ return Api_object_handle(from_handle(vulkan_handle));
}
- Pipeline_cache *get() const noexcept
+ static Api_object_handle make(const Create_info &create_info);
+};
+
+template <typename Object>
+inline typename Api_object_deleter<Object>::Vulkan_handle to_handle(Object *object) noexcept
+{
+ static_assert(!std::is_void<typename Api_object_deleter<Object>::Vulkan_handle>::value, "");
+ return reinterpret_cast<typename Api_object_deleter<Object>::Vulkan_handle>(object);
+}
+
+template <typename Object>
+inline typename Api_object_deleter<Object>::Vulkan_handle move_to_handle(
+ Api_object_handle<Object> object) noexcept
+{
+ return to_handle(object.release());
+}
+
+class Pipeline_cache;
+
+template <>
+struct Api_object_deleter<Pipeline_cache>
+{
+ void operator()(Pipeline_cache *pipeline_cache) const noexcept;
+ typedef VkPipelineCache Vulkan_handle;
+ typedef VkPipelineCacheCreateInfo Create_info;
+};
+
+typedef Api_object_handle<Pipeline_cache> Pipeline_cache_handle;
+
+class Render_pass;
+
+template <>
+struct Api_object_deleter<Render_pass>
+{
+ void operator()(Render_pass *render_pass) const noexcept;
+ typedef VkRenderPass Vulkan_handle;
+ typedef VkRenderPassCreateInfo Create_info;
+};
+
+typedef Api_object_handle<Render_pass> Render_pass_handle;
+
+class Pipeline_layout;
+
+template <>
+struct Api_object_deleter<Pipeline_layout>
+{
+ void operator()(Pipeline_layout *pipeline_layout) const noexcept;
+ typedef VkPipelineLayout Vulkan_handle;
+ typedef VkPipelineLayoutCreateInfo Create_info;
+};
+
+typedef Api_object_handle<Pipeline_layout> Pipeline_layout_handle;
+
+struct Shader_module
+{
+ std::shared_ptr<unsigned char> bytes;
+ std::size_t byte_count;
+ Shader_module(std::shared_ptr<unsigned char> bytes, std::size_t byte_count) noexcept
+ : bytes(std::move(bytes)),
+ byte_count(byte_count)
{
- return value;
}
- Pipeline_cache *release() noexcept
+ const spirv::Word *words() const noexcept
{
- auto retval = value;
- value = nullptr;
- return retval;
+ return reinterpret_cast<const spirv::Word *>(bytes.get());
}
- Pipeline_cache *operator->() const noexcept
+ std::size_t word_count() const noexcept
{
- assert(value);
- return value;
+ assert(byte_count % sizeof(spirv::Word) == 0);
+ return byte_count / sizeof(spirv::Word);
}
- Pipeline_cache &operator*() const noexcept
+};
+
+template <>
+struct Api_object_deleter<Shader_module>
+{
+ void operator()(Shader_module *shader_module) const noexcept
{
- return *operator->();
+ delete shader_module;
}
-
-private:
- Pipeline_cache *value;
+ typedef VkShaderModule Vulkan_handle;
+ typedef VkShaderModuleCreateInfo Create_info;
};
-inline VkPipelineCache to_handle(Pipeline_cache *pipeline_cache) noexcept
-{
- return reinterpret_cast<VkPipelineCache>(pipeline_cache);
-}
+typedef Api_object_handle<Shader_module> Shader_module_handle;
-inline VkPipelineCache move_to_handle(Pipeline_cache_handle pipeline_cache) noexcept
+template <>
+inline Shader_module_handle Shader_module_handle::make(const VkShaderModuleCreateInfo &create_info)
{
- return to_handle(pipeline_cache.release());
+ struct Code_deleter
+ {
+ void operator()(unsigned char *bytes) const noexcept
+ {
+ delete[] bytes;
+ }
+ };
+ auto bytes =
+ std::shared_ptr<unsigned char>(new unsigned char[create_info.codeSize], Code_deleter{});
+ std::memcpy(bytes.get(), create_info.pCode, create_info.codeSize);
+ return Shader_module_handle(new Shader_module(std::move(bytes), create_info.codeSize));
}
class Pipeline
class Graphics_pipeline final : public Pipeline
{
+private:
+ struct Implementation;
+
public:
#warning finish adding draw function parameters
typedef void (*Vertex_shader_function)(std::uint32_t vertex_start_index,
void *output_buffer);
public:
- const Vertex_shader_function get_vertex_shader_function() const noexcept
+ Vertex_shader_function get_vertex_shader_function() const noexcept
{
return vertex_shader_function;
}
+ std::size_t get_vertex_shader_output_struct_size() const noexcept
+ {
+ return vertex_shader_output_struct_size;
+ }
static std::unique_ptr<Graphics_pipeline> make(Pipeline_cache *pipeline_cache,
const VkGraphicsPipelineCreateInfo &create_info);
static std::unique_ptr<Graphics_pipeline> move_from_handle(VkPipeline pipeline) noexcept
}
private:
- Graphics_pipeline(std::shared_ptr<void> state,
- Vertex_shader_function vertex_shader_function) noexcept
- : state(std::move(state)),
- vertex_shader_function(vertex_shader_function)
+ Graphics_pipeline(std::shared_ptr<Implementation> implementation,
+ Vertex_shader_function vertex_shader_function,
+ std::size_t vertex_shader_output_struct_size) noexcept
+ : implementation(std::move(implementation)),
+ vertex_shader_function(vertex_shader_function),
+ vertex_shader_output_struct_size(vertex_shader_output_struct_size)
{
}
private:
- std::shared_ptr<void> state;
+ std::shared_ptr<Implementation> implementation;
Vertex_shader_function vertex_shader_function;
+ std::size_t vertex_shader_output_struct_size;
};
inline VkPipeline to_handle(Graphics_pipeline *pipeline) noexcept
return Converted_module(std::move(module),
std::move(entry_function_name),
std::move(inputs_struct),
- std::move(outputs_struct));
+ std::move(outputs_struct),
+ execution_model);
}
virtual void handle_header(unsigned version_number_major,
unsigned version_number_minor,
std::string entry_function_name;
std::shared_ptr<Struct_type_descriptor> inputs_struct;
std::shared_ptr<Struct_type_descriptor> outputs_struct;
+ spirv::Execution_model execution_model;
Converted_module() = default;
explicit Converted_module(llvm_wrapper::Module module,
std::string entry_function_name,
std::shared_ptr<Struct_type_descriptor> inputs_struct,
- std::shared_ptr<Struct_type_descriptor> outputs_struct) noexcept
+ std::shared_ptr<Struct_type_descriptor> outputs_struct,
+ spirv::Execution_model execution_model) noexcept
: module(std::move(module)),
entry_function_name(std::move(entry_function_name)),
inputs_struct(std::move(inputs_struct)),
- outputs_struct(std::move(outputs_struct))
+ outputs_struct(std::move(outputs_struct)),
+ execution_model(execution_model)
{
}
};
+struct Jit_symbol_resolver
+{
+ typedef void (*Resolved_symbol)();
+ Resolved_symbol resolve(const char *name)
+ {
+#warning finish implementing
+ return nullptr;
+ }
+ static std::uint64_t resolve(const char *name, void *user_data) noexcept
+ {
+ return reinterpret_cast<std::uint64_t>(
+ static_cast<Jit_symbol_resolver *>(user_data)->resolve(name));
+ }
+};
+
class Spirv_to_llvm;
Converted_module spirv_to_llvm(::LLVMContextRef context,
--- /dev/null
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * 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 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.
+ *
+ */
+#ifndef VULKAN_UTIL_H_
+#define VULKAN_UTIL_H_
+
+#include "vulkan/vulkan.h"
+#include "spirv/spirv.h"
+#include "util/enum.h"
+
+namespace vulkan_cpu
+{
+namespace vulkan
+{
+constexpr util::Enum_set<spirv::Execution_model> get_execution_models_from_shader_stage_flags(
+ VkShaderStageFlags stages) noexcept
+{
+ util::Enum_set<spirv::Execution_model> retval;
+ if(stages & VK_SHADER_STAGE_COMPUTE_BIT)
+ retval.insert(spirv::Execution_model::gl_compute);
+ if(stages & VK_SHADER_STAGE_FRAGMENT_BIT)
+ retval.insert(spirv::Execution_model::fragment);
+ if(stages & VK_SHADER_STAGE_GEOMETRY_BIT)
+ retval.insert(spirv::Execution_model::geometry);
+ if(stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
+ retval.insert(spirv::Execution_model::tessellation_control);
+ if(stages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
+ retval.insert(spirv::Execution_model::tessellation_evaluation);
+ if(stages & VK_SHADER_STAGE_VERTEX_BIT)
+ retval.insert(spirv::Execution_model::vertex);
+ return retval;
+}
+}
+}
+
+#endif // VULKAN_UTIL_H_