142 lines
4.9 KiB
C
142 lines
4.9 KiB
C
#include "evk/evkShader.h"
|
|
#include "shaderc/shaderc.h"
|
|
#include "ev_helpers.h"
|
|
#include "spirv_reflect.h"
|
|
|
|
evkShader evkInitShaderFromBytes(evkDevice device, const u8* shaderBytes, u32 shaderLen)
|
|
{
|
|
evkShader shader;
|
|
VkShaderModuleCreateInfo createInfo = {
|
|
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
|
.pCode = (u32*)shaderBytes,
|
|
.codeSize = shaderLen,
|
|
};
|
|
vkCreateShaderModule(device.vk, &createInfo, NULL, &shader.vk);
|
|
|
|
shader.reflect = evkGenerateShaderReflectionData(shaderBytes, shaderLen);
|
|
|
|
return shader;
|
|
}
|
|
|
|
evkShaderReflectionData evkGenerateShaderReflectionData(const u8* shaderBytes, u32 shaderLen)
|
|
{
|
|
evkShaderReflectionData res;
|
|
|
|
SpvReflectShaderModule spvref;
|
|
SpvReflectResult result = spvReflectCreateShaderModule(shaderLen, shaderBytes, &spvref);
|
|
assert(result == SPV_REFLECT_RESULT_SUCCESS);
|
|
|
|
// Fill evkShaderReflectionData
|
|
res.stage = spvref.shader_stage;
|
|
res.bindings = vec_init(evkDescriptorBinding);
|
|
|
|
|
|
uint32_t descSetCount = 0;
|
|
SpvReflectResult descSetResult = spvReflectEnumerateDescriptorSets(&spvref, &descSetCount, NULL);
|
|
if(descSetResult == SPV_REFLECT_RESULT_SUCCESS)
|
|
{
|
|
SpvReflectDescriptorSet* refDescriptorSets[descSetCount] = {};
|
|
spvReflectEnumerateDescriptorSets(&spvref, &descSetCount, refDescriptorSets);
|
|
|
|
for(int setIdx = 0; setIdx < descSetCount; setIdx++)
|
|
{
|
|
SpvReflectDescriptorSet* currentSet = refDescriptorSets[setIdx];
|
|
for(int bindingIdx = 0; bindingIdx < currentSet->binding_count; bindingIdx++)
|
|
{
|
|
evkDescriptorBinding binding = {
|
|
.name = evstring_new(currentSet->bindings[bindingIdx]->name),
|
|
.stageFlags = res.stage,
|
|
.binding = currentSet->bindings[bindingIdx]->binding,
|
|
.descriptorType = (VkDescriptorType) currentSet->bindings[bindingIdx]->descriptor_type,
|
|
.descriptorCount = currentSet->bindings[bindingIdx]->count,
|
|
// .set = currentSet->set,
|
|
};
|
|
|
|
vec_push(&res.bindings, &binding);
|
|
}
|
|
}
|
|
}
|
|
|
|
spvReflectDestroyShaderModule(&spvref);
|
|
return res;
|
|
}
|
|
|
|
void evkDestroyShaderReflectionData(evkShaderReflectionData data)
|
|
{
|
|
vec_fini(&data.bindings);
|
|
}
|
|
|
|
void evkDestroyShader(evkDevice device, evkShader shader)
|
|
{
|
|
vkDestroyShaderModule(device.vk, shader.vk, NULL);
|
|
evkDestroyShaderReflectionData(shader.reflect);
|
|
}
|
|
|
|
shaderc_include_result* _shader_include_resolve(void* user_data, const char* requested_source, int type, const char* requesting_source, size_t include_depth)
|
|
{
|
|
shaderc_include_result* result = malloc(sizeof(shaderc_include_result));
|
|
result->source_name = evstring_new(requested_source);
|
|
result->source_name_length = evstring_getLength((evstring)result->source_name);
|
|
|
|
result->content = evstring_readFile((evstring)result->source_name);
|
|
result->content_length = evstring_getLength((evstring)result->content);
|
|
|
|
return result;
|
|
}
|
|
|
|
void _shader_include_release(void* user_data, shaderc_include_result* include_result)
|
|
{
|
|
evstring_free((evstring)include_result->content);
|
|
evstring_free((evstring)include_result->source_name);
|
|
free(include_result);
|
|
}
|
|
|
|
evkShaderCompiler evkCreateShaderCompiler()
|
|
{
|
|
evkShaderCompiler compiler;
|
|
compiler.sc = shaderc_compiler_initialize();
|
|
compiler.scopt = shaderc_compile_options_initialize();
|
|
shaderc_compile_options_set_include_callbacks(compiler.scopt, _shader_include_resolve, _shader_include_release, NULL);
|
|
shaderc_compile_options_set_generate_debug_info(compiler.scopt);
|
|
return compiler;
|
|
}
|
|
|
|
void evkDestroyShaderCompiler(evkShaderCompiler compiler)
|
|
{
|
|
shaderc_compile_options_release(compiler.scopt);
|
|
shaderc_compiler_release(compiler.sc);
|
|
}
|
|
|
|
evkShader evkInitShaderFromFile(evkDevice device, evkShaderCompiler compiler, evstring shaderPath)
|
|
{
|
|
evstring shaderText = evstring_readFile(shaderPath);
|
|
|
|
shaderc_compilation_result_t compilation_result = shaderc_compile_into_spv(compiler.sc, shaderText, evstring_getLength(shaderText), shaderc_glsl_infer_from_source, shaderPath, "main", compiler.scopt);
|
|
|
|
shaderc_compilation_status status = shaderc_result_get_compilation_status(compilation_result);
|
|
|
|
u32 errorCount = shaderc_result_get_num_errors(compilation_result);
|
|
u32 warnCount = shaderc_result_get_num_warnings(compilation_result);
|
|
ev_log_info("[[evkShader]] %s Compilation Status: %d ( %d Errors, %d Warnings )", shaderPath, status, errorCount, warnCount);
|
|
if(errorCount + warnCount > 0)
|
|
{
|
|
ev_log_error("Errors:\n%s", shaderc_result_get_error_message(compilation_result));
|
|
}
|
|
|
|
evkShader shader = evkInitShaderFromBytes(device, (u8*)shaderc_result_get_bytes(compilation_result), shaderc_result_get_length(compilation_result));
|
|
|
|
evstring_free(shaderText);
|
|
|
|
return shader;
|
|
}
|
|
|
|
VkPipelineShaderStageCreateInfo evkGetShaderStageCreateInfo(evkShader shader)
|
|
{
|
|
return (VkPipelineShaderStageCreateInfo) {
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
.stage = shader.reflect.stage,
|
|
.module = shader.vk,
|
|
.pName = "main",
|
|
};
|
|
}
|