Files
evk/evk/evkShader.c
2025-07-07 16:44:22 +03:00

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",
};
}