一、效果

这是一个比较简单的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. ASCIITable: 演示 Arduino 串口输出的进阶功能

    原文地址 - https://www.arduino.cc/en/Tutorial/ASCIITable ASCII字符表 本例展示了高级的串口打印功能,通过本功能可以在Arduino软件(IDE)的 ...

  2. Python基础篇【第5篇】: Python模块基础(一)

    模块 简介 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就 ...

  3. 【HOW】如何限制Reporting Services报表导出功能中格式选项

    Reporting Services报表导出功能中缺省会提供多种导出格式选项,但很多情况下不需要全部的格式选项,因此需要对这些选项进行限制.下面我们以SQL Server 2008 R2为例来说明对这 ...

  4. Shift的用法

    Shell编程中Shift的用法     位置参数可以用shift命令左移.比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1.$2.$3丢弃,$0不移动.不带参数的 ...

  5. WEB页面采集器编写经验之一:静态页面采集器

    严格意义来说,采集器和爬虫不是一回事:采集器是对特定结构的数据来源进行解析.结构化,将所需的数据从中提取出来:而爬虫的主要目标更多的是页面里的链接和页面的TITLE. 采集器也写过不少了,随便写一点经 ...

  6. html基础 链接

    使用图像来作链接: (链接标签中嵌套图片标签) <html> <body> <p> 您也可以使用图像来作链接: <a href="/example/ ...

  7. Gold Game

    一.项目描述:黄金点游戏 黄金点游戏是一个数字小游戏,其游戏规则是: N个同学(N通常大于10),每人写一个0-100之间的有理数 (不包括0或100),交给裁判,裁判算出所有数字的平均值,然后乘以0 ...

  8. Ninject之旅之九:Ninject上下文绑定(附程序下载)

    摘要 既然在插件模型里,每一个服务类型可以被映射到多个实现,绑定方法不用决定要返回哪个实现.因为kernel应该返回所有的实现.然而,上下文绑定是多个绑定场景,在这个场景里,kernel需要根据给定的 ...

  9. J2EE应用监控后台执行SQL

    我们可能已经很熟悉在未使用数据库连接池的hibernate的环境下,配置p6spy和sql profiler.这在单独使用hibernate,以及项目初期是有效的.但是,在真实的开发环境下,往往是项目 ...

  10. Ajax请求数据

    后台使用数数组的形式存放数据(以键值对的形式存放).让后再Json转码. Map<String,String> map=new HashMap<String,String>() ...