From 562a7fbe1ea88861ad8a3050483fb190f7d6219a Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Sun, 24 Sep 2017 01:02:08 -0700 Subject: [PATCH] working on implementing shader uniforms; implemented matrix load/store with transpose --- src/demo/demo.cpp | 4 +- src/pipeline/pipeline.cpp | 119 ++++++++++++++++-- src/pipeline/pipeline.h | 52 ++++++-- src/spirv_to_llvm/CMakeLists.txt | 7 +- src/spirv_to_llvm/core_instructions.cpp | 97 ++++++++++++-- src/spirv_to_llvm/fragment_entry_point.cpp | 5 + src/spirv_to_llvm/matrix_operations.h | 107 ++++++++++++++++ src/spirv_to_llvm/spirv_to_llvm.cpp | 6 +- src/spirv_to_llvm/spirv_to_llvm.h | 28 ++++- .../spirv_to_llvm_implementation.h | 23 +++- src/spirv_to_llvm/vertex_entry_point.cpp | 5 + 11 files changed, 411 insertions(+), 42 deletions(-) create mode 100644 src/spirv_to_llvm/matrix_operations.h diff --git a/src/demo/demo.cpp b/src/demo/demo.cpp index d0b976b..400da19 100644 --- a/src/demo/demo.cpp +++ b/src/demo/demo.cpp @@ -230,7 +230,7 @@ std::unique_ptr load_shader(vulkan::Vulkan_device &devi return pipeline::Shader_module::create(device, shader_module_create_info); } -std::unique_ptr make_pipeline_layout(vulkan::Vulkan_device &device) +std::unique_ptr make_pipeline_layout(vulkan::Vulkan_device &device) { VkPipelineLayoutCreateInfo pipeline_layout_create_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, @@ -241,7 +241,7 @@ std::unique_ptr make_pipeline_layout(vulkan::Vulkan_d .pushConstantRangeCount = 0, .pPushConstantRanges = nullptr, }; - return pipeline::Pipeline_layout::create(device, pipeline_layout_create_info); + return vulkan::Vulkan_pipeline_layout::create(device, pipeline_layout_create_info); } template diff --git a/src/pipeline/pipeline.cpp b/src/pipeline/pipeline.cpp index 2cb457f..ed9db49 100644 --- a/src/pipeline/pipeline.cpp +++ b/src/pipeline/pipeline.cpp @@ -31,11 +31,105 @@ #include #include #include +#include namespace kazan { namespace pipeline { +Instantiated_pipeline_layout::Instantiated_pipeline_layout(vulkan::Vulkan_pipeline_layout &base, + ::LLVMContextRef llvm_context, + ::LLVMTargetDataRef target_data) + : base(base), + descriptor_sets(), + type(std::make_shared( + std::vector{}, + llvm_context, + target_data, + "pipeline_layout", + 0)) +{ + auto void_pointer_type = std::make_shared( + std::vector{}, + std::make_shared( + std::vector{}, + spirv_to_llvm::LLVM_type_and_alignment( + llvm_wrapper::Create_llvm_type()(llvm_context), alignof(char))), + 0, + target_data); + descriptor_sets.reserve(base.descriptor_set_layouts.size()); + for(auto *descriptor_set_layout : base.descriptor_set_layouts) + { + descriptor_sets.emplace_back(*descriptor_set_layout); + auto &descriptor_set = descriptor_sets.back(); + if(descriptor_set_layout->bindings.empty()) + continue; + std::size_t max_binding = 0; + for(auto &binding : descriptor_set_layout->bindings) + max_binding = std::max(max_binding, static_cast(binding.binding)); + std::size_t binding_array_size = max_binding + 1; + if(binding_array_size == 0) + throw std::bad_alloc(); // overflowed, prevent later out-of-bounds access from + // allocating too small + descriptor_set.bindings.resize(binding_array_size); + for(auto &binding_layout : descriptor_set_layout->bindings) + { + auto &binding = descriptor_set.bindings[binding_layout.binding]; + assert(!binding); + std::shared_ptr element_type; + switch(binding_layout.descriptor_type) + { + case VK_DESCRIPTOR_TYPE_SAMPLER: +#warning implement VK_DESCRIPTOR_TYPE_SAMPLER + break; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: +#warning implement VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + break; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: +#warning implement VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + break; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: +#warning implement VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: +#warning implement VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + break; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: +#warning implement VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + element_type = void_pointer_type; + break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: +#warning implement VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: +#warning implement VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC + break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: +#warning implement VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC + break; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: +#warning implement VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + break; + case VK_DESCRIPTOR_TYPE_MAX_ENUM: + case VK_DESCRIPTOR_TYPE_RANGE_SIZE: + break; + } + assert(element_type && "unimplemented descriptor type"); + auto binding_type = std::make_shared( + std::vector{}, + std::move(element_type), + binding_layout.descriptor_count, + 0); + auto member_index = + type->add_member(spirv_to_llvm::Struct_type_descriptor::Member({}, binding_type)); + binding = Binding(binding_layout, std::move(binding_type), member_index); + } + } + type->get_members(true); // fill in llvm type +} + llvm_wrapper::Module Pipeline::optimize_module(llvm_wrapper::Module module, ::LLVMTargetMachineRef target_machine) { @@ -110,6 +204,7 @@ struct Graphics_pipeline::Implementation spirv_to_llvm::Jit_symbol_resolver jit_symbol_resolver; llvm_wrapper::Orc_compile_stack jit_stack; llvm_wrapper::Target_data data_layout; + std::unique_ptr instantiated_pipeline_layout; std::vector compiled_shaders; std::shared_ptr vertex_shader_output_struct; std::string append_value_to_string(std::string str, @@ -853,7 +948,7 @@ std::unique_ptr Graphics_pipeline::create( assert(create_info.sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO); auto *render_pass = vulkan::Vulkan_render_pass::from_handle(create_info.renderPass); assert(render_pass); - auto *pipeline_layout = Pipeline_layout::from_handle(create_info.layout); + auto *pipeline_layout = vulkan::Vulkan_pipeline_layout::from_handle(create_info.layout); assert(pipeline_layout); if(create_info.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) { @@ -866,6 +961,9 @@ std::unique_ptr Graphics_pipeline::create( optimization_level = ::LLVMCodeGenLevelNone; auto llvm_target_machine = llvm_wrapper::Target_machine::create_native_target_machine(optimization_level); + implementation->data_layout = llvm_target_machine.create_target_data_layout(); + implementation->instantiated_pipeline_layout = std::make_unique( + *pipeline_layout, implementation->llvm_context.get(), implementation->data_layout.get()); implementation->compiled_shaders.reserve(create_info.stageCount); util::Enum_set found_shader_stages; for(std::size_t i = 0; i < create_info.stageCount; i++) @@ -897,14 +995,16 @@ std::unique_ptr Graphics_pipeline::create( assert(create_info.pVertexInputState); assert(create_info.pVertexInputState->sType == VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO); - 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->compiled_shaders.size(), - execution_model, - stage_info.pName, - create_info.pVertexInputState); + 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->compiled_shaders.size(), + execution_model, + stage_info.pName, + create_info.pVertexInputState, + *implementation->instantiated_pipeline_layout); std::cerr << "Translation to LLVM succeeded." << std::endl; ::LLVMDumpModule(compiled_shader.module.get()); bool failed = @@ -913,7 +1013,6 @@ std::unique_ptr Graphics_pipeline::create( throw std::runtime_error("LLVM module verification failed"); implementation->compiled_shaders.push_back(std::move(compiled_shader)); } - implementation->data_layout = llvm_target_machine.create_target_data_layout(); implementation->jit_stack = llvm_wrapper::Orc_compile_stack::create(std::move(llvm_target_machine), optimize_module); Vertex_shader_function vertex_shader_function = nullptr; diff --git a/src/pipeline/pipeline.h b/src/pipeline/pipeline.h index 637f363..d5af527 100644 --- a/src/pipeline/pipeline.h +++ b/src/pipeline/pipeline.h @@ -33,6 +33,7 @@ #include "vulkan/remove_xlib_macros.h" #include "spirv/spirv.h" #include "vulkan/api_objects.h" +#include "spirv_to_llvm/spirv_to_llvm.h" namespace kazan { @@ -52,17 +53,50 @@ public: } }; -class Pipeline_layout - : public vulkan::Vulkan_nondispatchable_object +struct Instantiated_pipeline_layout { -#warning finish implementing Pipeline_layout -public: - static std::unique_ptr create(vulkan::Vulkan_device &, - const VkPipelineLayoutCreateInfo &create_info) + vulkan::Vulkan_pipeline_layout &base; + struct Binding { -#warning finish implementing Pipeline_layout::create - return std::make_unique(); - } + vulkan::Vulkan_descriptor_set_layout::Binding *base; + std::shared_ptr type; + std::size_t member_index; + constexpr Binding() noexcept : base(), type(), member_index(-1) + { + } + Binding(vulkan::Vulkan_descriptor_set_layout::Binding &base, + std::shared_ptr type, + std::size_t member_index) noexcept : base(&base), + type(std::move(type)), + member_index(member_index) + { + } + explicit operator bool() const noexcept + { + return base != nullptr; + } + }; + struct Descriptor_set + { + vulkan::Vulkan_descriptor_set_layout *base; + std::vector bindings; + Descriptor_set() noexcept : base(nullptr), bindings() + { + } + explicit Descriptor_set(vulkan::Vulkan_descriptor_set_layout &base) + : base(&base), bindings() + { + } + explicit operator bool() const noexcept + { + return base != nullptr; + } + }; + std::vector descriptor_sets; + std::shared_ptr type; + Instantiated_pipeline_layout(vulkan::Vulkan_pipeline_layout &base, + ::LLVMContextRef llvm_context, + ::LLVMTargetDataRef target_data); }; struct Shader_module : public vulkan::Vulkan_nondispatchable_object diff --git a/src/spirv_to_llvm/CMakeLists.txt b/src/spirv_to_llvm/CMakeLists.txt index df1072a..39b1bb8 100644 --- a/src/spirv_to_llvm/CMakeLists.txt +++ b/src/spirv_to_llvm/CMakeLists.txt @@ -27,4 +27,9 @@ set(sources core_instructions.cpp spirv_to_llvm.cpp vertex_entry_point.cpp) add_library(kazan_spirv_to_llvm STATIC ${sources}) -target_link_libraries(kazan_spirv_to_llvm kazan_util kazan_spirv kazan_llvm_wrapper kazan_pipeline) +target_link_libraries(kazan_spirv_to_llvm + kazan_util + kazan_spirv + kazan_llvm_wrapper + kazan_pipeline + kazan_vulkan) diff --git a/src/spirv_to_llvm/core_instructions.cpp b/src/spirv_to_llvm/core_instructions.cpp index eae8eb1..172a0aa 100644 --- a/src/spirv_to_llvm/core_instructions.cpp +++ b/src/spirv_to_llvm/core_instructions.cpp @@ -1081,8 +1081,14 @@ void Spirv_to_llvm::handle_instruction_op_variable(Op_variable instruction, return; } case Storage_class::uniform: -#warning finish implementing Storage_class::uniform - break; + { + if(instruction.initializer) + throw Parser_error(instruction_start_index, + instruction_start_index, + "shader uniform variable initializers are not implemented"); + state.variable = Uniform_variable_state{}; + return; + } case Storage_class::output: { if(instruction.initializer) @@ -1237,11 +1243,37 @@ void Spirv_to_llvm::handle_instruction_op_variable(Op_variable instruction, #warning finish implementing Decoration::index break; case Decoration::binding: + { + switch(instruction.storage_class) + { + case spirv::Storage_class::uniform: + continue; #warning finish implementing Decoration::binding - break; + default: + throw Parser_error( + instruction_start_index, + instruction_start_index, + "OpVariable Binding decoration not implemented for storage " + "class: " + + std::string(get_enumerant_name(instruction.storage_class))); + } + } case Decoration::descriptor_set: + { + switch(instruction.storage_class) + { + case spirv::Storage_class::uniform: + continue; #warning finish implementing Decoration::descriptor_set - break; + default: + throw Parser_error( + instruction_start_index, + instruction_start_index, + "OpVariable DescriptorSet decoration not implemented for storage " + "class: " + + std::string(get_enumerant_name(instruction.storage_class))); + } + } case Decoration::offset: #warning finish implementing Decoration::offset break; @@ -1472,11 +1504,34 @@ void Spirv_to_llvm::handle_instruction_op_load(Op_load instruction, throw Parser_error(instruction_start_index, instruction_start_index, "OpLoad nontemporal not implemented"); - state.value = Value(::LLVMBuildLoad(builder.get(), - get_id_state(instruction.pointer).value.value().value, - get_name(instruction.result).c_str()), - get_type(instruction.result_type, instruction_start_index)); - ::LLVMSetAlignment(state.value->value, state.value->type->get_or_make_type().alignment); + auto result_type = get_type(instruction.result_type, instruction_start_index); + auto &pointer_value = get_id_state(instruction.pointer).value.value(); + assert(dynamic_cast(pointer_value.type.get())); + auto pointer_type = std::static_pointer_cast(pointer_value.type); + auto memory_type = pointer_type->get_base_type(); + switch(memory_type->get_load_store_implementation_kind()) + { + case Type_descriptor::Load_store_implementation_kind::Simple: + state.value = + Value(::LLVMBuildLoad(builder.get(), + get_id_state(instruction.pointer).value.value().value, + get_name(instruction.result).c_str()), + result_type); + ::LLVMSetAlignment(state.value->value, memory_type->get_or_make_type().alignment); + break; + case Type_descriptor::Load_store_implementation_kind::Transpose_matrix: + { + auto untransposed_value = ::LLVMBuildLoad( + builder.get(), get_id_state(instruction.pointer).value.value().value, ""); + ::LLVMSetAlignment(untransposed_value, memory_type->get_or_make_type().alignment); + state.value = Value(matrix_operations::transpose(context, + builder.get(), + untransposed_value, + get_name(instruction.result).c_str()), + result_type); + break; + } + } break; } } @@ -1507,8 +1562,28 @@ void Spirv_to_llvm::handle_instruction_op_store(Op_store instruction, "OpStore nontemporal not implemented"); auto &object_value = get_id_state(instruction.object).value.value(); auto &pointer_value = get_id_state(instruction.pointer).value.value(); - ::LLVMSetAlignment(::LLVMBuildStore(builder.get(), object_value.value, pointer_value.value), - object_value.type->get_or_make_type().alignment); + assert(dynamic_cast(pointer_value.type.get())); + auto pointer_type = std::static_pointer_cast(pointer_value.type); + auto memory_type = pointer_type->get_base_type(); + switch(memory_type->get_load_store_implementation_kind()) + { + case Type_descriptor::Load_store_implementation_kind::Simple: + ::LLVMSetAlignment( + ::LLVMBuildStore(builder.get(), object_value.value, pointer_value.value), + memory_type->get_or_make_type().alignment); + break; + case Type_descriptor::Load_store_implementation_kind::Transpose_matrix: + { + auto transposed_value = matrix_operations::transpose(context, + builder.get(), + object_value.value, + ""); + ::LLVMSetAlignment( + ::LLVMBuildStore(builder.get(), transposed_value, pointer_value.value), + memory_type->get_or_make_type().alignment); + break; + } + } break; } } diff --git a/src/spirv_to_llvm/fragment_entry_point.cpp b/src/spirv_to_llvm/fragment_entry_point.cpp index 5a5b868..0ae3979 100644 --- a/src/spirv_to_llvm/fragment_entry_point.cpp +++ b/src/spirv_to_llvm/fragment_entry_point.cpp @@ -631,6 +631,11 @@ using namespace spirv; after_call_callbacks.push_back(std::move(callback)); } } + else if(member_index == uniforms_member) + { +#warning implement shader uniforms + assert(this->pipeline_layout.descriptor_sets.empty() && "shader uniforms not implemented"); + } else { throw Parser_error(0, 0, "internal error: unhandled Io_struct member"); diff --git a/src/spirv_to_llvm/matrix_operations.h b/src/spirv_to_llvm/matrix_operations.h new file mode 100644 index 0000000..4b50332 --- /dev/null +++ b/src/spirv_to_llvm/matrix_operations.h @@ -0,0 +1,107 @@ +/* + * 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 SPIRV_TO_LLVM_MATRIX_OPERATIONS_H_ +#define SPIRV_TO_LLVM_MATRIX_OPERATIONS_H_ + +#include "llvm_wrapper/llvm_wrapper.h" +#include "spirv_to_llvm/spirv_to_llvm.h" +#include +#include + +namespace kazan +{ +namespace spirv_to_llvm +{ +namespace matrix_operations +{ +struct Matrix_descriptor +{ + std::uint32_t rows; + std::uint32_t columns; + ::LLVMTypeRef column_type; + ::LLVMTypeRef element_type; + ::LLVMTypeRef matrix_type; + explicit Matrix_descriptor(::LLVMTypeRef matrix_type) noexcept : matrix_type(matrix_type) + { + assert(::LLVMGetTypeKind(matrix_type) == ::LLVMArrayTypeKind); + columns = ::LLVMGetArrayLength(matrix_type); + column_type = ::LLVMGetElementType(matrix_type); + assert(::LLVMGetTypeKind(column_type) == ::LLVMVectorTypeKind); + rows = ::LLVMGetVectorSize(column_type); + element_type = ::LLVMGetElementType(column_type); + } + Matrix_descriptor(::LLVMTypeRef element_type, std::uint32_t rows, std::uint32_t columns) + : rows(rows), + columns(columns), + column_type(::LLVMVectorType(element_type, rows)), + element_type(element_type), + matrix_type(::LLVMArrayType(column_type, columns)) + { + } +}; + +inline ::LLVMValueRef transpose(::LLVMContextRef context, + ::LLVMBuilderRef builder, + ::LLVMValueRef input_matrix, + const char *output_name) +{ + auto i32_type = llvm_wrapper::Create_llvm_type()(context); + Matrix_descriptor input_matrix_descriptor(::LLVMTypeOf(input_matrix)); + Matrix_descriptor output_matrix_descriptor(input_matrix_descriptor.element_type, + input_matrix_descriptor.columns, + input_matrix_descriptor.rows); + std::vector<::LLVMValueRef> input_columns; + input_columns.reserve(input_matrix_descriptor.columns); + for(std::uint32_t input_column = 0; input_column < input_matrix_descriptor.columns; + input_column++) + input_columns.push_back(::LLVMBuildExtractValue(builder, input_matrix, input_column, "")); + auto output_value = ::LLVMGetUndef(output_matrix_descriptor.matrix_type); + for(std::uint32_t output_column = 0; output_column < output_matrix_descriptor.columns; + output_column++) + { + auto output_column_value = ::LLVMGetUndef(output_matrix_descriptor.column_type); + for(std::uint32_t output_row = 0; output_row < output_matrix_descriptor.rows; output_row++) + { + auto element_value = + ::LLVMBuildExtractElement(builder, + input_columns[output_row], + ::LLVMConstInt(i32_type, output_column, false), + ""); + output_column_value = + ::LLVMBuildInsertElement(builder, + output_column_value, + element_value, + ::LLVMConstInt(i32_type, output_row, false), + ""); + } + output_value = + ::LLVMBuildInsertValue(builder, output_value, output_column_value, output_column, ""); + } + ::LLVMSetValueName(output_value, output_name); + return output_value; +} +} +} +} + +#endif // SPIRV_TO_LLVM_MATRIX_OPERATIONS_H_ diff --git a/src/spirv_to_llvm/spirv_to_llvm.cpp b/src/spirv_to_llvm/spirv_to_llvm.cpp index d509fcc..44e2134 100644 --- a/src/spirv_to_llvm/spirv_to_llvm.cpp +++ b/src/spirv_to_llvm/spirv_to_llvm.cpp @@ -540,14 +540,16 @@ spirv_to_llvm::Converted_module spirv_to_llvm::spirv_to_llvm( std::uint64_t shader_id, spirv::Execution_model execution_model, util::string_view entry_point_name, - const VkPipelineVertexInputStateCreateInfo *vertex_input_state) + const VkPipelineVertexInputStateCreateInfo *vertex_input_state, + pipeline::Instantiated_pipeline_layout &pipeline_layout) { return Spirv_to_llvm(context, target_machine, shader_id, execution_model, entry_point_name, - vertex_input_state) + vertex_input_state, + pipeline_layout) .run(shader_words, shader_size); } } diff --git a/src/spirv_to_llvm/spirv_to_llvm.h b/src/spirv_to_llvm/spirv_to_llvm.h index f5ad1d4..7cc0d7c 100644 --- a/src/spirv_to_llvm/spirv_to_llvm.h +++ b/src/spirv_to_llvm/spirv_to_llvm.h @@ -36,10 +36,16 @@ #include "util/string_view.h" #include "vulkan/vulkan.h" #include "vulkan/remove_xlib_macros.h" +#include "vulkan/api_objects.h" #include "util/bitset.h" namespace kazan { +namespace pipeline +{ +struct Instantiated_pipeline_layout; +} + namespace spirv_to_llvm { struct LLVM_type_and_alignment @@ -236,6 +242,15 @@ public: return get_recursion_count() > 1; } }; + enum class Load_store_implementation_kind + { + Simple, + Transpose_matrix, + }; + virtual Load_store_implementation_kind get_load_store_implementation_kind() + { + return Load_store_implementation_kind::Simple; + } }; class Simple_type_descriptor final : public Type_descriptor @@ -493,9 +508,14 @@ public: target_data); column_major_type = std::make_shared( decorations, std::move(column_type), row_type->get_element_count()); - column_major_type->row_major_type = std::static_pointer_cast(shared_from_this()); + column_major_type->row_major_type = + std::static_pointer_cast(shared_from_this()); return column_major_type; } + virtual Load_store_implementation_kind get_load_store_implementation_kind() override + { + return Load_store_implementation_kind::Transpose_matrix; + } }; inline std::shared_ptr Matrix_type_descriptor::make_row_major_type( @@ -508,7 +528,8 @@ inline std::shared_ptr Matrix_type_descriptor::make_row_major_t target_data); auto retval = std::make_shared( decorations, std::move(row_type), column_type->get_element_count()); - retval->column_major_type = std::static_pointer_cast(shared_from_this()); + retval->column_major_type = + std::static_pointer_cast(shared_from_this()); return retval; } @@ -792,7 +813,8 @@ Converted_module spirv_to_llvm(::LLVMContextRef context, std::uint64_t shader_id, spirv::Execution_model execution_model, util::string_view entry_point_name, - const VkPipelineVertexInputStateCreateInfo *vertex_input_state); + const VkPipelineVertexInputStateCreateInfo *vertex_input_state, + pipeline::Instantiated_pipeline_layout &pipeline_layout); } } diff --git a/src/spirv_to_llvm/spirv_to_llvm_implementation.h b/src/spirv_to_llvm/spirv_to_llvm_implementation.h index cc4f6bf..83d8dfe 100644 --- a/src/spirv_to_llvm/spirv_to_llvm_implementation.h +++ b/src/spirv_to_llvm/spirv_to_llvm_implementation.h @@ -28,6 +28,7 @@ #include "util/variant.h" #include "util/enum.h" #include "pipeline/pipeline.h" +#include "matrix_operations.h" #include #include #include @@ -79,8 +80,13 @@ private: std::shared_ptr type; std::size_t member_index; }; - typedef util::variant - Variable_state; + struct Uniform_variable_state + { + }; + typedef util::variant Variable_state; struct Function_state { struct Entry_block @@ -223,6 +229,8 @@ private: std::size_t outputs_member; std::shared_ptr outputs_struct; std::shared_ptr outputs_struct_pointer_type; + std::size_t uniforms_member; + std::shared_ptr uniforms_struct_pointer_type; Stage stage; spirv::Id current_function_id = 0; spirv::Id current_basic_block_id = 0; @@ -233,6 +241,7 @@ private: util::string_view entry_point_name; Op_entry_point_state *entry_point_state_pointer = nullptr; const VkPipelineVertexInputStateCreateInfo *vertex_input_state; + pipeline::Instantiated_pipeline_layout &pipeline_layout; private: Id_state &get_id_state(spirv::Id id) @@ -381,14 +390,16 @@ public: std::uint64_t shader_id, spirv::Execution_model execution_model, util::string_view entry_point_name, - const VkPipelineVertexInputStateCreateInfo *vertex_input_state) + const VkPipelineVertexInputStateCreateInfo *vertex_input_state, + pipeline::Instantiated_pipeline_layout &pipeline_layout) : context(context), target_machine(target_machine), shader_id(shader_id), stage(), execution_model(execution_model), entry_point_name(entry_point_name), - vertex_input_state(vertex_input_state) + vertex_input_state(vertex_input_state), + pipeline_layout(pipeline_layout) { { std::ostringstream ss; @@ -434,6 +445,10 @@ public: std::vector{}, outputs_struct, 0, target_data); outputs_member = io_struct->add_member(Struct_type_descriptor::Member({}, outputs_struct_pointer_type)); + uniforms_struct_pointer_type = std::make_shared( + std::vector{}, pipeline_layout.type, 0, target_data); + uniforms_member = + io_struct->add_member(Struct_type_descriptor::Member({}, uniforms_struct_pointer_type)); } ::LLVMValueRef generate_vertex_entry_function(Op_entry_point_state &entry_point, ::LLVMValueRef main_function); diff --git a/src/spirv_to_llvm/vertex_entry_point.cpp b/src/spirv_to_llvm/vertex_entry_point.cpp index 7ed6f05..9843972 100644 --- a/src/spirv_to_llvm/vertex_entry_point.cpp +++ b/src/spirv_to_llvm/vertex_entry_point.cpp @@ -850,6 +850,11 @@ using namespace spirv; } } } + else if(member_index == uniforms_member) + { +#warning implement shader uniforms + assert(this->pipeline_layout.descriptor_sets.empty() && "shader uniforms not implemented"); + } else { throw Parser_error(0, 0, "internal error: unhandled Io_struct member"); -- 2.30.2