SOL9 Sample: Direct3D12MainView

SOL9 2.0 Samples

1 Screenshot


2 Source code

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


// 2016/10/01
// 2017/01/28 Updated to use ModuleFileName class and caught macro.

#define COMMONCONTROLS_V6
#define WIN10

#include <sol/direct3d12/DirectX3D12MainView.h>
#include <sol/direct3d12/DirectX3D12View.h>

#include <sol/direct3d12/Direct3d12CommandQueue.h>
#include <sol/direct3d12/Direct3D12CommandAllocator.h>
#include <sol/direct3d12/Direct3D12RenderTargetView.h>
#include <sol/direct3d12/Direct3D12DepthStencilView.h>

#include <sol/direct3d12/Direct3D12RootSignature.h>
#include <sol/direct3d12/Direct3D12GraphicsCommandList.h>

#include <sol/direct3d12/Direct3D12PipelineState.h>

#include <sol/direct3d12/D3D12RasterizerDesc.h>
#include <sol/direct3d12/D3D12BlendDesc.h>
#include <sol/direct3d12/D3D12GraphicsPipelineStateDesc.h>
#include <sol/direct3d12/D3D12ResourceBarrier.h>

#include <sol/direct3d12/Direct3D12Synchronizer.h>
#include <sol/direct3d12/D3D12GraphicsPipelineStateDesc.h>
#include <sol/direct3d12/Direct3D12VertexBuffer.h>
#include <sol/direct3d12/Direct3D12IndexBuffer.h>
#include <DirectXMath.h>
#include <sol/PushButton.h>

#include "resource.h"

using namespace DirectX;

namespace SOL {
  
class MainView :public DirectX3D12MainView {
  //Inner class starts.
  class SimpleView :public DirectX3D12View {
  private:
    SmartPtr<Direct3D12CommandAllocator>     commandAllocator;
    SmartPtr<Direct3D12RenderTargetView>     renderTargetView;
    SmartPtr<Direct3D12DepthStencilView>     depthStencilView;
    SmartPtr<Direct3D12RootSignature>        rootSignature;
    SmartPtr<Direct3D12GraphicsCommandList>  graphicsCommandList;
    SmartPtr<Direct3D12PipelineState>        pipelineState;
    SmartPtr<Direct3D12Synchronizer>         synchronizer;
    SmartPtr<Direct3D12VertexBuffer>         vertexBuffer;
    SmartPtr<Direct3D12IndexBuffer>          indexBuffer;
  
    UINT                            frameIndex;
    UINT                            vertexCount;
    StringT<TCHAR>      directory;

  private:
    //Application specific data

    virtual void createPipelineState(ID3D12Device* device)
    {
      //Create a graphicPipelineStateDes.
      D3D12GraphicsPipelineStateDesc graphicsPipelineStateDesc(*rootSignature);

      static D3D12_INPUT_ELEMENT_DESC inputElements[] = {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 0,  D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
        { "COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
      };
      
      D3D12RasterizerDesc  rasterDesc(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE, false);
      
      D3D12BlendDesc       blendDesc;
            
      graphicsPipelineStateDesc.setInputLayput(inputElements, _countof(inputElements));
      
      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);
    }

    virtual void createVertexBuffer(ID3D12Device* device)
    {
      typedef struct {
        XMFLOAT3 pos;
        XMFLOAT4 color;
      } Vertex;
       const Vertex vertices[] = {
          //Position(x, y, z)       Color(r, g, b, a)
          {XMFLOAT3( 0.0f ,  1.0f , 0.0f),  XMFLOAT4( 1.0f, 0.0f, 0.0f, 1.0f) },
          {XMFLOAT3( 1.0f , -1.0f , 0.0f),  XMFLOAT4( 0.0f, 1.0f, 0.0f, 1.0f) }, 
          {XMFLOAT3(-1.0f , -1.0f , 0.0f),  XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f) }, 
      };

      UINT verticesSizeInByte = sizeof(vertices);
      UINT strideInByte       = sizeof(Vertex);

      vertexCount = _countof(vertices);
      vertexBuffer = new Direct3D12VertexBuffer(device, vertices, strideInByte, verticesSizeInByte);
    }

    virtual void createIndexBuffer(ID3D12Device* device)
    {
      uint16_t indices[] = { 0, 1, 2 };
      UINT indicesSizeInByte = sizeof(indices);
      indexBuffer = new Direct3D12IndexBuffer(device, indices, indicesSizeInByte);
    }
    
    //Create a renderTargetView and a depthStencilView.
    void createViews(ID3D12Device* device, IDXGISwapChain3* swapChain,
                  int width, int height)
    {
      renderTargetView = new Direct3D12RenderTargetView(device, swapChain);
      depthStencilView = new Direct3D12DepthStencilView(device,  width, height);
    }
    
    //Delete a renderTargetView and a depthStencilView.
    void deleteViews()
    {
      graphicsCommandList->setOMRenderTargets(0, nullptr, FALSE, nullptr);
      renderTargetView = NULL;
      depthStencilView = NULL;
    }    

