PCEVA,PC绝对领域,探寻真正的电脑知识
开启左侧

从一个三角形开始看DX 12,DX11对比-1

[复制链接]
SCE-PhyreEngine 发表于 2016-2-27 23:57 | 显示全部楼层 |阅读模式
点击数:8249|回复数:14
      上篇帖子讲述了DX12一个有意思的功能: AFR多显示适配器的工作原理。从本帖开始,将从绘制一个三角形开始慢速介绍DX12的每一个特点并且和DX11对比。本帖属于入门贴但是跳过DX12大概述*(因为网上都说了)。这个帖子讲述的内容会很少但是以后会追加内容度。     DX12的相关结构定义和设备初始化
     





DX11的相关结构定义和设备初始化





DX11:D3D11CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,
                                            D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );
不必纠结代码,D3D11的CreateDevice创建起一个特点就是要传递一个要初始化的ID3D11DeviceContext指针对象。ID3D11DeviceContext在D3D11里面的很多功能开发操作都会用到,而且ID3D11DeviceContext里面的功能是依赖于显卡驱动的。
而且D3D11的每个相关状态的切换都要单独控制。
DX12:                ComPtr<IDXGIAdapter1> hardwareAdapter;
                GetHardwareAdapter(factory.Get(), &hardwareAdapter);

                ThrowIfFailed(D3D12CreateDevice(
                        hardwareAdapter.Get(),
                        D3D_FEATURE_LEVEL_12_1,
                        IID_PPV_ARGS(&m_device)
                        ));
        }

        // Describe and create the command queue.
        D3D12_COMMAND_QUEUE_DESC queueDesc = {};
        queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
        queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;

        ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)));

        // Describe and create the swap chain.
        DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
        swapChainDesc.BufferCount = FrameCount;
        swapChainDesc.BufferDesc.Width = m_width;
        swapChainDesc.BufferDesc.Height = m_height;
        swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
        swapChainDesc.OutputWindow = Win32Application::GetHwnd();
        swapChainDesc.SampleDesc.Count = 1;
        swapChainDesc.Windowed = TRUE;

        ComPtr<IDXGISwapChain> swapChain;
        ThrowIfFailed(factory->CreateSwapChain(
                m_commandQueue.Get(),                // Swap chain needs the queue so that it can force a flush on it.
                &swapChainDesc,
                &swapChain
                ));

        ThrowIfFailed(swapChain.As(&m_swapChain));

        // This sample does not support fullscreen transitions.
        ThrowIfFailed(factory->MakeWindowAssociation(Win32Application::GetHwnd(), DXGI_MWA_NO_ALT_ENTER));

        m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();

        // Create descriptor heaps.
        {
                // Describe and create a render target view (RTV) descriptor heap.
                D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
                rtvHeapDesc.NumDescriptors = FrameCount;
                rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
                rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
                ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap)));

                m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
        }

        // Create frame resources.
        {
                CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());

                // Create a RTV for each frame.
                for (UINT n = 0; n < FrameCount; n++)
                {
                        ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n])));
                        m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle);
                        rtvHandle.Offset(1, m_rtvDescriptorSize);
                }
        }

CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator)));
DX12的设备创建只需要你拿到硬件显示适配器并且指定D3D_FEATURE_LEVEL就可以了。
而原先DX11里D3D11DeviceContext交由具体开发人员自己来完成。
DX12相关状态的切换
首先需要开发人员CreateGraphicsPipelineState(
            _In_  const D3D12_GRAPHICS_PIPELINE_STATE_DESC *pDesc,
            REFIID riid,
            _COM_Outptr_  void **ppPipelineState) 创建一个统一的图形流水线的状态。

                D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
                psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };
                psoDesc.pRootSignature = m_rootSignature.Get();
                psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), vertexShader->GetBufferSize() };
                psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), pixelShader->GetBufferSize() };
                psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
                psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
                psoDesc.DepthStencilState.DepthEnable = FALSE;
                psoDesc.DepthStencilState.StencilEnable = FALSE;
                psoDesc.SampleMask = UINT_MAX;
                psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
                psoDesc.NumRenderTargets = 1;
                psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
                psoDesc.SampleDesc.Count = 1;
                ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState)));

