What happened to the rasterization stage? I can't even draw a triangle!

Started by
7 comments, last by lolanto lu 5 years, 2 months ago

I'm new to DirectX12. I've read document about DirectX12 for some days and now I just want to use it to draw a triangle. But it's not work! I used PIX to debug the program and I found that my pixel shader has no output!. I don't know if there's something wrong with my Pipeline State Object settings.

this is the function that create the PSO


/** vs and ps are indices of shader resource which have been compiled with dxc.exe in sm6 and stored in a map called shaders */
void Renderer::CreatePSO(uint32_t vs, uint32_t ps)
{
	D3D12_INPUT_LAYOUT_DESC inputDesc;
	D3D12_INPUT_ELEMENT_DESC pos;
	pos.SemanticName = "POSITION";
	pos.SemanticIndex = 0;
	pos.Format = DXGI_FORMAT_R32G32B32_FLOAT;
	pos.InputSlot = 0;
	pos.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
	pos.AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT;
	pos.InstanceDataStepRate = 0;
	inputDesc.NumElements = 1;
	inputDesc.pInputElementDescs = &pos;

	D3D12_RASTERIZER_DESC rasterDesc = {}; /**< use default value */
	rasterDesc.FillMode = D3D12_FILL_MODE_SOLID;
	rasterDesc.CullMode = D3D12_CULL_MODE_NONE; /**< disable cull */
	rasterDesc.DepthClipEnable = false;

	D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {};
	desc.pRootSignature = mRootSignature.Get();
	ID3DBlob* const vsb = shaders[vs].Get();
	ID3DBlob* const psb = shaders[ps].Get();
	desc.VS.BytecodeLength = vsb->GetBufferSize();
	desc.VS.pShaderBytecode = vsb->GetBufferPointer();
	desc.PS.BytecodeLength = psb->GetBufferSize();
	desc.PS.pShaderBytecode = psb->GetBufferPointer();
	desc.StreamOutput = {};
	desc.BlendState = {};
	desc.InputLayout = inputDesc;
	desc.SampleMask = 0;
	desc.RasterizerState = rasterDesc;
	desc.DepthStencilState = {}; /**< use the default value */
	desc.DepthStencilState.DepthEnable = false; /**< disable depth testing */
	desc.DepthStencilState.StencilEnable = false; /**< disable stencil testing */
	desc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
	desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
	desc.NumRenderTargets = 1;
	desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
	desc.DSVFormat = DXGI_FORMAT_UNKNOWN; /**< since there is no depth stencil buffer */
	desc.SampleDesc.Count = 1;
	desc.SampleDesc.Quality = 0;
	desc.NodeMask = 0;
	desc.CachedPSO = {};
	desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
	if (FAILED(mDevice->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&mPSO))))
		throw("create pipeline state failed");
}

And this is the function that setting command list for each frame


void Renderer::Run()
{
	WindowBase::MainLoop = [this](float) {
		/** Command List setting for each frame */
		mCmdList->Reset(mCmdAloc.Get(), nullptr);
		mCmdList->SetPipelineState(mPSO.Get()); /**< Which is created throgh Function CreatePSO */
		/** A constant buffer in the heap that I never use within my shaders */
		D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = mBufDescHeap->GetGPUDescriptorHandleForHeapStart();
		ID3D12DescriptorHeap* heaps[] = { mBufDescHeap.Get() };
		mCmdList->SetDescriptorHeaps(1, heaps);
		mCmdList->SetGraphicsRootSignature(mRootSignature.Get());
		mCmdList->SetGraphicsRootDescriptorTable(0, gpuHandle);
		/** Vertex And Index Buffers setting */
		mCmdList->IASetVertexBuffers(0, 1, &mVtxBufView);
		mCmdList->IASetIndexBuffer(&mIdxBufView);
		mCmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
		/** Viewport and Scissor Rect settings. mWidth = 300 and mHeight = 300. */
		D3D12_VIEWPORT viewport = {};
		viewport.Height = mHeight; viewport.Width = mWidth;
		viewport.MaxDepth = 1.0f; viewport.MinDepth = 0.0f;
		viewport.TopLeftX = 0; viewport.TopLeftY = 0;
		mCmdList->RSSetViewports(1, &viewport);
		D3D12_RECT scissorRect;
		scissorRect.bottom = mHeight;
		scissorRect.right = mWidth;
		scissorRect.top = scissorRect.left = 0;
		mCmdList->RSSetScissorRects(1, &scissorRect);
		D3D12_RESOURCE_BARRIER barrier;
		barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
		barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
		barrier.Transition.pResource = mRtvs[mSwapChain->GetCurrentBackBufferIndex()].Get();
		barrier.Transition.Subresource = 0;
		barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
		barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
		mCmdList->ResourceBarrier(1, &barrier);
		D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = mRtvDescHeap->GetCPUDescriptorHandleForHeapStart();
		rtvHandle.ptr += mRtvDescHeapSize * mSwapChain->GetCurrentBackBufferIndex();
		static float clearColor[] = { 0.2f, 0.4f, 0.6f, 1.0f };
		mCmdList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
		/** no depth stencil buffer here, since i don't want to use depth testing */
		mCmdList->OMSetRenderTargets(1, &rtvHandle, false, nullptr);
		mCmdList->DrawIndexedInstanced(3, 1, 0, 0, 0);

		barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
		barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
		mCmdList->ResourceBarrier(1, &barrier);
		mCmdList->Close();
		ID3D12CommandList* list[] = { mCmdList.Get() };
		mCmdQue->ExecuteCommandLists(1, list);
		mSwapChain->Present(1, 0);
		/** Waiting until above commands were executed */
		synchronizationCPU(mCmdQue.Get(), mFence.Get(), mNextFenceValue, mFenceEventHandle);
	};
	win->Run(); /** start window's main loop */
}

