flat assembler
Message board for the users of flat assembler.

Index > Projects and Ideas > Physically Based Fluid Effect

Author
Thread Post new topic Reply to topic
donn



Joined: 05 Mar 2010
Posts: 321
donn 29 Mar 2022, 05:29
Experimenting with the Navier Stokes Equations to visualize fluids. Just uploaded a video of some early results:

"Physically Based Fluid Effect" https://youtu.be/HGWMK2RYWoM

Fluid is slightly viscous and features vorticity confinement.

The orchestration of the compute shaders is done 100% with fasmg making calls to Vulkan. The calculations are mostly done in Vulkan's Compute Shaders unfortunately, but I have a plan to switch to something better, more fasm-like (SPIR-V).

There are 6 shaders: Advection, Divergence, Jacobi Integration, Projection, Torques, and visualization.

The fluid test is currently very tightly tied to a bigger project, would not be useful to share in its entirety as is. Can speak to how any specific sections work though and probably share snippets if desired.

Also did the music in the video as an improv, more to come. Next steps are numerous, but include working with gravity, differentiating between specific kinds of fluids, improving lighting and detail, including buoyancy etc.



References
______________________________
J. Stam. Stable Fluids. August 1999
M. Harris. Fast Fluid Dynamis Simulation on the GPU. 2004
K. Crane, et al. Real-Time Simulation and Rendering of 3D Fluids. 2007
R. Fedkiw, et al. Visual Simulation of Smoke. 2001
A. Selle, et al. A Vortex Particle Method for Smoke, Water and Explosions. 2005
J. Steinhof. Modification of the Euler equations for "vorticity confinement":
Application to the computation of interacting vortex rings. 1994


Description:
Filesize: 108.08 KB
Viewed: 7816 Time(s)

Thumbnail.JPG


Post 29 Mar 2022, 05:29
View user's profile Send private message Reply with quote
donn



Joined: 05 Mar 2010
Posts: 321
donn 12 Oct 2022, 04:46
Just finished this project. Now have a liquid that is influenced by gravity and interacts with obstacles

Scene of a TOXIC FLUID:
https://youtu.be/THH_ymq69ok

A ton of other improvements too, including:
- Better visualization 1920x1080 screen (HD)
- Up to 125 samples per path (Path Tracing), though visualization is still a bit unstable and crude, crashed during many renders
- Maccormack advection
- Interpolation of level sets, visualization, etc with Monotonic Cubic Hermites
- Vorticity Confinement (swirls, more realism)
- Multiple direct lights, diffuse and specular

Method:
- 100% orchestration of Vulkan (OpenGL successor) from fasmg, dispatching compute shaders, copying memory buffers, etc.
- Compute kernels in GLSL, still haven't built with SPIR-V yet from fasmg though I did some tests. Also have some great samples to work with in decompiled shaders.
- Trickiest part on fasmg side was in binding the resources used in each shader as I needed more and more. Defined the layouts in data sections and used a builder pattern to traverse and build them. Each buffer definition was a sequence of dqs but Vulkan is very tricky and you have to be careful that Resource Descriptors, binding slots, etc each line up.

Did the music myself and first time writing and playing guitar instruments so go easy on me! Any feedback welcome, however.


Description:
Filesize: 259.07 KB
Viewed: 7264 Time(s)

Thumb.JPG


Post 12 Oct 2022, 04:46
View user's profile Send private message Reply with quote
NETSTALKER



Joined: 17 Apr 2020
Posts: 10
Location: fidonet
NETSTALKER 12 Jan 2023, 13:42
Hello. This is a very interesting project. Can you show the source code?
Post 12 Jan 2023, 13:42
View user's profile Send private message Reply with quote
NETSTALKER



Joined: 17 Apr 2020
Posts: 10
Location: fidonet
NETSTALKER 14 Jan 2024, 19:14
How are things going with the project?
Post 14 Jan 2024, 19:14
View user's profile Send private message Reply with quote
donn



Joined: 05 Mar 2010
Posts: 321
donn 15 Jan 2024, 01:25
Hey! So sorry about the massive delay here. I was meaning to respond so you would see the reply but also wanted to make the explanation adequate and do it justice.

It's going well! Currently on hold, I will come back to it to do FlipFluids, larger bodies of water, and improved visualization with Monte Carlo. Currently focusing on solid mechanics, soft bodies. Have everything set up, just testing, and the math is very hard.

The main organization:
1. VulkanTest:..........fasm

    - ScreeningTest:..........main loop that presents images to the screen and sets them up initially.

      See Sample 1 below

    - VulkanTest:..........the main loop that kicks off fluid shader dispatches

      See Sample 2 below

    - BufferTest:..........a process that copies and maps memory from shader memory
    - Fluid

      - Each shader has an .inc to setup the shader pipeline, kick it off, synchronize, etc

        include './Fluid/FluidAdvectionTest.inc'
        include './Fluid/FluidJacobianTest.inc'
        include './Fluid/FluidTorquesTest.inc'
        include './Fluid/FluidDivergenceTest.inc'
        include './Fluid/FluidProjectionTest.inc'
        include './Fluid/FluidVisTest.inc'


        See Sample 3 below

      - Each shader also has a resource file that defines what it requires in terms of buffers. These are parsed and built by a utility


2. Vulkan:..........fasm

    - Wrappers around all the Vulkan library calls and some utilities to build more complicated buffers based on configs

      - Image resources have a lot of specific settings, for exmaple
      See Sample 4 below
      See Sample 5 below


3. Fluid shaders:..........glsl (for now, which is MATLAB-like, building with SPIR-V in future)

    - These do the fluid mechanics

      VkFluidAdvection.comp etc
      See Sample 6 below
      See Sample 7 below
      See Sample 8 below



