一、效果

这是一个比较简单的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. C语言fmod()函数:对浮点数取模(求余)

    头文件:#include <math.h> fmod() 用来对浮点数进行取模(求余),其原型为:    double fmod (double x); 设返回值为 ret,那么 x = ...

  2. Maven(一)maven环境搭建

    1.下载maven安装文件 https://maven.apache.org/download.cgi#,根据自己的需要下载对应版本 2. 配置maven环境变量,和java环境变量配置方式类似.   ...

  3. 慕课网-Java入门第一季-7-4 编程练习

    来源:http://www.imooc.com/code/1634 小伙伴们,请根据所学知识,参考注释,在代码编辑器中将代码补充完整.编写一个 Java 程序,实现输出学生年龄的最大值 要求: 1. ...

  4. 基于MFC的单文档,多文档,对话框应用程序

    从类的角度区分: 基于对话框(3个类): CAboutDlg 程序名App 程序名Dlg 单文档(5个类): CAboutDlg CMainFrame 程序名App 程序名Doc 程序名View 多文 ...

  5. cat > file << EOF 的用法

    cat> 文件名<<eof 用来创建文件在这之后输入任何东西 都是在 文件里的输入完成之后EOF结尾 代表结束比如cat > 1.txt <<eof12345eof ...

  6. 用JS实现九九乘法表

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. MVC中的@符号

    1: @if (@Model.DepositList != null) { } 2: @if (@Model.DepositList != null) { foreach (Deposit_ViewM ...

  8. Rendering pipeline overview(读书笔记1 --- Real-Time rendering)

    1. Rendering pipeline的作用就是在给定的虚拟相机.三维物体.光源.着色方程式.纹理等的条件下产生(渲染)二维图像 2. pipeline包含很多个stage,其效率由最慢的stag ...

  9. 几种linux脚本的简单执行方法

    1.hash脚本文件名:assign 内 容:#!/bin/sh cd $1ls 执行: [root@db2 ~]# sh helle2.sh /usr 或者[root@db2 ~]#./helle2 ...

  10. 用Python读写Excel文件(转)

    原文:google.com/ncr 虽然天天跟数据打交道,也频繁地使用Excel进行一些简单的数据处理和展示,但长期以来总是小心地避免用Python直接读写Excel文件.通常我都是把数据保存为以TA ...