And here is my simplest vertex shader and pixel shader(I used dxc.exe to compile it in Shader Model 6_0)


/////////////////////////////////
// VERTEX SHADER
/////////////////////////////////
float4 main( float3 pos : POSITION ) : SV_POSITION
{
	return float4(pos, 1.0f);
}


/////////////////////////////////
// PIXEL SHADER
/////////////////////////////////
float4 main() : SV_TARGET
{
	return float4(1.0f, 1.0f, 1.0f, 1.0f);
}

Vertex buffer and Index buffer are also very simple


std::array<float, 9> VtxData = {
	-.5f, 0.0f, 0.0f,
	0.0f, .5f, 0.0f,
	.5f, 0.0f, 0.0f
};

std::array<uint32_t, 3> IdxData = {
	0, 1, 2
};

 

By the way, I have used the debug layer and there is no error or warning message. When I try to use PIX to debug the pixel that should be inside the triangle, it warn me that "Shader Debugging returned no invocation records. Check that your selected pixel, vertex, or thread exists and was executed on this draw call". 

My Vertex Shader has the correct output which should not be culled anymore

thread.JPG.5090adff4754037bfe419b6549a663eb.JPG

Hope anybody can give me some suggestions to do more test. Thanks!!! (Seriously, DirectX12 is really harder than DirectX11...)

Advertisement

= {} doesn't give you defaults. You probably want CD3DX12_<state object type>(D3D12_DEFAULT) from d3dx12.h. Not sure if that's the problem, but it's the first thing that jumped out to me.


desc.DepthStencilState.DepthEnable = false; /**< disable depth testing */
	desc.DepthStencilState.StencilEnable = false; /**< disable stencil testing */

 

This is pretty unstandard to do. Check if your driver is not crazy by enabling at least depth buffer. (Also the comments are inappropriate, it does not disable depth testing as there is a command call in pipeline to do that any time, in desc it creates depth-buffer-less back buffer)

Also check your scissor test values

For the vertices, change Z to slightly above 0

5 hours ago, TeaTreeTim said:

For the vertices, change Z to slightly above 0

He has disabled existance of depth buffer and is in the fall space of XY in projection space

SampleMask must not be zero. You're asking for 0 out of the 1 available samples to be written.

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

@ajmiles will be right, I also bumped into this.

11 hours ago, ajmiles said:

SampleMask must not be zero. You're asking for 0 out of the 1 available samples to be written.

Yes, you're right! But it's one of problems in my settings. Thanks for your reply and I will learn more about SampleMask!.

(PS. I don't know how to make a reply of your post and click the "Report Post", Writing my reply and submitting. Sorry if it will bother you)

On 2/17/2019 at 12:26 AM, SoldierOfLight said:

= {} doesn't give you defaults. You probably want CD3DX12_<state object type>(D3D12_DEFAULT) from d3dx12.h. Not sure if that's the problem, but it's the first thing that jumped out to me.

Yes, I use it(after updating my windows and visual studio) and find out that there's something wrong with my blend setting.

It seem's there's a variable in the D3D12_BLEND_DESC structure which is one of the variable of D3D12_GRAPHICS_PIPELINE_STATE_DESC structure. In D3D12_BLEND_DESC, we need to set each render target's writeMask. In my code, I use ={} to initialize the D3D12_BLEND_DESC. And then, each writeMask is set to 0. So, nothing can be writted into the render target and pixel shader never be invocated.

={} DOESN'T GIVE YOU DEFAULTS BUT THE TRAP

Thanks for your reply and suggestions

This topic is closed to new replies.

Advertisement