Advertisement

HLSL Stream out Num Entries

Started by May 30, 2018 12:55 PM
0 comments, last by Kris1992 6 years, 8 months ago

I want implement Particle system based on stream out structure to my bigger project. I saw few articles about that method and I build one particle. It works almost correctly but in geometry shader with stream out i cant get value of InitVel.z and age because it always is 0. If i change order of age(for example age is before Position) it works fine for age but 6th float of order is still 0. It looks like he push only 5 first positions. I had no idea what i do wrong because i try change almost all(create input layout for vertex, the same like entry SO Declaration, change number of strides for static 28, change it to 32 but in this case he draw chaotic so size of strides is probably good). I think it is problem with limits of NumEntry in declaration Entry but on site msdn i saw the limit for directx is D3D11_SO_STREAM_COUNT(4)*D3D11_SO_OUTPUT_COMPONENT_COUNT(128) not 5. Pls can you look in this code and give me the way or hope of implement it correctly?? Thanks a lot for help.   


Structure of particle
    
    struct Particle{
    Particle() {}
    Particle(float x, float y, float z,float vx, float vy, float vz,float 
    l /*UINT typ*/)
    :InitPos(x, y, z), InitVel(vx, vy, vz), Age(l) /*, Type(typ)*/{}
    XMFLOAT3 InitPos;
    XMFLOAT3 InitVel;
    float Age;
    //UINT Type;
    };
    
    SO Entry

    D3D11_SO_DECLARATION_ENTRY PartlayoutSO[] =
    {
    
    { 0,"POSITION", 0, 0 , 3, 0 },  // output all components of position
    { 0,"VELOCITY", 0, 0, 3, 0 },     
    { 0,"AGE", 0, 0, 1, 0 }
    //{ 0,"TYPE", 0, 0, 1, 0 }
    };

    Global Variables

    //streamout shaders
    ID3D11VertexShader* Part_VSSO;
    ID3D11GeometryShader* Part_GSSO;
    ID3DBlob *Part_GSSO_Buffer;
    ID3DBlob *Part_VSSO_Buffer;
    //normal shaders
    ID3D11VertexShader* Part_VS;
    ID3D11GeometryShader* Part_GS;
    ID3DBlob *Part_GS_Buffer;
    ID3D11PixelShader* Part_PS;
    ID3DBlob *Part_VS_Buffer; 
    ID3DBlob *Part_PS_Buffer;
    ID3D11Buffer* PartVertBufferInit;
    //ID3D11Buffer* Popy;
    ID3D11Buffer* mDrawVB;
    ID3D11Buffer* mStreamOutVB;
    ID3D11InputLayout* PartVertLayout;// I try to set input layout too

    void ParticleSystem::InitParticles()
    {
    mFirstRun = true;
    srand(time(NULL));
    hr = D3DCompileFromFile(L"ParticleVertexShaderSO4.hlsl", NULL, 
    D3D_COMPILE_STANDARD_FILE_INCLUDE, "main", "vs_5_0", NULL, NULL, 
    &Part_VSSO_Buffer, NULL);
    hr = D3DCompileFromFile(L"ParticleGeometryShaderSO4.hlsl", NULL, 
    D3D_COMPILE_STANDARD_FILE_INCLUDE, "main", "gs_5_0", NULL, NULL, 
    &Part_GSSO_Buffer, NULL);

    UINT StrideArray[1] = { sizeof(Particle) };//I try to set static 28 bits-7*4 
    per float
    hr = device->CreateVertexShader(Part_VSSO_Buffer->GetBufferPointer(), 
    Part_VSSO_Buffer->GetBufferSize(), NULL, &Part_VSSO);
    hr = device->CreateGeometryShaderWithStreamOutput(Part_GSSO_Buffer- 
    >GetBufferPointer(), Part_GSSO_Buffer->GetBufferSize(), PartlayoutSO ,3/* 
    sizeof(PartlayoutSO)*/ , StrideArray, 1,D3D11_SO_NO_RASTERIZED_STREAM, 
    NULL,&Part_GSSO);
    
    //Draw Shaders
    hr = D3DCompileFromFile(L"ParticleVertexShaderDRAW4.hlsl", NULL, 
    D3D_COMPILE_STANDARD_FILE_INCLUDE, "main", "vs_5_0", NULL, NULL, 
    &Part_VS_Buffer, NULL);
    hr = D3DCompileFromFile(L"ParticleGeometryShaderDRAW4.hlsl", NULL, 
    D3D_COMPILE_STANDARD_FILE_INCLUDE, "main", "gs_5_0", NULL, NULL, 
    &Part_GS_Buffer, NULL);
    hr = D3DCompileFromFile(L"ParticlePixelShaderDRAW4.hlsl", NULL, 
    D3D_COMPILE_STANDARD_FILE_INCLUDE, "main", "ps_5_0", NULL, NULL, 
    &Part_PS_Buffer, NULL);

    hr = device->CreateVertexShader(Part_VS_Buffer->GetBufferPointer(), 
    Part_VS_Buffer->GetBufferSize(), NULL, &Part_VS);
    hr = device->CreateGeometryShader(Part_GS_Buffer->GetBufferPointer(), 
    Part_GS_Buffer->GetBufferSize(), NULL, &Part_GS);
    hr = device->CreatePixelShader(Part_PS_Buffer->GetBufferPointer(), 
    Part_PS_Buffer->GetBufferSize(), NULL, &Part_PS);
    BuildVertBuffer();
    }
    void ParticleSystem::BuildVertBuffer()
    {
    D3D11_BUFFER_DESC vertexBufferDesc1;
    ZeroMemory(&vertexBufferDesc1, sizeof(vertexBufferDesc1));
    vertexBufferDesc1.Usage = D3D11_USAGE_DEFAULT;
    vertexBufferDesc1.ByteWidth = sizeof(Particle)*1; //*numParticles;
    vertexBufferDesc1.BindFlags = D3D11_BIND_VERTEX_BUFFER;// | 
    D3D11_BIND_STREAM_OUTPUT;
    vertexBufferDesc1.CPUAccessFlags = 0;
    vertexBufferDesc1.MiscFlags = 0;
    vertexBufferDesc1.StructureByteStride = 0;// I tried to comment this too

    Particle p;
    ZeroMemory(&p, sizeof(Particle));
    p.InitPos = XMFLOAT3(0.0f, 0.0f, 0.0f);
    p.InitVel = XMFLOAT3(0.0f, 0.0f, 0.0f);
    p.Age = 0.0f;
    //p.Type = 100.0f;
    D3D11_SUBRESOURCE_DATA vertexBufferData1;
    ZeroMemory(&vertexBufferData1, sizeof(vertexBufferData1));
    vertexBufferData1.pSysMem = &p;//było &p
    vertexBufferData1.SysMemPitch = 0;
    vertexBufferData1.SysMemSlicePitch = 0;
    hr = device->CreateBuffer(&vertexBufferDesc1, &vertexBufferData1, 
    &PartVertBufferInit);
    
    ZeroMemory(&vertexBufferDesc1, sizeof(vertexBufferDesc1));
    vertexBufferDesc1.ByteWidth = sizeof(Particle) * numParticles;
    vertexBufferDesc1.BindFlags = D3D11_BIND_VERTEX_BUFFER | 
    D3D11_BIND_STREAM_OUTPUT;
    hr = device->CreateBuffer(&vertexBufferDesc1, 0, &mDrawVB);
    hr = device->CreateBuffer(&vertexBufferDesc1, 0, &mStreamOutVB);
    }
    void ParticleSystem::LoadDataParticles()
    {
    UINT stride = sizeof(Particle);
    UINT offset = 0;

    //Create the Input Layout
    //device->CreateInputLayout(Partlayout, numElementsPart, Part_VSSO_Buffer- 
    //>GetBufferPointer(), 
    //    Part_VSSO_Buffer->GetBufferSize(), &PartVertLayout); 
    //Set the Input Layout
    //context->IASetInputLayout(PartVertLayout);
    

    //Set Primitive Topology
    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);

    if (mFirstRun)
    {
    //    context->CopyResource(Popy, PartVertBufferInit);    
    context->IASetVertexBuffers(0, 1, &PartVertBufferInit, &stride, 
    &offset);    
    }
    else
    {    
    context->IASetVertexBuffers(0, 1, &mDrawVB, &stride, &offset);
    }

    context->SOSetTargets(1, &mStreamOutVB, &offset);
    context->VSSetShader(Part_VSSO, NULL, 0);
    context->GSSetShader(Part_GSSO, NULL, 0);
    context->PSSetShader(NULL, NULL, 0);
    //context->PSSetShader(Part_PS, NULL, 0);

    ID3D11DepthStencilState* depthState;//disable depth
    D3D11_DEPTH_STENCIL_DESC depthStateDesc;
    depthStateDesc.DepthEnable = false;
    depthStateDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
    device->CreateDepthStencilState(&depthStateDesc, &depthState);
    context->OMSetDepthStencilState(depthState, 0); 

    if (mFirstRun)
    {
    //mFirstRun;
    context->Draw(1, 0);
    mFirstRun = false;
    }
    else
    {
    context->DrawAuto();
    }
    //}
    // done streaming-out--unbind the vertex buffer
    ID3D11Buffer* bufferArray[1] = { 0 }; 
    context->SOSetTargets(1, bufferArray, &offset); 
    
    // ping-pong the vertex buffers
    std::swap(mStreamOutVB, mDrawVB);

    // Draw the updated particle system we just streamed-out. 
    
    //Create the Input Layout
    //device->CreateInputLayout(Partlayout, numElementsPart, Part_VS_Buffer- 
    //>GetBufferPointer(),
    //    Part_VS_Buffer->GetBufferSize(), &PartVertLayout);

    //Set the normal Input Layout
    //context->IASetInputLayout(PartVertLayout);

    context->IASetVertexBuffers(0, 1, &mDrawVB, &stride, &offset);
    ZeroMemory(&depthStateDesc, sizeof(depthStateDesc));
    depthStateDesc.DepthEnable = true;
    depthStateDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
    device->CreateDepthStencilState(&depthStateDesc, &depthState);
    context->OMSetDepthStencilState(depthState, 0);
    //I tried add normal layout here the same like Entry SO but no changes
    //Set Primitive Topology
    //context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
    context->VSSetShader(Part_VS, NULL, 0);
    context->GSSetShader(Part_GS, NULL, 0);
    context->PSSetShader(Part_PS, NULL, 0);
    context->DrawAuto();
    //mFirstRun = true;
    context->GSSetShader(NULL, NULL, 0);
    }
    void ParticleSystem::RenderParticles()
    {
    //mFirstRun = true;
    LoadDataParticles();
    }

