Update Files

This commit is contained in:
2025-01-22 17:22:38 +01:00
parent 89b9349629
commit 4c5e729485
5132 changed files with 1195369 additions and 0 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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>

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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;
}

View File

@ -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;

View File

@ -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, &currentPipeline->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, &currentPipeline->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, &currentPipeline->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, &currentPipeline->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, &currentPipeline->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);
}
}

View File

@ -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

View File

@ -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) {}

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {}

View File

@ -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

View File

@ -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) {}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,6 @@
#pragma once
#include "IndexBufferImpl.h"
#include "RenderTargetImpl.h"
#include "ShaderImpl.h"
#include "VertexBufferImpl.h"

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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) {}

View File

@ -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

View File

@ -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) {}

View File

@ -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

View File

@ -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) {}

View File

@ -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

View File

@ -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) {}

View File

@ -0,0 +1,13 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int nothing;
} kinc_g4_texture_array_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -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;
}

View File

@ -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

View File

@ -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(&current_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(&current_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(&current_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(&current_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(&current_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

View File

@ -0,0 +1,4 @@
#pragma once
#include <kinc/graphics4/graphics.h>
#include <kinc/math/matrix.h>

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -0,0 +1,6 @@
#pragma once
#include "IndexBufferImpl.h"
#include "RenderTargetImpl.h"
#include "TextureImpl.h"
#include "VertexBufferImpl.h"

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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) {}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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) {}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -0,0 +1,2 @@
DisableFormat: true
SortIncludes: false

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,6 @@
#pragma once
#include "IndexBufferImpl.h"
#include "RenderTargetImpl.h"
#include "TextureImpl.h"
#include "VertexBufferImpl.h"

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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
}

View File

@ -0,0 +1,13 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned texture;
} kinc_g4_texture_array_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -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;
}

View File

@ -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