REM Minimal Direct3D 11 application in BBC BASIC for Windows
REM (C) R. T. Russell, 31-Jul-2015, http://www.bbcbasic.co.uk
MODE 8
REM!WC Declare constants:
NULL = 0
S_OK = 0
DXGI_FORMAT_R8G8B8A8_UNORM = 28
DXGI_USAGE_RENDER_TARGET_OUTPUT = 1 << (1 + 4)
D3D_DRIVER_TYPE_HARDWARE = 1
D3D11_SDK_VERSION = 7
IID_ID3D11Texture2D = FN_guid("{6f15aaf2-d208-4e89-9ab4-489535d34f9c}")
REM Declare structures:
DIM DXGI_RATIONAL{Numerator%, Denominator%}
DIM DXGI_MODE_DESC{Width%, Height%, RefreshRate{} = DXGI_RATIONAL{}, \
\ Format%, ScanlineOrdering%, Scaling%}
DIM DXGI_SAMPLE_DESC{Count%, Quality%}
DIM DXGI_SWAP_CHAIN_DESC{BufferDesc{} = DXGI_MODE_DESC{}, \
\ SampleDesc{} = DXGI_SAMPLE_DESC{}, \
\ BufferUsage%, \
\ BufferCount%, \
\ OutputWindow%, \
\ Windowed%, \
\ SwapEffect%, \
\ Flags%}
DIM D3D11_VIEWPORT{TopLeftX%,TopLeftY%,Width%,Height%,MinDepth%,MaxDepth%}
REM Declare interfaces:
DIM IDXGISwapChain{QueryInterface%,AddRef%,Release%,SetPrivateData%, \
\ SetPrivateDataInterface%,GetPrivateData%,GetParent%,GetDevice%,Present%, \
\ GetBuffer%,SetFullscreenState%,GetFullscreenState%,GetDesc%,ResizeBuffers%, \
\ ResizeTarget%,GetContainingOutput%,GetFrameStatistics%,GetLastPresentCount%}
DIM ID3D11Texture2D{QueryInterface%,AddRef%,Release%,GetDevice%, \
\ GetPrivateData%,SetPrivateData%,SetPrivateDataInterface%,GetType%, \
\ SetEvictionPriority%,GetEvictionPriority%,GetDesc%}
DIM ID3D11Device{QueryInterface%,AddRef%,Release%,CreateBuffer%, \
\ CreateTexture1D%,CreateTexture2D%,CreateTexture3D%,CreateShaderResourceView%, \
\ CreateUnorderedAccessView%,CreateRenderTargetView%,CreateDepthStencilView%, \
\ CreateInputLayout%,CreateVertexShader%,CreateGeometryShader%, \
\ CreateGeometryShaderWithStreamOutput%,CreatePixelShader%,CreateHullShader%, \
\ CreateDomainShader%,CreateComputeShader%,CreateClassLinkage%,CreateBlendState%, \
\ CreateDepthStencilState%,CreateRasterizerState%,CreateSamplerState%, \
\ CreateQuery%,CreatePredicate%,CreateCounter%,CreateDeferredContext%, \
\ OpenSharedResource%,CheckFormatSupport%,CheckMultisampleQualityLevels%, \
\ CheckCounterInfo%,CheckCounter%,CheckFeatureSupport%,GetPrivateData%, \
\ SetPrivateData%,SetPrivateDataInterface%,GetFeatureLevel%,GetCreationFlags%, \
\ GetDeviceRemovedReason%,GetImmediateContext%,SetExceptionMode%,GetExceptionMode%}
DIM ID3D11DeviceContext{QueryInterface%,AddRef%,Release%,GetDevice%, \
\ GetPrivateData%,SetPrivateData%,SetPrivateDataInterface%,VSSetConstantBuffers%, \
\ PSSetShaderResources%,PSSetShader%,PSSetSamplers%,VSSetShader%, \
\ DrawIndexed%,Draw%,Map%,Unmap%,PSSetConstantBuffers%,IASetInputLayout%, \
\ IASetVertexBuffers%,IASetIndexBuffer%,DrawIndexedInstanced%,DrawInstanced%, \
\ GSSetConstantBuffers%,GSSetShader%,IASetPrimitiveTopology%,VSSetShaderResources%, \
\ VSSetSamplers%,Begin%,End%,GetData%,SetPredication%,GSSetShaderResources%, \
\ GSSetSamplers%,OMSetRenderTargets%,OMSetRenderTargetsAndUnorderedAccessViews%, \
\ OMSetBlendState%,OMSetDepthStencilState%,SOSetTargets%,DrawAuto%, \
\ DrawIndexedInstancedIndirect%,DrawInstancedIndirect%,Dispatch%, \
\ DispatchIndirect%,RSSetState%,RSSetViewports%,RSSetScissorRects%, \
\ CopySubresourceRegion%,CopyResource%,UpdateSubresource%,CopyStructureCount%, \
\ ClearRenderTargetView%,ClearUnorderedAccessViewUint%,ClearUnorderedAccessViewFloat%, \
\ ClearDepthStencilView%,GenerateMips%,SetResourceMinLOD%,GetResourceMinLOD%, \
\ ResolveSubresource%,ExecuteCommandList%,HSSetShaderResources%,HSSetShader%, \
\ HSSetSamplers%,HSSetConstantBuffers%,DSSetShaderResources%,DSSetShader%, \
\ DSSetSamplers%,DSSetConstantBuffers%,CSSetShaderResources%,CSSetUnorderedAccessViews%, \
\ CSSetShader%,CSSetSamplers%,CSSetConstantBuffers%,VSGetConstantBuffers%, \
\ PSGetShaderResources%,PSGetShader%,PSGetSamplers%,VSGetShader%, \
\ PSGetConstantBuffers%,IAGetInputLayout%,IAGetVertexBuffers%,IAGetIndexBuffer%, \
\ GSGetConstantBuffers%,GSGetShader%,IAGetPrimitiveTopology%,VSGetShaderResources%, \
\ VSGetSamplers%,GetPredication%,GSGetShaderResources%,GSGetSamplers%, \
\ OMGetRenderTargets%,OMGetRenderTargetsAndUnorderedAccessViews%, \
\ OMGetBlendState%,OMGetDepthStencilState%,SOGetTargets%,RSGetState%, \
\ RSGetViewports%,RSGetScissorRects%,HSGetShaderResources%,HSGetShader%, \
\ HSGetSamplers%,HSGetConstantBuffers%,DSGetShaderResources%,DSGetShader%, \
\ DSGetSamplers%,DSGetConstantBuffers%,CSGetShaderResources%,CSGetUnorderedAccessViews%, \
\ CSGetShader%,CSGetSamplers%,CSGetConstantBuffers%,ClearState%,Flush%, \
\ GetType%,GetContextFlags%,FinishCommandList%}
REM: Initialise:
SYS "LoadLibrary","D3D11.DLL" TO d3d11%
IF d3d11% = 0 ERROR 0, "DirectX 11 is not installed"
SYS "GetProcAddress", d3d11%, "D3D11CreateDeviceAndSwapChain" TO \
\ `D3D11CreateDeviceAndSwapChain`
REM Create the swap chain:
DIM sd{} = DXGI_SWAP_CHAIN_DESC{}
sd.BufferCount% = 1
sd.BufferDesc.Width% = 640
sd.BufferDesc.Height% = 512
sd.BufferDesc.Format% = DXGI_FORMAT_R8G8B8A8_UNORM
sd.BufferDesc.RefreshRate.Numerator% = 60
sd.BufferDesc.RefreshRate.Denominator% = 1
sd.BufferUsage% = DXGI_USAGE_RENDER_TARGET_OUTPUT
sd.OutputWindow% = @hwnd%
sd.SampleDesc.Count% = 1
sd.SampleDesc.Quality% = 0
sd.Windowed% = 1
SYS `D3D11CreateDeviceAndSwapChain`, NULL, D3D_DRIVER_TYPE_HARDWARE, \
\ NULL, 0, NULL, 0, D3D11_SDK_VERSION, sd{}, ^pSwapChain%, \
\ ^pd3dDevice%, NULL, ^pImmediateContext% TO result%
IF result% <> S_OK ERROR 100, "CreateDeviceAndSwapChain failed"
!(^IDXGISwapChain{}+4) = !pSwapChain%
!(^ID3D11Device{}+4) = !pd3dDevice%
!(^ID3D11DeviceContext{}+4) = !pImmediateContext%
REM Create a render target view:
SYS IDXGISwapChain.GetBuffer%, pSwapChain%, 0, IID_ID3D11Texture2D, \
\ ^pBackBuffer% TO result%
IF result% <> S_OK ERROR 100, "IDXGISwapChain::GetBuffer failed"
!(^ID3D11Texture2D{}+4) = !pBackBuffer%
SYS ID3D11Device.CreateRenderTargetView%, pd3dDevice%, pBackBuffer%, NULL, \
\ ^pRenderTargetView% TO result%
IF result% <> S_OK ERROR 100, "ID3D11Device::CreateRenderTargetView failed"
SYS ID3D11Texture2D.Release%, pBackBuffer%
SYS ID3D11DeviceContext.OMSetRenderTargets%, pImmediateContext%, \
\ 1, ^pRenderTargetView%, NULL
DIM vp{} = D3D11_VIEWPORT{} : REM All members are floats
vp.Width% = FN_f4(sd.BufferDesc.Width%)
vp.Height% = FN_f4(sd.BufferDesc.Height%)
vp.MinDepth% = 0
vp.MaxDepth% = FN_f4(1.0)
vp.TopLeftX% = 0
vp.TopLeftY% = 0
SYS ID3D11DeviceContext.RSSetViewports%, pImmediateContext%, 1, vp{}
REM Render:
DIM ClearColor%(3)
ClearColor%() = 0, FN_f4(0.125), FN_f4(0.6), FN_f4(1.0) : REM RGBA
SYS ID3D11DeviceContext.ClearRenderTargetView%, pImmediateContext%, \
\ pRenderTargetView%, ^ClearColor%(0)
SYS IDXGISwapChain.Present%, pSwapChain%, 0, 0
END
DEF FN_f4(a#)
LOCAL A% : PRIVATE F%
IF F% = 0 THEN
SYS "LoadLibrary", "OLEAUT32.DLL" TO F%
SYS "GetProcAddress", F%, "VarR4FromR8" TO F%
ENDIF
a# *= 1.0#
SYS F%,!^a#,!(^a#+4),^A%
=A%
DEF FN_guid(a$)
LOCAL C%, M% : PRIVATE O%
DIM C% 30, M% LOCAL 2*LENa$+2
C% = (C%+15) AND -16 : M% = (M%+1) AND -2
IF O% = 0 THEN
SYS "LoadLibrary", "OLE32.DLL" TO O%
SYS "GetProcAddress", O%, "CLSIDFromString" TO O%
ENDIF
SYS "MultiByteToWideChar", 0, 0, a$, -1, M%, LENa$+1
SYS O%, M%, C%
= C%
REM ****************************************************************
REM
REM Create a DirectX11 Device
REM
REM ****************************************************************
DEF PROC_Init_D3D11(hwnd%)
INSTALL @lib$ + "DirectX11\Functions\DLL"
INSTALL @lib$ + "DirectX11\Functions\Helper"
CALL @lib$ + "DirectX11\Constants"
CALL @lib$ + "DirectX11\Structures"
CALL @lib$ + "DirectX11\Interfaces"
PROC_Helper_AssembleFNf
REM Get the Dlls and the functions we need
D3D11DLL% = FN_DLL_LoadDLL("D3D11.DLL")
D3D11CreateDeviceAndSwapChain% = FN_DLL_GetFunctionAddress(D3D11DLL%, "D3D11CreateDeviceAndSwapChain")
D3DX11DLL% = FN_DLL_LoadDLL(FN_GetD3DX11DLL)
D3DX11CompileFromFile% = FN_DLL_GetFunctionAddress(D3DX11DLL%, "D3DX11CompileFromFileA")
REM Create our swap chain description{}
LOCAL scd{}
DIM scd{} = DXGI_SWAP_CHAIN_DESC{}
REM Fill out its members
scd.BufferCount% = 1
scd.BufferDesc.Width% = SCREENWIDTH
scd.BufferDesc.Height% = SCREENHEIGHT
scd.BufferDesc.Format% = DXGI_R8G8B8A8_UNORM
scd.BufferDesc.RefreshRate.Numerator% = 60
scd.BufferDesc.RefreshRate.Denominator% = 1
scd.BufferUsage% = DXGI_USAGE_RENDER_TARGET_OUTPUT
scd.OutputWindow% = hwnd%
scd.SampleDesc.Count% = 4
scd.SampleDesc.Quality% = 0
scd.Windowed% = _TRUE
scd.Flags% = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
REM Create the device
SYS D3D11CreateDeviceAndSwapChain%, 0, \
\ D3D_DRIVER_TYPE_HARDWARE, \
\ 0, \
\ 0, \
\ 0, \
\ 0, \
\ D3D11_SDK_VERSION , \
\ scd{}, \
\ ^SwapChain%, \
\ ^Device%, \
\ 0, \
\ ^DeviceContext% TO R%
IF R% PROC_D3DERR(R%) ELSE IF V% PRINT"Device Created."
PROC_Helper_CreateInterface(IDevice{}, ID3D11Device{}, Device%)
PROC_Helper_CreateInterface(ISwapChain{}, IDXGISwapChain{}, SwapChain%)
PROC_Helper_CreateInterface(IDeviceContext{}, ID3D11DeviceContext{}, DeviceContext%)
REM Get the address of the back buffer
SYS ISwapChain.GetBuffer%, SwapChain%, 0, IID_ID3D11Texture2D{}, ^pBackBuffer% TO R%
IF R% THEN ERROR 100,"Error : swapchain->GetBuffer : "+STR$~R%
REM Use the BackBufferAddress to create the Render Target
SYS IDevice.CreateRenderTargetView%, Device%, pBackBuffer%, 0, ^BackBuffer% TO R%
IF R% THEN ERROR 100,"Error : Couldn't Use the BackBufferAddress to create the Render Target"
REM Release the BackBuffer pointer
SYS !(!pBackBuffer% + 8), pBackBuffer%
REM OMSetRenderTargets : Returns Void
SYS IDeviceContext.OMSetRenderTargets%, DeviceContext%, 1, ^BackBuffer%, 0
REM Set the viewport
DIM vp{} = D3D11_VIEWPORT{}
vp.Width% = FNf(SCREENWIDTH)
vp.Height% = FNf(SCREENHEIGHT)
vp.TopLeftX% = 0
vp.TopLeftY% = 0
SYS IDeviceContext.RSSetViewports%, DeviceContext%, 1, vp{}
ENDPROC
REM ****************************************************************
REM
REM Closes DirextX11 and releases all the Objects created
REM
REM ****************************************************************
DEF PROC_Close_D3D11(D%)
PRINT'
REM switch to windowed mode
SwapChain% += 0
IF SwapChain% THEN
SYS ISwapChain.SetFullscreenState%, SwapChain%, 0, 0
ENDIF
REM Release Roger!
REM Release all our objects
IF FN_Helper_Release(VertexShader%) = 0 IF V% PRINT"VertexShader released."
IF FN_Helper_Release(PixelShader%) = 0 IF V% PRINT"PixelShader released."
IF FN_Helper_Release(BackBuffer%) = 0 IF V% PRINT"BackBuffer released."
IF FN_Helper_Release(SwapChain%) = 0 IF V% PRINT"Swapchain released."
IF FN_Helper_Release(Device%) = 0 IF V% PRINT"Device released."
IF FN_Helper_Release(DeviceContext%) = 0 IF V% PRINT"DeviceContext released."
REM Release our dlls
IF FN_DLL_FreeDLL(D3D11DLL%) IF V% THEN PRINT"D3D11.DLL Freed."
IF FN_DLL_FreeDLL(D3DX11DLL%) IF V% THEN PRINT"D3DX11.DLL Freed."
ENDPROC
DEF FN_Helper_Release(RETURN O%)
LOCAL R%
O% += 0 : IF O% THEN SYS !(!O%+8), O% TO R%
=R%
REM ****************************************************************
REM
REM DirextX11 Error handling
REM
REM ****************************************************************
DEF PROC_D3DERR(E%)
D3DERR_INVALIDCALL = FN_MAKE_D3DHRESULT(2156)
D3DERR_WASSTILLDRAWING = FN_MAKE_D3DHRESULT(540)
ENDPROC
DEF FN_MAKE_D3DHRESULT(C%)
=FN_MAKE_HRESULT(1, &876, C%)
DEF FN_MAKE_D3D10_HRESULT(C%)
=FN_MAKE_HRESULT(1, &879, C%)
DEF FN_MAKE_D3D11_HRESULT(C%)
=FN_MAKE_HRESULT(1, &87C, C%)
DEF FN_MAKE_HRESULT(S%, F%, C%)
=(S%<<31) OR (F%<<16) OR C%