Just a sampling! I'll provide more once the solid mechanics starts showing results or something new happens here. Or, of course if you have further questions. Also recommend reading the references at the end of the video. I think they're also in the description. The one by Harris is great to start with, along with Stam. I can explain how I approached their core principles, what I followed, what I strayed from, etc, and techniques.. for example Harris only works on 2D. Also can explain the general organization of things more if needed..!



Samples
Sample 1
Code:
testPrepareScreen:
namespace testPrepareScreen
        push rbp 
        mov rbp, rsp 
        sub rsp, (8*6);+(8*6)

        ;mov rcx, [rbp+8] 
        ;mov rdx, [rbp+12] 
        label imgIndex qword at rbp-8  
        label mappedMem qword at rbp-16
        label bufferRef qword at rbp-24 
        label queueRef qword at rbp-32
        label cmdBuffer qword at rbp-40
        label vulkanRef qword at rbp-48
        ;virtual at rbp-64
        ;       newList newList
        ;end virtual    


        ;mov [flow], rcx
        mov [vulkanRef], rcx
        mov [cmdBuffer], rdx
        mov [queueRef], r8
        mov [imgIndex], r9

        and rsp, -32
        push rbx rbp rdi rsi rsp r12 r13 r14 r15
        sub rsp, 8

        mov rcx, [bufferStarted]
        cmp rcx, 1
        je skipBufferTest

        sub rsp, 8*16
        mov rdx, [imgIndex]
        mov rcx, [vulkanRef]
        call startBufferTest
        add rsp, 8*16

        skipBufferTest:
        mov rcx, 1
        mov [bufferStarted], rcx



        sub rsp, 8*8
        mov rdx, synchRefs.queueCompletionFence
        mov rcx, [vulkanRef]
        call resetFences
        add rsp, 8*8

        sub rsp, 8*16
        mov r9, synchRefs.queueCompletionFence
        mov r8, vkQueueRefs.queue1
        mov rdx, [cmdBuffer]
        mov rcx, [vulkanRef]
        call submitQueue
        add rsp, 8*16



        waitLastPresentFenceCompletion:



        sub rsp, 8*8
        mov rdx, synchRefs.queueCompletionFence
        mov rcx, [vulkanRef]
        call getFenceStatus
        add rsp, 8*8





        cmp rax, 0
        jne waitLastPresentFenceCompletion
        





        sub rsp, 8*8
        mov rdx, synchRefs.queueCompletionFence
        mov rcx, [vulkanRef]
        call resetFences
        add rsp, 8*8




        completed:

        mov rax,0;[bufferRef]



        add rsp, 8      
        pop r15 r14 r13 r12 rsp rsi rdi rbp rbx

        mov rsp, rbp
        pop rbp

        retn 0
end namespace
    


Sample 2
Code:
        jmp endScreenTest
        presureJacobianPass:

        mov rcx, [pressureLevel]
        cmp rcx, 2
        jne lowPress

        mov rdx, 1200           ; high pressure iterations
        jmp pressureDefined
        lowPress:
        cmp rcx, 0
        jne medPress
        mov rdx, 400            ; low pressure iterations
        jmp pressureDefined
        medPress:
        mov rdx, 900            ; med pressure iterations

        ;mov rdx, 1200;400;;500;                ; 500 is harris' max amt        100;55
        pressureDefined:
        mov [iterCount], rdx





        ; Pressure Jacobian


        nextPressIter:                                  ; next pressure jacobian iteration
        mov rcx, [iterInd]
        mov rdx, [iterCount]
        cmp rcx, rdx
        jnl endPressIter


        ;nextSlicePress:
        ;sub rsp, 8*8
        ;call getSliceIndex
        ;add rsp, 8*8
        ;mov rcx, rax
        ;cmp rcx, 1b                                    ; final slice reached
        ;je doneSlicePress


        sub rsp, 8*16
        mov r12, vulkan.vkQueueRefs.queue1
        mov qword [rsp+4*8], r12
        mov r9, [currIndex]
        mov r8, [vulkan.fluidJacPipelineInfoRef]
        mov rdx, 0                                      ; set index
        mov rcx, [vulkanRef]
        call vulkan.testFluidJacobian
        add rsp, 8*16




        ;jmp nextSlicePress
        ;doneSlicePress:




        mov rcx, [iterInd]
        add rcx, 1b
        mov [iterInd], rcx

        jmp nextPressIter
        endPressIter:

    

Sample 3
Code:
namespace vulkan

