Update Files
This commit is contained in:
@ -0,0 +1,491 @@
|
||||
#ifdef KORE_OCULUS
|
||||
|
||||
#include <kinc/vr/vrinterface.h>
|
||||
|
||||
#include "Direct3D11.h"
|
||||
#include <Kore/Graphics4/Graphics.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
#include "OVR_CAPI_D3D.h"
|
||||
|
||||
#include "d3d11.h"
|
||||
#include <vector>
|
||||
#if _MSC_VER > 1600
|
||||
#include "DirectXMath.h"
|
||||
using namespace DirectX;
|
||||
#else
|
||||
#include "xnamath.h"
|
||||
#endif //_MSC_VER > 1600
|
||||
|
||||
#pragma comment(lib, "dxgi.lib")
|
||||
#pragma comment(lib, "d3d11.lib")
|
||||
#pragma comment(lib, "d3dcompiler.lib")
|
||||
|
||||
using namespace Kore;
|
||||
|
||||
namespace {
|
||||
kinc_vr_sensor_state_t sensorStates[2];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
struct DepthBuffer {
|
||||
ID3D11DepthStencilView *TexDsv;
|
||||
|
||||
DepthBuffer(ID3D11Device *Device, int sizeW, int sizeH, int sampleCount = 1) {
|
||||
DXGI_FORMAT format = DXGI_FORMAT_D32_FLOAT;
|
||||
D3D11_TEXTURE2D_DESC dsDesc;
|
||||
dsDesc.Width = sizeW;
|
||||
dsDesc.Height = sizeH;
|
||||
dsDesc.MipLevels = 1;
|
||||
dsDesc.ArraySize = 1;
|
||||
dsDesc.Format = format;
|
||||
dsDesc.SampleDesc.Count = sampleCount;
|
||||
dsDesc.SampleDesc.Quality = 0;
|
||||
dsDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
dsDesc.CPUAccessFlags = 0;
|
||||
dsDesc.MiscFlags = 0;
|
||||
dsDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
|
||||
ID3D11Texture2D *Tex;
|
||||
Device->CreateTexture2D(&dsDesc, nullptr, &Tex);
|
||||
Device->CreateDepthStencilView(Tex, nullptr, &TexDsv);
|
||||
Tex->Release();
|
||||
}
|
||||
~DepthBuffer() {
|
||||
TexDsv->Release();
|
||||
TexDsv = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------
|
||||
struct Camera {
|
||||
XMVECTOR Pos;
|
||||
XMVECTOR Rot;
|
||||
Camera(){};
|
||||
Camera(XMVECTOR *pos, XMVECTOR *rot) : Pos(*pos), Rot(*rot){};
|
||||
Camera(const XMVECTOR &pos, const XMVECTOR &rot) : Pos(pos), Rot(rot){};
|
||||
XMMATRIX GetViewMatrix() {
|
||||
XMVECTOR forward = XMVector3Rotate(XMVectorSet(0, 0, -1, 0), Rot);
|
||||
return (XMMatrixLookAtRH(Pos, XMVectorAdd(Pos, forward), XMVector3Rotate(XMVectorSet(0, 1, 0, 0), Rot)));
|
||||
}
|
||||
|
||||
static void *operator new(std::size_t size) {
|
||||
UNREFERENCED_PARAMETER(size);
|
||||
return _aligned_malloc(sizeof(Camera), __alignof(Camera));
|
||||
}
|
||||
|
||||
static void operator delete(void *p) {
|
||||
_aligned_free(p);
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
struct DirectX11 {
|
||||
HWND Window;
|
||||
bool Running;
|
||||
int WinSizeW;
|
||||
int WinSizeH;
|
||||
|
||||
HINSTANCE hInstance;
|
||||
|
||||
DirectX11() : Window(nullptr), Running(false), WinSizeW(0), WinSizeH(0), hInstance(nullptr) {}
|
||||
|
||||
~DirectX11() {
|
||||
ReleaseDevice();
|
||||
CloseWindow();
|
||||
}
|
||||
|
||||
bool InitWindow(HINSTANCE hinst, const char *title, const char *windowClassName) {
|
||||
hInstance = hinst;
|
||||
Running = true;
|
||||
|
||||
// Adjust the window size and show at InitDevice time
|
||||
wchar_t wchTitle[256];
|
||||
MultiByteToWideChar(CP_ACP, 0, title, -1, wchTitle, 256);
|
||||
wchar_t wchClassName[256];
|
||||
MultiByteToWideChar(CP_ACP, 0, windowClassName, -1, wchClassName, 256);
|
||||
Window = CreateWindowW(wchClassName, wchTitle, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, 0, 0, hinst, 0);
|
||||
if (!Window)
|
||||
return false;
|
||||
|
||||
SetWindowLongPtr(Window, 0, LONG_PTR(this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CloseWindow() {
|
||||
if (Window) {
|
||||
Window = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool InitDevice(int vpW, int vpH, const LUID *pLuid, bool windowed = true, int scale = 1) {
|
||||
WinSizeW = vpW;
|
||||
WinSizeH = vpH;
|
||||
|
||||
if (scale == 0)
|
||||
scale = 1;
|
||||
|
||||
RECT size = {0, 0, vpW / scale, vpH / scale};
|
||||
AdjustWindowRect(&size, WS_OVERLAPPEDWINDOW, false);
|
||||
const UINT flags = SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW;
|
||||
if (!SetWindowPos(Window, nullptr, 0, 0, size.right - size.left, size.bottom - size.top, flags))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetAndClearRenderTarget(ID3D11RenderTargetView *rendertarget, DepthBuffer *depthbuffer, float R = 0, float G = 0, float B = 0, float A = 0) {
|
||||
float black[] = {R, G, B, A}; // Important that alpha=0, if want pixels to be transparent, for manual layers
|
||||
dx_ctx.context->OMSetRenderTargets(1, &rendertarget, (depthbuffer ? depthbuffer->TexDsv : nullptr));
|
||||
dx_ctx.context->ClearRenderTargetView(rendertarget, black);
|
||||
if (depthbuffer)
|
||||
dx_ctx.context->ClearDepthStencilView(depthbuffer->TexDsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
|
||||
}
|
||||
|
||||
void SetViewport(float vpX, float vpY, float vpW, float vpH) {
|
||||
D3D11_VIEWPORT D3Dvp;
|
||||
D3Dvp.Width = vpW;
|
||||
D3Dvp.Height = vpH;
|
||||
D3Dvp.MinDepth = 0;
|
||||
D3Dvp.MaxDepth = 1;
|
||||
D3Dvp.TopLeftX = vpX;
|
||||
D3Dvp.TopLeftY = vpY;
|
||||
dx_ctx.context->RSSetViewports(1, &D3Dvp);
|
||||
}
|
||||
|
||||
void ReleaseDevice() {}
|
||||
};
|
||||
|
||||
static DirectX11 Platform;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
// ovrSwapTextureSet wrapper class that also maintains the render target views needed for D3D11 rendering.
|
||||
struct OculusTexture {
|
||||
ovrSession Session;
|
||||
ovrTextureSwapChain TextureChain;
|
||||
std::vector<ID3D11RenderTargetView *> TexRtv;
|
||||
|
||||
OculusTexture(ovrSession session, int sizeW, int sizeH, int sampleCount = 1) : Session(session), TextureChain(nullptr) {
|
||||
ovrTextureSwapChainDesc desc = {};
|
||||
desc.Type = ovrTexture_2D;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
desc.Width = sizeW;
|
||||
desc.Height = sizeH;
|
||||
desc.MipLevels = 1;
|
||||
desc.SampleCount = sampleCount;
|
||||
desc.MiscFlags = ovrTextureMisc_DX_Typeless | ovrTextureMisc_AutoGenerateMips;
|
||||
desc.BindFlags = ovrTextureBind_DX_RenderTarget;
|
||||
desc.StaticImage = ovrFalse;
|
||||
|
||||
ovrResult result = ovr_CreateTextureSwapChainDX(session, dx_ctx.device, &desc, &TextureChain);
|
||||
|
||||
int textureCount = 0;
|
||||
ovr_GetTextureSwapChainLength(Session, TextureChain, &textureCount);
|
||||
if (OVR_SUCCESS(result)) {
|
||||
for (int i = 0; i < textureCount; ++i) {
|
||||
ID3D11Texture2D *tex = nullptr;
|
||||
ovr_GetTextureSwapChainBufferDX(Session, TextureChain, i, IID_PPV_ARGS(&tex));
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
|
||||
rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
rtvd.ViewDimension = (sampleCount > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
ID3D11RenderTargetView *rtv;
|
||||
dx_ctx.device->CreateRenderTargetView(tex, &rtvd, &rtv);
|
||||
TexRtv.push_back(rtv);
|
||||
tex->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~OculusTexture() {
|
||||
for (int i = 0; i < (int)TexRtv.size(); ++i) {
|
||||
TexRtv[i]->Release();
|
||||
TexRtv[i] = nullptr;
|
||||
}
|
||||
if (TextureChain) {
|
||||
ovr_DestroyTextureSwapChain(Session, TextureChain);
|
||||
TextureChain = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11RenderTargetView *GetRTV() {
|
||||
int index = 0;
|
||||
ovr_GetTextureSwapChainCurrentIndex(Session, TextureChain, &index);
|
||||
return TexRtv[index];
|
||||
}
|
||||
|
||||
void Commit() {
|
||||
ovr_CommitTextureSwapChain(Session, TextureChain);
|
||||
}
|
||||
};
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
// Initialize these to nullptr here to handle dx_ctx.device lost failures cleanly
|
||||
ovrMirrorTexture mirrorTexture = nullptr;
|
||||
OculusTexture *pEyeRenderTexture[2] = {nullptr, nullptr};
|
||||
DepthBuffer *pEyeDepthBuffer[2] = {nullptr, nullptr};
|
||||
|
||||
ovrSizei windowSize;
|
||||
|
||||
long long frameIndex = 0;
|
||||
int msaaRate = 4;
|
||||
|
||||
bool isVisible = true;
|
||||
|
||||
ovrSession session;
|
||||
ovrHmdDesc hmdDesc;
|
||||
|
||||
ovrPosef EyeRenderPose[2];
|
||||
double sensorSampleTime;
|
||||
|
||||
// Make the eye render buffers (caution if actual size < requested due to HW limits).
|
||||
ovrRecti eyeRenderViewport[2];
|
||||
|
||||
void done() {
|
||||
if (mirrorTexture)
|
||||
ovr_DestroyMirrorTexture(session, mirrorTexture);
|
||||
for (int eye = 0; eye < 2; ++eye) {
|
||||
delete pEyeRenderTexture[eye];
|
||||
delete pEyeDepthBuffer[eye];
|
||||
}
|
||||
Platform.ReleaseDevice();
|
||||
ovr_Destroy(session);
|
||||
}
|
||||
|
||||
void createOculusTexture() {
|
||||
// Create mirror texture
|
||||
ovrMirrorTextureDesc mirrorDesc;
|
||||
memset(&mirrorDesc, 0, sizeof(mirrorDesc));
|
||||
mirrorDesc.Width = Platform.WinSizeW;
|
||||
mirrorDesc.Height = Platform.WinSizeH;
|
||||
mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
mirrorDesc.MirrorOptions = ovrMirrorOption_Default;
|
||||
HRESULT result = ovr_CreateMirrorTextureWithOptionsDX(session, dx_ctx.device, &mirrorDesc, &mirrorTexture);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to create mirror texture.");
|
||||
done();
|
||||
}
|
||||
|
||||
// Make eye render buffers
|
||||
for (int eye = 0; eye < 2; ++eye) {
|
||||
ovrSizei idealSize = ovr_GetFovTextureSize(session, ovrEyeType(eye), hmdDesc.DefaultEyeFov[eye], 1);
|
||||
pEyeRenderTexture[eye] = new OculusTexture(session, idealSize.w, idealSize.h);
|
||||
pEyeDepthBuffer[eye] = new DepthBuffer(dx_ctx.device, idealSize.w, idealSize.h);
|
||||
eyeRenderViewport[eye].Pos.x = 0;
|
||||
eyeRenderViewport[eye].Pos.y = 0;
|
||||
eyeRenderViewport[eye].Size = idealSize;
|
||||
if (!pEyeRenderTexture[eye]->TextureChain) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to create texture.");
|
||||
done();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *kinc_vr_interface_init(void *hinst, const char *title, const char *windowClassName) {
|
||||
// Initializes LibOVR, and the Rift
|
||||
ovrInitParams initParams = {ovrInit_RequestVersion | ovrInit_FocusAware, OVR_MINOR_VERSION, NULL, 0, 0};
|
||||
ovrResult result = ovr_Initialize(&initParams);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to initialize libOVR.");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!Platform.InitWindow((HINSTANCE)hinst, title, windowClassName)) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to open window.");
|
||||
return (0);
|
||||
}
|
||||
|
||||
ovrGraphicsLuid luid;
|
||||
result = ovr_Create(&session, &luid);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "HMD not connected.");
|
||||
return false; // TODO: retry
|
||||
}
|
||||
|
||||
hmdDesc = ovr_GetHmdDesc(session);
|
||||
|
||||
// Setup Window and Graphics
|
||||
// Note: the mirror window can be any size, for this sample we use 1/2 the HMD resolution
|
||||
windowSize = {hmdDesc.Resolution.w / 2, hmdDesc.Resolution.h / 2};
|
||||
if (!Platform.InitDevice(windowSize.w, windowSize.h, reinterpret_cast<LUID *>(&luid))) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to init dx_ctx.device.");
|
||||
done();
|
||||
}
|
||||
|
||||
// FloorLevel will give tracking poses where the floor height is 0
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
|
||||
|
||||
// Return window
|
||||
return Platform.Window;
|
||||
}
|
||||
|
||||
void kinc_vr_interface_begin() {
|
||||
// Call ovr_GetRenderDesc each frame to get the ovrEyeRenderDesc, as the returned values (e.g. HmdToEyeOffset) may change at runtime.
|
||||
ovrEyeRenderDesc eyeRenderDesc[2];
|
||||
eyeRenderDesc[0] = ovr_GetRenderDesc(session, ovrEye_Left, hmdDesc.DefaultEyeFov[0]);
|
||||
eyeRenderDesc[1] = ovr_GetRenderDesc(session, ovrEye_Right, hmdDesc.DefaultEyeFov[1]);
|
||||
|
||||
// Get both eye poses simultaneously, with IPD offset already included.
|
||||
ovrPosef HmdToEyePose[2] = {eyeRenderDesc[0].HmdToEyePose, eyeRenderDesc[1].HmdToEyePose};
|
||||
|
||||
ovr_GetEyePoses(session, frameIndex, ovrTrue, HmdToEyePose, EyeRenderPose, &sensorSampleTime);
|
||||
}
|
||||
|
||||
void kinc_vr_interface_begin_render(int eye) {
|
||||
if (pEyeRenderTexture[0] == nullptr || pEyeRenderTexture[1] == nullptr)
|
||||
createOculusTexture();
|
||||
|
||||
// Clear and set up rendertarget
|
||||
Platform.SetAndClearRenderTarget(pEyeRenderTexture[eye]->GetRTV(), pEyeDepthBuffer[eye]);
|
||||
Platform.SetViewport((float)eyeRenderViewport[eye].Pos.x, (float)eyeRenderViewport[eye].Pos.y, (float)eyeRenderViewport[eye].Size.w,
|
||||
(float)eyeRenderViewport[eye].Size.h);
|
||||
}
|
||||
|
||||
void kinc_vr_interface_end_render(int eye) {
|
||||
// Commit rendering to the swap chain
|
||||
pEyeRenderTexture[eye]->Commit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
kinc_matrix4x4_t convert(XMMATRIX &m) {
|
||||
XMFLOAT4X4 fView;
|
||||
XMStoreFloat4x4(&fView, m);
|
||||
|
||||
kinc_matrix4x4_t mat;
|
||||
kinc_matrix4x4_set(&mat, 0, 0, fView._11);
|
||||
kinc_matrix4x4_set(&mat, 0, 1, fView._12);
|
||||
kinc_matrix4x4_set(&mat, 0, 2, fView._13);
|
||||
kinc_matrix4x4_set(&mat, 0, 3, fView._14);
|
||||
kinc_matrix4x4_set(&mat, 1, 0, fView._21);
|
||||
kinc_matrix4x4_set(&mat, 1, 1, fView._22);
|
||||
kinc_matrix4x4_set(&mat, 1, 2, fView._23);
|
||||
kinc_matrix4x4_set(&mat, 1, 3, fView._24);
|
||||
kinc_matrix4x4_set(&mat, 2, 0, fView._31);
|
||||
kinc_matrix4x4_set(&mat, 2, 1, fView._32);
|
||||
kinc_matrix4x4_set(&mat, 2, 2, fView._33);
|
||||
kinc_matrix4x4_set(&mat, 2, 3, fView._34);
|
||||
kinc_matrix4x4_set(&mat, 3, 0, fView._41);
|
||||
kinc_matrix4x4_set(&mat, 3, 1, fView._42);
|
||||
kinc_matrix4x4_set(&mat, 3, 2, fView._43);
|
||||
kinc_matrix4x4_set(&mat, 3, 3, fView._44);
|
||||
return mat;
|
||||
}
|
||||
}
|
||||
|
||||
kinc_vr_sensor_state_t kinc_vr_interface_get_sensor_state(int eye) {
|
||||
kinc_vr_pose_state_t poseState;
|
||||
|
||||
ovrQuatf orientation = EyeRenderPose[eye].Orientation;
|
||||
poseState.vrPose.orientation.x = orientation.x;
|
||||
poseState.vrPose.orientation.y = orientation.y;
|
||||
poseState.vrPose.orientation.z = orientation.z;
|
||||
poseState.vrPose.orientation.w = orientation.w;
|
||||
|
||||
ovrVector3f pos = EyeRenderPose[eye].Position;
|
||||
poseState.vrPose.position.x = pos.x;
|
||||
poseState.vrPose.position.y = pos.y;
|
||||
poseState.vrPose.position.z = pos.z;
|
||||
|
||||
ovrFovPort fov = hmdDesc.DefaultEyeFov[eye];
|
||||
poseState.vrPose.left = fov.LeftTan;
|
||||
poseState.vrPose.right = fov.RightTan;
|
||||
poseState.vrPose.bottom = fov.DownTan;
|
||||
poseState.vrPose.top = fov.UpTan;
|
||||
|
||||
// Get the pose information in XM format
|
||||
XMVECTOR eyeQuat = XMVectorSet(orientation.x, orientation.y, orientation.z, orientation.w);
|
||||
XMVECTOR eyePos = XMVectorSet(pos.x, pos.y, pos.z, 0);
|
||||
|
||||
// Get view and projection matrices for the Rift camera
|
||||
Camera finalCam(eyePos, eyeQuat);
|
||||
XMMATRIX view = finalCam.GetViewMatrix();
|
||||
ovrMatrix4f p = ovrMatrix4f_Projection(fov, 0.2f, 1000.0f, ovrProjection_None);
|
||||
XMMATRIX proj = XMMatrixSet(p.M[0][0], p.M[1][0], p.M[2][0], p.M[3][0], p.M[0][1], p.M[1][1], p.M[2][1], p.M[3][1], p.M[0][2], p.M[1][2], p.M[2][2],
|
||||
p.M[3][2], p.M[0][3], p.M[1][3], p.M[2][3], p.M[3][3]);
|
||||
|
||||
poseState.vrPose.eye = convert(view);
|
||||
kinc_matrix4x4_transpose(&poseState.vrPose.eye);
|
||||
poseState.vrPose.projection = convert(proj);
|
||||
kinc_matrix4x4_transpose(&poseState.vrPose.projection);
|
||||
|
||||
ovrSessionStatus sessionStatus;
|
||||
ovr_GetSessionStatus(session, &sessionStatus);
|
||||
poseState.isVisible = sessionStatus.IsVisible;
|
||||
poseState.hmdPresenting = sessionStatus.HmdPresent;
|
||||
poseState.hmdMounted = sessionStatus.HmdMounted;
|
||||
poseState.displayLost = sessionStatus.DisplayLost;
|
||||
poseState.shouldQuit = sessionStatus.ShouldQuit;
|
||||
poseState.shouldRecenter = sessionStatus.ShouldRecenter;
|
||||
|
||||
sensorStates[eye].pose = poseState;
|
||||
|
||||
return sensorStates[eye];
|
||||
}
|
||||
|
||||
kinc_vr_pose_state_t kinc_vr_interface_get_controller(int index) {
|
||||
kinc_vr_pose_state_t todo;
|
||||
return todo;
|
||||
}
|
||||
|
||||
void kinc_vr_interface_warp_swap() {
|
||||
// Initialize our single full screen Fov layer.
|
||||
ovrLayerEyeFov ld = {};
|
||||
ld.Header.Type = ovrLayerType_EyeFov;
|
||||
ld.Header.Flags = 0;
|
||||
|
||||
if (isVisible) {
|
||||
for (int eye = 0; eye < 2; ++eye) {
|
||||
ld.ColorTexture[eye] = pEyeRenderTexture[eye]->TextureChain;
|
||||
ld.Viewport[eye] = eyeRenderViewport[eye];
|
||||
ld.Fov[eye] = hmdDesc.DefaultEyeFov[eye];
|
||||
ld.RenderPose[eye] = EyeRenderPose[eye];
|
||||
ld.SensorSampleTime = sensorSampleTime;
|
||||
}
|
||||
}
|
||||
|
||||
ovrLayerHeader *layers = &ld.Header;
|
||||
ovrResult result = ovr_SubmitFrame(session, frameIndex, nullptr, &layers, 1);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
isVisible = false;
|
||||
}
|
||||
else {
|
||||
isVisible = true;
|
||||
}
|
||||
|
||||
frameIndex++;
|
||||
|
||||
// Render mirror
|
||||
ID3D11Texture2D *tex = nullptr;
|
||||
ovr_GetMirrorTextureBufferDX(session, mirrorTexture, IID_PPV_ARGS(&tex));
|
||||
|
||||
dx_ctx.context->CopyResource(backBuffer, tex);
|
||||
tex->Release();
|
||||
}
|
||||
|
||||
void kinc_vr_interface_update_tracking_origin(kinc_tracking_origin_t origin) {
|
||||
switch (origin) {
|
||||
case KINC_TRACKING_ORIGIN_STAND:
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
|
||||
break;
|
||||
case KINC_TRACKING_ORIGIN_SIT:
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_EyeLevel);
|
||||
break;
|
||||
default:
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_vr_interface_reset_hmd_pose() {
|
||||
ovr_RecenterTrackingOrigin(session);
|
||||
}
|
||||
|
||||
void kinc_vr_interface_ovr_shutdown() {
|
||||
ovr_Shutdown();
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,384 @@
|
||||
#include "graphics4/Direct3D11.h"
|
||||
|
||||
#include <kinc/graphics4/compute.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#define NOMINMAX
|
||||
|
||||
#ifdef KORE_WINDOWSAPP
|
||||
#include <d3d11_1.h>
|
||||
#else
|
||||
#pragma warning(disable : 4005)
|
||||
#include <d3d11.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static uint8_t constantsMemory[1024 * 4];
|
||||
|
||||
static int getMultipleOf16(int value) {
|
||||
int ret = 16;
|
||||
while (ret < value)
|
||||
ret += 16;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void setInt(uint8_t *constants, uint32_t offset, uint32_t size, int value) {
|
||||
if (size == 0)
|
||||
return;
|
||||
int *ints = (int *)&constants[offset];
|
||||
ints[0] = value;
|
||||
}
|
||||
|
||||
static void setFloat(uint8_t *constants, uint32_t offset, uint32_t size, float value) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
floats[0] = value;
|
||||
}
|
||||
|
||||
static void setFloat2(uint8_t *constants, uint32_t offset, uint32_t size, float value1, float value2) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
}
|
||||
|
||||
static void setFloat3(uint8_t *constants, uint32_t offset, uint32_t size, float value1, float value2, float value3) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value3;
|
||||
}
|
||||
|
||||
static void setFloat4(uint8_t *constants, uint32_t offset, uint32_t size, float value1, float value2, float value3, float value4) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value3;
|
||||
floats[3] = value4;
|
||||
}
|
||||
|
||||
static void setFloats(uint8_t *constants, uint32_t offset, uint32_t size, uint8_t columns, uint8_t rows, float *values, int count) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
if (columns == 4 && rows == 4) {
|
||||
for (int i = 0; i < count / 16 && i < (int)size / 4; ++i) {
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[i * 16 + x + y * 4] = values[i * 16 + y + x * 4];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (columns == 3 && rows == 3) {
|
||||
for (int i = 0; i < count / 9 && i < (int)size / 3; ++i) {
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[i * 12 + x + y * 4] = values[i * 9 + y + x * 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (columns == 2 && rows == 2) {
|
||||
for (int i = 0; i < count / 4 && i < (int)size / 2; ++i) {
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[i * 8 + x + y * 4] = values[i * 4 + y + x * 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < count && i * 4 < (int)size; ++i) {
|
||||
floats[i] = values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void setBool(uint8_t *constants, uint32_t offset, uint32_t size, bool value) {
|
||||
if (size == 0)
|
||||
return;
|
||||
int *ints = (int *)&constants[offset];
|
||||
ints[0] = value ? 1 : 0;
|
||||
}
|
||||
|
||||
static void setMatrix4(uint8_t *constants, uint32_t offset, uint32_t size, kinc_matrix4x4_t *value) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[x + y * 4] = kinc_matrix4x4_get(value, y, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void setMatrix3(uint8_t *constants, uint32_t offset, uint32_t size, kinc_matrix3x3_t *value) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
for (int y = 0; y < 3; ++y) {
|
||||
for (int x = 0; x < 3; ++x) {
|
||||
floats[x + y * 4] = kinc_matrix3x3_get(value, y, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_compute_shader_init(kinc_compute_shader_t *shader, void *_data, int length) {
|
||||
unsigned index = 0;
|
||||
uint8_t *data = (uint8_t *)_data;
|
||||
|
||||
#ifndef KINC_KONG
|
||||
memset(&shader->impl.attributes, 0, sizeof(shader->impl.attributes));
|
||||
int attributesCount = data[index++];
|
||||
for (int i = 0; i < attributesCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.attributes[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.attributes[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.textures, 0, sizeof(shader->impl.textures));
|
||||
uint8_t texCount = data[index++];
|
||||
for (unsigned i = 0; i < texCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.textures[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.textures[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.constants, 0, sizeof(shader->impl.constants));
|
||||
uint8_t constantCount = data[index++];
|
||||
shader->impl.constantsSize = 0;
|
||||
for (unsigned i = 0; i < constantCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
kinc_compute_internal_shader_constant_t constant;
|
||||
constant.hash = kinc_internal_hash_name(name);
|
||||
constant.offset = *(uint32_t *)&data[index];
|
||||
index += 4;
|
||||
constant.size = *(uint32_t *)&data[index];
|
||||
index += 4;
|
||||
constant.columns = data[index];
|
||||
index += 1;
|
||||
constant.rows = data[index];
|
||||
index += 1;
|
||||
|
||||
shader->impl.constants[i] = constant;
|
||||
shader->impl.constantsSize = constant.offset + constant.size;
|
||||
}
|
||||
#endif
|
||||
|
||||
shader->impl.length = (int)(length - index);
|
||||
shader->impl.data = (uint8_t *)malloc(shader->impl.length);
|
||||
assert(shader->impl.data != NULL);
|
||||
memcpy(shader->impl.data, &data[index], shader->impl.length);
|
||||
|
||||
HRESULT hr =
|
||||
dx_ctx.device->lpVtbl->CreateComputeShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11ComputeShader **)&shader->impl.shader);
|
||||
|
||||
if (hr != S_OK) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not initialize compute shader.");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = getMultipleOf16(shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &shader->impl.constantBuffer));
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_shader_destroy(kinc_compute_shader_t *shader) {}
|
||||
|
||||
static kinc_compute_internal_shader_constant_t *findConstant(kinc_compute_internal_shader_constant_t *constants, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (constants[i].hash == hash) {
|
||||
return &constants[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static kinc_internal_hash_index_t *findTextureUnit(kinc_internal_hash_index_t *units, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (units[i].hash == hash) {
|
||||
return &units[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
kinc_compute_constant_location_t kinc_compute_shader_get_constant_location(kinc_compute_shader_t *shader, const char *name) {
|
||||
kinc_compute_constant_location_t location;
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
|
||||
|
||||
kinc_compute_internal_shader_constant_t *constant = findConstant(shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.offset = 0;
|
||||
location.impl.size = 0;
|
||||
location.impl.columns = 0;
|
||||
location.impl.rows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.offset = constant->offset;
|
||||
location.impl.size = constant->size;
|
||||
location.impl.columns = constant->columns;
|
||||
location.impl.rows = constant->rows;
|
||||
}
|
||||
|
||||
if (location.impl.size == 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_compute_texture_unit_t kinc_compute_shader_get_texture_unit(kinc_compute_shader_t *shader, const char *name) {
|
||||
char unitName[64];
|
||||
int unitOffset = 0;
|
||||
size_t len = strlen(name);
|
||||
if (len > 63)
|
||||
len = 63;
|
||||
strncpy(unitName, name, len + 1);
|
||||
if (unitName[len - 1] == ']') { // Check for array - mySampler[2]
|
||||
unitOffset = (int)(unitName[len - 2] - '0'); // Array index is unit offset
|
||||
unitName[len - 3] = 0; // Strip array from name
|
||||
}
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)unitName);
|
||||
|
||||
kinc_compute_texture_unit_t unit;
|
||||
kinc_internal_hash_index_t *vertexUnit = findTextureUnit(shader->impl.textures, hash);
|
||||
if (vertexUnit == NULL) {
|
||||
unit.impl.unit = -1;
|
||||
#ifndef NDEBUG
|
||||
static int notFoundCount = 0;
|
||||
if (notFoundCount < 10) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Sampler %s not found.", unitName);
|
||||
++notFoundCount;
|
||||
}
|
||||
else if (notFoundCount == 10) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Giving up on sampler not found messages.", unitName);
|
||||
++notFoundCount;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
unit.impl.unit = vertexUnit->index + unitOffset;
|
||||
}
|
||||
return unit;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_compute_set_bool(kinc_compute_constant_location_t location, bool value) {
|
||||
setBool(constantsMemory, location.impl.offset, location.impl.size, value);
|
||||
}
|
||||
|
||||
void kinc_compute_set_int(kinc_compute_constant_location_t location, int value) {
|
||||
setInt(constantsMemory, location.impl.offset, location.impl.size, value);
|
||||
}
|
||||
|
||||
void kinc_compute_set_float(kinc_compute_constant_location_t location, float value) {
|
||||
setFloat(constantsMemory, location.impl.offset, location.impl.size, value);
|
||||
}
|
||||
|
||||
void kinc_compute_set_float2(kinc_compute_constant_location_t location, float value1, float value2) {
|
||||
setFloat2(constantsMemory, location.impl.offset, location.impl.size, value1, value2);
|
||||
}
|
||||
|
||||
void kinc_compute_set_float3(kinc_compute_constant_location_t location, float value1, float value2, float value3) {
|
||||
setFloat3(constantsMemory, location.impl.offset, location.impl.size, value1, value2, value3);
|
||||
}
|
||||
|
||||
void kinc_compute_set_float4(kinc_compute_constant_location_t location, float value1, float value2, float value3, float value4) {
|
||||
setFloat4(constantsMemory, location.impl.offset, location.impl.size, value1, value2, value3, value4);
|
||||
}
|
||||
|
||||
void kinc_compute_set_floats(kinc_compute_constant_location_t location, float *values, int count) {
|
||||
setFloats(constantsMemory, location.impl.offset, location.impl.size, location.impl.columns, location.impl.rows, values, count);
|
||||
}
|
||||
|
||||
void kinc_compute_set_matrix4(kinc_compute_constant_location_t location, kinc_matrix4x4_t *value) {
|
||||
setMatrix4(constantsMemory, location.impl.offset, location.impl.size, value);
|
||||
}
|
||||
|
||||
void kinc_compute_set_matrix3(kinc_compute_constant_location_t location, kinc_matrix3x3_t *value) {
|
||||
setMatrix3(constantsMemory, location.impl.offset, location.impl.size, value);
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture(kinc_compute_texture_unit_t unit, struct kinc_g4_texture *texture, kinc_compute_access_t access) {
|
||||
ID3D11ShaderResourceView *nullView = NULL;
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, 0, 1, &nullView);
|
||||
|
||||
dx_ctx.context->lpVtbl->CSSetUnorderedAccessViews(dx_ctx.context, unit.impl.unit, 1, &texture->impl.computeView, NULL);
|
||||
}
|
||||
|
||||
void kinc_compute_set_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *texture, kinc_compute_access_t access) {}
|
||||
|
||||
void kinc_compute_set_sampled_texture(kinc_compute_texture_unit_t unit, struct kinc_g4_texture *texture) {}
|
||||
|
||||
void kinc_compute_set_sampled_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *target) {}
|
||||
|
||||
void kinc_compute_set_sampled_depth_from_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *target) {}
|
||||
|
||||
void kinc_compute_set_texture_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
|
||||
|
||||
void kinc_compute_set_texture_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
|
||||
|
||||
void kinc_compute_set_texture3d_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_shader(kinc_compute_shader_t *shader) {
|
||||
dx_ctx.context->lpVtbl->CSSetShader(dx_ctx.context, (ID3D11ComputeShader *)shader->impl.shader, NULL, 0);
|
||||
#ifndef KINC_KONG
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)shader->impl.constantBuffer, 0, NULL, constantsMemory, 0, 0);
|
||||
dx_ctx.context->lpVtbl->CSSetConstantBuffers(dx_ctx.context, 0, 1, &shader->impl.constantBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute(int x, int y, int z) {
|
||||
dx_ctx.context->lpVtbl->Dispatch(dx_ctx.context, x, y, z);
|
||||
|
||||
ID3D11UnorderedAccessView *nullView = NULL;
|
||||
dx_ctx.context->lpVtbl->CSSetUnorderedAccessViews(dx_ctx.context, 0, 1, &nullView, NULL);
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/backend/graphics4/ShaderHash.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct {
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
uint8_t columns;
|
||||
uint8_t rows;
|
||||
} kinc_compute_constant_location_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int unit;
|
||||
} kinc_compute_texture_unit_impl_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t hash;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
uint8_t columns;
|
||||
uint8_t rows;
|
||||
} kinc_compute_internal_shader_constant_t;
|
||||
|
||||
typedef struct {
|
||||
#ifndef KINC_KONG
|
||||
kinc_compute_internal_shader_constant_t constants[64];
|
||||
int constantsSize;
|
||||
kinc_internal_hash_index_t attributes[64];
|
||||
kinc_internal_hash_index_t textures[64];
|
||||
struct ID3D11Buffer *constantBuffer;
|
||||
#endif
|
||||
void *shader;
|
||||
uint8_t *data;
|
||||
int length;
|
||||
} kinc_compute_shader_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <dxgi.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAXIMUM_WINDOWS 16
|
||||
|
||||
struct dx_window {
|
||||
HWND hwnd;
|
||||
IDXGISwapChain *swapChain;
|
||||
ID3D11Texture2D *backBuffer;
|
||||
ID3D11RenderTargetView *renderTargetView;
|
||||
ID3D11Texture2D *depthStencil;
|
||||
ID3D11DepthStencilView *depthStencilView;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
int new_width;
|
||||
int new_height;
|
||||
|
||||
bool vsync;
|
||||
int depth_bits;
|
||||
int stencil_bits;
|
||||
};
|
||||
|
||||
struct dx_context {
|
||||
ID3D11Device *device;
|
||||
ID3D11DeviceContext *context;
|
||||
IDXGIDevice *dxgiDevice;
|
||||
IDXGIAdapter *dxgiAdapter;
|
||||
IDXGIFactory *dxgiFactory;
|
||||
|
||||
int current_window;
|
||||
struct dx_window windows[MAXIMUM_WINDOWS];
|
||||
};
|
||||
|
||||
extern struct dx_context dx_ctx;
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
@ -0,0 +1,11 @@
|
||||
#include "ShaderHash.h"
|
||||
|
||||
// djb2
|
||||
uint32_t kinc_internal_hash_name(unsigned char *str) {
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
while (c = *str++) {
|
||||
hash = hash * 33 ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t hash;
|
||||
uint32_t index;
|
||||
} kinc_internal_hash_index_t;
|
||||
|
||||
uint32_t kinc_internal_hash_name(unsigned char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,51 @@
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/graphics4/constantbuffer.h>
|
||||
|
||||
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
|
||||
buffer->impl.size = size;
|
||||
buffer->impl.last_start = 0;
|
||||
buffer->impl.last_size = size;
|
||||
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(size);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &buffer->impl.buffer));
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {
|
||||
buffer->impl.buffer->lpVtbl->Release(buffer->impl.buffer);
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
|
||||
return kinc_g4_constant_buffer_lock(buffer, 0, kinc_g4_constant_buffer_size(buffer));
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
|
||||
buffer->impl.last_start = start;
|
||||
buffer->impl.last_size = size;
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
||||
memset(&mapped_resource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource);
|
||||
uint8_t *data = (uint8_t *)mapped_resource.pData;
|
||||
return &data[start];
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g4_constant_buffer_unlock(buffer, buffer->impl.last_size);
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.buffer, 0);
|
||||
}
|
||||
|
||||
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
|
||||
return buffer->impl.size;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KINC_KONG
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct kinc_g4_constant_buffer_impl {
|
||||
struct ID3D11Buffer *buffer;
|
||||
size_t size;
|
||||
size_t last_start;
|
||||
size_t last_size;
|
||||
} kinc_g4_constant_buffer_impl;
|
||||
|
||||
#endif
|
@ -0,0 +1,108 @@
|
||||
// Windows 7
|
||||
#define WINVER 0x0601
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#define NOATOM
|
||||
#define NOCLIPBOARD
|
||||
#define NOCOLOR
|
||||
#define NOCOMM
|
||||
#define NOCTLMGR
|
||||
#define NODEFERWINDOWPOS
|
||||
#define NODRAWTEXT
|
||||
#define NOGDI
|
||||
#define NOGDICAPMASKS
|
||||
#define NOHELP
|
||||
#define NOICONS
|
||||
#define NOKANJI
|
||||
#define NOKEYSTATES
|
||||
#define NOMB
|
||||
#define NOMCX
|
||||
#define NOMEMMGR
|
||||
#define NOMENUS
|
||||
#define NOMETAFILE
|
||||
#define NOMINMAX
|
||||
//#define NOMSG
|
||||
#define NONLS
|
||||
#define NOOPENFILE
|
||||
#define NOPROFILER
|
||||
#define NORASTEROPS
|
||||
#define NOSCROLL
|
||||
#define NOSERVICE
|
||||
#define NOSHOWWINDOW
|
||||
#define NOSOUND
|
||||
#define NOSYSCOMMANDS
|
||||
#define NOSYSMETRICS
|
||||
#define NOTEXTMETRIC
|
||||
//#define NOUSER
|
||||
#define NOVIRTUALKEYCODES
|
||||
#define NOWH
|
||||
#define NOWINMESSAGES
|
||||
#define NOWINOFFSETS
|
||||
#define NOWINSTYLES
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#ifdef KORE_WINDOWSAPP
|
||||
#include <d3d11_1.h>
|
||||
#else
|
||||
#pragma warning(disable : 4005)
|
||||
#include <d3d11.h>
|
||||
#endif
|
||||
|
||||
#include "Direct3D11.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct dx_context dx_ctx = {0};
|
||||
|
||||
static uint8_t vertexConstants[1024 * 4];
|
||||
static uint8_t fragmentConstants[1024 * 4];
|
||||
static uint8_t geometryConstants[1024 * 4];
|
||||
static uint8_t tessControlConstants[1024 * 4];
|
||||
static uint8_t tessEvalConstants[1024 * 4];
|
||||
|
||||
static D3D11_COMPARISON_FUNC get_comparison(kinc_g4_compare_mode_t compare) {
|
||||
switch (compare) {
|
||||
default:
|
||||
case KINC_G4_COMPARE_ALWAYS:
|
||||
return D3D11_COMPARISON_ALWAYS;
|
||||
case KINC_G4_COMPARE_NEVER:
|
||||
return D3D11_COMPARISON_NEVER;
|
||||
case KINC_G4_COMPARE_EQUAL:
|
||||
return D3D11_COMPARISON_EQUAL;
|
||||
case KINC_G4_COMPARE_NOT_EQUAL:
|
||||
return D3D11_COMPARISON_NOT_EQUAL;
|
||||
case KINC_G4_COMPARE_LESS:
|
||||
return D3D11_COMPARISON_LESS;
|
||||
case KINC_G4_COMPARE_LESS_EQUAL:
|
||||
return D3D11_COMPARISON_LESS_EQUAL;
|
||||
case KINC_G4_COMPARE_GREATER:
|
||||
return D3D11_COMPARISON_GREATER;
|
||||
case KINC_G4_COMPARE_GREATER_EQUAL:
|
||||
return D3D11_COMPARISON_GREATER_EQUAL;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t get_multiple_of_16(size_t value) {
|
||||
size_t ret = 16;
|
||||
while (ret < value) {
|
||||
ret += 16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include "Direct3D11.c.h"
|
||||
#include "ShaderHash.c.h"
|
||||
#include "constantbuffer.c.h"
|
||||
#include "indexbuffer.c.h"
|
||||
#include "pipeline.c.h"
|
||||
#include "rendertarget.c.h"
|
||||
#include "shader.c.h"
|
||||
#include "texture.c.h"
|
||||
#include "texturearray.c.h"
|
||||
#include "vertexbuffer.c.h"
|
@ -0,0 +1,89 @@
|
||||
#include <kinc/graphics4/indexBuffer.h>
|
||||
|
||||
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
|
||||
buffer->impl.count = count;
|
||||
buffer->impl.sixteen = format == KINC_G4_INDEX_BUFFER_FORMAT_16BIT;
|
||||
buffer->impl.last_start = 0;
|
||||
buffer->impl.last_count = count;
|
||||
|
||||
uint32_t byte_size = buffer->impl.sixteen ? sizeof(uint16_t) * count : sizeof(uint32_t) * count;
|
||||
|
||||
if (usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
buffer->impl.indices = NULL;
|
||||
}
|
||||
else {
|
||||
buffer->impl.indices = malloc(byte_size);
|
||||
}
|
||||
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
bufferDesc.ByteWidth = byte_size;
|
||||
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
bufferDesc.StructureByteStride = 0;
|
||||
|
||||
buffer->impl.usage = usage;
|
||||
switch (usage) {
|
||||
case KINC_G4_USAGE_STATIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
case KINC_G4_USAGE_DYNAMIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
break;
|
||||
case KINC_G4_USAGE_READABLE:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &bufferDesc, NULL, &buffer->impl.ib));
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
|
||||
buffer->impl.ib->lpVtbl->Release(buffer->impl.ib);
|
||||
free(buffer->impl.indices);
|
||||
buffer->impl.indices = NULL;
|
||||
}
|
||||
|
||||
static int kinc_g4_internal_index_buffer_stride(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.sixteen ? 2 : 4;
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
return kinc_g4_index_buffer_lock(buffer, 0, kinc_g4_index_buffer_count(buffer));
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
|
||||
buffer->impl.last_start = start;
|
||||
buffer->impl.last_count = count;
|
||||
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
memset(&mappedResource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
uint8_t *data = (uint8_t *)mappedResource.pData;
|
||||
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
|
||||
}
|
||||
else {
|
||||
uint8_t *data = (uint8_t *)buffer->impl.indices;
|
||||
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_g4_index_buffer_unlock(buffer, buffer->impl.last_count);
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0);
|
||||
}
|
||||
else {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0, NULL, buffer->impl.indices, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.count;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Buffer *ib;
|
||||
void *indices;
|
||||
int count;
|
||||
int usage;
|
||||
bool sixteen;
|
||||
int last_start;
|
||||
int last_count;
|
||||
} kinc_g4_index_buffer_impl_t;
|
@ -0,0 +1,876 @@
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
#include <kinc/libs/stb_sprintf.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
kinc_g4_pipeline_t *currentPipeline = NULL;
|
||||
float currentBlendFactor[4] = {0, 0, 0, 0};
|
||||
bool needPipelineRebind = true;
|
||||
|
||||
static D3D11_CULL_MODE convert_cull_mode(kinc_g4_cull_mode_t cullMode) {
|
||||
switch (cullMode) {
|
||||
case KINC_G4_CULL_CLOCKWISE:
|
||||
return D3D11_CULL_BACK;
|
||||
case KINC_G4_CULL_COUNTER_CLOCKWISE:
|
||||
return D3D11_CULL_FRONT;
|
||||
case KINC_G4_CULL_NOTHING:
|
||||
return D3D11_CULL_NONE;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D11_CULL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D11_BLEND convert_blend_factor(kinc_g4_blending_factor_t factor) {
|
||||
switch (factor) {
|
||||
case KINC_G4_BLEND_ONE:
|
||||
return D3D11_BLEND_ONE;
|
||||
case KINC_G4_BLEND_ZERO:
|
||||
return D3D11_BLEND_ZERO;
|
||||
case KINC_G4_BLEND_SOURCE_ALPHA:
|
||||
return D3D11_BLEND_SRC_ALPHA;
|
||||
case KINC_G4_BLEND_DEST_ALPHA:
|
||||
return D3D11_BLEND_DEST_ALPHA;
|
||||
case KINC_G4_BLEND_INV_SOURCE_ALPHA:
|
||||
return D3D11_BLEND_INV_SRC_ALPHA;
|
||||
case KINC_G4_BLEND_INV_DEST_ALPHA:
|
||||
return D3D11_BLEND_INV_DEST_ALPHA;
|
||||
case KINC_G4_BLEND_SOURCE_COLOR:
|
||||
return D3D11_BLEND_SRC_COLOR;
|
||||
case KINC_G4_BLEND_DEST_COLOR:
|
||||
return D3D11_BLEND_DEST_COLOR;
|
||||
case KINC_G4_BLEND_INV_SOURCE_COLOR:
|
||||
return D3D11_BLEND_INV_SRC_COLOR;
|
||||
case KINC_G4_BLEND_INV_DEST_COLOR:
|
||||
return D3D11_BLEND_INV_DEST_COLOR;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D11_BLEND_SRC_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D11_BLEND_OP convert_blend_operation(kinc_g4_blending_operation_t operation) {
|
||||
switch (operation) {
|
||||
case KINC_G4_BLENDOP_ADD:
|
||||
return D3D11_BLEND_OP_ADD;
|
||||
case KINC_G4_BLENDOP_SUBTRACT:
|
||||
return D3D11_BLEND_OP_SUBTRACT;
|
||||
case KINC_G4_BLENDOP_REVERSE_SUBTRACT:
|
||||
return D3D11_BLEND_OP_REV_SUBTRACT;
|
||||
case KINC_G4_BLENDOP_MIN:
|
||||
return D3D11_BLEND_OP_MIN;
|
||||
case KINC_G4_BLENDOP_MAX:
|
||||
return D3D11_BLEND_OP_MAX;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D11_BLEND_OP_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D11_STENCIL_OP get_stencil_action(kinc_g4_stencil_action_t action) {
|
||||
switch (action) {
|
||||
default:
|
||||
case KINC_G4_STENCIL_KEEP:
|
||||
return D3D11_STENCIL_OP_KEEP;
|
||||
case KINC_G4_STENCIL_ZERO:
|
||||
return D3D11_STENCIL_OP_ZERO;
|
||||
case KINC_G4_STENCIL_REPLACE:
|
||||
return D3D11_STENCIL_OP_REPLACE;
|
||||
case KINC_G4_STENCIL_INCREMENT:
|
||||
return D3D11_STENCIL_OP_INCR;
|
||||
case KINC_G4_STENCIL_INCREMENT_WRAP:
|
||||
return D3D11_STENCIL_OP_INCR_SAT;
|
||||
case KINC_G4_STENCIL_DECREMENT:
|
||||
return D3D11_STENCIL_OP_DECR;
|
||||
case KINC_G4_STENCIL_DECREMENT_WRAP:
|
||||
return D3D11_STENCIL_OP_DECR_SAT;
|
||||
case KINC_G4_STENCIL_INVERT:
|
||||
return D3D11_STENCIL_OP_INVERT;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_set_constants(void) {
|
||||
#ifndef KINC_KONG
|
||||
if (currentPipeline->vertex_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.vertexConstantBuffer, 0, NULL, vertexConstants, 0, 0);
|
||||
dx_ctx.context->lpVtbl->VSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.vertexConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->fragment_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.fragmentConstantBuffer, 0, NULL, fragmentConstants, 0,
|
||||
0);
|
||||
dx_ctx.context->lpVtbl->PSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.fragmentConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->geometry_shader != NULL && currentPipeline->geometry_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.geometryConstantBuffer, 0, NULL, geometryConstants, 0,
|
||||
0);
|
||||
dx_ctx.context->lpVtbl->GSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.geometryConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->tessellation_control_shader != NULL && currentPipeline->tessellation_control_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.tessControlConstantBuffer, 0, NULL,
|
||||
tessControlConstants, 0, 0);
|
||||
dx_ctx.context->lpVtbl->HSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.tessControlConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->tessellation_evaluation_shader != NULL && currentPipeline->tessellation_evaluation_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.tessEvalConstantBuffer, 0, NULL, tessEvalConstants, 0,
|
||||
0);
|
||||
dx_ctx.context->lpVtbl->DSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.tessEvalConstantBuffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_init(struct kinc_g4_pipeline *state) {
|
||||
memset(state, 0, sizeof(struct kinc_g4_pipeline));
|
||||
kinc_g4_internal_pipeline_set_defaults(state);
|
||||
state->impl.d3d11inputLayout = NULL;
|
||||
state->impl.fragmentConstantBuffer = NULL;
|
||||
state->impl.vertexConstantBuffer = NULL;
|
||||
state->impl.geometryConstantBuffer = NULL;
|
||||
state->impl.tessEvalConstantBuffer = NULL;
|
||||
state->impl.tessControlConstantBuffer = NULL;
|
||||
state->impl.depthStencilState = NULL;
|
||||
state->impl.rasterizerState = NULL;
|
||||
state->impl.rasterizerStateScissor = NULL;
|
||||
state->impl.blendState = NULL;
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_destroy(struct kinc_g4_pipeline *state) {
|
||||
if (state->impl.d3d11inputLayout != NULL) {
|
||||
state->impl.d3d11inputLayout->lpVtbl->Release(state->impl.d3d11inputLayout);
|
||||
state->impl.d3d11inputLayout = NULL;
|
||||
}
|
||||
if (state->impl.fragmentConstantBuffer != NULL) {
|
||||
state->impl.fragmentConstantBuffer->lpVtbl->Release(state->impl.fragmentConstantBuffer);
|
||||
state->impl.fragmentConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.vertexConstantBuffer != NULL) {
|
||||
state->impl.vertexConstantBuffer->lpVtbl->Release(state->impl.vertexConstantBuffer);
|
||||
state->impl.vertexConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.geometryConstantBuffer != NULL) {
|
||||
state->impl.geometryConstantBuffer->lpVtbl->Release(state->impl.geometryConstantBuffer);
|
||||
state->impl.geometryConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.tessEvalConstantBuffer != NULL) {
|
||||
state->impl.tessEvalConstantBuffer->lpVtbl->Release(state->impl.tessEvalConstantBuffer);
|
||||
state->impl.tessEvalConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.tessControlConstantBuffer != NULL) {
|
||||
state->impl.tessControlConstantBuffer->lpVtbl->Release(state->impl.tessControlConstantBuffer);
|
||||
state->impl.tessControlConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.depthStencilState != NULL) {
|
||||
state->impl.depthStencilState->lpVtbl->Release(state->impl.depthStencilState);
|
||||
state->impl.depthStencilState = NULL;
|
||||
}
|
||||
if (state->impl.rasterizerState != NULL) {
|
||||
state->impl.rasterizerState->lpVtbl->Release(state->impl.rasterizerState);
|
||||
state->impl.rasterizerState = NULL;
|
||||
}
|
||||
if (state->impl.rasterizerStateScissor != NULL) {
|
||||
state->impl.rasterizerStateScissor->lpVtbl->Release(state->impl.rasterizerStateScissor);
|
||||
state->impl.rasterizerStateScissor = NULL;
|
||||
}
|
||||
if (state->impl.blendState != NULL) {
|
||||
state->impl.blendState->lpVtbl->Release(state->impl.blendState);
|
||||
state->impl.blendState = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_set_rasterizer_state(struct kinc_g4_pipeline *pipeline, bool scissoring) {
|
||||
if (scissoring && pipeline->impl.rasterizerStateScissor != NULL)
|
||||
dx_ctx.context->lpVtbl->RSSetState(dx_ctx.context, pipeline->impl.rasterizerStateScissor);
|
||||
else if (pipeline->impl.rasterizerState != NULL)
|
||||
dx_ctx.context->lpVtbl->RSSetState(dx_ctx.context, pipeline->impl.rasterizerState);
|
||||
}
|
||||
|
||||
void kinc_internal_set_pipeline(struct kinc_g4_pipeline *pipeline, bool scissoring) {
|
||||
dx_ctx.context->lpVtbl->OMSetDepthStencilState(dx_ctx.context, pipeline->impl.depthStencilState, pipeline->stencil_reference_value);
|
||||
UINT sampleMask = 0xffffffff;
|
||||
dx_ctx.context->lpVtbl->OMSetBlendState(dx_ctx.context, pipeline->impl.blendState, currentBlendFactor, sampleMask);
|
||||
kinc_internal_set_rasterizer_state(pipeline, scissoring);
|
||||
|
||||
dx_ctx.context->lpVtbl->VSSetShader(dx_ctx.context, (ID3D11VertexShader *)pipeline->vertex_shader->impl.shader, NULL, 0);
|
||||
dx_ctx.context->lpVtbl->PSSetShader(dx_ctx.context, (ID3D11PixelShader *)pipeline->fragment_shader->impl.shader, NULL, 0);
|
||||
|
||||
dx_ctx.context->lpVtbl->GSSetShader(dx_ctx.context,
|
||||
pipeline->geometry_shader != NULL ? (ID3D11GeometryShader *)pipeline->geometry_shader->impl.shader : NULL, NULL, 0);
|
||||
dx_ctx.context->lpVtbl->HSSetShader(
|
||||
dx_ctx.context, pipeline->tessellation_control_shader != NULL ? (ID3D11HullShader *)pipeline->tessellation_control_shader->impl.shader : NULL, NULL, 0);
|
||||
dx_ctx.context->lpVtbl->DSSetShader(
|
||||
dx_ctx.context, pipeline->tessellation_evaluation_shader != NULL ? (ID3D11DomainShader *)pipeline->tessellation_evaluation_shader->impl.shader : NULL,
|
||||
NULL, 0);
|
||||
|
||||
dx_ctx.context->lpVtbl->IASetInputLayout(dx_ctx.context, pipeline->impl.d3d11inputLayout);
|
||||
}
|
||||
|
||||
void kinc_internal_pipeline_rebind() {
|
||||
if (currentPipeline != NULL && needPipelineRebind) {
|
||||
kinc_internal_set_pipeline(currentPipeline, kinc_internal_scissoring);
|
||||
needPipelineRebind = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
static kinc_internal_shader_constant_t *findConstant(kinc_internal_shader_constant_t *constants, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (constants[i].hash == hash) {
|
||||
return &constants[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static kinc_internal_hash_index_t *findTextureUnit(kinc_internal_hash_index_t *units, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (units[i].hash == hash) {
|
||||
return &units[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_get_constant_locations(kinc_g4_pipeline_t *state, kinc_g4_constant_location_t *vertex_locations,
|
||||
kinc_g4_constant_location_t *fragment_locations, int *vertex_sizes, int *fragment_sizes, int *max_vertex,
|
||||
int *max_fragment) {
|
||||
|
||||
// *max_vertex = state->vertex_shader->impl.constantsSize;
|
||||
// *max_fragment = state->fragment_shader->impl.constantsSize;
|
||||
// if (vertex_locations != null && fragment_locations != null) {
|
||||
// for (int i = 0; i < state->vertex_shader->impl.constantsSize; i++) {
|
||||
// kinc_internal_shader_constant_t *constant = state->vertex_shader->impl.constants[i];
|
||||
// vertex_location[i].impl.vertexOffset = constant->offset;
|
||||
// vertex_location[i].impl.vertexSize = constant->size;
|
||||
// vertex_location[i].impl.vertexColumns = constant->columns;
|
||||
// vertex_location[i].impl.vertexRows = constant->rows;
|
||||
// vertex_sizes[i] = constant->size;
|
||||
// }
|
||||
|
||||
// for (int i = 0; i < state->fragment_shader->impl.constantsSize; i++) {
|
||||
// kinc_internal_shader_constant_t *constant = state->fragment_shader->impl.constants[i];
|
||||
// fragment_location[i].impl.vertexOffset = constant->offset;
|
||||
// fragment_location[i].impl.vertexSize = constant->size;
|
||||
// fragment_location[i].impl.vertexColumns = constant->columns;
|
||||
// fragment_location[i].impl.vertexRows = constant->rows;
|
||||
// fragment_sizes[i] = constant->size;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(struct kinc_g4_pipeline *state, const char *name) {
|
||||
kinc_g4_constant_location_t location;
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
|
||||
|
||||
kinc_internal_shader_constant_t *constant = findConstant(state->vertex_shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.vertexOffset = 0;
|
||||
location.impl.vertexSize = 0;
|
||||
location.impl.vertexColumns = 0;
|
||||
location.impl.vertexRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.vertexOffset = constant->offset;
|
||||
location.impl.vertexSize = constant->size;
|
||||
location.impl.vertexColumns = constant->columns;
|
||||
location.impl.vertexRows = constant->rows;
|
||||
}
|
||||
|
||||
constant = findConstant(state->fragment_shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.fragmentOffset = 0;
|
||||
location.impl.fragmentSize = 0;
|
||||
location.impl.fragmentColumns = 0;
|
||||
location.impl.fragmentRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.fragmentOffset = constant->offset;
|
||||
location.impl.fragmentSize = constant->size;
|
||||
location.impl.fragmentColumns = constant->columns;
|
||||
location.impl.fragmentRows = constant->rows;
|
||||
}
|
||||
|
||||
constant = state->geometry_shader == NULL ? NULL : findConstant(state->geometry_shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.geometryOffset = 0;
|
||||
location.impl.geometrySize = 0;
|
||||
location.impl.geometryColumns = 0;
|
||||
location.impl.geometryRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.geometryOffset = constant->offset;
|
||||
location.impl.geometrySize = constant->size;
|
||||
location.impl.geometryColumns = constant->columns;
|
||||
location.impl.geometryRows = constant->rows;
|
||||
}
|
||||
|
||||
constant = state->tessellation_control_shader == NULL ? NULL : findConstant(state->tessellation_control_shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.tessControlOffset = 0;
|
||||
location.impl.tessControlSize = 0;
|
||||
location.impl.tessControlColumns = 0;
|
||||
location.impl.tessControlRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.tessControlOffset = constant->offset;
|
||||
location.impl.tessControlSize = constant->size;
|
||||
location.impl.tessControlColumns = constant->columns;
|
||||
location.impl.tessControlRows = constant->rows;
|
||||
}
|
||||
|
||||
constant = state->tessellation_evaluation_shader == NULL ? NULL : findConstant(state->tessellation_evaluation_shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.tessEvalOffset = 0;
|
||||
location.impl.tessEvalSize = 0;
|
||||
location.impl.tessEvalColumns = 0;
|
||||
location.impl.tessEvalRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.tessEvalOffset = constant->offset;
|
||||
location.impl.tessEvalSize = constant->size;
|
||||
location.impl.tessEvalColumns = constant->columns;
|
||||
location.impl.tessEvalRows = constant->rows;
|
||||
}
|
||||
|
||||
if (location.impl.vertexSize == 0 && location.impl.fragmentSize == 0 && location.impl.geometrySize == 0 && location.impl.tessControlSize == 0 &&
|
||||
location.impl.tessEvalSize == 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(struct kinc_g4_pipeline *state, const char *name) {
|
||||
char unitName[64];
|
||||
int unitOffset = 0;
|
||||
size_t len = strlen(name);
|
||||
if (len > 63)
|
||||
len = 63;
|
||||
strncpy(unitName, name, len + 1);
|
||||
if (unitName[len - 1] == ']') { // Check for array - mySampler[2]
|
||||
unitOffset = (int)(unitName[len - 2] - '0'); // Array index is unit offset
|
||||
unitName[len - 3] = 0; // Strip array from name
|
||||
}
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)unitName);
|
||||
|
||||
kinc_g4_texture_unit_t unit;
|
||||
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
|
||||
unit.stages[i] = -1;
|
||||
}
|
||||
|
||||
kinc_internal_hash_index_t *fragmentUnit = findTextureUnit(state->fragment_shader->impl.textures, hash);
|
||||
if (fragmentUnit != NULL) {
|
||||
unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] = fragmentUnit->index + unitOffset;
|
||||
}
|
||||
|
||||
kinc_internal_hash_index_t *vertexUnit = findTextureUnit(state->vertex_shader->impl.textures, hash);
|
||||
if (vertexUnit != NULL) {
|
||||
unit.stages[KINC_G4_SHADER_TYPE_VERTEX] = vertexUnit->index + unitOffset;
|
||||
}
|
||||
|
||||
return unit;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char stringCache[1024];
|
||||
static int stringCacheIndex = 0;
|
||||
|
||||
static void setVertexDesc(D3D11_INPUT_ELEMENT_DESC *vertexDesc, int attributeIndex, int index, int stream, bool instanced, int subindex) {
|
||||
if (subindex < 0) {
|
||||
vertexDesc->SemanticName = "TEXCOORD";
|
||||
vertexDesc->SemanticIndex = attributeIndex;
|
||||
}
|
||||
else {
|
||||
// SPIRV_CROSS uses TEXCOORD_0_0,... for split up matrices
|
||||
int stringStart = stringCacheIndex;
|
||||
strcpy(&stringCache[stringCacheIndex], "TEXCOORD");
|
||||
stringCacheIndex += (int)strlen("TEXCOORD");
|
||||
sprintf(&stringCache[stringCacheIndex], "%i", attributeIndex);
|
||||
stringCacheIndex += (int)strlen(&stringCache[stringCacheIndex]);
|
||||
strcpy(&stringCache[stringCacheIndex], "_");
|
||||
stringCacheIndex += 2;
|
||||
vertexDesc->SemanticName = &stringCache[stringStart];
|
||||
vertexDesc->SemanticIndex = subindex;
|
||||
}
|
||||
vertexDesc->InputSlot = stream;
|
||||
vertexDesc->AlignedByteOffset = (index == 0) ? 0 : D3D11_APPEND_ALIGNED_ELEMENT;
|
||||
vertexDesc->InputSlotClass = instanced ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
|
||||
vertexDesc->InstanceDataStepRate = instanced ? 1 : 0;
|
||||
}
|
||||
|
||||
#define usedCount 32
|
||||
|
||||
static int getAttributeLocation(kinc_internal_hash_index_t *attributes, const char *name, bool *used) {
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
|
||||
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (attributes[i].hash == hash) {
|
||||
return attributes[i].index;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < usedCount; ++i) {
|
||||
if (!used[i]) {
|
||||
used[i] = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void createRenderTargetBlendDesc(struct kinc_g4_pipeline *pipe, D3D11_RENDER_TARGET_BLEND_DESC *rtbd, int targetNum) {
|
||||
rtbd->BlendEnable = pipe->blend_source != KINC_G4_BLEND_ONE || pipe->blend_destination != KINC_G4_BLEND_ZERO ||
|
||||
pipe->alpha_blend_source != KINC_G4_BLEND_ONE || pipe->alpha_blend_destination != KINC_G4_BLEND_ZERO;
|
||||
rtbd->SrcBlend = convert_blend_factor(pipe->blend_source);
|
||||
rtbd->DestBlend = convert_blend_factor(pipe->blend_destination);
|
||||
rtbd->BlendOp = convert_blend_operation(pipe->blend_operation);
|
||||
rtbd->SrcBlendAlpha = convert_blend_factor(pipe->alpha_blend_source);
|
||||
rtbd->DestBlendAlpha = convert_blend_factor(pipe->alpha_blend_destination);
|
||||
rtbd->BlendOpAlpha = convert_blend_operation(pipe->alpha_blend_operation);
|
||||
rtbd->RenderTargetWriteMask = (((pipe->color_write_mask_red[targetNum] ? D3D11_COLOR_WRITE_ENABLE_RED : 0) |
|
||||
(pipe->color_write_mask_green[targetNum] ? D3D11_COLOR_WRITE_ENABLE_GREEN : 0)) |
|
||||
(pipe->color_write_mask_blue[targetNum] ? D3D11_COLOR_WRITE_ENABLE_BLUE : 0)) |
|
||||
(pipe->color_write_mask_alpha[targetNum] ? D3D11_COLOR_WRITE_ENABLE_ALPHA : 0);
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_compile(struct kinc_g4_pipeline *state) {
|
||||
#ifndef KINC_KONG
|
||||
if (state->vertex_shader->impl.constantsSize > 0) {
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(state->vertex_shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.vertexConstantBuffer));
|
||||
}
|
||||
if (state->fragment_shader->impl.constantsSize > 0) {
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(state->fragment_shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.fragmentConstantBuffer));
|
||||
}
|
||||
if (state->geometry_shader != NULL && state->geometry_shader->impl.constantsSize > 0) {
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(state->geometry_shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.geometryConstantBuffer));
|
||||
}
|
||||
if (state->tessellation_control_shader != NULL && state->tessellation_control_shader->impl.constantsSize > 0) {
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(state->tessellation_control_shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.tessControlConstantBuffer));
|
||||
}
|
||||
if (state->tessellation_evaluation_shader != NULL && state->tessellation_evaluation_shader->impl.constantsSize > 0) {
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(state->tessellation_evaluation_shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.tessEvalConstantBuffer));
|
||||
}
|
||||
#endif
|
||||
|
||||
int all = 0;
|
||||
for (int stream = 0; state->input_layout[stream] != NULL; ++stream) {
|
||||
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
|
||||
if (state->input_layout[stream]->elements[index].data == KINC_G4_VERTEX_DATA_F32_4X4) {
|
||||
all += 4;
|
||||
}
|
||||
else {
|
||||
all += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
bool used[usedCount];
|
||||
for (int i = 0; i < usedCount; ++i)
|
||||
used[i] = false;
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
used[state->vertex_shader->impl.attributes[i].index] = true;
|
||||
}
|
||||
#endif
|
||||
stringCacheIndex = 0;
|
||||
D3D11_INPUT_ELEMENT_DESC *vertexDesc = (D3D11_INPUT_ELEMENT_DESC *)alloca(sizeof(D3D11_INPUT_ELEMENT_DESC) * all);
|
||||
|
||||
#ifdef KINC_KONG
|
||||
#define getAttributeLocation(a, b, c) index
|
||||
#endif
|
||||
|
||||
int i = 0;
|
||||
for (int stream = 0; state->input_layout[stream] != NULL; ++stream) {
|
||||
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
|
||||
switch (state->input_layout[stream]->elements[index].data) {
|
||||
case KINC_G4_VERTEX_DATA_F32_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32_FLOAT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32_FLOAT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_3X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_3X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_3X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X4: {
|
||||
char name[101];
|
||||
strcpy(name, state->input_layout[stream]->elements[index].name);
|
||||
strcat(name, "_");
|
||||
size_t length = strlen(name);
|
||||
sprintf(&name[length], "%i", 0);
|
||||
name[length + 1] = 0;
|
||||
int attributeLocation = getAttributeLocation(state->vertex_shader->impl.attributes, name, used);
|
||||
|
||||
for (int i2 = 0; i2 < 4; ++i2) {
|
||||
setVertexDesc(&vertexDesc[i], attributeLocation, index + i2, stream, state->input_layout[stream]->instanced, i2);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateInputLayout(dx_ctx.device, vertexDesc, all, state->vertex_shader->impl.data,
|
||||
state->vertex_shader->impl.length, &state->impl.d3d11inputLayout));
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_DESC desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
desc.DepthEnable = state->depth_mode != KINC_G4_COMPARE_ALWAYS;
|
||||
desc.DepthWriteMask = state->depth_write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
desc.DepthFunc = get_comparison(state->depth_mode);
|
||||
|
||||
desc.StencilEnable = state->stencil_front_mode != KINC_G4_COMPARE_ALWAYS || state->stencil_back_mode != KINC_G4_COMPARE_ALWAYS ||
|
||||
state->stencil_front_both_pass != KINC_G4_STENCIL_KEEP || state->stencil_back_both_pass != KINC_G4_STENCIL_KEEP ||
|
||||
state->stencil_front_depth_fail != KINC_G4_STENCIL_KEEP || state->stencil_back_depth_fail != KINC_G4_STENCIL_KEEP ||
|
||||
state->stencil_front_fail != KINC_G4_STENCIL_KEEP || state->stencil_back_fail != KINC_G4_STENCIL_KEEP;
|
||||
desc.StencilReadMask = state->stencil_read_mask;
|
||||
desc.StencilWriteMask = state->stencil_write_mask;
|
||||
desc.FrontFace.StencilFunc = desc.BackFace.StencilFunc = get_comparison(state->stencil_front_mode);
|
||||
desc.FrontFace.StencilDepthFailOp = desc.BackFace.StencilDepthFailOp = get_stencil_action(state->stencil_front_depth_fail);
|
||||
desc.FrontFace.StencilPassOp = desc.BackFace.StencilPassOp = get_stencil_action(state->stencil_front_both_pass);
|
||||
desc.FrontFace.StencilFailOp = desc.BackFace.StencilFailOp = get_stencil_action(state->stencil_front_fail);
|
||||
desc.BackFace.StencilFunc = desc.BackFace.StencilFunc = get_comparison(state->stencil_back_mode);
|
||||
desc.BackFace.StencilDepthFailOp = desc.BackFace.StencilDepthFailOp = get_stencil_action(state->stencil_back_depth_fail);
|
||||
desc.BackFace.StencilPassOp = desc.BackFace.StencilPassOp = get_stencil_action(state->stencil_back_both_pass);
|
||||
desc.BackFace.StencilFailOp = desc.BackFace.StencilFailOp = get_stencil_action(state->stencil_back_fail);
|
||||
|
||||
dx_ctx.device->lpVtbl->CreateDepthStencilState(dx_ctx.device, &desc, &state->impl.depthStencilState);
|
||||
}
|
||||
|
||||
{
|
||||
D3D11_RASTERIZER_DESC rasterDesc;
|
||||
rasterDesc.CullMode = convert_cull_mode(state->cull_mode);
|
||||
rasterDesc.FillMode = D3D11_FILL_SOLID;
|
||||
rasterDesc.FrontCounterClockwise = TRUE;
|
||||
rasterDesc.DepthBias = 0;
|
||||
rasterDesc.SlopeScaledDepthBias = 0.0f;
|
||||
rasterDesc.DepthBiasClamp = 0.0f;
|
||||
rasterDesc.DepthClipEnable = TRUE;
|
||||
rasterDesc.ScissorEnable = FALSE;
|
||||
rasterDesc.MultisampleEnable = FALSE;
|
||||
rasterDesc.AntialiasedLineEnable = FALSE;
|
||||
|
||||
dx_ctx.device->lpVtbl->CreateRasterizerState(dx_ctx.device, &rasterDesc, &state->impl.rasterizerState);
|
||||
rasterDesc.ScissorEnable = TRUE;
|
||||
dx_ctx.device->lpVtbl->CreateRasterizerState(dx_ctx.device, &rasterDesc, &state->impl.rasterizerStateScissor);
|
||||
|
||||
// We need d3d11_3 for conservative raster
|
||||
// D3D11_RASTERIZER_DESC2 rasterDesc;
|
||||
// rasterDesc.ConservativeRaster = conservativeRasterization ? D3D11_CONSERVATIVE_RASTERIZATION_MODE_ON : D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
// dx_ctx.device->CreateRasterizerState2(&rasterDesc, &rasterizerState);
|
||||
// rasterDesc.ScissorEnable = TRUE;
|
||||
// dx_ctx.device->CreateRasterizerState2(&rasterDesc, &rasterizerStateScissor);
|
||||
}
|
||||
|
||||
{
|
||||
bool independentBlend = false;
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
if (state->color_write_mask_red[0] != state->color_write_mask_red[i] || state->color_write_mask_green[0] != state->color_write_mask_green[i] ||
|
||||
state->color_write_mask_blue[0] != state->color_write_mask_blue[i] || state->color_write_mask_alpha[0] != state->color_write_mask_alpha[i]) {
|
||||
independentBlend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_BLEND_DESC blendDesc;
|
||||
memset(&blendDesc, 0, sizeof(blendDesc));
|
||||
blendDesc.AlphaToCoverageEnable = false;
|
||||
blendDesc.IndependentBlendEnable = independentBlend;
|
||||
|
||||
D3D11_RENDER_TARGET_BLEND_DESC rtbd[8];
|
||||
memset(&rtbd, 0, sizeof(rtbd));
|
||||
createRenderTargetBlendDesc(state, &rtbd[0], 0);
|
||||
blendDesc.RenderTarget[0] = rtbd[0];
|
||||
if (independentBlend) {
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
createRenderTargetBlendDesc(state, &rtbd[i], i);
|
||||
blendDesc.RenderTarget[i] = rtbd[i];
|
||||
}
|
||||
}
|
||||
|
||||
dx_ctx.device->lpVtbl->CreateBlendState(dx_ctx.device, &blendDesc, &state->impl.blendState);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11InputLayout;
|
||||
struct ID3D11PixelShader;
|
||||
struct ID3D11VertexShader;
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11DepthStencilState;
|
||||
struct ID3D11RasterizerState;
|
||||
struct ID3D11BlendState;
|
||||
|
||||
typedef struct {
|
||||
// PipelineStateImpl();
|
||||
//~PipelineStateImpl();
|
||||
struct ID3D11InputLayout *d3d11inputLayout;
|
||||
struct ID3D11Buffer *fragmentConstantBuffer;
|
||||
struct ID3D11Buffer *vertexConstantBuffer;
|
||||
struct ID3D11Buffer *geometryConstantBuffer;
|
||||
struct ID3D11Buffer *tessEvalConstantBuffer;
|
||||
struct ID3D11Buffer *tessControlConstantBuffer;
|
||||
struct ID3D11DepthStencilState *depthStencilState;
|
||||
struct ID3D11RasterizerState *rasterizerState;
|
||||
struct ID3D11RasterizerState *rasterizerStateScissor;
|
||||
struct ID3D11BlendState *blendState;
|
||||
// void set(Graphics4::PipelineState* pipeline, bool scissoring);
|
||||
// void setRasterizerState(bool scissoring);
|
||||
// static void setConstants();
|
||||
} kinc_g4_pipeline_impl_t;
|
||||
|
||||
void kinc_internal_set_constants(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,468 @@
|
||||
#include <kinc/error.h>
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
static DXGI_FORMAT convertRenderTargetFormat(kinc_g4_render_target_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
static int formatRenderTargetByteSize(kinc_g4_render_target_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
return 16;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
return 8;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
return 4;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
return 2;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
return 1;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->isCubeMap = false;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
renderTarget->texWidth = renderTarget->width = width;
|
||||
renderTarget->texHeight = renderTarget->height = height;
|
||||
renderTarget->impl.format = format;
|
||||
renderTarget->impl.textureStaging = NULL;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.MipLevels = desc.ArraySize = 1;
|
||||
desc.Format = convertRenderTargetFormat(format);
|
||||
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
|
||||
renderTarget->isDepthAttachment = true;
|
||||
depthBufferBits = 16;
|
||||
stencilBufferBits = 0;
|
||||
}
|
||||
|
||||
bool antialiasing = samples_per_pixel > 1;
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = samples_per_pixel;
|
||||
desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
}
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
renderTarget->impl.textureRender = NULL;
|
||||
renderTarget->impl.textureSample = NULL;
|
||||
renderTarget->impl.renderTargetSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.renderTargetViewRender[i] = NULL;
|
||||
renderTarget->impl.renderTargetViewSample[i] = NULL;
|
||||
}
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureRender));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = antialiasing ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
renderTargetViewDesc.Texture2D.MipSlice = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureRender,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewRender[0]));
|
||||
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureSample));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
renderTargetViewDesc.Texture2D.MipSlice = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewSample[0]));
|
||||
}
|
||||
else {
|
||||
renderTarget->impl.textureSample = renderTarget->impl.textureRender;
|
||||
renderTarget->impl.renderTargetViewSample[0] = renderTarget->impl.renderTargetViewRender[0];
|
||||
}
|
||||
}
|
||||
|
||||
renderTarget->impl.depthStencil = NULL;
|
||||
renderTarget->impl.depthStencilSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.depthStencilView[i] = NULL;
|
||||
}
|
||||
|
||||
DXGI_FORMAT depthFormat;
|
||||
DXGI_FORMAT depthViewFormat;
|
||||
DXGI_FORMAT depthResourceFormat;
|
||||
if (depthBufferBits == 16 && stencilBufferBits == 0) {
|
||||
depthFormat = DXGI_FORMAT_R16_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D16_UNORM;
|
||||
depthResourceFormat = DXGI_FORMAT_R16_UNORM;
|
||||
}
|
||||
else {
|
||||
depthFormat = DXGI_FORMAT_R24G8_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
depthResourceFormat = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
D3D11_TEXTURE2D_DESC depthStencilDesc;
|
||||
depthStencilDesc.Format = depthFormat;
|
||||
depthStencilDesc.Width = width;
|
||||
depthStencilDesc.Height = height;
|
||||
depthStencilDesc.ArraySize = 1;
|
||||
depthStencilDesc.MipLevels = 1;
|
||||
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
|
||||
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
depthStencilDesc.CPUAccessFlags = 0;
|
||||
depthStencilDesc.MiscFlags = 0;
|
||||
if (antialiasing) {
|
||||
depthStencilDesc.SampleDesc.Count = 4;
|
||||
depthStencilDesc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
depthStencilDesc.SampleDesc.Count = 1;
|
||||
depthStencilDesc.SampleDesc.Quality = 0;
|
||||
}
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &depthStencilDesc, NULL, &renderTarget->impl.depthStencil));
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC viewDesc;
|
||||
viewDesc.Format = depthViewFormat;
|
||||
viewDesc.ViewDimension = antialiasing ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
viewDesc.Flags = 0;
|
||||
if (!antialiasing) {
|
||||
viewDesc.Texture2D.MipSlice = 0;
|
||||
}
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDepthStencilView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil, &viewDesc,
|
||||
&renderTarget->impl.depthStencilView[0]));
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
shaderResourceViewDesc.Format = desc.Format;
|
||||
shaderResourceViewDesc.ViewDimension = antialiasing ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.Texture2D.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.renderTargetSRV));
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
shaderResourceViewDesc.Format = depthResourceFormat;
|
||||
shaderResourceViewDesc.ViewDimension = antialiasing ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.Texture2D.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.depthStencilSRV));
|
||||
}
|
||||
|
||||
if (renderTarget->impl.renderTargetViewRender[0] != NULL) {
|
||||
FLOAT colors[4] = {0, 0, 0, 0};
|
||||
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, renderTarget->impl.renderTargetViewRender[0], colors);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->width = cubeMapSize;
|
||||
renderTarget->height = cubeMapSize;
|
||||
renderTarget->isCubeMap = true;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
|
||||
renderTarget->texWidth = renderTarget->width;
|
||||
renderTarget->texHeight = renderTarget->height;
|
||||
renderTarget->impl.format = format;
|
||||
renderTarget->impl.textureStaging = NULL;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = renderTarget->width;
|
||||
desc.Height = renderTarget->height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 6;
|
||||
desc.Format = convertRenderTargetFormat(format);
|
||||
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
|
||||
renderTarget->isDepthAttachment = true;
|
||||
depthBufferBits = 16;
|
||||
stencilBufferBits = 0;
|
||||
}
|
||||
|
||||
bool antialiasing = samples_per_pixel > 1;
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = samples_per_pixel;
|
||||
desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
}
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
|
||||
|
||||
renderTarget->impl.textureRender = NULL;
|
||||
renderTarget->impl.textureSample = NULL;
|
||||
renderTarget->impl.renderTargetSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.renderTargetViewRender[i] = NULL;
|
||||
renderTarget->impl.renderTargetViewSample[i] = NULL;
|
||||
}
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureRender));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
renderTargetViewDesc.Texture2DArray.MipSlice = 0;
|
||||
renderTargetViewDesc.Texture2DArray.ArraySize = 1;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTargetViewDesc.Texture2DArray.FirstArraySlice = i;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureRender,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewRender[i]));
|
||||
}
|
||||
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureSample));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
renderTargetViewDesc.Texture2D.MipSlice = 0;
|
||||
renderTargetViewDesc.Texture2DArray.ArraySize = 1;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTargetViewDesc.Texture2DArray.FirstArraySlice = i;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewSample[i]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
renderTarget->impl.textureSample = renderTarget->impl.textureRender;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.renderTargetViewSample[i] = renderTarget->impl.renderTargetViewRender[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderTarget->impl.depthStencil = NULL;
|
||||
renderTarget->impl.depthStencilSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.depthStencilView[i] = NULL;
|
||||
}
|
||||
|
||||
DXGI_FORMAT depthFormat;
|
||||
DXGI_FORMAT depthViewFormat;
|
||||
DXGI_FORMAT depthResourceFormat;
|
||||
if (depthBufferBits == 16 && stencilBufferBits == 0) {
|
||||
depthFormat = DXGI_FORMAT_R16_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D16_UNORM;
|
||||
depthResourceFormat = DXGI_FORMAT_R16_UNORM;
|
||||
}
|
||||
else {
|
||||
depthFormat = DXGI_FORMAT_R24G8_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
depthResourceFormat = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
D3D11_TEXTURE2D_DESC depthStencilDesc;
|
||||
depthStencilDesc.Format = depthFormat;
|
||||
depthStencilDesc.Width = renderTarget->width;
|
||||
depthStencilDesc.Height = renderTarget->height;
|
||||
depthStencilDesc.ArraySize = 1;
|
||||
depthStencilDesc.MipLevels = 1;
|
||||
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
|
||||
depthStencilDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
|
||||
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
depthStencilDesc.CPUAccessFlags = 0;
|
||||
depthStencilDesc.ArraySize = 6;
|
||||
if (antialiasing) {
|
||||
depthStencilDesc.SampleDesc.Count = 4;
|
||||
depthStencilDesc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
depthStencilDesc.SampleDesc.Count = 1;
|
||||
depthStencilDesc.SampleDesc.Quality = 0;
|
||||
}
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &depthStencilDesc, NULL, &renderTarget->impl.depthStencil));
|
||||
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
|
||||
depthStencilViewDesc.Format = depthViewFormat;
|
||||
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
depthStencilViewDesc.Texture2DArray.MipSlice = 0;
|
||||
depthStencilViewDesc.Texture2DArray.ArraySize = 1;
|
||||
depthStencilViewDesc.Flags = 0;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
depthStencilViewDesc.Texture2DArray.FirstArraySlice = i;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDepthStencilView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
|
||||
&depthStencilViewDesc, &renderTarget->impl.depthStencilView[i]));
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
shaderResourceViewDesc.Format = desc.Format;
|
||||
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
shaderResourceViewDesc.TextureCube.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.TextureCube.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.renderTargetSRV));
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
shaderResourceViewDesc.Format = depthResourceFormat;
|
||||
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
shaderResourceViewDesc.TextureCube.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.TextureCube.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.depthStencilSRV));
|
||||
}
|
||||
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
FLOAT colors[4] = {0, 0, 0, 0};
|
||||
for (int i = 0; i < 6; i++) {
|
||||
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, renderTarget->impl.renderTargetViewRender[i], colors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (renderTarget->impl.renderTargetViewRender[i] != NULL)
|
||||
renderTarget->impl.renderTargetViewRender[i]->lpVtbl->Release(renderTarget->impl.renderTargetViewRender[i]);
|
||||
if (renderTarget->impl.renderTargetViewSample[i] != NULL &&
|
||||
renderTarget->impl.renderTargetViewSample[i] != renderTarget->impl.renderTargetViewRender[i])
|
||||
renderTarget->impl.renderTargetViewSample[i]->lpVtbl->Release(renderTarget->impl.renderTargetViewSample[i]);
|
||||
if (renderTarget->impl.depthStencilView[i] != NULL)
|
||||
renderTarget->impl.depthStencilView[i]->lpVtbl->Release(renderTarget->impl.depthStencilView[i]);
|
||||
}
|
||||
if (renderTarget->impl.renderTargetSRV != NULL)
|
||||
renderTarget->impl.renderTargetSRV->lpVtbl->Release(renderTarget->impl.renderTargetSRV);
|
||||
if (renderTarget->impl.depthStencilSRV != NULL)
|
||||
renderTarget->impl.depthStencilSRV->lpVtbl->Release(renderTarget->impl.depthStencilSRV);
|
||||
if (renderTarget->impl.depthStencil != NULL)
|
||||
renderTarget->impl.depthStencil->lpVtbl->Release(renderTarget->impl.depthStencil);
|
||||
if (renderTarget->impl.textureRender != NULL)
|
||||
renderTarget->impl.textureRender->lpVtbl->Release(renderTarget->impl.textureRender);
|
||||
if (renderTarget->impl.textureStaging != NULL)
|
||||
renderTarget->impl.textureStaging->lpVtbl->Release(renderTarget->impl.textureStaging);
|
||||
if (renderTarget->impl.textureSample != NULL && renderTarget->impl.textureSample != renderTarget->impl.textureRender)
|
||||
renderTarget->impl.textureSample->lpVtbl->Release(renderTarget->impl.textureSample);
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, uint32_t unit) {
|
||||
if (renderTarget->impl.textureSample != renderTarget->impl.textureRender) {
|
||||
dx_ctx.context->lpVtbl->ResolveSubresource(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureSample, 0,
|
||||
(ID3D11Resource *)renderTarget->impl.textureRender, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
}
|
||||
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit, 1,
|
||||
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV : &renderTarget->impl.renderTargetSRV);
|
||||
}
|
||||
#else
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0 && unit.stages[KINC_G4_SHADER_TYPE_VERTEX] < 0)
|
||||
return;
|
||||
|
||||
if (renderTarget->impl.textureSample != renderTarget->impl.textureRender) {
|
||||
dx_ctx.context->lpVtbl->ResolveSubresource(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureSample, 0,
|
||||
(ID3D11Resource *)renderTarget->impl.textureRender, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
|
||||
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1,
|
||||
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV
|
||||
: &renderTarget->impl.renderTargetSRV);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1,
|
||||
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV
|
||||
: &renderTarget->impl.renderTargetSRV);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
|
||||
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1, &renderTarget->impl.depthStencilSRV);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &renderTarget->impl.depthStencilSRV);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source) {
|
||||
renderTarget->impl.depthStencil = source->impl.depthStencil;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.depthStencilView[i] = source->impl.depthStencilView[i];
|
||||
}
|
||||
renderTarget->impl.depthStencilSRV = source->impl.depthStencilSRV;
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *renderTarget, uint8_t *data) {
|
||||
if (renderTarget->impl.textureStaging == NULL) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = renderTarget->texWidth;
|
||||
desc.Height = renderTarget->texHeight;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = convertRenderTargetFormat((kinc_g4_render_target_format_t)renderTarget->impl.format);
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.BindFlags = 0;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.MiscFlags = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureStaging));
|
||||
}
|
||||
|
||||
D3D11_BOX sourceRegion;
|
||||
sourceRegion.left = 0;
|
||||
sourceRegion.right = renderTarget->texWidth;
|
||||
sourceRegion.top = 0;
|
||||
sourceRegion.bottom = renderTarget->texHeight;
|
||||
sourceRegion.front = 0;
|
||||
sourceRegion.back = 1;
|
||||
dx_ctx.context->lpVtbl->CopySubresourceRegion(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0, 0, 0, 0,
|
||||
(ID3D11Resource *)renderTarget->impl.textureRender, 0, &sourceRegion);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0, D3D11_MAP_READ, 0, &mappedResource);
|
||||
int size;
|
||||
if (mappedResource.RowPitch != 0) {
|
||||
size = mappedResource.RowPitch * renderTarget->texHeight;
|
||||
}
|
||||
else {
|
||||
size = renderTarget->texWidth * renderTarget->texHeight * formatRenderTargetByteSize((kinc_g4_render_target_format_t)renderTarget->impl.format);
|
||||
}
|
||||
memcpy(data, mappedResource.pData, size);
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *renderTarget, int levels) {}
|
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11RenderTargetView;
|
||||
struct ID3D11DepthStencilView;
|
||||
struct ID3D11ShaderResourceView;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Texture2D *textureRender;
|
||||
struct ID3D11Texture2D *textureSample;
|
||||
struct ID3D11Texture2D *textureStaging;
|
||||
struct ID3D11RenderTargetView *renderTargetViewRender[6];
|
||||
struct ID3D11RenderTargetView *renderTargetViewSample[6];
|
||||
struct ID3D11Texture2D *depthStencil;
|
||||
struct ID3D11DepthStencilView *depthStencilView[6];
|
||||
struct ID3D11ShaderResourceView *renderTargetSRV;
|
||||
struct ID3D11ShaderResourceView *depthStencilSRV;
|
||||
int format;
|
||||
} kinc_g4_render_target_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,114 @@
|
||||
#include <kinc/graphics4/shader.h>
|
||||
|
||||
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {
|
||||
if (shader->impl.shader != NULL) {
|
||||
((IUnknown *)shader->impl.shader)->lpVtbl->Release(shader->impl.shader);
|
||||
free(shader->impl.data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *_data, size_t length, kinc_g4_shader_type_t type) {
|
||||
unsigned index = 0;
|
||||
uint8_t *data = (uint8_t *)_data;
|
||||
shader->impl.type = (int)type;
|
||||
|
||||
#ifndef KINC_KONG
|
||||
memset(&shader->impl.attributes, 0, sizeof(shader->impl.attributes));
|
||||
int attributesCount = data[index++];
|
||||
for (int i = 0; i < attributesCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.attributes[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.attributes[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.textures, 0, sizeof(shader->impl.textures));
|
||||
uint8_t texCount = data[index++];
|
||||
for (unsigned i = 0; i < texCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.textures[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.textures[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.constants, 0, sizeof(shader->impl.constants));
|
||||
uint8_t constantCount = data[index++];
|
||||
shader->impl.constantsSize = 0;
|
||||
for (unsigned i = 0; i < constantCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
kinc_internal_shader_constant_t constant;
|
||||
constant.hash = kinc_internal_hash_name(name);
|
||||
constant.offset = *(uint32_t *)&data[index];
|
||||
index += 4;
|
||||
constant.size = *(uint32_t *)&data[index];
|
||||
index += 4;
|
||||
constant.columns = data[index];
|
||||
index += 1;
|
||||
constant.rows = data[index];
|
||||
index += 1;
|
||||
|
||||
shader->impl.constants[i] = constant;
|
||||
shader->impl.constantsSize = constant.offset + constant.size;
|
||||
}
|
||||
#endif
|
||||
|
||||
shader->impl.length = (int)(length - index);
|
||||
shader->impl.data = (uint8_t *)malloc(shader->impl.length);
|
||||
assert(shader->impl.data != NULL);
|
||||
memcpy(shader->impl.data, &data[index], shader->impl.length);
|
||||
|
||||
switch (type) {
|
||||
case KINC_G4_SHADER_TYPE_VERTEX:
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateVertexShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
|
||||
(ID3D11VertexShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_FRAGMENT:
|
||||
kinc_microsoft_affirm(
|
||||
dx_ctx.device->lpVtbl->CreatePixelShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11PixelShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_GEOMETRY:
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateGeometryShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
|
||||
(ID3D11GeometryShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL:
|
||||
kinc_microsoft_affirm(
|
||||
dx_ctx.device->lpVtbl->CreateHullShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11HullShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION:
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDomainShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
|
||||
(ID3D11DomainShader **)&shader->impl.shader));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
extern int krafix_compile(const char *source, char *output, int *length, const char *targetlang, const char *system, const char *shadertype, int version);
|
||||
#endif
|
||||
|
||||
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
char *output = malloc(1024 * 1024);
|
||||
int length;
|
||||
int errors = krafix_compile(source, output, &length, "d3d11", "windows", type == KINC_G4_SHADER_TYPE_FRAGMENT ? "frag" : "vert", -1);
|
||||
if (errors > 0) {
|
||||
return errors;
|
||||
}
|
||||
kinc_g4_shader_init(shader, output, length, type);
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <kinc/backend/graphics4/ShaderHash.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t hash;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
uint8_t columns;
|
||||
uint8_t rows;
|
||||
} kinc_internal_shader_constant_t;
|
||||
|
||||
typedef struct {
|
||||
#ifndef KINC_KONG
|
||||
kinc_internal_shader_constant_t constants[64];
|
||||
int constantsSize;
|
||||
kinc_internal_hash_index_t attributes[64];
|
||||
kinc_internal_hash_index_t textures[64];
|
||||
#endif
|
||||
void *shader;
|
||||
uint8_t *data;
|
||||
int length;
|
||||
int type;
|
||||
} kinc_g4_shader_impl_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t vertexOffset;
|
||||
uint32_t vertexSize;
|
||||
uint32_t fragmentOffset;
|
||||
uint32_t fragmentSize;
|
||||
uint32_t geometryOffset;
|
||||
uint32_t geometrySize;
|
||||
uint32_t tessEvalOffset;
|
||||
uint32_t tessEvalSize;
|
||||
uint32_t tessControlOffset;
|
||||
uint32_t tessControlSize;
|
||||
uint8_t vertexColumns;
|
||||
uint8_t vertexRows;
|
||||
uint8_t fragmentColumns;
|
||||
uint8_t fragmentRows;
|
||||
uint8_t geometryColumns;
|
||||
uint8_t geometryRows;
|
||||
uint8_t tessEvalColumns;
|
||||
uint8_t tessEvalRows;
|
||||
uint8_t tessControlColumns;
|
||||
uint8_t tessControlRows;
|
||||
} kinc_g4_constant_location_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,353 @@
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/graphics4/textureunit.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static kinc_g4_texture_t *setTextures[16] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
|
||||
static DXGI_FORMAT convertFormat(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_RGB24:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case KINC_IMAGE_FORMAT_BGRA32:
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
default:
|
||||
assert(false);
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
static int formatByteSize(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
return 16;
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
return 8;
|
||||
case KINC_IMAGE_FORMAT_RGB24:
|
||||
return 4;
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
return 4;
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
return 2;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return 1;
|
||||
case KINC_IMAGE_FORMAT_BGRA32:
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
return 4;
|
||||
default:
|
||||
assert(false);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isHdr(kinc_image_format_t format) {
|
||||
return format == KINC_IMAGE_FORMAT_RGBA128 || format == KINC_IMAGE_FORMAT_RGBA64 || format == KINC_IMAGE_FORMAT_A32 || format == KINC_IMAGE_FORMAT_A16;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
|
||||
memset(&texture->impl, 0, sizeof(texture->impl));
|
||||
texture->impl.stage = 0;
|
||||
texture->tex_width = image->width;
|
||||
texture->tex_height = image->height;
|
||||
texture->tex_depth = 1;
|
||||
texture->format = image->format;
|
||||
texture->impl.rowPitch = 0;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = image->width;
|
||||
desc.Height = image->height;
|
||||
desc.MipLevels = desc.ArraySize = 1;
|
||||
desc.Format = convertFormat(image->format);
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA data;
|
||||
data.pSysMem = image->data;
|
||||
data.SysMemPitch = image->width * formatByteSize(image->format);
|
||||
data.SysMemSlicePitch = 0;
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, &data, &texture->impl.texture));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, NULL, &texture->impl.view));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init_from_image3d(kinc_g4_texture_t *texture, kinc_image_t *image) {
|
||||
memset(&texture->impl, 0, sizeof(texture->impl));
|
||||
texture->impl.stage = 0;
|
||||
texture->tex_width = image->width;
|
||||
texture->tex_height = image->height;
|
||||
texture->tex_depth = image->depth;
|
||||
texture->format = image->format;
|
||||
texture->impl.rowPitch = 0;
|
||||
|
||||
D3D11_TEXTURE3D_DESC desc;
|
||||
desc.Width = image->width;
|
||||
desc.Height = image->height;
|
||||
desc.Depth = image->depth;
|
||||
desc.MipLevels = 1;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.MiscFlags = 0;
|
||||
desc.Format = convertFormat(image->format);
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA data;
|
||||
data.pSysMem = image->data;
|
||||
data.SysMemPitch = image->width * formatByteSize(image->format);
|
||||
data.SysMemSlicePitch = image->width * image->height * formatByteSize(image->format);
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture3D(dx_ctx.device, &desc, &data, &texture->impl.texture3D));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D, NULL, &texture->impl.view));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
|
||||
memset(&texture->impl, 0, sizeof(texture->impl));
|
||||
texture->impl.stage = 0;
|
||||
texture->tex_width = width;
|
||||
texture->tex_height = height;
|
||||
texture->tex_depth = 1;
|
||||
texture->format = format;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.MipLevels = desc.ArraySize = 1;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
if (format == KINC_IMAGE_FORMAT_RGBA128) { // for compute
|
||||
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
}
|
||||
else {
|
||||
desc.Format = convertFormat(format);
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &texture->impl.texture));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, NULL, &texture->impl.view));
|
||||
|
||||
if (format == KINC_IMAGE_FORMAT_RGBA128) {
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC du;
|
||||
du.Format = desc.Format;
|
||||
du.Texture2D.MipSlice = 0;
|
||||
du.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
|
||||
kinc_microsoft_affirm(
|
||||
dx_ctx.device->lpVtbl->CreateUnorderedAccessView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, &du, &texture->impl.computeView));
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {
|
||||
memset(&texture->impl, 0, sizeof(texture->impl));
|
||||
texture->impl.stage = 0;
|
||||
texture->tex_width = width;
|
||||
texture->tex_height = height;
|
||||
texture->tex_depth = depth;
|
||||
texture->format = format;
|
||||
texture->impl.hasMipmaps = true;
|
||||
|
||||
D3D11_TEXTURE3D_DESC desc;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.Depth = depth;
|
||||
desc.MipLevels = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
|
||||
desc.Format = format == KINC_IMAGE_FORMAT_RGBA32 ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_R8_UNORM;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET | D3D11_BIND_UNORDERED_ACCESS;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture3D(dx_ctx.device, &desc, NULL, &texture->impl.texture3D));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D, NULL, &texture->impl.view));
|
||||
}
|
||||
|
||||
// TextureImpl::TextureImpl() : hasMipmaps(false), renderView(nullptr), computeView(nullptr) {}
|
||||
|
||||
void kinc_internal_texture_unset(kinc_g4_texture_t *texture);
|
||||
|
||||
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
|
||||
kinc_internal_texture_unset(texture);
|
||||
if (texture->impl.view != NULL) {
|
||||
texture->impl.view->lpVtbl->Release(texture->impl.view);
|
||||
}
|
||||
if (texture->impl.texture != NULL) {
|
||||
texture->impl.texture->lpVtbl->Release(texture->impl.texture);
|
||||
}
|
||||
if (texture->impl.texture3D != NULL) {
|
||||
texture->impl.texture3D->lpVtbl->Release(texture->impl.texture3D);
|
||||
}
|
||||
if (texture->impl.computeView != NULL) {
|
||||
texture->impl.computeView->lpVtbl->Release(texture->impl.computeView);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_texture_unmipmap(kinc_g4_texture_t *texture) {
|
||||
texture->impl.hasMipmaps = false;
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, uint32_t unit) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit, 1, &texture->impl.view);
|
||||
|
||||
texture->impl.stage = unit;
|
||||
setTextures[unit] = texture;
|
||||
}
|
||||
#else
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0 && unit.stages[KINC_G4_SHADER_TYPE_VERTEX] < 0)
|
||||
return;
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
|
||||
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1, &texture->impl.view);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &texture->impl.view);
|
||||
}
|
||||
|
||||
texture->impl.stage = unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0 ? unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] : unit.stages[KINC_G4_SHADER_TYPE_VERTEX];
|
||||
setTextures[texture->impl.stage] = texture;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_internal_texture_set_image(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0)
|
||||
return;
|
||||
|
||||
if (texture->impl.computeView == NULL) {
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC du;
|
||||
du.Format = texture->format == KINC_IMAGE_FORMAT_RGBA32 ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_R8_UNORM;
|
||||
du.Texture3D.MipSlice = 0;
|
||||
du.Texture3D.FirstWSlice = 0;
|
||||
du.Texture3D.WSize = -1;
|
||||
du.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
|
||||
kinc_microsoft_affirm(
|
||||
dx_ctx.device->lpVtbl->CreateUnorderedAccessView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D, &du, &texture->impl.computeView));
|
||||
}
|
||||
dx_ctx.context->lpVtbl->OMSetRenderTargetsAndUnorderedAccessViews(dx_ctx.context, 0, NULL, NULL, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1,
|
||||
&texture->impl.computeView, NULL);
|
||||
}
|
||||
|
||||
void kinc_internal_texture_unset(kinc_g4_texture_t *texture) {
|
||||
if (setTextures[texture->impl.stage] == texture) {
|
||||
|
||||
setTextures[texture->impl.stage] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
kinc_microsoft_affirm(dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource));
|
||||
texture->impl.rowPitch = mappedResource.RowPitch;
|
||||
return (uint8_t *)mappedResource.pData;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, 0);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {
|
||||
if (texture->impl.renderView == NULL) {
|
||||
texture->tex_depth > 1 ? kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D,
|
||||
0, &texture->impl.renderView))
|
||||
: kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, 0,
|
||||
&texture->impl.renderView));
|
||||
}
|
||||
static float clearColor[4];
|
||||
clearColor[0] = ((color & 0x00ff0000) >> 16) / 255.0f;
|
||||
clearColor[1] = ((color & 0x0000ff00) >> 8) / 255.0f;
|
||||
clearColor[2] = (color & 0x000000ff) / 255.0f;
|
||||
clearColor[3] = ((color & 0xff000000) >> 24) / 255.0f;
|
||||
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, texture->impl.renderView, clearColor);
|
||||
}
|
||||
|
||||
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
|
||||
assert(texture->impl.rowPitch != 0); // stride is not yet set, lock and unlock the texture first (or find a good fix for this and send a PR)
|
||||
return texture->impl.rowPitch;
|
||||
}
|
||||
|
||||
static void enableMipmaps(kinc_g4_texture_t *texture, int texWidth, int texHeight, int format) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = texWidth;
|
||||
desc.Height = texHeight;
|
||||
desc.MipLevels = 0;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = convertFormat((kinc_image_format_t)format);
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
|
||||
|
||||
ID3D11Texture2D *mipMappedTexture;
|
||||
ID3D11ShaderResourceView *mipMappedView;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &mipMappedTexture));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)mipMappedTexture, NULL, &mipMappedView));
|
||||
|
||||
D3D11_BOX sourceRegion;
|
||||
sourceRegion.left = 0;
|
||||
sourceRegion.right = texWidth;
|
||||
sourceRegion.top = 0;
|
||||
sourceRegion.bottom = texHeight;
|
||||
sourceRegion.front = 0;
|
||||
sourceRegion.back = 1;
|
||||
dx_ctx.context->lpVtbl->CopySubresourceRegion(dx_ctx.context, (ID3D11Resource *)mipMappedTexture, 0, 0, 0, 0, (ID3D11Resource *)texture->impl.texture, 0,
|
||||
&sourceRegion);
|
||||
|
||||
if (texture->impl.texture != NULL) {
|
||||
texture->impl.texture->lpVtbl->Release(texture->impl.texture);
|
||||
}
|
||||
texture->impl.texture = mipMappedTexture;
|
||||
|
||||
if (texture->impl.view != NULL) {
|
||||
texture->impl.view->lpVtbl->Release(texture->impl.view);
|
||||
}
|
||||
texture->impl.view = mipMappedView;
|
||||
|
||||
texture->impl.hasMipmaps = true;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {
|
||||
if (!texture->impl.hasMipmaps) {
|
||||
enableMipmaps(texture, texture->tex_width, texture->tex_height, texture->format);
|
||||
}
|
||||
dx_ctx.context->lpVtbl->GenerateMips(dx_ctx.context, texture->impl.view);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {
|
||||
if (!texture->impl.hasMipmaps) {
|
||||
enableMipmaps(texture, texture->tex_width, texture->tex_height, texture->format);
|
||||
}
|
||||
D3D11_BOX dstRegion;
|
||||
dstRegion.left = 0;
|
||||
dstRegion.right = mipmap->width;
|
||||
dstRegion.top = 0;
|
||||
dstRegion.bottom = mipmap->height;
|
||||
dstRegion.front = 0;
|
||||
dstRegion.back = 1;
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, level, &dstRegion, mipmap->data,
|
||||
mipmap->width * formatByteSize(mipmap->format), 0);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11Texture3D;
|
||||
struct ID3D11ShaderResourceView;
|
||||
struct ID3D11UnorderedAccessView;
|
||||
struct ID3D11RenderTargetView;
|
||||
|
||||
// TextureImpl();
|
||||
//~TextureImpl();
|
||||
// void enableMipmaps(int texWidth, int texHeight, int format);
|
||||
// void unmipmap();
|
||||
// void unset();
|
||||
|
||||
typedef struct {
|
||||
bool hasMipmaps;
|
||||
int stage;
|
||||
struct ID3D11Texture2D *texture;
|
||||
struct ID3D11Texture3D *texture3D;
|
||||
struct ID3D11ShaderResourceView *view;
|
||||
struct ID3D11UnorderedAccessView *computeView;
|
||||
struct ID3D11RenderTargetView *renderView;
|
||||
int rowPitch;
|
||||
} kinc_g4_texture_impl_t;
|
@ -0,0 +1,39 @@
|
||||
#include <kinc/graphics4/texturearray.h>
|
||||
#include <kinc/graphics4/textureunit.h>
|
||||
|
||||
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = textures[0].width;
|
||||
desc.Height = textures[0].height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 2;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA *resdata = (D3D11_SUBRESOURCE_DATA *)alloca(sizeof(D3D11_SUBRESOURCE_DATA) * count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
resdata[i].pSysMem = textures[i].data;
|
||||
resdata[i].SysMemPitch = textures[0].width * 4;
|
||||
resdata[i].SysMemSlicePitch = 0;
|
||||
}
|
||||
|
||||
array->impl.texture = NULL;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, resdata, &array->impl.texture));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)array->impl.texture, NULL, &array->impl.view));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
|
||||
|
||||
void kinc_internal_texture_array_set(kinc_g4_texture_array_t *array, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0)
|
||||
return;
|
||||
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &array->impl.view);
|
||||
// this->stage = unit.unit;
|
||||
// setTextures[stage] = this;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11ShaderResourceView;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Texture2D *texture;
|
||||
struct ID3D11ShaderResourceView *view;
|
||||
// void set(Kore::Graphics4::TextureUnit unit);
|
||||
} kinc_g4_texture_array_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,95 @@
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
|
||||
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int count, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
|
||||
int instance_data_step_rate) {
|
||||
buffer->impl.count = count;
|
||||
buffer->impl.stride = 0;
|
||||
for (int i = 0; i < structure->size; ++i) {
|
||||
buffer->impl.stride += kinc_g4_vertex_data_size(structure->elements[i].data);
|
||||
}
|
||||
|
||||
if (usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
buffer->impl.vertices = NULL;
|
||||
}
|
||||
else {
|
||||
buffer->impl.vertices = (float *)malloc(buffer->impl.stride * count);
|
||||
}
|
||||
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
|
||||
buffer->impl.usage = usage;
|
||||
switch (usage) {
|
||||
case KINC_G4_USAGE_STATIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
case KINC_G4_USAGE_DYNAMIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
break;
|
||||
case KINC_G4_USAGE_READABLE:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
bufferDesc.ByteWidth = buffer->impl.stride * count;
|
||||
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
bufferDesc.StructureByteStride = 0;
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &bufferDesc, NULL, &buffer->impl.vb));
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
|
||||
buffer->impl.vb->lpVtbl->Release(buffer->impl.vb);
|
||||
free(buffer->impl.vertices);
|
||||
buffer->impl.vertices = NULL;
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return kinc_g4_vertex_buffer_lock(buffer, 0, buffer->impl.count);
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
|
||||
buffer->impl.lockStart = start;
|
||||
buffer->impl.lockCount = count;
|
||||
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
memset(&mappedResource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
float *data = (float *)mappedResource.pData;
|
||||
return &data[start * buffer->impl.stride / 4];
|
||||
}
|
||||
else {
|
||||
return &buffer->impl.vertices[start * buffer->impl.stride / 4];
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
kinc_g4_vertex_buffer_unlock(buffer, buffer->impl.lockCount);
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0);
|
||||
}
|
||||
else {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0, NULL, buffer->impl.vertices, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
|
||||
// UINT stride = myStride;
|
||||
// UINT internaloffset = 0;
|
||||
// dx_ctx.context->IASetVertexBuffers(0, 1, &vb, &stride, &internaloffset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.count;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.stride;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Buffer *vb;
|
||||
int stride;
|
||||
int count;
|
||||
int lockStart;
|
||||
int lockCount;
|
||||
float *vertices;
|
||||
int usage;
|
||||
} kinc_g4_vertex_buffer_impl_t;
|
@ -0,0 +1,66 @@
|
||||
#include <Kinc/Compute/Compute.h>
|
||||
#include <Kinc/Graphics4/RenderTarget.h>
|
||||
#include <Kinc/Graphics4/Texture.h>
|
||||
#include <Kinc/Math/Core.h>
|
||||
|
||||
void kinc_compute_shader_init(kinc_compute_shader_t *shader, void *source, int length) {}
|
||||
|
||||
void kinc_compute_shader_destroy(kinc_compute_shader_t *shader) {}
|
||||
|
||||
kinc_compute_constant_location_t kinc_compute_shader_get_constant_location(kinc_compute_shader_t *shader, const char *name) {
|
||||
kinc_compute_constant_location_t location = {0};
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_compute_texture_unit_t kinc_compute_shader_get_texture_unit(kinc_compute_shader_t *shader, const char *name) {
|
||||
kinc_compute_texture_unit_t unit = {0};
|
||||
return unit;
|
||||
}
|
||||
|
||||
void kinc_compute_set_bool(kinc_compute_constant_location_t location, bool value) {}
|
||||
|
||||
void kinc_compute_set_int(kinc_compute_constant_location_t location, int value) {}
|
||||
|
||||
void kinc_compute_set_float(kinc_compute_constant_location_t location, float value) {}
|
||||
|
||||
void kinc_compute_set_float2(kinc_compute_constant_location_t location, float value1, float value2) {}
|
||||
|
||||
void kinc_compute_set_float3(kinc_compute_constant_location_t location, float value1, float value2, float value3) {}
|
||||
|
||||
void kinc_compute_set_float4(kinc_compute_constant_location_t location, float value1, float value2, float value3, float value4) {}
|
||||
|
||||
void kinc_compute_set_floats(kinc_compute_constant_location_t location, float *values, int count) {}
|
||||
|
||||
void kinc_compute_set_matrix4(kinc_compute_constant_location_t location, kinc_matrix4x4_t *value) {}
|
||||
|
||||
void kinc_compute_set_matrix3(kinc_compute_constant_location_t location, kinc_matrix3x3_t *value) {}
|
||||
|
||||
void kinc_compute_set_texture(kinc_compute_texture_unit_t unit, kinc_g4_texture_t *texture, kinc_compute_access_t access) {}
|
||||
|
||||
void kinc_compute_set_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target, kinc_compute_access_t access) {}
|
||||
|
||||
void kinc_compute_set_sampled_texture(kinc_compute_texture_unit_t unit, kinc_g4_texture_t *texture) {}
|
||||
|
||||
void kinc_compute_set_sampled_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target) {}
|
||||
|
||||
void kinc_compute_set_sampled_depth_from_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target) {}
|
||||
|
||||
void kinc_compute_set_texture_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
|
||||
|
||||
void kinc_compute_set_texture3d_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
|
||||
|
||||
void kinc_compute_set_texture_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_shader(kinc_compute_shader_t *shader) {}
|
||||
|
||||
void kinc_compute(int x, int y, int z) {}
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} kinc_compute_constant_location_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} kinc_compute_texture_unit_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} kinc_compute_internal_shader_constant_t;
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} kinc_compute_shader_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,841 @@
|
||||
#include <kinc/display.h>
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
#undef CreateWindow
|
||||
#include <kinc/system.h>
|
||||
#include <kinc/window.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
#include <kinc/backend/Windows.h>
|
||||
|
||||
#include <kinc/log.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
LPDIRECT3D9 d3d;
|
||||
LPDIRECT3DDEVICE9 device;
|
||||
|
||||
namespace {
|
||||
HWND hWnd;
|
||||
|
||||
int _width;
|
||||
int _height;
|
||||
|
||||
unsigned hz;
|
||||
bool vsync;
|
||||
|
||||
bool resizable;
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
bool swapBuffers() {
|
||||
HRESULT result;
|
||||
if (resizable) {
|
||||
RECT vRect;
|
||||
GetClientRect(hWnd, &vRect);
|
||||
result = device->Present(&vRect, &vRect, 0, 0);
|
||||
}
|
||||
else {
|
||||
result = device->Present(0, 0, 0, 0);
|
||||
}
|
||||
return result != D3DERR_DEVICELOST;
|
||||
}
|
||||
|
||||
kinc_g4_shader_t *pixelShader = nullptr;
|
||||
kinc_g4_shader_t *vertexShader = nullptr;
|
||||
IDirect3DSurface9 *backBuffer = nullptr;
|
||||
IDirect3DSurface9 *depthBuffer = nullptr;
|
||||
|
||||
void initDeviceStates() {
|
||||
D3DCAPS9 caps;
|
||||
device->GetDeviceCaps(&caps);
|
||||
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
// device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
||||
#ifndef USE_SHADER
|
||||
device->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
#endif
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
|
||||
#ifndef USE_SHADER
|
||||
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
||||
kinc_microsoft_affirm(device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE));
|
||||
kinc_microsoft_affirm(device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE));
|
||||
#endif
|
||||
// if (d3dpp.Windowed != TRUE) Cursor->Hide();
|
||||
|
||||
device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
device->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
|
||||
device->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
|
||||
device->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
|
||||
device->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, caps.MaxAnisotropy);
|
||||
}
|
||||
|
||||
device->SetSamplerState(D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
device->SetSamplerState(D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
|
||||
|
||||
device->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
|
||||
device->Clear(0, 0, D3DCLEAR_TARGET, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_internal_destroy_window(int window) {}
|
||||
void kinc_g4_internal_destroy() {}
|
||||
|
||||
extern "C" void kinc_internal_resize(int width, int height) {
|
||||
if (!resizable) {
|
||||
return;
|
||||
}
|
||||
|
||||
_width = width;
|
||||
_height = height;
|
||||
kinc_g4_viewport(0, 0, width, height);
|
||||
/*D3DPRESENT_PARAMETERS d3dpp;
|
||||
ZeroMemory(&d3dpp, sizeof(d3dpp));
|
||||
d3dpp.Windowed = (!fullscreen) ? TRUE : FALSE;
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dpp.BackBufferCount = 2;
|
||||
d3dpp.BackBufferWidth = width;
|
||||
d3dpp.BackBufferHeight = height;
|
||||
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
|
||||
d3dpp.EnableAutoDepthStencil = TRUE;
|
||||
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
|
||||
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; //D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
if (antialiasing()) {
|
||||
if (SUCCEEDED(d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, D3DMULTISAMPLE_4_SAMPLES, nullptr)))
|
||||
d3dpp.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES;
|
||||
if (SUCCEEDED(d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, D3DMULTISAMPLE_8_SAMPLES, nullptr)))
|
||||
d3dpp.MultiSampleType = D3DMULTISAMPLE_8_SAMPLES;
|
||||
}
|
||||
else {
|
||||
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
|
||||
}
|
||||
|
||||
device->Reset(&d3dpp);
|
||||
|
||||
initDeviceStates();*/
|
||||
}
|
||||
|
||||
extern "C" void kinc_internal_change_framebuffer(int window, struct kinc_framebuffer_options *frame) {}
|
||||
|
||||
void kinc_g4_internal_init() {}
|
||||
|
||||
void kinc_g4_internal_init_window(int windowId, int depthBufferBits, int stencilBufferBits, bool vsync) {
|
||||
bool fullscreen = kinc_window_get_mode(windowId) == KINC_WINDOW_MODE_FULLSCREEN || kinc_window_get_mode(windowId) == KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN;
|
||||
|
||||
d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
|
||||
hWnd = kinc_windows_window_handle(windowId);
|
||||
long style = GetWindowLong(hWnd, GWL_STYLE);
|
||||
|
||||
resizable = false;
|
||||
|
||||
if ((style & WS_SIZEBOX) != 0) {
|
||||
resizable = true;
|
||||
}
|
||||
|
||||
if ((style & WS_MAXIMIZEBOX) != 0) {
|
||||
resizable = true;
|
||||
}
|
||||
|
||||
// TODO (DK) just setup the primary window for now and ignore secondaries
|
||||
// -this should probably be implemented via swap chain for real at a later time
|
||||
// -http://www.mvps.org/directx/articles/rendering_to_multiple_windows.htm
|
||||
if (windowId > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
// TODO (DK) convert depthBufferBits + stencilBufferBits to: d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
ZeroMemory(&d3dpp, sizeof(d3dpp));
|
||||
d3dpp.Windowed = (!fullscreen) ? TRUE : FALSE;
|
||||
|
||||
if (resizable) {
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
|
||||
d3dpp.BackBufferCount = 1;
|
||||
kinc_display_mode_t mode = kinc_display_current_mode(kinc_primary_display());
|
||||
d3dpp.BackBufferWidth = mode.width;
|
||||
d3dpp.BackBufferHeight = mode.height;
|
||||
}
|
||||
else {
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dpp.BackBufferCount = 2;
|
||||
d3dpp.BackBufferWidth = kinc_window_width(windowId);
|
||||
d3dpp.BackBufferHeight = kinc_window_height(windowId);
|
||||
}
|
||||
|
||||
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
|
||||
d3dpp.EnableAutoDepthStencil = TRUE;
|
||||
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
|
||||
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
|
||||
// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
|
||||
if (kinc_g4_antialiasing_samples() > 1) {
|
||||
for (int samples = min(kinc_g4_antialiasing_samples(), 16); samples > 1; --samples) {
|
||||
if (SUCCEEDED(d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, (D3DMULTISAMPLE_TYPE)samples, nullptr))) {
|
||||
d3dpp.MultiSampleType = (D3DMULTISAMPLE_TYPE)samples;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!SUCCEEDED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device)))
|
||||
d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
|
||||
// d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
// if (System::hasShowWindowFlag(/*windowId*/)) {
|
||||
ShowWindow(hWnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hWnd);
|
||||
//}
|
||||
#endif
|
||||
|
||||
initDeviceStates();
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
if (fullscreen) {
|
||||
// hz = d3dpp.FullScreen_RefreshRateInHz;
|
||||
D3DDISPLAYMODE mode;
|
||||
device->GetDisplayMode(0, &mode);
|
||||
hz = mode.RefreshRate;
|
||||
}
|
||||
if (!fullscreen || hz == 0) {
|
||||
DEVMODE devMode;
|
||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
|
||||
hz = devMode.dmDisplayFrequency;
|
||||
}
|
||||
#endif
|
||||
|
||||
// vsync = d3dpp.PresentationInterval != D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
|
||||
kinc_ticks_t test1 = kinc_timestamp();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
kinc_g4_swap_buffers();
|
||||
}
|
||||
kinc_ticks_t test2 = kinc_timestamp();
|
||||
if (test2 - test1 < (1.0 / hz) * kinc_frequency()) {
|
||||
vsync = false;
|
||||
}
|
||||
else {
|
||||
vsync = true;
|
||||
}
|
||||
|
||||
_width = kinc_window_width(windowId);
|
||||
_height = kinc_window_height(windowId);
|
||||
}
|
||||
|
||||
void kinc_g4_flush() {}
|
||||
|
||||
namespace {
|
||||
DWORD convertFilter(kinc_g4_texture_filter_t filter) {
|
||||
switch (filter) {
|
||||
case KINC_G4_TEXTURE_FILTER_POINT:
|
||||
return D3DTEXF_POINT;
|
||||
case KINC_G4_TEXTURE_FILTER_LINEAR:
|
||||
return D3DTEXF_LINEAR;
|
||||
case KINC_G4_TEXTURE_FILTER_ANISOTROPIC:
|
||||
return D3DTEXF_ANISOTROPIC;
|
||||
default:
|
||||
return D3DTEXF_POINT;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD convertMipFilter(kinc_g4_mipmap_filter_t filter) {
|
||||
switch (filter) {
|
||||
case KINC_G4_MIPMAP_FILTER_NONE:
|
||||
return D3DTEXF_NONE;
|
||||
case KINC_G4_MIPMAP_FILTER_POINT:
|
||||
return D3DTEXF_POINT;
|
||||
case KINC_G4_MIPMAP_FILTER_LINEAR:
|
||||
return D3DTEXF_LINEAR;
|
||||
default:
|
||||
return D3DTEXF_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
device->SetSamplerState(texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MAGFILTER, convertFilter(filter));
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
kinc_g4_set_texture_magnification_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
device->SetSamplerState(texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MINFILTER, convertFilter(filter));
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
kinc_g4_set_texture_minification_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
|
||||
device->SetSamplerState(texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MIPFILTER, convertMipFilter(filter));
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
|
||||
kinc_g4_set_texture_mipmap_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {}
|
||||
|
||||
void kinc_g4_set_texture_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {}
|
||||
|
||||
void kinc_g4_set_cubemap_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {}
|
||||
|
||||
void kinc_g4_set_cubemap_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {}
|
||||
|
||||
void kinc_g4_set_texture_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {
|
||||
device->SetSamplerState(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MAXANISOTROPY, max_anisotropy);
|
||||
}
|
||||
|
||||
void kinc_g4_set_cubemap_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {}
|
||||
|
||||
void kinc_g4_set_texture_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {
|
||||
// device->SetSamplerState(unit.impl.unit, D3DSAMP_, );
|
||||
}
|
||||
|
||||
void kinc_g4_set_cubemap_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {}
|
||||
|
||||
void kinc_g4_set_render_targets(struct kinc_g4_render_target **targets, int count) {
|
||||
// if (backBuffer != nullptr) backBuffer->Release();
|
||||
|
||||
if (backBuffer == nullptr) {
|
||||
device->GetRenderTarget(0, &backBuffer);
|
||||
device->GetDepthStencilSurface(&depthBuffer);
|
||||
}
|
||||
kinc_microsoft_affirm(device->SetDepthStencilSurface(targets[0]->impl.depthSurface));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
kinc_microsoft_affirm(device->SetRenderTarget(i, targets[i]->impl.colorSurface));
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_render_target_face(struct kinc_g4_render_target *texture, int face) {}
|
||||
|
||||
int kinc_g4_max_bound_textures(void) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
// void Graphics::setDepthStencilTarget(Texture* texture) {
|
||||
// //if (depthBuffer != nullptr) depthBuffer->Release();
|
||||
// device->GetDepthStencilSurface(&depthBuffer);
|
||||
// Microsoft::affirm(device->SetDepthStencilSurface(dcast<D3D9Texture*>(texture)->getSurface()));
|
||||
//}
|
||||
|
||||
void kinc_g4_restore_render_target() {
|
||||
if (backBuffer != nullptr) {
|
||||
device->SetRenderTarget(0, backBuffer);
|
||||
device->SetRenderTarget(1, nullptr);
|
||||
backBuffer->Release();
|
||||
backBuffer = nullptr;
|
||||
device->SetDepthStencilSurface(depthBuffer);
|
||||
depthBuffer->Release();
|
||||
depthBuffer = nullptr;
|
||||
kinc_g4_viewport(0, 0, _width, _height);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices() {
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), 0,
|
||||
kinc_g4_index_buffer_count(kinc_internal_current_index_buffer) / 3);
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_from_to(int start, int count) {
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), start, count / 3);
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_from_to_from(int start, int count, int vertex_offset) {
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vertex_offset, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), start, count / 3);
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_instanced(int instanceCount) {
|
||||
kinc_microsoft_affirm(device->SetStreamSourceFreq(kinc_internal_current_vertex_buffer->impl._offset, (D3DSTREAMSOURCE_INDEXEDDATA | instanceCount)));
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), 0,
|
||||
kinc_g4_index_buffer_count(kinc_internal_current_index_buffer) / 3);
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_instanced_from_to(int instanceCount, int start, int count) {
|
||||
kinc_microsoft_affirm(device->SetStreamSourceFreq(kinc_internal_current_vertex_buffer->impl._offset, (D3DSTREAMSOURCE_INDEXEDDATA | instanceCount)));
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), start, count / 3);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
|
||||
DWORD value = 0;
|
||||
switch (addressing) {
|
||||
case KINC_G4_TEXTURE_ADDRESSING_REPEAT:
|
||||
value = D3DTADDRESS_WRAP;
|
||||
break;
|
||||
case KINC_G4_TEXTURE_ADDRESSING_MIRROR:
|
||||
value = D3DTADDRESS_MIRROR;
|
||||
break;
|
||||
case KINC_G4_TEXTURE_ADDRESSING_CLAMP:
|
||||
value = D3DTADDRESS_CLAMP;
|
||||
break;
|
||||
case KINC_G4_TEXTURE_ADDRESSING_BORDER:
|
||||
value = D3DTADDRESS_BORDER;
|
||||
break;
|
||||
}
|
||||
device->SetSamplerState(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], dir == KINC_G4_TEXTURE_DIRECTION_U ? D3DSAMP_ADDRESSU : D3DSAMP_ADDRESSV, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
|
||||
kinc_g4_set_texture_addressing(unit, dir, addressing);
|
||||
}
|
||||
|
||||
namespace {
|
||||
void tod3dmatrix(kinc_matrix4x4_t *matrix, D3DMATRIX &d3dm) {
|
||||
d3dm._11 = kinc_matrix4x4_get(matrix, 0, 0);
|
||||
d3dm._12 = kinc_matrix4x4_get(matrix, 0, 1);
|
||||
d3dm._13 = kinc_matrix4x4_get(matrix, 0, 2);
|
||||
d3dm._14 = kinc_matrix4x4_get(matrix, 0, 3);
|
||||
|
||||
d3dm._21 = kinc_matrix4x4_get(matrix, 1, 0);
|
||||
d3dm._22 = kinc_matrix4x4_get(matrix, 1, 1);
|
||||
d3dm._23 = kinc_matrix4x4_get(matrix, 1, 2);
|
||||
d3dm._24 = kinc_matrix4x4_get(matrix, 1, 3);
|
||||
|
||||
d3dm._31 = kinc_matrix4x4_get(matrix, 2, 0);
|
||||
d3dm._32 = kinc_matrix4x4_get(matrix, 2, 1);
|
||||
d3dm._33 = kinc_matrix4x4_get(matrix, 2, 2);
|
||||
d3dm._34 = kinc_matrix4x4_get(matrix, 2, 3);
|
||||
|
||||
d3dm._41 = kinc_matrix4x4_get(matrix, 3, 0);
|
||||
d3dm._42 = kinc_matrix4x4_get(matrix, 3, 1);
|
||||
d3dm._43 = kinc_matrix4x4_get(matrix, 3, 2);
|
||||
d3dm._44 = kinc_matrix4x4_get(matrix, 3, 3);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_clear(unsigned flags, unsigned color, float depth, int stencil) {
|
||||
device->Clear(0, nullptr, flags, color, depth, stencil);
|
||||
}
|
||||
|
||||
void kinc_g4_begin(int window) {
|
||||
// TODO (DK) ignore secondary windows for now
|
||||
if (window > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
kinc_g4_viewport(0, 0, _width, _height);
|
||||
device->BeginScene();
|
||||
}
|
||||
|
||||
void kinc_g4_viewport(int x, int y, int width, int height) {
|
||||
vp.X = x;
|
||||
vp.Y = y;
|
||||
vp.Width = width;
|
||||
vp.Height = height;
|
||||
device->SetViewport(&vp);
|
||||
}
|
||||
|
||||
void kinc_g4_scissor(int x, int y, int width, int height) {
|
||||
device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
|
||||
RECT rc;
|
||||
rc.left = x;
|
||||
rc.top = y;
|
||||
rc.right = x + width;
|
||||
rc.bottom = y + height;
|
||||
device->SetScissorRect(&rc);
|
||||
}
|
||||
|
||||
void kinc_g4_disable_scissor() {
|
||||
device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
void kinc_g4_end(int window) {
|
||||
// TODO (DK) ignore secondary windows for now
|
||||
if (window > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*if (backBuffer != nullptr) {
|
||||
backBuffer->Release();
|
||||
backBuffer = nullptr;
|
||||
}*/
|
||||
device->EndScene();
|
||||
}
|
||||
|
||||
bool kinc_window_vsynced(int window) {
|
||||
return vsync;
|
||||
}
|
||||
|
||||
// unsigned Graphics4::refreshRate() {
|
||||
// return hz;
|
||||
//}
|
||||
|
||||
bool kinc_g4_swap_buffers() {
|
||||
return ::swapBuffers();
|
||||
}
|
||||
|
||||
void kinc_g4_set_stencil_reference_value(int value) {}
|
||||
|
||||
void kinc_g4_set_blend_constant(float r, float g, float b, float a) {
|
||||
device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA((int)(r * 255), (int)(g * 255), (int)(b * 255), (int)(a * 255)));
|
||||
}
|
||||
|
||||
void kinc_g4_set_bool(kinc_g4_constant_location_t position, bool value) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
BOOL bools[4];
|
||||
bools[0] = value ? 1 : 0;
|
||||
bools[1] = bools[0];
|
||||
bools[2] = bools[0];
|
||||
bools[3] = bools[0];
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantB(position.impl.reg.regindex, &bools[0], 1);
|
||||
else
|
||||
device->SetPixelShaderConstantB(position.impl.reg.regindex, &bools[0], 1);
|
||||
}
|
||||
|
||||
void kinc_g4_set_int(kinc_g4_constant_location_t position, int value) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
if (position.impl.reg.regtype == 'f') {
|
||||
kinc_g4_set_float(position, (float)value);
|
||||
}
|
||||
else {
|
||||
int ints[4];
|
||||
ints[0] = value;
|
||||
ints[1] = value;
|
||||
ints[2] = value;
|
||||
ints[3] = value;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
else
|
||||
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_int2(kinc_g4_constant_location_t position, int value1, int value2) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
if (position.impl.reg.regtype == 'f') {
|
||||
kinc_g4_set_float2(position, (float)value1, (float)value2);
|
||||
}
|
||||
else {
|
||||
int ints[4];
|
||||
ints[0] = value1;
|
||||
ints[1] = value2;
|
||||
ints[2] = value1;
|
||||
ints[3] = value2;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
else
|
||||
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_int3(kinc_g4_constant_location_t position, int value1, int value2, int value3) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
if (position.impl.reg.regtype == 'f') {
|
||||
kinc_g4_set_float3(position, (float)value1, (float)value2, (float)value3);
|
||||
}
|
||||
else {
|
||||
int ints[4];
|
||||
ints[0] = value1;
|
||||
ints[1] = value2;
|
||||
ints[2] = value3;
|
||||
ints[3] = value1;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
else
|
||||
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_int4(kinc_g4_constant_location_t position, int value1, int value2, int value3, int value4) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
if (position.impl.reg.regtype == 'f') {
|
||||
kinc_g4_set_float4(position, (float)value1, (float)value2, (float)value3, (float)value4);
|
||||
}
|
||||
else {
|
||||
int ints[4];
|
||||
ints[0] = value1;
|
||||
ints[1] = value2;
|
||||
ints[2] = value3;
|
||||
ints[3] = value4;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
else
|
||||
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_ints(kinc_g4_constant_location_t location, int *values, int count) {
|
||||
if (location.impl.shaderType == -1)
|
||||
return;
|
||||
int registerCount = (count + 3) / 4; // round up
|
||||
if (registerCount == count / 4) { // round down
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(location.impl.reg.regindex, values, registerCount);
|
||||
else
|
||||
device->SetPixelShaderConstantI(location.impl.reg.regindex, values, registerCount);
|
||||
}
|
||||
else {
|
||||
int *data = (int *)alloca(registerCount * 4 * sizeof(int));
|
||||
memcpy(data, values, count * sizeof(int));
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(location.impl.reg.regindex, data, registerCount);
|
||||
else
|
||||
device->SetPixelShaderConstantI(location.impl.reg.regindex, data, registerCount);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_float(kinc_g4_constant_location_t position, float value) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[4];
|
||||
floats[0] = value;
|
||||
floats[1] = value;
|
||||
floats[2] = value;
|
||||
floats[3] = value;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
else
|
||||
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float2(kinc_g4_constant_location_t position, float value1, float value2) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[4];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value1;
|
||||
floats[3] = value2;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
else
|
||||
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float3(kinc_g4_constant_location_t position, float value1, float value2, float value3) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[4];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value3;
|
||||
floats[3] = value1;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
else
|
||||
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float4(kinc_g4_constant_location_t position, float value1, float value2, float value3, float value4) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[4];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value3;
|
||||
floats[3] = value4;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
else
|
||||
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
}
|
||||
|
||||
void kinc_g4_set_floats(kinc_g4_constant_location_t location, float *values, int count) {
|
||||
if (location.impl.shaderType == -1)
|
||||
return;
|
||||
int registerCount = (count + 3) / 4; // round up
|
||||
if (registerCount == count / 4) { // round down
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(location.impl.reg.regindex, values, registerCount);
|
||||
else
|
||||
device->SetPixelShaderConstantF(location.impl.reg.regindex, values, registerCount);
|
||||
}
|
||||
else {
|
||||
float *data = (float *)alloca(registerCount * 4 * sizeof(float));
|
||||
memcpy(data, values, count * sizeof(float));
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(location.impl.reg.regindex, data, registerCount);
|
||||
else
|
||||
device->SetPixelShaderConstantF(location.impl.reg.regindex, data, registerCount);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_matrix4(kinc_g4_constant_location_t location, kinc_matrix4x4_t *value) {
|
||||
if (location.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[16];
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[y * 4 + x] = kinc_matrix4x4_get(value, y, x);
|
||||
}
|
||||
}
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(location.impl.reg.regindex, floats, 4);
|
||||
else
|
||||
device->SetPixelShaderConstantF(location.impl.reg.regindex, floats, 4);
|
||||
}
|
||||
|
||||
void kinc_g4_set_matrix3(kinc_g4_constant_location_t location, kinc_matrix3x3_t *value) {
|
||||
if (location.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[12];
|
||||
for (int y = 0; y < 3; ++y) {
|
||||
for (int x = 0; x < 3; ++x) {
|
||||
floats[y * 4 + x] = kinc_matrix3x3_get(value, y, x);
|
||||
}
|
||||
}
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(location.impl.reg.regindex, floats, 3);
|
||||
else
|
||||
device->SetPixelShaderConstantF(location.impl.reg.regindex, floats, 3);
|
||||
}
|
||||
|
||||
void kinc_g4_set_vertex_buffers(kinc_g4_vertex_buffer_t **buffers, int count) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
kinc_internal_g4_vertex_buffer_set(buffers[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_index_buffer(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_internal_g4_index_buffer_set(buffer);
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, uint32_t unit);
|
||||
|
||||
void kinc_g4_set_texture(uint32_t unit, struct kinc_g4_texture *texture) {
|
||||
kinc_internal_texture_set(texture, unit);
|
||||
}
|
||||
#else
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit);
|
||||
|
||||
void kinc_g4_set_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_texture *texture) {
|
||||
kinc_internal_texture_set(texture, unit);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_set_image_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_texture *texture) {}
|
||||
|
||||
unsigned queryCount = 0;
|
||||
std::vector<IDirect3DQuery9 *> queryPool;
|
||||
|
||||
bool kinc_g4_init_occlusion_query(unsigned *occlusionQuery) {
|
||||
// check if the runtime supports queries
|
||||
HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL);
|
||||
if (FAILED(result)) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Internal query creation failed, result: 0x%X.", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
IDirect3DQuery9 *pQuery = nullptr;
|
||||
device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pQuery);
|
||||
|
||||
queryPool.push_back(pQuery);
|
||||
*occlusionQuery = queryCount;
|
||||
++queryCount;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void kinc_g4_delete_occlusion_query(unsigned occlusionQuery) {
|
||||
if (occlusionQuery < queryPool.size())
|
||||
queryPool[occlusionQuery] = nullptr;
|
||||
}
|
||||
|
||||
void kinc_g4_start_occlusion_query(unsigned occlusionQuery) {
|
||||
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
|
||||
if (pQuery != nullptr) {
|
||||
pQuery->Issue(D3DISSUE_BEGIN);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_end_occlusion_query(unsigned occlusionQuery) {
|
||||
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
|
||||
if (pQuery != nullptr) {
|
||||
pQuery->Issue(D3DISSUE_END);
|
||||
}
|
||||
}
|
||||
|
||||
bool kinc_g4_are_query_results_available(unsigned occlusionQuery) {
|
||||
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
|
||||
if (pQuery != nullptr) {
|
||||
if (S_OK == pQuery->GetData(0, 0, 0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void kinc_g4_get_query_results(unsigned occlusionQuery, unsigned *pixelCount) {
|
||||
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
|
||||
if (pQuery != nullptr) {
|
||||
DWORD numberOfPixelsDrawn;
|
||||
HRESULT result = pQuery->GetData(&numberOfPixelsDrawn, sizeof(DWORD), 0);
|
||||
if (S_OK == result) {
|
||||
*pixelCount = numberOfPixelsDrawn;
|
||||
}
|
||||
else {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Check first if results are available");
|
||||
*pixelCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_array(kinc_g4_texture_unit_t unit, struct kinc_g4_texture_array *array) {}
|
||||
|
||||
void kinc_g4_set_pipeline(struct kinc_g4_pipeline *pipeline) {
|
||||
kinc_g4_internal_set_pipeline(pipeline);
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_instanced_rendering() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_compute_shaders() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_blend_constants() {
|
||||
D3DCAPS9 pCaps = {};
|
||||
if (FAILED(device->GetDeviceCaps(&pCaps))) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to get device caps");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((pCaps.SrcBlendCaps & D3DPBLENDCAPS_BLENDFACTOR) != 0) && ((pCaps.DestBlendCaps & D3DPBLENDCAPS_BLENDFACTOR) != 0);
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_non_pow2_textures() {
|
||||
D3DCAPS9 pCaps = {};
|
||||
if (FAILED(device->GetDeviceCaps(&pCaps))) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to get device caps");
|
||||
return false;
|
||||
}
|
||||
// only advertise full npot support
|
||||
return ((pCaps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0) && ((pCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) == 0);
|
||||
}
|
||||
|
||||
bool kinc_g4_render_targets_inverted_y(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void kinc_g4_set_constant_buffer(uint32_t id, struct kinc_g4_constant_buffer *buffer) {}
|
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/math/matrix.h>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define D3D_DEBUG_INFO
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
extern IDirect3D9 *d3d;
|
||||
extern IDirect3DDevice9 *device;
|
@ -0,0 +1,34 @@
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/graphics4/constantbuffer.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
|
||||
buffer->impl.size = size;
|
||||
buffer->impl.last_start = 0;
|
||||
buffer->impl.last_size = size;
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
|
||||
buffer->impl.last_start = start;
|
||||
buffer->impl.last_size = size;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {}
|
||||
|
||||
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
|
||||
return buffer->impl.size;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KINC_KONG
|
||||
|
||||
typedef struct kinc_g4_constant_buffer_impl {
|
||||
size_t size;
|
||||
size_t last_start;
|
||||
size_t last_size;
|
||||
} kinc_g4_constant_buffer_impl;
|
||||
|
||||
#endif
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IndexBufferImpl.h"
|
||||
#include "RenderTargetImpl.h"
|
||||
#include "ShaderImpl.h"
|
||||
#include "VertexBufferImpl.h"
|
@ -0,0 +1,56 @@
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
struct kinc_g4_index_buffer *kinc_internal_current_index_buffer = NULL;
|
||||
|
||||
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
|
||||
buffer->impl.count = count;
|
||||
buffer->impl.format = format;
|
||||
|
||||
DWORD usageFlags = D3DUSAGE_WRITEONLY;
|
||||
if (usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
usageFlags = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(device->CreateIndexBuffer(
|
||||
sizeof(int) * count, usageFlags, format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, D3DPOOL_DEFAULT, &buffer->impl.ib, 0));
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
|
||||
buffer->impl.ib->Release();
|
||||
}
|
||||
|
||||
static int kinc_g4_internal_index_buffer_stride(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT ? 4 : 2;
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
return kinc_g4_index_buffer_lock(buffer, 0, kinc_g4_index_buffer_count(buffer));
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
|
||||
uint8_t *data;
|
||||
kinc_microsoft_affirm(buffer->impl.ib->Lock(0, sizeof(int) * kinc_g4_index_buffer_count(buffer), (void **)&data, D3DLOCK_DISCARD));
|
||||
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_microsoft_affirm(buffer->impl.ib->Unlock());
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
|
||||
kinc_g4_index_buffer_unlock_all(buffer);
|
||||
}
|
||||
|
||||
void kinc_internal_g4_index_buffer_set(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_internal_current_index_buffer = buffer;
|
||||
kinc_microsoft_affirm(device->SetIndices(buffer->impl.ib));
|
||||
}
|
||||
|
||||
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.count;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct IDirect3DIndexBuffer9;
|
||||
|
||||
typedef struct {
|
||||
struct IDirect3DIndexBuffer9 *ib;
|
||||
int count;
|
||||
int format;
|
||||
} kinc_g4_index_buffer_impl_t;
|
||||
|
||||
struct kinc_g4_index_buffer;
|
||||
|
||||
extern struct kinc_g4_index_buffer *kinc_internal_current_index_buffer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,365 @@
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/vertexstructure.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/system.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
|
||||
namespace {
|
||||
_D3DBLEND convert_blend_factor(kinc_g4_blending_factor_t factor) {
|
||||
switch (factor) {
|
||||
case KINC_G4_BLEND_ONE:
|
||||
return D3DBLEND_ONE;
|
||||
case KINC_G4_BLEND_ZERO:
|
||||
return D3DBLEND_ZERO;
|
||||
case KINC_G4_BLEND_SOURCE_ALPHA:
|
||||
return D3DBLEND_SRCALPHA;
|
||||
case KINC_G4_BLEND_DEST_ALPHA:
|
||||
return D3DBLEND_DESTALPHA;
|
||||
case KINC_G4_BLEND_INV_SOURCE_ALPHA:
|
||||
return D3DBLEND_INVSRCALPHA;
|
||||
case KINC_G4_BLEND_INV_DEST_ALPHA:
|
||||
return D3DBLEND_INVDESTALPHA;
|
||||
case KINC_G4_BLEND_CONSTANT:
|
||||
return D3DBLEND_BLENDFACTOR;
|
||||
case KINC_G4_BLEND_INV_CONSTANT:
|
||||
return D3DBLEND_INVBLENDFACTOR;
|
||||
default:
|
||||
assert(false);
|
||||
return D3DBLEND_SRCALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
_D3DBLENDOP convert_blend_operation(kinc_g4_blending_operation_t op) {
|
||||
switch (op) {
|
||||
case KINC_G4_BLENDOP_ADD:
|
||||
return D3DBLENDOP_ADD;
|
||||
case KINC_G4_BLENDOP_SUBTRACT:
|
||||
return D3DBLENDOP_SUBTRACT;
|
||||
case KINC_G4_BLENDOP_REVERSE_SUBTRACT:
|
||||
return D3DBLENDOP_REVSUBTRACT;
|
||||
case KINC_G4_BLENDOP_MIN:
|
||||
return D3DBLENDOP_MIN;
|
||||
case KINC_G4_BLENDOP_MAX:
|
||||
return D3DBLENDOP_MAX;
|
||||
default:
|
||||
assert(false);
|
||||
return D3DBLENDOP_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
_D3DCMPFUNC convert(kinc_g4_compare_mode_t mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
case KINC_G4_COMPARE_ALWAYS:
|
||||
return D3DCMP_ALWAYS;
|
||||
case KINC_G4_COMPARE_NEVER:
|
||||
return D3DCMP_NEVER;
|
||||
case KINC_G4_COMPARE_EQUAL:
|
||||
return D3DCMP_EQUAL;
|
||||
case KINC_G4_COMPARE_NOT_EQUAL:
|
||||
return D3DCMP_NOTEQUAL;
|
||||
case KINC_G4_COMPARE_LESS:
|
||||
return D3DCMP_LESS;
|
||||
case KINC_G4_COMPARE_LESS_EQUAL:
|
||||
return D3DCMP_LESSEQUAL;
|
||||
case KINC_G4_COMPARE_GREATER:
|
||||
return D3DCMP_GREATER;
|
||||
case KINC_G4_COMPARE_GREATER_EQUAL:
|
||||
return D3DCMP_GREATEREQUAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_init(kinc_g4_pipeline_t *state) {
|
||||
memset(state, 0, sizeof(kinc_g4_pipeline));
|
||||
kinc_g4_internal_pipeline_set_defaults(state);
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_destroy(kinc_g4_pipeline_t *state) {}
|
||||
|
||||
static int find_attribute(struct ShaderAttribute *attributes, const char *name) {
|
||||
for (int i = 0; i < KINC_INTERNAL_MAX_ATTRIBUTES; ++i) {
|
||||
if (attributes[i].name == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(attributes[i].name, name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int find_constant(struct ShaderRegister *constants, const char *name) {
|
||||
for (int i = 0; i < KINC_INTERNAL_MAX_CONSTANTS; ++i) {
|
||||
if (constants[i].name == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(constants[i].name, name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *state) {
|
||||
int highestIndex = 0;
|
||||
for (int i = 0;; ++i) {
|
||||
if (state->vertex_shader->impl.attributes[i].name[0] == 0) {
|
||||
break;
|
||||
}
|
||||
int index = state->vertex_shader->impl.attributes[i].index;
|
||||
if (index > highestIndex) {
|
||||
highestIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
int all = 0;
|
||||
for (int stream = 0; state->input_layout[stream] != nullptr; ++stream) {
|
||||
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
|
||||
if (state->input_layout[stream]->elements[index].data == KINC_G4_VERTEX_DATA_F32_4X4) {
|
||||
all += 4;
|
||||
}
|
||||
else {
|
||||
all += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3DVERTEXELEMENT9 *elements = (D3DVERTEXELEMENT9 *)_alloca(sizeof(D3DVERTEXELEMENT9) * (all + 1));
|
||||
int i = 0;
|
||||
for (int stream = 0; state->input_layout[stream] != nullptr; ++stream) {
|
||||
int stride = 0;
|
||||
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
|
||||
if (state->input_layout[stream]->elements[index].data != KINC_G4_VERTEX_DATA_F32_4X4) {
|
||||
elements[i].Stream = stream;
|
||||
elements[i].Offset = stride;
|
||||
}
|
||||
stride += kinc_g4_vertex_data_size(state->input_layout[stream]->elements[index].data);
|
||||
switch (state->input_layout[stream]->elements[index].data) {
|
||||
case KINC_G4_VERTEX_DATA_F32_1X:
|
||||
elements[i].Type = D3DDECLTYPE_FLOAT1;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_2X:
|
||||
elements[i].Type = D3DDECLTYPE_FLOAT2;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_3X:
|
||||
elements[i].Type = D3DDECLTYPE_FLOAT3;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X:
|
||||
elements[i].Type = D3DDECLTYPE_FLOAT4;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X:
|
||||
elements[i].Type = D3DDECLTYPE_UBYTE4;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED:
|
||||
elements[i].Type = D3DDECLTYPE_UBYTE4N;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X:
|
||||
elements[i].Type = D3DDECLTYPE_SHORT2;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED:
|
||||
elements[i].Type = D3DDECLTYPE_SHORT2N;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED:
|
||||
elements[i].Type = D3DDECLTYPE_USHORT2N;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X:
|
||||
elements[i].Type = D3DDECLTYPE_SHORT4;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED:
|
||||
elements[i].Type = D3DDECLTYPE_SHORT4N;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED:
|
||||
elements[i].Type = D3DDECLTYPE_USHORT4N;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_1X:
|
||||
case KINC_G4_VERTEX_DATA_U8_1X:
|
||||
case KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_I8_2X:
|
||||
case KINC_G4_VERTEX_DATA_U8_2X:
|
||||
case KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_I8_4X:
|
||||
case KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_I16_1X:
|
||||
case KINC_G4_VERTEX_DATA_U16_1X:
|
||||
case KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U16_2X:
|
||||
case KINC_G4_VERTEX_DATA_U16_4X:
|
||||
case KINC_G4_VERTEX_DATA_I32_1X:
|
||||
case KINC_G4_VERTEX_DATA_U32_1X:
|
||||
case KINC_G4_VERTEX_DATA_I32_2X:
|
||||
case KINC_G4_VERTEX_DATA_U32_2X:
|
||||
case KINC_G4_VERTEX_DATA_I32_3X:
|
||||
case KINC_G4_VERTEX_DATA_U32_3X:
|
||||
case KINC_G4_VERTEX_DATA_I32_4X:
|
||||
case KINC_G4_VERTEX_DATA_U32_4X:
|
||||
elements[i].Type = D3DDECLTYPE_UNUSED;
|
||||
assert(false);
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X4:
|
||||
for (int i2 = 0; i2 < 4; ++i2) {
|
||||
elements[i].Stream = stream;
|
||||
elements[i].Offset = stride;
|
||||
elements[i].Type = D3DDECLTYPE_FLOAT4;
|
||||
elements[i].Method = D3DDECLMETHOD_DEFAULT;
|
||||
elements[i].Usage = D3DDECLUSAGE_TEXCOORD;
|
||||
char name[101];
|
||||
strcpy(name, state->input_layout[stream]->elements[index].name);
|
||||
strcat(name, "_");
|
||||
size_t length = strlen(name);
|
||||
_itoa(i2, &name[length], 10);
|
||||
name[length + 1] = 0;
|
||||
int attribute_index = find_attribute(state->vertex_shader->impl.attributes, name);
|
||||
if (attribute_index < 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not find attribute %s.", name);
|
||||
elements[i].UsageIndex = ++highestIndex;
|
||||
}
|
||||
else {
|
||||
elements[i].UsageIndex = state->vertex_shader->impl.attributes[attribute_index].index;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (state->input_layout[stream]->elements[index].data != KINC_G4_VERTEX_DATA_F32_4X4) {
|
||||
elements[i].Method = D3DDECLMETHOD_DEFAULT;
|
||||
elements[i].Usage = D3DDECLUSAGE_TEXCOORD;
|
||||
int attribute_index = find_attribute(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name);
|
||||
if (attribute_index < 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not find attribute %s.", state->input_layout[stream]->elements[index].name);
|
||||
elements[i].UsageIndex = ++highestIndex;
|
||||
}
|
||||
else {
|
||||
elements[i].UsageIndex = state->vertex_shader->impl.attributes[attribute_index].index;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
elements[all].Stream = 0xff;
|
||||
elements[all].Offset = 0;
|
||||
elements[all].Type = D3DDECLTYPE_UNUSED;
|
||||
elements[all].Method = 0;
|
||||
elements[all].Usage = 0;
|
||||
elements[all].UsageIndex = 0;
|
||||
|
||||
state->impl.vertexDecleration = nullptr;
|
||||
kinc_microsoft_affirm(device->CreateVertexDeclaration(elements, &state->impl.vertexDecleration));
|
||||
|
||||
int constant_index = find_constant(state->vertex_shader->impl.constants, "gl_HalfPixel");
|
||||
state->impl.halfPixelLocation = state->vertex_shader->impl.constants[constant_index].regindex;
|
||||
}
|
||||
|
||||
void kinc_g4_internal_set_pipeline(kinc_g4_pipeline_t *pipeline) {
|
||||
kinc_microsoft_affirm(device->SetVertexShader((IDirect3DVertexShader9 *)pipeline->vertex_shader->impl.shader));
|
||||
kinc_microsoft_affirm(device->SetPixelShader((IDirect3DPixelShader9 *)pipeline->fragment_shader->impl.shader));
|
||||
kinc_microsoft_affirm(device->SetVertexDeclaration(pipeline->impl.vertexDecleration));
|
||||
|
||||
// TODO (DK) System::screenWidth/Height are only main-window dimensions, what about other windows?
|
||||
float floats[4];
|
||||
floats[0] = 1.0f / kinc_width();
|
||||
floats[1] = 1.0f / kinc_height();
|
||||
floats[2] = floats[0];
|
||||
floats[3] = floats[1];
|
||||
kinc_microsoft_affirm(device->SetVertexShaderConstantF(pipeline->impl.halfPixelLocation, floats, 1));
|
||||
|
||||
DWORD flags = 0;
|
||||
if (pipeline->color_write_mask_red[0]) {
|
||||
flags |= D3DCOLORWRITEENABLE_RED;
|
||||
}
|
||||
if (pipeline->color_write_mask_green[0]) {
|
||||
flags |= D3DCOLORWRITEENABLE_GREEN;
|
||||
}
|
||||
if (pipeline->color_write_mask_blue[0]) {
|
||||
flags |= D3DCOLORWRITEENABLE_BLUE;
|
||||
}
|
||||
if (pipeline->color_write_mask_alpha[0]) {
|
||||
flags |= D3DCOLORWRITEENABLE_ALPHA;
|
||||
}
|
||||
|
||||
device->SetRenderState(D3DRS_COLORWRITEENABLE, flags);
|
||||
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE,
|
||||
(pipeline->blend_source != KINC_G4_BLEND_ONE || pipeline->blend_destination != KINC_G4_BLEND_ZERO) ? TRUE : FALSE);
|
||||
device->SetRenderState(D3DRS_SRCBLEND, convert_blend_factor(pipeline->blend_source));
|
||||
device->SetRenderState(D3DRS_DESTBLEND, convert_blend_factor(pipeline->blend_destination));
|
||||
device->SetRenderState(D3DRS_BLENDOP, convert_blend_operation(pipeline->blend_operation));
|
||||
|
||||
switch (pipeline->cull_mode) {
|
||||
case KINC_G4_CULL_CLOCKWISE:
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
|
||||
break;
|
||||
case KINC_G4_CULL_COUNTER_CLOCKWISE:
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
||||
break;
|
||||
case KINC_G4_CULL_NOTHING:
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
device->SetRenderState(D3DRS_ZENABLE, pipeline->depth_mode != KINC_G4_COMPARE_ALWAYS ? TRUE : FALSE);
|
||||
device->SetRenderState(D3DRS_ZFUNC, convert(pipeline->depth_mode));
|
||||
device->SetRenderState(D3DRS_ZWRITEENABLE, pipeline->depth_write ? TRUE : FALSE);
|
||||
|
||||
/*
|
||||
case AlphaTestState:
|
||||
device->SetRenderState(D3DRS_ALPHATESTENABLE, on ? TRUE : FALSE);
|
||||
device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
break;
|
||||
case AlphaReferenceState:
|
||||
device->SetRenderState(D3DRS_ALPHAREF, (DWORD)v);
|
||||
break;
|
||||
*/
|
||||
}
|
||||
|
||||
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(kinc_g4_pipeline_t *state, const char *name) {
|
||||
kinc_g4_constant_location_t location;
|
||||
|
||||
int fragment_index = find_constant(state->fragment_shader->impl.constants, name);
|
||||
int vertex_index = find_constant(state->vertex_shader->impl.constants, name);
|
||||
|
||||
if (fragment_index >= 0) {
|
||||
location.impl.reg = state->fragment_shader->impl.constants[fragment_index];
|
||||
location.impl.shaderType = 1;
|
||||
}
|
||||
else if (vertex_index >= 0) {
|
||||
location.impl.reg = state->vertex_shader->impl.constants[vertex_index];
|
||||
location.impl.shaderType = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.shaderType = -1;
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not find uniform %s.", name);
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(kinc_g4_pipeline_t *state, const char *name) {
|
||||
int fragment_index = find_constant(state->fragment_shader->impl.constants, name);
|
||||
int vertex_index = find_constant(state->vertex_shader->impl.constants, name);
|
||||
|
||||
kinc_g4_texture_unit_t unit;
|
||||
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
|
||||
unit.stages[i] = -1;
|
||||
}
|
||||
|
||||
if (fragment_index >= 0) {
|
||||
unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] = state->fragment_shader->impl.constants[fragment_index].regindex;
|
||||
}
|
||||
|
||||
if (vertex_index >= 0) {
|
||||
unit.stages[KINC_G4_SHADER_TYPE_VERTEX] = state->vertex_shader->impl.constants[vertex_index].regindex;
|
||||
}
|
||||
|
||||
return unit;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct IDirect3DVertexDeclaration9;
|
||||
|
||||
typedef struct {
|
||||
struct IDirect3DVertexDeclaration9 *vertexDecleration;
|
||||
int halfPixelLocation;
|
||||
} kinc_g4_pipeline_impl_t;
|
||||
|
||||
void kinc_internal_set_constants(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,133 @@
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->width = width;
|
||||
renderTarget->height = height;
|
||||
renderTarget->texWidth = width;
|
||||
renderTarget->texHeight = height;
|
||||
renderTarget->isCubeMap = false;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
|
||||
const bool antialiasing = samples_per_pixel > 1;
|
||||
renderTarget->impl.antialiasing = antialiasing;
|
||||
|
||||
D3DFORMAT d3dformat;
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
d3dformat = D3DFMT_A16B16G16R16F;
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
d3dformat = D3DFMT_R32F;
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
d3dformat = D3DFMT_A8R8G8B8;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG)
|
||||
kinc_log(KINC_LOG_LEVEL_INFO, "depthBufferBits not implemented yet, using defaults (D3DFMT_D24S8)");
|
||||
kinc_log(KINC_LOG_LEVEL_INFO, "stencilBufferBits not implemented yet, using defaults (D3DFMT_D24S8)");
|
||||
#endif
|
||||
|
||||
renderTarget->impl.colorSurface = nullptr;
|
||||
renderTarget->impl.depthSurface = nullptr;
|
||||
renderTarget->impl.colorTexture = nullptr;
|
||||
renderTarget->impl.depthTexture = nullptr;
|
||||
|
||||
if (antialiasing) {
|
||||
kinc_microsoft_affirm(
|
||||
device->CreateRenderTarget(width, height, d3dformat, D3DMULTISAMPLE_8_SAMPLES, 0, FALSE, &renderTarget->impl.colorSurface, nullptr));
|
||||
kinc_microsoft_affirm(
|
||||
device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, D3DMULTISAMPLE_8_SAMPLES, 0, TRUE, &renderTarget->impl.depthSurface, nullptr));
|
||||
kinc_microsoft_affirm(
|
||||
device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, d3dformat, D3DPOOL_DEFAULT, &renderTarget->impl.colorTexture, nullptr));
|
||||
// Microsoft::affirm(device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &depthTexture, nullptr));
|
||||
renderTarget->impl.depthTexture = nullptr;
|
||||
}
|
||||
else {
|
||||
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
|
||||
kinc_microsoft_affirm(device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)MAKEFOURCC('N', 'U', 'L', 'L'), D3DPOOL_DEFAULT,
|
||||
&renderTarget->impl.colorTexture, nullptr));
|
||||
kinc_microsoft_affirm(device->CreateTexture(width, height, 1, D3DUSAGE_DEPTHSTENCIL, (D3DFORMAT)MAKEFOURCC('I', 'N', 'T', 'Z'), D3DPOOL_DEFAULT,
|
||||
&renderTarget->impl.depthTexture, nullptr));
|
||||
renderTarget->isDepthAttachment = true;
|
||||
}
|
||||
else {
|
||||
kinc_microsoft_affirm(
|
||||
device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, d3dformat, D3DPOOL_DEFAULT, &renderTarget->impl.colorTexture, nullptr));
|
||||
kinc_microsoft_affirm(
|
||||
device->CreateTexture(width, height, 1, D3DUSAGE_DEPTHSTENCIL, D3DFMT_D24S8, D3DPOOL_DEFAULT, &renderTarget->impl.depthTexture, nullptr));
|
||||
}
|
||||
kinc_microsoft_affirm(renderTarget->impl.colorTexture->GetSurfaceLevel(0, &renderTarget->impl.colorSurface));
|
||||
kinc_microsoft_affirm(renderTarget->impl.depthTexture->GetSurfaceLevel(0, &renderTarget->impl.depthSurface));
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->isCubeMap = true;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget) {
|
||||
if (renderTarget->impl.colorSurface != nullptr) {
|
||||
renderTarget->impl.colorSurface->Release();
|
||||
}
|
||||
if (renderTarget->impl.depthSurface != nullptr) {
|
||||
renderTarget->impl.depthSurface->Release();
|
||||
}
|
||||
if (renderTarget->impl.colorTexture != nullptr) {
|
||||
renderTarget->impl.colorTexture->Release();
|
||||
}
|
||||
if (renderTarget->impl.depthTexture != nullptr) {
|
||||
renderTarget->impl.depthTexture->Release();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, uint32_t unit) {
|
||||
if (renderTarget->impl.antialiasing) {
|
||||
IDirect3DSurface9 *surface;
|
||||
renderTarget->impl.colorTexture->GetSurfaceLevel(0, &surface);
|
||||
kinc_microsoft_affirm(device->StretchRect(renderTarget->impl.colorSurface, nullptr, surface, nullptr, D3DTEXF_NONE));
|
||||
surface->Release();
|
||||
}
|
||||
device->SetTexture(unit, renderTarget->isDepthAttachment ? renderTarget->impl.depthTexture : renderTarget->impl.colorTexture);
|
||||
}
|
||||
#else
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
if (renderTarget->impl.antialiasing) {
|
||||
IDirect3DSurface9 *surface;
|
||||
renderTarget->impl.colorTexture->GetSurfaceLevel(0, &surface);
|
||||
kinc_microsoft_affirm(device->StretchRect(renderTarget->impl.colorSurface, nullptr, surface, nullptr, D3DTEXF_NONE));
|
||||
surface->Release();
|
||||
}
|
||||
device->SetTexture(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT],
|
||||
renderTarget->isDepthAttachment ? renderTarget->impl.depthTexture : renderTarget->impl.colorTexture);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source) {
|
||||
renderTarget->impl.depthTexture = source->impl.depthTexture;
|
||||
renderTarget->impl.depthSurface = source->impl.depthSurface;
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
if (renderTarget->impl.antialiasing) {
|
||||
IDirect3DSurface9 *surface;
|
||||
renderTarget->impl.depthTexture->GetSurfaceLevel(0, &surface);
|
||||
kinc_microsoft_affirm(device->StretchRect(renderTarget->impl.depthSurface, nullptr, surface, nullptr, D3DTEXF_NONE));
|
||||
surface->Release();
|
||||
}
|
||||
device->SetTexture(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], renderTarget->impl.depthTexture);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *renderTarget, uint8_t *data) {}
|
||||
|
||||
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *renderTarget, int levels) {}
|
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct IDirect3DSurface9;
|
||||
struct IDirect3DTexture9;
|
||||
|
||||
typedef struct {
|
||||
struct IDirect3DSurface9 *colorSurface;
|
||||
struct IDirect3DSurface9 *depthSurface;
|
||||
struct IDirect3DTexture9 *colorTexture;
|
||||
struct IDirect3DTexture9 *depthTexture;
|
||||
bool antialiasing;
|
||||
} kinc_g4_render_target_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,54 @@
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *void_data, size_t length, kinc_g4_shader_type_t type) {
|
||||
unsigned index = 0;
|
||||
|
||||
uint8_t *data = (uint8_t *)void_data;
|
||||
int attributesCount = data[index++];
|
||||
for (int i = 0; i < attributesCount; ++i) {
|
||||
char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
strcpy(shader->impl.attributes[i].name, name);
|
||||
shader->impl.attributes[i].index = data[index++];
|
||||
}
|
||||
shader->impl.attributes[attributesCount].name[0] = 0;
|
||||
|
||||
uint8_t constantCount = data[index++];
|
||||
for (unsigned i = 0; i < constantCount; ++i) {
|
||||
char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
strcpy(shader->impl.constants[i].name, name);
|
||||
shader->impl.constants[i].regtype = data[index++];
|
||||
shader->impl.constants[i].regindex = data[index++];
|
||||
shader->impl.constants[i].regcount = data[index++];
|
||||
}
|
||||
shader->impl.constants[constantCount].name[0] = 0;
|
||||
|
||||
if (type == KINC_G4_SHADER_TYPE_VERTEX) {
|
||||
kinc_microsoft_affirm(device->CreateVertexShader((DWORD *)&data[index], (IDirect3DVertexShader9 **)&shader));
|
||||
}
|
||||
else {
|
||||
kinc_microsoft_affirm(device->CreatePixelShader((DWORD *)&data[index], (IDirect3DPixelShader9 **)&shader));
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {}
|
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ShaderRegister {
|
||||
char name[128];
|
||||
uint8_t regtype;
|
||||
uint8_t regindex;
|
||||
uint8_t regcount;
|
||||
};
|
||||
|
||||
struct ShaderAttribute {
|
||||
char name[128];
|
||||
int index;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct ShaderRegister reg;
|
||||
int shaderType; // 0: Vertex, 1: Fragment
|
||||
} kinc_g4_constant_location_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int unit;
|
||||
} kinc_g4_texture_unit_impl_t;
|
||||
|
||||
#define KINC_INTERNAL_MAX_CONSTANTS 64
|
||||
#define KINC_INTERNAL_MAX_ATTRIBUTES 64
|
||||
|
||||
typedef struct {
|
||||
struct ShaderRegister constants[KINC_INTERNAL_MAX_CONSTANTS];
|
||||
struct ShaderAttribute attributes[KINC_INTERNAL_MAX_ATTRIBUTES];
|
||||
void *shader;
|
||||
} kinc_g4_shader_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,110 @@
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
namespace {
|
||||
kinc_g4_texture_t *setTextures[16] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
|
||||
|
||||
D3DFORMAT convert(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
default:
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return D3DFMT_L8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
|
||||
texture->impl.stage = 0;
|
||||
texture->impl.mipmap = true;
|
||||
DWORD usage = 0;
|
||||
texture->tex_width = image->width;
|
||||
texture->tex_height = image->height;
|
||||
texture->tex_depth = 1;
|
||||
usage = D3DUSAGE_DYNAMIC;
|
||||
kinc_microsoft_affirm_message(
|
||||
device->CreateTexture(image->width, image->height, 1, usage, convert(image->format), D3DPOOL_DEFAULT, &texture->impl.texture, 0),
|
||||
"Texture creation failed.");
|
||||
D3DLOCKED_RECT rect;
|
||||
kinc_microsoft_affirm(texture->impl.texture->LockRect(0, &rect, 0, 0));
|
||||
texture->impl.pitch = rect.Pitch;
|
||||
uint8_t *from = (uint8_t *)image->data;
|
||||
uint8_t *to = (uint8_t *)rect.pBits;
|
||||
// memcpy(to, from, width * height * sizeOf(format));
|
||||
for (int y = 0; y < image->height; ++y) {
|
||||
for (int x = 0; x < image->width; ++x) {
|
||||
to[rect.Pitch * y + x * 4 + 0 /* blue*/] = (from[y * image->width * 4 + x * 4 + 2]); /// 255.0f;
|
||||
to[rect.Pitch * y + x * 4 + 1 /*green*/] = (from[y * image->width * 4 + x * 4 + 1]); /// 255.0f;
|
||||
to[rect.Pitch * y + x * 4 + 2 /* red*/] = (from[y * image->width * 4 + x * 4 + 0]); /// 255.0f;
|
||||
to[rect.Pitch * y + x * 4 + 3 /*alpha*/] = (from[y * image->width * 4 + x * 4 + 3]); /// 255.0f;
|
||||
}
|
||||
}
|
||||
kinc_microsoft_affirm(texture->impl.texture->UnlockRect(0));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {}
|
||||
|
||||
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
|
||||
texture->impl.stage = 0;
|
||||
texture->impl.mipmap = true;
|
||||
DWORD usage = 0;
|
||||
texture->tex_width = width;
|
||||
texture->tex_height = height;
|
||||
texture->tex_depth = 1;
|
||||
usage = D3DUSAGE_DYNAMIC;
|
||||
kinc_microsoft_affirm_message(device->CreateTexture(width, height, 1, usage, convert(format), D3DPOOL_DEFAULT, &texture->impl.texture, 0),
|
||||
"Texture creation failed.");
|
||||
}
|
||||
|
||||
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
|
||||
kinc_internal_texture_unset(texture);
|
||||
texture->impl.texture->Release();
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, uint32_t unit) {
|
||||
kinc_microsoft_affirm(device->SetTexture(unit, texture->impl.texture));
|
||||
texture->impl.stage = unit;
|
||||
setTextures[texture->impl.stage] = texture;
|
||||
}
|
||||
#else
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
|
||||
kinc_microsoft_affirm(device->SetTexture(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], texture->impl.texture));
|
||||
texture->impl.stage = unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT];
|
||||
setTextures[texture->impl.stage] = texture;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_internal_texture_unset(struct kinc_g4_texture *texture) {
|
||||
if (setTextures[texture->impl.stage] == texture) {
|
||||
device->SetTexture(texture->impl.stage, nullptr);
|
||||
setTextures[texture->impl.stage] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
|
||||
D3DLOCKED_RECT rect;
|
||||
kinc_microsoft_affirm(texture->impl.texture->LockRect(0, &rect, 0, 0));
|
||||
texture->impl.pitch = rect.Pitch;
|
||||
return (uint8_t *)rect.pBits;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
|
||||
kinc_microsoft_affirm(texture->impl.texture->UnlockRect(0));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {}
|
||||
|
||||
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
|
||||
return texture->impl.pitch;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {}
|
||||
|
||||
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {}
|
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct IDirect3DTexture9;
|
||||
|
||||
typedef struct {
|
||||
struct IDirect3DTexture9 *texture;
|
||||
int stage;
|
||||
bool mipmap;
|
||||
uint8_t pixfmt;
|
||||
int pitch;
|
||||
} kinc_g4_texture_impl_t;
|
||||
|
||||
struct kinc_g4_texture;
|
||||
|
||||
void kinc_internal_texture_unmipmap(struct kinc_g4_texture *texture);
|
||||
void kinc_internal_texture_unset(struct kinc_g4_texture *texture);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,5 @@
|
||||
#include <kinc/graphics4/texturearray.h>
|
||||
|
||||
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {}
|
||||
|
||||
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} kinc_g4_texture_array_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,75 @@
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
struct kinc_g4_vertex_buffer *kinc_internal_current_vertex_buffer = NULL;
|
||||
|
||||
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int count, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
|
||||
int instance_data_step_rate) {
|
||||
buffer->impl.myCount = count;
|
||||
buffer->impl.instanceDataStepRate = instance_data_step_rate;
|
||||
DWORD usageFlags = D3DUSAGE_WRITEONLY;
|
||||
if (usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
usageFlags = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
|
||||
}
|
||||
|
||||
buffer->impl.myStride = 0;
|
||||
for (int i = 0; i < structure->size; ++i) {
|
||||
buffer->impl.myStride += kinc_g4_vertex_data_size(structure->elements[i].data);
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(device->CreateVertexBuffer(kinc_g4_vertex_buffer_stride(buffer) * count, usageFlags, 0, D3DPOOL_DEFAULT, &buffer->impl.vb, 0));
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
|
||||
buffer->impl.vb->Release();
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return kinc_g4_vertex_buffer_lock(buffer, 0, kinc_g4_vertex_buffer_count(buffer));
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
|
||||
float *vertices;
|
||||
kinc_internal_vertex_buffer_unset(buffer);
|
||||
kinc_microsoft_affirm(buffer->impl.vb->Lock(start, count * kinc_g4_vertex_buffer_stride(buffer), (void **)&vertices, D3DLOCK_DISCARD));
|
||||
return vertices;
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
kinc_microsoft_affirm(buffer->impl.vb->Unlock());
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
|
||||
kinc_microsoft_affirm(buffer->impl.vb->Unlock());
|
||||
}
|
||||
|
||||
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
|
||||
buffer->impl._offset = offset;
|
||||
if (buffer->impl.instanceDataStepRate == 0) {
|
||||
kinc_internal_current_vertex_buffer = buffer;
|
||||
}
|
||||
else {
|
||||
kinc_microsoft_affirm(device->SetStreamSourceFreq(offset, (D3DSTREAMSOURCE_INSTANCEDATA | buffer->impl.instanceDataStepRate)));
|
||||
}
|
||||
kinc_microsoft_affirm(device->SetStreamSource(offset, buffer->impl.vb, 0, kinc_g4_vertex_buffer_stride(buffer)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kinc_internal_vertex_buffer_unset(struct kinc_g4_vertex_buffer *buffer) {
|
||||
if (kinc_internal_current_vertex_buffer == buffer) {
|
||||
kinc_microsoft_affirm(device->SetStreamSource(0, NULL, 0, 0));
|
||||
kinc_internal_current_vertex_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.myCount;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.myStride;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct IDirect3DVertexBuffer9;
|
||||
|
||||
typedef struct {
|
||||
struct IDirect3DVertexBuffer9 *vb;
|
||||
int myCount;
|
||||
int myStride;
|
||||
int instanceDataStepRate;
|
||||
int _offset;
|
||||
} kinc_g4_vertex_buffer_impl_t;
|
||||
|
||||
struct kinc_g4_vertex_buffer;
|
||||
|
||||
void kinc_internal_vertex_buffer_unset(struct kinc_g4_vertex_buffer *buffer);
|
||||
|
||||
extern struct kinc_g4_vertex_buffer *kinc_internal_current_vertex_buffer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,841 @@
|
||||
#include "G4.h"
|
||||
#include "kinc/graphics4/graphics.h"
|
||||
#include "kinc/window.h"
|
||||
|
||||
#include <kinc/backend/graphics4/indexbuffer.h>
|
||||
#include <kinc/backend/graphics4/pipeline.h>
|
||||
#include <kinc/backend/graphics4/vertexbuffer.h>
|
||||
#include <kinc/color.h>
|
||||
#include <kinc/graphics4/compute.h>
|
||||
#include <kinc/graphics4/constantbuffer.h>
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/graphics4/texturearray.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
#include <kinc/graphics5/commandlist.h>
|
||||
#include <kinc/graphics5/constantbuffer.h>
|
||||
#include <kinc/graphics5/graphics.h>
|
||||
#include <kinc/graphics5/sampler.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
#include <kinc/math/core.h>
|
||||
#include <kinc/math/matrix.h>
|
||||
#include <kinc/system.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
kinc_g5_command_list_t commandList;
|
||||
|
||||
uint64_t frameNumber = 0;
|
||||
bool waitAfterNextDraw = false;
|
||||
|
||||
static kinc_g5_constant_buffer_t vertexConstantBuffer;
|
||||
static kinc_g5_constant_buffer_t fragmentConstantBuffer;
|
||||
#define constantBufferSize 4096
|
||||
#define constantBufferMultiply 100
|
||||
static int constantBufferIndex = 0;
|
||||
|
||||
void kinc_g4_internal_init(void) {
|
||||
kinc_g5_internal_init();
|
||||
}
|
||||
|
||||
void kinc_g4_internal_destroy(void) {
|
||||
kinc_g5_internal_destroy();
|
||||
}
|
||||
|
||||
void kinc_g4_internal_destroy_window(int window) {
|
||||
kinc_g5_internal_destroy_window(window);
|
||||
}
|
||||
|
||||
#define bufferCount 2
|
||||
#define renderTargetCount 8
|
||||
|
||||
static struct {
|
||||
int currentBuffer;
|
||||
kinc_g5_render_target_t framebuffers[bufferCount];
|
||||
|
||||
kinc_g4_render_target_t *current_render_targets[renderTargetCount];
|
||||
int current_render_target_count;
|
||||
|
||||
bool resized;
|
||||
} windows[16] = {0};
|
||||
|
||||
static int current_window;
|
||||
|
||||
#define MAX_VERTEX_BUFFERS 16
|
||||
#define MAX_TEXTURES 16
|
||||
|
||||
typedef struct render_state {
|
||||
kinc_g5_pipeline_t *pipeline;
|
||||
|
||||
kinc_g5_index_buffer_t *index_buffer;
|
||||
|
||||
kinc_g5_vertex_buffer_t *vertex_buffers[MAX_VERTEX_BUFFERS];
|
||||
int vertex_buffer_offsets[MAX_VERTEX_BUFFERS];
|
||||
int vertex_buffer_count;
|
||||
|
||||
bool blend_constant_set;
|
||||
float blend_constant_r;
|
||||
float blend_constant_g;
|
||||
float blend_constant_b;
|
||||
float blend_constant_a;
|
||||
|
||||
bool viewport_set;
|
||||
int viewport_x;
|
||||
int viewport_y;
|
||||
int viewport_width;
|
||||
int viewport_height;
|
||||
|
||||
bool scissor_set;
|
||||
int scissor_x;
|
||||
int scissor_y;
|
||||
int scissor_width;
|
||||
int scissor_height;
|
||||
|
||||
kinc_g5_texture_t *textures[MAX_TEXTURES];
|
||||
kinc_g5_texture_unit_t texture_units[MAX_TEXTURES];
|
||||
int texture_count;
|
||||
|
||||
kinc_g5_render_target_t *render_targets[MAX_TEXTURES];
|
||||
kinc_g5_texture_unit_t render_target_units[MAX_TEXTURES];
|
||||
int render_target_count;
|
||||
|
||||
kinc_g5_render_target_t *depth_render_targets[MAX_TEXTURES];
|
||||
kinc_g5_texture_unit_t depth_render_target_units[MAX_TEXTURES];
|
||||
int depth_render_target_count;
|
||||
|
||||
uint8_t vertex_constant_data[constantBufferSize];
|
||||
uint8_t fragment_constant_data[constantBufferSize];
|
||||
} render_state;
|
||||
|
||||
static render_state current_state;
|
||||
|
||||
void kinc_g4_on_g5_internal_resize(int window, int width, int height) {
|
||||
windows[window].resized = true;
|
||||
}
|
||||
|
||||
void kinc_g4_on_g5_internal_restore_render_target(void) {
|
||||
windows[current_window].current_render_targets[0] = NULL;
|
||||
kinc_g5_render_target_t *render_target = &windows[current_window].framebuffers[windows[current_window].currentBuffer];
|
||||
kinc_g5_command_list_set_render_targets(&commandList, &render_target, 1);
|
||||
windows[current_window].current_render_target_count = 1;
|
||||
}
|
||||
|
||||
void kinc_g4_internal_init_window(int window, int depthBufferBits, int stencilBufferBits, bool vsync) {
|
||||
kinc_g5_internal_init_window(window, depthBufferBits, stencilBufferBits, vsync);
|
||||
|
||||
kinc_g5_command_list_init(&commandList);
|
||||
windows[window].currentBuffer = -1;
|
||||
for (int i = 0; i < bufferCount; ++i) {
|
||||
kinc_g5_render_target_init_framebuffer(&windows[window].framebuffers[i], kinc_window_width(window), kinc_window_height(window),
|
||||
KINC_G5_RENDER_TARGET_FORMAT_32BIT, depthBufferBits, 0);
|
||||
}
|
||||
kinc_g5_constant_buffer_init(&vertexConstantBuffer, constantBufferSize * constantBufferMultiply);
|
||||
kinc_g5_constant_buffer_init(&fragmentConstantBuffer, constantBufferSize * constantBufferMultiply);
|
||||
|
||||
// to support doing work after kinc_g4_end and before kinc_g4_begin
|
||||
kinc_g5_command_list_begin(&commandList);
|
||||
}
|
||||
|
||||
void kinc_g4_on_g5_internal_set_samplers(int count, kinc_g5_texture_unit_t *texture_units) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
for (int j = 0; j < KINC_G5_SHADER_TYPE_COUNT; ++j) {
|
||||
if (texture_units[i].stages[j] >= 0) {
|
||||
kinc_g5_sampler_t *sampler = get_current_sampler(j, texture_units[i].stages[j]);
|
||||
kinc_g5_texture_unit_t unit;
|
||||
for (int k = 0; k < KINC_G5_SHADER_TYPE_COUNT; ++k) {
|
||||
unit.stages[k] = -1;
|
||||
}
|
||||
unit.stages[j] = texture_units[i].stages[j];
|
||||
kinc_g5_command_list_set_sampler(&commandList, unit, sampler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void startDraw(void) {
|
||||
if ((constantBufferIndex + 1) >= constantBufferMultiply || waitAfterNextDraw) {
|
||||
memcpy(current_state.vertex_constant_data, vertexConstantBuffer.data, constantBufferSize);
|
||||
memcpy(current_state.fragment_constant_data, fragmentConstantBuffer.data, constantBufferSize);
|
||||
}
|
||||
kinc_g5_constant_buffer_unlock(&vertexConstantBuffer);
|
||||
kinc_g5_constant_buffer_unlock(&fragmentConstantBuffer);
|
||||
|
||||
kinc_g4_on_g5_internal_set_samplers(current_state.texture_count, current_state.texture_units);
|
||||
kinc_g4_on_g5_internal_set_samplers(current_state.render_target_count, current_state.render_target_units);
|
||||
kinc_g4_on_g5_internal_set_samplers(current_state.depth_render_target_count, current_state.depth_render_target_units);
|
||||
|
||||
kinc_g5_command_list_set_vertex_constant_buffer(&commandList, &vertexConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
|
||||
kinc_g5_command_list_set_fragment_constant_buffer(&commandList, &fragmentConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
|
||||
}
|
||||
|
||||
static void endDraw(void) {
|
||||
++constantBufferIndex;
|
||||
if (constantBufferIndex >= constantBufferMultiply || waitAfterNextDraw) {
|
||||
kinc_g5_command_list_end(&commandList);
|
||||
kinc_g5_command_list_execute(&commandList);
|
||||
kinc_g5_command_list_wait_for_execution_to_finish(&commandList);
|
||||
kinc_g5_command_list_begin(&commandList);
|
||||
if (windows[current_window].current_render_targets[0] == NULL) {
|
||||
kinc_g4_on_g5_internal_restore_render_target();
|
||||
}
|
||||
else {
|
||||
const int count = windows[current_window].current_render_target_count;
|
||||
kinc_g5_render_target_t *render_targets[16];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
render_targets[i] = &windows[current_window].current_render_targets[i]->impl._renderTarget;
|
||||
}
|
||||
kinc_g5_command_list_set_render_targets(&commandList, render_targets, count);
|
||||
}
|
||||
|
||||
if (current_state.pipeline != NULL) {
|
||||
kinc_g5_command_list_set_pipeline(&commandList, current_state.pipeline);
|
||||
}
|
||||
if (current_state.index_buffer != NULL) {
|
||||
kinc_g5_command_list_set_index_buffer(&commandList, current_state.index_buffer);
|
||||
}
|
||||
if (current_state.vertex_buffer_count > 0) {
|
||||
kinc_g5_command_list_set_vertex_buffers(&commandList, current_state.vertex_buffers, current_state.vertex_buffer_offsets,
|
||||
current_state.vertex_buffer_count);
|
||||
}
|
||||
if (current_state.blend_constant_set) {
|
||||
kinc_g5_command_list_set_blend_constant(&commandList, current_state.blend_constant_r, current_state.blend_constant_g,
|
||||
current_state.blend_constant_b, current_state.blend_constant_a);
|
||||
}
|
||||
if (current_state.viewport_set) {
|
||||
kinc_g5_command_list_viewport(&commandList, current_state.viewport_x, current_state.viewport_y, current_state.viewport_width,
|
||||
current_state.viewport_height);
|
||||
}
|
||||
if (current_state.scissor_set) {
|
||||
kinc_g5_command_list_scissor(&commandList, current_state.scissor_x, current_state.scissor_y, current_state.scissor_width,
|
||||
current_state.scissor_height);
|
||||
}
|
||||
for (int i = 0; i < current_state.texture_count; ++i) {
|
||||
kinc_g5_command_list_set_texture(&commandList, current_state.texture_units[i], current_state.textures[i]);
|
||||
}
|
||||
for (int i = 0; i < current_state.render_target_count; ++i) {
|
||||
kinc_g5_command_list_set_texture_from_render_target(&commandList, current_state.render_target_units[i], current_state.render_targets[i]);
|
||||
}
|
||||
for (int i = 0; i < current_state.depth_render_target_count; ++i) {
|
||||
kinc_g5_command_list_set_texture_from_render_target_depth(&commandList, current_state.depth_render_target_units[i],
|
||||
current_state.depth_render_targets[i]);
|
||||
}
|
||||
constantBufferIndex = 0;
|
||||
waitAfterNextDraw = false;
|
||||
|
||||
kinc_g5_constant_buffer_lock(&vertexConstantBuffer, 0, constantBufferSize);
|
||||
kinc_g5_constant_buffer_lock(&fragmentConstantBuffer, 0, constantBufferSize);
|
||||
|
||||
memcpy(vertexConstantBuffer.data, current_state.vertex_constant_data, constantBufferSize);
|
||||
memcpy(fragmentConstantBuffer.data, current_state.fragment_constant_data, constantBufferSize);
|
||||
}
|
||||
else {
|
||||
kinc_g5_constant_buffer_lock(&vertexConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
|
||||
kinc_g5_constant_buffer_lock(&fragmentConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices(void) {
|
||||
startDraw();
|
||||
kinc_g5_command_list_draw_indexed_vertices(&commandList);
|
||||
endDraw();
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_from_to(int start, int count) {
|
||||
startDraw();
|
||||
kinc_g5_command_list_draw_indexed_vertices_from_to(&commandList, start, count);
|
||||
endDraw();
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_from_to_from(int start, int count, int vertex_offset) {
|
||||
startDraw();
|
||||
kinc_g5_command_list_draw_indexed_vertices_from_to_from(&commandList, start, count, vertex_offset);
|
||||
endDraw();
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_instanced(int instanceCount) {
|
||||
startDraw();
|
||||
kinc_g5_command_list_draw_indexed_vertices_instanced(&commandList, instanceCount);
|
||||
endDraw();
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_instanced_from_to(int instanceCount, int start, int count) {
|
||||
startDraw();
|
||||
kinc_g5_command_list_draw_indexed_vertices_instanced_from_to(&commandList, instanceCount, start, count);
|
||||
endDraw();
|
||||
}
|
||||
|
||||
void kinc_g4_clear(unsigned flags, unsigned color, float depth, int stencil) {
|
||||
if (windows[current_window].current_render_target_count > 0) {
|
||||
if (windows[current_window].current_render_targets[0] == NULL) {
|
||||
kinc_g5_command_list_clear(&commandList, &windows[current_window].framebuffers[windows[current_window].currentBuffer], flags, color, depth,
|
||||
stencil);
|
||||
}
|
||||
else {
|
||||
if (windows[current_window].current_render_targets[0]->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET) {
|
||||
kinc_g5_command_list_texture_to_render_target_barrier(&commandList, &windows[current_window].current_render_targets[0]->impl._renderTarget);
|
||||
windows[current_window].current_render_targets[0]->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
|
||||
}
|
||||
kinc_g5_command_list_clear(&commandList, &windows[current_window].current_render_targets[0]->impl._renderTarget, flags, color, depth, stencil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool first_run = true;
|
||||
|
||||
void kinc_g4_begin(int window) {
|
||||
// to support doing work after kinc_g4_end and before kinc_g4_begin
|
||||
kinc_g5_command_list_end(&commandList);
|
||||
kinc_g5_command_list_execute(&commandList);
|
||||
|
||||
current_window = window;
|
||||
|
||||
windows[current_window].currentBuffer = (windows[current_window].currentBuffer + 1) % bufferCount;
|
||||
|
||||
bool resized = windows[window].resized;
|
||||
if (resized) {
|
||||
for (int i = 0; i < bufferCount; ++i) {
|
||||
kinc_g5_render_target_destroy(&windows[current_window].framebuffers[i]);
|
||||
}
|
||||
windows[current_window].currentBuffer = 0;
|
||||
}
|
||||
|
||||
kinc_g5_begin(&windows[current_window].framebuffers[windows[current_window].currentBuffer], window);
|
||||
|
||||
if (resized) {
|
||||
for (int i = 0; i < bufferCount; ++i) {
|
||||
kinc_g5_render_target_init_framebuffer(&windows[current_window].framebuffers[i], kinc_window_width(window), kinc_window_height(window),
|
||||
KINC_G5_RENDER_TARGET_FORMAT_32BIT, 16, 0);
|
||||
}
|
||||
windows[window].resized = false;
|
||||
}
|
||||
|
||||
windows[current_window].current_render_targets[0] = NULL;
|
||||
windows[current_window].current_render_target_count = 1;
|
||||
|
||||
current_state.pipeline = NULL;
|
||||
current_state.index_buffer = NULL;
|
||||
for (int i = 0; i < MAX_VERTEX_BUFFERS; ++i) {
|
||||
current_state.vertex_buffers[i] = NULL;
|
||||
current_state.vertex_buffer_offsets[i] = 0;
|
||||
}
|
||||
current_state.vertex_buffer_count = 0;
|
||||
current_state.blend_constant_set = false;
|
||||
current_state.viewport_set = false;
|
||||
current_state.scissor_set = false;
|
||||
current_state.texture_count = 0;
|
||||
current_state.render_target_count = 0;
|
||||
current_state.depth_render_target_count = 0;
|
||||
|
||||
samplers_reset();
|
||||
|
||||
// commandList = new Graphics5::CommandList;
|
||||
kinc_g5_command_list_begin(&commandList);
|
||||
|
||||
// Currently we do not necessarily wait at the end of a frame so for now it's endDraw
|
||||
// constantBufferIndex = 0;
|
||||
// kinc_g5_constant_buffer_lock(&vertexConstantBuffer, 0, constantBufferSize);
|
||||
// kinc_g5_constant_buffer_lock(&fragmentConstantBuffer, 0, constantBufferSize);
|
||||
endDraw();
|
||||
|
||||
kinc_g5_command_list_framebuffer_to_render_target_barrier(&commandList, &windows[current_window].framebuffers[windows[current_window].currentBuffer]);
|
||||
kinc_g4_restore_render_target();
|
||||
|
||||
++frameNumber;
|
||||
}
|
||||
|
||||
void kinc_g4_viewport(int x, int y, int width, int height) {
|
||||
current_state.viewport_x = x;
|
||||
current_state.viewport_y = y;
|
||||
current_state.viewport_width = width;
|
||||
current_state.viewport_height = height;
|
||||
current_state.viewport_set = true;
|
||||
kinc_g5_command_list_viewport(&commandList, x, y, width, height);
|
||||
}
|
||||
|
||||
void kinc_g4_scissor(int x, int y, int width, int height) {
|
||||
current_state.scissor_x = x;
|
||||
current_state.scissor_y = y;
|
||||
current_state.scissor_width = width;
|
||||
current_state.scissor_height = height;
|
||||
current_state.scissor_set = true;
|
||||
kinc_g5_command_list_scissor(&commandList, x, y, width, height);
|
||||
}
|
||||
|
||||
void kinc_g4_disable_scissor(void) {
|
||||
current_state.scissor_set = false;
|
||||
kinc_g5_command_list_disable_scissor(&commandList);
|
||||
}
|
||||
|
||||
void kinc_g4_end(int window) {
|
||||
kinc_g5_constant_buffer_unlock(&vertexConstantBuffer);
|
||||
kinc_g5_constant_buffer_unlock(&fragmentConstantBuffer);
|
||||
|
||||
kinc_g5_command_list_render_target_to_framebuffer_barrier(&commandList, &windows[current_window].framebuffers[windows[current_window].currentBuffer]);
|
||||
kinc_g5_command_list_end(&commandList);
|
||||
kinc_g5_command_list_execute(&commandList);
|
||||
|
||||
// delete commandList;
|
||||
// commandList = nullptr;
|
||||
kinc_g5_end(window);
|
||||
|
||||
// to support doing work after kinc_g4_end and before kinc_g4_begin
|
||||
kinc_g5_command_list_begin(&commandList);
|
||||
}
|
||||
|
||||
/*void Graphics4::_changeFramebuffer(int window, Kore::FramebufferOptions* frame) {
|
||||
|
||||
}*/
|
||||
|
||||
bool kinc_g4_swap_buffers(void) {
|
||||
return kinc_g5_swap_buffers();
|
||||
}
|
||||
|
||||
void kinc_g4_flush(void) {
|
||||
kinc_g5_flush();
|
||||
}
|
||||
|
||||
void kinc_g4_set_stencil_reference_value(int value) {}
|
||||
|
||||
void kinc_g4_set_int(kinc_g4_constant_location_t location, int value) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_int(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_int(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_int2(kinc_g4_constant_location_t location, int value1, int value2) {}
|
||||
|
||||
void kinc_g4_set_int3(kinc_g4_constant_location_t location, int value1, int value2, int value3) {}
|
||||
|
||||
void kinc_g4_set_int4(kinc_g4_constant_location_t location, int value1, int value2, int value3, int value4) {}
|
||||
|
||||
void kinc_g4_set_ints(kinc_g4_constant_location_t location, int *values, int count) {}
|
||||
|
||||
void kinc_g4_set_float(kinc_g4_constant_location_t location, float value) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float2(kinc_g4_constant_location_t location, float value1, float value2) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float2(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value1, value2);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float2(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value1, value2);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float3(kinc_g4_constant_location_t location, float value1, float value2, float value3) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float3(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value1, value2, value3);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float3(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value1, value2, value3);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float4(kinc_g4_constant_location_t location, float value1, float value2, float value3, float value4) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float4(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value1, value2, value3, value4);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float4(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value1, value2, value3, value4);
|
||||
}
|
||||
|
||||
void kinc_g4_set_floats(kinc_g4_constant_location_t location, float *values, int count) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_floats(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, values, count);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_floats(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, values, count);
|
||||
}
|
||||
|
||||
void kinc_g4_set_bool(kinc_g4_constant_location_t location, bool value) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_bool(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_bool(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_matrix4(kinc_g4_constant_location_t location, kinc_matrix4x4_t *value) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_matrix4(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_matrix4(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_matrix3(kinc_g4_constant_location_t location, kinc_matrix3x3_t *value) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_matrix3(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_matrix3(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit.stages[i] >= 0) {
|
||||
if (dir == KINC_G4_TEXTURE_DIRECTION_U) {
|
||||
sampler_options[i][unit.stages[i]].u_addressing = (kinc_g5_texture_addressing_t)addressing;
|
||||
}
|
||||
if (dir == KINC_G4_TEXTURE_DIRECTION_V) {
|
||||
sampler_options[i][unit.stages[i]].v_addressing = (kinc_g5_texture_addressing_t)addressing;
|
||||
}
|
||||
if (dir == KINC_G4_TEXTURE_DIRECTION_W) {
|
||||
sampler_options[i][unit.stages[i]].w_addressing = (kinc_g5_texture_addressing_t)addressing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
|
||||
kinc_g4_set_texture_addressing(unit, dir, addressing);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (texunit.stages[i] >= 0) {
|
||||
sampler_options[i][texunit.stages[i]].magnification_filter = (kinc_g5_texture_filter_t)filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
kinc_g4_set_texture_magnification_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (texunit.stages[i] >= 0) {
|
||||
sampler_options[i][texunit.stages[i]].minification_filter = (kinc_g5_texture_filter_t)filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
kinc_g4_set_texture_minification_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (texunit.stages[i] >= 0) {
|
||||
sampler_options[i][texunit.stages[i]].mipmap_filter = (kinc_g5_mipmap_filter_t)filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
|
||||
kinc_g4_set_texture_mipmap_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit.stages[i] >= 0) {
|
||||
sampler_options[i][unit.stages[i]].is_comparison = enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit.stages[i] >= 0) {
|
||||
sampler_options[i][unit.stages[i]].compare_mode = (kinc_g5_compare_mode_t)mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_cubemap_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {}
|
||||
void kinc_g4_set_cubemap_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {}
|
||||
|
||||
void kinc_g4_set_texture_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit.stages[i] >= 0) {
|
||||
sampler_options[i][unit.stages[i]].max_anisotropy = max_anisotropy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_cubemap_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {}
|
||||
|
||||
void kinc_g4_set_texture_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit.stages[i] >= 0) {
|
||||
sampler_options[i][unit.stages[i]].lod_min_clamp = lod_min_clamp;
|
||||
sampler_options[i][unit.stages[i]].lod_max_clamp = lod_max_clamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_cubemap_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {}
|
||||
|
||||
void kinc_g4_restore_render_target(void) {
|
||||
kinc_g4_on_g5_internal_restore_render_target();
|
||||
current_state.viewport_set = false;
|
||||
current_state.scissor_set = false;
|
||||
}
|
||||
|
||||
void kinc_g4_set_render_targets(kinc_g4_render_target_t **targets, int count) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
windows[current_window].current_render_targets[i] = targets[i];
|
||||
if (windows[current_window].current_render_targets[i]->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET) {
|
||||
kinc_g5_command_list_texture_to_render_target_barrier(&commandList, &windows[current_window].current_render_targets[i]->impl._renderTarget);
|
||||
windows[current_window].current_render_targets[i]->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
|
||||
}
|
||||
}
|
||||
windows[current_window].current_render_target_count = count;
|
||||
kinc_g5_render_target_t *render_targets[16];
|
||||
assert(count <= 16);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
render_targets[i] = &targets[i]->impl._renderTarget;
|
||||
}
|
||||
kinc_g5_command_list_set_render_targets(&commandList, render_targets, count);
|
||||
current_state.viewport_set = false;
|
||||
current_state.scissor_set = false;
|
||||
}
|
||||
|
||||
void kinc_g4_set_render_target_face(kinc_g4_render_target_t *texture, int face) {
|
||||
kinc_g5_command_list_set_render_target_face(&commandList, &texture->impl._renderTarget, face);
|
||||
current_state.viewport_set = false;
|
||||
current_state.scissor_set = false;
|
||||
}
|
||||
|
||||
void kinc_g4_set_vertex_buffers(kinc_g4_vertex_buffer_t **buffers, int count) {
|
||||
assert(count <= MAX_VERTEX_BUFFERS);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
current_state.vertex_buffers[i] = &buffers[i]->impl._buffer;
|
||||
int index = buffers[i]->impl._currentIndex;
|
||||
current_state.vertex_buffer_offsets[i] = index * kinc_g4_vertex_buffer_count(buffers[i]);
|
||||
}
|
||||
current_state.vertex_buffer_count = count;
|
||||
kinc_g5_command_list_set_vertex_buffers(&commandList, current_state.vertex_buffers, current_state.vertex_buffer_offsets, count);
|
||||
}
|
||||
|
||||
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
|
||||
kinc_g4_vertex_buffer_t *buffers[1];
|
||||
buffers[0] = buffer;
|
||||
kinc_g4_set_vertex_buffers(buffers, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kinc_g4_set_index_buffer(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_g5_index_buffer_t *g5_index_buffer = &buffer->impl._buffer;
|
||||
current_state.index_buffer = g5_index_buffer;
|
||||
kinc_g5_command_list_set_index_buffer(&commandList, g5_index_buffer);
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_set_texture(uint32_t unit, kinc_g4_texture_t *texture) {
|
||||
if (!texture->impl._uploaded) {
|
||||
kinc_g5_command_list_upload_texture(&commandList, &texture->impl._texture);
|
||||
texture->impl._uploaded = true;
|
||||
}
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g5_texture_unit_t g5_unit = {0};
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
g5_unit.stages[i] = unit;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < current_state.texture_count; ++i) {
|
||||
if (kinc_g5_texture_unit_equals(¤t_state.texture_units[i], &g5_unit)) {
|
||||
current_state.textures[i] = &texture->impl._texture;
|
||||
current_state.texture_units[i] = g5_unit;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(current_state.texture_count < MAX_TEXTURES);
|
||||
current_state.textures[current_state.texture_count] = &texture->impl._texture;
|
||||
current_state.texture_units[current_state.texture_count] = g5_unit;
|
||||
current_state.texture_count += 1;
|
||||
}
|
||||
|
||||
kinc_g5_command_list_set_texture(&commandList, g5_unit, &texture->impl._texture);
|
||||
}
|
||||
#else
|
||||
void kinc_g4_set_texture(kinc_g4_texture_unit_t unit, kinc_g4_texture_t *texture) {
|
||||
if (!texture->impl._uploaded) {
|
||||
kinc_g5_command_list_upload_texture(&commandList, &texture->impl._texture);
|
||||
texture->impl._uploaded = true;
|
||||
}
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g5_texture_unit_t g5_unit;
|
||||
memcpy(&g5_unit.stages[0], &unit.stages[0], KINC_G5_SHADER_TYPE_COUNT * sizeof(int));
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < current_state.texture_count; ++i) {
|
||||
if (kinc_g5_texture_unit_equals(¤t_state.texture_units[i], &g5_unit)) {
|
||||
current_state.textures[i] = &texture->impl._texture;
|
||||
current_state.texture_units[i] = g5_unit;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(current_state.texture_count < MAX_TEXTURES);
|
||||
current_state.textures[current_state.texture_count] = &texture->impl._texture;
|
||||
current_state.texture_units[current_state.texture_count] = g5_unit;
|
||||
current_state.texture_count += 1;
|
||||
}
|
||||
|
||||
kinc_g5_command_list_set_texture(&commandList, g5_unit, &texture->impl._texture);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_set_image_texture(kinc_g4_texture_unit_t unit, kinc_g4_texture_t *texture) {}
|
||||
|
||||
int kinc_g4_max_bound_textures(void) {
|
||||
return kinc_g5_max_bound_textures();
|
||||
}
|
||||
|
||||
bool kinc_g4_init_occlusion_query(unsigned *occlusionQuery) {
|
||||
return kinc_g5_command_list_init_occlusion_query(&commandList, occlusionQuery);
|
||||
}
|
||||
|
||||
void kinc_g4_delete_occlusion_query(unsigned occlusionQuery) {
|
||||
kinc_g5_command_list_delete_occlusion_query(&commandList, occlusionQuery);
|
||||
}
|
||||
|
||||
bool kinc_g4_are_query_results_available(unsigned occlusionQuery) {
|
||||
return kinc_g5_command_list_are_query_results_available(&commandList, occlusionQuery);
|
||||
}
|
||||
|
||||
void kinc_g4_get_query_result(unsigned occlusionQuery, unsigned *pixelCount) {
|
||||
kinc_g5_command_list_get_query_result(&commandList, occlusionQuery, pixelCount);
|
||||
}
|
||||
|
||||
void kinc_g4_set_pipeline(kinc_g4_pipeline_t *pipeline) {
|
||||
kinc_g5_pipeline_t *g5_pipeline = &pipeline->impl._pipeline;
|
||||
current_state.pipeline = g5_pipeline;
|
||||
kinc_g5_command_list_set_pipeline(&commandList, g5_pipeline);
|
||||
}
|
||||
|
||||
void kinc_g4_set_blend_constant(float r, float g, float b, float a) {
|
||||
current_state.blend_constant_set = true;
|
||||
current_state.blend_constant_r = r;
|
||||
current_state.blend_constant_g = g;
|
||||
current_state.blend_constant_b = b;
|
||||
current_state.blend_constant_a = a;
|
||||
kinc_g5_command_list_set_blend_constant(&commandList, r, g, b, a);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_array(kinc_g4_texture_unit_t unit, struct kinc_g4_texture_array *array) {}
|
||||
|
||||
bool kinc_g4_supports_instanced_rendering(void) {
|
||||
return kinc_g5_supports_instanced_rendering();
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_compute_shaders(void) {
|
||||
return kinc_g5_supports_compute_shaders();
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_blend_constants(void) {
|
||||
return kinc_g5_supports_blend_constants();
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_non_pow2_textures(void) {
|
||||
return kinc_g5_supports_non_pow2_textures();
|
||||
}
|
||||
|
||||
bool kinc_g4_render_targets_inverted_y(void) {
|
||||
return kinc_g5_render_targets_inverted_y();
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *render_target, uint32_t unit) {
|
||||
if (render_target->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE) {
|
||||
kinc_g5_command_list_render_target_to_texture_barrier(&commandList, &render_target->impl._renderTarget);
|
||||
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
|
||||
}
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g5_texture_unit_t g5_unit = {0};
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
g5_unit.stages[i] = unit;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < current_state.render_target_count; ++i) {
|
||||
if (kinc_g5_texture_unit_equals(¤t_state.render_target_units[i], &g5_unit)) {
|
||||
current_state.render_targets[i] = &render_target->impl._renderTarget;
|
||||
current_state.render_target_units[i] = g5_unit;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(current_state.render_target_count < MAX_TEXTURES);
|
||||
current_state.render_targets[current_state.render_target_count] = &render_target->impl._renderTarget;
|
||||
current_state.render_target_units[current_state.render_target_count] = g5_unit;
|
||||
current_state.render_target_count += 1;
|
||||
}
|
||||
|
||||
kinc_g5_command_list_set_texture_from_render_target(&commandList, g5_unit, &render_target->impl._renderTarget);
|
||||
}
|
||||
#else
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *render_target, kinc_g4_texture_unit_t unit) {
|
||||
if (render_target->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE) {
|
||||
kinc_g5_command_list_render_target_to_texture_barrier(&commandList, &render_target->impl._renderTarget);
|
||||
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
|
||||
}
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g5_texture_unit_t g5_unit;
|
||||
memcpy(&g5_unit.stages[0], &unit.stages[0], KINC_G5_SHADER_TYPE_COUNT * sizeof(int));
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < current_state.render_target_count; ++i) {
|
||||
if (kinc_g5_texture_unit_equals(¤t_state.render_target_units[i], &g5_unit)) {
|
||||
current_state.render_targets[i] = &render_target->impl._renderTarget;
|
||||
current_state.render_target_units[i] = g5_unit;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(current_state.render_target_count < MAX_TEXTURES);
|
||||
current_state.render_targets[current_state.render_target_count] = &render_target->impl._renderTarget;
|
||||
current_state.render_target_units[current_state.render_target_count] = g5_unit;
|
||||
current_state.render_target_count += 1;
|
||||
}
|
||||
|
||||
kinc_g5_command_list_set_texture_from_render_target(&commandList, g5_unit, &render_target->impl._renderTarget);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *render_target, kinc_g4_texture_unit_t unit) {
|
||||
if (render_target->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE) {
|
||||
kinc_g5_command_list_render_target_to_texture_barrier(&commandList, &render_target->impl._renderTarget);
|
||||
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
|
||||
}
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g5_texture_unit_t g5_unit;
|
||||
memcpy(&g5_unit.stages[0], &unit.stages[0], KINC_G5_SHADER_TYPE_COUNT * sizeof(int));
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < current_state.depth_render_target_count; ++i) {
|
||||
if (kinc_g5_texture_unit_equals(¤t_state.depth_render_target_units[i], &g5_unit)) {
|
||||
current_state.depth_render_targets[i] = &render_target->impl._renderTarget;
|
||||
current_state.depth_render_target_units[i] = g5_unit;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(current_state.depth_render_target_count < MAX_TEXTURES);
|
||||
current_state.depth_render_targets[current_state.depth_render_target_count] = &render_target->impl._renderTarget;
|
||||
current_state.depth_render_target_units[current_state.depth_render_target_count] = g5_unit;
|
||||
current_state.depth_render_target_count += 1;
|
||||
}
|
||||
|
||||
kinc_g5_command_list_set_texture_from_render_target_depth(&commandList, g5_unit, &render_target->impl._renderTarget);
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_set_constant_buffer(uint32_t id, struct kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g5_command_list_set_vertex_constant_buffer(&commandList, &buffer->impl.buffer, 0, kinc_g5_constant_buffer_size(&buffer->impl.buffer));
|
||||
}
|
||||
#endif
|
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/math/matrix.h>
|
@ -0,0 +1,35 @@
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/graphics4/constantbuffer.h>
|
||||
|
||||
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
|
||||
kinc_g5_constant_buffer_init(&buffer->impl.buffer, (int)size);
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g5_constant_buffer_destroy(&buffer->impl.buffer);
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g5_constant_buffer_lock_all(&buffer->impl.buffer);
|
||||
return buffer->impl.buffer.data;
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
|
||||
kinc_g5_constant_buffer_lock(&buffer->impl.buffer, (int)start, (int)size);
|
||||
return buffer->impl.buffer.data;
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g5_constant_buffer_unlock(&buffer->impl.buffer);
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {
|
||||
kinc_g5_constant_buffer_unlock(&buffer->impl.buffer);
|
||||
}
|
||||
|
||||
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
|
||||
return kinc_g5_constant_buffer_size(&buffer->impl.buffer);
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/graphics5/constantbuffer.h>
|
||||
|
||||
typedef struct kinc_g4_constant_buffer_impl {
|
||||
kinc_g5_constant_buffer_t buffer;
|
||||
} kinc_g4_constant_buffer_impl;
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
#include "samplers.c.h"
|
||||
|
||||
#include "G4.c.h"
|
||||
#include "constantbuffer.c.h"
|
||||
#include "indexbuffer.c.h"
|
||||
#include "pipeline.c.h"
|
||||
#include "rendertarget.c.h"
|
||||
#include "shader.c.h"
|
||||
#include "texture.c.h"
|
||||
#include "texturearray.c.h"
|
||||
#include "vertexbuffer.c.h"
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IndexBufferImpl.h"
|
||||
#include "RenderTargetImpl.h"
|
||||
#include "TextureImpl.h"
|
||||
#include "VertexBufferImpl.h"
|
@ -0,0 +1,35 @@
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
|
||||
#include <kinc/graphics5/commandlist.h>
|
||||
|
||||
extern kinc_g5_command_list_t commandList;
|
||||
|
||||
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
|
||||
kinc_g5_index_buffer_init(&buffer->impl._buffer, count, (kinc_g5_index_buffer_format_t)format, usage == KINC_G4_USAGE_STATIC);
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_g5_index_buffer_destroy(&buffer->impl._buffer);
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
return kinc_g5_index_buffer_lock_all(&buffer->impl._buffer);
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
|
||||
return kinc_g5_index_buffer_lock(&buffer->impl._buffer, start, count);
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_g5_index_buffer_unlock_all(&buffer->impl._buffer);
|
||||
kinc_g5_command_list_upload_index_buffer(&commandList, &buffer->impl._buffer);
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
|
||||
kinc_g5_index_buffer_unlock(&buffer->impl._buffer, count);
|
||||
kinc_g5_command_list_upload_index_buffer(&commandList, &buffer->impl._buffer);
|
||||
}
|
||||
|
||||
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
|
||||
return kinc_g5_index_buffer_count(&buffer->impl._buffer);
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/indexbuffer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
kinc_g5_index_buffer_t _buffer;
|
||||
} kinc_g4_index_buffer_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,64 @@
|
||||
#include <kinc/backend/graphics4/pipeline.h>
|
||||
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics5/pipeline.h>
|
||||
|
||||
void kinc_g4_pipeline_init(kinc_g4_pipeline_t *pipe) {
|
||||
kinc_g4_internal_pipeline_set_defaults(pipe);
|
||||
kinc_g5_pipeline_init(&pipe->impl._pipeline);
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_destroy(kinc_g4_pipeline_t *pipe) {
|
||||
kinc_g5_pipeline_destroy(&pipe->impl._pipeline);
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(kinc_g4_pipeline_t *pipe, const char *name) {
|
||||
kinc_g4_constant_location_t location;
|
||||
location.impl._location = kinc_g5_pipeline_get_constant_location(&pipe->impl._pipeline, name);
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(kinc_g4_pipeline_t *pipe, const char *name) {
|
||||
kinc_g5_texture_unit_t g5_unit = kinc_g5_pipeline_get_texture_unit(&pipe->impl._pipeline, name);
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g4_texture_unit_t g4_unit;
|
||||
memcpy(&g4_unit.stages[0], &g5_unit.stages[0], KINC_G4_SHADER_TYPE_COUNT * sizeof(int));
|
||||
|
||||
return g4_unit;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *pipe) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
pipe->impl._pipeline.inputLayout[i] = pipe->input_layout[i];
|
||||
}
|
||||
pipe->impl._pipeline.vertexShader = &pipe->vertex_shader->impl._shader;
|
||||
pipe->impl._pipeline.fragmentShader = &pipe->fragment_shader->impl._shader;
|
||||
pipe->impl._pipeline.geometryShader = pipe->geometry_shader != NULL ? &pipe->geometry_shader->impl._shader : NULL;
|
||||
pipe->impl._pipeline.tessellationControlShader = pipe->tessellation_control_shader != NULL ? &pipe->tessellation_control_shader->impl._shader : NULL;
|
||||
pipe->impl._pipeline.tessellationEvaluationShader =
|
||||
pipe->tessellation_evaluation_shader != NULL ? &pipe->tessellation_evaluation_shader->impl._shader : NULL;
|
||||
pipe->impl._pipeline.blend_source = (kinc_g5_blending_factor_t)pipe->blend_source;
|
||||
pipe->impl._pipeline.blend_destination = (kinc_g5_blending_factor_t)pipe->blend_destination;
|
||||
pipe->impl._pipeline.blend_operation = (kinc_g5_blending_operation_t)pipe->blend_operation;
|
||||
pipe->impl._pipeline.alpha_blend_source = (kinc_g5_blending_factor_t)pipe->alpha_blend_source;
|
||||
pipe->impl._pipeline.alpha_blend_destination = (kinc_g5_blending_factor_t)pipe->alpha_blend_destination;
|
||||
pipe->impl._pipeline.alpha_blend_operation = (kinc_g5_blending_operation_t)pipe->alpha_blend_operation;
|
||||
pipe->impl._pipeline.cullMode = (kinc_g5_cull_mode_t)pipe->cull_mode;
|
||||
pipe->impl._pipeline.depthMode = (kinc_g5_compare_mode_t)pipe->depth_mode;
|
||||
pipe->impl._pipeline.depthWrite = pipe->depth_write;
|
||||
pipe->impl._pipeline.colorAttachmentCount = pipe->color_attachment_count;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
pipe->impl._pipeline.colorWriteMaskRed[i] = pipe->color_write_mask_red[i];
|
||||
pipe->impl._pipeline.colorWriteMaskGreen[i] = pipe->color_write_mask_green[i];
|
||||
pipe->impl._pipeline.colorWriteMaskBlue[i] = pipe->color_write_mask_blue[i];
|
||||
pipe->impl._pipeline.colorWriteMaskAlpha[i] = pipe->color_write_mask_alpha[i];
|
||||
pipe->impl._pipeline.colorAttachment[i] = (kinc_g5_render_target_format_t)pipe->color_attachment[i];
|
||||
}
|
||||
pipe->impl._pipeline.depthAttachmentBits = pipe->depth_attachment_bits;
|
||||
pipe->impl._pipeline.stencilAttachmentBits = pipe->stencil_attachment_bits;
|
||||
kinc_g5_pipeline_compile(&pipe->impl._pipeline);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/constantlocation.h>
|
||||
#include <kinc/graphics5/pipeline.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// PipelineStateImpl();
|
||||
kinc_g5_pipeline_t _pipeline;
|
||||
} kinc_g4_pipeline_impl_t;
|
||||
|
||||
typedef struct {
|
||||
kinc_g5_constant_location_t _location;
|
||||
} kinc_g4_constant_location_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} Kinc_G4_AttributeLocationImpl;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,36 @@
|
||||
#include <kinc/backend/graphics4/rendertarget.h>
|
||||
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/graphics5/commandlist.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
extern kinc_g5_command_list_t commandList;
|
||||
|
||||
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *render_target, int width, int height, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
kinc_g5_render_target_init_with_multisampling(&render_target->impl._renderTarget, width, height, (kinc_g5_render_target_format_t)format, depthBufferBits,
|
||||
stencilBufferBits, samples_per_pixel);
|
||||
render_target->texWidth = render_target->width = width;
|
||||
render_target->texHeight = render_target->height = height;
|
||||
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *render_target, int cubeMapSize, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
kinc_g5_render_target_init_cube_with_multisampling(&render_target->impl._renderTarget, cubeMapSize, (kinc_g5_render_target_format_t)format, depthBufferBits,
|
||||
stencilBufferBits, samples_per_pixel);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *render_target) {
|
||||
kinc_g5_render_target_destroy(&render_target->impl._renderTarget);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *render_target, kinc_g4_render_target_t *source) {
|
||||
kinc_g5_render_target_set_depth_stencil_from(&render_target->impl._renderTarget, &source->impl._renderTarget);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *render_target, uint8_t *data) {
|
||||
kinc_g5_command_list_get_render_target_pixels(&commandList, &render_target->impl._renderTarget, data);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *render_target, int levels) {}
|
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/rendertarget.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum kinc_internal_render_target_state { KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET, KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE };
|
||||
|
||||
typedef struct {
|
||||
// RenderTargetImpl(int width, int height, int depthBufferBits, bool antialiasing, Graphics5::RenderTargetFormat format, int stencilBufferBits,
|
||||
// int contextId);
|
||||
// RenderTargetImpl(int cubeMapSize, int depthBufferBits, bool antialiasing, Graphics5::RenderTargetFormat format, int stencilBufferBits, int contextId);
|
||||
kinc_g5_render_target_t _renderTarget;
|
||||
enum kinc_internal_render_target_state state;
|
||||
} kinc_g4_render_target_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,50 @@
|
||||
#include <kinc/graphics5/sampler.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define MAX_SAMPLERS_PER_STAGE 16
|
||||
|
||||
static kinc_g5_sampler_options_t sampler_options[KINC_G5_SHADER_TYPE_COUNT][MAX_SAMPLERS_PER_STAGE];
|
||||
|
||||
static void samplers_reset(void) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
for (int j = 0; j < MAX_SAMPLERS_PER_STAGE; ++j) {
|
||||
kinc_g5_sampler_options_set_defaults(&sampler_options[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool sampler_options_equals(kinc_g5_sampler_options_t *options1, kinc_g5_sampler_options_t *options2) {
|
||||
return options1->u_addressing == options2->u_addressing && options1->v_addressing == options2->v_addressing &&
|
||||
options1->w_addressing == options2->w_addressing && options1->minification_filter == options2->minification_filter &&
|
||||
options1->magnification_filter == options2->magnification_filter && options1->mipmap_filter == options2->mipmap_filter &&
|
||||
options1->lod_min_clamp == options2->lod_min_clamp && options1->lod_max_clamp == options2->lod_max_clamp &&
|
||||
options1->max_anisotropy == options2->max_anisotropy && options1->is_comparison == options2->is_comparison &&
|
||||
options1->compare_mode == options2->compare_mode;
|
||||
}
|
||||
|
||||
struct sampler_cache_entry {
|
||||
kinc_g5_sampler_options_t options;
|
||||
kinc_g5_sampler_t sampler;
|
||||
};
|
||||
|
||||
#define MAX_SAMPLER_CACHE_SIZE 256
|
||||
static struct sampler_cache_entry sampler_cache[MAX_SAMPLER_CACHE_SIZE];
|
||||
static int sampler_cache_size = 0;
|
||||
|
||||
// TODO: Please make this much faster
|
||||
static kinc_g5_sampler_t *get_current_sampler(int stage, int unit) {
|
||||
for (int i = 0; i < sampler_cache_size; ++i) {
|
||||
if (sampler_options_equals(&sampler_cache[i].options, &sampler_options[stage][unit])) {
|
||||
return &sampler_cache[i].sampler;
|
||||
}
|
||||
}
|
||||
|
||||
assert(sampler_cache_size < MAX_SAMPLER_CACHE_SIZE);
|
||||
kinc_g5_sampler_t *sampler = &sampler_cache[sampler_cache_size].sampler;
|
||||
kinc_g5_sampler_init(sampler, &sampler_options[stage][unit]);
|
||||
sampler_cache[sampler_cache_size].options = sampler_options[stage][unit];
|
||||
sampler_cache_size += 1;
|
||||
|
||||
return sampler;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
#include <kinc/graphics4/shader.h>
|
||||
|
||||
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *_data, size_t length, kinc_g4_shader_type_t type) {
|
||||
kinc_g5_shader_init(&shader->impl._shader, _data, length, (kinc_g5_shader_type_t)type);
|
||||
}
|
||||
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
extern int krafix_compile(const char *source, char *output, int *length, const char *targetlang, const char *system, const char *shadertype, int version);
|
||||
#endif
|
||||
|
||||
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
char *output = malloc(1024 * 1024);
|
||||
int length;
|
||||
|
||||
#ifdef KINC_WINDOWS
|
||||
const char *system = "windows";
|
||||
#elif defined(KINC_MACOS)
|
||||
const char *system = "macos";
|
||||
#elif defined(KINC_LINUX)
|
||||
const char *system = "linux";
|
||||
#elif defined(KINC_ANDROID)
|
||||
const char *system = "android";
|
||||
#elif defined(KINC_IOS)
|
||||
const char *system = "ios";
|
||||
#endif
|
||||
|
||||
#ifdef KORE_VULKAN
|
||||
const char *target = "spirv";
|
||||
#elif defined(KORE_METAL)
|
||||
const char *target = "metal";
|
||||
#else
|
||||
const char *target = "d3d11";
|
||||
#endif
|
||||
|
||||
int errors = krafix_compile(source, output, &length, target, system, type == KINC_G4_SHADER_TYPE_FRAGMENT ? "frag" : "vert", -1);
|
||||
if (errors > 0) {
|
||||
return errors;
|
||||
}
|
||||
kinc_g4_shader_init(shader, output, length, type);
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {
|
||||
kinc_g5_shader_destroy(&shader->impl._shader);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/shader.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// ShaderImpl(void *data, int length, Graphics5::ShaderType type);
|
||||
kinc_g5_shader_t _shader;
|
||||
} kinc_g4_shader_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,70 @@
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/graphics5/texture.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
|
||||
#include <kinc/backend/graphics4/texture.h>
|
||||
|
||||
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
|
||||
texture->impl._uploaded = false;
|
||||
kinc_g5_texture_init_from_image(&texture->impl._texture, image);
|
||||
texture->tex_width = texture->impl._texture.texWidth;
|
||||
texture->tex_height = texture->impl._texture.texHeight;
|
||||
texture->tex_depth = 1;
|
||||
texture->format = image->format;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init_from_image3d(kinc_g4_texture_t *texture, kinc_image_t *image) {}
|
||||
|
||||
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
|
||||
texture->impl._uploaded = true;
|
||||
kinc_g5_texture_init(&texture->impl._texture, width, height, format);
|
||||
texture->tex_width = texture->impl._texture.texWidth;
|
||||
texture->tex_height = texture->impl._texture.texHeight;
|
||||
texture->tex_depth = 1;
|
||||
texture->format = format;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {}
|
||||
|
||||
void kinc_g4_texture_init_from_bytes(kinc_g4_texture_t *texture, void *data, int size, const char *format) {}
|
||||
|
||||
void kinc_g4_texture_init_from_bytes3d(kinc_g4_texture_t *texture, void *data, int width, int height, int depth, int format, bool readable) {}
|
||||
|
||||
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
|
||||
// kinc_g4_internal_texture_unset(texture);
|
||||
kinc_g5_texture_destroy(&texture->impl._texture);
|
||||
}
|
||||
|
||||
void kinc_g4_internal_texture_unset(kinc_g4_texture_t *texture) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void kinc_g4_internal_texture_unmipmap(kinc_g4_texture_t *texture) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
|
||||
return kinc_g5_texture_lock(&texture->impl._texture);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
|
||||
kinc_g5_texture_unlock(&texture->impl._texture);
|
||||
texture->impl._uploaded = false;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {
|
||||
kinc_g5_texture_clear(&texture->impl._texture, x, y, z, width, height, depth, color);
|
||||
}
|
||||
|
||||
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
|
||||
return kinc_g5_texture_stride(&texture->impl._texture);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {
|
||||
kinc_g5_texture_generate_mipmaps(&texture->impl._texture, levels);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {
|
||||
kinc_g5_texture_set_mipmap(&texture->impl._texture, mipmap, level);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/texture.h>
|
||||
#include <kinc/graphics5/textureunit.h>
|
||||
#include <kinc/image.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
kinc_g5_texture_unit_t _unit;
|
||||
} kinc_g4_texture_unit_impl_t;
|
||||
|
||||
typedef struct {
|
||||
/*TextureImpl();
|
||||
TextureImpl(int width, int height, Image::Format format, bool readable);
|
||||
TextureImpl(int width, int height, int depth, Image::Format format, bool readable);
|
||||
~TextureImpl();
|
||||
void unmipmap();
|
||||
void unset();*/
|
||||
|
||||
kinc_g5_texture_t _texture;
|
||||
bool _uploaded;
|
||||
} kinc_g4_texture_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,7 @@
|
||||
#include <kinc/graphics4/texturearray.h>
|
||||
|
||||
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {}
|
||||
|
||||
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
|
||||
|
||||
// void TextureArrayImpl::set(TextureUnit unit) {}
|
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// void set(Kore::Graphics4::TextureUnit unit);
|
||||
int nothing;
|
||||
} kinc_g4_texture_array_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,64 @@
|
||||
#include <kinc/backend/graphics4/vertexbuffer.h>
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
|
||||
extern uint64_t frameNumber;
|
||||
extern bool waitAfterNextDraw;
|
||||
|
||||
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int count, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
|
||||
int instanceDataStepRate) {
|
||||
int multiple = usage == KINC_G4_USAGE_STATIC ? 1 : 500;
|
||||
kinc_g5_vertex_buffer_init(&buffer->impl._buffer, count * multiple, structure, usage == KINC_G4_USAGE_STATIC, instanceDataStepRate);
|
||||
buffer->impl._multiple = multiple;
|
||||
buffer->impl._lastFrameNumber = 0;
|
||||
buffer->impl._currentIndex = 0;
|
||||
buffer->impl.myCount = count;
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
|
||||
kinc_g5_vertex_buffer_destroy(&buffer->impl._buffer);
|
||||
}
|
||||
|
||||
static void prepareLock(kinc_g4_vertex_buffer_t *buffer) {
|
||||
/*if (frameNumber > _lastFrameNumber) {
|
||||
_lastFrameNumber = frameNumber;
|
||||
_currentIndex = 0;
|
||||
}
|
||||
else {*/
|
||||
++buffer->impl._currentIndex;
|
||||
if (buffer->impl._currentIndex >= buffer->impl._multiple - 1) {
|
||||
waitAfterNextDraw = true;
|
||||
}
|
||||
if (buffer->impl._currentIndex >= buffer->impl._multiple) {
|
||||
buffer->impl._currentIndex = 0;
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
prepareLock(buffer);
|
||||
return kinc_g5_vertex_buffer_lock(&buffer->impl._buffer, buffer->impl._currentIndex * kinc_g4_vertex_buffer_count(buffer),
|
||||
kinc_g4_vertex_buffer_count(buffer));
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
|
||||
prepareLock(buffer);
|
||||
return kinc_g5_vertex_buffer_lock(&buffer->impl._buffer, start + buffer->impl._currentIndex * kinc_g4_vertex_buffer_count(buffer), count);
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
kinc_g5_vertex_buffer_unlock_all(&buffer->impl._buffer);
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
|
||||
kinc_g5_vertex_buffer_unlock(&buffer->impl._buffer, count);
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.myCount;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return kinc_g5_vertex_buffer_stride(&buffer->impl._buffer);
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/vertexbuffer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int myCount;
|
||||
// void prepareLock();
|
||||
kinc_g5_vertex_buffer_t _buffer;
|
||||
int _currentIndex;
|
||||
int _multiple;
|
||||
uint64_t _lastFrameNumber;
|
||||
} kinc_g4_vertex_buffer_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
2
Kinc/Backends/Graphics4/OpenGL/Sources/GL/.clang-format
Normal file
2
Kinc/Backends/Graphics4/OpenGL/Sources/GL/.clang-format
Normal file
@ -0,0 +1,2 @@
|
||||
DisableFormat: true
|
||||
SortIncludes: false
|
2261
Kinc/Backends/Graphics4/OpenGL/Sources/GL/eglew.h
Normal file
2261
Kinc/Backends/Graphics4/OpenGL/Sources/GL/eglew.h
Normal file
File diff suppressed because it is too large
Load Diff
23955
Kinc/Backends/Graphics4/OpenGL/Sources/GL/glew.c
Normal file
23955
Kinc/Backends/Graphics4/OpenGL/Sources/GL/glew.c
Normal file
File diff suppressed because it is too large
Load Diff
20113
Kinc/Backends/Graphics4/OpenGL/Sources/GL/glew.h
Normal file
20113
Kinc/Backends/Graphics4/OpenGL/Sources/GL/glew.h
Normal file
File diff suppressed because it is too large
Load Diff
1769
Kinc/Backends/Graphics4/OpenGL/Sources/GL/glxew.h
Normal file
1769
Kinc/Backends/Graphics4/OpenGL/Sources/GL/glxew.h
Normal file
File diff suppressed because it is too large
Load Diff
1427
Kinc/Backends/Graphics4/OpenGL/Sources/GL/wglew.h
Normal file
1427
Kinc/Backends/Graphics4/OpenGL/Sources/GL/wglew.h
Normal file
File diff suppressed because it is too large
Load Diff
451
Kinc/Backends/Graphics4/OpenGL/Sources/kinc/backend/compute.c
Normal file
451
Kinc/Backends/Graphics4/OpenGL/Sources/kinc/backend/compute.c
Normal file
@ -0,0 +1,451 @@
|
||||
#include <kinc/graphics4/compute.h>
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/image.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
#include <kinc/backend/graphics4/ogl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(KORE_WINDOWS) || (defined(KORE_LINUX) && defined(GL_VERSION_4_3)) || (defined(KORE_ANDROID) && defined(GL_ES_VERSION_3_1))
|
||||
#define HAS_COMPUTE
|
||||
bool kinc_internal_gl_has_compute = true;
|
||||
#else
|
||||
bool kinc_internal_gl_has_compute = false;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_COMPUTE
|
||||
static int convertInternalImageFormat(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
return GL_RGBA32F;
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
return GL_RGBA16F;
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
default:
|
||||
return GL_RGBA8;
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
return GL_R32F;
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
return GL_R16F;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return GL_R8;
|
||||
}
|
||||
}
|
||||
|
||||
static int convertInternalRTFormat(kinc_g4_render_target_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
return GL_RGBA16F;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
return GL_R32F;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
return GL_RGBA32F;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH:
|
||||
return GL_DEPTH_COMPONENT16;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
return GL_RED;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
return GL_R16F;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
return GL_RGBA;
|
||||
}
|
||||
}
|
||||
|
||||
static void setTextureAddressingInternal(GLenum target, kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir,
|
||||
kinc_g4_texture_addressing_t addressing) {
|
||||
glActiveTexture(GL_TEXTURE0 + unit.impl.unit);
|
||||
GLenum texDir = dir == KINC_G4_TEXTURE_DIRECTION_U ? GL_TEXTURE_WRAP_S : (KINC_G4_TEXTURE_DIRECTION_V ? GL_TEXTURE_WRAP_T : GL_TEXTURE_WRAP_R);
|
||||
switch (addressing) {
|
||||
case KINC_G4_TEXTURE_ADDRESSING_CLAMP:
|
||||
glTexParameteri(target, texDir, GL_CLAMP_TO_EDGE);
|
||||
break;
|
||||
case KINC_G4_TEXTURE_ADDRESSING_REPEAT:
|
||||
default:
|
||||
glTexParameteri(target, texDir, GL_REPEAT);
|
||||
break;
|
||||
}
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
static void setTextureMagnificationFilterInternal(GLenum target, kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {
|
||||
glActiveTexture(GL_TEXTURE0 + unit.impl.unit);
|
||||
switch (filter) {
|
||||
case KINC_G4_TEXTURE_FILTER_POINT:
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
case KINC_G4_TEXTURE_FILTER_LINEAR:
|
||||
case KINC_G4_TEXTURE_FILTER_ANISOTROPIC:
|
||||
default:
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
}
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
static kinc_g4_texture_filter_t minFilters[32] = {KINC_G4_TEXTURE_FILTER_POINT};
|
||||
static kinc_g4_mipmap_filter_t mipFilters[32] = {KINC_G4_MIPMAP_FILTER_NONE};
|
||||
|
||||
static void setMinMipFilters(GLenum target, int unit) {
|
||||
glActiveTexture(GL_TEXTURE0 + unit);
|
||||
switch (minFilters[unit]) {
|
||||
case KINC_G4_TEXTURE_FILTER_POINT:
|
||||
switch (mipFilters[unit]) {
|
||||
case KINC_G4_MIPMAP_FILTER_NONE:
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
break;
|
||||
case KINC_G4_MIPMAP_FILTER_POINT:
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
break;
|
||||
case KINC_G4_MIPMAP_FILTER_LINEAR:
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case KINC_G4_TEXTURE_FILTER_LINEAR:
|
||||
case KINC_G4_TEXTURE_FILTER_ANISOTROPIC:
|
||||
switch (mipFilters[unit]) {
|
||||
case KINC_G4_MIPMAP_FILTER_NONE:
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
break;
|
||||
case KINC_G4_MIPMAP_FILTER_POINT:
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
break;
|
||||
case KINC_G4_MIPMAP_FILTER_LINEAR:
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
break;
|
||||
}
|
||||
if (minFilters[unit] == KINC_G4_TEXTURE_FILTER_ANISOTROPIC) {
|
||||
float maxAniso = 0.0f;
|
||||
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso);
|
||||
glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso);
|
||||
}
|
||||
break;
|
||||
}
|
||||
glCheckErrors();
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_compute_shader_init(kinc_compute_shader_t *shader, void *source, int length) {
|
||||
shader->impl._length = length;
|
||||
shader->impl.textureCount = 0;
|
||||
shader->impl._source = (char *)malloc(sizeof(char) * (length + 1));
|
||||
for (int i = 0; i < length; ++i) {
|
||||
shader->impl._source[i] = ((char *)source)[i];
|
||||
}
|
||||
shader->impl._source[length] = 0;
|
||||
|
||||
#ifdef HAS_COMPUTE
|
||||
shader->impl._id = glCreateShader(GL_COMPUTE_SHADER);
|
||||
glCheckErrors();
|
||||
glShaderSource(shader->impl._id, 1, (const GLchar **)&shader->impl._source, NULL);
|
||||
glCompileShader(shader->impl._id);
|
||||
|
||||
int result;
|
||||
glGetShaderiv(shader->impl._id, GL_COMPILE_STATUS, &result);
|
||||
if (result != GL_TRUE) {
|
||||
int length;
|
||||
glGetShaderiv(shader->impl._id, GL_INFO_LOG_LENGTH, &length);
|
||||
char *errormessage = (char *)malloc(sizeof(char) * length);
|
||||
glGetShaderInfoLog(shader->impl._id, length, NULL, errormessage);
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "GLSL compiler error: %s\n", errormessage);
|
||||
free(errormessage);
|
||||
}
|
||||
|
||||
shader->impl._programid = glCreateProgram();
|
||||
glAttachShader(shader->impl._programid, shader->impl._id);
|
||||
glLinkProgram(shader->impl._programid);
|
||||
|
||||
glGetProgramiv(shader->impl._programid, GL_LINK_STATUS, &result);
|
||||
if (result != GL_TRUE) {
|
||||
int length;
|
||||
glGetProgramiv(shader->impl._programid, GL_INFO_LOG_LENGTH, &length);
|
||||
char *errormessage = (char *)malloc(sizeof(char) * length);
|
||||
glGetProgramInfoLog(shader->impl._programid, length, NULL, errormessage);
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "GLSL linker error: %s\n", errormessage);
|
||||
free(errormessage);
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: Get rid of allocations
|
||||
shader->impl.textures = (char **)malloc(sizeof(char *) * 16);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
shader->impl.textures[i] = (char *)malloc(sizeof(char) * 128);
|
||||
shader->impl.textures[i][0] = 0;
|
||||
}
|
||||
shader->impl.textureValues = (int *)malloc(sizeof(int) * 16);
|
||||
}
|
||||
|
||||
void kinc_compute_shader_destroy(kinc_compute_shader_t *shader) {
|
||||
free(shader->impl._source);
|
||||
shader->impl._source = NULL;
|
||||
#ifdef HAS_COMPUTE
|
||||
glDeleteProgram(shader->impl._programid);
|
||||
glDeleteShader(shader->impl._id);
|
||||
#endif
|
||||
}
|
||||
kinc_compute_constant_location_t kinc_compute_shader_get_constant_location(kinc_compute_shader_t *shader, const char *name) {
|
||||
kinc_compute_constant_location_t location;
|
||||
#ifdef HAS_COMPUTE
|
||||
location.impl.location = glGetUniformLocation(shader->impl._programid, name);
|
||||
location.impl.type = GL_FLOAT;
|
||||
GLint count = 0;
|
||||
glGetProgramiv(shader->impl._programid, GL_ACTIVE_UNIFORMS, &count);
|
||||
char arrayName[1024];
|
||||
strcpy(arrayName, name);
|
||||
strcat(arrayName, "[0]");
|
||||
for (GLint i = 0; i < count; ++i) {
|
||||
GLenum type;
|
||||
char uniformName[1024];
|
||||
GLsizei length;
|
||||
GLint size;
|
||||
glGetActiveUniform(shader->impl._programid, i, 1024 - 1, &length, &size, &type, uniformName);
|
||||
if (strcmp(uniformName, name) == 0 || strcmp(uniformName, arrayName) == 0) {
|
||||
location.impl.type = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
glCheckErrors();
|
||||
if (location.impl.location < 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
|
||||
}
|
||||
#endif
|
||||
return location;
|
||||
}
|
||||
|
||||
static int findTexture(kinc_compute_shader_t *shader, const char *name) {
|
||||
for (int index = 0; index < shader->impl.textureCount; ++index) {
|
||||
if (strcmp(shader->impl.textures[index], name) == 0) return index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
kinc_compute_texture_unit_t kinc_compute_shader_get_texture_unit(kinc_compute_shader_t *shader, const char *name) {
|
||||
int index = findTexture(shader, name);
|
||||
if (index < 0) {
|
||||
int location = glGetUniformLocation(shader->impl._programid, name);
|
||||
glCheckErrors();
|
||||
index = shader->impl.textureCount;
|
||||
shader->impl.textureValues[index] = location;
|
||||
strcpy(shader->impl.textures[index], name);
|
||||
++shader->impl.textureCount;
|
||||
}
|
||||
kinc_compute_texture_unit_t unit;
|
||||
unit.impl.unit = index;
|
||||
return unit;
|
||||
}
|
||||
|
||||
void kinc_compute_set_bool(kinc_compute_constant_location_t location, bool value) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glUniform1i(location.impl.location, value ? 1 : 0);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_int(kinc_compute_constant_location_t location, int value) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glUniform1i(location.impl.location, value);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_float(kinc_compute_constant_location_t location, float value) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glUniform1f(location.impl.location, value);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_float2(kinc_compute_constant_location_t location, float value1, float value2) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glUniform2f(location.impl.location, value1, value2);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_float3(kinc_compute_constant_location_t location, float value1, float value2, float value3) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glUniform3f(location.impl.location, value1, value2, value3);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_float4(kinc_compute_constant_location_t location, float value1, float value2, float value3, float value4) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glUniform4f(location.impl.location, value1, value2, value3, value4);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_floats(kinc_compute_constant_location_t location, float *values, int count) {
|
||||
#ifdef HAS_COMPUTE
|
||||
switch (location.impl.type) {
|
||||
case GL_FLOAT_VEC2:
|
||||
glUniform2fv(location.impl.location, count / 2, values);
|
||||
break;
|
||||
case GL_FLOAT_VEC3:
|
||||
glUniform3fv(location.impl.location, count / 3, values);
|
||||
break;
|
||||
case GL_FLOAT_VEC4:
|
||||
glUniform4fv(location.impl.location, count / 4, values);
|
||||
break;
|
||||
case GL_FLOAT_MAT4:
|
||||
glUniformMatrix4fv(location.impl.location, count / 16, false, values);
|
||||
break;
|
||||
default:
|
||||
glUniform1fv(location.impl.location, count, values);
|
||||
break;
|
||||
}
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_matrix4(kinc_compute_constant_location_t location, kinc_matrix4x4_t *value) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glUniformMatrix4fv(location.impl.location, 1, GL_FALSE, &value->m[0]);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_matrix3(kinc_compute_constant_location_t location, kinc_matrix3x3_t *value) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glUniformMatrix3fv(location.impl.location, 1, GL_FALSE, &value->m[0]);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_buffer(kinc_shader_storage_buffer_t *buffer, int index) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, buffer->impl.bufferId);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture(kinc_compute_texture_unit_t unit, kinc_g4_texture_t *texture, kinc_compute_access_t access) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glActiveTexture(GL_TEXTURE0 + unit.impl.unit);
|
||||
glCheckErrors();
|
||||
GLenum glaccess = access == KINC_COMPUTE_ACCESS_READ ? GL_READ_ONLY : (access == KINC_COMPUTE_ACCESS_WRITE ? GL_WRITE_ONLY : GL_READ_WRITE);
|
||||
glBindImageTexture(unit.impl.unit, texture->impl.texture, 0, GL_FALSE, 0, glaccess, convertInternalImageFormat(texture->format));
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *texture, kinc_compute_access_t access) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glActiveTexture(GL_TEXTURE0 + unit.impl.unit);
|
||||
glCheckErrors();
|
||||
GLenum glaccess = access == KINC_COMPUTE_ACCESS_READ ? GL_READ_ONLY : (access == KINC_COMPUTE_ACCESS_WRITE ? GL_WRITE_ONLY : GL_READ_WRITE);
|
||||
glBindImageTexture(unit.impl.unit, texture->impl._texture, 0, GL_FALSE, 0, glaccess,
|
||||
convertInternalRTFormat((kinc_g4_render_target_format_t)texture->impl.format));
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_sampled_texture(kinc_compute_texture_unit_t unit, kinc_g4_texture_t *texture) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glActiveTexture(GL_TEXTURE0 + unit.impl.unit);
|
||||
glCheckErrors();
|
||||
GLenum gltarget = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
|
||||
glBindTexture(gltarget, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_sampled_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glActiveTexture(GL_TEXTURE0 + unit.impl.unit);
|
||||
glCheckErrors();
|
||||
glBindTexture(target->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, target->impl._texture);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_sampled_depth_from_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glActiveTexture(GL_TEXTURE0 + unit.impl.unit);
|
||||
glCheckErrors();
|
||||
glBindTexture(target->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, target->impl._depthTexture);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
|
||||
#ifdef HAS_COMPUTE
|
||||
setTextureAddressingInternal(GL_TEXTURE_2D, unit, dir, addressing);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture3d_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
|
||||
#ifdef HAS_COMPUTE
|
||||
setTextureAddressingInternal(GL_TEXTURE_3D, unit, dir, addressing);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {
|
||||
#ifdef HAS_COMPUTE
|
||||
setTextureMagnificationFilterInternal(GL_TEXTURE_2D, unit, filter);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture3d_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {
|
||||
#ifdef HAS_COMPUTE
|
||||
setTextureMagnificationFilterInternal(GL_TEXTURE_3D, unit, filter);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {
|
||||
#ifdef HAS_COMPUTE
|
||||
minFilters[unit.impl.unit] = filter;
|
||||
setMinMipFilters(GL_TEXTURE_2D, unit.impl.unit);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture3d_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {
|
||||
#ifdef HAS_COMPUTE
|
||||
minFilters[unit.impl.unit] = filter;
|
||||
setMinMipFilters(GL_TEXTURE_3D, unit.impl.unit);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {
|
||||
#ifdef HAS_COMPUTE
|
||||
mipFilters[unit.impl.unit] = filter;
|
||||
setMinMipFilters(GL_TEXTURE_2D, unit.impl.unit);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture3d_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {
|
||||
#ifdef HAS_COMPUTE
|
||||
mipFilters[unit.impl.unit] = filter;
|
||||
setMinMipFilters(GL_TEXTURE_3D, unit.impl.unit);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_set_shader(kinc_compute_shader_t *shader) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glUseProgram(shader->impl._programid);
|
||||
glCheckErrors();
|
||||
|
||||
for (int index = 0; index < shader->impl.textureCount; ++index) {
|
||||
glUniform1i(shader->impl.textureValues[index], index);
|
||||
glCheckErrors();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute(int x, int y, int z) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glDispatchCompute(x, y, z);
|
||||
glCheckErrors();
|
||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||
glCheckErrors();
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
int location;
|
||||
unsigned int type;
|
||||
} kinc_compute_constant_location_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int unit;
|
||||
} kinc_compute_texture_unit_impl_t;
|
||||
|
||||
typedef struct {
|
||||
// int findTexture(const char* name);
|
||||
char **textures;
|
||||
int *textureValues;
|
||||
int textureCount;
|
||||
unsigned _id;
|
||||
unsigned _programid;
|
||||
char *_source;
|
||||
int _length;
|
||||
} kinc_compute_shader_impl_t;
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/textureunit.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef KINC_KONG
|
||||
int Kinc_G4_Internal_TextureAddressingU(uint32_t unit);
|
||||
int Kinc_G4_Internal_TextureAddressingV(uint32_t unit);
|
||||
#else
|
||||
int Kinc_G4_Internal_TextureAddressingU(kinc_g4_texture_unit_t unit);
|
||||
int Kinc_G4_Internal_TextureAddressingV(kinc_g4_texture_unit_t unit);
|
||||
#endif
|
||||
int Kinc_G4_Internal_StencilFunc(kinc_g4_compare_mode_t mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,221 @@
|
||||
#ifdef KORE_WINDOWS
|
||||
#include "OpenGLWindow.h"
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
#include <kinc/system.h>
|
||||
#include <kinc/window.h>
|
||||
|
||||
#include <kinc/backend/Windows.h>
|
||||
|
||||
#include "ogl.h"
|
||||
|
||||
#include <GL/wglew.h>
|
||||
|
||||
Kinc_Internal_OpenGLWindow Kinc_Internal_windows[10] = {0};
|
||||
|
||||
static kinc_g4_vertex_buffer_t windowVertexBuffer;
|
||||
static kinc_g4_index_buffer_t windowIndexBuffer;
|
||||
static kinc_g4_pipeline_t windowPipeline;
|
||||
|
||||
static bool initialized = false;
|
||||
static kinc_g4_shader_t windowVertexShader;
|
||||
static kinc_g4_shader_t windowFragmentShader;
|
||||
static bool glewInitialized = false;
|
||||
|
||||
void Kinc_Internal_initWindowsGLContext(int window, int depthBufferBits, int stencilBufferBits) {
|
||||
HWND windowHandle = kinc_windows_window_handle(window);
|
||||
|
||||
Kinc_Internal_windows[window].depthBufferBits = depthBufferBits;
|
||||
|
||||
#ifndef VR_RIFT
|
||||
PIXELFORMATDESCRIPTOR pfd = {sizeof(PIXELFORMATDESCRIPTOR),
|
||||
1,
|
||||
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
||||
PFD_TYPE_RGBA,
|
||||
32,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(BYTE)depthBufferBits,
|
||||
(BYTE)stencilBufferBits,
|
||||
0,
|
||||
PFD_MAIN_PLANE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0};
|
||||
|
||||
Kinc_Internal_windows[window].deviceContext = GetDC(windowHandle);
|
||||
GLuint pixelFormat = ChoosePixelFormat(Kinc_Internal_windows[window].deviceContext, &pfd);
|
||||
SetPixelFormat(Kinc_Internal_windows[window].deviceContext, pixelFormat, &pfd);
|
||||
HGLRC tempGlContext = wglCreateContext(Kinc_Internal_windows[window].deviceContext);
|
||||
wglMakeCurrent(Kinc_Internal_windows[window].deviceContext, tempGlContext);
|
||||
|
||||
if (!glewInitialized) {
|
||||
glewInit();
|
||||
glewInitialized = true;
|
||||
}
|
||||
|
||||
if (wglewIsSupported("WGL_ARB_create_context") == 1) {
|
||||
int attributes[] = {WGL_CONTEXT_MAJOR_VERSION_ARB,
|
||||
4,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB,
|
||||
2,
|
||||
WGL_CONTEXT_FLAGS_ARB,
|
||||
WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB,
|
||||
WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
0};
|
||||
|
||||
Kinc_Internal_windows[window].glContext =
|
||||
wglCreateContextAttribsARB(Kinc_Internal_windows[window].deviceContext, Kinc_Internal_windows[0].glContext, attributes);
|
||||
glCheckErrors();
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(tempGlContext);
|
||||
wglMakeCurrent(Kinc_Internal_windows[window].deviceContext, Kinc_Internal_windows[window].glContext);
|
||||
glCheckErrors();
|
||||
}
|
||||
else {
|
||||
Kinc_Internal_windows[window].glContext = tempGlContext;
|
||||
}
|
||||
#else
|
||||
deviceContexts[window] = GetDC(windowHandle);
|
||||
glContexts[window] = wglGetCurrentContext();
|
||||
if (!glewInitialized) {
|
||||
glewInit();
|
||||
glewInitialized = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (window != 0) {
|
||||
wglShareLists(Kinc_Internal_windows[0].glContext, Kinc_Internal_windows[window].glContext);
|
||||
wglMakeCurrent(Kinc_Internal_windows[0].deviceContext, Kinc_Internal_windows[0].glContext);
|
||||
kinc_g4_render_target_init(&Kinc_Internal_windows[window].renderTarget, kinc_windows_manual_width(window), kinc_windows_manual_height(window),
|
||||
KINC_G4_RENDER_TARGET_FORMAT_32BIT, depthBufferBits, 0);
|
||||
if (!initialized) {
|
||||
wglMakeCurrent(Kinc_Internal_windows[window].deviceContext, Kinc_Internal_windows[window].glContext);
|
||||
kinc_g4_vertex_structure_t structure;
|
||||
kinc_g4_vertex_structure_init(&structure);
|
||||
kinc_g4_vertex_structure_add(&structure, "pos", KINC_G4_VERTEX_DATA_F32_2X);
|
||||
kinc_g4_vertex_buffer_init(&windowVertexBuffer, 4, &structure, KINC_G4_USAGE_STATIC, 0);
|
||||
float *vertices = kinc_g4_vertex_buffer_lock_all(&windowVertexBuffer);
|
||||
vertices[0] = -1.0f;
|
||||
vertices[1] = -1.0f;
|
||||
vertices[2] = -1.0f;
|
||||
vertices[3] = 1.0f;
|
||||
vertices[4] = 1.0f;
|
||||
vertices[5] = 1.0f;
|
||||
vertices[6] = 1.0f;
|
||||
vertices[7] = -1.0f;
|
||||
kinc_g4_vertex_buffer_unlock_all(&windowVertexBuffer);
|
||||
|
||||
kinc_g4_index_buffer_init(&windowIndexBuffer, 6, KINC_G4_INDEX_BUFFER_FORMAT_32BIT, KINC_G4_USAGE_STATIC);
|
||||
int *indices = kinc_g4_index_buffer_lock_all(&windowIndexBuffer);
|
||||
indices[0] = 0;
|
||||
indices[1] = 1;
|
||||
indices[2] = 2;
|
||||
indices[3] = 0;
|
||||
indices[4] = 2;
|
||||
indices[5] = 3;
|
||||
kinc_g4_index_buffer_unlock_all(&windowIndexBuffer);
|
||||
|
||||
char *vertex_shader = "#version 450\n"
|
||||
"in vec2 pos;\n"
|
||||
"out vec2 texCoord;\n"
|
||||
"void main() {\n"
|
||||
"gl_Position = vec4(pos, 0.5, 1.0);\n"
|
||||
"texCoord = (pos + 1.0) / 2.0;\n"
|
||||
"}\n";
|
||||
|
||||
kinc_g4_shader_init(&windowVertexShader, vertex_shader, strlen(vertex_shader), KINC_G4_SHADER_TYPE_VERTEX);
|
||||
|
||||
char *fragment_shader = "#version 450\n"
|
||||
"uniform sampler2D tex;\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 frag;\n"
|
||||
"void main() {\n"
|
||||
"frag = texture(tex, texCoord);\n"
|
||||
"}\n";
|
||||
|
||||
kinc_g4_shader_init(&windowFragmentShader, fragment_shader, strlen(fragment_shader), KINC_G4_SHADER_TYPE_FRAGMENT);
|
||||
|
||||
kinc_g4_pipeline_init(&windowPipeline);
|
||||
windowPipeline.input_layout[0] = &structure;
|
||||
windowPipeline.input_layout[1] = NULL;
|
||||
windowPipeline.vertex_shader = &windowVertexShader;
|
||||
windowPipeline.fragment_shader = &windowFragmentShader;
|
||||
kinc_g4_pipeline_compile(&windowPipeline);
|
||||
|
||||
wglMakeCurrent(Kinc_Internal_windows[0].deviceContext, Kinc_Internal_windows[0].glContext);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
wglMakeCurrent(Kinc_Internal_windows[window].deviceContext, Kinc_Internal_windows[window].glContext);
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &Kinc_Internal_windows[window].framebuffer);
|
||||
|
||||
glGenVertexArrays(1, &Kinc_Internal_windows[window].vertexArray);
|
||||
glCheckErrors();
|
||||
|
||||
wglMakeCurrent(Kinc_Internal_windows[0].deviceContext, Kinc_Internal_windows[0].glContext);
|
||||
glBindVertexArray(Kinc_Internal_windows[0].vertexArray);
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
void Kinc_Internal_blitWindowContent(int window) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, Kinc_Internal_windows[window].framebuffer);
|
||||
kinc_g4_clear(KINC_G4_CLEAR_COLOR, 0xff00ffff, 0.0f, 0);
|
||||
kinc_g4_set_pipeline(&windowPipeline);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, Kinc_Internal_windows[window].renderTarget.impl._texture);
|
||||
kinc_g4_set_index_buffer(&windowIndexBuffer);
|
||||
|
||||
glBindVertexArray(Kinc_Internal_windows[window].vertexArray);
|
||||
|
||||
glCheckErrors();
|
||||
kinc_g4_vertex_buffer_t *vertexBuffers[1] = {&windowVertexBuffer};
|
||||
kinc_g4_set_vertex_buffers(vertexBuffers, 1);
|
||||
|
||||
glViewport(0, 0, kinc_window_width(window), kinc_window_height(window));
|
||||
|
||||
kinc_g4_draw_indexed_vertices();
|
||||
glCheckErrors();
|
||||
|
||||
glBindVertexArray(Kinc_Internal_windows[0].vertexArray);
|
||||
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
void Kinc_Internal_resizeWindowRenderTarget(int window, int width, int height) {
|
||||
if (window != 0) {
|
||||
kinc_g4_render_target_destroy(&Kinc_Internal_windows[window].renderTarget);
|
||||
kinc_g4_render_target_init(&Kinc_Internal_windows[window].renderTarget, width, height, KINC_G4_RENDER_TARGET_FORMAT_32BIT,
|
||||
Kinc_Internal_windows[window].depthBufferBits, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Kinc_Internal_setWindowRenderTarget(int window) {
|
||||
if (window == 0) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, Kinc_Internal_windows[window].framebuffer);
|
||||
}
|
||||
else {
|
||||
kinc_g4_render_target_t *renderTargets[1] = {&Kinc_Internal_windows[window].renderTarget};
|
||||
kinc_g4_set_render_targets(renderTargets, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct kinc_g4_render_target;
|
||||
|
||||
typedef struct {
|
||||
HDC deviceContext;
|
||||
HGLRC glContext;
|
||||
|
||||
int depthBufferBits;
|
||||
|
||||
int framebuffer;
|
||||
unsigned vertexArray;
|
||||
struct kinc_g4_render_target renderTarget;
|
||||
} Kinc_Internal_OpenGLWindow;
|
||||
|
||||
extern Kinc_Internal_OpenGLWindow Kinc_Internal_windows[10];
|
||||
|
||||
void Kinc_Internal_initWindowsGLContext(int window, int depthBufferBits, int stencilBufferBits);
|
||||
void Kinc_Internal_blitWindowContent(int window);
|
||||
void Kinc_Internal_setWindowRenderTarget(int window);
|
||||
void Kinc_Internal_resizeWindowRenderTarget(int window, int width, int height);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,55 @@
|
||||
#include "ogl.h"
|
||||
|
||||
#include <kinc/graphics4/compute.h>
|
||||
|
||||
#if defined(KORE_WINDOWS) || (defined(KORE_LINUX) && defined(GL_VERSION_4_3)) || (defined(KORE_ANDROID) && defined(GL_ES_VERSION_3_1))
|
||||
#define HAS_COMPUTE
|
||||
#endif
|
||||
|
||||
kinc_shader_storage_buffer_t *currentStorageBuffer = NULL;
|
||||
|
||||
static void unset(kinc_shader_storage_buffer_t *buffer) {
|
||||
if (currentStorageBuffer == buffer)
|
||||
currentStorageBuffer = NULL;
|
||||
}
|
||||
|
||||
void kinc_shader_storage_buffer_init(kinc_shader_storage_buffer_t *buffer, int indexCount, kinc_g4_vertex_data_t type) {
|
||||
buffer->impl.myCount = indexCount;
|
||||
buffer->impl.myStride = 0;
|
||||
buffer->impl.myStride += kinc_g4_vertex_data_size(type);
|
||||
#ifdef HAS_COMPUTE
|
||||
glGenBuffers(1, &buffer->impl.bufferId);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
buffer->impl.data = (int *)malloc(sizeof(int) * indexCount);
|
||||
}
|
||||
|
||||
void kinc_shader_storage_buffer_destroy(kinc_shader_storage_buffer_t *buffer) {
|
||||
unset(buffer);
|
||||
free(buffer->impl.data);
|
||||
}
|
||||
|
||||
int *kinc_shader_storage_buffer_lock(kinc_shader_storage_buffer_t *buffer) {
|
||||
return buffer->impl.data;
|
||||
}
|
||||
|
||||
void kinc_shader_storage_buffer_unlock(kinc_shader_storage_buffer_t *buffer) {
|
||||
#ifdef HAS_COMPUTE
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer->impl.bufferId);
|
||||
glCheckErrors();
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, buffer->impl.myCount * buffer->impl.myStride, buffer->impl.data, GL_STATIC_DRAW);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_shader_storage_buffer_internal_set(kinc_shader_storage_buffer_t *buffer) {
|
||||
currentStorageBuffer = buffer;
|
||||
#ifdef HAS_COMPUTE
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer->impl.bufferId);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
int kinc_shader_storage_buffer_count(kinc_shader_storage_buffer_t *buffer) {
|
||||
return buffer->impl.myCount;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
// ShaderStorageBufferImpl(int count, Graphics4::VertexData type);
|
||||
// void unset();
|
||||
int *data;
|
||||
int myCount;
|
||||
int myStride;
|
||||
unsigned bufferId;
|
||||
// static ShaderStorageBuffer* current;
|
||||
} kinc_compute_shader_storage_buffer_impl_t;
|
@ -0,0 +1,634 @@
|
||||
#ifdef KORE_OCULUS
|
||||
#include <Kinc/vr/vrinterface.h>
|
||||
|
||||
#include <Kinc/graphics4/graphics.h>
|
||||
#include <Kinc/graphics4/rendertarget.h>
|
||||
#include <Kore/Log.h>
|
||||
|
||||
#include "Extras/OVR_Math.h"
|
||||
#include "GL/CAPI_GLE.h"
|
||||
#include "OVR_CAPI_GL.h"
|
||||
#include <assert.h>
|
||||
|
||||
using namespace Kore;
|
||||
|
||||
namespace {
|
||||
kinc_vr_sensor_state_t sensorStates[2];
|
||||
}
|
||||
|
||||
struct TextureBuffer {
|
||||
ovrSession Session;
|
||||
ovrTextureSwapChain TextureChain;
|
||||
OVR::Sizei texSize;
|
||||
|
||||
kinc_g4_render_target_t OVRRenderTarget;
|
||||
bool render_target_initialized;
|
||||
|
||||
TextureBuffer(ovrSession session, bool displayableOnHmd, OVR::Sizei size, int mipLevels, unsigned char *data, int sampleCount)
|
||||
: Session(session), TextureChain(nullptr), texSize(size), render_target_initialized(false) {
|
||||
UNREFERENCED_PARAMETER(sampleCount);
|
||||
|
||||
assert(sampleCount <= 1); // The code doesn't currently handle MSAA textures.
|
||||
|
||||
if (displayableOnHmd) {
|
||||
// This texture isn't necessarily going to be a rendertarget, but it usually is.
|
||||
|
||||
assert(session); // No HMD? A little odd.
|
||||
assert(sampleCount == 1); // ovr_CreateSwapTextureSetD3D11 doesn't support MSAA.
|
||||
|
||||
ovrTextureSwapChainDesc desc = {};
|
||||
desc.Type = ovrTexture_2D;
|
||||
desc.ArraySize = 1;
|
||||
desc.Width = size.w;
|
||||
desc.Height = size.h;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
desc.SampleCount = 1;
|
||||
desc.StaticImage = ovrFalse;
|
||||
|
||||
ovrResult result = ovr_CreateTextureSwapChainGL(Session, &desc, &TextureChain);
|
||||
|
||||
int length = 0;
|
||||
ovr_GetTextureSwapChainLength(session, TextureChain, &length);
|
||||
|
||||
if (OVR_SUCCESS(result)) {
|
||||
for (int i = 0; i < length; ++i) {
|
||||
GLuint chainTexId;
|
||||
ovr_GetTextureSwapChainBufferGL(Session, TextureChain, i, &chainTexId);
|
||||
glBindTexture(GL_TEXTURE_2D, chainTexId);
|
||||
kinc_g4_render_target_init(&OVRRenderTarget, texSize.w, texSize.h, 0, false, KINC_G4_RENDER_TARGET_FORMAT_32BIT, 0, 0);
|
||||
render_target_initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mipLevels > 1) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
|
||||
~TextureBuffer() {
|
||||
if (TextureChain) {
|
||||
ovr_DestroyTextureSwapChain(Session, TextureChain);
|
||||
TextureChain = nullptr;
|
||||
}
|
||||
if (render_target_initialized) {
|
||||
kinc_g4_render_target_destroy(&OVRRenderTarget);
|
||||
}
|
||||
}
|
||||
|
||||
OVR::Sizei GetSize() const {
|
||||
return texSize;
|
||||
}
|
||||
|
||||
void SetAndClearRenderSurface() {
|
||||
GLuint curTexId;
|
||||
int curIndex;
|
||||
ovr_GetTextureSwapChainCurrentIndex(Session, TextureChain, &curIndex);
|
||||
ovr_GetTextureSwapChainBufferGL(Session, TextureChain, curIndex, &curTexId);
|
||||
|
||||
if (render_target_initialized) {
|
||||
kinc_g4_render_target_t *renderTargets[1] = {&OVRRenderTarget};
|
||||
kinc_g4_set_render_targets(renderTargets, 1);
|
||||
}
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, OVRRenderTarget.impl._depthTexture, 0);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
// glEnable(GL_FRAMEBUFFER_SRGB); // TODO: too bright
|
||||
}
|
||||
|
||||
void UnsetRenderSurface() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, OVRRenderTarget.impl._framebuffer);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
|
||||
void Commit() {
|
||||
if (TextureChain) {
|
||||
ovr_CommitTextureSwapChain(Session, TextureChain);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
struct OGL {
|
||||
HWND Window;
|
||||
HDC hDC;
|
||||
HGLRC WglContext;
|
||||
OVR::GLEContext GLEContext;
|
||||
bool Running;
|
||||
bool Key[256];
|
||||
int WinSizeW;
|
||||
int WinSizeH;
|
||||
HINSTANCE hInstance;
|
||||
|
||||
OGL() : Window(nullptr), hDC(nullptr), WglContext(nullptr), GLEContext(), Running(false), WinSizeW(0), WinSizeH(0), hInstance(nullptr) {
|
||||
// Clear input
|
||||
for (int i = 0; i < sizeof(Key) / sizeof(Key[0]); ++i)
|
||||
Key[i] = false;
|
||||
}
|
||||
|
||||
~OGL() {
|
||||
ReleaseDevice();
|
||||
CloseWindow();
|
||||
}
|
||||
|
||||
bool InitWindow(HINSTANCE hInst, const char *title, const char *windowClassName) {
|
||||
hInstance = hInst;
|
||||
Running = true;
|
||||
|
||||
// Adjust the window size and show at InitDevice time
|
||||
wchar_t wchTitle[256];
|
||||
MultiByteToWideChar(CP_ACP, 0, title, -1, wchTitle, 256);
|
||||
wchar_t wchClassName[256];
|
||||
MultiByteToWideChar(CP_ACP, 0, windowClassName, -1, wchClassName, 256);
|
||||
Window = CreateWindowW(wchClassName, wchTitle, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, 0, 0, hInst, 0);
|
||||
if (!Window)
|
||||
return false;
|
||||
|
||||
SetWindowLongPtr(Window, 0, LONG_PTR(this));
|
||||
|
||||
hDC = GetDC(Window);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CloseWindow() {
|
||||
if (Window) {
|
||||
if (hDC) {
|
||||
ReleaseDC(Window, hDC);
|
||||
hDC = nullptr;
|
||||
}
|
||||
Window = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: currently there is no way to get GL to use the passed pLuid
|
||||
bool InitDevice(int vpW, int vpH, const LUID * /*pLuid*/, bool windowed = true) {
|
||||
UNREFERENCED_PARAMETER(windowed);
|
||||
|
||||
WinSizeW = vpW;
|
||||
WinSizeH = vpH;
|
||||
|
||||
RECT size = {0, 0, vpW, vpH};
|
||||
AdjustWindowRect(&size, WS_OVERLAPPEDWINDOW, false);
|
||||
const UINT flags = SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW;
|
||||
if (!SetWindowPos(Window, nullptr, 0, 0, size.right - size.left, size.bottom - size.top, flags))
|
||||
return false;
|
||||
|
||||
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARBFunc = nullptr;
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARBFunc = nullptr;
|
||||
{
|
||||
// First create a context for the purpose of getting access to wglChoosePixelFormatARB / wglCreateContextAttribsARB.
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
memset(&pfd, 0, sizeof(pfd));
|
||||
pfd.nSize = sizeof(pfd);
|
||||
pfd.nVersion = 1;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
|
||||
pfd.cColorBits = 32;
|
||||
pfd.cDepthBits = 16;
|
||||
int pf = ChoosePixelFormat(hDC, &pfd);
|
||||
if (!pf) {
|
||||
log(Warning, "Failed to choose pixel format.");
|
||||
ReleaseDC(Window, hDC);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(hDC, pf, &pfd)) {
|
||||
log(Warning, "Failed to set pixel format.");
|
||||
ReleaseDC(Window, hDC);
|
||||
return false;
|
||||
}
|
||||
|
||||
HGLRC context = wglCreateContext(hDC);
|
||||
if (!context) {
|
||||
log(Warning, "wglCreateContextfailed.");
|
||||
ReleaseDC(Window, hDC);
|
||||
return false;
|
||||
}
|
||||
if (!wglMakeCurrent(hDC, context)) {
|
||||
log(Warning, "wglMakeCurrent failed.");
|
||||
wglDeleteContext(context);
|
||||
ReleaseDC(Window, hDC);
|
||||
return false;
|
||||
}
|
||||
|
||||
wglChoosePixelFormatARBFunc = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
||||
wglCreateContextAttribsARBFunc = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
|
||||
assert(wglChoosePixelFormatARBFunc && wglCreateContextAttribsARBFunc);
|
||||
|
||||
wglDeleteContext(context);
|
||||
}
|
||||
|
||||
// Now create the real context that we will be using.
|
||||
int iAttributes[] = {// WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
||||
WGL_SUPPORT_OPENGL_ARB,
|
||||
GL_TRUE,
|
||||
WGL_COLOR_BITS_ARB,
|
||||
32,
|
||||
WGL_DEPTH_BITS_ARB,
|
||||
16,
|
||||
WGL_DOUBLE_BUFFER_ARB,
|
||||
GL_TRUE,
|
||||
WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB,
|
||||
GL_TRUE,
|
||||
0,
|
||||
0};
|
||||
|
||||
float fAttributes[] = {0, 0};
|
||||
int pf = 0;
|
||||
UINT numFormats = 0;
|
||||
|
||||
if (!wglChoosePixelFormatARBFunc(hDC, iAttributes, fAttributes, 1, &pf, &numFormats)) {
|
||||
log(Warning, "wglChoosePixelFormatARBFunc failed.");
|
||||
ReleaseDC(Window, hDC);
|
||||
return false;
|
||||
}
|
||||
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
memset(&pfd, 0, sizeof(pfd));
|
||||
if (!SetPixelFormat(hDC, pf, &pfd)) {
|
||||
log(Warning, "SetPixelFormat failed.");
|
||||
ReleaseDC(Window, hDC);
|
||||
return false;
|
||||
}
|
||||
|
||||
GLint attribs[16];
|
||||
int attribCount = 0;
|
||||
attribs[attribCount] = 0;
|
||||
|
||||
WglContext = wglCreateContextAttribsARBFunc(hDC, 0, attribs);
|
||||
if (!wglMakeCurrent(hDC, WglContext)) {
|
||||
log(Warning, "wglMakeCurrent failed.");
|
||||
wglDeleteContext(WglContext);
|
||||
ReleaseDC(Window, hDC);
|
||||
return false;
|
||||
}
|
||||
|
||||
OVR::GLEContext::SetCurrentContext(&GLEContext);
|
||||
GLEContext.Init();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glFrontFace(GL_CW);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReleaseDevice() {
|
||||
if (WglContext) {
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(WglContext);
|
||||
WglContext = nullptr;
|
||||
}
|
||||
GLEContext.Shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
TextureBuffer *eyeRenderTexture[2] = {nullptr, nullptr};
|
||||
|
||||
ovrMirrorTexture mirrorTexture = nullptr;
|
||||
uint mirrorFBO = 0;
|
||||
long long frameIndex = 0;
|
||||
bool isVisible = true;
|
||||
|
||||
ovrSession session;
|
||||
ovrHmdDesc hmdDesc;
|
||||
|
||||
ovrPosef EyeRenderPose[2];
|
||||
double sensorSampleTime;
|
||||
|
||||
OGL Platform;
|
||||
|
||||
void done() {
|
||||
if (mirrorFBO)
|
||||
glDeleteFramebuffers(1, &mirrorFBO);
|
||||
if (mirrorTexture)
|
||||
ovr_DestroyMirrorTexture(session, mirrorTexture);
|
||||
for (int eye = 0; eye < 2; ++eye) {
|
||||
delete eyeRenderTexture[eye];
|
||||
}
|
||||
Platform.ReleaseDevice();
|
||||
ovr_Destroy(session);
|
||||
}
|
||||
|
||||
void createOculusTexture() {
|
||||
// Make eye render buffers
|
||||
for (int eye = 0; eye < 2; ++eye) {
|
||||
ovrSizei idealTextureSize = ovr_GetFovTextureSize(session, ovrEyeType(eye), hmdDesc.DefaultEyeFov[eye], 1);
|
||||
eyeRenderTexture[eye] = new TextureBuffer(session, true, idealTextureSize, 1, NULL, 1);
|
||||
|
||||
if (!eyeRenderTexture[eye]->TextureChain) {
|
||||
log(Info, "Failed to create texture.");
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
ovrMirrorTextureDesc desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.Width = Platform.WinSizeW;
|
||||
desc.Height = Platform.WinSizeH;
|
||||
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
|
||||
// Create mirror texture and an FBO used to copy mirror texture to back buffer
|
||||
ovrResult result = ovr_CreateMirrorTextureWithOptionsGL(session, &desc, &mirrorTexture);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
log(Info, "Failed to create mirror texture.");
|
||||
done();
|
||||
}
|
||||
|
||||
// Configure the mirror read buffer
|
||||
GLuint texId;
|
||||
ovr_GetMirrorTextureBufferGL(session, mirrorTexture, &texId);
|
||||
|
||||
glGenFramebuffers(1, &mirrorFBO);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO);
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);
|
||||
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void *kinc_vr_interface_init(void *hinst, const char *title, const char *windowClassName) {
|
||||
ovrInitParams initParams = {ovrInit_RequestVersion, OVR_MINOR_VERSION, NULL, 0, 0};
|
||||
ovrResult result = ovr_Initialize(&initParams);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
log(Warning, "Failed to initialize libOVR.");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!Platform.InitWindow((HINSTANCE)hinst, title, windowClassName)) {
|
||||
log(Warning, "Failed to open window.");
|
||||
return (0);
|
||||
}
|
||||
|
||||
ovrGraphicsLuid luid;
|
||||
result = ovr_Create(&session, &luid);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
log(Info, "HMD not connected.");
|
||||
return false; // TODO: retry
|
||||
}
|
||||
|
||||
hmdDesc = ovr_GetHmdDesc(session);
|
||||
|
||||
// Setup Window and Graphics
|
||||
// Note: the mirror window can be any size, for this sample we use 1/2 the HMD resolution
|
||||
ovrSizei windowSize = {hmdDesc.Resolution.w / 2, hmdDesc.Resolution.h / 2};
|
||||
if (!Platform.InitDevice(windowSize.w, windowSize.h, reinterpret_cast<LUID *>(&luid))) {
|
||||
log(Info, "Failed to init device.");
|
||||
done();
|
||||
}
|
||||
|
||||
// FloorLevel will give tracking poses where the floor height is 0
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
|
||||
|
||||
// Return window
|
||||
return Platform.Window;
|
||||
}
|
||||
|
||||
void kinc_vr_interface_begin() {
|
||||
// Call ovr_GetRenderDesc each frame to get the ovrEyeRenderDesc, as the returned values (e.g. HmdToEyeOffset) may change at runtime.
|
||||
ovrEyeRenderDesc eyeRenderDesc[2];
|
||||
eyeRenderDesc[0] = ovr_GetRenderDesc(session, ovrEye_Left, hmdDesc.DefaultEyeFov[0]);
|
||||
eyeRenderDesc[1] = ovr_GetRenderDesc(session, ovrEye_Right, hmdDesc.DefaultEyeFov[1]);
|
||||
|
||||
// Get both eye poses simultaneously, with IPD offset already included.
|
||||
ovrPosef HmdToEyePose[2] = {eyeRenderDesc[0].HmdToEyePose, eyeRenderDesc[1].HmdToEyePose};
|
||||
|
||||
ovr_GetEyePoses(session, frameIndex, ovrTrue, HmdToEyePose, EyeRenderPose, &sensorSampleTime);
|
||||
}
|
||||
|
||||
void kinc_vr_interface_begin_render(int eye) {
|
||||
if (eyeRenderTexture[0] == nullptr || eyeRenderTexture[1] == nullptr)
|
||||
createOculusTexture();
|
||||
// Switch to eye render target
|
||||
eyeRenderTexture[eye]->SetAndClearRenderSurface();
|
||||
}
|
||||
|
||||
void kinc_vr_interface_end_render(int eye) {
|
||||
// Avoids an error when calling SetAndClearRenderSurface during next iteration.
|
||||
eyeRenderTexture[eye]->UnsetRenderSurface();
|
||||
// Commit changes to the textures so they get picked up frame
|
||||
eyeRenderTexture[eye]->Commit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
kinc_matrix4x4_t convert(OVR::Matrix4f &m) {
|
||||
kinc_matrix4x4_t mat;
|
||||
kinc_matrix4x4_set(&mat, 0, 0, m.M[0][0]);
|
||||
kinc_matrix4x4_set(&mat, 0, 1, m.M[0][1]);
|
||||
kinc_matrix4x4_set(&mat, 0, 2, m.M[0][2]);
|
||||
kinc_matrix4x4_set(&mat, 0, 3, m.M[0][3]);
|
||||
kinc_matrix4x4_set(&mat, 1, 0, m.M[1][0]);
|
||||
kinc_matrix4x4_set(&mat, 1, 1, m.M[1][1]);
|
||||
kinc_matrix4x4_set(&mat, 1, 2, m.M[1][2]);
|
||||
kinc_matrix4x4_set(&mat, 1, 3, m.M[1][3]);
|
||||
kinc_matrix4x4_set(&mat, 2, 0, m.M[2][0]);
|
||||
kinc_matrix4x4_set(&mat, 2, 1, m.M[2][1]);
|
||||
kinc_matrix4x4_set(&mat, 2, 2, m.M[2][2]);
|
||||
kinc_matrix4x4_set(&mat, 2, 3, m.M[2][3]);
|
||||
kinc_matrix4x4_set(&mat, 3, 0, m.M[3][0]);
|
||||
kinc_matrix4x4_set(&mat, 3, 1, m.M[3][1]);
|
||||
kinc_matrix4x4_set(&mat, 3, 2, m.M[3][2]);
|
||||
kinc_matrix4x4_set(&mat, 3, 3, m.M[3][3]);
|
||||
return mat;
|
||||
}
|
||||
|
||||
// Vector<float, 3> vectorConvert(const OVR::Vector3f& v) {
|
||||
// return { v.x, v.y, v.z };
|
||||
// }
|
||||
|
||||
// OVR::Vector3f vectorConvert(const Vector<float, 3>& v) {
|
||||
// return { v.x(), v.y(), v.z() };
|
||||
// }
|
||||
}
|
||||
|
||||
/*SensorState VrInterface::getSensorState(int eye, Kore::Vector<float, 3>& headPosition) {
|
||||
VrPoseState poseState;
|
||||
|
||||
ovrQuatf orientation = EyeRenderPose[eye].Orientation;
|
||||
poseState.vrPose.orientation = Quaternion(orientation.x, orientation.y, orientation.z, orientation.w);
|
||||
|
||||
ovrVector3f pos = EyeRenderPose[eye].Position;
|
||||
poseState.vrPose.position = vec3(pos.x, pos.y, pos.z);
|
||||
|
||||
ovrFovPort fov = hmdDesc.DefaultEyeFov[eye];
|
||||
poseState.vrPose.left = fov.LeftTan;
|
||||
poseState.vrPose.right = fov.RightTan;
|
||||
poseState.vrPose.bottom = fov.DownTan;
|
||||
poseState.vrPose.top = fov.UpTan;
|
||||
|
||||
// Get view and projection matrices
|
||||
OVR::Matrix4f finalRollPitchYaw = OVR::Matrix4f(EyeRenderPose[eye].Orientation);
|
||||
OVR::Vector3f finalUp = finalRollPitchYaw.Transform(OVR::Vector3f(0, 1, 0));
|
||||
OVR::Vector3f finalForward = finalRollPitchYaw.Transform(OVR::Vector3f(0, 0, -1));
|
||||
|
||||
Kore::Vector<float, 3> right = vectorConvert(finalForward).cross(vectorConvert(finalUp)).normalize() * 0.01f;
|
||||
|
||||
OVR::Vector3f shiftedEyePos;
|
||||
|
||||
if (eye == 0) {
|
||||
shiftedEyePos = vectorConvert(headPosition - right);
|
||||
} else {
|
||||
shiftedEyePos = vectorConvert(headPosition + right);
|
||||
}
|
||||
|
||||
|
||||
OVR::Matrix4f view = OVR::Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + finalForward, finalUp);
|
||||
OVR::Matrix4f proj = ovrMatrix4f_Projection(hmdDesc.MaxEyeFov[eye], 0.2f, 1000.0f, ovrProjection_None);
|
||||
|
||||
poseState.vrPose.eye = convert(view);
|
||||
poseState.vrPose.projection = convert(proj);
|
||||
|
||||
ovrSessionStatus sessionStatus;
|
||||
ovr_GetSessionStatus(session, &sessionStatus);
|
||||
if (sessionStatus.IsVisible) poseState.isVisible = true;
|
||||
else poseState.isVisible = false;
|
||||
if (sessionStatus.HmdPresent) poseState.hmdPresenting = true;
|
||||
else poseState.hmdPresenting = false;
|
||||
if (sessionStatus.HmdMounted) poseState.hmdMounted = true;
|
||||
else poseState.hmdMounted = false;
|
||||
if (sessionStatus.DisplayLost) poseState.displayLost = true;
|
||||
else poseState.displayLost = false;
|
||||
if (sessionStatus.ShouldQuit) poseState.shouldQuit = true;
|
||||
else poseState.shouldQuit = false;
|
||||
if (sessionStatus.ShouldRecenter) poseState.shouldRecenter = true;
|
||||
else poseState.shouldRecenter = false;
|
||||
|
||||
sensorStates[eye].pose = poseState;
|
||||
|
||||
return sensorStates[eye];
|
||||
}*/
|
||||
|
||||
kinc_vr_sensor_state_t kinc_vr_interface_get_sensor_state(int eye) {
|
||||
kinc_vr_pose_state_t poseState;
|
||||
|
||||
ovrQuatf orientation = EyeRenderPose[eye].Orientation;
|
||||
poseState.vrPose.orientation.x = orientation.x;
|
||||
poseState.vrPose.orientation.y = orientation.y;
|
||||
poseState.vrPose.orientation.z = orientation.z;
|
||||
poseState.vrPose.orientation.w = orientation.w;
|
||||
|
||||
ovrVector3f pos = EyeRenderPose[eye].Position;
|
||||
poseState.vrPose.position.x = pos.x;
|
||||
poseState.vrPose.position.y = pos.y;
|
||||
poseState.vrPose.position.z = pos.z;
|
||||
|
||||
ovrFovPort fov = hmdDesc.DefaultEyeFov[eye];
|
||||
poseState.vrPose.left = fov.LeftTan;
|
||||
poseState.vrPose.right = fov.RightTan;
|
||||
poseState.vrPose.bottom = fov.DownTan;
|
||||
poseState.vrPose.top = fov.UpTan;
|
||||
|
||||
// Get view and projection matrices
|
||||
OVR::Matrix4f finalRollPitchYaw = OVR::Matrix4f(EyeRenderPose[eye].Orientation);
|
||||
OVR::Vector3f finalUp = finalRollPitchYaw.Transform(OVR::Vector3f(0, 1, 0));
|
||||
OVR::Vector3f finalForward = finalRollPitchYaw.Transform(OVR::Vector3f(0, 0, -1));
|
||||
OVR::Vector3f shiftedEyePos = EyeRenderPose[eye].Position;
|
||||
|
||||
OVR::Matrix4f view = OVR::Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + finalForward, finalUp);
|
||||
OVR::Matrix4f proj = ovrMatrix4f_Projection(hmdDesc.DefaultEyeFov[eye], 0.2f, 1000.0f, ovrProjection_None);
|
||||
|
||||
poseState.vrPose.eye = convert(view);
|
||||
poseState.vrPose.projection = convert(proj);
|
||||
|
||||
ovrSessionStatus sessionStatus;
|
||||
ovr_GetSessionStatus(session, &sessionStatus);
|
||||
if (sessionStatus.IsVisible)
|
||||
poseState.isVisible = true;
|
||||
else
|
||||
poseState.isVisible = false;
|
||||
if (sessionStatus.HmdPresent)
|
||||
poseState.hmdPresenting = true;
|
||||
else
|
||||
poseState.hmdPresenting = false;
|
||||
if (sessionStatus.HmdMounted)
|
||||
poseState.hmdMounted = true;
|
||||
else
|
||||
poseState.hmdMounted = false;
|
||||
if (sessionStatus.DisplayLost)
|
||||
poseState.displayLost = true;
|
||||
else
|
||||
poseState.displayLost = false;
|
||||
if (sessionStatus.ShouldQuit)
|
||||
poseState.shouldQuit = true;
|
||||
else
|
||||
poseState.shouldQuit = false;
|
||||
if (sessionStatus.ShouldRecenter)
|
||||
poseState.shouldRecenter = true;
|
||||
else
|
||||
poseState.shouldRecenter = false;
|
||||
|
||||
sensorStates[eye].pose = poseState;
|
||||
|
||||
return sensorStates[eye];
|
||||
}
|
||||
|
||||
kinc_vr_pose_state_t kinc_vr_interface_get_controller(int index) {
|
||||
kinc_vr_pose_state_t todo;
|
||||
return todo;
|
||||
}
|
||||
|
||||
void kinc_vr_interface_warp_swap() {
|
||||
// Initialize our single full screen Fov layer.
|
||||
ovrLayerEyeFov ld;
|
||||
ld.Header.Type = ovrLayerType_EyeFov;
|
||||
ld.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; // Because OpenGL.
|
||||
|
||||
if (isVisible) {
|
||||
for (int eye = 0; eye < 2; ++eye) {
|
||||
ld.ColorTexture[eye] = eyeRenderTexture[eye]->TextureChain;
|
||||
ld.Viewport[eye] = OVR::Recti(eyeRenderTexture[eye]->GetSize());
|
||||
ld.Fov[eye] = hmdDesc.DefaultEyeFov[eye];
|
||||
ld.RenderPose[eye] = EyeRenderPose[eye];
|
||||
ld.SensorSampleTime = sensorSampleTime;
|
||||
}
|
||||
}
|
||||
|
||||
ovrLayerHeader *layers = &ld.Header;
|
||||
ovrResult result = ovr_SubmitFrame(session, frameIndex, nullptr, &layers, 1);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
isVisible = false;
|
||||
}
|
||||
else {
|
||||
isVisible = true;
|
||||
}
|
||||
|
||||
frameIndex++;
|
||||
|
||||
// Blit mirror texture to back buffer
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
GLint w = Platform.WinSizeW;
|
||||
GLint h = Platform.WinSizeH;
|
||||
glBlitFramebuffer(0, h, w, 0, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void kinc_vr_interface_update_tracking_origin(kinc_tracking_origin_t origin) {
|
||||
switch (origin) {
|
||||
case KINC_TRACKING_ORIGIN_STAND:
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
|
||||
break;
|
||||
case KINC_TRACKING_ORIGIN_SIT:
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_EyeLevel);
|
||||
break;
|
||||
default:
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_vr_interface_reset_hmd_pose() {
|
||||
ovr_RecenterTrackingOrigin(session);
|
||||
}
|
||||
|
||||
void kinc_vr_interface_ovr_shutdown() {
|
||||
ovr_Shutdown();
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,53 @@
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/graphics4/constantbuffer.h>
|
||||
|
||||
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
|
||||
buffer->impl.size = size;
|
||||
buffer->impl.last_start = 0;
|
||||
buffer->impl.last_size = size;
|
||||
|
||||
buffer->impl.data = malloc(size);
|
||||
|
||||
buffer->impl.buffer = 0;
|
||||
glGenBuffers(1, &buffer->impl.buffer);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, buffer->impl.buffer);
|
||||
glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {
|
||||
free(buffer->impl.data);
|
||||
buffer->impl.data = NULL;
|
||||
|
||||
glDeleteBuffers(1, &buffer->impl.buffer);
|
||||
buffer->impl.buffer = 0;
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
|
||||
return kinc_g4_constant_buffer_lock(buffer, 0, kinc_g4_constant_buffer_size(buffer));
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
|
||||
buffer->impl.last_start = start;
|
||||
buffer->impl.last_size = size;
|
||||
|
||||
uint8_t *data = (uint8_t *)buffer->impl.data;
|
||||
return &data[start];
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g4_constant_buffer_unlock(buffer, buffer->impl.last_size);
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, buffer->impl.buffer);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, buffer->impl.last_start, buffer->impl.last_size, buffer->impl.data);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
|
||||
return buffer->impl.size;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct kinc_g4_constant_buffer_impl {
|
||||
unsigned buffer;
|
||||
void *data;
|
||||
size_t size;
|
||||
size_t last_start;
|
||||
size_t last_size;
|
||||
} kinc_g4_constant_buffer_impl;
|
||||
|
||||
#endif
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IndexBufferImpl.h"
|
||||
#include "RenderTargetImpl.h"
|
||||
#include "TextureImpl.h"
|
||||
#include "VertexBufferImpl.h"
|
@ -0,0 +1,105 @@
|
||||
#include "ogl.h"
|
||||
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
kinc_g4_index_buffer_t *Kinc_Internal_CurrentIndexBuffer = NULL;
|
||||
|
||||
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
|
||||
buffer->impl.count = count;
|
||||
buffer->impl.format = format;
|
||||
|
||||
glGenBuffers(1, &buffer->impl.buffer_id);
|
||||
glCheckErrors();
|
||||
if (format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT) {
|
||||
buffer->impl.data = malloc(count * sizeof(uint32_t));
|
||||
}
|
||||
else {
|
||||
buffer->impl.data = malloc(count * sizeof(uint16_t));
|
||||
}
|
||||
|
||||
if (format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT && kinc_internal_opengl_force_16bit_index_buffer) {
|
||||
buffer->impl.converted_data = malloc(count * sizeof(uint16_t));
|
||||
}
|
||||
else {
|
||||
buffer->impl.converted_data = NULL;
|
||||
}
|
||||
|
||||
switch (usage) {
|
||||
case KINC_G4_USAGE_STATIC:
|
||||
buffer->impl.usage = GL_STATIC_DRAW;
|
||||
break;
|
||||
case KINC_G4_USAGE_DYNAMIC:
|
||||
buffer->impl.usage = GL_DYNAMIC_DRAW;
|
||||
break;
|
||||
case KINC_G4_USAGE_READABLE:
|
||||
buffer->impl.usage = GL_DYNAMIC_DRAW;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Kinc_Internal_IndexBufferUnset(kinc_g4_index_buffer_t *buffer) {
|
||||
if (Kinc_Internal_CurrentIndexBuffer == buffer) {
|
||||
Kinc_Internal_CurrentIndexBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
|
||||
Kinc_Internal_IndexBufferUnset(buffer);
|
||||
glDeleteBuffers(1, &buffer->impl.buffer_id);
|
||||
free(buffer->impl.data);
|
||||
buffer->impl.data = NULL;
|
||||
free(buffer->impl.converted_data);
|
||||
buffer->impl.converted_data = NULL;
|
||||
}
|
||||
|
||||
static int kinc_g4_internal_index_buffer_stride(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT ? 4 : 2;
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
return kinc_g4_index_buffer_lock(buffer, 0, kinc_g4_index_buffer_count(buffer));
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
|
||||
uint8_t *data = (uint8_t *)buffer->impl.data;
|
||||
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->impl.buffer_id);
|
||||
glCheckErrors();
|
||||
|
||||
if (buffer->impl.format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT && kinc_internal_opengl_force_16bit_index_buffer) {
|
||||
uint32_t *data = (uint32_t *)buffer->impl.data;
|
||||
for (int i = 0; i < buffer->impl.count; ++i) {
|
||||
buffer->impl.converted_data[i] = (uint16_t)data[i];
|
||||
}
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer->impl.count * sizeof(uint16_t), buffer->impl.converted_data, buffer->impl.usage);
|
||||
glCheckErrors();
|
||||
}
|
||||
else {
|
||||
GLsizeiptr size =
|
||||
buffer->impl.format == KINC_G4_INDEX_BUFFER_FORMAT_16BIT ? buffer->impl.count * sizeof(uint16_t) : buffer->impl.count * sizeof(uint32_t);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, buffer->impl.data, buffer->impl.usage);
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
|
||||
kinc_g4_index_buffer_unlock_all(buffer);
|
||||
}
|
||||
|
||||
void kinc_internal_g4_index_buffer_set(kinc_g4_index_buffer_t *buffer) {
|
||||
Kinc_Internal_CurrentIndexBuffer = buffer;
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->impl.buffer_id);
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.count;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint16_t *converted_data;
|
||||
void *data;
|
||||
int count;
|
||||
unsigned usage;
|
||||
int format;
|
||||
unsigned buffer_id;
|
||||
} kinc_g4_index_buffer_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#ifdef KORE_MACOS
|
||||
#include <OpenGL/gl3.h>
|
||||
#include <OpenGL/gl3ext.h>
|
||||
#endif
|
||||
|
||||
#ifdef KORE_IOS
|
||||
#import <OpenGLES/ES2/gl.h>
|
||||
#import <OpenGLES/ES2/glext.h>
|
||||
#import <OpenGLES/ES3/gl.h>
|
||||
#endif
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
#include <EGL/egl.h>
|
||||
#if KORE_ANDROID_API >= 18
|
||||
#include <GLES3/gl3.h>
|
||||
#endif
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#endif
|
||||
|
||||
#ifdef KORE_EMSCRIPTEN
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#define EGL_EGLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#ifdef KORE_LINUX
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#endif
|
||||
|
||||
#ifdef KORE_PI
|
||||
// #define GL_GLEXT_PROTOTYPES
|
||||
#include "GLES2/gl2.h"
|
||||
|
||||
#include "EGL/egl.h"
|
||||
#include "EGL/eglext.h"
|
||||
#endif
|
||||
|
||||
#ifdef KORE_TIZEN
|
||||
#include <gl2.h>
|
||||
#endif
|
||||
|
||||
#ifdef KORE_WASM
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#include <kinc/log.h>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define glCheckErrors() \
|
||||
{}
|
||||
#else
|
||||
#define glCheckErrors() \
|
||||
{ \
|
||||
GLenum code = glGetError(); \
|
||||
if (code != GL_NO_ERROR) { \
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "GL Error %d %s %d\n", code, __FILE__, __LINE__); \
|
||||
} \
|
||||
}
|
||||
#endif
|
@ -0,0 +1,17 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
static bool kinc_internal_opengl_force_16bit_index_buffer = false;
|
||||
static int kinc_internal_opengl_max_vertex_attribute_arrays = 0;
|
||||
|
||||
#include "OpenGL.c.h"
|
||||
#include "OpenGLWindow.c.h"
|
||||
#include "ShaderStorageBufferImpl.c.h"
|
||||
#include "VrInterface.c.h"
|
||||
#include "constantbuffer.c.h"
|
||||
#include "indexbuffer.c.h"
|
||||
#include "pipeline.c.h"
|
||||
#include "rendertarget.c.h"
|
||||
#include "shader.c.h"
|
||||
#include "texture.c.h"
|
||||
#include "texturearray.c.h"
|
||||
#include "vertexbuffer.c.h"
|
@ -0,0 +1,482 @@
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include "ogl.h"
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/vertexstructure.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
#include <kinc/backend/graphics4/OpenGL.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef KORE_OPENGL_ES
|
||||
bool Kinc_Internal_ProgramUsesTessellation = false;
|
||||
#endif
|
||||
extern bool Kinc_Internal_SupportsConservativeRaster;
|
||||
|
||||
static GLenum convertStencilAction(kinc_g4_stencil_action_t action) {
|
||||
switch (action) {
|
||||
default:
|
||||
case KINC_G4_STENCIL_DECREMENT:
|
||||
return GL_DECR;
|
||||
case KINC_G4_STENCIL_DECREMENT_WRAP:
|
||||
return GL_DECR_WRAP;
|
||||
case KINC_G4_STENCIL_INCREMENT:
|
||||
return GL_INCR;
|
||||
case KINC_G4_STENCIL_INCREMENT_WRAP:
|
||||
return GL_INCR_WRAP;
|
||||
case KINC_G4_STENCIL_INVERT:
|
||||
return GL_INVERT;
|
||||
case KINC_G4_STENCIL_KEEP:
|
||||
return GL_KEEP;
|
||||
case KINC_G4_STENCIL_REPLACE:
|
||||
return GL_REPLACE;
|
||||
case KINC_G4_STENCIL_ZERO:
|
||||
return GL_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
static GLenum convert_blend_factor(kinc_g4_blending_factor_t factor) {
|
||||
switch (factor) {
|
||||
case KINC_G4_BLEND_ZERO:
|
||||
return GL_ZERO;
|
||||
case KINC_G4_BLEND_ONE:
|
||||
return GL_ONE;
|
||||
case KINC_G4_BLEND_SOURCE_ALPHA:
|
||||
return GL_SRC_ALPHA;
|
||||
case KINC_G4_BLEND_DEST_ALPHA:
|
||||
return GL_DST_ALPHA;
|
||||
case KINC_G4_BLEND_INV_SOURCE_ALPHA:
|
||||
return GL_ONE_MINUS_SRC_ALPHA;
|
||||
case KINC_G4_BLEND_INV_DEST_ALPHA:
|
||||
return GL_ONE_MINUS_DST_ALPHA;
|
||||
case KINC_G4_BLEND_SOURCE_COLOR:
|
||||
return GL_SRC_COLOR;
|
||||
case KINC_G4_BLEND_DEST_COLOR:
|
||||
return GL_DST_COLOR;
|
||||
case KINC_G4_BLEND_INV_SOURCE_COLOR:
|
||||
return GL_ONE_MINUS_SRC_COLOR;
|
||||
case KINC_G4_BLEND_INV_DEST_COLOR:
|
||||
return GL_ONE_MINUS_DST_COLOR;
|
||||
case KINC_G4_BLEND_CONSTANT:
|
||||
return GL_CONSTANT_COLOR;
|
||||
case KINC_G4_BLEND_INV_CONSTANT:
|
||||
return GL_ONE_MINUS_CONSTANT_COLOR;
|
||||
default:
|
||||
assert(false);
|
||||
return GL_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
static GLenum convert_blend_operation(kinc_g4_blending_operation_t operation) {
|
||||
switch (operation) {
|
||||
case KINC_G4_BLENDOP_ADD:
|
||||
return GL_FUNC_ADD;
|
||||
case KINC_G4_BLENDOP_SUBTRACT:
|
||||
return GL_FUNC_SUBTRACT;
|
||||
case KINC_G4_BLENDOP_REVERSE_SUBTRACT:
|
||||
return GL_FUNC_REVERSE_SUBTRACT;
|
||||
case KINC_G4_BLENDOP_MIN:
|
||||
return GL_MIN;
|
||||
case KINC_G4_BLENDOP_MAX:
|
||||
return GL_MAX;
|
||||
default:
|
||||
assert(false);
|
||||
return GL_FUNC_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_init(kinc_g4_pipeline_t *state) {
|
||||
memset(state, 0, sizeof(kinc_g4_pipeline_t));
|
||||
|
||||
kinc_g4_internal_pipeline_set_defaults(state);
|
||||
|
||||
state->impl.textureCount = 0;
|
||||
// TODO: Get rid of allocations
|
||||
state->impl.textures = (char **)malloc(sizeof(char *) * 16);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
state->impl.textures[i] = (char *)malloc(sizeof(char) * 128);
|
||||
state->impl.textures[i][0] = 0;
|
||||
}
|
||||
state->impl.textureValues = (int *)malloc(sizeof(int) * 16);
|
||||
state->impl.programId = glCreateProgram();
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_destroy(kinc_g4_pipeline_t *state) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
free(state->impl.textures[i]);
|
||||
}
|
||||
free(state->impl.textures);
|
||||
free(state->impl.textureValues);
|
||||
glDeleteProgram(state->impl.programId);
|
||||
}
|
||||
|
||||
static int toGlShader(kinc_g4_shader_type_t type) {
|
||||
switch (type) {
|
||||
case KINC_G4_SHADER_TYPE_VERTEX:
|
||||
default:
|
||||
return GL_VERTEX_SHADER;
|
||||
case KINC_G4_SHADER_TYPE_FRAGMENT:
|
||||
return GL_FRAGMENT_SHADER;
|
||||
#ifndef KORE_OPENGL_ES
|
||||
case KINC_G4_SHADER_TYPE_GEOMETRY:
|
||||
return GL_GEOMETRY_SHADER;
|
||||
case KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL:
|
||||
return GL_TESS_CONTROL_SHADER;
|
||||
case KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION:
|
||||
return GL_TESS_EVALUATION_SHADER;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void compileShader(unsigned *id, const char *source, size_t length, kinc_g4_shader_type_t type) {
|
||||
*id = glCreateShader(toGlShader(type));
|
||||
glCheckErrors();
|
||||
glShaderSource(*id, 1, (const GLchar **)&source, 0);
|
||||
glCompileShader(*id);
|
||||
|
||||
int result;
|
||||
glGetShaderiv(*id, GL_COMPILE_STATUS, &result);
|
||||
if (result != GL_TRUE) {
|
||||
int length = 0;
|
||||
glGetShaderiv(*id, GL_INFO_LOG_LENGTH, &length);
|
||||
char *errormessage = (char *)malloc(length);
|
||||
glGetShaderInfoLog(*id, length, NULL, errormessage);
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "GLSL compiler error: %s", errormessage);
|
||||
free(errormessage);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *state) {
|
||||
compileShader(&state->vertex_shader->impl._glid, state->vertex_shader->impl.source, state->vertex_shader->impl.length, KINC_G4_SHADER_TYPE_VERTEX);
|
||||
compileShader(&state->fragment_shader->impl._glid, state->fragment_shader->impl.source, state->fragment_shader->impl.length, KINC_G4_SHADER_TYPE_FRAGMENT);
|
||||
#ifndef KORE_OPENGL_ES
|
||||
if (state->geometry_shader != NULL) {
|
||||
compileShader(&state->geometry_shader->impl._glid, state->geometry_shader->impl.source, state->geometry_shader->impl.length,
|
||||
KINC_G4_SHADER_TYPE_GEOMETRY);
|
||||
}
|
||||
if (state->tessellation_control_shader != NULL) {
|
||||
compileShader(&state->tessellation_control_shader->impl._glid, state->tessellation_control_shader->impl.source,
|
||||
state->tessellation_control_shader->impl.length, KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL);
|
||||
}
|
||||
if (state->tessellation_evaluation_shader != NULL) {
|
||||
compileShader(&state->tessellation_evaluation_shader->impl._glid, state->tessellation_evaluation_shader->impl.source,
|
||||
state->tessellation_evaluation_shader->impl.length, KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION);
|
||||
}
|
||||
#endif
|
||||
glAttachShader(state->impl.programId, state->vertex_shader->impl._glid);
|
||||
glAttachShader(state->impl.programId, state->fragment_shader->impl._glid);
|
||||
#ifndef KORE_OPENGL_ES
|
||||
if (state->geometry_shader != NULL) {
|
||||
glAttachShader(state->impl.programId, state->geometry_shader->impl._glid);
|
||||
}
|
||||
if (state->tessellation_control_shader != NULL) {
|
||||
glAttachShader(state->impl.programId, state->tessellation_control_shader->impl._glid);
|
||||
}
|
||||
if (state->tessellation_evaluation_shader != NULL) {
|
||||
glAttachShader(state->impl.programId, state->tessellation_evaluation_shader->impl._glid);
|
||||
}
|
||||
#endif
|
||||
glCheckErrors();
|
||||
|
||||
int index = 0;
|
||||
for (int i1 = 0; state->input_layout[i1] != NULL; ++i1) {
|
||||
for (int i2 = 0; i2 < state->input_layout[i1]->size; ++i2) {
|
||||
kinc_g4_vertex_element_t element = state->input_layout[i1]->elements[i2];
|
||||
glBindAttribLocation(state->impl.programId, index, element.name);
|
||||
glCheckErrors();
|
||||
if (element.data == KINC_G4_VERTEX_DATA_F32_4X4) {
|
||||
index += 4;
|
||||
}
|
||||
else {
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glLinkProgram(state->impl.programId);
|
||||
|
||||
int result;
|
||||
glGetProgramiv(state->impl.programId, GL_LINK_STATUS, &result);
|
||||
if (result != GL_TRUE) {
|
||||
int length = 0;
|
||||
glGetProgramiv(state->impl.programId, GL_INFO_LOG_LENGTH, &length);
|
||||
char *errormessage = (char *)malloc(length);
|
||||
glGetProgramInfoLog(state->impl.programId, length, NULL, errormessage);
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "GLSL linker error: %s", errormessage);
|
||||
free(errormessage);
|
||||
}
|
||||
|
||||
#ifndef KORE_OPENGL_ES
|
||||
#ifndef KORE_LINUX
|
||||
if (state->tessellation_control_shader != NULL) {
|
||||
glPatchParameteri(GL_PATCH_VERTICES, 3);
|
||||
glCheckErrors();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_internal_set_pipeline(kinc_g4_pipeline_t *pipeline) {
|
||||
#ifndef KORE_OPENGL_ES
|
||||
Kinc_Internal_ProgramUsesTessellation = pipeline->tessellation_control_shader != NULL;
|
||||
#endif
|
||||
glUseProgram(pipeline->impl.programId);
|
||||
glCheckErrors();
|
||||
for (int index = 0; index < pipeline->impl.textureCount; ++index) {
|
||||
glUniform1i(pipeline->impl.textureValues[index], index);
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
if (pipeline->stencil_front_mode == KINC_G4_COMPARE_ALWAYS && pipeline->stencil_back_mode == KINC_G4_COMPARE_ALWAYS &&
|
||||
pipeline->stencil_front_both_pass == KINC_G4_STENCIL_KEEP && pipeline->stencil_back_both_pass == KINC_G4_STENCIL_KEEP &&
|
||||
pipeline->stencil_front_depth_fail == KINC_G4_STENCIL_KEEP && pipeline->stencil_back_depth_fail == KINC_G4_STENCIL_KEEP &&
|
||||
pipeline->stencil_front_fail == KINC_G4_STENCIL_KEEP && pipeline->stencil_back_fail == KINC_G4_STENCIL_KEEP) {
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
else {
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
glStencilMaskSeparate(GL_FRONT, pipeline->stencil_write_mask);
|
||||
glStencilOpSeparate(GL_FRONT, convertStencilAction(pipeline->stencil_front_fail), convertStencilAction(pipeline->stencil_front_depth_fail),
|
||||
convertStencilAction(pipeline->stencil_front_both_pass));
|
||||
glStencilFuncSeparate(GL_FRONT, Kinc_G4_Internal_StencilFunc(pipeline->stencil_front_mode), pipeline->stencil_reference_value,
|
||||
pipeline->stencil_read_mask);
|
||||
|
||||
glStencilMaskSeparate(GL_BACK, pipeline->stencil_write_mask);
|
||||
glStencilOpSeparate(GL_BACK, convertStencilAction(pipeline->stencil_back_fail), convertStencilAction(pipeline->stencil_back_depth_fail),
|
||||
convertStencilAction(pipeline->stencil_back_both_pass));
|
||||
glStencilFuncSeparate(GL_BACK, Kinc_G4_Internal_StencilFunc(pipeline->stencil_back_mode), pipeline->stencil_reference_value,
|
||||
pipeline->stencil_read_mask);
|
||||
}
|
||||
|
||||
#ifdef KORE_OPENGL_ES
|
||||
glColorMask(pipeline->color_write_mask_red[0], pipeline->color_write_mask_green[0], pipeline->color_write_mask_blue[0],
|
||||
pipeline->color_write_mask_alpha[0]);
|
||||
#else
|
||||
for (int i = 0; i < 8; ++i)
|
||||
glColorMaski(i, pipeline->color_write_mask_red[i], pipeline->color_write_mask_green[i], pipeline->color_write_mask_blue[i],
|
||||
pipeline->color_write_mask_alpha[i]);
|
||||
#endif
|
||||
|
||||
if (Kinc_Internal_SupportsConservativeRaster) {
|
||||
if (pipeline->conservative_rasterization) {
|
||||
glEnable(0x9346); // GL_CONSERVATIVE_RASTERIZATION_NV
|
||||
}
|
||||
else {
|
||||
glDisable(0x9346);
|
||||
}
|
||||
}
|
||||
|
||||
glCheckErrors();
|
||||
|
||||
/*switch (state) {
|
||||
case Normalize:
|
||||
device->SetRenderState(D3DRS_NORMALIZENORMALS, on ? TRUE : FALSE);
|
||||
break;
|
||||
case BackfaceCulling:
|
||||
if (on) device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
||||
else device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
break;
|
||||
case FogState:
|
||||
device->SetRenderState(D3DRS_FOGENABLE, on ? TRUE : FALSE);
|
||||
break;
|
||||
case ScissorTestState:
|
||||
device->SetRenderState(D3DRS_SCISSORTESTENABLE, on ? TRUE : FALSE);
|
||||
break;
|
||||
case AlphaTestState:
|
||||
device->SetRenderState(D3DRS_ALPHATESTENABLE, on ? TRUE : FALSE);
|
||||
device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
break;
|
||||
default:
|
||||
throw Exception();
|
||||
}*/
|
||||
|
||||
if (pipeline->depth_write) {
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
else {
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
|
||||
if (pipeline->depth_mode != KINC_G4_COMPARE_ALWAYS) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
else {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
GLenum func = GL_ALWAYS;
|
||||
switch (pipeline->depth_mode) {
|
||||
default:
|
||||
case KINC_G4_COMPARE_ALWAYS:
|
||||
func = GL_ALWAYS;
|
||||
break;
|
||||
case KINC_G4_COMPARE_NEVER:
|
||||
func = GL_NEVER;
|
||||
break;
|
||||
case KINC_G4_COMPARE_EQUAL:
|
||||
func = GL_EQUAL;
|
||||
break;
|
||||
case KINC_G4_COMPARE_NOT_EQUAL:
|
||||
func = GL_NOTEQUAL;
|
||||
break;
|
||||
case KINC_G4_COMPARE_LESS:
|
||||
func = GL_LESS;
|
||||
break;
|
||||
case KINC_G4_COMPARE_LESS_EQUAL:
|
||||
func = GL_LEQUAL;
|
||||
break;
|
||||
case KINC_G4_COMPARE_GREATER:
|
||||
func = GL_GREATER;
|
||||
break;
|
||||
case KINC_G4_COMPARE_GREATER_EQUAL:
|
||||
func = GL_GEQUAL;
|
||||
break;
|
||||
}
|
||||
glDepthFunc(func);
|
||||
glCheckErrors();
|
||||
|
||||
switch (pipeline->cull_mode) {
|
||||
case KINC_G4_CULL_CLOCKWISE:
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glCheckErrors();
|
||||
break;
|
||||
case KINC_G4_CULL_COUNTER_CLOCKWISE:
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_FRONT);
|
||||
glCheckErrors();
|
||||
break;
|
||||
case KINC_G4_CULL_NOTHING:
|
||||
glDisable(GL_CULL_FACE);
|
||||
glCheckErrors();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*switch (state) {
|
||||
case DepthTestCompare:
|
||||
switch (v) {
|
||||
// TODO: Cmp-Konstanten systemabhaengig abgleichen
|
||||
default:
|
||||
case ZCmp_Always : v = D3DCMP_ALWAYS; break;
|
||||
case ZCmp_Never : v = D3DCMP_NEVER; break;
|
||||
case ZCmp_Equal : v = D3DCMP_EQUAL; break;
|
||||
case ZCmp_NotEqual : v = D3DCMP_NOTEQUAL; break;
|
||||
case ZCmp_Less : v = D3DCMP_LESS; break;
|
||||
case ZCmp_LessEqual : v = D3DCMP_LESSEQUAL; break;
|
||||
case ZCmp_Greater : v = D3DCMP_GREATER; break;
|
||||
case ZCmp_GreaterEqual: v = D3DCMP_GREATEREQUAL; break;
|
||||
}
|
||||
device->SetRenderState(D3DRS_ZFUNC, v);
|
||||
break;
|
||||
case FogTypeState:
|
||||
switch (v) {
|
||||
case LinearFog:
|
||||
device->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
|
||||
}
|
||||
break;
|
||||
case AlphaReferenceState:
|
||||
device->SetRenderState(D3DRS_ALPHAREF, (DWORD)v);
|
||||
break;
|
||||
default:
|
||||
throw Exception();
|
||||
}*/
|
||||
|
||||
if (pipeline->blend_source != KINC_G4_BLEND_ONE || pipeline->blend_destination != KINC_G4_BLEND_ZERO || pipeline->alpha_blend_source != KINC_G4_BLEND_ONE ||
|
||||
pipeline->alpha_blend_destination != KINC_G4_BLEND_ZERO) {
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
// glBlendFunc(convert(pipeline->blendSource), convert(pipeline->blendDestination));
|
||||
glBlendFuncSeparate(convert_blend_factor(pipeline->blend_source), convert_blend_factor(pipeline->blend_destination),
|
||||
convert_blend_factor(pipeline->alpha_blend_source), convert_blend_factor(pipeline->alpha_blend_destination));
|
||||
glBlendEquationSeparate(convert_blend_operation(pipeline->blend_operation), convert_blend_operation(pipeline->alpha_blend_operation));
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_get_constant_locations(kinc_g4_pipeline_t *state, kinc_g4_constant_location_t *vertex_locations,
|
||||
kinc_g4_constant_location_t *fragment_locations, int *vertex_sizes, int *fragment_sizes, int *max_vertex,
|
||||
int *max_fragment) {
|
||||
// GLint count = 0;
|
||||
// glGetProgramiv(state->impl.programId, GL_ACTIVE_UNIFORMS, &count);
|
||||
// if (locations == NULL || sizes == NULL) {
|
||||
// *max_count = count;
|
||||
// }
|
||||
// else {
|
||||
// for (GLint i = 0; i < count; ++i) {
|
||||
// GLenum type;
|
||||
// char uniformName[1024];
|
||||
// GLsizei length;
|
||||
// GLint size;
|
||||
// glGetActiveUniform(state->impl.programId, i, 1024 - 1, &length, &size, &type, uniformName);
|
||||
// locations[i].impl.location = glGetUniformLocation(state->impl.programId, uniformName);
|
||||
// locations[i].impl.type = type;
|
||||
// sizes[i] = size;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(kinc_g4_pipeline_t *state, const char *name) {
|
||||
kinc_g4_constant_location_t location;
|
||||
location.impl.location = glGetUniformLocation(state->impl.programId, name);
|
||||
location.impl.type = GL_FLOAT;
|
||||
GLint count = 0;
|
||||
glGetProgramiv(state->impl.programId, GL_ACTIVE_UNIFORMS, &count);
|
||||
char arrayName[1024];
|
||||
strcpy(arrayName, name);
|
||||
strcat(arrayName, "[0]");
|
||||
for (GLint i = 0; i < count; ++i) {
|
||||
GLenum type;
|
||||
char uniformName[1024];
|
||||
GLsizei length;
|
||||
GLint size;
|
||||
glGetActiveUniform(state->impl.programId, i, 1024 - 1, &length, &size, &type, uniformName);
|
||||
if (strcmp(uniformName, name) == 0 || strcmp(uniformName, arrayName) == 0) {
|
||||
location.impl.type = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
glCheckErrors();
|
||||
if (location.impl.location < 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
static int findTexture(kinc_g4_pipeline_t *state, const char *name) {
|
||||
for (int index = 0; index < state->impl.textureCount; ++index) {
|
||||
if (strcmp(state->impl.textures[index], name) == 0)
|
||||
return index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(kinc_g4_pipeline_t *state, const char *name) {
|
||||
int index = findTexture(state, name);
|
||||
if (index < 0) {
|
||||
int location = glGetUniformLocation(state->impl.programId, name);
|
||||
glCheckErrors();
|
||||
index = state->impl.textureCount;
|
||||
state->impl.textureValues[index] = location;
|
||||
strcpy(state->impl.textures[index], name);
|
||||
++state->impl.textureCount;
|
||||
}
|
||||
kinc_g4_texture_unit_t unit;
|
||||
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
|
||||
unit.stages[i] = -1;
|
||||
}
|
||||
unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] = index;
|
||||
return unit;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned programId;
|
||||
char **textures;
|
||||
int *textureValues;
|
||||
int textureCount;
|
||||
} kinc_g4_pipeline_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,421 @@
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
|
||||
#include "ogl.h"
|
||||
|
||||
#include <kinc/backend/graphics4/OpenGL.h>
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/system.h>
|
||||
|
||||
#ifndef GL_RGBA16F_EXT
|
||||
#define GL_RGBA16F_EXT 0x881A
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA32F_EXT
|
||||
#define GL_RGBA32F_EXT 0x8814
|
||||
#endif
|
||||
|
||||
#ifndef GL_R16F_EXT
|
||||
#define GL_R16F_EXT 0x822D
|
||||
#endif
|
||||
|
||||
#ifndef GL_R32F_EXT
|
||||
#define GL_R32F_EXT 0x822E
|
||||
#endif
|
||||
|
||||
#ifndef GL_HALF_FLOAT
|
||||
#define GL_HALF_FLOAT 0x140B
|
||||
#endif
|
||||
|
||||
#ifndef GL_RED
|
||||
#define GL_RED GL_LUMINANCE
|
||||
#endif
|
||||
|
||||
#ifndef GL_R8
|
||||
#define GL_R8 GL_RED
|
||||
#endif
|
||||
|
||||
extern bool Kinc_Internal_SupportsDepthTexture;
|
||||
|
||||
static int pow2(int pow) {
|
||||
int ret = 1;
|
||||
for (int i = 0; i < pow; ++i)
|
||||
ret *= 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int getPower2(int i) {
|
||||
for (int power = 0;; ++power)
|
||||
if (pow2(power) >= i)
|
||||
return pow2(power);
|
||||
}
|
||||
|
||||
#ifdef KORE_OPENGL_ES
|
||||
extern int gles_version;
|
||||
#endif
|
||||
|
||||
bool kinc_opengl_internal_nonPow2RenderTargetsSupported() {
|
||||
#ifdef KORE_OPENGL_ES
|
||||
return gles_version >= 3;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void setupDepthStencil(kinc_g4_render_target_t *renderTarget, GLenum texType, int depthBufferBits, int stencilBufferBits, int width, int height) {
|
||||
if (depthBufferBits > 0 && stencilBufferBits > 0) {
|
||||
renderTarget->impl._hasDepth = true;
|
||||
#if defined(KORE_OPENGL_ES) && !defined(KORE_PI) && !defined(KORE_EMSCRIPTEN)
|
||||
GLenum internalFormat = GL_DEPTH24_STENCIL8_OES;
|
||||
#elif defined(KORE_OPENGL_ES)
|
||||
GLenum internalFormat = 0x88F0; // GL_DEPTH24_STENCIL8_OES
|
||||
#else
|
||||
GLenum internalFormat;
|
||||
if (depthBufferBits == 24)
|
||||
internalFormat = GL_DEPTH24_STENCIL8;
|
||||
else
|
||||
internalFormat = GL_DEPTH32F_STENCIL8;
|
||||
#endif
|
||||
// Renderbuffer
|
||||
// glGenRenderbuffers(1, &_depthRenderbuffer);
|
||||
// glCheckErrors();
|
||||
// glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer);
|
||||
// glCheckErrors();
|
||||
// glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height);
|
||||
// glCheckErrors();
|
||||
// #ifdef KORE_OPENGL_ES
|
||||
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
|
||||
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
|
||||
// #else
|
||||
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
|
||||
// #endif
|
||||
// glCheckErrors();
|
||||
// Texture
|
||||
glGenTextures(1, &renderTarget->impl._depthTexture);
|
||||
glCheckErrors();
|
||||
glBindTexture(texType, renderTarget->impl._depthTexture);
|
||||
glCheckErrors();
|
||||
glTexImage2D(texType, 0, internalFormat, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
|
||||
glCheckErrors();
|
||||
glTexParameteri(texType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(texType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(texType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(texType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glCheckErrors();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
|
||||
glCheckErrors();
|
||||
#ifdef KORE_OPENGL_ES
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texType, renderTarget->impl._depthTexture, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, texType, renderTarget->impl._depthTexture, 0);
|
||||
#else
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, texType, renderTarget->impl._depthTexture, 0);
|
||||
#endif
|
||||
glCheckErrors();
|
||||
}
|
||||
else if (depthBufferBits > 0) {
|
||||
renderTarget->impl._hasDepth = true;
|
||||
if (!Kinc_Internal_SupportsDepthTexture) {
|
||||
// Renderbuffer
|
||||
glGenRenderbuffers(1, &renderTarget->impl._depthTexture);
|
||||
glCheckErrors();
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, renderTarget->impl._depthTexture);
|
||||
glCheckErrors();
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
|
||||
glCheckErrors();
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderTarget->impl._depthTexture);
|
||||
glCheckErrors();
|
||||
}
|
||||
else {
|
||||
// Texture
|
||||
glGenTextures(1, &renderTarget->impl._depthTexture);
|
||||
glCheckErrors();
|
||||
glBindTexture(texType, renderTarget->impl._depthTexture);
|
||||
glCheckErrors();
|
||||
#if defined(KORE_EMSCRIPTEN) || defined(KORE_WASM)
|
||||
GLint format = GL_DEPTH_COMPONENT16;
|
||||
#else
|
||||
GLint format = depthBufferBits == 16 ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT;
|
||||
#endif
|
||||
glTexImage2D(texType, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
|
||||
glCheckErrors();
|
||||
glTexParameteri(texType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(texType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(texType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(texType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glCheckErrors();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
|
||||
glCheckErrors();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texType, renderTarget->impl._depthTexture, 0);
|
||||
glCheckErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->width = width;
|
||||
renderTarget->height = height;
|
||||
renderTarget->isCubeMap = false;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
|
||||
renderTarget->impl._hasDepth = false;
|
||||
|
||||
if (kinc_opengl_internal_nonPow2RenderTargetsSupported()) {
|
||||
renderTarget->texWidth = width;
|
||||
renderTarget->texHeight = height;
|
||||
}
|
||||
else {
|
||||
renderTarget->texWidth = getPower2(width);
|
||||
renderTarget->texHeight = getPower2(height);
|
||||
}
|
||||
|
||||
renderTarget->impl.format = (int)format;
|
||||
|
||||
glGenTextures(1, &renderTarget->impl._texture);
|
||||
glCheckErrors();
|
||||
glBindTexture(GL_TEXTURE_2D, renderTarget->impl._texture);
|
||||
glCheckErrors();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glCheckErrors();
|
||||
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
#ifdef KORE_OPENGL_ES
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_FLOAT, 0);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_FLOAT, 0);
|
||||
#endif
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
#ifdef KORE_OPENGL_ES
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||
#endif
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH:
|
||||
#ifdef KORE_OPENGL_ES
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
#endif
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, renderTarget->texWidth, renderTarget->texHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
#ifdef KORE_IOS
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
|
||||
#endif
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RED, GL_HALF_FLOAT, 0);
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RED, GL_FLOAT, 0);
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
}
|
||||
|
||||
glCheckErrors();
|
||||
glGenFramebuffers(1, &renderTarget->impl._framebuffer);
|
||||
glCheckErrors();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
|
||||
glCheckErrors();
|
||||
|
||||
setupDepthStencil(renderTarget, GL_TEXTURE_2D, depthBufferBits, stencilBufferBits, renderTarget->texWidth, renderTarget->texHeight);
|
||||
|
||||
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, renderTarget->impl._texture, 0);
|
||||
#ifndef KORE_OPENGL_ES
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget->impl._texture, 0);
|
||||
}
|
||||
glCheckErrors();
|
||||
// GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
|
||||
// glDrawBuffers(1, drawBuffers);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glCheckErrors();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->width = cubeMapSize;
|
||||
renderTarget->height = cubeMapSize;
|
||||
renderTarget->isCubeMap = true;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
|
||||
renderTarget->impl._hasDepth = false;
|
||||
|
||||
if (kinc_opengl_internal_nonPow2RenderTargetsSupported()) {
|
||||
renderTarget->texWidth = renderTarget->width;
|
||||
renderTarget->texHeight = renderTarget->height;
|
||||
}
|
||||
else {
|
||||
renderTarget->texWidth = getPower2(renderTarget->width);
|
||||
renderTarget->texHeight = getPower2(renderTarget->height);
|
||||
}
|
||||
|
||||
renderTarget->impl.format = (int)format;
|
||||
|
||||
glGenTextures(1, &renderTarget->impl._texture);
|
||||
glCheckErrors();
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, renderTarget->impl._texture);
|
||||
glCheckErrors();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glCheckErrors();
|
||||
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
#ifdef KORE_OPENGL_ES
|
||||
for (int i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_FLOAT, 0);
|
||||
#else
|
||||
for (int i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_FLOAT, 0);
|
||||
#endif
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
#ifdef KORE_OPENGL_ES
|
||||
for (int i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA16F_EXT, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||
#else
|
||||
for (int i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA16F, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||
#endif
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH:
|
||||
#ifdef KORE_OPENGL_ES
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
#endif
|
||||
for (int i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT16, renderTarget->texWidth, renderTarget->texHeight, 0, GL_DEPTH_COMPONENT,
|
||||
GL_UNSIGNED_INT, 0);
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
for (int i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, renderTarget->texWidth, renderTarget->texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
}
|
||||
|
||||
glCheckErrors();
|
||||
glGenFramebuffers(1, &renderTarget->impl._framebuffer);
|
||||
glCheckErrors();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
|
||||
glCheckErrors();
|
||||
|
||||
setupDepthStencil(renderTarget, GL_TEXTURE_CUBE_MAP, depthBufferBits, stencilBufferBits, renderTarget->texWidth, renderTarget->texHeight);
|
||||
|
||||
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
|
||||
renderTarget->isDepthAttachment = true;
|
||||
#ifndef KORE_OPENGL_ES
|
||||
glDrawBuffer(GL_NONE);
|
||||
glCheckErrors();
|
||||
glReadBuffer(GL_NONE);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glCheckErrors();
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget) {
|
||||
{
|
||||
GLuint textures[] = {renderTarget->impl._texture};
|
||||
glDeleteTextures(1, textures);
|
||||
}
|
||||
if (renderTarget->impl._hasDepth) {
|
||||
GLuint textures[] = {renderTarget->impl._depthTexture};
|
||||
glDeleteTextures(1, textures);
|
||||
}
|
||||
GLuint framebuffers[] = {renderTarget->impl._framebuffer};
|
||||
glDeleteFramebuffers(1, framebuffers);
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, uint32_t unit) {
|
||||
glActiveTexture(GL_TEXTURE0 + unit);
|
||||
glCheckErrors();
|
||||
glBindTexture(renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._texture);
|
||||
glCheckErrors();
|
||||
}
|
||||
#else
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
glActiveTexture(GL_TEXTURE0 + unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]);
|
||||
glCheckErrors();
|
||||
glBindTexture(renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._texture);
|
||||
glCheckErrors();
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
glActiveTexture(GL_TEXTURE0 + unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]);
|
||||
glCheckErrors();
|
||||
glBindTexture(renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._depthTexture);
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source) {
|
||||
renderTarget->impl._depthTexture = source->impl._depthTexture;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._depthTexture,
|
||||
0);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *renderTarget, uint8_t *data) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->impl._framebuffer);
|
||||
switch ((kinc_g4_render_target_format_t)renderTarget->impl.format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RGBA, GL_FLOAT, data);
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RGBA, GL_HALF_FLOAT, data);
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RED, GL_UNSIGNED_BYTE, data);
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RED, GL_HALF_FLOAT, data);
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RED, GL_FLOAT, data);
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
glReadPixels(0, 0, renderTarget->texWidth, renderTarget->texHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *renderTarget, int levels) {
|
||||
glBindTexture(GL_TEXTURE_2D, renderTarget->impl._texture);
|
||||
glCheckErrors();
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glCheckErrors();
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned _framebuffer;
|
||||
unsigned _texture;
|
||||
unsigned _depthTexture;
|
||||
bool _hasDepth;
|
||||
// unsigned _depthRenderbuffer;
|
||||
int format;
|
||||
} kinc_g4_render_target_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,53 @@
|
||||
#include "ogl.h"
|
||||
|
||||
#include <kinc/graphics4/shader.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *data, size_t length, kinc_g4_shader_type_t type) {
|
||||
shader->impl.length = length;
|
||||
shader->impl._glid = 0;
|
||||
char *source = (char *)malloc(length + 1);
|
||||
memcpy(source, data, length);
|
||||
source[length] = 0;
|
||||
shader->impl.source = source;
|
||||
}
|
||||
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
extern int krafix_compile(const char *source, char *output, int *length, const char *targetlang, const char *system, const char *shadertype, int version);
|
||||
#endif
|
||||
|
||||
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
char *output = malloc(1024 * 1024);
|
||||
int length;
|
||||
#ifdef KINC_WINDOWS
|
||||
const char *system = "windows";
|
||||
#elif defined(KINC_MACOS)
|
||||
const char *system = "macos";
|
||||
#elif defined(KINC_LINUX)
|
||||
const char *system = "linux";
|
||||
#elif defined(KINC_ANDROID)
|
||||
const char *system = "android";
|
||||
#elif defined(KINC_IOS)
|
||||
const char *system = "ios";
|
||||
#endif
|
||||
int errors = krafix_compile(source, output, &length, "glsl", system, type == KINC_G4_SHADER_TYPE_FRAGMENT ? "frag" : "vert", -1);
|
||||
if (errors > 0) {
|
||||
return errors;
|
||||
}
|
||||
kinc_g4_shader_init(shader, output, length, type);
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {
|
||||
free((void *)shader->impl.source);
|
||||
shader->impl.source = NULL;
|
||||
if (shader->impl._glid != 0) {
|
||||
glDeleteShader(shader->impl._glid);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned _glid;
|
||||
const char *source;
|
||||
size_t length;
|
||||
} kinc_g4_shader_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int location;
|
||||
unsigned type;
|
||||
} kinc_g4_constant_location_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int unit;
|
||||
} kinc_g4_texture_unit_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,640 @@
|
||||
#include <kinc/graphics4/texture.h>
|
||||
|
||||
#include "ogl.h"
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/image.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
#include "OpenGL.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef GL_TEXTURE_3D
|
||||
#define GL_TEXTURE_3D 0x806F
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA16F_EXT
|
||||
#define GL_RGBA16F_EXT 0x881A
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA32F_EXT
|
||||
#define GL_RGBA32F_EXT 0x8814
|
||||
#endif
|
||||
|
||||
#ifndef GL_R16F_EXT
|
||||
#define GL_R16F_EXT 0x822D
|
||||
#endif
|
||||
|
||||
#ifndef GL_R32F_EXT
|
||||
#define GL_R32F_EXT 0x822E
|
||||
#endif
|
||||
|
||||
#ifndef GL_HALF_FLOAT
|
||||
#define GL_HALF_FLOAT 0x140B
|
||||
#endif
|
||||
|
||||
#ifndef GL_RED
|
||||
#define GL_RED GL_LUMINANCE
|
||||
#endif
|
||||
|
||||
#ifndef GL_R8
|
||||
#define GL_R8 GL_RED
|
||||
#endif
|
||||
|
||||
#ifndef GL_RGBA8
|
||||
#define GL_RGBA8 GL_RGBA
|
||||
#endif
|
||||
|
||||
#ifndef GL_KHR_texture_compression_astc_ldr
|
||||
#define GL_KHR_texture_compression_astc_ldr 1
|
||||
|
||||
#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
|
||||
#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
|
||||
#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
|
||||
#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
|
||||
#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
|
||||
#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
|
||||
#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
|
||||
#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
|
||||
#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
|
||||
#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
|
||||
#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
|
||||
#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
|
||||
#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
|
||||
#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
|
||||
#endif
|
||||
|
||||
static int convertFormat(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_BGRA32:
|
||||
#ifdef GL_BGRA
|
||||
return GL_BGRA;
|
||||
#else
|
||||
return GL_RGBA;
|
||||
#endif
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
default:
|
||||
return GL_RGBA;
|
||||
case KINC_IMAGE_FORMAT_RGB24:
|
||||
return GL_RGB;
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return GL_RED;
|
||||
}
|
||||
}
|
||||
|
||||
static int convertInternalFormat(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
return GL_RGBA32F_EXT;
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
return GL_RGBA16F_EXT;
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
return GL_RGBA8;
|
||||
default:
|
||||
#ifdef KORE_IOS
|
||||
return GL_RGBA;
|
||||
#else
|
||||
// #ifdef GL_BGRA
|
||||
// return GL_BGRA;
|
||||
// #else
|
||||
return GL_RGBA;
|
||||
// #endif
|
||||
#endif
|
||||
case KINC_IMAGE_FORMAT_RGB24:
|
||||
return GL_RGB;
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
return GL_R32F_EXT;
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
return GL_R16F_EXT;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
#ifdef KORE_IOS
|
||||
return GL_RED;
|
||||
#else
|
||||
return GL_R8;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int convertType(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
return GL_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
default:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
}
|
||||
}
|
||||
|
||||
static int astcFormat(uint8_t blockX, uint8_t blockY) {
|
||||
switch (blockX) {
|
||||
case 4:
|
||||
switch (blockY) {
|
||||
case 4:
|
||||
return GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
|
||||
}
|
||||
case 5:
|
||||
switch (blockY) {
|
||||
case 4:
|
||||
return GL_COMPRESSED_RGBA_ASTC_5x4_KHR;
|
||||
case 5:
|
||||
return GL_COMPRESSED_RGBA_ASTC_5x5_KHR;
|
||||
}
|
||||
case 6:
|
||||
switch (blockY) {
|
||||
case 5:
|
||||
return GL_COMPRESSED_RGBA_ASTC_6x5_KHR;
|
||||
case 6:
|
||||
return GL_COMPRESSED_RGBA_ASTC_6x6_KHR;
|
||||
}
|
||||
case 8:
|
||||
switch (blockY) {
|
||||
case 5:
|
||||
return GL_COMPRESSED_RGBA_ASTC_8x5_KHR;
|
||||
case 6:
|
||||
return GL_COMPRESSED_RGBA_ASTC_8x6_KHR;
|
||||
case 8:
|
||||
return GL_COMPRESSED_RGBA_ASTC_8x8_KHR;
|
||||
}
|
||||
case 10:
|
||||
switch (blockY) {
|
||||
case 5:
|
||||
return GL_COMPRESSED_RGBA_ASTC_10x5_KHR;
|
||||
case 6:
|
||||
return GL_COMPRESSED_RGBA_ASTC_10x6_KHR;
|
||||
case 8:
|
||||
return GL_COMPRESSED_RGBA_ASTC_10x8_KHR;
|
||||
case 10:
|
||||
return GL_COMPRESSED_RGBA_ASTC_10x10_KHR;
|
||||
}
|
||||
case 12:
|
||||
switch (blockY) {
|
||||
case 10:
|
||||
return GL_COMPRESSED_RGBA_ASTC_12x10_KHR;
|
||||
case 12:
|
||||
return GL_COMPRESSED_RGBA_ASTC_12x12_KHR;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*static int pow2(int pow) {
|
||||
int ret = 1;
|
||||
for (int i = 0; i < pow; ++i) ret *= 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int getPower2(int i) {
|
||||
for (int power = 0;; ++power)
|
||||
if (pow2(power) >= i) return pow2(power);
|
||||
}*/
|
||||
|
||||
static void convertImageToPow2(kinc_image_format_t format, uint8_t *from, int fw, int fh, uint8_t *to, int tw, int th) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
for (int y = 0; y < th; ++y) {
|
||||
for (int x = 0; x < tw; ++x) {
|
||||
to[tw * 4 * y + x * 4 + 0] = 0;
|
||||
to[tw * 4 * y + x * 4 + 1] = 0;
|
||||
to[tw * 4 * y + x * 4 + 2] = 0;
|
||||
to[tw * 4 * y + x * 4 + 3] = 0;
|
||||
}
|
||||
}
|
||||
for (int y = 0; y < fh; ++y) {
|
||||
for (int x = 0; x < fw; ++x) {
|
||||
to[tw * 4 * y + x * 4 + 0] = from[y * fw * 4 + x * 4 + 0];
|
||||
to[tw * 4 * y + x * 4 + 1] = from[y * fw * 4 + x * 4 + 1];
|
||||
to[tw * 4 * y + x * 4 + 2] = from[y * fw * 4 + x * 4 + 2];
|
||||
to[tw * 4 * y + x * 4 + 3] = from[y * fw * 4 + x * 4 + 3];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
for (int y = 0; y < th; ++y) {
|
||||
for (int x = 0; x < tw; ++x) {
|
||||
to[tw * y + x] = 0;
|
||||
}
|
||||
}
|
||||
for (int y = 0; y < fh; ++y) {
|
||||
for (int x = 0; x < fw; ++x) {
|
||||
to[tw * y + x] = from[y * fw + x];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KINC_IMAGE_FORMAT_RGB24:
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
case KINC_IMAGE_FORMAT_BGRA32:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
|
||||
texture->format = image->format;
|
||||
bool toPow2;
|
||||
#ifdef KORE_IOS
|
||||
texture->tex_width = image->width;
|
||||
texture->tex_height = image->height;
|
||||
toPow2 = false;
|
||||
#else
|
||||
if (kinc_g4_supports_non_pow2_textures()) {
|
||||
texture->tex_width = image->width;
|
||||
texture->tex_height = image->height;
|
||||
toPow2 = false;
|
||||
}
|
||||
else {
|
||||
texture->tex_width = getPower2(image->width);
|
||||
texture->tex_height = getPower2(image->height);
|
||||
toPow2 = !(texture->tex_width == image->width && texture->tex_height == image->height);
|
||||
}
|
||||
#endif
|
||||
texture->tex_depth = 1;
|
||||
|
||||
uint8_t *conversionBuffer = NULL;
|
||||
|
||||
switch (image->compression) {
|
||||
case KINC_IMAGE_COMPRESSION_NONE:
|
||||
if (toPow2) {
|
||||
conversionBuffer = (uint8_t *)malloc(texture->tex_width * texture->tex_height * kinc_image_format_sizeof(image->format));
|
||||
convertImageToPow2(image->format, (uint8_t *)image->data, image->width, image->height, conversionBuffer, texture->tex_width, texture->tex_height);
|
||||
}
|
||||
break;
|
||||
case KINC_IMAGE_COMPRESSION_PVRTC:
|
||||
texture->tex_width = kinc_maxi(texture->tex_width, texture->tex_height);
|
||||
texture->tex_height = kinc_maxi(texture->tex_width, texture->tex_height);
|
||||
if (texture->tex_width < 8)
|
||||
texture->tex_width = 8;
|
||||
if (texture->tex_height < 8)
|
||||
texture->tex_height = 8;
|
||||
break;
|
||||
default:
|
||||
texture->tex_width = image->width;
|
||||
texture->tex_height = image->height;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
texture->impl.external_oes = false;
|
||||
#endif
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glCheckErrors();
|
||||
glGenTextures(1, &texture->impl.texture);
|
||||
glCheckErrors();
|
||||
glBindTexture(GL_TEXTURE_2D, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
|
||||
int convertedType = convertType(image->format);
|
||||
bool isHdr = convertedType == GL_FLOAT;
|
||||
|
||||
switch (image->compression) {
|
||||
case KINC_IMAGE_COMPRESSION_PVRTC:
|
||||
#ifdef KORE_IOS
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, texture->tex_width, texture->tex_height, 0,
|
||||
texture->tex_width * texture->tex_height / 2, image->data);
|
||||
#endif
|
||||
break;
|
||||
case KINC_IMAGE_COMPRESSION_ASTC: {
|
||||
uint8_t blockX = image->internal_format >> 8;
|
||||
uint8_t blockY = image->internal_format & 0xff;
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, astcFormat(blockX, blockY), texture->tex_width, texture->tex_height, 0, image->data_size, image->data);
|
||||
break;
|
||||
}
|
||||
case KINC_IMAGE_COMPRESSION_DXT5:
|
||||
#ifdef KORE_WINDOWS
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, texture->tex_width, texture->tex_height, 0, image->data_size, image->data);
|
||||
#endif
|
||||
break;
|
||||
case KINC_IMAGE_COMPRESSION_NONE: {
|
||||
void *texdata = image->data;
|
||||
if (!isHdr && toPow2) {
|
||||
texdata = conversionBuffer;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, convertInternalFormat(image->format), texture->tex_width, texture->tex_height, 0, convertFormat(image->format),
|
||||
convertedType, texdata);
|
||||
glCheckErrors();
|
||||
break;
|
||||
}
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (toPow2) {
|
||||
free(conversionBuffer);
|
||||
conversionBuffer = NULL;
|
||||
}
|
||||
|
||||
/*if (!readable) {
|
||||
if (isHdr) {
|
||||
free(texture->image.hdrData);
|
||||
texture->image.hdrData = NULL;
|
||||
}
|
||||
else {
|
||||
free(texture->image.data);
|
||||
texture->image.data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (readable && texture->image.compression != KINC_IMAGE_COMPRESSION_NONE) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Compressed images can not be readable.");
|
||||
}*/
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init_from_image3d(kinc_g4_texture_t *texture, kinc_image_t *image) {
|
||||
texture->format = image->format;
|
||||
#ifndef KORE_OPENGL_ES // Requires GLES 3.0
|
||||
texture->tex_width = image->width;
|
||||
texture->tex_height = image->height;
|
||||
texture->tex_depth = image->depth;
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
external_oes = false;
|
||||
#endif
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glCheckErrors();
|
||||
glGenTextures(1, &texture->impl.texture);
|
||||
glCheckErrors();
|
||||
glBindTexture(GL_TEXTURE_3D, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
|
||||
int convertedType = convertType(image->format);
|
||||
// bool isHdr = convertedType == GL_FLOAT;
|
||||
|
||||
void *texdata = image->data;
|
||||
glTexImage3D(GL_TEXTURE_3D, 0, convertInternalFormat(image->format), texture->tex_width, texture->tex_height, texture->tex_depth, 0,
|
||||
convertFormat(image->format), convertedType, texdata);
|
||||
glCheckErrors();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
|
||||
/*if (!readable) {
|
||||
if (isHdr) {
|
||||
free(texture->image.hdrData);
|
||||
texture->image.hdrData = NULL;
|
||||
}
|
||||
else {
|
||||
free(texture->image.data);
|
||||
texture->image.data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (texture->image.compression != KINC_IMAGE_COMPRESSION_NONE) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Compressed images can not be 3D.");
|
||||
}*/
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
|
||||
#ifdef KORE_IOS
|
||||
texture->tex_width = width;
|
||||
texture->tex_height = height;
|
||||
#else
|
||||
if (kinc_g4_supports_non_pow2_textures()) {
|
||||
texture->tex_width = width;
|
||||
texture->tex_height = height;
|
||||
}
|
||||
else {
|
||||
texture->tex_width = getPower2(width);
|
||||
texture->tex_height = getPower2(height);
|
||||
}
|
||||
#endif
|
||||
texture->tex_depth = 1;
|
||||
texture->format = format;
|
||||
// conversionBuffer = new u8[texWidth * texHeight * 4];
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
texture->impl.external_oes = false;
|
||||
#endif
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glCheckErrors();
|
||||
glGenTextures(1, &texture->impl.texture);
|
||||
glCheckErrors();
|
||||
glBindTexture(GL_TEXTURE_2D, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
|
||||
if (convertType(format) == GL_FLOAT) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, convertInternalFormat(format), texture->tex_width, texture->tex_height, 0, convertFormat(format), GL_FLOAT, NULL);
|
||||
}
|
||||
else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, convertInternalFormat(format), texture->tex_width, texture->tex_height, 0, convertFormat(format), GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
}
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {
|
||||
#ifndef KORE_OPENGL_ES
|
||||
texture->tex_width = width;
|
||||
texture->tex_height = height;
|
||||
texture->tex_depth = depth;
|
||||
texture->format = format;
|
||||
|
||||
glGenTextures(1, &texture->impl.texture);
|
||||
glCheckErrors();
|
||||
glBindTexture(GL_TEXTURE_3D, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glCheckErrors();
|
||||
|
||||
glTexImage3D(GL_TEXTURE_3D, 0, convertInternalFormat(format), width, height, depth, 0, convertFormat(format), GL_UNSIGNED_BYTE, NULL);
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
void kinc_g4_texture_init_from_id(kinc_g4_texture_t *texture, unsigned texid) {
|
||||
texture->impl.texture = texid;
|
||||
texture->impl.external_oes = true;
|
||||
texture->tex_width = 1023;
|
||||
texture->tex_height = 684;
|
||||
texture->format = KINC_IMAGE_FORMAT_RGBA32;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
|
||||
glDeleteTextures(1, &texture->impl.texture);
|
||||
glFlush();
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void Kinc_G4_Internal_TextureSet(kinc_g4_texture_t *texture, uint32_t unit) {
|
||||
GLenum target = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
|
||||
glActiveTexture(GL_TEXTURE0 + unit);
|
||||
glCheckErrors();
|
||||
#ifdef KORE_ANDROID
|
||||
if (texture->impl.external_oes) {
|
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
}
|
||||
else {
|
||||
glBindTexture(target, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
}
|
||||
#else
|
||||
glBindTexture(target, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Kinc_G4_Internal_TextureAddressingU(unit));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Kinc_G4_Internal_TextureAddressingV(unit));
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
void Kinc_G4_Internal_TextureSet(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
|
||||
GLenum target = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
|
||||
glActiveTexture(GL_TEXTURE0 + unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]);
|
||||
glCheckErrors();
|
||||
#ifdef KORE_ANDROID
|
||||
if (texture->impl.external_oes) {
|
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
}
|
||||
else {
|
||||
glBindTexture(target, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
}
|
||||
#else
|
||||
glBindTexture(target, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Kinc_G4_Internal_TextureAddressingU(unit));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Kinc_G4_Internal_TextureAddressingV(unit));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void Kinc_G4_Internal_TextureImageSet(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
|
||||
#if defined(KORE_WINDOWS) || (defined(KORE_LINUX) && defined(GL_VERSION_4_4))
|
||||
glBindImageTexture(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], texture->impl.texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, convertInternalFormat(texture->format));
|
||||
glCheckErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
|
||||
return texture->tex_width * kinc_image_format_sizeof(texture->format);
|
||||
}
|
||||
|
||||
static uint8_t *lock_cache = NULL;
|
||||
|
||||
unsigned char *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
|
||||
if (lock_cache == NULL) {
|
||||
lock_cache = (uint8_t *)malloc(4096 * 4096 * 4);
|
||||
}
|
||||
return lock_cache; //**(texture->image.data ? texture->image.data : (uint8_t *)texture->image.hdrData);
|
||||
}
|
||||
|
||||
/*void Texture::unlock() {
|
||||
if (conversionBuffer != nullptr) {
|
||||
convertImageToPow2(format, (u8*)data, width, height, conversionBuffer, texWidth, texHeight);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
#ifndef GL_LUMINANCE
|
||||
#define GL_LUMINANCE GL_RED
|
||||
#endif
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, (format == Image::RGBA32) ? GL_RGBA : GL_LUMINANCE, texWidth, texHeight, 0, (format == Image::RGBA32) ? GL_RGBA :
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, conversionBuffer);
|
||||
}
|
||||
}*/
|
||||
|
||||
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
|
||||
GLenum target = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
|
||||
void *texdata = lock_cache;
|
||||
glBindTexture(target, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
if (texture->tex_depth > 1) {
|
||||
#ifndef KORE_OPENGL_ES
|
||||
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, texture->tex_width, texture->tex_height, texture->tex_depth, convertFormat(texture->format),
|
||||
convertType(texture->format), texdata);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->tex_width, texture->tex_height, convertFormat(texture->format), convertType(texture->format), texdata);
|
||||
}
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {
|
||||
#ifdef GL_VERSION_4_4
|
||||
static float clearColor[4];
|
||||
clearColor[0] = ((color & 0x00ff0000) >> 16) / 255.0f;
|
||||
clearColor[1] = ((color & 0x0000ff00) >> 8) / 255.0f;
|
||||
clearColor[2] = (color & 0x000000ff) / 255.0f;
|
||||
clearColor[3] = ((color & 0xff000000) >> 24) / 255.0f;
|
||||
GLenum target = depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
|
||||
glBindTexture(target, texture->impl.texture);
|
||||
glClearTexSubImage(texture->impl.texture, 0, x, y, z, width, height, depth, convertFormat(texture->format), convertType(texture->format), clearColor);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(KORE_IOS) || defined(KORE_MACOS)
|
||||
void kinc_g4_texture_upload(kinc_g4_texture_t *texture, uint8_t *data, int stride) {
|
||||
glBindTexture(GL_TEXTURE_2D, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->tex_width, texture->tex_height, convertFormat(texture->format), GL_UNSIGNED_BYTE, data);
|
||||
glCheckErrors();
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {
|
||||
GLenum target = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
|
||||
glBindTexture(target, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
glGenerateMipmap(target);
|
||||
glCheckErrors();
|
||||
}
|
||||
|
||||
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {
|
||||
int convertedType = convertType(mipmap->format);
|
||||
// bool isHdr = convertedType == GL_FLOAT;
|
||||
GLenum target = texture->tex_depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
|
||||
glBindTexture(target, texture->impl.texture);
|
||||
glCheckErrors();
|
||||
glTexImage2D(target, level, convertInternalFormat(mipmap->format), mipmap->width, mipmap->height, 0, convertFormat(mipmap->format), convertedType,
|
||||
mipmap->data);
|
||||
glCheckErrors();
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned int texture;
|
||||
#ifdef KORE_ANDROID
|
||||
bool external_oes;
|
||||
#endif
|
||||
uint8_t pixfmt;
|
||||
} kinc_g4_texture_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,25 @@
|
||||
#include <kinc/graphics4/texturearray.h>
|
||||
#include <kinc/graphics4/textureunit.h>
|
||||
|
||||
#include <kinc/backend/graphics4/ogl.h>
|
||||
|
||||
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {
|
||||
#ifdef GL_VERSION_4_2
|
||||
glGenTextures(1, &array->impl.texture);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, array->impl.texture);
|
||||
// glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, textures[0].width, textures[0].height, count, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, textures[0].width, textures[0].height, count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, textures[i].width, textures[i].height, 1, GL_RGBA, GL_UNSIGNED_BYTE, textures[i].data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
|
||||
|
||||
void Kinc_G4_Internal_TextureArraySet(kinc_g4_texture_array_t *array, kinc_g4_texture_unit_t unit) {
|
||||
#ifdef GL_VERSION_4_2
|
||||
glActiveTexture(GL_TEXTURE0 + unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, array->impl.texture);
|
||||
#endif
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned texture;
|
||||
} kinc_g4_texture_array_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,304 @@
|
||||
#include "ogl.h"
|
||||
#include <kinc/backend/graphics4/shader.h>
|
||||
#include <kinc/backend/graphics4/vertexbuffer.h>
|
||||
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern kinc_g4_index_buffer_t *Kinc_Internal_CurrentIndexBuffer;
|
||||
static kinc_g4_vertex_buffer_t *currentVertexBuffer = NULL;
|
||||
|
||||
#if defined(KORE_OPENGL_ES) && defined(KORE_ANDROID) && KORE_ANDROID_API >= 18
|
||||
void *glesVertexAttribDivisor;
|
||||
#endif
|
||||
|
||||
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int vertexCount, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
|
||||
int instanceDataStepRate) {
|
||||
buffer->impl.myCount = vertexCount;
|
||||
buffer->impl.instanceDataStepRate = instanceDataStepRate;
|
||||
#ifndef NDEBUG
|
||||
buffer->impl.initialized = false;
|
||||
#endif
|
||||
buffer->impl.myStride = 0;
|
||||
for (int i = 0; i < structure->size; ++i) {
|
||||
kinc_g4_vertex_element_t element = structure->elements[i];
|
||||
buffer->impl.myStride += kinc_g4_vertex_data_size(element.data);
|
||||
}
|
||||
buffer->impl.structure = *structure;
|
||||
|
||||
unsigned gl_usage;
|
||||
switch (usage) {
|
||||
case KINC_G4_USAGE_STATIC:
|
||||
default:
|
||||
gl_usage = GL_STATIC_DRAW;
|
||||
break;
|
||||
case KINC_G4_USAGE_DYNAMIC:
|
||||
gl_usage = GL_DYNAMIC_DRAW;
|
||||
break;
|
||||
case KINC_G4_USAGE_READABLE:
|
||||
gl_usage = GL_DYNAMIC_DRAW;
|
||||
break;
|
||||
}
|
||||
|
||||
glGenBuffers(1, &buffer->impl.bufferId);
|
||||
glCheckErrors();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer->impl.bufferId);
|
||||
glCheckErrors();
|
||||
glBufferData(GL_ARRAY_BUFFER, buffer->impl.myStride * buffer->impl.myCount, NULL, gl_usage);
|
||||
glCheckErrors();
|
||||
buffer->impl.data = (float *)malloc(vertexCount * buffer->impl.myStride);
|
||||
}
|
||||
|
||||
void Kinc_Internal_G4_VertexBuffer_Unset(kinc_g4_vertex_buffer_t *buffer);
|
||||
|
||||
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
|
||||
Kinc_Internal_G4_VertexBuffer_Unset(buffer);
|
||||
glDeleteBuffers(1, &buffer->impl.bufferId);
|
||||
free(buffer->impl.data);
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
buffer->impl.sectionStart = 0;
|
||||
buffer->impl.sectionSize = buffer->impl.myCount * buffer->impl.myStride;
|
||||
return buffer->impl.data;
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
|
||||
buffer->impl.sectionStart = start * buffer->impl.myStride;
|
||||
buffer->impl.sectionSize = count * buffer->impl.myStride;
|
||||
uint8_t *u8data = (uint8_t *)buffer->impl.data;
|
||||
return (float *)&u8data[buffer->impl.sectionStart];
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer->impl.bufferId);
|
||||
glCheckErrors();
|
||||
uint8_t *u8data = (uint8_t *)buffer->impl.data;
|
||||
glBufferSubData(GL_ARRAY_BUFFER, buffer->impl.sectionStart, buffer->impl.sectionSize, u8data + buffer->impl.sectionStart);
|
||||
glCheckErrors();
|
||||
#ifndef NDEBUG
|
||||
buffer->impl.initialized = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer->impl.bufferId);
|
||||
glCheckErrors();
|
||||
uint8_t *u8data = (uint8_t *)buffer->impl.data;
|
||||
glBufferSubData(GL_ARRAY_BUFFER, buffer->impl.sectionStart, count * buffer->impl.myStride, u8data + buffer->impl.sectionStart);
|
||||
glCheckErrors();
|
||||
#ifndef NDEBUG
|
||||
buffer->impl.initialized = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
int Kinc_G4_Internal_SetVertexAttributes(kinc_g4_vertex_buffer_t *buffer, int offset);
|
||||
|
||||
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
|
||||
assert(buffer->impl.initialized); // Vertex Buffer is used before lock/unlock was called
|
||||
int offsetoffset = Kinc_G4_Internal_SetVertexAttributes(buffer, offset);
|
||||
if (Kinc_Internal_CurrentIndexBuffer != NULL) {
|
||||
kinc_internal_g4_index_buffer_set(Kinc_Internal_CurrentIndexBuffer);
|
||||
}
|
||||
return offsetoffset;
|
||||
}
|
||||
|
||||
void Kinc_Internal_G4_VertexBuffer_Unset(kinc_g4_vertex_buffer_t *buffer) {
|
||||
if (currentVertexBuffer == buffer) {
|
||||
currentVertexBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.myCount;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.myStride;
|
||||
}
|
||||
|
||||
#if !defined(KORE_OPENGL_ES) || (defined(KORE_OPENGL_ES) && defined(KORE_WASM)) || (defined(KORE_OPENGL_ES) && defined(KORE_ANDROID) && KORE_ANDROID_API >= 18)
|
||||
static bool attribDivisorUsed = false;
|
||||
#endif
|
||||
|
||||
int Kinc_G4_Internal_SetVertexAttributes(kinc_g4_vertex_buffer_t *buffer, int offset) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer->impl.bufferId);
|
||||
glCheckErrors();
|
||||
|
||||
int internaloffset = 0;
|
||||
int actualIndex = 0;
|
||||
for (int index = 0; index < buffer->impl.structure.size; ++index) {
|
||||
kinc_g4_vertex_element_t element = buffer->impl.structure.elements[index];
|
||||
int size = 0;
|
||||
GLenum type = GL_FLOAT;
|
||||
switch (element.data) {
|
||||
case KINC_G4_VERTEX_DATA_NONE:
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_1X:
|
||||
size = 1;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_2X:
|
||||
size = 2;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_3X:
|
||||
size = 3;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X:
|
||||
size = 4;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X4:
|
||||
size = 16;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_1X:
|
||||
case KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED:
|
||||
size = 1;
|
||||
type = GL_BYTE;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_1X:
|
||||
case KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED:
|
||||
size = 1;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_2X:
|
||||
case KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED:
|
||||
size = 2;
|
||||
type = GL_BYTE;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_2X:
|
||||
case KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED:
|
||||
size = 2;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_4X:
|
||||
case KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED:
|
||||
size = 4;
|
||||
type = GL_BYTE;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X:
|
||||
case KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED:
|
||||
size = 4;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_1X:
|
||||
case KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED:
|
||||
size = 1;
|
||||
type = GL_SHORT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_1X:
|
||||
case KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED:
|
||||
size = 1;
|
||||
type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X:
|
||||
case KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED:
|
||||
size = 2;
|
||||
type = GL_SHORT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_2X:
|
||||
case KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED:
|
||||
size = 2;
|
||||
type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X:
|
||||
case KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED:
|
||||
size = 4;
|
||||
type = GL_SHORT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_4X:
|
||||
case KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED:
|
||||
size = 4;
|
||||
type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_1X:
|
||||
size = 1;
|
||||
type = GL_INT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_1X:
|
||||
size = 1;
|
||||
type = GL_UNSIGNED_INT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_2X:
|
||||
size = 2;
|
||||
type = GL_INT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_2X:
|
||||
size = 2;
|
||||
type = GL_UNSIGNED_INT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_3X:
|
||||
size = 3;
|
||||
type = GL_INT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_3X:
|
||||
size = 3;
|
||||
type = GL_UNSIGNED_INT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_4X:
|
||||
size = 4;
|
||||
type = GL_INT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_4X:
|
||||
size = 4;
|
||||
type = GL_UNSIGNED_INT;
|
||||
break;
|
||||
}
|
||||
if (size > 4) {
|
||||
int subsize = size;
|
||||
int addonOffset = 0;
|
||||
while (subsize > 0) {
|
||||
glEnableVertexAttribArray(offset + actualIndex);
|
||||
glCheckErrors();
|
||||
glVertexAttribPointer(offset + actualIndex, 4, type, false, buffer->impl.myStride, (void *)(int64_t)(internaloffset + addonOffset));
|
||||
glCheckErrors();
|
||||
#if !defined(KORE_OPENGL_ES) || (defined(KORE_OPENGL_ES) && defined(KORE_WASM))
|
||||
if (attribDivisorUsed || buffer->impl.instanceDataStepRate != 0) {
|
||||
attribDivisorUsed = true;
|
||||
glVertexAttribDivisor(offset + actualIndex, buffer->impl.instanceDataStepRate);
|
||||
glCheckErrors();
|
||||
}
|
||||
#endif
|
||||
#if (defined(KORE_OPENGL_ES) && defined(KORE_ANDROID) && KORE_ANDROID_API >= 18)
|
||||
if (attribDivisorUsed || buffer->impl.instanceDataStepRate != 0) {
|
||||
attribDivisorUsed = true;
|
||||
((void (*)(GLuint, GLuint))glesVertexAttribDivisor)(offset + actualIndex, buffer->impl.instanceDataStepRate);
|
||||
glCheckErrors();
|
||||
}
|
||||
#endif
|
||||
subsize -= 4;
|
||||
addonOffset += 4 * 4;
|
||||
++actualIndex;
|
||||
}
|
||||
}
|
||||
else {
|
||||
glEnableVertexAttribArray(offset + actualIndex);
|
||||
glCheckErrors();
|
||||
glVertexAttribPointer(offset + actualIndex, size, type, type == GL_FLOAT ? false : true, buffer->impl.myStride, (void *)(int64_t)internaloffset);
|
||||
glCheckErrors();
|
||||
#if !defined(KORE_OPENGL_ES) || (defined(KORE_OPENGL_ES) && defined(KORE_WASM))
|
||||
if (attribDivisorUsed || buffer->impl.instanceDataStepRate != 0) {
|
||||
attribDivisorUsed = true;
|
||||
glVertexAttribDivisor(offset + actualIndex, buffer->impl.instanceDataStepRate);
|
||||
glCheckErrors();
|
||||
}
|
||||
#endif
|
||||
#if (defined(KORE_OPENGL_ES) && defined(KORE_ANDROID) && KORE_ANDROID_API >= 18)
|
||||
if (attribDivisorUsed || buffer->impl.instanceDataStepRate != 0) {
|
||||
attribDivisorUsed = true;
|
||||
((void (*)(GLuint, GLuint))glesVertexAttribDivisor)(offset + actualIndex, buffer->impl.instanceDataStepRate);
|
||||
glCheckErrors();
|
||||
}
|
||||
#endif
|
||||
++actualIndex;
|
||||
}
|
||||
internaloffset += kinc_g4_vertex_data_size(element.data);
|
||||
}
|
||||
int count = kinc_internal_opengl_max_vertex_attribute_arrays - offset;
|
||||
for (int index = actualIndex; index < count; ++index) {
|
||||
glDisableVertexAttribArray(offset + index);
|
||||
glCheckErrors();
|
||||
}
|
||||
return actualIndex;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics4/vertexstructure.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
float *data;
|
||||
int myCount;
|
||||
int myStride;
|
||||
unsigned bufferId;
|
||||
int sectionStart;
|
||||
int sectionSize;
|
||||
// #if defined KORE_ANDROID || defined KORE_EMSCRIPTEN || defined KORE_TIZEN
|
||||
kinc_g4_vertex_structure_t structure;
|
||||
// #endif
|
||||
int instanceDataStepRate;
|
||||
#ifndef NDEBUG
|
||||
bool initialized;
|
||||
#endif
|
||||
} kinc_g4_vertex_buffer_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user