GPU ThreadGroups 할당 연습
.compute
// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain
#pragma kernel ScreenCalc
struct Offset
{
float3 position;
float3 rotation;
};
RWStructuredBuffer<Offset> offsetBuffer;
RWTexture2D<float4> Result;
float time;
float updateSpeed;
float rowSize;
float waveFrequency;
[numthreads(8,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
float t = time * updateSpeed;
float3 pos = offsetBuffer[id.x].position;
float3 rot = offsetBuffer[id.x].rotation;
pos.x = sin(t);
rot.x = cos(t);
offsetBuffer[id.x].position = pos;
offsetBuffer[id.x].rotation = rot;
// TODO: insert actual code here!
//Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0);
}
[numthreads(8,8,1)]
void ScreenCalc(uint3 id : SV_DispatchThreadID)
{
float t = time * updateSpeed;
uint width, height;
Result.GetDimensions(width, height);
float2 uv = id.xy / float2(width, height) + abs(sin(t)*.5);
Result[id.xy] = float4(uv, 0, 1);
}
.cs
[System.Serializable]
private struct Offset
{
public Vector3 position;
public Vector3 rotation;
}
[SerializeField] private ComputeShader computeShader;
[SerializeField] private float updateSpeed = 10f;
[SerializeField] private float waveFrequency = 0.5f;
[SerializeField] private int size = 10;
[Space]
[SerializeField] private float rowSize = 32;
private ComputeBuffer m_offsetBuffer;
[SerializeField]private Offset[] m_offsetDatas;
private RenderTexture m_renderTarget;
/* private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
}*/
private void Start()
{
InitCompute();
}
private void Update()
{
DispatchComputeShader();
GetDataFromComputeShader();
}
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
Render(destination);
}
private void Render(RenderTexture destination)
{
InitRenderTexture();
computeShader.SetTexture(1, "Result", m_renderTarget);
int threadGroupsX = Mathf.CeilToInt(Screen.width / 8.0f);
int threadGroupsY = Mathf.CeilToInt(Screen.height / 8.0f);
computeShader.Dispatch(1, threadGroupsX, threadGroupsY, 1);
Graphics.Blit(m_renderTarget, destination);
}
private void InitRenderTexture()
{
if(m_renderTarget == null || m_renderTarget.width != Screen.width || m_renderTarget.height != Screen.height)
{
//release from memory
if (m_renderTarget != null) m_renderTarget.Release();
m_renderTarget = new RenderTexture(Screen.width, Screen.height, 0,
RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
m_renderTarget.enableRandomWrite = true;
m_renderTarget.Create();
}
}
private void InitCompute()
{
m_offsetDatas = new Offset[size];
// compute buffer instance create
m_offsetBuffer = new ComputeBuffer(8*1*1, sizeof(int));
m_offsetBuffer.SetData(m_offsetDatas);
computeShader.SetBuffer(0, "offsetBuffer", m_offsetBuffer);
}
private void DispatchComputeShader()
{
computeShader.SetFloat("time", Time.time);
computeShader.SetFloat("updateSpeed", updateSpeed);
computeShader.SetFloat("rowSize", rowSize);
computeShader.SetFloat("waveFrequency", waveFrequency);
/* // thread group calc
computeShader.GetKernelThreadGroupSizes(0, out uint numX, out _, out _);
int numThreadGroups = Mathf.CeilToInt(m_offsetDatas.Length / numX);*/
// dispatch
computeShader.Dispatch(0, 8, 8, 1);
}
private void GetDataFromComputeShader()
{
m_offsetBuffer.GetData(m_offsetDatas);
for(int i =0; i<m_offsetDatas.Length; i++)
{
Debug.Log(m_offsetDatas[i].position);
Debug.Log(m_offsetDatas[i].rotation);
}
}
댓글
댓글 쓰기