Advertisement

How to Properly Setup the Streamout Stage in D3D12

Started by February 01, 2025 01:42 PM
2 comments, last by isu diss 3 weeks ago
struct Mesh_Data
{
	string mMeshName;
	string mMeshTextureName;
	int mVertexCount;
	vector<RE_VERTEX> mMeshGeometry;
	ComPtr<ID3D12Resource> Mesh_Vertex_Buffer_GPU;
	ComPtr<ID3D12Resource> pStreamOutBuffer;
	UINT VertexByteStride;
	UINT VertexBufferByteSize;

	Mesh_Data()
	{
		Mesh_Vertex_Buffer_GPU = nullptr;
		VertexByteStride = 0;
		VertexBufferByteSize = 0;
	}

	void CreateMeshVertexBuffer(ComPtr<ID3D12Device5> inDevice, ComPtr<ID3D12GraphicsCommandList5> inCommandList)
	{
		const UINT vbByteSize = (UINT)mMeshGeometry.size() * sizeof(RE_VERTEX);

		Common::AllocateUploadBuffer(inDevice.Get(), mMeshGeometry.data(), sizeof(RE_VERTEX) * mMeshGeometry.size(), &Mesh_Vertex_Buffer_GPU);

		VertexByteStride = sizeof(RE_VERTEX);
		VertexBufferByteSize = vbByteSize;
	}

	void CreateStreamOutputBuffer(ComPtr<ID3D12Device5> inDevice)
	{
		D3D12_RESOURCE_DESC desc = {};
		desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
		desc.Width = sizeof(RE_VERTEX) * mMeshGeometry.size() * 3 * 3;
		desc.Height = 1;
		desc.DepthOrArraySize = 1;
		desc.MipLevels = 1;
		desc.Format = DXGI_FORMAT_UNKNOWN;
		desc.SampleDesc.Count = 1;
		desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
		desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;

		inDevice->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_STREAM_OUT, nullptr, IID_PPV_ARGS(&pStreamOutBuffer));
	}

	void SetStreamOutputTargets(ID3D12GraphicsCommandList5* commandList, ID3D12Resource* soBuffer)
	{
		D3D12_STREAM_OUTPUT_BUFFER_VIEW soBufferView = {};
		soBufferView.BufferLocation = soBuffer->GetGPUVirtualAddress();
		soBufferView.SizeInBytes = sizeof(RE_VERTEX) * mMeshGeometry.size() *3*3;
		soBufferView.BufferFilledSizeLocation = soBuffer->GetGPUVirtualAddress() + soBufferView.SizeInBytes;

		commandList->SOSetTargets(0, 1, &soBufferView);
	}

	D3D12_VERTEX_BUFFER_VIEW VertexBufferView()const
	{
		D3D12_VERTEX_BUFFER_VIEW vbv;
		vbv.BufferLocation = Mesh_Vertex_Buffer_GPU->GetGPUVirtualAddress();
		vbv.StrideInBytes = VertexByteStride;
		vbv.SizeInBytes = VertexBufferByteSize;
		return vbv;
	}

	void DrawMesh(ComPtr<ID3D12GraphicsCommandList5> inCommandList)
	{
		inCommandList->IASetVertexBuffers(0, 1, &VertexBufferView());
		inCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST);
		SetStreamOutputTargets(inCommandList.Get(), pStreamOutBuffer.Get());
		inCommandList->DrawInstanced((UINT)mMeshGeometry.size(), 1, 0, 0);
		inCommandList->SOSetTargets(0, 0, nullptr);
	}
};

Hi All,
Good day!

I'm trying to input a plane geometry into the raster pipeline and tessellate it and use back with DXR. soBufferView.BufferFilledSizeLocation = soBuffer->GetGPUVirtualAddress() + soBufferView.SizeInBytes;
above line causes problems, This is the first time I'm using streamout for such thing. Can anyone help me? I have provided the code for creating SO buffer and view.

Error was disappeared when I set up a counter buffer and set it on soBufferView.BufferFilledSizeLocation. Any thoughts?

