一、效果

这是一个比较简单的sample,运行sample可以看到,当红橙色长方形完全覆盖白色正方形时,白色正方形不显示,其他情况,均显示白色正方形。

二、实现

Render主要由三个部分组成

1.Far quad
2.Near quad Far
3.Quad bounding box

2和3都是是无论如何都要画的。在画3的时候,会进行一个Query,看3是不是所有的pixel都没有通过depth test(即是否被2全部覆盖)。根据上一帧Query的结果看是否画1,如果全部覆盖则不画1,否则画1。

程序逻辑如下:

1. 设置FarQuad的CBV(Constant Buffer View),根据上一帧Query的结果来SetPredication,画FarQuad;

2. SetPredication(NULL),设置NearQuad的CBV,画NearQuad;

3. 设置BoundingBox的CBV,为Query设置PSO(Pipeline State Object),BeginQuery – 画BoundingBox – EndQuery,导出Query的结果。

三、代码

首先要介绍一下API:

void SetPredication(
[in, optional] ID3D12Resource *pBuffer,
[in] UINT64 AlignedBufferOffset,
[in] D3D12_PREDICATION_OP Operation
);

官方SDK上面也有介绍,这里就简单说下,这个API表示,如果pBuffer里的数据满足Operation(=0或≠0),则后面的Rendering以及Resource操作都不会生效。如果pBuffer = NULL,则Predication被Disable掉(失效)。

Query的用法跟以前类似,需要注意的是,现在的SDK要求,除非Query type为TIMESTAMP,否则BeginQuery和EndQuery必须成对出现。

下面就来看一下代码。和这些samples相关的框架以及一些基本的API就不再赘述了,这里主要就介绍一下和PredicationQueries相关的代码。

D3D12PredicationQueries::LoadPipeline()

创建QueryHeap,类型为OCCLUSION,就是用来Query通过depth test的点的个数。

// Describe and create a heap for occlusion queries.
D3D12_QUERY_HEAP_DESC queryHeapDesc = {};
queryHeapDesc.Count = ;
queryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION;
ThrowIfFailed(m_device->CreateQueryHeap(&queryHeapDesc, IID_PPV_ARGS(&m_queryHeap)));

void D3D12PredicationQueries::LoadAssets()

为了能看到红橙色长方形下面是否画了白色正方形,必须打开Alpha blend

// Enable alpha blending so we can visualize the occlusion query results.
CD3DX12_BLEND_DESC blendDesc(D3D12_DEFAULT);
blendDesc.RenderTarget[] =
{
TRUE, FALSE,
D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD,
D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
D3D12_LOGIC_OP_NOOP,
D3D12_COLOR_WRITE_ENABLE_ALL,
};

在画Bounding box的时候,只是为了做Occlusion Query,因此不需要把render结果写到RT(RenderTarget)和DS(Depth Stencil)里面去。

// Disable color writes and depth writes for the occlusion query's state.
psoDesc.BlendState.RenderTarget[].RenderTargetWriteMask = ;
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_queryState)));

void D3D12PredicationQueries::OnUpdate()里面主要就是去更新红橙色长方形的CBV(即它的位置),因为它以一个速度从左至右移动。

void D3D12PredicationQueries::PopulateCommandList()

这里就是按照之前介绍的逻辑进行Render。

