1
Fork 0
mirror of https://github.com/redstrate/Novus.git synced 2025-04-25 05:17:44 +00:00

Pass real data to the new render system

Based off of structures reversed engineered by Ouroboros, now it can
render objects without shading! Note that it breaks the basic renderer
at the moment, will be fixed later.
This commit is contained in:
Joshua Goins 2024-04-21 09:01:02 -04:00
parent 640099f9db
commit 699141d04b
3 changed files with 265 additions and 18 deletions

View file

@ -35,7 +35,7 @@ target_link_libraries(renderer
dxbc
spirv-cross-core
spirv-cross-glsl)
target_compile_definitions(renderer PUBLIC GLM_FORCE_RADIANS GLM_FORCE_DEPTH_ZERO_TO_ONE GLM_ENABLE_EXPERIMENTAL)
target_compile_definitions(renderer PUBLIC GLM_FORCE_RADIANS GLM_FORCE_DEPTH_ZERO_TO_ONE GLM_ENABLE_EXPERIMENTAL GLM_FORCE_LEFT_HANDED)
target_compile_options(renderer PUBLIC -fexceptions) # needed for spirv-cross and dxbc
add_library(Novus::Renderer ALIAS renderer)

View file

@ -6,6 +6,7 @@
#include <QDebug>
#include <string_view>
#include <glm/glm.hpp>
#include <physis.hpp>
#include <spirv.hpp>
#include <spirv_cross.hpp>
@ -58,6 +59,7 @@ private:
std::vector<VkDescriptorSetLayout> setLayouts;
std::map<uint64_t, VkDescriptorSet> cachedDescriptors;
std::vector<RequestedSet> requestedSets;
physis_Shader vertexShader, pixelShader;
};
// combined vertex + pixel code length
@ -68,4 +70,69 @@ private:
VkExtent2D m_extent = {640, 480};
VkDescriptorSet createDescriptorFor(const RenderModel &model, const CachedPipeline &cachedPipeline, int i);
struct UniformBuffer {
VkBuffer buffer;
VkDeviceMemory memory;
size_t size;
};
UniformBuffer createUniformBuffer(size_t size);
void copyDataToUniform(UniformBuffer &uniformBuffer, void *data, size_t size);
// Structure definitions from https://github.com/Shaderlayan/Ouroboros
struct CameraParameter {
glm::mat3x4 m_ViewMatrix;
glm::mat3x4 m_InverseViewMatrix;
glm::mat4 m_InverseViewProjectionMatrix;
glm::mat4 m_InverseProjectionMatrix;
glm::mat4 m_ProjectionMatrix;
glm::mat4 m_ViewProjectionMatrix;
/*glm::mat4 m_MainViewToProjectionMatrix;
glm::vec3 m_EyePosition;
glm::vec3 m_LookAtVector;*/
};
UniformBuffer g_CameraParameter;
struct JointMatrixArray {
glm::mat3x4 g_JointMatrixArray[64];
};
UniformBuffer g_JointMatrixArray;
struct CameraLight {
glm::vec4 m_DiffuseSpecular;
glm::vec4 m_Rim;
};
struct InstanceParameterStruct {
glm::vec4 m_MulColor;
glm::vec4 m_EnvParameter;
CameraLight m_CameraLight;
glm::vec4 m_Wetness;
};
struct InstanceParameter {
InstanceParameterStruct g_InstanceParameter;
};
UniformBuffer g_InstanceParameter;
struct ModelParameterStruct {
glm::vec4 m_Params;
};
struct ModelParameter {
ModelParameterStruct g_ModelParameter;
};
UniformBuffer g_ModelParameter;
struct MaterialParameter {
glm::vec3 g_DiffuseColor;
float g_AlphaThreshold;
};
UniformBuffer g_MaterialParameter;
};

View file