Advertisement
3 = Tessellation Factor
struct Mesh_Data
{
	string mMeshName;
	string mMeshTextureName;
	int mVertexCount;
	vector<RE_VERTEX> mMeshGeometry;
	ComPtr<ID3D12Resource> Mesh_Vertex_Buffer_GPU;
	ComPtr<ID3D12Resource> pStreamOutBuffer;
	UINT VertexByteStride;
	UINT VertexBufferByteSize;

	Mesh_Data()
	{
		Mesh_Vertex_Buffer_GPU = nullptr;
		VertexByteStride = 0;
		VertexBufferByteSize = 0;
	}

	void CreateMeshVertexBuffer(ComPtr<ID3D12Device5> inDevice, ComPtr<ID3D12GraphicsCommandList5> inCommandList)
	{
		const UINT vbByteSize = (UINT)mMeshGeometry.size() * sizeof(RE_VERTEX);

		Common::AllocateUploadBuffer(inDevice.Get(), mMeshGeometry.data(), sizeof(RE_VERTEX) * mMeshGeometry.size(), &Mesh_Vertex_Buffer_GPU);

		VertexByteStride = sizeof(RE_VERTEX);
		VertexBufferByteSize = vbByteSize;
	}

	void CreateStreamOutputAndCounterBuffers(ComPtr<ID3D12Device5> inDevice)
	{
		D3D12_RESOURCE_DESC desc = {};
		desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
		desc.Width = sizeof(RE_VERTEX) * mMeshGeometry.size() * 3 * 3 * 3;
		desc.Height = 1;
		desc.DepthOrArraySize = 1;
		desc.MipLevels = 1;
		desc.Format = DXGI_FORMAT_UNKNOWN;
		desc.SampleDesc.Count = 1;
		desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
		desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;

		inDevice->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_STREAM_OUT, nullptr, IID_PPV_ARGS(&pStreamOutBuffer));
		
		ThrowIfFailed(inDevice->CreateCommittedResource(
			&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
			D3D12_HEAP_FLAG_NONE,
			/*&counterBufferDesc*/&CD3DX12_RESOURCE_DESC::Buffer(sizeof(PUINT_PTR)),
			D3D12_RESOURCE_STATE_STREAM_OUT,
			nullptr,
			IID_PPV_ARGS(&counterBuffer)));

	}

	void SetStreamOutputTargets(ID3D12GraphicsCommandList5* commandList, ID3D12Resource* soBuffer)
	{
		D3D12_STREAM_OUTPUT_BUFFER_VIEW soBufferView = {};
		soBufferView.BufferLocation = soBuffer->GetGPUVirtualAddress();
		soBufferView.SizeInBytes = sizeof(RE_VERTEX) * mMeshGeometry.size() * 3  * 3 * 3;
		soBufferView.BufferFilledSizeLocation = counterBuffer->GetGPUVirtualAddress();

		commandList->SOSetTargets(0, 1, &soBufferView);
	}

	D3D12_VERTEX_BUFFER_VIEW VertexBufferView()const
	{
		D3D12_VERTEX_BUFFER_VIEW vbv;
		vbv.BufferLocation = Mesh_Vertex_Buffer_GPU->GetGPUVirtualAddress();
		vbv.StrideInBytes = VertexByteStride;
		vbv.SizeInBytes = VertexBufferByteSize;
		return vbv;
	}

	void DrawMesh(ComPtr<ID3D12GraphicsCommandList5> inCommandList)
	{
		inCommandList->IASetVertexBuffers(0, 1, &VertexBufferView());
		inCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST);
		SetStreamOutputTargets(inCommandList.Get(), pStreamOutBuffer.Get());
		inCommandList->DrawInstanced((UINT)mMeshGeometry.size(), 1, 0, 0);
		inCommandList->SOSetTargets(0, 1, nullptr);
	}
};

I solved the problem, now the 3d plane, fed into input assembler will be tessellated and fed into blas for RT. I did it by myself

Advertisement