SOL9 Sample: Direct3D12FullScreenOrbitersWithMultiplePipelineStates
|
1 Screenshot
2 Source code
/*
* Direct3D12FullScreenOrbitersWithMultiplePipelineStates.cpp
* Copyright (c) 2015 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
*/
// 2016/11/10
// This is a fullscreen version of the sample program
//in "usr/src/direct3d12/Direct3D12OrbitersWithMultiplePipelineStats".
// 2017/01/15 Updated display and setDirectXTransform methods.
// 2017/01/28 Updated to use ModuleFileName class and caught macro.
// 2017/01/28 Updated to use ModuleFileName class and caught macro.
#define COMMONCONTROLS_V6
#define WIN10
#include <sol/Stdio.h>
#include <sol/PushButton.h>
#include <sol/Label.h>
#include <sol/CriticalSection.h>
#include <sol/SystemMetrics.h>
#include <sol/CharModuleFileName.h>
#include <sol/direct3d12/DirectX3D12MainView.h>
#include <sol/direct3d12/DirectX3D12View.h>
#include <sol/direct3d12/DirectXMatrix.h>
#include <sol/direct3d12/Direct3D12CommandAllocator.h>
#include <sol/direct3d12/Direct3D12RenderTargetView.h>
#include <sol/direct3d12/Direct3D12DepthStencilView.h>
#include <sol/direct3d12/Direct3D12TransformConstantBufferView.h>
#include <sol/direct3d12/Direct3D12TextureRootSignature.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/D3D12ResourceBarrier.h>
#include <sol/direct3d12/D3D12Transform.h>
#include <sol/direct3d12/D3D12GraphicsPipelineStateDesc.h>
#include <sol/direct3d12/Direct3D12Synchronizer.h>
#include <sol/direct3d12/Direct3D12ShaderResourceView.h>
#include <sol/direct3d12/Direct3D12Sampler.h>
#include <sol/direct3d12/Direct3DX12Sphere.h>
#include <sol/direct3d12/Direct3DX12Torus.h>
#include <sol/direct3d12/DirectXTransform.h>
#include <sol/direct3d12/Direct3D12CommonDescriptorHeap.h>
#include <sol/direct3d12/DirectX3D12TimerThread.h>
#include "resource.h"
namespace SOL {
class MainView :public DirectX3D12MainView {
private:
static const int MAX_PIPELINE_STATE = 2;
enum FILLMODE {
FILL_MODE_WIREFRAME = 0,
FILL_MODE_SOLID = 1,
};
SmartPtr<PushButton> quit;
SmartPtr<Label> label;
SmartPtr<Direct3D12CommandQueue> commandQueue;
SmartPtr<DirectXGISwapChain3> swapChain;
SmartPtr<Direct3D12CommandAllocator> commandAllocator;
SmartPtr<Direct3D12RenderTargetView> renderTargetView;
SmartPtr<Direct3D12DepthStencilView> depthStencilView;
SmartPtr<Direct3D12RootSignature> rootSignature;
SmartPtr<Direct3D12CommonDescriptorHeap> commonDescriptorHeap;
SmartPtr<Direct3D12TransformConstantBufferView> constantBufferView;
SmartPtr<Direct3D12BarrieredGraphicsCommandList> graphicsCommandList;
SmartPtr<Direct3D12PipelineState> pipelineState[MAX_PIPELINE_STATE];
SmartPtr<Direct3D12Synchronizer> synchronizer;
SmartPtr<Direct3DX12Sphere> sphere;
SmartPtr<Direct3DX12Torus> torus;
SmartPtr<DirectX3D12TimerThread> timerThread;
UINT frameIndex;
int pipelineCount;
int renderingInterval;
DirectXTransform worldViewProjection;
int angle;
StringT<TCHAR> directory;
static const int CIRCLE_ANGLE = 360;
CriticalSection criticalSection;
bool fullscreened;
private:
DirectXGISwapChain3* getSwapChain3()
{
return swapChain;
}
Direct3D12CommandQueue* getCommandQueue()
{
return commandQueue;
}
virtual void createWireFramePipelineState(ID3D12Device* device, Direct3DX12Shape* shape)
{
//Create a graphicPipelineStateDes.
D3D12GraphicsPipelineStateDesc graphicsPipelineStateDesc(*rootSignature);
UINT count = 0;
const D3D12_INPUT_ELEMENT_DESC* inputElements = sphere->getInputElementDesc(count);
D3D12RasterizerDesc rasterDesc(D3D12_FILL_MODE_WIREFRAME, 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[pipelineCount++] = new Direct3D12PipelineState(device, graphicsPipelineStateDesc);
}
virtual void createSolidPipelineState(ID3D12Device* device, Direct3DX12Shape* shape)
{
//Create a graphicPipelineStateDes.
D3D12GraphicsPipelineStateDesc graphicsPipelineStateDesc(*rootSignature);
UINT count = 0;
const D3D12_INPUT_ELEMENT_DESC* inputElements = sphere->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[pipelineCount] = new Direct3D12PipelineState(device, graphicsPipelineStateDesc);
}
float SIN(int degree)
{
float radian = (float)degree * MATH_PI / 180.0f;
return (float)sin(radian);
}
float COS(int degree)
{
float radian = (float)degree * MATH_PI / 180.0f;
return (float)cos(radian);
}
XMFLOAT3 getOrbitPosition(int pos)
{
static XMFLOAT3 vertices[CIRCLE_ANGLE] = {};
UINT count = _countof(vertices);
static bool initialized = false;
//Describe a circular orbit.
if (!initialized) {
float px = 0.0f;
float py = 0.0f;
float radius = 2.0f;
for (UINT i = 0; i<count - 1; i += 2) {
vertices[i ] = XMFLOAT3(px + radius * COS(i ), py + radius * SIN(i ), 0.5f);
vertices[i + 1] = XMFLOAT3(px + radius * COS(i + 1), py + radius * SIN(i + 1), 0.5f);
}
initialized = true;
}
if (pos > CIRCLE_ANGLE) {
pos = 0;
}
return vertices[pos];
}
void setDirectXTransform()
{
int width = 0;
int height = 0;
getClientSize(width, height);
try {
XMFLOAT3 position = getOrbitPosition(angle);
DirectXMatrix world = DirectXMatrix::scaling( 1.0f, 1.0f, 1.0f);
DirectXMatrix m = DirectXMatrix::translation(position.x, position.y, position.z);
world += m;
XMVECTOR eye = XMVectorSet( 2.0f, 3.0f, -6.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 = world;
worldViewProjection.view = DirectXMatrix::lookAtLH(eye, at, up);
worldViewProjection.projection = DirectXMatrix::perspectiveFovLH( XM_PIDIV2*0.3f,
(FLOAT)width /(FLOAT)height, 0.01f, 100.0f );
if (constantBufferView != nullptr) {
constantBufferView->update(worldViewProjection);
}
} catch (Exception& ex) {
caught(ex);
}
}
public:
//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()
{
if (graphicsCommandList == nullptr) {
throw IException("GraphicsCommandList is NULL.")
}
graphicsCommandList->setOMRenderTargets(0, nullptr, FALSE, nullptr);
renderTargetView = NULL;
depthStencilView = NULL;
}
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);
bool enableFullscreen = true;
swapChain = new DirectXGISwapChain3(*factory, *commandQueue, 2,
getWindow(), width, height, enableFullscreen);
commandAllocator = new Direct3D12CommandAllocator(*device);
renderTargetView = new Direct3D12RenderTargetView(*device, *swapChain);
depthStencilView = new Direct3D12DepthStencilView(*device, width, height);
graphicsCommandList = new Direct3D12BarrieredGraphicsCommandList(*device, *commandAllocator);
rootSignature = new Direct3D12RootSignature(*device);
commonDescriptorHeap = new Direct3D12CommonDescriptorHeap(*device, 1);
constantBufferView = new Direct3D12TransformConstantBufferView(*device,
commonDescriptorHeap->getCPUHandle(CBV_HANDLE) );
synchronizer = new Direct3D12Synchronizer(*device, *commandQueue);
//1 Create a renderTargetView and depthStencilView
createViews(*device, *swapChain, width, height);
//2 Define your own specific initialization procedures.
// Create your own shape
sphere = new Direct3DX12Sphere(*device, 0.5f, 20, 20);
torus = new Direct3DX12Torus(*device, 0.2f, 1.0f, 30, 30);
//3 Create two pipelineState(wireframe and solid) from the sphere.
createWireFramePipelineState(*device, sphere);
createSolidPipelineState(*device, sphere);
//4 Set world, view and projection to the constantBuffer.
setDirectXTransform();
//5 Create a rendering TimerThread.
timerThread = new DirectX3D12TimerThread(this, renderingInterval);
timerThread -> start();
} 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 ||
commonDescriptorHeap == nullptr ||
constantBufferView == nullptr ||
sphere == nullptr ||
torus == nullptr ||
graphicsCommandList == nullptr ||
pipelineState == nullptr ||
timerThread == nullptr ||
synchronizer == nullptr ) {
return false;
}
return true;
}
virtual void display()
{
int width = 0;
int height = 0;
validateClientSize(width, height);
if ( !ready() ) {
return;
}
criticalSection.enter();
try {
DirectXGISwapChain3* swapChain = getSwapChain3();
Direct3D12CommandQueue* commandQueue = getCommandQueue();
static const int INCREMENT = 2;
if (angle <(CIRCLE_ANGLE - INCREMENT) ) {
angle += INCREMENT;
} else {
angle = INCREMENT;
}
setDirectXTransform();
frameIndex = swapChain -> getCurrentBackBufferIndex();
graphicsCommandList->startRendering(renderTargetView->getResource(frameIndex));
graphicsCommandList->setDescriptorHeap(*commonDescriptorHeap);
graphicsCommandList->setGraphicsRootSignature(*rootSignature);
graphicsCommandList->setPipelineState(*pipelineState[FILL_MODE_WIREFRAME]);
graphicsCommandList->setGraphicsRootDescriptorTable(CBV_HANDLE,
commonDescriptorHeap->getGPUHandle(CBV_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.2f, 0.2f, 0.6f, 1.0f));
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = *depthStencilView;
graphicsCommandList->clearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH);
graphicsCommandList->setOMRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
//Draw the sphere on the worldViewProjection by wireFrame mode.
sphere -> drawIndexedInstanced(graphicsCommandList);
//Draw the torus on the worldViewProjection by solid mode.
graphicsCommandList->setPipelineState(*pipelineState[FILL_MODE_SOLID]);
torus->drawIndexedInstanced(graphicsCommandList);
graphicsCommandList->endRendering();
commandQueue->executeCommandList(*graphicsCommandList);
swapChain->present(1, 0);
synchronizer->waitForCompletion();
} catch (Exception& ex) {
caught(ex);
}
criticalSection.leave();
}
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:
MainView(Application& applet, const TCHAR* name, Args& args)
:DirectX3D12MainView(applet, name, args),
angle (30),
frameIndex(0),
directory(_T("")),
pipelineCount(0),
renderingInterval(100),
fullscreened(false)
{
// Change a style of this window to be no-captiion.
LONG style = getWindowLong(GWL_STYLE);
style &= ~WS_CAPTION;
setWindowLong(GWL_STYLE, style| WS_POPUP);
directory = (const TCHAR*)args.get(XmNapplicationDirectory);
renderingInterval = (int)args.get(XmNrenderingInterval);
for(int i = 0; i<MAX_PIPELINE_STATE; i++) {
pipelineState[i] = NULL;
}
//Create a quit pushbutton.
Args ar;
ar.set(XmNx, 10);
ar.set(XmNy, 10);
ar.set(XmNwidth, 120);
ar.set(XmNheight, 30);
quit = new PushButton(this, _T("QUIT"), ar);
quit->addCallback(XmNactivateCallback, this,
(Callback)&MainView::exit, NULL);
//Create a label.
ar.reset();
ar.set(XmNx, 200);
ar.set(XmNy, 200);
ar.set(XmNwidth, 400);
ar.set(XmNheight, 30);
ar.set(XmNtextColor, RGB(0xff, 0, 0));
ar.set(XmNtextAlignment, DT_LEFT); //DT_CENTER);
ar.set(XmNlabelString, _T("Torus and Sphere Orbiters. Hello world. こんにちは世界"));
label = new Label(this, _T(""), ar);
postResizeRequest();
}
~MainView()
{
}
};
}
//////////////////////////////////////////////
//
void Main(int argc, TCHAR** argv)
{
ModuleFileName module(argv[0]);
const TCHAR* directory = module.getDirectory();
const TCHAR* appClass = module.getAppName();
try {
SystemMetrics metrics;
int width = metrics.fullScreenWidth();
int height = metrics.fullScreenHeight();
Application applet(appClass, argc, argv);
Args args;
args.set(XmNx, 0);
args.set(XmNy, 0);
args.set(XmNwidth, width);
args.set(XmNheight, height);
args.set(XmNapplicationDirectory, directory);
args.set(XmNrenderingInterval, 100); //100ms
MainView mainView(applet, appClass, args);
mainView.realize(SW_SHOWMAXIMIZED);
applet.run();
} catch (Exception& ex) {
caught(ex);
}
}
Last modified: 1 Feb 2017
Copyright (c) 2017 Antillia.com ALL RIGHTS RESERVED.