prepareFluidJacobianTest:
namespace prepareFluidJacobianTest
        push rbp 
        mov rbp, rsp 
        sub rsp, (8*6);+(8*6)

        ;mov rcx, [rbp+8] 
        ;mov rdx, [rbp+12] 
        label heapAddress qword at rbp-8  
        label mappedMem qword at rbp-16
        label bufferRef qword at rbp-24 
        label memoryRef qword at rbp-32
        label prevItem qword at rbp-40
        label vulkanRef qword at rbp-48
        ;virtual at rbp-64
        ;       newList newList
        ;end virtual    


        ;mov [flow], rcx
        mov [vulkanRef], rcx
        ;mov [newList], rdx


        and rsp, -32
        push rbx rbp rdi rsi rsp r12 r13 r14 r15
        sub rsp, 8




        ;mov rbx, vkImgResourceDefsRefLoc       ; offsetBase used with resources
        ;mov rdx, [vkImgResDefsRef]
        ;mov [rbx], rdx                         ; Already cached by Advection




        sub rsp, 8*8
        mov r8, fluidJacResInfo
        mov rdx, fluidJacPipelineInfo
        mov rcx, [vulkanRef]
        call newPipeline
        add rsp, 8*8
        mov [fluidJacPipelineInfoRef], rax



        sub rsp, 8*16
        mov r9, fluidJacResMemImgs
        mov r8, fluidJacResDefs
        mov rdx, [fluidJacPipelineInfoRef]
        mov rcx, [vulkanRef]
        call setupPipeline
        add rsp, 8*16

        mov rbx, [fluidJacPipelineInfoRef]      
        add rbx, pipelineInfo.resourceInfoRefLoc - pipelineInfo
        mov rdx, [rbx]
        mov [fluidJacResInfoRef], rdx
        add rdx, resourceInfo.resourceDefsRefLoc - resourceInfo
        mov r8, [rdx]
        mov [fluidJacResDefsRef], r8




        sub rsp, 8*8
        mov rcx, fluidJacobianCompletedMsg
        call debugMsg2
        add rsp, 8*8
        




        sub rsp, 8*16
        mov r8, 0                               ; [setIndex]
        mov rdx, [fluidJacResInfoRef]
        mov rcx, [vulkanRef]
        call prepareRecordSetEntry
        add rsp, 8*16




        sub rsp, 8*16
        mov r10, [fluidJacPipelineInfoRef]
        mov qword [rsp+5*8], r10
        mov rbx, [fluidJacResDefsRef]
        add rbx, (fluidJacResDefs.set1.setRef - fluidJacResDefs)
        mov r10, rbx                            ; descriptorSetsRef.ref1
        mov qword [rsp+4*8], r10
        mov r9, swapchainImagesRef.img1
        mov r8, [bufferRef]
        mov r12, [fluidJacPipelineInfoRef]
        add r12, pipelineInfo.cmdBuffersRefLocs - pipelineInfo
        mov r11, [r12]
        add r11, 8*0                                    ; set1
        mov rdx, r11
        mov rcx, [vulkanRef]
        call recordFluidJacDispatchCmd
        add rsp, 8*16










        completed:

        sub rsp, 8*8
        mov rcx, fluidJacobianCompletedMsg
        call debugMsg2
        add rsp, 8*8


        mov rax,0;[bufferRef]



        add rsp, 8      
        pop r15 r14 r13 r12 rsp rsi rdi rbp rbx

        mov rsp, rbp
        pop rbp

        retn 0
end namespace





testFluidJacobian:
namespace testFluidJacobian
        push rbp 
        mov rbp, rsp 
        mov r10, [rsp+8*6]
        sub rsp, (8*9);+(8*6)

        ;mov rcx, [rbp+8] 
        ;mov rdx, [rbp+12] 
        label imgIndex qword at rbp-8  
        label mappedMem qword at rbp-16
        label bufferRef qword at rbp-24 
        label queueRef qword at rbp-32
        label cmdBuffer qword at rbp-40
        label vulkanRef qword at rbp-48
        label pipelineInfoRef qword at rbp-56
        label setIndex qword at rbp-64
        label resDefsRef qword at rbp-72
        ;virtual at rbp-64
        ;       newList newList
        ;end virtual    


        ;mov [flow], rcx
        mov [vulkanRef], rcx
        mov [setIndex], rdx
        mov [pipelineInfoRef], r8
        mov [imgIndex], r9
        mov [queueRef], r10

        and rsp, -32
        push rbx rbp rdi rsi rsp r12 r13 r14 r15
        sub rsp, 8



        sub rsp, 8*8
        mov rcx, testFluidJacobianStartingMsg
        ;call debugMsg2
        add rsp, 8*8

        mov rbx, [pipelineInfoRef]
        add rbx, pipelineInfo.resourceInfoRefLoc - pipelineInfo
        mov rdx, [rbx]
        add rdx, resourceInfo.resourceDefsRefLoc - resourceInfo
        mov r8, [rdx]
        mov [resDefsRef], r8



        mov rbx, [pipelineInfoRef]
        add rbx, pipelineInfo.cmdBuffersRefLocs - pipelineInfo
        mov r8, [rbx]
        mov rdx, 0
        mov rcx, 8
        mov rax, [setIndex]
        imul rcx
        add r8, rax
        mov [cmdBuffer], r8


        mov rcx, [bufferStarted]
        cmp rcx, 1
        je skipBufferTest

        sub rsp, 8*16
        mov rdx, [imgIndex]
        mov rcx, [vulkanRef]
        call startBufferTest
        add rsp, 8*16




        skipBufferTest:
        mov rcx, 1
        mov [bufferStarted], rcx





        sub rsp, 8*8
        mov rdx, synchRefs.queueCompletionFence
        mov rcx, [vulkanRef]
        call resetFences
        add rsp, 8*8



        sub rsp, 8*16
        mov r9, synchRefs.queueCompletionFence
        mov r8, [queueRef]
        mov rdx, [cmdBuffer]
        mov rcx, [vulkanRef]
        call submitQueue2
        add rsp, 8*16






        waitLastPresentFenceCompletion:





        sub rsp, 8*8
        mov rdx, synchRefs.queueCompletionFence
        mov rcx, [vulkanRef]
        call getFenceStatus
        add rsp, 8*8





        cmp rax, 0
        jne waitLastPresentFenceCompletion
        ; What should signal be?









        sub rsp, 8*8
        mov rdx, synchRefs.queueCompletionFence
        mov rcx, [vulkanRef]
        call resetFences
        add rsp, 8*8


        jmp skippedDebugBuff

        sub rsp, 8*8
        mov rcx, debugBreakMsg
        call debugMsg2
        add rsp, 8*8


        sub rsp, 8*8
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.mappedMem- resourceMemImg)
        mov rdx, [r10]        ;[memRefs.ref1]
        ;mov rdx, [r11]
        add rdx, testBuffer1Ref.output1 - testBuffer1Ref
        mov ecx, dword [rdx]
        call debugNumMsg
        add rsp, 8*8

        ;sub rsp, 8*8
        ;mov r11, [memRefs.ref1]
        ;mov rdx, [r11]
        ;add rdx, testBuffer1Ref.output2 - testBuffer1Ref
        ;mov ecx, dword [rdx]
        ;call debugNumMsg
        ;add rsp, 8*8



        sub rsp, 8*8
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.mappedMem- resourceMemImg)
        mov rdx, [r10]        ;[memRefs.ref1]
        ;mov rdx, [r11]
        add rdx, testBuffer1Ref.output2 - testBuffer1Ref
        mov ecx, dword [rdx]
        call debugNumMsg
        add rsp, 8*8


        sub rsp, 8*8
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.mappedMem- resourceMemImg)
        mov rdx, [r10]        ;[memRefs.ref1]
        ;mov rdx, [r11]
        add rdx, testBuffer1Ref.output3 - testBuffer1Ref
        mov ecx, dword [rdx]
        call debugNumMsg
        add rsp, 8*8


        sub rsp, 8*8
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.mappedMem- resourceMemImg)
        mov rdx, [r10]        ;[memRefs.ref1]
        ;mov rdx, [r11]
        add rdx, testBuffer1Ref.output4 - testBuffer1Ref
        mov ecx, dword [rdx]
        call debugNumMsg
        add rsp, 8*8


        sub rsp, 8*8
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.mappedMem- resourceMemImg)
        mov rdx, [r10]        ;[memRefs.ref1]
        ;mov rdx, [r11]
        add rdx, testBuffer1Ref.output5 - testBuffer1Ref
        mov ecx, dword [rdx]
        call debugNumMsg
        add rsp, 8*8



        sub rsp, 8*8
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.mappedMem- resourceMemImg)
        mov rdx, [r10]        ;[memRefs.ref1]
        ;mov rdx, [r11]
        add rdx, testBuffer1Ref.output6 - testBuffer1Ref
        mov ecx, dword [rdx]
        call debugNumMsg
        add rsp, 8*8




        jmp skippedDebugBuff




        skippedDebugBuff:



        flushAgain:
        ;jmp skipFlushAgain


        sub rsp, 8*8
        mov r8, 100
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.mappedMem- resourceMemImg)
        mov rdx, [r10]        ;[memRefs.ref1]                           ; this needs new ref
        mov rcx, testBuffer1Ref
        call allocate.copy
        add rsp, 8*8


        
        sub rsp, 8*8
        mov rcx, flushMappedMemMsg
        ;call debugMsg2
        add rsp, 8*8


        sub rsp, 8*16
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.memSize- resourceMemImg)
        mov r9, [r10]        ;[memRefs.ref1]                            ; this needs new ref
        mov r8, 0
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.memRefLoc- resourceMemImg)
        mov r11, [r10]        ;rawMemRefs.ref1          ; this needs new ref
        mov rdx, [r11]          ; VkDeviceMemory*
        mov rcx,[vulkanRef]
        ;call debugParams
        add rsp, 8*16


        sub rsp, 8*8
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.memSize- resourceMemImg)
        mov r9, [r10]        ;[memRefs.ref1]                            ; this needs new ref
        mov r8, 0
        mov rbx, [resDefsRef]
        add rbx, (vkImgResDefs.set1.res1 - vkImgResDefs)+(resourceEntry.resourceMemImgRefLoc - resourceEntry)
        mov r10, [rbx]
        add r10, (resourceMemImg.memRefLoc- resourceMemImg)
        mov r11, [r10]        ;rawMemRefs.ref1          ; this needs new ref
        mov rdx, [r11]          ; VkDeviceMemory*
        mov rcx,[vulkanRef]
        call flushMappedMem
        add rsp, 8*8

        skipFlushAgain:



        completed:


        sub rsp, 8*8
        mov rcx, testFluidJacobianCompletedMsg
        ;call debugMsg2
        add rsp, 8*8

        mov rax,0;[bufferRef]



        add rsp, 8      
        pop r15 r14 r13 r12 rsp rsi rdi rbp rbx

        mov rsp, rbp
        pop rbp

        retn 0
end namespace



; call
recordFluidJacDispatchCmd:
namespace recordFluidJacDispatchCmd
        push rbp 
        mov rbp, rsp 
        mov r10, [rsp+8*6]
        mov r11, [rsp+8*7]

        sub rsp, (8*6);+(8*6)
        ;mov r11, [rsp+8*7]
        ;mov r12, [rsp+8*8]

        ;mov rcx, [rbp+8] 
        ;mov rdx, [rbp+12] 
        label pipelineInfoRef qword at rbp-8  
        label imgRef qword at rbp-16
        label bufferRef qword at rbp-24 
        label descriptorSetRef qword at rbp-32
        label cmdBuffer qword at rbp-40
        label vulkanRef qword at rbp-48
        ;virtual at rbp-64
        ;       newList newList
        ;end virtual    


        mov [vulkanRef], rcx
        mov [cmdBuffer], rdx
        mov [bufferRef], r8
        mov [imgRef], r9
        mov [descriptorSetRef], r10
        mov [pipelineInfoRef], r11

        and rsp, -32
        push rbx rbp rdi rsi rsp r12 r13 r14 r15
        sub rsp, 8






        sub rsp, 8*8
        mov rdx, [cmdBuffer]
        mov rcx, [vulkanRef]
        call beginRecordCmd
        add rsp, 8*8



        sub rsp, 8*16
        mov r9, [descriptorSetRef]
        mov r8, [pipelineInfoRef]
        mov rdx, [cmdBuffer]
        mov rcx, [vulkanRef]
        call bindDescriptorSets         ; vkCmdBind
        add rsp, 8*16


        sub rsp, 8*8
        mov r8, [pipelineInfoRef]
        mov rdx, [cmdBuffer]
        mov rcx, [vulkanRef]
        call bindPipelines              ; vkCmdBind
        add rsp, 8*8








        ;sub rsp, 8*16
        ;mov r8, [imgRef]
        ;mov rdx, [cmdBuffer]
        ;mov rcx, [vulkanRef]
        ;call clearImgCmd
        ;add rsp, 8*16



        mov rbx, [fluidAdvResDefsRef]   ; MOVE TEMPPOINTS TO POINTS     should only be done once
        add rbx, (fluidAdvResDefs.set1.res9 - fluidAdvResDefs) + (resourceEntry.resRef - resourceEntry)
        mov r8, [rbx]                           ; descriptorSetsRef.ref9
        mov rdx, advecTempPointsToPointsbufferCopyInfoRef.srcBufferRef
        mov [rdx], r8

        mov rbx, [fluidAdvResDefsRef]
        add rbx, (fluidAdvResDefs.set1.res2 - fluidAdvResDefs) + (resourceEntry.resRef - resourceEntry)
        mov r8, [rbx]                           ; descriptorSetsRef.ref2
        mov rdx, advecTempPointsToPointsbufferCopyInfoRef.dstBufferRef
        mov [rdx], r8

        mov rbx, [fluidAdvResDefsRef]
        add rbx, (fluidAdvResDefs.set1.res9 - fluidAdvResDefs) + (resourceEntry.resSize - resourceEntry)
        mov r8, [rbx]                           ; descriptorSetsRef.ref9
        mov rdx, advecTempPointsToPointsbufferCopyInfoRef.vkSize
        mov [rdx], r8


        sub rsp, 8*16
        mov r8, advecTempPointsToPointsbufferCopyInfoRef
        mov rdx, [cmdBuffer]
        mov rcx, [vulkanRef]
        ;call copyBufferCmd
        add rsp, 8*16



        ;cmp baseICount, 0                      ; use dispatch or dispatchBase, get these baseCounts from pipelein or within pipelien
        ;boundHalfWidth*2.0 / sliceWidth
        ;baseIIndex 
        ;baseJIndex


        sub rsp, 8*8
        mov rdx, [cmdBuffer]
        mov rcx, [vulkanRef]
        ;call dispatchCmdBuffer
        add rsp, 8*8


        sub rsp, 8*16
        mov rdx, [cmdBuffer]
        mov rcx, [vulkanRef]
        call dispatchLinearCmdBuffers
        add rsp, 8*16



        sub rsp, 8*8
        mov rdx, [cmdBuffer]
        mov rcx, [vulkanRef]
        call endRecordCmd
        add rsp, 8*8


        sub rsp, 8*8
        mov rcx, rax
        call debugNumMsg
        add rsp, 8*8




        completed:

        mov rax, 0



        add rsp, 8      
        pop r15 r14 r13 r12 rsp rsi rdi rbp rbx

        mov rsp, rbp
        pop rbp

        retn 0
end namespace


end namespace

    

Sample 4
Code:
; setup pipeline once data specified
setupPipeline:
namespace setupPipeline
        push rbp 
        mov rbp, rsp 
        sub rsp, (8*10);+(8*6)

        ;mov rcx, [rbp+8] 
        ;mov rdx, [rbp+12] 
        label resourceEntriesRef qword at rbp-8  
        label resourceMemImgsRef qword at rbp-16
        label pipelineCacheRef qword at rbp-24 
        label pipelineVals qword at rbp-32
        label pipelineInfoRef qword at rbp-40
        label vulkanRef qword at rbp-48
        label resourceEntriesVals qword at rbp-56
        label resourceInfoRef qword at rbp-64
        label descriptorSetCount qword at rbp-72
        label descriptorSetIndex qword at rbp-80
        ;virtual at rbp-64
        ;       newList newList
        ;end virtual    


        ;mov rdx, swapchainImagesRef.img1
        ;mov r8, imageViewRef.ref1


        mov [vulkanRef], rcx
        mov [pipelineInfoRef], rdx
        mov [resourceEntriesRef], r8
        mov [resourceMemImgsRef], r9


        and rsp, -32
        push rbx rbp rdi rsi rsp r12 r13 r14 r15
        sub rsp, 8


        sub rsp, 8*8
        mov rcx, setupPipelineStartingMsg
        call debugMsg2
        add rsp, 8*8


        sub rsp, 8*8
        mov rcx, [pipelineInfoRef]
        call loadSPIRV
        add rsp, 8*8

        sub rsp, 8*8
        mov rdx, [pipelineInfoRef]
        mov rcx, [vulkanRef]
        call newShaderModule
        add rsp, 8*8







        sub rsp, 8*8
        mov r8,  [resourceEntriesRef]
        mov rdx, [pipelineInfoRef]
        mov rcx, [vulkanRef]
        call newDescriptorSetLayout
        add rsp, 8*8



        sub rsp, 8*8
        mov rdx, [pipelineInfoRef]
        mov rcx, [vulkanRef]
        call newPipelineLayout
        add rsp, 8*8



        sub rsp, 8*8
        mov r8, [pipelineInfoRef]
        mov rdx, 0                      ; cache
        mov rcx, [vulkanRef]
        call newComputePipeline         ; requires pipelineLayout, shaderModule
        add rsp, 8*8





        sub rsp, 8*16
        mov r9, [resourceMemImgsRef]
        mov r8, [resourceEntriesRef]
        mov rdx, [pipelineInfoRef]
        mov rcx, [vulkanRef]
        call buildResources
        add rsp, 8*16


        mov rcx, 0
        mov [descriptorSetIndex], rcx



        mov rbx, [pipelineInfoRef]
        add rbx, pipelineInfo.resourceInfoRefLoc - pipelineInfo
        mov r10, [rbx]
        mov [resourceInfoRef], r10
        add r10, resourceInfo.resourceDefsRefLoc - resourceInfo
        mov rdx, [r10]
        mov [resourceEntriesVals], rdx



        mov r10, [resourceInfoRef]
        add r10, resourceInfo.descriptorSetCount - resourceInfo
        mov rcx, [r10]
        mov [descriptorSetCount], rcx

        nextSet:
        mov rdx, [descriptorSetCount]
        mov rcx, [descriptorSetIndex]
        cmp rcx, rdx
        jnl completed

        sub rsp, 8*8
        mov rcx, nextSetMsg
        call debugMsg2
        add rsp, 8*8


        mov r12, [pipelineInfoRef]
        add r12, pipelineInfo.cmdBuffersRefLocs - pipelineInfo
        mov r11, [r12]
        mov rcx, [descriptorSetIndex]
        mov rax, 8
        mov rdx, 0
        imul rcx
        add r11, rax
        sub rsp, 8*8
        mov r8, r11
        mov rdx, 0                      ; cmd Pool index
        mov rcx, [vulkanRef]
        call allocCmdBuffer
        add rsp, 8*8



        mov rbx, [resourceEntriesVals]
        mov r10, [resourceInfoRef]
        add r10, resourceInfo.setEntrySize - resourceInfo
        mov rcx, [r10]
        add rbx, rcx
        mov [resourceEntriesVals], rbx                                  ; go past setEntry



        sub rsp, 8*16
        mov rbx, [resourceInfoRef]
        add rbx, resourceInfo.resourceDefsRefLoc - resourceInfo
        mov r9, [rbx]                                                   ; base resourceentriesref so copying of resources from it can occur 
        mov r10, [resourceInfoRef]
        add r10, resourceInfo.bindingsCount - resourceInfo
        mov r8, [r10]                                                   ; resCount
        mov rdx, [resourceEntriesVals]                                  ; resourceEntriesRef
        mov rcx, [vulkanRef]
        call buildBuffers
        add rsp, 8*16



        mov rbx, [resourceEntriesVals]
        mov r10, [resourceInfoRef]
        add r10, resourceInfo.entriesSize - resourceInfo
        mov rcx, [r10]
        add rbx, rcx
        mov [resourceEntriesVals], rbx                                  ; go past setEntry


        mov rcx, [descriptorSetIndex]
        add rcx, 1b
        mov [descriptorSetIndex], rcx
        
        jmp nextSet


        completed:

        mov rax, [pipelineInfoRef]



        add rsp, 8      
        pop r15 r14 r13 r12 rsp rsi rdi rbp rbx

        mov rsp, rbp
        pop rbp

        retn 0
