From: Jacob Lifshay Date: Fri, 18 Aug 2017 00:25:45 +0000 (-0700) Subject: vertex shader works; working on adding debugger-friendly compiler stack X-Git-Tag: gsoc-2017~41 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0dedc5c2e8bae761ed7aed3275e3bdc826c90bc9;p=kazan.git vertex shader works; working on adding debugger-friendly compiler stack --- diff --git a/src/demo/demo.cpp b/src/demo/demo.cpp index 3a9ccc9..17f1619 100644 --- a/src/demo/demo.cpp +++ b/src/demo/demo.cpp @@ -341,13 +341,19 @@ int test_main(int argc, char **argv) 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 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( + std::size_t output_buffer_size = + graphics_pipeline->get_vertex_shader_output_struct_size() * vertex_count; + std::unique_ptr output_buffer(new unsigned char[output_buffer_size]); + for(std::size_t i = 0; i < output_buffer_size; i++) + output_buffer[i] = 0; + graphics_pipeline->run_vertex_shader( vertex_start_index, vertex_end_index, instance_id, output_buffer.get()); std::cerr << "shader completed" << std::endl; + for(std::size_t i = 0; i < vertex_count; i++) + { + graphics_pipeline->dump_vertex_shader_output_struct(output_buffer.get() + + graphics_pipeline->get_vertex_shader_output_struct_size() * i); + } } catch(std::runtime_error &e) { diff --git a/src/llvm_wrapper/CMakeLists.txt b/src/llvm_wrapper/CMakeLists.txt index 30fad9f..8a56efc 100644 --- a/src/llvm_wrapper/CMakeLists.txt +++ b/src/llvm_wrapper/CMakeLists.txt @@ -20,7 +20,8 @@ # cmake_minimum_required(VERSION 3.1 FATAL_ERROR) -set(sources llvm_wrapper.cpp) +set(sources llvm_wrapper.cpp + orc_compile_stack.cpp) add_library(vulkan_cpu_llvm_wrapper STATIC ${sources}) if(0) llvm_map_components_to_libnames(llvm_libraries core native analysis orcjit mcjit nativecodegen) diff --git a/src/llvm_wrapper/llvm_wrapper.h b/src/llvm_wrapper/llvm_wrapper.h index 4f2b206..8ab6604 100644 --- a/src/llvm_wrapper/llvm_wrapper.h +++ b/src/llvm_wrapper/llvm_wrapper.h @@ -101,7 +101,7 @@ public: struct LLVM_string_deleter { - void operator()(char *str) + void operator()(char *str) const noexcept { ::LLVMDisposeMessage(str); } @@ -149,7 +149,7 @@ public: struct Context_deleter { - void operator()(::LLVMContextRef context) noexcept + void operator()(::LLVMContextRef context) const noexcept { ::LLVMContextDispose(context); } @@ -177,7 +177,7 @@ public: struct Target_deleter { - void operator()(::LLVMTargetRef target) noexcept + void operator()(::LLVMTargetRef target) const noexcept { static_cast(target); } @@ -220,7 +220,7 @@ struct Target : public Wrapper<::LLVMTargetRef, Target_deleter> struct Target_data_deleter { - void operator()(::LLVMTargetDataRef v) noexcept + void operator()(::LLVMTargetDataRef v) const noexcept { ::LLVMDisposeTargetData(v); } @@ -250,7 +250,7 @@ struct Target_data : public Wrapper<::LLVMTargetDataRef, Target_data_deleter> struct Target_machine_deleter { - void operator()(::LLVMTargetMachineRef tm) noexcept + void operator()(::LLVMTargetMachineRef tm) const noexcept { ::LLVMDisposeTargetMachine(tm); } @@ -304,7 +304,7 @@ struct Target_machine : public Wrapper<::LLVMTargetMachineRef, Target_machine_de struct Module_deleter { - void operator()(::LLVMModuleRef module) noexcept + void operator()(::LLVMModuleRef module) const noexcept { ::LLVMDisposeModule(module); } @@ -341,7 +341,7 @@ inline LLVM_string print_type_to_string(::LLVMTypeRef type) struct Builder_deleter { - void operator()(::LLVMBuilderRef v) noexcept + void operator()(::LLVMBuilderRef v) const noexcept { return ::LLVMDisposeBuilder(v); } @@ -401,7 +401,7 @@ inline ::LLVMTypeRef get_scalar_or_vector_element_type(::LLVMTypeRef type) #if LLVM_WRAPPER_ORC_REVISION_NUMBER >= 306166 struct Orc_shared_module_ref_deleter { - void operator()(::LLVMSharedModuleRef v) noexcept + void operator()(::LLVMSharedModuleRef v) const noexcept { ::LLVMOrcDisposeSharedModuleRef(v); } @@ -419,7 +419,7 @@ struct Orc_shared_module_ref : public Wrapper<::LLVMSharedModuleRef, Orc_shared_ struct Orc_jit_stack_deleter { - void operator()(::LLVMOrcJITStackRef v) noexcept + void operator()(::LLVMOrcJITStackRef v) const noexcept { ::LLVMOrcDisposeInstance(v); } diff --git a/src/llvm_wrapper/orc_compile_stack.cpp b/src/llvm_wrapper/orc_compile_stack.cpp new file mode 100644 index 0000000..3b437e9 --- /dev/null +++ b/src/llvm_wrapper/orc_compile_stack.cpp @@ -0,0 +1,110 @@ +/* + * 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. + * + */ +#include "orc_compile_stack.h" +#include +#include +#include +#include +#include +#include + +#if LLVM_VERSION_MAJOR != 4 || LLVM_VERSION_MINOR != 0 +#error Orc compile stack is not yet implemented for this version of LLVM +#endif + +namespace vulkan_cpu +{ +namespace llvm_wrapper +{ +namespace +{ +// implement the unwrap functions that aren't in public llvm headers +llvm::TargetMachine *unwrap(::LLVMTargetMachineRef v) noexcept +{ + return reinterpret_cast(v); +} +} + +class Orc_compile_stack_implementation +{ + Orc_compile_stack_implementation(const Orc_compile_stack_implementation &) = delete; + Orc_compile_stack_implementation(Orc_compile_stack_implementation &&) = delete; + Orc_compile_stack_implementation &operator=(const Orc_compile_stack_implementation &) = delete; + Orc_compile_stack_implementation &operator=(Orc_compile_stack_implementation &&) = delete; + +private: + std::unique_ptr target_machine; + const llvm::DataLayout data_layout; + llvm::orc::ObjectLinkingLayer<> object_linking_layer; + +public: + explicit Orc_compile_stack_implementation(Target_machine target_machine_in) + : target_machine(unwrap(target_machine_in.release())), + data_layout(target_machine->createDataLayout()) + { +#warning finish + assert(!"finish"); + } + void add_eagerly_compiled_ir(Module module, + ::LLVMOrcSymbolResolverFn symbol_resolver_callback, + void *symbol_resolver_user_data) + { +#warning finish + assert(!"finish"); + } + std::uintptr_t get_symbol_address(const char *symbol_name) + { +#warning finish + assert(!"finish"); + return 0; + } +}; + +void Orc_compile_stack_deleter::operator()(Orc_compile_stack_ref v) const noexcept +{ + delete v; +} + +Orc_compile_stack Orc_compile_stack::create(Target_machine target_machine) +{ +#warning finish + assert(!"finish"); + return {}; +} + +void Orc_compile_stack::add_eagerly_compiled_ir(Orc_compile_stack_ref orc_compile_stack, + Module module, + ::LLVMOrcSymbolResolverFn symbol_resolver_callback, + void *symbol_resolver_user_data) +{ + orc_compile_stack->add_eagerly_compiled_ir( + std::move(module), symbol_resolver_callback, symbol_resolver_user_data); +} + +std::uintptr_t Orc_compile_stack::get_symbol_address(Orc_compile_stack_ref orc_compile_stack, + const char *symbol_name) +{ + return orc_compile_stack->get_symbol_address(symbol_name); +} +} +} diff --git a/src/llvm_wrapper/orc_compile_stack.h b/src/llvm_wrapper/orc_compile_stack.h new file mode 100644 index 0000000..413d314 --- /dev/null +++ b/src/llvm_wrapper/orc_compile_stack.h @@ -0,0 +1,76 @@ +/* + * 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 LLVM_WRAPPER_ORC_COMPILE_STACK_H_ +#define LLVM_WRAPPER_ORC_COMPILE_STACK_H_ + +#include "llvm_wrapper.h" + +namespace vulkan_cpu +{ +namespace llvm_wrapper +{ +class Orc_compile_stack_implementation; + +typedef Orc_compile_stack_implementation *Orc_compile_stack_ref; + +struct Orc_compile_stack_deleter +{ + void operator()(Orc_compile_stack_ref v) const noexcept; +}; + +struct Orc_compile_stack : public Wrapper +{ + using Wrapper::Wrapper; + static Orc_compile_stack create(Target_machine target_machine); + static void add_eagerly_compiled_ir(Orc_compile_stack_ref orc_compile_stack, + Module module, + ::LLVMOrcSymbolResolverFn symbol_resolver_callback, + void *symbol_resolver_user_data); + void add_eagerly_compiled_ir(Module module, + ::LLVMOrcSymbolResolverFn symbol_resolver_callback, + void *symbol_resolver_user_data) + { + add_eagerly_compiled_ir( + get(), std::move(module), symbol_resolver_callback, symbol_resolver_user_data); + } + static std::uintptr_t get_symbol_address(Orc_compile_stack_ref orc_compile_stack, + const char *symbol_name); + template + static T *get_symbol(Orc_compile_stack_ref orc_compile_stack, const char *symbol_name) + { + return reinterpret_cast(get_symbol_address(orc_compile_stack, symbol_name)); + } + std::uintptr_t get_symbol_address(const char *symbol_name) + { + return get_symbol_address(get(), symbol_name); + } + template + T *get_symbol(const char *symbol_name) + { + return get_symbol(get(), symbol_name); + } +}; +} +} + +#endif // LLVM_WRAPPER_ORC_COMPILE_STACK_H_ diff --git a/src/pipeline/CMakeLists.txt b/src/pipeline/CMakeLists.txt index 65fdb94..5b4d980 100644 --- a/src/pipeline/CMakeLists.txt +++ b/src/pipeline/CMakeLists.txt @@ -22,4 +22,4 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) set(sources pipeline.cpp) add_library(vulkan_cpu_pipeline STATIC ${sources}) -target_link_libraries(vulkan_cpu_pipeline vulkan_cpu_spirv_to_llvm vulkan_cpu_util vulkan_cpu_spirv vulkan_cpu_llvm_wrapper vulkan_cpu_vulkan) +target_link_libraries(vulkan_cpu_pipeline vulkan_cpu_spirv_to_llvm vulkan_cpu_json vulkan_cpu_util vulkan_cpu_spirv vulkan_cpu_llvm_wrapper vulkan_cpu_vulkan) diff --git a/src/pipeline/pipeline.cpp b/src/pipeline/pipeline.cpp index 20544e4..84182a5 100644 --- a/src/pipeline/pipeline.cpp +++ b/src/pipeline/pipeline.cpp @@ -24,6 +24,8 @@ #include "spirv_to_llvm/spirv_to_llvm.h" #include "llvm_wrapper/llvm_wrapper.h" #include "vulkan/util.h" +#include "util/soft_float.h" +#include "json/json.h" #include #include #include @@ -78,16 +80,266 @@ Pipeline_layout_handle Pipeline_layout_handle::make( struct Graphics_pipeline::Implementation { + llvm_wrapper::Context llvm_context = llvm_wrapper::Context::create(); 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 + llvm_wrapper::Target_data data_layout; + std::vector compiled_shaders; + std::shared_ptr vertex_shader_output_struct; + std::string append_value_to_string(std::string str, + spirv_to_llvm::Type_descriptor &type, + const void *value) const { - return next_module_id++; + struct Visitor : public spirv_to_llvm::Type_descriptor::Type_visitor + { + const Implementation *this_; + std::string &str; + const void *value; + Visitor(const Implementation *this_, std::string &str, const void *value) noexcept + : this_(this_), + str(str), + value(value) + { + } + virtual void visit(spirv_to_llvm::Simple_type_descriptor &type) override + { + auto llvm_type = type.get_or_make_type().type; + switch(::LLVMGetTypeKind(llvm_type)) + { + case ::LLVMVoidTypeKind: + case ::LLVMX86_FP80TypeKind: + case ::LLVMFP128TypeKind: + case ::LLVMPPC_FP128TypeKind: + case ::LLVMLabelTypeKind: + case ::LLVMFunctionTypeKind: + case ::LLVMStructTypeKind: + case ::LLVMArrayTypeKind: + case ::LLVMPointerTypeKind: + case ::LLVMVectorTypeKind: + case ::LLVMMetadataTypeKind: + case ::LLVMX86_MMXTypeKind: + case ::LLVMTokenTypeKind: + break; + case ::LLVMHalfTypeKind: + { + auto integer_value = *static_cast(value); + auto float_value = + util::soft_float::ExtendedFloat::fromHalfPrecision(integer_value); + str = json::ast::Number_value::append_double_to_string( + static_cast(float_value), std::move(str)); + if(float_value.isNaN()) + { + str += " (0x"; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str), 0x10); + str += ")"; + } + return; + } + case ::LLVMFloatTypeKind: + { + static_assert(sizeof(std::uint32_t) == sizeof(float) + && alignof(std::uint32_t) == alignof(float), + ""); + union + { + std::uint32_t integer_value; + float float_value; + }; + integer_value = *static_cast(value); + str = json::ast::Number_value::append_double_to_string(float_value, + std::move(str)); + if(std::isnan(float_value)) + { + str += " (0x"; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str), 0x10); + str += ")"; + } + return; + } + case ::LLVMDoubleTypeKind: + { + static_assert(sizeof(std::uint64_t) == sizeof(double) + && alignof(std::uint64_t) == alignof(double), + ""); + union + { + std::uint64_t integer_value; + double float_value; + }; + integer_value = *static_cast(value); + str = json::ast::Number_value::append_double_to_string(float_value, + std::move(str)); + if(std::isnan(float_value)) + { + str += " (0x"; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str), 0x10); + str += ")"; + } + return; + } + case ::LLVMIntegerTypeKind: + { + switch(::LLVMGetIntTypeWidth(llvm_type)) + { + case 8: + { + auto integer_value = *static_cast(value); + str += "0x"; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str), 0x10); + str += " "; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str)); + str += " "; + str = json::ast::Number_value::append_signed_integer_to_string( + static_cast(integer_value), std::move(str)); + return; + } + case 16: + { + auto integer_value = *static_cast(value); + str += "0x"; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str), 0x10); + str += " "; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str)); + str += " "; + str = json::ast::Number_value::append_signed_integer_to_string( + static_cast(integer_value), std::move(str)); + return; + } + case 32: + { + auto integer_value = *static_cast(value); + str += "0x"; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str), 0x10); + str += " "; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str)); + str += " "; + str = json::ast::Number_value::append_signed_integer_to_string( + static_cast(integer_value), std::move(str)); + return; + } + case 64: + { + auto integer_value = *static_cast(value); + str += "0x"; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str), 0x10); + str += " "; + str = json::ast::Number_value::append_unsigned_integer_to_string( + integer_value, std::move(str)); + str += " "; + str = json::ast::Number_value::append_signed_integer_to_string( + static_cast(integer_value), std::move(str)); + return; + } + } + break; + } + } + assert(!"unhandled type"); + throw std::runtime_error("unhandled type"); + } + virtual void visit(spirv_to_llvm::Vector_type_descriptor &type) override + { + auto llvm_element_type = type.get_element_type()->get_or_make_type().type; + std::size_t element_size = + ::LLVMABISizeOfType(this_->data_layout.get(), llvm_element_type); + std::size_t element_count = type.get_element_count(); + str += "<"; + auto separator = ""; + for(std::size_t i = 0; i < element_count; i++) + { + str += separator; + separator = ", "; + str = this_->append_value_to_string( + std::move(str), + *type.get_element_type(), + static_cast(value) + i * element_size); + } + str += ">"; + } + virtual void visit(spirv_to_llvm::Matrix_type_descriptor &type) override + { + assert(!"dumping matrix not implemented"); + throw std::runtime_error("dumping matrix not implemented"); +#warning dumping matrix not implemented + } + virtual void visit(spirv_to_llvm::Array_type_descriptor &type) override + { + auto llvm_element_type = type.get_element_type()->get_or_make_type().type; + std::size_t element_size = + ::LLVMABISizeOfType(this_->data_layout.get(), llvm_element_type); + std::size_t element_count = type.get_element_count(); + str += "["; + auto separator = ""; + for(std::size_t i = 0; i < element_count; i++) + { + str += separator; + separator = ", "; + str = this_->append_value_to_string( + std::move(str), + *type.get_element_type(), + static_cast(value) + i * element_size); + } + str += "]"; + } + virtual void visit(spirv_to_llvm::Pointer_type_descriptor &type) override + { + str += "pointer:0x"; + str = json::ast::Number_value::append_unsigned_integer_to_string( + reinterpret_cast(*static_cast(value)), + std::move(str), + 0x10); + } + virtual void visit(spirv_to_llvm::Function_type_descriptor &type) override + { + str += "function:0x"; + str = json::ast::Number_value::append_unsigned_integer_to_string( + reinterpret_cast(*static_cast(value)), + std::move(str), + 0x10); + } + virtual void visit(spirv_to_llvm::Struct_type_descriptor &type) override + { + auto &&members = type.get_members(true); + auto llvm_type = type.get_or_make_type().type; + str += "{"; + auto separator = ""; + for(auto &member : members) + { + str += separator; + separator = ", "; + str = this_->append_value_to_string( + std::move(str), + *member.type, + static_cast(value) + + ::LLVMOffsetOfElement( + this_->data_layout.get(), llvm_type, member.llvm_member_index)); + } + str += "}"; + } + }; + type.visit(Visitor(this, str, value)); + return str; } }; +void Graphics_pipeline::dump_vertex_shader_output_struct(const void *output_struct) const +{ + std::cerr << "output: " + << implementation->append_value_to_string( + {}, *implementation->vertex_shader_output_struct, output_struct) + << std::endl; +} + std::unique_ptr Graphics_pipeline::make( Pipeline_cache *pipeline_cache, const VkGraphicsPipelineCreateInfo &create_info) { @@ -103,8 +355,7 @@ std::unique_ptr Graphics_pipeline::make( } auto implementation = std::make_shared(); auto llvm_target_machine = llvm_wrapper::Target_machine::create_native_target_machine(); - std::vector compiled_shaders; - compiled_shaders.reserve(create_info.stageCount); + implementation->compiled_shaders.reserve(create_info.stageCount); for(std::size_t i = 0; i < create_info.stageCount; i++) { auto &stage_info = create_info.pStages[i]; @@ -131,7 +382,7 @@ std::unique_ptr Graphics_pipeline::make( llvm_target_machine.get(), shader_module->words(), shader_module->word_count(), - implementation->make_module_id(), + implementation->compiled_shaders.size(), execution_model, stage_info.pName); std::cerr << "Translation to LLVM succeeded." << std::endl; @@ -140,13 +391,13 @@ std::unique_ptr Graphics_pipeline::make( ::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)); + implementation->compiled_shaders.push_back(std::move(compiled_shader)); } - auto data_layout = llvm_target_machine.create_target_data_layout(); + implementation->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) + for(auto &compiled_shader : implementation->compiled_shaders) { vertex_shader_output_struct_size = implementation->jit_stack.add_eagerly_compiled_ir( std::move(compiled_shader.module), @@ -176,8 +427,10 @@ std::unique_ptr Graphics_pipeline::make( { vertex_shader_function = reinterpret_cast(shader_entry_point_address); + implementation->vertex_shader_output_struct = compiled_shader.outputs_struct; vertex_shader_output_struct_size = ::LLVMABISizeOfType( - data_layout.get(), compiled_shader.outputs_struct->get_or_make_type().type); + implementation->data_layout.get(), + implementation->vertex_shader_output_struct->get_or_make_type().type); #warning finish implementing Graphics_pipeline::make continue; } diff --git a/src/pipeline/pipeline.h b/src/pipeline/pipeline.h index 6060044..80ccedc 100644 --- a/src/pipeline/pipeline.h +++ b/src/pipeline/pipeline.h @@ -204,14 +204,18 @@ public: void *output_buffer); public: - Vertex_shader_function get_vertex_shader_function() const noexcept + void run_vertex_shader(std::uint32_t vertex_start_index, + std::uint32_t vertex_end_index, + std::uint32_t instance_id, + void *output_buffer) const noexcept { - return vertex_shader_function; + vertex_shader_function(vertex_start_index, vertex_end_index, instance_id, output_buffer); } std::size_t get_vertex_shader_output_struct_size() const noexcept { return vertex_shader_output_struct_size; } + void dump_vertex_shader_output_struct(const void *output_struct) const; static std::unique_ptr make(Pipeline_cache *pipeline_cache, const VkGraphicsPipelineCreateInfo &create_info); static std::unique_ptr move_from_handle(VkPipeline pipeline) noexcept