Mercurial > games > semicongine
changeset 778:dfc5978a3168
fix: most errors and Nim 2 transition problems
author | Sam <sam@basx.dev> |
---|---|
date | Sat, 12 Aug 2023 23:54:28 +0700 |
parents | 754835bf175e |
children | a2c14402acd2 |
files | src/semicongine/engine.nim src/semicongine/material.nim src/semicongine/mesh.nim src/semicongine/renderer.nim src/semicongine/resources/mesh.nim src/semicongine/vulkan/buffer.nim src/semicongine/vulkan/image.nim src/semicongine/vulkan/memory.nim |
diffstat | 8 files changed, 100 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/src/semicongine/engine.nim Mon Aug 07 00:23:00 2023 +0700 +++ b/src/semicongine/engine.nim Sat Aug 12 23:54:28 2023 +0700 @@ -114,6 +114,7 @@ assert engine.renderer.isSome engine.renderer.get.setupDrawableBuffers(scene, vertexInput, samplers, transformAttribute=transformAttribute, materialIndexAttribute=materialIndexAttribute) +#[ proc addScene*(engine: var Engine, scene: Scene, materialShaders: Table[string, ShaderConfiguration], transformAttribute="transform", materialIndexAttribute="materialIndex") = if transformAttribute != "": for shader in materialShaders.values: @@ -123,6 +124,7 @@ assert materialIndexAttribute in map(shader.inputs, proc(a: ShaderAttribute): string = a.name) assert engine.renderer.isSome engine.renderer.get.setupDrawableBuffers(scene, vertexInput, samplers, transformAttribute=transformAttribute, materialIndexAttribute=materialIndexAttribute) + ]# proc renderScene*(engine: var Engine, scene: var Scene) = assert engine.state == Running
--- a/src/semicongine/material.nim Mon Aug 07 00:23:00 2023 +0700 +++ b/src/semicongine/material.nim Sat Aug 12 23:54:28 2023 +0700 @@ -1,4 +1,6 @@ import std/tables +import std/strformat +import std/strutils import ./core @@ -9,4 +11,11 @@ constants*: Table[string, DataValue] textures*: Table[string, Texture] -func `$`*(mat: Material): string = mat.name +proc `$`*(material: Material): string = + var constants: seq[string] + for key, value in material.constants.pairs: + constants.add &"{key}: {value}" + var textures: seq[string] + for key in material.textures.keys: + textures.add &"{key}" + return &"""{material.name} ({material.index}) | Values: {constants.join(", ")} | Textures: {textures.join(", ")}"""
--- a/src/semicongine/mesh.nim Mon Aug 07 00:23:00 2023 +0700 +++ b/src/semicongine/mesh.nim Sat Aug 12 23:54:28 2023 +0700 @@ -85,31 +85,36 @@ assert colors.len == 0 or colors.len == positions.len assert uvs.len == 0 or uvs.len == positions.len - result = Mesh(instanceCount: instanceCount, instanceTransforms: newSeqWith(int(instanceCount), Unit4F32)) + # determine index type (uint8, uint16, uint32) + var indexType = None + if indices.len > 0: + indexType = Big + if autoResize and uint32(positions.len) < uint32(high(uint8)) and false: # TODO: check feature support + indexType = Tiny + elif autoResize and uint32(positions.len) < uint32(high(uint16)): + indexType = Small + + result = Mesh(instanceCount: instanceCount, instanceTransforms: newSeqWith(int(instanceCount), Unit4F32), indexType: indexType) setMeshData(result, "position", positions.toSeq) if colors.len > 0: setMeshData(result, "color", colors.toSeq) if uvs.len > 0: setMeshData(result, "uv", uvs.toSeq) + # assert all indices are valid for i in indices: assert uint32(i[0]) < result.vertexCount assert uint32(i[1]) < result.vertexCount assert uint32(i[2]) < result.vertexCount - if indices.len == 0: - result.indexType = None - else: - if autoResize and uint32(positions.len) < uint32(high(uint8)) and false: # TODO: check feature support - result.indexType = Tiny - for i, tri in enumerate(indices): - result.tinyIndices.add [uint8(tri[0]), uint8(tri[1]), uint8(tri[2])] - elif autoResize and uint32(positions.len) < uint32(high(uint16)): - result.indexType = Small - for i, tri in enumerate(indices): - result.smallIndices.add [uint16(tri[0]), uint16(tri[1]), uint16(tri[2])] - else: - result.indexType = Big - for i, tri in enumerate(indices): - result.bigIndices.add [uint32(tri[0]), uint32(tri[1]), uint32(tri[2])] + # cast index values to appropiate type + if result.indexType == Tiny and uint32(positions.len) < uint32(high(uint8)) and false: # TODO: check feature support + for i, tri in enumerate(indices): + result.tinyIndices.add [uint8(tri[0]), uint8(tri[1]), uint8(tri[2])] + elif result.indexType == Small and uint32(positions.len) < uint32(high(uint16)): + for i, tri in enumerate(indices): + result.smallIndices.add [uint16(tri[0]), uint16(tri[1]), uint16(tri[2])] + elif result.indexType == Big: + for i, tri in enumerate(indices): + result.bigIndices.add [uint32(tri[0]), uint32(tri[1]), uint32(tri[2])] setInstanceData(result, "transform", newSeqWith(int(instanceCount), Unit4F32)) func newMesh*(
--- a/src/semicongine/renderer.nim Mon Aug 07 00:23:00 2023 +0700 +++ b/src/semicongine/renderer.nim Sat Aug 12 23:54:28 2023 +0700 @@ -95,7 +95,7 @@ assert mesh.materials.len > 0, "Missing material specification for mesh. Either set the 'materials' attribute or pass the argument 'materialIndexAttribute=\"\"' when calling 'addScene'" assert mesh.materials.len == getMeshData[uint16](mesh, scenedata.materialIndexAttribute)[].len for i, material in enumerate(mesh.materials): - let matIndex = materialIndex(scene, material) + let matIndex = scene.materialIndex(material) if matIndex < 0: raise newException(Exception, &"Required material '{material}' not available in scene (available are: {scene.materials.toSeq})") updateMeshData[uint16](mesh, scenedata.materialIndexAttribute, uint32(i), uint16(matIndex))
--- a/src/semicongine/resources/mesh.nim Mon Aug 07 00:23:00 2023 +0700 +++ b/src/semicongine/resources/mesh.nim Sat Aug 12 23:54:28 2023 +0700 @@ -137,10 +137,11 @@ mesh.appendMeshData(attribute.toLowerAscii, data) vertexCount = data.len - var materialId = 0'u8 + var materialId = 0'u16 if primitiveNode.hasKey("material"): - materialId = uint8(primitiveNode["material"].getInt()) - mesh.appendMeshData("material", newSeqWith[uint8](int(vertexCount), materialId)) + materialId = uint16(primitiveNode["material"].getInt()) + mesh.appendMeshData("materialIndex", newSeqWith[uint8](int(vertexCount), materialId)) + mesh.materials.add newSeqWith[string](int(vertexCount), root["materials"][int(materialId)]["name"].getStr()) if primitiveNode.hasKey("indices"): assert mesh.indexType != None @@ -164,21 +165,21 @@ raise newException(Exception, &"Unsupported index data type: {data.thetype}") # TODO: use one mesh per primitive?? right now we are merging primitives... check addPrimitive below -proc loadMesh(root: JsonNode, meshNode: JsonNode, mainBuffer: seq[uint8], materials: seq[string]): Mesh = - result = Mesh(instanceCount: 1, instanceTransforms: newSeqWith(1, Unit4F32)) +proc loadMesh(root: JsonNode, meshNode: JsonNode, mainBuffer: seq[uint8]): Mesh = # check if and how we use indexes var indexCount = 0 + var indexType = None let indexed = meshNode["primitives"][0].hasKey("indices") if indexed: for primitive in meshNode["primitives"]: indexCount += root["accessors"][primitive["indices"].getInt()]["count"].getInt() if indexCount < int(high(uint16)): - result.indexType = Small + indexType = Small else: - result.indexType = Big - else: - result.indexType = None + indexType = Big + + result = Mesh(instanceCount: 1, instanceTransforms: newSeqWith(1, Unit4F32), indexType: indexType) # check we have the same attributes for all primitives let attributes = meshNode["primitives"][0]["attributes"].keys.toSeq @@ -188,6 +189,7 @@ # prepare mesh attributes for attribute, accessor in meshNode["primitives"][0]["attributes"].pairs: result.setMeshData(attribute.toLowerAscii, newDataList(thetype=root["accessors"][accessor.getInt()].getGPUType())) + result.setMeshData("materialIndex", newDataList(theType=UInt16)) # add all mesh data for primitive in meshNode["primitives"]: @@ -195,7 +197,7 @@ setInstanceData(result, "transform", newSeqWith(int(result.instanceCount), Unit4F32)) -proc loadNode(root: JsonNode, node: JsonNode, mainBuffer: var seq[uint8], materials: seq[string]): Entity = +proc loadNode(root: JsonNode, node: JsonNode, mainBuffer: var seq[uint8]): Entity = var name = "<Unknown>" if node.hasKey("name"): name = node["name"].getStr() @@ -235,16 +237,16 @@ # children if node.hasKey("children"): for childNode in node["children"]: - result.add loadNode(root, root["nodes"][childNode.getInt()], mainBuffer, materials) + result.add loadNode(root, root["nodes"][childNode.getInt()], mainBuffer) # mesh if node.hasKey("mesh"): - result["mesh"] = loadMesh(root, root["meshes"][node["mesh"].getInt()], mainBuffer, materials) + result["mesh"] = loadMesh(root, root["meshes"][node["mesh"].getInt()], mainBuffer) -proc loadScene(root: JsonNode, scenenode: JsonNode, mainBuffer: var seq[uint8], materials: seq[string]): Scene = +proc loadScene(root: JsonNode, scenenode: JsonNode, mainBuffer: var seq[uint8]): Scene = var rootEntity = newEntity("<root>") for nodeId in scenenode["nodes"]: - var node = loadNode(root, root["nodes"][nodeId.getInt()], mainBuffer, materials) + var node = loadNode(root, root["nodes"][nodeId.getInt()], mainBuffer) node.transform = node.transform * scale3d(1'f32, -1'f32, 1'f32) rootEntity.add node @@ -283,7 +285,7 @@ result.sampler.wrapModeT = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()] proc loadMaterial(root: JsonNode, materialNode: JsonNode, mainBuffer: var seq[uint8], materialIndex: int): Material = - result = Material(name: materialNode.getStr("name"), index: materialIndex) + result = Material(name: materialNode["name"].getStr(), index: materialIndex) let pbr = materialNode["pbrMetallicRoughness"] @@ -367,14 +369,12 @@ let bufferLenDiff = int(chunkLength) - data.structuredContent["buffers"][0]["byteLength"].getInt() assert 0 <= bufferLenDiff <= 3 # binary buffer may be aligned to 4 bytes - debug data.structuredContent.pretty + debug "Loading mesh: ", data.structuredContent.pretty for scenedata in data.structuredContent["scenes"]: - var materials: seq[string] - var scene = data.structuredContent.loadScene(scenedata, data.binaryBufferData, materials) + var scene = data.structuredContent.loadScene(scenedata, data.binaryBufferData) for i, materialNode in enumerate(data.structuredContent["materials"]): let material = loadMaterial(data.structuredContent, materialNode, data.binaryBufferData, i) - materials.add material.name scene.addMaterial material result.add scene
--- a/src/semicongine/vulkan/buffer.nim Mon Aug 07 00:23:00 2023 +0700 +++ b/src/semicongine/vulkan/buffer.nim Sat Aug 12 23:54:28 2023 +0700 @@ -50,9 +50,17 @@ preferVRAM=preferVRAM, preferAutoFlush=preferAutoFlush ) - buffer.memoryAllocated = true + debug "Allocating memory for buffer: ", buffer.size, " bytes of type ", memoryType - buffer.memory = buffer.device.allocate(requirements.size, memoryType) + # need to replace the whole buffer object, due to case statement + buffer = Buffer( + device: buffer.device, + vk: buffer.vk, + size: buffer.size, + usage: buffer.usage, + memoryAllocated: true, + memory: buffer.device.allocate(requirements.size, memoryType) + ) checkVkResult buffer.device.vk.vkBindBufferMemory(buffer.vk, buffer.memory.vk, VkDeviceSize(0)) # currently no support for extended structure and concurrent/shared use @@ -109,7 +117,13 @@ if buffer.memoryAllocated: assert buffer.memory.vk.valid buffer.memory.free - buffer.memoryAllocated = false + buffer = Buffer( + device: buffer.device, + vk: buffer.vk, + size: buffer.size, + usage: buffer.usage, + memoryAllocated: false, + ) buffer.vk.reset proc setData*(dst: Buffer, src: pointer, size: uint64, bufferOffset=0'u64) = @@ -120,7 +134,7 @@ dst.memory.flush() else: # use staging buffer, slower but required if memory is not host visible var stagingBuffer = dst.device.createBuffer(size, [VK_BUFFER_USAGE_TRANSFER_SRC_BIT], requireMappable=true, preferVRAM=false, preferAutoFlush=true) - stagingBuffer.setData(src, size, 0) + setData(stagingBuffer, src, size, 0) stagingBuffer.copy(dst, bufferOffset) stagingBuffer.destroy()
--- a/src/semicongine/vulkan/image.nim Mon Aug 07 00:23:00 2023 +0700 +++ b/src/semicongine/vulkan/image.nim Sat Aug 12 23:54:28 2023 +0700 @@ -63,9 +63,19 @@ preferVRAM=preferVRAM, preferAutoFlush=preferAutoFlush ) - image.memoryAllocated = true + debug "Allocating memory for image: ", image.width, "x", image.height, "x", image.depth, ", ", requirements.size, " bytes of type ", memoryType - image.memory = image.device.allocate(requirements.size, memoryType) + image = VulkanImage( + device: image.device, + vk: image.vk, + width: image.width, + height: image.height, + depth: image.depth, + format: image.format, + usage: image.usage, + memoryAllocated: true, + memory: image.device.allocate(requirements.size, memoryType), + ) checkVkResult image.device.vk.vkBindImageMemory(image.vk, image.memory.vk, VkDeviceSize(0)) proc transitionImageLayout*(image: VulkanImage, oldLayout, newLayout: VkImageLayout) = @@ -184,7 +194,16 @@ if image.memoryAllocated: assert image.memory.vk.valid image.memory.free - image.memoryAllocated = false + image = VulkanImage( + device: image.device, + vk: image.vk, + width: image.width, + height: image.height, + depth: image.depth, + format: image.format, + usage: image.usage, + memoryAllocated: false, + ) image.vk.reset proc createSampler*(device: Device, sampler: Sampler): VulkanSampler =
--- a/src/semicongine/vulkan/memory.nim Mon Aug 07 00:23:00 2023 +0700 +++ b/src/semicongine/vulkan/memory.nim Sat Aug 12 23:54:28 2023 +0700 @@ -68,12 +68,13 @@ proc allocate*(device: Device, size: uint64, memoryType: MemoryType): DeviceMemory = assert device.vk.valid assert size > 0 - - result.device = device - result.size = size - result.memoryType = memoryType - result.canMap = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in result.memoryType.flags - result.needsFlushing = not (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in result.memoryType.flags) + result = DeviceMemory( + device: device, + size: size, + memoryType: memoryType, + canMap: VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in memoryType.flags, + needsFlushing: not (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in result.memoryType.flags), + ) var allocationInfo = VkMemoryAllocateInfo( sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,