DX12在相关渲染状态更新时,只在必要的时候去更新整个的图形流水线状态,不会像DX11那样频繁的切换每个单独的类型状态。

今天先介绍DX12和DX11两个明显不同的地方,后续帖子将讲述DX12,DX11绘制三角形的全过程。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

评分

参与人数 4代金券 +25 绝对值 +3 收起 理由
haierccc + 1 很给力!
马克吐槽 + 1 很给力!
hyenax1950xtx + 25
mrplplplpl + 1 很给力!

查看全部评分

SCE-PhyreEngine  楼主| 发表于 2016-2-28 00:31 | 显示全部楼层
今天讲述的内容比较少也可以说很少,因为DX12本身相比DX11对于程序人员都很难理解,若想学习好DX12,还必须了解硬件相关的。因为发的都是技术贴,要大家慢慢吸收。
今后一系列帖子只讨论技术,不讨论PC显卡好坏。因为由于我个人工作,爱好的原因我配置台式机,基本每配置一次至少两台机器,都是高端机,N卡旗舰一台,A卡期间一台,有代表性的每一代我都不会放过,如果赶上我自己研究新技术需要测试,那机器不会就两台,显卡数量就要看需要了。

我个人并不关心两厂显卡谁家强。因为反正我一样有俩,在上我业余时间PC只玩三大厂游戏。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
SCE-PhyreEngine  楼主| 发表于 2016-2-28 00:32 | 显示全部楼层
PS:微星主板内存通道坏了一次,还好在售后期就换了一个
mrplplplpl 发表于 2016-2-28 08:18 | 显示全部楼层
谢谢楼主的技术贴,做个记号
fastone 发表于 2016-2-28 09:04 | 显示全部楼层
创建渲染前一来就是上指针,没问题?
SCE-PhyreEngine  楼主| 发表于 2016-2-29 00:11 | 显示全部楼层
fastone 发表于 2016-2-28 09:04
创建渲染前一来就是上指针,没问题?

传进去之后会被赋值
hyenax1950xtx 发表于 2016-2-29 01:04 | 显示全部楼层
科普性好强,赞一个
建议以后中文解说部分标红,不然看起来有点点累
马克吐槽 发表于 2016-2-29 12:32 | 显示全部楼层
楼主讲讲原理就好吧,编程就记得一个hollo world
haierccc 发表于 2016-2-29 17:17 | 显示全部楼层
这类帖子很少有人懂的
所以要顶一顶!
fastone 发表于 2016-2-29 19:27 | 显示全部楼层
马克吐槽 发表于 2016-2-29 12:32
楼主讲讲原理就好吧,编程就记得一个hollo world

DX12那个原理的话,网上一堆,如果是写hallo world  DX12上面一堆东西依然要讲,因为实际纯DX12开发驱动部分基本是让程序员自己去写,同时包括DX11 要了解也需要先了解开头的驱动加载,不然写hallo world也没用,所以SCE的工程师才这样写这个文章的
马克吐槽 发表于 2016-2-29 22:18 | 显示全部楼层
fastone 发表于 2016-2-29 19:27
DX12那个原理的话,网上一堆,如果是写hallo world  DX12上面一堆东西依然要讲,因为实际纯DX12开发驱动 ...

谢谢,懂得。还有点建议。比如可以教教大家怎么玩这些编程,大学工科毕业的都会有这方面基础吧,就是需要点提示。比如用什么运行环境,代码也分享一下别用截图,这样我在自己电脑里也能玩玩
111alan 发表于 2016-3-1 03:12 | 显示全部楼层
大概能看懂代码,不过还是建议排个版说详细点
dongyi945 发表于 2016-3-2 12:20 | 显示全部楼层
c++的,dx12应该只能在win10下编译吧,毕竟win7是不支持dx12的。
代码截图看起来不方便,直接贴代码又没语法高亮。
darkion 发表于 2016-3-3 14:14 | 显示全部楼层
拜读,技术贴,纯支持了!
蜡笔小新 发表于 2016-3-14 12:51 | 显示全部楼层
技术贴 mark一下  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部