forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
@ -0,0 +1,491 @@
|
||||
#ifdef KINC_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
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <dxgi.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAXIMUM_WINDOWS 16
|
||||
|
||||
struct dx_window {
|
||||
HWND hwnd;
|
||||
IDXGISwapChain *swapChain;
|
||||
ID3D11Texture2D *backBuffer;
|
||||
ID3D11RenderTargetView *renderTargetView;
|
||||
ID3D11Texture2D *depthStencil;
|
||||
ID3D11DepthStencilView *depthStencilView;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
int new_width;
|
||||
int new_height;
|
||||
|
||||
bool vsync;
|
||||
int depth_bits;
|
||||
int stencil_bits;
|
||||
};
|
||||
|
||||
struct dx_context {
|
||||
ID3D11Device *device;
|
||||
ID3D11DeviceContext *context;
|
||||
IDXGIDevice *dxgiDevice;
|
||||
IDXGIAdapter *dxgiAdapter;
|
||||
IDXGIFactory *dxgiFactory;
|
||||
|
||||
int current_window;
|
||||
struct dx_window windows[MAXIMUM_WINDOWS];
|
||||
};
|
||||
|
||||
extern struct dx_context dx_ctx;
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
@ -0,0 +1,11 @@
|
||||
#include "ShaderHash.h"
|
||||
|
||||
// djb2
|
||||
uint32_t kinc_internal_hash_name(unsigned char *str) {
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
while ((c = *str++)) {
|
||||
hash = hash * 33 ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t hash;
|
||||
uint32_t index;
|
||||
} kinc_internal_hash_index_t;
|
||||
|
||||
uint32_t kinc_internal_hash_name(unsigned char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,203 @@
|
||||
#include "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>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static int getMultipleOf16(int value) {
|
||||
int ret = 16;
|
||||
while (ret < value)
|
||||
ret += 16;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void kinc_g4_compute_shader_init(kinc_g4_compute_shader *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_g4_compute_internal_shader_constant 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_g4_compute_shader_destroy(kinc_g4_compute_shader *shader) {}
|
||||
|
||||
static kinc_g4_compute_internal_shader_constant *compute_findConstant(kinc_g4_compute_internal_shader_constant *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 *compute_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_g4_constant_location_t kinc_g4_compute_shader_get_constant_location(kinc_g4_compute_shader *shader, const char *name) {
|
||||
kinc_g4_constant_location_t location = {0};
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
|
||||
|
||||
kinc_g4_compute_internal_shader_constant *constant = compute_findConstant(shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.computeOffset = 0;
|
||||
location.impl.computeSize = 0;
|
||||
location.impl.computeColumns = 0;
|
||||
location.impl.computeRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.computeOffset = constant->offset;
|
||||
location.impl.computeSize = constant->size;
|
||||
location.impl.computeColumns = constant->columns;
|
||||
location.impl.computeRows = constant->rows;
|
||||
}
|
||||
|
||||
if (location.impl.computeSize == 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_g4_texture_unit_t kinc_g4_compute_shader_get_texture_unit(kinc_g4_compute_shader *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_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 *compute_unit = compute_findTextureUnit(shader->impl.textures, hash);
|
||||
if (compute_unit == NULL) {
|
||||
unit.stages[KINC_G4_SHADER_TYPE_COMPUTE] = -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.stages[KINC_G4_SHADER_TYPE_COMPUTE] = compute_unit->index + unitOffset;
|
||||
}
|
||||
return unit;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_set_compute_shader(kinc_g4_compute_shader *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, computeConstants, 0, 0);
|
||||
dx_ctx.context->lpVtbl->CSSetConstantBuffers(dx_ctx.context, 0, 1, &shader->impl.constantBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_compute(int x, int y, int z) {
|
||||
dx_ctx.context->lpVtbl->Dispatch(dx_ctx.context, x, y, z);
|
||||
|
||||
ID3D11UnorderedAccessView *nullView = NULL;
|
||||
dx_ctx.context->lpVtbl->CSSetUnorderedAccessViews(dx_ctx.context, 0, 1, &nullView, NULL);
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/backend/graphics4/ShaderHash.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct kinc_g4_compute_constant_location_impl {
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
uint8_t columns;
|
||||
uint8_t rows;
|
||||
} kinc_g4_compute_constant_location_impl;
|
||||
|
||||
typedef struct kinc_g4_compute_texture_unit_impl {
|
||||
int unit;
|
||||
} kinc_g4_compute_texture_unit_impl;
|
||||
|
||||
typedef struct kinc_g4_compute_internal_shader_constant {
|
||||
uint32_t hash;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
uint8_t columns;
|
||||
uint8_t rows;
|
||||
} kinc_g4_compute_internal_shader_constant;
|
||||
|
||||
typedef struct kinc_g4_compute_shader_impl {
|
||||
#ifndef KINC_KONG
|
||||
kinc_g4_compute_internal_shader_constant 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_g4_compute_shader_impl;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,51 @@
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/graphics4/constantbuffer.h>
|
||||
|
||||
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
|
||||
buffer->impl.size = size;
|
||||
buffer->impl.last_start = 0;
|
||||
buffer->impl.last_size = size;
|
||||
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(size);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &buffer->impl.buffer));
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {
|
||||
buffer->impl.buffer->lpVtbl->Release(buffer->impl.buffer);
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
|
||||
return kinc_g4_constant_buffer_lock(buffer, 0, kinc_g4_constant_buffer_size(buffer));
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
|
||||
buffer->impl.last_start = start;
|
||||
buffer->impl.last_size = size;
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
||||
memset(&mapped_resource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource);
|
||||
uint8_t *data = (uint8_t *)mapped_resource.pData;
|
||||
return &data[start];
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g4_constant_buffer_unlock(buffer, buffer->impl.last_size);
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.buffer, 0);
|
||||
}
|
||||
|
||||
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
|
||||
return buffer->impl.size;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KINC_KONG
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct kinc_g4_constant_buffer_impl {
|
||||
struct ID3D11Buffer *buffer;
|
||||
size_t size;
|
||||
size_t last_start;
|
||||
size_t last_size;
|
||||
} kinc_g4_constant_buffer_impl;
|
||||
|
||||
#endif
|
@ -0,0 +1,113 @@
|
||||
// Windows 7
|
||||
#define WINVER 0x0601
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#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 KINC_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 uint8_t computeConstants[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 "compute.c.h"
|
||||
#include "constantbuffer.c.h"
|
||||
#include "indexbuffer.c.h"
|
||||
#include "pipeline.c.h"
|
||||
#include "rendertarget.c.h"
|
||||
#include "shader.c.h"
|
||||
#include "texture.c.h"
|
||||
#include "texturearray.c.h"
|
||||
#include "vertexbuffer.c.h"
|
@ -0,0 +1,89 @@
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
|
||||
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
|
||||
buffer->impl.count = count;
|
||||
buffer->impl.sixteen = format == KINC_G4_INDEX_BUFFER_FORMAT_16BIT;
|
||||
buffer->impl.last_start = 0;
|
||||
buffer->impl.last_count = count;
|
||||
|
||||
uint32_t byte_size = buffer->impl.sixteen ? sizeof(uint16_t) * count : sizeof(uint32_t) * count;
|
||||
|
||||
if (usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
buffer->impl.indices = NULL;
|
||||
}
|
||||
else {
|
||||
buffer->impl.indices = malloc(byte_size);
|
||||
}
|
||||
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
bufferDesc.ByteWidth = byte_size;
|
||||
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
bufferDesc.StructureByteStride = 0;
|
||||
|
||||
buffer->impl.usage = usage;
|
||||
switch (usage) {
|
||||
case KINC_G4_USAGE_STATIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
case KINC_G4_USAGE_DYNAMIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
break;
|
||||
case KINC_G4_USAGE_READABLE:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &bufferDesc, NULL, &buffer->impl.ib));
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
|
||||
buffer->impl.ib->lpVtbl->Release(buffer->impl.ib);
|
||||
free(buffer->impl.indices);
|
||||
buffer->impl.indices = NULL;
|
||||
}
|
||||
|
||||
static int kinc_g4_internal_index_buffer_stride(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.sixteen ? 2 : 4;
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
return kinc_g4_index_buffer_lock(buffer, 0, kinc_g4_index_buffer_count(buffer));
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
|
||||
buffer->impl.last_start = start;
|
||||
buffer->impl.last_count = count;
|
||||
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
memset(&mappedResource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
uint8_t *data = (uint8_t *)mappedResource.pData;
|
||||
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
|
||||
}
|
||||
else {
|
||||
uint8_t *data = (uint8_t *)buffer->impl.indices;
|
||||
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_g4_index_buffer_unlock(buffer, buffer->impl.last_count);
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0);
|
||||
}
|
||||
else {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0, NULL, buffer->impl.indices, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.count;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Buffer *ib;
|
||||
void *indices;
|
||||
int count;
|
||||
int usage;
|
||||
bool sixteen;
|
||||
int last_start;
|
||||
int last_count;
|
||||
} kinc_g4_index_buffer_impl_t;
|
@ -0,0 +1,878 @@
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
#include <kinc/libs/stb_sprintf.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
kinc_g4_pipeline_t *currentPipeline = NULL;
|
||||
float currentBlendFactor[4] = {0, 0, 0, 0};
|
||||
bool needPipelineRebind = true;
|
||||
|
||||
static D3D11_CULL_MODE convert_cull_mode(kinc_g4_cull_mode_t cullMode) {
|
||||
switch (cullMode) {
|
||||
case KINC_G4_CULL_CLOCKWISE:
|
||||
return D3D11_CULL_BACK;
|
||||
case KINC_G4_CULL_COUNTER_CLOCKWISE:
|
||||
return D3D11_CULL_FRONT;
|
||||
case KINC_G4_CULL_NOTHING:
|
||||
return D3D11_CULL_NONE;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D11_CULL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D11_BLEND convert_blend_factor(kinc_g4_blending_factor_t factor) {
|
||||
switch (factor) {
|
||||
case KINC_G4_BLEND_ONE:
|
||||
return D3D11_BLEND_ONE;
|
||||
case KINC_G4_BLEND_ZERO:
|
||||
return D3D11_BLEND_ZERO;
|
||||
case KINC_G4_BLEND_SOURCE_ALPHA:
|
||||
return D3D11_BLEND_SRC_ALPHA;
|
||||
case KINC_G4_BLEND_DEST_ALPHA:
|
||||
return D3D11_BLEND_DEST_ALPHA;
|
||||
case KINC_G4_BLEND_INV_SOURCE_ALPHA:
|
||||
return D3D11_BLEND_INV_SRC_ALPHA;
|
||||
case KINC_G4_BLEND_INV_DEST_ALPHA:
|
||||
return D3D11_BLEND_INV_DEST_ALPHA;
|
||||
case KINC_G4_BLEND_SOURCE_COLOR:
|
||||
return D3D11_BLEND_SRC_COLOR;
|
||||
case KINC_G4_BLEND_DEST_COLOR:
|
||||
return D3D11_BLEND_DEST_COLOR;
|
||||
case KINC_G4_BLEND_INV_SOURCE_COLOR:
|
||||
return D3D11_BLEND_INV_SRC_COLOR;
|
||||
case KINC_G4_BLEND_INV_DEST_COLOR:
|
||||
return D3D11_BLEND_INV_DEST_COLOR;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D11_BLEND_SRC_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D11_BLEND_OP convert_blend_operation(kinc_g4_blending_operation_t operation) {
|
||||
switch (operation) {
|
||||
case KINC_G4_BLENDOP_ADD:
|
||||
return D3D11_BLEND_OP_ADD;
|
||||
case KINC_G4_BLENDOP_SUBTRACT:
|
||||
return D3D11_BLEND_OP_SUBTRACT;
|
||||
case KINC_G4_BLENDOP_REVERSE_SUBTRACT:
|
||||
return D3D11_BLEND_OP_REV_SUBTRACT;
|
||||
case KINC_G4_BLENDOP_MIN:
|
||||
return D3D11_BLEND_OP_MIN;
|
||||
case KINC_G4_BLENDOP_MAX:
|
||||
return D3D11_BLEND_OP_MAX;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D11_BLEND_OP_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D11_STENCIL_OP get_stencil_action(kinc_g4_stencil_action_t action) {
|
||||
switch (action) {
|
||||
default:
|
||||
case KINC_G4_STENCIL_KEEP:
|
||||
return D3D11_STENCIL_OP_KEEP;
|
||||
case KINC_G4_STENCIL_ZERO:
|
||||
return D3D11_STENCIL_OP_ZERO;
|
||||
case KINC_G4_STENCIL_REPLACE:
|
||||
return D3D11_STENCIL_OP_REPLACE;
|
||||
case KINC_G4_STENCIL_INCREMENT:
|
||||
return D3D11_STENCIL_OP_INCR;
|
||||
case KINC_G4_STENCIL_INCREMENT_WRAP:
|
||||
return D3D11_STENCIL_OP_INCR_SAT;
|
||||
case KINC_G4_STENCIL_DECREMENT:
|
||||
return D3D11_STENCIL_OP_DECR;
|
||||
case KINC_G4_STENCIL_DECREMENT_WRAP:
|
||||
return D3D11_STENCIL_OP_DECR_SAT;
|
||||
case KINC_G4_STENCIL_INVERT:
|
||||
return D3D11_STENCIL_OP_INVERT;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_set_constants(void) {
|
||||
#ifndef KINC_KONG
|
||||
if (currentPipeline->vertex_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.vertexConstantBuffer, 0, NULL, vertexConstants, 0, 0);
|
||||
dx_ctx.context->lpVtbl->VSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.vertexConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->fragment_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.fragmentConstantBuffer, 0, NULL, fragmentConstants, 0,
|
||||
0);
|
||||
dx_ctx.context->lpVtbl->PSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.fragmentConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->geometry_shader != NULL && currentPipeline->geometry_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.geometryConstantBuffer, 0, NULL, geometryConstants, 0,
|
||||
0);
|
||||
dx_ctx.context->lpVtbl->GSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.geometryConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->tessellation_control_shader != NULL && currentPipeline->tessellation_control_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.tessControlConstantBuffer, 0, NULL,
|
||||
tessControlConstants, 0, 0);
|
||||
dx_ctx.context->lpVtbl->HSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.tessControlConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->tessellation_evaluation_shader != NULL && currentPipeline->tessellation_evaluation_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.tessEvalConstantBuffer, 0, NULL, tessEvalConstants, 0,
|
||||
0);
|
||||
dx_ctx.context->lpVtbl->DSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.tessEvalConstantBuffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_init(struct kinc_g4_pipeline *state) {
|
||||
memset(state, 0, sizeof(struct kinc_g4_pipeline));
|
||||
kinc_g4_internal_pipeline_set_defaults(state);
|
||||
state->impl.d3d11inputLayout = NULL;
|
||||
state->impl.fragmentConstantBuffer = NULL;
|
||||
state->impl.vertexConstantBuffer = NULL;
|
||||
state->impl.geometryConstantBuffer = NULL;
|
||||
state->impl.tessEvalConstantBuffer = NULL;
|
||||
state->impl.tessControlConstantBuffer = NULL;
|
||||
state->impl.depthStencilState = NULL;
|
||||
state->impl.rasterizerState = NULL;
|
||||
state->impl.rasterizerStateScissor = NULL;
|
||||
state->impl.blendState = NULL;
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_destroy(struct kinc_g4_pipeline *state) {
|
||||
if (state->impl.d3d11inputLayout != NULL) {
|
||||
state->impl.d3d11inputLayout->lpVtbl->Release(state->impl.d3d11inputLayout);
|
||||
state->impl.d3d11inputLayout = NULL;
|
||||
}
|
||||
if (state->impl.fragmentConstantBuffer != NULL) {
|
||||
state->impl.fragmentConstantBuffer->lpVtbl->Release(state->impl.fragmentConstantBuffer);
|
||||
state->impl.fragmentConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.vertexConstantBuffer != NULL) {
|
||||
state->impl.vertexConstantBuffer->lpVtbl->Release(state->impl.vertexConstantBuffer);
|
||||
state->impl.vertexConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.geometryConstantBuffer != NULL) {
|
||||
state->impl.geometryConstantBuffer->lpVtbl->Release(state->impl.geometryConstantBuffer);
|
||||
state->impl.geometryConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.tessEvalConstantBuffer != NULL) {
|
||||
state->impl.tessEvalConstantBuffer->lpVtbl->Release(state->impl.tessEvalConstantBuffer);
|
||||
state->impl.tessEvalConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.tessControlConstantBuffer != NULL) {
|
||||
state->impl.tessControlConstantBuffer->lpVtbl->Release(state->impl.tessControlConstantBuffer);
|
||||
state->impl.tessControlConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.depthStencilState != NULL) {
|
||||
state->impl.depthStencilState->lpVtbl->Release(state->impl.depthStencilState);
|
||||
state->impl.depthStencilState = NULL;
|
||||
}
|
||||
if (state->impl.rasterizerState != NULL) {
|
||||
state->impl.rasterizerState->lpVtbl->Release(state->impl.rasterizerState);
|
||||
state->impl.rasterizerState = NULL;
|
||||
}
|
||||
if (state->impl.rasterizerStateScissor != NULL) {
|
||||
state->impl.rasterizerStateScissor->lpVtbl->Release(state->impl.rasterizerStateScissor);
|
||||
state->impl.rasterizerStateScissor = NULL;
|
||||
}
|
||||
if (state->impl.blendState != NULL) {
|
||||
state->impl.blendState->lpVtbl->Release(state->impl.blendState);
|
||||
state->impl.blendState = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_set_rasterizer_state(struct kinc_g4_pipeline *pipeline, bool scissoring) {
|
||||
if (scissoring && pipeline->impl.rasterizerStateScissor != NULL)
|
||||
dx_ctx.context->lpVtbl->RSSetState(dx_ctx.context, pipeline->impl.rasterizerStateScissor);
|
||||
else if (pipeline->impl.rasterizerState != NULL)
|
||||
dx_ctx.context->lpVtbl->RSSetState(dx_ctx.context, pipeline->impl.rasterizerState);
|
||||
}
|
||||
|
||||
void kinc_internal_set_pipeline(struct kinc_g4_pipeline *pipeline, bool scissoring) {
|
||||
dx_ctx.context->lpVtbl->OMSetDepthStencilState(dx_ctx.context, pipeline->impl.depthStencilState, pipeline->stencil_reference_value);
|
||||
UINT sampleMask = 0xffffffff;
|
||||
dx_ctx.context->lpVtbl->OMSetBlendState(dx_ctx.context, pipeline->impl.blendState, currentBlendFactor, sampleMask);
|
||||
kinc_internal_set_rasterizer_state(pipeline, scissoring);
|
||||
|
||||
dx_ctx.context->lpVtbl->VSSetShader(dx_ctx.context, (ID3D11VertexShader *)pipeline->vertex_shader->impl.shader, NULL, 0);
|
||||
dx_ctx.context->lpVtbl->PSSetShader(dx_ctx.context, (ID3D11PixelShader *)pipeline->fragment_shader->impl.shader, NULL, 0);
|
||||
|
||||
dx_ctx.context->lpVtbl->GSSetShader(dx_ctx.context,
|
||||
pipeline->geometry_shader != NULL ? (ID3D11GeometryShader *)pipeline->geometry_shader->impl.shader : NULL, NULL, 0);
|
||||
dx_ctx.context->lpVtbl->HSSetShader(
|
||||
dx_ctx.context, pipeline->tessellation_control_shader != NULL ? (ID3D11HullShader *)pipeline->tessellation_control_shader->impl.shader : NULL, NULL, 0);
|
||||
dx_ctx.context->lpVtbl->DSSetShader(
|
||||
dx_ctx.context, pipeline->tessellation_evaluation_shader != NULL ? (ID3D11DomainShader *)pipeline->tessellation_evaluation_shader->impl.shader : NULL,
|
||||
NULL, 0);
|
||||
|
||||
dx_ctx.context->lpVtbl->IASetInputLayout(dx_ctx.context, pipeline->impl.d3d11inputLayout);
|
||||
}
|
||||
|
||||
void kinc_internal_pipeline_rebind() {
|
||||
if (currentPipeline != NULL && needPipelineRebind) {
|
||||
kinc_internal_set_pipeline(currentPipeline, kinc_internal_scissoring);
|
||||
needPipelineRebind = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
static kinc_internal_shader_constant_t *findConstant(kinc_internal_shader_constant_t *constants, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (constants[i].hash == hash) {
|
||||
return &constants[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static kinc_internal_hash_index_t *findTextureUnit(kinc_internal_hash_index_t *units, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (units[i].hash == hash) {
|
||||
return &units[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_get_constant_locations(kinc_g4_pipeline_t *state, kinc_g4_constant_location_t *vertex_locations,
|
||||
kinc_g4_constant_location_t *fragment_locations, int *vertex_sizes, int *fragment_sizes, int *max_vertex,
|
||||
int *max_fragment) {
|
||||
|
||||
// *max_vertex = state->vertex_shader->impl.constantsSize;
|
||||
// *max_fragment = state->fragment_shader->impl.constantsSize;
|
||||
// if (vertex_locations != null && fragment_locations != null) {
|
||||
// for (int i = 0; i < state->vertex_shader->impl.constantsSize; i++) {
|
||||
// kinc_internal_shader_constant_t *constant = state->vertex_shader->impl.constants[i];
|
||||
// vertex_location[i].impl.vertexOffset = constant->offset;
|
||||
// vertex_location[i].impl.vertexSize = constant->size;
|
||||
// vertex_location[i].impl.vertexColumns = constant->columns;
|
||||
// vertex_location[i].impl.vertexRows = constant->rows;
|
||||
// vertex_sizes[i] = constant->size;
|
||||
// }
|
||||
|
||||
// for (int i = 0; i < state->fragment_shader->impl.constantsSize; i++) {
|
||||
// kinc_internal_shader_constant_t *constant = state->fragment_shader->impl.constants[i];
|
||||
// fragment_location[i].impl.vertexOffset = constant->offset;
|
||||
// fragment_location[i].impl.vertexSize = constant->size;
|
||||
// fragment_location[i].impl.vertexColumns = constant->columns;
|
||||
// fragment_location[i].impl.vertexRows = constant->rows;
|
||||
// fragment_sizes[i] = constant->size;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(struct kinc_g4_pipeline *state, const char *name) {
|
||||
kinc_g4_constant_location_t location = {0};
|
||||
|
||||
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;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateInputLayout(dx_ctx.device, vertexDesc, all, state->vertex_shader->impl.data,
|
||||
state->vertex_shader->impl.length, &state->impl.d3d11inputLayout));
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_DESC desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
desc.DepthEnable = state->depth_mode != KINC_G4_COMPARE_ALWAYS;
|
||||
desc.DepthWriteMask = state->depth_write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
desc.DepthFunc = get_comparison(state->depth_mode);
|
||||
|
||||
desc.StencilEnable = state->stencil_front_mode != KINC_G4_COMPARE_ALWAYS || state->stencil_back_mode != KINC_G4_COMPARE_ALWAYS ||
|
||||
state->stencil_front_both_pass != KINC_G4_STENCIL_KEEP || state->stencil_back_both_pass != KINC_G4_STENCIL_KEEP ||
|
||||
state->stencil_front_depth_fail != KINC_G4_STENCIL_KEEP || state->stencil_back_depth_fail != KINC_G4_STENCIL_KEEP ||
|
||||
state->stencil_front_fail != KINC_G4_STENCIL_KEEP || state->stencil_back_fail != KINC_G4_STENCIL_KEEP;
|
||||
desc.StencilReadMask = state->stencil_read_mask;
|
||||
desc.StencilWriteMask = state->stencil_write_mask;
|
||||
desc.FrontFace.StencilFunc = desc.BackFace.StencilFunc = get_comparison(state->stencil_front_mode);
|
||||
desc.FrontFace.StencilDepthFailOp = desc.BackFace.StencilDepthFailOp = get_stencil_action(state->stencil_front_depth_fail);
|
||||
desc.FrontFace.StencilPassOp = desc.BackFace.StencilPassOp = get_stencil_action(state->stencil_front_both_pass);
|
||||
desc.FrontFace.StencilFailOp = desc.BackFace.StencilFailOp = get_stencil_action(state->stencil_front_fail);
|
||||
desc.BackFace.StencilFunc = desc.BackFace.StencilFunc = get_comparison(state->stencil_back_mode);
|
||||
desc.BackFace.StencilDepthFailOp = desc.BackFace.StencilDepthFailOp = get_stencil_action(state->stencil_back_depth_fail);
|
||||
desc.BackFace.StencilPassOp = desc.BackFace.StencilPassOp = get_stencil_action(state->stencil_back_both_pass);
|
||||
desc.BackFace.StencilFailOp = desc.BackFace.StencilFailOp = get_stencil_action(state->stencil_back_fail);
|
||||
|
||||
dx_ctx.device->lpVtbl->CreateDepthStencilState(dx_ctx.device, &desc, &state->impl.depthStencilState);
|
||||
}
|
||||
|
||||
{
|
||||
D3D11_RASTERIZER_DESC rasterDesc;
|
||||
rasterDesc.CullMode = convert_cull_mode(state->cull_mode);
|
||||
rasterDesc.FillMode = D3D11_FILL_SOLID;
|
||||
rasterDesc.FrontCounterClockwise = TRUE;
|
||||
rasterDesc.DepthBias = 0;
|
||||
rasterDesc.SlopeScaledDepthBias = 0.0f;
|
||||
rasterDesc.DepthBiasClamp = 0.0f;
|
||||
rasterDesc.DepthClipEnable = TRUE;
|
||||
rasterDesc.ScissorEnable = FALSE;
|
||||
rasterDesc.MultisampleEnable = FALSE;
|
||||
rasterDesc.AntialiasedLineEnable = FALSE;
|
||||
|
||||
dx_ctx.device->lpVtbl->CreateRasterizerState(dx_ctx.device, &rasterDesc, &state->impl.rasterizerState);
|
||||
rasterDesc.ScissorEnable = TRUE;
|
||||
dx_ctx.device->lpVtbl->CreateRasterizerState(dx_ctx.device, &rasterDesc, &state->impl.rasterizerStateScissor);
|
||||
|
||||
// We need d3d11_3 for conservative raster
|
||||
// D3D11_RASTERIZER_DESC2 rasterDesc;
|
||||
// rasterDesc.ConservativeRaster = conservativeRasterization ? D3D11_CONSERVATIVE_RASTERIZATION_MODE_ON : D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
// dx_ctx.device->CreateRasterizerState2(&rasterDesc, &rasterizerState);
|
||||
// rasterDesc.ScissorEnable = TRUE;
|
||||
// dx_ctx.device->CreateRasterizerState2(&rasterDesc, &rasterizerStateScissor);
|
||||
}
|
||||
|
||||
{
|
||||
bool independentBlend = false;
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
if (state->color_write_mask_red[0] != state->color_write_mask_red[i] || state->color_write_mask_green[0] != state->color_write_mask_green[i] ||
|
||||
state->color_write_mask_blue[0] != state->color_write_mask_blue[i] || state->color_write_mask_alpha[0] != state->color_write_mask_alpha[i]) {
|
||||
independentBlend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_BLEND_DESC blendDesc;
|
||||
memset(&blendDesc, 0, sizeof(blendDesc));
|
||||
blendDesc.AlphaToCoverageEnable = false;
|
||||
blendDesc.IndependentBlendEnable = independentBlend;
|
||||
|
||||
D3D11_RENDER_TARGET_BLEND_DESC rtbd[8];
|
||||
memset(&rtbd, 0, sizeof(rtbd));
|
||||
createRenderTargetBlendDesc(state, &rtbd[0], 0);
|
||||
blendDesc.RenderTarget[0] = rtbd[0];
|
||||
if (independentBlend) {
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
createRenderTargetBlendDesc(state, &rtbd[i], i);
|
||||
blendDesc.RenderTarget[i] = rtbd[i];
|
||||
}
|
||||
}
|
||||
|
||||
dx_ctx.device->lpVtbl->CreateBlendState(dx_ctx.device, &blendDesc, &state->impl.blendState);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11InputLayout;
|
||||
struct ID3D11PixelShader;
|
||||
struct ID3D11VertexShader;
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11DepthStencilState;
|
||||
struct ID3D11RasterizerState;
|
||||
struct ID3D11BlendState;
|
||||
|
||||
typedef struct {
|
||||
// PipelineStateImpl();
|
||||
//~PipelineStateImpl();
|
||||
struct ID3D11InputLayout *d3d11inputLayout;
|
||||
struct ID3D11Buffer *fragmentConstantBuffer;
|
||||
struct ID3D11Buffer *vertexConstantBuffer;
|
||||
struct ID3D11Buffer *geometryConstantBuffer;
|
||||
struct ID3D11Buffer *tessEvalConstantBuffer;
|
||||
struct ID3D11Buffer *tessControlConstantBuffer;
|
||||
struct ID3D11DepthStencilState *depthStencilState;
|
||||
struct ID3D11RasterizerState *rasterizerState;
|
||||
struct ID3D11RasterizerState *rasterizerStateScissor;
|
||||
struct ID3D11BlendState *blendState;
|
||||
// void set(Graphics4::PipelineState* pipeline, bool scissoring);
|
||||
// void setRasterizerState(bool scissoring);
|
||||
// static void setConstants();
|
||||
} kinc_g4_pipeline_impl_t;
|
||||
|
||||
void kinc_internal_set_constants(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,468 @@
|
||||
#include <kinc/error.h>
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
static DXGI_FORMAT convertRenderTargetFormat(kinc_g4_render_target_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
static int formatRenderTargetByteSize(kinc_g4_render_target_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
return 16;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
return 8;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
return 4;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
return 2;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
return 1;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->isCubeMap = false;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
renderTarget->texWidth = renderTarget->width = width;
|
||||
renderTarget->texHeight = renderTarget->height = height;
|
||||
renderTarget->impl.format = format;
|
||||
renderTarget->impl.textureStaging = NULL;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.MipLevels = desc.ArraySize = 1;
|
||||
desc.Format = convertRenderTargetFormat(format);
|
||||
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
|
||||
renderTarget->isDepthAttachment = true;
|
||||
depthBufferBits = 16;
|
||||
stencilBufferBits = 0;
|
||||
}
|
||||
|
||||
bool antialiasing = samples_per_pixel > 1;
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = samples_per_pixel;
|
||||
desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
}
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
renderTarget->impl.textureRender = NULL;
|
||||
renderTarget->impl.textureSample = NULL;
|
||||
renderTarget->impl.renderTargetSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.renderTargetViewRender[i] = NULL;
|
||||
renderTarget->impl.renderTargetViewSample[i] = NULL;
|
||||
}
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureRender));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = antialiasing ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
renderTargetViewDesc.Texture2D.MipSlice = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureRender,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewRender[0]));
|
||||
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureSample));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
renderTargetViewDesc.Texture2D.MipSlice = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewSample[0]));
|
||||
}
|
||||
else {
|
||||
renderTarget->impl.textureSample = renderTarget->impl.textureRender;
|
||||
renderTarget->impl.renderTargetViewSample[0] = renderTarget->impl.renderTargetViewRender[0];
|
||||
}
|
||||
}
|
||||
|
||||
renderTarget->impl.depthStencil = NULL;
|
||||
renderTarget->impl.depthStencilSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.depthStencilView[i] = NULL;
|
||||
}
|
||||
|
||||
DXGI_FORMAT depthFormat;
|
||||
DXGI_FORMAT depthViewFormat;
|
||||
DXGI_FORMAT depthResourceFormat;
|
||||
if (depthBufferBits == 16 && stencilBufferBits == 0) {
|
||||
depthFormat = DXGI_FORMAT_R16_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D16_UNORM;
|
||||
depthResourceFormat = DXGI_FORMAT_R16_UNORM;
|
||||
}
|
||||
else {
|
||||
depthFormat = DXGI_FORMAT_R24G8_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
depthResourceFormat = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
D3D11_TEXTURE2D_DESC depthStencilDesc;
|
||||
depthStencilDesc.Format = depthFormat;
|
||||
depthStencilDesc.Width = width;
|
||||
depthStencilDesc.Height = height;
|
||||
depthStencilDesc.ArraySize = 1;
|
||||
depthStencilDesc.MipLevels = 1;
|
||||
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
|
||||
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
depthStencilDesc.CPUAccessFlags = 0;
|
||||
depthStencilDesc.MiscFlags = 0;
|
||||
if (antialiasing) {
|
||||
depthStencilDesc.SampleDesc.Count = 4;
|
||||
depthStencilDesc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
depthStencilDesc.SampleDesc.Count = 1;
|
||||
depthStencilDesc.SampleDesc.Quality = 0;
|
||||
}
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &depthStencilDesc, NULL, &renderTarget->impl.depthStencil));
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC viewDesc;
|
||||
viewDesc.Format = depthViewFormat;
|
||||
viewDesc.ViewDimension = antialiasing ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
viewDesc.Flags = 0;
|
||||
if (!antialiasing) {
|
||||
viewDesc.Texture2D.MipSlice = 0;
|
||||
}
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDepthStencilView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil, &viewDesc,
|
||||
&renderTarget->impl.depthStencilView[0]));
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
shaderResourceViewDesc.Format = desc.Format;
|
||||
shaderResourceViewDesc.ViewDimension = antialiasing ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.Texture2D.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.renderTargetSRV));
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
shaderResourceViewDesc.Format = depthResourceFormat;
|
||||
shaderResourceViewDesc.ViewDimension = antialiasing ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.Texture2D.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.depthStencilSRV));
|
||||
}
|
||||
|
||||
if (renderTarget->impl.renderTargetViewRender[0] != NULL) {
|
||||
FLOAT colors[4] = {0, 0, 0, 0};
|
||||
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, renderTarget->impl.renderTargetViewRender[0], colors);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->width = cubeMapSize;
|
||||
renderTarget->height = cubeMapSize;
|
||||
renderTarget->isCubeMap = true;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
|
||||
renderTarget->texWidth = renderTarget->width;
|
||||
renderTarget->texHeight = renderTarget->height;
|
||||
renderTarget->impl.format = format;
|
||||
renderTarget->impl.textureStaging = NULL;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = renderTarget->width;
|
||||
desc.Height = renderTarget->height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 6;
|
||||
desc.Format = convertRenderTargetFormat(format);
|
||||
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
|
||||
renderTarget->isDepthAttachment = true;
|
||||
depthBufferBits = 16;
|
||||
stencilBufferBits = 0;
|
||||
}
|
||||
|
||||
bool antialiasing = samples_per_pixel > 1;
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = samples_per_pixel;
|
||||
desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
}
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
|
||||
|
||||
renderTarget->impl.textureRender = NULL;
|
||||
renderTarget->impl.textureSample = NULL;
|
||||
renderTarget->impl.renderTargetSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.renderTargetViewRender[i] = NULL;
|
||||
renderTarget->impl.renderTargetViewSample[i] = NULL;
|
||||
}
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureRender));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
renderTargetViewDesc.Texture2DArray.MipSlice = 0;
|
||||
renderTargetViewDesc.Texture2DArray.ArraySize = 1;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTargetViewDesc.Texture2DArray.FirstArraySlice = i;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureRender,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewRender[i]));
|
||||
}
|
||||
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureSample));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
renderTargetViewDesc.Texture2D.MipSlice = 0;
|
||||
renderTargetViewDesc.Texture2DArray.ArraySize = 1;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTargetViewDesc.Texture2DArray.FirstArraySlice = i;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewSample[i]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
renderTarget->impl.textureSample = renderTarget->impl.textureRender;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.renderTargetViewSample[i] = renderTarget->impl.renderTargetViewRender[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderTarget->impl.depthStencil = NULL;
|
||||
renderTarget->impl.depthStencilSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.depthStencilView[i] = NULL;
|
||||
}
|
||||
|
||||
DXGI_FORMAT depthFormat;
|
||||
DXGI_FORMAT depthViewFormat;
|
||||
DXGI_FORMAT depthResourceFormat;
|
||||
if (depthBufferBits == 16 && stencilBufferBits == 0) {
|
||||
depthFormat = DXGI_FORMAT_R16_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D16_UNORM;
|
||||
depthResourceFormat = DXGI_FORMAT_R16_UNORM;
|
||||
}
|
||||
else {
|
||||
depthFormat = DXGI_FORMAT_R24G8_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
depthResourceFormat = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
D3D11_TEXTURE2D_DESC depthStencilDesc;
|
||||
depthStencilDesc.Format = depthFormat;
|
||||
depthStencilDesc.Width = renderTarget->width;
|
||||
depthStencilDesc.Height = renderTarget->height;
|
||||
depthStencilDesc.ArraySize = 1;
|
||||
depthStencilDesc.MipLevels = 1;
|
||||
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
|
||||
depthStencilDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
|
||||
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
depthStencilDesc.CPUAccessFlags = 0;
|
||||
depthStencilDesc.ArraySize = 6;
|
||||
if (antialiasing) {
|
||||
depthStencilDesc.SampleDesc.Count = 4;
|
||||
depthStencilDesc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
depthStencilDesc.SampleDesc.Count = 1;
|
||||
depthStencilDesc.SampleDesc.Quality = 0;
|
||||
}
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &depthStencilDesc, NULL, &renderTarget->impl.depthStencil));
|
||||
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
|
||||
depthStencilViewDesc.Format = depthViewFormat;
|
||||
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
depthStencilViewDesc.Texture2DArray.MipSlice = 0;
|
||||
depthStencilViewDesc.Texture2DArray.ArraySize = 1;
|
||||
depthStencilViewDesc.Flags = 0;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
depthStencilViewDesc.Texture2DArray.FirstArraySlice = i;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDepthStencilView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
|
||||
&depthStencilViewDesc, &renderTarget->impl.depthStencilView[i]));
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
shaderResourceViewDesc.Format = desc.Format;
|
||||
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
shaderResourceViewDesc.TextureCube.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.TextureCube.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.renderTargetSRV));
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
shaderResourceViewDesc.Format = depthResourceFormat;
|
||||
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
shaderResourceViewDesc.TextureCube.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.TextureCube.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.depthStencilSRV));
|
||||
}
|
||||
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
FLOAT colors[4] = {0, 0, 0, 0};
|
||||
for (int i = 0; i < 6; i++) {
|
||||
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, renderTarget->impl.renderTargetViewRender[i], colors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (renderTarget->impl.renderTargetViewRender[i] != NULL)
|
||||
renderTarget->impl.renderTargetViewRender[i]->lpVtbl->Release(renderTarget->impl.renderTargetViewRender[i]);
|
||||
if (renderTarget->impl.renderTargetViewSample[i] != NULL &&
|
||||
renderTarget->impl.renderTargetViewSample[i] != renderTarget->impl.renderTargetViewRender[i])
|
||||
renderTarget->impl.renderTargetViewSample[i]->lpVtbl->Release(renderTarget->impl.renderTargetViewSample[i]);
|
||||
if (renderTarget->impl.depthStencilView[i] != NULL)
|
||||
renderTarget->impl.depthStencilView[i]->lpVtbl->Release(renderTarget->impl.depthStencilView[i]);
|
||||
}
|
||||
if (renderTarget->impl.renderTargetSRV != NULL)
|
||||
renderTarget->impl.renderTargetSRV->lpVtbl->Release(renderTarget->impl.renderTargetSRV);
|
||||
if (renderTarget->impl.depthStencilSRV != NULL)
|
||||
renderTarget->impl.depthStencilSRV->lpVtbl->Release(renderTarget->impl.depthStencilSRV);
|
||||
if (renderTarget->impl.depthStencil != NULL)
|
||||
renderTarget->impl.depthStencil->lpVtbl->Release(renderTarget->impl.depthStencil);
|
||||
if (renderTarget->impl.textureRender != NULL)
|
||||
renderTarget->impl.textureRender->lpVtbl->Release(renderTarget->impl.textureRender);
|
||||
if (renderTarget->impl.textureStaging != NULL)
|
||||
renderTarget->impl.textureStaging->lpVtbl->Release(renderTarget->impl.textureStaging);
|
||||
if (renderTarget->impl.textureSample != NULL && renderTarget->impl.textureSample != renderTarget->impl.textureRender)
|
||||
renderTarget->impl.textureSample->lpVtbl->Release(renderTarget->impl.textureSample);
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, uint32_t unit) {
|
||||
if (renderTarget->impl.textureSample != renderTarget->impl.textureRender) {
|
||||
dx_ctx.context->lpVtbl->ResolveSubresource(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureSample, 0,
|
||||
(ID3D11Resource *)renderTarget->impl.textureRender, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
}
|
||||
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit, 1,
|
||||
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV : &renderTarget->impl.renderTargetSRV);
|
||||
}
|
||||
#else
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0 && unit.stages[KINC_G4_SHADER_TYPE_VERTEX] < 0)
|
||||
return;
|
||||
|
||||
if (renderTarget->impl.textureSample != renderTarget->impl.textureRender) {
|
||||
dx_ctx.context->lpVtbl->ResolveSubresource(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureSample, 0,
|
||||
(ID3D11Resource *)renderTarget->impl.textureRender, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
|
||||
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1,
|
||||
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV
|
||||
: &renderTarget->impl.renderTargetSRV);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1,
|
||||
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV
|
||||
: &renderTarget->impl.renderTargetSRV);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
|
||||
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1, &renderTarget->impl.depthStencilSRV);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &renderTarget->impl.depthStencilSRV);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source) {
|
||||
renderTarget->impl.depthStencil = source->impl.depthStencil;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.depthStencilView[i] = source->impl.depthStencilView[i];
|
||||
}
|
||||
renderTarget->impl.depthStencilSRV = source->impl.depthStencilSRV;
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *renderTarget, uint8_t *data) {
|
||||
if (renderTarget->impl.textureStaging == NULL) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = renderTarget->texWidth;
|
||||
desc.Height = renderTarget->texHeight;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = convertRenderTargetFormat((kinc_g4_render_target_format_t)renderTarget->impl.format);
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.BindFlags = 0;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.MiscFlags = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureStaging));
|
||||
}
|
||||
|
||||
D3D11_BOX sourceRegion;
|
||||
sourceRegion.left = 0;
|
||||
sourceRegion.right = renderTarget->texWidth;
|
||||
sourceRegion.top = 0;
|
||||
sourceRegion.bottom = renderTarget->texHeight;
|
||||
sourceRegion.front = 0;
|
||||
sourceRegion.back = 1;
|
||||
dx_ctx.context->lpVtbl->CopySubresourceRegion(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0, 0, 0, 0,
|
||||
(ID3D11Resource *)renderTarget->impl.textureRender, 0, &sourceRegion);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0, D3D11_MAP_READ, 0, &mappedResource);
|
||||
int size;
|
||||
if (mappedResource.RowPitch != 0) {
|
||||
size = mappedResource.RowPitch * renderTarget->texHeight;
|
||||
}
|
||||
else {
|
||||
size = renderTarget->texWidth * renderTarget->texHeight * formatRenderTargetByteSize((kinc_g4_render_target_format_t)renderTarget->impl.format);
|
||||
}
|
||||
memcpy(data, mappedResource.pData, size);
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *renderTarget, int levels) {}
|
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11RenderTargetView;
|
||||
struct ID3D11DepthStencilView;
|
||||
struct ID3D11ShaderResourceView;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Texture2D *textureRender;
|
||||
struct ID3D11Texture2D *textureSample;
|
||||
struct ID3D11Texture2D *textureStaging;
|
||||
struct ID3D11RenderTargetView *renderTargetViewRender[6];
|
||||
struct ID3D11RenderTargetView *renderTargetViewSample[6];
|
||||
struct ID3D11Texture2D *depthStencil;
|
||||
struct ID3D11DepthStencilView *depthStencilView[6];
|
||||
struct ID3D11ShaderResourceView *renderTargetSRV;
|
||||
struct ID3D11ShaderResourceView *depthStencilSRV;
|
||||
int format;
|
||||
} kinc_g4_render_target_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,114 @@
|
||||
#include <kinc/graphics4/shader.h>
|
||||
|
||||
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {
|
||||
if (shader->impl.shader != NULL) {
|
||||
((IUnknown *)shader->impl.shader)->lpVtbl->Release(shader->impl.shader);
|
||||
free(shader->impl.data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *_data, size_t length, kinc_g4_shader_type_t type) {
|
||||
unsigned index = 0;
|
||||
uint8_t *data = (uint8_t *)_data;
|
||||
shader->impl.type = (int)type;
|
||||
|
||||
#ifndef KINC_KONG
|
||||
memset(&shader->impl.attributes, 0, sizeof(shader->impl.attributes));
|
||||
int attributesCount = data[index++];
|
||||
for (int i = 0; i < attributesCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.attributes[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.attributes[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.textures, 0, sizeof(shader->impl.textures));
|
||||
uint8_t texCount = data[index++];
|
||||
for (unsigned i = 0; i < texCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.textures[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.textures[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.constants, 0, sizeof(shader->impl.constants));
|
||||
uint8_t constantCount = data[index++];
|
||||
shader->impl.constantsSize = 0;
|
||||
for (unsigned i = 0; i < constantCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
kinc_internal_shader_constant_t constant;
|
||||
constant.hash = kinc_internal_hash_name(name);
|
||||
constant.offset = *(uint32_t *)&data[index];
|
||||
index += 4;
|
||||
constant.size = *(uint32_t *)&data[index];
|
||||
index += 4;
|
||||
constant.columns = data[index];
|
||||
index += 1;
|
||||
constant.rows = data[index];
|
||||
index += 1;
|
||||
|
||||
shader->impl.constants[i] = constant;
|
||||
shader->impl.constantsSize = constant.offset + constant.size;
|
||||
}
|
||||
#endif
|
||||
|
||||
shader->impl.length = (int)(length - index);
|
||||
shader->impl.data = (uint8_t *)malloc(shader->impl.length);
|
||||
assert(shader->impl.data != NULL);
|
||||
memcpy(shader->impl.data, &data[index], shader->impl.length);
|
||||
|
||||
switch (type) {
|
||||
case KINC_G4_SHADER_TYPE_VERTEX:
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateVertexShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
|
||||
(ID3D11VertexShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_FRAGMENT:
|
||||
kinc_microsoft_affirm(
|
||||
dx_ctx.device->lpVtbl->CreatePixelShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11PixelShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_GEOMETRY:
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateGeometryShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
|
||||
(ID3D11GeometryShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL:
|
||||
kinc_microsoft_affirm(
|
||||
dx_ctx.device->lpVtbl->CreateHullShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11HullShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION:
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDomainShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
|
||||
(ID3D11DomainShader **)&shader->impl.shader));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
extern int krafix_compile(const char *source, char *output, int *length, const char *targetlang, const char *system, const char *shadertype, int version);
|
||||
#endif
|
||||
|
||||
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
char *output = malloc(1024 * 1024);
|
||||
int length;
|
||||
int errors = krafix_compile(source, output, &length, "d3d11", "windows", type == KINC_G4_SHADER_TYPE_FRAGMENT ? "frag" : "vert", -1);
|
||||
if (errors > 0) {
|
||||
return errors;
|
||||
}
|
||||
kinc_g4_shader_init(shader, output, length, type);
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
#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;
|
||||
uint32_t computeOffset;
|
||||
uint32_t computeSize;
|
||||
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;
|
||||
uint8_t computeColumns;
|
||||
uint8_t computeRows;
|
||||
} kinc_g4_constant_location_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,377 @@
|
||||
#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 && unit.stages[KINC_G4_SHADER_TYPE_COMPUTE] < 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);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_COMPUTE] >= 0) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_COMPUTE], 1, &texture->impl.view);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0 || unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
|
||||
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 && unit.stages[KINC_G4_SHADER_TYPE_VERTEX] < 0 && unit.stages[KINC_G4_SHADER_TYPE_COMPUTE] < 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));
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
ID3D11ShaderResourceView *nullView = NULL;
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, 0, 1, &nullView);
|
||||
|
||||
dx_ctx.context->lpVtbl->CSSetUnorderedAccessViews(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &texture->impl.computeView, NULL);
|
||||
}
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
|
||||
ID3D11ShaderResourceView *nullView = NULL;
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, 0, 1, &nullView);
|
||||
|
||||
dx_ctx.context->lpVtbl->CSSetUnorderedAccessViews(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1, &texture->impl.computeView, NULL);
|
||||
}
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_COMPUTE] >= 0) {
|
||||
ID3D11ShaderResourceView *nullView = NULL;
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, 0, 1, &nullView);
|
||||
|
||||
dx_ctx.context->lpVtbl->CSSetUnorderedAccessViews(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_COMPUTE], 1, &texture->impl.computeView, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_texture_unset(kinc_g4_texture_t *texture) {
|
||||
if (setTextures[texture->impl.stage] == texture) {
|
||||
|
||||
setTextures[texture->impl.stage] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
kinc_microsoft_affirm(dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource));
|
||||
texture->impl.rowPitch = mappedResource.RowPitch;
|
||||
return (uint8_t *)mappedResource.pData;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, 0);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {
|
||||
if (texture->impl.renderView == NULL) {
|
||||
texture->tex_depth > 1 ? kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D,
|
||||
0, &texture->impl.renderView))
|
||||
: kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, 0,
|
||||
&texture->impl.renderView));
|
||||
}
|
||||
static float clearColor[4];
|
||||
clearColor[0] = ((color & 0x00ff0000) >> 16) / 255.0f;
|
||||
clearColor[1] = ((color & 0x0000ff00) >> 8) / 255.0f;
|
||||
clearColor[2] = (color & 0x000000ff) / 255.0f;
|
||||
clearColor[3] = ((color & 0xff000000) >> 24) / 255.0f;
|
||||
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, texture->impl.renderView, clearColor);
|
||||
}
|
||||
|
||||
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
|
||||
assert(texture->impl.rowPitch != 0); // stride is not yet set, lock and unlock the texture first (or find a good fix for this and send a PR)
|
||||
return texture->impl.rowPitch;
|
||||
}
|
||||
|
||||
static void enableMipmaps(kinc_g4_texture_t *texture, int texWidth, int texHeight, int format) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = texWidth;
|
||||
desc.Height = texHeight;
|
||||
desc.MipLevels = 0;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = convertFormat((kinc_image_format_t)format);
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
|
||||
|
||||
ID3D11Texture2D *mipMappedTexture;
|
||||
ID3D11ShaderResourceView *mipMappedView;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &mipMappedTexture));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)mipMappedTexture, NULL, &mipMappedView));
|
||||
|
||||
D3D11_BOX sourceRegion;
|
||||
sourceRegion.left = 0;
|
||||
sourceRegion.right = texWidth;
|
||||
sourceRegion.top = 0;
|
||||
sourceRegion.bottom = texHeight;
|
||||
sourceRegion.front = 0;
|
||||
sourceRegion.back = 1;
|
||||
dx_ctx.context->lpVtbl->CopySubresourceRegion(dx_ctx.context, (ID3D11Resource *)mipMappedTexture, 0, 0, 0, 0, (ID3D11Resource *)texture->impl.texture, 0,
|
||||
&sourceRegion);
|
||||
|
||||
if (texture->impl.texture != NULL) {
|
||||
texture->impl.texture->lpVtbl->Release(texture->impl.texture);
|
||||
}
|
||||
texture->impl.texture = mipMappedTexture;
|
||||
|
||||
if (texture->impl.view != NULL) {
|
||||
texture->impl.view->lpVtbl->Release(texture->impl.view);
|
||||
}
|
||||
texture->impl.view = mipMappedView;
|
||||
|
||||
texture->impl.hasMipmaps = true;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {
|
||||
if (!texture->impl.hasMipmaps) {
|
||||
enableMipmaps(texture, texture->tex_width, texture->tex_height, texture->format);
|
||||
}
|
||||
dx_ctx.context->lpVtbl->GenerateMips(dx_ctx.context, texture->impl.view);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {
|
||||
if (!texture->impl.hasMipmaps) {
|
||||
enableMipmaps(texture, texture->tex_width, texture->tex_height, texture->format);
|
||||
}
|
||||
D3D11_BOX dstRegion;
|
||||
dstRegion.left = 0;
|
||||
dstRegion.right = mipmap->width;
|
||||
dstRegion.top = 0;
|
||||
dstRegion.bottom = mipmap->height;
|
||||
dstRegion.front = 0;
|
||||
dstRegion.back = 1;
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, level, &dstRegion, mipmap->data,
|
||||
mipmap->width * formatByteSize(mipmap->format), 0);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11Texture3D;
|
||||
struct ID3D11ShaderResourceView;
|
||||
struct ID3D11UnorderedAccessView;
|
||||
struct ID3D11RenderTargetView;
|
||||
|
||||
// TextureImpl();
|
||||
//~TextureImpl();
|
||||
// void enableMipmaps(int texWidth, int texHeight, int format);
|
||||
// void unmipmap();
|
||||
// void unset();
|
||||
|
||||
typedef struct {
|
||||
bool hasMipmaps;
|
||||
int stage;
|
||||
struct ID3D11Texture2D *texture;
|
||||
struct ID3D11Texture3D *texture3D;
|
||||
struct ID3D11ShaderResourceView *view;
|
||||
struct ID3D11UnorderedAccessView *computeView;
|
||||
struct ID3D11RenderTargetView *renderView;
|
||||
int rowPitch;
|
||||
} kinc_g4_texture_impl_t;
|
@ -0,0 +1,39 @@
|
||||
#include <kinc/graphics4/texturearray.h>
|
||||
#include <kinc/graphics4/textureunit.h>
|
||||
|
||||
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = textures[0].width;
|
||||
desc.Height = textures[0].height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 2;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA *resdata = (D3D11_SUBRESOURCE_DATA *)alloca(sizeof(D3D11_SUBRESOURCE_DATA) * count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
resdata[i].pSysMem = textures[i].data;
|
||||
resdata[i].SysMemPitch = textures[0].width * 4;
|
||||
resdata[i].SysMemSlicePitch = 0;
|
||||
}
|
||||
|
||||
array->impl.texture = NULL;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, resdata, &array->impl.texture));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)array->impl.texture, NULL, &array->impl.view));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
|
||||
|
||||
void kinc_internal_texture_array_set(kinc_g4_texture_array_t *array, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0)
|
||||
return;
|
||||
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &array->impl.view);
|
||||
// this->stage = unit.unit;
|
||||
// setTextures[stage] = this;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11ShaderResourceView;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Texture2D *texture;
|
||||
struct ID3D11ShaderResourceView *view;
|
||||
// void set(Kore::Graphics4::TextureUnit unit);
|
||||
} kinc_g4_texture_array_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,95 @@
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
|
||||
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int count, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
|
||||
int instance_data_step_rate) {
|
||||
buffer->impl.count = count;
|
||||
buffer->impl.stride = 0;
|
||||
for (int i = 0; i < structure->size; ++i) {
|
||||
buffer->impl.stride += kinc_g4_vertex_data_size(structure->elements[i].data);
|
||||
}
|
||||
|
||||
if (usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
buffer->impl.vertices = NULL;
|
||||
}
|
||||
else {
|
||||
buffer->impl.vertices = (float *)malloc(buffer->impl.stride * count);
|
||||
}
|
||||
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
|
||||
buffer->impl.usage = usage;
|
||||
switch (usage) {
|
||||
case KINC_G4_USAGE_STATIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
case KINC_G4_USAGE_DYNAMIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
break;
|
||||
case KINC_G4_USAGE_READABLE:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
bufferDesc.ByteWidth = buffer->impl.stride * count;
|
||||
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
bufferDesc.StructureByteStride = 0;
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &bufferDesc, NULL, &buffer->impl.vb));
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
|
||||
buffer->impl.vb->lpVtbl->Release(buffer->impl.vb);
|
||||
free(buffer->impl.vertices);
|
||||
buffer->impl.vertices = NULL;
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return kinc_g4_vertex_buffer_lock(buffer, 0, buffer->impl.count);
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
|
||||
buffer->impl.lockStart = start;
|
||||
buffer->impl.lockCount = count;
|
||||
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
memset(&mappedResource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
float *data = (float *)mappedResource.pData;
|
||||
return &data[start * buffer->impl.stride / 4];
|
||||
}
|
||||
else {
|
||||
return &buffer->impl.vertices[start * buffer->impl.stride / 4];
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
kinc_g4_vertex_buffer_unlock(buffer, buffer->impl.lockCount);
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0);
|
||||
}
|
||||
else {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0, NULL, buffer->impl.vertices, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
|
||||
// UINT stride = myStride;
|
||||
// UINT internaloffset = 0;
|
||||
// dx_ctx.context->IASetVertexBuffers(0, 1, &vb, &stride, &internaloffset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.count;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.stride;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Buffer *vb;
|
||||
int stride;
|
||||
int count;
|
||||
int lockStart;
|
||||
int lockCount;
|
||||
float *vertices;
|
||||
int usage;
|
||||
} kinc_g4_vertex_buffer_impl_t;
|
Reference in New Issue
Block a user