DirectX 11에서 Raw Buffer는 특정한 해석이나 형식 없이 바이트 시퀀스를 저장하는 데 사용되는 버퍼 객체의 유형을 가리킨다. 단순히 그래픽 처리 장치(GPU)가 유연한 방식으로 접근할 수 있는 메모리 블록이다. Raw Buffer를 사용하면 미리 정의된 형식으로 제한되지 않고 저장되는 데이터의 형식과 구조를 정의할 수 있다.

 

목차

     

     


     

     

     

    Raw Buffer

     

    DirectX 11에서 Raw Buffer는 특정한 해석이나 형식 없이 바이트 시퀀스를 저장하는 데 사용되는 버퍼 객체의 유형을 가리킨다. 단순히 그래픽 처리 장치(GPU)가 유연한 방식으로 접근할 수 있는 메모리 블록이다.

    Raw Buffer는 일반적으로 CPU와 GPU 사이 또는 GPU 내의 서로 다른 셰이더 단계 사이에 전달되어야 하는 임의의 데이터를 저장하는 데 사용된다. 예를 들어 Raw Buffer는 정점 데이터, 텍스처 데이터 또는 다른 유형의 메타데이터를 저장하는 데 사용될 수 있다.

    Raw Buffer를 사용하는 한 가지 이점은 프로그래머가 미리 정의된 형식으로 제한되지 않고 저장되는 데이터의 형식과 구조를 정의할 수 있다는 것이다. 이것은 사용자 정의 데이터 유형 또는 비표준 데이터 형식으로 작업할 때 특히 유용할 수 있습니다.

    DirectX 11에서 Raw Buffer를 사용하려면 일반적으로 ID3D11Device 인터페이스를 사용하여 버퍼 개체를 만들고 버퍼 크기를 바이트 단위로 지정한다. 그런 다음 버퍼 개체를 사용하여 ID3D11DeviceContext 인터페이스를 사용하여 필요에 따라 데이터를 읽거나 쓸 수 있다.

     

    Shader
       
    Framework
      Render
      Buffer.h .cpp
    UnitTest
      DirectCompute
      RawBufferDemo.h .cpp
      Main.h .cpp

     


    Buffer

     

    Buffers.h

    더보기
    #pragma once
    
    class VertexBuffer
    {
    public:
    	VertexBuffer(void* data, UINT count, UINT stride, UINT slot = 0, bool bCpuWrite = false, bool bGpuWrite = false);
    	~VertexBuffer();
    
    	UINT Count() { return count; }
    	UINT Stride() { return stride; }
    	ID3D11Buffer* Buffer() { return buffer; }
    
    	void Render();
    
    private:
    	ID3D11Buffer* buffer;
    
    	void* data;
    	UINT count;
    	UINT stride;
    	UINT slot;
    
    	bool bCpuWrite;
    	bool bGpuWrite;
    };
    
    
    
    class IndexBuffer
    {
    public:
    	IndexBuffer(void* data, UINT count);
    	~IndexBuffer();
    
    	UINT Count() { return count; }
    	ID3D11Buffer* Buffer() { return buffer; }
    
    	void Render();
    
    private:
    	ID3D11Buffer* buffer;
    
    	void* data;
    	UINT count;
    };
    
    //
    
    class ConstantBuffer
    {
    public:
    	ConstantBuffer(void* data, UINT dataSize);
    	~ConstantBuffer();
    
    	ID3D11Buffer* Buffer() { return buffer; }
    
    	void Render();
    
    private:
    	ID3D11Buffer* buffer;
    
    	void* data;
    	UINT dataSize;
    };
    
    //
    
    class CsResource
    {
    public:
    	CsResource();
    	virtual ~CsResource();
    
    protected:
    	virtual void CreateInput() {}
    	virtual void CreateSRV() {}
    
    	virtual void CreateOutput() {}
    	virtual void CreateUAV() {}
    
    	virtual void CreateResult() {}
    
    	void CreateBuffer();
    
    public:
    	ID3D11ShaderResourceView* SRV() { return srv; }
    	ID3D11UnorderedAccessView* UAV() { return uav; }
    
    protected:
    	ID3D11Resource* input = NULL;
    	ID3D11ShaderResourceView* srv = NULL; //Input
    
    	ID3D11Resource* output = NULL;
    	ID3D11UnorderedAccessView* uav = NULL; //Output
    
    	ID3D11Resource* result = NULL;
    };
    
    //
    
    class RawBuffer : public CsResource
    {
    public:
    	RawBuffer(void* inputData, UINT inputByte, UINT outputByte);
    	~RawBuffer();
    
    private:
    	void CreateInput() override;
    	void CreateSRV() override;
    
    	void CreateOutput() override;
    	void CreateUAV() override;
    
    	void CreateResult() override;
    
    public:
    	void CopyToInput(void* data);   //input으로부터 데이터를 복사해올때 
    	void CopyFromOuput(void* data); //output으로부터 데이터를 복사해올때
    
    private:
    	void* inputData;
    	
    	UINT inputByte;  //입력으로 얼마나 Byte쓸지
    	UINT outputByte; //출력으로 얼마나 Byte쓸지
    };

     

     

    Buffers.cpp

    더보기
    #include "Framework.h"
    #include "Buffers.h"
    
    VertexBuffer::VertexBuffer(void * data, UINT count, UINT stride, UINT slot, bool bCpuWrite, bool bGpuWrite)
    	: data(data), count(count), stride(stride), slot(slot)
    	, bCpuWrite(bCpuWrite), bGpuWrite(bGpuWrite)
    {
    	D3D11_BUFFER_DESC desc;
    	ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
    	desc.ByteWidth = stride * count;
    	desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    
    	if (bCpuWrite == false && bGpuWrite == false)
    	{
    		desc.Usage = D3D11_USAGE_IMMUTABLE; //GPU 읽기
    	}
    	else if (bCpuWrite == true && bGpuWrite == false)
    	{
    		desc.Usage = D3D11_USAGE_DYNAMIC; //CPU 쓰기, GPU 읽기
    		desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
    	}
    	else if (bCpuWrite == false && bGpuWrite == true)
    	{
    		//CPU 쓰기 가능 - UpdateSubResource
    		desc.Usage = D3D11_USAGE_DEFAULT;
    	}
    	else
    	{
    		desc.Usage = D3D11_USAGE_STAGING;
    		desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
    	}
    
    	D3D11_SUBRESOURCE_DATA subResource = { 0 };
    	subResource.pSysMem = data;
    
    	Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &buffer));
    }
    
    VertexBuffer::~VertexBuffer()
    {
    	SafeRelease(buffer);
    }
    
    void VertexBuffer::Render()
    {
    	UINT offset = 0;
    	D3D::GetDC()->IASetVertexBuffers(slot, 1, &buffer, &stride, &offset);
    }
    
    //
    
    IndexBuffer::IndexBuffer(void * data, UINT count)
    	: data(data), count(count)
    {
    	D3D11_BUFFER_DESC desc;
    	ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
    
    	desc.ByteWidth = sizeof(UINT) * count;
    	desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
    	desc.Usage = D3D11_USAGE_IMMUTABLE;
    
    
    	D3D11_SUBRESOURCE_DATA subResource = { 0 };
    	subResource.pSysMem = data;
    
    	Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &buffer));
    }
    
    IndexBuffer::~IndexBuffer()
    {
    	SafeRelease(buffer);
    }
    
    void IndexBuffer::Render()
    {
    	D3D::GetDC()->IASetIndexBuffer(buffer, DXGI_FORMAT_R32_UINT, 0);
    }
    
    //
    
    ConstantBuffer::ConstantBuffer(void * data, UINT dataSize)
    	: data(data), dataSize(dataSize)
    {
    	D3D11_BUFFER_DESC desc;
    	ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
    
    	desc.ByteWidth = dataSize;
    	desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    	desc.Usage = D3D11_USAGE_DYNAMIC;
    	desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
    
    	Check(D3D::GetDevice()->CreateBuffer(&desc, NULL, &buffer));
    }
    
    ConstantBuffer::~ConstantBuffer()
    {
    	SafeRelease(buffer);
    }
    
    void ConstantBuffer::Render()
    {
    	D3D11_MAPPED_SUBRESOURCE subResource;
    	D3D::GetDC()->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource);
    	{
    		memcpy(subResource.pData, data, dataSize);
    	}
    	D3D::GetDC()->Unmap(buffer, 0);
    }
    
    //
    
    CsResource::CsResource()
    {
    
    }
    
    CsResource::~CsResource()
    {
    	SafeRelease(input);
    	SafeRelease(srv);
    
    	SafeRelease(output);
    	SafeRelease(uav);
    
    	SafeRelease(result);
    }
    
    void CsResource::CreateBuffer()
    {
    	CreateInput();
    	CreateSRV();
    
    	CreateOutput();
    	CreateUAV();
    
    	CreateResult();
    }
    
    //
    
    RawBuffer::RawBuffer(void * inputData, UINT inputByte, UINT outputByte)
    	: CsResource()
    	, inputData(inputData), inputByte(inputByte), outputByte(outputByte)
    {
    	CreateBuffer();
    }
    
    RawBuffer::~RawBuffer()
    {
    
    }
    
    void RawBuffer::CreateInput()
    {
    	if (inputByte < 1) return; //inputByte가 1보다 작으면 버퍼를 생성할 수 없으니 패스.
    
    
    	ID3D11Buffer* buffer = NULL; 
    
    	D3D11_BUFFER_DESC desc;
    	ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
    
    	desc.ByteWidth = inputByte;
    	desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    	desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; //Buffer용도
    	desc.Usage = D3D11_USAGE_DYNAMIC;
    	desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    
    	D3D11_SUBRESOURCE_DATA subResource = { 0 };
    	subResource.pSysMem = inputData;
    
    	//inputData가 있으면 subResourse를 넣어주고 없으면 NULL.
    	Check(D3D::GetDevice()->CreateBuffer(&desc, inputData != NULL ? &subResource : NULL, &buffer));
    
    	//input에 buffer 저장
    	input = (ID3D11Resource *)buffer;
    }
    
    void RawBuffer::CreateSRV()
    {
    	if (inputByte < 1) return;
    
    
    	ID3D11Buffer* buffer = (ID3D11Buffer *)input;
    
    	D3D11_BUFFER_DESC desc;
    	buffer->GetDesc(&desc);
    
    
    	D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    	ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));//SHADER_RESOURCE_VIEW에 연결하겠다.
    	srvDesc.Format = DXGI_FORMAT_R32_TYPELESS; //32비트(=4바이트). buffer의 데이터 하나를 4바이트로 설정하는게 일반적이다.
    	srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
    	srvDesc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW; //RawBuffer용 ByteAddress로 다루어라.
    	srvDesc.BufferEx.NumElements = desc.ByteWidth / 4; //전체 데이터의 개수 = 전체크기(ByteWidth)/ 설정한 기본 바이트 크기(4바이트)
    
    	Check(D3D::GetDevice()->CreateShaderResourceView(buffer, &srvDesc, &srv));
    }
    
    void RawBuffer::CreateOutput()
    {
    	ID3D11Buffer* buffer = NULL;
    
    	D3D11_BUFFER_DESC desc;
    	ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
    
    	desc.ByteWidth = outputByte;
    	desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;
    	desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
    
    	Check(D3D::GetDevice()->CreateBuffer(&desc, NULL, &buffer));
    
    	output = (ID3D11Resource *)buffer;
    }
    
    void RawBuffer::CreateUAV()
    {
    	ID3D11Buffer* buffer = (ID3D11Buffer *)output;
    
    	D3D11_BUFFER_DESC desc;
    	buffer->GetDesc(&desc);
    
    
    	D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
    	ZeroMemory(&uavDesc, sizeof(D3D11_UNORDERED_ACCESS_VIEW_DESC));
    	uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
    	uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
    	uavDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
    	uavDesc.Buffer.NumElements = desc.ByteWidth / 4;
    
    	Check(D3D::GetDevice()->CreateUnorderedAccessView(buffer, &uavDesc, &uav));
    }
    
    void RawBuffer::CreateResult()
    {
    	ID3D11Buffer* buffer;
    
    	D3D11_BUFFER_DESC desc;
    	((ID3D11Buffer *)output)->GetDesc(&desc); //output이 만들어진 데이터를 가져온다.
    	desc.Usage = D3D11_USAGE_STAGING;
    	desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; //결과를 읽는다.
    	desc.BindFlags = D3D11_USAGE_DEFAULT; //D3D11_USAGE_DEFAULT = 0
    	desc.MiscFlags = 0;
    
    	Check(D3D::GetDevice()->CreateBuffer(&desc, NULL, &buffer));
    
    	result = (ID3D11Resource *)buffer;
    }
    
    void RawBuffer::CopyToInput(void * data)
    {
    	D3D11_MAPPED_SUBRESOURCE subResource; //CPU에게 데이터를 써주거나 읽을때 MAPPED 사용.
    	D3D::GetDC()->Map(input, 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource);
    	{
    		memcpy(subResource.pData, data, inputByte);
    	}
    	D3D::GetDC()->Unmap(input, 0);
    }
    
    void RawBuffer::CopyFromOuput(void * data)
    {
    	//usage가 뭐든간에 ouput에 접근에서 리소스를 복사하여 result에 대입한다.
    	D3D::GetDC()->CopyResource(result, output);
    
    	D3D11_MAPPED_SUBRESOURCE subResource;
    	D3D::GetDC()->Map(result, 0, D3D11_MAP_READ, 0, &subResource);
    	{
    		memcpy(data, subResource.pData, outputByte);
    	}
    	D3D::GetDC()->Unmap(result, 0);
    }

     

    void RawBuffer::CreateInput()

     


     

    Raw Buffer

     

    RawBuffer.h

    더보기
    #pragma once
    #include "Systems/IExecute.h"
    
    class RawBufferDemo : public IExecute
    {
    public:
    	virtual void Initialize() override;
    	virtual void Ready() override {}
    	virtual void Destroy() override {}
    	virtual void Update() override;
    	virtual void PreRender() override {}
    	virtual void Render() override;
    	virtual void PostRender() override {}
    	virtual void ResizeScreen() override {}
    
    private:
    };

     

     

    RawBuffer.cpp

    더보기
    #include "stdafx.h"
    #include "RawBufferDemo.h"
    
    void RawBufferDemo::Initialize()
    {
    	
    }
    
    void RawBufferDemo::Update()
    {
    	
    }
    
    void RawBufferDemo::Render()
    {
    	
    }

     

     


     

    실행화면