end namespace
    

Sample 5
Code:
; call vkEnumeratePhysicalDevices
enumPhysDevs:
namespace enumPhysDevs
        push rbp 
        mov rbp, rsp 
        sub rsp, (8*6);+(8*6)

        ;mov rcx, [rbp+8] 
        ;mov rdx, [rbp+12] 
        label heapAddress qword at rbp-8  
        label handleAllocatedMemory qword at rbp-16
        label newList qword at rbp-24 
        label flow qword at rbp-32
        label prevItem qword at rbp-40
        label vulkanRef qword at rbp-48
        ;virtual at rbp-64
        ;       newList newList
        ;end virtual    


        mov [vulkanRef], rcx
        ;mov [newList], rdx


        and rsp, -32
        push rbx rbp rdi rsi rsp r12 r13 r14 r15
        sub rsp, 8




        ; vkInstanceRef
        ; 0
        ; vkInstanceCreateInfoRef
        sub rsp, 8*8
        mov rbx, [vulkanRef]
        add rbx, Vulkan.devicesAddr
        mov r8, rbx;[rbx]
        mov rbx, [vulkanRef]
        add rbx, Vulkan.deviceCount
        mov rdx, rbx;[rbx]
        mov rbx, [vulkanRef]
        add rbx, Vulkan.vkInstanceRef
        mov rcx, [rbx]
        mov rbx, vkEnumeratePhysicalDevicesProc
        mov r10, [rbx]
        call r10
        add rsp, 8*8
        ;mov [vkCreateInstanceProc], rax

        ;sub rsp, 8*8
        ;mov rcx, rax
        ;call debugNumMsg
        ;add rsp, 8*8


        completed:

        mov rax, 0



        add rsp, 8      
        pop r15 r14 r13 r12 rsp rsi rdi rbp rbx

        mov rsp, rbp
        pop rbp

        retn 0
end namespace
    