And the code of shaders:
VertexShader to stream out 

    struct Particle
    {
    float3 InitPos : POSITION;
    float3 InitVel : VELOCITY;
    float Age : AGE;
    //uint Type        : TYPE;
    };

    Particle main(Particle vin)
    {
    return vin;// just push data into geomtrywithso
    }

GeometrywithSo

    struct Particle
    {
    float3 InitPos : POSITION;
    float3 InitVel : VELOCITY;
    float Age : AGE;
    //uint Type : TYPE;
    };
    float RandomPosition(float offset)
    {
    float u = Time + offset;// (Time + offset);
    float v = ObjTexture13.SampleLevel(ObjSamplerState, u, 0).r;
    return (v);
    }

    [maxvertexcount(6)]
    void main(
    point Particle gin[1],
    inout PointStream< Particle > Output
    )
    {
    //gin[0].Age = Time;

    if ( StartPart == 1.0f  )
    {
    //if (gin[0].Age < 100.0f)
    //{
    for (int i = 0; i < 6; i++)
    {
    float3 VelRandom; //= 5.0f * RandomPosition((float)i / 5.0f);
    VelRandom.y = 10.0f+i;
    VelRandom.x = 35 * i* RandomPosition((float)i / 5.0f);//+ offse;
    VelRandom.z = 10.0f;//35*i * RandomPosition((float)i / 5.0f);
    Particle p;
    p.InitPos = VelRandom;//float3(0.0f, 5.0f, 0.0f); //+ VelRandom;
    p.InitVel = float3(10.0f, 10.0f, 10.0f);
    p.Age = 0.0f;//VelRandom.y;
    //p.Type = PT_FLARE;
    Output.Append(p);

    }
    Output.Append(gin[0]);
    }
    else if (StartPart == 0.0f)
    {
    if (gin[0].Age >= 0)
    {
    Output.Append(gin[0]);
    }
    }
    }

