return pipeline::Shader_module::create(device, shader_module_create_info);
}
-std::unique_ptr<pipeline::Pipeline_layout> make_pipeline_layout(vulkan::Vulkan_device &device)
+std::unique_ptr<vulkan::Vulkan_pipeline_layout> make_pipeline_layout(vulkan::Vulkan_device &device)
{
VkPipelineLayoutCreateInfo pipeline_layout_create_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.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 <typename Integer_type>
#include <cassert>
#include <vector>
#include <iostream>
+#include <algorithm>
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<spirv_to_llvm::Struct_type_descriptor>(
+ std::vector<spirv::Decoration_with_parameters>{},
+ llvm_context,
+ target_data,
+ "pipeline_layout",
+ 0))
+{
+ auto void_pointer_type = std::make_shared<spirv_to_llvm::Pointer_type_descriptor>(
+ std::vector<spirv::Decoration_with_parameters>{},
+ std::make_shared<spirv_to_llvm::Simple_type_descriptor>(
+ std::vector<spirv::Decoration_with_parameters>{},
+ spirv_to_llvm::LLVM_type_and_alignment(
+ llvm_wrapper::Create_llvm_type<char>()(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<std::size_t>(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<spirv_to_llvm::Type_descriptor> 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<spirv_to_llvm::Array_type_descriptor>(
+ std::vector<spirv::Decoration_with_parameters>{},
+ 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)
{
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> instantiated_pipeline_layout;
std::vector<spirv_to_llvm::Converted_module> compiled_shaders;
std::shared_ptr<spirv_to_llvm::Struct_type_descriptor> vertex_shader_output_struct;
std::string append_value_to_string(std::string str,
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)
{
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<Instantiated_pipeline_layout>(
+ *pipeline_layout, implementation->llvm_context.get(), implementation->data_layout.get());
implementation->compiled_shaders.reserve(create_info.stageCount);
util::Enum_set<spirv::Execution_model> found_shader_stages;
for(std::size_t i = 0; i < create_info.stageCount; i++)
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 =
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;
#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
{
}
};
-class Pipeline_layout
- : public vulkan::Vulkan_nondispatchable_object<Pipeline_layout, VkPipelineLayout>
+struct Instantiated_pipeline_layout
{
-#warning finish implementing Pipeline_layout
-public:
- static std::unique_ptr<Pipeline_layout> 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<Pipeline_layout>();
- }
+ vulkan::Vulkan_descriptor_set_layout::Binding *base;
+ std::shared_ptr<spirv_to_llvm::Array_type_descriptor> 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<spirv_to_llvm::Array_type_descriptor> 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<Binding> 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_set> descriptor_sets;
+ std::shared_ptr<spirv_to_llvm::Struct_type_descriptor> type;
+ Instantiated_pipeline_layout(vulkan::Vulkan_pipeline_layout &base,
+ ::LLVMContextRef llvm_context,
+ ::LLVMTargetDataRef target_data);
};
struct Shader_module : public vulkan::Vulkan_nondispatchable_object<Shader_module, VkShaderModule>
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)
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)
#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;
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_type_descriptor *>(pointer_value.type.get()));
+ auto pointer_type = std::static_pointer_cast<Pointer_type_descriptor>(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;
}
}
"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_type_descriptor *>(pointer_value.type.get()));
+ auto pointer_type = std::static_pointer_cast<Pointer_type_descriptor>(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;
}
}
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");
--- /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 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 <cstdint>
+#include <vector>
+
+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<std::uint32_t>()(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_
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);
}
}
#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
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
target_data);
column_major_type = std::make_shared<Matrix_type_descriptor>(
decorations, std::move(column_type), row_type->get_element_count());
- column_major_type->row_major_type = std::static_pointer_cast<Row_major_matrix_type_descriptor>(shared_from_this());
+ column_major_type->row_major_type =
+ std::static_pointer_cast<Row_major_matrix_type_descriptor>(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<Type_descriptor> Matrix_type_descriptor::make_row_major_type(
target_data);
auto retval = std::make_shared<Row_major_matrix_type_descriptor>(
decorations, std::move(row_type), column_type->get_element_count());
- retval->column_major_type = std::static_pointer_cast<Matrix_type_descriptor>(shared_from_this());
+ retval->column_major_type =
+ std::static_pointer_cast<Matrix_type_descriptor>(shared_from_this());
return retval;
}
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);
}
}
#include "util/variant.h"
#include "util/enum.h"
#include "pipeline/pipeline.h"
+#include "matrix_operations.h"
#include <functional>
#include <list>
#include <iostream>
std::shared_ptr<Type_descriptor> type;
std::size_t member_index;
};
- typedef util::variant<util::monostate, Input_variable_state, Output_variable_state>
- Variable_state;
+ struct Uniform_variable_state
+ {
+ };
+ typedef util::variant<util::monostate,
+ Input_variable_state,
+ Output_variable_state,
+ Uniform_variable_state> Variable_state;
struct Function_state
{
struct Entry_block
std::size_t outputs_member;
std::shared_ptr<Struct_type_descriptor> outputs_struct;
std::shared_ptr<Pointer_type_descriptor> outputs_struct_pointer_type;
+ std::size_t uniforms_member;
+ std::shared_ptr<Pointer_type_descriptor> uniforms_struct_pointer_type;
Stage stage;
spirv::Id current_function_id = 0;
spirv::Id current_basic_block_id = 0;
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)
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;
std::vector<spirv::Decoration_with_parameters>{}, 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<Pointer_type_descriptor>(
+ std::vector<spirv::Decoration_with_parameters>{}, 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);
}
}
}
+ 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");