vertex shader runs
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 17 Aug 2017 08:19:36 +0000 (01:19 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 17 Aug 2017 08:19:36 +0000 (01:19 -0700)
src/demo/CMakeLists.txt
src/demo/demo.cpp
src/pipeline/pipeline.cpp
src/pipeline/pipeline.h
src/spirv_to_llvm/spirv_to_llvm.cpp
src/spirv_to_llvm/spirv_to_llvm.h
src/vulkan/util.h [new file with mode: 0644]

index 5b6bfcf261374ffa1590f9c2b00d2225f1616870..01ff840db9d1c5757ede7018c846c1725dabb210 100644 (file)
@@ -21,4 +21,4 @@
 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)
index 5c40345a9b632556857b0ea6bb62248e7d472660..3a9ccc9922a932c58f2fdd4f68760078440894cb 100644 (file)
@@ -31,8 +31,8 @@
 #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
 {
@@ -219,61 +219,141 @@ int test_main(int argc, char **argv)
     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
     {
index 11d7ce5412d64634d5199d44ce86569f16ad777f..20544e47da23aa3b99ed08f2c32db4894ea58f81 100644 (file)
  *
  */
 #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));
 }
 }
 }
index 54b4e57745661f641d43b3854f1354f22cf84bfb..60600440265853f8aa166f32437c51b259503eca 100644 (file)
 #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
@@ -141,6 +193,9 @@ inline VkPipeline move_to_handle(std::unique_ptr<Pipeline> pipeline) noexcept
 
 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,
@@ -149,10 +204,14 @@ public:
                                            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
@@ -167,16 +226,19 @@ public:
     }
 
 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
index 423507c7096b88397c4d7586d58f2dd80178d7ab..9e7eadc14cac43818bcf61e3d18d77ab54ef16c5 100644 (file)
@@ -1590,7 +1590,8 @@ public:
         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,
index 42ed3f45867ba97aad6eee1eff1e7050b4b45c08..1291233f2fcacdd275891a07a32c567782ae455c 100644 (file)
@@ -570,19 +570,37 @@ struct Converted_module
     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,
diff --git a/src/vulkan/util.h b/src/vulkan/util.h
new file mode 100644 (file)
index 0000000..98edf17
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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_