summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/models/cube.binbin840 -> 1224 bytes
-rw-r--r--assets/models/cube.gltf69
-rw-r--r--assets/models/cube.pngbin0 -> 182802 bytes
-rw-r--r--assets/shaders/texture.frag16
-rw-r--r--assets/shaders/vert.vert32
-rw-r--r--src/components.hpp6
-rw-r--r--src/entities.cpp412
-rw-r--r--src/entities.hpp8
-rw-r--r--src/window.cpp45
9 files changed, 521 insertions, 67 deletions
diff --git a/assets/models/cube.bin b/assets/models/cube.bin
index c59221c..6223cf0 100644
--- a/assets/models/cube.bin
+++ b/assets/models/cube.bin
Binary files differ
diff --git a/assets/models/cube.gltf b/assets/models/cube.gltf
index 5077394..9bc8a22 100644
--- a/assets/models/cube.gltf
+++ b/assets/models/cube.gltf
@@ -21,14 +21,11 @@
"materials":[
{
"doubleSided":true,
- "name":"Material",
+ "name":"Material.001",
"pbrMetallicRoughness":{
- "baseColorFactor":[
- 0.800000011920929,
- 0.800000011920929,
- 0.800000011920929,
- 1
- ],
+ "baseColorTexture":{
+ "index":0
+ },
"metallicFactor":0,
"roughnessFactor":0.5
}
@@ -36,25 +33,45 @@
],
"meshes":[
{
- "name":"Cube",
+ "name":"Cube.001",
"primitives":[
{
"attributes":{
- "POSITION":0,
- "NORMAL":1,
- "TEXCOORD_0":2
+ "COLOR_0":0,
+ "POSITION":1,
+ "NORMAL":2,
+ "TEXCOORD_0":3
},
- "indices":3,
+ "indices":4,
"material":0
}
]
}
],
+ "textures":[
+ {
+ "sampler":0,
+ "source":0
+ }
+ ],
+ "images":[
+ {
+ "mimeType":"image/png",
+ "name":"cube",
+ "uri":"cube.png"
+ }
+ ],
"accessors":[
{
"bufferView":0,
"componentType":5126,
"count":24,
+ "type":"VEC4"
+ },
+ {
+ "bufferView":1,
+ "componentType":5126,
+ "count":24,
"max":[
1,
1,
@@ -68,19 +85,19 @@
"type":"VEC3"
},
{
- "bufferView":1,
+ "bufferView":2,
"componentType":5126,
"count":24,
"type":"VEC3"
},
{
- "bufferView":2,
+ "bufferView":3,
"componentType":5126,
"count":24,
"type":"VEC2"
},
{
- "bufferView":3,
+ "bufferView":4,
"componentType":5123,
"count":36,
"type":"SCALAR"
@@ -89,32 +106,44 @@
"bufferViews":[
{
"buffer":0,
- "byteLength":288,
+ "byteLength":384,
"byteOffset":0,
"target":34962
},
{
"buffer":0,
"byteLength":288,
- "byteOffset":288,
+ "byteOffset":384,
+ "target":34962
+ },
+ {
+ "buffer":0,
+ "byteLength":288,
+ "byteOffset":672,
"target":34962
},
{
"buffer":0,
"byteLength":192,
- "byteOffset":576,
+ "byteOffset":960,
"target":34962
},
{
"buffer":0,
"byteLength":72,
- "byteOffset":768,
+ "byteOffset":1152,
"target":34963
}
],
+ "samplers":[
+ {
+ "magFilter":9729,
+ "minFilter":9987
+ }
+ ],
"buffers":[
{
- "byteLength":840,
+ "byteLength":1224,
"uri":"cube.bin"
}
]
diff --git a/assets/models/cube.png b/assets/models/cube.png
new file mode 100644
index 0000000..74a7e29
--- /dev/null
+++ b/assets/models/cube.png
Binary files differ
diff --git a/assets/shaders/texture.frag b/assets/shaders/texture.frag
new file mode 100644
index 0000000..e63995f
--- /dev/null
+++ b/assets/shaders/texture.frag
@@ -0,0 +1,16 @@
+# version 450
+
+layout(location = 0) in vec3 fragColor;
+layout(location = 1) in vec3 fragTexCoord;
+
+layout(location = 0) out vec4 outColor;
+
+layout(binding = 1) uniform sampler2D texSampler;
+
+void main() {
+ vec4 color = texture(texSampler, fragTexCoord.xy);
+ if (color.w == 0) {
+ discard;
+ }
+ outColor = color;
+}
diff --git a/assets/shaders/vert.vert b/assets/shaders/vert.vert
new file mode 100644
index 0000000..f3e7cf2
--- /dev/null
+++ b/assets/shaders/vert.vert
@@ -0,0 +1,32 @@
+#version 450
+
+layout(binding = 0) uniform UniformBufferObject {
+ mat4 model;
+ mat4 view;
+ mat4 proj;
+} ubo;
+
+// vertex
+layout(location = 0) in vec4 inColor;
+layout(location = 1) in vec3 inPosition;
+layout(location = 2) in vec3 inNorm;
+layout(location = 3) in vec2 inTexCoord;
+
+// instance
+layout(location = 4) in mat4 instPosRotScale;
+layout(location = 8) in float textureIndex;
+
+// output
+layout(location = 0) out vec3 fragColor;
+layout(location = 1) out vec3 fragTexCoord;
+
+void main() {
+ gl_Position =
+ ubo.proj *
+ ubo.view *
+ ubo.model *
+ instPosRotScale *
+ vec4(inPosition, 1.0);
+ fragColor = inColor;
+ fragTexCoord = vec3(inTexCoord, textureIndex);
+}
diff --git a/src/components.hpp b/src/components.hpp
index ce5f0f2..76dd7fc 100644
--- a/src/components.hpp
+++ b/src/components.hpp
@@ -31,8 +31,8 @@ struct InstPos {
struct CompGrBinds {
EntityHandle entHandle = EntityHandle_MAX;
GrBindsHandle grBindsHandle = GrBindsHandle_MAX;
- VkDeviceMemory deviceMemoryVert = VK_NULL_HANDLE;
- VkDeviceMemory deviceMemoryInst = VK_NULL_HANDLE;
+ VkPipelineLayout vkPipelineLayout = VK_NULL_HANDLE;
+ VkDescriptorSet vkDescriptorSet = VK_NULL_HANDLE;
VkBuffer vertexBuffer = VK_NULL_HANDLE;
uint32_t vertexFirstBinding = 0;
uint32_t vertexCount = 0;
@@ -54,8 +54,6 @@ struct CompGrBinds {
uint32_t instanceCount = 0;
VkDeviceSize instanceOffsets = 0;
DynArray<InstPos> instances{0};
- VkPipelineLayout vkPipelineLayout = VK_NULL_HANDLE;
- VkDescriptorSet vkDescriptorSet = VK_NULL_HANDLE;
};
struct CompInstance {
diff --git a/src/entities.cpp b/src/entities.cpp
index 75b56f4..b439da1 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -2,11 +2,57 @@
#include "entities.hpp"
DynArray<EntityType> globalEntityTypes{16};
+VkDescriptorSetLayout vkDescriptorSetLayout_Texture = VK_NULL_HANDLE;
+VkPipelineLayout vkPipelineLayout_Texture = VK_NULL_HANDLE;
+VkSampler vkSampler_Texture = VK_NULL_HANDLE;
+
+VkPipelineLayoutCreateInfo sharedVkPipelineLayoutCreateInfo {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .setLayoutCount = 0,
+ .pSetLayouts = nullptr,
+ .pushConstantRangeCount = 0,
+ .pPushConstantRanges = nullptr,
+};
+
+VkWriteDescriptorSet uboDescriptor {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .pNext = nullptr,
+ .dstSet = nullptr,
+ .dstBinding = 0,
+ .dstArrayElement = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ .pImageInfo = nullptr,
+ .pBufferInfo = nullptr,
+ .pTexelBufferView = nullptr,
+};
+
+VkDescriptorImageInfo textureDescriptorInfo {
+ .sampler = nullptr,
+ .imageView = nullptr,
+ .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+};
+
+VkWriteDescriptorSet samplerDescriptor {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .pNext = nullptr,
+ .dstSet = nullptr,
+ .dstBinding = 1,
+ .dstArrayElement = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .pImageInfo = &textureDescriptorInfo,
+ .pBufferInfo = nullptr,
+ .pTexelBufferView = nullptr,
+};
void EntityType_Init() {
globalEntityTypes.Push(
EntityType {
- .modelFile = "assets/models/cube.gltf",
+ .modelsDir = "assets/models",
+ .modelFile = "cube.gltf",
.entityTypeCode = "EntTypeCube",
.entityHandle = ECS_CreateEntity(),
.startingInstanceCount = 16,
@@ -19,6 +65,60 @@ void EntityType_Init() {
}
);
+ VkDescriptorSetLayoutBinding vkDescriptorSetLayoutBindings[2];
+ for (long i = 0; i < 2; ++i) {
+ vkDescriptorSetLayoutBindings[i].pImmutableSamplers = nullptr;
+ }
+ vkDescriptorSetLayoutBindings[0].binding = 0;
+ vkDescriptorSetLayoutBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ vkDescriptorSetLayoutBindings[0].descriptorCount = 1;
+ vkDescriptorSetLayoutBindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+ vkDescriptorSetLayoutBindings[1].binding = 1;
+ vkDescriptorSetLayoutBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ vkDescriptorSetLayoutBindings[1].descriptorCount = 1;
+ vkDescriptorSetLayoutBindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+ VkDescriptorSetLayoutCreateInfo vkDescriptorSetLayoutCreateInfo {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .bindingCount = 2,
+ .pBindings = vkDescriptorSetLayoutBindings,
+ };
+ vkCreateDescriptorSetLayout(vkDevice, &vkDescriptorSetLayoutCreateInfo, vkAllocator, &vkDescriptorSetLayout_Texture);
+
+ VkPipelineLayoutCreateInfo vkPipelineLayoutCreateInfo {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .setLayoutCount = 1,
+ .pSetLayouts = &vkDescriptorSetLayout_Texture,
+ .pushConstantRangeCount = 0,
+ .pPushConstantRanges = nullptr,
+ };
+ vkCreatePipelineLayout(vkDevice, &vkPipelineLayoutCreateInfo, vkAllocator, &vkPipelineLayout_Texture);
+
+ VkSamplerCreateInfo vkSamplerCreateInfo;
+ vkSamplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ vkSamplerCreateInfo.pNext = nullptr;
+ vkSamplerCreateInfo.flags = 0;
+ vkSamplerCreateInfo.magFilter = VK_FILTER_NEAREST;
+ vkSamplerCreateInfo.minFilter = VK_FILTER_NEAREST;
+ vkSamplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ vkSamplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ vkSamplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ vkSamplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ vkSamplerCreateInfo.mipLodBias = 0.0f;
+ vkSamplerCreateInfo.anisotropyEnable = VK_TRUE;
+ vkSamplerCreateInfo.maxAnisotropy = vkPhysicalDeviceProperties.limits.maxSamplerAnisotropy;
+ vkSamplerCreateInfo.compareEnable = VK_FALSE;
+ vkSamplerCreateInfo.compareOp = VK_COMPARE_OP_ALWAYS;
+ vkSamplerCreateInfo.minLod = 0.0f;
+ // TODO MipMap
+ vkSamplerCreateInfo.maxLod = 1;
+ vkSamplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
+ vkSamplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
+ vkCreateSampler(vkDevice, &vkSamplerCreateInfo, vkAllocator, &vkSampler_Texture);
+
long entityTypeCount = globalEntityTypes.Count();
for (long i = 0; i < entityTypeCount; ++i) {
EntityType_Load(globalEntityTypes[i]);
@@ -28,14 +128,27 @@ void EntityType_Init() {
void EntityType_Load(EntityType &et) {
assert(et.startingInstanceCount > 0);
if (et.modelFile != nullptr && et.modelFile != CAFE_BABE(char)) {
+ // assert(et.vkDescriptorSetLayoutCreateInfo != nullptr && et.vkDescriptorSetLayoutCreateInfo != CAFE_BABE(VkDescriptorSetLayoutCreateInfo) && "EntityType with a defined model must also contain appropriate Vulkan CreateInfos");
// assert(et.vkPipelineLayoutCreateInfo != nullptr && et.vkPipelineLayoutCreateInfo != CAFE_BABE(VkPipelineLayoutCreateInfo) && "EntityType with a defined model must also contain appropriate Vulkan CreateInfos");
- AssetHandle assetHandle{AM_Register(et.modelFile)};
+
+ char modelPath[128];
+ memset(modelPath, '\0', 128);
+ snprintf(modelPath, 128, "%s/%s", et.modelsDir, et.modelFile);
+ AssetHandle assetHandle{AM_Register(modelPath)};
const Asset *asset = AM_Get(assetHandle);
CompGrBinds &grBinds = ECS_CreateGrBinds(et.entityHandle);
- // auto vkResult = vkCreatePipelineLayout(vkDevice, et.vkPipelineLayoutCreateInfo, vkAllocator, &grBinds.vkPipelineLayout);
+ /*
+ * 2023-09-13 - JCB
+ * I don't like that we're just copying this.
+ * This should be moved to window.cpp.
+ */
+ grBinds.vkPipelineLayout = vkPipelineLayout_Texture;
+ // et.textureSampler = vkPipelineLayout_Texture;
+ // VkResult vkResult = vkCreateDescriptorSetLayout(vkDevice, et.vkDescriptorSetLayoutCreateInfo, vkAllocator, &grBinds.vkDescriptorSetLayout);
+ // assert(vkResult == VK_SUCCESS);
+ // vkResult = vkCreatePipelineLayout(vkDevice, et.vkPipelineLayoutCreateInfo, vkAllocator, &grBinds.vkPipelineLayout);
// assert(vkResult == VK_SUCCESS);
- // TODO grBinds.vkDescriptorSet
cgltf_options options{};
// TODO allocator
@@ -43,10 +156,224 @@ void EntityType_Load(EntityType &et) {
cgltf_result result = cgltf_parse(&options, asset->ptr, asset->size, &gltfData);
assert(result == cgltf_result_success);
// TODO consider using AssetHandler OR loading this directly to the GPU
- result = cgltf_load_buffers(&options, gltfData, et.modelFile);
+ result = cgltf_load_buffers(&options, gltfData, modelPath);
assert(result == cgltf_result_success);
result = cgltf_validate(gltfData);
assert(result == cgltf_result_success);
+ assert(gltfData->images_count < 2);
+
+ // AssetHandle textureAssetHandle = AssetHandle_MAX;
+ if (gltfData->images_count == 1) {
+ char imagePath[128];
+ memset(imagePath, '\0', 128);
+ snprintf(imagePath, 128, "%s/%s", et.modelsDir, gltfData->images[0].uri);
+
+ int pixelWidth, pixelHeight, pixelChannels;
+ auto *pixels = stbi_load(imagePath, &pixelWidth, &pixelHeight, &pixelChannels, STBI_rgb_alpha);
+ assert(pixels != nullptr && "sbti_load failed to load image.");
+
+ uint32_t imageSizeBytes = pixelWidth * pixelHeight * pixelChannels;
+ AssetHandle textureAssetHandle{AM_Register(pixels, imageSizeBytes, imagePath)};
+ const Asset *textureAsset = AM_Get(textureAssetHandle);
+
+ VkFormat imageFormat = VK_FORMAT_R8G8B8A8_SRGB;
+ if (pixelChannels == 3) {
+ imageFormat = VK_FORMAT_R8G8B8_SRGB;
+ } else if (pixelChannels == 2) {
+ imageFormat = VK_FORMAT_R8G8_SRGB;
+ } else if (pixelChannels == 1) {
+ imageFormat = VK_FORMAT_R8_SRGB;
+ } else {
+ assert(pixelChannels != 0 && pixelChannels < 5);
+ }
+
+ VkImageCreateInfo vkImageCreateInfo;
+ vkImageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ vkImageCreateInfo.pNext = nullptr;
+ vkImageCreateInfo.flags = 0;
+ vkImageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
+ vkImageCreateInfo.format = imageFormat;
+ vkImageCreateInfo.extent = VkExtent3D {
+ .width = static_cast<uint32_t>(pixelWidth),
+ .height = static_cast<uint32_t>(pixelHeight),
+ .depth = 1
+ };
+ vkImageCreateInfo.mipLevels = 1;
+ vkImageCreateInfo.arrayLayers = 1;
+ vkImageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ vkImageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ vkImageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+ vkImageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ vkImageCreateInfo.queueFamilyIndexCount = 0;
+ vkImageCreateInfo.pQueueFamilyIndices = nullptr;
+ vkImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ vkCreateImage(vkDevice, &vkImageCreateInfo, vkAllocator, &et.textureImage);
+
+ VkMemoryRequirements imageMemReqs;
+ vkGetImageMemoryRequirements(vkDevice, et.textureImage, &imageMemReqs);
+ VkMemoryAllocateInfo imageAllocInfo;
+ imageAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ imageAllocInfo.pNext = nullptr;
+ imageAllocInfo.allocationSize = imageMemReqs.size;
+ imageAllocInfo.memoryTypeIndex = FindMemoryTypeIndex(imageMemReqs.memoryTypeBits, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
+ vkAllocateMemory(vkDevice, &imageAllocInfo, vkAllocator, &et.deviceMemoryTexture);
+ vkBindImageMemory(vkDevice, et.textureImage, et.deviceMemoryTexture, 0);
+
+ VkImageViewCreateInfo vkImageViewCreateInfo;
+ vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ vkImageViewCreateInfo.pNext = nullptr;
+ vkImageViewCreateInfo.flags = 0;
+ vkImageViewCreateInfo.image = et.textureImage;
+ // TODO animated textures
+ vkImageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ vkImageViewCreateInfo.format = imageFormat;
+ vkImageViewCreateInfo.components = VkComponentMapping {
+ .r = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .g = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .b = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .a = VK_COMPONENT_SWIZZLE_IDENTITY,
+ };
+ vkImageViewCreateInfo.subresourceRange = VkImageSubresourceRange {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ // TODO MapMap
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ // TODO animated textures
+ .layerCount = 1,
+ };
+
+ vkCreateImageView(vkDevice, &vkImageViewCreateInfo, vkAllocator, &et.textureImageView);
+
+ // transition image layout and copy to buffer
+ VkBuffer transferImageBuffer;
+ VkDeviceMemory transferImageMemory;
+ void *deviceData;
+ BeginTransferBuffer(imageSizeBytes, transferImageBuffer, transferImageMemory, deviceData);
+ memcpy(deviceData, gltfData->buffers[0].data, gltfData->buffers[0].size);
+ {
+ VkImageMemoryBarrier vkImageMemoryBarrier;
+ vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ vkImageMemoryBarrier.pNext = nullptr;
+ vkImageMemoryBarrier.srcAccessMask = {};
+ vkImageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ vkImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ vkImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vkImageMemoryBarrier.image = et.textureImage;
+ vkImageMemoryBarrier.subresourceRange = VkImageSubresourceRange {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ // TODO MipMap
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ // TODO animated textures
+ .layerCount = 1,
+ };
+
+ VkCommandBufferBeginInfo vkCommandBufferBeginInfo;
+ vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ vkCommandBufferBeginInfo.pNext = nullptr;
+ vkCommandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ vkCommandBufferBeginInfo.pInheritanceInfo = nullptr;
+
+ vkBeginCommandBuffer(transferCommandBuffer, &vkCommandBufferBeginInfo);
+
+ vkCmdPipelineBarrier(transferCommandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkImageMemoryBarrier);
+
+ // TODO animated textures / texture array - make this an array
+ VkBufferImageCopy vkBufferImageCopy;
+ vkBufferImageCopy.bufferOffset = 0;
+ vkBufferImageCopy.bufferRowLength = pixelWidth;
+ vkBufferImageCopy.bufferImageHeight = pixelHeight;
+ vkBufferImageCopy.imageSubresource = VkImageSubresourceLayers {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ // TODO animated textures
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ };
+ vkBufferImageCopy.imageOffset = VkOffset3D {
+ .x = 0,
+ .y = 0,
+ .z = 0,
+ };
+ vkBufferImageCopy.imageExtent = VkExtent3D {
+ .width = static_cast<uint32_t>(pixelWidth),
+ .height = static_cast<uint32_t>(pixelHeight),
+ .depth = 1,
+ };
+ vkCmdCopyBufferToImage(transferCommandBuffer, transferImageBuffer, et.textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vkBufferImageCopy);
+
+ vkEndCommandBuffer(transferCommandBuffer);
+
+ VkSubmitInfo submitInfo;
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.pNext = nullptr;
+ submitInfo.waitSemaphoreCount = 0;
+ submitInfo.pWaitSemaphores = nullptr;
+ submitInfo.pWaitDstStageMask = nullptr;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &transferCommandBuffer;
+ submitInfo.signalSemaphoreCount = 0;
+ submitInfo.pSignalSemaphores = nullptr;
+ vkQueueSubmit(transferQueue, 1, &submitInfo, nullptr);
+ vkQueueWaitIdle(transferQueue);
+ vkResetCommandBuffer(transferCommandBuffer, 0);
+ }
+ EndTransferBuffer(transferImageBuffer, transferImageMemory);
+ {
+ VkImageMemoryBarrier vkImageMemoryBarrier;
+ vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ vkImageMemoryBarrier.pNext = nullptr;
+ vkImageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ vkImageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ vkImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ vkImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ vkImageMemoryBarrier.image = et.textureImage;
+ vkImageMemoryBarrier.subresourceRange = VkImageSubresourceRange {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ // TODO MipMap
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ // TODO animated textures
+ .layerCount = 1,
+ };
+
+ VkCommandBufferBeginInfo vkCommandBufferBeginInfo;
+ vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ vkCommandBufferBeginInfo.pNext = nullptr;
+ vkCommandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ vkCommandBufferBeginInfo.pInheritanceInfo = nullptr;
+
+ vkBeginCommandBuffer(graphicsCommandBuffer, &vkCommandBufferBeginInfo);
+
+ vkCmdPipelineBarrier(graphicsCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkImageMemoryBarrier);
+
+ vkEndCommandBuffer(graphicsCommandBuffer);
+
+ VkSubmitInfo submitInfo;
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.pNext = nullptr;
+ submitInfo.waitSemaphoreCount = 0;
+ submitInfo.pWaitSemaphores = nullptr;
+ submitInfo.pWaitDstStageMask = nullptr;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &graphicsCommandBuffer;
+ submitInfo.signalSemaphoreCount = 0;
+ submitInfo.pSignalSemaphores = nullptr;
+ vkQueueSubmit(graphicsQueue, 1, &submitInfo, nullptr);
+ vkQueueWaitIdle(graphicsQueue);
+ }
+
+ stbi_image_free(pixels);
+ }
+
// make sure cgltf can interpret our model
for (long i = 0; i < gltfData->accessors_count; ++i) {
@@ -120,28 +447,32 @@ void EntityType_Load(EntityType &et) {
vkMemoryAllocateInfo.pNext = nullptr;
vkMemoryAllocateInfo.allocationSize = vkMemoryRequirements.size;
vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(vkMemoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &grBinds.deviceMemoryVert);
+ vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &et.deviceMemoryVert);
// bind buffers
+ uint32_t runningOffset = 0;
if (et.Importer_GLTF.AccessorIndexVertex > -1) {
const auto &acc = gltfData->accessors[et.Importer_GLTF.AccessorIndexVertex];
assert(acc.buffer_view->offset % vkMemoryRequirements.alignment == 0);
- vkBindBufferMemory(vkDevice, grBinds.vertexBuffer, grBinds.deviceMemoryVert, acc.buffer_view->offset);
+ vkBindBufferMemory(vkDevice, grBinds.vertexBuffer, et.deviceMemoryVert, runningOffset);
+ runningOffset += acc.buffer_view->size;
}
if (et.Importer_GLTF.AccessorIndexNormal > -1) {
const auto &acc = gltfData->accessors[et.Importer_GLTF.AccessorIndexNormal];
assert(acc.buffer_view->offset % vkMemoryRequirements.alignment == 0);
- vkBindBufferMemory(vkDevice, grBinds.normalsBuffer, grBinds.deviceMemoryVert, acc.buffer_view->offset);
+ vkBindBufferMemory(vkDevice, grBinds.normalsBuffer, et.deviceMemoryVert, runningOffset);
+ runningOffset += acc.buffer_view->size;
}
if (et.Importer_GLTF.AccessorIndexUV > -1) {
const auto &acc = gltfData->accessors[et.Importer_GLTF.AccessorIndexUV];
assert(acc.buffer_view->offset % vkMemoryRequirements.alignment == 0);
- vkBindBufferMemory(vkDevice, grBinds.uvBuffer , grBinds.deviceMemoryVert, acc.buffer_view->offset);
+ vkBindBufferMemory(vkDevice, grBinds.uvBuffer , et.deviceMemoryVert, runningOffset);
+ runningOffset += acc.buffer_view->size;
}
if (et.Importer_GLTF.AccessorIndexIndex > -1) {
const auto &acc = gltfData->accessors[et.Importer_GLTF.AccessorIndexIndex];
assert(acc.buffer_view->offset % vkMemoryRequirements.alignment == 0);
- vkBindBufferMemory(vkDevice, grBinds.indexBuffer, grBinds.deviceMemoryVert, acc.buffer_view->offset);
+ vkBindBufferMemory(vkDevice, grBinds.indexBuffer, et.deviceMemoryVert, runningOffset);
}
// create transfer items && transfer
@@ -161,8 +492,36 @@ void EntityType_Load(EntityType &et) {
vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &transferDeviceMemory);
vkBindBufferMemory(vkDevice, transferBuffer, transferDeviceMemory, 0);
void *data;
- vkMapMemory(vkDevice, transferDeviceMemory, 0, gltfData->buffers[0].size, 0, &data);
- memcpy(data, gltfData->buffers[0].data, gltfData->buffers[0].size);
+ vkMapMemory(vkDevice, transferDeviceMemory, 0, vkMemoryRequirements.size, 0, &data);
+ // memcpy(data, gltfData->buffers[0].data, vkMemoryRequirements.size);
+ uint32_t runningOffset2 = 0;
+ if (et.Importer_GLTF.AccessorIndexVertex > -1) {
+ const auto &acc = gltfData->accessors[et.Importer_GLTF.AccessorIndexVertex];
+ char *dstPtr = static_cast<char *>(data) + runningOffset2;
+ char *srcPtr = static_cast<char *>(gltfData->buffers[0].data) + acc.buffer_view->offset;
+ memcpy(dstPtr, srcPtr, acc.buffer_view->size);
+ runningOffset2 += acc.buffer_view->size;
+ }
+ if (et.Importer_GLTF.AccessorIndexNormal > -1) {
+ const auto &acc = gltfData->accessors[et.Importer_GLTF.AccessorIndexNormal];
+ char *dstPtr = static_cast<char *>(data) + runningOffset2;
+ char *srcPtr = static_cast<char *>(gltfData->buffers[0].data) + acc.buffer_view->offset;
+ memcpy(dstPtr, srcPtr, acc.buffer_view->size);
+ runningOffset2 += acc.buffer_view->size;
+ }
+ if (et.Importer_GLTF.AccessorIndexUV > -1) {
+ const auto &acc = gltfData->accessors[et.Importer_GLTF.AccessorIndexUV];
+ char *dstPtr = static_cast<char *>(data) + runningOffset2;
+ char *srcPtr = static_cast<char *>(gltfData->buffers[0].data) + acc.buffer_view->offset;
+ memcpy(dstPtr, srcPtr, acc.buffer_view->size);
+ runningOffset2 += acc.buffer_view->size;
+ }
+ if (et.Importer_GLTF.AccessorIndexIndex > -1) {
+ const auto &acc = gltfData->accessors[et.Importer_GLTF.AccessorIndexIndex];
+ char *dstPtr = static_cast<char *>(data) + runningOffset2;
+ char *srcPtr = static_cast<char *>(gltfData->buffers[0].data) + acc.buffer_view->offset;
+ memcpy(dstPtr, srcPtr, acc.buffer_view->size);
+ }
vkUnmapMemory(vkDevice, transferDeviceMemory);
VkCommandBufferBeginInfo vkCommandBufferBeginInfo;
@@ -207,7 +566,7 @@ void EntityType_Load(EntityType &et) {
vkEndCommandBuffer(transferCommandBuffer);
- VkSubmitInfo submitInfo{};
+ VkSubmitInfo submitInfo;
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pNext = nullptr;
submitInfo.waitSemaphoreCount = 0;
@@ -232,8 +591,8 @@ void EntityType_Load(EntityType &et) {
vkGetBufferMemoryRequirements(vkDevice, grBinds.instanceBuffer, &vkMemoryRequirementsInst);
vkMemoryAllocateInfo.allocationSize = vkMemoryRequirementsInst.size;
vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(vkMemoryRequirementsInst.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &grBinds.deviceMemoryInst);
- vkBindBufferMemory(vkDevice, grBinds.instanceBuffer, grBinds.deviceMemoryInst, 0);
+ vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &et.deviceMemoryInst);
+ vkBindBufferMemory(vkDevice, grBinds.instanceBuffer, et.deviceMemoryInst, 0);
// cleanup
cgltf_free(gltfData);
@@ -244,8 +603,8 @@ void EntityType_Teardown() {
long entityTypeCount = globalEntityTypes.Count();
for (long i = 0; i < entityTypeCount; ++i) {
if (globalEntityTypes[i].modelFile == nullptr) continue;
+ auto *et = &globalEntityTypes[i];
auto *grBinds = ECS_GetGrBinds(globalEntityTypes[i].entityHandle);
- vkDestroyPipelineLayout(vkDevice, grBinds->vkPipelineLayout, vkAllocator);
if (grBinds->vertexBuffer != VK_NULL_HANDLE)
vkDestroyBuffer(vkDevice, grBinds->vertexBuffer, vkAllocator);
if (grBinds->normalsBuffer != VK_NULL_HANDLE)
@@ -256,9 +615,22 @@ void EntityType_Teardown() {
vkDestroyBuffer(vkDevice, grBinds->indexBuffer, vkAllocator);
if (grBinds->instanceBuffer != VK_NULL_HANDLE)
vkDestroyBuffer(vkDevice, grBinds->instanceBuffer, vkAllocator);
- if (grBinds->deviceMemoryInst != VK_NULL_HANDLE)
- vkFreeMemory(vkDevice, grBinds->deviceMemoryInst, vkAllocator);
- if (grBinds->deviceMemoryVert != VK_NULL_HANDLE)
- vkFreeMemory(vkDevice, grBinds->deviceMemoryVert, vkAllocator);
+
+ if (et->textureImageView != VK_NULL_HANDLE)
+ vkDestroyImageView(vkDevice, et->textureImageView, vkAllocator);
+ if (et->textureImage != VK_NULL_HANDLE)
+ vkDestroyImage(vkDevice, et->textureImage, vkAllocator);
+ if (et->deviceMemoryInst != VK_NULL_HANDLE)
+ vkFreeMemory(vkDevice, et->deviceMemoryInst, vkAllocator);
+ if (et->deviceMemoryVert != VK_NULL_HANDLE)
+ vkFreeMemory(vkDevice, et->deviceMemoryVert, vkAllocator);
+ if (et->deviceMemoryTexture != VK_NULL_HANDLE)
+ vkFreeMemory(vkDevice, et->deviceMemoryTexture, vkAllocator);
}
+ if (vkSampler_Texture != VK_NULL_HANDLE)
+ vkDestroySampler(vkDevice, vkSampler_Texture, vkAllocator);
+ if (vkPipelineLayout_Texture != VK_NULL_HANDLE)
+ vkDestroyPipelineLayout(vkDevice, vkPipelineLayout_Texture, vkAllocator);
+ if (vkDescriptorSetLayout_Texture != VK_NULL_HANDLE)
+ vkDestroyDescriptorSetLayout(vkDevice, vkDescriptorSetLayout_Texture, vkAllocator);
}
diff --git a/src/entities.hpp b/src/entities.hpp
index 53fe0d9..98aba33 100644
--- a/src/entities.hpp
+++ b/src/entities.hpp
@@ -2,6 +2,7 @@
#define PKE_ENTITIES_HPP
#include "vendor/cgltf-include.hpp"
+#include "vendor/stb_image_include.hpp"
#include "ecs.hpp"
#include "components.hpp"
#include "asset-manager.hpp"
@@ -11,10 +12,15 @@
#include <vulkan/vulkan_core.h>
struct EntityType {
+ const char *modelsDir = nullptr;
const char *modelFile = nullptr;
const char *entityTypeCode = nullptr;
EntityHandle entityHandle = EntityHandle_MAX;
- VkPipelineLayoutCreateInfo *vkPipelineLayoutCreateInfo = nullptr;
+ VkDeviceMemory deviceMemoryVert = VK_NULL_HANDLE;
+ VkDeviceMemory deviceMemoryInst = VK_NULL_HANDLE;
+ VkDeviceMemory deviceMemoryTexture = VK_NULL_HANDLE;
+ VkImage textureImage = VK_NULL_HANDLE;
+ VkImageView textureImageView = VK_NULL_HANDLE;
uint32_t startingInstanceCount = 1024;
struct Importer_GLTF {
int16_t AccessorIndexVertex = -1;
diff --git a/src/window.cpp b/src/window.cpp
index 084f5c2..02249a5 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -1020,6 +1020,29 @@ void RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
throw "failed to begin recording command buffer";
}
+ // TODO there should be a RenderPass that sandwiches this somewhere
+ const uint64_t bindBucketCount = ECS_GetGrBinds_BucketCount();
+ for (long b = 0; b < bindBucketCount; ++b) {
+ uint64_t itemCount;
+ CompGrBinds *items = ECS_GetGrBinds(b, itemCount);
+ for (long i = 0; i < itemCount; ++i) {
+ CompGrBinds *binder = &items[i];
+ vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, binder->vkPipelineLayout, 0U, 1U, &binder->vkDescriptorSet, 0, {});
+ vkCmdBindVertexBuffers(commandBuffer, binder->vertexFirstBinding, binder->vertexCount, &binder->vertexBuffer, &binder->vertexOffsets);
+ if (binder->normalsCount > 0)
+ vkCmdBindVertexBuffers(commandBuffer, binder->normalsFirstBinding, binder->normalsCount, &binder->normalsBuffer, &binder->normalsOffsets);
+ if (binder->uvCount > 0)
+ vkCmdBindVertexBuffers(commandBuffer, binder->uvFirstBinding, binder->uvCount, &binder->uvBuffer, &binder->uvOffsets);
+ if (binder->indexCount > 0)
+ vkCmdBindIndexBuffer(commandBuffer, binder->indexBuffer, binder->vertexOffsets, VK_INDEX_TYPE_UINT16);
+
+ vkCmdBindVertexBuffers(commandBuffer, binder->indexFirstBinding, binder->instanceCount, &binder->instanceBuffer, &binder->instanceOffsets);
+
+ vkCmdDrawIndexed(commandBuffer, binder->indexCount, binder->instanceCount, 0, 0, 0);
+ }
+ }
+
+ // present pass
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
VkRenderPassBeginInfo renderPassInfo{};
@@ -1049,28 +1072,6 @@ void RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
-
- const uint64_t bindBucketCount = ECS_GetGrBinds_BucketCount();
- for (long b = 0; b < bindBucketCount; ++b) {
- uint64_t itemCount;
- CompGrBinds *items = ECS_GetGrBinds(b, itemCount);
- for (long i = 0; i < itemCount; ++i) {
- CompGrBinds *binder = &items[i];
- vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, binder->vkPipelineLayout, 0U, 1U, &binder->vkDescriptorSet, 0, {});
- vkCmdBindVertexBuffers(commandBuffer, binder->vertexFirstBinding, binder->vertexCount, &binder->vertexBuffer, &binder->vertexOffsets);
- if (binder->normalsCount > 0)
- vkCmdBindVertexBuffers(commandBuffer, binder->normalsFirstBinding, binder->normalsCount, &binder->normalsBuffer, &binder->normalsOffsets);
- if (binder->uvCount > 0)
- vkCmdBindVertexBuffers(commandBuffer, binder->uvFirstBinding, binder->uvCount, &binder->uvBuffer, &binder->uvOffsets);
- if (binder->indexCount > 0)
- vkCmdBindIndexBuffer(commandBuffer, binder->indexBuffer, binder->vertexOffsets, VK_INDEX_TYPE_UINT16);
-
- vkCmdBindVertexBuffers(commandBuffer, binder->indexFirstBinding, binder->instanceCount, &binder->instanceBuffer, &binder->instanceOffsets);
-
- vkCmdDrawIndexed(commandBuffer, binder->indexCount, binder->instanceCount, 0, 0, 0);
- }
- }
-
// reminder that present.vert is a triangle
vkCmdDraw(commandBuffer, 3, 1, 0, 0);