SOL9 Sample: Direct3D11On12Bitmap

SOL9 2.0 Samples

1 Screenshot


2 Source code

/*
 * Direct3D11On12Bitmap.cpp 
 * Copyright (c) 2015 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


// 2016/11/29
// This is based on the sample program in
// https://github.com/Microsoft/DirectX-Graphics-Samples
// See: DirectX-Graphics-Samples-master\Samples\Desktop\D3D1211On12

// You can rotate a shape by the left and right keys, without 
//changing an image of "TokyoSkyTree.png".
  
// 2017/01/28 Updated to use ModuleFileName and caught macro.


#define COMMONCONTROLS_V6
#define WIN10

#include <sol/COMInitializer.h>
#include <sol/CharModuleFileName.h>

#include <sol/WCharModuleFileName.h>
#include <sol/direct3d12/DirectX3D12MainView.h>
#include <sol/direct3d12/DirectXMatrix.h>
#include <sol/direct3d12/Direct3D11On12Device.h>
#include <sol/direct3d12/Direct3D11On12WrappedResource.h>
#include <sol/direct3d12/Direct3D12CommandAllocator.h>
#include <sol/direct3d12/Direct3D12RenderTargetView.h>
#include <sol/direct3d12/Direct3D12DepthStencilView.h>
#include <sol/direct3d12/Direct3D12ShaderResourceView.h>
#include <sol/direct3d12/Direct3D12TransformConstantBufferView.h>
#include <sol/direct3d12/Direct3D12RootSignature.h>
#include <sol/direct3d12/Direct3D12BarrieredGraphicsCommandList.h>
#include <sol/direct3d12/Direct3D12PipelineState.h>
#include <sol/direct3d12/D3D12RasterizerDesc.h>
#include <sol/direct3d12/D3D12BlendDesc.h>
#include <sol/direct3d12/D3D12GraphicsPipelineStateDesc.h>
#include <sol/direct3d12/D3D12Transform.h>
#include <sol/direct3d12/D3D12GraphicsPipelineStateDesc.h>
#include <sol/direct3d12/Direct3D12Synchronizer.h>
#include <sol/direct3d12/Direct3DX12TexturedCube.h>
#include <sol/direct3d12/DirectXTransform.h>
#include <sol/direct3d12/Direct3D12CommonDescriptorHeap.h>
#include <sol/direct3d12/Direct3D12Texture2D.h>

#include <sol/directx/Direct2D1Factory3.h>
#include <sol/directx/Direct2D1Device2.h>
#include <sol/directx/Direct2D1DeviceContext2.h>
#include <sol/directx/Direct2D1Bitmap1.h>
#include <sol/directx/Direct2D1Bitmap.h>
#include <sol/directx/Direct2D1LinearGradientBrush.h>
#include <sol/directx/Direct2D1GradientStopCollection.h>

#include <sol/dxgi/DirectXGIDevice1.h>
#include <sol/dxgi/DirectXGISurface.h>
#include <sol/wic/WICBitmapFileReader.h>

#include <sol/direct3d12/Direct3D12IntermediateResource.h>
#include <sol/ImageFileReader.h>
#include <sol/direct3d12/D3D12SubresourceData.h>

#include "resource.h"

namespace SOL {
  
class MainView :public DirectX3D12MainView {
private:
  static const int FRAME_COUNT = 3;
  
private:
  //Inner class starts.
  //-----------------------------------------------------------------------------------------
  class DirectXGeometryRenderer : public  DirectXGIDevice1 {
    
  private:    
      SmartPtr<Direct2D1Device2>              d2d1Device2;
    SmartPtr<Direct2D1DeviceContext2>       d2d1DeviceContext2;
    
    SmartPtr<Direct3D11On12WrappedResource> wrappedBackBuffers[FRAME_COUNT];
    SmartPtr<Direct2D1Bitmap1>              d2d1RenderTargets1[FRAME_COUNT];
    SmartPtr<DirectXGIDevice1>              dxgiDevice1;
    SmartPtr<Direct2D1Factory3>             d2d1Factory3;
    SmartPtr<Direct2D1Bitmap>               bitmap;

    void createWrappedBackBuffers(ID3D11On12Device* d3d11On12Device,
                              Direct3D12RenderTargetView* renderTargetView)
    {
      try {
        float dpiX;
        float dpiY;
        d2d1Factory3->getDesktopDpi(&dpiX, &dpiY);

        for (UINT n = 0; n < FRAME_COUNT; n++) {
          wrappedBackBuffers[n] = new Direct3D11On12WrappedResource(d3d11On12Device, 
                renderTargetView->getResource(n));
          IDXGISurface* surface = nullptr;
          wrappedBackBuffers[n]->queryInterface(IID_PPV_ARGS(&surface));
        
          d2d1RenderTargets1[n] = new Direct2D1Bitmap1(*d2d1DeviceContext2, surface,
              dpiX,
              dpiY);
          surface->Release();
        }
      }
      catch (Exception& ex) {
        caught(ex);
      }
    }
    
  public:
    //
    //Inner class constructor
    DirectXGeometryRenderer(ID3D11On12Device* d3d11On12Device,
                  Direct3D12RenderTargetView* renderTargetView,
                  int width,
                  int height,
                  const wchar_t* fileName)
    :DirectXGIDevice1(d3d11On12Device)
    {
      d2d1Factory3 = new Direct2D1Factory3();

      d2d1Device2        = new Direct2D1Device2(*d2d1Factory3, *this);
             
      d2d1DeviceContext2 = new Direct2D1DeviceContext2(*d2d1Device2);

      createWrappedBackBuffers(d3d11On12Device, renderTargetView);
 
      WICImagingFactory imagingFactory;

      WCharModuleFileName moduleFileName;
      const wchar_t* dir = moduleFileName.getDir();
      wchar_t url[MAX_PATH];
      swprintf_s(url, CountOf(url), L"%s\\..\\image\\%s", dir, fileName);;
        
      WICBitmapFileReader reader(imagingFactory, url);
      bitmap = reader.read(*d2d1DeviceContext2, width, height);
    }

    ~DirectXGeometryRenderer()
    {
    }
          
    void drawBitmap(int frameIndex)
    {
      try {
        wrappedBackBuffers[frameIndex]->acquire();

        d2d1DeviceContext2->setTarget(*d2d1RenderTargets1[frameIndex]);

        d2d1DeviceContext2->beginDraw();
        d2d1DeviceContext2->setTransform(D2D1::Matrix3x2F::Identity());

        D2D1_SIZE_F bsize = bitmap->getSize();
        auto rectangle = D2D1::RectF(0.0f, 0.0f, bsize.width/3, bsize.height/3);
        d2d1DeviceContext2->drawBitmap(*bitmap, rectangle, 1.f, D2D1_INTERPOLATION_MODE_LINEAR, NULL, NULL);

        d2d1DeviceContext2->endDraw();
        wrappedBackBuffers[frameIndex]->release();
    }
    catch (Exception& ex) {
      caught(ex);
    }
  }

  };
  //Inner class ends.
  //-----------------------------------------------------------------------------------------
    
private:

  SmartPtr<Direct3D12CommandQueue>         commandQueue;
  SmartPtr<Direct3D12CommandAllocator>     commandAllocators[FRAME_COUNT]; 
  SmartPtr<DirectXGISwapChain3>            swapChain;
  SmartPtr<Direct3D12RenderTargetView>     renderTargetView;
  SmartPtr<Direct3D12DepthStencilView>     depthStencilView;
  SmartPtr<Direct3D12RootSignature>        rootSignature;
  SmartPtr<Direct3D12CommonDescriptorHeap>  commonDescriptorHeap;
  SmartPtr<Direct3D12TransformConstantBufferView>   constantBufferView;
  SmartPtr<Direct3D12ShaderResourceView>   shaderResourceView;
  SmartPtr<Direct3D12GraphicsCommandList>  graphicsCommandList;
  SmartPtr<Direct3D12PipelineState>        pipelineState;
  SmartPtr<Direct3D12Synchronizer>         synchronizer;
  SmartPtr<Direct3D12IntermediateResource> intermediateResource;
  
  SmartPtr<Direct3D12Texture2D>            texture2D;
  SmartPtr<Direct3DX12TexturedCube>        texturedCube;
  
  UINT                                     frameIndex;
 
  DirectXTransform                         worldViewProjection;
  float                                    angle;
    
  StringT<TCHAR>                           directory;
  
  SmartPtr<Direct3D11On12Device>           d3d11On12Device;
  SmartPtr<DirectXGeometryRenderer>        geometryRenderer;
    
public:
  
  virtual void createPipelineState(ID3D12Device* device)
  {
    //Create a graphicPipelineStateDes.
    D3D12GraphicsPipelineStateDesc graphicsPipelineStateDesc(*rootSignature);
      
    UINT count = 0;
    const D3D12_INPUT_ELEMENT_DESC* inputElements = texturedCube->getInputElementDesc(count);
      
    D3D12RasterizerDesc  rasterDesc(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE,  true);
      
    D3D12BlendDesc       blendDesc;
            
    graphicsPipelineStateDesc.setInputLayput(inputElements, count);
      
    graphicsPipelineStateDesc.setRasterizerState(rasterDesc);
    graphicsPipelineStateDesc.setBlendState(blendDesc);
      
    StringT<TCHAR> vsshaderFile = getShaderFilePath(directory, _T("VertexShader.cso"));
    StringT<TCHAR> psshaderFile = getShaderFilePath(directory, _T("PixelShader.cso"));

    graphicsPipelineStateDesc.setVertexShader(vsshaderFile);
    graphicsPipelineStateDesc.setPixelShader(psshaderFile);

    pipelineState = new Direct3D12PipelineState(device, graphicsPipelineStateDesc);
  }

   //Read a jpg or png image by using ImageFileReader.
  void readImageFile(__inout int& width, __inout int& height, const char* fileName,
    __out D3D12SubresourceData& subresource)
  {
    CharModuleFileName moduleFileName;
    const char* dir = moduleFileName.getDir();
    char path[MAX_PATH];
    sprintf_s(path, CountOf(path), "%s\\..\\image\\%s", dir, fileName);
    ImageInfo imageInfo;
    ImageFileReader reader(path, imageInfo);

    width  = imageInfo.width;
    height = imageInfo.height;
    subresource.set(imageInfo.width,
                      imageInfo.height,
                      imageInfo.rowBytes,
                      imageInfo.imageDataSize,
                      imageInfo.imageData,
                      imageInfo.format);
  }
  
  void setDirectXTransform()
  {
    int width = 0;
    int height = 0;
    getClientSize(width, height);

    try {
      XMVECTOR eye = XMVectorSet(2.0f, 4.0f, -7.0f, 0.0f);
      XMVECTOR at  = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
      XMVECTOR up  = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);

      worldViewProjection.world = DirectXMatrix::rotationY(angle);
      worldViewProjection.view = DirectXMatrix::lookAtLH(eye, at, up);
      worldViewProjection.projection = DirectXMatrix::perspectiveFovLH(XM_PIDIV2*0.3f, width / (FLOAT)height, 0.01f, 100.0f);

      if (constantBufferView != nullptr) {
        constantBufferView->update(worldViewProjection);
      }
    }
    catch (Exception& ex) {
      caught(ex);
    }
  }


public:
  void deleteViews()
  {
    if (graphicsCommandList) {
      graphicsCommandList->setOMRenderTargets(0, nullptr, FALSE, nullptr);
    }
    renderTargetView = nullptr;
    depthStencilView = nullptr;
  }

  virtual void createViews()
  {
    int width = 0;
    int height = 0;
    validateClientSize(width, height);

    try {      
      Direct3D12Device*   device  = getD3D12Device();      
      DirectXGISwapChain3* swapChain = getSwapChain3();

      renderTargetView = new Direct3D12RenderTargetView(*device, *swapChain, FRAME_COUNT);
      depthStencilView = new Direct3D12DepthStencilView(*device, width, height);

    } catch (Exception& ex) {
      caught(ex);
    }
  }
  
  DirectXGISwapChain3* getSwapChain3()
  {
    return swapChain;
  }
  
  Direct3D12CommandQueue* getCommandQueue()
  {
    return commandQueue;
  }
  
  virtual void initialize()
  {
    int width  = 0;
    int height = 0;
    validateClientSize(width, height);
    
    DirectXGIFactory4* factory = getDXGIFactory4(); //From DirectX3D12MainView

    Direct3D12Device*  device  = getD3D12Device();  //From DirectX3D12MainView

    try {
      commandQueue             = new Direct3D12CommandQueue(*device);
  
      for (int i = 0; i < FRAME_COUNT; i++) {
        commandAllocators[i] = new Direct3D12CommandAllocator(*device);
      }

      swapChain                = new DirectXGISwapChain3(*factory, *commandQueue, FRAME_COUNT,
                                      getWindow(), width, height, false);
       
      d3d11On12Device          =  new Direct3D11On12Device(*device, *commandQueue);

      createViews();
      
      geometryRenderer         = new DirectXGeometryRenderer(*d3d11On12Device, 
                                    renderTargetView,
                                    width, height,
                                    L"TokyoSkyTree2.png");
        
      graphicsCommandList      = new Direct3D12GraphicsCommandList(*device, *commandAllocators[0]);
        
      rootSignature            = new Direct3D12RootSignature(*device);

      commonDescriptorHeap     = new Direct3D12CommonDescriptorHeap(*device, 2);

      constantBufferView       = new Direct3D12TransformConstantBufferView(*device,
                                            commonDescriptorHeap->getCPUHandle(CBV_HANDLE) );

      synchronizer             = new Direct3D12Synchronizer(*device, *commandQueue);
   
      texturedCube                   = new Direct3DX12TexturedCube(*device, 0.6f, 0.6f, 0.6f);
      
      D3D12SubresourceData imageResource;
        
      //Get texture width, height and texture imageResource
      int twidth  = width; 
      int theight = height;
      readImageFile(twidth, theight, "TokyoSkyTree2.png", imageResource);
        
      //Create a textured of size specified twidth and theight;
      texture2D                = new Direct3D12Texture2D(*device, 
                                    twidth, 
                                    theight, imageResource.getFormat());
        
      //Create an intermediate texture resource from the texture2D and the imageResource. 
      intermediateResource     = new Direct3D12IntermediateResource(*device, *texture2D, imageResource);
       
      //Update the intermediate texture resource to the destionation texture2D.
      Direct3D12CommandAllocator commandAllocator(*device);
      intermediateResource -> upload(*graphicsCommandList,
            commandAllocator,
            *commandQueue,
            synchronizer);

      shaderResourceView = new Direct3D12ShaderResourceView(*device,
             commonDescriptorHeap->getCPUHandle(SRV_HANDLE),
             *texture2D);

      createPipelineState(*device);

      setDirectXTransform();

    } catch (Exception& ex) {
      caught(ex);
    }
  }
  
  bool ready()
  {
    Direct3D12Device*    device          = getD3D12Device();
    DirectXGISwapChain3* swapChain       = getSwapChain3();
    Direct3D12CommandQueue* commandQueue = getCommandQueue();
      
    if (
        commandQueue          == nullptr ||
        swapChain             == nullptr ||
        renderTargetView      == nullptr ||
        depthStencilView      == nullptr ||
        rootSignature         == nullptr ||
        commonDescriptorHeap  == nullptr ||
        shaderResourceView    == nullptr ||
        intermediateResource  == nullptr ||
        texture2D             == nullptr ||
        constantBufferView    == nullptr ||
        graphicsCommandList   == nullptr ||
        pipelineState         == nullptr ||
        synchronizer          == nullptr ||
        texturedCube          == nullptr ||
        geometryRenderer      == nullptr) {

      return false;
    }
    return true;
  }
  
  virtual void display()
  {
    int width  = 0;
    int height = 0;
    validateClientSize(width, height);
    if ( !ready() ) {
      return;
    }
    
    try {
        DirectXGISwapChain3*    swapChain = getSwapChain3();
        Direct3D12CommandQueue* commandQueue = getCommandQueue();
        
        setDirectXTransform();

        frameIndex = swapChain -> getCurrentBackBufferIndex();

        commandAllocators[frameIndex]->reset();

        graphicsCommandList->reset(*commandAllocators[frameIndex], nullptr);

        D3D12ResourceBarrier barrier(renderTargetView->getResource(frameIndex));

        barrier.startRendering();

        graphicsCommandList->resourceBarrier(1, barrier);

        graphicsCommandList->setDescriptorHeap(*commonDescriptorHeap);

        graphicsCommandList->setGraphicsRootSignature(*rootSignature);

        graphicsCommandList->setPipelineState(*pipelineState);
        
        graphicsCommandList->setGraphicsRootDescriptorTable(CBV_HANDLE, 
                commonDescriptorHeap->getGPUHandle(CBV_HANDLE));

        graphicsCommandList->setGraphicsRootDescriptorTable(SRV_HANDLE, 
                commonDescriptorHeap->getGPUHandle(SRV_HANDLE));

        graphicsCommandList-> setRSViewport(0, 0, width, height);

        graphicsCommandList-> setRSScissorRect(0, 0, width, height);

        D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = renderTargetView->getHandle(frameIndex);
                 
        graphicsCommandList->clearRenderTargetView(rtvHandle, XMColor(0.0f, 0.0f, 0.3f, 1.0f));

        D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = *depthStencilView;
        
        graphicsCommandList->clearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH);
        
        graphicsCommandList->setOMRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
       
        texturedCube->drawIndexedInstanced(graphicsCommandList);

        barrier.endRendering();
        graphicsCommandList->resourceBarrier(1, barrier);

        graphicsCommandList->close();

        commandQueue->executeCommandList(*graphicsCommandList);

        geometryRenderer -> drawBitmap(frameIndex);

        d3d11On12Device->flush();
      
        swapChain->present(1, 0);
        
        synchronizer->waitForCompletion();
       
    } catch (Exception& ex) {
        caught(ex);
    }
  }
    
public:
  /**
   * Constructor
   */
  MainView(Application& applet, const TCHAR* name, Args& args)
  :DirectX3D12MainView(applet, name, args )
  {
    directory = (const TCHAR*)args.get(XmNapplicationDirectory);
    angle = 1.0f;
    restorePlacement();

    postResizeRequest(); 
  }

