Directx 11 HLSL流式输出条目不';我不能正常工作

Directx 11 HLSL流式输出条目不';我不能正常工作,directx-11,hlsl,geometry-shader,Directx 11,Hlsl,Geometry Shader,我想在我的大项目中实现基于流式输出结构的粒子系统。我看了几篇关于这个方法的文章,我构建了一个粒子。它几乎正常工作,但在具有stream out的几何体着色器中,我无法获得InitVel.z和age的值,因为它始终为0。如果我更改了年龄顺序(例如,年龄在位置之前),它对年龄适用,但顺序的第六个浮动仍然是0。看起来他只推了5个第一位置。我不知道我做错了什么,因为我尝试改变几乎所有(为顶点创建输入布局,与条目SO声明相同,更改静态28的跨步数,将其更改为32,但在这种情况下,他绘制混乱,所以跨步的大小

我想在我的大项目中实现基于流式输出结构的粒子系统。我看了几篇关于这个方法的文章,我构建了一个粒子。它几乎正常工作,但在具有stream out的几何体着色器中,我无法获得InitVel.z和age的值,因为它始终为0。如果我更改了年龄顺序(例如,年龄在位置之前),它对年龄适用,但顺序的第六个浮动仍然是0。看起来他只推了5个第一位置。我不知道我做错了什么,因为我尝试改变几乎所有(为顶点创建输入布局,与条目SO声明相同,更改静态28的跨步数,将其更改为32,但在这种情况下,他绘制混乱,所以跨步的大小可能很好)。我认为申报条目中的数值限制有问题,但在msdn网站上,我看到directx的数值限制是D3D11\u SO\u STREAM\u COUNT(4)*D3D11\u SO\u OUTPUT\u COMPONENT\u COUNT(128)而不是5。请你看看这个代码,给我的方法或希望正确地实现它??非常感谢你的帮助

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();
}
以及着色器的代码: 要流式输出的VertexShader

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
}
几何

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]);
}
}
}
将点更改为线的几何体着色器

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);
}
}
}

请注意,在Direct3D 10时间框架中,将GS+流输出用于GPU粒子系统的想法是示例之一(
ParticlesGS
),但实际上,物理硬件从未投入足够的精力使GS快速。使用DirectX 11和D3D功能级或更好的硬件,更好的解决方案是使用DirectCompute,如示例。谢谢。我尝试实现FluidCS,但在我再次尝试重写代码之前,可能我在某个地方出错了,我看不到这一点。“请注意,在Direct3D 10时间范围内,将GS+流输出用于GPU粒子系统的想法是示例之一(ParticlesGS),但实际上,物理硬件从未投入足够的精力使GS快速”问题不在于该方法速度不太快,但它会在某处丢失粒子数据,我只能使用5个浮点数,因为始终大于5个浮点数是0:(可能这是在管道的每个步骤中查看顶点缓冲区的一种方法??或者我看到D3D11_SO_声明_条目有使用0-4个数据槽的选项。现在我只使用一个,也许我可以在其他槽中推送其他数据,但如何使用该选项?这会降低性能??我使用D3D11_创建_设备_调试标志,并且我收到输入布局大小的警告。)太少28位(最小值为32位)和大量D3D11警告:0x00FCF224处的活动对象,引用计数:0。[状态创建警告#0:未知]。我修复了第一个警告,在D3D11_SO_声明_项中添加了一个浮点,但这没有改变任何内容。可能是第二个警告是我的问题吗??
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);
}
}
}
struct GSOutput
{
float4 Pos      : SV_POSITION;
float4 Colour   : COLOR;
};

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