@ -14,6 +14,8 @@
#include "renderer.hpp"
#include <spirv_glsl.hpp>
#include <glm/ext/matrix_clip_space.hpp>
dxvk::Logger dxvk::Logger::s_instance("dxbc.log");
const std::array passes = {
@ -62,11 +64,50 @@ RenderSystem::RenderSystem(Renderer &renderer, GameData *data)
: m_renderer(renderer)
, m_data(data)
{
// camera data
{
g_CameraParameter = createUniformBuffer(sizeof(CameraParameter));
}
// joint matrix data
{
g_JointMatrixArray = createUniformBuffer(sizeof(JointMatrixArray));
JointMatrixArray jointMatrixArray{};
for (int i = 0; i < 64; i++) {
jointMatrixArray.g_JointMatrixArray[i] = glm::mat3x4(1.0f);
}
copyDataToUniform(g_JointMatrixArray, &jointMatrixArray, sizeof(JointMatrixArray));
}
// instance data
{
g_InstanceParameter = createUniformBuffer(sizeof(InstanceParameter));
InstanceParameter instanceParameter{};
copyDataToUniform(g_InstanceParameter, &instanceParameter, sizeof(InstanceParameter));
}
// model data
{
g_ModelParameter = createUniformBuffer(sizeof(ModelParameter));
ModelParameter modelParameter{};
copyDataToUniform(g_ModelParameter, &modelParameter, sizeof(ModelParameter));
}
// material data
{
g_MaterialParameter = createUniformBuffer(sizeof(MaterialParameter));
MaterialParameter materialParameter{};
materialParameter.g_AlphaThreshold = 0.0f;
materialParameter.g_DiffuseColor = glm::vec3(1.0f);
copyDataToUniform(g_MaterialParameter, &materialParameter, sizeof(MaterialParameter));
}
}
void RenderSystem::testInit(::RenderModel *m)
{
qInfo() << "initialzing render system with dummy data...";
RenderModel model{.shpk = physis_parse_shpk(physis_gamedata_extract_file(m_data, "shader/sm5/shpk/character.shpk")),
.internal_model = new ::RenderModel(*m)};
m_renderModels.push_back(model);
@ -74,6 +115,25 @@ void RenderSystem::testInit(::RenderModel *m)
void RenderSystem::render(uint32_t imageIndex, VkCommandBuffer commandBuffer)
{
// TODO: this shouldn't be here
CameraParameter cameraParameter{};
glm::mat4 projectionMatrix = glm::perspective(glm::radians(45.0f), 640.0f / 480.0f, 0.1f, 1000.0f);
glm::mat4 viewMatrix = m_renderer.view;
glm::mat4 viewProjectionMatrix = projectionMatrix * viewMatrix;
cameraParameter.m_ViewMatrix = viewMatrix;
cameraParameter.m_InverseViewMatrix = glm::inverse(viewMatrix);
cameraParameter.m_ViewProjectionMatrix = glm::transpose(viewProjectionMatrix);
cameraParameter.m_InverseViewProjectionMatrix = glm::inverse(viewProjectionMatrix);
cameraParameter.m_InverseProjectionMatrix = glm::inverse(projectionMatrix);
cameraParameter.m_ProjectionMatrix = projectionMatrix;
/*cameraParameter.m_MainViewToProjectionMatrix = glm::mat4(1.0f); // ???
cameraParameter.m_EyePosition = glm::vec3(5.0f); // placeholder
cameraParameter.m_LookAtVector = glm::vec3(0.0f); // placeholder*/
copyDataToUniform(g_CameraParameter, &cameraParameter, sizeof(CameraParameter));
int i = 0;
for (const auto pass : passes) {
beginPass(imageIndex, commandBuffer, pass);
@ -110,8 +170,6 @@ void RenderSystem::render(uint32_t imageIndex, VkCommandBuffer commandBuffer)
int i = 0;
for (auto setLayout : cachedPipeline.setLayouts) {
qInfo() << "Trying to cache descriptor set at " << i;
if (!cachedPipeline.cachedDescriptors.count(i)) {
if (auto descriptor = createDescriptorFor(model, cachedPipeline, i); descriptor != VK_NULL_HANDLE) {
cachedPipeline.cachedDescriptors[i] = descriptor;
@ -129,7 +187,6 @@ void RenderSystem::render(uint32_t imageIndex, VkCommandBuffer commandBuffer)
&cachedPipeline.cachedDescriptors[i],
0,
nullptr);
qInfo() << "Binding descriptor set at " << i;
i++;
}
@ -138,7 +195,6 @@ void RenderSystem::render(uint32_t imageIndex, VkCommandBuffer commandBuffer)
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &part.vertexBuffer, offsets);
vkCmdBindIndexBuffer(commandBuffer, part.indexBuffer, 0, VK_INDEX_TYPE_UINT16);
qInfo() << "Calling index";
vkCmdDrawIndexed(commandBuffer, part.numIndices, 1, 0, 0, 0);
//}
}
@ -340,15 +396,13 @@ void RenderSystem::bindPipeline(VkCommandBuffer commandBuffer, physis_Shader &ve
}
}
VkVertexInputAttributeDescription positionAttribute = {};
positionAttribute.format = VK_FORMAT_R32G32B32_SFLOAT;
positionAttribute.offset = offsetof(Vertex, position);
std::vector<VkVertexInputAttributeDescription> attributeDescs;
for (auto texture : vertex_resources.stage_inputs) {
unsigned binding = vertex_glsl.get_decoration(texture.id, spv::DecorationLocation);
auto name = vertex_glsl.get_name(texture.id);
VkVertexInputAttributeDescription uv0Attribute = {};
auto type = vertex_glsl.get_type(texture.type_id);
@ -364,7 +418,7 @@ void RenderSystem::bindPipeline(VkCommandBuffer commandBuffer, physis_Shader &ve
uv0Attribute.format = VK_FORMAT_R32G32B32_SINT;
break;
case 4:
uv0Attribute.format = VK_FORMAT_R32G32B32A32_SINT;
uv0Attribute.format = VK_FORMAT_R8G8B8A8_UINT; // supposed to be VK_FORMAT_R32G32B32A32_SINT, but our bone_id is uint8_t currently
break;
}
} else {
@ -385,7 +439,25 @@ void RenderSystem::bindPipeline(VkCommandBuffer commandBuffer, physis_Shader &ve
}
uv0Attribute.location = binding;
uv0Attribute.offset = offsetof(Vertex, position);
// TODO: temporary
if (name == "v0") {
uv0Attribute.offset = offsetof(Vertex, position);
} else if (name == "v1") {
uv0Attribute.offset = offsetof(Vertex, color);
} else if (name == "v2") {
uv0Attribute.offset = offsetof(Vertex, normal);
} else if (name == "v3") {
uv0Attribute.offset = offsetof(Vertex, uv0);
} else if (name == "v4") {
uv0Attribute.offset = offsetof(Vertex, bitangent); // FIXME: should be tangent
} else if (name == "v5") {
uv0Attribute.offset = offsetof(Vertex, bitangent);
} else if (name == "v6") {
uv0Attribute.offset = offsetof(Vertex, bone_weight);
} else if (name == "v7") {
uv0Attribute.offset = offsetof(Vertex, bone_id);
}
attributeDescs.push_back(uv0Attribute);
}
@ -493,8 +565,12 @@ void RenderSystem::bindPipeline(VkCommandBuffer commandBuffer, physis_Shader &ve
vkCreateGraphicsPipelines(m_renderer.device, VK_NULL_HANDLE, 1, &createInfo, nullptr, &pipeline);
qInfo() << "Created" << pipeline << "for hash" << hash;
m_cachedPipelines[hash] =
CachedPipeline{.pipeline = pipeline, .pipelineLayout = pipelineLayout, .setLayouts = setLayouts, .requestedSets = requestedSets};
m_cachedPipelines[hash] = CachedPipeline{.pipeline = pipeline,
.pipelineLayout = pipelineLayout,
.setLayouts = setLayouts,
.requestedSets = requestedSets,
.vertexShader = vertexShader,
.pixelShader = pixelShader};
}
auto &pipeline = m_cachedPipelines[hash];
@ -518,6 +594,41 @@ VkShaderModule RenderSystem::convertShaderModule(const physis_Shader &shader, sp
VkShaderModule shaderModule;
vkCreateShaderModule(m_renderer.device, &createInfo, nullptr, &shaderModule);
// TODO: for debug only
spirv_cross::CompilerGLSL glsl(result.code.data(), result.code.dwords());
auto resources = glsl.get_shader_resources();
int i = 0;
for (auto texture : resources.stage_inputs) {
// glsl.set_name(texture.id, shader.)
// qInfo() << shader.resource_parameters[i].name << texture.id;
// qInfo() << "stage input" << i << texture.name << glsl.get_type(texture.type_id).width;
i++;
// glsl.set_name(remap.combined_id, "SPIRV_Cross_Combined");
}
// Here you can also set up decorations if you want (binding = #N).
i = 0;
for (auto texture : resources.separate_images) {
glsl.set_name(texture.id, shader.resource_parameters[i].name);
i++;
}
i = 0;
for (auto buffer : resources.uniform_buffers) {
glsl.set_name(buffer.id, shader.scalar_parameters[i].name);
i++;
}
spirv_cross::CompilerGLSL::Options options;
options.vulkan_semantics = true;
options.enable_420pack_extension = false;
glsl.set_common_options(options);
glsl.set_entry_point("main", executionModel);
qInfo() << "Compiled GLSL:" << glsl.compile().c_str();
return shaderModule;
}
@ -529,7 +640,6 @@ spirv_cross::CompilerGLSL RenderSystem::getShaderModuleResources(const physis_Sh
dxvk::DxbcModuleInfo info;
auto result = module.compile(info, "test");
;
// glsl.build_combined_image_samplers();
@ -562,6 +672,7 @@ VkDescriptorSet RenderSystem::createDescriptorFor(const RenderModel &model, cons
imageInfo.reserve(pipeline.requestedSets[i].bindings.size());
int j = 0;
int z = 0;
for (auto binding : pipeline.requestedSets[i].bindings) {
if (binding.used) {
VkWriteDescriptorSet &descriptorWrite = writes.emplace_back();
@ -589,8 +700,38 @@ VkDescriptorSet RenderSystem::createDescriptorFor(const RenderModel &model, cons
auto info = &bufferInfo.emplace_back();
descriptorWrite.pBufferInfo = info;
info->buffer = m_renderer.dummyBuffer;
info->range = 655360;
auto useUniformBuffer = [&info](UniformBuffer &buffer) {
info->buffer = buffer.buffer;
info->range = buffer.size;
};
if (binding.stageFlags == VK_SHADER_STAGE_VERTEX_BIT && z < 4) {
auto name = pipeline.vertexShader.scalar_parameters[z].name;
qInfo() << "Requesting" << name << "at" << j;
if (strcmp(name, "g_CameraParameter") == 0) {
useUniformBuffer(g_CameraParameter);
} else if (strcmp(name, "g_JointMatrixArray") == 0) {
useUniformBuffer(g_JointMatrixArray);
} else if (strcmp(name, "g_InstanceParameter") == 0) {
useUniformBuffer(g_InstanceParameter);
} else if (strcmp(name, "g_ModelParameter") == 0) {
useUniformBuffer(g_ModelParameter);
} else {
qInfo() << "Unknown resource:" << name;
info->buffer = m_renderer.dummyBuffer;
info->range = 655360;
}
z++;
} else if (binding.stageFlags == VK_SHADER_STAGE_FRAGMENT_BIT && j == 0) {
// TODO: temporary hack
useUniformBuffer(g_MaterialParameter);
} else {
// placeholder buffer so it at least doesn't crash
info->buffer = m_renderer.dummyBuffer;
info->range = 655360;
}
} break;
}
}
@ -600,4 +741,43 @@ VkDescriptorSet RenderSystem::createDescriptorFor(const RenderModel &model, cons
vkUpdateDescriptorSets(m_renderer.device, writes.size(), writes.data(), 0, nullptr);
return set;
}
}
RenderSystem::UniformBuffer RenderSystem::createUniformBuffer(size_t size)
{
UniformBuffer uniformBuffer{};
uniformBuffer.size = size;
VkBufferCreateInfo bufferInfo = {};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size;
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
vkCreateBuffer(m_renderer.device, &bufferInfo, nullptr, &uniformBuffer.buffer);
// allocate staging memory
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(m_renderer.device, uniformBuffer.buffer, &memRequirements);
VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex =
m_renderer.findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
vkAllocateMemory(m_renderer.device, &allocInfo, nullptr, &uniformBuffer.memory);
vkBindBufferMemory(m_renderer.device, uniformBuffer.buffer, uniformBuffer.memory, 0);
return uniformBuffer;
}
void RenderSystem::copyDataToUniform(RenderSystem::UniformBuffer &uniformBuffer, void *data, size_t size)
{
// copy to staging buffer
void *mapped_data;
vkMapMemory(m_renderer.device, uniformBuffer.memory, 0, size, 0, &mapped_data);
memcpy(mapped_data, data, size);
vkUnmapMemory(m_renderer.device, uniformBuffer.memory);
}