From a7d842c97c9803d7003a9a9d6e85097df5aeb0fc Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 26 Feb 2019 22:09:37 -0800 Subject: [PATCH] turnip: compile VkPipelineShaderStageCreateInfo Compile all shaders and upload the binaries to a BO. --- src/freedreno/vulkan/tu_pipeline.c | 138 +++++++++++++++++++++++++++++ src/freedreno/vulkan/tu_private.h | 5 ++ 2 files changed, 143 insertions(+) diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index ebed283a8cc..d289115175a 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -46,6 +46,11 @@ struct tu_pipeline_builder const VkAllocationCallbacks *alloc; const VkGraphicsPipelineCreateInfo *create_info; + struct tu_shader *shaders[MESA_SHADER_STAGES]; + uint32_t shader_offsets[MESA_SHADER_STAGES]; + uint32_t binning_vs_offset; + uint32_t shader_total_size; + bool rasterizer_discard; /* these states are affectd by rasterizer_discard */ VkSampleCountFlagBits samples; @@ -82,6 +87,28 @@ tu_dynamic_state_bit(VkDynamicState state) } } +static gl_shader_stage +tu_shader_stage(VkShaderStageFlagBits stage) +{ + switch (stage) { + case VK_SHADER_STAGE_VERTEX_BIT: + return MESA_SHADER_VERTEX; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + return MESA_SHADER_TESS_CTRL; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + return MESA_SHADER_TESS_EVAL; + case VK_SHADER_STAGE_GEOMETRY_BIT: + return MESA_SHADER_GEOMETRY; + case VK_SHADER_STAGE_FRAGMENT_BIT: + return MESA_SHADER_FRAGMENT; + case VK_SHADER_STAGE_COMPUTE_BIT: + return MESA_SHADER_COMPUTE; + default: + unreachable("invalid VkShaderStageFlagBits"); + return MESA_SHADER_NONE; + } +} + static bool tu_logic_op_reads_dst(VkLogicOp op) { @@ -694,6 +721,91 @@ tu_pipeline_builder_create_pipeline(struct tu_pipeline_builder *builder, return VK_SUCCESS; } +static VkResult +tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder) +{ + const VkPipelineShaderStageCreateInfo *stage_infos[MESA_SHADER_STAGES] = { + NULL + }; + for (uint32_t i = 0; i < builder->create_info->stageCount; i++) { + gl_shader_stage stage = + tu_shader_stage(builder->create_info->pStages[i].stage); + stage_infos[stage] = &builder->create_info->pStages[i]; + } + + struct tu_shader_compile_options options; + tu_shader_compile_options_init(&options, builder->create_info); + + /* compile shaders in reverse order */ + struct tu_shader *next_stage_shader = NULL; + for (gl_shader_stage stage = MESA_SHADER_STAGES - 1; + stage > MESA_SHADER_NONE; stage--) { + const VkPipelineShaderStageCreateInfo *stage_info = stage_infos[stage]; + if (!stage_info) + continue; + + struct tu_shader *shader = + tu_shader_create(builder->device, stage, stage_info, builder->alloc); + if (!shader) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + VkResult result = + tu_shader_compile(builder->device, shader, next_stage_shader, + &options, builder->alloc); + if (result != VK_SUCCESS) + return result; + + builder->shaders[stage] = shader; + builder->shader_offsets[stage] = builder->shader_total_size; + builder->shader_total_size += + sizeof(uint32_t) * shader->variants[0].info.sizedwords; + + next_stage_shader = shader; + } + + if (builder->shaders[MESA_SHADER_VERTEX]->has_binning_pass) { + const struct tu_shader *vs = builder->shaders[MESA_SHADER_VERTEX]; + builder->binning_vs_offset = builder->shader_total_size; + builder->shader_total_size += + sizeof(uint32_t) * vs->variants[1].info.sizedwords; + } + + return VK_SUCCESS; +} + +static VkResult +tu_pipeline_builder_upload_shaders(struct tu_pipeline_builder *builder, + struct tu_pipeline *pipeline) +{ + struct tu_bo *bo = &pipeline->program.binary_bo; + + VkResult result = + tu_bo_init_new(builder->device, bo, builder->shader_total_size); + if (result != VK_SUCCESS) + return result; + + result = tu_bo_map(builder->device, bo); + if (result != VK_SUCCESS) + return result; + + for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { + const struct tu_shader *shader = builder->shaders[i]; + if (!shader) + continue; + + memcpy(bo->map + builder->shader_offsets[i], shader->binary, + sizeof(uint32_t) * shader->variants[0].info.sizedwords); + } + + if (builder->shaders[MESA_SHADER_VERTEX]->has_binning_pass) { + const struct tu_shader *vs = builder->shaders[MESA_SHADER_VERTEX]; + memcpy(bo->map + builder->binning_vs_offset, vs->binning_binary, + sizeof(uint32_t) * vs->variants[1].info.sizedwords); + } + + return VK_SUCCESS; +} + static void tu_pipeline_builder_parse_dynamic(struct tu_pipeline_builder *builder, struct tu_pipeline *pipeline) @@ -887,6 +999,9 @@ tu_pipeline_finish(struct tu_pipeline *pipeline, const VkAllocationCallbacks *alloc) { tu_cs_finish(dev, &pipeline->cs); + + if (pipeline->program.binary_bo.gem_handle) + tu_bo_finish(dev, &pipeline->program.binary_bo); } static VkResult @@ -897,6 +1012,18 @@ tu_pipeline_builder_build(struct tu_pipeline_builder *builder, if (result != VK_SUCCESS) return result; + /* compile and upload shaders */ + result = tu_pipeline_builder_compile_shaders(builder); + if (result == VK_SUCCESS) + result = tu_pipeline_builder_upload_shaders(builder, *pipeline); + if (result != VK_SUCCESS) { + tu_pipeline_finish(*pipeline, builder->device, builder->alloc); + vk_free2(&builder->device->alloc, builder->alloc, *pipeline); + *pipeline = VK_NULL_HANDLE; + + return result; + } + tu_pipeline_builder_parse_dynamic(builder, *pipeline); tu_pipeline_builder_parse_input_assembly(builder, *pipeline); tu_pipeline_builder_parse_viewport(builder, *pipeline); @@ -912,6 +1039,16 @@ tu_pipeline_builder_build(struct tu_pipeline_builder *builder, return VK_SUCCESS; } +static void +tu_pipeline_builder_finish(struct tu_pipeline_builder *builder) +{ + for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { + if (!builder->shaders[i]) + continue; + tu_shader_destroy(builder->device, builder->shaders[i], builder->alloc); + } +} + static void tu_pipeline_builder_init_graphics( struct tu_pipeline_builder *builder, @@ -972,6 +1109,7 @@ tu_CreateGraphicsPipelines(VkDevice device, struct tu_pipeline *pipeline; VkResult result = tu_pipeline_builder_build(&builder, &pipeline); + tu_pipeline_builder_finish(&builder); if (result != VK_SUCCESS) { for (uint32_t j = 0; j < i; j++) { diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h index 57678e37196..90935364081 100644 --- a/src/freedreno/vulkan/tu_private.h +++ b/src/freedreno/vulkan/tu_private.h @@ -1038,6 +1038,11 @@ struct tu_pipeline bool need_indirect_descriptor_sets; VkShaderStageFlags active_stages; + struct + { + struct tu_bo binary_bo; + } program; + struct { enum pc_di_primtype primtype; -- 2.30.2