1
Fork 0
mirror of https://github.com/redstrate/Novus.git synced 2025-04-25 21:27:45 +00:00

"Implement" the directional lighting pass, fix GBuffer normal

Implement is in quotes because it doesn't work yet, the code is just
written. We still need actual framebuffers to do work in and not the
swapchain image we're reusing.

In other news, the GBuffer shader now works and outputs normals! I
forced it to simple texture mode for now so it makes development easier.
This commit is contained in:
Joshua Goins 2024-04-21 11:52:30 -04:00
parent 2d17af5675
commit fd61cfca26
2 changed files with 134 additions and 49 deletions

View file

@ -29,8 +29,8 @@ public:
private:
void beginPass(uint32_t imageIndex, VkCommandBuffer commandBuffer, std::string_view passName);
void endPass(VkCommandBuffer commandBuffer);
void bindPipeline(VkCommandBuffer commandBuffer, physis_Shader &vertexShader, physis_Shader &pixelShader);
void endPass(VkCommandBuffer commandBuffer, std::string_view passName);
void bindPipeline(VkCommandBuffer commandBuffer, std::string_view passName, physis_Shader &vertexShader, physis_Shader &pixelShader);
VkShaderModule convertShaderModule(const physis_Shader &shader, spv::ExecutionModel executionModel);
spirv_cross::CompilerGLSL getShaderModuleResources(const physis_Shader &shader);
@ -71,7 +71,7 @@ private:
GameData *m_data = nullptr;
VkExtent2D m_extent = {640, 480};
VkDescriptorSet createDescriptorFor(const RenderModel &model, const CachedPipeline &cachedPipeline, int i);
VkDescriptorSet createDescriptorFor(const CachedPipeline &cachedPipeline, int i);
struct UniformBuffer {
VkBuffer buffer;
@ -137,4 +137,7 @@ private:
};
UniformBuffer g_MaterialParameter;
VkBuffer m_planeVertexBuffer;
VkDeviceMemory m_planeVertexMemory;
};

View file