CD3DX12_GPU_DESCRIPTOR_HANDLE cbvFarQuad(m_cbvHeap->GetGPUDescriptorHandleForHeapStart(), m_frameIndex * CbvCountPerFrame, m_cbvSrvDescriptorSize);
CD3DX12_GPU_DESCRIPTOR_HANDLE cbvNearQuad(cbvFarQuad, m_cbvSrvDescriptorSize); m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
m_commandList->IASetVertexBuffers(, , &m_vertexBufferView); // Draw the far quad conditionally based on the result of the occlusion query
// from the previous frame.
m_commandList->SetGraphicsRootDescriptorTable(, cbvFarQuad);
m_commandList->SetPredication(m_queryResult.Get(), , D3D12_PREDICATION_OP_EQUAL_ZERO);
m_commandList->DrawInstanced(, , , ); // Disable predication and always draw the near quad.
m_commandList->SetPredication(nullptr, , D3D12_PREDICATION_OP_EQUAL_ZERO);
m_commandList->SetGraphicsRootDescriptorTable(, cbvNearQuad);
m_commandList->DrawInstanced(, , , ); // Run the occlusion query with the bounding box quad.
m_commandList->SetGraphicsRootDescriptorTable(, cbvFarQuad);
m_commandList->SetPipelineState(m_queryState.Get());
m_commandList->BeginQuery(m_queryHeap.Get(), D3D12_QUERY_TYPE_BINARY_OCCLUSION, );
m_commandList->DrawInstanced(, , , );
m_commandList->EndQuery(m_queryHeap.Get(), D3D12_QUERY_TYPE_BINARY_OCCLUSION, ); // Resolve the occlusion query and store the results in the query result buffer
// to be used on the subsequent frame.
m_commandList->ResourceBarrier(, &CD3DX12_RESOURCE_BARRIER::Transition(m_queryResult.Get(), D3D12_RESOURCE_STATE_PREDICATION, D3D12_RESOURCE_STATE_COPY_DEST));
m_commandList->ResolveQueryData(m_queryHeap.Get(), D3D12_QUERY_TYPE_BINARY_OCCLUSION, , , m_queryResult.Get(), );
m_commandList->ResourceBarrier(, &CD3DX12_RESOURCE_BARRIER::Transition(m_queryResult.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D

从上面的代码可以看到,最后一个Draw实际上就是去Query通过Depth test的点的个数,ResolveQueryData会将Query的结果Resolve到一块buffer里面。Query Type为D3D12_QUERY_TYPE_BINARY_OCCLUSION表示Query结果只有两种:0表示点通过depth stencil test,1表示至少有一个点通过。也就是说在下一帧Draw far quad之前,会根据这个buffer里面的结果是否等于0来SetPredication。如果结果为0,表示上一帧的长方形完全覆盖住白色正方形,则后面的Draw失效,不画白色正方形。

话说有个问题就是,为什么不把Draw bounding box放在最前面?那样就可以实时的判断当前帧是否需要画白色正方形。不知道放在后面,让下一帧再去判断是什么意思。

DirectX12 Samples 学习笔记 – PredicationQueries的更多相关文章

  1. Intel® Media SDK Media Samples Linux 学习笔记(转)

    最近折腾intel media sdk,主要硬件平台是在HD4600的核显上进行测试,intel media sdk是intel提供的一种基于核显的硬件编解码的解决方案,之前已经有使用ffmpeg进行 ...

  2. Caffe学习笔记2--Ubuntu 14.04 64bit 安装Caffe(GPU版本)

    0.检查配置 1. VMWare上运行的Ubuntu,并不能支持真实的GPU(除了特定版本的VMWare和特定的GPU,要求条件严格,所以我在VMWare上搭建好了Caffe环境后,又重新在Windo ...

  3. DirectX 总结和DirectX 9.0 学习笔记

    转自:http://www.cnblogs.com/graphics/archive/2009/11/25/1583682.html DirectX 总结 DDS DirectXDraw Surfac ...

  4. CentOS学习笔记--Tomcat安装

    Tomcat安装 通常情况下我们要配置Tomcat是很容易的一件事情,但是如果您要架设多用户多服务的Java虚拟主机就不那么容易了.其中最大的一个问题就是Tomcat执行权限.普通方式配置的Tomca ...

  5. opencv2.4.13+python2.7学习笔记--使用 knn对手写数字OCR

    阅读对象:熟悉knn.了解opencv和python. 1.knn理论介绍:算法学习笔记:knn理论介绍 2. opencv中knn函数 路径:opencv\sources\modules\ml\in ...

  6. Deep learning with Python 学习笔记(7)

    介绍一维卷积神经网络 卷积神经网络能够进行卷积运算,从局部输入图块中提取特征,并能够将表示模块化,同时可以高效地利用数据.这些性质让卷积神经网络在计算机视觉领域表现优异,同样也让它对序列处理特别有效. ...

  7. monkeyrunner学习笔记

    前面部分内容转自http://blog.csdn.net/zm2714/article/details/7980634 Android自动化测试之Monkeyrunner使用方法及实例 目前andro ...

  8. Keras学习笔记——Hello Keras

    最近几年,随着AlphaGo的崛起,深度学习开始出现在各个领域,比如无人车.图像识别.物体检测.推荐系统.语音识别.聊天问答等等.因此具备深度学习的知识并能应用实践,已经成为很多开发者包括博主本人的下 ...

  9. Deep learning with Python 学习笔记(6)

    本节介绍循环神经网络及其优化 循环神经网络(RNN,recurrent neural network)处理序列的方式是,遍历所有序列元素,并保存一个状态(state),其中包含与已查看内容相关的信息. ...

随机推荐

  1. java如何区分是form表单请求,还是ajax请求

    requestType = request.getHeader("X-Requested-With");                 if(requestType==null) ...

  2. day8-异常

    异常处理 1.异常基础 在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!! try: pass except Ex ...

  3. android sdk manager 代理设置(送给牛逼的)

    解决android sdk更新慢的问题(公司竟然把sdk更新给墙了). 第一步:如下图 第二部:进入代理设置页面,进行设置.如下图  

  4. Android开发-无法新建Activity及新建后编译错误

    下载了其他的工程后,新建Activity时无法进行下一步,报错:“This template requires a minimum SDK version of at least 7, and the ...

  5. ShellExecute 使用方法

    ShellExecute的功能是运行一个外部程序(或者是打开一个已注册的文件.打开一个目录.打印一个文件等等),并对外部程序有一定的控制. 有几个API函数都可以实现这些功能,但是在大多数情况下She ...

  6. GPUImage实现摄像头暂停

    GPUImage相信很多开发者都用过,其本身也是十分简单易用,因此对于GPUImage的基本用法不再赘述. 最近在使用GPUImage时要实现摄像时暂停和继续的功能,但GPUImage本身并没有提供相 ...

  7. node.js搭建简单的websocket

    1.首先在官网http://www.nodejs.org/下载NODE.JS 2.打开命令行CMD,进入NODEJS\node_modules\的目录,输入npm install socket.io  ...

  8. Bay Trail平板安装Ubuntu ThinkPad 8(20BNA00RCD)

    首先说下没搞定的事项: 1,grub不能启动w10 2,ubuntu不能检测到无线网卡硬件 3,ubuntu更新软件和语言支持时,unpacking文件时经常都会发生卡死(怀疑是emmc驱动的问题) ...

  9. 对于有了ACM以后的生活

    我是大二学生,才接触ACM不到5个星期,因为受到我们班dalao的"引诱",去参加了一次我们学校举行的萌新杯,于是就入坑了,而我又在校外学习一些关于安全的知识,前几天一直纠结要不要 ...

  10. es6 Class的继承extends & super

    Class之间可以通过extends关键字,实现继承. 子类会继承父类的属性和方法. class Point { constructor(x, y) { this.x = x; this.y = y; ...