  public:
    virtual void initialize()
    {
      int width  = 0;
      int height = 0;
      validateClientSize(width, height);
      //The following three objects are from the parent DirectX3D12View.
      Direct3D12Device*    device          = getD3D12Device();
      DirectXGISwapChain3* swapChain       = getSwapChain3();
      Direct3D12CommandQueue* commandQueue = getCommandQueue();
      
      try {
        commandAllocator         = new Direct3D12CommandAllocator(*device);

        graphicsCommandList      = new Direct3D12GraphicsCommandList(*device, *commandAllocator);

        rootSignature            = new Direct3D12RootSignature(*device);
        
        createViews(*device, *swapChain, width, height);
        
        createPipelineState(*device);

        createVertexBuffer(*device);

        createIndexBuffer(*device);

        synchronizer            = new Direct3D12Synchronizer(*device, *commandQueue);
        
      } catch (Exception& ex) {
        caught(ex);
      }
    }

    bool ready()
    {
      Direct3D12Device*    device = getD3D12Device();
      DirectXGISwapChain3* swapChain = getSwapChain3();
      Direct3D12CommandQueue* commandQueue = getCommandQueue();
      
      if (
        device                    == nullptr ||
        commandQueue              == nullptr ||

        swapChain                 == nullptr ||
        commandAllocator          == nullptr ||
        renderTargetView          == nullptr ||
        depthStencilView          == nullptr ||
        rootSignature             == nullptr ||

        graphicsCommandList       == nullptr ||
        pipelineState             == nullptr ||
        synchronizer              == nullptr ||

        vertexBuffer              == nullptr ||
        indexBuffer               == 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();

        commandAllocator    -> reset();
        
        graphicsCommandList -> reset(*commandAllocator, *pipelineState);
        
        frameIndex = swapChain -> getCurrentBackBufferIndex();
        
        D3D12ResourceBarrier barrier(renderTargetView->getResource(frameIndex));
        
        barrier.startRendering();

        graphicsCommandList->resourceBarrier(1, barrier);

        graphicsCommandList->setGraphicsRootSignature(*rootSignature);

        graphicsCommandList->setPipelineState(*pipelineState);
        
        graphicsCommandList -> setRSViewport(width, height);

        graphicsCommandList -> setRSScissorRect(width, height);

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

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

        graphicsCommandList->setIAPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

        graphicsCommandList->setIAVertexBuffers(0, 1, *vertexBuffer);

        graphicsCommandList->setIAIndexBuffer(*indexBuffer);

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

        graphicsCommandList->close();

        commandQueue->executeCommandList(*graphicsCommandList);

        swapChain->present(1, 0);
        
        synchronizer->waitForCompletion();
       
      } catch (Exception& ex) {
        caught(ex);
      }
    }
    
    
    virtual void resize(int width, int height)
    {
      Direct3D12Device*   device = getD3D12Device();
      DirectXGISwapChain3* swapChain = getSwapChain3();
      if (device           == NULL || 
         swapChain        == NULL) { 
        return ;
      }
      
      try {
        deleteViews();
        
        swapChain->resizeBuffers(width, height);

        createViews(*device, *swapChain, width, height);
        
      } catch (Exception& ex) {
        caught(ex);
      }
    }
    
  public:
    //Constructor
    SimpleView(DirectX3D12MainView* parent, const TCHAR* name, Args& args)
    :DirectX3D12View(parent, name, args),
    frameIndex(0),
    directory(_T(""))
    {
      directory = (const TCHAR*)args.get(XmNapplicationDirectory);

      postResizeRequest();
    }
    
    ~SimpleView()
    {
    }
  };
  // Inner class ends.
  
private:
  SmartPtr<SimpleView> view;
  SmartPtr<PushButton> quit;

  static const int MARGIN          = 10;
  static const int WORK_AREA_WIDTH = 140;

public:
  /**
   * Constructor
   */
  MainView(Application& applet, const TCHAR* name, Args& args)
  :DirectX3D12MainView(applet, name,
                 args.set(XmNstyle, (ulong)WS_CLIPCHILDREN|WS_CLIPSIBLINGS) )
  {
    const TCHAR* directory = (const TCHAR*)args.get(XmNapplicationDirectory);

    // 1 Restore the replacement of MainView 
    restorePlacement();

    // 2 Create a view of SimpleView.
    Args ar;
    int width  = 0;
    int height = 0;
    getClientSize(width, height);

    ar.set(XmNwidth, width);
    ar.set(XmNheight,height);
    ar.set(XmNapplicationDirectory, (const TCHAR*)directory);

    ar.set(XmNstyle, WS_BORDER|WS_CHILD|WS_VISIBLE);
    view = new SimpleView(this, _T(""), ar);

    // 3 Create a quit PushButton.
    ar.reset();
    ar.set(XmNwidth, 120);
    ar.set(XmNheight, 30);
    quit = new PushButton(this, _T("QUIT"), ar);
    quit ->addCallback(XmNactivateCallback, this,
      (Callback)&MainView::exit, NULL);

    // 4 Post a resize request to this MainView.
    postResizeRequest();
  }

public:
  ~MainView()
  {
  }

  void resize(int width, int height)
  {
    if (view != nullptr && quit != nullptr) {
      int w = width;

      if (width > WORK_AREA_WIDTH) {
        w = width - WORK_AREA_WIDTH;
      }
      if (w < 1) {
        w = width;
      }

      view -> reshape(0, 0, w, height);
      quit -> reshape(w + 2, 2, 120, 30);
    }
  }  
};
}


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

  try {    
    Application applet(appClass, argc, argv);

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

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

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


Last modified: 1 Feb 2017

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