首页 > 其他分享 >DX 使用常量缓冲区

DX 使用常量缓冲区

时间:2023-02-16 00:22:23浏览次数:54  
标签:常量 constantBufferData float4 FLAG DX SIGNATURE 缓冲区 D3D12 ROOT

前言

​ 本篇将展示如何使用常量缓冲区渲染一个移动的三角形,本篇基于绘制三角形篇展示新增步骤

流程图

Hello ConstantBuffer

shader file

//常量寄存器由tn指定,n为寄存器槽号
cbuffer SceneConstantBuffer : register(b0)
{
    float4 offset;	//用于实现移动的三角形
    float4 padding[15];
};

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

PSInput VSMain(float4 position : POSITION, float4 color : COLOR)
{
    PSInput result;

    result.position = position + offset;
    result.color = color;

    return result;
}

float4 PSMain(PSInput input) : SV_TARGET
{
    return input.color;
}

header file

struct SceneConstantBuffer
{
    XMFLOAT4 offset;
    float padding[60]; // 常量缓冲区的大小需要为最小分配空间256B的整数倍
};

static_assert((sizeof(SceneConstantBuffer) % 256) == 0, "Constant Buffer size must be 256-byte aligned");

ComPtr<ID3D12DescriptorHeap> m_cbvHeap;
ComPtr<ID3D12Resource> m_constantBuffer;
SceneConstantBuffer m_constantBufferData;
UINT8* m_pCbvDataBegin;

source file

初始化

加载管线

创建CBV描述符堆

// Describe and create a constant buffer view (CBV) descriptor heap.
// Flags indicate that this descriptor heap can be bound to the pipeline 
// and that descriptors contained in it can be referenced by a root table.
D3D12_DESCRIPTOR_HEAP_DESC cbvHeapDesc = {};
cbvHeapDesc.NumDescriptors = 1;
cbvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
cbvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvHeapDesc, IID_PPV_ARGS(&m_cbvHeap)));

加载资源

创建根签名

D3D12_FEATURE_DATA_ROOT_SIGNATURE featureData = {};

// This is the highest version the sample supports. If CheckFeatureSupport succeeds, the HighestVersion returned will not be greater than this.
featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1;

if (FAILED(m_device->CheckFeatureSupport(D3D12_FEATURE_ROOT_SIGNATURE, &featureData, sizeof(featureData))))
{
    featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0;
}

CD3DX12_DESCRIPTOR_RANGE1 ranges[1];
CD3DX12_ROOT_PARAMETER1 rootParameters[1];

ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC);
rootParameters[0].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_VERTEX);		//顶点着色器可以访问该根参数

// Allow input layout and deny uneccessary access to certain pipeline stages
D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =
    D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
    D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
    D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
    D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
    D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;

CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc;
rootSignatureDesc.Init_1_1(_countof(rootParameters), rootParameters, 0, nullptr, rootSignatureFlags);

ComPtr<ID3DBlob> signature;
ComPtr<ID3DBlob> error;
ThrowIfFailed(D3DX12SerializeVersionedRootSignature(&rootSignatureDesc, featureData.HighestVersion, &signature, &error));
ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)));

创建常量缓冲区

const UINT constantBufferSize = sizeof(SceneConstantBuffer);    // CB size is required to be 256-byte aligned.

ThrowIfFailed(m_device->CreateCommittedResource(
    &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
    D3D12_HEAP_FLAG_NONE,
    &CD3DX12_RESOURCE_DESC::Buffer(constantBufferSize),
    D3D12_RESOURCE_STATE_GENERIC_READ,
    nullptr,
    IID_PPV_ARGS(&m_constantBuffer)));

// Describe and create a constant buffer view.
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
cbvDesc.BufferLocation = m_constantBuffer->GetGPUVirtualAddress();
cbvDesc.SizeInBytes = constantBufferSize;
m_device->CreateConstantBufferView(&cbvDesc, m_cbvHeap->GetCPUDescriptorHandleForHeapStart());

//无需在此处进行Unmap(),因为后续在更新时会更改常量缓冲区的值
CD3DX12_RANGE readRange(0, 0);        // We do not intend to read from this resource on the CPU.
ThrowIfFailed(m_constantBuffer->Map(0, &readRange, reinterpret_cast<void**>(&m_pCbvDataBegin)));
memcpy(m_pCbvDataBegin, &m_constantBufferData, sizeof(m_constantBufferData));

更新

改变顶点坐标

const float translationSpeed = 0.005f;
const float offsetBounds = 1.25f;

m_constantBufferData.offset.x += translationSpeed;
if (m_constantBufferData.offset.x > offsetBounds)
{
    m_constantBufferData.offset.x = -offsetBounds;
}
memcpy(m_pCbvDataBegin, &m_constantBufferData, sizeof(m_constantBufferData));

渲染

设置描述符堆

ID3D12DescriptorHeap* ppHeaps[] = { m_cbvHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);

设置根描述符表

m_commandList->SetGraphicsRootDescriptorTable(0, m_cbvHeap->GetGPUDescriptorHandleForHeapStart());

reference

https://github.com/microsoft/DirectX-Graphics-Samples

标签:常量,constantBufferData,float4,FLAG,DX,SIGNATURE,缓冲区,D3D12,ROOT
From: https://www.cnblogs.com/chenglixue/p/17125225.html

相关文章

  • 常量、变量、表达式
    (1)常量在声明时就要赋值。constabc=1234;全局变量可以在声明的同时赋值,局部变量不可以在声明时赋值,变量不可以在程序主体的begin.end之间声明。全局变量,有一个简单的区......
  • 字符串常用类及常量池和扩容机制理解
    字符串相关类:String、StringBuffer、StringBuilder  字符串相关的类:* 1.String字符串类,底层是基于常量char[],一旦创建长度就固定不变了,适用于字符串不经常增删改的......
  • storclie64定位sdx盘符
    场景一:jbod盘定位系统里的sdd盘对应关系os命令键值关联关系raid卡命令键值lsscsi-uiwwn=storcli/c0/ex/sxshowallWWNlsscsitargetid=storc......
  • pycharm的使用与常量变量
    常量与变量pycharm软件的基本使用#1.下载与安装#2.pycharm的语言,一定要使用英文的#修改主题背景File settings Apperance Theme#修改字体......
  • Integer缓冲区
    publicclassDemo01{publicstaticvoidmain(String[]args){Integerinteger1=newInteger(100);Integerinteger2=newInteger(100);......
  • 常量表达式
    常量表达式——常量表达式指的是值不会改变,并且计算结果在编译过程就能得出的表达式。C++11新增的constexpr就是为直接检测某一表达式是否是常量表达式而存在,使用cons......
  • linux008之echo命令显示系统变量和常量
    linux中的系统变量和常量:简介:这里说的变量和常量与windows中的环境变量类似,如在windows中配置的java的环境变量,是这么配置的。java_home:xxxxx/bin,这个时候如果在linu......
  • 8.包装类、类型转换和装箱拆箱、整数缓冲区
    包装类基本数据类型所对应的引用数据类型Object可统一所有数据,包装类的默认值是null基本数据类型包装类型byteByteshortShortintIntegerlongLong......
  • Kotlin 变量、常量和类型
      02.Kotlin变量、常量和类型acc8226关注IP属地:云南0.2962023.01.2322:42:19字数2,359阅读41数据类型数值类型在Kotlin,一切都是一个对象,你可以调用......
  • Go 内置常量、类型、函数
    常量:true、false、iota、nil类型:int、int8、int16、int32、int64uint、uint8、unit16、uint32、uint64、uintptrfloat32、float64、complex128、complex64bool、......