1
Fork 0
mirror of https://github.com/redstrate/Novus.git synced 2025-04-24 13:07:44 +00:00

Begin working on bone support for the new renderer

Doesn't work completely yet (not sure why) but for basic items it works.
This commit is contained in:
Joshua Goins 2024-04-21 18:49:48 -04:00
parent e34daadbcd
commit dcb54cf4e3
3 changed files with 100 additions and 64 deletions

View file

@ -209,6 +209,7 @@ void MDLPart::reloadBoneData()
for (uint32_t i = 0; i < model.model.num_affected_bones; i++) { for (uint32_t i = 0; i < model.model.num_affected_bones; i++) {
const int originalBoneId = boneMapping[i]; const int originalBoneId = boneMapping[i];
qInfo() << "Remapped" << originalBoneId << "to" << i;
model.boneData[i] = boneData[originalBoneId].localTransform * deformBones[i] * boneData[originalBoneId].inversePose; model.boneData[i] = boneData[originalBoneId].localTransform * deformBones[i] * boneData[originalBoneId].inversePose;
} }
} }

View file

@ -37,24 +37,6 @@ public:
Texture &getCompositeTexture() override; Texture &getCompositeTexture() override;
private: private:
void beginPass(uint32_t imageIndex, VkCommandBuffer commandBuffer, std::string_view passName);
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);
void createImageResources();
physis_SHPK directionalLightningShpk;
physis_SHPK createViewPositionShpk;
struct RenderModel {
physis_SHPK shpk;
::DrawObject *internal_model = nullptr;
};
std::vector<RenderModel> m_renderModels;
struct RequestedBinding { struct RequestedBinding {
VkDescriptorType type; VkDescriptorType type;
VkShaderStageFlags stageFlags; VkShaderStageFlags stageFlags;
@ -76,16 +58,34 @@ private:
physis_Shader vertexShader, pixelShader; physis_Shader vertexShader, pixelShader;
}; };
void beginPass(uint32_t imageIndex, VkCommandBuffer commandBuffer, std::string_view passName);
void endPass(VkCommandBuffer commandBuffer, std::string_view passName);
CachedPipeline &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);
void createImageResources();
physis_SHPK directionalLightningShpk;
physis_SHPK createViewPositionShpk;
struct RenderModel {
physis_SHPK shpk;
::DrawObject *internal_model = nullptr;
};
std::vector<RenderModel> m_renderModels;
// combined vertex + pixel code length // combined vertex + pixel code length
std::unordered_map<uint32_t, CachedPipeline> m_cachedPipelines; std::unordered_map<uint32_t, CachedPipeline> m_cachedPipelines;
Device &m_device; Device &m_device;
GameData *m_data = nullptr; GameData *m_data = nullptr;
VkDescriptorSet createDescriptorFor(const CachedPipeline &cachedPipeline, int i); VkDescriptorSet createDescriptorFor(const RenderModel *object, const CachedPipeline &cachedPipeline, int i);
void bindDescriptorSets(VkCommandBuffer commandBuffer, CachedPipeline &pipeline, const RenderModel *object);
Buffer g_CameraParameter; Buffer g_CameraParameter;
Buffer g_JointMatrixArray;
Buffer g_InstanceParameter; Buffer g_InstanceParameter;
Buffer g_ModelParameter; Buffer g_ModelParameter;
Buffer g_MaterialParameter; Buffer g_MaterialParameter;

View file

