1
\$\begingroup\$

I started learning Direct3D a week ago and I've been following many tutorials but after I got to the point where I had to create a Constant Buffer I got stuck, the creation of the buffer seems to be working correctly but the UpdateSubresource function doesn't seem to update it, the value I'm trying to put in the buffer has no purpose apart from being a proof of concept, the value is the float brightness inside the struct VS_CONSTANT_BUFFER.

It is set to 1.0 during the buffer creation, then it is set 0.5 when the frame is redrawn but it doesn't update the buffer on the shader side.

Here is the code, I put all of the Direct3D stuff in one place so there is nothing you don't see:

#include "GraphicsInit.h"
#include"Window.h"


float red = 0.0f;
int angle = 0;

struct Vertex
{
    float x, y, z;
    float r, g, b, a;
};

Vertex triangle[] = {
    {-0.5f,-0.5f,0.5f,    1.0f,0.0f,0.0f,1.0f},
    {-0.5f, 0.5f,0.5f,    0.0f,1.0f,0.0f,1.0f},
    { 0.5f, 0.5f,0.5f,    0.0f,0.0f,1.0f,1.0f},
    { 0.5f,-0.5f,0.5f,    0.0f,1.0f,0.0f,1.0f},

    {-0.6f, 0.7,0.4f,    1.0f,1.0f,1.0f,1.0f},
    { 0.4f, 0.3f,0.9f,    1.0f,1.0f,1.0f,1.0f},
    { 0.9f,-0.8f,0.6f,    1.0f,1.0f,1.0f,1.0f}
};

unsigned int indices[] = {
    0, 1, 2,
    0, 2, 3,
    4,5,6
};

ID3D11VertexShader* vs;
ID3D11PixelShader* ps;
ID3D11InputLayout* InputLayout;
ID3D11Buffer* VertexBuffer;
ID3D11Buffer* IndexBuffer;

ID3D11Buffer* VSConstantBuffer = NULL;

//Struct needs to be equal to the one in the shaders
struct VS_CONSTANT_BUFFER
{
    float brightness;
};
VS_CONSTANT_BUFFER VSCBdata;

//CBStruct CBDat = {
//    {
//     std::cos(angle), std::sin(angle), 0.0f, 0.0f,
//    -std::sin(angle), std::cos(angle), 0.0f, 0.0f,
//     0.0f,            0.0f,            0.0f, 0.0f,
//     0.0f,            0.0f,            0.0f, 0.0f
//    }
//};

void InitD3D(HWND hWnd)
{
    //////////////////DEVICE AND SWAPCHAIN//////////////////
    DXGI_SWAP_CHAIN_DESC scd;
    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));

    scd.BufferCount = 1;                                    // one back buffer
    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
    scd.OutputWindow = hWnd;                                // the window to be used
    scd.SampleDesc.Count = 4;                               // how many multisamples
    scd.Windowed = TRUE;                                    // windowed/full-screen mode

    D3D11CreateDeviceAndSwapChain(
        NULL,
        D3D_DRIVER_TYPE_HARDWARE,
        NULL,
        NULL,
        NULL,
        NULL,
        D3D11_SDK_VERSION,
        &scd,
        &swapchain,
        &dev,
        NULL,
        &devcon);

    /////////////////////////////////////////////////////////

    //////////////////SET THE RENDER TARGET//////////////////

    // get the address of the back buffer
    ID3D11Texture2D* pBackBuffer;
    swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);

    // use the back buffer address to create the render target
    dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
    pBackBuffer->Release();

    // set the render target as the back buffer
    devcon->OMSetRenderTargets(1, &backbuffer, NULL);

    /////////////////////////////////////////////////////////

    //////////////////SET THE VIEW PORT//////////////////

    D3D11_VIEWPORT viewport;
    ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    viewport.Width = sizeX;
    viewport.Height = sizeY;

    devcon->RSSetViewports(1, &viewport);

    /////////////////////////////////////////////////////////

    InitBuffers();
    InitPipeline();


}

void InitPipeline()
{
    //////////////////SHADERS COMPILING//////////////////

    ID3D10Blob* blobvs, * blobps;
    D3DX11CompileFromFile(L"Shaders.hlsl", 0, 0, "VS", "vs_4_0", 0, 0, 0, &blobvs, 0, 0);
    D3DX11CompileFromFile(L"Shaders.hlsl", 0, 0, "PS", "ps_4_0", 0, 0, 0, &blobps, 0, 0);

    dev->CreateVertexShader(blobvs->GetBufferPointer(), blobvs->GetBufferSize(), NULL, &vs);
    dev->CreatePixelShader(blobps->GetBufferPointer(), blobps->GetBufferSize(), NULL, &ps);

    devcon->VSSetShader(vs, 0, 0);
    devcon->PSSetShader(ps, 0, 0);

    /////////////////////////////////////////////////////////

    //////////////////INPUT LAYOUT//////////////////

    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    dev->CreateInputLayout(layout, 2, blobvs->GetBufferPointer(), blobvs->GetBufferSize(), &InputLayout);
    devcon->IASetInputLayout(InputLayout);

    /////////////////////////////////////////////////////////

    blobvs->Release();
    blobps->Release();

    //////////////////IA//////////////////

    // select which vertex buffer to display
    UINT stride = sizeof(Vertex);
    UINT offset = 0;
    devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
    devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);

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

    /////////////////////////////////////////////////////////
}

