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