Starting Out
Signed-off-by: Robear Selwans <robear.selwans@outlook.com>
This commit is contained in:
138
evk/evkShader.c
Normal file
138
evk/evkShader.c
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "evk/evkShader.h"
|
||||
#include "shaderc/shaderc.h"
|
||||
#include "ev_helpers.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 = {
|
||||
.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);
|
||||
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);
|
||||
printf("[[evkShader]] %s Compilation Status: %d ( %d Errors, %d Warnings )\n", shaderPath, status, errorCount, warnCount);
|
||||
if(errorCount + warnCount > 0)
|
||||
{
|
||||
printf("Errors:\n%s\n", 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",
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user