1
votes

I am totally noob to 3D drawing using DirectX so, I wanted to learn the very basics of it and so, I attempted to use a mix of every example I stumbled upon through the web.

My first objective is to simply draw a few lines on the screen but so far, the only thing I was able to realize is to clear the screen with some varying color...

In order to draw my 2D lines, I actually use HLSL vertex and pixel shaders compiled directly by the 2015 version of Visual Studio into cso files. (I initially had trouble with the pixel shader but managed to find that its properties have to be set )

When I use the Visual Studio Graphics Analyzer/Debugger, I can see the IA step which seems to be correct as the lines are drawn. But after this step, I can't see anything more although I can debug step by step in the vertex shader and I see the correct values in position and color parameters.

VSGA report

The main issues, here, are:

  • In pixel history, I can't see any Draw() call issued on the deviceContext. I can only see ClearRenderTarget()
  • The pixel shader displays the message "Stage did not run. No ouput"

I don't know what is wrong in the process, are the world/view/projection matrices or the depthStencilView mandatory? Did I forgot to provide a specific buffer to the swapChain and pipeline? I tried to disable depth, scissor, and culling in the rasterState object but I can't be sure.

I use a structure for my vertices which is :

#define LINES_NB 1000
struct Point
{
    float x, y, z, rhw;
    float r, g, b, a;
} lineList[LINES_NB];

Finally, here is the code for the VERTEX SHADER:

struct VIn
{
    float4 position : POSITION;
    float4 color : COLOR;
};

struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

VOut main(VIn input)
{
    VOut output;

    output.position = input.position;
    output.color = input.color;

    return output;
}

Which I compile with the following line :

/Zi /E"main" /Od /Fo"E:\PATH\VertexShader.cso" /vs"_5_0" /nologo

And the code for the PIXEL SHADER is the following:

struct PIn
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

float4 main(PIn input) : SV_TARGET
{
    return input.color;
}

Which I compile with the following line:

/Zi /E"main" /Od /Fo"E:\PATH\PixelShader.cso" /ps"_5_0" /nologo 

This is the RASTERIZER STATE creation part:

D3D11_RASTERIZER_DESC rasterDesc;
rasterDesc.AntialiasedLineEnable = false;
rasterDesc.CullMode = D3D11_CULL_NONE;
rasterDesc.DepthBias = 0;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = false;
rasterDesc.FillMode = D3D11_FILL_WIREFRAME;
rasterDesc.FrontCounterClockwise = true;
rasterDesc.MultisampleEnable = false;
rasterDesc.ScissorEnable = false;
rasterDesc.SlopeScaledDepthBias = 0.0f;

result = _device->CreateRasterizerState(&rasterDesc, &_rasterState);
if (FAILED(result))
{
    OutputDebugString("FAILED TO CREATE RASTERIZER STATE.\n");
    HR(result);
    return -1;
}
_immediateContext->RSSetState(_rasterState);

And this is the INPUT LAYOUT registration part (_vertexShaderCode->code contains the contents of vertexShader.cso and _vertexShaderCode->size, the size of those contents):

// create the input layout object
D3D11_INPUT_ELEMENT_DESC ied[] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

HR(_device->CreateInputLayout(ied, sizeof(ied) / sizeof(D3D11_INPUT_ELEMENT_DESC), _vertexShaderCode->code, _vertexShaderCode->size, &_vertexInputLayout));
_immediateContext->IASetInputLayout(_vertexInputLayout);

Where variables are declared as:

struct Shader
{
    BYTE *code;
    UINT size;
};

ID3D11Device*           _device;
ID3D11DeviceContext*    _immediateContext;
ID3D11RasterizerState*  _rasterState;
ID3D11InputLayout*      _vertexInputLayout;
Shader*                 _vertexShaderCode;
Shader*                 _pixelShaderCode;

My VERTEX BUFFER is created by calling createLinesBuffer once, and then, calling renderVertice for mapping it at every drawcall:

void        DxDraw::createLinesBuffer(ID3D11Device* device)
{
    D3D11_BUFFER_DESC vertexBufferDesc;
    ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));
    vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
    vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    vertexBufferDesc.ByteWidth = sizeof(Point) * LINES_NB;
    std::cout << "buffer size : " << sizeof(Point) * LINES_NB <<     std::endl;
    vertexBufferDesc.MiscFlags = 0;
    vertexBufferDesc.StructureByteStride = 0;

    D3D11_SUBRESOURCE_DATA vertexBufferData;
    ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
    vertexBufferData.pSysMem = lineList;
    std::cout << "lineList : " << lineList << std::endl;
    vertexBufferData.SysMemPitch = 0;
    vertexBufferData.SysMemSlicePitch = 0;

    HR(device->CreateBuffer(&vertexBufferDesc, &vertexBufferData,     &_vertexBuffer));
}

void        DxDraw::renderVertice(ID3D11DeviceContext* ctx, UINT count, D3D11_PRIMITIVE_TOPOLOGY type)
{
    D3D11_MAPPED_SUBRESOURCE ms;
    ZeroMemory(&ms, sizeof(D3D11_MAPPED_SUBRESOURCE));
    // map the buffer   
    HR(ctx->Map(_vertexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms));
    // copy the data to it
    memcpy(ms.pData, lineList, sizeof(lineList));
    // unmap it
    ctx->Unmap(_vertexBuffer, NULL);

    // select which vertex buffer to display
    UINT stride = sizeof(Point);
    UINT offset = 0;
    ctx->IASetVertexBuffers(0, 1, &_vertexBuffer, &stride, &offset);

    // select which primtive type we are using
    ctx->IASetPrimitiveTopology(type);

    // draw the vertex buffer to the back buffer
    ctx->Draw(count, 0);
}
2
Perhaps this link could be of some help social.msdn.microsoft.com/Forums/en-US/…SvinSimpe

2 Answers

2
votes

Copied from comment, since it solved the issue.

InputLayout looks OK, VertexBuffer looks ok either. At this point, I would check actual vertex coordinates. From your screenshot, it lookl like you're using pretty big numbers, like x = 271, y = 147. Normally, those position are transformed via World-View-Projection transformation, so they end up in <-1.0f;1.0f> range. Since you're not using any transformations, I would recommend to change your lineGenerator function so it generates geometry in <-1.0f; 1.0f> range for x and y coordinates. For example, if your current x value is 271, make it 0.271f

3
votes

There are many things that might have gone wrong here, potentially you can check:

  • is Input Layout properly declared? It looks like your Vertex Shader doesn't get any geometry
  • how do you declare your Rasterizer Stage? Sometime there might be some issues, like culling, depth clipping, etc.
  • how does your geometry look like? Do you apply any world/view/projection transformation before applying geometry to Input Assembler?
  • how do you construct your Vertex Buffer? Do you Map/Unmap it? Or maybe you construct this for every drawcall?

I cannot guarantee that this will help, but IMHO all of this is worth checking out.

As for no output from Pixel Shader, it seems that nothing was feeded to it - so there must be something either with VS output or RS clipped all the geometry somehow (because of culling, depth testing, etc.)