Sample 6
Code:
void main() {
        ivec2 pathPos = ivec2(0,0);
        pathPos.x = int(gl_LocalInvocationID.x);
        pathPos.y = int(gl_LocalInvocationID.y);
        int baseI = int(gl_WorkGroupID.x);
        int baseJ = int(gl_WorkGroupID.y);
        int baseK = int(gl_WorkGroupID.z);
        
        ivec2 slicePathPos = pathPos;
        int sliceHeight = b1.b1s[0].sliceHeight;        //32;
        int sliceWidth  = b1.b1s[0].sliceWidth;         //32;           // should not specify these manually!
        float atmosphericPressure = 0.0;//0.001;//0.0;//0.001;
        float boundsPressure = 0.0;//100.0;//0.001;

        vec3 bounds1[8]; 
        vec3 bounds2[8]; 
        Bearing bearing;

        bearing = updateBearingSlices(bearing, baseI, baseJ, baseK);
        Fluid fluid = b1.b1s[0].fluid;

        fluid.boundHalfWidth = b1.b1s[0].fluid.boundHalfWidth;  //112.0f;//85;//60;180;//85;//60.0;//64.0;//128.0;//256;
        fluid.boundHalfLength = b1.b1s[0].fluid.boundHalfLength;        //45.0f;//42;72;//42;//28.0;//32.0;// 64.0;//128;
        fluid.boundHalfHeight = b1.b1s[0].fluid.boundHalfHeight;        //64.0f;//42;72;//42;//28.0;//32.0;//64.0;//128;
            


Sample 7
Code:
// 1 if diffusion, 0 if pressure calc. 
vec3 jacobian(Fluid fluid, PSample pSample, PSample velSample, float divergenceAmt, int jacobianDiffusion){

        vec3 jacobianAmt;
        float betaVal;
        float timeStep = fluid.timeStep;
        if (jacobianDiffusion == 1 ){
                vec3 fieldL = velSample.velocities[0];
                vec3 fieldR = velSample.velocities[1];
                vec3 fieldD = velSample.velocities[2];
                vec3 fieldT = velSample.velocities[3];
                vec3 fieldF = velSample.velocities[4];
                vec3 fieldB = velSample.velocities[5];
                float alphVal = 0.0;
                //alphVal = 1.0/((0.000001)*timeStep);  // water   0.0001    gas 0.000001?
                alphVal = 1.0/((0.0001)*timeStep);      // water   0.0001    gas 0.000001?
                //alphVal = 1.0/((0.1)*timeStep);       // water   0.0001    gas 0.000001?      // new way

                jacobianAmt = (fieldL + fieldR + fieldD + fieldT + fieldF + fieldB + (alphVal*velSample.cellVelocity)) / (6.0+alphVal);

        }else{
                betaVal = 6.0;
                float fieldL = pSample.pressures[0];
                float fieldR = pSample.pressures[1];
                float fieldD = pSample.pressures[2];
                float fieldT = pSample.pressures[3];
                float fieldF = pSample.pressures[4];
                float fieldB = pSample.pressures[5];
        

                jacobianAmt.x = (fieldL + fieldR + fieldD + fieldT + fieldF + fieldB - divergenceAmt) / betaVal;

        }

        return jacobianAmt;
}
    

Sample 8
Code:
float divergence(Fluid fluid, PSample pSample){
        float divergenceAmt;
        vec3 fieldL = pSample.velocities[0];    //.lVelocity;
        vec3 fieldR = pSample.velocities[1];    //.rVelocity;
        vec3 fieldD = pSample.velocities[2];    //.dVelocity;
        vec3 fieldT = pSample.velocities[3];    //.tVelocity;
        vec3 fieldF = pSample.velocities[4];    //.fVelocity;
        vec3 fieldB = pSample.velocities[5];    //.bVelocity;

        divergenceAmt = 0.5f * ((fieldR.x - fieldL.x) + 
                            (fieldT.y - fieldD.y) +
                            (fieldF.z - fieldB.z));


        return divergenceAmt;
}    
Post 15 Jan 2024, 01:25
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1847
Roman 15 Jan 2024, 15:43
Sample 6 compute shader.
Its explained why so small asm code for Vulkan API
Post 15 Jan 2024, 15:43
View user's profile Send private message Reply with quote
donn



Joined: 05 Mar 2010
Posts: 321
donn 15 Jan 2024, 16:58
Samples 6-8 are parts of compute shaders. Each compute shader is ~3000 lines of GLSL.

Quote:
3. Fluid shaders:..........glsl (for now, which is MATLAB-like, building with SPIR-V in future)


You can do this in fasm, but it would be faster to dispatch as a shader, not on the CPU.

I'm also in the middle of building binary versions of the compute shaders from fasm. So this would be binary, not asm. SPIR-V asm of Sample 7 looks like this:

Code:
57(jacobian(struct-Fluid-vf3-f1-f1-f1-vf3[8]-vf3[6]-f1-vf3-f1-vf3-vf3-i11;struct-PSample-vf3-vf3-vf3[6]-f1-i1-f1[6]-i1[6]1;struct-PSample-vf3-vf3-vf3[6]-f1-i1-f1[6]-i1[6]1;f1;i1;):   10(fvec3) Function None 51
       52(fluid):     17(ptr) FunctionParameter
     53(pSample):     36(ptr) FunctionParameter
   54(velSample):     36(ptr) FunctionParameter
55(divergenceAmt):     37(ptr) FunctionParameter
56(jacobianDiffusion):     25(ptr) FunctionParameter
              58:             Label
   392(timeStep):     37(ptr) Variable Function
     400(fieldL):    211(ptr) Variable Function
     403(fieldR):    211(ptr) Variable Function
     406(fieldD):    211(ptr) Variable Function
     409(fieldT):    211(ptr) Variable Function
     412(fieldF):    211(ptr) Variable Function
     415(fieldB):    211(ptr) Variable Function
    418(alphVal):     37(ptr) Variable Function
423(jacobianAmt):    211(ptr) Variable Function
    446(betaVal):     37(ptr) Variable Function
     447(fieldL):     37(ptr) Variable Function
     450(fieldR):     37(ptr) Variable Function
     453(fieldD):     37(ptr) Variable Function
     456(fieldT):     37(ptr) Variable Function
     459(fieldF):     37(ptr) Variable Function
     462(fieldB):     37(ptr) Variable Function
             394:     37(ptr) AccessChain 52(fluid) 393
             395:    9(float) Load 394
                              Store 392(timeStep) 395
             396:      6(int) Load 56(jacobianDiffusion)
             397:    63(bool) IEqual 396 87
                              SelectionMerge 399 None
                              BranchConditional 397 398 445
             398:               Label
             401:    211(ptr)   AccessChain 54(velSample) 112 67
             402:   10(fvec3)   Load 401
                                Store 400(fieldL) 402
             404:    211(ptr)   AccessChain 54(velSample) 112 87
             405:   10(fvec3)   Load 404
                                Store 403(fieldR) 405
             407:    211(ptr)   AccessChain 54(velSample) 112 112
             408:   10(fvec3)   Load 407
                                Store 406(fieldD) 408
             410:    211(ptr)   AccessChain 54(velSample) 112 100
             411:   10(fvec3)   Load 410
                                Store 409(fieldT) 411
             413:    211(ptr)   AccessChain 54(velSample) 112 324
             414:   10(fvec3)   Load 413
                                Store 412(fieldF) 414
             416:    211(ptr)   AccessChain 54(velSample) 112 339
             417:   10(fvec3)   Load 416
                                Store 415(fieldB) 417
                                Store 418(alphVal) 272
             420:    9(float)   Load 392(timeStep)
             421:    9(float)   FMul 419 420
             422:    9(float)   FDiv 191 421
                                Store 418(alphVal) 422
             424:   10(fvec3)   Load 400(fieldL)
             425:   10(fvec3)   Load 403(fieldR)
             426:   10(fvec3)   FAdd 424 425
             427:   10(fvec3)   Load 406(fieldD)
             428:   10(fvec3)   FAdd 426 427
             429:   10(fvec3)   Load 409(fieldT)
             430:   10(fvec3)   FAdd 428 429
             431:   10(fvec3)   Load 412(fieldF)
             432:   10(fvec3)   FAdd 430 431
             433:   10(fvec3)   Load 415(fieldB)
             434:   10(fvec3)   FAdd 432 433
             435:    9(float)   Load 418(alphVal)
             436:    211(ptr)   AccessChain 54(velSample) 87
             437:   10(fvec3)   Load 436
             438:   10(fvec3)   VectorTimesScalar 437 435
             439:   10(fvec3)   FAdd 434 438
             441:    9(float)   Load 418(alphVal)
             442:    9(float)   FAdd 440 441
             443:   10(fvec3)   CompositeConstruct 442 442 442
             444:   10(fvec3)   FDiv 439 443
                                Store 423(jacobianAmt) 444
                                Branch 399
             445:               Label
                                Store 446(betaVal) 440
             448:     37(ptr)   AccessChain 53(pSample) 339 67
             449:    9(float)   Load 448
                                Store 447(fieldL) 449
             451:     37(ptr)   AccessChain 53(pSample) 339 87
             452:    9(float)   Load 451
                                Store 450(fieldR) 452
             454:     37(ptr)   AccessChain 53(pSample) 339 112
             455:    9(float)   Load 454
                                Store 453(fieldD) 455
             457:     37(ptr)   AccessChain 53(pSample) 339 100
             458:    9(float)   Load 457
                                Store 456(fieldT) 458
             460:     37(ptr)   AccessChain 53(pSample) 339 324
             461:    9(float)   Load 460
                                Store 459(fieldF) 461
             463:     37(ptr)   AccessChain 53(pSample) 339 339
             464:    9(float)   Load 463
                                Store 462(fieldB) 464
             465:    9(float)   Load 447(fieldL)
             466:    9(float)   Load 450(fieldR)
             467:    9(float)   FAdd 465 466
             468:    9(float)   Load 453(fieldD)
             469:    9(float)   FAdd 467 468
             470:    9(float)   Load 456(fieldT)
             471:    9(float)   FAdd 469 470
             472:    9(float)   Load 459(fieldF)
             473:    9(float)   FAdd 471 472
             474:    9(float)   Load 462(fieldB)
             475:    9(float)   FAdd 473 474
             476:    9(float)   Load 55(divergenceAmt)
             477:    9(float)   FSub 475 476
             478:    9(float)   Load 446(betaVal)
             479:    9(float)   FDiv 477 478
             480:     37(ptr)   AccessChain 423(jacobianAmt) 64
                                Store 480 479
                                Branch 399
             399:             Label
             481:   10(fvec3) Load 423(jacobianAmt)
                              ReturnValue 481
                              FunctionEnd    


And the Vulkan dispatching asm from fasm is not small, it's quite massive. The above are just samples.
Post 15 Jan 2024, 16:58
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1847
Roman 16 Jan 2024, 08:53
2016 year. My Vulkan API & fasm game.
https://www.youtube.com/watch?v=-G_kjgklYEs
Post 16 Jan 2024, 08:53
View user's profile Send private message Reply with quote
NETSTALKER



Joined: 17 Apr 2020
Posts: 10
Location: fidonet
NETSTALKER 21 Jan 2024, 17:14
What sources did you use to study SPIR-V? How do you compile it? How do I use your code from the last message?
Post 21 Jan 2024, 17:14
View user's profile Send private message Reply with quote
donn



Joined: 05 Mar 2010
Posts: 321
donn 14 Apr 2024, 20:45
Roman wrote:
2016 year. My Vulkan API & fasm game.
https://www.youtube.com/watch?v=-G_kjgklYEs


Cool game! Was it difficult? How did you organize it
Post 14 Apr 2024, 20:45
View user's profile Send private message Reply with quote
donn



Joined: 05 Mar 2010
Posts: 321
donn 14 Apr 2024, 20:54
NETSTALKER wrote:
What sources did you use to study SPIR-V? How do you compile it? How do I use your code from the last message?


SPIR-V is here, with a few other docs on the Khronos site:
https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html

SPIR-V tools is the other project to build it. Vulkan is also by Khronos and their docs specify how to dispatch it, etc.

John Kessenich is the architect of SPIR-V, he gives some interesting overviews:
https://youtu.be/qKbtrVEhaw8?si=4P-vEkX_rI4Soyad&t=1947

I would learn how to just assemble the simple example or anything that is 'legal' SPIR-V if you want to use it. You might also be able to use it as a high level library. Then, if you want to do some damage, you'll be most efficient using GLSL or HLSL or something and converting to SPIR-V. You can see the SPIR-V in the conversions and this might help you plan out how to use SPIR-V directly. That's the approach I took.
Post 14 Apr 2024, 20:54
View user's profile Send private message Reply with quote
donn



Joined: 05 Mar 2010
Posts: 321
donn 14 Apr 2024, 20:58
Sorry last thing: If you want usable examples, this was useful to me: https://github.com/SaschaWillems/Vulkan
You'll see you need to use bindings, setup buffers, etc, using my snippets above will not work.
Post 14 Apr 2024, 20:58
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.