From c636c4bb08ffed9ce193150b845c3f07489e99a0 Mon Sep 17 00:00:00 2001 From: nek0 Date: Sun, 2 Apr 2023 10:46:02 +0200 Subject: [PATCH] invisible ambient color --- shadersrc/rainbow_lit.frag | 19 +++++++++++ src/CommandBuffer.hs | 64 +++++++++++++++++++++++++++++++------- src/Draw.hs | 3 ++ src/Init.hs | 40 ++++++++++++++++++------ src/Memory.hs | 5 ++- src/Types.hs | 46 +++++++++++++++++++++++---- src/Util.hs | 50 +++++++++++++++++++++++++++++ 7 files changed, 196 insertions(+), 31 deletions(-) create mode 100644 shadersrc/rainbow_lit.frag diff --git a/shadersrc/rainbow_lit.frag b/shadersrc/rainbow_lit.frag new file mode 100644 index 0000000..74fb132 --- /dev/null +++ b/shadersrc/rainbow_lit.frag @@ -0,0 +1,19 @@ +#version 450 + +// shader input +layout(location = 0) in vec4 fragColor; + +// output write +layout(location = 0) out vec4 outColor; + +layout(set = 0, binding = 1) uniform SceneData{ + vec4 fogColor; // w is for exponent + vec4 fogDistances; //x for min, y for max, zw unused. + vec4 ambientColor; + vec4 sunlightDirection; //w for sun power + vec4 sunlightColor; +} sceneData; + +void main() { + outColor = vec4(fragColor.xyz + sceneData.ambientColor.xyz, 1.0f); +} diff --git a/src/CommandBuffer.hs b/src/CommandBuffer.hs index 1d19335..bfbf501 100644 --- a/src/CommandBuffer.hs +++ b/src/CommandBuffer.hs @@ -24,7 +24,7 @@ import qualified VulkanMemoryAllocator as VMA import Devices import Types import Memory -import Util (getFrame) +import Util frameOverlap :: Int frameOverlap = 2 @@ -41,6 +41,8 @@ createFrames physicalDevice logicalDevice allocator descriptorPool setLayout = d queueFamilyIndex <- getQueueFamily physicalDevice Vk.QUEUE_GRAPHICS_BIT + deviceProperties <- Vk.getPhysicalDeviceProperties physicalDevice + let poolCreateInfo = Vk.zero { Vk.flags = Vk.COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT , Vk.queueFamilyIndex = queueFamilyIndex @@ -49,7 +51,7 @@ createFrames physicalDevice logicalDevice allocator descriptorPool setLayout = d graphicsQueue <- Vk.getDeviceQueue logicalDevice queueFamilyIndex 0 frames <- V.mapM - (\_ -> do + (\index -> do commandPool <- snd <$> allocate (Vk.createCommandPool logicalDevice poolCreateInfo Nothing) @@ -87,7 +89,6 @@ createFrames physicalDevice logicalDevice allocator descriptorPool setLayout = d ) cameraBuffer <- createAllocatedBuffer - logicalDevice allocator (sizeOf (GPUCameraData identity identity identity)) Vk.BUFFER_USAGE_UNIFORM_BUFFER_BIT @@ -101,20 +102,35 @@ createFrames physicalDevice logicalDevice allocator descriptorPool setLayout = d globalDescriptor <- Vk.allocateDescriptorSets logicalDevice allocationInfo - let bufferInfo = Vk.zero + let cameraInfo = Vk.zero { Vk.buffer = allocatedBuffer cameraBuffer , Vk.offset = 0 , Vk.range = fromIntegral $ sizeOf (GPUCameraData identity identity identity) } :: Vk.DescriptorBufferInfo - setWrite = Vk.zero - { Vk.dstBinding = 0 - , Vk.dstSet = V.head globalDescriptor - , Vk.descriptorCount = 1 - , Vk.descriptorType = Vk.DESCRIPTOR_TYPE_UNIFORM_BUFFER - , Vk.bufferInfo = V.singleton bufferInfo - } + sceneInfo = Vk.zero + { Vk.buffer = allocatedBuffer cameraBuffer + , Vk.offset = padUniformBufferSize + (fromIntegral $ sizeOf (undefinedGPUSceneData) * fromIntegral index) + deviceProperties + , Vk.range = fromIntegral $ sizeOf (undefinedGPUSceneData) + } :: Vk.DescriptorBufferInfo + cameraWrite = writeDescriptorBuffer + Vk.DESCRIPTOR_TYPE_UNIFORM_BUFFER + (V.head globalDescriptor) + cameraInfo + 0 + sceneWrite = writeDescriptorBuffer + Vk.DESCRIPTOR_TYPE_UNIFORM_BUFFER + (V.head globalDescriptor) + sceneInfo + 1 + setWrites = V.fromList + [ cameraWrite + , sceneWrite + ] - Vk.updateDescriptorSets logicalDevice (V.singleton (Vk.SomeStruct setWrite)) V.empty + + Vk.updateDescriptorSets logicalDevice setWrites V.empty return FrameData { framePresentSemaphore = presentSemaphore @@ -140,6 +156,9 @@ recordCommandBuffer -> Vk.Pipeline -> Vk.PipelineLayout -> VMA.Allocator + -> GPUSceneData + -> AllocatedBuffer + -> Vk.PhysicalDeviceProperties -> FrameData -> Int -> m () @@ -151,6 +170,9 @@ recordCommandBuffer graphicsPipeline meshLayout allocator + sceneParameters + sceneParameterBuffer + deviceProps frame frameNumber = do @@ -204,6 +226,24 @@ recordCommandBuffer Vk.cmdSetViewport commandBuffer 0 (V.singleton viewport) Vk.cmdSetScissor commandBuffer 0 (V.singleton scissor) + let framed = fromIntegral frameNumber / 120 + ambient = V4 (sin framed) 0 (cos framed) 1 + frameIndex = frameNumber `mod` frameOverlap + + scenePointer <- VMA.mapMemory allocator (bufferAllocation sceneParameterBuffer) + + liftIO $ poke + (castPtr scenePointer `plusPtr` + (fromIntegral $ + padUniformBufferSize (fromIntegral $ sizeOf (undefinedGPUSceneData)) deviceProps * + fromIntegral frameIndex)) + (sceneParameters + { ambientColor = ambient + } + ) + + VMA.unmapMemory allocator (bufferAllocation sceneParameterBuffer) + renderObjects <- (liftIO . STM.atomically . STM.readTMVar) =<< asks renderables meshMap <- (liftIO . STM.atomically . STM.readTMVar) =<< asks meshLibrary materialMap <- (liftIO . STM.atomically . STM.readTMVar) =<< asks materialLibrary diff --git a/src/Draw.hs b/src/Draw.hs index e3de7f8..d31b65e 100644 --- a/src/Draw.hs +++ b/src/Draw.hs @@ -63,6 +63,9 @@ drawFrame engineData frameNumber = do (materialPipeline $ matLibrary M.! "defaultMesh") (meshPipelineLayout engineData) (engineAllocator engineData) + (engineSceneParameters engineData) + (engineSceneParameterBuffer engineData) + (enginePhysicalDeviceProperties engineData) frame frameNumber diff --git a/src/Init.hs b/src/Init.hs index a179fea..c3cdb1c 100644 --- a/src/Init.hs +++ b/src/Init.hs @@ -10,17 +10,18 @@ import Control.Monad import Control.Monad.IO.Class import Control.Monad.Reader import Control.Monad.Trans.Resource -import Data.Bits (Bits(bit)) +import Data.Bits ((.|.)) import qualified Data.Vector as V import qualified SDL hiding (V2) import qualified SDL.Video.Vulkan as SDL +import Foreign (sizeOf) import Foreign.Ptr import Linear as L +import qualified VulkanMemoryAllocator as VMA import qualified Vulkan.Core10 as Vk import qualified Vulkan.Extensions.VK_KHR_swapchain as Khr import qualified Vulkan.Extensions.VK_KHR_surface as Khr import qualified Vulkan.Zero as Vk -import qualified VulkanMemoryAllocator as VMA -- internal imports @@ -32,6 +33,7 @@ import Memory import Types import Mesh import CommandBuffer +import Util initEngine :: Render EngineData @@ -99,7 +101,7 @@ initVulkan window = do createSwapchain vulkanSurface surfaceFormats dimensions vulkanLogicalDevice allocator imageViews <- getImageViewHandles swapchain surfaceFormat vulkanLogicalDevice meshVertexShader <- loadShader vulkanLogicalDevice "shadersrc/mesh.vert" "vert" - meshFragmentShader <- loadShader vulkanLogicalDevice "shadersrc/rainbow.frag" "frag" + meshFragmentShader <- loadShader vulkanLogicalDevice "shadersrc/rainbow_lit.frag" "frag" renderPass <- createRenderPass vulkanLogicalDevice (Khr.format surfaceFormat) Vk.FORMAT_D32_SFLOAT meshLayout <- createMeshPipelineLayout vulkanLogicalDevice descriptorSetLayout let meshContainer = ShaderContainer (Just meshVertexShader) (Just meshFragmentShader) @@ -138,6 +140,19 @@ initVulkan window = do descriptorSetLayout descriptorPool <$> Vk.getPhysicalDeviceProperties vulkanPhysicalDevice + <*> pure (GPUSceneData + (V4 0 0 0 0) + (V4 0 0 0 0) + (V4 0 0 0 0) + (V4 0 0 0 0) + (V4 0 0 0 0) + ) + <*> createAllocatedBuffer + allocator + (sizeOf (undefinedGPUSceneData)) + Vk.BUFFER_USAGE_UNIFORM_BUFFER_BIT + VMA.MEMORY_USAGE_CPU_TO_GPU + initScene :: (MonadReader ReadState m, MonadIO m) => m () initScene = do @@ -175,15 +190,20 @@ initDescriptors => Vk.Device -> m (Vk.DescriptorSetLayout, Vk.DescriptorPool) initDescriptors device = do - let cameraBufferBinding = Vk.zero - { Vk.binding = 0 - , Vk.descriptorCount = 1 - , Vk.descriptorType = Vk.DESCRIPTOR_TYPE_UNIFORM_BUFFER - , Vk.stageFlags = Vk.SHADER_STAGE_VERTEX_BIT - } + let cameraBind = descriptorsetLayoutBinding + Vk.DESCRIPTOR_TYPE_UNIFORM_BUFFER + Vk.SHADER_STAGE_VERTEX_BIT + 0 + sceneBind = descriptorsetLayoutBinding + Vk.DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC + (Vk.SHADER_STAGE_VERTEX_BIT .|. Vk.SHADER_STAGE_FRAGMENT_BIT) + 1 setInfo = Vk.zero { Vk.flags = Vk.DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT - , Vk.bindings = V.singleton cameraBufferBinding + , Vk.bindings = V.fromList + [ cameraBind + , sceneBind + ] } poolInfo = Vk.zero { Vk.flags = Vk.DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT diff --git a/src/Memory.hs b/src/Memory.hs index 7e22612..175f96d 100644 --- a/src/Memory.hs +++ b/src/Memory.hs @@ -49,13 +49,12 @@ initAllocator physicalDevice device instance' = do createAllocatedBuffer :: (MonadResource m, MonadIO m) - => Vk.Device - -> VMA.Allocator + => VMA.Allocator -> Int -> Vk.BufferUsageFlags -> VMA.MemoryUsage -> m AllocatedBuffer -createAllocatedBuffer device allocator allocationSize usage memoryUsage = do +createAllocatedBuffer allocator allocationSize usage memoryUsage = do let bufferInfo = Vk.zero { Vk.size = fromIntegral allocationSize , Vk.usage = usage diff --git a/src/Types.hs b/src/Types.hs index 8800510..47d69ce 100644 --- a/src/Types.hs +++ b/src/Types.hs @@ -42,6 +42,8 @@ data EngineData = EngineData , engineGlobalSetLayout :: Vk.DescriptorSetLayout , engineDescriptorPool :: Vk.DescriptorPool , enginePhysicalDeviceProperties :: Vk.PhysicalDeviceProperties + , engineSceneParameters :: GPUSceneData + , engineSceneParameterBuffer :: AllocatedBuffer } data AllocatedBuffer = AllocatedBuffer @@ -200,14 +202,46 @@ data GPUCameraData = GPUCameraData instance Storable GPUCameraData where - sizeOf (GPUCameraData view projection viewProjection) = - sizeOf view + sizeOf projection + sizeOf viewProjection + sizeOf (GPUCameraData pview pprojection pviewProjection) = + sizeOf pview + sizeOf pprojection + sizeOf pviewProjection alignment = undefined peek _ = undefined - poke ptr (GPUCameraData view projection viewProjection) = do - poke (castPtr ptr) view - poke (castPtr ptr `plusPtr` sizeOf view) projection - poke (castPtr ptr `plusPtr` sizeOf view `plusPtr` sizeOf projection) viewProjection + poke ptr (GPUCameraData pview pprojection pviewProjection) = do + poke (castPtr ptr) pview + poke (castPtr ptr `plusPtr` sizeOf pview) pprojection + poke (castPtr ptr `plusPtr` sizeOf pview `plusPtr` sizeOf pprojection) pviewProjection + +data GPUSceneData = GPUSceneData + { fogColor :: V4 Float + , fogDistance :: V4 Float + , ambientColor :: V4 Float + , sunDirection :: V4 Float + , sunColor :: V4 Float + } + +undefinedGPUSceneData :: GPUSceneData +undefinedGPUSceneData = GPUSceneData + (V4 0 0 0 0) + (V4 0 0 0 0) + (V4 0 0 0 0) + (V4 0 0 0 0) + (V4 0 0 0 0) + +instance Storable GPUSceneData where + + sizeOf (GPUSceneData fogCol fogDist ambCol sunDir sunCol) = + sizeOf fogCol + sizeOf fogDist + sizeOf ambCol + sizeOf sunDir + sizeOf sunCol + + alignment = undefined + + peek _ = undefined + + poke ptr (GPUSceneData fogCol fogDist ambCol sunDir sunCol) = do + poke (castPtr ptr) fogCol + poke (castPtr ptr `plusPtr` sizeOf fogCol) fogDist + poke (castPtr ptr `plusPtr` sizeOf fogCol `plusPtr` sizeOf fogDist) ambCol + poke (castPtr ptr `plusPtr` sizeOf fogCol `plusPtr` sizeOf fogDist `plusPtr` sizeOf ambCol) sunDir + poke (castPtr ptr `plusPtr` sizeOf fogCol `plusPtr` sizeOf fogDist `plusPtr` sizeOf ambCol `plusPtr` sizeOf sunDir) sunCol diff --git a/src/Util.hs b/src/Util.hs index 78e83db..e22e316 100644 --- a/src/Util.hs +++ b/src/Util.hs @@ -1,7 +1,17 @@ +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE DataKinds #-} module Util where +import Data.Bits + import qualified Data.Vector as V +import Data.Word (Word32) + +import qualified Vulkan as Vk +import qualified Vulkan.CStruct.Extends as Vk +import qualified Vulkan.Zero as Vk + -- internal imports import Types @@ -11,3 +21,43 @@ getFrame engineData frame = let frameVector = engineFrames engineData in frameVector V.! (frame `mod` V.length frameVector) + +padUniformBufferSize + :: Vk.DeviceSize + -> Vk.PhysicalDeviceProperties + -> Vk.DeviceSize +padUniformBufferSize origSize gpuProperties = + let minUBOAlignment = Vk.minUniformBufferOffsetAlignment $ Vk.limits gpuProperties + in + if minUBOAlignment > 0 + then (origSize + minUBOAlignment - 1) .&. complement (minUBOAlignment - 1) + else origSize + +descriptorsetLayoutBinding + :: Vk.DescriptorType + -> Vk.ShaderStageFlags + -> Word32 + -> Vk.DescriptorSetLayoutBinding +descriptorsetLayoutBinding type' stageFlags binding = + Vk.zero + { Vk.binding = binding + , Vk.descriptorCount = 1 + , Vk.descriptorType = type' + , Vk.immutableSamplers = V.empty + , Vk.stageFlags = stageFlags + } + +writeDescriptorBuffer + :: Vk.DescriptorType + -> Vk.DescriptorSet + -> Vk.DescriptorBufferInfo + -> Word32 + -> Vk.SomeStruct Vk.WriteDescriptorSet +writeDescriptorBuffer type' dstSet bufferInfo binding = Vk.SomeStruct $ + Vk.zero + { Vk.dstBinding = binding + , Vk.dstSet = dstSet + , Vk.descriptorCount = 1 + , Vk.descriptorType = type' + , Vk.bufferInfo = V.singleton bufferInfo + }