If I change Age in geometry with so: for example Age += Time from const buffer
In geometry shader its fine once but in draw shader it is 0 and next time if it is reading in geometry with so it is 0 too.

Vertex shader to draw

    struct VertexOut
    {
    float3 Pos            : POSITION;
    float4 Colour        : COLOR;
    //uint Type            : TYPE;
    };
    struct Particle
    {
    float3 InitPos : POSITION;
    float3 InitVel : VELOCITY;
    float Age : AGE;
    //    uint Type        : TYPE;
    };

    VertexOut main(Particle vin)
    {
    VertexOut vout;
    float3 gAccelW = float3(0.0f, -0.98f, 0.0f);
    float t = vin.Age;
    //float b = Time/10000;
    // constant Acceleration equation
    vout.Pos = vin.InitVel+ (0.7f * gAccelW)*Time/100;
    //vout.Pos.x = t;                            
    vout.Colour = float4(1.0f, 0.0f, 0.0f, 1.0f);
    //vout.Age = vout.Pos.y;
    //vout.Type =  vin.Type;

    return vout;
    }

Geometry shader to change point into line

    struct VertexOut
    {
    float3 Pos            : POSITION;
    float4 Colour        : COLOR;
    //uint Type            : TYPE;
    };

    struct GSOutput
    {
    float4 Pos        : SV_POSITION;
    float4 Colour    : COLOR;
    //float2 Tex        : TEXCOORD;
    };

    [maxvertexcount(2)]
    void main(
    point VertexOut gin[1],
    inout LineStream< GSOutput > Output
    )
    {
    float3 gAccelW = float3(0.0f, -0.98f, 0.0f);

    //if (gin[0].Type != PT_EMITTER)
    {    
    float4 v[2];
    v[0] = float4(gin[0].Pos, 1.0f);
    v[1] = float4((gin[0].Pos + gAccelW), 1.0f);
    GSOutput gout;
    [unroll]
    for (int i = 0; i < 2; ++i)
    {
    gout.Pos = mul(v[i], WVP);// mul(v[i], gViewProj);
    gout.Colour = gin[0].Colour;
    Output.Append(gout);
    }
    }
    }

And pixel Shader

    struct GSOutput
    {
    float4 Pos        : SV_POSITION;
    float4 Colour    : COLOR;
    };

    float4 main(GSOutput pin) : SV_TARGET
    {
    return pin.Colour;
    }

 

This topic is closed to new replies.

Advertisement