Compare commits

...

27 commits

Author SHA1 Message Date
nek0 bab538a0e4 flake update 2023-11-05 12:02:16 +01:00
Amedeo Molnár 2d3fc457be a little cleaner 2023-10-22 12:46:16 +02:00
nek0 4feac51f26 weed out stuff 2023-10-22 07:14:22 +02:00
nek0 def6e56d1f implement FPS meter in Console output 2023-10-22 06:08:43 +02:00
Amedeo Molnár 1b6a6392ba fix rendering! 2023-10-22 02:27:33 +02:00
Amedeo Molnár 8f6f5e428d flake update 2023-10-22 01:32:38 +02:00
nek0 676e02ed8d more twiddling 2023-10-22 01:30:52 +02:00
nek0 167599df74 try fixing 2023-10-22 01:30:52 +02:00
nek0 9350198e35 explicitly enable multiIndirectDraw 2023-10-22 01:30:52 +02:00
nek0 9d34dacf76 condense flake 2023-10-22 01:30:52 +02:00
nek0 a6af76f3b3 fix ambiguous record updates 2023-10-22 01:30:51 +02:00
nek0 934085906c final flake fix 2023-10-22 01:30:18 +02:00
nek0 c55bfc5416 make shell 2023-10-22 01:30:18 +02:00
nek0 f873fa7291 move package 2023-10-22 01:30:18 +02:00
nek0 ccd18f803b flake update 2023-10-22 01:30:16 +02:00
nek0 fe4155d26f fix flake 2023-10-22 01:29:49 +02:00
nek0 2ae3daf0f9 fix flake 2023-10-22 01:29:49 +02:00
nek0 d2dac89ce3 small-ish fixes 2023-10-22 01:29:47 +02:00
nek0 0cb8bd8363 add test/debug VM capability 2023-10-22 01:28:21 +02:00
nek0 d9b7c48953 using indirect draw, not working yet 2023-10-22 01:27:18 +02:00
nek0 9084be8bba first little optimisation 2023-10-22 01:27:13 +02:00
nek0 3928655bb0 fix changing rules 2023-10-22 01:15:03 +02:00
nek0 ea87f58b26 flake update 2023-10-22 00:33:07 +02:00
nek0 272db907a0 fix double spaceships 2023-06-11 08:13:53 +02:00
nek0 6caf99a13c remove lambda 2023-06-11 08:13:53 +02:00
nek0 ef135731a4 first little optimisation 2023-06-11 08:13:49 +02:00
nek0 b3a7670c97 fix UVs in Code, not in shader 2023-05-30 01:44:20 +01:00
12 changed files with 226 additions and 81 deletions

View file

@ -5,11 +5,11 @@
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1681202837, "lastModified": 1694529238,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401", "rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -20,11 +20,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1684120848, "lastModified": 1699181587,
"narHash": "sha256-gIwJ5ac1FwZEkCRwjY+gLwgD4G1Bw3Xtr2jr2XihMPo=", "narHash": "sha256-v35mUUgVU2ituIHPNHifpjl5uiYQYyLrpaMtz8X8Ums=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "0cb867999eec4085e1c9ca61c09b72261fa63bb4", "rev": "197629b470f184a47b2a5716312d25b09454bbf8",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -11,28 +11,36 @@
let let
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
haskellPackages = pkgs.haskellPackages; nixos-lib = import (nixpkgs + "/nixos/lib") {};
haskellPackages = pkgs.haskellPackages.override (old: {
overrides = final: prev: {
wavefront = jailbreakUnbreak prev.wavefront;
vulkan-tutorial = vulkan-tutorial;
};
});
vulkan-tutorial = # (ref:haskell-package-def)
haskellPackages.callCabal2nix packageName self {
# Dependency overrides go here
#wavefront = jailbreakUnbreak haskellPackages.wavefront;
};
jailbreakUnbreak = pkg: jailbreakUnbreak = pkg:
pkgs.haskell.lib.doJailbreak (pkg.overrideAttrs (_: { meta = { }; })); pkgs.haskell.lib.doJailbreak (pkgs.haskell.lib.markUnbroken pkg);
packageName = "vulkan-tutorial"; packageName = "vulkan-tutorial";
in rec { in rec {
packages.${packageName} = # (ref:haskell-package-def) packages.default = haskellPackages.vulkan-tutorial;
haskellPackages.callCabal2nix packageName self rec {
# Dependency overrides go here
wavefront = jailbreakUnbreak haskellPackages.wavefront;
};
defaultPackage = self.packages.${system}.${packageName}; devShells.default = haskellPackages.shellFor {
packages = p: [ p.vulkan-tutorial ];
devShell = haskellPackages.shellFor {
packages = p: [ defaultPackage ];
withHoogle = true; withHoogle = true;
buildInputs = (with haskellPackages; [ buildInputs = (with haskellPackages; [
haskell-language-server haskell-language-server
ghcid ghcid
cabal-install cabal-install
(jailbreakUnbreak wavefront)
]) ++ (with pkgs; [ ]) ++ (with pkgs; [
shaderc shaderc
vulkan-loader vulkan-loader
@ -42,21 +50,6 @@
VK_LAYER_PATH="${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d"; VK_LAYER_PATH="${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d";
SDL_VULKAN_LIBRARY="${pkgs.vulkan-loader}/lib/libvulkan.so"; SDL_VULKAN_LIBRARY="${pkgs.vulkan-loader}/lib/libvulkan.so";
}; };
#devShell = pkgs.mkShell { });
# buildInputs = with haskellPackages; [
# haskell-language-server
# ghcid
# cabal-install
# ];
# nativeBuildInputs = with pkgs; [
# pkg-config
# SDL2
# vulkan-validation-layers
# vulkan-headers
# vulkan-loader
# ];
# inputsFrom = builtins.attrValues self.packages.${system};
#};
});
} }

View file

@ -19,8 +19,6 @@ layout(set = 2, binding = 0) uniform sampler2D tex1;
void main() void main()
{ {
// Flip y coordinate of UVs to fix display vec3 color = texture(tex1, texCoord).xyz;
float y = texCoord.y * -1;
vec3 color = texture(tex1, vec2(texCoord.x ,y)).xyz;
outFragColor = vec4(color, inColor.w); outFragColor = vec4(color, inColor.w);
} }

View file

@ -1,4 +1,3 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
@ -23,7 +22,7 @@ import qualified VulkanMemoryAllocator as VMA
import Types import Types
import Memory import Memory
import Util import Util
import Data.Maybe (fromMaybe) import Mesh (compactDraws)
frameOverlap :: Int frameOverlap :: Int
frameOverlap = 2 frameOverlap = 2
@ -60,7 +59,7 @@ createFrames
(\_ -> do (\_ -> do
commandPool <- snd <$> commandPool <- snd <$>
(Vk.withCommandPool logicalDevice poolCreateInfo Nothing allocate) Vk.withCommandPool logicalDevice poolCreateInfo Nothing allocate
let commandBufferAllocationInfo = Vk.zero let commandBufferAllocationInfo = Vk.zero
{ Vk.commandPool = commandPool { Vk.commandPool = commandPool
@ -100,6 +99,15 @@ createFrames
Vk.BUFFER_USAGE_STORAGE_BUFFER_BIT Vk.BUFFER_USAGE_STORAGE_BUFFER_BIT
VMA.MEMORY_USAGE_CPU_TO_GPU VMA.MEMORY_USAGE_CPU_TO_GPU
indirectBuffer <- createAllocatedBuffer
allocator
(maxObjects * sizeOf (undefined :: Vk.DrawIndirectCommand))
(Vk.BUFFER_USAGE_TRANSFER_DST_BIT .|.
Vk.BUFFER_USAGE_STORAGE_BUFFER_BIT .|.
Vk.BUFFER_USAGE_INDIRECT_BUFFER_BIT
)
VMA.MEMORY_USAGE_CPU_TO_GPU
let allocationInfo = Vk.zero let allocationInfo = Vk.zero
{ Vk.descriptorPool = descriptorPool { Vk.descriptorPool = descriptorPool
, Vk.setLayouts = V.singleton setLayout , Vk.setLayouts = V.singleton setLayout
@ -161,6 +169,7 @@ createFrames
, frameCameraBuffer = cameraBuffer , frameCameraBuffer = cameraBuffer
, frameSceneBuffer = sceneBuffer , frameSceneBuffer = sceneBuffer
, frameObjectBuffer = objectBuffer , frameObjectBuffer = objectBuffer
, frameIndirectBuffer = indirectBuffer
, frameGlobalDescriptor = V.head globalDescriptor , frameGlobalDescriptor = V.head globalDescriptor
, frameObjectDescriptor = V.head objectDescriptor , frameObjectDescriptor = V.head objectDescriptor
} }
@ -172,7 +181,8 @@ createFrames
recordCommandBuffer recordCommandBuffer
:: (MonadResource m, MonadReader ReadState m, MonadIO m) :: (MonadResource m, MonadReader ReadState m, MonadIO m)
=> Vk.CommandBuffer => VMA.Allocator
-> Vk.CommandBuffer
-> Vk.RenderPass -> Vk.RenderPass
-> Vk.Framebuffer -> Vk.Framebuffer
-> V2 CInt -> V2 CInt
@ -180,6 +190,7 @@ recordCommandBuffer
-> FrameData -> FrameData
-> m () -> m ()
recordCommandBuffer recordCommandBuffer
allocator
commandBuffer commandBuffer
renderPass renderPass
frameBuffer frameBuffer
@ -221,22 +232,43 @@ recordCommandBuffer
renderObjects <- (liftIO . STM.atomically . STM.readTMVar) =<< asks renderables renderObjects <- (liftIO . STM.atomically . STM.readTMVar) =<< asks renderables
meshMap <- (liftIO . STM.atomically . STM.readTMVar) =<< asks meshLibrary meshMap <- (liftIO . STM.atomically . STM.readTMVar) =<< asks meshLibrary
materialMap <- (liftIO . STM.atomically . STM.readTMVar) =<< asks materialLibrary
let draws = compactDraws meshMap materialMap renderObjects
drawCommands = V.map
(\(i, RenderObject mesh _ _) ->
Vk.DrawIndirectCommand
{ vertexCount = fromIntegral (V.length $ meshVertices $ meshMap M.! mesh)
, firstVertex = 0
, instanceCount = 1
, firstInstance = i
}
)
(V.zip
(V.fromList [0..])
renderObjects
)
(memRelease, memPtr) <- VMA.withMappedMemory
allocator
(bufferAllocation $ frameIndirectBuffer frame)
allocate
V.mapM_ V.mapM_
(\(index, RenderObject meshID materialID modelMatrix) -> do (\(idx, command) -> liftIO $
poke
(castPtr memPtr `plusPtr` (idx * sizeOf command))
command
)
(V.zip
(V.fromList [0 ..])
drawCommands
)
materialMap <- (liftIO . STM.atomically . STM.readTMVar) =<< asks materialLibrary release memRelease
let constants = MeshPushConstants V.mapM_
{ meshPushData = V4 0 0 0 0 (\(IndirectBatch mesh material first count) -> do
, meshRenderMatrix = modelMatrix
}
mesh = fromMaybe
(error $ "no mesh called " <> meshID <> " present")
(meshMap M.!? meshID)
material = fromMaybe
(error $ "no material called " <> materialID <> " present")
(materialMap M.!? materialID)
when when
(materialTextureSet material /= Vk.NULL_HANDLE) (materialTextureSet material /= Vk.NULL_HANDLE)
@ -267,28 +299,24 @@ recordCommandBuffer
(V.singleton $ frameObjectDescriptor frame) (V.singleton $ frameObjectDescriptor frame)
V.empty V.empty
dataPointer <- liftIO (castPtr <$> new constants)
Vk.cmdPushConstants
commandBuffer
(materialPipelineLayout material)
Vk.SHADER_STAGE_VERTEX_BIT
0
(fromIntegral $ sizeOf constants)
dataPointer
Vk.cmdBindVertexBuffers Vk.cmdBindVertexBuffers
commandBuffer commandBuffer
0 0
(V.fromList [ allocatedBuffer $ meshBuffer mesh ]) (V.fromList [ allocatedBuffer $ meshBuffer mesh ])
(V.fromList [ 0 ]) (V.fromList [ 0 ])
Vk.cmdDraw commandBuffer (fromIntegral $ V.length $ meshVertices mesh) 1 0 index let indirectOffset = fromIntegral $
) first * fromIntegral ( sizeOf (undefined :: Vk.DrawIndirectCommand))
(V.zip drawStride = fromIntegral $ sizeOf (undefined :: Vk.DrawIndirectCommand)
(V.fromList [0 ..])
renderObjects Vk.cmdDrawIndirect
commandBuffer
(allocatedBuffer $ frameIndirectBuffer frame)
indirectOffset
count
drawStride
) )
draws
prepareRecording prepareRecording
:: V2 CInt :: V2 CInt

View file

@ -1,6 +1,7 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedRecordDot #-}
module Devices where module Devices where
import Control.Monad import Control.Monad
@ -38,7 +39,7 @@ pickPhysicalDevice vkInstance = do
physDevices physDevices
let discretePhysDevices = V.filter let discretePhysDevices = V.filter
(\(_, devProps, devFeatures) -> (\(_, _, devFeatures) ->
-- Vk.deviceType devProps == Vk.PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && -- Vk.deviceType devProps == Vk.PHYSICAL_DEVICE_TYPE_DISCRETE_GPU &&
Vk.geometryShader devFeatures Vk.geometryShader devFeatures
) )
@ -104,6 +105,9 @@ createLogicalDevice physDevice surface = do
deviceCreateInfo = Vk.zero deviceCreateInfo = Vk.zero
{ Vk.queueCreateInfos = V.singleton (Vk.SomeStruct queueCreateInfo) { Vk.queueCreateInfos = V.singleton (Vk.SomeStruct queueCreateInfo)
, Vk.enabledExtensionNames = extensionNames , Vk.enabledExtensionNames = extensionNames
, Vk.enabledFeatures = Just (Vk.zero
{ Vk.multiDrawIndirect = True
} :: Vk.PhysicalDeviceFeatures)
} }
shaderDrawParametersFeatures = Vk.zero shaderDrawParametersFeatures = Vk.zero
{ Vk.shaderDrawParameters = True { Vk.shaderDrawParameters = True
@ -140,9 +144,9 @@ createSwapchain surface surfaceFormats windowDimension logicalDevice allocator =
if if
V.any V.any
(\a -> (\a ->
(Vk.format :: Vk.SurfaceFormatKHR -> Vk.Format) a == a.format ==
Vk.FORMAT_B8G8R8A8_SRGB Vk.FORMAT_B8G8R8A8_SRGB
&& (Vk.colorSpace :: Vk.SurfaceFormatKHR -> Vk.ColorSpaceKHR) a == && a.colorSpace ==
Vk.COLOR_SPACE_SRGB_NONLINEAR_KHR) Vk.COLOR_SPACE_SRGB_NONLINEAR_KHR)
surfaceFormats surfaceFormats
then then
@ -219,7 +223,7 @@ getImageViewHandles swapchain surfaceFormat logicalDevice = do
let createInfo = Vk.zero let createInfo = Vk.zero
{ Vk.image = tmpImage { Vk.image = tmpImage
, Vk.viewType = Vk.IMAGE_VIEW_TYPE_2D , Vk.viewType = Vk.IMAGE_VIEW_TYPE_2D
, Vk.format = (Vk.format :: Vk.SurfaceFormatKHR -> Vk.Format) surfaceFormat , Vk.format = surfaceFormat.format
, Vk.components = Vk.ComponentMapping , Vk.components = Vk.ComponentMapping
{ Vk.r = Vk.COMPONENT_SWIZZLE_IDENTITY { Vk.r = Vk.COMPONENT_SWIZZLE_IDENTITY
, Vk.g = Vk.COMPONENT_SWIZZLE_IDENTITY , Vk.g = Vk.COMPONENT_SWIZZLE_IDENTITY

View file

@ -1,6 +1,7 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedRecordDot #-}
module Draw where module Draw where
import qualified Control.Concurrent.STM as STM import qualified Control.Concurrent.STM as STM
@ -80,6 +81,7 @@ drawFrame engineData frameNumber = do
cameraData cameraData
recordCommandBuffer recordCommandBuffer
(engineData.engineAllocator)
(frameMainCommandBuffer frame) (frameMainCommandBuffer frame)
(engineRenderPass engineData) (engineRenderPass engineData)
(engineFramebuffers engineData V.! fromIntegral index) (engineFramebuffers engineData V.! fromIntegral index)

View file

@ -1,6 +1,8 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedRecordDot #-}
module Main where module Main where
import qualified Control.Concurrent.STM as STM import qualified Control.Concurrent.STM as STM
@ -9,10 +11,12 @@ import Control.Monad.Loops
import Control.Monad.IO.Class import Control.Monad.IO.Class
import Control.Monad.Trans.Resource import Control.Monad.Trans.Resource
import Data.Bits import Data.Bits
import Data.ByteString.Char8
import qualified Data.Map.Strict as M import qualified Data.Map.Strict as M
import Data.Time.Clock
import qualified Data.Vector as V import qualified Data.Vector as V
import Data.Word
import qualified SDL hiding (V2) import qualified SDL hiding (V2)
import System.IO (stdout)
import System.Mem import System.Mem
import qualified Vulkan as Vk import qualified Vulkan as Vk
import qualified Vulkan.Zero as Vk import qualified Vulkan.Zero as Vk
@ -43,6 +47,8 @@ main = do
-- create abort condition for upcoming lop -- create abort condition for upcoming lop
quit <- liftIO $ STM.newTMVarIO True quit <- liftIO $ STM.newTMVarIO True
time <- liftIO $ STM.newTMVarIO =<< getCurrentTime
average <- liftIO $ STM.newTMVarIO 0
-- main loop -- main loop
whileM_ whileM_
@ -50,11 +56,24 @@ main = do
) )
( do ( do
liftIO performMajorGC liftIO performMajorGC
now <- liftIO getCurrentTime
before <- liftIO $ STM.atomically $ STM.swapTMVar time now
let timeDiff = diffUTCTime now before
fps = recip $ nominalDiffTimeToSeconds timeDiff
liftIO $ hPutStr stdout $ pack $ "Current FPS: " <> show (floor fps) <> " \r"
number <- liftIO $ STM.atomically $ do number <- liftIO $ STM.atomically $ do
number <- STM.readTMVar frameNumber number <- STM.readTMVar frameNumber
if number == 0 then
void $ STM.swapTMVar average fps
else do
oldAverage <- STM.readTMVar average
let newAverage = (oldAverage * fromIntegral number + fps) / frameCount
frameCount = fromIntegral number + 1
void $ STM.swapTMVar average newAverage
void $ STM.swapTMVar frameNumber (succ number) void $ STM.swapTMVar frameNumber (succ number)
return number return number
-- draw -- draw
-- liftIO $ putStr $ show (recip $ nominalDiffTimeToSeconds timeDiff) <> "\r"
drawFrame engineData number drawFrame engineData number
-- poll events -- poll events
evs <- liftIO SDL.pollEvents evs <- liftIO SDL.pollEvents
@ -68,6 +87,12 @@ main = do
evs evs
) )
fps <- liftIO $ STM.atomically $ STM.readTMVar average
liftIO $ hPutStr stdout $
"\n" <>
"Average FPS: " <> pack (show fps) <> "\n"
Vk.deviceWaitIdle $ engineLogicalDevice engineData Vk.deviceWaitIdle $ engineLogicalDevice engineData
createBufferView createBufferView
@ -103,7 +128,7 @@ allocateMemory logicalDevice buffer = do
memoryRequirements <- Vk.getBufferMemoryRequirements logicalDevice buffer memoryRequirements <- Vk.getBufferMemoryRequirements logicalDevice buffer
let memoryAllocateInfo = Vk.zero let memoryAllocateInfo = Vk.zero
{ Vk.allocationSize = (Vk.size :: Vk.MemoryRequirements -> Word64) memoryRequirements { Vk.allocationSize = memoryRequirements.size
, Vk.memoryTypeIndex = error ("createBuffer: TODO: populate memoryTypeIndex!" :: String) , Vk.memoryTypeIndex = error ("createBuffer: TODO: populate memoryTypeIndex!" :: String)
} }

View file

@ -1,6 +1,7 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedRecordDot #-}
module Memory where module Memory where
import Control.Monad.IO.Class import Control.Monad.IO.Class
@ -27,9 +28,9 @@ initAllocator
-> m VMA.Allocator -> m VMA.Allocator
initAllocator physicalDevice device instance' = do initAllocator physicalDevice device instance' = do
let instanceProcAddr = castFunPtr $ let instanceProcAddr = castFunPtr $
Vk.pVkGetInstanceProcAddr ((Vk.instanceCmds :: Vk.Instance -> Vk.InstanceCmds) instance') Vk.pVkGetInstanceProcAddr (instance'.instanceCmds)
deviceProcAddr = castFunPtr $ deviceProcAddr = castFunPtr $
Vk.pVkGetDeviceProcAddr ((Vk.deviceCmds :: Vk.Device -> Vk.DeviceCmds) device) Vk.pVkGetDeviceProcAddr (device.deviceCmds)
let allocatorInfo = Vk.zero let allocatorInfo = Vk.zero
{ VMA.physicalDevice = Vk.physicalDeviceHandle physicalDevice { VMA.physicalDevice = Vk.physicalDeviceHandle physicalDevice
, VMA.device = Vk.deviceHandle device , VMA.device = Vk.deviceHandle device

View file

@ -188,4 +188,39 @@ loadFromObj filepath vma uploadContext queue device = do
texCoords V.! texCoords V.!
(fromMaybe (error "no UV coordinates present") (faceTexCoordIndex index) - 1) (fromMaybe (error "no UV coordinates present") (faceTexCoordIndex index) - 1)
in in
V2 r s -- flip V coordinate of UVs to fix display
V2 r (-s)
compactDraws
:: M.Map String Mesh
-> M.Map String Material
-> V.Vector RenderObject
-> V.Vector IndirectBatch
compactDraws meshLib materialLib objects =
V.foldl
(\acc (index, RenderObject mesh material _) ->
let newDraw = IndirectBatch
{ batchMesh = meshLib M.! mesh
, batchMaterial = materialLib M.! material
, batchFirst = index
, batchCount = 1
}
sameMesh = not (V.null acc) && (meshLib M.! mesh == batchMesh (V.last acc))
sameMaterial = not (V.null acc) && (materialLib M.! material == batchMaterial (V.last acc))
in
if sameMesh && sameMaterial
then
V.init acc `V.snoc` ((V.last acc)
{ batchCount = batchCount (V.last acc) + 1
})
else
acc `V.snoc` newDraw
)
V.empty
(V.zip
(V.fromList [0..])
objects
)

View file

@ -54,13 +54,17 @@ data AllocatedBuffer = AllocatedBuffer
} }
deriving (Show) deriving (Show)
instance Eq AllocatedBuffer where
(AllocatedBuffer buf1 _ _) == (AllocatedBuffer buf2 _ _) = buf1 == buf2
data Vertex = Vertex data Vertex = Vertex
{ vertexPosition :: V3 Float { vertexPosition :: V3 Float
, vertexNormal :: V3 Float , vertexNormal :: V3 Float
, vertexColor :: V4 Float , vertexColor :: V4 Float
, vertexUV :: V2 Float , vertexUV :: V2 Float
} }
deriving (Show) deriving (Show, Eq)
instance Storable Vertex where instance Storable Vertex where
@ -143,7 +147,7 @@ data Mesh = Mesh
{ meshVertices :: V.Vector Vertex { meshVertices :: V.Vector Vertex
, meshBuffer :: AllocatedBuffer , meshBuffer :: AllocatedBuffer
} }
deriving (Show) deriving (Show, Eq)
data MeshPushConstants = MeshPushConstants data MeshPushConstants = MeshPushConstants
{ meshPushData :: V4 Float { meshPushData :: V4 Float
@ -180,7 +184,7 @@ data Material = Material
, materialPipeline :: Vk.Pipeline , materialPipeline :: Vk.Pipeline
, materialPipelineLayout :: Vk.PipelineLayout , materialPipelineLayout :: Vk.PipelineLayout
} }
deriving (Show) deriving (Show, Eq)
data RenderObject = RenderObject data RenderObject = RenderObject
{ objectMesh :: String { objectMesh :: String
@ -223,6 +227,7 @@ data FrameData = FrameData
, frameCameraBuffer :: AllocatedBuffer , frameCameraBuffer :: AllocatedBuffer
, frameSceneBuffer :: AllocatedBuffer , frameSceneBuffer :: AllocatedBuffer
, frameObjectBuffer :: AllocatedBuffer , frameObjectBuffer :: AllocatedBuffer
, frameIndirectBuffer :: AllocatedBuffer
, frameGlobalDescriptor :: Vk.DescriptorSet , frameGlobalDescriptor :: Vk.DescriptorSet
, frameObjectDescriptor :: Vk.DescriptorSet , frameObjectDescriptor :: Vk.DescriptorSet
} }
@ -317,3 +322,10 @@ data UploadContext = UploadContext
, uploadCommandBuffer :: Vk.CommandBuffer , uploadCommandBuffer :: Vk.CommandBuffer
} }
deriving (Show) deriving (Show)
data IndirectBatch = IndirectBatch
{ batchMesh :: Mesh
, batchMaterial :: Material
, batchFirst :: Word32
, batchCount :: Word32
}

46
test.nix Normal file
View file

@ -0,0 +1,46 @@
{pkgs, vulkan-tutorial, ...}:
pkgs.nixosTest ({
name = "test";
nodes = {
machine = { config, pkgs, ...}: {
environment = {
systemPackages = with pkgs; [
vulkan-tutorial
git
shaderc
vulkan-loader
vulkan-validation-layers
];
sessionVariables = {
VK_LAYER_PATH="${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d";
SDL_VULKAN_LIBRARY="${pkgs.vulkan-loader}/lib/libvulkan.so";
};
};
hardware.opengl = {
enable = true;
driSupport = true;
driSupport32Bit = true;
};
services.xserver = {
enable = true;
displayManager.sddm.enable = true;
desktopManager.cinnamon.enable = true;
};
users.users.test = {
password = "test";
extraGroups = [
"wheel"
];
isNormalUser = true;
};
};
};
skipLint = true;
testScript = ''
start_all()
machine.shell_interact()
'';
})

View file

@ -41,7 +41,7 @@ executable vulkan-tutorial
-- LANGUAGE extensions used by modules in this package. -- LANGUAGE extensions used by modules in this package.
-- other-extensions: -- other-extensions:
build-depends: base >=4.14.3.0 build-depends: base
, sdl2 , sdl2
, vulkan , vulkan
, vulkan-utils , vulkan-utils
@ -50,6 +50,7 @@ executable vulkan-tutorial
, linear , linear
, monad-loops , monad-loops
, stm , stm
, time
, bytestring , bytestring
, text , text
, vector , vector