Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by Tudor · Apr 14, 2014 at 11:49 PM · compute shaderhlsldx11changing shader

Swapping Compute Shaders

I am editing some point cloud volume data in Unity, on the GPU.

My issue is that I have to edit my data in multiple passes (applying multiple different compute shaders to the same data). Is it possible to pass the output from one compute shader to another one? You know, stopping the current compute shader, starting another one, and pointing it to the same data in the GPU memory?

How would that be done? We have the ComputeShader.Dispatch to begin with (in unity), which starts one compute shader, and then what? Can I somehow just make multiple ComputeShader objects and then do secondComputeShader.SetBuffer(--existingGPUBuffer--) and then .Dispatch()? (note: it wouldn't be necessary or optimal for me to run multiple compute shaders in the same frame, unless there's no other option)

I am using DX11, with HLSL. My data structure is in a RWStructuredBuffer, which according to MSDN, is synced across the entire GPU -- and indeed I can access this StructuredBuffer in my regular shader for display purposes.

Ideally I would be able to define a layering order "CS-A, CS-B, CS-A, CS-C"; if that is at all possible (but not all in the same frame).

Cheers!

[EDIT]

Alright, after Ben's comment, I'm posting what I'm doing right now:

 public List<ComputeShader> computeShaderList;
 ComputeBuffer particleBuffer;
 struct Particle
 {
     public Vector3 position;
     public Vector3 velocity;
 };
 ComputeShader currentComputeShader; 
 
 void Start () 
 {
     Particle[] particleArray = new Particle[particleCount];//remember to initialize for each Particle (position and velocity)
                 
     //create new compute buffer instance, and initialize it with your data.
     particleBuffer = new ComputeBuffer(particleCount, 24); // 24 = "stride" = size allocated for each particle, probably in bytes, no idea what happens with this
     particleBuffer.SetData(particleArray);
     //so now we should have all our point data stored on the GPU, right?
                 
     foreach(ComputeShader cs in computeShaderList)
     {
         cs.SetBuffer(0, "particleBuffer", particleBuffer);
     }
     material.SetBuffer ("particleBuffer", particleBuffer);//this is for the regular shader
     //and now we have told each of our (compute) shaders to reference that data we have stored on the GPU
 }
             
 void Update()
 {
     switch(currentState)// you don't need to run this each frame
     {
     case ComputeStates.CS_One:
         currentComputeShader =  computeShaderList[0];
         break;
     case ComputeStates.CS_Two:
         currentComputeShader = computeShaderList[1];
         break;
     }
                 
     //currentComputeShader.SetFloat(  ...set all your stuff
     
     //Start the current compute shader to work this frame on your particles.
     currentComputeShader.Dispatch(0, threadCount, 1, 1);
 }
 //note: you also need your OnRender with Graphics.DrawProcedural...


The Unity documentation on compute shaders is lacking, and the exposed ComputeShader object isn't very transparent. All I can say is that according to the Profiler, there seems to be no performance impact from having a bunch of different compute shaders, and choosing which one of them you want to dispatch at what time.

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Benproductions1 · Apr 15, 2014 at 12:25 AM 0
Share

Given the way graphics cards work, it's very doubtful that if such a thing exists, you won't be able to "drag it out" over more than one frame. That would also negate the whole point of "stacking" compute shaders. So if "stacking" does exist, it will definitely have to happen in one "frame".

avatar image Tudor · Apr 15, 2014 at 09:00 AM 0
Share

Perhaps Stacking isn't the right term. I just mean swapping shaders. That's possible, right? With regular shaders that is; you have $$anonymous$$aterial.Shader. It's just that I want the new shader to access the same GPU Buffer already existing on the gpu...

Don't think of it in a videogame context; think of it more like a 3d modelling tool.

avatar image Benproductions1 · Apr 16, 2014 at 12:02 PM 1
Share

Using SetBuffer won't cause a re-upload of the buffer to the GPU if that's why you're asking. Once you call SetData all the uploading is done. If you use a different shader with the same data, this shader is simply passed the memory address of the already existing buffer.

avatar image Tudor · Apr 16, 2014 at 02:47 PM 0
Share

Well I did not know that, Ben. ^_^ I have updated my question with some code. I can't verify if what I'm doing is good practice (no idea what magic happens in unity's backend), but it seems that I can have all the compute shaders I want, and just choose which one to Dispatch each frame. Do you see any negative impact in this?(compared to doing the same switching with regular shaders)

PS: feel free to convert your comments into an answer.

1 Reply

· Add your reply
  • Sort: 
avatar image
3
Best Answer

Answer by Benproductions1 · Apr 18, 2014 at 01:37 AM

As per all OpenGL buffers (IDK about D3D, but I'd assume it's the same), Unity uploads the data when you set it. For Texture2D that would be Apply, for compute buffers it's SetBuffer. Once the buffer is uploaded to the GPU it will stay there until you either delete the buffer or use SetBuffer again.

When the "data" for a material/shader is "set", if it's a pre-uploaded buffer, it gets simply passed a reference, like a pointer, to the data. Just like textures, compute buffers won't get re-uploaded when they are set on a shader. This is actually true for all buffers, as long as the implementation on the drivers is somewhat sane ;)

You should be able to freely pass around buffers between materials and shaders without much of an overhead.

That said, I am not familiar with the new OpenGL 4.X api, but I am versed in both OpenGL 3.X and OpenCL, so I shouldn't be too far from the truth.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

A node in a childnode? 1 Answer

Visual Studio Community on Mac will not recognize HLSL 0 Answers

Compute shader loop in editor 1 Answer

Sharing code between shader and c# - how? 3 Answers

Unity 4.5 broke shader in DX11 mode 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges