for first shader being inserted in pipeline.
--- /dev/null
+
+/*
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ *
+ * based in part on anv driver which is:
+ * Copyright © 2015 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 <stdlib.h>
+#include <stdio.h>
+#include <sys/utsname.h>
+
+#include "util/mesa-sha1.h"
+#include "libresoc_debug.h"
+#include "libresoc_shader.h"
+
+void
+libresoc_print_spirv(const char *data, uint32_t size, FILE *fp)
+{
+ char path[] = "/tmp/fileXXXXXX";
+ char line[2048], command[128];
+ FILE *p;
+ int fd;
+
+ /* Dump the binary into a temporary file. */
+ fd = mkstemp(path);
+ if (fd < 0)
+ return;
+
+ if (write(fd, data, size) == -1)
+ goto fail;
+
+ sprintf(command, "spirv-dis %s", path);
+
+ /* Disassemble using spirv-dis if installed. */
+ p = popen(command, "r");
+ if (p) {
+ while (fgets(line, sizeof(line), p))
+ fprintf(fp, "%s", line);
+ pclose(p);
+ }
+
+fail:
+ close(fd);
+ unlink(path);
+}
LIBRESOC_DEBUG_DISCARD_TO_DEMOTE = 1 << 26,
LIBRESOC_DEBUG_LLVM = 1 << 27,
LIBRESOC_DEBUG_FORCE_COMPRESS = 1 << 28,
+ LIBRESOC_DEBUG_DUMP_NIR = 1 << 29,
};
enum {
LIBRESOC_PERFTEST_DFSM = 1 << 7,
};
-bool
-libresoc_init_trace(struct libresoc_device *device);
-
void
libresoc_print_spirv(const char *data, uint32_t size, FILE *fp);
-void
-libresoc_dump_enabled_options(struct libresoc_device *device, FILE *f);
-
#endif
#include "util/debug.h"
#include "util/driconf.h"
#include "libresoc_private.h"
+#include "compiler/glsl_types.h"
#include "vk_util.h"
#include "vk_alloc.h"
{"nomemorycache", LIBRESOC_DEBUG_NO_MEMORY_CACHE},
{"llvm", LIBRESOC_DEBUG_LLVM},
{"forcecompress", LIBRESOC_DEBUG_FORCE_COMPRESS},
+ {"nir", LIBRESOC_DEBUG_DUMP_NIR},
{NULL, 0}
};
}
instance->physical_devices_enumerated = false;
list_inithead(&instance->physical_devices);
+ glsl_type_singleton_init_or_ref();
libresoc_init_dri_options(instance);
*pInstance = libresoc_instance_to_handle(instance);
*/
#include "libresoc_private.h"
+#include "libresoc_shader.h"
#include "vk_util.h"
#include "vk_format.h"
#include "util/debug.h"
-VkResult
-libresoc_CreateShaderModule(VkDevice _device,
- const VkShaderModuleCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkShaderModule *pShaderModule)
+VkResult libresoc_create_shaders(struct libresoc_pipeline *pipeline,
+ struct libresoc_device *device,
+ const VkPipelineShaderStageCreateInfo **pStages,
+ const VkPipelineCreateFlags flags)
{
- /* FIXME: stub */
+ struct libresoc_shader_module *modules[MESA_SHADER_STAGES] = { 0, };
+ nir_shader *nir[MESA_SHADER_STAGES] = {0};
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; ++i) {
+ if (pStages[i]) {
+ modules[i] = libresoc_shader_module_from_handle(pStages[i]->module);
+ pipeline->active_stages |= mesa_to_vk_shader_stage(i);
+ }
+ }
+
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; ++i) {
+ const VkPipelineShaderStageCreateInfo *stage = pStages[i];
+ unsigned subgroup_size = 64, ballot_bit_size = 64;
+
+ if (!modules[i])
+ continue;
+
+ nir[i] = libresoc_shader_compile_to_nir(device, modules[i],
+ stage ? stage->pName : "main", i,
+ stage ? stage->pSpecializationInfo : NULL,
+ flags,
+ subgroup_size, ballot_bit_size);
+
+ /* We don't want to alter meta shaders IR directly so clone it
+ * first.
+ */
+ if (nir[i]->info.name) {
+ nir[i] = nir_shader_clone(NULL, nir[i]);
+ }
+
+ }
+
return VK_SUCCESS;
}
+static VkResult
+libresoc_pipeline_init(struct libresoc_pipeline *pipeline,
+ struct libresoc_device *device,
+ const VkGraphicsPipelineCreateInfo *pCreateInfo)
+{
+ VkResult result;
+ pipeline->device = device;
+
+ const VkPipelineShaderStageCreateInfo *pStages[MESA_SHADER_STAGES] = { 0, };
+ for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
+ gl_shader_stage stage = ffs(pCreateInfo->pStages[i].stage) - 1;
+ pStages[stage] = &pCreateInfo->pStages[i];
+ }
+
+ result = libresoc_create_shaders(pipeline, device, pStages,
+ pCreateInfo->flags);
+ if (result != VK_SUCCESS)
+ return result;
+
+ //TODO: add more code as required
+ return result;
+}
-void
-libresoc_DestroyShaderModule(VkDevice _device,
- VkShaderModule _module,
- const VkAllocationCallbacks *pAllocator)
+VkResult
+libresoc_graphics_pipeline_create(
+ VkDevice _device,
+ VkPipelineCache _cache,
+ const VkGraphicsPipelineCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkPipeline *pPipeline)
{
- /* FIXME: stub */
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ struct libresoc_pipeline *pipeline;
+ VkResult result;
+
+ pipeline = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (pipeline == NULL)
+ return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ vk_object_base_init(&device->vk, &pipeline->base,
+ VK_OBJECT_TYPE_PIPELINE);
+
+ result = libresoc_pipeline_init(pipeline, device,
+ pCreateInfo);
+ if (result != VK_SUCCESS) {
+ //libresoc_pipeline_destroy(device, pipeline, pAllocator);
+ return result;
+ }
+
+ *pPipeline = libresoc_pipeline_to_handle(pipeline);
+
+ return VK_SUCCESS;
}
VkResult libresoc_CreateGraphicsPipelines(
const VkAllocationCallbacks* pAllocator,
VkPipeline* pPipelines)
{
- return VK_ERROR_UNKNOWN;
- //FIXME: stub
+ VkResult result = VK_SUCCESS;
+ unsigned i = 0;
+
+ for (; i < count; i++) {
+ VkResult r;
+ r = libresoc_graphics_pipeline_create(_device,
+ pipelineCache,
+ &pCreateInfos[i],
+ pAllocator, &pPipelines[i]);
+ if (r != VK_SUCCESS) {
+ result = r;
+ pPipelines[i] = VK_NULL_HANDLE;
+
+ if (pCreateInfos[i].flags & VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT)
+ break;
+ }
+ }
+
+ for (; i < count; ++i)
+ pPipelines[i] = VK_NULL_HANDLE;
+
+ return result;
}
VkResult libresoc_CreateComputePipelines(
#include "wsi_common.h"
#define LIBRESOC_MAX_QUEUE_FAMILIES 1
+static inline gl_shader_stage
+vk_to_mesa_shader_stage(VkShaderStageFlagBits vk_stage)
+{
+ assert(__builtin_popcount(vk_stage) == 1);
+ return ffs(vk_stage) - 1;
+}
+
+static inline VkShaderStageFlagBits
+mesa_to_vk_shader_stage(gl_shader_stage mesa_stage)
+{
+ return (1 << mesa_stage);
+}
+
static inline uint32_t
align_u32(uint32_t v, uint32_t a)
{
struct libresoc_shader_binary;
struct libresoc_shader_variant;
+struct libresoc_pipeline {
+ struct vk_object_base base;
+ struct libresoc_device * device;
+
+
+ VkShaderStageFlags active_stages;
+
+};
void
libresoc_pipeline_cache_init(struct libresoc_pipeline_cache *cache,
struct libresoc_device *device);
VkImageLayout layout,
bool in_render_loop,
unsigned queue_mask);
+VkResult
+libresoc_graphics_pipeline_create(VkDevice device,
+ VkPipelineCache cache,
+ const VkGraphicsPipelineCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *alloc,
+ VkPipeline *pPipeline);
#define libresoc_printflike(a, b) __attribute__((__format__(__printf__, a, b)))
LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_image, VkImage)
//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_image_view, VkImageView);
LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_pipeline_cache, VkPipelineCache)
-//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_pipeline, VkPipeline)
+LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_pipeline, VkPipeline)
//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_pipeline_layout, VkPipelineLayout)
//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_query_pool, VkQueryPool)
//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_render_pass, VkRenderPass)
//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_sampler, VkSampler)
//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_sampler_ycbcr_conversion, VkSamplerYcbcrConversion)
-//LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_shader_module, VkShaderModule)
+LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_shader_module, VkShaderModule)
LIBRESOC_DEFINE_NONDISP_HANDLE_CASTS(libresoc_semaphore, VkSemaphore)
#endif /* LIBRESOC_PRIVATE_H */
--- /dev/null
+/*
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ *
+ * based in part on anv driver which is:
+ * Copyright © 2015 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 "libresoc_shader.h"
+
+static const struct nir_shader_compiler_options nir_options_llvm = {
+ .vertex_id_zero_based = true,
+ .lower_scmp = true,
+ .lower_flrp16 = true,
+ .lower_flrp32 = true,
+ .lower_flrp64 = true,
+ .lower_device_index_to_zero = true,
+ .lower_fsat = true,
+ .lower_fdiv = true,
+ .lower_fmod = true,
+ .lower_bitfield_insert_to_bitfield_select = true,
+ .lower_bitfield_extract = true,
+ .lower_sub = true,
+ .lower_pack_snorm_2x16 = true,
+ .lower_pack_snorm_4x8 = true,
+ .lower_pack_unorm_2x16 = true,
+ .lower_pack_unorm_4x8 = true,
+ .lower_unpack_snorm_2x16 = true,
+ .lower_unpack_snorm_4x8 = true,
+ .lower_unpack_unorm_2x16 = true,
+ .lower_unpack_unorm_4x8 = true,
+ .lower_extract_byte = true,
+ .lower_extract_word = true,
+ .lower_ffma = true,
+ .lower_fpow = true,
+ .lower_mul_2x32_64 = true,
+ .lower_rotate = true,
+ .use_scoped_barrier = true,
+ .max_unroll_iterations = 32,
+ .use_interpolated_input_intrinsics = true,
+ /* nir_lower_int64() isn't actually called for the LLVM backend, but
+ * this helps the loop unrolling heuristics. */
+ .lower_int64_options = nir_lower_imul64 |
+ nir_lower_imul_high64 |
+ nir_lower_imul_2x32_64 |
+ nir_lower_divmod64 |
+ nir_lower_minmax64 |
+ nir_lower_iabs64,
+ .lower_doubles_options = nir_lower_drcp |
+ nir_lower_dsqrt |
+ nir_lower_drsq |
+ nir_lower_ddiv,
+};
+
+static char *
+libresoc_dump_nir_shaders(struct nir_shader * const *shaders,
+ int shader_count)
+{
+ char *data = NULL;
+ char *ret = NULL;
+ size_t size = 0;
+ FILE *f = open_memstream(&data, &size);
+ if (f) {
+ for (int i = 0; i < shader_count; ++i)
+ nir_print_shader(shaders[i], f);
+ fclose(f);
+ }
+
+ ret = malloc(size + 1);
+ if (ret) {
+ memcpy(ret, data, size);
+ ret[size] = 0;
+ }
+ free(data);
+ return ret;
+}
+
+nir_shader *
+libresoc_shader_compile_to_nir(struct libresoc_device *device,
+ struct libresoc_shader_module *module,
+ const char *entrypoint_name,
+ gl_shader_stage stage,
+ const VkSpecializationInfo *spec_info,
+ const VkPipelineCreateFlags flags,
+ unsigned subgroup_size, unsigned ballot_bit_size)
+{
+ nir_shader *nir;
+ const nir_shader_compiler_options *nir_options =
+ &nir_options_llvm;
+
+ if (module->nir) {
+ /* Some things such as our meta clear/blit code will give us a NIR
+ * shader directly. In that case, we just ignore the SPIR-V entirely
+ * and just use the NIR shader */
+ nir = module->nir;
+ nir->options = nir_options;
+ nir_validate_shader(nir, "in internal shader");
+
+ assert(exec_list_length(&nir->functions) == 1);
+ } else {
+ uint32_t *spirv = (uint32_t *) module->data;
+ assert(module->size % 4 == 0);
+
+ if (device->instance->debug_flags & LIBRESOC_DEBUG_DUMP_SPIRV)
+ libresoc_print_spirv(module->data, module->size, stderr);
+
+ uint32_t num_spec_entries = 0;
+ struct nir_spirv_specialization *spec_entries = NULL;
+ if (spec_info && spec_info->mapEntryCount > 0) {
+ num_spec_entries = spec_info->mapEntryCount;
+ spec_entries = calloc(num_spec_entries, sizeof(*spec_entries));
+ for (uint32_t i = 0; i < num_spec_entries; i++) {
+ VkSpecializationMapEntry entry = spec_info->pMapEntries[i];
+ const void *data = spec_info->pData + entry.offset;
+ assert(data + entry.size <= spec_info->pData + spec_info->dataSize);
+
+ spec_entries[i].id = spec_info->pMapEntries[i].constantID;
+ switch (entry.size) {
+ case 8:
+ spec_entries[i].value.u64 = *(const uint64_t *)data;
+ break;
+ case 4:
+ spec_entries[i].value.u32 = *(const uint32_t *)data;
+ break;
+ case 2:
+ spec_entries[i].value.u16 = *(const uint16_t *)data;
+ break;
+ case 1:
+ spec_entries[i].value.u8 = *(const uint8_t *)data;
+ break;
+ default:
+ assert(!"Invalid spec constant size");
+ break;
+ }
+ }
+ }
+
+ const struct spirv_to_nir_options spirv_options = {0};
+ nir = spirv_to_nir(spirv, module->size / 4,
+ spec_entries, num_spec_entries,
+ stage, entrypoint_name,
+ &spirv_options, nir_options);
+ assert(nir->info.stage == stage);
+ nir_validate_shader(nir, "after spirv_to_nir");
+
+ if (device->instance->debug_flags & LIBRESOC_DEBUG_DUMP_NIR)
+ nir_print_shader(nir, stderr);
+ free(spec_entries);
+ }
+return nir;
+}
+
+VkResult
+libresoc_CreateShaderModule(VkDevice _device,
+ const VkShaderModuleCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkShaderModule *pShaderModule)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ struct libresoc_shader_module *module;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
+ assert(pCreateInfo->flags == 0);
+
+ module = vk_alloc2(&device->vk.alloc, pAllocator,
+ sizeof(*module) + pCreateInfo->codeSize, 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (module == NULL)
+ return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ vk_object_base_init(&device->vk, &module->base,
+ VK_OBJECT_TYPE_SHADER_MODULE);
+
+ module->nir = NULL;
+ module->size = pCreateInfo->codeSize;
+ memcpy(module->data, pCreateInfo->pCode, module->size);
+
+ _mesa_sha1_compute(module->data, module->size, module->sha1);
+
+ *pShaderModule = libresoc_shader_module_to_handle(module);
+
+ return VK_SUCCESS;
+}
+
+void
+libresoc_DestroyShaderModule(VkDevice _device,
+ VkShaderModule _module,
+ const VkAllocationCallbacks *pAllocator)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ LIBRESOC_FROM_HANDLE(libresoc_shader_module, module, _module);
+
+ if (!module)
+ return;
+
+ vk_object_base_finish(&module->base);
+ vk_free2(&device->vk.alloc, pAllocator, module);
+}
--- /dev/null
+/*
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ *
+ * based in part on anv driver which is:
+ * Copyright © 2015 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 LIBRESOC_SHADER_H
+#define LIBRESOC_SHADER_H
+
+#include "libresoc_constants.h"
+
+#include "util/mesa-sha1.h"
+#include "nir/nir.h"
+#include "nir/nir_builder.h"
+#include "spirv/nir_spirv.h"
+#include "libresoc_private.h"
+#include "nir/nir.h"
+#include "vulkan/vulkan.h"
+#include "vulkan/util/vk_object.h"
+
+struct libresoc_device;
+
+struct libresoc_shader_module {
+ struct vk_object_base base;
+ struct nir_shader *nir;
+ unsigned char sha1[20];
+ uint32_t size;
+ char data[0];
+};
+
+nir_shader *
+libresoc_shader_compile_to_nir(struct libresoc_device *device,
+ struct libresoc_shader_module *module,
+ const char *entrypoint_name,
+ gl_shader_stage stage,
+ const VkSpecializationInfo *spec_info,
+ const VkPipelineCreateFlags flags,
+ unsigned subgroup_size, unsigned ballot_bit_size);
+
+void
+libresoc_destroy_shader_slabs(struct libresoc_device *device);
+
+VkResult
+libresoc_create_shaders(struct libresoc_pipeline *pipeline,
+ struct libresoc_device *device,
+ const VkPipelineShaderStageCreateInfo **pStages,
+ const VkPipelineCreateFlags flags);
+
+#endif
liblibresoc_files = files(
'libresoc_device.c',
+ 'libresoc_debug.c',
+ 'libresoc_shader.c',
'libresoc_descriptor_set.c',
'libresoc_pass.c',
'libresoc_meta_clear.c',