// this is the function used to render a single frame
void RenderFrame(void)
{
    VSCBdata.brightness = 0.5f;
    // clear the back buffer to a deep blue
    devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(red, 0.2f, 0.4f, 1.0f));

    devcon->UpdateSubresource(VSConstantBuffer, 0, NULL, &VSCBdata, 0, 0);
    devcon->VSSetConstantBuffers(0, 1, &VSConstantBuffer);

    // draw the vertex buffer to the back buffer
    devcon->DrawIndexed(9, 0,0);

    // do 3D rendering on the back buffer here

    // switch the back buffer and the front buffer
    swapchain->Present(0, 0);
}

void InitBuffers()
{
    //////////////////VERTEX BUFFER//////////////////

    D3D11_BUFFER_DESC buffer_desc = { 0 };
    buffer_desc.ByteWidth = sizeof(Vertex) * ARRAYSIZE(triangle);
    buffer_desc.Usage = D3D11_USAGE_DEFAULT;
    buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    buffer_desc.CPUAccessFlags = 0;
    buffer_desc.MiscFlags = 0;
    buffer_desc.StructureByteStride = 0;

    D3D11_SUBRESOURCE_DATA sub = { 0 };
    sub.pSysMem = triangle;
    sub.SysMemPitch = 0;
    sub.SysMemSlicePitch = 0;

    dev->CreateBuffer(&buffer_desc, &sub, &VertexBuffer);

    /////////////////////////////////////////////////////////

    //////////////////INDEX BUFFER//////////////////

    D3D11_BUFFER_DESC index_desc = { 0 };
    index_desc.Usage = D3D11_USAGE_DEFAULT;
    index_desc.ByteWidth = sizeof(unsigned int) * ARRAYSIZE(indices);
    index_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
    index_desc.CPUAccessFlags = 0;
    index_desc.MiscFlags = 0;

    // Define the resource data.
    D3D11_SUBRESOURCE_DATA index_data;
    index_data.pSysMem = indices;
    index_data.SysMemPitch = 0;
    index_data.SysMemSlicePitch = 0;

    dev->CreateBuffer(&index_desc, &index_data, &IndexBuffer);

    /////////////////////////////////////////////////////////

    //////////////////CONSTANT BUFFER//////////////////

    // Define the constant data used to communicate with shaders.
    // Supply the vertex shader constant data.
    VSCBdata.brightness = 1.0f;

    // Fill in a buffer description.
    D3D11_BUFFER_DESC CBDesc;
    /////VERY STRANGÊ BEHAVIOUR 
    CBDesc.ByteWidth = 16;
    //////
    CBDesc.Usage = D3D11_USAGE_DYNAMIC;
    CBDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    CBDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    CBDesc.MiscFlags = 0;
    CBDesc.StructureByteStride = 0;

    // Fill in the subresource data.
    D3D11_SUBRESOURCE_DATA CBInitData;
    CBInitData.pSysMem = &VSCBdata;
    CBInitData.SysMemPitch = 0;
    CBInitData.SysMemSlicePitch = 0;

    // Create the buffer.
    dev->CreateBuffer(&CBDesc, &CBInitData,&VSConstantBuffer);

    // Set the buffer.
    devcon->VSSetConstantBuffers(0, 1, &VSConstantBuffer);

    /////////////////////////////////////////////////////////
}

void CleanD3D(void)
{
    //Device
    dev->Release();
    devcon->Release();
    /////////

    //Swapchain
    swapchain->Release();
    backbuffer->Release();
    /////////

    //Pipeline
    vs->Release();
    ps->Release();
    InputLayout->Release();
    /////////

    //Buffers
    VertexBuffer->Release();
    IndexBuffer->Release();
    VSConstantBuffer->Release();
    /////////
}

Here is the header file:

    #pragma once

#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#include <directxmath.h>
#include <d3dx10math.h>

using namespace DirectX;

// include the Direct3D Library file
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")

//////GLOBAL VARIABLES//////
static IDXGISwapChain* swapchain;             // the pointer to the swap chain interface
static ID3D11Device* dev;                     // the pointer to our Direct3D device interface
static ID3D11DeviceContext* devcon;           // the pointer to our Direct3D device context
static ID3D11RenderTargetView* backbuffer;    // the pointer to our render target
/////////////////////////

void InitD3D(HWND hWnd);     // sets up and initializes Direct3D
void RenderFrame(void);
void CleanD3D(void);             // closes Direct3D and releases memory
void InitPipeline();
void InitBuffers();

And the shaders:

cbuffer VS_CONSTANT_BUFFER
{
    float brightness;
};

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

VOut VS(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    float4 col = { brightness,brightness,brightness,1.0f };
    output.position = position;
    output.color = col;

    return output;
}


float4 PS(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
 }
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

https://docs.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-updatesubresource

A resource cannot be used as a destination if..... the resource is created with immutable or dynamic usage.

You can't use UpdateSubResource with a buffer created with D3D11_USAGE_DYNAMIC - you need to use Map instead.

Alternatively create with D3D11_USAGE_DEFAULT and use UpdateSubResource.

Which is better? It depends. Some drivers handle both the same internally. Map means that you shouldn't read from the returned pointer so you may need to refactor a little. UpdateSubResource involves an extra memory copy.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thank you really much, changed that and now it works, I had no idea there was a difference. \$\endgroup\$ Commented Jul 28, 2020 at 18:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .