Unified Vertex Data.
This commit is contained in:
parent
a87da63c98
commit
7bdf76c202
|
|
@ -13,8 +13,6 @@ add_executable(model_render model_render.cpp
|
||||||
model_loader.cpp
|
model_loader.cpp
|
||||||
model_loader.h
|
model_loader.h
|
||||||
)
|
)
|
||||||
add_shader(model_render shader/model.vert.glsl)
|
|
||||||
add_shader(model_render shader/model.frag.glsl)
|
|
||||||
add_shader(model_render shader/model.vs.hlsl)
|
add_shader(model_render shader/model.vs.hlsl)
|
||||||
add_shader(model_render shader/model.ps.hlsl)
|
add_shader(model_render shader/model.ps.hlsl)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -291,9 +291,7 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
// TODO: Support scenes
|
// TODO: Support scenes
|
||||||
|
|
||||||
eastl::vector<vec4> vertexPositions;
|
eastl::vector<vec4> vertexPositions;
|
||||||
eastl::vector<vec4> normalVectors;
|
eastl::vector<VertexData> vertexData;
|
||||||
eastl::vector<vec2> texCoord0;
|
|
||||||
eastl::vector<vec4> color0;
|
|
||||||
eastl::vector<u32> indices;
|
eastl::vector<u32> indices;
|
||||||
eastl::vector<MeshPrimitive> meshPrimitives;
|
eastl::vector<MeshPrimitive> meshPrimitives;
|
||||||
meshPrimitives.reserve(model.meshes.size());
|
meshPrimitives.reserve(model.meshes.size());
|
||||||
|
|
@ -303,9 +301,6 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
meshPrimRanges.reserve(model.meshes.size());
|
meshPrimRanges.reserve(model.meshes.size());
|
||||||
|
|
||||||
u32 vertexOffset = 0;
|
u32 vertexOffset = 0;
|
||||||
u32 normalOffset = 0;
|
|
||||||
u32 texCoord0Offset = 0;
|
|
||||||
u32 color0Offset = 0;
|
|
||||||
u32 indexOffset = 0;
|
u32 indexOffset = 0;
|
||||||
|
|
||||||
for (auto &mesh : model.meshes)
|
for (auto &mesh : model.meshes)
|
||||||
|
|
@ -315,9 +310,6 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
{
|
{
|
||||||
u32 vertexCount = 0;
|
u32 vertexCount = 0;
|
||||||
u32 indexCount = 0;
|
u32 indexCount = 0;
|
||||||
u32 normalCount = 0;
|
|
||||||
u32 texCoord0Count = 0;
|
|
||||||
u32 color0Count = 0;
|
|
||||||
|
|
||||||
#pragma region Position
|
#pragma region Position
|
||||||
assert(prim.attributes.contains(APosition));
|
assert(prim.attributes.contains(APosition));
|
||||||
|
|
@ -357,7 +349,10 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
#pragma region Normal
|
|
||||||
|
vertexData.resize(vertexPositions.size());
|
||||||
|
|
||||||
|
#pragma region Normal
|
||||||
// Normal Coords
|
// Normal Coords
|
||||||
if (prim.attributes.contains(ANormal))
|
if (prim.attributes.contains(ANormal))
|
||||||
{
|
{
|
||||||
|
|
@ -369,20 +364,25 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
tinygltf::Buffer *normBuffer = &model.buffers[normBufferView->buffer];
|
tinygltf::Buffer *normBuffer = &model.buffers[normBufferView->buffer];
|
||||||
usize byteOffset = (normAccessor->byteOffset + normBufferView->byteOffset);
|
usize byteOffset = (normAccessor->byteOffset + normBufferView->byteOffset);
|
||||||
|
|
||||||
normalCount = Cast<i32>(normAccessor->count);
|
|
||||||
normalVectors.reserve(vertexPositions.size());
|
|
||||||
|
|
||||||
if (normAccessor->type == TINYGLTF_TYPE_VEC4)
|
if (normAccessor->type == TINYGLTF_TYPE_VEC4)
|
||||||
{
|
{
|
||||||
vec4 *data = Recast<vec4 *>(normBuffer->data.data() + byteOffset);
|
vec4 *data = Recast<vec4 *>(normBuffer->data.data() + byteOffset);
|
||||||
normalVectors.insert(normalVectors.end(), data, data + vertexCount);
|
|
||||||
|
vec4 *end = data + vertexCount;
|
||||||
|
u32 idx = vertexOffset;
|
||||||
|
vec4 *it = data;
|
||||||
|
while (it != end)
|
||||||
|
{
|
||||||
|
vertexData[idx++].m_Normal = *(it++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (normAccessor->type == TINYGLTF_TYPE_VEC3)
|
else if (normAccessor->type == TINYGLTF_TYPE_VEC3)
|
||||||
{
|
{
|
||||||
vec3 *data = Recast<vec3 *>(normBuffer->data.data() + byteOffset);
|
vec3 *data = Recast<vec3 *>(normBuffer->data.data() + byteOffset);
|
||||||
for (u32 i = 0; i < vertexCount; ++i)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
normalVectors.push_back(vec4(data[i], 1.0f));
|
auto norm = vec4(data[i], 0.0f);
|
||||||
|
vertexData[vertexOffset + i].m_Normal = norm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (normAccessor->type == TINYGLTF_TYPE_VEC2)
|
else if (normAccessor->type == TINYGLTF_TYPE_VEC2)
|
||||||
|
|
@ -390,7 +390,8 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
vec2 *data = Recast<vec2 *>(normBuffer->data.data() + byteOffset);
|
vec2 *data = Recast<vec2 *>(normBuffer->data.data() + byteOffset);
|
||||||
for (u32 i = 0; i < vertexCount; ++i)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
normalVectors.push_back(vec4(data[i], 0.0f, 1.0f));
|
auto norm = vec4(data[i], 0.0f, 0.0f);
|
||||||
|
vertexData[vertexOffset + i].m_Normal = norm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -407,14 +408,17 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
tinygltf::Buffer *uvBuffer = &model.buffers[uvBufferView->buffer];
|
tinygltf::Buffer *uvBuffer = &model.buffers[uvBufferView->buffer];
|
||||||
usize byteOffset = (uvAccessor->byteOffset + uvBufferView->byteOffset);
|
usize byteOffset = (uvAccessor->byteOffset + uvBufferView->byteOffset);
|
||||||
|
|
||||||
texCoord0Count = Cast<i32>(uvAccessor->count);
|
|
||||||
texCoord0.reserve(vertexPositions.size());
|
|
||||||
|
|
||||||
assert(uvAccessor->type == TINYGLTF_TYPE_VEC2 &&
|
assert(uvAccessor->type == TINYGLTF_TYPE_VEC2 &&
|
||||||
uvAccessor->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT);
|
uvAccessor->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT);
|
||||||
{
|
{
|
||||||
vec2 *data = Recast<vec2 *>(uvBuffer->data.data() + byteOffset);
|
vec2 *data = Recast<vec2 *>(uvBuffer->data.data() + byteOffset);
|
||||||
texCoord0.insert(texCoord0.end(), data, data + vertexCount);
|
vec2 *end = data + vertexCount;
|
||||||
|
u32 idx = vertexOffset;
|
||||||
|
vec2 *it = data;
|
||||||
|
while (it != end)
|
||||||
|
{
|
||||||
|
vertexData[idx++].m_TexCoord0 = *(it++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
@ -429,21 +433,25 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
tinygltf::Buffer *colorBuffer = &model.buffers[colorBufferView->buffer];
|
tinygltf::Buffer *colorBuffer = &model.buffers[colorBufferView->buffer];
|
||||||
usize byteOffset = (colorAccessor->byteOffset + colorBufferView->byteOffset);
|
usize byteOffset = (colorAccessor->byteOffset + colorBufferView->byteOffset);
|
||||||
|
|
||||||
color0Count = Cast<i32>(colorAccessor->count);
|
|
||||||
color0.reserve(vertexPositions.size());
|
|
||||||
assert(color0Count == vertexCount);
|
|
||||||
|
|
||||||
if (colorAccessor->type == TINYGLTF_TYPE_VEC4)
|
if (colorAccessor->type == TINYGLTF_TYPE_VEC4)
|
||||||
{
|
{
|
||||||
vec4 *data = Recast<vec4 *>(colorBuffer->data.data() + byteOffset);
|
vec4 *data = Recast<vec4 *>(colorBuffer->data.data() + byteOffset);
|
||||||
color0.insert(color0.end(), data, data + vertexCount);
|
|
||||||
|
vec4 *end = data + vertexCount;
|
||||||
|
u32 idx = vertexOffset;
|
||||||
|
vec4 *it = data;
|
||||||
|
while (it != end)
|
||||||
|
{
|
||||||
|
vertexData[idx++].m_Color0 = *(it++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (colorAccessor->type == TINYGLTF_TYPE_VEC3)
|
else if (colorAccessor->type == TINYGLTF_TYPE_VEC3)
|
||||||
{
|
{
|
||||||
vec3 *data = Recast<vec3 *>(colorBuffer->data.data() + byteOffset);
|
vec3 *data = Recast<vec3 *>(colorBuffer->data.data() + byteOffset);
|
||||||
for (u32 i = 0; i < color0Count; ++i)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
color0.push_back(vec4(data[i], 1.0f));
|
auto color = vec4(data[i], 1.0f);
|
||||||
|
vertexData[vertexOffset + i].m_Color0 = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -492,9 +500,6 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
|
|
||||||
meshPrimitives.push_back({
|
meshPrimitives.push_back({
|
||||||
.m_VertexOffset = vertexOffset,
|
.m_VertexOffset = vertexOffset,
|
||||||
.m_NormalOffset = normalCount > 0 ? Cast<i32>(normalOffset) : -1,
|
|
||||||
.m_TexCoord0Offset = texCoord0Count > 0 ? Cast<i32>(texCoord0Offset) : -1,
|
|
||||||
// TODO: Color offset
|
|
||||||
.m_FirstIndex = indexOffset,
|
.m_FirstIndex = indexOffset,
|
||||||
.m_IndexCount = indexCount,
|
.m_IndexCount = indexCount,
|
||||||
.m_MaterialIdx = prim.material,
|
.m_MaterialIdx = prim.material,
|
||||||
|
|
@ -503,12 +508,6 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
|
|
||||||
vertexOffset += vertexCount;
|
vertexOffset += vertexCount;
|
||||||
indexOffset += indexCount;
|
indexOffset += indexCount;
|
||||||
texCoord0Offset += texCoord0Count;
|
|
||||||
normalOffset += normalCount;
|
|
||||||
color0Offset += color0Count;
|
|
||||||
|
|
||||||
assert(normalVectors.empty() || normalVectors.size() == vertexPositions.size());
|
|
||||||
assert(texCoord0.empty() || texCoord0.size() == vertexPositions.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -576,39 +575,13 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
BufferHandle nodeHandle = m_ResourceManager->Commit(&nodeBuffer);
|
BufferHandle nodeHandle = m_ResourceManager->Commit(&nodeBuffer);
|
||||||
|
|
||||||
#pragma region Staging / Transfer / Uploads
|
#pragma region Staging / Transfer / Uploads
|
||||||
StorageBuffer positionBuffer;
|
BufferHandle positionBufferHandle;
|
||||||
positionBuffer.Init(pDevice, vertexPositions.size() * sizeof vertexPositions[0], false);
|
BufferHandle vertexDataHandle;
|
||||||
BufferHandle positionBufferHandle = m_ResourceManager->Commit(&positionBuffer);
|
|
||||||
|
|
||||||
StorageBuffer normalBuffer;
|
|
||||||
BufferHandle normalBufferHandle;
|
|
||||||
if (!normalVectors.empty())
|
|
||||||
{
|
|
||||||
normalBuffer.Init(pDevice, normalVectors.size() * sizeof normalVectors[0], false);
|
|
||||||
normalBufferHandle = m_ResourceManager->Commit(&normalBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageBuffer texCoord0Buffer;
|
|
||||||
BufferHandle texCoord0BufferHandle;
|
|
||||||
if (!texCoord0.empty())
|
|
||||||
{
|
|
||||||
texCoord0Buffer.Init(pDevice, texCoord0.size() * sizeof texCoord0[0], false);
|
|
||||||
texCoord0BufferHandle = m_ResourceManager->Commit(&texCoord0Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageBuffer color0Buffer;
|
|
||||||
BufferHandle color0Handle;
|
|
||||||
if (!color0.empty())
|
|
||||||
{
|
|
||||||
color0Buffer.Init(pDevice, color0.size() * sizeof color0[0], false);
|
|
||||||
color0Handle = m_ResourceManager->Commit(&color0Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
IndexBuffer indexBuffer;
|
IndexBuffer indexBuffer;
|
||||||
indexBuffer.Init(pDevice, indices.size() * sizeof indices[0]);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
auto uploadBufferData = [cmd = this->m_CommandBuffer, &stagingBuffers, pDevice](const Buffer *buffer, void* data) {
|
auto uploadBufferData = [cmd = this->m_CommandBuffer, &stagingBuffers, pDevice](const Buffer *buffer,
|
||||||
|
const void *data) {
|
||||||
vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = buffer->GetSize()};
|
vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = buffer->GetSize()};
|
||||||
StagingBuffer &stagingBuffer = stagingBuffers.push_back();
|
StagingBuffer &stagingBuffer = stagingBuffers.push_back();
|
||||||
stagingBuffer.Init(pDevice, bufferCopy.size);
|
stagingBuffer.Init(pDevice, bufferCopy.size);
|
||||||
|
|
@ -616,23 +589,17 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
cmd.copyBuffer(stagingBuffer.m_Buffer, buffer->m_Buffer, 1, &bufferCopy);
|
cmd.copyBuffer(stagingBuffer.m_Buffer, buffer->m_Buffer, 1, &bufferCopy);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StorageBuffer positionBuffer;
|
||||||
|
positionBuffer.Init(pDevice, vertexPositions.size() * sizeof vertexPositions[0], false);
|
||||||
|
positionBufferHandle = m_ResourceManager->Commit(&positionBuffer);
|
||||||
uploadBufferData(&positionBuffer, vertexPositions.data());
|
uploadBufferData(&positionBuffer, vertexPositions.data());
|
||||||
|
|
||||||
if (normalBuffer.IsValid())
|
StorageBuffer vertexDataBuffer;
|
||||||
{
|
vertexDataBuffer.Init(pDevice, vertexData.size() * sizeof vertexData[0], false);
|
||||||
uploadBufferData(&normalBuffer, normalVectors.data());
|
vertexDataHandle = m_ResourceManager->Commit(&vertexDataBuffer);
|
||||||
}
|
uploadBufferData(&vertexDataBuffer, vertexData.data());
|
||||||
|
|
||||||
if (texCoord0Buffer.IsValid())
|
|
||||||
{
|
|
||||||
uploadBufferData(&texCoord0Buffer, texCoord0.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (color0Buffer.IsValid())
|
|
||||||
{
|
|
||||||
uploadBufferData(&color0Buffer, color0.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
indexBuffer.Init(pDevice, indices.size() * sizeof indices[0]);
|
||||||
uploadBufferData(&indexBuffer, indices.data());
|
uploadBufferData(&indexBuffer, indices.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -662,24 +629,23 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
||||||
buffer.Destroy(pDevice);
|
buffer.Destroy(pDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Model::ModelHandles handles = {
|
||||||
|
.m_VertexPositionHandle = positionBufferHandle,
|
||||||
|
.m_VertexDataHandle = vertexDataHandle,
|
||||||
|
.m_MaterialsHandle = materialsHandle,
|
||||||
|
.m_NodeHandle = nodeHandle,
|
||||||
|
};
|
||||||
|
|
||||||
return Model{m_ResourceManager, std::move(textureHandles), std::move(nodes),
|
return Model{m_ResourceManager, std::move(textureHandles), std::move(nodes),
|
||||||
materialsHandle, positionBufferHandle, normalBufferHandle,
|
handles, indexBuffer, meshPrimitives, };
|
||||||
texCoord0BufferHandle, color0Handle, indexBuffer, meshPrimitives, nodeHandle};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Model::Model(GpuResourceManager *resourceManager, eastl::vector<TextureHandle> &&textureHandles, Nodes &&nodes,
|
Model::Model(GpuResourceManager *resourceManager, eastl::vector<TextureHandle> &&textureHandles, Nodes &&nodes,
|
||||||
BufferHandle materialsHandle, BufferHandle vertexPosHandle, BufferHandle normalHandle,
|
const ModelHandles &handles, const IndexBuffer &indexBuffer, const eastl::vector<MeshPrimitive> &meshPrimitives)
|
||||||
BufferHandle uv0Handle, BufferHandle vertexColor, const IndexBuffer &indexBuffer,
|
|
||||||
const eastl::vector<MeshPrimitive> &meshPrimitives, BufferHandle nodeHandle)
|
|
||||||
: m_ResourceManager(resourceManager)
|
: m_ResourceManager(resourceManager)
|
||||||
, m_TextureHandles(std::move(textureHandles))
|
, m_TextureHandles(std::move(textureHandles))
|
||||||
, m_Nodes(std::move(nodes))
|
, m_Nodes(std::move(nodes))
|
||||||
, m_MaterialsHandle(materialsHandle)
|
, m_Handles(handles)
|
||||||
, m_VertexPositionHandle(vertexPosHandle)
|
|
||||||
, m_NormalHandle(normalHandle)
|
|
||||||
, m_TexCoord0Handle(uv0Handle)
|
|
||||||
, m_VertexColorHandle(vertexColor)
|
|
||||||
, m_NodeHandle(nodeHandle)
|
|
||||||
, m_IndexBuffer(indexBuffer)
|
, m_IndexBuffer(indexBuffer)
|
||||||
, m_MeshPrimitives(meshPrimitives)
|
, m_MeshPrimitives(meshPrimitives)
|
||||||
{
|
{
|
||||||
|
|
@ -688,12 +654,7 @@ Model::Model(GpuResourceManager *resourceManager, eastl::vector<TextureHandle> &
|
||||||
Model::Model(Model &&other) noexcept
|
Model::Model(Model &&other) noexcept
|
||||||
: m_ResourceManager(Take(other.m_ResourceManager))
|
: m_ResourceManager(Take(other.m_ResourceManager))
|
||||||
, m_TextureHandles(std::move(other.m_TextureHandles))
|
, m_TextureHandles(std::move(other.m_TextureHandles))
|
||||||
, m_MaterialsHandle(other.m_MaterialsHandle)
|
, m_Handles(other.m_Handles)
|
||||||
, m_VertexPositionHandle(other.m_VertexPositionHandle)
|
|
||||||
, m_NormalHandle(other.m_NormalHandle)
|
|
||||||
, m_TexCoord0Handle(other.m_TexCoord0Handle)
|
|
||||||
, m_VertexColorHandle(other.m_VertexColorHandle)
|
|
||||||
, m_NodeHandle(other.m_NodeHandle)
|
|
||||||
, m_IndexBuffer(other.m_IndexBuffer)
|
, m_IndexBuffer(other.m_IndexBuffer)
|
||||||
, m_MeshPrimitives(std::move(other.m_MeshPrimitives))
|
, m_MeshPrimitives(std::move(other.m_MeshPrimitives))
|
||||||
{
|
{
|
||||||
|
|
@ -706,17 +667,121 @@ Model::operator=(Model &&other) noexcept
|
||||||
return *this;
|
return *this;
|
||||||
m_ResourceManager = Take(other.m_ResourceManager);
|
m_ResourceManager = Take(other.m_ResourceManager);
|
||||||
m_TextureHandles = std::move(other.m_TextureHandles);
|
m_TextureHandles = std::move(other.m_TextureHandles);
|
||||||
m_MaterialsHandle = other.m_MaterialsHandle;
|
m_Handles = other.m_Handles;
|
||||||
m_VertexPositionHandle = other.m_VertexPositionHandle;
|
|
||||||
m_NormalHandle = other.m_NormalHandle;
|
|
||||||
m_TexCoord0Handle = other.m_TexCoord0Handle;
|
|
||||||
m_VertexColorHandle = other.m_VertexColorHandle;
|
|
||||||
m_NodeHandle = other.m_NodeHandle;
|
|
||||||
m_IndexBuffer = other.m_IndexBuffer;
|
m_IndexBuffer = other.m_IndexBuffer;
|
||||||
m_MeshPrimitives = std::move(other.m_MeshPrimitives);
|
m_MeshPrimitives = std::move(other.m_MeshPrimitives);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32
|
||||||
|
Nodes::Add(const mat4 &transform, const i32 parent)
|
||||||
|
{
|
||||||
|
m_Dirty = true;
|
||||||
|
const u32 index = Count();
|
||||||
|
m_Transforms.push_back(transform);
|
||||||
|
m_GlobalTransforms.push_back(transform);
|
||||||
|
const u32 parentVal = (parent < 0 ? ROOT_BIT : parent & PARENT_MASK) | DIRTY_BIT;
|
||||||
|
m_Parents_.push_back(parentVal);
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mat4 &
|
||||||
|
Nodes::Get(const u32 index) const
|
||||||
|
{
|
||||||
|
return m_Transforms[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Nodes::Set(const u32 index, const mat4 &transform)
|
||||||
|
{
|
||||||
|
m_Dirty = true;
|
||||||
|
m_Transforms[index] = transform;
|
||||||
|
m_Parents_[index] |= DIRTY_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mat4 &
|
||||||
|
Nodes::operator[](const u32 index) const
|
||||||
|
{
|
||||||
|
return m_Transforms[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 &
|
||||||
|
Nodes::operator[](const u32 index)
|
||||||
|
{
|
||||||
|
m_Dirty = true;
|
||||||
|
m_Parents_[index] |= DIRTY_BIT;
|
||||||
|
return m_Transforms[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
u32
|
||||||
|
Nodes::Count() const
|
||||||
|
{
|
||||||
|
return Cast<u32>(m_Transforms.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
usize
|
||||||
|
Nodes::GetGlobalTransformByteSize() const
|
||||||
|
{
|
||||||
|
return m_GlobalTransforms.size() * sizeof m_GlobalTransforms[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const mat4 *
|
||||||
|
Nodes::GetGlobalTransformPtr() const
|
||||||
|
{
|
||||||
|
return m_GlobalTransforms.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Nodes::Update()
|
||||||
|
{
|
||||||
|
if (!m_Dirty)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto transformIter = m_Transforms.begin();
|
||||||
|
auto globalTransformIter = m_GlobalTransforms.begin();
|
||||||
|
auto parentIter = m_Parents_.begin();
|
||||||
|
const auto parentEnd = m_Parents_.end();
|
||||||
|
|
||||||
|
while (parentIter != parentEnd)
|
||||||
|
{
|
||||||
|
const bool isRoot = *parentIter & ROOT_BIT;
|
||||||
|
const bool isDirty = *parentIter & DIRTY_BIT;
|
||||||
|
|
||||||
|
if (isRoot)
|
||||||
|
{
|
||||||
|
if (isDirty)
|
||||||
|
{
|
||||||
|
// Copy-update if the root is dirty.
|
||||||
|
*globalTransformIter = *transformIter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const u32 parentIdx = *parentIter & PARENT_MASK;
|
||||||
|
const bool isParentDirty = m_Parents_[parentIdx] & DIRTY_BIT;
|
||||||
|
if (isDirty || isParentDirty)
|
||||||
|
{
|
||||||
|
// Update w.r.t parent if either local or parent transforms updated.
|
||||||
|
*globalTransformIter = m_GlobalTransforms[parentIdx] * *transformIter;
|
||||||
|
m_Parents_[parentIdx] |= DIRTY_BIT; // Set dirty to propagate the update.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++parentIter;
|
||||||
|
++globalTransformIter;
|
||||||
|
++transformIter;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 &parentValue : m_Parents_)
|
||||||
|
{
|
||||||
|
parentValue &= ~DIRTY_BIT; // Unset dirty.
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Dirty = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const mat4 &
|
const mat4 &
|
||||||
Model::GetModelTransform() const
|
Model::GetModelTransform() const
|
||||||
{
|
{
|
||||||
|
|
@ -735,16 +800,16 @@ Model::~Model()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_IndexBuffer.Destroy(m_ResourceManager->m_Device);
|
m_IndexBuffer.Destroy(m_ResourceManager->m_Device);
|
||||||
m_ResourceManager->Release(m_NodeHandle);
|
|
||||||
m_ResourceManager->Release(m_VertexColorHandle);
|
m_ResourceManager->Release(m_Handles.m_VertexDataHandle);
|
||||||
m_ResourceManager->Release(m_VertexPositionHandle);
|
m_ResourceManager->Release(m_Handles.m_NodeHandle);
|
||||||
m_ResourceManager->Release(m_NormalHandle);
|
m_ResourceManager->Release(m_Handles.m_VertexPositionHandle);
|
||||||
m_ResourceManager->Release(m_TexCoord0Handle);
|
m_ResourceManager->Release(m_Handles.m_MaterialsHandle);
|
||||||
|
|
||||||
for (const TextureHandle &handle : m_TextureHandles)
|
for (const TextureHandle &handle : m_TextureHandles)
|
||||||
{
|
{
|
||||||
m_ResourceManager->Release(handle);
|
m_ResourceManager->Release(handle);
|
||||||
}
|
}
|
||||||
m_ResourceManager->Release(m_MaterialsHandle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -752,7 +817,7 @@ Model::Update()
|
||||||
{
|
{
|
||||||
if (m_Nodes.Update())
|
if (m_Nodes.Update())
|
||||||
{
|
{
|
||||||
m_ResourceManager->Write(m_NodeHandle, 0, m_Nodes.GetGlobalTransformByteSize(),
|
m_ResourceManager->Write(m_Handles.m_NodeHandle, 0, m_Nodes.GetGlobalTransformByteSize(),
|
||||||
m_Nodes.GetGlobalTransformPtr());
|
m_Nodes.GetGlobalTransformPtr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -782,5 +847,31 @@ ModelLoader::ModelLoader(GpuResourceManager *resourceManager, vk::Queue transfer
|
||||||
|
|
||||||
ModelLoader::~ModelLoader()
|
ModelLoader::~ModelLoader()
|
||||||
{
|
{
|
||||||
|
if (m_ResourceManager)
|
||||||
|
{
|
||||||
m_ResourceManager->m_Device->m_Device.destroy(m_CommandPool, nullptr);
|
m_ResourceManager->m_Device->m_Device.destroy(m_CommandPool, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelLoader::ModelLoader(ModelLoader &&other) noexcept: m_ResourceManager(Take(other.m_ResourceManager)),
|
||||||
|
m_CommandPool(other.m_CommandPool),
|
||||||
|
m_CommandBuffer(other.m_CommandBuffer),
|
||||||
|
m_TransferQueue(other.m_TransferQueue),
|
||||||
|
m_TransferQueueIndex(other.m_TransferQueueIndex),
|
||||||
|
m_GraphicsQueueIndex(other.m_GraphicsQueueIndex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelLoader &
|
||||||
|
ModelLoader::operator=(ModelLoader &&other) noexcept
|
||||||
|
{
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
m_ResourceManager = Take(other.m_ResourceManager);
|
||||||
|
m_CommandPool = other.m_CommandPool;
|
||||||
|
m_CommandBuffer = other.m_CommandBuffer;
|
||||||
|
m_TransferQueue = other.m_TransferQueue;
|
||||||
|
m_TransferQueueIndex = other.m_TransferQueueIndex;
|
||||||
|
m_GraphicsQueueIndex = other.m_GraphicsQueueIndex;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -21,8 +21,6 @@ constexpr auto GLTF_BINARY_FILE_EXTENSION = ".glb";
|
||||||
struct MeshPrimitive
|
struct MeshPrimitive
|
||||||
{
|
{
|
||||||
u32 m_VertexOffset;
|
u32 m_VertexOffset;
|
||||||
i32 m_NormalOffset; // <0 for invalid
|
|
||||||
i32 m_TexCoord0Offset; // <0 for invalid
|
|
||||||
u32 m_FirstIndex;
|
u32 m_FirstIndex;
|
||||||
u32 m_IndexCount;
|
u32 m_IndexCount;
|
||||||
i32 m_MaterialIdx; // <0 for invalid
|
i32 m_MaterialIdx; // <0 for invalid
|
||||||
|
|
@ -41,114 +39,18 @@ struct Nodes
|
||||||
constexpr static u32 DIRTY_BIT = 1u << 30;
|
constexpr static u32 DIRTY_BIT = 1u << 30;
|
||||||
constexpr static u32 PARENT_MASK = ~(ROOT_BIT | DIRTY_BIT);
|
constexpr static u32 PARENT_MASK = ~(ROOT_BIT | DIRTY_BIT);
|
||||||
|
|
||||||
u32
|
u32 Add(const mat4 &transform, const i32 parent = -1);
|
||||||
Add(const mat4& transform, const i32 parent = -1)
|
[[nodiscard]] const mat4 &Get(const u32 index) const;
|
||||||
{
|
void Set(const u32 index, const mat4 &transform);
|
||||||
m_Dirty = true;
|
[[nodiscard]] u32 Count() const;
|
||||||
const u32 index = Count();
|
|
||||||
m_Transforms.push_back(transform);
|
|
||||||
m_GlobalTransforms.push_back(transform);
|
|
||||||
const u32 parentVal = (parent < 0 ? ROOT_BIT : parent & PARENT_MASK) | DIRTY_BIT;
|
|
||||||
m_Parents_.push_back(parentVal);
|
|
||||||
|
|
||||||
return index;
|
[[nodiscard]] const mat4 &operator[](const u32 index) const;
|
||||||
}
|
[[nodiscard]] mat4 &operator[](const u32 index);
|
||||||
|
|
||||||
[[nodiscard]] const mat4 &
|
[[nodiscard]] usize GetGlobalTransformByteSize() const;
|
||||||
Get(const u32 index) const
|
[[nodiscard]] const mat4 *GetGlobalTransformPtr() const;
|
||||||
{
|
|
||||||
return m_Transforms[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
bool Update();
|
||||||
Set(const u32 index, const mat4 &transform)
|
|
||||||
{
|
|
||||||
m_Dirty = true;
|
|
||||||
m_Transforms[index] = transform;
|
|
||||||
m_Parents_[index] |= DIRTY_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] const mat4 &
|
|
||||||
operator[](const u32 index) const
|
|
||||||
{
|
|
||||||
return m_Transforms[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] mat4 &
|
|
||||||
operator[](const u32 index)
|
|
||||||
{
|
|
||||||
m_Dirty = true;
|
|
||||||
m_Parents_[index] |= DIRTY_BIT;
|
|
||||||
return m_Transforms[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] u32
|
|
||||||
Count() const
|
|
||||||
{
|
|
||||||
return Cast<u32>(m_Transforms.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] usize
|
|
||||||
GetGlobalTransformByteSize() const
|
|
||||||
{
|
|
||||||
return m_GlobalTransforms.size() * sizeof m_GlobalTransforms[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] const mat4 *
|
|
||||||
GetGlobalTransformPtr() const
|
|
||||||
{
|
|
||||||
return m_GlobalTransforms.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Update()
|
|
||||||
{
|
|
||||||
if (!m_Dirty)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto transformIter = m_Transforms.begin();
|
|
||||||
auto globalTransformIter = m_GlobalTransforms.begin();
|
|
||||||
auto parentIter = m_Parents_.begin();
|
|
||||||
const auto parentEnd = m_Parents_.end();
|
|
||||||
|
|
||||||
while (parentIter != parentEnd)
|
|
||||||
{
|
|
||||||
const bool isRoot = *parentIter & ROOT_BIT;
|
|
||||||
const bool isDirty = *parentIter & DIRTY_BIT;
|
|
||||||
|
|
||||||
if (isRoot)
|
|
||||||
{
|
|
||||||
if (isDirty)
|
|
||||||
{
|
|
||||||
// Copy-update if the root is dirty.
|
|
||||||
*globalTransformIter = *transformIter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const u32 parentIdx = *parentIter & PARENT_MASK;
|
|
||||||
const bool isParentDirty = m_Parents_[parentIdx] & DIRTY_BIT;
|
|
||||||
if (isDirty || isParentDirty)
|
|
||||||
{
|
|
||||||
// Update w.r.t parent if either local or parent transforms updated.
|
|
||||||
*globalTransformIter = m_GlobalTransforms[parentIdx] * *transformIter;
|
|
||||||
m_Parents_[parentIdx] |= DIRTY_BIT; // Set dirty to propagate the update.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++parentIter;
|
|
||||||
++globalTransformIter;
|
|
||||||
++transformIter;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 &parentValue : m_Parents_)
|
|
||||||
{
|
|
||||||
parentValue &= ~DIRTY_BIT; // Unset dirty.
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Dirty = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Material
|
struct Material
|
||||||
|
|
@ -164,6 +66,14 @@ struct Material
|
||||||
TextureHandle m_EmissionTex; // 04 56
|
TextureHandle m_EmissionTex; // 04 56
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VertexData
|
||||||
|
{
|
||||||
|
vec4 m_Normal;
|
||||||
|
vec2 m_TexCoord0 = vec2{0.0f, 0.0f};
|
||||||
|
vec2 m_TexCoord1 = vec2{0.0f, 0.0f};
|
||||||
|
vec4 m_Color0 = vec4{1.0f, 0.0f, 1.0f, 1.0f};
|
||||||
|
};
|
||||||
|
|
||||||
struct Model
|
struct Model
|
||||||
{
|
{
|
||||||
GpuResourceManager *m_ResourceManager;
|
GpuResourceManager *m_ResourceManager;
|
||||||
|
|
@ -171,12 +81,13 @@ struct Model
|
||||||
eastl::vector<TextureHandle> m_TextureHandles;
|
eastl::vector<TextureHandle> m_TextureHandles;
|
||||||
Nodes m_Nodes;
|
Nodes m_Nodes;
|
||||||
|
|
||||||
BufferHandle m_MaterialsHandle;
|
struct ModelHandles
|
||||||
|
{
|
||||||
BufferHandle m_VertexPositionHandle;
|
BufferHandle m_VertexPositionHandle;
|
||||||
BufferHandle m_NormalHandle;
|
BufferHandle m_VertexDataHandle;
|
||||||
BufferHandle m_TexCoord0Handle;
|
BufferHandle m_MaterialsHandle;
|
||||||
BufferHandle m_VertexColorHandle;
|
|
||||||
BufferHandle m_NodeHandle;
|
BufferHandle m_NodeHandle;
|
||||||
|
} m_Handles;
|
||||||
|
|
||||||
IndexBuffer m_IndexBuffer;
|
IndexBuffer m_IndexBuffer;
|
||||||
eastl::vector<MeshPrimitive> m_MeshPrimitives;
|
eastl::vector<MeshPrimitive> m_MeshPrimitives;
|
||||||
|
|
@ -185,15 +96,15 @@ struct Model
|
||||||
void SetModelTransform(const mat4 &transform);
|
void SetModelTransform(const mat4 &transform);
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
Model(GpuResourceManager *resourceManager, eastl::vector<TextureHandle> &&textureHandles, Nodes&& nodes,
|
Model(GpuResourceManager *resourceManager, eastl::vector<TextureHandle> &&textureHandles, Nodes &&nodes,
|
||||||
BufferHandle materialsHandle, BufferHandle vertexPosHandle, BufferHandle normalHandle, BufferHandle uv0Handle, BufferHandle vertexColor,
|
const ModelHandles& handles, const IndexBuffer &indexBuffer, const eastl::vector<MeshPrimitive> &meshPrimitives);
|
||||||
const IndexBuffer &indexBuffer, const eastl::vector<MeshPrimitive> &meshPrimitives, BufferHandle nodeHandle);
|
~Model();
|
||||||
|
|
||||||
Model(Model &&other) noexcept;
|
Model(Model &&other) noexcept;
|
||||||
Model &operator=(Model &&other) noexcept;
|
Model &operator=(Model &&other) noexcept;
|
||||||
~Model();
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(Model);
|
Model(const Model &) = delete;
|
||||||
|
const Model &operator=(const Model &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModelLoader
|
struct ModelLoader
|
||||||
|
|
@ -205,10 +116,6 @@ struct ModelLoader
|
||||||
u32 m_TransferQueueIndex;
|
u32 m_TransferQueueIndex;
|
||||||
u32 m_GraphicsQueueIndex;
|
u32 m_GraphicsQueueIndex;
|
||||||
|
|
||||||
ModelLoader(GpuResourceManager *resourceManager, vk::Queue transferQueue, u32 transferQueueIndex,
|
|
||||||
u32 graphicsQueueIndex);
|
|
||||||
~ModelLoader();
|
|
||||||
|
|
||||||
TextureHandle LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBuffer,
|
TextureHandle LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBuffer,
|
||||||
tinygltf::Image *image) const;
|
tinygltf::Image *image) const;
|
||||||
Model LoadModel(cstr path, cstr name = nullptr, bool batched = false);
|
Model LoadModel(cstr path, cstr name = nullptr, bool batched = false);
|
||||||
|
|
@ -221,4 +128,13 @@ struct ModelLoader
|
||||||
constexpr static auto AColor0 = "COLOR_0";
|
constexpr static auto AColor0 = "COLOR_0";
|
||||||
constexpr static auto AJoints0 = "JOINTS_0";
|
constexpr static auto AJoints0 = "JOINTS_0";
|
||||||
constexpr static auto AWeights0 = "WEIGHTS_0";
|
constexpr static auto AWeights0 = "WEIGHTS_0";
|
||||||
|
|
||||||
|
ModelLoader(GpuResourceManager *resourceManager, vk::Queue transferQueue, u32 transferQueueIndex,
|
||||||
|
u32 graphicsQueueIndex);
|
||||||
|
~ModelLoader();
|
||||||
|
|
||||||
|
ModelLoader(ModelLoader &&other) noexcept;
|
||||||
|
ModelLoader &operator=(ModelLoader &&other) noexcept;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ModelLoader);
|
||||||
};
|
};
|
||||||
|
|
@ -214,23 +214,6 @@ main(int, char **)
|
||||||
|
|
||||||
Time::Init();
|
Time::Init();
|
||||||
|
|
||||||
struct ModelData
|
|
||||||
{
|
|
||||||
BufferHandle m_VertexBuffer;
|
|
||||||
BufferHandle m_Color;
|
|
||||||
BufferHandle m_UvBuffer;
|
|
||||||
BufferHandle m_Materials;
|
|
||||||
BufferHandle m_Nodes;
|
|
||||||
};
|
|
||||||
|
|
||||||
ModelData modelData = {
|
|
||||||
.m_VertexBuffer = model.m_VertexPositionHandle,
|
|
||||||
.m_Color = model.m_VertexColorHandle,
|
|
||||||
.m_UvBuffer = model.m_TexCoord0Handle,
|
|
||||||
.m_Materials = model.m_MaterialsHandle,
|
|
||||||
.m_Nodes = model.m_NodeHandle,
|
|
||||||
};
|
|
||||||
|
|
||||||
INFO("Starting loop");
|
INFO("Starting loop");
|
||||||
while (window.Poll())
|
while (window.Poll())
|
||||||
{
|
{
|
||||||
|
|
@ -297,13 +280,15 @@ main(int, char **)
|
||||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 1, 1, &descriptorSet, 0, nullptr);
|
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 1, 1, &descriptorSet, 0, nullptr);
|
||||||
|
|
||||||
cmd.bindIndexBuffer(model.m_IndexBuffer.m_Buffer, 0, vk::IndexType::eUint32);
|
cmd.bindIndexBuffer(model.m_IndexBuffer.m_Buffer, 0, vk::IndexType::eUint32);
|
||||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, 0, sizeof modelData, &modelData);
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, 0, sizeof model.m_Handles,
|
||||||
|
&model.m_Handles);
|
||||||
|
|
||||||
for (auto &prim : model.m_MeshPrimitives)
|
for (auto &prim : model.m_MeshPrimitives)
|
||||||
{
|
{
|
||||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, sizeof modelData,
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, sizeof model.m_Handles,
|
||||||
sizeof prim.m_MaterialIdx, &prim.m_MaterialIdx);
|
sizeof prim.m_MaterialIdx, &prim.m_MaterialIdx);
|
||||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, sizeof modelData + sizeof prim.m_MaterialIdx,
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll,
|
||||||
|
sizeof model.m_Handles + sizeof prim.m_MaterialIdx,
|
||||||
sizeof prim.m_TransformIdx, &prim.m_TransformIdx);
|
sizeof prim.m_TransformIdx, &prim.m_TransformIdx);
|
||||||
cmd.drawIndexed(prim.m_IndexCount, 1, prim.m_FirstIndex, Cast<i32>(prim.m_VertexOffset), 0);
|
cmd.drawIndexed(prim.m_IndexCount, 1, prim.m_FirstIndex, Cast<i32>(prim.m_VertexOffset), 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ CreatePipeline(const Device *device, const Swapchain *swapchain, const GpuResour
|
||||||
vk::PushConstantRange pushConstantRange = {
|
vk::PushConstantRange pushConstantRange = {
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = 28,
|
.size = 24,
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,5 @@ struct Device;
|
||||||
constexpr auto VERTEX_SHADER_FILE = "shader/model.vs.hlsl.spv";
|
constexpr auto VERTEX_SHADER_FILE = "shader/model.vs.hlsl.spv";
|
||||||
constexpr auto FRAGMENT_SHADER_FILE = "shader/model.ps.hlsl.spv";
|
constexpr auto FRAGMENT_SHADER_FILE = "shader/model.ps.hlsl.spv";
|
||||||
|
|
||||||
struct Vertex
|
|
||||||
{
|
|
||||||
vec3 m_Position;
|
|
||||||
vec2 m_TexCoord0;
|
|
||||||
};
|
|
||||||
|
|
||||||
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
|
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
|
||||||
Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain, const GpuResourceManager *resourceManager);
|
Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain, const GpuResourceManager *resourceManager);
|
||||||
|
|
|
||||||
|
|
@ -342,7 +342,7 @@ GpuResourceManager::GpuResourceManager(const Device *device, u16 maxSize)
|
||||||
.borderColor = vk::BorderColor::eFloatOpaqueBlack,
|
.borderColor = vk::BorderColor::eFloatOpaqueBlack,
|
||||||
.unnormalizedCoordinates = false,
|
.unnormalizedCoordinates = false,
|
||||||
};
|
};
|
||||||
AbortIfFailed(device->m_Device.createSampler(&samplerCreateInfo, nullptr, &m_Sampler));
|
AbortIfFailed(device->m_Device.createSampler(&samplerCreateInfo, nullptr, &m_ImmutableSampler));
|
||||||
|
|
||||||
INFO("Max Buffer Count: {}", buffersCount);
|
INFO("Max Buffer Count: {}", buffersCount);
|
||||||
INFO("Max Texture Count: {}", texturesCount);
|
INFO("Max Texture Count: {}", texturesCount);
|
||||||
|
|
@ -368,7 +368,7 @@ GpuResourceManager::GpuResourceManager(const Device *device, u16 maxSize)
|
||||||
};
|
};
|
||||||
AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
|
AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
|
||||||
|
|
||||||
eastl::vector immutableSamplers(texturesCount, m_Sampler);
|
eastl::vector immutableSamplers(texturesCount, m_ImmutableSampler);
|
||||||
eastl::array descriptorLayoutBindings = {
|
eastl::array descriptorLayoutBindings = {
|
||||||
vk::DescriptorSetLayoutBinding{
|
vk::DescriptorSetLayoutBinding{
|
||||||
.binding = BUFFER_BINDING_INDEX,
|
.binding = BUFFER_BINDING_INDEX,
|
||||||
|
|
@ -414,7 +414,7 @@ GpuResourceManager::~GpuResourceManager()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_BufferManager.Destroy(m_Device);
|
m_BufferManager.Destroy(m_Device);
|
||||||
m_Device->m_Device.destroy(m_Sampler, nullptr);
|
m_Device->m_Device.destroy(m_ImmutableSampler, nullptr);
|
||||||
m_Device->m_Device.destroy(m_DescriptorPool, nullptr);
|
m_Device->m_Device.destroy(m_DescriptorPool, nullptr);
|
||||||
m_Device->m_Device.destroy(m_SetLayout, nullptr);
|
m_Device->m_Device.destroy(m_SetLayout, nullptr);
|
||||||
}
|
}
|
||||||
|
|
@ -423,7 +423,7 @@ GpuResourceManager::GpuResourceManager(GpuResourceManager &&other) noexcept
|
||||||
: m_WriteInfos(std::move(other.m_WriteInfos)),
|
: m_WriteInfos(std::move(other.m_WriteInfos)),
|
||||||
m_Writes(std::move(other.m_Writes)),
|
m_Writes(std::move(other.m_Writes)),
|
||||||
m_WriteOwner(std::move(other.m_WriteOwner)),
|
m_WriteOwner(std::move(other.m_WriteOwner)),
|
||||||
m_Sampler(other.m_Sampler),
|
m_ImmutableSampler(other.m_ImmutableSampler),
|
||||||
m_BufferManager(std::move(other.m_BufferManager)),
|
m_BufferManager(std::move(other.m_BufferManager)),
|
||||||
m_TextureManager(std::move(other.m_TextureManager)),
|
m_TextureManager(std::move(other.m_TextureManager)),
|
||||||
m_Device(Take(other.m_Device)),
|
m_Device(Take(other.m_Device)),
|
||||||
|
|
@ -444,7 +444,7 @@ GpuResourceManager::operator=(GpuResourceManager &&other) noexcept
|
||||||
m_WriteInfos = std::move(other.m_WriteInfos);
|
m_WriteInfos = std::move(other.m_WriteInfos);
|
||||||
m_Writes = std::move(other.m_Writes);
|
m_Writes = std::move(other.m_Writes);
|
||||||
m_WriteOwner = std::move(other.m_WriteOwner);
|
m_WriteOwner = std::move(other.m_WriteOwner);
|
||||||
m_Sampler = other.m_Sampler;
|
m_ImmutableSampler = other.m_ImmutableSampler;
|
||||||
m_BufferManager = std::move(other.m_BufferManager);
|
m_BufferManager = std::move(other.m_BufferManager);
|
||||||
m_TextureManager = std::move(other.m_TextureManager);
|
m_TextureManager = std::move(other.m_TextureManager);
|
||||||
m_Device = Take(other.m_Device); // Ensure taken.
|
m_Device = Take(other.m_Device); // Ensure taken.
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,12 @@
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
|
||||||
#include <EASTL/deque.h>
|
#include <EASTL/deque.h>
|
||||||
#include <EASTL/stack.h>
|
|
||||||
#include <EASTL/vector_map.h>
|
#include <EASTL/vector_map.h>
|
||||||
|
|
||||||
struct Device;
|
struct Device;
|
||||||
struct Texture;
|
struct Texture;
|
||||||
struct UniformStorageBuffer;
|
struct UniformStorageBuffer;
|
||||||
|
|
||||||
struct GpuResourceManager;
|
|
||||||
|
|
||||||
struct GpuResourceHandle
|
struct GpuResourceHandle
|
||||||
{
|
{
|
||||||
constexpr static u32 INVALID_HANDLE = MaxValue<u32>;
|
constexpr static u32 INVALID_HANDLE = MaxValue<u32>;
|
||||||
|
|
@ -96,9 +93,8 @@ private:
|
||||||
eastl::vector<vk::WriteDescriptorSet> m_Writes;
|
eastl::vector<vk::WriteDescriptorSet> m_Writes;
|
||||||
eastl::vector<WriteOwner> m_WriteOwner;
|
eastl::vector<WriteOwner> m_WriteOwner;
|
||||||
|
|
||||||
vk::Sampler m_Sampler;
|
vk::Sampler m_ImmutableSampler;
|
||||||
|
|
||||||
//FreeList m_BufferFreeList;
|
|
||||||
BufferManager m_BufferManager;
|
BufferManager m_BufferManager;
|
||||||
TextureManager m_TextureManager;
|
TextureManager m_TextureManager;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,14 @@ typedef float2 UVData;
|
||||||
typedef float4 NormalData;
|
typedef float4 NormalData;
|
||||||
typedef float4 ColorData;
|
typedef float4 ColorData;
|
||||||
|
|
||||||
|
struct VertexData
|
||||||
|
{
|
||||||
|
float4 m_Normal;
|
||||||
|
float2 m_TexCoord0;
|
||||||
|
float2 m_TexCoord1;
|
||||||
|
float4 m_Color0;
|
||||||
|
};
|
||||||
|
|
||||||
struct TransformData
|
struct TransformData
|
||||||
{
|
{
|
||||||
float4x4 transform;
|
float4x4 transform;
|
||||||
|
|
@ -25,8 +33,7 @@ struct MaterialData
|
||||||
struct Block
|
struct Block
|
||||||
{
|
{
|
||||||
uint vertexBufferHandle;
|
uint vertexBufferHandle;
|
||||||
uint colorHandle;
|
uint vertexDataHandle;
|
||||||
uint uvBufferHandle;
|
|
||||||
uint materialBufferHandle;
|
uint materialBufferHandle;
|
||||||
uint nodeBufferHandle;
|
uint nodeBufferHandle;
|
||||||
int m_MaterialIdx;
|
int m_MaterialIdx;
|
||||||
|
|
@ -43,9 +50,7 @@ struct Camera
|
||||||
#define INVALID_HANDLE 0xFFFFFFFF
|
#define INVALID_HANDLE 0xFFFFFFFF
|
||||||
|
|
||||||
[[vk::binding(0, 0)]] StructuredBuffer<PositionData> vertexBuffer[];
|
[[vk::binding(0, 0)]] StructuredBuffer<PositionData> vertexBuffer[];
|
||||||
[[vk::binding(0, 0)]] StructuredBuffer<UVData> uvBuffer[];
|
[[vk::binding(0, 0)]] StructuredBuffer<VertexData> vertexDataBuffer[];
|
||||||
[[vk::binding(0, 0)]] StructuredBuffer<NormalData> normalBuffer[];
|
|
||||||
[[vk::binding(0, 0)]] StructuredBuffer<ColorData> colorBuffer[];
|
|
||||||
[[vk::binding(0, 0)]] StructuredBuffer<MaterialData> materialsBuffer[];
|
[[vk::binding(0, 0)]] StructuredBuffer<MaterialData> materialsBuffer[];
|
||||||
[[vk::binding(0, 0)]] StructuredBuffer<TransformData> nodeBuffer[];
|
[[vk::binding(0, 0)]] StructuredBuffer<TransformData> nodeBuffer[];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
#version 450
|
|
||||||
#pragma shader_stage(fragment)
|
|
||||||
#extension GL_EXT_nonuniform_qualifier : enable
|
|
||||||
|
|
||||||
layout (location = 0) in vec2 inUV;
|
|
||||||
layout (location = 0) out vec4 outColor;
|
|
||||||
|
|
||||||
struct VertexData {
|
|
||||||
float position[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MaterialData {
|
|
||||||
float m_AlbedoFactor[4];
|
|
||||||
float m_EmissionFactor[3];
|
|
||||||
float m_MetalFactor;
|
|
||||||
float m_RoughFactor;
|
|
||||||
uint m_AlbedoTex;
|
|
||||||
uint m_NormalTex;
|
|
||||||
uint m_MetalRoughTex;
|
|
||||||
uint m_OcclusionTex;
|
|
||||||
uint m_EmissionTex;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define INVALID_HANDLE 0xFFFFFFFF
|
|
||||||
|
|
||||||
layout(set = 0, binding = 1) uniform sampler2D textures[];
|
|
||||||
layout(std430, set = 0, binding = 0) readonly buffer Vertices {
|
|
||||||
VertexData data[];
|
|
||||||
} vertexBuffer[];
|
|
||||||
layout(std430, set = 0, binding = 0) readonly buffer Materials {
|
|
||||||
MaterialData data[];
|
|
||||||
} materialsBuffer[];
|
|
||||||
|
|
||||||
|
|
||||||
layout(push_constant) uniform Block {
|
|
||||||
uint vertexBufferHandle;
|
|
||||||
uint uvBufferHandle;
|
|
||||||
uint materialBufferHandle;
|
|
||||||
uint m_VertexOffset;
|
|
||||||
int m_NormalOffset; // <0 for invalid
|
|
||||||
int m_TexCoord0Offset; // <0 for invalid
|
|
||||||
uint m_FirstIndex;
|
|
||||||
uint m_IndexCount;
|
|
||||||
int m_MaterialIdx; // <0 for invalid
|
|
||||||
} pcb;
|
|
||||||
|
|
||||||
vec4 ToVec4(float array[4]) {
|
|
||||||
return vec4(array[0], array[1], array[2], array[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 GetAlbedo(uint materialBufferId, int materialId, vec2 uv0) {
|
|
||||||
if (materialId < 0) {
|
|
||||||
return vec4(1.0f, 0.0f, 1.0f, 1.0f);
|
|
||||||
} else {
|
|
||||||
vec4 albedoFactor = ToVec4(materialsBuffer[materialBufferId].data[materialId].m_AlbedoFactor);
|
|
||||||
uint albedoTexId = materialsBuffer[materialBufferId].data[materialId].m_AlbedoTex;
|
|
||||||
if (albedoTexId == INVALID_HANDLE) {
|
|
||||||
return albedoFactor;
|
|
||||||
} else {
|
|
||||||
return texture(textures[albedoTexId], uv0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
outColor = GetAlbedo(pcb.materialBufferHandle, pcb.m_MaterialIdx, inUV);// texture(textures[materialsBuffer[pcb.materialBufferHandle].data[pcb.m_MaterialIdx].m_AlbedoTex], inUV);// ToVec4(materialsBuffer[pcb.materialBufferHandle].data[pcb.m_MaterialIdx].m_AlbedoFactor);// vec4(texture(textures[textureHandle], inUV).rgb, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
#version 460 core
|
|
||||||
#pragma shader_stage(vertex)
|
|
||||||
#extension GL_EXT_nonuniform_qualifier : enable
|
|
||||||
|
|
||||||
layout(location = 0) out vec2 outUV;
|
|
||||||
|
|
||||||
struct Position {
|
|
||||||
float position[4];
|
|
||||||
};
|
|
||||||
struct Normal {
|
|
||||||
float normal[4];
|
|
||||||
};
|
|
||||||
struct UV {
|
|
||||||
float uv[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MaterialData {
|
|
||||||
float m_AlbedoFactor[4];
|
|
||||||
float m_EmissionFactor[3];
|
|
||||||
float m_MetalFactor;
|
|
||||||
float m_RoughFactor;
|
|
||||||
uint m_AlbedoTex;
|
|
||||||
uint m_NormalTex;
|
|
||||||
uint m_MetalRoughTex;
|
|
||||||
uint m_OcclusionTex;
|
|
||||||
uint m_EmissionTex;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define INVALID_HANDLE 0xFFFFFFFF
|
|
||||||
|
|
||||||
layout(std430, set = 0, binding = 0) readonly buffer Vertices {
|
|
||||||
Position data[];
|
|
||||||
} vertexBuffer[];
|
|
||||||
layout(std430, set = 0, binding = 0) readonly buffer Normals {
|
|
||||||
Normal data[];
|
|
||||||
} normalBuffer[];
|
|
||||||
layout(std430, set = 0, binding = 0) readonly buffer TexCoord0 {
|
|
||||||
UV data[];
|
|
||||||
} uvBuffer[];
|
|
||||||
layout(std430, set = 0, binding = 0) readonly buffer Materials {
|
|
||||||
MaterialData data[];
|
|
||||||
} materialsBuffer[];
|
|
||||||
|
|
||||||
vec3 GetPosition(uint bufferId, uint vertexIdx) {
|
|
||||||
return vec3(
|
|
||||||
vertexBuffer[bufferId].data[vertexIdx].position[0],
|
|
||||||
vertexBuffer[bufferId].data[vertexIdx].position[1],
|
|
||||||
vertexBuffer[bufferId].data[vertexIdx].position[2]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 GetUV(uint bufferId, uint vertexIdx) {
|
|
||||||
if (bufferId == INVALID_HANDLE) {
|
|
||||||
return vec2(0.0f, 0.0f);
|
|
||||||
} else {
|
|
||||||
return vec2(
|
|
||||||
uvBuffer[bufferId].data[vertexIdx].uv[0],
|
|
||||||
uvBuffer[bufferId].data[vertexIdx].uv[1]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layout(set = 1, binding = 0) uniform Camera {
|
|
||||||
mat4 model;
|
|
||||||
mat4 view;
|
|
||||||
mat4 proj;
|
|
||||||
} ubo;
|
|
||||||
|
|
||||||
layout(push_constant) uniform Block {
|
|
||||||
uint vertexBufferHandle;
|
|
||||||
uint uvBufferHandle;
|
|
||||||
uint materialBufferHandle;
|
|
||||||
uint m_VertexOffset;
|
|
||||||
int m_NormalOffset; // <0 for invalid
|
|
||||||
int m_TexCoord0Offset; // <0 for invalid
|
|
||||||
uint m_FirstIndex;
|
|
||||||
uint m_IndexCount;
|
|
||||||
int m_MaterialIdx; // <0 for invalid
|
|
||||||
} pcb;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
outUV = GetUV(pcb.uvBufferHandle, gl_VertexIndex);
|
|
||||||
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(GetPosition(pcb.vertexBufferHandle, gl_VertexIndex), 1.0f);
|
|
||||||
}
|
|
||||||
|
|
@ -15,14 +15,7 @@ struct VS_Output
|
||||||
|
|
||||||
float2 GetUV(uint bufferId, uint vertexIdx)
|
float2 GetUV(uint bufferId, uint vertexIdx)
|
||||||
{
|
{
|
||||||
if (bufferId == INVALID_HANDLE)
|
return (bufferId == INVALID_HANDLE) ? 0.0f.xx : vertexDataBuffer[bufferId][vertexIdx].m_TexCoord0.xy;
|
||||||
{
|
|
||||||
return 0.0f.xx;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return uvBuffer[bufferId][vertexIdx];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 GetPosition(uint bufferId, uint vertexIdx)
|
float4 GetPosition(uint bufferId, uint vertexIdx)
|
||||||
|
|
@ -32,7 +25,7 @@ float4 GetPosition(uint bufferId, uint vertexIdx)
|
||||||
|
|
||||||
float4 GetColor(uint bufferId, uint vertexIdx)
|
float4 GetColor(uint bufferId, uint vertexIdx)
|
||||||
{
|
{
|
||||||
return (bufferId != INVALID_HANDLE) ? colorBuffer[bufferId][vertexIdx] : float4(1.0f, 0.0f, 1.0f, 1.0f);
|
return (bufferId == INVALID_HANDLE) ? float4(1.0f, 0.0f, 1.0f, 1.0f) : vertexDataBuffer[bufferId][vertexIdx].m_Color0;
|
||||||
}
|
}
|
||||||
|
|
||||||
float4x4 GetModel(uint bufferId, uint index)
|
float4x4 GetModel(uint bufferId, uint index)
|
||||||
|
|
@ -44,8 +37,8 @@ VS_Output main(VS_Input stage_input)
|
||||||
{
|
{
|
||||||
VS_Output output;
|
VS_Output output;
|
||||||
output.outPosition = GetPosition(pcb.vertexBufferHandle, stage_input.vertexIndex);
|
output.outPosition = GetPosition(pcb.vertexBufferHandle, stage_input.vertexIndex);
|
||||||
output.outUV = GetUV(pcb.uvBufferHandle, stage_input.vertexIndex);
|
output.outUV = GetUV(pcb.vertexDataHandle, stage_input.vertexIndex);
|
||||||
output.outColor = GetColor(pcb.colorHandle, stage_input.vertexIndex);
|
output.outColor = GetColor(pcb.vertexDataHandle, stage_input.vertexIndex);
|
||||||
|
|
||||||
float4 globalPosition = mul(camera.model, mul(GetModel(pcb.nodeBufferHandle, pcb.m_NodeIdx), GetPosition(pcb.vertexBufferHandle, stage_input.vertexIndex)));
|
float4 globalPosition = mul(camera.model, mul(GetModel(pcb.nodeBufferHandle, pcb.m_NodeIdx), GetPosition(pcb.vertexBufferHandle, stage_input.vertexIndex)));
|
||||||
float4 clipSpace = mul(camera.view, globalPosition);
|
float4 clipSpace = mul(camera.view, globalPosition);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue