abstruct custom shader

This commit is contained in:
IlyaShurupov 2024-11-18 14:44:11 +03:00
parent a6f4b253ae
commit 51e7730fdb

206
main.cpp
View file

@ -53,6 +53,107 @@ const std::vector<Vertex> vertices = {
const std::vector<uint16_t > indices = { 0, 1, 2, 2, 3, 0 };
struct CustomShader {
void create(VkDevice device) {
std::vector<char> vertShaderByteCode = readFile("bin/vert.spv");
mVertexModule = createShaderModule(device, vertShaderByteCode);
std::vector<char> fragShaderByteCode = readFile("bin/frag.spv");
mFragmentModule = createShaderModule(device, fragShaderByteCode);
VkPipelineShaderStageCreateInfo vertShaderStageCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = mVertexModule,
.pName = "main",
};
VkPipelineShaderStageCreateInfo fragShaderStageCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = mFragmentModule,
.pName = "main",
};
mStageCreateInfos = {
vertShaderStageCreateInfo,
fragShaderStageCreateInfo
};
}
void destroy(VkDevice device) const {
vkDestroyShaderModule(device, mVertexModule, nullptr);
vkDestroyShaderModule(device, mFragmentModule, nullptr);
}
static std::vector<char> readFile(const std::string &fileName) {
std::ifstream file(fileName, std::ios::ate | std::ios::binary);
if (!file.is_open()) {
throw std::runtime_error("cannot open file");
}
size_t fileSize = (size_t) file.tellg();
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), (std::streamsize) fileSize);
file.close();
return buffer;
}
static VkShaderModule createShaderModule(VkDevice device, const std::vector<char> &bytecode) {
VkShaderModuleCreateInfo createInfo{
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = (uint32_t) bytecode.size(),
.pCode = (uint32_t *) bytecode.data(),
};
VkShaderModule shaderModule;
if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
throw std::runtime_error("cannot create shader module");
}
return shaderModule;
}
public:
struct UniformBuffer {
glm::mat4 transforms {};
glm::vec4 origin {};
} mVertexUBO;
VkVertexInputBindingDescription mVertexInputDescription {
.binding = 0,
.stride = sizeof(Vertex),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
};
std::vector<VkVertexInputAttributeDescription> mVertexAttributes = {
{
.location = 0,
.binding = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = offsetof(Vertex, pos),
},
{
.location = 1,
.binding = 0,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(Vertex, color),
},
};
std::vector<VkPipelineShaderStageCreateInfo> mStageCreateInfos;
VkShaderModule mVertexModule = VK_NULL_HANDLE;
VkShaderModule mFragmentModule = VK_NULL_HANDLE;
};
class Application {
public:
void run() {
@ -99,6 +200,8 @@ private:
createSwapChain(width, height);
createSwapChainImageViews();
mShader.create(mDevice);
createRenderPass();
createGraphicsPipeline();
@ -521,30 +624,6 @@ private:
}
void createGraphicsPipeline() {
std::vector<char> vertShaderByteCode = readFile("bin/vert.spv");
mShaderModuleVert = createShaderModule(vertShaderByteCode);
VkPipelineShaderStageCreateInfo vertShaderStageCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = mShaderModuleVert,
.pName = "main",
};
std::vector<char> fragShaderByteCode = readFile("bin/frag.spv");
mShaderModuleFrag = createShaderModule(fragShaderByteCode);
VkPipelineShaderStageCreateInfo fragShaderStageCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = mShaderModuleFrag,
.pName = "main",
};
VkPipelineShaderStageCreateInfo shaderStageCreateInfos[] = {
vertShaderStageCreateInfo,
fragShaderStageCreateInfo
};
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
@ -557,15 +636,12 @@ private:
.pDynamicStates = dynamicStates.data(),
};
auto attributes = getShaderAttributesDescriptors();
auto vertexInput = getShaderVertexInputDescription();
VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = &vertexInput,
.vertexAttributeDescriptionCount = (uint32_t) attributes.size(),
.pVertexAttributeDescriptions = attributes.data(),
.pVertexBindingDescriptions = &mShader.mVertexInputDescription,
.vertexAttributeDescriptionCount = (uint32_t) mShader.mVertexAttributes.size(),
.pVertexAttributeDescriptions = mShader.mVertexAttributes.data(),
};
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo{
@ -643,7 +719,7 @@ private:
VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.stageCount = 2,
.pStages = shaderStageCreateInfos,
.pStages = mShader.mStageCreateInfos.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
.pViewportState = &viewportState,
@ -710,46 +786,11 @@ private:
}
void destroyGraphicsPipeline() {
vkDestroyShaderModule(mDevice, mShaderModuleVert, nullptr);
vkDestroyShaderModule(mDevice, mShaderModuleFrag, nullptr);
mShader.destroy(mDevice);
vkDestroyPipelineLayout(mDevice, mGraphicsPipelineLayout, nullptr);
vkDestroyPipeline(mDevice, mGraphicsPipeline, nullptr);
}
VkShaderModule createShaderModule(const std::vector<char> &bytecode) {
VkShaderModuleCreateInfo createInfo{
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = (uint32_t) bytecode.size(),
.pCode = (uint32_t *) bytecode.data(),
};
VkShaderModule shaderModule;
if (vkCreateShaderModule(mDevice, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
throw std::runtime_error("cannot create shader module");
}
return shaderModule;
}
static std::vector<char> readFile(const std::string &fileName) {
std::ifstream file(fileName, std::ios::ate | std::ios::binary);
if (!file.is_open()) {
throw std::runtime_error("cannot open file");
}
size_t fileSize = (size_t) file.tellg();
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), (std::streamsize) fileSize);
file.close();
return buffer;
}
void createCommandPool() {
VkCommandPoolCreateInfo createInfo{
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
@ -1044,34 +1085,6 @@ private:
*/
}
static VkVertexInputBindingDescription getShaderVertexInputDescription() {
return {
.binding = 0,
.stride = sizeof(Vertex),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
};
}
static std::vector<VkVertexInputAttributeDescription> getShaderAttributesDescriptors() {
std::vector<VkVertexInputAttributeDescription> out(2);
out[0] = {
.location = 0,
.binding = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = offsetof(Vertex, pos),
};
out[1] = {
.location = 1,
.binding = 0,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(Vertex, color),
};
return out;
}
void destroySynchronizationObjects() {
vkDestroySemaphore(mDevice, mSemaphoreImageAcquired, nullptr);
vkDestroySemaphore(mDevice, mSemaphoreFramebufferDrawn, nullptr);
@ -1127,9 +1140,8 @@ private:
std::vector<VkImageView> mSwapChainImageViews;
std::vector<VkFramebuffer> mSwapChainFrameBuffers;
CustomShader mShader;
VkPipeline mGraphicsPipeline = VK_NULL_HANDLE;
VkShaderModule mShaderModuleVert = VK_NULL_HANDLE;
VkShaderModule mShaderModuleFrag = VK_NULL_HANDLE;
VkRenderPass mGraphicsRenderPass = VK_NULL_HANDLE;
VkPipelineLayout mGraphicsPipelineLayout{}; // no uniforms used in the shader