@ -16,6 +16,17 @@
#include <glm/ext/matrix_clip_space.hpp>
// TODO: maybe need UV?
const std::vector<glm::vec4> planeVertices = {
{-0.5f, -0.5f, 0.0f, 0.0f},
{0.5f, -0.5f, 0.0f, 0.0f},
{0.5f, 0.5f, 0.0f, 0.0f},
{-0.5f, 0.5f, 0.0f, 0.0f},
{-0.5f, -0.5f, 0.0f, 0.0f},
{0.5f, 0.5f, 0.0f, 0.0f},
};
dxvk::Logger dxvk::Logger::s_instance("dxbc.log");
const std::array<std::string, 14> passes = {
@ -44,6 +55,28 @@ RenderSystem::RenderSystem(Renderer &renderer, GameData *data)
: m_renderer(renderer)
, m_data(data)
{
size_t vertexSize = planeVertices.size() * sizeof(glm::vec4);
auto [vertexBuffer, vertexMemory] = m_renderer.createBuffer(vertexSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
m_planeVertexBuffer = vertexBuffer;
m_planeVertexMemory = vertexMemory;
// copy vertex data
{
void *mapped_data = nullptr;
vkMapMemory(m_renderer.device, vertexMemory, 0, vertexSize, 0, &mapped_data);
memcpy(mapped_data, planeVertices.data(), vertexSize);
VkMappedMemoryRange range = {};
range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
range.memory = vertexMemory;
range.size = vertexSize;
vkFlushMappedMemoryRanges(m_renderer.device, 1, &range);
vkUnmapMemory(m_renderer.device, vertexMemory);
}
directionalLightningShpk = physis_parse_shpk(physis_gamedata_extract_file(m_data, "shader/sm5/shpk/directionallighting.shpk"));
// camera data
@ -133,12 +166,15 @@ void RenderSystem::render(uint32_t imageIndex, VkCommandBuffer commandBuffer)
};
std::vector<uint32_t> materialKeys;
for (int j = 0; j < model.shpk.num_material_keys; j++) {
materialKeys.push_back(model.shpk.material_keys[j].default_value);
auto value = model.shpk.material_keys[j].default_value;
// Replace MODE_DEFAULT with MODE_SIMPLE for now
if (value != 0x5CC605B5) {
materialKeys.push_back(model.shpk.material_keys[j].default_value);
} else {
materialKeys.push_back(0x22A4AABF);
}
}
std::vector<uint32_t> subviewKeys = {
physis_shpk_crc("Default"),
physis_shpk_crc("SUB_VIEW_MAIN"),
};
std::vector<uint32_t> subviewKeys = {physis_shpk_crc("Default"), physis_shpk_crc("SUB_VIEW_MAIN")};
const u_int32_t selector = physis_shpk_build_selector_from_all_keys(systemKeys.data(),
systemKeys.size(),
@ -161,40 +197,14 @@ void RenderSystem::render(uint32_t imageIndex, VkCommandBuffer commandBuffer)
const Pass currentPass = node.passes[passIndice];
const uint32_t vertexShaderIndice = currentPass.vertex_shader;
const uint32_t pixelShaderIndice = currentPass.vertex_shader;
const uint32_t pixelShaderIndice = currentPass.pixel_shader;
physis_Shader vertexShader = model.shpk.vertex_shaders[vertexShaderIndice];
physis_Shader pixelShader = model.shpk.pixel_shaders[pixelShaderIndice];
bindPipeline(commandBuffer, vertexShader, pixelShader);
bindPipeline(commandBuffer, pass, vertexShader, pixelShader);
for (const auto &part : model.internal_model->parts) {
const uint32_t hash = vertexShader.len + pixelShader.len;
auto &cachedPipeline = m_cachedPipelines[hash];
int i = 0;
for (auto setLayout : cachedPipeline.setLayouts) {
if (!cachedPipeline.cachedDescriptors.count(i)) {
if (auto descriptor = createDescriptorFor(model, cachedPipeline, i); descriptor != VK_NULL_HANDLE) {
cachedPipeline.cachedDescriptors[i] = descriptor;
} else {
continue;
}
}
// TODO: we can pass all descriptors in one function call
vkCmdBindDescriptorSets(commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
cachedPipeline.pipelineLayout,
i,
1,
&cachedPipeline.cachedDescriptors[i],
0,
nullptr);
i++;
}
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &part.vertexBuffer, offsets);
vkCmdBindIndexBuffer(commandBuffer, part.indexBuffer, 0, VK_INDEX_TYPE_UINT16);
@ -203,7 +213,7 @@ void RenderSystem::render(uint32_t imageIndex, VkCommandBuffer commandBuffer)
}
}
}
} else if (pass == "PASS_LIGHTING_OPAQUE") {
} else if (false && pass == "PASS_LIGHTING_OPAQUE") {
std::vector<uint32_t> systemKeys = {
physis_shpk_crc("DecodeDepthBuffer_RAWZ"),
};
@ -237,16 +247,21 @@ void RenderSystem::render(uint32_t imageIndex, VkCommandBuffer commandBuffer)
const Pass currentPass = node.passes[passIndice];
const uint32_t vertexShaderIndice = currentPass.vertex_shader;
const uint32_t pixelShaderIndice = currentPass.vertex_shader;
const uint32_t pixelShaderIndice = currentPass.pixel_shader;
physis_Shader vertexShader = directionalLightningShpk.vertex_shaders[vertexShaderIndice];
physis_Shader pixelShader = directionalLightningShpk.pixel_shaders[pixelShaderIndice];
// TODO: draw plane for directional lighting
bindPipeline(commandBuffer, pass, vertexShader, pixelShader);
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &m_planeVertexBuffer, offsets);
vkCmdDraw(commandBuffer, 6, 1, 0, 0);
}
}
endPass(commandBuffer);
endPass(commandBuffer, pass);
i++;
}
@ -259,8 +274,11 @@ void RenderSystem::setSize(uint32_t width, uint32_t height)
void RenderSystem::beginPass(uint32_t imageIndex, VkCommandBuffer commandBuffer, const std::string_view passName)
{
VkRenderingInfo renderingInfo{VK_STRUCTURE_TYPE_RENDERING_INFO};
if (passName != "PASS_G_OPAQUE") {
return;
}
VkRenderingInfo renderingInfo{VK_STRUCTURE_TYPE_RENDERING_INFO};
renderingInfo.renderArea.extent = m_extent;
std::vector<VkRenderingAttachmentInfo> colorAttachments;
@ -271,7 +289,7 @@ void RenderSystem::beginPass(uint32_t imageIndex, VkCommandBuffer commandBuffer,
{
VkRenderingAttachmentInfo attachmentInfo{VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO};
attachmentInfo.imageView = m_renderer.swapchainViews[imageIndex];
attachmentInfo.imageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
attachmentInfo.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
@ -316,6 +334,33 @@ void RenderSystem::beginPass(uint32_t imageIndex, VkCommandBuffer commandBuffer,
depthStencilAttachment = attachmentInfo;
}
} else if (passName == "PASS_LIGHTING_OPAQUE") {
// normals, it seems like
{
VkRenderingAttachmentInfo attachmentInfo{VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO};
attachmentInfo.imageView = m_renderer.swapchainViews[imageIndex];
attachmentInfo.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachmentInfo.clearValue.color.float32[0] = 0.24;
attachmentInfo.clearValue.color.float32[1] = 0.24;
attachmentInfo.clearValue.color.float32[2] = 0.24;
attachmentInfo.clearValue.color.float32[3] = 1.0;
colorAttachments.push_back(attachmentInfo);
}
// unknown
{
VkRenderingAttachmentInfo attachmentInfo{VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO};
attachmentInfo.imageView = VK_NULL_HANDLE;
attachmentInfo.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachments.push_back(attachmentInfo);
}
} else {
// qWarning() << "Unimplemented pass" << passName;
}
@ -331,14 +376,17 @@ void RenderSystem::beginPass(uint32_t imageIndex, VkCommandBuffer commandBuffer,
vkCmdBeginRendering(commandBuffer, &renderingInfo);
}
void RenderSystem::endPass(VkCommandBuffer commandBuffer)
void RenderSystem::endPass(VkCommandBuffer commandBuffer, std::string_view passName)
{
if (passName != "PASS_G_OPAQUE") {
return;
}
vkCmdEndRendering(commandBuffer);
}
void RenderSystem::bindPipeline(VkCommandBuffer commandBuffer, physis_Shader &vertexShader, physis_Shader &pixelShader)
void RenderSystem::bindPipeline(VkCommandBuffer commandBuffer, std::string_view passName, physis_Shader &vertexShader, physis_Shader &pixelShader)
{
const uint32_t hash = vertexShader.len + pixelShader.len;
const uint32_t hash = vertexShader.len + pixelShader.len + physis_shpk_crc(passName.data());
if (!m_cachedPipelines.contains(hash)) {
auto vertexShaderModule = convertShaderModule(vertexShader, spv::ExecutionModelVertex);
auto fragmentShaderModule = convertShaderModule(pixelShader, spv::ExecutionModelFragment);
@ -352,13 +400,19 @@ void RenderSystem::bindPipeline(VkCommandBuffer commandBuffer, physis_Shader &ve
VkPipelineShaderStageCreateInfo fragmentShaderStageInfo = {};
fragmentShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragmentShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragmentShaderStageInfo.module = fragmentShaderModule;
fragmentShaderStageInfo.module = fragmentShaderModule; // m_renderer.loadShaderFromDisk(":/shaders/dummy.frag.spv");
fragmentShaderStageInfo.pName = "main";
std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages = {vertexShaderStageInfo, fragmentShaderStageInfo};
VkVertexInputBindingDescription binding = {};
binding.stride = sizeof(Vertex);
// TODO: temporary
if (passName == "PASS_G_OPAQUE") {
binding.stride = sizeof(Vertex);
} else if (passName == "PASS_LIGHTING_OPAQUE") {
binding.stride = sizeof(glm::vec4);
}
auto vertex_glsl = getShaderModuleResources(vertexShader);
auto vertex_resources = vertex_glsl.get_shader_resources();
@ -543,7 +597,19 @@ void RenderSystem::bindPipeline(VkCommandBuffer commandBuffer, physis_Shader &ve
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachments = {colorBlendAttachment, colorBlendAttachment, colorBlendAttachment};
std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachments;
int colorAttachmentCount = 1;
// TODO: hardcoded, should be a reusable function to get the color attachments
if (passName == "PASS_G_OPAQUE") {
colorAttachmentCount = 3;
} else if (passName == "PASS_LIGHTING_OPAQUE") {
colorAttachmentCount = 2;
}
for (int i = 0; i < colorAttachmentCount; i++) {
colorBlendAttachments.push_back(colorBlendAttachment);
}
VkPipelineColorBlendStateCreateInfo colorBlending = {};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
@ -616,6 +682,22 @@ void RenderSystem::bindPipeline(VkCommandBuffer commandBuffer, physis_Shader &ve
auto &pipeline = m_cachedPipelines[hash];
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline); // TODO: return CachedPipeline&
int i = 0;
for (auto setLayout : pipeline.setLayouts) {
if (!pipeline.cachedDescriptors.count(i)) {
if (auto descriptor = createDescriptorFor(pipeline, i); descriptor != VK_NULL_HANDLE) {
pipeline.cachedDescriptors[i] = descriptor;
} else {
continue;
}
}
// TODO: we can pass all descriptors in one function call
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipelineLayout, i, 1, &pipeline.cachedDescriptors[i], 0, nullptr);
i++;
}
}
VkShaderModule RenderSystem::convertShaderModule(const physis_Shader &shader, spv::ExecutionModel executionModel)
@ -687,7 +769,7 @@ spirv_cross::CompilerGLSL RenderSystem::getShaderModuleResources(const physis_Sh
return spirv_cross::CompilerGLSL(result.code.data(), result.code.dwords());
}
VkDescriptorSet RenderSystem::createDescriptorFor(const RenderModel &model, const CachedPipeline &pipeline, int i)
VkDescriptorSet RenderSystem::createDescriptorFor(const CachedPipeline &pipeline, int i)
{
VkDescriptorSet set;