UID
Unique ID
All libraries like Graphics System, image\model loaders
must have unique ID
// Like a GUID
struct slUID
{
uint32_t d1;
uint16_t d2;
uint16_t d3;
uint16_t d4;
uint8_t d5[6];
};
#define slDEFINE_UID(name, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11) \
const slUID name \
= { d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11 }
Graphic System
I need abstract class that will have all methods that I need for drawing.
slGS must provide basic things. No need to write complex classes.
First vesion looks like this. I just need to fill window background with color (ClearColor).
// Graphics System
class slGS
{
public:
slGS() {}
virtual ~slGS() {}
// Init GPU things.
// `parameters` is optional thing, it depends on library implementation.
virtual bool Init(slWindow*, const char* parameters) = 0;
// Init more window. For drawing in many windows.
virtual bool InitWindow(slWindow*) = 0;
// For drawing in many windows.
virtual void SetActiveWindow(slWindow*) = 0;
// Get name
virtual slString GetName() = 0;
// Get all other info in text.
virtual slString GetTextInfo() = 0;
// Get unique ID
virtual slUID GetUID() = 0;
virtual void UseVSync(bool) = 0;
virtual bool UseDepth(bool) = 0; // return old
virtual bool UseBlend(bool) = 0; // return old
// use x and y
virtual void GetDepthRange(slVec3f*) = 0;
// Color for `canvas`
virtual void SetClearColor(float r, float g, float b, float a) = 0;
// Call before drawing
virtual void BeginDraw() = 0;
virtual void ClearDepth() = 0;
virtual void ClearColor() = 0;
virtual void ClearAll() = 0; // ClearDepth и ClearColor
// Call after drawing
virtual void EndDraw() = 0;
virtual void SwapBuffers() = 0;
// Call this when window resized.
// x and y
virtual void UpdateMainRenderTarget(const slVec3f&);
virtual void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0;
virtual void SetScissorRect(const slVec4f& rect, slVec4f* old) = 0;
};
D3D11 library
I need to create new static library.
This new static library will have D3D11 implementation for slGS.
...I duplicate slowlib project file and change it name...
First I need new methods in `slFramework`
// Get number of Graphics Systems
static uint32_t GetGSCount();
static slString GetGSName(uint32_t);
static slUID GetGSUID(uint32_t);
// Create GS using slUID
static slGS* SummonGS(slUID);
// Create GS using it's name
static slGS* SummonGS(const char*);
// Both
static slGS* SummonGS(slUID, const char*);
Before I continue implement this methods, I need to write D3D11 library.
Class
Drawing will be in render target texture, but now without it, because I dont
have class for textures.
I don't know how to do anything in right way. I have 2 stencilstates,
2 blend states and 4 rasterizer states.
class slGSD3D11 : public slGS
{
slWindow* m_activeWindow = 0;
slPoint* m_activeWindowSize = 0;
IDXGISwapChain* m_SwapChain = 0;
ID3D11Device* m_d3d11Device = 0;
ID3D11DeviceContext* m_d3d11DevCon = 0;
ID3D11DepthStencilState* m_depthStencilStateEnabled = 0;
ID3D11DepthStencilState* m_depthStencilStateDisabled = 0;
ID3D11RasterizerState* m_RasterizerSolid = 0;
ID3D11RasterizerState* m_RasterizerSolidNoBackFaceCulling = 0;
ID3D11RasterizerState* m_RasterizerWireframeNoBackFaceCulling = 0;
ID3D11RasterizerState* m_RasterizerWireframe = 0;
ID3D11BlendState* m_blendStateAlphaEnabled = 0;
ID3D11BlendState* m_blendStateAlphaDisabled = 0;
ID3D11DepthStencilView* m_depthStencilView = 0;
ID3D11Texture2D* m_depthStencilBuffer = 0;
ID3D11RenderTargetView* m_MainTargetView = 0;
ID3D11RenderTargetView* m_currentTargetView = 0;
// it for this: you have fullscreen window but you can use lower `resolution`
// I need to use Render Target Texture for this
slVec3f m_mainTargetSize;
slColor m_clearColor;
bool m_vsync = false;
bool createBackBuffer(float x, float y);
bool updateMainTarget();
public:
slGSD3D11();
virtual ~slGSD3D11();
virtual bool Init(slWindow*, const char* parameters) final;
virtual bool InitWindow(slWindow*) final;
virtual void SetActiveWindow(slWindow*) final;
virtual slString GetName() final;
virtual slString GetTextInfo() final;
virtual slUID GetUID() final;
virtual void UseVSync(bool) final;
virtual bool UseDepth(bool) final;
virtual bool UseBlend(bool) final;
virtual void GetDepthRange(slVec3f*) final;
virtual void SetClearColor(float r, float g, float b, float a) final;
virtual void BeginDraw() final;
virtual void ClearDepth() final;
virtual void ClearColor() final;
virtual void ClearAll() final; // ClearDepth и ClearColor
virtual void EndDraw() final;
virtual void SwapBuffers() final;
virtual void UpdateMainRenderTarget(const slVec3f&) final;
virtual void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) final;
virtual void SetScissorRect(const slVec4f& rect, slVec4f* old) final;
};
And some implementation
slGSD3D11::~slGSD3D11()
{
if (m_depthStencilView) m_depthStencilView->Release();
if (m_blendStateAlphaDisabled) m_blendStateAlphaDisabled->Release();
if (m_blendStateAlphaEnabled) m_blendStateAlphaEnabled->Release();
if (m_RasterizerWireframeNoBackFaceCulling) m_RasterizerWireframeNoBackFaceCulling->Release();
if (m_RasterizerWireframe) m_RasterizerWireframe->Release();
if (m_RasterizerSolidNoBackFaceCulling) m_RasterizerSolidNoBackFaceCulling->Release();
if (m_RasterizerSolid) m_RasterizerSolid->Release();
if (m_depthStencilStateDisabled) m_depthStencilStateDisabled->Release();
if (m_depthStencilStateEnabled) m_depthStencilStateEnabled->Release();
if (m_depthStencilBuffer) m_depthStencilBuffer->Release();
if (m_MainTargetView) m_MainTargetView->Release();
if (m_d3d11DevCon) m_d3d11DevCon->Release();
if (m_SwapChain) m_SwapChain->Release();
if (m_d3d11Device) m_d3d11Device->Release();
}
bool slGSD3D11::Init(slWindow* w, const char* parameters)
{
SL_ASSERT_ST(w);
slLog::PrintInfo("Init video driver - D3D11...\n");
m_activeWindow = w;
m_activeWindowSize = w->GetCurrentSize();
m_mainTargetSize.x = (float)m_activeWindowSize->x;
m_mainTargetSize.y = (float)m_activeWindowSize->y;
DXGI_MODE_DESC bufferDesc;
memset(&bufferDesc, 0, sizeof(bufferDesc));
bufferDesc.Width = (UINT)m_activeWindowSize->x;
bufferDesc.Height = (UINT)m_activeWindowSize->y;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
auto hr = D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
D3D11_CREATE_DEVICE_SINGLETHREADED,
nullptr,
0,
D3D11_SDK_VERSION,
&m_d3d11Device,
&featureLevel,
&m_d3d11DevCon);
if (FAILED(hr))
{
slLog::PrintError("Can't create Direct3D 11 Device : code %u\n", hr);
return false;
}
IDXGIDevice* dxgiDevice = nullptr;
IDXGIAdapter* dxgiAdapter = nullptr;
IDXGIFactory1* dxgiFactory = nullptr;
hr = m_d3d11Device->QueryInterface(IID_IDXGIDevice, (void**)&dxgiDevice);
if (FAILED(hr))
{
slLog::PrintError("Can't QueryInterface : IID_IDXGIDevice, code %u\n", hr);
return false;
}
hr = dxgiDevice->GetParent(IID_IDXGIAdapter, (void**)&dxgiAdapter);
if (FAILED(hr))
{
slLog::PrintError("Can't get DXGI adapter, code %u\n", hr);
return false;
}
hr = dxgiAdapter->GetParent(IID_IDXGIFactory, (void**)&dxgiFactory);
if (FAILED(hr))
{
slLog::PrintError("Can't get DXGI factory, code %u\n", hr);
return false;
}
slWindowWin32* w32 = (slWindowWin32*)w->GetData()->m_implementation;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
memset(&swapChainDesc, 0, sizeof(swapChainDesc));
swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = w32->m_hWnd;
swapChainDesc.BufferCount = 1;
swapChainDesc.Windowed = true/*m_params.m_fullScreen ? false : true*/;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.Flags = 0;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
hr = dxgiFactory->CreateSwapChain(m_d3d11Device, &swapChainDesc, &m_SwapChain);
if (FAILED(hr))
{
slLog::PrintError("Can't create Swap Chain : code %u\n", hr);
return false;
}
dxgiFactory->MakeWindowAssociation(w32->m_hWnd, DXGI_MWA_NO_ALT_ENTER);
dxgiDevice->Release();
dxgiAdapter->Release();
dxgiFactory->Release();
createBackBuffer((float)m_activeWindowSize->x, (float)m_activeWindowSize->y);
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
depthStencilDesc.StencilEnable = true;
depthStencilDesc.StencilReadMask = 0xFF;
depthStencilDesc.StencilWriteMask = 0xFF;
depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
if (FAILED(m_d3d11Device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilStateEnabled)))
{
slLog::PrintError("Can't create Direct3D 11 depth stencil state\n");
return false;
}
m_d3d11DevCon->OMSetDepthStencilState(this->m_depthStencilStateEnabled, 0);
depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
depthStencilDesc.StencilEnable = false;
depthStencilDesc.DepthEnable = false;
if (FAILED(m_d3d11Device->CreateDepthStencilState(&depthStencilDesc, &this->m_depthStencilStateDisabled)))
{
slLog::PrintError("Can't create Direct3D 11 depth stencil state\n");
return false;
}
D3D11_RASTERIZER_DESC rasterDesc;
ZeroMemory(&rasterDesc, sizeof(D3D11_RASTERIZER_DESC));
rasterDesc.AntialiasedLineEnable = false;
rasterDesc.CullMode = D3D11_CULL_BACK;
rasterDesc.DepthBias = 0;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = true;
rasterDesc.FillMode = D3D11_FILL_SOLID;
rasterDesc.FrontCounterClockwise = false;
rasterDesc.MultisampleEnable = false;
rasterDesc.ScissorEnable = true;
rasterDesc.SlopeScaledDepthBias = 0.0f;
if (FAILED(m_d3d11Device->CreateRasterizerState(&rasterDesc, &m_RasterizerSolid)))
{
slLog::PrintError("Can not create rasterizer state\n");
return false;
}
rasterDesc.CullMode = D3D11_CULL_NONE;
m_d3d11Device->CreateRasterizerState(&rasterDesc, &m_RasterizerSolidNoBackFaceCulling);
rasterDesc.FillMode = D3D11_FILL_WIREFRAME;
m_d3d11Device->CreateRasterizerState(&rasterDesc, &m_RasterizerWireframeNoBackFaceCulling);
rasterDesc.CullMode = D3D11_CULL_BACK;
m_d3d11Device->CreateRasterizerState(&rasterDesc, &m_RasterizerWireframe);
m_d3d11DevCon->RSSetState(m_RasterizerSolid);
D3D11_BLEND_DESC bd;
memset(&bd, 0, sizeof(bd));
bd.AlphaToCoverageEnable = 0;
bd.RenderTarget[0].BlendEnable = TRUE;
bd.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
bd.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
bd.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
bd.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
bd.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
bd.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
bd.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
if (FAILED(m_d3d11Device->CreateBlendState(&bd, &m_blendStateAlphaEnabled)))
{
slLog::PrintError("Can't create Direct3D 11 blend state\n");
return false;
}
bd.RenderTarget[0].BlendEnable = FALSE;
if (FAILED(m_d3d11Device->CreateBlendState(&bd, &m_blendStateAlphaDisabled)))
{
slLog::PrintError("Can't create Direct3D 11 blend state\n");
return false;
}
float blendFactor[4];
blendFactor[0] = 0.0f;
blendFactor[1] = 0.0f;
blendFactor[2] = 0.0f;
blendFactor[3] = 0.0f;
m_d3d11DevCon->OMSetBlendState(m_blendStateAlphaEnabled, blendFactor, 0xffffffff);
D3D11_RECT sr;
sr.left = 0;
sr.top = 0;
sr.right = (LONG)m_activeWindowSize->x;
sr.bottom = (LONG)m_activeWindowSize->y;
m_d3d11DevCon->RSSetScissorRects(1, &sr);
D3D11_VIEWPORT viewport;
viewport.Width = (float)m_activeWindowSize->x;
viewport.Height = (float)m_activeWindowSize->y;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
m_d3d11DevCon->RSSetViewports(1, &viewport);
// shaders here
m_d3d11DevCon->OMSetDepthStencilState(m_depthStencilStateEnabled, 0);
return true;
}
bool slGSD3D11::updateMainTarget()
{
m_d3d11DevCon->OMSetRenderTargets(0, 0, 0);
if (m_depthStencilBuffer)
{
m_depthStencilBuffer->Release();
m_depthStencilBuffer = 0;
}
if (m_depthStencilView)
{
m_depthStencilView->Release();
m_depthStencilView = 0;
}
if (m_MainTargetView)
{
m_MainTargetView->Release();
m_MainTargetView = 0;
}
m_SwapChain->ResizeBuffers(0, (UINT)m_activeWindowSize->x, (UINT)m_activeWindowSize->y, DXGI_FORMAT_UNKNOWN, 0);
createBackBuffer((float)m_activeWindowSize->x, (float)m_activeWindowSize->y);
return true;
}
bool slGSD3D11::createBackBuffer(float x, float y)
{
if (m_depthStencilBuffer)
{
m_depthStencilBuffer->Release();
m_depthStencilBuffer = 0;
}
if (m_depthStencilView)
{
m_depthStencilView->Release();
m_depthStencilView = 0;
}
if (m_MainTargetView)
{
m_MainTargetView->Release();
m_MainTargetView = 0;
}
ID3D11Texture2D* BackBuffer = 0;
if (FAILED(m_SwapChain->GetBuffer(
0,
IID_ID3D11Texture2D,
(void**)&BackBuffer)))
{
slLog::PrintError("Can't create Direct3D 11 back buffer\n");
return false;
}
if (FAILED(this->m_d3d11Device->CreateRenderTargetView(
BackBuffer, 0, &m_MainTargetView)))
{
slLog::PrintError("Can't create Direct3D 11 render target\n");
if (BackBuffer) BackBuffer->Release();
return false;
}
if (BackBuffer) BackBuffer->Release();
D3D11_TEXTURE2D_DESC DSD;
ZeroMemory(&DSD, sizeof(DSD));
DSD.Width = (UINT)x;
DSD.Height = (UINT)y;
DSD.MipLevels = 1;
DSD.ArraySize = 1;
DSD.Format = DXGI_FORMAT_D32_FLOAT;
DSD.SampleDesc.Count = 1;
DSD.SampleDesc.Quality = 0;
DSD.Usage = D3D11_USAGE_DEFAULT;
DSD.BindFlags = D3D11_BIND_DEPTH_STENCIL;
DSD.CPUAccessFlags = 0;
DSD.MiscFlags = 0;
if (FAILED(m_d3d11Device->CreateTexture2D(&DSD, 0, &m_depthStencilBuffer)))
{
slLog::PrintError("Can't create Direct3D 11 depth stencil buffer\n");
return false;
}
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
memset(&depthStencilViewDesc, 0, sizeof(depthStencilViewDesc));
depthStencilViewDesc.Format = DXGI_FORMAT_D32_FLOAT;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;
if (FAILED(m_d3d11Device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView)))
{
slLog::PrintError("Can't create Direct3D 11 depth stencil view\n");
return false;
}
m_d3d11DevCon->OMSetRenderTargets(1, &m_MainTargetView, m_depthStencilView);
return true;
}
void slGSD3D11::BeginDraw()
{
m_currentTargetView = m_MainTargetView;
m_d3d11DevCon->OMSetRenderTargets(1, &m_currentTargetView, m_depthStencilView);
//SetViewport(0, 0, m_mainTargetSize.x, m_mainTargetSize.y);
SetViewport(0, 0, m_activeWindowSize->x, m_activeWindowSize->y);
}
void slGSD3D11::ClearAll()
{
m_d3d11DevCon->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
m_d3d11DevCon->ClearRenderTargetView(m_currentTargetView, m_clearColor.data());
}
void slGSD3D11::SwapBuffers()
{
m_vsync ? m_SwapChain->Present(1, 0) : m_SwapChain->Present(0, 0);
}
For basic version of GS I added in d3d11 library a function
extern "C"
{
slGS* SL_CDECL slGSD3D11_create()
{
slGSD3D11* gs = slCreate<slGSD3D11>();
return gs;
}
}
And slowlib.base have this (in slFramework)
extern "C"
{
slGS* SL_CDECL slGSD3D11_create();
}
SL_LINK_LIBRARY("slowlib.d3d11");
Color
Just class that have float m_data[4] and methods.
class slColor
{
public:
float m_data[4];
...
slColor(uint32_t uint_data) // 0xFF112233 ARGB
{
setAsInteger(uint_data);
}
...
void setAlpha(float v) { m_data[3u] = v; }
void setRed(float v) { m_data[0u] = v; }
void setGreen(float v) { m_data[1u] = v; }
void setBlue(float v) { m_data[2u] = v; }
...
// 0xff112233
uint32_t getAsInteger()
{
return SL_MAKEFOURCC(
this->getAsByteBlue(),
this->getAsByteGreen(),
this->getAsByteRed(),
this->getAsByteAlpha()
);
}
And giant list of colors
const slColor ColorAliceBlue = 0xffF0F8FF;
const slColor ColorAntiqueWhite = 0xffFAEBD7;
const slColor ColorAqua = 0xff00FFFF;
...
Colors is here
color list
Other things
I moved slWindowWin32 into inc\slowlib.base\system\
Everything works. Now I need to create DLL version, and implement all
that functions for creating GS.
Download code
Please enable JavaScript to view the comments powered by Disqus.