public:
  ~MainView()
  {
  }

private:

  virtual void resize(int width, int height)
  {
    Direct3D12Device*   device = getD3D12Device();
    DirectXGISwapChain3* swapChain = getSwapChain3();
    if (device           == nullptr || 
        swapChain        == nullptr) { 
      return ;
    }
      
    try {
      deleteViews();
      
      swapChain->resizeBuffers(width, height);
          
      createViews();
  
    } catch (Exception& ex) {
      caught(ex);
    }
  }
  
  virtual void keyDown(Event& event)
  {
    WPARAM wparam = event.getWParam();
    switch(wparam) {
    case VK_LEFT:
        angle += 0.1f;
        display();
        break;
        
    case VK_RIGHT:
        angle -= 0.1f;
        display();
        break;
    }  
  }
};
}

//////////////////////////////////////////////
//
void  Main(int argc, TCHAR** argv)
{
  ModuleFileName module(argv[0]);
  const TCHAR* directory = module.getDirectory();
  const TCHAR* appClass =  module.getAppName(); 
  
  try {  
    COMInitializer initializer( COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

    Application applet(appClass, argc, argv);

    Args args;
    args.set(XmNwidth,  480);
    args.set(XmNheight, 480);
    args.set(XmNapplicationDirectory, directory);

    MainView mainv(applet, appClass, args);
    
    mainv.realize();

    applet.run();
  } catch (Exception& ex) {
    caught(ex);
  }
}


Last modified: 1 Feb 2017

Copyright (c) 2017 Antillia.com ALL RIGHTS RESERVED.