@ -73,16 +73,6 @@ GameRenderer::GameRenderer(Device &device, GameData *data)
g_CameraParameter = m_device.createBuffer(sizeof(CameraParameter), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); g_CameraParameter = m_device.createBuffer(sizeof(CameraParameter), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
} }
// joint matrix data
{
g_JointMatrixArray = m_device.createBuffer(sizeof(JointMatrixArray), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
JointMatrixArray jointMatrixArray{};
for (int i = 0; i < 64; i++) {
jointMatrixArray.g_JointMatrixArray[i] = glm::mat3x4(1.0f);
}
m_device.copyToBuffer(g_JointMatrixArray, &jointMatrixArray, sizeof(JointMatrixArray));
}
// instance data // instance data
{ {
g_InstanceParameter = m_device.createBuffer(sizeof(InstanceParameter), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); g_InstanceParameter = m_device.createBuffer(sizeof(InstanceParameter), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
@ -152,7 +142,7 @@ void GameRenderer::addDrawObject(const DrawObject &drawObject)
m_renderModels.push_back(model); m_renderModels.push_back(model);
} }
void GameRenderer::render(VkCommandBuffer commandBuffer, uint32_t imageIndex, Camera &camera, const std::vector<DrawObject> &) void GameRenderer::render(VkCommandBuffer commandBuffer, uint32_t imageIndex, Camera &camera, const std::vector<DrawObject> &models)
{ {
// TODO: this shouldn't be here // TODO: this shouldn't be here
CameraParameter cameraParameter{}; CameraParameter cameraParameter{};
@ -180,7 +170,42 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, uint32_t imageIndex, Ca
if (pass == "PASS_G_OPAQUE" || pass == "PASS_Z_OPAQUE") { if (pass == "PASS_G_OPAQUE" || pass == "PASS_Z_OPAQUE") {
beginPass(imageIndex, commandBuffer, pass); beginPass(imageIndex, commandBuffer, pass);
for (auto &model : m_renderModels) { for (auto &model : models) {
std::optional<GameRenderer::RenderModel> renderModel;
// FIXME: this is terrible
auto it = std::find_if(m_renderModels.begin(), m_renderModels.end(), [&model](const RenderModel &a_model) {
return model.model.p_ptr == a_model.internal_model->model.p_ptr;
});
if (it != m_renderModels.end()) {
renderModel = *it;
}
if (!renderModel.has_value()) {
continue;
}
// copy bone data
{
const size_t bufferSize = sizeof(glm::mat3x4) * 64;
void *mapped_data = nullptr;
vkMapMemory(m_device.device, model.boneInfoBuffer.memory, 0, bufferSize, 0, &mapped_data);
std::vector<glm::mat3x4> newBoneData(model.boneData.size());
for (int i = 0; i < 64; i++) {
newBoneData[i] = model.boneData[i];
}
memcpy(mapped_data, newBoneData.data(), bufferSize);
VkMappedMemoryRange range = {};
range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
range.memory = model.boneInfoBuffer.memory;
range.size = bufferSize;
vkFlushMappedMemoryRanges(m_device.device, 1, &range);
vkUnmapMemory(m_device.device, model.boneInfoBuffer.memory);
}
std::vector<uint32_t> systemKeys; std::vector<uint32_t> systemKeys;
std::vector<uint32_t> sceneKeys = { std::vector<uint32_t> sceneKeys = {
physis_shpk_crc("TransformViewSkin"), physis_shpk_crc("TransformViewSkin"),
@ -190,11 +215,11 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, uint32_t imageIndex, Ca
physis_shpk_crc("ApplyDitherClipOff"), physis_shpk_crc("ApplyDitherClipOff"),
}; };
std::vector<uint32_t> materialKeys; std::vector<uint32_t> materialKeys;
for (int j = 0; j < model.shpk.num_material_keys; j++) { for (int j = 0; j < renderModel->shpk.num_material_keys; j++) {
auto value = model.shpk.material_keys[j].default_value; auto value = renderModel->shpk.material_keys[j].default_value;
// Replace MODE_DEFAULT with MODE_SIMPLE for now // Replace MODE_DEFAULT with MODE_SIMPLE for now
if (value != 0x5CC605B5) { if (value != 0x5CC605B5) {
materialKeys.push_back(model.shpk.material_keys[j].default_value); materialKeys.push_back(renderModel->shpk.material_keys[j].default_value);
} else { } else {
materialKeys.push_back(0x22A4AABF); materialKeys.push_back(0x22A4AABF);
} }
@ -209,7 +234,7 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, uint32_t imageIndex, Ca
materialKeys.size(), materialKeys.size(),
subviewKeys.data(), subviewKeys.data(),
subviewKeys.size()); subviewKeys.size());
const physis_SHPKNode node = physis_shpk_get_node(&model.shpk, selector); const physis_SHPKNode node = physis_shpk_get_node(&renderModel->shpk, selector);
// check if invalid // check if invalid
if (node.pass_count == 0) { if (node.pass_count == 0) {
@ -224,12 +249,13 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, uint32_t imageIndex, Ca
const uint32_t vertexShaderIndice = currentPass.vertex_shader; const uint32_t vertexShaderIndice = currentPass.vertex_shader;
const uint32_t pixelShaderIndice = currentPass.pixel_shader; const uint32_t pixelShaderIndice = currentPass.pixel_shader;
physis_Shader vertexShader = model.shpk.vertex_shaders[vertexShaderIndice]; physis_Shader vertexShader = renderModel->shpk.vertex_shaders[vertexShaderIndice];
physis_Shader pixelShader = model.shpk.pixel_shaders[pixelShaderIndice]; physis_Shader pixelShader = renderModel->shpk.pixel_shaders[pixelShaderIndice];
bindPipeline(commandBuffer, pass, vertexShader, pixelShader); auto &pipeline = bindPipeline(commandBuffer, pass, vertexShader, pixelShader);
bindDescriptorSets(commandBuffer, pipeline, &renderModel.value());
for (const auto &part : model.internal_model->parts) { for (const auto &part : renderModel->internal_model->parts) {
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &part.vertexBuffer.buffer, offsets); vkCmdBindVertexBuffers(commandBuffer, 0, 1, &part.vertexBuffer.buffer, offsets);
vkCmdBindIndexBuffer(commandBuffer, part.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdBindIndexBuffer(commandBuffer, part.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16);
@ -277,7 +303,8 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, uint32_t imageIndex, Ca
physis_Shader vertexShader = createViewPositionShpk.vertex_shaders[vertexShaderIndice]; physis_Shader vertexShader = createViewPositionShpk.vertex_shaders[vertexShaderIndice];
physis_Shader pixelShader = createViewPositionShpk.pixel_shaders[pixelShaderIndice]; physis_Shader pixelShader = createViewPositionShpk.pixel_shaders[pixelShaderIndice];
bindPipeline(commandBuffer, "PASS_LIGHTING_OPAQUE_VIEWPOSITION", vertexShader, pixelShader); auto &pipeline = bindPipeline(commandBuffer, "PASS_LIGHTING_OPAQUE_VIEWPOSITION", vertexShader, pixelShader);
bindDescriptorSets(commandBuffer, pipeline, nullptr);
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &m_planeVertexBuffer.buffer, offsets); vkCmdBindVertexBuffers(commandBuffer, 0, 1, &m_planeVertexBuffer.buffer, offsets);
@ -328,7 +355,8 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, uint32_t imageIndex, Ca
physis_Shader vertexShader = directionalLightningShpk.vertex_shaders[vertexShaderIndice]; physis_Shader vertexShader = directionalLightningShpk.vertex_shaders[vertexShaderIndice];
physis_Shader pixelShader = directionalLightningShpk.pixel_shaders[pixelShaderIndice]; physis_Shader pixelShader = directionalLightningShpk.pixel_shaders[pixelShaderIndice];
bindPipeline(commandBuffer, pass, vertexShader, pixelShader); auto &pipeline = bindPipeline(commandBuffer, pass, vertexShader, pixelShader);
bindDescriptorSets(commandBuffer, pipeline, nullptr);
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &m_planeVertexBuffer.buffer, offsets); vkCmdBindVertexBuffers(commandBuffer, 0, 1, &m_planeVertexBuffer.buffer, offsets);
@ -499,7 +527,8 @@ void GameRenderer::endPass(VkCommandBuffer commandBuffer, std::string_view passN
vkCmdEndRendering(commandBuffer); vkCmdEndRendering(commandBuffer);
} }
void GameRenderer::bindPipeline(VkCommandBuffer commandBuffer, std::string_view passName, physis_Shader &vertexShader, physis_Shader &pixelShader) GameRenderer::CachedPipeline &
GameRenderer::bindPipeline(VkCommandBuffer commandBuffer, std::string_view passName, physis_Shader &vertexShader, physis_Shader &pixelShader)
{ {
const uint32_t hash = vertexShader.len + pixelShader.len + physis_shpk_crc(passName.data()); const uint32_t hash = vertexShader.len + pixelShader.len + physis_shpk_crc(passName.data());
if (!m_cachedPipelines.contains(hash)) { if (!m_cachedPipelines.contains(hash)) {
@ -789,23 +818,7 @@ void GameRenderer::bindPipeline(VkCommandBuffer commandBuffer, std::string_view
} }
auto &pipeline = m_cachedPipelines[hash]; auto &pipeline = m_cachedPipelines[hash];
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline); // TODO: return CachedPipeline& vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline);
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++;
}
VkViewport viewport = {}; VkViewport viewport = {};
viewport.width = m_device.swapChain->extent.width; viewport.width = m_device.swapChain->extent.width;
@ -817,6 +830,8 @@ void GameRenderer::bindPipeline(VkCommandBuffer commandBuffer, std::string_view
vkCmdSetViewport(commandBuffer, 0, 1, &viewport); vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor); vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
return pipeline;
} }
VkShaderModule GameRenderer::convertShaderModule(const physis_Shader &shader, spv::ExecutionModel executionModel) VkShaderModule GameRenderer::convertShaderModule(const physis_Shader &shader, spv::ExecutionModel executionModel)
@ -888,7 +903,7 @@ spirv_cross::CompilerGLSL GameRenderer::getShaderModuleResources(const physis_Sh
return spirv_cross::CompilerGLSL(result.code.data(), result.code.dwords()); return spirv_cross::CompilerGLSL(result.code.data(), result.code.dwords());
} }
VkDescriptorSet GameRenderer::createDescriptorFor(const CachedPipeline &pipeline, int i) VkDescriptorSet GameRenderer::createDescriptorFor(const RenderModel *object, const CachedPipeline &pipeline, int i)
{ {
VkDescriptorSet set; VkDescriptorSet set;
@ -968,18 +983,19 @@ VkDescriptorSet GameRenderer::createDescriptorFor(const CachedPipeline &pipeline
auto info = &bufferInfo.emplace_back(); auto info = &bufferInfo.emplace_back();
descriptorWrite.pBufferInfo = info; descriptorWrite.pBufferInfo = info;
auto useUniformBuffer = [&info](Buffer &buffer) { auto useUniformBuffer = [&info](const Buffer &buffer) {
info->buffer = buffer.buffer; info->buffer = buffer.buffer;
info->range = buffer.size; info->range = buffer.size;
}; };
auto bindBuffer = [this, &useUniformBuffer, &info, j](const char *name) { auto bindBuffer = [this, &useUniformBuffer, &info, j, &object](const char *name) {
qInfo() << "Requesting" << name << "at" << j; qInfo() << "Requesting" << name << "at" << j;
if (strcmp(name, "g_CameraParameter") == 0) { if (strcmp(name, "g_CameraParameter") == 0) {
useUniformBuffer(g_CameraParameter); useUniformBuffer(g_CameraParameter);
} else if (strcmp(name, "g_JointMatrixArray") == 0) { } else if (strcmp(name, "g_JointMatrixArray") == 0) {
useUniformBuffer(g_JointMatrixArray); Q_ASSERT(object != nullptr);
useUniformBuffer(object->internal_model->boneInfoBuffer);
} else if (strcmp(name, "g_InstanceParameter") == 0) { } else if (strcmp(name, "g_InstanceParameter") == 0) {
useUniformBuffer(g_InstanceParameter); useUniformBuffer(g_InstanceParameter);
} else if (strcmp(name, "g_ModelParameter") == 0) { } else if (strcmp(name, "g_ModelParameter") == 0) {
@ -1055,3 +1071,22 @@ Texture &GameRenderer::getCompositeTexture()
{ {
return m_compositeBuffer; return m_compositeBuffer;
} }
void GameRenderer::bindDescriptorSets(VkCommandBuffer commandBuffer, GameRenderer::CachedPipeline &pipeline, const RenderModel *object)
{
int i = 0;
for (auto setLayout : pipeline.setLayouts) {
if (!pipeline.cachedDescriptors.count(i)) {
if (auto descriptor = createDescriptorFor(object, 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++;
}
}